Commits

Armin Rigo committed e756614

Add an optional "pure" flag to bh_getfield_gc & friends, as well as to raw_load.

  • Participants
  • Parent commits 65abf16
  • Branches stmgc-c7

Comments (0)

Files changed (8)

File rpython/jit/backend/llgraph/runner.py

     bh_call_f = _do_call
     bh_call_v = _do_call
 
-    def bh_getfield_gc(self, p, descr):
+    def _bh_getfield(self, p, descr, pure=False):
         p = support.cast_arg(lltype.Ptr(descr.S), p)
         return support.cast_result(descr.FIELD, getattr(p, descr.fieldname))
 
-    bh_getfield_gc_pure = bh_getfield_gc
-    bh_getfield_gc_i = bh_getfield_gc
-    bh_getfield_gc_r = bh_getfield_gc
-    bh_getfield_gc_f = bh_getfield_gc
+    direct_getfield_gc = _bh_getfield
+    direct_getfield_gc_pure = _bh_getfield
+    direct_getfield_raw = _bh_getfield
+    direct_getfield_raw_pure = _bh_getfield
 
-    bh_getfield_raw = bh_getfield_gc
-    bh_getfield_raw_pure = bh_getfield_raw
-    bh_getfield_raw_i = bh_getfield_raw
-    bh_getfield_raw_r = bh_getfield_raw
-    bh_getfield_raw_f = bh_getfield_raw
+    bh_getfield_gc_i = _bh_getfield
+    bh_getfield_gc_r = _bh_getfield
+    bh_getfield_gc_f = _bh_getfield
 
-    def bh_setfield_gc(self, p, newvalue, descr):
+    bh_getfield_raw_i = _bh_getfield
+    bh_getfield_raw_r = _bh_getfield
+    bh_getfield_raw_f = _bh_getfield
+
+    def _bh_setfield(self, p, newvalue, descr):
         p = support.cast_arg(lltype.Ptr(descr.S), p)
         setattr(p, descr.fieldname, support.cast_arg(descr.FIELD, newvalue))
 
-    bh_setfield_gc_i = bh_setfield_gc
-    bh_setfield_gc_r = bh_setfield_gc
-    bh_setfield_gc_f = bh_setfield_gc
+    direct_setfield_gc = _bh_setfield
+    direct_setfield_raw = _bh_setfield
 
-    bh_setfield_raw   = bh_setfield_gc
-    bh_setfield_raw_i = bh_setfield_raw
-    bh_setfield_raw_f = bh_setfield_raw
+    bh_setfield_gc_i = _bh_setfield
+    bh_setfield_gc_r = _bh_setfield
+    bh_setfield_gc_f = _bh_setfield
+
+    bh_setfield_raw   = _bh_setfield
+    bh_setfield_raw_i = _bh_setfield
+    bh_setfield_raw_f = _bh_setfield
 
     def bh_arraylen_gc(self, a, descr):
         array = a._obj.container
             array = getattr(array, descr.OUTERA._arrayfld)
         return array.getlength()
 
-    def bh_getarrayitem_gc(self, a, index, descr):
+    def _bh_getarrayitem(self, a, index, descr, pure=False):
         a = support.cast_arg(lltype.Ptr(descr.A), a)
         array = a._obj
         return support.cast_result(descr.A.OF, array.getitem(index))
 
-    bh_getarrayitem_gc_pure = bh_getarrayitem_gc
-    bh_getarrayitem_gc_i = bh_getarrayitem_gc
-    bh_getarrayitem_gc_r = bh_getarrayitem_gc
-    bh_getarrayitem_gc_f = bh_getarrayitem_gc
+    direct_getarrayitem_gc = _bh_getarrayitem
+    direct_getarrayitem_gc_pure = _bh_getarrayitem
+    direct_getarrayitem_raw = _bh_getarrayitem
+    direct_getarrayitem_raw_pure = _bh_getarrayitem
 
-    bh_getarrayitem_raw = bh_getarrayitem_gc
-    bh_getarrayitem_raw_pure = bh_getarrayitem_raw
-    bh_getarrayitem_raw_i = bh_getarrayitem_raw
-    bh_getarrayitem_raw_r = bh_getarrayitem_raw
-    bh_getarrayitem_raw_f = bh_getarrayitem_raw
+    bh_getarrayitem_gc_i = _bh_getarrayitem
+    bh_getarrayitem_gc_r = _bh_getarrayitem
+    bh_getarrayitem_gc_f = _bh_getarrayitem
 
-    def bh_setarrayitem_gc(self, a, index, item, descr):
+    bh_getarrayitem_raw_i = _bh_getarrayitem
+    bh_getarrayitem_raw_r = _bh_getarrayitem
+    bh_getarrayitem_raw_f = _bh_getarrayitem
+
+    def _bh_setarrayitem(self, a, index, item, descr):
         a = support.cast_arg(lltype.Ptr(descr.A), a)
         array = a._obj
         array.setitem(index, support.cast_arg(descr.A.OF, item))
 
-    bh_setarrayitem_gc_i = bh_setarrayitem_gc
-    bh_setarrayitem_gc_r = bh_setarrayitem_gc
-    bh_setarrayitem_gc_f = bh_setarrayitem_gc
+    direct_setarrayitem_gc = _bh_setarrayitem
+    direct_setarrayitem_raw = _bh_setarrayitem
 
-    bh_setarrayitem_raw   = bh_setarrayitem_gc
-    bh_setarrayitem_raw_i = bh_setarrayitem_raw
-    bh_setarrayitem_raw_r = bh_setarrayitem_raw
-    bh_setarrayitem_raw_f = bh_setarrayitem_raw
+    bh_setarrayitem_gc_i = _bh_setarrayitem
+    bh_setarrayitem_gc_r = _bh_setarrayitem
+    bh_setarrayitem_gc_f = _bh_setarrayitem
+
+    bh_setarrayitem_raw_i = _bh_setarrayitem
+    bh_setarrayitem_raw_r = _bh_setarrayitem
+    bh_setarrayitem_raw_f = _bh_setarrayitem
 
     def bh_getinteriorfield_gc(self, a, index, descr):
         array = a._obj.container
         return _op_default_implementation
 
     def _new_execute(opname):
+        if hasattr(LLGraphCPU, 'direct_' + opname):
+            methname = 'direct_' + opname
+        else:
+            methname = 'bh_' + opname
+        #
         def execute(self, descr, *args):
             if descr is not None:
                 new_args = args + (descr,)
             else:
                 new_args = args
-            return getattr(self.cpu, 'bh_' + opname)(*new_args)
+            return getattr(self.cpu, methname)(*new_args)
         execute.func_name = 'execute_' + opname
         return execute
 

File rpython/jit/backend/llsupport/llmodel.py

     # ____________________ RAW PRIMITIVES ________________________
 
     @specialize.argtype(1)
-    def read_int_at_mem(self, gcref, ofs, size, sign):
+    def read_int_at_mem(self, gcref, ofs, size, sign, pure=False):
         for STYPE, UTYPE, itemsize in unroll_basic_sizes:
             if size == itemsize:
                 if sign:
-                    val = llop.raw_load(STYPE, gcref, ofs)
+                    val = llop.raw_load(STYPE, gcref, ofs, pure)
                     val = rffi.cast(lltype.Signed, val)
                 else:
-                    val = llop.raw_load(UTYPE, gcref, ofs)
+                    val = llop.raw_load(UTYPE, gcref, ofs, pure)
                     val = rffi.cast(lltype.Signed, val)
                 return val
         else:
             raise NotImplementedError("size = %d" % size)
 
     @specialize.argtype(1)
-    def read_ref_at_mem(self, gcref, ofs):
-        return llop.raw_load(llmemory.GCREF, gcref, ofs)
+    def read_ref_at_mem(self, gcref, ofs, pure=False):
+        return llop.raw_load(llmemory.GCREF, gcref, ofs, pure)
 
     # non-@specialized: must only be called with llmemory.GCREF
     def write_ref_at_mem(self, gcref, ofs, newvalue):
         # the write barrier is implied above
 
     @specialize.argtype(1)
-    def read_float_at_mem(self, gcref, ofs):
-        return llop.raw_load(longlong.FLOATSTORAGE, gcref, ofs)
+    def read_float_at_mem(self, gcref, ofs, pure=False):
+        return llop.raw_load(longlong.FLOATSTORAGE, gcref, ofs, pure)
 
     @specialize.argtype(1)
     def write_float_at_mem(self, gcref, ofs, newvalue):
     def bh_arraylen_gc(self, array, arraydescr):
         assert isinstance(arraydescr, ArrayDescr)
         ofs = arraydescr.lendescr.offset
-        return self.read_int_at_mem(array, ofs, WORD, 1)
+        return self.read_int_at_mem(array, ofs, WORD, 1, True)
 
     @specialize.argtype(1)
-    def bh_getarrayitem_gc_i(self, gcref, itemindex, arraydescr):
+    def bh_getarrayitem_gc_i(self, gcref, itemindex, arraydescr, pure=False):
         ofs, size, sign = self.unpack_arraydescr_size(arraydescr)
         return self.read_int_at_mem(gcref, ofs + itemindex * size, size,
-                                    sign)
+                                    sign, pure)
 
-    def bh_getarrayitem_gc_r(self, gcref, itemindex, arraydescr):
+    def bh_getarrayitem_gc_r(self, gcref, itemindex, arraydescr, pure=False):
         ofs = self.unpack_arraydescr(arraydescr)
-        return self.read_ref_at_mem(gcref, itemindex * WORD + ofs)
+        return self.read_ref_at_mem(gcref, itemindex * WORD + ofs, pure)
 
     @specialize.argtype(1)
-    def bh_getarrayitem_gc_f(self, gcref, itemindex, arraydescr):
+    def bh_getarrayitem_gc_f(self, gcref, itemindex, arraydescr, pure=False):
         ofs = self.unpack_arraydescr(arraydescr)
         fsize = rffi.sizeof(longlong.FLOATSTORAGE)
-        return self.read_float_at_mem(gcref, itemindex * fsize + ofs)
+        return self.read_float_at_mem(gcref, itemindex * fsize + ofs, pure)
 
     @specialize.argtype(1)
     def bh_setarrayitem_gc_i(self, gcref, itemindex, newvalue, arraydescr):
         return ord(u.chars[index])
 
     @specialize.argtype(1)
-    def bh_getfield_gc_i(self, struct, fielddescr):
+    def bh_getfield_gc_i(self, struct, fielddescr, pure=False):
         ofs, size, sign = self.unpack_fielddescr_size(fielddescr)
-        return self.read_int_at_mem(struct, ofs, size, sign)
+        return self.read_int_at_mem(struct, ofs, size, sign, pure)
 
     @specialize.argtype(1)
-    def bh_getfield_gc_r(self, struct, fielddescr):
+    def bh_getfield_gc_r(self, struct, fielddescr, pure=False):
         ofs = self.unpack_fielddescr(fielddescr)
-        return self.read_ref_at_mem(struct, ofs)
+        return self.read_ref_at_mem(struct, ofs, pure)
 
     @specialize.argtype(1)
-    def bh_getfield_gc_f(self, struct, fielddescr):
+    def bh_getfield_gc_f(self, struct, fielddescr, pure=False):
         ofs = self.unpack_fielddescr(fielddescr)
-        return self.read_float_at_mem(struct, ofs)
+        return self.read_float_at_mem(struct, ofs, pure)
 
     bh_getfield_raw_i = bh_getfield_gc_i
     bh_getfield_raw_r = bh_getfield_gc_r

File rpython/jit/backend/model.py

     # lltype specific operations
     # --------------------------
 
-    def bh_getarrayitem_gc_i(self, array, index, arraydescr):
+    def bh_getarrayitem_gc_i(self, array, index, arraydescr, pure=False):
         raise NotImplementedError
-    def bh_getarrayitem_gc_r(self, array, index, arraydescr):
+    def bh_getarrayitem_gc_r(self, array, index, arraydescr, pure=False):
         raise NotImplementedError
-    def bh_getarrayitem_gc_f(self, array, index, arraydescr):
+    def bh_getarrayitem_gc_f(self, array, index, arraydescr, pure=False):
         raise NotImplementedError
 
-    def bh_getfield_gc_i(self, struct, fielddescr):
+    def bh_getfield_gc_i(self, struct, fielddescr, pure=False):
         raise NotImplementedError
-    def bh_getfield_gc_r(self, struct, fielddescr):
+    def bh_getfield_gc_r(self, struct, fielddescr, pure=False):
         raise NotImplementedError
-    def bh_getfield_gc_f(self, struct, fielddescr):
+    def bh_getfield_gc_f(self, struct, fielddescr, pure=False):
         raise NotImplementedError
 
-    def bh_getfield_raw_i(self, struct, fielddescr):
+    def bh_getfield_raw_i(self, struct, fielddescr, pure=False):
         raise NotImplementedError
-    def bh_getfield_raw_r(self, struct, fielddescr):
+    def bh_getfield_raw_r(self, struct, fielddescr, pure=False):
         raise NotImplementedError
-    def bh_getfield_raw_f(self, struct, fielddescr):
+    def bh_getfield_raw_f(self, struct, fielddescr, pure=False):
         raise NotImplementedError
 
     def bh_new(self, sizedescr):

File rpython/jit/backend/test/runner_test.py

         r = self.cpu.bh_getfield_gc_i(r1.value, descrshort)
         assert r == 1313
         self.cpu.bh_setfield_gc_i(r1.value, 1333, descrshort)
-        r = self.cpu.bh_getfield_gc_i(r1.value, descrshort)
+        r = self.cpu.bh_getfield_gc_i(r1.value, descrshort, pure=True)
         assert r == 1333
         r = self.execute_operation(rop.GETFIELD_GC, [r1], 'int',
                                    descr=descrshort)
         b = lltype.malloc(B, 4)
         b[3] = a
         x = cpu.bh_getarrayitem_gc_r(
-            lltype.cast_opaque_ptr(llmemory.GCREF, b), 3, descr_B)
+            lltype.cast_opaque_ptr(llmemory.GCREF, b), 3, descr_B, pure=True)
         assert lltype.cast_opaque_ptr(lltype.Ptr(A), x) == a
         if self.cpu.supports_floats:
             C = lltype.GcArray(lltype.Float)
             descrfld_rx)
         assert x == ord('?')
         #
+        x = cpu.bh_getfield_raw_i(
+            heaptracker.adr2int(llmemory.cast_ptr_to_adr(rs)),
+            descrfld_rx, pure=True)
+        assert x == ord('?')
+        #
         cpu.bh_setfield_raw_i(
             heaptracker.adr2int(llmemory.cast_ptr_to_adr(rs)),
             ord('!'), descrfld_rx)
             expected = rffi.cast(lltype.Signed, rffi.cast(RESTYPE, value))
             a[3] = rffi.cast(RESTYPE, value)
             a_rawint = heaptracker.adr2int(llmemory.cast_ptr_to_adr(a))
-            x = cpu.bh_getarrayitem_raw_i(a_rawint, 3, descrarray)
+            x = cpu.bh_getarrayitem_raw_i(a_rawint, 3, descrarray, pure=False)
+            assert x == expected, (
+                "%r: got %r, expected %r" % (RESTYPE, x, expected))
+            x = cpu.bh_getarrayitem_raw_i(a_rawint, 3, descrarray, pure=True)
             assert x == expected, (
                 "%r: got %r, expected %r" % (RESTYPE, x, expected))
             lltype.free(a, flavor='raw')

File rpython/jit/metainterp/executor.py

     if condbox.getint():
         do_call(cpu, metainterp, argboxes[1:], descr)
 
-def do_getarrayitem_gc(cpu, _, arraybox, indexbox, arraydescr):
+def _do_getarrayitem_gc(cpu, pure, arraybox, indexbox, arraydescr):
     array = arraybox.getref_base()
     index = indexbox.getint()
     if arraydescr.is_array_of_pointers():
-        return BoxPtr(cpu.bh_getarrayitem_gc_r(array, index, arraydescr))
+        return BoxPtr(cpu.bh_getarrayitem_gc_r(array, index, arraydescr, pure))
     elif arraydescr.is_array_of_floats():
-        return BoxFloat(cpu.bh_getarrayitem_gc_f(array, index, arraydescr))
+        return BoxFloat(cpu.bh_getarrayitem_gc_f(array, index, arraydescr,
+                                                 pure))
     else:
-        return BoxInt(cpu.bh_getarrayitem_gc_i(array, index, arraydescr))
+        return BoxInt(cpu.bh_getarrayitem_gc_i(array, index, arraydescr, pure))
 
-def do_getarrayitem_raw(cpu, _, arraybox, indexbox, arraydescr):
+def do_getarrayitem_gc(cpu, _, arraybox, indexbox, arraydescr):
+    return _do_getarrayitem_gc(cpu, False, arraybox, indexbox, arraydescr)
+
+def do_getarrayitem_gc_pure(cpu, _, arraybox, indexbox, arraydescr):
+    return _do_getarrayitem_gc(cpu, True, arraybox, indexbox, arraydescr)
+
+def _do_getarrayitem_raw(cpu, pure, arraybox, indexbox, arraydescr):
     array = arraybox.getint()
     index = indexbox.getint()
     assert not arraydescr.is_array_of_pointers()
     if arraydescr.is_array_of_floats():
-        return BoxFloat(cpu.bh_getarrayitem_raw_f(array, index, arraydescr))
+        return BoxFloat(cpu.bh_getarrayitem_raw_f(array, index, arraydescr,
+                                                  pure))
     else:
-        return BoxInt(cpu.bh_getarrayitem_raw_i(array, index, arraydescr))
+        return BoxInt(cpu.bh_getarrayitem_raw_i(array, index, arraydescr,
+                                                pure))
+
+def do_getarrayitem_raw(cpu, _, arraybox, indexbox, arraydescr):
+    return _do_getarrayitem_raw(cpu, False, arraybox, indexbox, arraydescr)
+
+def do_getarrayitem_raw_pure(cpu, _, arraybox, indexbox, arraydescr):
+    return _do_getarrayitem_raw(cpu, True, arraybox, indexbox, arraydescr)
 
 def do_setarrayitem_gc(cpu, _, arraybox, indexbox, itembox, arraydescr):
     array = arraybox.getref_base()
     else:
         cpu.bh_setinteriorfield_gc_i(array, index, valuebox.getint(), descr)
 
-def do_getfield_gc(cpu, _, structbox, fielddescr):
+def _do_getfield_gc(cpu, pure, structbox, fielddescr):
     struct = structbox.getref_base()
     if fielddescr.is_pointer_field():
-        return BoxPtr(cpu.bh_getfield_gc_r(struct, fielddescr))
+        return BoxPtr(cpu.bh_getfield_gc_r(struct, fielddescr, pure))
     elif fielddescr.is_float_field():
-        return BoxFloat(cpu.bh_getfield_gc_f(struct, fielddescr))
+        return BoxFloat(cpu.bh_getfield_gc_f(struct, fielddescr, pure))
     else:
-        return BoxInt(cpu.bh_getfield_gc_i(struct, fielddescr))
+        return BoxInt(cpu.bh_getfield_gc_i(struct, fielddescr, pure))
 
-def do_getfield_raw(cpu, _, structbox, fielddescr):
+def do_getfield_gc(cpu, _, structbox, fielddescr):
+    return _do_getfield_gc(cpu, False, structbox, fielddescr)
+
+def do_getfield_gc_pure(cpu, _, structbox, fielddescr):
+    return _do_getfield_gc(cpu, True, structbox, fielddescr)
+
+def _do_getfield_raw(cpu, pure, structbox, fielddescr):
     check_descr(fielddescr)
     struct = structbox.getint()
     if fielddescr.is_pointer_field():
-        return BoxPtr(cpu.bh_getfield_raw_r(struct, fielddescr))
+        return BoxPtr(cpu.bh_getfield_raw_r(struct, fielddescr, pure))
     elif fielddescr.is_float_field():
-        return BoxFloat(cpu.bh_getfield_raw_f(struct, fielddescr))
+        return BoxFloat(cpu.bh_getfield_raw_f(struct, fielddescr, pure))
     else:
-        return BoxInt(cpu.bh_getfield_raw_i(struct, fielddescr))
+        return BoxInt(cpu.bh_getfield_raw_i(struct, fielddescr, pure))
+
+def do_getfield_raw(cpu, _, structbox, fielddescr):
+    return _do_getfield_raw(cpu, False, structbox, fielddescr)
+
+def do_getfield_raw_pure(cpu, _, structbox, fielddescr):
+    return _do_getfield_raw(cpu, True, structbox, fielddescr)
 
 def do_setfield_gc(cpu, _, structbox, itembox, fielddescr):
     struct = structbox.getref_base()
                 execute[value] = globals()[name]
                 continue
             #
-            # Maybe the same without the _PURE suffix?
-            if key.endswith('_PURE'):
-                key = key[:-5]
-                name = 'do_' + key.lower()
-                if name in globals():
-                    execute[value] = globals()[name]
-                    continue
-            #
             # If missing, fallback to the bhimpl_xxx() method of the
             # blackhole interpreter.  This only works if there is a
             # method of the exact same name and it accepts simple
                          rop.DEBUG_MERGE_POINT,
                          rop.JIT_DEBUG,
                          rop.SETARRAYITEM_RAW,
+                         rop.CALL_PURE,
                          rop.CALL_RELEASE_GIL,
                          rop.QUASIIMMUT_FIELD,
                          rop.CALL_MALLOC_GC,

File rpython/rtyper/lltypesystem/opimpl.py

     p = rffi.cast(rffi.CArrayPtr(TVAL), p + ofs)
     p[0] = newvalue
 
-def op_raw_load(TVAL, p, ofs):
+def op_raw_load(TVAL, p, ofs, pure=False):
     from rpython.rtyper.lltypesystem import rffi
     p = rffi.cast(llmemory.Address, p)
     p = rffi.cast(rffi.CArrayPtr(TVAL), p + ofs)

File rpython/translator/stm/readbarrier.py

 from rpython.flowspace.model import SpaceOperation, Constant, Variable
 from rpython.translator.unsimplify import varoftype
 from rpython.rtyper.lltypesystem import lltype
+from rpython.translator.stm.support import is_immutable
 
 
 READ_OPS = set(['getfield', 'getarrayitem', 'getinteriorfield', 'raw_load'])
         else:
             raise AssertionError(v)
 
-def is_immutable(op):
-    if op.opname in ('getfield', 'setfield'):
-        STRUCT = op.args[0].concretetype.TO
-        return STRUCT._immutable_field(op.args[1].value)
-    if op.opname in ('getarrayitem', 'setarrayitem'):
-        ARRAY = op.args[0].concretetype.TO
-        return ARRAY._immutable_field()
-    if op.opname == 'getinteriorfield':
-        OUTER = op.args[0].concretetype.TO
-        return OUTER._immutable_interiorfield(unwraplist(op.args[1:]))
-    if op.opname == 'setinteriorfield':
-        OUTER = op.args[0].concretetype.TO
-        return OUTER._immutable_interiorfield(unwraplist(op.args[1:-1]))
-    if op.opname in ('raw_load', 'raw_store'):
-        return False
-
 
 def insert_stm_read_barrier(transformer, graph):
     # We need to put enough 'stm_read' in the graph so that any

File rpython/translator/stm/support.py

     if op.opname == 'setinteriorfield':
         OUTER = op.args[0].concretetype.TO
         return OUTER._immutable_interiorfield(unwraplist(op.args[1:-1]))
-    if op.opname in ('raw_load', 'raw_store'):
+    if op.opname == 'raw_load':
+        return len(op.args) >= 3 and bool(op.args[2].value)
+    if op.opname == 'raw_store':
         return False
     raise AssertionError(op)