[pypy-svn] r52786 - in pypy/branch/jit-hotpath/pypy/jit/rainbow: . test

arigo at codespeak.net arigo at codespeak.net
Thu Mar 20 18:36:03 CET 2008


Author: arigo
Date: Thu Mar 20 18:36:02 2008
New Revision: 52786

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
Log:
(cfbolz a bit, arigo)

Support for exception-raising operations (mostly arithmetic ovf)
in the rainbow and fallback interpreters.


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	Thu Mar 20 18:36:02 2008
@@ -571,9 +571,14 @@
             self.register_redvar(op.result)
         if (opdesc is not None and 
             opdesc.tryfold and not opdesc.canfold and opdesc.canraise):
+            # XXX len(canraise) should be 1, except in
+            # kind-of-deprecated cases
             exc_class = opdesc.llop.canraise[0]
-            self.emit("split_raisingop",
-                      self.exceptioninstance_position(exc_class))
+            if self.hannotator.policy.hotpath:
+                self.emit("hp_split_raisingop")
+            else:
+                self.emit("split_raisingop")
+            self.emit(self.exceptioninstance_position(exc_class))
 
     def serialize_opcode(self, color, op):
         opname = op.opname

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	Thu Mar 20 18:36:02 2008
@@ -90,6 +90,11 @@
         else:
             Xxx("capture_exception")
 
+    def residual_ll_exception(self, ll_evalue):
+        ll_etype = self.hotrunnerdesc.ts.get_typeptr(ll_evalue)
+        self.gv_exc_type  = self.rgenop.genconst(ll_etype)
+        self.gv_exc_value = self.rgenop.genconst(ll_evalue)
+
     def run_directly(self, greenargs, redargs, targetbytecode):
         return self.perform_call_mixed(greenargs, redargs,
                                        targetbytecode.gv_ownfnptr,
@@ -539,6 +544,12 @@
         if has_result:
             self.red_result(gv_res)
 
+    @arguments("exception")
+    def opimpl_hp_split_raisingop(self, ll_evalue):
+        gv_raised = self.local_green.pop()
+        if gv_raised.revealconst(lltype.Bool):
+            self.residual_ll_exception(ll_evalue)
+
     def hp_return(self):
         frame = self.current_source_jitframe.backframe
         if frame is None:
@@ -591,17 +602,33 @@
 
     def get_opcode_implementation(self, func_name, argspec, opdesc):
         numargs = unrolling_iterable(range(opdesc.nb_args))
-        def implementation(self, *args_gv):
-            args = (opdesc.RESULT, )
-            for i in numargs:
-                arg = args_gv[i].revealconst(opdesc.ARGS[i])
-                args += (arg, )
-            if not we_are_translated():
-                if opdesc.opname == "int_is_true":
-                    # special case for tests, as in llinterp.py
-                    if type(args[1]) is CDefinedIntSymbolic:
-                        args = (args[0], args[1].default)
-            return self.rgenop.genconst(opdesc.llop(*args))
+        if not opdesc.canraise:
+            def implementation(self, *args_gv):
+                args = (opdesc.RESULT, )
+                for i in numargs:
+                    arg = args_gv[i].revealconst(opdesc.ARGS[i])
+                    args += (arg, )
+                if not we_are_translated():
+                    if opdesc.opname == "int_is_true":
+                        # special case for tests, as in llinterp.py
+                        if type(args[1]) is CDefinedIntSymbolic:
+                            args = (args[0], args[1].default)
+                return self.rgenop.genconst(opdesc.llop(*args))
+        else:
+            exceptions_tuple = opdesc.llop.canraise
+            def implementation(self, *args_gv):
+                args = (opdesc.RESULT, )
+                for i in numargs:
+                    arg = args_gv[i].revealconst(opdesc.ARGS[i])
+                    args += (arg, )
+                try:
+                    result = opdesc.llop(*args)
+                    gv_raised = opdesc.gv_False
+                except exceptions_tuple:
+                    result = opdesc.whatever_result
+                    gv_raised = opdesc.gv_True
+                self.local_green.append(gv_raised)
+                return self.rgenop.genconst(result)
         implementation.func_name = func_name
         # the argspec may unwrap *args_gv from local_red or local_green
         # and put the result back into local_red or local_green

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	Thu Mar 20 18:36:02 2008
@@ -27,6 +27,7 @@
         self.RGenOp = RGenOp
         self.exceptiondesc = codewriter.exceptiondesc
         self.interpreter = codewriter.interpreter
+        self.ts = self.interpreter.ts
         self.codewriter = codewriter
         self.threshold = threshold
         self.translate_support_code = translate_support_code

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	Thu Mar 20 18:36:02 2008
@@ -932,6 +932,11 @@
         rhotpath.hp_after_residual_call(self.jitstate, self.hotrunnerdesc,
                                         withexc, True)
 
+    @arguments("exception")
+    def opimpl_hp_split_raisingop(self, ll_evalue):
+        rhotpath.hp_after_raisingop(self.jitstate, self.hotrunnerdesc,
+                                    ll_evalue)
+
     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	Thu Mar 20 18:36:02 2008
@@ -420,3 +420,53 @@
     generate_fallback_code(fbp, hotpromotiondesc, flagbox,
                            check_exceptions=withexc)
     assert 0, "unreachable"
+
+# ____________________________________________________________
+
+# support for turning the 'gv_raised' left behind by primitive raising
+# operations directly into a virtualized exception on the JITState,
+# splitting the machine code in two paths.
+
+class AfterRaisingOpFallbackPoint(PromoteFallbackPoint):
+        
+    def __init__(self, jitstate, hotrunnerdesc, promotebox, hotpromotiondesc,
+                 ll_evalue):
+        PromoteFallbackPoint.__init__(self, jitstate, hotrunnerdesc,
+                                      promotebox, hotpromotiondesc)
+        self.ll_evalue = ll_evalue
+
+    @specialize.arglltype(2)
+    def prepare_fallbackinterp(self, fallbackinterp, value):
+        value = bool(value)
+        fallbackinterp.local_red.pop()   # remove the temporary raisedbox
+        if value:
+            # got an exception, register it on the fallbackinterp
+            fallbackinterp.residual_ll_exception(self.ll_evalue)
+
+    def prepare_compiler(self, interpreter, gv_value):
+        # remove the temporary raisedbox
+        interpreter.frame.local_boxes.pop()
+        if gv_value.revealconst(lltype.Bool):
+            # got an exception, register it on the interpreter
+            interpreter.jitstate.residual_ll_exception(self.ll_evalue)
+
+
+def hp_after_raisingop(jitstate, hotrunnerdesc, ll_evalue):
+    gv_raised = jitstate.greens.pop() # XXX hackish interface,
+                                      # pushed here by ll_gen1 or ll_gen2
+    # XXX slightly hackish as well, we actually need gv_raised to be
+    # in local_boxes to be passed along to the new block
+    assert not gv_raised.is_const
+    tok_bool = hotrunnerdesc.RGenOp.kindToken(lltype.Bool)
+    raisedbox = rvalue.IntRedBox(tok_bool, gv_raised)
+    jitstate.frame.local_boxes.append(raisedbox)
+    
+    hotpromotiondesc = hotrunnerdesc.bool_hotpromotiondesc
+    fbp = AfterRaisingOpFallbackPoint(jitstate, hotrunnerdesc,
+                                      raisedbox, hotpromotiondesc,
+                                      ll_evalue)
+    generate_fallback_code(fbp, hotpromotiondesc, raisedbox,
+                           check_exceptions=False)
+    # NB. check_exceptions is False because no exception should set
+    # set now (the RGenOp's genraisingop cannot set an exception itself)
+    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	Thu Mar 20 18:36:02 2008
@@ -5,6 +5,7 @@
 from pypy.rlib.objectmodel import keepalive_until_here
 from pypy.jit.hintannotator.policy import HintAnnotatorPolicy, StopAtXPolicy
 from pypy.jit.rainbow.test import test_hotpath
+from pypy.rlib.rarithmetic import ovfcheck
 
 import sys
 
@@ -1753,26 +1754,28 @@
 
 
     def test_red_int_add_ovf(self):
+        class MyJitDriver(JitDriver):
+            greens = []
+            reds = ['n', 'm', 'i', 'result']
         def f(n, m):
-            try:
-                result = ovfcheck(n + m)
-            except OverflowError:
-                return -42 + m
+            i = 1024
+            while i > 0:
+                i >>= 1
+                try:
+                    result = ovfcheck(n + m)
+                except OverflowError:
+                    result = -42 + m
+                MyJitDriver.jit_merge_point(n=n, m=m, i=i, result=result)
+                MyJitDriver.can_enter_jit(n=n, m=m, i=i, result=result)
             return result + 1
 
-        res = self.interpret(f, [100, 20])
+        res = self.run(f, [100, 20], threshold=2)
         assert res == 121
-        self.check_insns(int_add_ovf=1)
-        #res = self.interpret(f, [100, 20], [0, 1])
-        #assert res == 121
-        #self.check_insns()
+        self.check_insns_in_loops(int_add_ovf=1)
 
-        res = self.interpret(f, [sys.maxint, 1])
-        assert res == -41
-        self.check_insns(int_add_ovf=1)
-        res = self.interpret(f, [sys.maxint, 5], [0, 1])
-        assert res == -42 + 5
-        self.check_insns()
+        res = self.run(f, [sys.maxint, 1], threshold=2)
+        assert res == -40
+        self.check_insns_in_loops(int_add_ovf=1)
 
     def test_green_int_add_ovf(self):
         py.test.skip("not working yet")



More information about the Pypy-commit mailing list