Commits

Armin Rigo committed 781dce1 Merge

hg merge default

  • Participants
  • Parent commits 4a08783, af5e7f0
  • Branches stmgc-c4

Comments (0)

Files changed (13)

File lib_pypy/_tkinter/__init__.py

 READABLE = tklib.TCL_READABLE
 WRITABLE = tklib.TCL_WRITABLE
 EXCEPTION = tklib.TCL_EXCEPTION
+DONT_WAIT = tklib.TCL_DONT_WAIT
 
 def create(screenName=None, baseName=None, className=None,
            interactive=False, wantobjects=False, wantTk=True,

File lib_pypy/_tkinter/app.py

 from . import TclError
 from .tclobj import TclObject, FromObj, AsObj, TypeCache
 
+import contextlib
 import sys
+import threading
+import time
+
+
+class _DummyLock(object):
+    "A lock-like object that does not do anything"
+    def acquire(self):
+        pass
+    def release(self):
+        pass
+    def __enter__(self):
+        pass
+    def __exit__(self, *exc):
+        pass
+
 
 def varname_converter(input):
     if isinstance(input, TclObject):
     def PythonCmd(clientData, interp, argc, argv):
         self = tkffi.from_handle(clientData)
         assert self.app.interp == interp
-        try:
-            args = [tkffi.string(arg) for arg in argv[1:argc]]
-            result = self.func(*args)
-            obj = AsObj(result)
-            tklib.Tcl_SetObjResult(interp, obj)
-        except:
-            self.app.errorInCmd = True
-            self.app.exc_info = sys.exc_info()
-            return tklib.TCL_ERROR
-        else:
-            return tklib.TCL_OK
+        with self.app._tcl_lock_released():
+            try:
+                args = [tkffi.string(arg) for arg in argv[1:argc]]
+                result = self.func(*args)
+                obj = AsObj(result)
+                tklib.Tcl_SetObjResult(interp, obj)
+            except:
+                self.app.errorInCmd = True
+                self.app.exc_info = sys.exc_info()
+                return tklib.TCL_ERROR
+            else:
+                return tklib.TCL_OK
 
     @tkffi.callback("Tcl_CmdDeleteProc")
     def PythonCmdDelete(clientData):
 
 
 class TkApp(object):
+    _busywaitinterval = 0.02  # 20ms.
+
     def __new__(cls, screenName, baseName, className,
                 interactive, wantobjects, wantTk, sync, use):
         if not wantobjects:
         self.quitMainLoop = False
         self.errorInCmd = False
 
+        if not self.threaded:
+            # TCL is not thread-safe, calls needs to be serialized.
+            self._tcl_lock = threading.Lock()
+        else:
+            self._tcl_lock = _DummyLock()
+
         self._typeCache = TypeCache()
         self._commands = {}
 
         if self.threaded and self.thread_id != tklib.Tcl_GetCurrentThread():
             raise RuntimeError("Calling Tcl from different appartment")
 
+    @contextlib.contextmanager
+    def _tcl_lock_released(self):
+        "Context manager to temporarily release the tcl lock."
+        self._tcl_lock.release()
+        yield
+        self._tcl_lock.acquire()
+
     def loadtk(self):
         # We want to guard against calling Tk_Init() multiple times
         err = tklib.Tcl_Eval(self.interp, "info exists     tk_version")
         flags=tklib.TCL_LEAVE_ERR_MSG
         if global_only:
             flags |= tklib.TCL_GLOBAL_ONLY
-        res = tklib.Tcl_GetVar2Ex(self.interp, name1, name2, flags)
-        if not res:
-            self.raiseTclError()
-        assert self._wantobjects
-        return FromObj(self, res)
+        with self._tcl_lock:
+            res = tklib.Tcl_GetVar2Ex(self.interp, name1, name2, flags)
+            if not res:
+                self.raiseTclError()
+            assert self._wantobjects
+            return FromObj(self, res)
 
     def _setvar(self, name1, value, global_only=False):
         name1 = varname_converter(name1)
+        # XXX Acquire tcl lock???
         newval = AsObj(value)
         flags=tklib.TCL_LEAVE_ERR_MSG
         if global_only:
             flags |= tklib.TCL_GLOBAL_ONLY
-        res = tklib.Tcl_SetVar2Ex(self.interp, name1, tkffi.NULL,
-                                  newval, flags)
-        if not res:
-            self.raiseTclError()
+        with self._tcl_lock:
+            res = tklib.Tcl_SetVar2Ex(self.interp, name1, tkffi.NULL,
+                                      newval, flags)
+            if not res:
+                self.raiseTclError()
 
     def _unsetvar(self, name1, name2=None, global_only=False):
         name1 = varname_converter(name1)
         flags=tklib.TCL_LEAVE_ERR_MSG
         if global_only:
             flags |= tklib.TCL_GLOBAL_ONLY
-        res = tklib.Tcl_UnsetVar2(self.interp, name1, name2, flags)
-        if res == tklib.TCL_ERROR:
-            self.raiseTclError()
+        with self._tcl_lock:
+            res = tklib.Tcl_UnsetVar2(self.interp, name1, name2, flags)
+            if res == tklib.TCL_ERROR:
+                self.raiseTclError()
 
     def getvar(self, name1, name2=None):
         return self._var_invoke(self._getvar, name1, name2)
         if self.threaded and self.thread_id != tklib.Tcl_GetCurrentThread():
             raise NotImplementedError("Call from another thread")
 
-        res = tklib.Tcl_CreateCommand(
-            self.interp, cmdName, _CommandData.PythonCmd,
-            clientData, _CommandData.PythonCmdDelete)
+        with self._tcl_lock:
+            res = tklib.Tcl_CreateCommand(
+                self.interp, cmdName, _CommandData.PythonCmd,
+                clientData, _CommandData.PythonCmdDelete)
         if not res:
             raise TclError("can't create Tcl command")
 
         if self.threaded and self.thread_id != tklib.Tcl_GetCurrentThread():
             raise NotImplementedError("Call from another thread")
 
-        res = tklib.Tcl_DeleteCommand(self.interp, cmdName)
+        with self._tcl_lock:
+            res = tklib.Tcl_DeleteCommand(self.interp, cmdName)
         if res == -1:
             raise TclError("can't delete Tcl command")
 
                 tklib.Tcl_IncrRefCount(obj)
                 objects[i] = obj
 
-            res = tklib.Tcl_EvalObjv(self.interp, argc, objects, flags)
-            if res == tklib.TCL_ERROR:
-                self.raiseTclError()
-            else:
-                result = self._callResult()
+            with self._tcl_lock:
+                res = tklib.Tcl_EvalObjv(self.interp, argc, objects, flags)
+                if res == tklib.TCL_ERROR:
+                    self.raiseTclError()
+                else:
+                    result = self._callResult()
         finally:
             for obj in objects:
                 if obj:
 
     def eval(self, script):
         self._check_tcl_appartment()
-        res = tklib.Tcl_Eval(self.interp, script)
-        if res == tklib.TCL_ERROR:
-            self.raiseTclError()
-        return tkffi.string(tklib.Tcl_GetStringResult(self.interp))
+        with self._tcl_lock:
+            res = tklib.Tcl_Eval(self.interp, script)
+            if res == tklib.TCL_ERROR:
+                self.raiseTclError()
+            return tkffi.string(tklib.Tcl_GetStringResult(self.interp))
 
     def evalfile(self, filename):
         self._check_tcl_appartment()
-        res = tklib.Tcl_EvalFile(self.interp, filename)
-        if res == tklib.TCL_ERROR:
-            self.raiseTclError()
-        return tkffi.string(tklib.Tcl_GetStringResult(self.interp))
+        with self._tcl_lock:
+            res = tklib.Tcl_EvalFile(self.interp, filename)
+            if res == tklib.TCL_ERROR:
+                self.raiseTclError()
+            return tkffi.string(tklib.Tcl_GetStringResult(self.interp))
 
     def split(self, arg):
         if isinstance(arg, tuple):
             if self.threaded:
                 result = tklib.Tcl_DoOneEvent(0)
             else:
-                raise NotImplementedError("TCL configured without threads")
+                with self._tcl_lock:
+                    result = tklib.Tcl_DoOneEvent(tklib.TCL_DONT_WAIT)
+                if result == 0:
+                    time.sleep(self._busywaitinterval)
 
             if result < 0:
                 break

File lib_pypy/_tkinter/tklib.py

 #define TCL_EVAL_DIRECT ...
 #define TCL_EVAL_GLOBAL ...
 
+#define TCL_DONT_WAIT ...
+
 typedef unsigned short Tcl_UniChar;
 typedef ... Tcl_Interp;
 typedef ...* Tcl_ThreadId;
     linklibs = ['tk85', 'tcl85']
     libdirs = ['/usr/local/lib', '/usr/X11R6/lib']
 else:
-    incdirs=['/usr/include/tcl'],
-    linklibs=['tcl', 'tk'],
+    incdirs=['/usr/include/tcl']
+    linklibs=['tcl', 'tk']
     libdirs = []
 
 tklib = tkffi.verify("""

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

 
     @specialize.argtype(1)
     def read_int_at_mem(self, gcref, ofs, size, sign):
-        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:
             if size == itemsize:
                 if sign:
-                    items = rffi.cast(rffi.CArrayPtr(STYPE), items)
-                    val = items[0]
+                    val = llop.raw_load(STYPE, gcref, ofs)
                     val = rffi.cast(lltype.Signed, val)
                 else:
-                    items = rffi.cast(rffi.CArrayPtr(UTYPE), items)
-                    val = items[0]
+                    val = llop.raw_load(UTYPE, gcref, ofs)
                     val = rffi.cast(lltype.Signed, val)
-                # --- end of GC unsafe code ---
                 return val
         else:
             raise NotImplementedError("size = %d" % size)
 
     @specialize.argtype(1)
-    def write_int_at_mem(self, gcref, ofs, size, sign, newvalue):
-        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)
+    def write_int_at_mem(self, gcref, ofs, size, newvalue):
         for TYPE, _, itemsize in unroll_basic_sizes:
             if size == itemsize:
-                items = rffi.cast(rffi.CArrayPtr(TYPE), items)
-                items[0] = rffi.cast(TYPE, newvalue)
-                # --- end of GC unsafe code ---
+                newvalue = rffi.cast(TYPE, newvalue)
+                llop.raw_store(lltype.Void, gcref, ofs, newvalue)
                 return
         else:
             raise NotImplementedError("size = %d" % size)
 
     def read_ref_at_mem(self, gcref, 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), ofs)
-        items = rffi.cast(rffi.CArrayPtr(lltype.Signed), items)
-        pval = self._cast_int_to_gcref(items[0])
-        # --- end of GC unsafe code ---
-        return pval
+        return llop.raw_load(llmemory.GCREF, gcref, ofs)
 
     def write_ref_at_mem(self, gcref, ofs, newvalue):
-        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(lltype.Signed), items)
-        items[0] = self.cast_gcref_to_int(newvalue)
-        # --- end of GC unsafe code ---
+        llop.raw_store(lltype.Void, gcref, ofs, newvalue)
+        # the write barrier is implied above
 
     @specialize.argtype(1)
     def read_float_at_mem(self, gcref, 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), ofs)
-        items = rffi.cast(rffi.CArrayPtr(longlong.FLOATSTORAGE), items)
-        fval = items[0]
-        # --- end of GC unsafe code ---
-        return fval
+        return llop.raw_load(longlong.FLOATSTORAGE, gcref, ofs)
 
     @specialize.argtype(1)
     def write_float_at_mem(self, gcref, ofs, newvalue):
-        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)
-        items[0] = newvalue
-        # --- end of GC unsafe code ---
+        llop.raw_store(lltype.Void, gcref, ofs, newvalue)
 
     # ____________________________________________________________
 
         """
         descr = self.gc_ll_descr.getframedescrs(self).arraydescr
         ofs = self.unpack_arraydescr(descr)
-        self.write_int_at_mem(newframe, ofs + index, WORD, 1, value)
+        self.write_int_at_mem(newframe, ofs + index, WORD, value)
 
     def set_ref_value(self, newframe, index, value):
         descr = self.gc_ll_descr.getframedescrs(self).arraydescr
 
     def bh_arraylen_gc(self, array, arraydescr):
         assert isinstance(arraydescr, ArrayDescr)
-        array = self.gc_ll_descr.do_stm_barrier(array, 'R')
         ofs = arraydescr.lendescr.offset
-        return rffi.cast(rffi.CArrayPtr(lltype.Signed), array)[ofs/WORD]
+        return self.read_int_at_mem(array, ofs, WORD, 1)
 
     @specialize.argtype(1)
     def bh_getarrayitem_gc_i(self, gcref, itemindex, arraydescr):
     @specialize.argtype(1)
     def bh_setarrayitem_gc_i(self, gcref, itemindex, newvalue, arraydescr):
         ofs, size, sign = self.unpack_arraydescr_size(arraydescr)
-        self.write_int_at_mem(gcref, ofs + itemindex * size, size, sign,
-                              newvalue)
+        self.write_int_at_mem(gcref, ofs + itemindex * size, size, newvalue)
 
     def bh_setarrayitem_gc_r(self, gcref, itemindex, newvalue, arraydescr):
         ofs = self.unpack_arraydescr(arraydescr)
 
     def bh_getinteriorfield_gc_i(self, gcref, itemindex, descr):
         assert isinstance(descr, InteriorFieldDescr)
-        arraydescr = descr.arraydescr
-        ofs, size, _ = self.unpack_arraydescr_size(arraydescr)
-        ofs += descr.fielddescr.offset
-        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:
-            if fieldsize == itemsize:
-                if sign:
-                    item = rffi.cast(rffi.CArrayPtr(STYPE), items)
-                    val = item[0]
-                    val = rffi.cast(lltype.Signed, val)
-                else:
-                    item = rffi.cast(rffi.CArrayPtr(UTYPE), items)
-                    val = item[0]
-                    val = rffi.cast(lltype.Signed, val)
-                # --- end of GC unsafe code ---
-                return val
-        else:
-            raise NotImplementedError("size = %d" % fieldsize)
+        ofs, size, _ = self.unpack_arraydescr_size(descr.arraydescr)
+        fldofs, fldsize, sign = self.unpack_fielddescr_size(descr.fielddescr)
+        ofs += itemindex * size + fldofs
+        return self.read_int_at_mem(gcref, ofs, fldsize, sign)
 
     def bh_getinteriorfield_gc_r(self, gcref, itemindex, descr):
         assert isinstance(descr, InteriorFieldDescr)
-        arraydescr = descr.arraydescr
-        ofs, size, _ = self.unpack_arraydescr_size(arraydescr)
+        ofs, size, _ = self.unpack_arraydescr_size(descr.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)
-        items = rffi.cast(rffi.CArrayPtr(lltype.Signed), items)
-        pval = self._cast_int_to_gcref(items[0])
-        # --- end of GC unsafe code ---
-        return pval
+        fullofs = itemindex * size + ofs
+        return self.read_ref_at_mem(gcref, fullofs)
 
     def bh_getinteriorfield_gc_f(self, gcref, itemindex, descr):
         assert isinstance(descr, InteriorFieldDescr)
-        arraydescr = descr.arraydescr
-        ofs, size, _ = self.unpack_arraydescr_size(arraydescr)
+        ofs, size, _ = self.unpack_arraydescr_size(descr.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)
-        items = rffi.cast(rffi.CArrayPtr(longlong.FLOATSTORAGE), items)
-        fval = items[0]
-        # --- end of GC unsafe code ---
-        return fval
+        fullofs = itemindex * size + ofs
+        return self.read_float_at_mem(gcref, fullofs)
 
-    def bh_setinteriorfield_gc_i(self, gcref, itemindex, value, descr):
+    def bh_setinteriorfield_gc_i(self, gcref, itemindex, newvalue, descr):
         assert isinstance(descr, InteriorFieldDescr)
-        arraydescr = descr.arraydescr
-        ofs, size, _ = self.unpack_arraydescr_size(arraydescr)
-        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:
-            if fieldsize == itemsize:
-                items = rffi.cast(rffi.CArrayPtr(TYPE), items)
-                items[0] = rffi.cast(TYPE, value)
-                # --- end of GC unsafe code ---
-                return
-        else:
-            raise NotImplementedError("size = %d" % fieldsize)
+        ofs, size, _ = self.unpack_arraydescr_size(descr.arraydescr)
+        fldofs, fldsize, _ = self.unpack_fielddescr_size(descr.fielddescr)
+        ofs += itemindex * size + fldofs
+        self.write_int_at_mem(gcref, ofs, fldsize, newvalue)
 
     def bh_setinteriorfield_gc_r(self, gcref, itemindex, newvalue, descr):
         assert isinstance(descr, InteriorFieldDescr)
-        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),
-                            ofs + size * itemindex)
-        items = rffi.cast(rffi.CArrayPtr(lltype.Signed), items)
-        items[0] = self.cast_gcref_to_int(newvalue)
-        # --- end of GC unsafe code ---
+        ofs, size, _ = self.unpack_arraydescr_size(descr.arraydescr)
+        ofs += itemindex * size + descr.fielddescr.offset
+        self.write_ref_at_mem(gcref, ofs, newvalue)
 
     def bh_setinteriorfield_gc_f(self, gcref, itemindex, newvalue, descr):
         assert isinstance(descr, InteriorFieldDescr)
-        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)
-        items = rffi.cast(rffi.CArrayPtr(longlong.FLOATSTORAGE), items)
-        items[0] = newvalue
-        # --- end of GC unsafe code ---
+        ofs, size, _ = self.unpack_arraydescr_size(descr.arraydescr)
+        ofs += itemindex * size + descr.fielddescr.offset
+        self.write_float_at_mem(gcref, ofs, newvalue)
 
     def bh_strlen(self, string):
-        string = self.gc_ll_descr.do_stm_barrier(string, 'R')
         s = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string)
         return len(s.chars)
 
     def bh_unicodelen(self, string):
-        string = self.gc_ll_descr.do_stm_barrier(string, 'R')
         u = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string)
         return len(u.chars)
 
     def bh_strgetitem(self, string, index):
-        string = self.gc_ll_descr.do_stm_barrier(string, 'R')
         s = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string)
         return ord(s.chars[index])
 
     def bh_unicodegetitem(self, string, index):
-        string = self.gc_ll_descr.do_stm_barrier(string, 'R')
         u = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string)
         return ord(u.chars[index])
 
     @specialize.argtype(1)
-    def _base_do_getfield_i(self, struct, fielddescr):
+    def bh_getfield_gc_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:
-            if size == itemsize:
-                # Note that in the common case where size==sizeof(Signed),
-                # both cases of what follows are doing the same thing.
-                # But gcc is clever enough to figure this out :-)
-                if sign:
-                    val = rffi.cast(rffi.CArrayPtr(STYPE), fieldptr)[0]
-                    val = rffi.cast(lltype.Signed, val)
-                else:
-                    val = rffi.cast(rffi.CArrayPtr(UTYPE), fieldptr)[0]
-                    val = rffi.cast(lltype.Signed, val)
-                # --- end of GC unsafe code ---
-                return val
-        else:
-            raise NotImplementedError("size = %d" % size)
+        return self.read_int_at_mem(struct, ofs, size, sign)
+
+    def bh_getfield_gc_r(self, struct, fielddescr):
+        ofs = self.unpack_fielddescr(fielddescr)
+        return self.read_ref_at_mem(struct, ofs)
 
     @specialize.argtype(1)
-    def _base_do_getfield_r(self, struct, fielddescr):
+    def bh_getfield_gc_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)
-        pval = rffi.cast(rffi.CArrayPtr(lltype.Signed), fieldptr)[0]
-        pval = self._cast_int_to_gcref(pval)
-        # --- end of GC unsafe code ---
-        return pval
+        return self.read_float_at_mem(struct, ofs)
+
+    bh_getfield_raw_i = bh_getfield_gc_i
+    bh_getfield_raw_f = bh_getfield_gc_f
 
     @specialize.argtype(1)
-    def _base_do_getfield_f(self, struct, fielddescr):
+    def bh_setfield_gc_i(self, struct, newvalue, fielddescr):
+        ofs, size, _ = self.unpack_fielddescr_size(fielddescr)
+        self.write_int_at_mem(struct, ofs, size, newvalue)
+
+    def bh_setfield_gc_r(self, struct, newvalue, 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]
-        # --- end of GC unsafe code ---
-        return fval
-
-    bh_getfield_gc_i = _base_do_getfield_i
-    bh_getfield_gc_r = _base_do_getfield_r
-    bh_getfield_gc_f = _base_do_getfield_f
-    bh_getfield_raw_i = _base_do_getfield_i
-    bh_getfield_raw_r = _base_do_getfield_r
-    bh_getfield_raw_f = _base_do_getfield_f
+        self.write_ref_at_mem(struct, ofs, newvalue)
 
     @specialize.argtype(1)
-    def _base_do_setfield_i(self, struct, newvalue, fielddescr):
-        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:
-            if size == itemsize:
-                fieldptr = rffi.cast(rffi.CArrayPtr(TYPE), fieldptr)
-                fieldptr[0] = rffi.cast(TYPE, newvalue)
-                # --- end of GC unsafe code ---
-                return
-        else:
-            raise NotImplementedError("size = %d" % size)
+    def bh_setfield_gc_f(self, struct, newvalue, fielddescr):
+        ofs = self.unpack_fielddescr(fielddescr)
+        self.write_float_at_mem(struct, ofs, newvalue)
 
-    @specialize.argtype(1)
-    def _base_do_setfield_r(self, struct, newvalue, fielddescr):
-        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)
-        fieldptr = rffi.cast(rffi.CArrayPtr(lltype.Signed), fieldptr)
-        fieldptr[0] = self.cast_gcref_to_int(newvalue)
-        # --- end of GC unsafe code ---
-
-    @specialize.argtype(1)
-    def _base_do_setfield_f(self, struct, newvalue, fielddescr):
-        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)
-        fieldptr[0] = newvalue
-        # --- end of GC unsafe code ---
-
-    bh_setfield_gc_i = _base_do_setfield_i
-    bh_setfield_gc_r = _base_do_setfield_r
-    bh_setfield_gc_f = _base_do_setfield_f
-    bh_setfield_raw_i = _base_do_setfield_i
-    bh_setfield_raw_r = _base_do_setfield_r
-    bh_setfield_raw_f = _base_do_setfield_f
+    bh_setfield_raw_i = bh_setfield_gc_i
+    bh_setfield_raw_f = bh_setfield_gc_f
 
     def bh_raw_store_i(self, addr, offset, newvalue, descr):
-        ofs, size, sign = self.unpack_arraydescr_size(descr)
-        items = addr + offset
-        for TYPE, _, itemsize in unroll_basic_sizes:
-            if size == itemsize:
-                items = rffi.cast(rffi.CArrayPtr(TYPE), items)
-                items[0] = rffi.cast(TYPE, newvalue)
-                break
+        ofs, size, _ = self.unpack_arraydescr_size(descr)
+        assert ofs == 0     # otherwise, 'descr' is not a raw length-less array
+        self.write_int_at_mem(addr, offset, size, newvalue)
 
     def bh_raw_store_f(self, addr, offset, newvalue, descr):
-        items = rffi.cast(rffi.CArrayPtr(longlong.FLOATSTORAGE), addr + offset)
-        items[0] = newvalue
+        self.write_float_at_mem(addr, offset, newvalue)
 
     def bh_raw_load_i(self, addr, offset, descr):
         ofs, size, sign = self.unpack_arraydescr_size(descr)
         return self.read_int_at_mem(addr, offset, size, sign)
 
     def bh_raw_load_f(self, addr, offset, descr):
-        items = rffi.cast(rffi.CArrayPtr(longlong.FLOATSTORAGE), addr + offset)
-        return items[0]
+        return self.read_float_at_mem(addr, offset)
 
     def bh_new(self, sizedescr):
         return self.gc_ll_descr.gc_malloc(sizedescr)
     def bh_new_with_vtable(self, vtable, sizedescr):
         res = self.gc_ll_descr.gc_malloc(sizedescr)
         if self.vtable_offset is not None:
-            assert not self.gc_ll_descr.stm
-            res = self.gc_ll_descr.do_stm_barrier(res, 'W')
-            as_array = rffi.cast(rffi.CArrayPtr(lltype.Signed), res)
-            as_array[self.vtable_offset/WORD] = vtable
+            self.write_int_at_mem(res, self.vtable_offset, WORD, vtable)
         return res
 
     def bh_new_raw_buffer(self, size):
         return lltype.malloc(rffi.CCHARP.TO, size, flavor='raw')
 
     def bh_classof(self, struct):
-        struct = self.gc_ll_descr.do_stm_barrier(struct, 'R')
         struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct)
         result_adr = llmemory.cast_ptr_to_adr(struct.typeptr)
         return heaptracker.adr2int(result_adr)
         return self.gc_ll_descr.gc_malloc_unicode(length)
 
     def bh_strsetitem(self, string, index, newvalue):
-        string = self.gc_ll_descr.do_stm_barrier(string, 'W')
         s = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string)
         s.chars[index] = chr(newvalue)
 
     def bh_unicodesetitem(self, string, index, newvalue):
-        string = self.gc_ll_descr.do_stm_barrier(string, 'W')
         u = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string)
         u.chars[index] = unichr(newvalue)
 
     def bh_copystrcontent(self, src, dst, srcstart, dststart, length):
-        src = self.gc_ll_descr.do_stm_barrier(src, 'R')
-        dst = self.gc_ll_descr.do_stm_barrier(dst, 'W')
         src = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), src)
         dst = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), dst)
         rstr.copy_string_contents(src, dst, srcstart, dststart, length)
 
     def bh_copyunicodecontent(self, src, dst, srcstart, dststart, length):
-        src = self.gc_ll_descr.do_stm_barrier(src, 'R')
-        dst = self.gc_ll_descr.do_stm_barrier(dst, 'W')
         src = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), src)
         dst = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), dst)
         rstr.copy_unicode_contents(src, dst, srcstart, dststart, length)

File rpython/jit/backend/x86/assembler.py

         for ofs in self.frame_depth_to_patch:
             self._patch_frame_depth(ofs + rawstart, framedepth)
 
-    def _check_frame_depth(self, mc, gcmap, expected_size=-1):
+    def _check_frame_depth(self, mc, gcmap):
         """ check if the frame is of enough depth to follow this bridge.
         Otherwise reallocate the frame in a helper.
         There are other potential solutions
         """
         descrs = self.cpu.gc_ll_descr.getframedescrs(self.cpu)
         ofs = self.cpu.unpack_fielddescr(descrs.arraydescr.lendescr)
-        if expected_size == -1:
-            mc.CMP_bi(ofs, 0xffffff)
-        else:
-            mc.CMP_bi(ofs, expected_size)
+        mc.CMP_bi(ofs, 0xffffff)     # force writing 32 bit
         stack_check_cmp_ofs = mc.get_relative_pos() - 4
         mc.J_il8(rx86.Conditions['GE'], 0)
         jg_location = mc.get_relative_pos()
-        if expected_size == -1:
-            mc.MOV_si(WORD, 0xffffff)
-        else:
-            mc.MOV_si(WORD, expected_size)
+        mc.MOV_si(WORD, 0xffffff)     # force writing 32 bit
         ofs2 = mc.get_relative_pos() - 4
         self.push_gcmap(mc, gcmap, mov=True)
         mc.CALL(imm(self._frame_realloc_slowpath))

File rpython/memory/gctransform/framework.py

         opname = hop.spaceop.opname
         v_struct = hop.spaceop.args[0]
         v_newvalue = hop.spaceop.args[-1]
-        assert opname in ('setfield', 'setarrayitem', 'setinteriorfield')
+        assert opname in ('setfield', 'setarrayitem', 'setinteriorfield',
+                          'raw_store')
         assert isinstance(v_newvalue.concretetype, lltype.Ptr)
         # XXX for some GCs the skipping if the newvalue is a constant won't be
         # ok

File rpython/memory/gctransform/transform.py

             hop.rename('bare_' + hop.spaceop.opname)
     gct_setarrayitem = gct_setfield
     gct_setinteriorfield = gct_setfield
+    gct_raw_store = gct_setfield
 
     gct_getfield = default
 

File rpython/rlib/rstring.py

 
 
 @specialize.argtype(0)
+@jit.elidable
 def replace(input, sub, by, maxsplit=-1):
     if isinstance(input, str):
         assert isinstance(sub, str)

File rpython/rtyper/llinterp.py

     op_raw_load.need_result_type = True
 
     def op_raw_store(self, addr, offset, value):
+        # XXX handle the write barrier by delegating to self.heap instead
+        self.op_bare_raw_store(addr, offset, value)
+
+    def op_bare_raw_store(self, addr, offset, value):
         checkadr(addr)
         ARGTYPE = lltype.typeOf(value)
         if isinstance(offset, int):

File rpython/rtyper/lltypesystem/lloperation.py

     'raw_memclear':         LLOp(),
     'raw_memcopy':          LLOp(),
     'raw_memmove':          LLOp(),
-    'raw_load':             LLOp(sideeffects=False),
-    'raw_store':            LLOp(),
+    'raw_load':             LLOp(sideeffects=False, canrun=True),
+    'raw_store':            LLOp(canrun=True),
+    'bare_raw_store':       LLOp(),
     'stack_malloc':         LLOp(), # mmh
     'track_alloc_start':    LLOp(),
     'track_alloc_stop':     LLOp(),

File rpython/rtyper/lltypesystem/opimpl.py

 def op_stm_get_tid(x):
     raise NotImplementedError
 
+def op_raw_store(p, ofs, newvalue):
+    from rpython.rtyper.lltypesystem import rffi
+    TP = lltype.typeOf(p)
+    if TP != llmemory.Address:
+        assert TP == llmemory.GCREF
+        p = rffi.cast(llmemory.Address, p)
+    TVAL = lltype.typeOf(newvalue)
+    p = rffi.cast(rffi.CArrayPtr(TVAL), p + ofs)
+    p[0] = newvalue
+
+def op_raw_load(TVAL, p, ofs):
+    from rpython.rtyper.lltypesystem import rffi
+    TP = lltype.typeOf(p)
+    if TP != llmemory.Address:
+        assert TP == llmemory.GCREF
+        p = rffi.cast(llmemory.Address, p)
+    p = rffi.cast(rffi.CArrayPtr(TVAL), p + ofs)
+    return p[0]
+op_raw_load.need_result_type = True
+
 # ____________________________________________________________
 
 def get_op_impl(opname):

File rpython/translator/c/funcgen.py

         return (
            '((%(typename)s) (((char *)%(addr)s) + %(offset)s))[0] = %(value)s;'
            % locals())
+    OP_BARE_RAW_STORE = OP_RAW_STORE
 
     def OP_RAW_LOAD(self, op):
         addr = self.expr(op.args[0])

File rpython/translator/c/src/mem.h

File contents unchanged.