[pypy-svn] r68259 - in pypy/branch/gc-compress/pypy/rpython/lltypesystem: . test

arigo at codespeak.net arigo at codespeak.net
Thu Oct 8 22:59:35 CEST 2009


Author: arigo
Date: Thu Oct  8 22:59:31 2009
New Revision: 68259

Modified:
   pypy/branch/gc-compress/pypy/rpython/lltypesystem/llarena.py
   pypy/branch/gc-compress/pypy/rpython/lltypesystem/llmemory.py
   pypy/branch/gc-compress/pypy/rpython/lltypesystem/lltype.py
   pypy/branch/gc-compress/pypy/rpython/lltypesystem/test/test_llarena.py
Log:
Kill the llarena feature of replacing an object with a stub.
Instead, add the feature of swapping the header of an object
for a completely different header.


Modified: pypy/branch/gc-compress/pypy/rpython/lltypesystem/llarena.py
==============================================================================
--- pypy/branch/gc-compress/pypy/rpython/lltypesystem/llarena.py	(original)
+++ pypy/branch/gc-compress/pypy/rpython/lltypesystem/llarena.py	Thu Oct  8 22:59:31 2009
@@ -103,6 +103,48 @@
         Arena.object_arena_location[container] = self, offset
         Arena.old_object_arena_location[container] = self, offset
 
+    def get_header_ofs(self, obj, oldheadersize):
+        headers = []
+        for offset, ptr in self.objectptrs.items():
+            size = self.objectsizes[offset]
+            if offset >= obj:      # object is at or after 'obj'
+                continue
+            if offset + size < obj:   # object is before the header
+                continue
+            headers.append(offset)
+        assert len(headers) >= 1, "header not found"
+        assert len(headers) == 1, "uh? multiple headers?"
+        offset = headers[0]
+        size = self.objectsizes[offset]
+        assert offset + size == obj + self.objectsizes[obj], "not a header?"
+        assert obj - offset == llmemory.raw_malloc_usage(oldheadersize)
+        return offset
+
+    def swap_header(self, startobj, oldheadersize, newheadersize):
+        prev_end = [0]
+        for offset, ptr in self.objectptrs.items():
+            size = self.objectsizes[offset]
+            if offset + size < startobj:
+                prev_end.append((offset + size))
+        prev_end = max(prev_end)
+        new_bytes = llmemory.raw_malloc_usage(newheadersize)
+        assert prev_end <= startobj - new_bytes, "new header too big"
+        old_offset = self.get_header_ofs(startobj, oldheadersize)
+        assert isinstance(newheadersize, llmemory.GCHeaderOffset)
+        obj = self.objectptrs[startobj]
+        oldheaderptr = self.objectptrs.pop(old_offset)
+        oldheadersize.gcheaderbuilder.detach_header(obj, oldheaderptr)
+        newheader = newheadersize.gcheaderbuilder.new_header(obj)
+        newheader = llmemory.cast_ptr_to_adr(newheader)
+        #
+        del self.objectsizes[old_offset]
+        self.setobject(newheader, startobj - new_bytes,
+                       new_bytes + self.objectsizes[startobj])
+        oldheaderobj = oldheaderptr._as_obj()
+        del Arena.object_arena_location[oldheaderobj]
+        oldheaderobj._free()
+
+
 class fakearenaaddress(llmemory.fakeaddress):
 
     def __init__(self, arena, offset):
@@ -309,6 +351,13 @@
     """
     return Arena(ptr.arena.nbytes, False).getaddr(0)
 
+def arena_swap_header(obj, oldheadersize, newheadersize):
+    """Free the old header attached to 'obj', and attach one
+    of the size 'newheadersize' instead."""
+    arena_addr = _getfakearenaaddress(obj)
+    arena_addr.arena.swap_header(arena_addr.offset, oldheadersize,
+                                 newheadersize)
+
 # ____________________________________________________________
 #
 # Translation support: the functions above turn into the code below.

Modified: pypy/branch/gc-compress/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/branch/gc-compress/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/branch/gc-compress/pypy/rpython/lltypesystem/llmemory.py	Thu Oct  8 22:59:31 2009
@@ -376,9 +376,7 @@
     # NOTE: the 'ptr' in the addresses must be normalized.
     # Use cast_ptr_to_adr() instead of directly fakeaddress() if unsure.
     def __init__(self, ptr):
-        if ptr is not None and ptr._obj0 is None:
-            ptr = None   # null ptr => None
-        self.ptr = ptr
+        self.ptr = ptr or None   # null ptr => None
 
     def __repr__(self):
         if self.ptr is None:
@@ -417,8 +415,8 @@
     def __eq__(self, other):
         if isinstance(other, fakeaddress):
             try:
-                obj1 = self._fixup().ptr
-                obj2 = other._fixup().ptr
+                obj1 = self.ptr
+                obj2 = other.ptr
                 if obj1 is not None: obj1 = obj1._obj
                 if obj2 is not None: obj2 = obj2._obj
                 return obj1 == obj2
@@ -457,9 +455,8 @@
         return self.ptr
 
     def _cast_to_ptr(self, EXPECTED_TYPE):
-        addr = self._fixup()
-        if addr:
-            return cast_any_ptr(EXPECTED_TYPE, addr.ptr)
+        if self:
+            return cast_any_ptr(EXPECTED_TYPE, self.ptr)
         else:
             return lltype.nullptr(EXPECTED_TYPE.TO)
 
@@ -469,14 +466,6 @@
         else:
             return 0
 
-    def _fixup(self):
-        if self.ptr is not None and self.ptr._was_freed():
-            # hack to support llarena.test_replace_object_with_stub()
-            from pypy.rpython.lltypesystem import llarena
-            return llarena._getfakearenaaddress(self)
-        else:
-            return self
-
 # ____________________________________________________________
 
 class NullAddressError(Exception):

Modified: pypy/branch/gc-compress/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/branch/gc-compress/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/branch/gc-compress/pypy/rpython/lltypesystem/lltype.py	Thu Oct  8 22:59:31 2009
@@ -1194,10 +1194,6 @@
         from pypy.rpython.lltypesystem import llmemory
         if isinstance(self._T, FuncType):
             return llmemory.fakeaddress(self)
-        elif self._was_freed():
-            # hack to support llarena.test_replace_object_with_stub()
-            from pypy.rpython.lltypesystem import llarena
-            return llarena._oldobj_to_address(self._getobj(check=False))
         elif isinstance(self._obj, _subarray):
             return llmemory.fakeaddress(self)
 ##            # return an address built as an offset in the whole array

Modified: pypy/branch/gc-compress/pypy/rpython/lltypesystem/test/test_llarena.py
==============================================================================
--- pypy/branch/gc-compress/pypy/rpython/lltypesystem/test/test_llarena.py	(original)
+++ pypy/branch/gc-compress/pypy/rpython/lltypesystem/test/test_llarena.py	Thu Oct  8 22:59:31 2009
@@ -5,6 +5,7 @@
 from pypy.rpython.lltypesystem.llarena import arena_reserve, arena_free
 from pypy.rpython.lltypesystem.llarena import round_up_for_allocation
 from pypy.rpython.lltypesystem.llarena import ArenaError, arena_new_view
+from pypy.rpython.lltypesystem.llarena import arena_swap_header
 
 def test_arena():
     S = lltype.Struct('S', ('x',lltype.Signed))
@@ -217,13 +218,15 @@
     assert llmemory.cast_adr_to_int(a) == llmemory.cast_adr_to_int(a1)
     assert llmemory.cast_adr_to_int(a+1) == llmemory.cast_adr_to_int(a1) + 1
 
-def test_replace_object_with_stub():
+def test_replace_object_header():
     from pypy.rpython.memory.gcheader import GCHeaderBuilder
     HDR = lltype.Struct('HDR', ('x', lltype.Signed))
+    STUB = lltype.Struct('STUB', ('t', lltype.Char))
     S = lltype.GcStruct('S', ('y', lltype.Signed), ('z', lltype.Signed))
-    STUB = lltype.GcStruct('STUB', ('t', lltype.Char))
     gcheaderbuilder = GCHeaderBuilder(HDR)
     size_gc_header = gcheaderbuilder.size_gc_header
+    gcstubbuilder = GCHeaderBuilder(STUB)
+    size_stub = gcstubbuilder.size_gc_header
     ssize = llmemory.raw_malloc_usage(llmemory.sizeof(S))
 
     a = arena_malloc(13*ssize, True)
@@ -231,31 +234,28 @@
     arena_reserve(hdraddr, size_gc_header + llmemory.sizeof(S))
     hdr = llmemory.cast_adr_to_ptr(hdraddr, lltype.Ptr(HDR))
     hdr.x = 42
-    obj = llmemory.cast_adr_to_ptr(hdraddr + size_gc_header, lltype.Ptr(S))
+    objaddr = hdraddr + size_gc_header
+    obj = llmemory.cast_adr_to_ptr(objaddr, lltype.Ptr(S))
     obj.y = -5
     obj.z = -6
 
-    hdraddr = llmemory.cast_ptr_to_adr(obj) - size_gc_header
-    arena_reset(hdraddr, size_gc_header + llmemory.sizeof(S), False)
-    arena_reserve(hdraddr, size_gc_header + llmemory.sizeof(STUB))
-
-    # check that it possible to reach the newly reserved HDR+STUB
-    # via the header of the old 'obj' pointer, both via the existing
-    # 'hdraddr':
-    hdr = llmemory.cast_adr_to_ptr(hdraddr, lltype.Ptr(HDR))
-    hdr.x = 46
-    stub = llmemory.cast_adr_to_ptr(hdraddr + size_gc_header, lltype.Ptr(STUB))
-    stub.t = '!'
-
-    # and via a (now-invalid) pointer to the old 'obj': (this is needed
-    # because during a garbage collection there are still pointers to
-    # the old 'obj' around to be fixed)
-    hdraddr = llmemory.cast_ptr_to_adr(obj) - size_gc_header
-    hdr = llmemory.cast_adr_to_ptr(hdraddr, lltype.Ptr(HDR))
-    assert hdr.x == 46
-    stub = llmemory.cast_adr_to_ptr(hdraddr + size_gc_header,
-                                    lltype.Ptr(STUB))
-    assert stub.t == '!'
+    arena_swap_header(objaddr, size_gc_header, size_stub)
+    assert obj.y == -5
+    assert obj.z == -6
+    stubaddr = objaddr - size_stub
+    stub = llmemory.cast_adr_to_ptr(stubaddr, lltype.Ptr(STUB))
+    stub.t = 'A'
+    py.test.raises(RuntimeError, "hdr.x")
+    py.test.raises(KeyError, "objaddr - size_gc_header")
+
+    arena_swap_header(objaddr, size_stub, size_gc_header)
+    hdr2addr = objaddr - size_gc_header
+    hdr2 = llmemory.cast_adr_to_ptr(hdr2addr, lltype.Ptr(HDR))
+    hdr2.x = 42
+    assert obj.y == -5
+    assert obj.z == -6
+    py.test.raises(RuntimeError, "stub.t")
+    py.test.raises(KeyError, "objaddr - size_stub")
 
 
 def test_llinterpreted():



More information about the Pypy-commit mailing list