[pypy-commit] pypy stmgc-c4: Fix: cannot put the BUSY flag in the same counter modified in

arigo noreply at buildbot.pypy.org
Sat Oct 5 17:10:14 CEST 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: stmgc-c4
Changeset: r67159:e80585133345
Date: 2013-10-05 17:09 +0200
http://bitbucket.org/pypy/pypy/changeset/e80585133345/

Log:	Fix: cannot put the BUSY flag in the same counter modified in
	'stm_ignored' mode. We end up in cases where the guard's code is
	compiled twice, which crashes later in the x86 backend.

diff --git a/rpython/jit/metainterp/compile.py b/rpython/jit/metainterp/compile.py
--- a/rpython/jit/metainterp/compile.py
+++ b/rpython/jit/metainterp/compile.py
@@ -498,6 +498,9 @@
     rd_virtuals = None
     rd_pendingfields = lltype.nullptr(PENDINGFIELDSP.TO)
 
+    rd_stm_busy = False       # same as CNT_BUSY_FLAG, in a different field,
+                              # only for stm
+
     CNT_BASE_MASK  =  0x0FFFFFFF     # the base counter value
     CNT_BUSY_FLAG  =  0x10000000     # if set, busy tracing from the guard
     CNT_TYPE_MASK  =  0x60000000     # mask for the type
@@ -559,35 +562,35 @@
     _trace_and_compile_from_bridge._dont_inline_ = True
 
     def must_compile(self, deadframe, metainterp_sd, jitdriver_sd):
-        ok = self.must_compile_approx(deadframe, metainterp_sd, jitdriver_sd)
-        if not rgc.stm_is_enabled():
-            return ok
+        if rgc.stm_is_enabled():
+            method = self.must_compile_stm
         else:
-            # in stm mode, the return value may (rarely) be True even if a
-            # real, stm-protected read of self._counter says "busy".
-            return ok and not (self._counter & self.CNT_BUSY_FLAG)
+            method = self.must_compile_nonstm
+        return method(deadframe, metainterp_sd, jitdriver_sd)
 
-    def must_compile_approx(self, deadframe, metainterp_sd, jitdriver_sd):
+    def must_compile_stm(self, deadframe, metainterp_sd, jitdriver_sd):
+        trace_eagerness = jitdriver_sd.warmstate.trace_eagerness
+        with stm_ignored:
+            approx_counter = self._counter + 1
+            self._counter = approx_counter
+        return approx_counter >= trace_eagerness and not self.rd_stm_busy
+
+    def must_compile_nonstm(self, deadframe, metainterp_sd, jitdriver_sd):
         trace_eagerness = jitdriver_sd.warmstate.trace_eagerness
         #
-        with stm_ignored:
-            approx_counter = self._counter
-        if approx_counter <= self.CNT_BASE_MASK:
+        if self._counter <= self.CNT_BASE_MASK:
             # simple case: just counting from 0 to trace_eagerness
-            approx_counter += 1
-            with stm_ignored:
-                self._counter = approx_counter
-            return approx_counter >= trace_eagerness
+            self._counter += 1
+            return self._counter >= trace_eagerness
         #
         # do we have the BUSY flag?  If so, we're tracing right now, e.g. in an
         # outer invocation of the same function, so don't trace again for now.
-        elif approx_counter & self.CNT_BUSY_FLAG:
+        elif self._counter & self.CNT_BUSY_FLAG:
             return False
         #
         else: # we have a GUARD_VALUE that fails.  Make a _counters instance
             # (only now, when the guard is actually failing at least once),
             # and use it to record some statistics about the failing values.
-            assert not rgc.stm_is_enabled(), "XXX"
             index = self._counter & self.CNT_BASE_MASK
             typetag = self._counter & self.CNT_TYPE_MASK
             counters = self._counters
@@ -621,7 +624,10 @@
 
     def start_compiling(self):
         # start tracing and compiling from this guard.
-        self._counter |= self.CNT_BUSY_FLAG
+        if rgc.stm_is_enabled():
+            self.rd_stm_busy = True
+        else:
+            self._counter |= self.CNT_BUSY_FLAG
 
     def done_compiling(self):
         # done tracing and compiling from this guard.  Either the bridge has
@@ -629,8 +635,12 @@
         # in self._counter will not be seen any more, or not, in which case
         # we should reset the counter to 0, in order to wait a bit until the
         # next attempt.
-        if self._counter >= 0:
+        if rgc.stm_is_enabled():
+            self.rd_stm_busy = False
             self._counter = 0
+        else:
+            if self._counter >= 0:
+                self._counter = 0
         self._counters = None
 
     def compile_and_attach(self, metainterp, new_loop):


More information about the pypy-commit mailing list