Author: Armin Rigo <ar...@tunes.org> 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) - -@specialize.arg(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 pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit