[pypy-svn] r27270 - in pypy/dist/pypy/rpython: lltypesystem lltypesystem/test memory/test

arigo at codespeak.net arigo at codespeak.net
Tue May 16 13:50:07 CEST 2006


Author: arigo
Date: Tue May 16 13:50:05 2006
New Revision: 27270

Modified:
   pypy/dist/pypy/rpython/lltypesystem/llmemory.py
   pypy/dist/pypy/rpython/lltypesystem/lltype.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
   pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
Log:
Normalize addresses, so that the address of a parent structure is
completely equivalent to the address of its first inlined substructure;
similarily, the address of an opaque that hides a structure is replaced
by the address of that structure.



Modified: pypy/dist/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/llmemory.py	Tue May 16 13:50:05 2006
@@ -74,7 +74,8 @@
 
     def ref(self, containerref):
         struct = containerref.get()
-        assert lltype.typeOf(struct).TO == self.TYPE
+        if lltype.typeOf(struct).TO != self.TYPE:
+            struct = lltype.cast_pointer(lltype.Ptr(self.TYPE), struct)
         return _structfieldref(struct, self.fldname)
 
     def raw_malloc(self, rest, parenttype=None):
@@ -200,21 +201,7 @@
 
     def ref(self, gcptrref):
         gcptr = gcptrref.get()
-        try:
-            headerobj = _gc_struct2header[gcptr._obj]
-        except KeyError:
-            # sanity checks
-            HDR = self.minimal_layout
-            gcobj = gcptr._obj
-            assert isinstance(gcobj._TYPE, lltype.GC_CONTAINER)
-            assert not gcobj._parentstructure()
-            
-            headerobj = lltype.malloc(HDR, immortal=True)._obj
-            # make uninitialized access explode
-            for fldname in HDR._names:
-                getattr(type(headerobj), fldname).__set__(headerobj, None)
-            _gc_struct2header[gcptr._obj] = headerobj
-            _gc_header2struct[headerobj] = gcobj
+        headerobj = getgcheaderobj(self.minimal_layout, gcptr._obj)
         p = lltype._ptr(lltype.Ptr(headerobj._TYPE), headerobj, True)
         return _obref(p)
 
@@ -291,9 +278,10 @@
 # -------------------------------------------------------------
 
 class fakeaddress(object):
+    # NOTE: the 'ob' in the addresses must be normalized.
+    # Use cast_ptr_to_adr() instead of directly fakeaddress() if unsure.
     def __init__(self, ob, offset=None):
-        assert not isinstance(ob, lltype._parentable)
-        self.ob = ob or None    # replace null pointers with None
+        self.ob = ob
         self.offset = offset
 
     def __repr__(self):
@@ -312,7 +300,7 @@
             else:
                 offset = self.offset + other
             res = fakeaddress(self.ob, offset)
-            #res.ref() # sanity check
+            res.ref() # sanity check
             return res
         if other == 0:
             return self
@@ -436,7 +424,7 @@
 
     def convert(self, value):
         if isinstance(value, lltype._ptr):
-            return fakeaddress(value)
+            return value._cast_to_adr()
         elif lltype.typeOf(value) == Address:
             return value
         else:
@@ -495,6 +483,25 @@
 _gc_struct2header = weakref.WeakKeyDictionary()
 _gc_header2struct = weakref.WeakKeyDictionary()
 
+def getgcheaderobj(HDR, gcobj):
+    # XXX! this doesn't work if we use different HDRs in different tests
+    # for the same constants
+    try:
+        headerobj = _gc_struct2header[gcobj]
+    except KeyError:
+        # sanity checks
+        assert isinstance(gcobj._TYPE, lltype.GC_CONTAINER)
+        assert not isinstance(gcobj._TYPE, lltype.GcOpaqueType)
+        assert not gcobj._parentstructure()
+
+        headerobj = lltype.malloc(HDR, immortal=True)._obj
+        # make uninitialized access explode
+        for fldname in HDR._names:
+            getattr(type(headerobj), fldname).__set__(headerobj, None)
+        _gc_struct2header[gcobj] = headerobj
+        _gc_header2struct[headerobj] = gcobj
+    return headerobj
+
 def raw_malloc(size):
     if not isinstance(size, AddressOffset):
         raise NotImplementedError(size)

Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py	Tue May 16 13:50:05 2006
@@ -778,6 +778,36 @@
         top_parent = parent
     return top_parent
 
+def normalizeptr(p):
+    # If p is a pointer, returns the same pointer casted to the largest
+    # containing structure (for the cast where p points to the header part).
+    # Also un-hides pointers to opaque.  Null pointers become None.
+    assert not isinstance(p, _parentable)  # pointer or primitive
+    T = typeOf(p)
+    if not isinstance(T, Ptr):
+        return p      # primitive
+    if not p:
+        return None   # null pointer
+    # - if p is an opaque pointer containing a normal Struct/GcStruct,
+    #   unwrap it now
+    if isinstance(T.TO, OpaqueType) and hasattr(p._obj, 'container'):
+        T = Ptr(typeOf(p._obj.container))
+        p = cast_opaque_ptr(T, p)
+    # - if p points to the first inlined substructure of a structure,
+    #   make it point to the whole (larger) structure instead
+    container = p._obj
+    while True:
+        parent, index = parentlink(container)
+        if parent is None:
+            break
+        T = typeOf(parent)
+        if not isinstance(T, Struct) or T._first_struct()[0] != index:
+            break
+        container = parent
+    if container is not p._obj:
+        p = _ptr(Ptr(T), container, p._solid)
+    return p
+
 
 class _ptr(object):
     __slots__ = ('_TYPE', '_T', 
@@ -1012,12 +1042,12 @@
             # return an address built as an offset in the whole array
             parent, parentindex = parentlink(self._obj)
             T = typeOf(parent)
-            addr = llmemory.fakeaddress(_ptr(Ptr(T), parent))
+            addr = llmemory.fakeaddress(normalizeptr(_ptr(Ptr(T), parent)))
             addr += llmemory.itemoffsetof(T, parentindex)
             return addr
         else:
             # normal case
-            return llmemory.fakeaddress(self)
+            return llmemory.fakeaddress(normalizeptr(self))
 
 assert not '__dict__' in dir(_ptr)
 

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_llmemory.py	Tue May 16 13:50:05 2006
@@ -295,6 +295,27 @@
     py.test.raises(IndexError,
                    "(adr + offsetof(S, 'y') + itemoffsetof(A, 10)).signed[0]")
 
+def test_inlined_substruct():
+    T = lltype.Struct('T', ('x', lltype.Signed))
+    S1 = lltype.GcStruct('S1', ('t1', T), ('t2', T))
+    S = lltype.GcStruct('S', ('header', S1), ('t', T))
+
+    s = lltype.malloc(S)
+    s.header.t1.x = 1
+    s.header.t2.x = 2
+    s.t.x = 3
+
+    for adr in [cast_ptr_to_adr(s), cast_ptr_to_adr(s.header)]:
+        assert (adr + offsetof(S, 'header')
+                    + offsetof(S1, 't1')
+                    + offsetof(T, 'x')).signed[0] == 1
+        assert (adr + offsetof(S1, 't1')
+                    + offsetof(T, 'x')).signed[0] == 1
+        assert (adr + offsetof(S1, 't2')
+                    + offsetof(T, 'x')).signed[0] == 2
+        assert (adr + offsetof(S, 't')
+                    + offsetof(T, 'x')).signed[0] == 3
+
 def test_arena_bump_ptr():
     S = lltype.Struct('S', ('x',lltype.Signed))
     SPTR = lltype.Ptr(S)

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 May 16 13:50:05 2006
@@ -228,6 +228,7 @@
                 while j < 30:
                     j += 1
                     a.append(j)
+            return 0
         run, statistics = self.runner(malloc_a_lot, statistics=True)
         run([])
         heap_size = statistics().item0
@@ -244,6 +245,7 @@
                 while j < 20:
                     j += 1
                     b.append((1, j, i))
+            return 0
         run, statistics = self.runner(malloc_a_lot, statistics=True)
         run([])
         heap_size = statistics().item0
@@ -277,3 +279,10 @@
         assert res == concat(100, 0)
         heap_size = statistics().item0
         assert heap_size < 16000 * INT_SIZE / 4 # xxx
+
+
+class INPROGRESS_TestStacklessMarkSweepGC(TestMarkSweepGC):
+
+    class gcpolicy(gc.StacklessFrameworkGcPolicy):
+        class transformerclass(gctransform.StacklessFrameworkGCTransformer):
+            GC_PARAMS = {'start_heap_size': 4096 }



More information about the Pypy-commit mailing list