[pypy-svn] r47577 - in pypy/dist/pypy/rpython/lltypesystem: . test

arigo at codespeak.net arigo at codespeak.net
Fri Oct 19 13:54:50 CEST 2007


Author: arigo
Date: Fri Oct 19 13:54:49 2007
New Revision: 47577

Modified:
   pypy/dist/pypy/rpython/lltypesystem/llarena.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_llarena.py
Log:
More hack hack hacking to attempt to order fakeaddresses that
ultimately come from an arena.


Modified: pypy/dist/pypy/rpython/lltypesystem/llarena.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llarena.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llarena.py	Fri Oct 19 13:54:49 2007
@@ -14,7 +14,7 @@
     pass
 
 class Arena(object):
-    object_arena_location = {}     # {container: (arena, offset)}
+    object_arena_location = {}     # {topcontainer: (arena, offset)}
 
     def __init__(self, nbytes, zero):
         self.nbytes = nbytes
@@ -39,10 +39,10 @@
                 assert offset >= stop, "object overlaps cleared area"
             else:
                 obj = ptr._obj
-                obj._free()
-                del Arena.object_arena_location[obj]
+                del Arena.object_arena_location[lltype.top_container(obj)]
                 del self.objectptrs[offset]
                 del self.objectsizes[offset]
+                obj._free()
         if zero:
             initialbyte = "0"
         else:
@@ -81,7 +81,8 @@
         self.usagemap[offset:offset+bytes] = array.array('c', pattern)
         self.objectptrs[offset] = addr2.ptr
         self.objectsizes[offset] = bytes
-        Arena.object_arena_location[addr2.ptr._obj] = self, offset
+        top = lltype.top_container(addr2.ptr._obj)
+        Arena.object_arena_location[top] = self, offset
         # common case: 'size' starts with a GCHeaderOffset.  In this case
         # we can also remember that the real object starts after the header.
         while isinstance(size, RoundedUpForAllocation):
@@ -94,7 +95,8 @@
             assert objoffset not in self.objectptrs
             self.objectptrs[objoffset] = objaddr.ptr
             self.objectsizes[objoffset] = bytes - hdrbytes
-            Arena.object_arena_location[objaddr.ptr._obj] = self, objoffset
+            top = lltype.top_container(objaddr.ptr._obj)
+            Arena.object_arena_location[top] = self, objoffset
         return addr2
 
 class fakearenaaddress(llmemory.fakeaddress):
@@ -147,28 +149,53 @@
     def __nonzero__(self):
         return True
 
+    def compare_with_fakeaddr(self, other):
+        if not other:
+            return None, None
+        obj = other.ptr._obj
+        top = lltype.top_container(obj)
+        if top not in Arena.object_arena_location:
+            return None, None   
+        arena, offset = Arena.object_arena_location[top]
+        # common case: top is a FixedSizeArray of size 1 with just obj in it
+        T = lltype.typeOf(top)
+        if (top is obj or (isinstance(T, lltype.FixedSizeArray) and
+                           T.OF == lltype.typeOf(obj))):
+            # in this case, addr(obj) == addr(top)
+            pass
+        else:
+            # here, it's likely that addr(obj) is a bit larger than addr(top).
+            # We could estimate the correct offset but it's a bit messy;
+            # instead, let's check the answer doesn't depend on it
+            if self.arena is arena:
+                objectsize = arena.objectsizes[offset]
+                if offset < self.offset < offset+objectsize:
+                    raise AssertionError(
+                        "comparing an inner address with a "
+                        "fakearenaaddress that points in the "
+                        "middle of the same object")
+                offset += objectsize // 2      # arbitrary
+        return arena, offset
+
     def __eq__(self, other):
         if isinstance(other, fakearenaaddress):
-            return self.arena is other.arena and self.offset == other.offset
+            arena = other.arena
+            offset = other.offset
         elif isinstance(other, llmemory.fakeaddress):
-            if other.ptr and other.ptr._obj in Arena.object_arena_location:
-                arena, offset = Arena.object_arena_location[other.ptr._obj]
-                return self.arena is arena and self.offset == offset
-            else:
-                return False
+            arena, offset = self.compare_with_fakeaddr(other)
         else:
             return llmemory.fakeaddress.__eq__(self, other)
+        return self.arena is arena and self.offset == offset
 
     def __lt__(self, other):
         if isinstance(other, fakearenaaddress):
             arena = other.arena
             offset = other.offset
         elif isinstance(other, llmemory.fakeaddress):
-            if other.ptr and other.ptr._obj in Arena.object_arena_location:
-                arena, offset = Arena.object_arena_location[other.ptr._obj]
-            else:
-                # arbitrarily, 'self' > any address not in any arena
-                return False
+            arena, offset = self.compare_with_fakeaddr(other)
+            if arena is None:
+                return False       # self < other-not-in-any-arena  => False
+                                   # (arbitrarily)
         else:
             raise TypeError("comparing a %s and a %s" % (
                 self.__class__.__name__, other.__class__.__name__))

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	Fri Oct 19 13:54:49 2007
@@ -112,8 +112,25 @@
     assert lt(a+19, b)
     assert lt(a, b+19)
 
+    c = b + round_up_for_allocation(llmemory.sizeof(lltype.Char))
+    arena_reserve(c, precomputed_size)
+    assert lt(b, c)
+    assert lt(a, c)
+    assert lt(llmemory.NULL, c)
+    d = c + llmemory.offsetof(SX, 'x')
+    assert lt(c, d)
+    assert lt(b, d)
+    assert lt(a, d)
+    assert lt(llmemory.NULL, d)
+    e = c + precomputed_size
+    assert lt(d, e)
+    assert lt(c, e)
+    assert lt(b, e)
+    assert lt(a, e)
+    assert lt(llmemory.NULL, e)
 
-SX = lltype.Struct('S', ('x',lltype.Signed))
+
+SX = lltype.Struct('S', ('foo',lltype.Signed), ('x',lltype.Signed))
 SPTR = lltype.Ptr(SX)
 precomputed_size = round_up_for_allocation(llmemory.sizeof(SX))
 



More information about the Pypy-commit mailing list