[pypy-commit] pypy stmgc-c7: Fix the handling of pypy_stm_nursery_low_fill_mark for what is hopefully all the cases.

arigo noreply at buildbot.pypy.org
Mon Mar 31 14:26:37 CEST 2014


Author: Armin Rigo <arigo at tunes.org>
Branch: stmgc-c7
Changeset: r70346:3616feaae9f8
Date: 2014-03-31 14:25 +0200
http://bitbucket.org/pypy/pypy/changeset/3616feaae9f8/

Log:	Fix the handling of pypy_stm_nursery_low_fill_mark for what is
	hopefully all the cases.

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
@@ -807,7 +807,7 @@
     def _call_footer(self):
         gcrootmap = self.cpu.gc_ll_descr.gcrootmap
         if self.cpu.gc_ll_descr.stm and we_are_translated():
-            # call _stm_become_inevitable() if the current jmpbuf is set
+            # call _pypy_stm_become_inevitable() if the current jmpbuf is set
             # to this frame, because we're about to leave.  This is if
             # we called a pypy_stm_start_transaction() earlier.
             assert IS_X86_64
@@ -822,9 +822,9 @@
             jne_location = mc.get_relative_pos()
             #
             # if they are equal, we need to become inevitable now
-            mc.MOV_ri(edi.value, rstm.adr_jit_default_msg)
-            mc.CALL(imm(rstm.adr__stm_become_inevitable))
-            # there could have been a collection in _stm_become_inevitable;
+            mc.XOR_rr(edi.value, edi.value)
+            mc.CALL(imm(rstm.adr__pypy_stm_become_inevitable))
+            # there could have been a collection in the call above;
             # reload the frame into ebp (but we don't need to apply the
             # write barrier to it now)
             mc.MOV(ecx, self.heap_shadowstack_top())
diff --git a/rpython/rlib/rstm.py b/rpython/rlib/rstm.py
--- a/rpython/rlib/rstm.py
+++ b/rpython/rlib/rstm.py
@@ -22,10 +22,8 @@
     CFlexSymbolic('((long)&STM_SEGMENT->jmpbuf_ptr)'))
 adr_write_slowpath = CFlexSymbolic('((long)&_stm_write_slowpath)')
 
-adr_jit_default_msg = (
-    CFlexSymbolic('((long)(char *)"return from JITted function")'))
-adr__stm_become_inevitable = (
-    CFlexSymbolic('((long)&_stm_become_inevitable)'))
+adr__pypy_stm_become_inevitable = (
+    CFlexSymbolic('((long)&_pypy_stm_become_inevitable)'))
 adr_stm_commit_transaction = (
     CFlexSymbolic('((long)&stm_commit_transaction)'))
 adr_pypy_stm_start_transaction = (
diff --git a/rpython/translator/stm/funcgen.py b/rpython/translator/stm/funcgen.py
--- a/rpython/translator/stm/funcgen.py
+++ b/rpython/translator/stm/funcgen.py
@@ -131,7 +131,7 @@
     except AttributeError:
         pass
     string_literal = c_string_constant(info)
-    return 'stm_become_inevitable(&stm_thread_local, %s);' % (string_literal,)
+    return 'pypy_stm_become_inevitable(%s);' % (string_literal,)
 
 def stm_become_globally_unique_transaction(funcgen, op):
     return ('stm_become_globally_unique_transaction(&stm_thread_local,'
diff --git a/rpython/translator/stm/src_stm/stmgcintf.c b/rpython/translator/stm/src_stm/stmgcintf.c
--- a/rpython/translator/stm/src_stm/stmgcintf.c
+++ b/rpython/translator/stm/src_stm/stmgcintf.c
@@ -14,8 +14,8 @@
 
 inline ssize_t stmcb_size_rounded_up(struct object_s *obj) {
     ssize_t result = pypy_stmcb_size_rounded_up(obj);
-    assert(result >= 16);
-    assert((result & 7) == 0);
+    OPT_ASSERT(result >= 16);
+    OPT_ASSERT((result & 7) == 0);
     return result;
 }
 
@@ -41,8 +41,8 @@
     /* the value '100' means 'use the default'.  Other values are
        interpreted proportionally, up to some maximum. */
     long low_fill_mark = (long)(LOW_FILL_MARK * fraction);
-    if (low_fill_mark > NURSERY_SIZE / 2)
-        low_fill_mark = NURSERY_SIZE / 2;
+    if (low_fill_mark > NURSERY_SIZE * 3 / 4)
+        low_fill_mark = NURSERY_SIZE * 3 / 4;
     pypy_transaction_length = low_fill_mark;
 }
 
@@ -141,8 +141,13 @@
     while (1) {
 
         if (pypy_stm_ready_atomic == 1) {
-            /* Not in an atomic transaction
+            /* Not in an atomic transaction; but it might be an inevitable
+               transaction.
              */
+            assert(pypy_stm_nursery_low_fill_mark != (uintptr_t) -1);
+            assert((STM_SEGMENT->jmpbuf_ptr == NULL) ==
+                   (pypy_stm_nursery_low_fill_mark == 0));
+
             stm_commit_transaction();
 
             /* After setjmp(), the local variables v_* are preserved because
@@ -173,6 +178,8 @@
            transaction whose jmpbuf points into this function
         */
         if (pypy_stm_ready_atomic == 1) {
+            assert(pypy_stm_nursery_low_fill_mark != 0);
+            assert(pypy_stm_nursery_low_fill_mark != (uintptr_t) -1);
             stm_commit_transaction();
             stm_start_inevitable_transaction(&stm_thread_local);
             pypy_stm_nursery_low_fill_mark = 0;
@@ -180,11 +187,36 @@
         else {
             _stm_become_inevitable("perform_transaction left with atomic");
             assert(pypy_stm_nursery_low_fill_mark == (uintptr_t) -1);
+            pypy_stm_nursery_low_fill_mark_saved = 0;
         }
     }
+    /* double-check */
+    if (pypy_stm_ready_atomic == 1) {
+        assert((STM_SEGMENT->jmpbuf_ptr == NULL) ==
+               (pypy_stm_nursery_low_fill_mark == 0));
+    }
+    else {
+        assert(pypy_stm_nursery_low_fill_mark == (uintptr_t) -1);
+    }
 
     //gcptr x = stm_pop_root();   /* pop the END_MARKER */
     //assert(x == END_MARKER_OFF || x == END_MARKER_ON);
     STM_POP_ROOT_RET(stm_thread_local);             /* pop the 'arg' */
     assert(v_old_shadowstack == stm_thread_local.shadowstack);
 }
+
+void _pypy_stm_become_inevitable(const char *msg)
+{
+    if (msg == NULL) {
+        msg = "return from JITted function";
+    }
+    _stm_become_inevitable(msg);
+
+    if (pypy_stm_ready_atomic == 1) {
+        pypy_stm_nursery_low_fill_mark = 0;
+    }
+    else {
+        assert(pypy_stm_nursery_low_fill_mark == (uintptr_t) -1);
+        pypy_stm_nursery_low_fill_mark_saved = 0;
+    }
+}
diff --git a/rpython/translator/stm/src_stm/stmgcintf.h b/rpython/translator/stm/src_stm/stmgcintf.h
--- a/rpython/translator/stm/src_stm/stmgcintf.h
+++ b/rpython/translator/stm/src_stm/stmgcintf.h
@@ -12,20 +12,34 @@
 extern __thread long pypy_stm_ready_atomic;
 extern __thread uintptr_t pypy_stm_nursery_low_fill_mark;
 extern __thread uintptr_t pypy_stm_nursery_low_fill_mark_saved;
+/* Invariant: if we're running a transaction:
+   - if it is atomic, pypy_stm_nursery_low_fill_mark == (uintptr_t) -1
+   - otherwise, if it is inevitable, pypy_stm_nursery_low_fill_mark == 0
+   - otherwise, it's a fraction of the nursery size strictly between 0 and 1
+*/
 
 void pypy_stm_setup(void);
 void pypy_stm_setup_prebuilt(void);        /* generated into stm_prebuilt.c */
 void pypy_stm_register_thread_local(void); /* generated into stm_prebuilt.c */
 void pypy_stm_unregister_thread_local(void); /* generated into stm_prebuilt.c */
 
+void _pypy_stm_become_inevitable(const char *);
+
+
+static inline void pypy_stm_become_inevitable(const char *msg)
+{
+    assert(STM_SEGMENT->running_thread == &stm_thread_local);
+    if (STM_SEGMENT->jmpbuf_ptr != NULL) {
+        _pypy_stm_become_inevitable(msg);
+    }
+}
 static inline void pypy_stm_commit_if_not_atomic(void) {
     int e = errno;
     if (pypy_stm_ready_atomic == 1) {
         stm_commit_transaction();
     }
     else {
-        stm_become_inevitable(&stm_thread_local,
-                              "commit_if_not_atomic in atomic");
+        pypy_stm_become_inevitable("commit_if_not_atomic in atomic");
     }
     errno = e;
 }
@@ -40,6 +54,7 @@
 static inline void pypy_stm_increment_atomic(void) {
     switch (++pypy_stm_ready_atomic) {
     case 2:
+        assert(pypy_stm_nursery_low_fill_mark != (uintptr_t) -1);
         pypy_stm_nursery_low_fill_mark_saved = pypy_stm_nursery_low_fill_mark;
         pypy_stm_nursery_low_fill_mark = (uintptr_t) -1;
         break;
@@ -51,6 +66,9 @@
     switch (--pypy_stm_ready_atomic) {
     case 1:
         pypy_stm_nursery_low_fill_mark = pypy_stm_nursery_low_fill_mark_saved;
+        assert(pypy_stm_nursery_low_fill_mark != (uintptr_t) -1);
+        assert((STM_SEGMENT->jmpbuf_ptr == NULL) ==
+               (pypy_stm_nursery_low_fill_mark == 0));
         break;
     case 0:
         pypy_stm_ready_atomic = 1;


More information about the pypy-commit mailing list