[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