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

antocuni at codespeak.net antocuni at codespeak.net
Thu Sep 13 19:08:07 CEST 2007


Author: antocuni
Date: Thu Sep 13 19:08:07 2007
New Revision: 46547

Modified:
   pypy/dist/pypy/rpython/lltypesystem/rbuiltin.py
   pypy/dist/pypy/rpython/ootypesystem/ootype.py
   pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py
   pypy/dist/pypy/rpython/ootypesystem/test/test_ootype.py
   pypy/dist/pypy/rpython/rbuiltin.py
   pypy/dist/pypy/rpython/rweakref.py
   pypy/dist/pypy/rpython/test/test_rweakref.py
Log:
implement rweakref for ootype.



Modified: pypy/dist/pypy/rpython/lltypesystem/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rbuiltin.py	Thu Sep 13 19:08:07 2007
@@ -66,3 +66,40 @@
 BUILTIN_TYPER[hasattr] = rtype_builtin_hasattr
 BUILTIN_TYPER[__import__] = rtype_builtin___import__
 BUILTIN_TYPER[objectmodel.r_dict] = rtype_r_dict
+
+# _________________________________________________________________
+# weakrefs
+
+import weakref
+from pypy.rpython.lltypesystem import llmemory
+
+def rtype_weakref_create(hop):
+    # Note: this code also works for the RPython-level calls 'weakref.ref(x)'.
+    vlist = hop.inputargs(hop.args_r[0])
+    hop.exception_cannot_occur()
+    return hop.genop('weakref_create', vlist, resulttype=llmemory.WeakRefPtr)
+
+def rtype_weakref_deref(hop):
+    c_ptrtype, v_wref = hop.inputargs(lltype.Void, hop.args_r[1])
+    assert v_wref.concretetype == llmemory.WeakRefPtr
+    hop.exception_cannot_occur()
+    return hop.genop('weakref_deref', [v_wref], resulttype=c_ptrtype.value)
+
+def rtype_cast_ptr_to_weakrefptr(hop):
+    vlist = hop.inputargs(hop.args_r[0])
+    hop.exception_cannot_occur()
+    return hop.genop('cast_ptr_to_weakrefptr', vlist,
+                     resulttype=llmemory.WeakRefPtr)
+
+def rtype_cast_weakrefptr_to_ptr(hop):
+    c_ptrtype, v_wref = hop.inputargs(lltype.Void, hop.args_r[1])
+    assert v_wref.concretetype == llmemory.WeakRefPtr
+    hop.exception_cannot_occur()
+    return hop.genop('cast_weakrefptr_to_ptr', [v_wref],
+                     resulttype=c_ptrtype.value)
+
+BUILTIN_TYPER[weakref.ref] = rtype_weakref_create
+BUILTIN_TYPER[llmemory.weakref_create] = rtype_weakref_create
+BUILTIN_TYPER[llmemory.weakref_deref ] = rtype_weakref_deref
+BUILTIN_TYPER[llmemory.cast_ptr_to_weakrefptr] = rtype_cast_ptr_to_weakrefptr
+BUILTIN_TYPER[llmemory.cast_weakrefptr_to_ptr] = rtype_cast_weakrefptr_to_ptr

Modified: pypy/dist/pypy/rpython/ootypesystem/ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/ootype.py	Thu Sep 13 19:08:07 2007
@@ -381,6 +381,25 @@
     def _specialize(self, generic_types):
         return self
 
+# WARNING: the name WeakReference is rebound at the end of file
+class WeakReference(BuiltinADTType):
+    def __init__(self):
+        self._null = _null_weak_reference(self)
+        self._GENERIC_METHODS = frozendict({
+            "ll_set": Meth([ROOT], Void),
+            "ll_deref": Meth([], ROOT),
+            })
+        self._setup_methods({})
+
+    def _defl(self):
+        return self._null
+
+    def _get_interp_class(self):
+        return _weak_reference
+
+    def _specialize(self, generic_types):
+        return self
+
 class List(BuiltinADTType):
     # placeholders for types
     # make sure that each derived class has his own SELFTYPE_T
@@ -787,6 +806,9 @@
     _enforce = _upcast
 
     def _downcast(self, INSTANCE):
+        if not self._inst:
+            assert isSubclass(INSTANCE, self._TYPE) or isSubclass(self._TYPE, INSTANCE)
+            return null(INSTANCE)
         assert isSubclass(INSTANCE, self._TYPE)
         return _view(INSTANCE, self._inst)
 
@@ -1133,6 +1155,37 @@
     def __init__(self, STRING_BUILDER):
         self.__dict__["_TYPE"] = STRING_BUILDER
 
+import weakref
+
+class _weak_reference(_builtin_type):
+    def __init__(self, WEAK_REFERENCE):
+        self._TYPE = WEAK_REFERENCE
+        self._ref = None
+
+    def _unwrap_view(self, obj):
+        # we can't store directly the view inside the weakref because
+        # the view can be a temp object that is not referenced
+        # anywhere else.
+        while isinstance(obj, _view):
+            obj = obj._inst
+        return obj
+
+    def ll_set(self, target):
+        assert isinstance(typeOf(target), Instance)
+        target = self._unwrap_view(target)
+        self._ref = weakref.ref(target)
+
+    def ll_deref(self):
+        if self._ref is None:
+            return null(ROOT)
+        result = self._ref()
+        if result is None:
+            return null(ROOT)
+        return _view(ROOT, result)
+
+class _null_weak_reference(_null_mixin(_weak_reference), _weak_reference):
+    def __init__(self, WEAK_REFERENCE):
+        self.__dict__["_TYPE"] = WEAK_REFERENCE
 
 class _list(_builtin_type):
     def __init__(self, LIST):
@@ -1475,6 +1528,13 @@
 def hasDictTypes(DICT):
     return DICT._is_initialized()
 
+def ooweakref_create(obj):
+    ref = new(WeakReference)
+    ref.ll_set(obj)
+    return ref
+
+ROOT = Instance('Root', None, _is_root=True)
 String = String()
 StringBuilder = StringBuilder()
-ROOT = Instance('Root', None, _is_root=True)
+WeakReference = WeakReference()
+dead_wref = new(WeakReference)

Modified: pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/rbuiltin.py	Thu Sep 13 19:08:07 2007
@@ -101,3 +101,18 @@
 BUILTIN_TYPER[isinstance] = rtype_builtin_isinstance
 BUILTIN_TYPER[objectmodel.r_dict] = rtype_r_dict
 BUILTIN_TYPER[objectmodel.instantiate] = rtype_instantiate
+
+
+# _________________________________________________________________
+# weakrefs
+
+import weakref
+from pypy.rpython.lltypesystem import llmemory
+
+def rtype_weakref_create(hop):
+    # Note: this code also works for the RPython-level calls 'weakref.ref(x)'.
+    vlist = hop.inputargs(hop.args_r[0])
+    hop.exception_cannot_occur()
+    return hop.gendirectcall(ootype.ooweakref_create, *vlist)
+
+BUILTIN_TYPER[weakref.ref] = rtype_weakref_create

Modified: pypy/dist/pypy/rpython/ootypesystem/test/test_ootype.py
==============================================================================
--- pypy/dist/pypy/rpython/ootypesystem/test/test_ootype.py	(original)
+++ pypy/dist/pypy/rpython/ootypesystem/test/test_ootype.py	Thu Sep 13 19:08:07 2007
@@ -451,3 +451,27 @@
     DT = DictItemsIterator(String, Signed)
     _, meth = DT._lookup('ll_go_next')
     assert meth._can_raise == True
+
+def test_cast_null():
+    A = Instance("A", ROOT)
+    B = Instance("B", ROOT)
+    rootnull = null(ROOT)
+    anull = oodowncast(A, rootnull)
+    assert typeOf(anull) is A
+    assert ooupcast(ROOT, anull) == rootnull
+    py.test.raises(AssertionError, oodowncast, B, anull)
+
+def test_weak_reference():
+    import gc
+    A = Instance("A", ROOT)
+    obj = new(A)
+    ref = new(WeakReference)
+    ref.ll_set(obj)
+    assert oodowncast(A, ref.ll_deref()) == obj
+    del obj
+    gc.collect()
+    assert ref.ll_deref() is null(ROOT)
+
+def test_dead_wref():
+    ref = new(WeakReference)
+    assert ref.ll_deref() is null(ROOT)

Modified: pypy/dist/pypy/rpython/rbuiltin.py
==============================================================================
--- pypy/dist/pypy/rpython/rbuiltin.py	(original)
+++ pypy/dist/pypy/rpython/rbuiltin.py	Thu Sep 13 19:08:07 2007
@@ -594,42 +594,6 @@
 BUILTIN_TYPER[llmemory.offsetof] = rtype_offsetof
 
 # _________________________________________________________________
-# weakrefs
-
-import weakref
-
-def rtype_weakref_create(hop):
-    # Note: this code also works for the RPython-level calls 'weakref.ref(x)'.
-    vlist = hop.inputargs(hop.args_r[0])
-    hop.exception_cannot_occur()
-    return hop.genop('weakref_create', vlist, resulttype=llmemory.WeakRefPtr)
-
-def rtype_weakref_deref(hop):
-    c_ptrtype, v_wref = hop.inputargs(lltype.Void, hop.args_r[1])
-    assert v_wref.concretetype == llmemory.WeakRefPtr
-    hop.exception_cannot_occur()
-    return hop.genop('weakref_deref', [v_wref], resulttype=c_ptrtype.value)
-
-def rtype_cast_ptr_to_weakrefptr(hop):
-    vlist = hop.inputargs(hop.args_r[0])
-    hop.exception_cannot_occur()
-    return hop.genop('cast_ptr_to_weakrefptr', vlist,
-                     resulttype=llmemory.WeakRefPtr)
-
-def rtype_cast_weakrefptr_to_ptr(hop):
-    c_ptrtype, v_wref = hop.inputargs(lltype.Void, hop.args_r[1])
-    assert v_wref.concretetype == llmemory.WeakRefPtr
-    hop.exception_cannot_occur()
-    return hop.genop('cast_weakrefptr_to_ptr', [v_wref],
-                     resulttype=c_ptrtype.value)
-
-BUILTIN_TYPER[weakref.ref] = rtype_weakref_create
-BUILTIN_TYPER[llmemory.weakref_create] = rtype_weakref_create
-BUILTIN_TYPER[llmemory.weakref_deref ] = rtype_weakref_deref
-BUILTIN_TYPER[llmemory.cast_ptr_to_weakrefptr] = rtype_cast_ptr_to_weakrefptr
-BUILTIN_TYPER[llmemory.cast_weakrefptr_to_ptr] = rtype_cast_weakrefptr_to_ptr
-
-# _________________________________________________________________
 # non-gc objects
 
 def rtype_free_non_gc_object(hop):

Modified: pypy/dist/pypy/rpython/rweakref.py
==============================================================================
--- pypy/dist/pypy/rpython/rweakref.py	(original)
+++ pypy/dist/pypy/rpython/rweakref.py	Thu Sep 13 19:08:07 2007
@@ -5,6 +5,7 @@
 from pypy.rpython.rmodel import Repr
 from pypy.rpython.rclass import getinstancerepr
 from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.ootypesystem import ootype
 
 # ____________________________________________________________
 #
@@ -12,13 +13,14 @@
 
 class __extend__(annmodel.SomeWeakRef):
     def rtyper_makerepr(self, rtyper):
-        return WeakRefRepr(rtyper)
+        if rtyper.type_system.name == 'lltypesystem':
+            return LLWeakRefRepr(rtyper)
+        else:
+            return OOWeakRefRepr(rtyper)
     def rtyper_makekey(self):
         return self.__class__,
 
-
-class WeakRefRepr(Repr):
-    lowleveltype = llmemory.WeakRefPtr
+class BaseWeakRefRepr(Repr):
 
     def __init__(self, rtyper):
         self.rtyper = rtyper
@@ -26,11 +28,6 @@
             raise TyperError("RPython-level weakrefs are not supported by "
                              "this backend or GC policy")
 
-    def rtype_simple_call(self, hop):
-        v_wref, = hop.inputargs(self)
-        hop.exception_cannot_occur()
-        return hop.genop('weakref_deref', [v_wref], resulttype=hop.r_result)
-
     def convert_const(self, value):
         assert isinstance(value, weakref.ReferenceType)
         instance = value()
@@ -38,8 +35,37 @@
         # obscure!  if the annotator hasn't seen this object before,
         # we don't want to look at it now (confusion tends to result).
         if instance is None or not bk.have_seen(instance):
-            return llmemory.dead_wref
+            return self.dead_wref
         else:
             repr = self.rtyper.bindingrepr(Constant(instance))
             llinstance = repr.convert_const(instance)
-            return llmemory.weakref_create(llinstance)
+            return self._weakref_create(llinstance)
+
+    def _weakref_create(self, llinstance):
+        raise NotImplementedError
+
+class LLWeakRefRepr(BaseWeakRefRepr):
+    lowleveltype = llmemory.WeakRefPtr
+    dead_wref = llmemory.dead_wref
+
+    def rtype_simple_call(self, hop):
+        v_wref, = hop.inputargs(self)
+        hop.exception_cannot_occur()
+        return hop.genop('weakref_deref', [v_wref], resulttype=hop.r_result)
+
+    def _weakref_create(self, llinstance):
+        return llmemory.weakref_create(llinstance)
+
+class OOWeakRefRepr(BaseWeakRefRepr):
+    lowleveltype = ootype.WeakReference
+    dead_wref = ootype.dead_wref
+    
+    def rtype_simple_call(self, hop):
+        v_wref, = hop.inputargs(self)
+        cname = hop.inputconst(ootype.Void, 'll_deref')
+        hop.exception_cannot_occur()
+        v_deref = hop.genop('oosend', [cname, v_wref], resulttype=ootype.ROOT)
+        return hop.genop('oodowncast', [v_deref], resulttype=hop.r_result)
+
+    def _weakref_create(self, llinstance):
+        return ootype.ooweakref_create(llinstance)

Modified: pypy/dist/pypy/rpython/test/test_rweakref.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rweakref.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rweakref.py	Thu Sep 13 19:08:07 2007
@@ -1,89 +1,95 @@
 import py, weakref
 from pypy.rlib import rgc
 from pypy.rpython.lltypesystem import lltype, llmemory
-from pypy.rpython.test.test_llinterp import interpret
+from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
 
+class BaseTestRweakref(BaseRtypingTest):
 
-def test_ll_weakref():
-    S = lltype.GcStruct('S', ('x',lltype.Signed))
-    def g():
-        s = lltype.malloc(S)
-        w = llmemory.weakref_create(s)
-        assert llmemory.weakref_deref(lltype.Ptr(S), w) == s
-        assert llmemory.weakref_deref(lltype.Ptr(S), w) == s
-        return w   # 's' is forgotten here
-    def f():
-        w = g()
+    def test_weakref_simple(self):
+        class A:
+            pass
+        class B(A):
+            pass
+        class C(A):
+            pass
+
+        def f(n):
+            if n:
+                x = B()
+                x.hello = 42
+                r = weakref.ref(x)
+            else:
+                x = C()
+                x.hello = 64
+                r = weakref.ref(x)
+            return r().hello, x      # returns 'x' too, to keep it alive
+        res = self.interpret(f, [1])
+        assert res.item0 == 42
+        res = self.interpret(f, [0])
+        assert res.item0 == 64
+
+    def test_prebuilt_weakref(self):
+        class A:
+            pass
+        a1 = A()
+        a1.hello = 5
+        w1 = weakref.ref(a1)
+        a2 = A()
+        a2.hello = 8
+        w2 = weakref.ref(a2)
+
+        def f(n):
+            if n:
+                r = w1
+            else:
+                r = w2
+            return r().hello
+        res = self.interpret(f, [1])
+        assert res == 5
+        res = self.interpret(f, [0])
+        assert res == 8
+
+    def test_prebuilt_dead_weakref(self):
+        class A:
+            pass
+        a1 = A()
+        w1 = weakref.ref(a1)
+        a2 = A()
+        w2 = weakref.ref(a2)
+
+        del a1
         rgc.collect()
-        return llmemory.weakref_deref(lltype.Ptr(S), w)
+        assert w1() is None
+
+        def f(n):
+            if n:
+                r = w1
+            else:
+                r = w2
+            return r() is not None
+        res = self.interpret(f, [1])
+        assert res == False
+        res = self.interpret(f, [0])
+        assert res == True
+
+
+class TestLLtype(BaseTestRweakref, LLRtypeMixin):
+    def test_ll_weakref(self):
+        S = lltype.GcStruct('S', ('x',lltype.Signed))
+        def g():
+            s = lltype.malloc(S)
+            w = llmemory.weakref_create(s)
+            assert llmemory.weakref_deref(lltype.Ptr(S), w) == s
+            assert llmemory.weakref_deref(lltype.Ptr(S), w) == s
+            return w   # 's' is forgotten here
+        def f():
+            w = g()
+            rgc.collect()
+            return llmemory.weakref_deref(lltype.Ptr(S), w)
 
-    res = interpret(f, [])
-    assert res == lltype.nullptr(S)
+        res = self.interpret(f, [])
+        assert res == lltype.nullptr(S)
 
 
-def test_weakref_simple():
-    class A:
-        pass
-    class B(A):
-        pass
-    class C(A):
-        pass
-
-    def f(n):
-        if n:
-            x = B()
-            x.hello = 42
-            r = weakref.ref(x)
-        else:
-            x = C()
-            x.hello = 64
-            r = weakref.ref(x)
-        return r().hello, x      # returns 'x' too, to keep it alive
-    res = interpret(f, [1])
-    assert res.item0 == 42
-    res = interpret(f, [0])
-    assert res.item0 == 64
-
-def test_prebuilt_weakref():
-    class A:
-        pass
-    a1 = A()
-    a1.hello = 5
-    w1 = weakref.ref(a1)
-    a2 = A()
-    a2.hello = 8
-    w2 = weakref.ref(a2)
-
-    def f(n):
-        if n:
-            r = w1
-        else:
-            r = w2
-        return r().hello
-    res = interpret(f, [1])
-    assert res == 5
-    res = interpret(f, [0])
-    assert res == 8
-
-def test_prebuilt_dead_weakref():
-    class A:
-        pass
-    a1 = A()
-    w1 = weakref.ref(a1)
-    a2 = A()
-    w2 = weakref.ref(a2)
-
-    del a1
-    rgc.collect()
-    assert w1() is None
-
-    def f(n):
-        if n:
-            r = w1
-        else:
-            r = w2
-        return r() is not None
-    res = interpret(f, [1])
-    assert res == False
-    res = interpret(f, [0])
-    assert res == True
+class TestOOtype(BaseTestRweakref, OORtypeMixin):
+    pass


More information about the pypy-svn mailing list