Author: Remi Meier <remi.me...@inf.ethz.ch>
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)
 
+@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
_______________________________________________
pypy-commit mailing list
pypy-commit@python.org
https://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to