Commits

Remi Meier committed 867a7c2 Merge

Merge with stm-thread-2

Comments (0)

Files changed (9)

 ------------------------------------------------------------
 
 implement thread-locals in RPython (for the executioncontext)
+
+------------------------------------------------------------
+
+optimize the static placement of the STM_XxxBARRIERs

pypy/interpreter/executioncontext.py

         #
         config = self.space.config
         if config.translation.stm and config.objspace.std.withmethodcache:
-                from pypy.objspace.std.typeobject import MethodCache
-                self._methodcache = MethodCache(self.space)
-
+            from pypy.objspace.std.typeobject import MethodCache
+            self._methodcache = MethodCache(self.space)
 
     def gettopframe(self):
         return self.topframeref()
         assert isinstance(action, PeriodicAsyncAction)
         self._periodic_actions.append(action)
         if use_bytecode_counter:
+            assert not action.space.config.translation.stm, (
+                "Cannot use the bytecode counter with STM")
             self.has_bytecode_counter = True
         self._rebuild_action_dispatcher()
 

pypy/module/signal/__init__.py

     }
 
     def buildloaders(cls):
-        from pypy.module.signal import interp_signal
-        for name in interp_signal.signal_names:
-            signum = getattr(interp_signal, name)
+        from pypy.rlib import rsignal
+        for name in rsignal.signal_names:
+            signum = getattr(rsignal, name)
             if signum is not None:
                 Module.interpleveldefs[name] = 'space.wrap(%d)' % (signum,)
         super(Module, cls).buildloaders()

pypy/module/signal/interp_signal.py

 from __future__ import with_statement
+
+import signal as cpy_signal
+
 from pypy.interpreter.error import OperationError, exception_from_errno
-from pypy.interpreter.executioncontext import AsyncAction, AbstractActionFlag
-from pypy.interpreter.executioncontext import PeriodicAsyncAction
+from pypy.interpreter.executioncontext import (AsyncAction, AbstractActionFlag,
+    PeriodicAsyncAction)
 from pypy.interpreter.gateway import unwrap_spec
-import signal as cpy_signal
+
+from pypy.rlib import jit, rposix
+from pypy.rlib.rarithmetic import intmask
+from pypy.rlib.rsignal import (pypysig_getaddr_occurred, pypysig_setflag,
+    pypysig_poll, pypysig_reinstall, pypysig_ignore, pypysig_default,
+    pypysig_set_wakeup_fd, c_alarm, c_pause, c_getitimer, c_setitimer,
+    c_siginterrupt, itimervalP, NSIG, SIG_DFL, SIG_IGN, ITIMER_REAL,
+    ITIMER_PROF, ITIMER_VIRTUAL, signal_values)
 from pypy.rpython.lltypesystem import lltype, rffi
-from pypy.rpython.tool import rffi_platform
-from pypy.translator.tool.cbuild import ExternalCompilationInfo
-import py
-import sys
-from pypy.tool import autopath
-from pypy.rlib import jit, rposix
-from pypy.rlib.rarithmetic import intmask, is_valid_int
-
-def setup():
-    for key, value in cpy_signal.__dict__.items():
-        if (key.startswith('SIG') or key.startswith('CTRL_')) and \
-                is_valid_int(value) and \
-                key != 'SIG_DFL' and key != 'SIG_IGN':
-            globals()[key] = value
-            yield key
-
-NSIG    = cpy_signal.NSIG
-SIG_DFL = cpy_signal.SIG_DFL
-SIG_IGN = cpy_signal.SIG_IGN
-signal_names = list(setup())
-signal_values = {}
-for key in signal_names:
-    signal_values[globals()[key]] = None
-if sys.platform == 'win32' and not hasattr(cpy_signal,'CTRL_C_EVENT'):
-    # XXX Hack to revive values that went missing,
-    #     Remove this once we are sure the host cpy module has them.
-    signal_values[0] = None
-    signal_values[1] = None
-    signal_names.append('CTRL_C_EVENT')
-    signal_names.append('CTRL_BREAK_EVENT')
-    CTRL_C_EVENT = 0
-    CTRL_BREAK_EVENT = 1
-includes = ['stdlib.h', 'src/signals.h']
-if sys.platform != 'win32':
-    includes.append('sys/time.h')
-
-cdir = py.path.local(autopath.pypydir).join('translator', 'c')
-
-eci = ExternalCompilationInfo(
-    includes = includes,
-    separate_module_files = [cdir / 'src' / 'signals.c'],
-    include_dirs = [str(cdir)],
-    export_symbols = ['pypysig_poll', 'pypysig_default',
-                      'pypysig_ignore', 'pypysig_setflag',
-                      'pypysig_reinstall',
-                      'pypysig_set_wakeup_fd',
-                      'pypysig_getaddr_occurred'],
-)
-
-class CConfig:
-    _compilation_info_ = eci
-
-if sys.platform != 'win32':
-    for name in """ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF""".split():
-        setattr(CConfig, name, rffi_platform.DefinedConstantInteger(name))
-
-    CConfig.timeval = rffi_platform.Struct(
-        'struct timeval',
-        [('tv_sec', rffi.LONG),
-         ('tv_usec', rffi.LONG)])
-
-    CConfig.itimerval = rffi_platform.Struct(
-        'struct itimerval',
-        [('it_value', CConfig.timeval),
-         ('it_interval', CConfig.timeval)])
-
-for k, v in rffi_platform.configure(CConfig).items():
-    globals()[k] = v
-
-def external(name, args, result, **kwds):
-    return rffi.llexternal(name, args, result, compilation_info=eci,
-                           sandboxsafe=True, **kwds)
-
-pypysig_ignore = external('pypysig_ignore', [rffi.INT], lltype.Void)
-pypysig_default = external('pypysig_default', [rffi.INT], lltype.Void)
-pypysig_setflag = external('pypysig_setflag', [rffi.INT], lltype.Void)
-pypysig_reinstall = external('pypysig_reinstall', [rffi.INT], lltype.Void)
-pypysig_set_wakeup_fd = external('pypysig_set_wakeup_fd', [rffi.INT], rffi.INT)
-pypysig_poll = external('pypysig_poll', [], rffi.INT, threadsafe=False)
-# don't bother releasing the GIL around a call to pypysig_poll: it's
-# pointless and a performance issue
-
-# don't use rffi.LONGP because the JIT doesn't support raw arrays so far
-struct_name = 'pypysig_long_struct'
-LONG_STRUCT = lltype.Struct(struct_name, ('c_value', lltype.Signed),
-                            hints={'c_name' : struct_name, 'external' : 'C'})
-del struct_name
-
-pypysig_getaddr_occurred = external('pypysig_getaddr_occurred', [],
-                                    lltype.Ptr(LONG_STRUCT), _nowrapper=True,
-                                    elidable_function=True)
-c_alarm = external('alarm', [rffi.INT], rffi.INT)
-c_pause = external('pause', [], rffi.INT, threadsafe=True)
-c_siginterrupt = external('siginterrupt', [rffi.INT, rffi.INT], rffi.INT)
-
-if sys.platform != 'win32':
-    itimervalP = rffi.CArrayPtr(itimerval)
-    c_setitimer = external('setitimer',
-                           [rffi.INT, itimervalP, itimervalP], rffi.INT)
-    c_getitimer = external('getitimer', [rffi.INT, itimervalP], rffi.INT)
 
 
 class SignalActionFlag(AbstractActionFlag):
     # This class uses the C-level pypysig_counter variable as the tick
     # counter.  The C-level signal handler will reset it to -1 whenever
-    # a signal is received.
+    # a signal is received.  This causes CheckSignalAction.perform() to
+    # be called.
 
     def get_ticker(self):
         p = pypysig_getaddr_occurred()
     def __init__(self, space):
         AsyncAction.__init__(self, space)
         self.handlers_w = {}
-        if space.config.objspace.usemodules.thread:
-            # need a helper action in case signals arrive in a non-main thread
-            self.pending_signals = {}
-            self.reissue_signal_action = ReissueSignalAction(space)
-        else:
-            self.reissue_signal_action = None
+        self.emulated_sigint = False
 
     @jit.dont_look_inside
     def perform(self, executioncontext, frame):
-        while True:
-            n = pypysig_poll()
-            if n < 0:
-                break
-            self.perform_signal(executioncontext, n)
-
-    @jit.dont_look_inside
-    def perform_signal(self, executioncontext, n):
-        if self.reissue_signal_action is None:
-            # no threads: we can report the signal immediately
-            self.report_signal(n)
+        if self.space.config.objspace.usemodules.thread:
+            main_ec = self.space.threadlocals.getmainthreadvalue()
+            in_main = executioncontext is main_ec
         else:
-            main_ec = self.space.threadlocals.getmainthreadvalue()
-            if executioncontext is main_ec:
-                # running in the main thread: we can report the
-                # signal immediately
-                self.report_signal(n)
-            else:
-                # running in another thread: we need to hack a bit
-                self.pending_signals[n] = None
-                self.reissue_signal_action.fire_after_thread_switch()
+            in_main = True
+        # If we are in the main thread, poll and report the signals now.
+        if in_main:
+            if self.emulated_sigint:
+                self.emulated_sigint = False
+                self._report_signal(cpy_signal.SIGINT)
+            while True:
+                n = pypysig_poll()
+                if n < 0:
+                    break
+                self._report_signal(n)
+        else:
+            # Otherwise, don't call pypysig_poll() at all.  Instead,
+            # arrange for perform() to be called again after a thread
+            # switch.  It might be called again and again, until we
+            # land in the main thread.
+            self.fire_after_thread_switch()
 
     @jit.dont_look_inside
     def set_interrupt(self):
         "Simulates the effect of a SIGINT signal arriving"
         ec = self.space.getexecutioncontext()
-        self.perform_signal(ec, cpy_signal.SIGINT)
+        self.emulated_sigint = True
+        self.perform(ec, None)
 
-    @jit.dont_look_inside
-    def report_signal(self, n):
+    def _report_signal(self, n):
         try:
             w_handler = self.handlers_w[n]
         except KeyError:
         w_frame = space.wrap(ec.gettopframe_nohidden())
         space.call_function(w_handler, space.wrap(n), w_frame)
 
-    @jit.dont_look_inside
-    def report_pending_signals(self):
-        # XXX this logic isn't so complicated but I have no clue how
-        # to test it :-(
-        pending_signals = self.pending_signals.keys()
-        self.pending_signals.clear()
-        try:
-            while pending_signals:
-                self.report_signal(pending_signals.pop())
-        finally:
-            # in case of exception, put the undelivered signals back
-            # into the dict instead of silently swallowing them
-            if pending_signals:
-                for n in pending_signals:
-                    self.pending_signals[n] = None
-                self.reissue_signal_action.fire()
-
-
-class ReissueSignalAction(AsyncAction):
-    """A special action to help deliver signals to the main thread.  If
-    a non-main thread caught a signal, this action fires after every
-    thread switch until we land in the main thread.
-    """
-
-    def perform(self, executioncontext, frame):
-        main_ec = self.space.threadlocals.getmainthreadvalue()
-        if executioncontext is main_ec:
-            # now running in the main thread: we can really report the signals
-            self.space.check_signal_action.report_pending_signals()
-        else:
-            # still running in some other thread: try again later
-            self.fire_after_thread_switch()
-
 
 @unwrap_spec(signum=int)
 def getsignal(space, signum):

pypy/rlib/rsignal.py

+import signal as cpy_signal
+import sys
+import py
+from pypy.tool import autopath
+from pypy.rpython.tool import rffi_platform
+from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.translator.tool.cbuild import ExternalCompilationInfo
+from pypy.rlib.rarithmetic import is_valid_int
+
+def setup():
+    for key, value in cpy_signal.__dict__.items():
+        if (key.startswith('SIG') or key.startswith('CTRL_')) and \
+                is_valid_int(value) and \
+                key != 'SIG_DFL' and key != 'SIG_IGN':
+            globals()[key] = value
+            yield key
+
+NSIG    = cpy_signal.NSIG
+SIG_DFL = cpy_signal.SIG_DFL
+SIG_IGN = cpy_signal.SIG_IGN
+signal_names = list(setup())
+signal_values = {}
+for key in signal_names:
+    signal_values[globals()[key]] = None
+if sys.platform == 'win32' and not hasattr(cpy_signal,'CTRL_C_EVENT'):
+    # XXX Hack to revive values that went missing,
+    #     Remove this once we are sure the host cpy module has them.
+    signal_values[0] = None
+    signal_values[1] = None
+    signal_names.append('CTRL_C_EVENT')
+    signal_names.append('CTRL_BREAK_EVENT')
+    CTRL_C_EVENT = 0
+    CTRL_BREAK_EVENT = 1
+includes = ['stdlib.h', 'src/signals.h']
+if sys.platform != 'win32':
+    includes.append('sys/time.h')
+
+cdir = py.path.local(autopath.pypydir).join('translator', 'c')
+
+eci = ExternalCompilationInfo(
+    includes = includes,
+    separate_module_files = [cdir / 'src' / 'signals.c'],
+    include_dirs = [str(cdir)],
+    export_symbols = ['pypysig_poll', 'pypysig_default',
+                      'pypysig_ignore', 'pypysig_setflag',
+                      'pypysig_reinstall',
+                      'pypysig_set_wakeup_fd',
+                      'pypysig_getaddr_occurred'],
+)
+
+class CConfig:
+    _compilation_info_ = eci
+
+if sys.platform != 'win32':
+    for name in """ITIMER_REAL ITIMER_VIRTUAL ITIMER_PROF""".split():
+        setattr(CConfig, name, rffi_platform.DefinedConstantInteger(name))
+
+    CConfig.timeval = rffi_platform.Struct(
+        'struct timeval',
+        [('tv_sec', rffi.LONG),
+         ('tv_usec', rffi.LONG)])
+
+    CConfig.itimerval = rffi_platform.Struct(
+        'struct itimerval',
+        [('it_value', CConfig.timeval),
+         ('it_interval', CConfig.timeval)])
+
+for k, v in rffi_platform.configure(CConfig).items():
+    globals()[k] = v
+
+def external(name, args, result, **kwds):
+    return rffi.llexternal(name, args, result, compilation_info=eci,
+                           sandboxsafe=True, **kwds)
+
+pypysig_ignore = external('pypysig_ignore', [rffi.INT], lltype.Void)
+pypysig_default = external('pypysig_default', [rffi.INT], lltype.Void)
+pypysig_setflag = external('pypysig_setflag', [rffi.INT], lltype.Void)
+pypysig_reinstall = external('pypysig_reinstall', [rffi.INT], lltype.Void)
+pypysig_set_wakeup_fd = external('pypysig_set_wakeup_fd', [rffi.INT], rffi.INT)
+pypysig_poll = external('pypysig_poll', [], rffi.INT, threadsafe=False)
+# don't bother releasing the GIL around a call to pypysig_poll: it's
+# pointless and a performance issue
+
+# don't use rffi.LONGP because the JIT doesn't support raw arrays so far
+struct_name = 'pypysig_long_struct'
+LONG_STRUCT = lltype.Struct(struct_name, ('c_value', lltype.Signed),
+                            hints={'c_name' : struct_name, 'external' : 'C'})
+del struct_name
+
+pypysig_getaddr_occurred = external('pypysig_getaddr_occurred', [],
+                                    lltype.Ptr(LONG_STRUCT), _nowrapper=True,
+                                    transactionsafe=True,
+                                    elidable_function=True)
+c_alarm = external('alarm', [rffi.INT], rffi.INT)
+c_pause = external('pause', [], rffi.INT, threadsafe=True)
+c_siginterrupt = external('siginterrupt', [rffi.INT, rffi.INT], rffi.INT)
+
+if sys.platform != 'win32':
+    itimervalP = rffi.CArrayPtr(itimerval)
+    c_setitimer = external('setitimer',
+                           [rffi.INT, itimervalP, itimervalP], rffi.INT)
+    c_getitimer = external('getitimer', [rffi.INT, itimervalP], rffi.INT)

pypy/rpython/memory/gc/stmshared.py

 
     def add_regular(self, obj):
         """After malloc_object(), register the object in the internal chained
-        list.  For objects whose 'version' field is not otherwise needed."""
+        list.  For objects whose 'revision' field is not otherwise needed."""
         self.gc.set_obj_revision(obj, self.chained_list)
         self.chained_list = obj
 

pypy/rpython/memory/gc/test/test_stmgc.py

 import py
+from pypy.rlib.rarithmetic import r_uint
 from pypy.rpython.lltypesystem import lltype, llmemory, llarena, llgroup, rffi
-from pypy.rpython.memory.gc.stmgc import StmGC, WORD
+from pypy.rpython.memory.gc.stmgc import StmGC, WORD, REV_INITIAL
 from pypy.rpython.memory.gc.stmgc import GCFLAG_GLOBAL, GCFLAG_NOT_WRITTEN
 from pypy.rpython.memory.gc.stmgc import GCFLAG_POSSIBLY_OUTDATED
 from pypy.rpython.memory.gc.stmgc import GCFLAG_LOCAL_COPY, GCFLAG_VISITED
-from pypy.rpython.memory.gc.stmgc import GCFLAG_HASH_FIELD, REV_FLAG_NEW_HASH
+from pypy.rpython.memory.gc.stmgc import GCFLAG_HASH_FIELD
 from pypy.rpython.memory.gc.stmgc import hdr_revision, set_hdr_revision
 from pypy.rpython.memory.support import mangle_hash
 
                     == key)
             callback(tls, value)
 
-    def stm_HashObject(self, P):
-        # see et.c
-        hdr = self._gc.header(P)
-        if hdr.tid & (GCFLAG_GLOBAL|GCFLAG_LOCAL_COPY) == 0:
-            hdr.revision |= REV_FLAG_NEW_HASH
-            return P
-
-        while True:
-            hdr = self._gc.header(P)
-            if hdr.tid & GCFLAG_HASH_FIELD:
-                return P
-            v = hdr.revision
-            if isinstance(v, llmemory.AddressAsInt):   # "is a pointer"
-                P = llmemory.cast_int_to_adr(v)
-            else:
-                # add the flag without caring about atomicity here
-                hdr.revision = v | REV_FLAG_NEW_HASH
-                return P
-
 
 def fake_get_size(obj):
     TYPE = obj.ptr._TYPE.TO
             addr = adr1 + self.gc.gcheaderbuilder.size_gc_header
             self.gc.header(addr).tid = self.gc.combine(
                 tid, GCFLAG_GLOBAL | GCFLAG_NOT_WRITTEN)
+            self.gc.header(addr).revision = REV_INITIAL
             realobj = llmemory.cast_adr_to_ptr(addr, lltype.Ptr(STRUCT))
         else:
             gcref = self.gc.malloc_fixedsize_clear(tid, size,
                                                    contains_weakptr=weakref)
             realobj = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), gcref)
-            addr = llmemory.cast_ptr_to_adr(realobj)
-        return realobj, addr
+        return realobj
     def select_thread(self, threadnum):
         self.gc.stm_operations.threadnum = threadnum
         if threadnum not in self.gc.stm_operations._tls_dict:
         if must_have_version != '?':
             assert hdr.version == must_have_version
 
-    def stm_writebarrier(self, P):
+    def header(self, P):
         if lltype.typeOf(P) != llmemory.Address:
             P = llmemory.cast_ptr_to_adr(P)
-        hdr = self.gc.header(P)
+        return self.gc.header(P)
+
+    def set_hdr_revision(self, hdr, P):
+        if lltype.typeOf(P) != llmemory.Address:
+            P = llmemory.cast_ptr_to_adr(P)
+        set_hdr_revision(hdr, P)
+
+    def stm_readbarrier(self, P):
+        hdr = self.header(P)
+        if hdr.tid & GCFLAG_GLOBAL == 0:
+            # already a local object
+            R = P
+        else:
+            R = self.stm_latest_global_rev(P)
+            L = self.gc.stm_operations.tldict_lookup(R)
+            if hdr.tid & GCFLAG_POSSIBLY_OUTDATED == 0:
+                assert not L
+            elif L:
+                xxx
+        return R.ptr
+
+    def stm_latest_global_rev(self, G):
+        hdr = self.gc.header(G)
+        assert hdr.tid & GCFLAG_GLOBAL != 0
+        while hdr.revision != REV_INITIAL:
+            xxx
+        return G
+
+    def stm_writebarrier(self, P):
+        hdr = self.header(P)
         if hdr.tid & GCFLAG_NOT_WRITTEN == 0:
             # already a local, written-to object
             assert hdr.tid & GCFLAG_GLOBAL == 0
 
     def test_write_barrier_exists(self):
         self.select_thread(1)
-        t, t_adr = self.malloc(S)
-        obj = self.stm_writebarrier(t_adr)     # local object
-        assert obj == t_adr
+        t = self.malloc(S)
+        obj = self.stm_writebarrier(t)     # local object
+        assert obj == t
         #
         self.select_thread(0)
-        s, s_adr = self.malloc(S)
+        s = self.malloc(S)
         #
         self.select_thread(1)
-        assert self.gc.header(s_adr).tid & GCFLAG_GLOBAL != 0
-        assert self.gc.header(t_adr).tid & GCFLAG_GLOBAL == 0
-        self.gc.header(s_adr).tid |= GCFLAG_POSSIBLY_OUTDATED
-        self.gc.header(t_adr).tid |= GCFLAG_LOCAL_COPY | GCFLAG_VISITED
-        set_hdr_revision(self.gc.header(t_adr), s_adr)
+        assert self.header(s).tid & GCFLAG_GLOBAL != 0
+        assert self.header(t).tid & GCFLAG_GLOBAL == 0
+        self.header(s).tid |= GCFLAG_POSSIBLY_OUTDATED
+        self.header(t).tid |= GCFLAG_LOCAL_COPY | GCFLAG_VISITED
+        self.set_hdr_revision(self.header(t), s)
         self.gc.stm_operations._tldicts[1][s_adr] = t_adr
-        obj = self.stm_writebarrier(s_adr)     # global copied object
-        assert obj == t_adr
+        obj = self.stm_writebarrier(s)     # global copied object
+        assert obj == t
         assert self.gc.stm_operations._transactional_copies == []
 
     def test_write_barrier_new(self):
             pending = list(source_objects)
             found = set(obj._obj for obj in pending)
             for x in pending:
+                x = self.stm_readbarrier(x)
                 for name in ('sr2', 'sr3'):
-                    obj = self.gc.stm_operations.read_attribute(x, name)
+                    obj = getattr(x, name)
                     if obj and obj._obj not in found:
                         found.add(obj._obj)
                         pending.append(obj)
             pending = [source_object]
             found = {source_object._obj: 0}
             for x in pending:
+                x_orig = x
+                x = self.stm_readbarrier(x)
+                if not can_be_indirect:
+                    assert x == x_orig
                 for name in ('sr2', 'sr3'):
-                    obj = self.gc.stm_operations.read_attribute(x, name)
-                    if not can_be_indirect:
-                        assert obj == getattr(x, name)
+                    obj = getattr(x, name)
                     if not obj:
                         shape.append(None)
                     else:
                 dstobj = random.choice(missing_objects)
                 name = random.choice(('sr2', 'sr3'))
                 src_adr = llmemory.cast_ptr_to_adr(srcobj)
-                adr2 = self.gc.stm_writebarrier(src_adr)
+                adr2 = self.stm_writebarrier(src_adr)
                 obj2 = llmemory.cast_adr_to_ptr(adr2, lltype.Ptr(SR))
                 setattr(obj2, name, dstobj)
             #
         from pypy.rpython.memory.gc.test import test_stmtls
         self.gc.root_walker = test_stmtls.FakeRootWalker()
         #
-        tr1, tr1_adr = self.malloc(SR, globl=True)   # three prebuilt objects
-        tr2, tr2_adr = self.malloc(SR, globl=True)
-        tr3, tr3_adr = self.malloc(SR, globl=True)
+        tr1 = self.malloc(SR, globl=True)   # three prebuilt objects
+        tr2 = self.malloc(SR, globl=True)
+        tr3 = self.malloc(SR, globl=True)
         tr1.sr2 = tr2
         self.gc.root_walker.push(tr1)
-        sr1_adr = self.gc.stm_writebarrier(tr1_adr)
-        assert sr1_adr != tr1_adr
-        sr2_adr = self.gc.stm_writebarrier(tr2_adr)
-        assert sr2_adr != tr2_adr
-        sr3_adr = self.gc.stm_writebarrier(tr3_adr)
-        assert sr3_adr != tr3_adr
-        self.checkflags(sr1_adr, False, True)    # sr1 is local
-        self.checkflags(sr2_adr, False, True)    # sr2 is local
-        self.checkflags(sr3_adr, False, True)    # sr3 is local
+        sr1 = self.stm_writebarrier(tr1)
+        assert sr1 != tr1
+        sr2 = self.stm_writebarrier(tr2)
+        assert sr2 != tr2
+        sr3 = self.gc.stm_writebarrier(tr3)
+        assert sr3 != tr3
+        self.checkflags(sr1, False, True)    # sr1 is local
+        self.checkflags(sr2, False, True)    # sr2 is local
+        self.checkflags(sr3, False, True)    # sr3 is local
         #
         self.gc.stop_transaction()
         self.gc.start_transaction()

pypy/rpython/memory/gc/test/test_stmtls.py

 import py
+from pypy.rlib.rarithmetic import r_uint
 from pypy.rpython.lltypesystem import lltype, llmemory, llarena, llgroup
 from pypy.rpython.memory.gc.stmtls import StmGCTLS, WORD
-from pypy.rpython.memory.gc.test.test_stmgc import StmGCTests
 from pypy.rpython.memory.support import get_address_stack, get_address_deque
 from pypy.rpython.memory.gcheader import GCHeaderBuilder
 
     sharedarea = FakeSharedArea()
     root_walker = FakeRootWalker()
     HDR = lltype.Struct('header', ('tid', lltype.Signed),
-                                  ('version', llmemory.Address))
+                                  ('revision', lltype.Unsigned))
     gcheaderbuilder = GCHeaderBuilder(HDR)
     maximum_extra_threshold = 0
 
     def get_size(self, addr):
         return llmemory.sizeof(lltype.typeOf(addr.ptr).TO)
 
+    def set_obj_revision(self, addr, nrevision):
+        hdr = self.header(addr)
+        hdr.revision = llmemory.cast_adr_to_uint_symbolic(nrevision)
+
     def trace(self, obj, callback, arg):
         TYPE = obj.ptr._TYPE.TO
         if TYPE == S:
         obj = adr + size_gc_header
         hdr = self.gc.header(obj)
         hdr.tid = 0
-        hdr.version = NULL
+        hdr.revision = r_uint(0)
         return llmemory.cast_adr_to_ptr(obj, lltype.Ptr(STRUCT))
 
     # ----------

pypy/translator/goal/targetpypystandalone.py

         global space, entry_point
 
         if config.translation.stm:
-            config.objspace.usemodules.signal = False     # XXX! FIXME
             config.translation.thread = True
 
         if config.objspace.allworkingmodules:
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.