[pypy-commit] pypy stm-gc: Test and fix.

arigo noreply at buildbot.pypy.org
Mon Apr 23 13:29:02 CEST 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: stm-gc
Changeset: r54672:55e1db872e5a
Date: 2012-04-23 12:12 +0200
http://bitbucket.org/pypy/pypy/changeset/55e1db872e5a/

Log:	Test and fix.

diff --git a/pypy/rpython/memory/gc/stmgc.py b/pypy/rpython/memory/gc/stmgc.py
--- a/pypy/rpython/memory/gc/stmgc.py
+++ b/pypy/rpython/memory/gc/stmgc.py
@@ -279,9 +279,13 @@
         def _stm_write_barrier_global(obj):
             tls = self.get_tls()
             if tls is self.main_thread_tls:
-                return obj        # not in transaction
+                # not in a transaction: the main thread writes to a global obj.
+                # In this case we turn the object local.
+                tls.main_thread_writes_to_global_obj(obj)
+                return obj
             #
-            # we need to find or make a local copy
+            # else, in a transaction: we find or make a local copy of the
+            # global object
             hdr = self.header(obj)
             if hdr.tid & GCFLAG_WAS_COPIED == 0:
                 #
diff --git a/pypy/rpython/memory/gc/stmtls.py b/pypy/rpython/memory/gc/stmtls.py
--- a/pypy/rpython/memory/gc/stmtls.py
+++ b/pypy/rpython/memory/gc/stmtls.py
@@ -113,6 +113,13 @@
                 if value is not self:
                     del StmGCTLS.nontranslated_dict[key]
         self.start_transaction()
+        # do something special here after we restarted the "transaction"
+        # in the main thread: we have to make sure that the write_barrier
+        # calls done in the main thread before enter/leave_transactional_mode
+        # are still pointing to local objects.  Conservatively, we mark as
+        # local all objects directly referenced from the stack.
+        self.gc.root_walker.walk_current_stack_roots(
+            StmGCTLS._remark_object_as_local, self)
 
     def start_transaction(self):
         """Start a transaction: performs any pending cleanups, and set
@@ -256,6 +263,16 @@
     def fresh_new_weakref(self, obj):
         self.local_weakrefs.append(obj)
 
+    def _remark_object_as_local(self, root):
+        self.main_thread_writes_to_global_obj(root.address[0])
+
+    def main_thread_writes_to_global_obj(self, obj):
+        hdr = self.gc.header(obj)
+        ll_assert(hdr.tid & GCFLAG_WAS_COPIED == 0,
+                  "write in main thread: unexpected GCFLAG_WAS_COPIED")
+        hdr.tid &= ~GCFLAG_GLOBAL
+        self.sharedarea_tls.add_regular(obj)
+
     # ------------------------------------------------------------
 
     def _promote_locals_to_globals(self):
diff --git a/pypy/rpython/memory/gc/test/test_stmgc.py b/pypy/rpython/memory/gc/test/test_stmgc.py
--- a/pypy/rpython/memory/gc/test/test_stmgc.py
+++ b/pypy/rpython/memory/gc/test/test_stmgc.py
@@ -336,7 +336,28 @@
         self.checkflags(t_adr, True, False)
         obj = self.gc.stm_writebarrier(t_adr)     # main thread, global:
         assert obj == t_adr                       # doesn't make a copy
-        #self.checkflags(obj, False, False) -- LATER check that it becomes local
+        self.checkflags(obj, False, False)        # but it becomes local
+
+    def test_relocalize_objects_after_transactional_mode(self):
+        from pypy.rpython.memory.gc.test import test_stmtls
+        self.gc.root_walker = test_stmtls.FakeRootWalker()
+        #
+        tr1, tr1_adr = self.malloc(SR, globl=True)
+        tr2, tr2_adr = self.malloc(SR, globl=True)
+        tr1.sr2 = tr2
+        self.gc.root_walker.current_stack = [tr1]
+        obj = self.gc.stm_writebarrier(tr1_adr)
+        assert obj == tr1_adr
+        obj = self.gc.stm_writebarrier(tr2_adr)
+        assert obj == tr2_adr
+        self.checkflags(tr1_adr, False, False)    # tr1 has become local
+        self.checkflags(tr2_adr, False, False)    # tr2 has become local
+        #
+        self.gc.enter_transactional_mode()
+        self.gc.leave_transactional_mode()
+        self.checkflags(tr2_adr, True, False)     # tr2 has become global again
+        # but tr1 is still local, because it is directly referenced from stack
+        self.checkflags(tr1_adr, False, False)
 
     def test_commit_transaction_empty(self):
         self.select_thread(1)


More information about the pypy-commit mailing list