[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