Author: Remi Meier <[email protected]>
Branch: stmgc-c4
Changeset: r66017:406b5e69c06e
Date: 2013-08-08 16:14 +0200
http://bitbucket.org/pypy/pypy/changeset/406b5e69c06e/

Log:    first test for stm_read_barrier fastpath

diff --git a/rpython/jit/backend/x86/assembler.py 
b/rpython/jit/backend/x86/assembler.py
--- a/rpython/jit/backend/x86/assembler.py
+++ b/rpython/jit/backend/x86/assembler.py
@@ -845,7 +845,8 @@
         rst = self._get_root_stack_top_addr()
         
         if rx86.fits_in_32bits(rst):
-            if gcrootmap.is_stm:
+            if gcrootmap.is_stm and we_are_translated():
+                # during testing, it will be an absolute address
                 stmtlocal.tl_segment_prefix(mc)
             mc.MOV_rj(ebx.value, rst)            # MOV ebx, [rootstacktop]
         else:
@@ -861,7 +862,8 @@
         self.mc.ADD_ri(ebx.value, WORD)
         
         if rx86.fits_in_32bits(rst):
-            if gcrootmap.is_stm:
+            if gcrootmap.is_stm and we_are_translated():
+                # during testing, it will be an absolute address
                 stmtlocal.tl_segment_prefix(self.mc)
             self.mc.MOV_jr(rst, ebx.value)            # MOV [rootstacktop], ebx
         else:
@@ -875,7 +877,8 @@
         rst = self._get_root_stack_top_addr()
         
         if rx86.fits_in_32bits(rst):
-            if gcrootmap.is_stm:
+            if gcrootmap.is_stm and we_are_translated():
+                # during testing, it will be an absolute address
                 stmtlocal.tl_segment_prefix(self.mc)
             self.mc.SUB_ji8(rst, WORD)       # SUB [rootstacktop], WORD
         else:
@@ -1192,7 +1195,8 @@
         gcrootmap = self.cpu.gc_ll_descr.gcrootmap
         
         rst = gcrootmap.get_root_stack_top_addr()
-        if gcrootmap.is_stm:
+        if gcrootmap.is_stm and we_are_translated():
+            # during testing, we return an absolute address
             rst = rst - stmtlocal.threadlocal_base()
             assert rx86.fits_in_32bits(rst)
         return rst
@@ -1203,7 +1207,8 @@
         if gcrootmap and gcrootmap.is_shadow_stack:
             rst = self._get_root_stack_top_addr()
 
-            if gcrootmap.is_stm:
+            if gcrootmap.is_stm and we_are_translated():
+                # during testing, it will be an absolute address
                 stmtlocal.tl_segment_prefix(mc)
             mc.MOV(ecx, heap(rst))
             mc.MOV(ebp, mem(ecx, -WORD))
@@ -2267,16 +2272,17 @@
         # OK: flags already set
         if j_ok1:
             offset = mc.get_relative_pos() - j_ok1
+            assert 0 <= offset <= 127
             mc.overwrite(j_ok1 - 1, chr(offset))
         if j_ok2:
             offset = mc.get_relative_pos() - j_ok2
+            assert 0 <= offset <= 127
             mc.overwrite(j_ok2 - 1, chr(offset))
         if j_ok3:
             offset = mc.get_relative_pos() - j_ok3
+            assert 0 <= offset <= 127
             mc.overwrite(j_ok3 - 1, chr(offset))
 
-        
-        
     def _get_stm_private_rev_num_addr(self):
         assert self.cpu.gc_ll_descr.stm
         rn = rstm.get_adr_of_private_rev_num()
@@ -2294,9 +2300,9 @@
     def _stm_barrier_fastpath(self, mc, descr, arglocs, is_frame=False,
                               align_stack=False):
         assert self.cpu.gc_ll_descr.stm
-        from rpython.jit.backend.llsupport.gc import (
-            STMBarrierDescr, STMReadBarrierDescr, STMWriteBarrierDescr)
-        assert isinstance(descr, STMBarrierDescr)
+        #from rpython.jit.backend.llsupport.gc import (
+        #    STMBarrierDescr, STMReadBarrierDescr, STMWriteBarrierDescr)
+        #assert isinstance(descr, STMBarrierDescr)
         assert descr.returns_modified_object
         loc_base = arglocs[0]
         assert isinstance(loc_base, RegLoc)
@@ -2321,14 +2327,20 @@
         jnz_location = 0
         # compare h_revision with stm_private_rev_num (XXX: may be slow)
         rn = self._get_stm_private_rev_num_addr()
-        stmtlocal.tl_segment_prefix(mc)
-        mc.MOV_rj(X86_64_SCRATCH_REG.value, rn)
+        if we_are_translated():
+            # during tests, _get_stm_private_rev_num_addr returns
+            # an absolute address, not a tl-offset
+            stmtlocal.tl_segment_prefix(mc)
+            mc.MOV_rj(X86_64_SCRATCH_REG.value, rn)
+        else: # testing:
+            mc.MOV(X86_64_SCRATCH_REG, heap(rn))
+            
         if loc_base == ebp:
             mc.CMP_rb(X86_64_SCRATCH_REG.value, StmGC.H_REVISION)
         else:
             mc.CMP(X86_64_SCRATCH_REG, mem(loc_base, StmGC.H_REVISION))
         #
-        if isinstance(descr, STMReadBarrierDescr):
+        if descr.stmcat == 'P2R':#isinstance(descr, STMReadBarrierDescr):
             # jump to end if h_rev==priv_rev
             mc.J_il8(rx86.Conditions['Z'], 0) # patched below
             jz_location = mc.get_relative_pos()
@@ -2338,21 +2350,29 @@
             jnz_location = mc.get_relative_pos()
 
         # FXCACHE_AT(obj) != obj
-        if isinstance(descr, STMReadBarrierDescr):
+        if descr.stmcat == 'P2R':#isinstance(descr, STMReadBarrierDescr):
             # calculate: temp = obj & FX_MASK
             assert StmGC.FX_MASK == 65535
             assert not is_frame
             mc.MOVZX16(X86_64_SCRATCH_REG, loc_base)
             # calculate: rbc + temp == obj
             rbc = self._get_stm_read_barrier_cache_addr()
-            stmtlocal.tl_segment_prefix(mc)
-            mc.ADD_rj(X86_64_SCRATCH_REG.value, rbc)
+            if we_are_translated():
+                # during tests, _get_stm_rbca returns
+                # an absolute address, not a tl-offset
+                stmtlocal.tl_segment_prefix(mc)
+                mc.ADD_rj(X86_64_SCRATCH_REG.value, rbc)
+            else: # testing:
+                mc.PUSH_r(eax.value)
+                mc.MOV(eax, heap(rbc))
+                mc.ADD(X86_64_SCRATCH_REG, eax)
+                mc.POP_r(eax.value)
             mc.CMP_rm(loc_base.value, (X86_64_SCRATCH_REG.value, 0))
             mc.J_il8(rx86.Conditions['Z'], 0) # patched below
             jz_location2 = mc.get_relative_pos()
 
         # obj->h_tid & GCFLAG_WRITE_BARRIER) != 0
-        if isinstance(descr, STMWriteBarrierDescr):
+        if descr.stmcat == 'P2W':#isinstance(descr, STMWriteBarrierDescr):
             assert IS_X86_64 and (StmGC.GCFLAG_WRITE_BARRIER >> 32) > 0
             assert (StmGC.GCFLAG_WRITE_BARRIER >> 40) == 0
             off = 4
@@ -2398,7 +2418,7 @@
         offset = mc.get_relative_pos() - jz_location
         assert 0 < offset <= 127
         mc.overwrite(jz_location - 1, chr(offset))
-        if isinstance(descr, STMReadBarrierDescr):
+        if descr.stmcat == 'P2R':#isinstance(descr, STMReadBarrierDescr):
             offset = mc.get_relative_pos() - jz_location2
             assert 0 < offset <= 127
             mc.overwrite(jz_location2 - 1, chr(offset))
diff --git a/rpython/jit/backend/x86/test/test_stm_integration.py 
b/rpython/jit/backend/x86/test/test_stm_integration.py
new file mode 100644
--- /dev/null
+++ b/rpython/jit/backend/x86/test/test_stm_integration.py
@@ -0,0 +1,209 @@
+import py
+from rpython.rtyper.lltypesystem import lltype, llmemory, rffi, rstr
+from rpython.jit.metainterp.history import ResOperation, TargetToken,\
+     JitCellToken
+from rpython.jit.metainterp.history import (BoxInt, BoxPtr, ConstInt,
+                                            ConstPtr, Box,
+                                            BasicFailDescr, BasicFinalDescr)
+from rpython.jit.backend.detect_cpu import getcpuclass
+from rpython.jit.backend.x86.arch import WORD
+from rpython.jit.backend.x86.rx86 import fits_in_32bits
+from rpython.jit.backend.llsupport import symbolic
+from rpython.jit.metainterp.resoperation import rop
+from rpython.jit.metainterp.executor import execute
+from rpython.jit.backend.test.runner_test import LLtypeBackendTest
+from rpython.jit.tool.oparser import parse
+from rpython.rtyper.annlowlevel import llhelper, llhelper_args
+from rpython.jit.backend.llsupport.gc import (
+    GcRootMap_stm, BarrierDescr)
+from rpython.jit.backend.llsupport.test.test_gc_integration import (
+    GCDescrShadowstackDirect, BaseTestRegalloc)
+from rpython.jit.backend.llsupport import jitframe
+import ctypes
+
+CPU = getcpuclass()
+
+class MockSTMRootMap(object):
+    is_shadow_stack = True
+    is_stm = True
+    def __init__(self):
+        TP = rffi.CArray(lltype.Signed)
+        self.stack = lltype.malloc(TP, 10, flavor='raw')
+        self.stack_addr = lltype.malloc(TP, 1,
+                                        flavor='raw')
+        self.stack_addr[0] = rffi.cast(lltype.Signed, self.stack)
+    def __del__(self):
+        lltype.free(self.stack_addr, flavor='raw')
+        lltype.free(self.stack, flavor='raw')
+    def register_asm_addr(self, start, mark):
+        pass
+    def get_root_stack_top_addr(self):
+        return rffi.cast(lltype.Signed, self.stack_addr)
+
+class FakeSTMBarrier(BarrierDescr):
+    def __init__(self, gc_ll_descr, stmcat, func):
+        BarrierDescr.__init__(self, gc_ll_descr)
+        self.stmcat = stmcat
+        self.returns_modified_object = True
+        self.B_FUNCPTR_MOD = lltype.Ptr(lltype.FuncType(
+            [llmemory.Address], llmemory.Address))
+        self.write_barrier_fn = llhelper(self.B_FUNCPTR_MOD, func)
+    def get_barrier_funcptr(self, returns_modified_object):
+        assert returns_modified_object
+        return self.write_barrier_fn
+    def get_barrier_fn(self, cpu, returns_modified_object):
+        assert returns_modified_object
+        return self.write_barrier_fn
+
+# ____________________________________________________________
+
+
+def jitframe_allocate(frame_info):
+    frame = lltype.malloc(JITFRAME, frame_info.jfi_frame_depth, zero=True)
+    frame.jf_frame_info = frame_info
+    return frame
+
+JITFRAME = lltype.GcStruct(
+    'JITFRAME',
+    ('h_tid', lltype.Signed),
+    ('h_revision', lltype.Signed),
+    ('h_original', lltype.Signed),
+    ('jf_frame_info', lltype.Ptr(jitframe.JITFRAMEINFO)),
+    ('jf_descr', llmemory.GCREF),
+    ('jf_force_descr', llmemory.GCREF),
+    ('jf_extra_stack_depth', lltype.Signed),
+    ('jf_guard_exc', llmemory.GCREF),
+    ('jf_gcmap', lltype.Ptr(jitframe.GCMAP)),
+    ('jf_gc_trace_state', lltype.Signed),
+    ('jf_frame', lltype.Array(lltype.Signed)),
+    adtmeths = {
+        'allocate': jitframe_allocate,
+    },
+)
+
+JITFRAMEPTR = lltype.Ptr(JITFRAME)
+class FakeGCHeaderBuilder:
+    size_gc_header = WORD
+        
+
+class GCDescrStm(GCDescrShadowstackDirect):
+    def __init__(self):
+        GCDescrShadowstackDirect.__init__(self)
+        self.gcrootmap = MockSTMRootMap()
+        self.gcheaderbuilder = FakeGCHeaderBuilder()
+        self.write_barrier_descr = None
+        self.llop1 = None
+        self.rb_called_on = []
+        self.wb_called_on = []
+        self.stm = True
+
+        def read_barrier(obj):
+            self.rb_called_on.append(obj)
+            return obj
+        def write_barrier(obj):
+            self.wb_called_on.append(obj)
+            return obj
+
+        self.P2Rdescr = FakeSTMBarrier(self, 'P2R', read_barrier)
+        self.P2Wdescr = FakeSTMBarrier(self, 'P2W', write_barrier)
+        
+        self.do_write_barrier = None
+        self.get_nursery_top_addr = None
+        self.get_nursery_free_addr = None
+
+        def malloc_str(length):
+            assert False
+        self.generate_function('malloc_str', malloc_str,
+                               [lltype.Signed])
+        def malloc_unicode(length):
+            assert False
+        self.generate_function('malloc_unicode', malloc_unicode,
+                               [lltype.Signed])
+        def inevitable():
+            pass
+        self.generate_function('stm_try_inevitable',
+                               inevitable, [],
+                               RESULT=lltype.Void)
+        def ptr_eq(x, y): return x == y
+        def ptr_ne(x, y): return x != y
+        self.generate_function('stm_ptr_eq', ptr_eq, [llmemory.GCREF] * 2,
+                               RESULT=lltype.Bool)
+        self.generate_function('stm_ptr_ne', ptr_ne, [llmemory.GCREF] * 2,
+                               RESULT=lltype.Bool)
+
+    def get_malloc_slowpath_addr(self):
+        return None
+
+
+class TestGcStm(BaseTestRegalloc):
+    def get_priv_rev_num(self):
+        return rffi.cast(lltype.Signed, self.priv_rev_num)
+
+    def get_read_cache(self):
+        return rffi.cast(lltype.Signed, self.read_cache_adr)
+    
+    def setup_method(self, meth):
+        cpu = CPU(None, None)
+        cpu.gc_ll_descr = GCDescrStm()
+        self.p2wd = cpu.gc_ll_descr.P2Wdescr
+        self.p2rd = cpu.gc_ll_descr.P2Rdescr
+
+        TP = rffi.CArray(lltype.Signed)
+        self.priv_rev_num = lltype.malloc(TP, 1, flavor='raw')
+        self.read_cache = lltype.malloc(TP, n=65536 / WORD, flavor='raw')
+        self.read_cache_adr = lltype.malloc(TP, 1, flavor='raw')
+        self.read_cache_adr[0] = rffi.cast(lltype.Signed, self.read_cache)
+        
+        cpu.assembler._get_stm_private_rev_num_addr = self.get_priv_rev_num
+        cpu.assembler._get_stm_read_barrier_cache_addr = self.get_read_cache
+        
+        S = lltype.GcForwardReference()
+        S.become(lltype.GcStruct(
+            'S', ('h_tid', lltype.Signed),
+            ('h_revision', lltype.Signed),
+            ('h_original', lltype.Signed)))
+        cpu.gc_ll_descr.fielddescr_tid = None # not needed
+        # = cpu.fielddescrof(S, 'h_tid')
+        self.S = S
+        self.cpu = cpu
+
+    def teardown_method(self, meth):
+        rffi.aroundstate._cleanup_()
+        
+    def assert_in_read_barrier(self, *args):
+        rb_called_on = self.cpu.gc_ll_descr.rb_called_on
+        for i, ref in enumerate(args):
+            assert rffi.cast_ptr_to_adr(ref) == rb_called_on[i]
+    def assert_not_in_read_barrier(self, *args):
+        rb_called_on = self.cpu.gc_ll_descr.rb_called_on
+        for ref in args:
+            assert not rffi.cast_ptr_to_adr(ref) in rb_called_on
+        
+    def test_read_barrier_fastpath(self):
+        cpu = self.cpu
+        cpu.setup_once()
+        PRIV_REV = 3
+        self.priv_rev_num[0] = PRIV_REV
+        for rev in [PRIV_REV, PRIV_REV+1]:
+            s = lltype.malloc(self.S)
+            sgcref = lltype.cast_opaque_ptr(llmemory.GCREF, s)
+            s.h_tid = 0
+            s.h_revision = rev
+            p0 = BoxPtr()
+            operations = [
+                ResOperation(rop.COND_CALL_STM_B, [p0,], None,
+                             descr=self.p2rd),
+                ResOperation(rop.FINISH, [p0], None, descr=BasicFinalDescr(0)),
+                ]
+            inputargs = [p0]
+            looptoken = JitCellToken()
+            cpu.compile_loop(inputargs, operations, looptoken)
+            self.cpu.execute_token(looptoken, sgcref)
+            if rev == PRIV_REV:
+                # fastpath
+                self.assert_not_in_read_barrier(sgcref)
+            else:
+                self.assert_in_read_barrier(sgcref)
+
+
+        
_______________________________________________
pypy-commit mailing list
[email protected]
http://mail.python.org/mailman/listinfo/pypy-commit

Reply via email to