[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