Author: Armin Rigo <ar...@tunes.org> Branch: stmgc-c4 Changeset: r66866:781dce1d3438 Date: 2013-09-09 18:25 +0200 http://bitbucket.org/pypy/pypy/changeset/781dce1d3438/
Log: hg merge default diff --git a/lib_pypy/_tkinter/__init__.py b/lib_pypy/_tkinter/__init__.py --- a/lib_pypy/_tkinter/__init__.py +++ b/lib_pypy/_tkinter/__init__.py @@ -22,6 +22,7 @@ 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, diff --git a/lib_pypy/_tkinter/app.py b/lib_pypy/_tkinter/app.py --- a/lib_pypy/_tkinter/app.py +++ b/lib_pypy/_tkinter/app.py @@ -4,7 +4,23 @@ 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): @@ -37,17 +53,18 @@ 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): @@ -58,6 +75,8 @@ class TkApp(object): + _busywaitinterval = 0.02 # 20ms. + def __new__(cls, screenName, baseName, className, interactive, wantobjects, wantTk, sync, use): if not wantobjects: @@ -73,6 +92,12 @@ 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 = {} @@ -133,6 +158,13 @@ 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") @@ -159,22 +191,25 @@ 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) @@ -183,9 +218,10 @@ 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) @@ -219,9 +255,10 @@ 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") @@ -229,7 +266,8 @@ 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") @@ -256,11 +294,12 @@ 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: @@ -280,17 +319,19 @@ 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): @@ -375,7 +416,10 @@ 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 diff --git a/lib_pypy/_tkinter/tklib.py b/lib_pypy/_tkinter/tklib.py --- a/lib_pypy/_tkinter/tklib.py +++ b/lib_pypy/_tkinter/tklib.py @@ -19,6 +19,8 @@ #define TCL_EVAL_DIRECT ... #define TCL_EVAL_GLOBAL ... +#define TCL_DONT_WAIT ... + typedef unsigned short Tcl_UniChar; typedef ... Tcl_Interp; typedef ...* Tcl_ThreadId; @@ -110,8 +112,8 @@ 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(""" diff --git a/rpython/jit/backend/llsupport/llmodel.py b/rpython/jit/backend/llsupport/llmodel.py --- a/rpython/jit/backend/llsupport/llmodel.py +++ b/rpython/jit/backend/llsupport/llmodel.py @@ -373,73 +373,42 @@ @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) # ____________________________________________________________ @@ -449,7 +418,7 @@ """ 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 @@ -476,9 +445,8 @@ 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): @@ -499,8 +467,7 @@ @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) @@ -520,231 +487,101 @@ 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) @@ -752,8 +589,7 @@ 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) @@ -761,17 +597,13 @@ 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) @@ -786,25 +618,19 @@ 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) 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 @@ -740,7 +740,7 @@ 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 @@ -748,17 +748,11 @@ """ 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)) diff --git a/rpython/memory/gctransform/framework.py b/rpython/memory/gctransform/framework.py --- a/rpython/memory/gctransform/framework.py +++ b/rpython/memory/gctransform/framework.py @@ -1119,7 +1119,8 @@ 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 diff --git a/rpython/memory/gctransform/transform.py b/rpython/memory/gctransform/transform.py --- a/rpython/memory/gctransform/transform.py +++ b/rpython/memory/gctransform/transform.py @@ -330,6 +330,7 @@ hop.rename('bare_' + hop.spaceop.opname) gct_setarrayitem = gct_setfield gct_setinteriorfield = gct_setfield + gct_raw_store = gct_setfield gct_getfield = default diff --git a/rpython/rlib/rstring.py b/rpython/rlib/rstring.py --- a/rpython/rlib/rstring.py +++ b/rpython/rlib/rstring.py @@ -149,6 +149,7 @@ @specialize.argtype(0) +@jit.elidable def replace(input, sub, by, maxsplit=-1): if isinstance(input, str): assert isinstance(sub, str) diff --git a/rpython/rtyper/llinterp.py b/rpython/rtyper/llinterp.py --- a/rpython/rtyper/llinterp.py +++ b/rpython/rtyper/llinterp.py @@ -1025,6 +1025,10 @@ 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): diff --git a/rpython/rtyper/lltypesystem/lloperation.py b/rpython/rtyper/lltypesystem/lloperation.py --- a/rpython/rtyper/lltypesystem/lloperation.py +++ b/rpython/rtyper/lltypesystem/lloperation.py @@ -461,8 +461,9 @@ '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(), diff --git a/rpython/rtyper/lltypesystem/opimpl.py b/rpython/rtyper/lltypesystem/opimpl.py --- a/rpython/rtyper/lltypesystem/opimpl.py +++ b/rpython/rtyper/lltypesystem/opimpl.py @@ -678,6 +678,26 @@ 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): diff --git a/rpython/translator/c/funcgen.py b/rpython/translator/c/funcgen.py --- a/rpython/translator/c/funcgen.py +++ b/rpython/translator/c/funcgen.py @@ -744,6 +744,7 @@ 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]) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit