[pypy-commit] pypy stmgc-c4: fix bug where spilled references do not get updated by stm barriers
Raemi
noreply at buildbot.pypy.org
Mon Aug 26 18:14:02 CEST 2013
Author: Remi Meier <remi.meier at gmail.com>
Branch: stmgc-c4
Changeset: r66322:9832428e54e4
Date: 2013-08-26 18:12 +0200
http://bitbucket.org/pypy/pypy/changeset/9832428e54e4/
Log: fix bug where spilled references do not get updated by stm barriers
diff --git a/rpython/jit/backend/llsupport/stmrewrite.py b/rpython/jit/backend/llsupport/stmrewrite.py
--- a/rpython/jit/backend/llsupport/stmrewrite.py
+++ b/rpython/jit/backend/llsupport/stmrewrite.py
@@ -47,7 +47,8 @@
for op in operations:
if not we_are_translated():
# only possible in tests:
- if op.getopnum() in (rop.COND_CALL_STM_B,):
+ if op.getopnum() in (rop.COND_CALL_STM_B,
+ -124): # FORCE_SPILL
self.newops.append(op)
continue
if op.getopnum() == rop.DEBUG_MERGE_POINT:
diff --git a/rpython/jit/backend/x86/regalloc.py b/rpython/jit/backend/x86/regalloc.py
--- a/rpython/jit/backend/x86/regalloc.py
+++ b/rpython/jit/backend/x86/regalloc.py
@@ -807,7 +807,21 @@
for i in range(N)]
self.perform_discard(op, arglocs)
- consider_cond_call_stm_b = consider_cond_call_gc_wb
+ def consider_cond_call_stm_b(self, op):
+ assert op.result is None
+ # we force all arguments in a reg (unless they are Consts),
+ # because it will be needed anyway by the following setfield_gc
+ # or setarrayitem_gc. It avoids loading it twice from the memory.
+ arg = op.getarg(0)
+ argloc = self.rm.make_sure_var_in_reg(arg)
+ self.perform_discard(op, [argloc])
+
+ spilled_loc = self.rm.frame_manager.get(arg)
+ if spilled_loc:
+ # spilled var, make sure it gets updated in the frame too
+ self.assembler.regalloc_mov(argloc, spilled_loc)
+
+
consider_cond_call_gc_wb_array = consider_cond_call_gc_wb
def consider_call_malloc_nursery(self, op):
diff --git a/rpython/jit/backend/x86/test/test_stm_integration.py b/rpython/jit/backend/x86/test/test_stm_integration.py
--- a/rpython/jit/backend/x86/test/test_stm_integration.py
+++ b/rpython/jit/backend/x86/test/test_stm_integration.py
@@ -767,6 +767,58 @@
assert frame_adr != id(finaldescr)
+ def test_write_barrier_on_spilled(self):
+ cpu = self.cpu
+
+ PRIV_REV = rffi.cast(lltype.Signed, StmGC.PREBUILT_REVISION)
+ self.priv_rev_num[0] = PRIV_REV
+
+ s = self.allocate_prebuilt_s()
+ other_s = self.allocate_prebuilt_s()
+ sgcref = lltype.cast_opaque_ptr(llmemory.GCREF, s)
+ other_sgcref = lltype.cast_opaque_ptr(llmemory.GCREF, other_s)
+ s.h_revision = PRIV_REV+4
+ other_s.h_revision = PRIV_REV+4
+
+ called_on = []
+ def write_barrier(obj):
+ called_on.append(obj)
+ if llmemory.cast_ptr_to_adr(sgcref) == obj:
+ return rffi.cast(llmemory.Address, other_sgcref)
+ return obj
+ P2W = FakeSTMBarrier(cpu.gc_ll_descr, 'P2W', write_barrier)
+ old_p2w = cpu.gc_ll_descr.P2Wdescr
+ cpu.gc_ll_descr.P2Wdescr = P2W
+
+ cpu.gc_ll_descr.init_nursery(100)
+ cpu.setup_once()
+
+
+ from rpython.jit.tool.oparser import FORCE_SPILL
+ p0 = BoxPtr()
+ spill = FORCE_SPILL(None)
+ spill.initarglist([p0])
+ operations = [
+ ResOperation(rop.COND_CALL_STM_B, [p0], None,
+ descr=P2W),
+ spill,
+ ResOperation(rop.COND_CALL_STM_B, [p0], None,
+ descr=P2W),
+ ResOperation(rop.FINISH, [p0], None,
+ descr=BasicFinalDescr(0)),
+ ]
+ inputargs = [p0]
+ looptoken = JitCellToken()
+ print cpu.compile_loop(inputargs, operations, looptoken)
+ cpu.execute_token(looptoken, sgcref)
+
+ # the second write-barrier must see the result of the
+ # first one
+ self.assert_in(called_on, [sgcref, other_sgcref])
+
+ # for other tests:
+ cpu.gc_ll_descr.P2Wdescr = old_p2w
+
More information about the pypy-commit
mailing list