[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