[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