[pypy-commit] pypy default: Trying out a small hack: setting the oopspec to 'jit.not_in_trace()'
arigo
noreply at buildbot.pypy.org
Wed Oct 8 20:55:18 CEST 2014
Author: Armin Rigo <arigo at tunes.org>
Branch:
Changeset: r73841:277d77803c7a
Date: 2014-10-08 18:42 +0200
http://bitbucket.org/pypy/pypy/changeset/277d77803c7a/
Log: Trying out a small hack: setting the oopspec to 'jit.not_in_trace()'
makes the function call disappear from the jit traces. It is still
called in interpreted mode, and by the jit tracing and blackholing,
but not by the final assembler.
diff --git a/rpython/jit/codewriter/effectinfo.py b/rpython/jit/codewriter/effectinfo.py
--- a/rpython/jit/codewriter/effectinfo.py
+++ b/rpython/jit/codewriter/effectinfo.py
@@ -25,6 +25,7 @@
OS_THREADLOCALREF_GET = 5 # llop.threadlocalref_get
OS_GET_ERRNO = 6 # rposix.get_errno
OS_SET_ERRNO = 7 # rposix.set_errno
+ OS_NOT_IN_TRACE = 8 # for calls not recorded in the jit trace
#
OS_STR_CONCAT = 22 # "stroruni.concat"
OS_STR_SLICE = 23 # "stroruni.slice"
@@ -96,6 +97,7 @@
_OS_CANRAISE = set([
OS_NONE, OS_STR2UNICODE, OS_LIBFFI_CALL, OS_RAW_MALLOC_VARSIZE_CHAR,
OS_JIT_FORCE_VIRTUAL, OS_SHRINK_ARRAY, OS_DICT_LOOKUP,
+ OS_NOT_IN_TRACE,
])
def __new__(cls, readonly_descrs_fields, readonly_descrs_arrays,
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
@@ -1562,7 +1562,18 @@
kind = getkind(args[0].concretetype)
return SpaceOperation('%s_isvirtual' % kind, args, op.result)
elif oopspec_name == 'jit.force_virtual':
- return self._handle_oopspec_call(op, args, EffectInfo.OS_JIT_FORCE_VIRTUAL, EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE)
+ return self._handle_oopspec_call(op, args,
+ EffectInfo.OS_JIT_FORCE_VIRTUAL,
+ EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE)
+ elif oopspec_name == 'jit.not_in_trace':
+ # ignore 'args' and use the original 'op.args'
+ if op.result.concretetype is not lltype.Void:
+ raise Exception(
+ "%r: jit.not_in_trace() function must return None"
+ % (op.args[0],))
+ return self._handle_oopspec_call(op, op.args[1:],
+ EffectInfo.OS_NOT_IN_TRACE,
+ EffectInfo.EF_CAN_RAISE)
else:
raise AssertionError("missing support for %r" % oopspec_name)
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
@@ -1427,6 +1427,8 @@
if effect == effectinfo.EF_LOOPINVARIANT:
return self.execute_varargs(rop.CALL_LOOPINVARIANT, allboxes,
descr, False, False)
+ if effectinfo.oopspecindex == effectinfo.OS_NOT_IN_TRACE:
+ return self.metainterp.do_not_in_trace_call(allboxes, descr)
exc = effectinfo.check_can_raise()
pure = effectinfo.check_is_elidable()
return self.execute_varargs(rop.CALL, allboxes, descr, exc, pure)
@@ -2830,6 +2832,19 @@
if not we_are_translated(): # for llgraph
descr._original_func_ = op.getarg(0).value
+ def do_not_in_trace_call(self, allboxes, descr):
+ self.clear_exception()
+ resbox = executor.execute_varargs(self.cpu, self, rop.CALL,
+ allboxes, descr)
+ assert resbox is None
+ if self.last_exc_value_box is not None:
+ # cannot trace this! it raises, so we have to follow the
+ # exception-catching path, but the trace doesn't contain
+ # the call at all
+ raise SwitchToBlackhole(Counters.ABORT_ESCAPE,
+ raising_exception=True)
+ return None
+
# ____________________________________________________________
class ChangeFrame(jitexc.JitException):
diff --git a/rpython/jit/metainterp/test/test_ajit.py b/rpython/jit/metainterp/test/test_ajit.py
--- a/rpython/jit/metainterp/test/test_ajit.py
+++ b/rpython/jit/metainterp/test/test_ajit.py
@@ -4044,3 +4044,49 @@
res = self.interp_operations(f, [17])
assert res == 42
self.check_operations_history(guard_true=1, guard_false=0)
+
+ def test_not_in_trace(self):
+ class X:
+ n = 0
+ def g(x):
+ if we_are_jitted():
+ raise NotImplementedError
+ x.n += 1
+ g.oopspec = 'jit.not_in_trace()'
+
+ jitdriver = JitDriver(greens=[], reds=['n', 'token', 'x'])
+ def f(n):
+ token = 0
+ x = X()
+ while n >= 0:
+ jitdriver.jit_merge_point(n=n, x=x, token=token)
+ if not we_are_jitted():
+ token += 1
+ g(x)
+ n -= 1
+ return x.n + token * 1000
+
+ res = self.meta_interp(f, [10])
+ assert res == 2003 # two runs before jitting; then one tracing run
+ self.check_resops(int_add=0, call=0, call_may_force=0)
+
+ def test_not_in_trace_exception(self):
+ def g():
+ if we_are_jitted():
+ raise NotImplementedError
+ raise ValueError
+ g.oopspec = 'jit.not_in_trace()'
+
+ jitdriver = JitDriver(greens=[], reds=['n'])
+ def f(n):
+ while n >= 0:
+ jitdriver.jit_merge_point(n=n)
+ try:
+ g()
+ except ValueError:
+ n -= 1
+ return 42
+
+ res = self.meta_interp(f, [10])
+ assert res == 42
+ self.check_aborted_count(3)
More information about the pypy-commit
mailing list