[pypy-commit] pypy default: Issue #2015 second attempt: don't put 'call_pure' in short preamble, not

arigo noreply at buildbot.pypy.org
Fri Apr 3 17:02:07 CEST 2015


Author: Armin Rigo <arigo at tunes.org>
Branch: 
Changeset: r76701:56eebe9dd813
Date: 2015-04-03 15:28 +0200
http://bitbucket.org/pypy/pypy/changeset/56eebe9dd813/

Log:	Issue #2015 second attempt: don't put 'call_pure' in short preamble,
	not at all, if they can raise. I *think* the issue is that an
	exception that we'd get then would be propagated outside, uncaught.

diff --git a/rpython/jit/metainterp/optimizeopt/pure.py b/rpython/jit/metainterp/optimizeopt/pure.py
--- a/rpython/jit/metainterp/optimizeopt/pure.py
+++ b/rpython/jit/metainterp/optimizeopt/pure.py
@@ -80,7 +80,13 @@
         args = op.getarglist()
         self.emit_operation(ResOperation(rop.CALL, args, op.result,
                                          op.getdescr()))
-        self.call_pure_positions.append(len(self.optimizer._newoperations) - 1)
+
+        # don't move call_pure_with_exception in the short preamble...
+        # issue #2015
+        effectinfo = op.getdescr().get_extra_info()
+        if not effectinfo.check_can_raise():
+            self.call_pure_positions.append(
+                len(self.optimizer._newoperations) - 1)
 
     def optimize_GUARD_NO_EXCEPTION(self, op):
         if self.last_emitted_operation is REMOVED:
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -3605,7 +3605,7 @@
         ops = '''
         [p1, i1, i4]
         setfield_gc(p1, i1, descr=valuedescr)
-        i3 = call_pure(p1, descr=plaincalldescr)
+        i3 = call_pure(p1, descr=cannotraisecalldescr)
         setfield_gc(p1, i3, descr=valuedescr)
         jump(p1, i4, i3)
         '''
@@ -3617,7 +3617,7 @@
         preamble = '''
         [p1, i1, i4]
         setfield_gc(p1, i1, descr=valuedescr)
-        i3 = call(p1, descr=plaincalldescr)
+        i3 = call(p1, descr=cannotraisecalldescr)
         setfield_gc(p1, i3, descr=valuedescr)
         i148 = same_as(i3)
         i147 = same_as(i3)
@@ -3630,7 +3630,7 @@
         ops = '''
         [p1, i1, i4]
         setfield_gc(p1, i1, descr=valuedescr)
-        i3 = call_pure(p1, descr=plaincalldescr)
+        i3 = call_pure(p1, descr=cannotraisecalldescr)
         setfield_gc(p1, i1, descr=valuedescr)
         jump(p1, i4, i3)
         '''
@@ -3642,7 +3642,7 @@
         preamble = '''
         [p1, i1, i4]
         setfield_gc(p1, i1, descr=valuedescr)
-        i3 = call(p1, descr=plaincalldescr)
+        i3 = call(p1, descr=cannotraisecalldescr)
         setfield_gc(p1, i1, descr=valuedescr)
         i151 = same_as(i3)
         jump(p1, i4, i3, i151)
@@ -3656,15 +3656,15 @@
         [i0, i1, i2]
         escape(i1)
         escape(i2)
-        i3 = call_pure(123456, 4, 5, 6, descr=plaincalldescr)
-        i4 = call_pure(123456, 4, i0, 6, descr=plaincalldescr)
+        i3 = call_pure(123456, 4, 5, 6, descr=cannotraisecalldescr)
+        i4 = call_pure(123456, 4, i0, 6, descr=cannotraisecalldescr)
         jump(i0, i3, i4)
         '''
         preamble = '''
         [i0, i1, i2]
         escape(i1)
         escape(i2)
-        i4 = call(123456, 4, i0, 6, descr=plaincalldescr)
+        i4 = call(123456, 4, i0, 6, descr=cannotraisecalldescr)
         i153 = same_as(i4)
         jump(i0, i4, i153)
         '''
@@ -3678,6 +3678,8 @@
 
     def test_call_pure_constant_folding_exc(self):
         # CALL_PURE may be followed by GUARD_NO_EXCEPTION
+        # XXX maybe temporary, but we can't remove such call_pures from
+        # the loop, because the short preamble can't call them safely.
         arg_consts = [ConstInt(i) for i in (123456, 4, 5, 6)]
         call_pure_results = {tuple(arg_consts): ConstInt(42)}
         ops = '''
@@ -3696,14 +3698,15 @@
         escape(i2)
         i4 = call(123456, 4, i0, 6, descr=plaincalldescr)
         guard_no_exception() []
-        i155 = same_as(i4)
-        jump(i0, i4, i155)
+        jump(i0, i4)
         '''
         expected = '''
-        [i0, i2, i3]
+        [i0, i2]
         escape(42)
         escape(i2)
-        jump(i0, i3, i3)
+        i4 = call(123456, 4, i0, 6, descr=plaincalldescr)
+        guard_no_exception() []
+        jump(i0, i4)
         '''
         self.optimize_loop(ops, expected, preamble, call_pure_results)
 
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py b/rpython/jit/metainterp/optimizeopt/test/test_util.py
--- a/rpython/jit/metainterp/optimizeopt/test/test_util.py
+++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py
@@ -182,6 +182,9 @@
     FUNC = lltype.FuncType([lltype.Signed], lltype.Signed)
     plaincalldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                                      EffectInfo.MOST_GENERAL)
+    cannotraisecalldescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
+                                    EffectInfo([], [], [], [valuedescr], [], [],
+                                               EffectInfo.EF_CANNOT_RAISE))
     nonwritedescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
                                     EffectInfo([], [], [], [], [], []))
     writeadescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
diff --git a/rpython/jit/metainterp/optimizeopt/unroll.py b/rpython/jit/metainterp/optimizeopt/unroll.py
--- a/rpython/jit/metainterp/optimizeopt/unroll.py
+++ b/rpython/jit/metainterp/optimizeopt/unroll.py
@@ -438,9 +438,7 @@
         if op.is_ovf():
             guard = ResOperation(rop.GUARD_NO_OVERFLOW, [], None)
             optimizer.send_extra_operation(guard)
-        if op.is_call_pure_with_exception():
-            guard = ResOperation(rop.GUARD_NO_EXCEPTION, [], None)
-            optimizer.send_extra_operation(guard)
+        assert not op.is_call_pure_with_exception()
 
     def add_op_to_short(self, op, emit=True, guards_needed=False):
         if op is None:
@@ -474,9 +472,7 @@
             # FIXME: ensure that GUARD_OVERFLOW:ed ops not end up here
             guard = ResOperation(rop.GUARD_NO_OVERFLOW, [], None)
             self.add_op_to_short(guard, emit, guards_needed)
-        if op.is_call_pure_with_exception():
-            guard = ResOperation(rop.GUARD_NO_EXCEPTION, [], None)
-            self.add_op_to_short(guard, emit, guards_needed)
+        assert not op.is_call_pure_with_exception()
         for guard in value_guards:
             self.add_op_to_short(guard, emit, guards_needed)
 


More information about the pypy-commit mailing list