[pypy-commit] pypy default: Fix for 004a5d649ed9 (issue #2132). See comment in pyjitpl.py.
arigo
noreply at buildbot.pypy.org
Sun Oct 11 10:26:28 CEST 2015
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r80106:66ca1ac6c1dc
Date: 2015-10-11 09:31 +0200
http://bitbucket.org/pypy/pypy/changeset/66ca1ac6c1dc/
Log: Fix for 004a5d649ed9 (issue #2132). See comment in pyjitpl.py.
diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py
--- a/rpython/jit/backend/llgraph/runner.py
+++ b/rpython/jit/backend/llgraph/runner.py
@@ -40,10 +40,13 @@
self.inputargs = map(mapping, inputargs)
self.operations = []
for op in operations:
- if op.getopnum() == rop.GUARD_VALUE:
+ opnum = op.getopnum()
+ if opnum == rop.GUARD_VALUE:
# we don't care about the value 13 here, because we gonna
# fish it from the extra slot on frame anyway
op.getdescr().make_a_counter_per_value(op, 13)
+ elif opnum == rop.BRIDGE_EXCEPTION:
+ assert len(self.operations) == 0 # must be first
if op.getdescr() is not None:
if op.is_guard() or op.getopnum() == rop.FINISH:
newdescr = op.getdescr()
@@ -890,7 +893,10 @@
# -----------------------------------------------------
- def fail_guard(self, descr, saved_data=None, extra_value=None):
+ def fail_guard(self, descr, saved_data=None, extra_value=None,
+ propagate_exception=False):
+ if not propagate_exception:
+ assert self.last_exception is None
values = []
for box in self.current_op.getfailargs():
if box is not None:
@@ -899,6 +905,9 @@
value = None
values.append(value)
if hasattr(descr, '_llgraph_bridge'):
+ if propagate_exception:
+ assert (descr._llgraph_bridge.operations[0].opnum ==
+ rop.BRIDGE_EXCEPTION)
target = (descr._llgraph_bridge, -1)
values = [value for value in values if value is not None]
raise Jump(target, values)
@@ -977,7 +986,7 @@
def execute_guard_no_exception(self, descr):
if self.last_exception is not None:
- self.fail_guard(descr)
+ self.fail_guard(descr, propagate_exception=True)
def execute_guard_exception(self, descr, excklass):
lle = self.last_exception
@@ -989,7 +998,7 @@
llmemory.cast_int_to_adr(excklass),
rclass.CLASSTYPE)
if gotklass != excklass:
- self.fail_guard(descr)
+ self.fail_guard(descr, propagate_exception=True)
#
res = lle.args[1]
self.last_exception = None
@@ -998,7 +1007,7 @@
def execute_guard_not_forced(self, descr):
if self.forced_deadframe is not None:
saved_data = self.forced_deadframe._saved_data
- self.fail_guard(descr, saved_data)
+ self.fail_guard(descr, saved_data, propagate_exception=True)
self.force_guard_op = self.current_op
execute_guard_not_forced_2 = execute_guard_not_forced
@@ -1220,6 +1229,9 @@
def execute_keepalive(self, descr, x):
pass
+ def execute_bridge_exception(self, descr):
+ pass
+
def _getdescr(op):
d = op.getdescr()
diff --git a/rpython/jit/backend/llsupport/rewrite.py b/rpython/jit/backend/llsupport/rewrite.py
--- a/rpython/jit/backend/llsupport/rewrite.py
+++ b/rpython/jit/backend/llsupport/rewrite.py
@@ -1,4 +1,5 @@
from rpython.rlib import rgc
+from rpython.rlib.objectmodel import we_are_translated
from rpython.rlib.rarithmetic import ovfcheck
from rpython.rtyper.lltypesystem import llmemory, lltype
from rpython.jit.metainterp import history
@@ -14,6 +15,9 @@
FLAG_STR = 1
FLAG_UNICODE = 2
+class BridgeExceptionNotFirst(Exception):
+ pass
+
class GcRewriterAssembler(object):
""" This class performs the following rewrites on the list of operations:
@@ -164,6 +168,9 @@
continue
if op.getopnum() == rop.JUMP or op.getopnum() == rop.FINISH:
self.emit_pending_zeros()
+ if op.getopnum() == rop.BRIDGE_EXCEPTION:
+ self.remove_bridge_exception(operations, i)
+ continue
#
self.emit_op(op)
return self._newops
@@ -678,3 +685,14 @@
# assume that "self.gc_ll_descr.minimal_size_in_nursery" is 2 WORDs
size = max(size, 2 * WORD)
return (size + WORD-1) & ~(WORD-1) # round up
+
+ def remove_bridge_exception(self, operations, i):
+ """Check that the 'bridge_exception' operation occurs at the
+ start of the bridge."""
+ if i == 0:
+ return # first operation, ok
+ if i == 1 and operations[0].getopnum() == rop.INCREMENT_DEBUG_COUNTER:
+ return # 2nd operation after INCREMENT_DEBUG_COUNTER, ok
+ # not ok!
+ assert we_are_translated()
+ raise BridgeExceptionNotFirst
diff --git a/rpython/jit/metainterp/executor.py b/rpython/jit/metainterp/executor.py
--- a/rpython/jit/metainterp/executor.py
+++ b/rpython/jit/metainterp/executor.py
@@ -386,6 +386,7 @@
rop.CALL_MALLOC_NURSERY_VARSIZE_FRAME,
rop.NURSERY_PTR_INCREMENT,
rop.LABEL,
+ rop.BRIDGE_EXCEPTION,
): # list of opcodes never executed by pyjitpl
continue
raise AssertionError("missing %r" % (key,))
diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -2480,6 +2480,21 @@
exception = self.cpu.grab_exc_value(deadframe)
if (isinstance(resumedescr, compile.ResumeGuardExcDescr) or
isinstance(resumedescr, compile.ResumeGuardCopiedExcDescr)):
+ # Add a GUARD_EXCEPTION or GUARD_NO_EXCEPTION at the start
+ # of the bridge---except it is not really the start, because
+ # the history aleady contains operations from resume.py.
+ # The optimizer should remove these operations. However,
+ # 'test_guard_no_exception_incorrectly_removed_from_bridge'
+ # shows a corner case in which just putting GuARD_NO_EXCEPTION
+ # here is a bad idea: the optimizer might remove it too.
+ # So we put a pair BRIDGE_EXCEPTION / GUARD_(NO)_EXCEPTION.
+ # The BRIDGE_EXCEPTION is meant to re-raise the exception
+ # caught before the bridge, but in reality it must end up
+ # as the first operation and thus is a no-op for the backends
+ # (it is removed in rewrite.py). Its real purpose is only to
+ # pass through the optimizer unmodified, so that the following
+ # GUARD_NO_EXCEPTION is not killed.
+ self.history.record(rop.BRIDGE_EXCEPTION, [], None)
if exception:
self.execute_ll_raised(lltype.cast_opaque_ptr(rclass.OBJECTPTR,
exception))
diff --git a/rpython/jit/metainterp/resoperation.py b/rpython/jit/metainterp/resoperation.py
--- a/rpython/jit/metainterp/resoperation.py
+++ b/rpython/jit/metainterp/resoperation.py
@@ -827,6 +827,7 @@
'QUASIIMMUT_FIELD/1d/n', # [objptr], descr=SlowMutateDescr
'RECORD_EXACT_CLASS/2/n', # [objptr, clsptr]
'KEEPALIVE/1/n',
+ 'BRIDGE_EXCEPTION/0/n', # pyjitpl: prepare_resume_from_failure()
'_CANRAISE_FIRST', # ----- start of can_raise operations -----
'_CALL_FIRST',
More information about the pypy-commit
mailing list