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

arigo at codespeak.net arigo at codespeak.net
Sat Jan 14 23:00:35 CET 2006


Author: arigo
Date: Sat Jan 14 23:00:32 2006
New Revision: 22182

Modified:
   pypy/dist/pypy/rpython/rlist.py
   pypy/dist/pypy/rpython/rtyper.py
   pypy/dist/pypy/rpython/test/test_llinterp.py
   pypy/dist/pypy/rpython/test/test_rlist.py
Log:
The RTyper side of the JIT problem of building real lists from virtual lists
at any time.  Now each LIST GcStruct has a list_builder() adt-method that
produces lloperations that create a corresponding list.  The ListBuilder class
exists because of some order-of-initialization fun.



Modified: pypy/dist/pypy/rpython/rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/rlist.py	(original)
+++ pypy/dist/pypy/rpython/rlist.py	Sat Jan 14 23:00:32 2006
@@ -68,8 +68,12 @@
             self.external_item_repr, self.item_repr = externalvsinternal(rtyper, item_repr)
         self.listitem = listitem
         self.list_cache = {}
+        self.list_builder = ListBuilder()
         # setup() needs to be called to finish this initialization
-        
+
+    def _setup_repr_final(self):
+        self.list_builder.setup(self)
+
     def recast(self, llops, v):
         return llops.convertvar(v, self.item_repr, self.external_item_repr)
 
@@ -146,6 +150,46 @@
                                            temp),
                               rstr.list_str_close_bracket))
 
+class ListBuilder(object):
+    """Interface to allow lazy list building by the JIT."""
+    # This should not keep a reference to the RTyper, even indirectly via
+    # the list_repr.
+
+    def setup(self, list_repr):
+        # Precompute the c_newitem and c_setitem_nonneg function pointers,
+        # needed below.
+        if list_repr.rtyper is None:
+            return     # only for test_rlist, which doesn't need this anyway
+        LIST = list_repr.LIST
+        LISTPTR = list_repr.lowleveltype
+        ITEM = list_repr.item_repr.lowleveltype
+        self.LIST = LIST
+        self.LISTPTR = LISTPTR
+
+        argtypes = [Signed]
+        fnptr = list_repr.rtyper.annotate_helper_fn(LIST.ll_newlist, argtypes)
+        self.c_newlist = inputconst(typeOf(fnptr), fnptr)
+
+        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.c_setitem_nonneg = inputconst(typeOf(fnptr), fnptr)
+
+    def build(self, llop, items_v):
+        """Make the operations that would build a list containing the
+        provided items."""
+        # This is called by the JIT with llop.rtyper == None, so
+        # llop.gendirectcall() doesn't work.  Instead, we need to call
+        # directly the c_newitem and c_setitem_nonneg precomputed above.
+        c_list = inputconst(Void, self.LIST)
+        c_len  = inputconst(Signed, len(items_v))
+        v_result = llop.genop('direct_call', [self.c_newlist, c_list, c_len],
+                              resulttype = self.LISTPTR)
+        for i, v in enumerate(items_v):
+            llop.genop('direct_call', [self.c_setitem_nonneg, v_result,
+                                       inputconst(Signed, i), v])
+        return v_result
+
 class ListRepr(BaseListRepr):
 
     def _setup_repr(self):
@@ -161,6 +205,7 @@
                                           "ll_newlist": ll_newlist,
                                           "ll_length": ll_length,
                                           "ll_items": ll_items,
+                                          "list_builder": self.list_builder.build,
                                       })
                              )
 
@@ -233,6 +278,7 @@
                                      "ll_newlist": ll_fixed_newlist,
                                      "ll_length": ll_fixed_length,
                                      "ll_items": ll_fixed_items,
+                                     "list_builder": self.list_builder.build,
                                 })
 
             self.LIST.become(ITEMARRAY)

Modified: pypy/dist/pypy/rpython/rtyper.py
==============================================================================
--- pypy/dist/pypy/rpython/rtyper.py	(original)
+++ pypy/dist/pypy/rpython/rtyper.py	Sat Jan 14 23:00:32 2006
@@ -538,15 +538,31 @@
 
         return self.type_system.getcallable(graph, getconcretetype)
 
-    def annotate_helper(self, ll_function, arglltypes):
-        """Annotate the given low-level helper function
-        and return it as a function pointer object.
+    def annotate_helper(self, ll_function, argtypes):
+        """Annotate the given low-level helper function and return its graph
         """
-        args_s = [annmodel.lltype_to_annotation(T) for T in arglltypes]
+        args_s = []
+        for s in argtypes:
+            # assume 's' is a low-level type, unless it is already an annotation
+            if not isinstance(s, annmodel.SomeObject):
+                s = annmodel.lltype_to_annotation(s)
+            args_s.append(s)
+        # hack for bound methods
+        if hasattr(ll_function, 'im_func'):
+            bk = self.annotator.bookkeeper
+            args_s.insert(0, bk.immutablevalue(ll_function.im_self))
+            ll_function = ll_function.im_func
         helper_graph = annotate_lowlevel_helper(self.annotator,
                                                 ll_function, args_s)
         return helper_graph
 
+    def annotate_helper_fn(self, ll_function, argtypes):
+        """Annotate the given low-level helper function
+        and return it as a function pointer
+        """
+        graph = self.annotate_helper(ll_function, argtypes)
+        return self.getcallable(graph)
+
     def attachRuntimeTypeInfoFunc(self, GCSTRUCT, func, ARG_GCSTRUCT=None,
                                   destrptr=None):
         self.call_all_setups()  # compute ForwardReferences now

Modified: pypy/dist/pypy/rpython/test/test_llinterp.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_llinterp.py	(original)
+++ pypy/dist/pypy/rpython/test/test_llinterp.py	Sat Jan 14 23:00:32 2006
@@ -1,7 +1,6 @@
 
 import py
 from pypy.rpython.lltypesystem.lltype import typeOf, pyobjectptr, Ptr, PyObject, Void
-from pypy.rpython.rtyper import RPythonTyper
 from pypy.rpython.llinterp import LLInterpreter, LLException,log
 from pypy.rpython.rmodel import inputconst
 from pypy.translator.translator import TranslationContext

Modified: pypy/dist/pypy/rpython/test/test_rlist.py
==============================================================================
--- pypy/dist/pypy/rpython/test/test_rlist.py	(original)
+++ pypy/dist/pypy/rpython/test/test_rlist.py	Sat Jan 14 23:00:32 2006
@@ -1,10 +1,12 @@
 import sys
 from pypy.rpython.lltypesystem.lltype import *
-from pypy.rpython.rtyper import RPythonTyper
+from pypy.rpython.rtyper import LowLevelOpList
 from pypy.rpython.rlist import *
 from pypy.rpython.rslice import ll_newslice
 from pypy.rpython.rint import signed_repr
 from pypy.rpython.test.test_llinterp import interpret, interpret_raises
+from pypy.translator.translator import TranslationContext
+from pypy.objspace.flow.model import Constant, Variable
 
 # undo the specialization parameter
 for n1 in 'get set del'.split():
@@ -891,3 +893,37 @@
     res = interpret(fn, [2])
     assert res == 0
     interpret_raises(MemoryError, fn, [sys.maxint])
+
+def test_list_builder():
+    def fixed_size_case():
+        return [42]
+    def variable_size_case():
+        lst = []
+        lst.append(42)
+        return lst
+
+    for fn in [fixed_size_case, variable_size_case]:
+        t = TranslationContext()
+        t.buildannotator().build_types(fn, [])
+        t.buildrtyper().specialize()
+        LIST = t.graphs[0].getreturnvar().concretetype.TO
+        llop = LowLevelOpList(None)
+        v0 = Constant(42)
+        v0.concretetype = Signed
+        v1 = Variable()
+        v1.concretetype = Signed
+        vr = LIST.list_builder(llop, [v0, v1])
+        assert len(llop) == 3
+        assert llop[0].opname == 'direct_call'
+        assert llop[0].args[1].concretetype == Void
+        assert llop[0].args[1].value == LIST
+        assert llop[0].args[2].concretetype == Signed
+        assert llop[0].args[2].value == 2
+        assert llop[0].result is vr
+        for op, i, vi in [(llop[1], 0, v0), (llop[2], 1, v1)]:
+            assert op.opname == 'direct_call'
+            assert op.args[-3] is vr
+            assert op.args[-2].concretetype == Signed
+            assert op.args[-2].value == i
+            assert op.args[-1] is vi
+            assert op.result.concretetype is Void



More information about the Pypy-commit mailing list