[pypy-commit] pypy stm-gc: Reading fields of various sizes.

arigo noreply at buildbot.pypy.org
Mon Feb 6 16:25:49 CET 2012


Author: Armin Rigo <arigo at tunes.org>
Branch: stm-gc
Changeset: r52137:c200bc59446e
Date: 2012-02-06 16:25 +0100
http://bitbucket.org/pypy/pypy/changeset/c200bc59446e/

Log:	Reading fields of various sizes.

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
@@ -1,4 +1,4 @@
-from pypy.rpython.lltypesystem import lltype, llmemory, llarena
+from pypy.rpython.lltypesystem import lltype, llmemory, llarena, rffi
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.lltypesystem.llmemory import raw_malloc_usage
 from pypy.rpython.memory.gc.base import GCBase
@@ -16,6 +16,11 @@
 GCFLAG_GLOBAL     = first_gcflag << 0     # keep in sync with et.c
 GCFLAG_WAS_COPIED = first_gcflag << 1     # keep in sync with et.c
 
+PRIMITIVE_SIZES   = {1: lltype.Char,
+                     2: rffi.SHORT,
+                     4: rffi.INT,
+                     8: lltype.SignedLongLong}
+
 
 def always_inline(fn):
     fn._always_inline_ = True
@@ -71,7 +76,8 @@
             return self.get_size(obj)
         self._getsize_fn = _get_size
         #
-        self.declare_readers()
+        for size, TYPE in PRIMITIVE_SIZES.items():
+            self.declare_reader(size, TYPE)
         self.declare_write_barrier()
 
     def setup(self):
@@ -205,18 +211,22 @@
 
     # ----------
 
-    def declare_readers(self):
+    def declare_reader(self, size, TYPE):
         # Reading functions.  Defined here to avoid the extra burden of
         # passing 'self' explicitly.
-        stm_read_word = self.stm_operations.stm_read_word
+        assert rffi.sizeof(TYPE) == size
+        PTYPE = rffi.CArrayPtr(TYPE)
+        stm_read_int = getattr(self.stm_operations, 'stm_read_int%d' % size)
         #
         @always_inline
-        def read_signed(obj, offset):
+        def reader(obj, offset):
             if self.header(obj).tid & GCFLAG_GLOBAL == 0:
-                return (obj + offset).signed[0]    # local obj: read directly
+                # local obj: read directly
+                adr = rffi.cast(PTYPE, obj + offset)
+                return adr[0]
             else:
-                return stm_read_word(obj, offset)  # else: call a helper
-        self.read_signed = read_signed
+                return stm_read_int(obj, offset)   # else: call a helper
+        setattr(self, 'read_int%d' % size, reader)
         #
         # the following logic was moved to et.c to avoid a double call
 ##        @dont_inline
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,5 +1,5 @@
-from pypy.rpython.lltypesystem import lltype, llmemory
-from pypy.rpython.memory.gc.stmgc import StmGC
+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 GCFLAG_GLOBAL, GCFLAG_WAS_COPIED
 
 
@@ -87,14 +87,23 @@
         assert state[2] is not None
         return state[2]
 
-    def stm_read_word(self, obj, offset):
-        hdr = self._gc.header(obj)
-        if hdr.tid & GCFLAG_WAS_COPIED != 0:
-            localobj = self.tldict_lookup(obj)
-            if localobj:
-                assert self._gc.header(localobj).tid & GCFLAG_GLOBAL == 0
-                return (localobj + offset).signed[0]
-        return 'stm_ll_read_word(%r, %r)' % (obj, offset)
+    def _get_stm_reader(size, TYPE):
+        assert rffi.sizeof(TYPE) == size
+        PTYPE = rffi.CArrayPtr(TYPE)
+        def stm_reader(self, obj, offset):
+            hdr = self._gc.header(obj)
+            if hdr.tid & GCFLAG_WAS_COPIED != 0:
+                localobj = self.tldict_lookup(obj)
+                if localobj:
+                    assert self._gc.header(localobj).tid & GCFLAG_GLOBAL == 0
+                    adr = rffi.cast(PTYPE, localobj + offset)
+                    return adr[0]
+            return 'stm_ll_read_int%d(%r, %r)' % (size, obj, offset)
+        return stm_reader
+
+    for _size, _TYPE in PRIMITIVE_SIZES.items():
+        _func = _get_stm_reader(_size, _TYPE)
+        locals()['stm_read_int%d' % _size] = _func
 
     def stm_copy_transactional_to_raw(self, srcobj, dstobj, size):
         sizehdr = self._gc.gcheaderbuilder.size_gc_header
@@ -143,6 +152,8 @@
         self.gc.setup()
 
     def teardown_method(self, meth):
+        if not hasattr(self, 'gc'):
+            return
         for key in self.gc.stm_operations._tls_dict.keys():
             if key != 0:
                 self.gc.stm_operations.threadnum = key
@@ -151,7 +162,8 @@
     # ----------
     # test helpers
     def malloc(self, STRUCT):
-        gcref = self.gc.malloc_fixedsize_clear(123, llmemory.sizeof(STRUCT))
+        size = llarena.round_up_for_allocation(llmemory.sizeof(STRUCT))
+        gcref = self.gc.malloc_fixedsize_clear(123, size)
         realobj = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), gcref)
         addr = llmemory.cast_ptr_to_adr(realobj)
         return realobj, addr
@@ -171,6 +183,9 @@
         assert (hdr.tid & GCFLAG_WAS_COPIED != 0) == must_have_was_copied
         if must_have_version != '?':
             assert hdr.version == must_have_version
+    def read_signed(self, obj, offset):
+        meth = getattr(self.gc, 'read_int%d' % WORD)
+        return meth(obj, offset)
 
     def test_gc_creation_works(self):
         pass
@@ -206,15 +221,15 @@
         s, s_adr = self.malloc(S)
         assert self.gc.header(s_adr).tid & GCFLAG_GLOBAL != 0
         s.a = 42
-        value = self.gc.read_signed(s_adr, ofs_a)
-        assert value == 'stm_ll_read_word(%r, %r)' % (s_adr, ofs_a)
+        value = self.read_signed(s_adr, ofs_a)
+        assert value == 'stm_ll_read_int%d(%r, %r)' % (WORD, s_adr, ofs_a)
         #
         self.select_thread(1)
         s, s_adr = self.malloc(S)
         assert self.gc.header(s_adr).tid & GCFLAG_GLOBAL == 0
         self.gc.header(s_adr).tid |= GCFLAG_WAS_COPIED   # should be ignored
         s.a = 42
-        value = self.gc.read_signed(s_adr, ofs_a)
+        value = self.read_signed(s_adr, ofs_a)
         assert value == 42
 
     def test_reader_through_dict(self):
@@ -228,9 +243,30 @@
         self.gc.header(s_adr).tid |= GCFLAG_WAS_COPIED
         self.gc.stm_operations._tldicts[1][s_adr] = t_adr
         #
-        value = self.gc.read_signed(s_adr, ofs_a)
+        value = self.read_signed(s_adr, ofs_a)
         assert value == 84
 
+    def test_reader_sizes(self):
+        for size, TYPE in PRIMITIVE_SIZES.items():
+            T = lltype.GcStruct('T', ('a', TYPE))
+            ofs_a = llmemory.offsetof(T, 'a')
+            #
+            self.select_thread(0)
+            t, t_adr = self.malloc(T)
+            assert self.gc.header(t_adr).tid & GCFLAG_GLOBAL != 0
+            t.a = lltype.cast_primitive(TYPE, 42)
+            #
+            value = getattr(self.gc, 'read_int%d' % size)(t_adr, ofs_a)
+            assert value == 'stm_ll_read_int%d(%r, %r)' % (size, t_adr, ofs_a)
+            #
+            self.select_thread(1)
+            t, t_adr = self.malloc(T)
+            assert self.gc.header(t_adr).tid & GCFLAG_GLOBAL == 0
+            t.a = lltype.cast_primitive(TYPE, 42)
+            value = getattr(self.gc, 'read_int%d' % size)(t_adr, ofs_a)
+            assert lltype.typeOf(value) == TYPE
+            assert lltype.cast_primitive(lltype.Signed, value) == 42
+
     def test_write_barrier_exists(self):
         self.select_thread(1)
         t, t_adr = self.malloc(S)


More information about the pypy-commit mailing list