[pypy-svn] r27541 - in pypy/dist/pypy: annotation rpython rpython/lltypesystem rpython/lltypesystem/test rpython/memory/test rpython/rctypes

arigo at codespeak.net arigo at codespeak.net
Sun May 21 18:40:08 CEST 2006


Author: arigo
Date: Sun May 21 18:40:05 2006
New Revision: 27541

Added:
   pypy/dist/pypy/rpython/rgc.py   (contents, props changed)
Modified:
   pypy/dist/pypy/annotation/model.py
   pypy/dist/pypy/rpython/lltypesystem/lltype.py
   pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py
   pypy/dist/pypy/rpython/memory/test/test_gctransform.py
   pypy/dist/pypy/rpython/memory/test/test_transformed_gc.py
   pypy/dist/pypy/rpython/rctypes/implementation.py
   pypy/dist/pypy/rpython/rexternalobj.py
   pypy/dist/pypy/rpython/rmodel.py
   pypy/dist/pypy/rpython/rtyper.py
Log:
(some pedronis, arigo)

* added pypy.rpython.rgc with an RPython interface to the gc_x_swap_pool
  and gc_x_clone operations.

* made SomeExternalObject use the extregistry too.

* bug fixes; extended cast_opaque_ptr to also do a cast_pointer for
  you.



Modified: pypy/dist/pypy/annotation/model.py
==============================================================================
--- pypy/dist/pypy/annotation/model.py	(original)
+++ pypy/dist/pypy/annotation/model.py	Sun May 21 18:40:05 2006
@@ -405,9 +405,10 @@
 
 
 class SomeExternalObject(SomeObject):
-    """Stands for an object of 'external' type.  External types are defined
-    in pypy.rpython.extfunctable.declaretype(), and represent simple types
-    with some methods that need direct back-end support."""
+    """Stands for an object of 'external' type.  External types have a Repr
+    controlled by pypy.rpython.extregistry; or they come from the (obsolete)
+    table created by pypy.rpython.extfunctable.declaretype() and represent
+    simple types with some methods that need direct back-end support."""
 
     def __init__(self, knowntype):
         self.knowntype = knowntype
@@ -415,7 +416,7 @@
     def can_be_none(self):
         return True
 
-class SomeCTypesObject(SomeObject):
+class SomeCTypesObject(SomeExternalObject):
     """Stands for an object of the ctypes module."""
 
     NOMEMORY = "NOMEMORY"

Modified: pypy/dist/pypy/rpython/lltypesystem/lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/lltype.py	Sun May 21 18:40:05 2006
@@ -679,13 +679,10 @@
         try:
             container = ptr._obj.container
         except AttributeError:
-            raise RuntimeError("%r does not come from a container" % (ptr,))
-        if typeOf(container) != PTRTYPE.TO:
-            raise RuntimeError("%r contains a container of the wrong type:\n"
-                               "%r instead of %r" % (ptr, typeOf(container),
-                                                     PTRTYPE.TO))
+            raise InvalidCast("%r does not come from a container" % (ptr,))
         solid = getattr(ptr._obj, 'solid', False)
-        return _ptr(PTRTYPE, container, solid)
+        p = _ptr(Ptr(typeOf(container)), container, solid)
+        return cast_pointer(PTRTYPE, p)
     elif (not isinstance(CURTYPE.TO, OpaqueType)
           and isinstance(PTRTYPE.TO, OpaqueType)):
         if not ptr:
@@ -699,7 +696,7 @@
         try:
             container = ptr._obj.container
         except AttributeError:
-            raise RuntimeError("%r does not come from a container" % (ptr,))
+            raise InvalidCast("%r does not come from a container" % (ptr,))
         return opaqueptr(PTRTYPE.TO, 'hidden',
                          container = container,
                          solid     = ptr._obj.solid)

Modified: pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/test/test_lltype.py	Sun May 21 18:40:05 2006
@@ -470,7 +470,7 @@
     py.test.raises(TypeError, "cast_opaque_ptr(Ptr(S), o1)")
     py.test.raises(TypeError, "cast_opaque_ptr(Ptr(O1), s)")
     S2 = Struct('S2', ('z', Signed))
-    py.test.raises(RuntimeError, "cast_opaque_ptr(Ptr(S2), o1)")
+    py.test.raises(InvalidCast, "cast_opaque_ptr(Ptr(S2), o1)")
 
 def test_is_atomic():
     U = Struct('inlined', ('z', Signed))

Modified: pypy/dist/pypy/rpython/memory/test/test_gctransform.py
==============================================================================
--- pypy/dist/pypy/rpython/memory/test/test_gctransform.py	(original)
+++ pypy/dist/pypy/rpython/memory/test/test_gctransform.py	Sun May 21 18:40:05 2006
@@ -64,7 +64,7 @@
     t = TranslationContext()
     t.buildannotator().build_types(func, inputtypes)
     if specialize:
-        t.buildrtyper().specialize(t)
+        t.buildrtyper().specialize()
     return t    
 
 def rtype_and_transform(func, inputtypes, transformcls, specialize=True, check=True):
@@ -442,7 +442,7 @@
         pass
     t = TranslationContext()
     t.buildannotator().build_types(f, [])
-    t.buildrtyper().specialize(t)
+    t.buildrtyper().specialize()
     transformer = cls(t)
     fptr = getattr(transformer, attr)(TYPE)
     transformer.finish()
@@ -554,7 +554,7 @@
         pass
     t = TranslationContext()
     t.buildannotator().build_types(f, [])
-    t.buildrtyper().specialize(t)
+    t.buildrtyper().specialize()
     transformer = gctransform.RefcountingGCTransformer(t)
     p_S = transformer.dynamic_deallocation_funcptr_for_type(S)
     p_S1 = transformer.dynamic_deallocation_funcptr_for_type(S1)

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	Sun May 21 18:40:05 2006
@@ -170,7 +170,7 @@
     t = TranslationContext()
     t.buildannotator().build_types(func, inputtypes)
     if specialize:
-        t.buildrtyper().specialize(t)
+        t.buildrtyper().specialize()
     if conftest.option.view:
         t.view()
     return t
@@ -382,6 +382,40 @@
         res = run([])
         assert res == 111222333
 
+    def test_cloning_highlevel(self):
+        from pypy.rpython import rgc
+        class A:
+            pass
+        class B(A):
+            pass
+        def func(n, dummy):
+            if n > 5:
+                x = A()
+            else:
+                x = B()
+                x.bvalue = 123
+            x.next = A()
+            x.next.next = x
+            y, newpool = rgc.gc_clone(x, None)
+            assert y is not x
+            assert y.next is not x
+            assert y is not x.next
+            assert y.next is not x.next
+            assert y is not y.next
+            assert y is y.next.next
+            if isinstance(y, B):
+                assert n <= 5
+                assert y.bvalue == 123
+            else:
+                assert n > 5
+            return 1
+
+        run = self.runner(func, nbargs=2)
+        res = run([3, 0])
+        assert res == 1
+        res = run([7, 0])
+        assert res == 1
+
     def test_tree_cloning(self):
         import os
         # this makes a tree of calls.  Each leaf stores its path (a linked

Modified: pypy/dist/pypy/rpython/rctypes/implementation.py
==============================================================================
--- pypy/dist/pypy/rpython/rctypes/implementation.py	(original)
+++ pypy/dist/pypy/rpython/rctypes/implementation.py	Sun May 21 18:40:05 2006
@@ -118,15 +118,3 @@
 import pypy.rpython.rctypes.avoid_p
 import pypy.rpython.rctypes.astringbuf
 import pypy.rpython.rctypes.apyobject
-
-
-# Register the correspondance between SomeCTypesObject and the get_repr()
-# functions attached to the extregistry to create CTypesReprs
-
-class __extend__( SomeCTypesObject ):
-    def rtyper_makerepr( self, rtyper ):
-        entry = extregistry.lookup_type(self.knowntype)
-        return entry.get_repr(rtyper, self)
-
-    def rtyper_makekey( self ):
-        return self.__class__, self.knowntype, self.memorystate

Modified: pypy/dist/pypy/rpython/rexternalobj.py
==============================================================================
--- pypy/dist/pypy/rpython/rexternalobj.py	(original)
+++ pypy/dist/pypy/rpython/rexternalobj.py	Sun May 21 18:40:05 2006
@@ -5,16 +5,33 @@
 from pypy.rpython import rbuiltin
 from pypy.rpython.module.support import init_opaque_object
 from pypy.objspace.flow.model import Constant
+from pypy.rpython import extregistry
 
 
 class __extend__(annmodel.SomeExternalObject):
+
     def rtyper_makerepr(self, rtyper):
-        return ExternalObjRepr(self.knowntype)
+        if self.knowntype in typetable:
+            return ExternalObjRepr(self.knowntype)
+        else:
+            # delegate to the get_repr() of the extregistrered Entry class
+            entry = extregistry.lookup_type(self.knowntype)
+            return entry.get_repr(rtyper, self)
+
     def rtyper_makekey(self):
-        return self.__class__, self.knowntype
+        # grab all attributes of the SomeExternalObject for the key
+        attrs = lltype.frozendict(self.__dict__)
+        if 'const' in attrs:
+            del attrs['const']
+        if 'const_box' in attrs:
+            del attrs['const_box']
+        return self.__class__, attrs
 
 
 class ExternalObjRepr(Repr):
+    """Repr for the (obsolecent) extfunctable.declaretype() case.
+    If you use the extregistry instead you get to pick your own Repr.
+    """
 
     def __init__(self, knowntype):
         self.exttypeinfo = typetable[knowntype]

Added: pypy/dist/pypy/rpython/rgc.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/rpython/rgc.py	Sun May 21 18:40:05 2006
@@ -0,0 +1,94 @@
+from pypy.rpython.extregistry import ExtRegistryEntry
+
+# ____________________________________________________________
+# Framework GC features
+
+class GcPool(object):
+    pass
+
+def gc_swap_pool(newpool):
+    """Set newpool as the current pool (create one if newpool is None).
+    All malloc'ed objects are put into the current pool;this is a
+    way to separate objects depending on when they were allocated.
+    """
+    raise NotImplementedError("only works in stacklessgc translated versions")
+
+def gc_clone(gcobject, pool):
+    """Recursively clone the gcobject and everything it points to,
+    directly or indirectly -- but stops at objects that are not
+    in the specified pool.  Pool can be None to mean the current one.
+    A new pool is built to contain the copies.  Return (newobject, newpool).
+    """
+    raise NotImplementedError("only works in stacklessgc translated versions")
+
+# ____________________________________________________________
+# Annotation and specialization
+
+class GcPoolEntry(ExtRegistryEntry):
+    "Link GcPool to its Repr."
+    _type_ = GcPool
+
+    def get_repr(self, rtyper, s_pool):
+        from pypy.rpython.rmodel import SimplePointerRepr
+        from pypy.rpython.memory.gc import X_POOL_PTR
+        return SimplePointerRepr(X_POOL_PTR)
+
+
+class SwapPoolFnEntry(ExtRegistryEntry):
+    "Annotation and specialization of gc_swap_pool()."
+    _about_ = gc_swap_pool
+
+    def compute_result_annotation(self, s_newpool):
+        from pypy.annotation import model as annmodel
+        return annmodel.SomeExternalObject(GcPool)
+
+    def specialize_call(self, hop):
+        from pypy.annotation import model as annmodel
+        s_pool_ptr = annmodel.SomeExternalObject(GcPool)
+        r_pool_ptr = hop.rtyper.getrepr(s_pool_ptr)
+        vlist = hop.inputargs(r_pool_ptr)
+        return hop.genop('gc_x_swap_pool', vlist, resulttype = r_pool_ptr)
+
+
+class CloneFnEntry(ExtRegistryEntry):
+    "Annotation and specialization of gc_clone()."
+    _about_ = gc_clone
+
+    def compute_result_annotation(self, s_gcobject, s_pool):
+        from pypy.annotation import model as annmodel
+        return annmodel.SomeTuple([s_gcobject,
+                                   annmodel.SomeExternalObject(GcPool)])
+
+    def specialize_call(self, hop):
+        from pypy.rpython.error import TyperError
+        from pypy.rpython.lltypesystem import lltype, llmemory, rtuple
+        r_gcobject = hop.args_r[0]
+        if (not isinstance(r_gcobject.lowleveltype, lltype.Ptr) or
+            not isinstance(r_gcobject.lowleveltype.TO, lltype.GC_CONTAINER)):
+            raise TyperError("gc_clone() can only clone a dynamically "
+                             "allocated object;\ngot %r" % (r_gcobject,))
+        from pypy.annotation import model as annmodel
+        from pypy.rpython.memory.gc import X_CLONE, X_CLONE_PTR
+        s_pool_ptr = annmodel.SomeExternalObject(GcPool)
+        r_pool_ptr = hop.rtyper.getrepr(s_pool_ptr)
+        r_tuple = hop.r_result
+
+        c_CLONE       = hop.inputconst(lltype.Void, X_CLONE)
+        c_gcobjectptr = hop.inputconst(lltype.Void, "gcobjectptr")
+        c_pool        = hop.inputconst(lltype.Void, "pool")
+
+        v_gcobject, v_pool = hop.inputargs(hop.args_r[0], r_pool_ptr)
+        v_gcobjectptr = hop.genop('cast_opaque_ptr', [v_gcobject],
+                                  resulttype = llmemory.GCREF)
+        v_clonedata = hop.genop('malloc', [c_CLONE],
+                                resulttype = X_CLONE_PTR)
+        hop.genop('setfield', [v_clonedata, c_gcobjectptr, v_gcobjectptr])
+        hop.genop('setfield', [v_clonedata, c_pool, v_pool])
+        hop.genop('gc_x_clone', [v_clonedata])
+        v_gcobjectptr = hop.genop('getfield', [v_clonedata, c_gcobjectptr],
+                                  resulttype = llmemory.GCREF)
+        v_pool        = hop.genop('getfield', [v_clonedata, c_pool],
+                                  resulttype = r_pool_ptr)
+        v_gcobject = hop.genop('cast_opaque_ptr', [v_gcobjectptr],
+                               resulttype = r_tuple.items_r[0])
+        return rtuple.newtuple(hop.llops, r_tuple, [v_gcobject, v_pool])

Modified: pypy/dist/pypy/rpython/rmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/rmodel.py	(original)
+++ pypy/dist/pypy/rpython/rmodel.py	Sun May 21 18:40:05 2006
@@ -344,6 +344,18 @@
     get_ll_fasthash_function = get_ll_hash_function
 impossible_repr = VoidRepr()
 
+class SimplePointerRepr(Repr):
+    "Convenience Repr for simple ll pointer types with no operation on them."
+
+    def __init__(self, lowleveltype):
+        self.lowleveltype = lowleveltype
+
+    def convert_const(self, value):
+        if value is not None:
+            raise TyperError("%r only supports None as prebuilt constant, "
+                             "got %r" % (self, value))
+        return lltype.nullptr(self.lowleveltype.TO)
+
 # ____________________________________________________________
 
 def inputdesc(reqtype, desc):

Modified: pypy/dist/pypy/rpython/rtyper.py
==============================================================================
--- pypy/dist/pypy/rpython/rtyper.py	(original)
+++ pypy/dist/pypy/rpython/rtyper.py	Sun May 21 18:40:05 2006
@@ -158,6 +158,7 @@
         """Main entry point: specialize all annotated blocks of the program."""
         self.crash_on_first_typeerror = crash_on_first_typeerror
         # specialize depends on annotator simplifications
+        assert dont_simplify_again in (False, True)  # safety check
         if not dont_simplify_again:
             self.annotator.simplify()
             



More information about the Pypy-commit mailing list