[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