[pypy-svn] r31450 - in pypy/dist/pypy/jit/timeshifter: . test

arigo at codespeak.net arigo at codespeak.net
Mon Aug 21 19:50:30 CEST 2006


Author: arigo
Date: Mon Aug 21 19:50:27 2006
New Revision: 31450

Modified:
   pypy/dist/pypy/jit/timeshifter/rtimeshift.py
   pypy/dist/pypy/jit/timeshifter/rtyper.py
   pypy/dist/pypy/jit/timeshifter/test/test_timeshift.py
   pypy/dist/pypy/jit/timeshifter/timeshift.py
Log:
(pedronis, arre, arigo)

More support for calls: saving local variables around calls.



Modified: pypy/dist/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtimeshift.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rtimeshift.py	Mon Aug 21 19:50:27 2006
@@ -145,10 +145,13 @@
 # ____________________________________________________________
 # other jitstate/graph level operations
 
-def enter_graph(builder):
-    return builder.build_jitstate()
+def enter_graph(builder, backstate=None):
+    return builder.build_jitstate(backstate)
 
 def retrieve_jitstate_for_merge(states_dic, jitstate, key, redboxes):
+    mylocalredboxes = redboxes
+    redboxes = list(redboxes)
+    jitstate.extend_with_parent_locals(redboxes)
     if key not in states_dic:
         memo = rvalue.freeze_memo()
         frozens = [redbox.freeze(memo) for redbox in redboxes]
@@ -196,8 +199,9 @@
             box = box.copy(replace_memo) # copy to avoid patching the original
         box.genvar = rgenop.geninputarg(newblock, box.gv_type)
     if replace_memo.boxes:
-        for i in range(len(redboxes)):
-            redboxes[i] = redboxes[i].replace(replace_memo)
+        for i in range(len(mylocalredboxes)):
+            newbox = redboxes[i].replace(replace_memo)
+            mylocalredboxes[i] = redboxes[i] = newbox
     jitstate.curbuilder.leave_block()
     jitstate.curbuilder.enter_block(linkargs, newblock)
     memo = rvalue.freeze_memo()
@@ -207,15 +211,25 @@
 retrieve_jitstate_for_merge._annspecialcase_ = "specialize:arglltype(2)"
     
 def enter_block(jitstate, redboxes):
+    # 'redboxes' is a fixed-size list (s_box_list) of the current red boxes
     newblock = rgenop.newblock()
     incoming = []
     memo = rvalue.enter_block_memo()
-    for i in range(len(redboxes)):
-        redboxes[i].enter_block(newblock, incoming, memo)
+    for redbox in redboxes:
+        redbox.enter_block(newblock, incoming, memo)
+    js = jitstate.backstate
+    while js is not None:
+        lrb = js.localredboxes
+        assert lrb is not None
+        for redbox in lrb:
+            redbox.enter_block(newblock, incoming, memo)
+        js = js.backstate
     jitstate.curbuilder.enter_block(incoming, newblock)
     return jitstate
 
 def dyn_enter_block(jitstate, redboxes):
+    # 'redboxes' is a var-sized list (s_box_accum) of *all* the boxes
+    # including the ones from the callers' locals
     newblock = rgenop.newblock()
     incoming = []
     memo = rvalue.enter_block_memo()
@@ -273,6 +287,9 @@
 def ll_gvar_from_constant(ll_value):
     return rgenop.genconst(ll_value)
 
+def save_locals(jitstate, redboxes):
+    jitstate.localredboxes = redboxes
+
 def before_call(jitstate):
     leave_block(jitstate)
     return jitstate.curbuilder
@@ -289,8 +306,8 @@
         self.outgoinglink = link
         self.valuebox = None
 
-    def build_jitstate(self):
-        return JITState(self)
+    def build_jitstate(self, backstate=None):
+        return JITState(self, backstate)
 
     def enter_block(self, linkargs, newblock):
         rgenop.closelink(self.outgoinglink, linkargs, newblock)
@@ -343,10 +360,18 @@
         
 class JITState(object):
     # XXX obscure interface
+    localredboxes = None
 
-    def __init__(self, builder):
+    def __init__(self, builder, backstate=None):
         self.split_queue = []
         self.return_queue = []
         self.curbuilder = builder
+        self.backstate = backstate
 
-
+    def extend_with_parent_locals(self, redboxes):
+        js = self.backstate
+        while js is not None:
+            lrb = js.localredboxes
+            assert lrb is not None
+            redboxes.extend(lrb)
+            js = js.backstate

Modified: pypy/dist/pypy/jit/timeshifter/rtyper.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/rtyper.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/rtyper.py	Mon Aug 21 19:50:27 2006
@@ -234,8 +234,7 @@
             args_v = hop.inputargs(*args_r)
             fnptr = self.getcallable(graph)
             self.timeshifter.schedule_graph(graph)
-            args_v.insert(0, v_builder)
-            args_v.insert(0, hop.llops.genconst(fnptr))
+            args_v[:0] = [hop.llops.genconst(fnptr), v_builder, v_jitstate]
             v_newbuilder = hop.genop('direct_call', args_v,
                                      ts.r_ResidualGraphBuilder.lowleveltype)
             return hop.llops.genmixlevelhelpercall(rtimeshift.after_call,
@@ -243,6 +242,19 @@
                                    [v_jitstate,    v_newbuilder],
                                    ts.s_RedBox)
 
+    def translate_op_save_locals(self, hop):
+        ts = self.timeshifter
+        v_jitstate = hop.llops.getjitstate()
+        boxes_v = []
+        for r, v in zip(hop.args_r, hop.args_v):
+            if isinstance(r, RedRepr):
+                boxes_v.append(v)
+        v_boxes = ts.build_box_list(hop.llops, boxes_v)
+        hop.llops.genmixlevelhelpercall(rtimeshift.save_locals,
+                                        [ts.s_JITState, ts.s_box_list],
+                                        [v_jitstate,    v_boxes],
+                                        annmodel.s_None)
+
     def handle_highlevel_operation(self, fnobj, hop):
         from pypy.jit.timeshifter.oop import OopSpecDesc, Index
         oopspecdesc = OopSpecDesc(fnobj)

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	Mon Aug 21 19:50:27 2006
@@ -80,10 +80,10 @@
     graph1 = ha.translator.graphs[0]
     llinterp = LLInterpreter(rtyper)
     builder = llinterp.eval_graph(htshift.ll_make_builder_graph, [])
-    graph1args = [builder]
+    graph1args = [builder, lltype.nullptr(htshift.r_JITState.lowleveltype.TO)]
     residual_graph_args = []
-    assert len(graph1.getargs()) == 1 + len(values)
-    for i, (v, llvalue) in enumerate(zip(graph1.getargs()[1:], values)):
+    assert len(graph1.getargs()) == 2 + len(values)
+    for i, (v, llvalue) in enumerate(zip(graph1.getargs()[2:], values)):
         r = htshift.hrtyper.bindingrepr(v)
         residual_v = r.residual_values(llvalue)
         if len(residual_v) == 0:
@@ -569,3 +569,12 @@
     insns, res = timeshift(ll_function, [5], [], policy=P_NOVIRTUAL)
     assert res == 6
     assert insns == {'int_add': 1}
+
+def test_call_2():
+    def ll_add_one(x):
+        return x + 1
+    def ll_function(y):
+        return ll_add_one(y) + y
+    insns, res = timeshift(ll_function, [5], [], policy=P_NOVIRTUAL)
+    assert res == 11
+    assert insns == {'int_add': 2}

Modified: pypy/dist/pypy/jit/timeshifter/timeshift.py
==============================================================================
--- pypy/dist/pypy/jit/timeshifter/timeshift.py	(original)
+++ pypy/dist/pypy/jit/timeshifter/timeshift.py	Mon Aug 21 19:50:27 2006
@@ -225,15 +225,16 @@
     def insert_start_setup(self):
         newstartblock = self.insert_before_block(self.graph.startblock, None, closeblock=True)
         v_builder = varoftype(self.r_ResidualGraphBuilder.lowleveltype, 'builder')
+        v_backstate = varoftype(self.r_JITState.lowleveltype, 'backstate')
         v_jitstate = newstartblock.inputargs[0]
-        newstartblock.inputargs[0] = v_builder
+        newstartblock.inputargs[:1] = [v_builder, v_backstate]
         llops = HintLowLevelOpList(self, None)
 
         llops.genop('direct_call', [self.c_ll_clearcaches_ptr])
         v_jitstate1 = llops.genmixlevelhelpercall(rtimeshift.enter_graph,
-                                                  [self.s_ResidualGraphBuilder],
-                                                  [v_builder],
-                                                  self.s_JITState)
+                               [self.s_ResidualGraphBuilder, self.s_JITState],
+                               [v_builder,                   v_backstate],
+                               self.s_JITState)
         llops.append(flowmodel.SpaceOperation('same_as', [v_jitstate1], v_jitstate))
         newstartblock.operations = list(llops)
         
@@ -691,6 +692,20 @@
             if op.opname == 'direct_call':
                 link = support.split_block_with_keepalive(block, i+1,
                                          annotator=self.hannotator)
+
+                # the 'save_locals' pseudo-operation is used to save all
+                # alive local variables into the current JITState
+                args = list(link.args)
+                while op.result in args:
+                    args.remove(op.result)
+                assert op is block.operations[i]
+                v_dummy = varoftype(lltype.Void)
+                self.hannotator.setbinding(v_dummy, annmodel.s_ImpossibleValue)
+                extraop = flowmodel.SpaceOperation('save_locals',
+                                                   args,
+                                                   v_dummy)
+                block.operations.insert(i, extraop)
+
                 block = link.target
                 entering_links[block] = [link]
                 blocks.append(block)



More information about the Pypy-commit mailing list