Author: Remi Meier <[email protected]>
Branch: stmgc-c7
Changeset: r70687:bd3323514386
Date: 2014-04-17 11:14 +0200
http://bitbucket.org/pypy/pypy/changeset/bd3323514386/
Log: try emitting less transaction breaks by adding some logic from
optimizeopt/stm.py to heapcache.
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
@@ -45,6 +45,13 @@
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)
@@ -120,6 +127,9 @@
opnum == rop.COPYSTRCONTENT or
opnum == rop.COPYUNICODECONTENT):
return
+ if opnum in (rop.GUARD_NOT_FORCED, rop.GUARD_NOT_FORCED_2):
+ self.stm_break_wanted = True
+ return
if (rop._OVF_FIRST <= opnum <= rop._OVF_LAST or
rop._NOSIDEEFFECT_FIRST <= opnum <= rop._NOSIDEEFFECT_LAST or
rop._GUARD_FIRST <= opnum <= rop._GUARD_LAST):
@@ -184,6 +194,7 @@
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():
@@ -202,6 +213,8 @@
self.heap_cache.clear()
self.heap_array_cache.clear()
+ self.stm_break_wanted = True
+
def is_class_known(self, box):
return box in self.known_class_boxes
@@ -308,3 +321,6 @@
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/pyjitpl.py
b/rpython/jit/metainterp/pyjitpl.py
--- a/rpython/jit/metainterp/pyjitpl.py
+++ b/rpython/jit/metainterp/pyjitpl.py
@@ -197,25 +197,33 @@
mi.vrefs_after_residual_call()
mi.vable_after_residual_call()
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):
- from rpython.rtyper.lltypesystem import llmemory
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:
- self._record_stm_transaction_break(False)
+ # 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)
-
+
for _opimpl in ['int_add', 'int_sub', 'int_mul', 'int_floordiv', 'int_mod',
'int_lt', 'int_le', 'int_eq',
'int_ne', 'int_gt', 'int_ge',
@@ -1692,7 +1700,7 @@
self.call_ids = []
self.current_call_id = 0
-
+
def retrace_needed(self, trace):
self.partial_trace = trace
@@ -1819,6 +1827,8 @@
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()
else:
diff --git a/rpython/jit/metainterp/test/test_heapcache.py
b/rpython/jit/metainterp/test/test_heapcache.py
--- a/rpython/jit/metainterp/test/test_heapcache.py
+++ b/rpython/jit/metainterp/test/test_heapcache.py
@@ -533,3 +533,27 @@
[]
)
assert h.getarrayitem(box1, index1, descr1) is box3
+
+ def test_stm_break(self):
+ h = HeapCache()
+ assert h.stm_break_wanted
+ h.stm_break_done()
+ assert not h.stm_break_wanted
+ # loop headers
+ h.reset()
+ assert h.stm_break_wanted
+ h.stm_break_done()
+ assert not h.stm_break_wanted
+ # call that may make the transaction inevitable
+ h.invalidate_caches(
+ rop.CALL, FakeCallDescr(FakeEffectinfo.EF_RANDOM_EFFECTS), [box1]
+ )
+ assert h.stm_break_wanted
+ h.stm_break_done()
+ # unknown op
+ h.invalidate_caches(rop.JIT_DEBUG, None, [box1, lengthbox2, box2])
+ assert h.stm_break_wanted
+ h.stm_break_done()
+ # GUARD_NOT_FORCED
+ h.invalidate_caches(rop.GUARD_NOT_FORCED, None, [])
+ assert h.stm_break_wanted
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
@@ -43,16 +43,29 @@
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(True) # keep (True)
+ rstm.jit_stm_should_break_transaction(True) # keep (True)
+ 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':1,
+ 'stm_should_break_transaction':3,
+ 'guard_not_forced':2,
+ 'guard_no_exception':1,
+ 'call_may_force':1})
+
+
+
class TestLLtype(STMTests, LLJitMixin):
pass
-
-
-
-
-
-
-
diff --git a/rpython/rlib/rstm.py b/rpython/rlib/rstm.py
--- a/rpython/rlib/rstm.py
+++ b/rpython/rlib/rstm.py
@@ -37,6 +37,7 @@
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
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit