[pypy-commit] pypy stm-thread-2: Reimplement llmodel for stm using a read/write barrier (easier).
arigo
noreply at buildbot.pypy.org
Thu Sep 13 07:33:50 CEST 2012
Author: Armin Rigo <arigo at tunes.org>
Branch: stm-thread-2
Changeset: r57314:aa131bf06b7a
Date: 2012-09-12 21:50 +0200
http://bitbucket.org/pypy/pypy/changeset/aa131bf06b7a/
Log: Reimplement llmodel for stm using a read/write barrier (easier).
diff --git a/pypy/jit/backend/llsupport/gc.py b/pypy/jit/backend/llsupport/gc.py
--- a/pypy/jit/backend/llsupport/gc.py
+++ b/pypy/jit/backend/llsupport/gc.py
@@ -64,6 +64,9 @@
return True
def initialize(self):
pass
+ @specialize.argtype(1)
+ def do_stm_barrier(self, gcref, cat):
+ return gcref
def do_write_barrier(self, gcref_struct, gcref_newptr):
pass
def can_use_nursery_malloc(self, size):
@@ -594,6 +597,8 @@
self.WB_FUNCPTR_MOD = lltype.Ptr(lltype.FuncType(
[llmemory.Address], llmemory.Address))
self.fielddescr_tid = gc_ll_descr.fielddescr_tid
+ self.gcheaderbuilder = gc_ll_descr.gcheaderbuilder
+ self.HDRPTR = gc_ll_descr.HDRPTR
#
GCClass = gc_ll_descr.GCClass
if GCClass is None: # for tests
@@ -642,12 +647,10 @@
while value[i] == '\x00': i += 1
return (i, struct.unpack('b', value[i])[0])
- def get_write_barrier_fn(self, cpu, returns_modified_object=False):
- # must pass in 'self.returns_modified_object', to make sure that
- # the callers are fixed for this case
+ def get_barrier_funcptr(self, returns_modified_object):
assert returns_modified_object == self.returns_modified_object
llop1 = self.llop1
- if self.returns_modified_object:
+ if returns_modified_object:
FUNCTYPE = self.WB_FUNCPTR_MOD
_, cat = self.stmcat
assert len(cat) == 3 and cat[1] == '2' # "x2y"
@@ -656,6 +659,12 @@
else:
FUNCTYPE = self.WB_FUNCPTR
funcptr = llop1.get_write_barrier_failing_case(FUNCTYPE)
+ return funcptr
+
+ def get_write_barrier_fn(self, cpu, returns_modified_object):
+ # must pass in 'self.returns_modified_object', to make sure that
+ # the callers are fixed for this case
+ funcptr = self.get_barrier_funcptr(returns_modified_object)
funcaddr = llmemory.cast_ptr_to_adr(funcptr)
return cpu.cast_adr_to_int(funcaddr)
@@ -679,6 +688,22 @@
def set_wb_slowpath(self, withcards, withfloats, addr):
self.wb_slowpath[withcards + 2 * withfloats] = addr
+ def _do_write_barrier(self, gcref_struct, returns_modified_object):
+ assert self.returns_modified_object == returns_modified_object
+ hdr_addr = llmemory.cast_ptr_to_adr(gcref_struct)
+ hdr_addr -= self.gcheaderbuilder.size_gc_header
+ hdr = llmemory.cast_adr_to_ptr(hdr_addr, self.HDRPTR)
+ if self.jit_wb_if_flag == 0 or hdr.tid & self.jit_wb_if_flag:
+ # get a pointer to the 'remember_young_pointer' function from
+ # the GC, and call it immediately
+ funcptr = self.get_barrier_funcptr(returns_modified_object)
+ return funcptr(llmemory.cast_ptr_to_adr(gcref_struct))
+ else:
+ if returns_modified_object:
+ return gcref_struct
+ else:
+ return None
+
class GcLLDescr_framework(GcLLDescription):
DEBUG = False # forced to True by x86/test/test_zrpy_gc.py
@@ -716,6 +741,8 @@
else:
self.max_size_of_young_obj = 1000
self.GCClass = None
+ self.gcheaderbuilder = None
+ self.HDRPTR = None
def _check_valid_gc(self):
# we need the hybrid or minimark GC for rgc._make_sure_does_not_move()
@@ -764,15 +791,29 @@
def _setup_write_barrier(self):
if self.stm:
- from pypy.rpython.memory.gc import stmgc
- WBDescr = WriteBarrierDescr
- self.P2Rdescr = WBDescr(self, (stmgc.GCFLAG_GLOBAL, 'P2R'))
- self.P2Wdescr = WBDescr(self, (stmgc.GCFLAG_NOT_WRITTEN, 'P2W'))
- self.R2Wdescr = WBDescr(self, (stmgc.GCFLAG_NOT_WRITTEN, 'R2W'))
- self.write_barrier_descr = "wbdescr: do not use"
+ self._setup_barriers_for_stm()
else:
self.write_barrier_descr = WriteBarrierDescr(self)
+ def _setup_barriers_for_stm(self):
+ from pypy.rpython.memory.gc import stmgc
+ WBDescr = WriteBarrierDescr
+ self.P2Rdescr = WBDescr(self, (stmgc.GCFLAG_GLOBAL, 'P2R'))
+ self.P2Wdescr = WBDescr(self, (stmgc.GCFLAG_NOT_WRITTEN, 'P2W'))
+ self.R2Wdescr = WBDescr(self, (stmgc.GCFLAG_NOT_WRITTEN, 'R2W'))
+ self.write_barrier_descr = "wbdescr: do not use"
+ #
+ @specialize.argtype(0)
+ def do_stm_barrier(gcref, cat):
+ if lltype.typeOf(gcref) is lltype.Signed: # ignore if 'raw'
+ return gcref
+ if cat == 'W':
+ descr = self.P2Wdescr
+ else:
+ descr = self.P2Rdescr
+ return descr._do_write_barrier(gcref, True)
+ self.do_stm_barrier = do_stm_barrier
+
def _make_functions(self, really_not_translated):
from pypy.rpython.memory.gctypelayout import check_typeid
llop1 = self.llop1
@@ -932,16 +973,7 @@
hdr.tid = tid
def do_write_barrier(self, gcref_struct, gcref_newptr):
- hdr_addr = llmemory.cast_ptr_to_adr(gcref_struct)
- hdr_addr -= self.gcheaderbuilder.size_gc_header
- hdr = llmemory.cast_adr_to_ptr(hdr_addr, self.HDRPTR)
- if hdr.tid & self.GCClass.JIT_WB_IF_FLAG:
- # get a pointer to the 'remember_young_pointer' function from
- # the GC, and call it immediately
- llop1 = self.llop1
- funcptr = llop1.get_write_barrier_failing_case(
- self.write_barrier_descr.WB_FUNCPTR)
- funcptr(llmemory.cast_ptr_to_adr(gcref_struct))
+ self.write_barrier_descr._do_write_barrier(gcref_struct, False)
def can_use_nursery_malloc(self, size):
return (self.max_size_of_young_obj is not None and
diff --git a/pypy/jit/backend/llsupport/llmodel.py b/pypy/jit/backend/llsupport/llmodel.py
--- a/pypy/jit/backend/llsupport/llmodel.py
+++ b/pypy/jit/backend/llsupport/llmodel.py
@@ -315,6 +315,7 @@
@specialize.argtype(2)
def bh_getarrayitem_gc_i(self, arraydescr, gcref, itemindex):
ofs, size, sign = self.unpack_arraydescr_size(arraydescr)
+ gcref = self.gc_ll_descr.do_stm_barrier(gcref, 'R')
# --- start of GC unsafe code (no GC operation!) ---
items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs)
for STYPE, UTYPE, itemsize in unroll_basic_sizes:
@@ -334,6 +335,7 @@
def bh_getarrayitem_gc_r(self, arraydescr, gcref, itemindex):
ofs = self.unpack_arraydescr(arraydescr)
+ gcref = self.gc_ll_descr.do_stm_barrier(gcref, 'R')
# --- start of GC unsafe code (no GC operation!) ---
items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs)
items = rffi.cast(rffi.CArrayPtr(lltype.Signed), items)
@@ -344,6 +346,7 @@
@specialize.argtype(2)
def bh_getarrayitem_gc_f(self, arraydescr, gcref, itemindex):
ofs = self.unpack_arraydescr(arraydescr)
+ gcref = self.gc_ll_descr.do_stm_barrier(gcref, 'R')
# --- start of GC unsafe code (no GC operation!) ---
items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs)
items = rffi.cast(rffi.CArrayPtr(longlong.FLOATSTORAGE), items)
@@ -354,6 +357,7 @@
@specialize.argtype(2)
def bh_setarrayitem_gc_i(self, arraydescr, gcref, itemindex, newvalue):
ofs, size, sign = self.unpack_arraydescr_size(arraydescr)
+ gcref = self.gc_ll_descr.do_stm_barrier(gcref, 'W')
# --- start of GC unsafe code (no GC operation!) ---
items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs)
for TYPE, _, itemsize in unroll_basic_sizes:
@@ -367,6 +371,7 @@
def bh_setarrayitem_gc_r(self, arraydescr, gcref, itemindex, newvalue):
ofs = self.unpack_arraydescr(arraydescr)
+ gcref = self.gc_ll_descr.do_stm_barrier(gcref, 'W')
self.gc_ll_descr.do_write_barrier(gcref, newvalue)
# --- start of GC unsafe code (no GC operation!) ---
items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs)
@@ -377,6 +382,7 @@
@specialize.argtype(2)
def bh_setarrayitem_gc_f(self, arraydescr, gcref, itemindex, newvalue):
ofs = self.unpack_arraydescr(arraydescr)
+ gcref = self.gc_ll_descr.do_stm_barrier(gcref, 'W')
# --- start of GC unsafe code (no GC operation!) ---
items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs)
items = rffi.cast(rffi.CArrayPtr(longlong.FLOATSTORAGE), items)
@@ -397,6 +403,7 @@
fieldsize = descr.fielddescr.field_size
sign = descr.fielddescr.is_field_signed()
fullofs = itemindex * size + ofs
+ gcref = self.gc_ll_descr.do_stm_barrier(gcref, 'R')
# --- start of GC unsafe code (no GC operation!) ---
items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), fullofs)
for STYPE, UTYPE, itemsize in unroll_basic_sizes:
@@ -419,6 +426,7 @@
arraydescr = descr.arraydescr
ofs, size, _ = self.unpack_arraydescr_size(arraydescr)
ofs += descr.fielddescr.offset
+ gcref = self.gc_ll_descr.do_stm_barrier(gcref, 'R')
# --- start of GC unsafe code (no GC operation!) ---
items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs +
size * itemindex)
@@ -432,6 +440,7 @@
arraydescr = descr.arraydescr
ofs, size, _ = self.unpack_arraydescr_size(arraydescr)
ofs += descr.fielddescr.offset
+ gcref = self.gc_ll_descr.do_stm_barrier(gcref, 'R')
# --- start of GC unsafe code (no GC operation!) ---
items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs +
size * itemindex)
@@ -447,6 +456,7 @@
ofs += descr.fielddescr.offset
fieldsize = descr.fielddescr.field_size
ofs = itemindex * size + ofs
+ gcref = self.gc_ll_descr.do_stm_barrier(gcref, 'W')
# --- start of GC unsafe code (no GC operation!) ---
items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref), ofs)
for TYPE, _, itemsize in unroll_basic_sizes:
@@ -463,6 +473,7 @@
arraydescr = descr.arraydescr
ofs, size, _ = self.unpack_arraydescr_size(arraydescr)
ofs += descr.fielddescr.offset
+ gcref = self.gc_ll_descr.do_stm_barrier(gcref, 'W')
self.gc_ll_descr.do_write_barrier(gcref, newvalue)
# --- start of GC unsafe code (no GC operation!) ---
items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref),
@@ -476,6 +487,7 @@
arraydescr = descr.arraydescr
ofs, size, _ = self.unpack_arraydescr_size(arraydescr)
ofs += descr.fielddescr.offset
+ gcref = self.gc_ll_descr.do_stm_barrier(gcref, 'W')
# --- start of GC unsafe code (no GC operation!) ---
items = rffi.ptradd(rffi.cast(rffi.CCHARP, gcref),
ofs + size * itemindex)
@@ -502,6 +514,7 @@
@specialize.argtype(1)
def _base_do_getfield_i(self, struct, fielddescr):
ofs, size, sign = self.unpack_fielddescr_size(fielddescr)
+ struct = self.gc_ll_descr.do_stm_barrier(struct, 'R')
# --- start of GC unsafe code (no GC operation!) ---
fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs)
for STYPE, UTYPE, itemsize in unroll_basic_sizes:
@@ -523,6 +536,7 @@
@specialize.argtype(1)
def _base_do_getfield_r(self, struct, fielddescr):
ofs = self.unpack_fielddescr(fielddescr)
+ struct = self.gc_ll_descr.do_stm_barrier(struct, 'R')
# --- start of GC unsafe code (no GC operation!) ---
fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs)
pval = rffi.cast(rffi.CArrayPtr(lltype.Signed), fieldptr)[0]
@@ -533,6 +547,7 @@
@specialize.argtype(1)
def _base_do_getfield_f(self, struct, fielddescr):
ofs = self.unpack_fielddescr(fielddescr)
+ struct = self.gc_ll_descr.do_stm_barrier(struct, 'R')
# --- start of GC unsafe code (no GC operation!) ---
fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs)
fval = rffi.cast(rffi.CArrayPtr(longlong.FLOATSTORAGE), fieldptr)[0]
@@ -549,6 +564,7 @@
@specialize.argtype(1)
def _base_do_setfield_i(self, struct, fielddescr, newvalue):
ofs, size, sign = self.unpack_fielddescr_size(fielddescr)
+ struct = self.gc_ll_descr.do_stm_barrier(struct, 'W')
# --- start of GC unsafe code (no GC operation!) ---
fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs)
for TYPE, _, itemsize in unroll_basic_sizes:
@@ -565,6 +581,7 @@
ofs = self.unpack_fielddescr(fielddescr)
assert lltype.typeOf(struct) is not lltype.Signed, (
"can't handle write barriers for setfield_raw")
+ struct = self.gc_ll_descr.do_stm_barrier(struct, 'W')
self.gc_ll_descr.do_write_barrier(struct, newvalue)
# --- start of GC unsafe code (no GC operation!) ---
fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs)
@@ -575,6 +592,7 @@
@specialize.argtype(1)
def _base_do_setfield_f(self, struct, fielddescr, newvalue):
ofs = self.unpack_fielddescr(fielddescr)
+ struct = self.gc_ll_descr.do_stm_barrier(struct, 'W')
# --- start of GC unsafe code (no GC operation!) ---
fieldptr = rffi.ptradd(rffi.cast(rffi.CCHARP, struct), ofs)
fieldptr = rffi.cast(rffi.CArrayPtr(longlong.FLOATSTORAGE), fieldptr)
diff --git a/pypy/jit/backend/llsupport/test/test_stmrewrite.py b/pypy/jit/backend/llsupport/test/test_stmrewrite.py
--- a/pypy/jit/backend/llsupport/test/test_stmrewrite.py
+++ b/pypy/jit/backend/llsupport/test/test_stmrewrite.py
@@ -404,6 +404,8 @@
unicodesetitem(p1, i2, i3)
jump()
""")
+ py.test.skip("XXX not really right: should instead be an assert "
+ "that p1 is already a W")
def test_fallback_to_inevitable(self):
oplist = [
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -2468,8 +2468,8 @@
# then produce the condition here. The fast-path that does not
# require any call is if some bit in the header of the object is
# *cleared*.
+ loc_base = arglocs[0]
if mask != 0:
- loc_base = arglocs[0]
byteaddr = addr_add_const(loc_base, descr.jit_wb_if_flag_byteofs)
self.mc.TEST8(byteaddr, imm(mask))
self.mc.J_il8(rx86.Conditions['Z'], 0) # patched later
More information about the pypy-commit
mailing list