[pypy-svn] r51787 - in pypy/branch/unified-rtti/pypy/rpython/memory: . gc gctransform
arigo at codespeak.net
arigo at codespeak.net
Fri Feb 22 13:06:10 CET 2008
Author: arigo
Date: Fri Feb 22 13:06:08 2008
New Revision: 51787
Modified:
pypy/branch/unified-rtti/pypy/rpython/memory/gc/base.py
pypy/branch/unified-rtti/pypy/rpython/memory/gc/marksweep.py
pypy/branch/unified-rtti/pypy/rpython/memory/gcheader.py
pypy/branch/unified-rtti/pypy/rpython/memory/gctransform/refcounting.py
pypy/branch/unified-rtti/pypy/rpython/memory/gctransform/transform.py
pypy/branch/unified-rtti/pypy/rpython/memory/gctypelayout.py
pypy/branch/unified-rtti/pypy/rpython/memory/gcwrapper.py
pypy/branch/unified-rtti/pypy/rpython/memory/support.py
Log:
In-progress: some MarkSweep tests pass. Many other tests broke :-)
Modified: pypy/branch/unified-rtti/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/branch/unified-rtti/pypy/rpython/memory/gc/base.py (original)
+++ pypy/branch/unified-rtti/pypy/rpython/memory/gc/base.py Fri Feb 22 13:06:08 2008
@@ -1,4 +1,5 @@
from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.memory import gcheader, gctypelayout
from pypy.rlib.debug import ll_assert
class GCBase(object):
@@ -8,6 +9,10 @@
needs_zero_gc_pointers = True
prebuilt_gc_objects_are_static_roots = True
+ def __init__(self):
+ TYPE_INFO = gctypelayout.GCData.TYPE_INFO
+ self.gcheaderbuilder = gcheader.GCHeaderBuilder(self.HDR, TYPE_INFO)
+
def set_query_functions(self, is_varsize, has_gcptr_in_varsize,
is_gcarrayofgcptr,
getfinalizer,
Modified: pypy/branch/unified-rtti/pypy/rpython/memory/gc/marksweep.py
==============================================================================
--- pypy/branch/unified-rtti/pypy/rpython/memory/gc/marksweep.py (original)
+++ pypy/branch/unified-rtti/pypy/rpython/memory/gc/marksweep.py Fri Feb 22 13:06:08 2008
@@ -1,13 +1,13 @@
from pypy.rpython.lltypesystem.llmemory import raw_malloc, raw_free
from pypy.rpython.lltypesystem.llmemory import raw_memcopy, raw_memclear
from pypy.rpython.lltypesystem.llmemory import NULL, raw_malloc_usage
-from pypy.rpython.memory.support import DEFAULT_CHUNK_SIZE
+from pypy.rpython.memory.support import DEFAULT_CHUNK_SIZE, RTTIPTR
from pypy.rpython.memory.support import get_address_stack
-from pypy.rpython.memory.gcheader import GCHeaderBuilder
from pypy.rpython.lltypesystem import lltype, llmemory
from pypy.rlib.objectmodel import free_non_gc_object
from pypy.rpython.lltypesystem.lloperation import llop
from pypy.rlib.rarithmetic import ovfcheck
+from pypy.rlib.debug import ll_assert
from pypy.rpython.memory.gc.base import GCBase
@@ -19,6 +19,24 @@
('pool', X_POOL_PTR))
X_CLONE_PTR = lltype.Ptr(X_CLONE)
+def ll_getnext(hdr):
+ "Return the 'next' header by reading the 'next_and_flags' fields"
+ next = hdr.next_and_flags & ~1
+ return llmemory.cast_adr_to_ptr(next, MarkSweepGC.HDRPTR)
+
+def ll_setnext_clear(hdr, next):
+ hdr.next_and_flags = llmemory.cast_ptr_to_adr(next)
+
+def ll_ismarked(hdr):
+ return (llmemory.cast_adr_to_int(hdr.next_and_flags) & 1) != 0
+
+def ll_setmark(hdr):
+ hdr.next_and_flags |= 1
+
+def ll_clearmark(hdr):
+ hdr.next_and_flags &= ~1
+
+
DEBUG_PRINT = False
memoryError = MemoryError()
class MarkSweepGC(GCBase):
@@ -28,18 +46,24 @@
HDRPTR = lltype.Ptr(HDR)
# need to maintain a linked list of malloced objects, since we used the
# systems allocator and can't walk the heap
- HDR.become(lltype.Struct('header', ('typeid', lltype.Signed),
- ('next', HDRPTR)))
+ HDR.become(lltype.Struct('header', ('typeptr', RTTIPTR),
+ ('next_and_flags', llmemory.Address),
+ adtmeths={'getnext': ll_getnext,
+ 'setnext_clear': ll_setnext_clear,
+ 'ismarked': ll_ismarked,
+ 'setmark': ll_setmark,
+ 'clearmark': ll_clearmark}))
POOL = lltype.GcStruct('gc_pool')
POOLPTR = lltype.Ptr(POOL)
POOLNODE = lltype.ForwardReference()
POOLNODEPTR = lltype.Ptr(POOLNODE)
- POOLNODE.become(lltype.Struct('gc_pool_node', ('linkedlist', HDRPTR),
+ POOLNODE.become(lltype.Struct('gc_pool_node', ('linkedlisthdr', HDR),
('nextnode', POOLNODEPTR)))
def __init__(self, chunk_size=DEFAULT_CHUNK_SIZE, start_heap_size=4096):
+ GCBase.__init__(self)
self.heap_usage = 0 # at the end of the latest collection
self.bytes_malloced = 0 # since the latest collection
self.bytes_malloced_threshold = start_heap_size
@@ -50,7 +74,6 @@
# these are usually only the small bits of memory that make a
# weakref object
self.objects_with_weak_pointers = lltype.nullptr(self.HDR)
- self.gcheaderbuilder = GCHeaderBuilder(self.HDR)
# pools, for x_swap_pool():
# 'curpool' is the current pool, lazily allocated (i.e. NULL means
# the current POOL object is not yet malloc'ed). POOL objects are
@@ -97,15 +120,15 @@
if not result:
raise memoryError
hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR)
- hdr.typeid = typeid << 1
+ hdr.typeptr = typeid
if has_finalizer:
- hdr.next = self.malloced_objects_with_finalizer
+ hdr.setnext_clear(self.malloced_objects_with_finalizer)
self.malloced_objects_with_finalizer = hdr
elif contains_weakptr:
- hdr.next = self.objects_with_weak_pointers
+ hdr.setnext_clear(self.objects_with_weak_pointers)
self.objects_with_weak_pointers = hdr
else:
- hdr.next = self.malloced_objects
+ hdr.setnext_clear(self.malloced_objects)
self.malloced_objects = hdr
self.bytes_malloced = bytes_malloced
result += size_gc_header
@@ -132,15 +155,15 @@
raise memoryError
raw_memclear(result, tot_size)
hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR)
- hdr.typeid = typeid << 1
+ hdr.typeptr = typeid
if has_finalizer:
- hdr.next = self.malloced_objects_with_finalizer
+ hdr.setnext_clear(self.malloced_objects_with_finalizer)
self.malloced_objects_with_finalizer = hdr
elif contains_weakptr:
- hdr.next = self.objects_with_weak_pointers
+ hdr.setnext_clear(self.objects_with_weak_pointers)
self.objects_with_weak_pointers = hdr
else:
- hdr.next = self.malloced_objects
+ hdr.setnext_clear(self.malloced_objects)
self.malloced_objects = hdr
self.bytes_malloced = bytes_malloced
result += size_gc_header
@@ -169,12 +192,12 @@
raise memoryError
(result + size_gc_header + offset_to_length).signed[0] = length
hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR)
- hdr.typeid = typeid << 1
+ hdr.typeptr = typeid
if has_finalizer:
- hdr.next = self.malloced_objects_with_finalizer
+ hdr.setnext_clear(self.malloced_objects_with_finalizer)
self.malloced_objects_with_finalizer = hdr
else:
- hdr.next = self.malloced_objects
+ hdr.setnext_clear(self.malloced_objects)
self.malloced_objects = hdr
self.bytes_malloced = bytes_malloced
@@ -207,12 +230,12 @@
raw_memclear(result, tot_size)
(result + size_gc_header + offset_to_length).signed[0] = length
hdr = llmemory.cast_adr_to_ptr(result, self.HDRPTR)
- hdr.typeid = typeid << 1
+ hdr.typeptr = typeid
if has_finalizer:
- hdr.next = self.malloced_objects_with_finalizer
+ hdr.setnext_clear(self.malloced_objects_with_finalizer)
self.malloced_objects_with_finalizer = hdr
else:
- hdr.next = self.malloced_objects
+ hdr.setnext_clear(self.malloced_objects)
self.malloced_objects = hdr
self.bytes_malloced = bytes_malloced
@@ -259,20 +282,19 @@
# survive the collection
hdr = self.malloced_objects_with_finalizer
while hdr:
- next = hdr.next
- typeid = hdr.typeid >> 1
gc_info = llmemory.cast_ptr_to_adr(hdr)
obj = gc_info + size_gc_header
- if not hdr.typeid & 1:
+ if not hdr.ismarked():
self.add_reachable_to_stack(obj, objects)
addr = llmemory.cast_ptr_to_adr(hdr)
+ typeid = hdr.typeptr
size = self.fixed_size(typeid)
if self.is_varsize(typeid):
length = (obj + self.varsize_offset_to_length(typeid)).signed[0]
size += self.varsize_item_sizes(typeid) * length
estimate = raw_malloc_usage(size_gc_header + size)
curr_heap_size += estimate
- hdr = next
+ hdr = hdr.getnext()
# mark thinks on the mark stack and put their descendants onto the
# stack until the stack is empty
@@ -280,31 +302,29 @@
curr = objects.pop()
gc_info = curr - size_gc_header
hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR)
- if hdr.typeid & 1:
+ if hdr.ismarked():
continue
self.add_reachable_to_stack(curr, objects)
- hdr.typeid = hdr.typeid | 1
+ hdr.setmark()
objects.delete()
# also mark self.curpool
if self.curpool:
gc_info = llmemory.cast_ptr_to_adr(self.curpool) - size_gc_header
hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR)
- hdr.typeid = hdr.typeid | 1
+ hdr.setmark()
# go through the list of objects containing weak pointers
# and kill the links if they go to dead objects
# if the object itself is not marked, free it
hdr = self.objects_with_weak_pointers
surviving = lltype.nullptr(self.HDR)
while hdr:
- typeid = hdr.typeid >> 1
- next = hdr.next
+ typeid = hdr.typeptr
+ next = hdr.getnext()
addr = llmemory.cast_ptr_to_adr(hdr)
size = self.fixed_size(typeid)
estimate = raw_malloc_usage(size_gc_header + size)
- if hdr.typeid & 1:
- typeid = hdr.typeid >> 1
+ if hdr.ismarked():
offset = self.weakpointer_offset(typeid)
- hdr.typeid = hdr.typeid & (~1)
gc_info = llmemory.cast_ptr_to_adr(hdr)
weakref_obj = gc_info + size_gc_header
pointing_to = (weakref_obj + offset).address[0]
@@ -315,9 +335,9 @@
# pointed to object will die
# XXX what to do if the object has a finalizer which resurrects
# the object?
- if not hdr_pointing_to.typeid & 1:
+ if not hdr_pointing_to.ismarked():
(weakref_obj + offset).address[0] = NULL
- hdr.next = surviving
+ hdr.setnext_clear(surviving) # this also clears the mark
surviving = hdr
curr_heap_size += estimate
else:
@@ -331,28 +351,27 @@
# sweep: delete objects without del if they are not marked
# unmark objects without del that are marked
firstpoolnode = lltype.malloc(self.POOLNODE, flavor='raw')
- firstpoolnode.linkedlist = self.malloced_objects
+ firstpoolnode.linkedlisthdr.setnext_clear(self.malloced_objects)
firstpoolnode.nextnode = self.poolnodes
prevpoolnode = lltype.nullptr(self.POOLNODE)
poolnode = firstpoolnode
while poolnode: #sweep
- ppnext = llmemory.cast_ptr_to_adr(poolnode)
- ppnext += llmemory.offsetof(self.POOLNODE, 'linkedlist')
- hdr = poolnode.linkedlist
+ previous = poolnode.linkedlisthdr
+ hdr = previous.getnext()
while hdr: #sweep
- typeid = hdr.typeid >> 1
- next = hdr.next
+ typeid = hdr.typeptr
+ next = hdr.getnext()
addr = llmemory.cast_ptr_to_adr(hdr)
size = self.fixed_size(typeid)
if self.is_varsize(typeid):
length = (addr + size_gc_header + self.varsize_offset_to_length(typeid)).signed[0]
size += self.varsize_item_sizes(typeid) * length
estimate = raw_malloc_usage(size_gc_header + size)
- if hdr.typeid & 1:
- hdr.typeid = hdr.typeid & (~1)
- ppnext.address[0] = addr
- ppnext = llmemory.cast_ptr_to_adr(hdr)
- ppnext += llmemory.offsetof(self.HDR, 'next')
+ if hdr.ismarked():
+ # hdr.clearmark() -- done automatically by the
+ # call to setnext_clear() that will follow
+ previous.setnext_clear(hdr)
+ previous = hdr
curr_heap_size += estimate
else:
gc_info = llmemory.cast_ptr_to_adr(hdr)
@@ -361,16 +380,16 @@
freed_size += estimate
raw_free(addr)
hdr = next
- ppnext.address[0] = llmemory.NULL
+ previous.setnext_clear(lltype.nullptr(self.HDR))
next = poolnode.nextnode
- if not poolnode.linkedlist and prevpoolnode:
+ if not poolnode.linkedlisthdr.getnext() and prevpoolnode:
# completely empty node
prevpoolnode.nextnode = next
lltype.free(poolnode, flavor='raw')
else:
prevpoolnode = poolnode
poolnode = next
- self.malloced_objects = firstpoolnode.linkedlist
+ self.malloced_objects = firstpoolnode.linkedlisthdr.getnext()
self.poolnodes = firstpoolnode.nextnode
lltype.free(firstpoolnode, flavor='raw')
#llop.debug_view(lltype.Void, self.malloced_objects, self.malloced_objects_with_finalizer, size_gc_header)
@@ -431,25 +450,24 @@
self.malloced_objects_with_finalizer = lltype.nullptr(self.HDR)
last = lltype.nullptr(self.HDR)
while hdr:
- next = hdr.next
- if hdr.typeid & 1:
- hdr.next = lltype.nullptr(self.HDR)
+ next = hdr.getnext()
+ if hdr.ismarked():
+ hdr.setnext_clear(lltype.nullptr(self.HDR)) # also clears mark
if not self.malloced_objects_with_finalizer:
self.malloced_objects_with_finalizer = hdr
else:
- last.next = hdr
- hdr.typeid = hdr.typeid & (~1)
+ last.setnext_clear(hdr)
last = hdr
else:
obj = llmemory.cast_ptr_to_adr(hdr) + size_gc_header
- finalizer = self.getfinalizer(hdr.typeid >> 1)
+ finalizer = self.getfinalizer(hdr.typeptr)
# make malloced_objects_with_finalizer consistent
# for the sake of a possible collection caused by finalizer
if not self.malloced_objects_with_finalizer:
self.malloced_objects_with_finalizer = next
else:
- last.next = next
- hdr.next = self.malloced_objects
+ last.setnext_clear(next)
+ hdr.setnext_clear(self.malloced_objects)
self.malloced_objects = hdr
#llop.debug_view(lltype.Void, self.malloced_objects, self.malloced_objects_with_finalizer, size_gc_header)
finalizer(obj)
@@ -464,11 +482,11 @@
# now it gets annoying: finalizer caused a malloc of something
# with a finalizer
last = self.malloced_objects_with_finalizer
- while last.next != next:
- last = last.next
- last.next = lltype.nullptr(self.HDR)
+ while last.getnext() != next:
+ last = last.getnext()
+ last.setnext_clear(lltype.nullptr(self.HDR))
else:
- last.next = lltype.nullptr(self.HDR)
+ last.setnext_clear(lltype.nullptr(self.HDR))
hdr = next
self.collect_in_progress = False
@@ -482,7 +500,7 @@
size_gc_header = self.gcheaderbuilder.size_gc_header
gc_info = gcobjectaddr - size_gc_header
hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR)
- hdr.typeid = hdr.typeid & (~1)
+ hdr.clearmark()
STAT_HEAP_USAGE = 0
STAT_BYTES_MALLOCED = 1
@@ -492,7 +510,7 @@
size_gc_header = self.gcheaderbuilder.size_gc_header
gc_info = obj - size_gc_header
hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR)
- return hdr.typeid >> 1
+ return hdr.typeptr
def add_reachable_to_stack(self, obj, objects):
self.trace(obj, self._add_reachable, objects)
@@ -511,15 +529,10 @@
return self.bytes_malloced
return -1
- def init_gc_object(self, addr, typeid):
- hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR)
- hdr.typeid = typeid << 1
-
- def init_gc_object_immortal(self, addr, typeid, flags=0):
+ def init_gc_object_immortal(self, hdr, typeid):
# prebuilt gc structures always have the mark bit set
- # ignore flags
- hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR)
- hdr.typeid = (typeid << 1) | 1
+ hdr.typeptr = typeid
+ hdr.setmark()
# experimental support for thread cloning
def x_swap_pool(self, newpool):
@@ -542,7 +555,7 @@
hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR)
# put this new POOL object in the poolnodes list
node = lltype.malloc(self.POOLNODE, flavor="raw")
- node.linkedlist = hdr
+ node.linkedlisthdr.setnext_clear(hdr)
node.nextnode = self.poolnodes
self.poolnodes = node
else:
@@ -550,7 +563,7 @@
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
+ hdr.setnext_clear(self.malloced_objects)
newpool = lltype.cast_opaque_ptr(self.POOLPTR, newpool)
if newpool:
@@ -558,11 +571,11 @@
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
+ self.malloced_objects = hdr.getnext()
# invariant: now that objects in the hdr.next list are accessible
# through self.malloced_objects, make sure they are not accessible
# via poolnodes (which has a node pointing to newpool):
- hdr.next = lltype.nullptr(self.HDR)
+ hdr.setnext_clear(lltype.nullptr(self.HDR))
else:
# start a fresh new linked list
self.malloced_objects = lltype.nullptr(self.HDR)
@@ -575,7 +588,6 @@
# 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.
- CURPOOL_FLAG = sys.maxint // 2 + 1
# install a new pool into which all the mallocs go
curpool = self.x_swap_pool(lltype.nullptr(X_POOL))
@@ -589,11 +601,13 @@
addr -= size_gc_header
hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR)
- hdr = hdr.next # skip the POOL object itself
+ hdr = hdr.getnext() # skip the POOL object itself
while hdr:
- next = hdr.next
- hdr.typeid |= CURPOOL_FLAG # mark all objects from malloced_list
- hdr.next = lltype.nullptr(self.HDR) # abused to point to the copy
+ next = hdr.getnext()
+ # 'hdr.next' is abused to point to the copy
+ ll_assert(not hdr.ismarked(), "x_clone: object already marked")
+ hdr.setnext_clear(lltype.nullptr(self.HDR))
+ hdr.setmark() # mark all objects from malloced_list
oldobjects.append(llmemory.cast_ptr_to_adr(hdr))
hdr = next
@@ -609,12 +623,11 @@
continue # pointer is NULL
oldhdr = llmemory.cast_adr_to_ptr(oldobj_addr - size_gc_header,
self.HDRPTR)
- typeid = oldhdr.typeid
- if not (typeid & CURPOOL_FLAG):
+ if not oldhdr.ismarked():
continue # ignore objects that were not in the malloced_list
- newhdr = oldhdr.next # abused to point to the copy
+ newhdr = oldhdr.getnext() # abused to point to the copy
if not newhdr:
- typeid = (typeid & ~CURPOOL_FLAG) >> 1
+ typeid = hdr.typeptr
size = self.fixed_size(typeid)
# XXX! collect() at the beginning if the free heap is low
if self.is_varsize(typeid):
@@ -640,11 +653,11 @@
newhdr_addr = newobj_addr - size_gc_header
newhdr = llmemory.cast_adr_to_ptr(newhdr_addr, self.HDRPTR)
- saved_id = newhdr.typeid # XXX hack needed for genc
- saved_next = newhdr.next # where size_gc_header == 0
+ saved_tid = newhdr.typeptr # XXX hack needed for genc
+ saved_next = newhdr.next_and_flags # where size_gc_header == 0
raw_memcopy(oldobj_addr, newobj_addr, size)
- newhdr.typeid = saved_id
- newhdr.next = saved_next
+ newhdr.typeptr = saved_tid
+ newhdr.next_and_flags = saved_next
offsets = self.offsets_to_gc_pointers(typeid)
i = 0
@@ -669,7 +682,8 @@
j += 1
i += 1
- oldhdr.next = newhdr
+ oldhdr.setnext_clear(newhdr)
+ oldhdr.setmark()
newobj_addr = llmemory.cast_ptr_to_adr(newhdr) + size_gc_header
gcptr_addr.address[0] = newobj_addr
stack.delete()
@@ -678,8 +692,7 @@
next = lltype.nullptr(self.HDR)
while oldobjects.non_empty():
hdr = llmemory.cast_adr_to_ptr(oldobjects.pop(), self.HDRPTR)
- hdr.typeid &= ~CURPOOL_FLAG # reset the flag
- hdr.next = next
+ hdr.setnext_clear(next) # this also resets the mark
next = hdr
oldobjects.delete()
@@ -687,7 +700,7 @@
addr = llmemory.cast_ptr_to_adr(oldpool)
addr -= size_gc_header
hdr = llmemory.cast_adr_to_ptr(addr, self.HDRPTR)
- assert hdr.next == next
+ ll_assert(hdr.getnext() == next, "bad .next at the end of x_clone")
# build the new pool object collecting the new objects, and
# reinstall the pool that was current at the beginning of x_clone()
Modified: pypy/branch/unified-rtti/pypy/rpython/memory/gcheader.py
==============================================================================
--- pypy/branch/unified-rtti/pypy/rpython/memory/gcheader.py (original)
+++ pypy/branch/unified-rtti/pypy/rpython/memory/gcheader.py Fri Feb 22 13:06:08 2008
@@ -17,6 +17,7 @@
self.rtti2typeinfo = weakref.WeakKeyDictionary()
self.size_gc_header = llmemory.GCHeaderOffset(self)
self.size_gc_typeinfo = llmemory.GCTypeInfoOffset(self)
+ self.rtticache = {}
def header_of_object(self, gcptr):
# XXX hackhackhack
@@ -68,5 +69,8 @@
addr += self.size_gc_typeinfo
return llmemory.cast_adr_to_ptr(addr, lltype.Ptr(self.TYPEINFO))
+ def getRtti(self, TYPE):
+ return lltype.getRuntimeTypeInfo(TYPE, self.rtticache)
+
def _freeze_(self):
return True # for reads of size_gc_header
Modified: pypy/branch/unified-rtti/pypy/rpython/memory/gctransform/refcounting.py
==============================================================================
--- pypy/branch/unified-rtti/pypy/rpython/memory/gctransform/refcounting.py (original)
+++ pypy/branch/unified-rtti/pypy/rpython/memory/gctransform/refcounting.py Fri Feb 22 13:06:08 2008
@@ -148,7 +148,7 @@
llops.genop("direct_call", [self.decrefptr, v_adr])
def gct_fv_gc_malloc(self, hop, flags, TYPE, c_size):
- rtti = lltype.getRuntimeTypeInfo(TYPE, self.rtticache)
+ rtti = self.gcheaderbuilder.getTypeInfo(TYPE)
c_rtti = rmodel.inputconst(RTTIPTR, rtti)
v_raw = hop.genop("direct_call",
[self.malloc_fixedsize_ptr, c_size, c_rtti],
@@ -157,7 +157,7 @@
def gct_fv_gc_malloc_varsize(self, hop, flags, TYPE, v_length, c_const_size, c_item_size,
c_offset_to_length):
- rtti = lltype.getRuntimeTypeInfo(TYPE, self.rtticache)
+ rtti = self.gcheaderbuilder.getTypeInfo(TYPE)
c_rtti = rmodel.inputconst(RTTIPTR, rtti)
if c_offset_to_length is None:
v_raw = hop.genop("direct_call",
@@ -187,7 +187,7 @@
return # you don't really have an RPython deallocator for PyObjects
assert TYPE._gckind == 'gc'
- rtti = lltype.getRuntimeTypeInfo(TYPE, self.rtticache)
+ rtti = self.gcheaderbuilder.getTypeInfo(TYPE)
destrptr = rtti.destructor_funcptr
if destrptr is not None:
DESTR_ARG = lltype.typeOf(destrptr).TO.ARGS[0]
Modified: pypy/branch/unified-rtti/pypy/rpython/memory/gctransform/transform.py
==============================================================================
--- pypy/branch/unified-rtti/pypy/rpython/memory/gctransform/transform.py (original)
+++ pypy/branch/unified-rtti/pypy/rpython/memory/gctransform/transform.py Fri Feb 22 13:06:08 2008
@@ -534,7 +534,6 @@
# at the moment, all GC transformers are based on a GCHeaderBuilder.
self.gcheaderbuilder = gcheaderbuilder
self.gchelpers = GCHelpers(gcheaderbuilder)
- self.rtticache = {}
if self.translator:
self.gc_runtime_type_info_ptr = self.inittime_helper(
self.gchelpers.gc_runtime_type_info, [llmemory.Address],
@@ -683,7 +682,7 @@
p = value._as_ptr()
if not self.gcheaderbuilder.get_header(p):
hdr = self.gcheaderbuilder.new_header(p)
- hdr.typeptr = lltype.getRuntimeTypeInfo(TYPE, self.rtticache)
+ hdr.typeptr = self.gcheaderbuilder.getTypeInfo(TYPE)
self.initialize_constant_header(hdr, TYPE, value)
def initialize_constant_header(self, hdr, TYPE, value):
Modified: pypy/branch/unified-rtti/pypy/rpython/memory/gctypelayout.py
==============================================================================
--- pypy/branch/unified-rtti/pypy/rpython/memory/gctypelayout.py (original)
+++ pypy/branch/unified-rtti/pypy/rpython/memory/gctypelayout.py Fri Feb 22 13:06:08 2008
@@ -28,37 +28,52 @@
("weakptrofs", lltype.Signed),
)
- def q_is_varsize(self, typeinfo):
+ def __init__(self, gcheaderbuilder):
+ self.gcheaderbuilder = gcheaderbuilder
+ self.cast_rtti_to_typeinfo = gcheaderbuilder.cast_rtti_to_typeinfo
+
+ def q_is_varsize(self, typeid):
+ typeinfo = self.cast_rtti_to_typeinfo(typeid)
return (typeinfo.flags & T_IS_VARSIZE) != 0
- def q_has_gcptr_in_varsize(self, typeinfo):
+ def q_has_gcptr_in_varsize(self, typeid):
+ typeinfo = self.cast_rtti_to_typeinfo(typeid)
return (typeinfo.flags & T_HAS_GCPTR_IN_VARSIZE) != 0
- def q_is_gcarrayofgcptr(self, typeinfo):
+ def q_is_gcarrayofgcptr(self, typeid):
+ typeinfo = self.cast_rtti_to_typeinfo(typeid)
return (typeinfo.flags & T_IS_GCARRAYOFGCPTR) != 0
- def q_finalizer(self, typeinfo):
+ def q_finalizer(self, typeid):
+ typeinfo = self.cast_rtti_to_typeinfo(typeid)
return typeinfo.finalizer
- def q_offsets_to_gc_pointers(self, typeinfo):
+ def q_offsets_to_gc_pointers(self, typeid):
+ typeinfo = self.cast_rtti_to_typeinfo(typeid)
return typeinfo.ofstoptrs
- def q_fixed_size(self, typeinfo):
+ def q_fixed_size(self, typeid):
+ typeinfo = self.cast_rtti_to_typeinfo(typeid)
return typeinfo.fixedsize
- def q_varsize_item_sizes(self, typeinfo):
+ def q_varsize_item_sizes(self, typeid):
+ typeinfo = self.cast_rtti_to_typeinfo(typeid)
return typeinfo.varitemsize
- def q_varsize_offset_to_variable_part(self, typeinfo):
+ def q_varsize_offset_to_variable_part(self, typeid):
+ typeinfo = self.cast_rtti_to_typeinfo(typeid)
return typeinfo.ofstovar
- def q_varsize_offset_to_length(self, typeinfo):
+ def q_varsize_offset_to_length(self, typeid):
+ typeinfo = self.cast_rtti_to_typeinfo(typeid)
return typeinfo.ofstolength
- def q_varsize_offsets_to_gcpointers_in_var_part(self, typeinfo):
+ def q_varsize_offsets_to_gcpointers_in_var_part(self, typeid):
+ typeinfo = self.cast_rtti_to_typeinfo(typeid)
return typeinfo.varofstoptrs
- def q_weakpointer_offset(self, typeinfo):
+ def q_weakpointer_offset(self, typeid):
+ typeinfo = self.cast_rtti_to_typeinfo(typeid)
return typeinfo.weakptrofs
def set_query_functions(self, gc):
@@ -152,8 +167,8 @@
class TypeLayoutBuilder(object):
- def __init__(self):
- self.typeinfos = {} # {LLTYPE: TYPE_INFO}
+ def __init__(self, gcheaderbuilder):
+ self.id_of_type = {} # {LLTYPE: fully-initialized-RTTIPTR}
self.seen_roots = {}
# the following are lists of addresses of gc pointers living inside the
# prebuilt structures. It should list all the locations that could
@@ -168,17 +183,25 @@
self.additional_roots_sources = 0
self.finalizer_funcptrs = {}
self.offsettable_cache = {}
+ self.gcheaderbuilder = gcheaderbuilder
+ assert gcheaderbuilder.TYPEINFO == GCData.TYPE_INFO
- def get_type_info(self, TYPE):
+ def get_type_id(self, TYPE):
+ """The 'typeid' of a TYPE is an opaque RTTIPTR; this is the
+ same pointer as the 'type info', but the latter is not opaque.
+ """
try:
- return self.typeinfos[TYPE]
+ return self.id_of_type[TYPE]
except KeyError:
- assert isinstance(TYPE, (lltype.GcStruct, lltype.GcArray))
# Record the new type description as a TYPE_INFO structure.
- info = lltype.malloc(GCData.TYPE_INFO, immortal=True, zero=True)
- encode_type_shape(self, info, TYPE)
- self.typeinfos[TYPE] = info
- return info
+ rtti = self.gcheaderbuilder.getRtti(TYPE)
+ try:
+ self.gcheaderbuilder.typeinfo_from_rtti(rtti)
+ except KeyError:
+ typeinfo = self.gcheaderbuilder.new_typeinfo(rtti)
+ encode_type_shape(self, typeinfo, TYPE)
+ self.id_of_type[TYPE] = rtti
+ return rtti
def offsets2table(self, offsets, TYPE):
try:
@@ -203,7 +226,7 @@
return lltype.nullptr(GCData.ADDRESS_VOID_FUNC)
def initialize_gc_query_function(self, gc):
- return GCData(self.type_info_list).set_query_functions(gc)
+ return GCData(self.gcheaderbuilder).set_query_functions(gc)
def consider_constant(self, TYPE, value, gc):
if value is not lltype.top_container(value):
@@ -213,10 +236,9 @@
self.seen_roots[id(value)] = True
if isinstance(TYPE, (lltype.GcStruct, lltype.GcArray)):
- typeinfo = self.get_type_info(TYPE)
+ typeid = self.get_type_id(TYPE)
hdr = gc.gcheaderbuilder.new_header(value)
- adr = llmemory.cast_ptr_to_adr(hdr)
- gc.init_gc_object_immortal(adr, typeinfo)
+ gc.init_gc_object_immortal(hdr, typeid)
# The following collects the addresses of all the fields that have
# a GC Pointer type, inside the current prebuilt object. All such
Modified: pypy/branch/unified-rtti/pypy/rpython/memory/gcwrapper.py
==============================================================================
--- pypy/branch/unified-rtti/pypy/rpython/memory/gcwrapper.py (original)
+++ pypy/branch/unified-rtti/pypy/rpython/memory/gcwrapper.py Fri Feb 22 13:06:08 2008
@@ -15,7 +15,8 @@
self.gc.setup()
def prepare_graphs(self, flowgraphs):
- layoutbuilder = DirectRunLayoutBuilder(self.llinterp)
+ layoutbuilder = DirectRunLayoutBuilder(self.gc.gcheaderbuilder,
+ self.llinterp)
self.get_type_id = layoutbuilder.get_type_id
layoutbuilder.initialize_gc_query_function(self.gc)
@@ -85,8 +86,8 @@
# we have to be lazy in reading the llinterp variable containing
# the 'obj' pointer, because the gc.malloc() call below could
# move it around
- type_id = self.get_type_id(gctypelayout.WEAKREF)
- addr = self.gc.malloc(type_id, None, zero=False)
+ type_info = self.get_type_info(gctypelayout.WEAKREF)
+ addr = self.gc.malloc(type_info, None, zero=False)
result = llmemory.cast_adr_to_ptr(addr, gctypelayout.WEAKREFPTR)
result.weakptr = llmemory.cast_ptr_to_adr(objgetter())
return llmemory.cast_ptr_to_weakrefptr(result)
@@ -132,16 +133,16 @@
class DirectRunLayoutBuilder(gctypelayout.TypeLayoutBuilder):
- def __init__(self, llinterp):
+ def __init__(self, gcheaderbuilder, llinterp):
self.llinterp = llinterp
- super(DirectRunLayoutBuilder, self).__init__()
+ super(DirectRunLayoutBuilder, self).__init__(gcheaderbuilder)
def make_finalizer_funcptr_for_type(self, TYPE):
- from pypy.rpython.memory.gctransform.support import get_rtti, \
+ from pypy.rpython.memory.gctransform.support import \
type_contains_pyobjs
- rtti = get_rtti(TYPE)
- if rtti is not None and hasattr(rtti._obj, 'destructor_funcptr'):
- destrptr = rtti._obj.destructor_funcptr
+ rtti = self.gcheaderbuilder.getRtti(TYPE)
+ destrptr = rtti.destructor_funcptr
+ if destrptr is not None:
DESTR_ARG = lltype.typeOf(destrptr).TO.ARGS[0]
destrgraph = destrptr._obj.graph
else:
Modified: pypy/branch/unified-rtti/pypy/rpython/memory/support.py
==============================================================================
--- pypy/branch/unified-rtti/pypy/rpython/memory/support.py (original)
+++ pypy/branch/unified-rtti/pypy/rpython/memory/support.py Fri Feb 22 13:06:08 2008
@@ -2,6 +2,7 @@
from pypy.rlib.objectmodel import free_non_gc_object, we_are_translated
from pypy.rlib.debug import ll_assert
+RTTIPTR = lltype.Ptr(lltype.RuntimeTypeInfo)
DEFAULT_CHUNK_SIZE = 1019
More information about the Pypy-commit
mailing list