[pypy-svn] r31614 - in pypy/dist/pypy: annotation jit/codegen/llgraph jit/timeshifter jit/timeshifter/test objspace/flow rpython

arigo at codespeak.net arigo at codespeak.net
Thu Aug 24 18:19:58 CEST 2006


Author: arigo
Date: Thu Aug 24 18:19:50 2006
New Revision: 31614

Modified:
   pypy/dist/pypy/annotation/annrpython.py
   pypy/dist/pypy/annotation/specialize.py
   pypy/dist/pypy/annotation/unaryop.py
   pypy/dist/pypy/jit/codegen/llgraph/rgenop.py
   pypy/dist/pypy/jit/timeshifter/rtimeshift.py
   pypy/dist/pypy/jit/timeshifter/rvalue.py
   pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py
   pypy/dist/pypy/jit/timeshifter/timeshift.py
   pypy/dist/pypy/objspace/flow/model.py
   pypy/dist/pypy/rpython/annlowlevel.py
   pypy/dist/pypy/rpython/rtyper.py
Log:
(pedronis, arigo)

Refactor the timeshifter test runner to be parametrizable on the RGenOp.
Caused a lot of pain and obscure crashes.  Added sanity checks and XXXs
a bit everywhere.



Modified: pypy/dist/pypy/annotation/annrpython.py
==============================================================================
--- pypy/dist/pypy/annotation/annrpython.py	(original)
+++ pypy/dist/pypy/annotation/annrpython.py	Thu Aug 24 18:19:50 2006
@@ -169,15 +169,24 @@
 
     def addpendingblock(self, graph, block, cells, called_from_graph=None):
         """Register an entry point into block with the given input cells."""
-        assert not self.frozen
-        for a in cells:
-            assert isinstance(a, annmodel.SomeObject)
-        if block not in self.annotated:
-            self.bindinputargs(graph, block, cells, called_from_graph)
+        if graph in self.fixed_graphs:
+            # special case for annotating/rtyping in several phases: calling
+            # a graph that has already been rtyped.  Safety-check the new
+            # annotations that are passed in, and don't annotate the old
+            # graph -- it's already low-level operations!
+            for a, s_newarg in zip(graph.getargs(), cells):
+                s_oldarg = self.binding(a)
+                assert s_oldarg.contains(s_newarg)
         else:
-            self.mergeinputargs(graph, block, cells, called_from_graph)
-        if not self.annotated[block]:
-            self.pendingblocks[block] = graph
+            assert not self.frozen
+            for a in cells:
+                assert isinstance(a, annmodel.SomeObject)
+            if block not in self.annotated:
+                self.bindinputargs(graph, block, cells, called_from_graph)
+            else:
+                self.mergeinputargs(graph, block, cells, called_from_graph)
+            if not self.annotated[block]:
+                self.pendingblocks[block] = graph
 
     def complete(self):
         """Process pending blocks until none is left."""
@@ -348,17 +357,8 @@
             callpositions[callback] = True
 
         # generalize the function's input arguments
-        if graph in self.fixed_graphs:
-            # special case for annotating/rtyping in several phases: calling
-            # a graph that has already been rtyped.  Safety-check the new
-            # annotations that are passed in, and don't annotate the old
-            # graph -- it's already low-level operations!
-            for a, s_newarg in zip(graph.getargs(), inputcells):
-                s_oldarg = self.binding(a)
-                assert s_oldarg.contains(s_newarg)
-        else:
-            self.addpendingblock(graph, graph.startblock, inputcells,
-                                 position_key)
+        self.addpendingblock(graph, graph.startblock, inputcells,
+                             position_key)
 
         # get the (current) return value
         v = graph.getreturnvar()
@@ -456,6 +456,7 @@
 
     def reflowpendingblock(self, graph, block):
         assert not self.frozen
+        assert graph not in self.fixed_graphs
         self.pendingblocks[block] = graph
         assert block in self.annotated
         self.annotated[block] = False  # must re-flow

Modified: pypy/dist/pypy/annotation/specialize.py
==============================================================================
--- pypy/dist/pypy/annotation/specialize.py	(original)
+++ pypy/dist/pypy/annotation/specialize.py	Thu Aug 24 18:19:50 2006
@@ -77,6 +77,7 @@
 
     def finish(self):
         from pypy.annotation.model import unionof
+        assert self.graph is None, "MemoTable already finished"
         # list of which argument positions can take more than one value
         example_args, example_value = self.table.iteritems().next()
         nbargs = len(example_args)
@@ -236,15 +237,12 @@
 
         def compute_one_result(args):
             value = func(*args)
-            return MemoTable(funcdesc, args, value)
-
-        def finish():
-            for memotable in memotables.infos():
-                memotable.finish()
+            memotable = MemoTable(funcdesc, args, value)
+            bookkeeper.pending_specializations.append(memotable.finish)
+            return memotable
 
         memotables = UnionFind(compute_one_result)
         bookkeeper.all_specializations[funcdesc] = memotables
-        bookkeeper.pending_specializations.append(finish)
 
     # merge the MemoTables for the individual argument combinations
     firstvalues = possiblevalues.next()

Modified: pypy/dist/pypy/annotation/unaryop.py
==============================================================================
--- pypy/dist/pypy/annotation/unaryop.py	(original)
+++ pypy/dist/pypy/annotation/unaryop.py	Thu Aug 24 18:19:50 2006
@@ -607,8 +607,11 @@
             v_lltype = annotation_to_lltype(s_value)
             setattr(example, s_attr.const, v_lltype._defl())
 
-    def simple_call(p, *args_s):
-        llargs = [annotation_to_lltype(arg_s)._defl() for arg_s in args_s]
+    def call(p, args):
+        args_s, kwds_s = args.unpack()
+        if kwds_s:
+            raise Exception("keyword arguments to call to a low-level fn ptr")
+        llargs = [annotation_to_lltype(s_arg)._defl() for s_arg in args_s]
         v = p.ll_ptrtype._example()(*llargs)
         return ll_to_annotation(v)
 

Modified: pypy/dist/pypy/jit/codegen/llgraph/rgenop.py
==============================================================================
--- pypy/dist/pypy/jit/codegen/llgraph/rgenop.py	(original)
+++ pypy/dist/pypy/jit/codegen/llgraph/rgenop.py	Thu Aug 24 18:19:50 2006
@@ -87,7 +87,11 @@
 
     # not RPython, just for debugging.  Specific to llgraph.
     def reveal(gv):
-        return llimpl.reveal(gv.v)
+        if hasattr(gv, 'v'):
+            v = gv.v
+        else:
+            v = fishllattr(gv, 'v')
+        return llimpl.reveal(v)
     reveal = staticmethod(reveal)
 
     # Builds a real flow.model.FunctionGraph. Specific to llgraph.
@@ -99,8 +103,6 @@
         return llimpl.buildgraph(b)
     buildgraph = staticmethod(buildgraph)
 
-    testgengraph = staticmethod(llimpl.testgengraph)
-
     def get_rgenop_for_testing():
         return rgenop
     get_rgenop_for_testing = staticmethod(get_rgenop_for_testing)

Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtimeshift.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py	Thu Aug 24 18:19:50 2006
@@ -366,7 +366,10 @@
     
 def ll_close_builder(builder):
     builder.finish_and_return()
-        
+
+def ll_gencallableconst(builder, name, startblock, gv_functype):
+    return builder.rgenop.gencallableconst(name, startblock, gv_functype)
+
 class JITState(object):
     # XXX obscure interface
     localredboxes = None

Modified: pypy/dist/pypy/jit/timeshifter/rvalue.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rvalue.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rvalue.py	Thu Aug 24 18:19:50 2006
@@ -67,9 +67,9 @@
         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 redboxbuilder_int(gv_type, gv_value): return IntRedBox(gv_type, gv_value)
+def redboxbuilder_dbl(gv_type, gv_value): return DoubleRedBox(gv_type,gv_value)
+def redboxbuilder_ptr(gv_type, gv_value): return PtrRedBox(gv_type, gv_value)
 
 def ll_redboxbuilder(TYPE):
     if TYPE is lltype.Void:

Modified: pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py	Thu Aug 24 18:19:50 2006
@@ -4,12 +4,14 @@
 from pypy.jit.hintannotator.bookkeeper import HintBookkeeper
 from pypy.jit.hintannotator.model import *
 from pypy.jit.timeshifter.timeshift import HintTimeshift
-from pypy.jit.timeshifter import rtimeshift, rtyper as hintrtyper
+from pypy.jit.timeshifter import rtimeshift, rvalue, rtyper as hintrtyper
 from pypy.jit.llabstractinterp.test.test_llabstractinterp import annotation
 from pypy.jit.llabstractinterp.test.test_llabstractinterp import summary
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython.objectmodel import hint, keepalive_until_here
+from pypy.rpython.unroll import unrolling_iterable
 from pypy.rpython.lltypesystem import rstr
+from pypy.rpython.annlowlevel import PseudoHighLevelCallable
 from pypy.annotation import model as annmodel
 from pypy.rpython.llinterp import LLInterpreter
 from pypy.objspace.flow.model import checkgraph
@@ -65,6 +67,8 @@
             hs, ha, rtyper = hannotate(ll_function, values,
                                        inline=inline, policy=policy)
             htshift = HintTimeshift(ha, rtyper, self.RGenOp)
+            RESTYPE = htshift.originalconcretetype(
+                ha.translator.graphs[0].getreturnvar())
             htshift.timeshift()
             t = rtyper.annotator.translator
             for graph in ha.translator.graphs:
@@ -73,62 +77,101 @@
             if conftest.option.view:
                 from pypy.translator.tool.graphpage import FlowGraphPage
                 FlowGraphPage(t, ha.translator.graphs).display()
-            result = hs, ha, rtyper, htshift
+            result = hs, ha, rtyper, htshift, RESTYPE
             self._cache[key] = result, getargtypes(rtyper.annotator, values)
             self._cache_order.append(key)
         else:
-            hs, ha, rtyper, htshift = result
+            hs, ha, rtyper, htshift, RESTYPE = result
             assert argtypes == getargtypes(rtyper.annotator, values)
         return result
 
     def timeshift(self, ll_function, values, opt_consts=[], inline=None,
                   policy=None):
-        hs, ha, rtyper, htshift = self.timeshift_cached(ll_function, values,
-                                                        inline, policy)
-        # run the time-shifted graph-producing graphs
+        hs, ha, rtyper, htshift, RESTYPE = self.timeshift_cached(
+            ll_function, values, inline, policy)
+        # build a runner function
+        original_entrypoint_graph = rtyper.annotator.translator.graphs[0]
         graph1 = ha.translator.graphs[0]
-        llinterp = LLInterpreter(rtyper)
-        builder = llinterp.eval_graph(htshift.ll_make_builder_graph, [])
-        graph1args = [builder, lltype.nullptr(htshift.r_JITState.lowleveltype.TO)]
-        residual_graph_args = []
+        timeshifted_entrypoint_fnptr = rtyper.type_system.getcallable(graph1)
         assert len(graph1.getargs()) == 2 + len(values)
-        for i, (v, llvalue) in enumerate(zip(graph1.getargs()[2:], values)):
+        graph1varargs = graph1.getargs()[2:]
+
+        argdescription = []   # list of: ("green"/"redconst"/"redvar", value)
+        residual_args = []
+        residual_argtypes = []
+        timeshifted_entrypoint_args_s = []
+
+        for i, (v, llvalue) in enumerate(zip(graph1varargs, values)):
             r = htshift.hrtyper.bindingrepr(v)
             residual_v = r.residual_values(llvalue)
             if len(residual_v) == 0:
                 # green
-                graph1args.append(llvalue)
+                color = "green"
+                s_var = annmodel.ll_to_annotation(llvalue)
+                timeshifted_entrypoint_args_s.append(s_var)
             else:
                 # red
                 assert residual_v == [llvalue], "XXX for now"
-                TYPE = htshift.originalconcretetype(v)
-                gv_type = self.RGenOp.constTYPE(TYPE)
-                ll_type = htshift.r_ConstOrVar.convert_const(gv_type)
-                ll_gvar = llinterp.eval_graph(htshift.ll_geninputarg_graph,
-                                              [builder, ll_type])
-                if i in opt_consts: # XXX what should happen here interface wise is unclear
-                    gvar = self.RGenOp.constPrebuiltGlobal(llvalue)
-                    ll_gvar = htshift.r_ConstOrVar.convert_const(gvar)
-                if isinstance(lltype.typeOf(llvalue), lltype.Ptr):
-                    ll_box_graph = htshift.ll_addr_box_graph
-                elif isinstance(llvalue, float):
-                    ll_box_graph = htshift.ll_double_box_graph
+                if i in opt_consts:
+                    color = "redconst"
                 else:
-                    ll_box_graph = htshift.ll_int_box_graph
-                box = llinterp.eval_graph(ll_box_graph, [ll_type, ll_gvar])
-                graph1args.append(box)
-                residual_graph_args.append(llvalue)
-        startblock = llinterp.eval_graph(htshift.ll_end_setup_builder_graph, [builder])
-
-        builder = llinterp.eval_graph(graph1, graph1args)
-        r = htshift.hrtyper.getrepr(hs)
-        llinterp.eval_graph(htshift.ll_close_builder_graph, [builder])
+                    color = "redvar"
+                    ARGTYPE = htshift.originalconcretetype(v)
+                    residual_argtypes.append(ARGTYPE)
+                    residual_args.append(llvalue)
+                timeshifted_entrypoint_args_s.append(htshift.s_RedBox)
+            argdescription.append((color, llvalue))
+
+        argdescription = unrolling_iterable(argdescription)
+        RGenOp = self.RGenOp
+        timeshifted_entrypoint = PseudoHighLevelCallable(
+            timeshifted_entrypoint_fnptr,
+            [htshift.s_ResidualGraphBuilder, htshift.s_JITState]
+            + timeshifted_entrypoint_args_s,
+            htshift.s_ResidualGraphBuilder)
+        FUNCTYPE = lltype.FuncType(residual_argtypes, RESTYPE)
+        gv_functype = RGenOp.constTYPE(FUNCTYPE)
+
+        def ll_runner():
+            rgenop = RGenOp.get_rgenop_for_testing()
+            builder = rtimeshift.make_builder(rgenop)
+            timeshifted_entrypoint_args = ()
+            for color, llvalue in argdescription:
+                if color == "green":
+                    timeshifted_entrypoint_args += (llvalue,)
+                else:
+                    TYPE = lltype.typeOf(llvalue)
+                    gv_type = rgenop.constTYPE(TYPE)
+                    boxcls = rvalue.ll_redboxcls(TYPE)
+                    if color == "redconst":
+                        gv_arg = rgenop.genconst(llvalue)
+                    else:
+                        gv_arg = rtimeshift.ll_geninputarg(builder, gv_type)
+                    box = boxcls(gv_type, gv_arg)
+                    timeshifted_entrypoint_args += (box,)
+            startblock = rtimeshift.ll_end_setup_builder(builder)
+            endbuilder = timeshifted_entrypoint(builder, None,
+                                                *timeshifted_entrypoint_args)
+            endbuilder.finish_and_return()
+            gv_generated = rgenop.gencallableconst("generated", startblock,
+                                                   gv_functype)
+            return gv_generated
+
+        annhelper = htshift.annhelper
+        runner_graph = annhelper.getgraph(ll_runner, [], htshift.s_ConstOrVar)
+        annhelper.finish()
+
+        # run the runner
+        llinterp = LLInterpreter(rtyper)
+        ll_gv_generated = llinterp.eval_graph(runner_graph, [])
 
-        # now try to run the blocks produced by the builder
-        residual_graph = self.RGenOp.buildgraph(startblock)
+        # now try to run the residual graph generated by the builder
+        c_generatedfn = RGenOp.reveal(ll_gv_generated)
+        residual_graph = c_generatedfn.value._obj.graph
+        if conftest.option.view:
+            residual_graph.show()
         insns = summary(residual_graph)
-        res = self.RGenOp.testgengraph(residual_graph, residual_graph_args,
-                                       viewbefore = conftest.option.view)
+        res = llinterp.eval_graph(residual_graph, residual_args)
         return insns, res
 
 

Modified: pypy/dist/pypy/jit/timeshifter/timeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/timeshift.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/timeshift.py	Thu Aug 24 18:19:50 2006
@@ -55,6 +55,7 @@
             rgenop = RGenOp.get_rgenop_for_testing()
             return rtimeshift.make_builder(rgenop)
 
+        # XXX find a different way to enforce the interface types
         self.ll_make_builder_graph = self.annhelper.getgraph(
             ll_make_builder,
             [], self.s_ResidualGraphBuilder)
@@ -88,14 +89,15 @@
             rtimeshift.ll_close_builder,
             [self.s_ResidualGraphBuilder],
             annmodel.s_None)
+        self.annhelper.getgraph(
+            rtimeshift.ll_gencallableconst,
+            [self.s_ResidualGraphBuilder, annmodel.SomeString(),
+             self.s_Block, self.s_ConstOrVar],
+            self.s_ConstOrVar)
 
     def s_r_instanceof(self, cls, can_be_None=True):
         # Return a SomeInstance / InstanceRepr pair correspnding to the specified class.
-        classdesc = self.rtyper.annotator.bookkeeper.getdesc(cls)
-        classdef = classdesc.getuniqueclassdef()
-        s_instance = annmodel.SomeInstance(classdef, can_be_None)
-        r_instance = self.annhelper.getdelayedrepr(s_instance)
-        return s_instance, r_instance
+        return self.annhelper.s_r_instanceof(cls, can_be_None=can_be_None)
 
     # creates and numbers reentry_block for block reached by link
     # argument:

Modified: pypy/dist/pypy/objspace/flow/model.py
==============================================================================
--- pypy/dist/pypy/objspace/flow/model.py	(original)
+++ pypy/dist/pypy/objspace/flow/model.py	Thu Aug 24 18:19:50 2006
@@ -268,6 +268,13 @@
 class Variable(object):
     __slots__ = ["_name", "_nr", "concretetype"]
 
+##    def getter(x): return x._ct
+##    def setter(x, ct):
+##        if repr(ct) == '<* PyObject>':
+##            import pdb; pdb.set_trace()
+##        x._ct = ct
+##    concretetype = property(getter, setter)
+
     dummyname = 'v'
     namesdict = {dummyname : (dummyname, 0)}
 

Modified: pypy/dist/pypy/rpython/annlowlevel.py
==============================================================================
--- pypy/dist/pypy/rpython/annlowlevel.py	(original)
+++ pypy/dist/pypy/rpython/annlowlevel.py	Thu Aug 24 18:19:50 2006
@@ -285,6 +285,10 @@
         r_res = hop.rtyper.getrepr(self.instance.s_result)
         vlist = hop.inputargs(*args_r)
         p = self.instance.llfnptr
-        c_func = Constant(p, lltype.typeOf(p))
+        TYPE = lltype.typeOf(p)
+        c_func = Constant(p, TYPE)
+        for r_arg, ARGTYPE in zip(args_r, TYPE.TO.ARGS):
+            assert r_arg.lowleveltype == ARGTYPE
+        assert r_res.lowleveltype == TYPE.TO.RESULT
         hop.exception_is_here()
         return hop.genop('direct_call', [c_func] + vlist, resulttype = r_res)

Modified: pypy/dist/pypy/rpython/rtyper.py
==============================================================================
--- pypy/dist/pypy/rpython/rtyper.py	(original)
+++ pypy/dist/pypy/rpython/rtyper.py	Thu Aug 24 18:19:50 2006
@@ -67,7 +67,6 @@
         self.cache_dummy_values = {}
         self.typererrors = []
         self.typererror_count = 0
-        self.seen_graphs_count = 0
         # make the primitive_to_repr constant mapping
         self.primitive_to_repr = {}
         if self.type_system.offers_exceptiondata:
@@ -233,12 +232,6 @@
         if self.typererrors: 
             self.dump_typererrors(to_log=True) 
             raise TyperError("there were %d error" % len(self.typererrors))
-        # make sure that the return variables of all graphs are concretetype'd
-        newgraphs = self.annotator.translator.graphs[self.seen_graphs_count:]
-        self.seen_graphs_count += len(newgraphs)
-        for graph in newgraphs:
-            v = graph.getreturnvar()
-            self.setconcretetype(v)
         log.event('-=- specialized %d%s blocks -=-' % (blockcount, newtext))
 
     def dump_typererrors(self, num=None, minimize=True, to_log=False): 
@@ -311,7 +304,11 @@
 
     def specialize_block(self, block):
         graph = self.annotator.annotated[block]
-        self.annotator.fixed_graphs[graph] = True
+        if graph not in self.annotator.fixed_graphs:
+            self.annotator.fixed_graphs[graph] = True
+            # make sure that the return variables of all graphs
+            # are concretetype'd
+            self.setconcretetype(graph.getreturnvar())
 
         # give the best possible types to the input args
         try:



More information about the Pypy-commit mailing list