[pypy-svn] r65409 - in pypy/branch/tagged-pointers-framework/pypy/rpython: lltypesystem memory/gc memory/test test

cfbolz at codespeak.net cfbolz at codespeak.net
Mon May 25 14:25:21 CEST 2009


Author: cfbolz
Date: Mon May 25 14:25:19 2009
New Revision: 65409

Modified:
   pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/llmemory.py
   pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/lltype.py
   pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py
   pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/hybrid.py
   pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py
   pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_transformed_gc.py
   pypy/branch/tagged-pointers-framework/pypy/rpython/test/test_rptr.py
Log:
 - fix casting of opaque pointers to ints. Needed for correct GCREF handing
 - allowing casting of addresses of dead objects to int. Fixes some
   test_transformed_gc tests
 - proper id handling of tagged pointers in moving GCs


Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/llmemory.py
==============================================================================
--- pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/llmemory.py	(original)
+++ pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/llmemory.py	Mon May 25 14:25:19 2009
@@ -461,8 +461,10 @@
             return lltype.nullptr(EXPECTED_TYPE.TO)
 
     def _cast_to_int(self):
+        # This is a bit annoying. We want this method to still work when the
+        # pointed-to object is dead
         if self:
-            return self.ptr._cast_to_int()
+            return self.ptr._cast_to_int(False)
         else:
             return 0
 

Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/branch/tagged-pointers-framework/pypy/rpython/lltypesystem/lltype.py	Mon May 25 14:25:19 2009
@@ -816,6 +816,7 @@
         if not ptr:
             return nullptr(PTRTYPE.TO)
         return opaqueptr(PTRTYPE.TO, 'hidden', container = ptr._obj,
+                                               ORIGTYPE = CURTYPE,
                                                solid     = ptr._solid)
     elif (isinstance(CURTYPE.TO, OpaqueType)
           and isinstance(PTRTYPE.TO, OpaqueType)):
@@ -899,7 +900,7 @@
         top_parent = parent
     return top_parent
 
-def normalizeptr(p):
+def normalizeptr(p, check=True):
     # 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.
@@ -907,12 +908,17 @@
     T = typeOf(p)
     if not isinstance(T, Ptr):
         return p      # primitive
-    if not p:
+    obj = p._getobj(check)
+    if not obj:
         return None   # null pointer
     if type(p._obj0) is int:
         return p      # a pointer obtained by cast_int_to_ptr
-    container = p._obj._normalizedcontainer()
-    if container is not p._obj:
+    container = obj._normalizedcontainer()
+    if type(container) is int:
+        # this must be an opaque ptr originating from an integer
+        assert isinstance(obj, _opaque)
+        return cast_int_to_ptr(obj.ORIGTYPE, container)
+    if container is not obj:
         p = _ptr(Ptr(typeOf(container)), container, p._solid)
     return p
 
@@ -1171,13 +1177,15 @@
             raise RuntimeError("widening %r inside %r instead of %r" % (CURTYPE, PARENTTYPE, PTRTYPE.TO))
         return _ptr(PTRTYPE, struc, solid=self._solid)
 
-    def _cast_to_int(self):
-        if not self:
+    def _cast_to_int(self, check=True):
+        obj = self._getobj(check)
+        if not obj:
             return 0       # NULL pointer
-        obj = self._obj
         if isinstance(obj, int):
             return obj     # special case for cast_int_to_ptr() results
-        obj = normalizeptr(self)._obj
+        obj = normalizeptr(self, check)._getobj(check)
+        if isinstance(obj, int):
+            return obj     # special case for cast_int_to_ptr() results put into opaques
         result = intmask(obj._getid())
         # assume that id() returns an addressish value which is
         # not zero and aligned to at least a multiple of 4
@@ -1718,6 +1726,9 @@
         # if we are an opaque containing a normal Struct/GcStruct,
         # unwrap it
         if hasattr(self, 'container'):
+            # an integer, cast to a ptr, cast to an opaque    
+            if type(self.container) is int:
+                return self.container
             return self.container._normalizedcontainer()
         else:
             return _parentable._normalizedcontainer(self)

Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py
==============================================================================
--- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py	(original)
+++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/base.py	Mon May 25 14:25:19 2009
@@ -243,6 +243,8 @@
         GCBase.setup(self)
         self.objects_with_id = self.AddressDict()
         self.id_free_list = self.AddressStack()
+        # XXX XXX XXX think of something sane:
+        # how do we prevent clashing with tagged pointers?
         self.next_free_id = 1
 
     def can_move(self, addr):
@@ -252,6 +254,11 @@
         # Default implementation for id(), assuming that "external" objects
         # never move.  Overriden in the HybridGC.
         obj = llmemory.cast_ptr_to_adr(ptr)
+
+        # is it a tagged pointer?
+        if not self.is_valid_gc_object(obj):
+            return llmemory.cast_adr_to_int(obj) // 2
+
         if self._is_external(obj):
             result = obj
         else:

Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/hybrid.py
==============================================================================
--- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/hybrid.py	(original)
+++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/gc/hybrid.py	Mon May 25 14:25:19 2009
@@ -553,6 +553,11 @@
 
     def id(self, ptr):
         obj = llmemory.cast_ptr_to_adr(ptr)
+
+        # is it a tagged pointer?
+        if not self.is_valid_gc_object(obj):
+            return llmemory.cast_adr_to_int(obj)
+
         if self._is_external(obj):
             # a prebuilt or rawmalloced object
             if self.is_last_generation(obj):

Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py
==============================================================================
--- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py	(original)
+++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_gc.py	Mon May 25 14:25:19 2009
@@ -514,6 +514,35 @@
         res = self.interpret(fn, [-1000])
         assert res == -897
 
+    def test_tagged_id(self):
+        from pypy.rlib.objectmodel import UnboxedValue, compute_unique_id
+
+        class Unrelated(object):
+            pass
+
+        u = Unrelated()
+        u.x = UnboxedObject(47)
+        def fn(n):
+            id_prebuilt1 = compute_unique_id(u.x)
+            if n > 0:
+                x = BoxedObject(n)
+            else:
+                x = UnboxedObject(n)
+            id_x1 = compute_unique_id(x)
+            rgc.collect() # check that a prebuilt tagged pointer doesn't explode
+            id_prebuilt2 = compute_unique_id(u.x)
+            id_x2 = compute_unique_id(x)
+            print u.x, id_prebuilt1, id_prebuilt2
+            print x, id_x1, id_x2
+            return ((id_x1 == id_x2) * 1 +
+                    (id_prebuilt1 == id_prebuilt2) * 10 +
+                    (id_x1 != id_prebuilt1) * 100)
+        res = self.interpret(fn, [1000])
+        assert res == 111
+        res = self.interpret(fn, [-1000])
+        assert res == 111
+
+
 from pypy.rlib.objectmodel import UnboxedValue
 
 class TaggedBase(object):

Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_transformed_gc.py
==============================================================================
--- pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_transformed_gc.py	(original)
+++ pypy/branch/tagged-pointers-framework/pypy/rpython/memory/test/test_transformed_gc.py	Mon May 25 14:25:19 2009
@@ -525,7 +525,7 @@
         res = fn([])
         assert res == 'y'
 
-    def test_tagged(self):
+    def test_tagged_simple(self):
         class Unrelated(object):
             pass
 
@@ -546,6 +546,27 @@
         res = func([])
         assert res == fn(1000) + fn(-1000)
 
+    def test_tagged_prebuilt(self):
+
+        class F:
+            pass
+
+        f = F()
+        f.l = [UnboxedObject(10)]
+        def fn(n):
+            if n > 0:
+                x = BoxedObject(n)
+            else:
+                x = UnboxedObject(n)
+            f.l.append(x)
+            rgc.collect()
+            return f.l[-1].meth(100)
+        def func():
+            return fn(1000) ^ fn(-1000)
+        func = self.runner(func)
+        res = func([])
+        assert res == fn(1000) ^ fn(-1000)
+
 from pypy.rlib.objectmodel import UnboxedValue
 
 class TaggedBase(object):

Modified: pypy/branch/tagged-pointers-framework/pypy/rpython/test/test_rptr.py
==============================================================================
--- pypy/branch/tagged-pointers-framework/pypy/rpython/test/test_rptr.py	(original)
+++ pypy/branch/tagged-pointers-framework/pypy/rpython/test/test_rptr.py	Mon May 25 14:25:19 2009
@@ -112,6 +112,20 @@
 
     interpret(fn, [11521])
 
+def test_odd_ints_opaque():
+    T = GcStruct('T')
+    Q = GcOpaqueType('Q')
+    PT = Ptr(T)
+    PQ = Ptr(Q)
+    def fn(n):
+        t = cast_int_to_ptr(PT, n)
+        assert typeOf(t) == PT
+        assert cast_ptr_to_int(t) == n
+        o = cast_opaque_ptr(PQ, t)
+        assert cast_ptr_to_int(o) == n
+
+    fn(13)
+    interpret(fn, [11521])
 
 def test_Ptr():
     S = GcStruct('s')



More information about the Pypy-commit mailing list