[pypy-svn] r46470 - in pypy/dist/pypy: rpython/memory/gctransform translator/c translator/c/test

arigo at codespeak.net arigo at codespeak.net
Tue Sep 11 15:19:51 CEST 2007


Author: arigo
Date: Tue Sep 11 15:19:50 2007
New Revision: 46470

Modified:
   pypy/dist/pypy/rpython/memory/gctransform/boehm.py
   pypy/dist/pypy/translator/c/gc.py
   pypy/dist/pypy/translator/c/primitive.py
   pypy/dist/pypy/translator/c/test/test_boehm.py
Log:
Prebuilt weakrefs in genc/Boehm.


Modified: pypy/dist/pypy/rpython/memory/gctransform/boehm.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/gctransform/boehm.py	(original)
+++ pypy/dist/pypy/rpython/memory/gctransform/boehm.py	Tue Sep 11 15:19:50 2007
@@ -171,3 +171,12 @@
     # abuse of llop.cast_pointer()
     link = llop.cast_pointer(llmemory.Address, wref)
     return link and link.address[0]
+
+def convert_prebuilt_weakref_to(targetptr):
+    # Prebuilt weakrefs don't really need to be weak at all,
+    # but we need to emulate the structure expected by ll_weakref_deref().
+    # This is essentially the same code as in ll_weakref_create(), but I'm
+    # not sure trying to share it is worth the hassle...
+    link = lltype.malloc(WEAKLINK, immortal=True)
+    link[0] = llmemory.cast_ptr_to_adr(targetptr)
+    return link

Modified: pypy/dist/pypy/translator/c/gc.py
==============================================================================
--- pypy/dist/pypy/translator/c/gc.py	(original)
+++ pypy/dist/pypy/translator/c/gc.py	Tue Sep 11 15:19:50 2007
@@ -175,6 +175,10 @@
 class BoehmGcPolicy(BasicGcPolicy):
     transformerclass = boehm.BoehmGCTransformer
 
+    def __init__(self, *args, **kwds):
+        BasicGcPolicy.__init__(self, *args, **kwds)
+        self.weakref_llwrapper_cache = {}
+
     def array_setup(self, arraydefnode):
         pass
 
@@ -213,6 +217,16 @@
             yield 'GC_all_interior_pointers = 0;'
         yield 'GC_init();'
 
+    def name_weakref_to(self, target):
+        # the cache is essential to ensure that repeated calls to
+        # db.get(weakref) don't return new llwrapper structures all
+        # the time, which defeats the db.complete() logic.
+        try:
+            llwrapper = self.weakref_llwrapper_cache[target._obj]
+        except KeyError:
+            llwrapper = boehm.convert_prebuilt_weakref_to(target)
+            self.weakref_llwrapper_cache[target._obj] = llwrapper
+        return '((GCWeakRef)%s)' % (self.db.get(llwrapper),)
 
     def OP_GC_FETCH_EXCEPTION(self, funcgen, op):
         result = funcgen.expr(op.result)

Modified: pypy/dist/pypy/translator/c/primitive.py
==============================================================================
--- pypy/dist/pypy/translator/c/primitive.py	(original)
+++ pypy/dist/pypy/translator/c/primitive.py	Tue Sep 11 15:19:50 2007
@@ -6,7 +6,7 @@
 from pypy.rpython.lltypesystem.llmemory import Address, \
      AddressOffset, ItemOffset, ArrayItemsOffset, FieldOffset, \
      CompositeOffset, ArrayLengthOffset, WeakGcAddress, fakeweakaddress, \
-     GCHeaderOffset, WeakRef
+     GCHeaderOffset, WeakRef, fakeweakref
 from pypy.translator.c.support import cdecl
 
 # ____________________________________________________________
@@ -121,6 +121,14 @@
         assert ob is not None
         return 'HIDE_POINTER(%s)'%db.get(ob)
 
+def name_weakref(value, db):
+    assert isinstance(value, fakeweakref)
+    target = value.get()
+    if target is None:
+        return 'NULL'
+    else:
+        return db.gcpolicy.name_weakref_to(target)
+
 # On 64 bit machines, SignedLongLong and Signed are the same, so the
 # order matters, because we want the Signed implementation.
 PrimitiveName = {
@@ -135,6 +143,7 @@
     Void:     name_void,
     Address:  name_address,
     WeakGcAddress:  name_weakgcaddress,
+    WeakRef:  name_weakref,
     }
 
 PrimitiveType = {

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 Sep 11 15:19:50 2007
@@ -318,6 +318,33 @@
         # more than half of them should have been freed, ideally up to 6000
         assert 3500 <= res <= 6000
 
+    def test_prebuilt_weakref(self):
+        import weakref
+        from pypy.rlib import rgc
+        class A:
+            pass
+        a = A()
+        a.hello = 42
+        r1 = weakref.ref(a)
+        r2 = weakref.ref(A())
+        rgc.collect()
+        assert r2() is None
+        def fn(n):
+            if n:
+                r = r1
+            else:
+                r = r2
+            a = r()
+            if a is None:
+                return -5
+            else:
+                return a.hello
+        c_fn = self.getcompiled(fn, [int])
+        res = c_fn(1)
+        assert res == 42
+        res = c_fn(0)
+        assert res == -5
+
 
 class TestUsingExactBoehm(TestUsingBoehm):
     gcpolicy = "exact_boehm"



More information about the Pypy-commit mailing list