Author: Armin Rigo <[email protected]>
Branch: remove-raisingops
Changeset: r83993:36d247e2bc68
Date: 2016-04-27 19:35 +0200
http://bitbucket.org/pypy/pypy/changeset/36d247e2bc68/

Log:    Revert the changes in flatten.py, and handle it by jtransform'ing
        the graphs with calls to ll_int_add_ovf to graphs with 'int_add_ovf'
        (which are then handled by flatten.py)

diff --git a/rpython/jit/codewriter/flatten.py 
b/rpython/jit/codewriter/flatten.py
--- a/rpython/jit/codewriter/flatten.py
+++ b/rpython/jit/codewriter/flatten.py
@@ -103,7 +103,7 @@
         self.seen_blocks = {}
         self.make_bytecode_block(self.graph.startblock)
 
-    def make_bytecode_block(self, block):
+    def make_bytecode_block(self, block, handling_ovf=False):
         if block.exits == ():
             self.make_return(block.inputargs)
             return
@@ -117,10 +117,15 @@
         #
         operations = block.operations
         for i, op in enumerate(operations):
-            assert '_ovf' not in op.opname   # should not exist any more
+            if '_ovf' in op.opname:
+                if (len(block.exits) not in (2, 3) or
+                    block.exitswitch is not c_last_exception):
+                    raise Exception("detected a block containing ovfcheck()"
+                                    " but no OverflowError is caught, this"
+                                    " is not legal in jitted blocks")
             self.serialize_op(op)
         #
-        self.insert_exits(block)
+        self.insert_exits(block, handling_ovf)
 
     def make_return(self, args):
         if len(args) == 1:
@@ -140,16 +145,16 @@
             raise Exception("?")
         self.emitline("---")
 
-    def make_link(self, link):
+    def make_link(self, link, handling_ovf):
         if (link.target.exits == ()
             and link.last_exception not in link.args
             and link.last_exc_value not in link.args):
             self.make_return(link.args)     # optimization only
             return
         self.insert_renamings(link)
-        self.make_bytecode_block(link.target)
+        self.make_bytecode_block(link.target, handling_ovf)
 
-    def make_exception_link(self, link):
+    def make_exception_link(self, link, handling_ovf):
         # Like make_link(), but also introduces the 'last_exception' and
         # 'last_exc_value' as variables if needed.  Also check if the link
         # is jumping directly to the re-raising exception block.
@@ -157,31 +162,52 @@
         assert link.last_exc_value is not None
         if link.target.operations == () and link.args == [link.last_exception,
                                                           link.last_exc_value]:
-            self.emitline("reraise")
+            if handling_ovf:
+                exc_data = self.cpu.rtyper.exceptiondata
+                ll_ovf = exc_data.get_standard_ll_exc_instance_by_class(
+                    OverflowError)
+                c = Constant(ll_ovf, concretetype=lltype.typeOf(ll_ovf))
+                self.emitline("raise", c)
+            else:
+                self.emitline("reraise")
             self.emitline("---")
             return   # done
-        self.make_link(link)
+        self.make_link(link, handling_ovf)
 
-    def insert_exits(self, block):
+    def insert_exits(self, block, handling_ovf=False):
         if len(block.exits) == 1:
             # A single link, fall-through
             link = block.exits[0]
             assert link.exitcase in (None, False, True)
             # the cases False or True should not really occur, but can show
             # up in the manually hacked graphs for generators...
-            self.make_link(link)
+            self.make_link(link, handling_ovf)
         #
         elif block.canraise:
             # An exception block. See test_exc_exitswitch in test_flatten.py
             # for an example of what kind of code this makes.
             index = -1
             opname = block.operations[index].opname
-            assert '_ovf' not in opname    # should not exist any more
-            while True:
-                lastopname = block.operations[index].opname
-                if lastopname != '-live-':
-                    break
-                index -= 1
+            if '_ovf' in opname:
+                # ovf checking operation as a lat thing, -live- should be
+                # one before it
+                line = self.popline()
+                self.emitline(opname[:7] + '_jump_if_ovf',
+                              TLabel(block.exits[1]), *line[1:])
+                assert len(block.exits) in (2, 3)
+                self.make_link(block.exits[0], False)
+                self.emitline(Label(block.exits[1]))
+                self.make_exception_link(block.exits[1], True)
+                if len(block.exits) == 3:
+                    assert block.exits[2].exitcase is Exception
+                    self.make_exception_link(block.exits[2], False)
+                return
+            else:
+                while True:
+                    lastopname = block.operations[index].opname
+                    if lastopname != '-live-':
+                        break
+                    index -= 1
             assert block.exits[0].exitcase is None # is this always True?
             #
             if not self._include_all_exc_links:
@@ -235,10 +261,10 @@
             #if not livebefore:
             #    self.emitline('-live-', TLabel(linkfalse))
             # true path:
-            self.make_link(linktrue)
+            self.make_link(linktrue, handling_ovf)
             # false path:
             self.emitline(Label(linkfalse))
-            self.make_link(linkfalse)
+            self.make_link(linkfalse, handling_ovf)
         #
         else:
             # A switch.
@@ -261,7 +287,7 @@
                                     switchdict)
             # emit the default path
             if block.exits[-1].exitcase == 'default':
-                self.make_link(block.exits[-1])
+                self.make_link(block.exits[-1], handling_ovf)
             else:
                 self.emitline("unreachable")
                 self.emitline("---")
@@ -275,7 +301,7 @@
                 # if the switched value doesn't match any case.
                 self.emitline(Label(switch))
                 self.emitline('-live-')
-                self.make_link(switch)
+                self.make_link(switch, handling_ovf)
 
     def insert_renamings(self, link):
         renamings = {}
diff --git a/rpython/jit/codewriter/jtransform.py 
b/rpython/jit/codewriter/jtransform.py
--- a/rpython/jit/codewriter/jtransform.py
+++ b/rpython/jit/codewriter/jtransform.py
@@ -425,6 +425,8 @@
         # dispatch to various implementations depending on the oopspec_name
         if oopspec_name.startswith('list.') or 
oopspec_name.startswith('newlist'):
             prepare = self._handle_list_call
+        elif oopspec_name.startswith('int.'):
+            prepare = self._handle_int_ovf
         elif oopspec_name.startswith('stroruni.'):
             prepare = self._handle_stroruni_call
         elif oopspec_name == 'str.str2unicode':
@@ -1900,6 +1902,14 @@
                 llmemory.cast_ptr_to_adr(c_func.value))
         self.callcontrol.callinfocollection.add(oopspecindex, calldescr, func)
 
+    def _handle_int_ovf(self, op, oopspec_name, args):
+        assert oopspec_name in ('int.add_ovf', 'int.sub_ovf', 'int.mul_ovf')
+        op0 = SpaceOperation(oopspec_name.replace('.', '_'), args, op.result)
+        if oopspec_name != 'int.sub_ovf':
+            op0 = self._rewrite_symmetric(op0)
+        oplive = SpaceOperation('-live-', [], None)
+        return [oplive, op0]
+
     def _handle_stroruni_call(self, op, oopspec_name, args):
         SoU = args[0].concretetype     # Ptr(STR) or Ptr(UNICODE)
         can_raise_memoryerror = {
diff --git a/rpython/jit/codewriter/test/test_flatten.py 
b/rpython/jit/codewriter/test/test_flatten.py
--- a/rpython/jit/codewriter/test/test_flatten.py
+++ b/rpython/jit/codewriter/test/test_flatten.py
@@ -71,6 +71,9 @@
     _descr_cannot_raise = FakeDescr()
     callinfocollection = FakeCallInfoCollection()
     def guess_call_kind(self, op):
+        if op.args[0].value._obj._name.startswith(
+                ('ll_int_add_ovf', 'll_int_sub_ovf', 'll_int_mul_ovf')):
+            return 'builtin'
         return 'residual'
     def getcalldescr(self, op, oopspecindex=EffectInfo.OS_NONE,
                      extraeffect=None, extradescr=None):
@@ -478,7 +481,7 @@
             except ZeroDivisionError:
                 return -42
         self.encoding_test(f, [7, 2], """
-            residual_call_ir_i $<* fn int_floordiv_ovf_zer>, I[%i0, %i1], R[], 
<Descr> -> %i2
+            residual_call_ir_i $<* fn ll_int_floordiv_ovf_zer__Signed_Signed>, 
I[%i0, %i1], R[], <Descr> -> %i2
             -live-
             catch_exception L1
             int_return %i2
@@ -505,7 +508,7 @@
                 return 42
         # XXX so far, this really produces a int_mod_ovf_zer...
         self.encoding_test(f, [7, 2], """
-            residual_call_ir_i $<* fn int_mod_ovf_zer>, I[%i0, %i1], R[], 
<Descr> -> %i2
+            residual_call_ir_i $<* fn ll_int_mod_ovf_zer__Signed_Signed>, 
I[%i0, %i1], R[], <Descr> -> %i2
             -live-
             catch_exception L1
             int_return %i2
@@ -548,6 +551,36 @@
             int_return $42
         """, transform=True, liveness=True)
 
+    def test_int_sub_ovf(self):
+        def f(i, j):
+            try:
+                return ovfcheck(i - j)
+            except OverflowError:
+                return 42
+        self.encoding_test(f, [7, 2], """
+            -live- %i0, %i1
+            int_sub_jump_if_ovf L1, %i0, %i1 -> %i2
+            int_return %i2
+            ---
+            L1:
+            int_return $42
+        """, transform=True, liveness=True)
+
+    def test_int_mul_ovf(self):
+        def f(i, j):
+            try:
+                return ovfcheck(i * j)
+            except OverflowError:
+                return 42
+        self.encoding_test(f, [7, 2], """
+            -live- %i0, %i1
+            int_mul_jump_if_ovf L1, %i0, %i1 -> %i2
+            int_return %i2
+            ---
+            L1:
+            int_return $42
+        """, transform=True, liveness=True)
+
     def test_multiple_int_add_ovf(self):
         def f(i, j):
             try:
diff --git a/rpython/rtyper/rint.py b/rpython/rtyper/rint.py
--- a/rpython/rtyper/rint.py
+++ b/rpython/rtyper/rint.py
@@ -378,7 +378,6 @@
 LLONG_BITS_1 = r_longlong.BITS - 1
 LLLONG_BITS_1 = r_longlonglong.BITS - 1
 INT_MIN = int(-(1 << INT_BITS_1))
-LLONG_MIN = r_longlong(-(1 << LLONG_BITS_1))
 
 
 # ---------- floordiv ----------
@@ -505,35 +504,28 @@
 
 # ---------- add, sub, mul ----------
 
[email protected]("add_ovf")
[email protected]("int.add_ovf(x, y)")
 def ll_int_add_ovf(x, y):
     r = intmask(r_uint(x) + r_uint(y))
     if r^x < 0 and r^y < 0:
         raise OverflowError("integer addition")
     return r
 
[email protected]("add_ovf")
[email protected]("int.add_ovf(x, y)")
 def ll_int_add_nonneg_ovf(x, y):     # y can be assumed >= 0
     r = intmask(r_uint(x) + r_uint(y))
     if r < x:
         raise OverflowError("integer addition")
     return r
 
[email protected]("sub_ovf")
[email protected]("int.sub_ovf(x, y)")
 def ll_int_sub_ovf(x, y):
     r = intmask(r_uint(x) - r_uint(y))
     if r^x < 0 and r^~y < 0:
         raise OverflowError("integer subtraction")
     return r
 
[email protected]("sub_ovf")
-def ll_llong_sub_ovf(x, y):
-    r = longlongmask(r_ulonglong(x) - r_ulonglong(y))
-    if r^x < 0 and r^~y < 0:
-        raise OverflowError("longlong subtraction")
-    return r
-
[email protected]("mul_ovf")
[email protected]("int.mul_ovf(a, b)")
 def ll_int_mul_ovf(a, b):
     if INT_BITS_1 < LLONG_BITS_1:
         rr = r_longlong(a) * r_longlong(b)
@@ -578,23 +570,11 @@
         raise OverflowError
     return -x
 
-def ll_llong_neg_ovf(x):
-    if jit.we_are_jitted():
-        return ll_llong_sub_ovf(0, x)
-    if x == LLONG_MIN:
-        raise OverflowError
-    return -x
-
 def ll_int_abs_ovf(x):
     if x == INT_MIN:
         raise OverflowError
     return abs(x)
 
-def ll_llong_abs_ovf(x):
-    if x == LLONG_MIN:
-        raise OverflowError
-    return abs(x)
-
 
 #Helper functions for comparisons
 
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to