Author: Armin Rigo <[email protected]>
Branch: stmgc-c7-rewindjmp
Changeset: r72846:02f43fae7c8c
Date: 2014-08-17 18:17 +0200
http://bitbucket.org/pypy/pypy/changeset/02f43fae7c8c/
Log: In-progress: kill stuff from the JIT
diff --git a/pypy/module/pypyjit/interp_jit.py
b/pypy/module/pypyjit/interp_jit.py
--- a/pypy/module/pypyjit/interp_jit.py
+++ b/pypy/module/pypyjit/interp_jit.py
@@ -56,9 +56,6 @@
pypyjitdriver.jit_merge_point(ec=ec,
frame=self, next_instr=next_instr, pycode=pycode,
is_being_profiled=self.is_being_profiled)
- if self.space.threadlocals.threads_running: # quasi-immutable field
- if rstm.jit_stm_should_break_transaction(False):
- rstm.jit_stm_transaction_break_point()
co_code = pycode.co_code
self.valuestackdepth = hint(self.valuestackdepth, promote=True)
@@ -89,8 +86,7 @@
ec.bytecode_trace(self, decr_by)
jumpto = r_uint(self.last_instr)
if self.space.threadlocals.threads_running: # quasi-immutable field
- if rstm.jit_stm_should_break_transaction(True):
- rstm.jit_stm_transaction_break_point()
+ rstm.possible_transaction_break()
#
pypyjitdriver.can_enter_jit(frame=self, ec=ec, next_instr=jumpto,
pycode=self.getcode(),
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
@@ -1418,20 +1418,9 @@
[v], None))
return ops
- def rewrite_op_jit_stm_should_break_transaction(self, op):
- assert isinstance(op.args[0], Constant)
-
- arg = int(op.args[0].value)
- c_arg = Constant(arg, lltype.Signed)
+ def rewrite_op_stm_rewind_jmp_frame(self, op):
+ return []
- return [SpaceOperation('stm_should_break_transaction',
- [c_arg], op.result),
- SpaceOperation('-live-', [], None),]
-
- def rewrite_op_jit_stm_transaction_break_point(self, op):
- return [SpaceOperation('stm_transaction_break', [], op.result),
- SpaceOperation('-live-', [], None),]
-
def rewrite_op_jit_marker(self, op):
key = op.args[0].value
jitdriver = op.args[1].value
diff --git a/rpython/jit/codewriter/test/test_jtransform.py
b/rpython/jit/codewriter/test/test_jtransform.py
--- a/rpython/jit/codewriter/test/test_jtransform.py
+++ b/rpython/jit/codewriter/test/test_jtransform.py
@@ -929,15 +929,18 @@
assert block.operations[1].result is None
assert block.exits[0].args == [v1]
-def test_jit_stm_transaction_break_point():
- py.test.skip("XXX?")
- op = SpaceOperation('jit_stm_transaction_break_point',
- [Constant(1, lltype.Signed)], lltype.Void)
+def test_stm_should_break_transaction():
+ op = SpaceOperation('stm_should_break_transaction', [], lltype.Bool)
tr = Transformer()
op2 = tr.rewrite_operation(op)
- assert op2.opname == 'stm_transaction_break'
- assert op2.args[0].value == 1
-
+ assert op2.opname == 'stm_should_break_transaction'
+
+def test_stm_rewind_jmp_frame():
+ op = SpaceOperation('stm_rewind_jmp_frame', [], lltype.Void)
+ tr = Transformer()
+ op2 = tr.rewrite_operation(op)
+ assert op2 == []
+
def test_jit_merge_point_1():
class FakeJitDriverSD:
index = 42
diff --git a/rpython/jit/metainterp/blackhole.py
b/rpython/jit/metainterp/blackhole.py
--- a/rpython/jit/metainterp/blackhole.py
+++ b/rpython/jit/metainterp/blackhole.py
@@ -908,18 +908,15 @@
return False
- @arguments("i", returns="i")
- def bhimpl_stm_should_break_transaction(if_there_is_no_other):
- return False
-
-
- @arguments()
- def bhimpl_stm_transaction_break():
- pass
+ @arguments(returns="i")
+ def bhimpl_stm_should_break_transaction():
+ from rpython.rlib import rstm
+ return rstm.should_break_transaction()
@arguments()
def bhimpl_stm_hint_commit_soon():
- pass
+ from rpython.rlib import rstm
+ rstm.hint_commit_soon()
# ----------
diff --git a/rpython/jit/metainterp/heapcache.py
b/rpython/jit/metainterp/heapcache.py
--- a/rpython/jit/metainterp/heapcache.py
+++ b/rpython/jit/metainterp/heapcache.py
@@ -51,13 +51,6 @@
self.input_indirections = {}
self.output_indirections = {}
-
- # to do some of the work of optimizeopt/stm.py, we have a similar
- # logic here:
- self.stm_break_wanted = True
-
-
-
def _input_indirection(self, box):
return self.input_indirections.get(box, box)
@@ -137,11 +130,8 @@
opnum == rop.SETFIELD_RAW or
opnum == rop.SETARRAYITEM_RAW or
opnum == rop.SETINTERIORFIELD_RAW or
- opnum == rop.RAW_STORE):
- return
- if opnum in (rop.GUARD_NOT_FORCED, rop.GUARD_NOT_FORCED_2,
- rop.STM_HINT_COMMIT_SOON):
- self.stm_break_wanted = True
+ opnum == rop.RAW_STORE or
+ opnum == rop.STM_HINT_COMMIT_SOON):
return
if (rop._OVF_FIRST <= opnum <= rop._OVF_LAST or
rop._NOSIDEEFFECT_FIRST <= opnum <= rop._NOSIDEEFFECT_LAST or
@@ -207,7 +197,6 @@
del cache[frombox]
return
else:
- self.stm_break_wanted = True
# Only invalidate things that are either escaped or arguments
for descr, boxes in self.heap_cache.iteritems():
for box in boxes.keys():
@@ -226,8 +215,6 @@
# above, but hit an assertion in "pypy test_multiprocessing.py".
self.reset(reset_virtuals=False, trace_branch=False)
- self.stm_break_wanted = True
-
def is_class_known(self, box):
return box in self.known_class_boxes
@@ -338,6 +325,3 @@
def replace_box(self, oldbox, newbox):
self.input_indirections[self._output_indirection(newbox)] =
self._input_indirection(oldbox)
self.output_indirections[self._input_indirection(oldbox)] =
self._output_indirection(newbox)
-
- def stm_break_done(self):
- self.stm_break_wanted = False
diff --git a/rpython/jit/metainterp/history.py
b/rpython/jit/metainterp/history.py
--- a/rpython/jit/metainterp/history.py
+++ b/rpython/jit/metainterp/history.py
@@ -627,7 +627,6 @@
operations = None
call_pure_results = None
stm_info = None
- is_really_loop = False
logops = None
quasi_immutable_deps = None
diff --git a/rpython/jit/metainterp/optimizeopt/__init__.py
b/rpython/jit/metainterp/optimizeopt/__init__.py
--- a/rpython/jit/metainterp/optimizeopt/__init__.py
+++ b/rpython/jit/metainterp/optimizeopt/__init__.py
@@ -8,7 +8,6 @@
from rpython.jit.metainterp.optimizeopt.simplify import OptSimplify
from rpython.jit.metainterp.optimizeopt.pure import OptPure
from rpython.jit.metainterp.optimizeopt.earlyforce import OptEarlyForce
-from rpython.jit.metainterp.optimizeopt.stm import OptSTM
from rpython.rlib.jit import PARAMETERS, ENABLE_ALL_OPTS
from rpython.rlib.unroll import unrolling_iterable
from rpython.rlib.debug import debug_start, debug_stop, debug_print
@@ -35,9 +34,6 @@
def build_opt_chain(metainterp_sd, enable_opts):
optimizations = []
unroll = 'unroll' in enable_opts # 'enable_opts' is normally a dict
- if metainterp_sd.config.translation.stm:
- optimizations.append(OptSTM())
-
for name, opt in unroll_all_opts:
if name in enable_opts:
if opt is not None:
diff --git a/rpython/jit/metainterp/optimizeopt/heap.py
b/rpython/jit/metainterp/optimizeopt/heap.py
--- a/rpython/jit/metainterp/optimizeopt/heap.py
+++ b/rpython/jit/metainterp/optimizeopt/heap.py
@@ -275,14 +275,12 @@
opnum == rop.COPYSTRCONTENT or # no effect on GC struct/array
opnum == rop.COPYUNICODECONTENT): # no effect on GC struct/array
return
- if (opnum == rop.STM_TRANSACTION_BREAK or
- opnum == rop.CALL_ASSEMBLER):
- self._seen_guard_not_invalidated = False
if (opnum == rop.CALL or
opnum == rop.CALL_PURE or
opnum == rop.COND_CALL or
opnum == rop.CALL_MAY_FORCE or
- opnum == rop.CALL_RELEASE_GIL):
+ opnum == rop.CALL_RELEASE_GIL or
+ opnum == rop.CALL_ASSEMBLER):
if opnum == rop.CALL_ASSEMBLER:
self._seen_guard_not_invalidated = False
else:
diff --git a/rpython/jit/metainterp/optimizeopt/stm.py
b/rpython/jit/metainterp/optimizeopt/stm.py
deleted file mode 100644
--- a/rpython/jit/metainterp/optimizeopt/stm.py
+++ /dev/null
@@ -1,94 +0,0 @@
-from rpython.jit.metainterp.optimizeopt.optimizer import (Optimization, )
-from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
-from rpython.jit.codewriter.effectinfo import EffectInfo
-from rpython.jit.metainterp.resoperation import rop, ResOperation
-
-class OptSTM(Optimization):
- """
- This step removes a lot of uncecessary transaction_breaks (TBs)
- emitted by pyjitpl from traces. We only want to keep these
- unconditional TBs after external calls (identified by GUARD_NOT_FORCED)
- because they are likely to return as inevitable transactions which
- we want to break ASAP.
- Guarded TBs are left in place, as they represent app-level loops
- and are likely points to break between atomic transactions.
-
- The cached_ops is here to remove the virtualizable-forcing added
- by pyjitpl before unconditional TBs. See tests.
- """
- def __init__(self):
- self.remove_next_gnf = False # guard_not_forced
- self.keep_but_ignore_gnf = False
- self.cached_ops = []
-
- def propagate_forward(self, op):
- dispatch_opt(self, op)
-
- def flush_cached(self):
- while self.cached_ops:
- self.emit_operation(self.cached_ops.pop(0))
-
- def flush(self):
- # just in case. it shouldn't be necessary
- self.flush_cached()
-
- def default_emit(self, op):
- self.flush_cached()
- self.emit_operation(op)
-
- def _break_wanted(self):
- is_loop = self.optimizer.loop.is_really_loop
- return self.optimizer.stm_info.get('break_wanted', is_loop)
-
- def _set_break_wanted(self, val):
- self.optimizer.stm_info['break_wanted'] = val
-
- def optimize_FORCE_TOKEN(self, op):
- # if we have cached stuff, flush it. Not our case
- self.flush_cached()
- self.cached_ops.append(op)
-
- def optimize_SETFIELD_GC(self, op):
- if not self.cached_ops:
- # setfield not for force_token
- self.emit_operation(op)
- else:
- assert len(self.cached_ops) == 1
- assert self.cached_ops[0].getopnum() == rop.FORCE_TOKEN
- self.cached_ops.append(op)
-
- def optimize_STM_SHOULD_BREAK_TRANSACTION(self, op):
- self.flush_cached()
- self._set_break_wanted(False)
- self.emit_operation(op)
-
- def optimize_STM_TRANSACTION_BREAK(self, op):
- assert not self.remove_next_gnf
- really_wanted = op.getarg(0).getint()
- if really_wanted or self._break_wanted():
- self.flush_cached()
- self._set_break_wanted(False)
- self.emit_operation(op)
- self.keep_but_ignore_gnf = True
- else:
- self.cached_ops = []
- self.remove_next_gnf = True
-
- def optimize_GUARD_NOT_FORCED(self, op):
- self.flush_cached()
- if self.remove_next_gnf:
- self.remove_next_gnf = False
- else:
- if not self.keep_but_ignore_gnf:
- self._set_break_wanted(True)
- self.keep_but_ignore_gnf = False
- self.emit_operation(op)
-
- def optimize_STM_HINT_COMMIT_SOON(self, op):
- self.flush_cached()
- self._set_break_wanted(True)
- self.emit_operation(op)
-
-
-dispatch_opt = make_dispatcher_method(OptSTM, 'optimize_',
- default=OptSTM.default_emit)
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_stm.py
b/rpython/jit/metainterp/optimizeopt/test/test_stm.py
deleted file mode 100644
--- a/rpython/jit/metainterp/optimizeopt/test/test_stm.py
+++ /dev/null
@@ -1,331 +0,0 @@
-from rpython.jit.metainterp.optimizeopt.test.test_optimizeopt import (
- BaseTestWithUnroll,)
-from rpython.jit.metainterp.optimizeopt.test.test_util import LLtypeMixin
-from rpython.jit.codewriter.effectinfo import EffectInfo
-from rpython.rtyper.lltypesystem import lltype, rclass, rffi, llmemory
-
-
-class TestSTM(BaseTestWithUnroll, LLtypeMixin):
- stm = True
-
- namespace = LLtypeMixin.namespace.copy()
- namespace.update(locals())
-
-
- def test_unrolled_loop(self):
- ops = """
- []
- i0 = stm_should_break_transaction()
- guard_false(i0) []
- jump()
- """
- self.optimize_loop(ops, ops, expected_preamble=ops)
-
- def test_really_wanted_tb(self):
- ops = """
- []
- stm_transaction_break(0)
- guard_not_forced() []
-
- stm_transaction_break(1)
- guard_not_forced() []
-
- jump()
- """
- preamble = """
- []
- stm_transaction_break(0)
- guard_not_forced() []
-
- stm_transaction_break(1)
- guard_not_forced() []
-
- jump()
- """
- expected = """
- []
- stm_transaction_break(1)
- guard_not_forced() []
-
- jump()
- """
- self.optimize_loop(ops, expected, expected_preamble=preamble)
-
-
- def test_unrolled_loop2(self):
- ops = """
- []
- stm_transaction_break(0)
- guard_not_forced() []
-
- i0 = stm_should_break_transaction()
- guard_false(i0) []
-
- jump()
- """
- preamble = """
- []
- stm_transaction_break(0)
- guard_not_forced() []
-
- i0 = stm_should_break_transaction()
- guard_false(i0) []
-
- jump()
- """
- expected = """
- []
- i0 = stm_should_break_transaction()
- guard_false(i0) []
- jump()
- """
- self.optimize_loop(ops, expected, expected_preamble=preamble)
-
- def test_not_disable_opt(self):
- ops = """
- [p1]
- i1 = getfield_gc(p1, descr=adescr)
-
- i0 = stm_should_break_transaction()
- guard_false(i0) []
- jump(p1)
- """
- preamble = """
- [p1]
- i1 = getfield_gc(p1, descr=adescr)
-
- i0 = stm_should_break_transaction()
- guard_false(i0) []
- jump(p1)
- """
- expected = """
- [p1]
- i0 = stm_should_break_transaction()
- guard_false(i0) []
-
- jump(p1)
- """
- self.optimize_loop(ops, expected, expected_preamble=preamble)
-
- def test_dont_remove_first_tb(self):
- ops = """
- []
- stm_transaction_break(0)
- guard_not_forced() []
- stm_transaction_break(0)
- guard_not_forced() []
- stm_transaction_break(0)
- guard_not_forced() []
- i0 = stm_should_break_transaction()
- guard_false(i0) []
- jump()
- """
- preamble = """
- []
- stm_transaction_break(0)
- guard_not_forced() []
-
- i0 = stm_should_break_transaction()
- guard_false(i0) []
- jump()
- """
- expected = """
- []
- i0 = stm_should_break_transaction()
- guard_false(i0) []
- jump()
- """
- self.optimize_loop(ops, expected, expected_preamble=preamble)
-
- def test_add_tb_after_guard_not_forced(self):
- ops = """
- []
- stm_transaction_break(0)
- guard_not_forced() []
-
- escape() # e.g. like a call_release_gil
- guard_not_forced() []
-
- stm_transaction_break(0)
- guard_not_forced() []
- stm_transaction_break(0)
- guard_not_forced() []
- i0 = stm_should_break_transaction()
- guard_false(i0) []
- jump()
- """
- preamble = """
- []
- stm_transaction_break(0)
- guard_not_forced() []
-
- escape()
- guard_not_forced() []
-
- stm_transaction_break(0)
- guard_not_forced() []
-
- i0 = stm_should_break_transaction()
- guard_false(i0) []
- jump()
- """
- expected = """
- []
- escape()
- guard_not_forced() []
-
- stm_transaction_break(0)
- guard_not_forced() []
-
- i0 = stm_should_break_transaction()
- guard_false(i0) []
- jump()
- """
- self.optimize_loop(ops, expected, expected_preamble=preamble)
-
- def test_remove_force_token(self):
- ops = """
- [p0]
- p1 = force_token()
- setfield_gc(p0, p1, descr=adescr)
- stm_transaction_break(0)
- guard_not_forced() []
-
- p2 = force_token()
- setfield_gc(p0, p2, descr=adescr)
- stm_transaction_break(0)
- guard_not_forced() []
-
- p3 = force_token()
- setfield_gc(p0, p3, descr=adescr)
- stm_transaction_break(0)
- guard_not_forced() []
-
- escape()
-
- p4 = force_token()
- setfield_gc(p0, p4, descr=adescr)
- stm_transaction_break(0)
- guard_not_forced() []
-
- p6 = force_token() # not removed!
-
- i0 = stm_should_break_transaction()
- guard_false(i0) []
- jump(p0)
- """
- preamble = """
- [p0]
- p1 = force_token()
- setfield_gc(p0, p1, descr=adescr)
- stm_transaction_break(0)
- guard_not_forced() []
-
- escape()
-
- p6 = force_token() # not removed!
-
- i0 = stm_should_break_transaction()
- guard_false(i0) []
- jump(p0)
- """
- expected = """
- [p0]
- escape()
-
- p6 = force_token() # not removed!
-
- i0 = stm_should_break_transaction()
- guard_false(i0) []
- jump(p0)
- """
- self.optimize_loop(ops, expected, expected_preamble=preamble)
-
- def test_not_remove_setfield(self):
- ops = """
- [p0, p1]
- setfield_gc(p0, p1, descr=adescr)
- stm_transaction_break(0)
-
- p2 = force_token()
- p3 = force_token()
- jump(p0, p1)
- """
- preamble = """
- [p0, p1]
- setfield_gc(p0, p1, descr=adescr)
- stm_transaction_break(0)
-
- p2 = force_token()
- p3 = force_token()
- jump(p0, p1)
- """
- expected = """
- [p0, p1]
- p2 = force_token()
- p3 = force_token()
-
- setfield_gc(p0, p1, descr=adescr) # moved here by other stuff...
- jump(p0, p1)
- """
- self.optimize_loop(ops, expected, expected_preamble=preamble)
-
- def test_stm_location_1(self):
- # This tests setfield_gc on a non-virtual. On a virtual, it doesn't
- # really matter, because STM conflicts are impossible anyway
- ops = """
- [i1, p1]
- setfield_gc(p1, i1, descr=adescr) {81}
- call(i1, descr=nonwritedescr) {90}
- jump(i1, p1)
- """
- expected = """
- [i1, p1]
- call(i1, descr=nonwritedescr) {90}
- setfield_gc(p1, i1, descr=adescr) {81}
- jump(i1, p1)
- """
- self.optimize_loop(ops, expected)
-
- def test_add_tb_after_commit_soon(self):
- ops = """
- []
- stm_transaction_break(0)
- guard_not_forced() []
-
- stm_hint_commit_soon()
-
- stm_transaction_break(0)
- guard_not_forced() []
- stm_transaction_break(0)
- guard_not_forced() []
- i0 = stm_should_break_transaction()
- guard_false(i0) []
- jump()
- """
- preamble = """
- []
- stm_transaction_break(0)
- guard_not_forced() []
-
- stm_hint_commit_soon()
-
- stm_transaction_break(0)
- guard_not_forced() []
-
- i0 = stm_should_break_transaction()
- guard_false(i0) []
- jump()
- """
- expected = """
- []
- stm_hint_commit_soon()
-
- stm_transaction_break(0)
- guard_not_forced() []
-
- i0 = stm_should_break_transaction()
- guard_false(i0) []
- jump()
- """
- self.optimize_loop(ops, expected, expected_preamble=preamble)
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
@@ -1,6 +1,6 @@
import py, random
-from rpython.rtyper.lltypesystem import lltype, llmemory, rclass, rstr, rffi
+from rpython.rtyper.lltypesystem import lltype, llmemory, rclass, rffi
from rpython.rtyper.lltypesystem.rclass import OBJECT, OBJECT_VTABLE
from rpython.rtyper.rclass import FieldListAccessor, IR_QUASIIMMUTABLE
@@ -331,7 +331,7 @@
def get_name_from_address(self, addr):
# hack
try:
- return "".join(addr.ptr.name)[:-1] # remove \x00
+ return "".join(addr.ptr.name.chars)
except AttributeError:
return ""
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
@@ -75,7 +75,6 @@
start_label = loop.operations[0]
if start_label.getopnum() == rop.LABEL:
- loop.is_really_loop = True
loop.operations = loop.operations[1:]
# We need to emit the label op before import_state() as emitting it
# will clear heap caches
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
@@ -186,52 +186,16 @@
raise AssertionError("bad result box type")
# ------------------------------
- def _record_stm_transaction_break(self, really_wanted):
- # records an unconditional stm_transaction_break
- mi = self.metainterp
- mi.vable_and_vrefs_before_residual_call()
- mi._record_helper_nonpure_varargs(
- rop.STM_TRANSACTION_BREAK, None, None,
- [history.ConstInt(really_wanted)])
- mi.vrefs_after_residual_call()
- mi.vable_after_residual_call()
- #
- if not really_wanted:
- # we're about the return ConstInt(0), which will go into the
- # jitcode's %iN variable. But it will be captured by the
- # GUARD_NOT_FORCED's resume data too. It is essential that we
- # don't capture the old, stale value! Also, store ConstInt(1)
- # to make sure that upon resuming we'll see a result of 1 (XXX
- # unsure if it's needed, but it shouldn't hurt).
- self.make_result_of_lastop(ConstInt(1))
- #
- mi.generate_guard(rop.GUARD_NOT_FORCED, None)
- self.metainterp.heapcache.stm_break_done()
-
-
- @arguments("int")
- def opimpl_stm_should_break_transaction(self, if_there_is_no_other):
- val = bool(if_there_is_no_other)
- mi = self.metainterp
- if val:
- # app-level loop: only one of these per loop is really needed
- resbox = history.BoxInt(0)
- mi.history.record(rop.STM_SHOULD_BREAK_TRANSACTION, [], resbox)
- self.metainterp.heapcache.stm_break_done()
- return resbox
- else:
- # between byte-code instructions: only keep if it is
- # likely that we are inevitable here
- if self.metainterp.heapcache.stm_break_wanted:
- self._record_stm_transaction_break(False)
- return ConstInt(0)
@arguments()
- def opimpl_stm_transaction_break(self):
- # always wanted: inserted after we compile a bridge because there
- # were just too many breaks and we failed the should_break&guard
- # because of that
- self._record_stm_transaction_break(True)
+ def opimpl_stm_should_break_transaction(self):
+ # XXX make it return BoxInt(1) instead of BoxInt(0) if there
+ # is an inevitable transaction, because it's likely that there
+ # will always be an inevitable transaction here
+ resbox = history.BoxInt(0)
+ mi = self.metainterp
+ mi.history.record(rop.STM_SHOULD_BREAK_TRANSACTION, [], resbox)
+ return resbox
@arguments()
def opimpl_stm_hint_commit_soon(self):
@@ -1855,8 +1819,6 @@
if opnum == rop.GUARD_NOT_FORCED or opnum == rop.GUARD_NOT_FORCED_2:
resumedescr = compile.ResumeGuardForcedDescr(self.staticdata,
self.jitdriver_sd)
- # for detecting stm breaks that are needed
- self.heapcache.invalidate_caches(opnum, resumedescr, moreargs)
elif opnum == rop.GUARD_NOT_INVALIDATED:
resumedescr = compile.ResumeGuardNotInvalidated()
elif opnum == rop.GUARD_FUTURE_CONDITION:
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
@@ -521,7 +521,6 @@
'QUASIIMMUT_FIELD/1d', # [objptr], descr=SlowMutateDescr
'RECORD_KNOWN_CLASS/2', # [objptr, clsptr]
'KEEPALIVE/1',
- 'STM_TRANSACTION_BREAK/1',
'STM_READ/1',
'_CANRAISE_FIRST', # ----- start of can_raise operations -----
diff --git a/rpython/jit/metainterp/test/test_stm.py
b/rpython/jit/metainterp/test/test_stm.py
--- a/rpython/jit/metainterp/test/test_stm.py
+++ b/rpython/jit/metainterp/test/test_stm.py
@@ -11,63 +11,10 @@
class STMTests:
def test_simple(self):
def g():
- return rstm.jit_stm_should_break_transaction(False)
+ return rstm.should_break_transaction()
res = self.interp_operations(g, [], translationoptions={"stm":True})
assert res == False
- self.check_operations_history(stm_transaction_break=1,
- stm_should_break_transaction=0)
-
- def test_not_removed(self):
- import time
- def g():
- time.sleep(0)
- return rstm.jit_stm_should_break_transaction(False)
- res = self.interp_operations(g, [], translationoptions={"stm":True})
- assert res == False
- self.check_operations_history(stm_transaction_break=1,
- call_may_force=1,
- stm_should_break_transaction=0)
-
- def test_not_removed2(self):
- def g():
- return rstm.jit_stm_should_break_transaction(True)
- res = self.interp_operations(g, [], translationoptions={"stm":True})
- assert res == False
- self.check_operations_history(stm_transaction_break=0,
- stm_should_break_transaction=1)
-
- def test_transaction_break(self):
- def g():
- rstm.jit_stm_transaction_break_point()
- return 42
- self.interp_operations(g, [], translationoptions={"stm":True})
- self.check_operations_history({'stm_transaction_break':1,
- 'guard_not_forced':1})
-
- def test_heapcache(self):
- import time
- def g():
- rstm.jit_stm_should_break_transaction(True) # keep (start of loop)
- rstm.jit_stm_should_break_transaction(False)
- time.sleep(0)
- rstm.jit_stm_should_break_transaction(False) # keep (after
guard_not_forced)
- rstm.jit_stm_should_break_transaction(False)
- rstm.jit_stm_should_break_transaction(True) # keep (True)
- rstm.jit_stm_should_break_transaction(True) # keep (True)
- rstm.jit_stm_should_break_transaction(False)
- rstm.hint_commit_soon()
- rstm.jit_stm_should_break_transaction(False) # keep
- rstm.jit_stm_should_break_transaction(False)
- return 42
- res = self.interp_operations(g, [], translationoptions={"stm":True})
- assert res == 42
- self.check_operations_history({
- 'stm_transaction_break':2,
- 'stm_hint_commit_soon':1,
- 'stm_should_break_transaction':3,
- 'guard_not_forced':3,
- 'guard_no_exception':1,
- 'call_may_force':1})
+ self.check_operations_history(stm_should_break_transaction=1)
def test_debug_merge_points(self):
myjitdriver = JitDriver(greens = ['a'], reds = ['x', 'res'])
diff --git a/rpython/rlib/jit.py b/rpython/rlib/jit.py
--- a/rpython/rlib/jit.py
+++ b/rpython/rlib/jit.py
@@ -483,12 +483,14 @@
name = 'jitdriver'
inline_jit_merge_point = False
_store_last_enter_jit = None
+ stm_report_location = None
def __init__(self, greens=None, reds=None, virtualizables=None,
get_jitcell_at=None, set_jitcell_at=None,
get_printable_location=None, confirm_enter_jit=None,
can_never_inline=None, should_unroll_one_iteration=None,
- name='jitdriver', check_untranslated=True):
+ name='jitdriver', check_untranslated=True,
+ stm_report_location=None):
if greens is not None:
self.greens = greens
self.name = name
@@ -524,6 +526,8 @@
self.can_never_inline = can_never_inline
self.should_unroll_one_iteration = should_unroll_one_iteration
self.check_untranslated = check_untranslated
+ if stm_report_location is not None:
+ self.stm_report_location = stm_report_location
def _freeze_(self):
return True
diff --git a/rpython/rlib/rstm.py b/rpython/rlib/rstm.py
--- a/rpython/rlib/rstm.py
+++ b/rpython/rlib/rstm.py
@@ -46,47 +46,13 @@
function with the interpreter's dispatch loop, this must be called
(it turns into a marker in the caller's function). There is one
automatically in any jit.jit_merge_point()."""
- # special-cased below
+ # special-cased below: the emitted operation must be placed
+ # directly in the caller's graph
def possible_transaction_break():
if stm_is_enabled():
if llop.stm_should_break_transaction(lltype.Bool):
- llop.stm_transaction_break(lltype.Void)
-
-# Typical usage of the following two functions:
-#
-# just after jit_merge_point:
-# if rstm.jit_stm_should_break_transaction(False):
-# rstm.jit_stm_transaction_break_point()
-#
-# just before can_enter_jit:
-# if rstm.jit_stm_should_break_transaction(True):
-# rstm.jit_stm_transaction_break_point()
-#
-# resulting JIT trace (common case):
-# ...
-# call_release_gil(...)
-# stm_transaction_break(0) # in-line, because we expect "inevitable"
-# guard_not_forced()
-# ...
-# i1 = stm_should_break_transaction()
-# guard_false(i1) # out-of-line, because rarely needed
-# jump()
-#
-def jit_stm_transaction_break_point():
- # XXX REFACTOR AWAY
- if we_are_translated():
- llop.jit_stm_transaction_break_point(lltype.Void)
-
[email protected](0)
-def jit_stm_should_break_transaction(if_there_is_no_other):
- # XXX REFACTOR AWAY
- # if_there_is_no_other means that we use this point only
- # if there is no other break point in the trace.
- # If it is False, the point may be used if it comes right
- # after a CALL_RELEASE_GIL
- return llop.jit_stm_should_break_transaction(lltype.Bool,
- if_there_is_no_other)
+ break_transaction()
def hint_commit_soon():
"""As the name says, just a hint. Maybe calling it
@@ -104,7 +70,6 @@
def partial_commit_and_resume_other_threads():
pass # for now
-@dont_look_inside
def should_break_transaction():
return we_are_translated() and (
llop.stm_should_break_transaction(lltype.Bool))
diff --git a/rpython/rtyper/llinterp.py b/rpython/rtyper/llinterp.py
--- a/rpython/rtyper/llinterp.py
+++ b/rpython/rtyper/llinterp.py
@@ -943,7 +943,6 @@
op_stm_initialize = _stm_not_implemented
op_stm_finalize = _stm_not_implemented
op_stm_perform_transaction = _stm_not_implemented
- op_stm_should_break_transaction = _stm_not_implemented
op_stm_commit_transaction = _stm_not_implemented
op_stm_begin_inevitable_transaction = _stm_not_implemented
op_stm_barrier = _stm_not_implemented
@@ -971,6 +970,9 @@
op_stm_stop_all_other_threads = _stm_not_implemented
op_stm_partial_commit_and_resume_other_threads = _stm_not_implemented
+ def op_stm_should_break_transaction(self):
+ return False
+
def op_threadlocalref_set(self, key, value):
try:
d = self.llinterpreter.tlrefsdict
diff --git a/rpython/rtyper/lltypesystem/lloperation.py
b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -436,7 +436,7 @@
'stm_leave_callback_call': LLOp(),
'stm_transaction_break': LLOp(canmallocgc=True),
'stm_should_break_transaction': LLOp(sideeffects=False),
- 'stm_rewind_jmp_frame': LLOp(),
+ 'stm_rewind_jmp_frame': LLOp(canrun=True),
'stm_set_transaction_length': LLOp(),
'stm_hint_commit_soon': LLOp(canrun=True),
@@ -521,8 +521,6 @@
'jit_assembler_call': LLOp(canrun=True, # similar to an 'indirect_call'
canraise=(Exception,),
canmallocgc=True),
- 'jit_stm_transaction_break_point' : LLOp(canrun=True,canmallocgc=True),
- 'jit_stm_should_break_transaction' : LLOp(canrun=True),
# __________ GC operations __________
diff --git a/rpython/rtyper/lltypesystem/opimpl.py
b/rpython/rtyper/lltypesystem/opimpl.py
--- a/rpython/rtyper/lltypesystem/opimpl.py
+++ b/rpython/rtyper/lltypesystem/opimpl.py
@@ -715,10 +715,7 @@
def op_jit_assembler_call(funcptr, *args):
return funcptr(*args)
-def op_jit_stm_should_break_transaction(if_there_is_no_other):
- return False
-
-def op_jit_stm_transaction_break_point():
+def op_stm_rewind_jmp_frame():
pass
def op_stm_hint_commit_soon():
diff --git a/rpython/translator/stm/breakfinder.py
b/rpython/translator/stm/breakfinder.py
--- a/rpython/translator/stm/breakfinder.py
+++ b/rpython/translator/stm/breakfinder.py
@@ -7,7 +7,6 @@
'stm_start_if_not_atomic',
#'stm_partial_commit_and_resume_other_threads', # new priv_revision
#'jit_assembler_call',
- #'jit_stm_transaction_break_point',
'stm_enter_callback_call',
'stm_leave_callback_call',
])
diff --git a/rpython/translator/stm/inevitable.py
b/rpython/translator/stm/inevitable.py
--- a/rpython/translator/stm/inevitable.py
+++ b/rpython/translator/stm/inevitable.py
@@ -18,8 +18,7 @@
'gc_adr_of_root_stack_top', 'gc_add_memory_pressure',
'weakref_create', 'weakref_deref',
'jit_assembler_call', 'gc_writebarrier',
- 'shrink_array', 'jit_stm_transaction_break_point',
- 'jit_stm_should_break_transaction',
+ 'shrink_array',
'threadlocalref_get', 'threadlocalref_set',
])
ALWAYS_ALLOW_OPERATIONS |= set(lloperation.enum_tryfold_ops())
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit