[pypy-svn] r32682 - in pypy/dist/pypy/rpython: . test

arigo at codespeak.net arigo at codespeak.net
Wed Sep 27 21:11:23 CEST 2006


Author: arigo
Date: Wed Sep 27 21:11:22 2006
New Revision: 32682

Modified:
   pypy/dist/pypy/rpython/annlowlevel.py
   pypy/dist/pypy/rpython/rmodel.py
   pypy/dist/pypy/rpython/test/test_llann.py
Log:
(pedronis, arre, arigo)

Mostly obscure extensions to annlowlevel.py to cope with what the JIT
requires: capability to build delayed function pointers whose lltype
is still computed early; and a bunch of cast_xxx() functions to convert
between low-level and high-level representations of objects.



Modified: pypy/dist/pypy/rpython/annlowlevel.py
==============================================================================
--- pypy/dist/pypy/rpython/annlowlevel.py	(original)
+++ pypy/dist/pypy/rpython/annlowlevel.py	Wed Sep 27 21:11:22 2006
@@ -119,8 +119,9 @@
 
 class MixLevelAnnotatorPolicy(LowLevelAnnotatorPolicy):
 
-    def __init__(pol, rtyper):
-        pol.rtyper = rtyper
+    def __init__(pol, annhelper):
+        pol.annhelper = annhelper
+        pol.rtyper = annhelper.rtyper
 
     def default_specialize(pol, funcdesc, args_s):
         name = funcdesc.name
@@ -147,9 +148,9 @@
 
     def __init__(self, rtyper):
         self.rtyper = rtyper
-        self.policy = MixLevelAnnotatorPolicy(rtyper)
+        self.policy = MixLevelAnnotatorPolicy(self)
         self.pending = []     # list of (ll_function, graph, args_s, s_result)
-        self.delayedreprs = []
+        self.delayedreprs = {}
         self.delayedconsts = []
         self.delayedfuncs = []
         self.original_graph_count = len(rtyper.annotator.translator.graphs)
@@ -167,18 +168,26 @@
         self.pending.append((ll_function, graph, args_s, s_result))
         return graph
 
-    def delayedfunction(self, ll_function, args_s, s_result):
+    def delayedfunction(self, ll_function, args_s, s_result, needtype=False):
         # get a delayed pointer to the low-level function, annotated as
         # specified.  The pointer is only valid after finish() was called.
         graph = self.getgraph(ll_function, args_s, s_result)
-        return self.graph2delayed(graph)
+        if needtype:
+            ARGS = [self.getdelayedrepr(s_arg, False).lowleveltype
+                    for s_arg in args_s]
+            RESULT = self.getdelayedrepr(s_result, False).lowleveltype
+            FUNCTYPE = lltype.FuncType(ARGS, RESULT)
+        else:
+            FUNCTYPE = None
+        return self.graph2delayed(graph, FUNCTYPE)
 
     def constfunc(self, ll_function, args_s, s_result):
         p = self.delayedfunction(ll_function, args_s, s_result)
         return Constant(p, lltype.typeOf(p))
 
-    def graph2delayed(self, graph):
-        FUNCTYPE = lltype.ForwardReference()
+    def graph2delayed(self, graph, FUNCTYPE=None):
+        if FUNCTYPE is None:
+            FUNCTYPE = lltype.ForwardReference()
         # obscure hack: embed the name of the function in the string, so
         # that the genc database can get it even before the delayedptr
         # is really computed
@@ -191,20 +200,25 @@
         p = self.graph2delayed(graph)
         return Constant(p, lltype.typeOf(p))
 
-    def getdelayedrepr(self, s_value):
+    def getdelayedrepr(self, s_value, check_never_seen=True):
         """Like rtyper.getrepr(), but the resulting repr will not be setup() at
         all before finish() is called.
         """
         r = self.rtyper.getrepr(s_value)
-        r.set_setup_delayed(True)
-        self.delayedreprs.append(r)
+        if check_never_seen:
+            r.set_setup_delayed(True)
+            delayed = True
+        else:
+            delayed = r.set_setup_maybe_delayed()
+        if delayed:
+            self.delayedreprs[r] = True
         return r
 
-    def s_r_instanceof(self, cls, can_be_None=True):
+    def s_r_instanceof(self, cls, can_be_None=True, check_never_seen=True):
         classdesc = self.rtyper.annotator.bookkeeper.getdesc(cls)
         classdef = classdesc.getuniqueclassdef()
         s_instance = annmodel.SomeInstance(classdef, can_be_None)
-        r_instance = self.getdelayedrepr(s_instance)
+        r_instance = self.getdelayedrepr(s_instance, check_never_seen)
         return s_instance, r_instance
 
     def delayedconst(self, repr, obj):
@@ -259,10 +273,14 @@
         rtyper.call_all_setups()
         for p, graph in self.delayedfuncs:
             real_p = rtyper.getcallable(graph)
-            lltype.typeOf(p).TO.become(lltype.typeOf(real_p).TO)
+            REAL = lltype.typeOf(real_p).TO
+            FUNCTYPE = lltype.typeOf(p).TO
+            if isinstance(FUNCTYPE, lltype.ForwardReference):
+                FUNCTYPE.become(REAL)
+            assert FUNCTYPE == REAL
             p._become(real_p)
         rtyper.specialize_more_blocks()
-        del self.delayedreprs[:]
+        self.delayedreprs.clear()
         del self.delayedconsts[:]
         del self.delayedfuncs[:]
 
@@ -330,7 +348,73 @@
 
     def specialize_call(self, hop):
         return hop.args_r[1].get_unique_llfn()
-        
+
+# ____________________________________________________________
+
+def cast_object_to_ptr(PTR, object):
+    raise NotImplementedError("cast_object_to_ptr")
+
+def cast_instance_to_base_ptr(instance):
+    return cast_object_to_ptr(base_ptr_lltype(), instance)
+
+def base_ptr_lltype():
+    from pypy.rpython.lltypesystem.rclass import OBJECTPTR
+    return OBJECTPTR
+
+class CastObjectToPtrEntry(extregistry.ExtRegistryEntry):
+    _about_ = cast_object_to_ptr
+
+    def compute_result_annotation(self, s_PTR, s_object):
+        assert s_PTR.is_constant()
+        assert isinstance(s_PTR.const, lltype.Ptr)
+        return annmodel.SomePtr(s_PTR.const)
+
+    def specialize_call(self, hop):
+        v_arg = hop.inputarg(hop.args_r[1], arg=1)
+        assert isinstance(v_arg.concretetype, lltype.Ptr)
+        return hop.genop('cast_pointer', [v_arg],
+                         resulttype = hop.r_result.lowleveltype)
+
+# ____________________________________________________________
+
+def cast_base_ptr_to_instance(Class, ptr):
+    raise NotImplementedError("cast_base_ptr_to_instance")
+
+class CastBasePtrToInstanceEntry(extregistry.ExtRegistryEntry):
+    _about_ = cast_base_ptr_to_instance
+
+    def compute_result_annotation(self, s_Class, s_ptr):
+        assert s_Class.is_constant()
+        classdef = self.bookkeeper.getuniqueclassdef(s_Class.const)
+        return annmodel.SomeInstance(classdef, can_be_None=True)
+
+    def specialize_call(self, hop):
+        v_arg = hop.inputarg(hop.args_r[1], arg=1)
+        assert isinstance(v_arg.concretetype, lltype.Ptr)
+        return hop.genop('cast_pointer', [v_arg],
+                         resulttype = hop.r_result.lowleveltype)
+
+# ____________________________________________________________
+
+## XXX finish me
+##def cast_instance_to_ptr(Class, instance):
+##    raise NotImplementedError("cast_instance_to_ptr")
+
+##class CastInstanceToPtrEntry(extregistry.ExtRegistryEntry):
+##    _about_ = cast_instance_to_ptr
+
+##    def compute_result_annotation(self, s_Class, s_instance):
+##        assert s_Class.is_constant()
+##        pol = self.bookkeeper.annotator.policy
+##        s_Instance, r_Instance = pol.annhelper.s_r_instanceof(s_Class.const)
+##        return annmodel.SomePtr(r_Instance.lowleveltype)
+
+##    def specialize_call(self, hop):
+##        v_arg = hop.inputarg(hop.args_r[1], arg=1)
+##        assert isinstance(v_arg.concretetype, lltype.Ptr)
+##        return hop.genop('cast_pointer', [v_arg],
+##                         resulttype = hop.r_result.lowleveltype)
+
 # ____________________________________________________________
 
 def placeholder_sigarg(s):
@@ -401,3 +485,22 @@
             else:
                 meth._annenforceargs_ = sig
         return adtmeths
+
+# ____________________________________________________________
+
+class cachedtype(type):
+    """Metaclass for classes that should only have one instance per
+    tuple of arguments given to the constructor."""
+
+    def __init__(selfcls, name, bases, dict):
+        super(cachedtype, selfcls).__init__(name, bases, dict)
+        selfcls._instancecache = {}
+
+    def __call__(selfcls, *args):
+        d = selfcls._instancecache
+        try:
+            return d[args]
+        except KeyError:
+            instance = d[args] = selfcls.__new__(selfcls, *args)
+            instance.__init__(*args)
+            return instance

Modified: pypy/dist/pypy/rpython/rmodel.py
==============================================================================
--- pypy/dist/pypy/rpython/rmodel.py	(original)
+++ pypy/dist/pypy/rpython/rmodel.py	Wed Sep 27 21:11:22 2006
@@ -90,6 +90,11 @@
         else:
             self._initialized = setupstate.NOTINITIALIZED
 
+    def set_setup_maybe_delayed(self):
+        if self._initialized == setupstate.NOTINITIALIZED:
+            self._initialized = setupstate.DELAYED
+        return self._initialized == setupstate.DELAYED
+
     def __getattr__(self, name):
         # Assume that when an attribute is missing, it's because setup() needs
         # to be called

Modified: pypy/dist/pypy/rpython/test/test_llann.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_llann.py	(original)
+++ pypy/dist/pypy/rpython/test/test_llann.py	Wed Sep 27 21:11:22 2006
@@ -1,10 +1,12 @@
 from pypy.rpython.lltypesystem.lltype import *
+from pypy.rpython.lltypesystem.rclass import OBJECTPTR, fishllattr
 from pypy.translator.translator import TranslationContext
 from pypy.annotation import model as annmodel
 from pypy.rpython.annlowlevel import annotate_lowlevel_helper
 from pypy.rpython.annlowlevel import MixLevelHelperAnnotator
 from pypy.rpython.annlowlevel import PseudoHighLevelCallable
-from pypy.rpython.annlowlevel import llhelper
+from pypy.rpython.annlowlevel import llhelper, cast_instance_to_base_ptr
+from pypy.rpython.annlowlevel import base_ptr_lltype
 from pypy.rpython.llinterp import LLInterpreter
 from pypy.rpython.test.test_llinterp import interpret
 from pypy.objspace.flow import FlowObjSpace 
@@ -371,3 +373,20 @@
 
     res = interpret(h, [8, 5, 2])
     assert res == 99
+
+
+def test_cast_instance_to_base_ptr():
+    class A:
+        def __init__(self, x, y):
+            self.x = x
+            self.y = y
+
+    def f(x, y):
+        a = A(x, y)
+        a1 = cast_instance_to_base_ptr(a)
+        return a1
+
+    res = interpret(f, [5, 10])
+    assert typeOf(res) == base_ptr_lltype()
+    assert fishllattr(res, 'x') == 5
+    assert fishllattr(res, 'y') == 10



More information about the Pypy-commit mailing list