[pypy-svn] r29490 - in pypy/dist/pypy: jit/timeshifter jit/timeshifter/test rpython rpython/lltypesystem

arigo at codespeak.net arigo at codespeak.net
Thu Jun 29 15:40:50 CEST 2006


Author: arigo
Date: Thu Jun 29 15:40:47 2006
New Revision: 29490

Added:
   pypy/dist/pypy/jit/timeshifter/oop.py   (contents, props changed)
Modified:
   pypy/dist/pypy/jit/timeshifter/rtyper.py
   pypy/dist/pypy/jit/timeshifter/rvalue.py
   pypy/dist/pypy/jit/timeshifter/test/test_vlist.py
   pypy/dist/pypy/jit/timeshifter/vlist.py
   pypy/dist/pypy/rpython/lltypesystem/rlist.py
   pypy/dist/pypy/rpython/rgenop.py
Log:
(arre, pedronis, arigo)

Forcing lists, and more oopspec wacking to support falling back to the
original operation in case of forced lists.



Added: pypy/dist/pypy/jit/timeshifter/oop.py
==============================================================================
--- (empty file)
+++ pypy/dist/pypy/jit/timeshifter/oop.py	Thu Jun 29 15:40:47 2006
@@ -0,0 +1,71 @@
+from pypy.rpython.lltypesystem import lltype
+from pypy.rpython import rgenop
+from pypy.jit.timeshifter.rcontainer import cachedtype
+from pypy.jit.timeshifter import rvalue
+
+
+class Index:
+    def __init__(self, n):
+        self.n = n
+
+
+class OopSpecDesc:
+    __metaclass__ = cachedtype
+
+    def __init__(self, fnobj):
+        ll_func = fnobj._callable
+        FUNCTYPE = lltype.typeOf(fnobj)
+        nb_args = len(FUNCTYPE.ARGS)
+
+        # parse the oopspec and fill in the arguments
+        operation_name, args = ll_func.oopspec.split('(', 1)
+        assert args.endswith(')')
+        args = args[:-1] + ','     # trailing comma to force tuple syntax
+        argnames = ll_func.func_code.co_varnames[:nb_args]
+        d = dict(zip(argnames, [Index(n) for n in range(nb_args)]))
+        self.argtuple = eval(args, d)
+        # end of rather XXX'edly hackish parsing
+
+        self.argpositions = []
+        for i, obj in enumerate(self.argtuple):
+            if isinstance(obj, Index):
+                self.argpositions.append(obj.n + 1)
+            else:
+                self.argpositions.append(0)
+
+        for i in range(nb_args):
+            ARGTYPE = FUNCTYPE.ARGS[i]
+            assert ((i+1) in self.argpositions) == (ARGTYPE is not lltype.Void)
+
+        self.args_gv = [rgenop.placeholder(None)] * nb_args
+        self.args_gv.insert(0, rgenop.genconst(fnobj._as_ptr()))
+        self.gv_result_type = rgenop.constTYPE(FUNCTYPE.RESULT)
+        self.redboxbuilder = rvalue.ll_redboxbuilder(FUNCTYPE.RESULT)
+
+        if operation_name == 'newlist':
+            from pypy.jit.timeshifter.vlist import ListTypeDesc, oop_newlist
+            self.typedesc = ListTypeDesc(FUNCTYPE.RESULT.TO)
+            self.ll_handler = oop_newlist
+        else:
+            typename, method = operation_name.split('.')
+            method = 'oop_%s_%s' % (typename, method)
+            vmodule = __import__('pypy.jit.timeshifter.v%s' % (typename,),
+                                 None, None, [method])
+            self.ll_handler = getattr(vmodule, method)
+
+    def _freeze_(self):
+        return True
+
+    def residual_call(self, jitstate, argboxes):
+        args_gv = self.args_gv[:]
+        argpositions = self.argpositions
+        for i in range(len(argpositions)):
+            pos = argpositions[i]
+            if pos > 0:
+                gv_arg = argboxes[i].getgenvar(jitstate)
+                args_gv[pos] = gv_arg
+        gv_result = rgenop.genop(jitstate.curblock,
+                                 'direct_call',
+                                 args_gv,
+                                 self.gv_result_type)
+        return self.redboxbuilder(self.gv_result_type, gv_result)

Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtyper.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rtyper.py	Thu Jun 29 15:40:47 2006
@@ -207,23 +207,16 @@
         fnobj = c_func.value._obj
         if hasattr(fnobj._callable, 'oopspec'):
             hop.r_s_popfirstarg()
-            return self.handle_highlevel_operation(fnobj._callable, hop)
+            return self.handle_highlevel_operation(fnobj, hop)
         else:
             raise NotImplementedError("direct_call")
 
-    def handle_highlevel_operation(self, ll_func, hop):
-        # parse the oopspec and fill in the arguments
-        class Index:
-            def __init__(self, n):
-                self.n = n
-        operation_name, args = ll_func.oopspec.split('(', 1)
-        assert args.endswith(')')
-        args = args[:-1] + ','     # trailing comma to force tuple syntax
-        argnames = ll_func.func_code.co_varnames[:hop.nb_args]
-        d = dict(zip(argnames, [Index(n) for n in range(hop.nb_args)]))
-        argtuple = eval(args, d)
+    def handle_highlevel_operation(self, fnobj, hop):
+        from pypy.jit.timeshifter.oop import OopSpecDesc, Index
+        oopspecdesc = OopSpecDesc(fnobj)
+
         args_v = []
-        for obj in argtuple:
+        for obj in oopspecdesc.argtuple:
             if isinstance(obj, Index):
                 hs = hop.args_s[obj.n]
                 r_arg = self.getredrepr(originalconcretetype(hs))
@@ -231,7 +224,6 @@
             else:
                 v = hop.inputconst(self.getredrepr(lltype.typeOf(obj)), obj)
             args_v.append(v)
-        # end of rather XXX'edly hackish parsing
 
         ts = self.timeshifter
         args_s = [ts.s_RedBox] * len(args_v)
@@ -241,26 +233,15 @@
         else:
             s_result = ts.s_RedBox
 
-        if operation_name == 'newlist':
-            from pypy.jit.timeshifter.vlist import ListTypeDesc, oop_newlist
-            typedesc = ListTypeDesc(RESULT.TO)
-            c_typedesc = inputconst(lltype.Void, typedesc)
-            s_typedesc = ts.rtyper.annotator.bookkeeper.immutablevalue(typedesc)
-            args_v.insert(0, c_typedesc)
-            args_s.insert(0, s_typedesc)
-            ll_handler = oop_newlist
-        else:
-            typename, method = operation_name.split('.')
-            method = 'oop_%s_%s' % (typename, method)
-            vmodule = __import__('pypy.jit.timeshifter.v%s' % (typename,),
-                                 None, None, [method])
-            ll_handler = getattr(vmodule, method)
+        c_oopspecdesc = hop.inputconst(lltype.Void, oopspecdesc)
+        s_oopspecdesc = ts.rtyper.annotator.bookkeeper.immutablevalue(
+            oopspecdesc)
 
         v_jitstate = hop.llops.getjitstate()
-        return hop.llops.genmixlevelhelpercall(ll_handler,
-                                               [ts.s_JITState] + args_s,
-                                               [v_jitstate] + args_v,
-                                               s_result)
+        return hop.llops.genmixlevelhelpercall(oopspecdesc.ll_handler,
+                                      [ts.s_JITState, s_oopspecdesc] + args_s,
+                                      [v_jitstate,    c_oopspecdesc] + args_v,
+                                      s_result)
 
 
 class HintLowLevelOpList(LowLevelOpList):

Modified: pypy/dist/pypy/jit/timeshifter/rvalue.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rvalue.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rvalue.py	Thu Jun 29 15:40:47 2006
@@ -63,6 +63,23 @@
         # XXX what about long longs?
         return IntRedBox
 
+def redboxbuilder_void(gv_type, gv_value):return None
+def redboxbuilder_int(gv_ptr, gv_value):  return IntRedBox(gv_ptr, gv_value)
+def redboxbuilder_dbl(gv_ptr, gv_value):  return DoubleRedBox(gv_ptr, gv_value)
+def redboxbuilder_ptr(gv_ptr, gv_value):  return PtrRedBox(gv_ptr, gv_value)
+
+def ll_redboxbuilder(TYPE):
+    if TYPE is lltype.Void:
+        return redboxbuilder_void
+    elif isinstance(TYPE, lltype.Ptr):
+        return redboxbuilder_ptr
+    elif TYPE is lltype.Float:
+        return redboxbuilder_dbl
+    else:
+        assert isinstance(TYPE, lltype.Primitive)
+        # XXX what about long longs?
+        return redboxbuilder_int
+
 def ll_fromvalue(value):
     "Make a constant RedBox from a low-level value."
     T = lltype.typeOf(value)

Modified: pypy/dist/pypy/jit/timeshifter/test/test_vlist.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_vlist.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_vlist.py	Thu Jun 29 15:40:47 2006
@@ -60,3 +60,15 @@
     insns, res = timeshift(ll_function, [0], [], policy=P_OOPSPEC)
     assert res == 131
     assert insns == {'int_is_true': 1}
+
+def test_force():
+    def ll_function(n):
+        lst = []
+        lst.append(n)
+        if n:
+            lst.append(12)
+        return lst[-1]
+    insns, res = timeshift(ll_function, [6], [], policy=P_OOPSPEC)
+    assert res == 12
+    insns, res = timeshift(ll_function, [0], [], policy=P_OOPSPEC)
+    assert res == 0

Modified: pypy/dist/pypy/jit/timeshifter/vlist.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/vlist.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/vlist.py	Thu Jun 29 15:40:47 2006
@@ -12,6 +12,8 @@
         self.LISTPTR = lltype.Ptr(LIST)
         self.gv_type = rgenop.constTYPE(self.LIST)
         self.gv_ptrtype = rgenop.constTYPE(self.LISTPTR)
+        self.build_newlist = LIST.list_builder.build_newlist
+        self.build_setitem = LIST.list_builder.build_setitem
 
     def _freeze_(self):
         return True
@@ -73,7 +75,16 @@
                 box.enter_block(newblock, incoming, memo)
 
     def force_runtime_container(self, jitstate):
-        assert 0
+        typedesc = self.typedesc
+        boxes = self.item_boxes
+        self.item_boxes = None
+        llops = rgenop.LowLevelOpBuilder(jitstate.curblock)
+        gv_list = typedesc.build_newlist(llops, len(boxes))
+        self.ownbox.genvar = gv_list
+        self.ownbox.content = None
+        for i in range(len(boxes)):
+            gv_item = boxes[i].getgenvar(jitstate)
+            typedesc.build_setitem(llops, gv_list, i, gv_item)
 
     def freeze(self, memo):
         contmemo = memo.containers
@@ -105,18 +116,21 @@
             self.ownbox = self.ownbox.replace(memo)
 
 
-def oop_newlist(jitstate, typedesc, lengthbox):
+def oop_newlist(jitstate, oopspecdesc, lengthbox):
     assert lengthbox.is_constant()
     length = rvalue.ll_getvalue(lengthbox, lltype.Signed)
     assert length == 0
-    return typedesc.ll_factory()
+    return oopspecdesc.typedesc.ll_factory()
 
-def oop_list_append(jitstate, selfbox, itembox):
-    assert isinstance(selfbox.content, VirtualList)
-    selfbox.content.item_boxes.append(itembox)
-
-def oop_list_getitem(jitstate, selfbox, indexbox):
-    assert isinstance(selfbox.content, VirtualList)
-    assert indexbox.is_constant()
-    index = rvalue.ll_getvalue(indexbox, lltype.Signed)
-    return selfbox.content.item_boxes[index]
+def oop_list_append(jitstate, oopspecdesc, selfbox, itembox):
+    if isinstance(selfbox.content, VirtualList):
+        selfbox.content.item_boxes.append(itembox)
+    else:
+        oopspecdesc.residual_call(jitstate, [selfbox, itembox])
+
+def oop_list_getitem(jitstate, oopspecdesc, selfbox, indexbox):
+    if isinstance(selfbox.content, VirtualList) and indexbox.is_constant():
+        index = rvalue.ll_getvalue(indexbox, lltype.Signed)
+        return selfbox.content.item_boxes[index]
+    else:
+        return oopspecdesc.residual_call(jitstate, [selfbox, indexbox])

Modified: pypy/dist/pypy/rpython/lltypesystem/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/lltypesystem/rlist.py	(original)
+++ pypy/dist/pypy/rpython/lltypesystem/rlist.py	Thu Jun 29 15:40:47 2006
@@ -106,32 +106,41 @@
         self.LISTPTR = LISTPTR
 
         argtypes = [Signed]
-        fnptr = list_repr.rtyper.annotate_helper_fn(LIST.ll_newlist, argtypes)
-        self.newlist_ptr = fnptr
+        newlist_ptr = list_repr.rtyper.annotate_helper_fn(LIST.ll_newlist,
+                                                          argtypes)
 
         bk = list_repr.rtyper.annotator.bookkeeper
         argtypes = [bk.immutablevalue(dum_nocheck), LISTPTR, Signed, ITEM]
-        fnptr = list_repr.rtyper.annotate_helper_fn(ll_setitem_nonneg, argtypes)
-        self.setitem_nonneg_ptr = fnptr
+        setitem_nonneg_ptr = list_repr.rtyper.annotate_helper_fn(
+            ll_setitem_nonneg, argtypes)
         #self.c_dum_nocheck = inputconst(Void, dum_nocheck)
         #self.c_LIST = inputconst(Void, self.LIST)
 
-    def build(self, llops, items_v):
-        """Make the operations that would build a list containing the
-        provided items."""
-        c_newlist = llops.genconst(self.newlist_ptr)
-        c_len     = llops.genconst(len(items_v))
-        c_LIST    = llops.genvoidconst(self.LIST)
-        v_result = llops.genop('direct_call',
+        def build_newlist(llops, length):
+            c_newlist = llops.genconst(newlist_ptr)
+            c_len     = llops.genconst(length)
+            c_LIST    = llops.genvoidconst(LIST)
+            return llops.genop('direct_call',
                                [c_newlist, c_LIST, c_len],
-                               self.LISTPTR)
-        c_setitem_nonneg = llops.genconst(self.setitem_nonneg_ptr)
-        for i in range(len(items_v)):
-            c_i = llops.genconst(i)
+                               LISTPTR)
+
+        def build_setitem(llops, v_list, index, v_item):
+            c_setitem_nonneg = llops.genconst(setitem_nonneg_ptr)
+            c_i = llops.genconst(index)
             llops.genop('direct_call', [c_setitem_nonneg,
                                         llops.genvoidconst(dum_nocheck),
-                                        v_result, c_i, items_v[i]])
-        return v_result
+                                        v_list, c_i, v_item])
+
+        self.build_newlist = build_newlist
+        self.build_setitem = build_setitem
+
+    def build(self, llops, items_v):
+        """Make the operations that would build a list containing the
+        provided items."""
+        v_list = self.build_newlist(llops, len(items_v))
+        for i, v in enumerate(items_v):
+            self.build_setitem(llops, v_list, i, v)
+        return v_list
 
     def getlistptr(self):
         list_repr = self.tmp_list_repr

Modified: pypy/dist/pypy/rpython/rgenop.py
==============================================================================
--- pypy/dist/pypy/rpython/rgenop.py	(original)
+++ pypy/dist/pypy/rpython/rgenop.py	Thu Jun 29 15:40:47 2006
@@ -311,3 +311,18 @@
 setannotation(constFieldName, s_ConstOrVar, specialize_as_constant=True)
 setannotation(constTYPE,      s_ConstOrVar, specialize_as_constant=True)
 setannotation(placeholder,    s_ConstOrVar, specialize_as_constant=True)
+
+# ____________________________________________________________
+
+class LowLevelOpBuilder(object):
+
+    def __init__(self, block):
+        self.block = block
+
+    genconst = staticmethod(genconst)
+    genvoidconst = staticmethod(placeholder)
+
+    def genop(self, opname, args_gv, RESULTTYPE=lltype.Void):
+        gv_result_type = constTYPE(RESULTTYPE)
+        return genop(self.block, opname, args_gv, gv_result_type)
+    genop._annspecialcase_ = 'specialize:arg(3)'



More information about the Pypy-commit mailing list