[pypy-svn] r32239 - in pypy/dist/pypy: jit/hintannotator jit/hintannotator/test jit/timeshifter jit/timeshifter/test rpython

arigo at codespeak.net arigo at codespeak.net
Tue Sep 12 21:03:07 CEST 2006


Author: arigo
Date: Tue Sep 12 21:03:04 2006
New Revision: 32239

Added:
   pypy/dist/pypy/jit/timeshifter/test/test_tlc.py
      - copied, changed from r32217, pypy/dist/pypy/jit/timeshifter/test/test_tl.py
Modified:
   pypy/dist/pypy/jit/hintannotator/bookkeeper.py
   pypy/dist/pypy/jit/hintannotator/test/test_annotator.py
   pypy/dist/pypy/jit/hintannotator/test/test_toy.py
   pypy/dist/pypy/jit/timeshifter/rtyper.py
   pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py
   pypy/dist/pypy/jit/timeshifter/timeshift.py
   pypy/dist/pypy/rpython/rtyper.py
Log:
(pedronis, arigo)

started timeshifting support for indirect calls, still in progress, we bumped into normalisation problems.




Modified: pypy/dist/pypy/jit/hintannotator/bookkeeper.py
==============================================================================
--- pypy/dist/pypy/jit/hintannotator/bookkeeper.py	(original)
+++ pypy/dist/pypy/jit/hintannotator/bookkeeper.py	Tue Sep 12 21:03:04 2006
@@ -137,30 +137,36 @@
     def warning(self, msg):
         return self.annotator.warning(msg)
 
-    def get_graph_for_call(self, graph, fixed, args_hs):
-        # this can modify args_hs in-place!
-        from pypy.jit.hintannotator.model import SomeLLAbstractConstant
-        desc = self.getdesc(graph)
-        key = None
-        alt_name = None
+    def specialization_key(self, fixed, args_hs):
         if fixed:
-            key = 'fixed'
-            alt_name = graph.name + '_HFixed'
+            return 'fixed'
         else:
             key = []
             specialize = False
             for i, arg_hs in enumerate(args_hs):
-                if isinstance(arg_hs, SomeLLAbstractConstant) and arg_hs.eager_concrete:
+                if (isinstance(arg_hs, hintmodel.SomeLLAbstractConstant)
+                    and arg_hs.eager_concrete):
                     key.append('E')
                     specialize = True
                 else:
                     key.append('x')
             if specialize:
-                key = ''.join(key)
-                alt_name = graph.name + '_H'+key
+                return ''.join(key)
             else:
-                key = None
+                return None
+
+    def get_graph_by_key(self, graph, specialization_key):
+        desc = self.getdesc(graph)
+        return desc._cache[specialization_key]
 
+    def get_graph_for_call(self, graph, fixed, args_hs):
+        # this can modify args_hs in-place!
+        key = self.specialization_key(fixed, args_hs)
+        if key is None:
+            alt_name = None
+        else:
+            alt_name = graph.name + '_H'+key
+        desc = self.getdesc(graph)
         graph = desc.specialize(args_hs, key=key, alt_name=alt_name)
         return graph
 

Modified: pypy/dist/pypy/jit/hintannotator/test/test_annotator.py
==============================================================================
--- pypy/dist/pypy/jit/hintannotator/test/test_annotator.py	(original)
+++ pypy/dist/pypy/jit/hintannotator/test/test_annotator.py	Tue Sep 12 21:03:04 2006
@@ -18,7 +18,8 @@
 P_OOPSPEC_NOVIRTUAL.oopspec = True
 P_OOPSPEC_NOVIRTUAL.novirtualcontainer = True
 
-def hannotate(func, argtypes, policy=None, annotator=False, inline=None):
+def hannotate(func, argtypes, policy=None, annotator=False, inline=None,
+              backendoptimize=False):
     # build the normal ll graphs for ll_function
     t = TranslationContext()
     a = t.buildannotator()
@@ -27,6 +28,9 @@
     rtyper.specialize()
     if inline:
         auto_inlining(t, inline)
+    if backendoptimize:
+        from pypy.translator.backendopt.all import backend_optimizations
+        backend_optimizations(t)
     graph1 = graphof(t, func)
     # build hint annotator types
     hannotator = HintAnnotator(base_translator=t, policy=policy)

Modified: pypy/dist/pypy/jit/hintannotator/test/test_toy.py
==============================================================================
--- pypy/dist/pypy/jit/hintannotator/test/test_toy.py	(original)
+++ pypy/dist/pypy/jit/hintannotator/test/test_toy.py	Tue Sep 12 21:03:04 2006
@@ -17,4 +17,4 @@
 def test_hannotate_tlc_novirtual():
     from pypy.jit.tl import tlc
     hannotate(tlc.interp_without_call, [str, int, int],
-              policy=P_OOPSPEC_NOVIRTUAL)
+              policy=P_OOPSPEC_NOVIRTUAL, backendoptimize=True)

Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtyper.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rtyper.py	Tue Sep 12 21:03:04 2006
@@ -333,6 +333,8 @@
 
 
     def guess_call_kind(self, spaceop):
+        if spaceop.opname == 'indirect_call':
+            return 'red'  # for now
         assert spaceop.opname == 'direct_call'
         c_func = spaceop.args[0]
         fnobj = c_func.value._obj
@@ -351,6 +353,34 @@
         meth = getattr(self, 'handle_%s_call' % (kind,))
         return meth(hop)
 
+    def translate_op_indirect_call(self, hop):
+        bk = self.annotator.bookkeeper
+        ts = self.timeshifter
+        v_jitstate = hop.llops.getjitstate()
+        v_funcbox = hop.args_v[0]
+        graph_list = hop.args_v[-1].value
+        hop.r_s_pop(0)
+        hop.r_s_pop()
+        args_hs = hop.args_s[:]
+        # fixed is always false here
+        specialization_key = bk.specialization_key(False, args_hs)
+        FUNC = ts.originalconcretetype(v_funcbox)
+
+        mapper, TS_FUNC, args_r, tsgraphs = ts.get_timeshift_mapper(
+            FUNC, specialization_key, graph_list)
+        args_v = hop.inputargs(*args_r)
+
+        v_tsfunc = hop.llops.genmixlevelhelpercall(mapper,
+                                                   [ts.s_RedBox],
+                                                   [v_funcbox],
+                                                   annmodel.SomePtr(TS_FUNC))
+        args_v[:0] = [v_tsfunc, v_jitstate]
+        RESULT = v_tsfunc.concretetype.TO.RESULT
+        args_v.append(hop.inputconst(lltype.Void, tsgraphs))
+        v_newjitstate = hop.genop('indirect_call', args_v, RESULT)
+        hop.llops.setjitstate(v_newjitstate)
+
+
     def translate_op_save_locals(self, hop):
         ts = self.timeshifter
         v_jitstate = hop.llops.getjitstate()
@@ -441,18 +471,12 @@
         hop.r_s_popfirstarg()
         args_hs = hop.args_s[:]
         # fixed is always false here
-        graph = bk.get_graph_for_call(fnobj.graph, False, args_hs)
-        args_r = [self.getrepr(hs) for hs in args_hs]
+        specialization_key = bk.specialization_key(False, args_hs)
+        fnptr, args_r = ts.get_timeshifted_fnptr(fnobj.graph,
+                                                 specialization_key)
         args_v = hop.inputargs(*args_r)
-        ARGS = [ts.r_JITState.lowleveltype]
-        ARGS += [r.lowleveltype for r in args_r]
-        RESULT = ts.r_JITState.lowleveltype
-        fnptr = lltype.functionptr(lltype.FuncType(ARGS, RESULT),
-                                   graph.name,
-                                   graph=graph,
-                                   _callable = graph.func)
-        self.timeshifter.schedule_graph(graph)
         args_v[:0] = [hop.llops.genconst(fnptr), v_jitstate]
+        RESULT = lltype.typeOf(fnptr).TO.RESULT
         v_newjitstate = hop.genop('direct_call', args_v, RESULT)
         hop.llops.setjitstate(v_newjitstate)
 
@@ -491,7 +515,10 @@
 
         # build the 'direct_call' operation
         rtyper = self.timeshifter.rtyper
-        RESULT = rtyper.getrepr(s_result).lowleveltype
+        try:
+            RESULT = annmodel.annotation_to_lltype(s_result)
+        except ValueError:
+            RESULT = rtyper.getrepr(s_result).lowleveltype
         return self.genop('direct_call', [c]+args_v,
                           resulttype = RESULT)
 

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	Tue Sep 12 21:03:04 2006
@@ -33,7 +33,7 @@
         t = annmodel.lltype_to_annotation(T)
     return a.typeannotation(t)
 
-def hannotate(func, values, policy=None, inline=None):
+def hannotate(func, values, policy=None, inline=None, backendoptimize=False):
     # build the normal ll graphs for ll_function
     t = TranslationContext()
     a = t.buildannotator()
@@ -43,6 +43,9 @@
     rtyper.specialize()
     if inline:
         auto_inlining(t, inline)
+    if backendoptimize:
+        from pypy.translator.backendopt.all import backend_optimizations
+        backend_optimizations(t)
     graph1 = graphof(t, func)
     # build hint annotator types
     hannotator = HintAnnotator(base_translator=t, policy=policy)
@@ -66,7 +69,8 @@
         del cls._cache_order
 
     def timeshift_cached(self, ll_function, values, inline=None, policy=None,
-                         check_raises='ignored anyway'):
+                         check_raises='ignored anyway',
+                         backendoptimize=False):
         # decode the 'values' if they are specified as strings
         if hasattr(ll_function, 'convert_arguments'):
             assert len(ll_function.convert_arguments) == len(values)
@@ -86,7 +90,8 @@
         if len(self._cache_order) >= 3:
             del self._cache[self._cache_order.pop(0)]
         hs, ha, rtyper = hannotate(ll_function, values,
-                                   inline=inline, policy=policy)
+                                   inline=inline, policy=policy,
+                                   backendoptimize=backendoptimize)
 
         # make the timeshifted graphs
         htshift = HintTimeshift(ha, rtyper, self.RGenOp)

Modified: pypy/dist/pypy/jit/timeshifter/timeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/timeshift.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/timeshift.py	Tue Sep 12 21:03:04 2006
@@ -24,8 +24,9 @@
         self.rtyper = rtyper
         self.RGenOp = RGenOp
         self.hrtyper = HintRTyper(hannotator, self)
-        self.latestexitindex = -1
         self.annhelper = annlowlevel.MixLevelHelperAnnotator(rtyper)
+        self.timeshift_mapping = {}
+        self.sigs = {}
 
         self.s_CodeGenerator, self.r_CodeGenerator = self.s_r_instanceof(
             cgmodel.CodeGenerator)
@@ -124,9 +125,84 @@
         # Return a SomeInstance / InstanceRepr pair correspnding to the specified class.
         return self.annhelper.s_r_instanceof(cls, can_be_None=can_be_None)
 
+    def get_sig_hs(self, tsgraph):
+        # the signature annotations are cached here because
+        # the graph is going to be modified
+        try:
+            return self.sigs[tsgraph]
+        except KeyError:
+            ha = self.hannotator
+            sig_hs = ([ha.binding(v) for v in tsgraph.getargs()],
+                      ha.binding(tsgraph.getreturnvar()))
+            self.sigs[tsgraph] = sig_hs
+            return sig_hs
+
+    def get_timeshifted_fnptr(self, graph, specialization_key):
+        bk = self.hannotator.bookkeeper
+        tsgraph = bk.get_graph_by_key(graph, specialization_key)
+        args_hs, hs_res = self.get_sig_hs(tsgraph)
+        args_r = [self.hrtyper.getrepr(hs_arg) for hs_arg in args_hs]
+        ARGS = [self.r_JITState.lowleveltype]
+        ARGS += [r.lowleveltype for r in args_r]
+        RESULT = self.r_JITState.lowleveltype
+        fnptr = lltype.functionptr(lltype.FuncType(ARGS, RESULT),
+                                   tsgraph.name,
+                                   graph=tsgraph,
+                                   _callable = graph.func)
+        self.schedule_graph(tsgraph)
+        return fnptr, args_r
+
     def error_value(self, TYPE):
         return exceptiontransform.error_value(TYPE)
 
+    def get_timeshift_mapper(self, FUNC, specialization_key, graphs):
+        key = FUNC, specialization_key
+        try:
+            timeshift_mapper, values, keys = self.timeshift_mapping[key]
+        except KeyError:
+            values = []
+            keys = []
+            fnptrmap = {}
+
+            def getter(fnptrmap, fnptr):
+                # indirection needed to defeat the flow object space
+                return fnptrmap[fnptr]
+
+            def fill_dict(fnptrmap, values, keys):
+                for i in range(len(values)):
+                    fnptrmap[values[i]] = keys[i]
+
+            def timeshift_mapper(fnptrbox):
+                fnptr = rvalue.ll_getvalue(fnptrbox, FUNC)
+                try:
+                    return getter(fnptrmap, fnptr)
+                except KeyError:
+                    fill_dict(fnptrmap, values, keys)
+                    return getter(fnptrmap, fnptr)   # try again
+
+            self.timeshift_mapping[key] = timeshift_mapper, values, keys
+
+        bk = self.hannotator.bookkeeper
+        common_args_r = None
+        COMMON_TS_FUNC = None
+        tsgraphs = []
+        for graph in graphs:
+            fnptr = self.rtyper.getcallable(graph)
+            ts_fnptr, args_r = self.get_timeshifted_fnptr(graph,
+                                   specialization_key)
+            tsgraphs.append(ts_fnptr._obj.graph)
+            TS_FUNC = lltype.typeOf(ts_fnptr)
+            if common_args_r is None:
+                common_args_r = args_r
+                COMMON_TS_FUNC = TS_FUNC
+            else:
+                # XXX for now
+                assert COMMON_TS_FUNC == TS_FUNC
+                assert common_args_r == args_r
+            keys.append(fnptr)
+            values.append(ts_fnptr)
+        return timeshift_mapper, COMMON_TS_FUNC, common_args_r, tsgraphs
+
     # creates and numbers reentry_block for block reached by link
     # argument:
     #
@@ -199,21 +275,29 @@
 
     def timeshift_graph(self, graph):
         #print 'timeshift_graph START', graph
+        assert graph.startblock in self.hannotator.annotated
         self.graph = graph
         self.dispatch_to = []
         self.statecaches = []
         self.return_cache = None
-        entering_links = flowmodel.mkentrymap(graph)
+        self.latestexitindex = -1
+
+        # cache the annotation signature before changing the graph
+        args_hs, hs_res = self.get_sig_hs(graph)
+        assert (originalconcretetype(hs_res) is lltype.Void
+                or not hs_res.is_green())      # XXX not supported yet
 
         originalblocks = list(graph.iterblocks())
         timeshifted_blocks = []
         for block in originalblocks:
-            self.timeshift_block(timeshifted_blocks, entering_links,  block)
+            self.timeshift_block(timeshifted_blocks, block)
         originalblocks = timeshifted_blocks
 
+        entering_links = flowmodel.mkentrymap(graph)
         inputlinkcounters = {}
         for block in originalblocks:
             inputlinkcounters[block] = len(entering_links[block])
+        # XXX try to not use entering_links in the sequel
 
         returnblock = graph.returnblock
         self.r_returnvalue = self.hrtyper.bindingrepr(returnblock.inputargs[0])
@@ -296,8 +380,9 @@
             block.isstartblock = False
             newblock.isstartblock = True
             self.graph.startblock = newblock
-        else:
+        if block_entering_links:
             for link in block_entering_links:
+                assert link.target is block
                 link.settarget(newblock)
 
         if closeblock:
@@ -629,14 +714,14 @@
             dispatchblock.closeblock(*exitlinks)
 
 
-    def timeshift_block(self, timeshifted_blocks, entering_links, block):
+    def timeshift_block(self, timeshifted_blocks, block):
         hrtyper = self.hrtyper
         blocks = [block]
         i = 0
         # XXX in-progress, split block at direct_calls for call support 
         while i < len(block.operations):
             op = block.operations[i]
-            if (op.opname == 'direct_call'
+            if (op.opname in ('direct_call', 'indirect_call')
                 and hrtyper.guess_call_kind(op) == 'red'):
 
                 link = support.split_block_with_keepalive(block, i+1,
@@ -682,7 +767,6 @@
 
                 link.args = [replacement.get(var, var) for var in link.args]
                 block = link.target
-                entering_links[block] = [link]
                 blocks.append(block)
                 self.hannotator.annotated[block] = self.graph
                 # for now the call doesn't return its redbox result, but only

Modified: pypy/dist/pypy/rpython/rtyper.py
==============================================================================
--- pypy/dist/pypy/rpython/rtyper.py	(original)
+++ pypy/dist/pypy/rpython/rtyper.py	Tue Sep 12 21:03:04 2006
@@ -721,11 +721,15 @@
     def gendirectcall(self, ll_function, *args_v):
         return self.llops.gendirectcall(ll_function, *args_v)
 
+    def r_s_pop(self, index=-1):
+        "Return and discard the argument with index position."        
+        self.nb_args -= 1
+        self.args_v.pop(index)
+        return self.args_r.pop(index), self.args_s.pop(index)
+    
     def r_s_popfirstarg(self):
         "Return and discard the first argument."
-        self.nb_args -= 1
-        self.args_v.pop(0)
-        return self.args_r.pop(0), self.args_s.pop(0)
+        return self.r_s_pop(0)
 
     def v_s_insertfirstarg(self, v_newfirstarg, s_newfirstarg):
         r_newfirstarg = self.rtyper.getrepr(s_newfirstarg)



More information about the Pypy-commit mailing list