[pypy-svn] r40500 - in pypy/branch/jit-virtual-world/pypy: jit/codegen jit/codegen/llgraph jit/hintannotator jit/timeshifter jit/timeshifter/test rpython rpython/lltypesystem rpython/test

arigo at codespeak.net arigo at codespeak.net
Wed Mar 14 19:48:53 CET 2007


Author: arigo
Date: Wed Mar 14 19:48:50 2007
New Revision: 40500

Modified:
   pypy/branch/jit-virtual-world/pypy/jit/codegen/llgraph/llimpl.py
   pypy/branch/jit-virtual-world/pypy/jit/codegen/llgraph/rgenop.py
   pypy/branch/jit-virtual-world/pypy/jit/codegen/model.py
   pypy/branch/jit-virtual-world/pypy/jit/hintannotator/model.py
   pypy/branch/jit-virtual-world/pypy/jit/timeshifter/hrtyper.py
   pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rtimeshift.py
   pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_timeshift.py
   pypy/branch/jit-virtual-world/pypy/jit/timeshifter/transform.py
   pypy/branch/jit-virtual-world/pypy/rpython/llinterp.py
   pypy/branch/jit-virtual-world/pypy/rpython/lltypesystem/lloperation.py
   pypy/branch/jit-virtual-world/pypy/rpython/test/test_llinterp.py
Log:
(arigo, arre, pedronis)

Support for the 'int_xyz_ovf' kind of operations in the timeshifter and
the llgraph back-end.



Modified: pypy/branch/jit-virtual-world/pypy/jit/codegen/llgraph/llimpl.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/codegen/llgraph/llimpl.py	(original)
+++ pypy/branch/jit-virtual-world/pypy/jit/codegen/llgraph/llimpl.py	Wed Mar 14 19:48:50 2007
@@ -168,6 +168,10 @@
     return to_opaque_object(erasedvar(v, block))
 
 def guess_result_type(opname, opvars):
+    if opname.endswith('_zer'):   # h
+        opname = opname[:-4]      # a
+    if opname.endswith('_ovf'):   # c
+        opname = opname[:-4]      # k
     op = getattr(llop, opname)
     need_result_type = getattr(op.fold, 'need_result_type', False)
     assert not need_result_type, ("cannot guess the result type of %r"

Modified: pypy/branch/jit-virtual-world/pypy/jit/codegen/llgraph/rgenop.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/codegen/llgraph/rgenop.py	(original)
+++ pypy/branch/jit-virtual-world/pypy/jit/codegen/llgraph/rgenop.py	Wed Mar 14 19:48:50 2007
@@ -111,12 +111,31 @@
         return LLVar(llimpl.genop(self.b, opname, [gv_arg], llimpl.guess))
 
     @specialize.arg(1)
+    def genraisingop1(self, opname, gv_arg):
+        debug_assert(self.rgenop.currently_writing is self,
+                     "genraisingop1: bad currently_writing")
+        gv_res = LLVar(llimpl.genop(self.b, opname, [gv_arg], llimpl.guess))
+        gv_exc = LLVar(llimpl.genop(self.b, "check_and_clear_exc", [],
+                                    gv_Bool.v))
+        return gv_res, gv_exc
+
+    @specialize.arg(1)
     def genop2(self, opname, gv_arg1, gv_arg2):
         debug_assert(self.rgenop.currently_writing is self,
                      "genop2: bad currently_writing")
         return LLVar(llimpl.genop(self.b, opname, [gv_arg1, gv_arg2],
                                   llimpl.guess))
 
+    @specialize.arg(1)
+    def genraisingop2(self, opname, gv_arg1, gv_arg2):
+        debug_assert(self.rgenop.currently_writing is self,
+                     "genraisingop2: bad currently_writing")
+        gv_res = LLVar(llimpl.genop(self.b, opname, [gv_arg1, gv_arg2],
+                                    llimpl.guess))
+        gv_exc = LLVar(llimpl.genop(self.b, "check_and_clear_exc", [],
+                                    gv_Bool.v))
+        return gv_res, gv_exc
+
     def genop_call(self, (ARGS_gv, gv_RESULT, _), gv_callable, args_gv):
         debug_assert(self.rgenop.currently_writing is self,
                      "genop_call: bad currently_writing")

Modified: pypy/branch/jit-virtual-world/pypy/jit/codegen/model.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/codegen/model.py	(original)
+++ pypy/branch/jit-virtual-world/pypy/jit/codegen/model.py	Wed Mar 14 19:48:50 2007
@@ -65,6 +65,14 @@
 ##     @specialize.arg(1)
 ##     def genop2(self, opname, gv_arg1, gv_arg2):
 
+##     @specialize.arg(1)
+##     def genraisingop1(self, opname, gv_arg):
+##         return a pair (gv_result, gv_flag_set_if_exception)
+
+##     @specialize.arg(1)
+##     def genraisingop2(self, opname, gv_arg1, gv_arg2):
+##         return a pair (gv_result, gv_flag_set_if_exception)
+
 ##     def genop_getfield(self, fieldtoken, gv_ptr):
 ##     def genop_setfield(self, fieldtoken, gv_ptr, gv_value):
 ##     def genop_getsubstruct(self, fieldtoken, gv_ptr):
@@ -402,9 +410,17 @@
         return dummy_var
 
     @specialize.arg(1)
+    def genraisingop1(self, opname, gv_arg):
+        return dummy_var, dummy_var
+
+    @specialize.arg(1)
     def genop2(self, opname, gv_arg1, gv_arg2):
         return dummy_var
 
+    @specialize.arg(1)
+    def genraisingop2(self, opname, gv_arg1, gv_arg2):
+        return dummy_var, dummy_var
+
     def genop_ptr_iszero(self, kind, gv_ptr):
         return dummy_var
 

Modified: pypy/branch/jit-virtual-world/pypy/jit/hintannotator/model.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/hintannotator/model.py	(original)
+++ pypy/branch/jit-virtual-world/pypy/jit/hintannotator/model.py	Wed Mar 14 19:48:50 2007
@@ -7,7 +7,8 @@
                       cast_pointer
                       direct_call
                       indirect_call
-                      int_is_true int_neg int_invert bool_not
+                      int_is_true int_neg int_abs int_invert bool_not
+                      int_neg_ovf int_abs_ovf
                       uint_is_true
                       cast_int_to_char
                       cast_int_to_uint
@@ -20,6 +21,8 @@
 
 BINARY_OPERATIONS = """int_add int_sub int_mul int_mod int_and int_rshift
                        int_lshift int_floordiv int_xor int_or
+                       int_add_ovf int_sub_ovf int_mul_ovf int_mod_ovf
+                       int_floordiv_ovf int_lshift_ovf
                        uint_add uint_sub uint_mul uint_mod uint_and
                        uint_lshift uint_rshift uint_floordiv
                        char_gt char_lt char_le char_ge char_eq char_ne
@@ -730,10 +733,10 @@
 def setup(oplist, ValueCls, var_fn, ConstantCls, const_fn):
     for name in oplist:
         llop = getattr(lloperation.llop, name)
-        if not llop.sideeffects:
+        if not llop.sideeffects or llop.tryfold:
             if name not in ValueCls.__dict__:
                 setattr(ValueCls, name, var_fn)
-            if llop.canfold:
+            if llop.canfold or llop.tryfold:
                 if name not in ConstantCls.__dict__:
                     setattr(ConstantCls, name, const_fn)
 setup(UNARY_OPERATIONS,

Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/hrtyper.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/hrtyper.py	(original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/hrtyper.py	Wed Mar 14 19:48:50 2007
@@ -21,7 +21,6 @@
 from pypy.jit.hintannotator import container as hintcontainer
 from pypy.jit.hintannotator.model import originalconcretetype
 from pypy.jit.timeshifter import rtimeshift, rvalue, rcontainer, oop
-from pypy.jit.timeshifter.transform import HintGraphTransformer
 from pypy.jit.timeshifter.exception import ExceptionDesc
 from pypy.jit.codegen import model as cgmodel
 
@@ -404,6 +403,7 @@
     def timeshift_cflow(self, graph, is_portal=False):
         # prepare the graphs by inserting all bookkeeping/dispatching logic
         # as special operations
+        from pypy.jit.timeshifter.transform import HintGraphTransformer
         assert graph.startblock in self.annotator.annotated
         transformer = HintGraphTransformer(self.annotator, graph,
                                            is_portal=is_portal)
@@ -1040,7 +1040,8 @@
                                               self.s_ConstOrVar)
 
     def translate_op_split(self, hop, splitfn=rtimeshift.split,
-                                      reverse=False):
+                                      reverse=False,
+                                      s_result=annmodel.s_Bool):
         if splitfn is rtimeshift.split:
             nb_fixed_args = 2
         else:
@@ -1049,7 +1050,10 @@
         r_switch = self.getredrepr(lltype.Bool)
         GREENS = [v.concretetype for v in hop.args_v[nb_fixed_args:]]
         extra_r = [self.getgreenrepr(TYPE) for TYPE in GREENS]
-        if splitfn is not rtimeshift.split:
+        if splitfn is rtimeshift.split_raisingop:
+            r_switch = lltype.Void
+            extra_r.insert(0, lltype.Void)
+        elif splitfn is not rtimeshift.split:
             TYPE = originalconcretetype(hop.args_s[2])
             r_ptrbox = self.getredrepr(TYPE)
             extra_r.insert(0, r_ptrbox)
@@ -1065,7 +1069,20 @@
         args_s = [self.s_JITState, self.s_RedBox, s_Int]
         args_v = [v_jitstate, v_switch, c_resumepoint]
 
-        if splitfn is not rtimeshift.split:
+        if splitfn is rtimeshift.split_raisingop:
+            bk = self.rtyper.annotator.bookkeeper
+            excclass = vlist[2].value
+            exccdef = bk.getuniqueclassdef(excclass)
+            ll_exc = self.rtyper.exceptiondata.get_standard_ll_exc_instance(
+                self.rtyper, exccdef)
+            LL_EXC = lltype.typeOf(ll_exc)
+            c_excinstance = hop.inputconst(LL_EXC, ll_exc)
+            s_excinstance = annmodel.lltype_to_annotation(LL_EXC)
+            del args_s[1]    # no v_switch in this case
+            del args_v[1]
+            args_s += [s_excinstance]
+            args_v += [c_excinstance]
+        elif splitfn is not rtimeshift.split:
             v_ptrbox = vlist[2]
             c_reverse = hop.inputconst(lltype.Bool, reverse)
             args_s += [self.s_PtrRedBox,                 annmodel.s_Bool]
@@ -1075,7 +1092,7 @@
         args_v += greens_v
         return hop.llops.genmixlevelhelpercall(splitfn,
                                                args_s, args_v,
-                                               annmodel.SomeBool())
+                                               s_result)
 
     def translate_op_split_ptr_nonzero(self, hop):
         return self.translate_op_split(hop, rtimeshift.split_ptr_nonzero,
@@ -1085,6 +1102,10 @@
         return self.translate_op_split(hop, rtimeshift.split_ptr_nonzero,
                                             reverse=True)
 
+    def translate_op_split_raisingop(self, hop):
+        self.translate_op_split(hop, rtimeshift.split_raisingop,
+                                s_result=annmodel.s_None)
+
     def translate_op_collect_split(self, hop):
         GREENS = [v.concretetype for v in hop.args_v[1:]]
         greens_r = [self.getgreenrepr(TYPE) for TYPE in GREENS]

Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rtimeshift.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rtimeshift.py	(original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/rtimeshift.py	Wed Mar 14 19:48:50 2007
@@ -8,12 +8,12 @@
 from pypy.rpython.annlowlevel import cast_instance_to_base_ptr
 from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
 
-FOLDABLE_OPS = dict.fromkeys(lloperation.enum_foldable_ops())
-
-FOLDABLE_GREEN_OPS = FOLDABLE_OPS.copy()
+FOLDABLE_GREEN_OPS = dict.fromkeys(lloperation.enum_foldable_ops())
 FOLDABLE_GREEN_OPS['getfield'] = None
 FOLDABLE_GREEN_OPS['getarrayitem'] = None
 
+NULL_OBJECT = base_ptr_lltype()._defl()
+
 debug_view = lloperation.llop.debug_view
 debug_print = lloperation.llop.debug_print
 debug_pdb = lloperation.llop.debug_pdb
@@ -28,7 +28,8 @@
     that can be passed around to low level helpers
     to inform op generation
     """
-    
+    canraise = False
+
     def _freeze_(self):
         return True
 
@@ -40,8 +41,14 @@
         self.ARGS = ARGS
         self.RESULT = RESULT
         self.result_kind = RGenOp.kindToken(RESULT)
+        self.whatever_result = RESULT._defl()
         self.redboxcls = rvalue.ll_redboxcls(RESULT)
-        self.canfold = opname in FOLDABLE_OPS
+        self.canfold = self.llop.canfold
+        self.tryfold = self.llop.tryfold
+        if self.tryfold and self.llop.canraise:
+            self.canraise = True
+            self.gv_True  = RGenOp.constPrebuiltGlobal(True)
+            self.gv_False = RGenOp.constPrebuiltGlobal(False)
 
     def __getattr__(self, name): # .ARGx -> .ARGS[x]
         if name.startswith('ARG'):
@@ -71,12 +78,27 @@
     ARG0 = opdesc.ARG0
     RESULT = opdesc.RESULT
     opname = opdesc.name
-    if opdesc.canfold and argbox.is_constant():
+    if opdesc.tryfold and argbox.is_constant():
         arg = rvalue.ll_getvalue(argbox, ARG0)
-        res = opdesc.llop(RESULT, arg)
+        if not opdesc.canraise:
+            res = opdesc.llop(RESULT, arg)
+        else:
+            try:
+                res = opdesc.llop(RESULT, arg)
+            except Exception:   # shouldn't raise anything unexpected
+                res = opdesc.whatever_result
+                gv_flag = opdesc.gv_True
+            else:
+                gv_flag = opdesc.gv_False
+            jitstate.greens.append(gv_flag)
         return rvalue.ll_fromvalue(jitstate, res)
     gv_arg = argbox.getgenvar(jitstate)
-    genvar = jitstate.curbuilder.genop1(opdesc.opname, gv_arg)
+    if not opdesc.canraise:
+        genvar = jitstate.curbuilder.genop1(opdesc.opname, gv_arg)
+    else:
+        genvar, gv_raised = jitstate.curbuilder.genraisingop1(opdesc.opname,
+                                                              gv_arg)
+        jitstate.greens.append(gv_raised)    # for split_raisingop()
     return opdesc.redboxcls(opdesc.result_kind, genvar)
 
 def ll_gen2(opdesc, jitstate, argbox0, argbox1):
@@ -84,15 +106,30 @@
     ARG1 = opdesc.ARG1
     RESULT = opdesc.RESULT
     opname = opdesc.name
-    if opdesc.canfold and argbox0.is_constant() and argbox1.is_constant():
+    if opdesc.tryfold and argbox0.is_constant() and argbox1.is_constant():
         # const propagate
         arg0 = rvalue.ll_getvalue(argbox0, ARG0)
         arg1 = rvalue.ll_getvalue(argbox1, ARG1)
-        res = opdesc.llop(RESULT, arg0, arg1)
+        if not opdesc.canraise:
+            res = opdesc.llop(RESULT, arg0, arg1)
+        else:
+            try:
+                res = opdesc.llop(RESULT, arg0, arg1)
+            except Exception:   # shouldn't raise anything unexpected
+                res = opdesc.whatever_result
+                gv_flag = opdesc.gv_True
+            else:
+                gv_flag = opdesc.gv_False
+            jitstate.greens.append(gv_flag)
         return rvalue.ll_fromvalue(jitstate, res)
     gv_arg0 = argbox0.getgenvar(jitstate)
     gv_arg1 = argbox1.getgenvar(jitstate)
-    genvar = jitstate.curbuilder.genop2(opdesc.opname, gv_arg0, gv_arg1)
+    if not opdesc.canraise:
+        genvar = jitstate.curbuilder.genop2(opdesc.opname, gv_arg0, gv_arg1)
+    else:
+        genvar, gv_raised = jitstate.curbuilder.genraisingop2(opdesc.opname,
+                                                              gv_arg0, gv_arg1)
+        jitstate.greens.append(gv_raised)    # for split_raisingop()
     return opdesc.redboxcls(opdesc.result_kind, genvar)
 
 def ll_genmalloc_varsize(jitstate, contdesc, sizebox):
@@ -343,7 +380,7 @@
                                      ptrbox, reverse, list(greens_gv))
 
 def split_nonconstantcase(jitstate, exitgvar, resumepoint,
-                          ptrbox, reverse, greens_gv):
+                          ptrbox, reverse, greens_gv, ll_evalue=NULL_OBJECT):
     resuming = jitstate.get_resuming()
     if resuming is not None and resuming.mergesleft == 0:
         node = resuming.path.pop()
@@ -352,8 +389,11 @@
             ptrbox.learn_nonzeroness(jitstate,
                                      nonzeroness = node.answer ^ reverse)
         return node.answer
-    false_gv = jitstate.get_locals_gv() # alive gvs on the false path
-    later_builder = jitstate.curbuilder.jump_if_false(exitgvar, false_gv)
+    later_gv = jitstate.get_locals_gv() # alive gvs on the later path
+    if ll_evalue:    # special case - we want jump_if_true in split_raisingop
+        later_builder = jitstate.curbuilder.jump_if_true(exitgvar, later_gv)
+    else:
+        later_builder = jitstate.curbuilder.jump_if_false(exitgvar, later_gv)
     memo = rvalue.copy_memo()
     jitstate2 = jitstate.split(later_builder, resumepoint, greens_gv, memo)
     if ptrbox is not None:
@@ -364,12 +404,25 @@
             pass
         else:
             copybox.learn_nonzeroness(jitstate2, nonzeroness = reverse)
+    if ll_evalue:
+        jitstate2.residual_ll_exception(ll_evalue)
     if resuming is None:
         node = jitstate.promotion_path
         jitstate2.promotion_path = PromotionPathNo(node)
         jitstate .promotion_path = PromotionPathYes(node)
     return True
 
+def split_raisingop(jitstate, resumepoint, ll_evalue, *greens_gv):
+    exitgvar = jitstate.greens.pop()   # pushed here by the raising op
+    if exitgvar.is_const:
+        gotexc = exitgvar.revealconst(lltype.Bool)
+    else:
+        gotexc = not split_nonconstantcase(jitstate, exitgvar, resumepoint,
+                                           None, False, list(greens_gv),
+                                           ll_evalue)
+    if gotexc:
+        jitstate.residual_ll_exception(ll_evalue)
+
 def collect_split(jitstate_chain, resumepoint, *greens_gv):
     # YYY split to avoid over-specialization
     # assumes that the head of the jitstate_chain is ready for writing,

Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_timeshift.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_timeshift.py	(original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/test/test_timeshift.py	Wed Mar 14 19:48:50 2007
@@ -1,4 +1,5 @@
 import py
+import sys
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.jit.hintannotator.annotator import HintAnnotator, HintAnnotatorPolicy
 from pypy.jit.hintannotator.annotator import StopAtXPolicy
@@ -10,6 +11,7 @@
 from pypy.rpython.lltypesystem import lltype, llmemory, rstr
 from pypy.rlib.objectmodel import hint, keepalive_until_here, debug_assert
 from pypy.rlib.unroll import unrolling_iterable
+from pypy.rlib.rarithmetic import ovfcheck
 from pypy.rpython.annlowlevel import PseudoHighLevelCallable
 from pypy.rpython.module.support import LLSupport
 from pypy.annotation import model as annmodel
@@ -1496,3 +1498,33 @@
         res = self.timeshift(f, [4, 113], [], policy=P)
         assert res == f(4,113)
         self.check_insns({})
+
+    def test_red_int_add_ovf(self):
+        def f(n, m):
+            try:
+                return ovfcheck(n + m)
+            except OverflowError:
+                return -42
+
+        res = self.timeshift(f, [100, 20])
+        assert res == 120
+        self.check_insns(int_add_ovf=1)
+        res = self.timeshift(f, [sys.maxint, 1])
+        assert res == -42
+        self.check_insns(int_add_ovf=1)
+
+    def test_green_int_add_ovf(self):
+        def f(n, m):
+            try:
+                res = ovfcheck(n + m)
+            except OverflowError:
+                res = -42
+            hint(res, concrete=True)
+            return res
+
+        res = self.timeshift(f, [100, 20])
+        assert res == 120
+        self.check_insns({})
+        res = self.timeshift(f, [sys.maxint, 1])
+        assert res == -42
+        self.check_insns({})

Modified: pypy/branch/jit-virtual-world/pypy/jit/timeshifter/transform.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/jit/timeshifter/transform.py	(original)
+++ pypy/branch/jit-virtual-world/pypy/jit/timeshifter/transform.py	Wed Mar 14 19:48:50 2007
@@ -3,7 +3,7 @@
 from pypy.annotation        import model as annmodel
 from pypy.jit.hintannotator import model as hintmodel
 from pypy.jit.hintannotator.model import originalconcretetype
-from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.lltypesystem import lltype, llmemory, lloperation
 from pypy.rpython.rmodel import inputconst
 from pypy.translator.unsimplify import varoftype, copyvar
 from pypy.translator.unsimplify import split_block, split_block_at_start
@@ -59,6 +59,7 @@
         self.insert_save_return()
         self.insert_splits()
         self.split_after_calls()
+        self.split_after_raisingop()
         self.handle_hints()
         self.insert_merge_points()
         self.insert_enter_frame()
@@ -847,6 +848,43 @@
             link_f.exitcase = False
             block.recloseblock(link_f, link_t)
 
+    # __________ raising ops (xxx_ovf & co) __________
+
+    def split_after_raisingop(self):
+        for block in list(self.graph.iterblocks()):
+            for i in range(len(block.operations)-1, -1, -1):
+                op = block.operations[i]
+                try:
+                    opdesc = getattr(lloperation.llop, op.opname)
+                except AttributeError:
+                    continue
+                if opdesc.tryfold and not opdesc.canfold and opdesc.canraise:
+                    self.handle_raisingop(block, i, opdesc)
+
+    def handle_raisingop(self, block, i, opdesc):
+        op = block.operations[i]
+        if self.hannotator.binding(op.result).is_green():
+            # case not really well supported
+            v_red = Variable(op.result)
+            v_red.concretetype = op.result.concretetype
+            hs_red = hintmodel.SomeLLAbstractVariable(op.result.concretetype)
+            self.hannotator.setbinding(v_red, hs_red)
+            spaceop = SpaceOperation('revealconst', [v_red], op.result)
+            op.result = v_red
+            i += 1
+            block.operations.insert(i, spaceop)
+
+        link = split_block(self.hannotator, block, i+1)
+
+        reds, greens = self.sort_by_color(link.args)
+        self.genop(block, 'save_locals', reds)
+        resumepoint = self.get_resume_point(link.target)
+        c_resumepoint = inputconst(lltype.Signed, resumepoint)
+
+        assert len(opdesc.canraise) == 1    # for now
+        c_canraise = inputconst(lltype.Void, opdesc.canraise[0])
+        self.genop(block, 'split_raisingop',
+                   [self.c_dummy, c_resumepoint, c_canraise] + greens)
 
     # __________ hints __________
 

Modified: pypy/branch/jit-virtual-world/pypy/rpython/llinterp.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/rpython/llinterp.py	(original)
+++ pypy/branch/jit-virtual-world/pypy/rpython/llinterp.py	Wed Mar 14 19:48:50 2007
@@ -382,7 +382,21 @@
                                 break
                         else:
                             raise TypeError("the operation %s is not expected to raise %s" % (operation, exc))
-                raise
+
+                # for exception-transformed graphs, store the LLException
+                # into the exc_data used by this graph
+                exc_data = self.llinterpreter.get_transformed_exc_data(
+                    self.graph)
+                if exc_data:
+                    etype = e.args[0]
+                    evalue = e.args[1]
+                    exc_data.exc_type  = etype
+                    exc_data.exc_value = evalue
+                    from pypy.translator.c import exceptiontransform
+                    retval = exceptiontransform.error_value(
+                        operation.result.concretetype)
+                else:
+                    raise
         self.setvar(operation.result, retval)
         if tracer:
             if retval is None:
@@ -557,19 +571,7 @@
 
     def op_direct_call(self, f, *args):
         FTYPE = self.llinterpreter.typer.type_system.derefType(lltype.typeOf(f))
-        try:
-            return self.perform_call(f, FTYPE.ARGS, args)
-        except LLException, e:
-            exc_data = self.llinterpreter.get_transformed_exc_data(self.graph)
-            if exc_data:
-                # store the LLException into the exc_data used by this graph
-                etype = e.args[0]
-                evalue = e.args[1]
-                exc_data.exc_type  = etype
-                exc_data.exc_value = evalue
-                from pypy.translator.c import exceptiontransform
-                return exceptiontransform.error_value(FTYPE.RESULT)
-            raise
+        return self.perform_call(f, FTYPE.ARGS, args)
 
     def op_indirect_call(self, f, *args):
         graphs = args[-1]
@@ -878,7 +880,18 @@
     def op_frame_info(self, *vars):
         pass
     op_frame_info.specialform = True
- 
+
+    # hack for jit.codegen.llgraph
+
+    def op_check_and_clear_exc(self):
+        exc_data = self.llinterpreter.get_transformed_exc_data(self.graph)
+        assert exc_data
+        etype  = exc_data.exc_type
+        evalue = exc_data.exc_value
+        exc_data.exc_type  = lltype.typeOf(etype )._defl()
+        exc_data.exc_value = lltype.typeOf(evalue)._defl()
+        return bool(etype)
+
     #Operation of ootype
 
     def op_new(self, INST):

Modified: pypy/branch/jit-virtual-world/pypy/rpython/lltypesystem/lloperation.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/rpython/lltypesystem/lloperation.py	(original)
+++ pypy/branch/jit-virtual-world/pypy/rpython/lltypesystem/lloperation.py	Wed Mar 14 19:48:50 2007
@@ -9,7 +9,8 @@
 class LLOp(object):
 
     def __init__(self, sideeffects=True, canfold=False, canraise=(),
-                 pyobj=False, canunwindgc=False, canrun=False, oo=False):
+                 pyobj=False, canunwindgc=False, canrun=False, oo=False,
+                 tryfold=False):
         # self.opname = ... (set afterwards)
 
         if canfold:
@@ -23,6 +24,9 @@
         #  and always gives the same result for given args
         self.canfold = canfold
 
+        # Can *try* to fold the operation, but it may raise on you
+        self.tryfold = tryfold or canfold
+
         # Exceptions that can be raised
         self.canraise = canraise
         assert isinstance(canraise, tuple)
@@ -96,12 +100,12 @@
             if not opdesc.canraise or raising_is_ok:
                 yield opname
 
-def enum_foldable_ops(raising_is_ok=False):
+def enum_foldable_ops(_ignored=None):
     """Enumerate operations that can be constant-folded."""
     for opname, opdesc in LL_OPERATIONS.iteritems():
         if opdesc.canfold:
-            if not opdesc.canraise or raising_is_ok:
-                yield opname
+            assert not opdesc.canraise
+            yield opname
 
 
 class Entry(ExtRegistryEntry):
@@ -154,18 +158,18 @@
 
     'int_is_true':          LLOp(canfold=True),
     'int_neg':              LLOp(canfold=True),
-    'int_neg_ovf':          LLOp(canraise=(OverflowError,)),
+    'int_neg_ovf':          LLOp(canraise=(OverflowError,), tryfold=True),
     'int_abs':              LLOp(canfold=True),
-    'int_abs_ovf':          LLOp(canraise=(OverflowError,)),
+    'int_abs_ovf':          LLOp(canraise=(OverflowError,), tryfold=True),
     'int_invert':           LLOp(canfold=True),
 
     'int_add':              LLOp(canfold=True),
     'int_sub':              LLOp(canfold=True),
     'int_mul':              LLOp(canfold=True),
     'int_floordiv':         LLOp(canfold=True),
-    'int_floordiv_zer':     LLOp(canraise=(ZeroDivisionError,)),
+    'int_floordiv_zer':     LLOp(canraise=(ZeroDivisionError,), tryfold=True),
     'int_mod':              LLOp(canfold=True),
-    'int_mod_zer':          LLOp(canraise=(ZeroDivisionError,)),
+    'int_mod_zer':          LLOp(canraise=(ZeroDivisionError,), tryfold=True),
     'int_lt':               LLOp(canfold=True),
     'int_le':               LLOp(canfold=True),
     'int_eq':               LLOp(canfold=True),
@@ -175,20 +179,23 @@
     'int_and':              LLOp(canfold=True),
     'int_or':               LLOp(canfold=True),
     'int_lshift':           LLOp(canfold=True),
-    'int_lshift_val':       LLOp(canraise=(ValueError,)),
+    'int_lshift_val':       LLOp(canraise=(ValueError,), tryfold=True),
     'int_rshift':           LLOp(canfold=True),
-    'int_rshift_val':       LLOp(canraise=(ValueError,)),
+    'int_rshift_val':       LLOp(canraise=(ValueError,), tryfold=True),
     'int_xor':              LLOp(canfold=True),
 
-    'int_add_ovf':          LLOp(canraise=(OverflowError,)),
-    'int_sub_ovf':          LLOp(canraise=(OverflowError,)),
-    'int_mul_ovf':          LLOp(canraise=(OverflowError,)),
-    'int_floordiv_ovf':     LLOp(canraise=(OverflowError,)),
-    'int_floordiv_ovf_zer': LLOp(canraise=(OverflowError, ZeroDivisionError)),
-    'int_mod_ovf':          LLOp(canraise=(OverflowError,)),
-    'int_mod_ovf_zer':      LLOp(canraise=(OverflowError, ZeroDivisionError)),
-    'int_lshift_ovf':       LLOp(canraise=(OverflowError,)),
-    'int_lshift_ovf_val':   LLOp(canraise=(OverflowError, ValueError,)),
+    'int_add_ovf':          LLOp(canraise=(OverflowError,), tryfold=True),
+    'int_sub_ovf':          LLOp(canraise=(OverflowError,), tryfold=True),
+    'int_mul_ovf':          LLOp(canraise=(OverflowError,), tryfold=True),
+    'int_floordiv_ovf':     LLOp(canraise=(OverflowError,), tryfold=True),
+    'int_floordiv_ovf_zer': LLOp(canraise=(OverflowError, ZeroDivisionError),
+                                                            tryfold=True),
+    'int_mod_ovf':          LLOp(canraise=(OverflowError,), tryfold=True),
+    'int_mod_ovf_zer':      LLOp(canraise=(OverflowError, ZeroDivisionError),
+                                                            tryfold=True),
+    'int_lshift_ovf':       LLOp(canraise=(OverflowError,), tryfold=True),
+    'int_lshift_ovf_val':   LLOp(canraise=(OverflowError, ValueError,),
+                                                            tryfold=True),
 
     'uint_is_true':         LLOp(canfold=True),
     'uint_invert':          LLOp(canfold=True),
@@ -197,9 +204,9 @@
     'uint_sub':             LLOp(canfold=True),
     'uint_mul':             LLOp(canfold=True),
     'uint_floordiv':        LLOp(canfold=True),
-    'uint_floordiv_zer':    LLOp(canraise=(ZeroDivisionError,)),
+    'uint_floordiv_zer':    LLOp(canraise=(ZeroDivisionError,), tryfold=True),
     'uint_mod':             LLOp(canfold=True),
-    'uint_mod_zer':         LLOp(canraise=(ZeroDivisionError,)),
+    'uint_mod_zer':         LLOp(canraise=(ZeroDivisionError,), tryfold=True),
     'uint_lt':              LLOp(canfold=True),
     'uint_le':              LLOp(canfold=True),
     'uint_eq':              LLOp(canfold=True),
@@ -209,9 +216,9 @@
     'uint_and':             LLOp(canfold=True),
     'uint_or':              LLOp(canfold=True),
     'uint_lshift':          LLOp(canfold=True),
-    'uint_lshift_val':      LLOp(canraise=(ValueError,)),
+    'uint_lshift_val':      LLOp(canraise=(ValueError,), tryfold=True),
     'uint_rshift':          LLOp(canfold=True),
-    'uint_rshift_val':      LLOp(canraise=(ValueError,)),
+    'uint_rshift_val':      LLOp(canraise=(ValueError,), tryfold=True),
     'uint_xor':             LLOp(canfold=True),
 
     'float_is_true':        LLOp(canfold=True),
@@ -232,18 +239,18 @@
 
     'llong_is_true':        LLOp(canfold=True),
     'llong_neg':            LLOp(canfold=True),
-    'llong_neg_ovf':        LLOp(canraise=(OverflowError,)),
+    'llong_neg_ovf':        LLOp(canraise=(OverflowError,), tryfold=True),
     'llong_abs':            LLOp(canfold=True),
-    'llong_abs_ovf':        LLOp(canraise=(OverflowError,)),    
+    'llong_abs_ovf':        LLOp(canraise=(OverflowError,), tryfold=True),
     'llong_invert':         LLOp(canfold=True),
 
     'llong_add':            LLOp(canfold=True),
     'llong_sub':            LLOp(canfold=True),
     'llong_mul':            LLOp(canfold=True),
     'llong_floordiv':       LLOp(canfold=True),
-    'llong_floordiv_zer':   LLOp(canraise=(ZeroDivisionError,)),
+    'llong_floordiv_zer':   LLOp(canraise=(ZeroDivisionError,), tryfold=True),
     'llong_mod':            LLOp(canfold=True),
-    'llong_mod_zer':        LLOp(canraise=(ZeroDivisionError,)),
+    'llong_mod_zer':        LLOp(canraise=(ZeroDivisionError,), tryfold=True),
     'llong_lt':             LLOp(canfold=True),
     'llong_le':             LLOp(canfold=True),
     'llong_eq':             LLOp(canfold=True),
@@ -253,9 +260,9 @@
     'llong_and':            LLOp(canfold=True),
     'llong_or':             LLOp(canfold=True),
     'llong_lshift':         LLOp(canfold=True),
-    'llong_lshift_val':     LLOp(canraise=(ValueError,)),
+    'llong_lshift_val':     LLOp(canraise=(ValueError,), tryfold=True),
     'llong_rshift':         LLOp(canfold=True),
-    'llong_rshift_val':     LLOp(canraise=(ValueError,)),
+    'llong_rshift_val':     LLOp(canraise=(ValueError,), tryfold=True),
     'llong_xor':            LLOp(canfold=True),
 
     'ullong_is_true':       LLOp(canfold=True),
@@ -265,9 +272,9 @@
     'ullong_sub':           LLOp(canfold=True),
     'ullong_mul':           LLOp(canfold=True),
     'ullong_floordiv':      LLOp(canfold=True),
-    'ullong_floordiv_zer':  LLOp(canraise=(ZeroDivisionError,)),
+    'ullong_floordiv_zer':  LLOp(canraise=(ZeroDivisionError,), tryfold=True),
     'ullong_mod':           LLOp(canfold=True),
-    'ullong_mod_zer':       LLOp(canraise=(ZeroDivisionError,)),
+    'ullong_mod_zer':       LLOp(canraise=(ZeroDivisionError,), tryfold=True),
     'ullong_lt':            LLOp(canfold=True),
     'ullong_le':            LLOp(canfold=True),
     'ullong_eq':            LLOp(canfold=True),
@@ -277,9 +284,9 @@
     'ullong_and':           LLOp(canfold=True),
     'ullong_or':            LLOp(canfold=True),
     'ullong_lshift':        LLOp(canfold=True),
-    'ullong_lshift_val':    LLOp(canraise=(ValueError,)),
+    'ullong_lshift_val':    LLOp(canraise=(ValueError,), tryfold=True),
     'ullong_rshift':        LLOp(canfold=True),
-    'ullong_rshift_val':    LLOp(canraise=(ValueError,)),
+    'ullong_rshift_val':    LLOp(canraise=(ValueError,), tryfold=True),
     'ullong_xor':           LLOp(canfold=True),
 
     'cast_primitive':       LLOp(canfold=True),
@@ -295,8 +302,8 @@
     'cast_int_to_longlong': LLOp(canfold=True),
     'cast_uint_to_int':     LLOp(canfold=True),
     'cast_uint_to_float':   LLOp(canfold=True),
-    'cast_float_to_int':    LLOp(canraise=(OverflowError,)),
-    'cast_float_to_uint':   LLOp(canfold=True),
+    'cast_float_to_int':    LLOp(canraise=(OverflowError,), tryfold=True),
+    'cast_float_to_uint':   LLOp(canraise=(OverflowError,), tryfold=True),
     'truncate_longlong_to_int':LLOp(canfold=True),
 
     # __________ pointer operations __________
@@ -410,7 +417,7 @@
     'debug_view':           LLOp(),
     'debug_print':          LLOp(),
     'debug_pdb':            LLOp(),
-    'debug_assert':         LLOp(),
+    'debug_assert':         LLOp(tryfold=True),
     'debug_fatalerror':     LLOp(),
 
     # __________ instrumentation _________

Modified: pypy/branch/jit-virtual-world/pypy/rpython/test/test_llinterp.py
==============================================================================
--- pypy/branch/jit-virtual-world/pypy/rpython/test/test_llinterp.py	(original)
+++ pypy/branch/jit-virtual-world/pypy/rpython/test/test_llinterp.py	Wed Mar 14 19:48:50 2007
@@ -1,4 +1,5 @@
 import py
+import sys
 from pypy.rpython.lltypesystem.lltype import typeOf, pyobjectptr, Ptr, PyObject, Void
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.llinterp import LLInterpreter, LLException, log
@@ -563,3 +564,22 @@
     assert res == 6
     res = interp.eval_graph(graph, [3, -9831])
     assert res == 7
+
+def test_exceptiontransformed_add_ovf():
+    from pypy.translator.c import exceptiontransform
+    def f(x, y):
+        try:
+            return ovfcheck(x + y)
+        except OverflowError:
+            return -42
+    t = TranslationContext()
+    t.buildannotator().build_types(f, [int, int])
+    t.buildrtyper().specialize()
+    etrafo = exceptiontransform.ExceptionTransformer(t)
+    graph = graphof(t, f)
+    etrafo.create_exception_handling(graph)
+    interp = LLInterpreter(t.rtyper)
+    res = interp.eval_graph(graph, [1, -64])
+    assert res == -63
+    res = interp.eval_graph(graph, [1, sys.maxint])
+    assert res == -42



More information about the Pypy-commit mailing list