[pypy-commit] pypy stmgc-c7-rewindjmp: Minimal set of changes to pass targetdemo2 while moving away from the
arigo
noreply at buildbot.pypy.org
Sat Aug 16 16:39:48 CEST 2014
Author: Armin Rigo <arigo at tunes.org>
Branch: stmgc-c7-rewindjmp
Changeset: r72824:459042b5f19d
Date: 2014-08-16 16:39 +0200
http://bitbucket.org/pypy/pypy/changeset/459042b5f19d/
Log: Minimal set of changes to pass targetdemo2 while moving away from
the stm_perform_*() model
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -18,7 +18,6 @@
from pypy.interpreter.nestedscope import Cell
from pypy.interpreter.pycode import PyCode, BytecodeCorruption
from pypy.tool.stdlib_opcode import bytecode_spec
-from rpython.rlib.jit import we_are_jitted
def unaryoperation(operationname):
"""NOT_RPYTHON"""
@@ -44,14 +43,6 @@
return func_with_new_name(opimpl, "opcode_impl_for_%s" % operationname)
-# ____________________________________________________________
-
-stmonly_jitdriver = jit.JitDriver(greens=[], reds=['next_instr', 'ec',
- 'self', 'co_code'],
- stm_do_transaction_breaks=True)
-
-# ____________________________________________________________
-
opcodedesc = bytecode_spec.opcodedesc
HAVE_ARGUMENT = bytecode_spec.HAVE_ARGUMENT
@@ -65,13 +56,8 @@
# For the sequel, force 'next_instr' to be unsigned for performance
next_instr = r_uint(next_instr)
co_code = pycode.co_code
+ rstm.rewind_jmp_frame()
while True:
- if self.space.config.translation.stm:
- # only used for no-jit. The jit-jitdriver is
- # in interp_jit.py
- stmonly_jitdriver.jit_merge_point(
- self=self, co_code=co_code,
- next_instr=next_instr, ec=ec)
rstm.push_marker(intmask(next_instr) * 2 + 1, self.pycode)
try:
next_instr = self.handle_bytecode(co_code, next_instr, ec)
@@ -165,6 +151,7 @@
ec.bytecode_only_trace(self)
else:
ec.bytecode_trace(self)
+ rstm.possible_transaction_break()
next_instr = r_uint(self.last_instr)
opcode = ord(co_code[next_instr])
next_instr += 1
@@ -199,7 +186,7 @@
else:
unroller = SReturnValue(w_returnvalue)
next_instr = block.handle(self, unroller)
- # now inside a 'finally' block
+ return next_instr # now inside a 'finally' block
elif opcode == opcodedesc.END_FINALLY.index:
unroller = self.end_finally()
if isinstance(unroller, SuspendedUnroller):
@@ -211,12 +198,13 @@
raise Return
else:
next_instr = block.handle(self, unroller)
+ return next_instr
elif opcode == opcodedesc.JUMP_ABSOLUTE.index:
return self.jump_absolute(oparg, ec)
elif opcode == opcodedesc.BREAK_LOOP.index:
next_instr = self.BREAK_LOOP(oparg, next_instr)
elif opcode == opcodedesc.CONTINUE_LOOP.index:
- next_instr = self.CONTINUE_LOOP(oparg, next_instr)
+ return self.CONTINUE_LOOP(oparg, next_instr)
elif opcode == opcodedesc.FOR_ITER.index:
next_instr = self.FOR_ITER(oparg, next_instr)
elif opcode == opcodedesc.JUMP_FORWARD.index:
@@ -457,22 +445,6 @@
if jit.we_are_jitted():
return next_instr
- if self.space.config.translation.stm:
- # with STM, if should_break_transaction(), then it is a good
- # idea to leave and let _dispatch_stm_breaking_transaction()
- # break the transaction. But avoid doing it if we are in a
- # tail-call position: if the next opcode is RETURN_VALUE, or
- # one of the opcodes in the one of the sequences
- # * POP_TOP/LOAD_CONST/RETURN_VALUE
- # * POP_TOP/LOAD_FAST/RETURN_VALUE
- if rstm.should_break_transaction():
- opcode = ord(co_code[next_instr])
- if opcode not in (opcodedesc.RETURN_VALUE.index,
- opcodedesc.POP_TOP.index,
- opcodedesc.LOAD_CONST.index,
- opcodedesc.LOAD_FAST.index):
- return next_instr
-
rstm.update_marker_num(intmask(next_instr) * 2 + 1)
@jit.unroll_safe
diff --git a/rpython/rlib/jit.py b/rpython/rlib/jit.py
--- a/rpython/rlib/jit.py
+++ b/rpython/rlib/jit.py
@@ -483,16 +483,12 @@
name = 'jitdriver'
inline_jit_merge_point = False
_store_last_enter_jit = None
- stm_do_transaction_breaks = False
- stm_report_location = None
def __init__(self, greens=None, reds=None, virtualizables=None,
get_jitcell_at=None, set_jitcell_at=None,
get_printable_location=None, confirm_enter_jit=None,
can_never_inline=None, should_unroll_one_iteration=None,
- name='jitdriver', check_untranslated=True,
- stm_do_transaction_breaks=None,
- stm_report_location=None):
+ name='jitdriver', check_untranslated=True):
if greens is not None:
self.greens = greens
self.name = name
@@ -528,10 +524,6 @@
self.can_never_inline = can_never_inline
self.should_unroll_one_iteration = should_unroll_one_iteration
self.check_untranslated = check_untranslated
- if stm_do_transaction_breaks is not None:
- self.stm_do_transaction_breaks = stm_do_transaction_breaks
- if stm_report_location is not None:
- self.stm_report_location = stm_report_location
def _freeze_(self):
return True
@@ -826,6 +818,9 @@
v_red = hop.inputarg(r_red, arg=i)
reds_v.append(v_red)
hop.exception_cannot_occur()
+ if self.instance.__name__ == 'jit_merge_point':
+ if hop.rtyper.annotator.translator.config.translation.stm:
+ hop.genop('stm_rewind_jmp_frame', [], resulttype=lltype.Void)
vlist = [hop.inputconst(lltype.Void, self.instance.__name__),
hop.inputconst(lltype.Void, driver)]
vlist.extend(greens_v)
diff --git a/rpython/rlib/rstm.py b/rpython/rlib/rstm.py
--- a/rpython/rlib/rstm.py
+++ b/rpython/rlib/rstm.py
@@ -1,5 +1,6 @@
from rpython.rlib.objectmodel import we_are_translated, specialize
from rpython.rlib.objectmodel import CDefinedIntSymbolic
+from rpython.rlib.rgc import stm_is_enabled
from rpython.rtyper.lltypesystem import lltype, rffi, rstr, llmemory
from rpython.rtyper.lltypesystem.lloperation import llop
from rpython.rtyper.extregistry import ExtRegistryEntry
@@ -40,6 +41,18 @@
CFlexSymbolic('((long)&pypy_stm_start_transaction)'))
+def rewind_jmp_frame():
+ """At some key places, like the entry point of the thread and in the
+ function with the interpreter's dispatch loop, this must be called
+ (it turns into a marker in the caller's function). There is one
+ automatically in any jit.jit_merge_point()."""
+ # special-cased below
+
+def possible_transaction_break():
+ if stm_is_enabled():
+ if llop.stm_should_break_transaction(lltype.Bool):
+ llop.stm_transaction_break(lltype.Void)
+
def jit_stm_transaction_break_point():
# XXX REFACTOR AWAY
if we_are_translated():
@@ -77,6 +90,10 @@
llop.stm_should_break_transaction(lltype.Bool))
@dont_look_inside
+def break_transaction():
+ llop.stm_break_transaction(lltype.Void)
+
+ at dont_look_inside
def set_transaction_length(fraction):
llop.stm_set_transaction_length(lltype.Void, float(fraction))
@@ -161,26 +178,13 @@
# ____________________________________________________________
-def make_perform_transaction(func, CONTAINERP):
- from rpython.rtyper.annlowlevel import llhelper
- from rpython.rtyper.annlowlevel import cast_instance_to_base_ptr
- from rpython.translator.stm.stmgcintf import CALLBACK_TX
- #
- def _stm_callback(llcontainer, retry_counter):
- llcontainer = rffi.cast(CONTAINERP, llcontainer)
- retry_counter = rffi.cast(lltype.Signed, retry_counter)
- try:
- res = func(llcontainer, retry_counter)
- except Exception, e:
- res = 0 # ends perform_transaction() and returns
- lle = cast_instance_to_base_ptr(e)
- llcontainer.got_exception = lle
- return rffi.cast(rffi.INT_real, res)
- #
- @dont_look_inside
- def perform_transaction(llcontainer):
- llcallback = llhelper(CALLBACK_TX, _stm_callback)
- llop.stm_perform_transaction(lltype.Void, llcontainer, llcallback)
- perform_transaction._transaction_break_ = True
- #
- return perform_transaction
+class _Entry(ExtRegistryEntry):
+ _about_ = rewind_jmp_frame
+
+ def compute_result_annotation(self):
+ pass
+
+ def specialize_call(self, hop):
+ hop.exception_cannot_occur()
+ if hop.rtyper.annotator.translator.config.translation.stm:
+ hop.genop('stm_rewind_jmp_frame', [], resulttype=lltype.Void)
diff --git a/rpython/rtyper/lltypesystem/lloperation.py b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -434,8 +434,9 @@
'stm_abort_and_retry': LLOp(canmallocgc=True),
'stm_enter_callback_call': LLOp(canmallocgc=True),
'stm_leave_callback_call': LLOp(),
- 'stm_perform_transaction': LLOp(canmallocgc=True),
+ 'stm_transaction_break': LLOp(canmallocgc=True),
'stm_should_break_transaction': LLOp(sideeffects=False),
+ 'stm_rewind_jmp_frame': LLOp(),
'stm_set_transaction_length': LLOp(),
'stm_hint_commit_soon': LLOp(canrun=True),
diff --git a/rpython/rtyper/lltypesystem/rffi.py b/rpython/rtyper/lltypesystem/rffi.py
--- a/rpython/rtyper/lltypesystem/rffi.py
+++ b/rpython/rtyper/lltypesystem/rffi.py
@@ -318,8 +318,11 @@
if aroundstate is not None:
if aroundstate.enter_callback is not None:
token = aroundstate.enter_callback()
- elif aroundstate.after is not None:
- aroundstate.after()
+ llop.stm_rewind_jmp_frame(lltype.Void, 1)
+ else:
+ after = aroundstate.after
+ if after is not None:
+ after()
# from now on we hold the GIL
stackcounter.stacks_counter += 1
llop.gc_stack_bottom(lltype.Void) # marker for trackgcroot.py
@@ -336,9 +339,12 @@
stackcounter.stacks_counter -= 1
if aroundstate is not None:
if aroundstate.leave_callback is not None:
+ llop.stm_rewind_jmp_frame(lltype.Void, 2)
aroundstate.leave_callback(token)
- elif aroundstate.before is not None:
- aroundstate.before()
+ else:
+ before = aroundstate.before
+ if before is not None:
+ before()
# here we don't hold the GIL any more. As in the wrapper() produced
# by llexternal, it is essential that no exception checking occurs
# after the call to before().
diff --git a/rpython/translator/backendopt/gilanalysis.py b/rpython/translator/backendopt/gilanalysis.py
--- a/rpython/translator/backendopt/gilanalysis.py
+++ b/rpython/translator/backendopt/gilanalysis.py
@@ -21,13 +21,11 @@
self, graph, seen)
def analyze_external_call(self, op, seen=None):
- funcobj = op.args[0].value._obj
- if getattr(funcobj, 'transactionsafe', False):
- return False
- else:
- return False
-
+ return False
+
def analyze_simple_operation(self, op, graphinfo):
+ if op.opname == 'stm_break_transaction':
+ return True
return False
def analyze(graphs, translator):
diff --git a/rpython/translator/c/funcgen.py b/rpython/translator/c/funcgen.py
--- a/rpython/translator/c/funcgen.py
+++ b/rpython/translator/c/funcgen.py
@@ -1,5 +1,4 @@
import sys
-from rpython.translator.c.support import USESLOTS # set to False if necessary while refactoring
from rpython.translator.c.support import cdecl
from rpython.translator.c.support import llvalue_from_constant, gen_assignments
from rpython.translator.c.support import c_string_constant, barebonearray
@@ -24,17 +23,7 @@
Collects information about a function which we have to generate
from a flow graph.
"""
-
- if USESLOTS:
- __slots__ = """graph db gcpolicy
- exception_policy
- more_ll_values
- vars all_cached_consts
- illtypes
- functionname
- blocknum
- innerloops
- oldgraph""".split()
+ use_stm_rewind_jmp_frame = False
def __init__(self, graph, db, exception_policy=None, functionname=None):
graph._seen_by_the_backend = True
@@ -75,6 +64,11 @@
for block in self.graph.iterblocks():
mix.extend(block.inputargs)
for op in block.operations:
+ if op.opname == 'stm_rewind_jmp_frame':
+ if len(op.args) == 0:
+ self.use_stm_rewind_jmp_frame = "automatic"
+ elif not self.use_stm_rewind_jmp_frame:
+ self.use_stm_rewind_jmp_frame = True
mix.extend(op.args)
mix.append(op.result)
for link in block.exits:
@@ -203,6 +197,11 @@
# ____________________________________________________________
def cfunction_body(self):
+ if self.use_stm_rewind_jmp_frame:
+ yield 'rewind_jmp_buf rjbuf1;'
+ if self.use_stm_rewind_jmp_frame == "automatic":
+ yield 'stm_rewind_jmp_enterframe(&stm_thread_local, &rjbuf1);'
+ #
graph = self.graph
yield 'goto block0;' # to avoid a warning "this label is not used"
@@ -221,6 +220,9 @@
if len(block.exits) == 0:
assert len(block.inputargs) == 1
# regular return block
+ if self.use_stm_rewind_jmp_frame == "automatic":
+ yield ('stm_rewind_jmp_leaveframe('
+ '&stm_thread_local, &rjbuf1);')
retval = self.expr(block.inputargs[0])
if self.exception_policy != "exc_helper":
yield 'RPY_DEBUG_RETURN();'
@@ -920,5 +922,3 @@
self.expr(op.args[0]))
else:
return None # use the default
-
-assert not USESLOTS or '__dict__' not in dir(FunctionCodeGenerator)
diff --git a/rpython/translator/c/src/entrypoint.c b/rpython/translator/c/src/entrypoint.c
--- a/rpython/translator/c/src/entrypoint.c
+++ b/rpython/translator/c/src/entrypoint.c
@@ -49,6 +49,11 @@
errmsg = RPython_StartupCode();
if (errmsg) goto error;
+#ifdef RPY_STM
+ rewind_jmp_buf rjbuf;
+ stm_rewind_jmp_enterframe(&stm_thread_local, &rjbuf);
+#endif
+
exitcode = STANDALONE_ENTRY_POINT(argc, argv);
pypy_debug_alloc_results();
@@ -60,6 +65,10 @@
pypy_malloc_counters_results();
+#ifdef RPY_STM
+ stm_rewind_jmp_leaveframe(&stm_thread_local, &rjbuf);
+#endif
+
RPython_TeardownCode();
return exitcode;
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
@@ -175,11 +175,8 @@
arg0 = funcgen.expr(op.args[0])
return 'pypy_stm_set_transaction_length(%s);' % (arg0,)
-def stm_perform_transaction(funcgen, op):
- arg0 = funcgen.expr(op.args[0])
- arg1 = funcgen.expr(op.args[1])
- return ('pypy_stm_perform_transaction((object_t *)%s, '
- '(int(*)(object_t *, int))%s);' % (arg0, arg1))
+def stm_transaction_break(funcgen, op):
+ return 'pypy_stm_transaction_break();'
def stm_increment_atomic(funcgen, op):
return 'pypy_stm_increment_atomic();'
@@ -259,3 +256,11 @@
'stm_thread_local.longest_marker_time = 0.0;\n'
'stm_thread_local.longest_marker_self[0] = 0;\n'
'stm_thread_local.longest_marker_other[0] = 0;')
+
+def stm_rewind_jmp_frame(funcgen, op):
+ if len(op.args) == 0:
+ return '/* automatic stm_rewind_jmp_frame */'
+ elif op.args[0].value == 1:
+ return 'stm_rewind_jmp_enterframe(&stm_thread_local, &rjbuf1);'
+ else:
+ return 'stm_rewind_jmp_leaveframe(&stm_thread_local, &rjbuf1);'
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
@@ -167,55 +167,11 @@
return counter;
}
-void pypy_stm_perform_transaction(object_t *arg, int callback(object_t *, int))
-{ /* must save roots around this call */
- //
- // XXX this function should be killed! We no longer need a
- // callback-based approach at all.
-
-#ifndef NDEBUG
- struct stm_shadowentry_s *volatile v_old_shadowstack =
- stm_thread_local.shadowstack;
-#endif
- rewind_jmp_buf rjbuf;
- stm_rewind_jmp_enterframe(&stm_thread_local, &rjbuf);
- //STM_PUSH_ROOT(stm_thread_local, STM_STACK_MARKER_NEW);
- STM_PUSH_ROOT(stm_thread_local, arg);
-
- while (1) {
- long counter;
- if (pypy_stm_should_break_transaction()) { //pypy_stm_ready_atomic == 1) {
- /* Not in an atomic transaction; but it might be an inevitable
- transaction.
- */
- assert(pypy_stm_nursery_low_fill_mark != (uintptr_t) -1);
-
- stm_commit_transaction();
-
- counter = _pypy_stm_start_transaction();
- }
- else {
- /* In an atomic transaction */
- //assert(pypy_stm_nursery_low_fill_mark == (uintptr_t) -1);
- counter = 0;
- }
-
- /* invoke the callback in the new transaction */
- STM_POP_ROOT(stm_thread_local, arg);
- assert(v_old_shadowstack == stm_thread_local.shadowstack);// - 1);
- STM_PUSH_ROOT(stm_thread_local, arg);
-
- long result = callback(arg, counter);
- if (result <= 0)
- break;
- }
-
- STM_POP_ROOT_RET(stm_thread_local); /* pop the 'arg' */
- //uintptr_t x = (uintptr_t)STM_POP_ROOT_RET(stm_thread_local);
- //assert(x == STM_STACK_MARKER_NEW || x == STM_STACK_MARKER_OLD);
- assert(v_old_shadowstack == stm_thread_local.shadowstack);
-
- stm_rewind_jmp_leaveframe(&stm_thread_local, &rjbuf);
+void pypy_stm_transaction_break(void)
+{
+ assert(pypy_stm_nursery_low_fill_mark != (uintptr_t) -1);
+ stm_commit_transaction();
+ _pypy_stm_start_transaction();
}
void _pypy_stm_inev_state(void)
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
@@ -92,7 +92,7 @@
long pypy_stm_enter_callback_call(void);
void pypy_stm_leave_callback_call(long);
void pypy_stm_set_transaction_length(double);
-void pypy_stm_perform_transaction(object_t *, int(object_t *, int));//XXX
+void pypy_stm_transaction_break(void);
static inline int pypy_stm_should_break_transaction(void)
{
diff --git a/rpython/translator/stm/test/targetdemo2.py b/rpython/translator/stm/test/targetdemo2.py
--- a/rpython/translator/stm/test/targetdemo2.py
+++ b/rpython/translator/stm/test/targetdemo2.py
@@ -1,6 +1,6 @@
import time
from rpython.rlib import rthread
-from rpython.rlib import rstm, jit
+from rpython.rlib import rstm
from rpython.rlib.objectmodel import we_are_translated
from rpython.rlib.objectmodel import compute_identity_hash
from rpython.rlib.debug import ll_assert
@@ -65,12 +65,6 @@
print "check ok!"
-jitdriver_hash = jit.JitDriver(greens=[], reds=['value', 'self'])
-jitdriver_inev = jit.JitDriver(greens=[], reds=['value', 'self'])
-jitdriver_ptreq = jit.JitDriver(greens=[], reds=['self'])
-jitdriver_really = jit.JitDriver(greens=[], reds=['value', 'self'])
-
-
class ThreadRunner(object):
arg = None
@@ -94,7 +88,7 @@
def do_run_really(self):
value = 0
while True:
- jitdriver_really.jit_merge_point(self=self, value=value)
+ rstm.possible_transaction_break()
if not self.run_really(value):
break
value += 1
@@ -115,7 +109,7 @@
return (value+1) < glob.LENGTH
def do_check_ptr_equality(self):
- jitdriver_ptreq.jit_merge_point(self=self)
+ rstm.possible_transaction_break()
self.check_ptr_equality(0)
def check_ptr_equality(self, foo):
@@ -129,7 +123,7 @@
def do_check_inev(self):
value = 0
while True:
- jitdriver_inev.jit_merge_point(self=self, value=value)
+ rstm.possible_transaction_break()
if not self.check_inev(value):
break
value += 1
@@ -157,7 +151,7 @@
def do_check_hash(self):
value = 0
while True:
- jitdriver_hash.jit_merge_point(self=self, value=value)
+ rstm.possible_transaction_break()
value = self.check_hash(value)
if value >= glob.LENGTH:
break
More information about the pypy-commit
mailing list