[pypy-svn] r52567 - in pypy/branch/jit-hotpath/pypy/jit: rainbow rainbow/test timeshifter

arigo at codespeak.net arigo at codespeak.net
Sat Mar 15 22:04:05 CET 2008


Author: arigo
Date: Sat Mar 15 22:04:03 2008
New Revision: 52567

Modified:
   pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py
   pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py
   pypy/branch/jit-hotpath/pypy/jit/rainbow/hotpath.py
   pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py
   pypy/branch/jit-hotpath/pypy/jit/rainbow/rhotpath.py
   pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hp_interpreter.py
   pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py
Log:
Improve the tests (see big comment).
Fallback interp calls to functions that have both red and green args.
Residual calls, with exception checking.


Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py
==============================================================================
--- pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py	(original)
+++ pypy/branch/jit-hotpath/pypy/jit/rainbow/codewriter.py	Sat Mar 15 22:04:03 2008
@@ -32,10 +32,11 @@
 class CallDesc:
     __metaclass__ = cachedtype
 
-    def __init__(self, RGenOp, exceptiondesc, FUNCTYPE):
+    def __init__(self, RGenOp, exceptiondesc, FUNCTYPE, colororder=None):
         self.exceptiondesc = exceptiondesc
         self.sigtoken = RGenOp.sigToken(FUNCTYPE.TO)
         self.result_kind = RGenOp.kindToken(FUNCTYPE.TO.RESULT)
+        self.colororder = colororder
         # xxx what if the result is virtualizable?
         self.redboxbuilder = rvalue.ll_redboxbuilder(FUNCTYPE.TO.RESULT)
         whatever_return_value = FUNCTYPE.TO.RESULT._defl()
@@ -52,16 +53,16 @@
             self.gv_whatever_return_value = RGenOp.constPrebuiltGlobal(
                 whatever_return_value)
 
-        def perform_call(rgenop, gv_fnptr, greenargs):
+        def perform_call(rgenop, gv_fnptr, args_gv):
             fnptr = gv_fnptr.revealconst(FUNCTYPE)
-            assert len(greenargs) + voidargcount == numargs
+            assert len(args_gv) + voidargcount == numargs
             args = ()
             j = 0
             for ARG in argiter:
                 if ARG == lltype.Void:
                     args += (None, )
                 else:
-                    genconst = greenargs[j]
+                    genconst = args_gv[j]
                     arg = genconst.revealconst(ARG)
                     args += (arg, )
                     j += 1
@@ -77,6 +78,7 @@
         return True
 
     def green_call(self, interpreter, gv_fnptr, greenargs):
+        assert self.colororder is None
         rgenop = interpreter.jitstate.curbuilder.rgenop
         try:
             gv_result = self.perform_call(rgenop, gv_fnptr, greenargs)
@@ -90,6 +92,25 @@
         if gv_result is not None:
             interpreter.green_result(gv_result)
 
+    def perform_call_mixed(self, rgenop, gv_fnptr, greens_gv, reds_gv):
+        if self.colororder is None:
+            args_gv = greens_gv + reds_gv
+        else:
+            args_gv = []
+            gi = 0
+            ri = 0
+            for c in self.colororder:
+                if c == 'g':
+                    gv = greens_gv[gi]
+                    gi += 1
+                else:
+                    gv = reds_gv[ri]
+                    ri += 1
+                args_gv.append(gv)
+            assert gi == len(greens_gv)
+            assert ri == len(reds_gv)
+        return self.perform_call(rgenop, gv_fnptr, args_gv)
+
 
 class IndirectCallsetDesc(object):
     __metaclass__ = cachedtype
@@ -264,8 +285,22 @@
         RESULT = graph.getreturnvar().concretetype
         FUNCTYPE = lltype.FuncType(ARGS, RESULT)
 
+        # if the graph takes both red and green arguments, we need
+        # a way for the fallback interp to rezip the two lists
+        # 'greenargs' and 'redargs' into a single one
+        colororder = ""
+        in_order = True           # "in order" means allgreens+allreds
+        for v in graph.getargs():
+            if self.hannotator.binding(v).is_green():
+                if "r" in colororder:
+                    in_order = False
+                colororder += "g"
+            else:
+                colororder += "r"
+        if in_order:
+            colororder = None
         owncalldesc = CallDesc(self.RGenOp, self.exceptiondesc,
-                               lltype.Ptr(FUNCTYPE))
+                               lltype.Ptr(FUNCTYPE), colororder)
         ownfnptr = lltype.functionptr(FUNCTYPE, graph.name, graph=graph)
         gv_ownfnptr = self.RGenOp.constPrebuiltGlobal(ownfnptr)
         return owncalldesc, gv_ownfnptr
@@ -987,10 +1022,14 @@
             if v.concretetype == lltype.Void:
                 continue
             emitted_args.append(self.serialize_oparg("red", v))
-        self.emit("red_residual_call")
+        if self.hannotator.policy.hotpath:
+            self.emit("hp_residual_call")
+        else:
+            self.emit("red_residual_call")
         self.emit(func, pos, withexc, has_result, len(emitted_args))
         self.emit(*emitted_args)
-        self.emit(self.promotiondesc_position(lltype.Signed))
+        if not self.hannotator.policy.hotpath:
+            self.emit(self.promotiondesc_position(lltype.Signed))
         if has_result:
             self.register_redvar(op.result)
 

Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py
==============================================================================
--- pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py	(original)
+++ pypy/branch/jit-hotpath/pypy/jit/rainbow/fallback.py	Sat Mar 15 22:04:03 2008
@@ -85,12 +85,11 @@
             Xxx("capture_exception")
 
     def run_directly(self, greenargs, redargs, targetbytecode):
-        assert not (greenargs and redargs)  # XXX for now
         calldesc = targetbytecode.owncalldesc
         try:
-            gv_res = calldesc.perform_call(self.rgenop,
-                                           targetbytecode.gv_ownfnptr,
-                                           greenargs or redargs)
+            gv_res = calldesc.perform_call_mixed(self.rgenop,
+                                                 targetbytecode.gv_ownfnptr,
+                                                 greenargs, redargs)
         except Exception, e:
             self.capture_exception(e)
             gv_res = calldesc.gv_whatever_return_value
@@ -248,7 +247,12 @@
 
     @arguments("green", "green_varargs", "jumptargets")
     def opimpl_green_switch(self, exitcase, cases, targets):
-        Xxx("green_switch")
+        arg = exitcase.revealconst(lltype.Signed)
+        assert len(cases) == len(targets)
+        for i in range(len(cases)):
+            if arg == cases[i].revealconst(lltype.Signed):
+                self.pc = targets[i]
+                break
 
     @arguments("bool", "red", "red", "jumptarget")
     def opimpl_red_goto_ifptrnonzero(self, reverse, gv_ptr, gv_switch, target):
@@ -337,12 +341,6 @@
     def opimpl_red_oopspec_call_noresult_3(self, oopspec, deepfrozen, arg1, arg2, arg3):
         self.oopspec_call(oopspec, [arg1, arg2, arg3])
 
-    @arguments("red", "calldesc", "bool", "bool", "red_varargs",
-               "promotiondesc")
-    def opimpl_red_residual_call(self, gv_func, calldesc, withexc, has_result,
-                                 redargs, promotiondesc):
-        Xxx("red_residual_call")
-
     @arguments("metacalldesc", "red_varargs", returns="red")
     def opimpl_metacall(self, metafunc, redargs):
         Xxx("metacall")
@@ -392,7 +390,9 @@
 
     @arguments("red", "fielddesc", "bool", returns="green_from_red")
     def opimpl_green_getfield(self, gv_struct, fielddesc, deepfrozen):
-        Xxx("green_getfield")
+        gv_res = fielddesc.getfield_if_non_null(self.rgenop, gv_struct)
+        assert gv_res is not None, "segfault!"
+        return gv_res
 
     @arguments("red", "fielddesc", "red")
     def opimpl_red_setfield(self, gv_dest, fielddesc, gv_value):
@@ -479,6 +479,17 @@
         gv_res = self.run_directly(greenargs, redargs, targetbytecode)
         self.green_result(gv_res)
 
+    @arguments("red", "calldesc", "bool", "bool", "red_varargs")
+    def opimpl_hp_residual_call(self, gv_func, calldesc, withexc, has_result,
+                                redargs_gv):
+        try:
+            gv_res = calldesc.perform_call(self.rgenop, gv_func, redargs_gv)
+        except Exception, e:
+            self.capture_exception(e)
+            gv_res = calldesc.gv_whatever_return_value
+        if has_result:
+            self.red_result(gv_res)
+
     def hp_return(self):
         frame = self.current_source_jitframe.backframe
         if frame is None:

Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/hotpath.py
==============================================================================
--- pypy/branch/jit-hotpath/pypy/jit/rainbow/hotpath.py	(original)
+++ pypy/branch/jit-hotpath/pypy/jit/rainbow/hotpath.py	Sat Mar 15 22:04:03 2008
@@ -97,9 +97,12 @@
         self.maybe_enter_jit_fn = maybe_enter_jit
 
     def make_descs(self):
-        ERASED = self.RGenOp.erasedType(lltype.Bool)
-        self.bool_hotpromotiondesc = rhotpath.HotPromotionDesc(ERASED,
-                                                               self.RGenOp)
+        HotPromotionDesc = rhotpath.HotPromotionDesc
+        RGenOp = self.RGenOp
+        EBOOL   = RGenOp.erasedType(lltype.Bool)
+        ESIGNED = RGenOp.erasedType(lltype.Signed)
+        self.bool_hotpromotiondesc   = HotPromotionDesc(EBOOL,   RGenOp)
+        self.signed_hotpromotiondesc = HotPromotionDesc(ESIGNED, RGenOp)
 
     def rewrite_graphs(self):
         for graph in self.hintannotator.base_translator.graphs:

Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py
==============================================================================
--- pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py	(original)
+++ pypy/branch/jit-hotpath/pypy/jit/rainbow/interpreter.py	Sat Mar 15 22:04:03 2008
@@ -908,6 +908,16 @@
     opimpl_hp_gray_direct_call = opimpl_hp_red_direct_call
     opimpl_hp_yellow_direct_call = opimpl_hp_red_direct_call
 
+    @arguments("red", "calldesc", "bool", "bool", "red_varargs")
+    def opimpl_hp_residual_call(self, funcbox, calldesc, withexc, has_result,
+                                redargs):
+        result = rtimeshift.gen_residual_call(self.jitstate, calldesc,
+                                              funcbox, redargs)
+        if has_result:
+            self.red_result(result)
+        rhotpath.hp_after_residual_call(self.jitstate, self.hotrunnerdesc,
+                                        withexc, True)
+
     def hp_return(self):
         frame = self.frame.backframe
         if frame is None:

Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/rhotpath.py
==============================================================================
--- pypy/branch/jit-hotpath/pypy/jit/rainbow/rhotpath.py	(original)
+++ pypy/branch/jit-hotpath/pypy/jit/rainbow/rhotpath.py	Sat Mar 15 22:04:03 2008
@@ -23,7 +23,7 @@
     interp.frame.local_green = greenargs
     interp.graphsigtoken = graphsigtoken
 
-def leave_graph(interp):
+def leave_graph(interp, store_back_exception=True):
     jitstate = interp.jitstate
     exceptiondesc = interp.exceptiondesc
     builder = jitstate.curbuilder
@@ -277,13 +277,16 @@
         # compile from that state
         interpreter = self.hotrunnerdesc.interpreter
         interpreter.newjitstate(jitstate)
-        interpreter.green_result(gv_value)
         jitstate.curbuilder = self.flexswitch.add_case(gv_value)
+        self.prepare_compiler(interpreter, gv_value)
         compile(interpreter)
         # done
         greenkey = GreenKey([gv_value], self.hotpromotiondesc.greenkeydesc)
         self.counters[greenkey] = -1     # means "compiled"
 
+    def prepare_compiler(self, interpreter, gv_value):
+        interpreter.green_result(gv_value)
+
 
 def hotsplit(jitstate, hotrunnerdesc, switchbox,
              falsepath_pc, truepath_pc):
@@ -298,7 +301,8 @@
                                hotpromotiondesc)
     generate_fallback_code(fbp, hotpromotiondesc, promotebox)
 
-def generate_fallback_code(fbp, hotpromotiondesc, switchbox):
+def generate_fallback_code(fbp, hotpromotiondesc, switchbox,
+                           check_exceptions=False):
     jitstate = fbp.saved_jitstate
     incoming = jitstate.enter_block_sweep_virtualizables()
     switchblock = rtimeshift.enter_next_block(jitstate, incoming)
@@ -307,7 +311,17 @@
     flexswitch, default_builder = jitstate.curbuilder.flexswitch(gv_switchvar,
                                                                  incoming_gv)
     jitstate.curbuilder = default_builder
+
     # default case of the switch:
+    exceptiondesc = fbp.hotrunnerdesc.exceptiondesc
+    if check_exceptions:
+        # virtualize the exception into the jitstate (xxx fragile code)
+        prevtypebox = jitstate.exc_type_box
+        prevvaluebox = jitstate.exc_value_box
+        exceptiondesc.fetch_global_excdata(jitstate)
+        incoming_gv.append(jitstate.exc_type_box.genvar)
+        incoming_gv.append(jitstate.exc_value_box.genvar)
+
     frameinfo = default_builder.get_frame_info(incoming_gv)
     fbp.set_machine_code_info(flexswitch, frameinfo)
     ll_fbp = _cast_fallback_point_to_base_ptr(fbp)
@@ -321,11 +335,18 @@
     # The call above may either return normally, meaning that more machine
     # code was compiled and we should loop back to 'switchblock' to enter it,
     # or it may have set an exception.
-    exceptiondesc = fbp.hotrunnerdesc.exceptiondesc
     gv_exc_type = exceptiondesc.genop_get_exc_type(default_builder)
     gv_noexc = default_builder.genop_ptr_iszero(
         exceptiondesc.exc_type_kind, gv_exc_type)
     excpath_builder = default_builder.jump_if_false(gv_noexc, [])
+
+    if check_exceptions:
+        # unvirtualize the exception
+        exceptiondesc.store_global_excdata(jitstate)
+        incoming_gv.pop()
+        incoming_gv.pop()
+        jitstate.exc_type_box = prevtypebox
+        jitstate.exc_value_box = prevvaluebox
     default_builder.finish_and_goto(incoming_gv, switchblock)
 
     jitstate.curbuilder = excpath_builder
@@ -345,3 +366,52 @@
         return cast_instance_to_base_ptr(instance)
     else:
         return instance
+
+# ____________________________________________________________
+
+# support for reading the state after a residual call, XXX a bit lengthy
+
+class AfterResidualCallFallbackPoint(PromoteFallbackPoint):
+
+    def __init__(self, jitstate, hotrunnerdesc, promotebox, hotpromotiondesc,
+                 check_forced):
+        PromoteFallbackPoint.__init__(self, jitstate, hotrunnerdesc,
+                                      promotebox, hotpromotiondesc)
+        self.check_forced = check_forced
+
+    @specialize.arglltype(2)
+    def prepare_fallbackinterp(self, fallbackinterp, value):
+        fallbackinterp.local_red.pop()   # remove the temporary flagbox
+
+    def prepare_compiler(self, interpreter, gv_value):
+        # remove the temporary flagbox
+        flagbox = interpreter.frame.local_boxes.pop()
+        exceptiondesc = self.hotrunnerdesc.exceptiondesc
+        rtimeshift.residual_fetch(interpreter.jitstate, exceptiondesc,
+                                  self.check_forced, flagbox)
+
+
+def hp_after_residual_call(jitstate, hotrunnerdesc, withexc, check_forced):
+    if withexc:
+        exceptiondesc = hotrunnerdesc.exceptiondesc
+    else:
+        exceptiondesc = None
+    gv_flags = rtimeshift.gvflags_after_residual_call(jitstate,
+                                                      exceptiondesc,
+                                                      check_forced)
+    if gv_flags is None:
+        return     # nothing to check
+    # XXX slightly hackish: the gv_flags needs to be in local_boxes
+    # to be passed along to the new block
+    assert not gv_flags.is_const
+    tok_signed = hotrunnerdesc.RGenOp.kindToken(lltype.Signed)
+    flagbox = rvalue.IntRedBox(tok_signed, gv_flags)
+    jitstate.frame.local_boxes.append(flagbox)
+
+    hotpromotiondesc = hotrunnerdesc.signed_hotpromotiondesc
+    fbp = AfterResidualCallFallbackPoint(jitstate, hotrunnerdesc,
+                                         flagbox, hotpromotiondesc,
+                                         check_forced)
+    generate_fallback_code(fbp, hotpromotiondesc, flagbox,
+                           check_exceptions=withexc)
+    assert 0, "unreachable"

Modified: pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hp_interpreter.py
==============================================================================
--- pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hp_interpreter.py	(original)
+++ pypy/branch/jit-hotpath/pypy/jit/rainbow/test/test_hp_interpreter.py	Sat Mar 15 22:04:03 2008
@@ -6,6 +6,24 @@
 
 import sys
 
+# ------------------------------------------------------------------------
+# A note about these tests.  Their portal function is generally structured
+# like this:
+#
+#    i = 1024
+#    while i > 0:
+#        ...real test code here...
+#        MyJitDriver.jit_merge_point(...)
+#        MyJitDriver.can_enter_jit(...)
+#
+# and we use a threshold of 2, typically.  This ensures that in a single
+# call, the test code is run in all three ways:
+#  - first it runs directly
+#  - then we start the JIT but immediately pause at the 'i > 0' check,
+#      so that the real test code runs in the fallback interp
+#  - then we JIT everything
+# ------------------------------------------------------------------------
+
 
 class TestHotInterpreter(test_hotpath.HotPathTest):
 
@@ -21,16 +39,16 @@
         def ll_function(x, y):
             tot = 0
             while x:    # conversion from green '0' to red 'tot'
-                MyJitDriver.jit_merge_point(x=x, y=y, tot=tot)
-                MyJitDriver.can_enter_jit(x=x, y=y, tot=tot)
                 hint(x, concrete=True)
                 tot += y
                 x -= 1
+                MyJitDriver.jit_merge_point(x=x, y=y, tot=tot)
+                MyJitDriver.can_enter_jit(x=x, y=y, tot=tot)
             return tot
 
         res = self.run(ll_function, [7, 2], threshold=1)
         assert res == 14
-        self.check_insns_excluding_return({'int_add': 7})
+        self.check_insns_excluding_return({'int_add': 6})
 
     def test_ifs(self):
         class MyJitDriver(JitDriver):
@@ -225,15 +243,11 @@
     def test_arith_plus_minus(self):
         class MyJitDriver(JitDriver):
             greens = ['encoded_insn', 'nb_insn']
-            reds = ['i', 'x', 'y']
+            reds = ['i', 'x', 'y', 'acc']
         def ll_plus_minus(encoded_insn, nb_insn, x, y):
             i = 1024
             while i > 0:
                 i >>= 1
-                MyJitDriver.jit_merge_point(encoded_insn=encoded_insn,
-                                            nb_insn=nb_insn, x=x, y=y, i=i)
-                MyJitDriver.can_enter_jit(encoded_insn=encoded_insn,
-                                          nb_insn=nb_insn, x=x, y=y, i=i)
                 hint(nb_insn, concrete=True)
                 acc = x
                 pc = 0
@@ -245,6 +259,12 @@
                     elif op == 0x5:
                         acc -= y
                     pc += 1
+                MyJitDriver.jit_merge_point(encoded_insn=encoded_insn,
+                                            nb_insn=nb_insn, x=x, y=y, i=i,
+                                            acc=acc)
+                MyJitDriver.can_enter_jit(encoded_insn=encoded_insn,
+                                          nb_insn=nb_insn, x=x, y=y, i=i,
+                                          acc=acc)
             return acc
         assert ll_plus_minus(0xA5A, 3, 32, 10) == 42
         res = self.run(ll_plus_minus, [0xA5A, 3, 32, 10], threshold=2)
@@ -255,7 +275,7 @@
     def test_call_3(self):
         class MyJitDriver(JitDriver):
             greens = []
-            reds = ['i', 'y']
+            reds = ['i', 'y', 'res']
         def ll_add_one(x):
             return x + 1
         def ll_two(x):
@@ -264,33 +284,69 @@
             i = 1024
             while i > 0:
                 i >>= 1
-                MyJitDriver.jit_merge_point(y=y, i=i)
-                MyJitDriver.can_enter_jit(y=y, i=i)
                 res = ll_two(y) * y
+                MyJitDriver.jit_merge_point(y=y, i=i, res=res)
+                MyJitDriver.can_enter_jit(y=y, i=i, res=res)
             return res
         res = self.run(ll_function, [5], threshold=2)
         assert res == 10
         self.check_insns_in_loops({'int_add': 2, 'int_sub': 1, 'int_mul': 1,
                                    'int_gt': 1, 'int_rshift': 1})
 
+    def test_call_mixed_color_args(self):
+        class MyJitDriver(JitDriver):
+            greens = ['g1', 'g2']
+            reds = ['r1', 'r2', 'i', 'res']
+
+        def ll_grr(a, b, c): return a + 3*b + 7*c
+        def ll_rgr(a, b, c): return a + 3*b + 7*c
+        def ll_rrg(a, b, c): return a + 3*b + 7*c
+        def ll_ggr(a, b, c): return a + 3*b + 7*c
+        def ll_grg(a, b, c): return a + 3*b + 7*c
+        def ll_rgg(a, b, c): return a + 3*b + 7*c
+        
+        def ll_function(g1, g2, r1, r2):
+            i = 1024
+            while i > 0:
+                i >>= 1
+                res = (ll_grr(g1, r1, r2) * 1 +
+                       ll_rgr(r1, g2, r2) * 10 +
+                       ll_rrg(r2, r1, g1) * 100 +
+                       ll_ggr(g1, g2, r2) * 1000 +
+                       ll_grg(g2, r2, g1) * 10000 +
+                       ll_rgg(r1, g2, g1) * 100000)
+                hint(g1, concrete=True)
+                hint(g2, concrete=True)
+                MyJitDriver.jit_merge_point(g1=g1, g2=g2, r1=r1, r2=r2,
+                                            i=i, res=res)
+                MyJitDriver.can_enter_jit(g1=g1, g2=g2, r1=r1, r2=r2,
+                                          i=i, res=res)
+            return res
+        res = self.run(ll_function, [1, 2, 4, 8], threshold=2)
+        assert res == ll_function(1, 2, 4, 8)
+
     def test_void_call(self):
         class MyJitDriver(JitDriver):
             greens = []
             reds = ['y', 'i']
-        def ll_do_nothing(x):
-            pass
+        S = lltype.GcStruct('S', ('x', lltype.Signed))
+        def ll_do_nothing(s, x):
+            s.x = x + 1
         def ll_function(y):
             i = 1024
             while i > 0:
                 i >>= 1
+                s = lltype.malloc(S)
+                ll_do_nothing(s, y)
+                y = s.x
                 MyJitDriver.jit_merge_point(y=y, i=i)
                 MyJitDriver.can_enter_jit(y=y, i=i)
-                ll_do_nothing(y)
             return y
 
         res = self.run(ll_function, [3], threshold=2)
-        assert res == 3
-        self.check_insns_in_loops({'int_gt': 1, 'int_rshift': 1})
+        assert res == ll_function(3)
+        self.check_insns_in_loops({'int_add': 1,
+                                   'int_gt': 1, 'int_rshift': 1})
 
     def test_green_return(self):
         class MyJitDriver(JitDriver):
@@ -761,16 +817,16 @@
     def test_residual_red_call(self):
         class MyJitDriver(JitDriver):
             greens = []
-            reds = ['i', 'x']
+            reds = ['i', 'x', 'res']
         def g(x):
             return x+1
         def f(x):
             i = 1024
             while i > 0:
                 i >>= 1
-                MyJitDriver.jit_merge_point(x=x, i=i)
-                MyJitDriver.can_enter_jit(x=x, i=i)
                 res = 2*g(x)
+                MyJitDriver.jit_merge_point(x=x, i=i, res=res)
+                MyJitDriver.can_enter_jit(x=x, i=i, res=res)
             return res
 
         res = self.run(f, [20], threshold=2, policy=StopAtXPolicy(g))
@@ -779,10 +835,9 @@
                                    'int_gt': 1, 'int_rshift': 1})
 
     def test_residual_red_call_with_exc(self):
-        py.test.skip("in-progress")
         class MyJitDriver(JitDriver):
             greens = []
-            reds = ['i', 'x']
+            reds = ['i', 'x', 'res']
 
         def h(x):
             if x > 0:
@@ -797,12 +852,12 @@
             i = 1024
             while i > 0:
                 i >>= 1
-                MyJitDriver.jit_merge_point(x=x, i=i)
-                MyJitDriver.can_enter_jit(x=x, i=i)
                 try:
                     res = g(x)
                 except ValueError:
                     res = 7
+                MyJitDriver.jit_merge_point(x=x, i=i, res=res)
+                MyJitDriver.can_enter_jit(x=x, i=i, res=res)
             return res
 
         stop_at_h = StopAtXPolicy(h)

Modified: pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py	(original)
+++ pypy/branch/jit-hotpath/pypy/jit/timeshifter/rtimeshift.py	Sat Mar 15 22:04:03 2008
@@ -585,7 +585,7 @@
     gv_result = builder.genop_call(calldesc.sigtoken, gv_funcbox, args_gv)
     return calldesc.redboxbuilder(calldesc.result_kind, gv_result)
 
-def after_residual_call(jitstate, exceptiondesc, check_forced):
+def gvflags_after_residual_call(jitstate, exceptiondesc, check_forced):
     builder = jitstate.curbuilder
     if check_forced:
         gv_flags = jitstate.check_forced_after_residual_call()
@@ -602,6 +602,11 @@
         else:
             assert gv_flags is None
             exceptiondesc.fetch_global_excdata(jitstate)
+    return gv_flags
+
+def after_residual_call(jitstate, exceptiondesc, check_forced):
+    gv_flags = gvflags_after_residual_call(jitstate, exceptiondesc,
+                                           check_forced)
     if gv_flags is None:
         gv_flags = builder.rgenop.constPrebuiltGlobal(0)
     return rvalue.IntRedBox(builder.rgenop.kindToken(lltype.Signed), gv_flags)



More information about the Pypy-commit mailing list