[pypy-svn] r47353 - in pypy/dist/pypy: rpython/lltypesystem rpython/lltypesystem/test rpython/memory rpython/memory/test translator/c/test

arigo at codespeak.net arigo at codespeak.net
Tue Oct 9 16:40:40 CEST 2007


Author: arigo
Date: Tue Oct  9 16:40:40 2007
New Revision: 47353

Modified:
   pypy/dist/pypy/rpython/lltypesystem/llarena.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_llarena.py
   pypy/dist/pypy/rpython/memory/gc.py
   pypy/dist/pypy/rpython/memory/gctypelayout.py
   pypy/dist/pypy/rpython/memory/lltypelayout.py
   pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
   pypy/dist/pypy/translator/c/test/test_boehm.py
   pypy/dist/pypy/translator/c/test/test_newgc.py
Log:
Alignment support for the GCs.  Fix the SemiSpaceGC to always allocate
objects properly aligned.


Modified: pypy/dist/pypy/rpython/lltypesystem/llarena.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llarena.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llarena.py	Tue Oct  9 16:40:40 2007
@@ -216,12 +216,16 @@
     assert myarenasize == arena_addr.arena.nbytes
     arena_addr.arena.reset(zero)
 
-def arena_reserve(addr, size):
+def arena_reserve(addr, size, check_alignment=True):
     """Mark some bytes in an arena as reserved, and returns addr.
     For debugging this can check that reserved ranges of bytes don't
     overlap.  The size must be symbolic; in non-translated version
     this is used to know what type of lltype object to allocate."""
+    from pypy.rpython.memory.lltypelayout import memory_alignment
     assert isinstance(addr, fakearenaaddress)
+    if check_alignment and (addr.offset & (memory_alignment-1)) != 0:
+        raise ArenaError("object at offset %d would not be correctly aligned"
+                         % (addr.offset,))
     addr.arena.allocate_object(addr.offset, size)
 
 def round_up_for_allocation(size):

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llarena.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_llarena.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_llarena.py	Tue Oct  9 16:40:40 2007
@@ -22,7 +22,9 @@
     assert s1_ptr2.x == 1
     assert s1_ptr1 == s1_ptr2
 
-    arena_reserve(a + ssize + 1, llmemory.sizeof(S))
+    py.test.raises(ArenaError, arena_reserve, a + ssize + 1,  # misaligned
+                   llmemory.sizeof(S))
+    arena_reserve(a + ssize + 1, llmemory.sizeof(S), check_alignment=False)
     s2_ptr1 = cast_adr_to_ptr(a + ssize + 1, SPTR)
     py.test.raises(lltype.UninitializedMemoryAccess, 's2_ptr1.x')
     s2_ptr1.x = 2
@@ -40,10 +42,14 @@
     py.test.raises(ArenaError, cast_adr_to_ptr, a+ssize, SPTR)
     py.test.raises(ArenaError, cast_adr_to_ptr, a+2*ssize, SPTR)
     py.test.raises(ArenaError, cast_adr_to_ptr, a+2*ssize+1, SPTR)
-    py.test.raises(ArenaError, arena_reserve, a+1, llmemory.sizeof(S))
-    py.test.raises(ArenaError, arena_reserve, a+ssize, llmemory.sizeof(S))
-    py.test.raises(ArenaError, arena_reserve, a+2*ssize, llmemory.sizeof(S))
-    py.test.raises(ArenaError, arena_reserve, a+2*ssize+1, llmemory.sizeof(S))
+    py.test.raises(ArenaError, arena_reserve, a+1, llmemory.sizeof(S),
+                   False)
+    py.test.raises(ArenaError, arena_reserve, a+ssize, llmemory.sizeof(S),
+                   False)
+    py.test.raises(ArenaError, arena_reserve, a+2*ssize, llmemory.sizeof(S),
+                   False)
+    py.test.raises(ArenaError, arena_reserve, a+2*ssize+1, llmemory.sizeof(S),
+                   False)
 
     arena_reset(a, myarenasize, True)
     py.test.raises(ArenaError, cast_adr_to_ptr, a, SPTR)
@@ -52,7 +58,7 @@
     assert s1_ptr1.x == 0
     s1_ptr1.x = 5
 
-    arena_reserve(a + ssize, llmemory.sizeof(S2))
+    arena_reserve(a + ssize, llmemory.sizeof(S2), check_alignment=False)
     s2_ptr1 = cast_adr_to_ptr(a + ssize, S2PTR)
     assert s2_ptr1.y == '\x00'
     s2_ptr1.y = 'X'
@@ -114,7 +120,7 @@
     SPTR = lltype.Ptr(SX)
     myarenasize = 50
     a = arena_malloc(myarenasize, False)
-    b = a + 4
+    b = a + round_up_for_allocation(llmemory.sizeof(lltype.Char))
     arena_reserve(b, precomputed_size)
     (b + llmemory.offsetof(SX, 'x')).signed[0] = 123
     assert llmemory.cast_adr_to_ptr(b, SPTR).x == 123

Modified: pypy/dist/pypy/rpython/memory/gc.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gc.py	(original)
+++ pypy/dist/pypy/rpython/memory/gc.py	Tue Oct  9 16:40:40 2007
@@ -1012,7 +1012,7 @@
         llarena.arena_reserve(result, totalsize)
         self.init_gc_object(result, typeid)
         (result + size_gc_header + offset_to_length).signed[0] = length
-        self.free += totalsize
+        self.free += llarena.round_up_for_allocation(totalsize)
         if has_finalizer:
             self.objects_with_finalizers.append(result + size_gc_header)
         return llmemory.cast_adr_to_ptr(result+size_gc_header, llmemory.GCREF)
@@ -1129,6 +1129,7 @@
             lenaddr = obj + self.varsize_offset_to_length(typeid)
             length = lenaddr.signed[0]
             size += length * self.varsize_item_sizes(typeid)
+            size = llarena.round_up_for_allocation(size)
         return size
 
     def header(self, addr):

Modified: pypy/dist/pypy/rpython/memory/gctypelayout.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctypelayout.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctypelayout.py	Tue Oct  9 16:40:40 2007
@@ -1,4 +1,4 @@
-from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.lltypesystem import lltype, llmemory, llarena
 from pypy.rpython.memory.gctransform.support import find_gc_ptrs_in_type
 
 
@@ -33,8 +33,13 @@
             info["weakptrofs"] = weakpointer_offset(TYPE)
             if not TYPE._is_varsize():
                 info["isvarsize"] = False
-                info["fixedsize"] = llmemory.sizeof(TYPE)
+                info["fixedsize"] = llarena.round_up_for_allocation(
+                    llmemory.sizeof(TYPE))
                 info["ofstolength"] = -1
+                # note about round_up_for_allocation(): in the 'info' table
+                # we put a rounded-up size only for fixed-size objects.  For
+                # varsize ones, the GC must anyway compute the size at run-time
+                # and round up that result.
             else:
                 info["isvarsize"] = True
                 info["fixedsize"] = llmemory.sizeof(TYPE, 0)

Modified: pypy/dist/pypy/rpython/memory/lltypelayout.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/lltypelayout.py	(original)
+++ pypy/dist/pypy/rpython/memory/lltypelayout.py	Tue Oct  9 16:40:40 2007
@@ -2,6 +2,8 @@
 
 import struct
 
+memory_alignment = 4
+
 primitive_to_fmt = {lltype.Signed:          "l",
                     lltype.Unsigned:        "L",
                     lltype.Char:            "c",
@@ -108,6 +110,7 @@
         return 0
     elif isinstance(offset, llarena.RoundedUpForAllocation):
         basesize = convert_offset_to_int(offset.basesize)
-        return (basesize + 7) & ~ 7
+        mask = memory_alignment - 1
+        return (basesize + mask) & ~ mask
     else:
         raise Exception("unknown offset type %r"%offset)

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	Tue Oct  9 16:40:40 2007
@@ -83,15 +83,17 @@
 
     class gcpolicy(gc.FrameworkGcPolicy):
         class transformerclass(framework.FrameworkGCTransformer):
-            from pypy.rpython.memory.gc import MarkSweepGC as GCClass
             GC_PARAMS = {'start_heap_size': 4096 }
             root_stack_depth = 200
     gcname = "framework"
 
     def heap_usage(self, statistics):
-        if hasattr(self.gcpolicy.transformerclass.GCClass, 'STAT_HEAP_USAGE'):
-            return statistics(
-                self.gcpolicy.transformerclass.GCClass.STAT_HEAP_USAGE)
+        try:
+            GCClass = self.gcpolicy.transformerclass.GCClass
+        except AttributeError:
+            from pypy.rpython.memory.gc import MarkSweepGC as GCClass
+        if hasattr(GCClass, 'STAT_HEAP_USAGE'):
+            return statistics(GCClass.STAT_HEAP_USAGE)
         else:
             return -1     # xxx
 

Modified: pypy/dist/pypy/translator/c/test/test_boehm.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_boehm.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_boehm.py	Tue Oct  9 16:40:40 2007
@@ -27,6 +27,8 @@
         config = get_pypy_config(translating=True)
         config.translation.gc = self.gcpolicy
         config.translation.stacklessgc = self.stacklessgc
+        if self.gcpolicy == "framework":
+            config.translation.frameworkgc = self.frameworkgc
         config.translation.simplifying = True
         t = TranslationContext(config=config)
         self.t = t

Modified: pypy/dist/pypy/translator/c/test/test_newgc.py
==============================================================================
--- pypy/dist/pypy/translator/c/test/test_newgc.py	(original)
+++ pypy/dist/pypy/translator/c/test/test_newgc.py	Tue Oct  9 16:40:40 2007
@@ -278,6 +278,7 @@
 
 class TestUsingFramework(AbstractGCTestClass):
     gcpolicy = "framework"
+    frameworkgc = "marksweep"
 
     def test_empty_collect(self):
         def f():
@@ -774,6 +775,27 @@
         res = fn()
         assert res == 42
 
+    def test_object_alignment(self):
+        # all objects returned by the GC should be aligned on a 8-bytes
+        # boundary, or whatever sizeof(double) is on this platform
+        mylist = ['a', 'bc', '84139871', 'ajkdh', '876']
+        def f():
+            result = 0
+            buffer = ""
+            for j in range(100):
+                for s in mylist:
+                    buffer += s
+                    result |= id(buffer)
+            return result
+
+        fn = self.getcompiled(f)
+        res = fn()
+        import struct
+        expected_alignment = struct.calcsize("d")
+        assert (expected_alignment & (expected_alignment-1)) == 0, (
+            "sizeof(double) not a power of two")
+        assert (res & (expected_alignment-1)) == 0
+
 class TestUsingStacklessFramework(TestUsingFramework):
 
     def getcompiled(self, f):
@@ -799,3 +821,9 @@
 
     def test_weakref(self):
         py.test.skip("fails for some reason I couldn't figure out yet :-(")
+
+class TestSemiSpaceGC(TestUsingFramework):
+    frameworkgc = "semispace"
+
+    def setup_class(cls):
+        py.test.skip("in-progress")



More information about the Pypy-commit mailing list