[pypy-commit] pypy stmgc-c4: revert changes to assembler.py and start support of transaction breaks in optimizeopt
Raemi
noreply at buildbot.pypy.org
Mon Jan 13 16:39:51 CET 2014
Author: Remi Meier <remi.meier at gmail.com>
Branch: stmgc-c4
Changeset: r68645:195b15f42c66
Date: 2014-01-13 12:15 +0100
http://bitbucket.org/pypy/pypy/changeset/195b15f42c66/
Log: revert changes to assembler.py and start support of transaction
breaks in optimizeopt
diff --git a/rpython/jit/backend/x86/assembler.py b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -3160,17 +3160,52 @@
return # tests only
mc = self.mc
+ # if stm_should_break_transaction()
+ fn = stmtlocal.stm_should_break_transaction_fn
+ mc.CALL(imm(self.cpu.cast_ptr_to_int(fn)))
+ mc.TEST8(eax.lowest8bits(), eax.lowest8bits())
+ mc.J_il(rx86.Conditions['Z'], 0xfffff) # patched later
+ jz_location2 = mc.get_relative_pos()
#
# call stm_transaction_break() with the address of the
# STM_RESUME_BUF and the custom longjmp function
self.push_gcmap(mc, gcmap, mov=True)
#
+ # save all registers
+ base_ofs = self.cpu.get_baseofs_of_frame_field()
+ for gpr in self._regalloc.rm.reg_bindings.values():
+ v = gpr_reg_mgr_cls.all_reg_indexes[gpr.value]
+ mc.MOV_br(v * WORD + base_ofs, gpr.value)
+ if IS_X86_64:
+ coeff = 1
+ else:
+ coeff = 2
+ ofs = len(gpr_reg_mgr_cls.all_regs)
+ for xr in self._regalloc.xrm.reg_bindings.values():
+ mc.MOVSD_bx((ofs + xr.value * coeff) * WORD + base_ofs, xr.value)
+ #
# CALL break function
fn = self.stm_transaction_break_path
mc.CALL(imm(fn))
# ** HERE ** is the place an aborted transaction retries
# ebp/frame reloaded by longjmp callback
#
+ # restore regs
+ base_ofs = self.cpu.get_baseofs_of_frame_field()
+ for gpr in self._regalloc.rm.reg_bindings.values():
+ v = gpr_reg_mgr_cls.all_reg_indexes[gpr.value]
+ mc.MOV_rb(gpr.value, v * WORD + base_ofs)
+ if IS_X86_64:
+ coeff = 1
+ else:
+ coeff = 2
+ ofs = len(gpr_reg_mgr_cls.all_regs)
+ for xr in self._regalloc.xrm.reg_bindings.values():
+ mc.MOVSD_xb(xr.value, (ofs + xr.value * coeff) * WORD + base_ofs)
+ #
+ # patch the JZ above
+ offset = mc.get_relative_pos() - jz_location2
+ mc.overwrite32(jz_location2-4, offset)
diff --git a/rpython/jit/backend/x86/regalloc.py b/rpython/jit/backend/x86/regalloc.py
--- a/rpython/jit/backend/x86/regalloc.py
+++ b/rpython/jit/backend/x86/regalloc.py
@@ -1278,8 +1278,8 @@
def consider_stm_transaction_break(self, op):
#
# only save regs for the should_break_transaction call
- self.xrm.before_call(save_all_regs=1)
- self.rm.before_call(save_all_regs=1)
+ self.xrm.before_call()
+ self.rm.before_call()
gcmap = self.get_gcmap() # allocate the gcmap *before*
#
self.assembler.stm_transaction_break(gcmap)
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
@@ -1347,11 +1347,13 @@
arg = int(op.args[0].value)
c_arg = Constant(arg, lltype.Signed)
- return SpaceOperation('stm_should_break_transaction',
- [c_arg], op.result)
+ 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)
+ return [SpaceOperation('stm_transaction_break', [], op.result),
+ SpaceOperation('-live-', [], None),]
def rewrite_op_jit_marker(self, op):
key = op.args[0].value
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,6 +8,7 @@
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,6 +36,9 @@
config = metainterp_sd.config
optimizations = []
unroll = 'unroll' in enable_opts # 'enable_opts' is normally a dict
+ if 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/stm.py b/rpython/jit/metainterp/optimizeopt/stm.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/metainterp/optimizeopt/stm.py
@@ -0,0 +1,36 @@
+from rpython.jit.metainterp.history import (Const, ConstInt, BoxInt, BoxFloat,
+ BoxPtr, make_hashable_int)
+from rpython.jit.metainterp.optimizeopt.optimizer import (Optimization, REMOVED,
+ CONST_0, CONST_1)
+from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method
+from rpython.jit.metainterp.resoperation import (opboolinvers, opboolreflex, rop,
+ ResOperation)
+
+
+class OptSTM(Optimization):
+ """
+ For now only changes some guarded transaction breaks
+ to unconditional ones.
+ """
+ def __init__(self):
+ pass
+
+ def new(self):
+ return OptSTM()
+
+ def propagate_forward(self, op):
+ dispatch_opt(self, op)
+
+ def optimize_CALL(self, op):
+ self.emit_operation(op)
+
+ def optimize_STM_TRANSACTION_BREAK(self, op):
+ self.emit_operation(op)
+
+dispatch_opt = make_dispatcher_method(OptSTM, 'optimize_',
+ default=OptSTM.emit_operation)
+
+
+
+
+
diff --git a/rpython/jit/metainterp/optimizeopt/test/test_stm.py b/rpython/jit/metainterp/optimizeopt/test/test_stm.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/metainterp/optimizeopt/test/test_stm.py
@@ -0,0 +1,26 @@
+from rpython.jit.metainterp.optimizeopt.test.test_optimizebasic import (
+ BaseTestBasic,)
+from rpython.jit.metainterp.optimizeopt.test.test_util import LLtypeMixin
+
+
+
+
+class BaseTestSTM(BaseTestBasic):
+ stm = True
+
+ def test_simple(self):
+ ops = """
+ []
+ stm_transaction_break()
+ guard_not_forced() []
+ jump()
+ """
+ expected = ops
+ self.optimize_loop(ops, expected)
+
+
+
+class TestLLtype(BaseTestSTM, LLtypeMixin):
+ pass
+
+
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
@@ -365,6 +365,8 @@
metainterp_sd.virtualref_info = self.vrefinfo
if hasattr(self, 'callinfocollection'):
metainterp_sd.callinfocollection = self.callinfocollection
+ if hasattr(self, 'stm'):
+ metainterp_sd.config.translation.stm = self.stm
#
optimize_trace(metainterp_sd, loop, self.enable_opts)
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
@@ -187,14 +187,46 @@
raise AssertionError("bad result box type")
# ------------------------------
+ def _record_stm_transaction_break(self):
+ # 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, [])
+ mi.vrefs_after_residual_call()
+ mi.vable_after_residual_call()
+ mi.generate_guard(rop.GUARD_NOT_FORCED, None)
+
+
@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 (mi.stm_break_wanted or (val and not mi.stm_break_done)):
- mi.stm_break_done = True
+ if mi.stm_break_wanted:
+ # after call_release_gil and similar we want to have
+ # stm_transaction_break that may disable optimizations,
+ # but they would have been disabled anyways by the call
+ self._record_stm_transaction_break()
mi.stm_break_wanted = False
- # insert a CALL
+ return ConstInt(0)
+ elif val:
+ # Never ignore these. As long as we don't track the info
+ # if we are atomic, this could be the only possible
+ # transaction break in the loop (they are the most
+ # likely ones):
+ # loop: stmts -> inc_atomic -> stmts -> dec_atomic ->
+ # transaction_break -> loop_end
+ #
+ # we insert:
+ # i0 = call(should_break_transaction)
+ # stm_transaction_break()
+ # guard_not_forced()
+ # guard_false(i0)
+ #
+ # the stm_transaction_break() and its guard,
+ # OR
+ # the call(should_break_transaction) and its guard,
+ # or both are going to be removed by optimizeopt
resbox = history.BoxInt(0)
funcptr = mi.staticdata.stm_should_break_transaction
funcdescr = mi.staticdata.stm_should_break_transaction_descr
@@ -202,14 +234,21 @@
mi._record_helper_nonpure_varargs(
rop.CALL, resbox, funcdescr,
[ConstInt(heaptracker.adr2int(funcaddr)),])
+ #
+ # ALSO generate an stm_transaction_break
+ # This is needed to be able to transform the guard
+ # into an unconditional TB during optimizeopt
+ # if wanted...
+ self._record_stm_transaction_break()
+ #
return resbox
else:
+ # we ignore this one.
return ConstInt(0)
@arguments()
def opimpl_stm_transaction_break(self):
- self.metainterp._record_helper_nonpure_varargs(
- rop.STM_TRANSACTION_BREAK, None, None, [])
+ self._record_stm_transaction_break()
for _opimpl in ['int_add', 'int_sub', 'int_mul', 'int_floordiv', 'int_mod',
'int_lt', 'int_le', 'int_eq',
@@ -1703,7 +1742,7 @@
# for stm: placement of stm_break_point, used by MIFrame
self.stm_break_wanted = False
- self.stm_break_done = False
+ self.stm_insert_first_break = True
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
@@ -23,14 +23,22 @@
return rstm.jit_stm_should_break_transaction(False)
res = self.interp_operations(g, [], translationoptions={"stm":True})
assert res == False
- self.check_operations_history(call=1, call_may_force=1)
+ self.check_operations_history(stm_transaction_break=1, call_may_force=1)
+
+ 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(call=1, stm_transaction_break=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})
+ self.check_operations_history({'stm_transaction_break':1,
+ 'guard_not_forced':1})
More information about the pypy-commit
mailing list