[pypy-commit] pypy stm-gc: Fix fix fix.

arigo noreply at buildbot.pypy.org
Thu Feb 9 18:16:31 CET 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: stm-gc
Changeset: r52324:1509515879ae
Date: 2012-02-09 18:16 +0100
http://bitbucket.org/pypy/pypy/changeset/1509515879ae/

Log:	Fix fix fix.

diff --git a/pypy/rlib/rstm.py b/pypy/rlib/rstm.py
--- a/pypy/rlib/rstm.py
+++ b/pypy/rlib/rstm.py
@@ -12,6 +12,7 @@
 @specialize.memo()
 def _get_stm_callback(func, argcls):
     def _stm_callback(llarg, retry_counter):
+        llop.stm_start_transaction(lltype.Void)
         if we_are_translated():
             llarg = rffi.cast(rclass.OBJECTPTR, llarg)
             arg = cast_base_ptr_to_instance(argcls, llarg)
@@ -19,6 +20,7 @@
             arg = lltype.TLS.stm_callback_arg
         res = func(arg, retry_counter)
         assert res is None
+        llop.stm_commit_transaction(lltype.Void)
         return lltype.nullptr(rffi.VOIDP.TO)
     return _stm_callback
 
diff --git a/pypy/rpython/lltypesystem/lloperation.py b/pypy/rpython/lltypesystem/lloperation.py
--- a/pypy/rpython/lltypesystem/lloperation.py
+++ b/pypy/rpython/lltypesystem/lloperation.py
@@ -395,13 +395,15 @@
     # direct_calls and maybe several casts, but it looks less heavy-weight
     # to keep them as operations until the genc stage)
 
-    'stm_getfield':         LLOp(sideeffects=False, canrun=True),
-    'stm_getarrayitem':     LLOp(sideeffects=False, canrun=True),
-    'stm_getinteriorfield': LLOp(sideeffects=False, canrun=True),
-    'stm_become_inevitable':LLOp(),
-    'stm_descriptor_init':  LLOp(),
-    'stm_descriptor_done':  LLOp(),
-    'stm_writebarrier':     LLOp(sideeffects=False),
+    'stm_getfield':           LLOp(sideeffects=False, canrun=True),
+    'stm_getarrayitem':       LLOp(sideeffects=False, canrun=True),
+    'stm_getinteriorfield':   LLOp(sideeffects=False, canrun=True),
+    'stm_become_inevitable':  LLOp(),
+    'stm_descriptor_init':    LLOp(),
+    'stm_descriptor_done':    LLOp(),
+    'stm_writebarrier':       LLOp(sideeffects=False),
+    'stm_start_transaction':  LLOp(),
+    'stm_commit_transaction': LLOp(),
 
     # __________ address operations __________
 
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
@@ -22,6 +22,9 @@
                      4: rffi.INT,
                      8: lltype.SignedLongLong}
 
+CALLBACK = lltype.Ptr(lltype.FuncType([llmemory.Address] * 3, lltype.Void))
+GETSIZE  = lltype.Ptr(lltype.FuncType([llmemory.Address], lltype.Signed))
+
 
 def always_inline(fn):
     fn._always_inline_ = True
@@ -81,13 +84,11 @@
         ##    self.declare_reader(size, TYPE)
         self.declare_write_barrier()
 
-    GETSIZE = lltype.Ptr(lltype.FuncType([llmemory.Address], lltype.Signed))
-
     def setup(self):
         """Called at run-time to initialize the GC."""
         GCBase.setup(self)
         self.stm_operations.setup_size_getter(
-                llhelper(self.GETSIZE, self._getsize_fn))
+                llhelper(GETSIZE, self._getsize_fn))
         self.main_thread_tls = self.setup_thread(True)
         self.mutex_lock = ll_thread.allocate_ll_lock()
 
@@ -217,6 +218,12 @@
     def collect(self, gen=0):
         raise NotImplementedError
 
+    def start_transaction(self):
+        self.collector.start_transaction()
+
+    def commit_transaction(self):
+        self.collector.commit_transaction()
+
 
     @always_inline
     def get_type_id(self, obj):
@@ -428,20 +435,27 @@
         tls.pending_list = NULL
         # Enumerate the roots, which are the local copies of global objects.
         # For each root, trace it.
-        self.stm_operations.enum_tldict_start()
-        while self.stm_operations.enum_tldict_find_next():
-            globalobj = self.stm_operations.enum_tldict_globalobj()
-            localobj = self.stm_operations.enum_tldict_localobj()
-            #
-            localhdr = self.header(localobj)
-            ll_assert(localhdr.version == globalobj,
-                      "in a root: localobj.version != globalobj")
-            ll_assert(localhdr.tid & GCFLAG_GLOBAL == 0,
-                      "in a root: unexpected GCFLAG_GLOBAL")
-            ll_assert(localhdr.tid & GCFLAG_WAS_COPIED != 0,
-                      "in a root: missing GCFLAG_WAS_COPIED")
-            #
-            self.trace_and_drag_out_of_nursery(tls, localobj)
+        callback = llhelper(CALLBACK, self._enum_entries)
+        # xxx hack hack hack!  Stores 'self' in a global place... but it's
+        # pointless after translation because 'self' is a Void.
+        _global_collector.collector = self
+        self.stm_operations.tldict_enum(callback)
+
+
+    @staticmethod
+    def _enum_entries(tls_addr, globalobj, localobj):
+        self = _global_collector.collector
+        tls = llmemory.cast_adr_to_ptr(tls_addr, lltype.Ptr(StmGC.GCTLS))
+        #
+        localhdr = self.header(localobj)
+        ll_assert(localhdr.version == globalobj,
+                  "in a root: localobj.version != globalobj")
+        ll_assert(localhdr.tid & GCFLAG_GLOBAL == 0,
+                  "in a root: unexpected GCFLAG_GLOBAL")
+        ll_assert(localhdr.tid & GCFLAG_WAS_COPIED != 0,
+                  "in a root: missing GCFLAG_WAS_COPIED")
+        #
+        self.trace_and_drag_out_of_nursery(tls, localobj)
 
 
     def collect_from_pending_list(self, tls):
@@ -519,3 +533,8 @@
         #
         # Fix the original root.address[0] to point to the globalobj
         root.address[0] = globalobj
+
+
+class _GlobalCollector(object):
+    pass
+_global_collector = _GlobalCollector()
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
@@ -1,6 +1,6 @@
 import py
 from pypy.rpython.lltypesystem import lltype, llmemory, llarena, rffi
-from pypy.rpython.memory.gc.stmgc import StmGC, PRIMITIVE_SIZES, WORD
+from pypy.rpython.memory.gc.stmgc import StmGC, PRIMITIVE_SIZES, WORD, CALLBACK
 from pypy.rpython.memory.gc.stmgc import GCFLAG_GLOBAL, GCFLAG_WAS_COPIED
 
 
@@ -37,7 +37,6 @@
             assert not hasattr(self, '_tls_dict')
             self._tls_dict = {0: tls}
             self._tldicts = {0: {}}
-            self._tldicts_iterators = {}
             self._transactional_copies = []
         else:
             assert in_main_thread == 0
@@ -64,32 +63,11 @@
         assert obj not in tldict
         tldict[obj] = localobj
 
-    def enum_tldict_start(self):
-        it = self._tldicts[self.threadnum].iteritems()
-        self._tldicts_iterators[self.threadnum] = [it, None, None]
-
-    def enum_tldict_find_next(self):
-        state = self._tldicts_iterators[self.threadnum]
-        try:
-            next_key, next_value = state[0].next()
-        except StopIteration:
-            state[1] = None
-            state[2] = None
-            del self._tldicts_iterators[self.threadnum]
-            return False
-        state[1] = next_key
-        state[2] = next_value
-        return True
-
-    def enum_tldict_globalobj(self):
-        state = self._tldicts_iterators[self.threadnum]
-        assert state[1] is not None
-        return state[1]
-
-    def enum_tldict_localobj(self):
-        state = self._tldicts_iterators[self.threadnum]
-        assert state[2] is not None
-        return state[2]
+    def tldict_enum(self, callback):
+        assert lltype.typeOf(callback) == CALLBACK
+        tls = self.get_tls()
+        for key, value in self._tldicts[self.threadnum].iteritems():
+            callback(tls, key, value)
 
     def _get_stm_reader(size, TYPE):
         assert rffi.sizeof(TYPE) == size
diff --git a/pypy/rpython/memory/gctransform/stmframework.py b/pypy/rpython/memory/gctransform/stmframework.py
--- a/pypy/rpython/memory/gctransform/stmframework.py
+++ b/pypy/rpython/memory/gctransform/stmframework.py
@@ -18,6 +18,12 @@
         self.stm_writebarrier_ptr = getfn(
             self.gcdata.gc.stm_writebarrier,
             [annmodel.SomeAddress()], annmodel.SomeAddress())
+        self.stm_start_ptr = getfn(
+            self.gcdata.gc.start_transaction.im_func,
+            [s_gc], annmodel.s_None)
+        self.stm_commit_ptr = getfn(
+            self.gcdata.gc.commit_transaction.im_func,
+            [s_gc], annmodel.s_None)
 
     def push_roots(self, hop, keep_current_args=False):
         pass
@@ -44,6 +50,12 @@
                                resulttype=llmemory.Address)
         hop.genop('cast_adr_to_ptr', [v_localadr], resultvar=op.result)
 
+    def gct_stm_start_transaction(self, hop):
+        hop.genop("direct_call", [self.stm_start_ptr, self.c_const_gc])
+
+    def gct_stm_commit_transaction(self, hop):
+        hop.genop("direct_call", [self.stm_commit_ptr, self.c_const_gc])
+
 
 class StmStackRootWalker(BaseRootWalker):
 
diff --git a/pypy/translator/stm/src_stm/et.c b/pypy/translator/stm/src_stm/et.c
--- a/pypy/translator/stm/src_stm/et.c
+++ b/pypy/translator/stm/src_stm/et.c
@@ -789,14 +789,15 @@
   redolog_insert(&d->redolog, key, value);
 }
 
-void stm_tldict_enum(void(*callback)(void*, void*))
+void stm_tldict_enum(void(*callback)(void*, void*, void*))
 {
   struct tx_descriptor *d = thread_descriptor;
   wlog_t *item;
+  void *tls = stm_get_tls();
 
   REDOLOG_LOOP_FORWARD(d->redolog, item)
     {
-      callback(item->addr, item->val);
+      callback(tls, item->addr, item->val);
     } REDOLOG_LOOP_END;
 }
 
diff --git a/pypy/translator/stm/src_stm/et.h b/pypy/translator/stm/src_stm/et.h
--- a/pypy/translator/stm/src_stm/et.h
+++ b/pypy/translator/stm/src_stm/et.h
@@ -20,7 +20,7 @@
 
 void *stm_tldict_lookup(void *);
 void stm_tldict_add(void *, void *);
-void stm_tlidct_enum(void(*)(void*, void*));
+void stm_tldict_enum(void(*)(void*, void*, void*));
 
 char      stm_read_int1(void *, long);
 short     stm_read_int2(void *, long);
diff --git a/pypy/translator/stm/stmgcintf.py b/pypy/translator/stm/stmgcintf.py
--- a/pypy/translator/stm/stmgcintf.py
+++ b/pypy/translator/stm/stmgcintf.py
@@ -1,14 +1,11 @@
 from pypy.rpython.lltypesystem import lltype, llmemory
-from pypy.rpython.memory.gc.stmgc import PRIMITIVE_SIZES
+from pypy.rpython.memory.gc.stmgc import PRIMITIVE_SIZES, GETSIZE, CALLBACK
 from pypy.translator.stm import _rffi_stm
 
 
 def smexternal(name, args, result):
     return staticmethod(_rffi_stm.llexternal(name, args, result))
 
-CALLBACK = lltype.Ptr(lltype.FuncType([llmemory.Address] * 2, lltype.Void))
-GETSIZE  = lltype.Ptr(lltype.FuncType([llmemory.Address], lltype.Signed))
-
 
 class StmOperations(object):
 
diff --git a/pypy/translator/stm/test/test_stmgcintf.py b/pypy/translator/stm/test/test_stmgcintf.py
--- a/pypy/translator/stm/test/test_stmgcintf.py
+++ b/pypy/translator/stm/test/test_stmgcintf.py
@@ -77,7 +77,8 @@
         return content
 
     def get_callback(self):
-        def callback(key, value):
+        def callback(tls, key, value):
+            assert tls == llmemory.cast_ptr_to_adr(self.tls)
             seen.append((key, value))
         seen = []
         p_callback = llhelper(CALLBACK, callback)
@@ -88,6 +89,19 @@
         stm_operations.tldict_enum(p_callback)
         assert seen == []
 
+    def test_enum_tldict_nonempty(self):
+        a1 = rffi.cast(llmemory.Address, 0x4020)
+        a2 = rffi.cast(llmemory.Address, 10002)
+        a3 = rffi.cast(llmemory.Address, 0x4028)
+        a4 = rffi.cast(llmemory.Address, 10004)
+        #
+        stm_operations.tldict_add(a1, a2)
+        stm_operations.tldict_add(a3, a4)
+        p_callback, seen = self.get_callback()
+        stm_operations.tldict_enum(p_callback)
+        assert (seen == [(a1, a2), (a3, a4)] or
+                seen == [(a3, a4), (a1, a2)])
+
     def stm_read_case(self, flags, copied=False):
         # doesn't test STM behavior, but just that it appears to work
         s1 = lltype.malloc(S1, flavor='raw')


More information about the pypy-commit mailing list