[pypy-svn] r68397 - in pypy/branch/gc-hash/pypy: rpython/memory/gc rpython/memory/gctransform translator/c/test

arigo at codespeak.net arigo at codespeak.net
Tue Oct 13 21:38:25 CEST 2009


Author: arigo
Date: Tue Oct 13 21:38:23 2009
New Revision: 68397

Modified:
   pypy/branch/gc-hash/pypy/rpython/memory/gc/marksweep.py
   pypy/branch/gc-hash/pypy/rpython/memory/gc/semispace.py
   pypy/branch/gc-hash/pypy/rpython/memory/gctransform/framework.py
   pypy/branch/gc-hash/pypy/translator/c/test/test_newgc.py
Log:
Test passes with the semispace GC after collections
that move data around.


Modified: pypy/branch/gc-hash/pypy/rpython/memory/gc/marksweep.py
==============================================================================
--- pypy/branch/gc-hash/pypy/rpython/memory/gc/marksweep.py	(original)
+++ pypy/branch/gc-hash/pypy/rpython/memory/gc/marksweep.py	Tue Oct 13 21:38:23 2009
@@ -707,9 +707,7 @@
 
     def identityhash(self, obj):
         obj = llmemory.cast_ptr_to_adr(obj)
-        size_gc_header = self.gcheaderbuilder.size_gc_header
-        gc_info = obj - size_gc_header
-        hdr = llmemory.cast_adr_to_ptr(gc_info, self.HDRPTR)
+        hdr = self.header(obj)
         if ord(hdr.flags) & FL_WITHHASH:
             obj += self.get_size(obj)
             return obj.signed[0]

Modified: pypy/branch/gc-hash/pypy/rpython/memory/gc/semispace.py
==============================================================================
--- pypy/branch/gc-hash/pypy/rpython/memory/gc/semispace.py	(original)
+++ pypy/branch/gc-hash/pypy/rpython/memory/gc/semispace.py	Tue Oct 13 21:38:23 2009
@@ -19,6 +19,8 @@
 # either immortal objects or (for HybridGC) externally raw_malloc'ed
 GCFLAG_EXTERNAL = first_gcflag << 1
 GCFLAG_FINALIZATION_ORDERING = first_gcflag << 2
+GCFLAG_HASHTAKEN = first_gcflag << 3      # someone already asked for the hash
+GCFLAG_HASHFIELD = first_gcflag << 4      # we have an extra hash field
 
 memoryError = MemoryError()
 
@@ -28,12 +30,13 @@
     inline_simple_malloc = True
     inline_simple_malloc_varsize = True
     malloc_zero_filled = True
-    first_unused_gcflag = first_gcflag << 3
+    first_unused_gcflag = first_gcflag << 5
     total_collection_time = 0.0
     total_collection_count = 0
 
     HDR = lltype.Struct('header', ('tid', lltype.Signed))   # XXX or rffi.INT?
     typeid_is_in_field = 'tid'
+    withhash_flag_is_in_field = 'tid', (GCFLAG_HASHTAKEN|GCFLAG_HASHFIELD)
     FORWARDSTUB = lltype.GcStruct('forwarding_stub',
                                   ('forw', llmemory.Address))
     FORWARDSTUBPTR = lltype.Ptr(FORWARDSTUB)
@@ -297,11 +300,19 @@
             if free_after_collection < self.space_size // 5:
                 self.red_zone += 1
 
+    def extra_hash_space(self, obj):
+        hdr = self.header(obj)
+        if hdr.tid & GCFLAG_HASHFIELD:
+            return llmemory.sizeof(lltype.Signed)
+        else:
+            return 0
+
     def scan_copied(self, scan):
         while scan < self.free:
             curr = scan + self.size_gc_header()
             self.trace_and_copy(curr)
-            scan += self.size_gc_header() + self.get_size(curr)
+            scan += (self.size_gc_header() + self.get_size(curr)
+                                           + self.extra_hash_space(curr))
         return scan
 
     def collect_roots(self):
@@ -331,9 +342,21 @@
     def make_a_copy(self, obj, objsize):
         totalsize = self.size_gc_header() + objsize
         newaddr = self.free
-        self.free += totalsize
         llarena.arena_reserve(newaddr, totalsize)
         raw_memcopy(obj - self.size_gc_header(), newaddr, totalsize)
+        #
+        # check if we need to write a hash value at the end of the new obj
+        newhdr = llmemory.cast_adr_to_ptr(newaddr, lltype.Ptr(self.HDR))
+        if newhdr.tid & (GCFLAG_HASHTAKEN|GCFLAG_HASHFIELD):
+            if newhdr.tid & GCFLAG_HASHFIELD:
+                hash = (obj + self.get_size(obj)).signed[0]
+            else:
+                hash = llmemory.cast_adr_to_int(obj)
+                newhdr.tid |= GCFLAG_HASHFIELD
+            (newaddr + totalsize).signed[0] = hash
+            totalsize += llmemory.sizeof(lltype.Signed)
+        #
+        self.free += totalsize
         newobj = newaddr + self.size_gc_header()
         return newobj
 
@@ -570,3 +593,12 @@
 
     STATISTICS_NUMBERS = 0
 
+    def identityhash(self, obj):
+        obj = llmemory.cast_ptr_to_adr(obj)
+        hdr = self.header(obj)
+        if hdr.tid & GCFLAG_HASHFIELD:
+            obj += self.get_size(obj)
+            return obj.signed[0]
+        else:
+            hdr.tid |= GCFLAG_HASHTAKEN
+            return llmemory.cast_adr_to_int(obj)

Modified: pypy/branch/gc-hash/pypy/rpython/memory/gctransform/framework.py
==============================================================================
--- pypy/branch/gc-hash/pypy/rpython/memory/gctransform/framework.py	(original)
+++ pypy/branch/gc-hash/pypy/rpython/memory/gctransform/framework.py	Tue Oct 13 21:38:23 2009
@@ -439,7 +439,7 @@
     def gc_field_values_for(self, obj):
         hdr = self.gcdata.gc.gcheaderbuilder.header_of_object(obj)
         HDR = self._gc_HDR
-        withhash, flag = self.gcdata.gc.withhash_flag_is_in_field
+        withhash, flags = self.gcdata.gc.withhash_flag_is_in_field
         result = []
         for fldname in HDR._names:
             x = getattr(hdr, fldname)
@@ -447,9 +447,9 @@
                 TYPE = lltype.typeOf(x)
                 x = lltype.cast_primitive(lltype.Signed, x)
                 if hasattr(obj._normalizedcontainer(), '_hash_cache_'):
-                    x |= flag
+                    x |= flags       # set the flag(s) in the header
                 else:
-                    x &= ~flag
+                    x &= ~flags      # clear the flag(s) in the header
                 x = lltype.cast_primitive(TYPE, x)
             result.append(x)
         return result

Modified: pypy/branch/gc-hash/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/branch/gc-hash/pypy/translator/c/test/test_newgc.py	(original)
+++ pypy/branch/gc-hash/pypy/translator/c/test/test_newgc.py	Tue Oct 13 21:38:23 2009
@@ -702,11 +702,17 @@
         h_t = compute_hash(("Hi", None, (7.5, 2, d)))
         #
         def f():
-            d2 = D()
-            if compute_hash(d2) != current_object_addr_as_int(d2): return 11
             if compute_hash(c) != compute_hash(c): return 12
             if compute_hash(d) != h_d: return 13
             if compute_hash(("Hi", None, (7.5, 2, d))) != h_t: return 14
+            c2 = C()
+            h_c2 = compute_hash(c2)
+            if compute_hash(c2) != h_c2: return 15
+            i = 0
+            while i < 6:
+                rgc.collect()
+                if compute_hash(c2) != h_c2: return i
+                i += 1
             return 42
         return f
 



More information about the Pypy-commit mailing list