[pypy-svn] r27492 - in pypy/dist/pypy/rpython: lltypesystem memory memory/test
arigo at codespeak.net
arigo at codespeak.net
Sat May 20 10:47:15 CEST 2006
Author: arigo
Date: Sat May 20 10:47:12 2006
New Revision: 27492
Modified:
pypy/dist/pypy/rpython/lltypesystem/lloperation.py
pypy/dist/pypy/rpython/memory/gc.py
pypy/dist/pypy/rpython/memory/gctransform.py
pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
Log:
Renamed 'malloced_lists' to 'pools'. These pools are now GcOpaque
objects themselves, so that they are collectable. Work in progress.
(Collecting a pool only means collecting the small overhead data, not
all the objects inside the pool, which stay alive as usual as long as
they are referenced.)
Modified: pypy/dist/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lloperation.py (original)
+++ pypy/dist/pypy/rpython/lltypesystem/lloperation.py Sat May 20 10:47:12 2006
@@ -319,7 +319,7 @@
'gc_reload_possibly_moved': LLOp(),
# experimental operations in support of thread cloning, only
# implemented by the Mark&Sweep GC
- 'gc_x_swap_list': LLOp(),
+ 'gc_x_swap_pool': LLOp(canraise=(MemoryError,)),
'gc_x_clone': LLOp(canraise=(MemoryError,)),
# __________ stackless operation(s) __________
Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py (original)
+++ pypy/dist/pypy/rpython/memory/gc.py Sat May 20 10:47:12 2006
@@ -12,8 +12,12 @@
int_size = lltypesimulation.sizeof(lltype.Signed)
gc_header_two_ints = 2*int_size
+X_POOL = lltype.GcOpaqueType('gc.pool')
+X_POOL_PTR = lltype.Ptr(X_POOL)
X_CLONE = lltype.GcStruct('CloneData', ('gcobjectptr', llmemory.GCREF),
- ('malloced_list', llmemory.Address))
+ ('pool', X_POOL_PTR))
+X_CLONE_PTR = lltype.Ptr(X_CLONE)
+
class GCError(Exception):
pass
@@ -114,6 +118,9 @@
HDR.become(lltype.Struct('header', ('typeid', lltype.Signed),
('next', HDRPTR)))
+ POOL = lltype.GcStruct('gc_pool')
+ POOLPTR = lltype.Ptr(POOL)
+
def __init__(self, AddressLinkedList, start_heap_size=4096, get_roots=None):
self.heap_usage = 0 # at the end of the latest collection
self.bytes_malloced = 0 # since the latest collection
@@ -122,6 +129,7 @@
self.AddressLinkedList = AddressLinkedList
#self.set_query_functions(None, None, None, None, None, None, None)
self.malloced_objects = lltype.nullptr(self.HDR)
+ self.curpool = lltype.nullptr(self.POOL)
self.get_roots = get_roots
self.gcheaderbuilder = GCHeaderBuilder(self.HDR)
@@ -255,8 +263,8 @@
self.bytes_malloced_threshold = curr_heap_size
end_time = time.time()
self.total_collection_time += end_time - start_time
- # warning, the following debug print allocates memory to manipulate
- # the strings! so it must be at the end
+ # warning, the following debug prints allocate memory to manipulate
+ # the strings! so they must be at the end
if DEBUG_PRINT:
os.write(2, " malloced since previous collection: %s bytes\n" %
old_malloced)
@@ -285,24 +293,54 @@
init_gc_object_immortal = init_gc_object
# experimental support for thread cloning
- def x_swap_list(self, malloced_list):
- # Swap the current malloced_objects linked list with another one.
- # All malloc'ed objects are put into the current malloced_objects
- # list; this is a way to separate objects depending on when they
- # were allocated.
- current = llmemory.cast_ptr_to_adr(self.malloced_objects)
- self.malloced_objects = llmemory.cast_adr_to_ptr(malloced_list,
- self.HDRPTR)
- return current
+ def x_swap_pool(self, newpool):
+ # Set newpool as the current pool (create one if newpool == NULL).
+ # All malloc'ed objects are put into the current pool;this is a
+ # way to separate objects depending on when they were allocated.
+ size_gc_header = self.gcheaderbuilder.size_gc_header
+ # invariant: each POOL GcStruct is at the _front_ of a linked list
+ # of malloced objects.
+ oldpool = self.curpool
+ if not oldpool:
+ # make a fresh pool object, which is automatically inserted at the
+ # front of the current list
+ oldpool = lltype.malloc(self.POOL)
+ else:
+ # manually insert oldpool at the front of the current list
+ addr = llmemory.cast_ptr_to_adr(oldpool)
+ addr -= size_gc_header
+ hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR)
+ hdr.next = self.malloced_objects
+
+ newpool = lltype.cast_opaque_ptr(self.POOLPTR, newpool)
+ if newpool:
+ # newpool is at the front of the new linked list to install
+ addr = llmemory.cast_ptr_to_adr(newpool)
+ addr -= size_gc_header
+ hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR)
+ self.malloced_objects = hdr.next
+ else:
+ # start a fresh new linked list
+ self.malloced_objects = lltype.nullptr(self.HDR)
+ # note that newpool will not be freed by a collect as long as
+ # it sits in self.malloced_objects_box, because it is not itself
+ # part of any linked list
+ self.curpool = newpool
+ return lltype.cast_opaque_ptr(X_POOL_PTR, oldpool)
def x_clone(self, clonedata):
# Recursively clone the gcobject and everything it points to,
# directly or indirectly -- but stops at objects that are not
- # in the malloced_list. The gcobjectptr and the malloced_list
- # fields of clonedata are adjusted to refer to the result.
+ # in the specified pool. A new pool is built to contain the
+ # copies, and the 'gcobjectptr' and 'pool' fields of clonedata
+ # are adjusted to refer to the result.
size_gc_header = self.gcheaderbuilder.size_gc_header
oldobjects = self.AddressLinkedList()
- hdr = llmemory.cast_adr_to_ptr(clonedata.malloced_list, self.HDRPTR)
+ oldpool = lltype.cast_opaque_ptr(self.POOLPTR, clonedata.pool)
+ addr = llmemory.cast_ptr_to_adr(oldpool)
+ addr -= size_gc_header
+ hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR)
+ hdr = hdr.next
while hdr:
next = hdr.next
hdr.typeid |= 1 # mark all objects from malloced_list
@@ -348,8 +386,6 @@
newobj_addr = llmemory.cast_ptr_to_adr(newhdr) + size_gc_header
gcptr_addr.address[0] = newobj_addr
- clonedata.malloced_list = llmemory.cast_ptr_to_adr(newobjectlist)
-
# re-create the original linked list
next = lltype.nullptr(self.HDR)
while oldobjects.non_empty():
@@ -359,6 +395,12 @@
next = hdr
oldobjects.delete()
+ # make the new pool object to collect newobjectlist
+ curpool = self.x_swap_pool(lltype.nullptr(X_POOL))
+ assert not self.malloced_objects
+ self.malloced_objects = newobjectlist
+ clonedata.pool = self.x_swap_pool(curpool)
+
class SemiSpaceGC(GCBase):
_alloc_flavor_ = "raw"
Modified: pypy/dist/pypy/rpython/memory/gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform.py (original)
+++ pypy/dist/pypy/rpython/memory/gctransform.py Sat May 20 10:47:12 2006
@@ -844,9 +844,11 @@
annhelper = annlowlevel.MixLevelHelperAnnotator(self.translator.rtyper)
- def getfn(ll_function, args_s, s_result, inline=False):
+ def getfn(ll_function, args_s, s_result, inline=False,
+ minimal_transform=True):
graph = annhelper.getgraph(ll_function, args_s, s_result)
- self.need_minimal_transform(graph)
+ if minimal_transform:
+ self.need_minimal_transform(graph)
if inline:
self.graphs_to_inline[graph] = True
return annhelper.graph2const(graph)
@@ -888,13 +890,18 @@
[s_gc], annmodel.SomeTuple(statics_s))
# experimental gc_x_* operations
- self.x_swap_list_ptr = getfn(GCClass.x_swap_list.im_func,
- [s_gc, annmodel.SomeAddress()],
- annmodel.SomeAddress())
+ s_x_pool = annmodel.SomePtr(gc.X_POOL_PTR)
+ s_x_clone = annmodel.SomePtr(gc.X_CLONE_PTR)
+ # the x_*() methods use some regular mallocs that must be
+ # transformed in the normal way
+ self.x_swap_pool_ptr = getfn(GCClass.x_swap_pool.im_func,
+ [s_gc, s_x_pool],
+ s_x_pool,
+ minimal_transform = False)
self.x_clone_ptr = getfn(GCClass.x_clone.im_func,
- [s_gc,
- annmodel.SomePtr(lltype.Ptr(gc.X_CLONE))],
- annmodel.s_None)
+ [s_gc, s_x_clone],
+ annmodel.s_None,
+ minimal_transform = False)
annhelper.finish() # at this point, annotate all mix-level helpers
annhelper.backend_optimize()
@@ -1162,10 +1169,10 @@
block.operations.index(op))
return ops
- def replace_gc_x_swap_list(self, op, livevars, block):
+ def replace_gc_x_swap_pool(self, op, livevars, block):
[v_malloced] = op.args
newop = SpaceOperation("direct_call",
- [self.x_swap_list_ptr, self.c_const_gc,
+ [self.x_swap_pool_ptr, self.c_const_gc,
v_malloced],
op.result)
return [newop]
Modified: pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py (original)
+++ pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py Sat May 20 10:47:12 2006
@@ -161,7 +161,7 @@
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rpython.lltypesystem import lltype
from pypy.rpython.memory.support import INT_SIZE
-from pypy.rpython.memory.gc import X_CLONE
+from pypy.rpython.memory.gc import X_CLONE, X_POOL, X_POOL_PTR
from pypy import conftest
@@ -304,18 +304,18 @@
return a
def func():
a1 = make(111)
- # start recording mallocs in a new list
- oldlist = llop.gc_x_swap_list(llmemory.Address, llmemory.NULL)
+ # start recording mallocs in a new pool
+ oldpool = llop.gc_x_swap_pool(X_POOL_PTR, lltype.nullptr(X_POOL))
# the following a2 goes into the new list
a2 = make(222)
- # now put the old list back and get the new list
- newlist = llop.gc_x_swap_list(llmemory.Address, oldlist)
+ # now put the old pool back and get the new pool
+ newpool = llop.gc_x_swap_pool(X_POOL_PTR, oldpool)
a3 = make(333)
# clone a2
a2ref = lltype.cast_opaque_ptr(llmemory.GCREF, a2)
clonedata = lltype.malloc(X_CLONE)
clonedata.gcobjectptr = a2ref
- clonedata.malloced_list = newlist
+ clonedata.pool = newpool
llop.gc_x_clone(lltype.Void, clonedata)
a2copyref = clonedata.gcobjectptr
a2copy = lltype.cast_opaque_ptr(lltype.Ptr(A), a2copyref)
More information about the Pypy-commit
mailing list