[pypy-svn] r78907 - in pypy/trunk/pypy: jit/backend/llsupport jit/backend/x86 jit/backend/x86/test rpython/memory/gc

arigo at codespeak.net arigo at codespeak.net
Tue Nov 9 10:11:13 CET 2010


Author: arigo
Date: Tue Nov  9 10:11:11 2010
New Revision: 78907

Modified:
   pypy/trunk/pypy/jit/backend/llsupport/gc.py
   pypy/trunk/pypy/jit/backend/x86/assembler.py
   pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_gc.py
   pypy/trunk/pypy/rpython/memory/gc/minimark.py
   pypy/trunk/pypy/rpython/memory/gc/semispace.py
Log:
Test and fix for an obscure crash that shows up
on the JIT with (preferencially) 64-bit versions.

The issue is that the JIT did not respect the minimal
allocation size in the nursery.  This gives strange
effects at the next minor collection.


Modified: pypy/trunk/pypy/jit/backend/llsupport/gc.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/llsupport/gc.py	(original)
+++ pypy/trunk/pypy/jit/backend/llsupport/gc.py	Tue Nov  9 10:11:11 2010
@@ -19,6 +19,7 @@
 # ____________________________________________________________
 
 class GcLLDescription(GcCache):
+    minimal_size_in_nursery = 0
     def __init__(self, gcdescr, translator=None, rtyper=None):
         GcCache.__init__(self, translator is not None, rtyper)
         self.gcdescr = gcdescr
@@ -386,6 +387,7 @@
         (self.array_basesize, _, self.array_length_ofs) = \
              symbolic.get_array_token(lltype.GcArray(lltype.Signed), True)
         self.max_size_of_young_obj = self.GCClass.JIT_max_size_of_young_obj()
+        self.minimal_size_in_nursery=self.GCClass.JIT_minimal_size_in_nursery()
 
         # make a malloc function, with three arguments
         def malloc_basic(size, tid):
@@ -468,6 +470,7 @@
         def malloc_fixedsize_slowpath(size):
             if self.DEBUG:
                 random_usage_of_xmm_registers()
+            assert size >= self.minimal_size_in_nursery
             try:
                 gcref = llop1.do_malloc_fixedsize_clear(llmemory.GCREF,
                                             0, size, True, False, False)

Modified: pypy/trunk/pypy/jit/backend/x86/assembler.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/x86/assembler.py	(original)
+++ pypy/trunk/pypy/jit/backend/x86/assembler.py	Tue Nov  9 10:11:11 2010
@@ -1853,6 +1853,7 @@
 
     def malloc_cond_fixedsize(self, nursery_free_adr, nursery_top_adr,
                               size, tid):
+        size = max(size, self.cpu.gc_ll_descr.minimal_size_in_nursery)
         self.mc.ensure_bytes_available(256)
         self.mc.MOV(eax, heap(nursery_free_adr))
         self.mc.LEA_rm(edx.value, (eax.value, size))

Modified: pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_gc.py
==============================================================================
--- pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_gc.py	(original)
+++ pypy/trunk/pypy/jit/backend/x86/test/test_zrpy_gc.py	Tue Nov  9 10:11:11 2010
@@ -550,3 +550,29 @@
 
     def test_compile_framework_float(self):
         self.run('compile_framework_float')
+
+    def define_compile_framework_minimal_size_in_nursery(self):
+        S = lltype.GcStruct('S')    # no fields!
+        T = lltype.GcStruct('T', ('i', lltype.Signed))
+        @unroll_safe
+        def f42(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+            lst1 = []
+            lst2 = []
+            i = 0
+            while i < 42:
+                s1 = lltype.malloc(S)
+                t1 = lltype.malloc(T)
+                t1.i = 10000 + i + n
+                lst1.append(s1)
+                lst2.append(t1)
+                i += 1
+            i = 0
+            while i < 42:
+                check(lst2[i].i == 10000 + i + n)
+                i += 1
+            n -= 1
+            return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
+        return None, f42, None
+
+    def test_compile_framework_minimal_size_in_nursery(self):
+        self.run('compile_framework_minimal_size_in_nursery')

Modified: pypy/trunk/pypy/rpython/memory/gc/minimark.py
==============================================================================
--- pypy/trunk/pypy/rpython/memory/gc/minimark.py	(original)
+++ pypy/trunk/pypy/rpython/memory/gc/minimark.py	Tue Nov  9 10:11:11 2010
@@ -77,7 +77,7 @@
 
     # During a minor collection, the objects in the nursery that are
     # moved outside are changed in-place: their header is replaced with
-    # the value -1, and the following word is set to the address of
+    # the value -42, and the following word is set to the address of
     # where the object was moved.  This means that all objects in the
     # nursery need to be at least 2 words long, but objects outside the
     # nursery don't need to.
@@ -656,10 +656,13 @@
     def is_forwarded(self, obj):
         """Returns True if the nursery obj is marked as forwarded.
         Implemented a bit obscurely by checking an unrelated flag
-        that can never be set on a young object -- except if tid == -1.
+        that can never be set on a young object -- except if tid == -42.
         """
         assert self.is_in_nursery(obj)
-        return self.header(obj).tid & GCFLAG_FINALIZATION_ORDERING
+        result = (self.header(obj).tid & GCFLAG_FINALIZATION_ORDERING != 0)
+        if result:
+            ll_assert(self.header(obj).tid == -42, "bogus header for young obj")
+        return result
 
     def get_forwarding_address(self, obj):
         return llmemory.cast_adr_to_ptr(obj, FORWARDSTUBPTR).forw
@@ -743,6 +746,10 @@
     def JIT_max_size_of_young_obj(cls):
         return cls.TRANSLATION_PARAMS['large_object']
 
+    @classmethod
+    def JIT_minimal_size_in_nursery(cls):
+        return cls.minimal_size_in_nursery
+
     def write_barrier(self, newvalue, addr_struct):
         if self.header(addr_struct).tid & GCFLAG_NO_YOUNG_PTRS:
             self.remember_young_pointer(addr_struct, newvalue)
@@ -1080,7 +1087,7 @@
         llarena.arena_reset(obj - size_gc_header, totalsize, 0)
         llarena.arena_reserve(obj - size_gc_header,
                               size_gc_header + llmemory.sizeof(FORWARDSTUB))
-        self.header(obj).tid = -1
+        self.header(obj).tid = -42
         newobj = newhdr + size_gc_header
         llmemory.cast_adr_to_ptr(obj, FORWARDSTUBPTR).forw = newobj
         #

Modified: pypy/trunk/pypy/rpython/memory/gc/semispace.py
==============================================================================
--- pypy/trunk/pypy/rpython/memory/gc/semispace.py	(original)
+++ pypy/trunk/pypy/rpython/memory/gc/semispace.py	Tue Nov  9 10:11:11 2010
@@ -230,6 +230,10 @@
         while self.max_space_size > size:
             self.max_space_size >>= 1
 
+    @classmethod
+    def JIT_minimal_size_in_nursery(cls):
+        return cls.object_minimal_size
+
     def collect(self, gen=0):
         self.debug_check_consistency()
         self.semispace_collect()



More information about the Pypy-commit mailing list