Author: Spenser Andrew Bauman <saba...@gmail.com> Branch: remove-getfield-pure Changeset: r81514:b131bc726e2b Date: 2015-12-31 11:49 -0500 http://bitbucket.org/pypy/pypy/changeset/b131bc726e2b/
Log: Sync with master diff too long, truncating to 2000 out of 2109 lines diff --git a/lib_pypy/cffi.egg-info/PKG-INFO b/lib_pypy/cffi.egg-info/PKG-INFO --- a/lib_pypy/cffi.egg-info/PKG-INFO +++ b/lib_pypy/cffi.egg-info/PKG-INFO @@ -1,6 +1,6 @@ Metadata-Version: 1.1 Name: cffi -Version: 1.4.1 +Version: 1.4.2 Summary: Foreign Function Interface for Python calling C code. Home-page: http://cffi.readthedocs.org Author: Armin Rigo, Maciej Fijalkowski diff --git a/lib_pypy/cffi/__init__.py b/lib_pypy/cffi/__init__.py --- a/lib_pypy/cffi/__init__.py +++ b/lib_pypy/cffi/__init__.py @@ -4,8 +4,8 @@ from .api import FFI, CDefError, FFIError from .ffiplatform import VerificationError, VerificationMissing -__version__ = "1.4.1" -__version_info__ = (1, 4, 1) +__version__ = "1.4.2" +__version_info__ = (1, 4, 2) # The verifier module file names are based on the CRC32 of a string that # contains the following version number. It may be older than __version__ diff --git a/pypy/module/_cffi_backend/cglob.py b/pypy/module/_cffi_backend/cglob.py --- a/pypy/module/_cffi_backend/cglob.py +++ b/pypy/module/_cffi_backend/cglob.py @@ -3,6 +3,7 @@ from pypy.interpreter.typedef import TypeDef from pypy.module._cffi_backend.cdataobj import W_CData from pypy.module._cffi_backend import newtype +from rpython.rlib import rgil from rpython.rlib.objectmodel import we_are_translated from rpython.rtyper.lltypesystem import lltype, rffi from rpython.translator.tool.cbuild import ExternalCompilationInfo @@ -26,7 +27,9 @@ if not we_are_translated(): FNPTR = rffi.CCallback([], rffi.VOIDP) fetch_addr = rffi.cast(FNPTR, self.fetch_addr) + rgil.release() result = fetch_addr() + rgil.acquire() else: # careful in translated versions: we need to call fetch_addr, # but in a GIL-releasing way. The easiest is to invoke a diff --git a/pypy/module/_cffi_backend/ctypefunc.py b/pypy/module/_cffi_backend/ctypefunc.py --- a/pypy/module/_cffi_backend/ctypefunc.py +++ b/pypy/module/_cffi_backend/ctypefunc.py @@ -423,7 +423,9 @@ exchange_offset += rffi.getintfield(self.atypes[i], 'c_size') # store the exchange data size - cif_descr.exchange_size = exchange_offset + # we also align it to the next multiple of 8, in an attempt to + # work around bugs(?) of libffi (see cffi issue #241) + cif_descr.exchange_size = self.align_arg(exchange_offset) def fb_extra_fields(self, cif_descr): cif_descr.abi = self.fabi diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py --- a/pypy/module/cpyext/slotdefs.py +++ b/pypy/module/cpyext/slotdefs.py @@ -386,7 +386,7 @@ return @cpython_api([PyObject, PyObject], PyObject, - error=lltype.nullptr(rffi.VOIDP.TO), external=True) + external=True) @func_renamer("cpyext_tp_getattro_%s" % (typedef.name,)) def slot_tp_getattro(space, w_self, w_name): return space.call_function(getattr_fn, w_self, w_name) diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py --- a/pypy/module/cpyext/test/test_typeobject.py +++ b/pypy/module/cpyext/test/test_typeobject.py @@ -414,15 +414,26 @@ return NULL; } PyObject *name = PyString_FromString("attr1"); - PyIntObject *attr1 = obj->ob_type->tp_getattro(obj, name); - if (attr1->ob_ival != value->ob_ival) + PyIntObject *attr = obj->ob_type->tp_getattro(obj, name); + if (attr->ob_ival != value->ob_ival) { PyErr_SetString(PyExc_ValueError, "tp_getattro returned wrong value"); return NULL; } Py_DECREF(name); - Py_DECREF(attr1); + Py_DECREF(attr); + name = PyString_FromString("attr2"); + attr = obj->ob_type->tp_getattro(obj, name); + if (attr == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) + { + PyErr_Clear(); + } else { + PyErr_SetString(PyExc_ValueError, + "tp_getattro should have raised"); + return NULL; + } + Py_DECREF(name); Py_RETURN_TRUE; ''' ) @@ -637,7 +648,7 @@ IntLikeObject *intObj; long intval; - if (!PyArg_ParseTuple(args, "i", &intval)) + if (!PyArg_ParseTuple(args, "l", &intval)) return NULL; IntLike_Type.tp_as_number = &intlike_as_number; @@ -657,7 +668,7 @@ IntLikeObjectNoOp *intObjNoOp; long intval; - if (!PyArg_ParseTuple(args, "i", &intval)) + if (!PyArg_ParseTuple(args, "l", &intval)) return NULL; IntLike_Type_NoOp.tp_flags |= Py_TPFLAGS_CHECKTYPES; diff --git a/pypy/module/pypyjit/test_pypy_c/test_struct.py b/pypy/module/pypyjit/test_pypy_c/test_struct.py --- a/pypy/module/pypyjit/test_pypy_c/test_struct.py +++ b/pypy/module/pypyjit/test_pypy_c/test_struct.py @@ -45,7 +45,7 @@ # the newstr and the strsetitems are because the string is forced, # which is in turn because the optimizer doesn't know how to handle a - # getarrayitem_gc_i on a virtual string. It could be improved, but it + # gc_load_indexed_i on a virtual string. It could be improved, but it # is also true that in real life cases struct.unpack is called on # strings which come from the outside, so it's a minor issue. assert loop.match_by_id("unpack", """ @@ -55,17 +55,17 @@ strsetitem(p88, 1, i14) strsetitem(p88, 2, i17) strsetitem(p88, 3, i20) - i91 = getarrayitem_gc_i(p88, 0, descr=<ArrayS 4>) + i91 = gc_load_indexed_i(p88, 0, 1, _, -4) """) def test_struct_object(self): def main(n): import struct - s = struct.Struct("i") + s = struct.Struct("ii") i = 1 while i < n: - buf = s.pack(i) # ID: pack - x = s.unpack(buf)[0] # ID: unpack + buf = s.pack(-1, i) # ID: pack + x = s.unpack(buf)[1] # ID: unpack i += x / i return i @@ -88,10 +88,15 @@ assert loop.match_by_id('unpack', """ # struct.unpack - p88 = newstr(4) - strsetitem(p88, 0, i11) - strsetitem(p88, 1, i14) - strsetitem(p88, 2, i17) - strsetitem(p88, 3, i20) - i91 = getarrayitem_gc_i(p88, 0, descr=<ArrayS 4>) + p88 = newstr(8) + strsetitem(p88, 0, 255) + strsetitem(p88, 1, 255) + strsetitem(p88, 2, 255) + strsetitem(p88, 3, 255) + strsetitem(p88, 4, i11) + strsetitem(p88, 5, i14) + strsetitem(p88, 6, i17) + strsetitem(p88, 7, i20) + i90 = gc_load_indexed_i(p88, 0, 1, _, -4) + i91 = gc_load_indexed_i(p88, 4, 1, _, -4) """) diff --git a/rpython/annotator/signature.py b/rpython/annotator/signature.py --- a/rpython/annotator/signature.py +++ b/rpython/annotator/signature.py @@ -100,6 +100,7 @@ self.argtypes = argtypes def __call__(self, funcdesc, inputcells): + from rpython.rlib.objectmodel import NOT_CONSTANT from rpython.rtyper.lltypesystem import lltype args_s = [] from rpython.annotator import model as annmodel @@ -115,6 +116,9 @@ args_s.append(s_input) elif argtype is None: args_s.append(inputcells[i]) # no change + elif argtype is NOT_CONSTANT: + from rpython.annotator.model import not_const + args_s.append(not_const(inputcells[i])) else: args_s.append(annotation(argtype, bookkeeper=funcdesc.bookkeeper)) if len(inputcells) != len(args_s): diff --git a/rpython/jit/backend/arm/regalloc.py b/rpython/jit/backend/arm/regalloc.py --- a/rpython/jit/backend/arm/regalloc.py +++ b/rpython/jit/backend/arm/regalloc.py @@ -804,7 +804,7 @@ base_loc = self.make_sure_var_in_reg(boxes[0], boxes) ofs = boxes[1].getint() value_loc = self.make_sure_var_in_reg(boxes[2], boxes) - size = abs(boxes[3].getint()) + size = boxes[3].getint() ofs_size = default_imm_size if size < 8 else VMEM_imm_size if check_imm_arg(ofs, size=ofs_size): ofs_loc = imm(ofs) @@ -849,7 +849,7 @@ index_loc = self.make_sure_var_in_reg(boxes[1], boxes) assert boxes[3].getint() == 1 # scale ofs = boxes[4].getint() - size = abs(boxes[5].getint()) + size = boxes[5].getint() assert check_imm_arg(ofs) return [value_loc, base_loc, index_loc, imm(size), imm(ofs)] diff --git a/rpython/jit/backend/llgraph/runner.py b/rpython/jit/backend/llgraph/runner.py --- a/rpython/jit/backend/llgraph/runner.py +++ b/rpython/jit/backend/llgraph/runner.py @@ -13,6 +13,7 @@ from rpython.rtyper.llinterp import LLInterpreter, LLException from rpython.rtyper.lltypesystem import lltype, llmemory, rffi, rstr +from rpython.rtyper.lltypesystem.lloperation import llop from rpython.rtyper import rclass from rpython.rlib.clibffi import FFI_DEFAULT_ABI @@ -635,18 +636,9 @@ return array.getlength() def bh_getarrayitem_gc(self, a, index, descr): + a = support.cast_arg(lltype.Ptr(descr.A), a) + array = a._obj assert index >= 0 - if descr.A is descr.OUTERA: - a = support.cast_arg(lltype.Ptr(descr.A), a) - else: - # we use rffi.cast instead of support.cast_arg because the types - # might not be "compatible" enough from the lltype point of - # view. In particular, this happens when we use - # str_storage_getitem, in which an rpy_string is casted to - # rpy_string_as_Signed (or similar) - a = rffi.cast(lltype.Ptr(descr.OUTERA), a) - a = getattr(a, descr.OUTERA._arrayfld) - array = a._obj return support.cast_result(descr.A.OF, array.getitem(index)) bh_getarrayitem_gc_pure_i = bh_getarrayitem_gc @@ -711,6 +703,24 @@ else: return self.bh_raw_load_i(struct, offset, descr) + def bh_gc_load_indexed_i(self, struct, index, scale, base_ofs, bytes): + if bytes == 1: T = rffi.UCHAR + elif bytes == 2: T = rffi.USHORT + elif bytes == 4: T = rffi.UINT + elif bytes == 8: T = rffi.ULONGLONG + elif bytes == -1: T = rffi.SIGNEDCHAR + elif bytes == -2: T = rffi.SHORT + elif bytes == -4: T = rffi.INT + elif bytes == -8: T = rffi.LONGLONG + else: raise NotImplementedError(bytes) + x = llop.gc_load_indexed(T, struct, index, scale, base_ofs) + return lltype.cast_primitive(lltype.Signed, x) + + def bh_gc_load_indexed_f(self, struct, index, scale, base_ofs, bytes): + if bytes != 8: + raise Exception("gc_load_indexed_f is only for 'double'!") + return llop.gc_load_indexed(rffi.DOUBLE, struct, index, scale, base_ofs) + def bh_increment_debug_counter(self, addr): p = rffi.cast(rffi.CArrayPtr(lltype.Signed), addr) p[0] += 1 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 @@ -725,6 +725,16 @@ def bh_raw_load_f(self, addr, offset, descr): return self.read_float_at_mem(addr, offset) + def bh_gc_load_indexed_i(self, addr, index, scale, base_ofs, bytes): + offset = base_ofs + scale * index + return self.read_int_at_mem(addr, offset, abs(bytes), bytes < 0) + + def bh_gc_load_indexed_f(self, addr, index, scale, base_ofs, bytes): + # only for 'double'! + assert bytes == rffi.sizeof(lltype.Float) + offset = base_ofs + scale * index + return self.read_float_at_mem(addr, offset) + def bh_new(self, sizedescr): return self.gc_ll_descr.gc_malloc(sizedescr) diff --git a/rpython/jit/backend/llsupport/rewrite.py b/rpython/jit/backend/llsupport/rewrite.py --- a/rpython/jit/backend/llsupport/rewrite.py +++ b/rpython/jit/backend/llsupport/rewrite.py @@ -126,11 +126,11 @@ def emit_gc_store_or_indexed(self, op, ptr_box, index_box, value_box, itemsize, factor, offset): factor, offset, index_box = \ - self._emit_mul_add_if_factor_offset_not_supported(index_box, + self._emit_mul_if_factor_offset_not_supported(index_box, factor, offset) # - if factor == 1 and offset == 0: - args = [ptr_box, index_box, value_box, ConstInt(itemsize)] + if index_box is None: + args = [ptr_box, ConstInt(offset), value_box, ConstInt(itemsize)] newload = ResOperation(rop.GC_STORE, args) else: args = [ptr_box, index_box, value_box, ConstInt(factor), @@ -153,18 +153,15 @@ index_box = op.getarg(1) self.emit_gc_load_or_indexed(op, ptr_box, index_box, itemsize, 1, ofs, sign) - def _emit_mul_add_if_factor_offset_not_supported(self, index_box, factor, offset): - orig_factor = factor - # factor - must_manually_load_const = False # offset != 0 and not self.cpu.load_constant_offset - if factor != 1 and (factor not in self.cpu.load_supported_factors or \ - (not index_box.is_constant() and must_manually_load_const)): - # enter here if the factor is supported by the cpu - # OR the index is not constant and a new resop must be emitted - # to add the offset - if isinstance(index_box, ConstInt): - index_box = ConstInt(index_box.value * factor) - else: + def _emit_mul_if_factor_offset_not_supported(self, index_box, + factor, offset): + # Returns (factor, offset, index_box) where index_box is either + # a non-constant BoxInt or None. + if isinstance(index_box, ConstInt): + return 1, index_box.value * factor + offset, None + else: + if factor != 1 and factor not in self.cpu.load_supported_factors: + # the factor is supported by the cpu # x & (x - 1) == 0 is a quick test for power of 2 assert factor > 0 if (factor & (factor - 1)) == 0: @@ -174,20 +171,13 @@ index_box = ResOperation(rop.INT_MUL, [index_box, ConstInt(factor)]) self.emit_op(index_box) - factor = 1 - # adjust the constant offset - #if must_manually_load_const: - # if isinstance(index_box, ConstInt): - # index_box = ConstInt(index_box.value + offset) - # else: - # index_box = ResOperation(rop.INT_ADD, [index_box, ConstInt(offset)]) - # self.emit_op(index_box) - # offset = 0 - return factor, offset, index_box + factor = 1 + return factor, offset, index_box - def emit_gc_load_or_indexed(self, op, ptr_box, index_box, itemsize, factor, offset, sign, type='i'): + def emit_gc_load_or_indexed(self, op, ptr_box, index_box, itemsize, + factor, offset, sign, type='i'): factor, offset, index_box = \ - self._emit_mul_add_if_factor_offset_not_supported(index_box, + self._emit_mul_if_factor_offset_not_supported(index_box, factor, offset) # if sign: @@ -197,8 +187,8 @@ optype = type if op is not None: optype = op.type - if factor == 1 and offset == 0: - args = [ptr_box, index_box, ConstInt(itemsize)] + if index_box is None: + args = [ptr_box, ConstInt(offset), ConstInt(itemsize)] newload = ResOperation(OpHelpers.get_gc_load(optype), args) else: args = [ptr_box, index_box, ConstInt(factor), @@ -547,9 +537,8 @@ ofs, size, sign = unpack_fielddescr(descrs.jfi_frame_depth) if sign: size = -size - args = [ConstInt(frame_info), ConstInt(0), ConstInt(1), - ConstInt(ofs), ConstInt(size)] - size = ResOperation(rop.GC_LOAD_INDEXED_I, args) + args = [ConstInt(frame_info), ConstInt(ofs), ConstInt(size)] + size = ResOperation(rop.GC_LOAD_I, args) self.emit_op(size) frame = ResOperation(rop.NEW_ARRAY, [size], descr=descrs.arraydescr) @@ -560,9 +549,8 @@ ofs, size, sign = unpack_fielddescr(descrs.jfi_frame_size) if sign: size = -size - args = [ConstInt(frame_info), ConstInt(0), ConstInt(1), - ConstInt(ofs), ConstInt(size)] - size = ResOperation(rop.GC_LOAD_INDEXED_I, args) + args = [ConstInt(frame_info), ConstInt(ofs), ConstInt(size)] + size = ResOperation(rop.GC_LOAD_I, args) self.emit_op(size) frame = self.gen_malloc_nursery_varsize_frame(size) self.gen_initialize_tid(frame, descrs.arraydescr.tid) @@ -612,15 +600,12 @@ descr = self.cpu.getarraydescr_for_frame(arg.type) assert self.cpu.JITFRAME_FIXED_SIZE & 1 == 0 _, itemsize, _ = self.cpu.unpack_arraydescr_size(descr) - index = index_list[i] // itemsize # index is in bytes - # emit GC_LOAD_INDEXED - itemsize, basesize, _ = unpack_arraydescr(descr) - factor, offset, index_box = \ - self._emit_mul_add_if_factor_offset_not_supported(ConstInt(index), - itemsize, basesize) - args = [frame, index_box, arg, ConstInt(factor), - ConstInt(offset), ConstInt(itemsize)] - self.emit_op(ResOperation(rop.GC_STORE_INDEXED, args)) + array_offset = index_list[i] # index, already measured in bytes + # emit GC_STORE + _, basesize, _ = unpack_arraydescr(descr) + offset = basesize + array_offset + args = [frame, ConstInt(offset), arg, ConstInt(itemsize)] + self.emit_op(ResOperation(rop.GC_STORE, args)) descr = op.getdescr() assert isinstance(descr, JitCellToken) diff --git a/rpython/jit/backend/llsupport/test/test_rewrite.py b/rpython/jit/backend/llsupport/test/test_rewrite.py --- a/rpython/jit/backend/llsupport/test/test_rewrite.py +++ b/rpython/jit/backend/llsupport/test/test_rewrite.py @@ -30,13 +30,26 @@ class RewriteTests(object): def check_rewrite(self, frm_operations, to_operations, **namespace): - def trans_getarray_to_load(descr): - size = descr.basesize - if descr.is_item_signed(): - size = -size - return ','.join([str(n) for n in [descr.itemsize, - descr.basesize, - size]]) + def setfield(baseptr, newvalue, descr): + assert isinstance(baseptr, str) + assert isinstance(newvalue, (str, int)) + assert not isinstance(descr, (str, int)) + return 'gc_store(%s, %d, %s, %d)' % (baseptr, descr.offset, + newvalue, descr.field_size) + def setarrayitem(baseptr, index, newvalue, descr): + assert isinstance(baseptr, str) + assert isinstance(index, (str, int)) + assert isinstance(newvalue, (str, int)) + assert not isinstance(descr, (str, int)) + if isinstance(index, int): + offset = descr.basesize + index * descr.itemsize + return 'gc_store(%s, %d, %s, %d)' % (baseptr, offset, + newvalue, descr.itemsize) + else: + return 'gc_store_indexed(%s, %s, %s, %d, %d, %s)' % ( + baseptr, index, newvalue, + descr.itemsize, descr.basesize, descr.itemsize) + # WORD = globals()['WORD'] S = lltype.GcStruct('S', ('x', lltype.Signed), ('y', lltype.Signed)) @@ -376,7 +389,7 @@ gc_store(p1, 0, 5678, 8) p2 = nursery_ptr_increment(p1, %(tdescr.size)d) gc_store(p2, 0, 1234, 8) - gc_store(p1, %(tdescr.gc_fielddescrs[0].offset)s, 0, %(tdescr.gc_fielddescrs[0].offset)s) + %(setfield('p1', 0, tdescr.gc_fielddescrs[0]))s jump() """) @@ -485,7 +498,7 @@ """, """ [i0] p0 = call_malloc_nursery_varsize(1, 1, i0, descr=strdescr) - gc_store_indexed(p0, 0, i0, 1, %(strlendescr.offset)s, %(strlendescr.field_size)s) + gc_store(p0, %(strlendescr.offset)s, i0, %(strlendescr.field_size)s) gc_store(p0, 0, 0, %(strlendescr.field_size)s) jump(i0) """) @@ -611,19 +624,19 @@ %(strdescr.basesize + 16 * strdescr.itemsize + \ unicodedescr.basesize + 10 * unicodedescr.itemsize)d) gc_store(p0, 0, %(strdescr.tid)d, %(tiddescr.field_size)s) - gc_store_indexed(p0, 0, 14, 1, %(strlendescr.offset)s, %(strlendescr.field_size)s) + gc_store(p0, %(strlendescr.offset)s, 14, %(strlendescr.field_size)s) gc_store(p0, 0, 0, %(strhashdescr.field_size)s) p1 = nursery_ptr_increment(p0, %(strdescr.basesize + 16 * strdescr.itemsize)d) gc_store(p1, 0, %(unicodedescr.tid)d, %(tiddescr.field_size)s) - gc_store_indexed(p1, 0, 10, 1, %(unicodelendescr.offset)s, %(unicodelendescr.field_size)s) + gc_store(p1, %(unicodelendescr.offset)s, 10, %(unicodelendescr.field_size)s) gc_store(p1, 0, 0, %(unicodehashdescr.field_size)s) p2 = call_malloc_nursery_varsize(2, %(unicodedescr.itemsize)d, i2,\ descr=unicodedescr) - gc_store_indexed(p2, 0, i2, 1, %(unicodelendescr.offset)s, %(unicodelendescr.field_size)s) + gc_store(p2, %(unicodelendescr.offset)s, i2, %(unicodelendescr.field_size)s) gc_store(p2, 0, 0, %(unicodehashdescr.field_size)s) p3 = call_malloc_nursery_varsize(1, 1, i2, \ descr=strdescr) - gc_store_indexed(p3, 0, i2, 1, %(strlendescr.offset)s, %(strlendescr.field_size)s) + gc_store(p3, %(strlendescr.offset)s, i2, %(strlendescr.field_size)s) gc_store(p3, 0, 0, %(strhashdescr.field_size)s) jump() """) @@ -636,7 +649,7 @@ """, """ [p1, p2] cond_call_gc_wb(p1, descr=wbdescr) - gc_store_indexed(p1, 0, p2, 1, %(tzdescr.offset)s, %(tzdescr.field_size)s) + gc_store(p1, %(tzdescr.offset)s, p2, %(tzdescr.field_size)s) jump() """) @@ -650,7 +663,7 @@ """, """ [p1, i2, p3] cond_call_gc_wb(p1, descr=wbdescr) - gc_store_indexed(p1, i2, p3, %(trans_getarray_to_load(cdescr))s) + %(setarrayitem('p1', 'i2', 'p3', cdescr))s jump() """) @@ -671,7 +684,7 @@ zero_array(p1, 0, 129, descr=cdescr) call_n(123456) cond_call_gc_wb(p1, descr=wbdescr) - gc_store_indexed(p1, i2, p3, %(trans_getarray_to_load(cdescr))s) + %(setarrayitem('p1', 'i2', 'p3', cdescr))s jump() """) @@ -693,7 +706,7 @@ zero_array(p1, 0, 130, descr=cdescr) call_n(123456) cond_call_gc_wb_array(p1, i2, descr=wbdescr) - gc_store_indexed(p1, i2, p3, %(trans_getarray_to_load(cdescr))s) + %(setarrayitem('p1', 'i2', 'p3', cdescr))s jump() """) @@ -705,7 +718,7 @@ """, """ [p1, i2, p3] cond_call_gc_wb_array(p1, i2, descr=wbdescr) - gc_store_indexed(p1, i2, p3, %(trans_getarray_to_load(cdescr))s) + %(setarrayitem('p1', 'i2', 'p3', cdescr))s jump() """) @@ -725,7 +738,7 @@ zero_array(p1, 0, 5, descr=cdescr) label(p1, i2, p3) cond_call_gc_wb_array(p1, i2, descr=wbdescr) - gc_store_indexed(p1, i2, p3, %(trans_getarray_to_load(cdescr))s) + %(setarrayitem('p1', 'i2', 'p3', cdescr))s jump() """) @@ -743,12 +756,12 @@ size = interiorzdescr.arraydescr.itemsize self.check_rewrite(""" [p1, p2] - setinteriorfield_gc(p1, 0, p2, descr=interiorzdescr) + setinteriorfield_gc(p1, 7, p2, descr=interiorzdescr) jump(p1, p2) """, """ [p1, p2] - cond_call_gc_wb_array(p1, 0, descr=wbdescr) - gc_store_indexed(p1, 0, p2, %(scale)s, %(offset)s, %(size)s) + cond_call_gc_wb_array(p1, 7, descr=wbdescr) + gc_store(p1, %(offset + 7 * scale)s, p2, %(size)s) jump(p1, p2) """, interiorzdescr=interiorzdescr, scale=scale, offset=offset, size=size) @@ -763,7 +776,7 @@ [p1] p0 = call_malloc_nursery(%(tdescr.size)d) gc_store(p0, 0, 5678, %(tiddescr.field_size)s) - gc_store_indexed(p0, 0, p1, 1, %(tzdescr.offset)s, %(tzdescr.field_size)s) + gc_store(p0, %(tzdescr.offset)s, p1, %(tzdescr.field_size)s) jump() """) @@ -781,7 +794,7 @@ p1 = nursery_ptr_increment(p0, %(tdescr.size)d) gc_store(p1, 0, 1234, %(tiddescr.field_size)s) # <<<no cond_call_gc_wb here>>> - gc_store_indexed(p0, 0, p1, 1, %(tzdescr.offset)s, %(tzdescr.field_size)s) + gc_store(p0, %(tzdescr.offset)s, p1, %(tzdescr.field_size)s) jump() """) @@ -798,7 +811,7 @@ gc_store(p0, 0, 8111, %(tiddescr.field_size)s) gc_store(p0, 0, 5, %(clendescr.field_size)s) zero_array(p0, 0, 5, descr=cdescr) - gc_store_indexed(p0, i2, p1, %(trans_getarray_to_load(cdescr))s) + %(setarrayitem('p0', 'i2', 'p1', cdescr))s jump() """) @@ -816,8 +829,8 @@ gc_store(p0, 0, 8111, %(tiddescr.field_size)s) gc_store(p0, 0, 5, %(clendescr.field_size)s) zero_array(p0, 2, 3, descr=cdescr) - gc_store_indexed(p0, 1, p1, %(trans_getarray_to_load(cdescr))s) - gc_store_indexed(p0, 0, p2, %(trans_getarray_to_load(cdescr))s) + %(setarrayitem('p0', 1, 'p1', cdescr))s + %(setarrayitem('p0', 0, 'p2', cdescr))s jump() """) @@ -835,8 +848,8 @@ gc_store(p0, 0, 8111, %(tiddescr.field_size)s) gc_store(p0, 0, 5, %(clendescr.field_size)s) zero_array(p0, 0, 3, descr=cdescr) - gc_store_indexed(p0, 3, p1, %(trans_getarray_to_load(cdescr))s) - gc_store_indexed(p0, 4, p2, %(trans_getarray_to_load(cdescr))s) + %(setarrayitem('p0', 3, 'p1', cdescr))s + %(setarrayitem('p0', 4, 'p2', cdescr))s jump() """) @@ -855,9 +868,9 @@ gc_store(p0, 0, 8111, %(tiddescr.field_size)s) gc_store(p0, 0, 5, %(clendescr.field_size)s) zero_array(p0, 0, 5, descr=cdescr) - gc_store_indexed(p0, 3, p1, %(trans_getarray_to_load(cdescr))s) - gc_store_indexed(p0, 2, p2, %(trans_getarray_to_load(cdescr))s) - gc_store_indexed(p0, 1, p2, %(trans_getarray_to_load(cdescr))s) + %(setarrayitem('p0', 3, 'p1', cdescr))s + %(setarrayitem('p0', 2, 'p2', cdescr))s + %(setarrayitem('p0', 1, 'p2', cdescr))s jump() """) @@ -878,11 +891,11 @@ gc_store(p0, 0, 8111, %(tiddescr.field_size)s) gc_store(p0, 0, 5, %(clendescr.field_size)s) zero_array(p0, 5, 0, descr=cdescr) - gc_store_indexed(p0, 3, p1, %(trans_getarray_to_load(cdescr))s) - gc_store_indexed(p0, 4, p2, %(trans_getarray_to_load(cdescr))s) - gc_store_indexed(p0, 0, p1, %(trans_getarray_to_load(cdescr))s) - gc_store_indexed(p0, 2, p2, %(trans_getarray_to_load(cdescr))s) - gc_store_indexed(p0, 1, p2, %(trans_getarray_to_load(cdescr))s) + %(setarrayitem('p0', 3, 'p1', cdescr))s + %(setarrayitem('p0', 4, 'p2', cdescr))s + %(setarrayitem('p0', 0, 'p1', cdescr))s + %(setarrayitem('p0', 2, 'p2', cdescr))s + %(setarrayitem('p0', 1, 'p2', cdescr))s jump() """) @@ -901,10 +914,10 @@ gc_store(p0, 0, 8111, %(tiddescr.field_size)s) gc_store(p0, 0, 5, %(clendescr.field_size)s) zero_array(p0, 1, 4, descr=cdescr) - gc_store_indexed(p0, 0, p1, %(trans_getarray_to_load(cdescr))s) + %(setarrayitem('p0', 0, 'p1', cdescr))s call_n(321321) cond_call_gc_wb(p0, descr=wbdescr) - gc_store_indexed(p0, 1, p2, %(trans_getarray_to_load(cdescr))s) + %(setarrayitem('p0', 1, 'p2', cdescr))s jump() """) @@ -923,10 +936,10 @@ gc_store(p0, 0, 8111, %(tiddescr.field_size)s) gc_store(p0, 0, 5, %(clendescr.field_size)s) zero_array(p0, 1, 4, descr=cdescr) - gc_store_indexed(p0, 0, p1, %(trans_getarray_to_load(cdescr))s) + %(setarrayitem('p0', 0, 'p1', cdescr))s label(p0, p2) cond_call_gc_wb_array(p0, 1, descr=wbdescr) - gc_store_indexed(p0, 1, p2, %(trans_getarray_to_load(cdescr))s) + %(setarrayitem('p0', 1, 'p2', cdescr))s jump() """) @@ -955,7 +968,7 @@ gc_store(p0, 0, i3, %(blendescr.field_size)s) zero_array(p0, 0, i3, descr=bdescr) cond_call_gc_wb_array(p0, 0, descr=wbdescr) - gc_store_indexed(p0, 0, p1, 1, %(bdescr.basesize)s, 1) + %(setarrayitem('p0', 0, 'p1', bdescr))s jump() """) @@ -991,10 +1004,10 @@ gc_store(p0, %(tdescr.gc_fielddescrs[0].offset)s, 0, %(tdescr.gc_fielddescrs[0].offset)s) p1 = call_malloc_nursery_varsize(1, 1, i0, \ descr=strdescr) - gc_store_indexed(p1, 0, i0, 1, %(strlendescr.offset)s, %(strlendescr.field_size)s) + gc_store(p1, %(strlendescr.offset)s, i0, %(strlendescr.field_size)s) gc_store(p1, 0, 0, %(strhashdescr.field_size)s) cond_call_gc_wb(p0, descr=wbdescr) - gc_store_indexed(p0, 0, p1, 1, %(tzdescr.offset)s, %(tzdescr.field_size)s) + gc_store(p0, %(tzdescr.offset)s, p1, %(tzdescr.field_size)s) jump() """) @@ -1012,7 +1025,7 @@ gc_store(p0, %(tdescr.gc_fielddescrs[0].offset)s, 0, %(tdescr.gc_fielddescrs[0].offset)s) label(p0, p1) cond_call_gc_wb(p0, descr=wbdescr) - gc_store_indexed(p0, 0, p1, 1, %(tzdescr.offset)s, %(tzdescr.field_size)s) + gc_store(p0, %(tzdescr.offset)s, p1, %(tzdescr.field_size)s) jump() """) @@ -1025,8 +1038,8 @@ """, """ [p0, p1, p2] cond_call_gc_wb(p0, descr=wbdescr) - gc_store_indexed(p0, 0, p1, 1, %(tzdescr.offset)s, %(tzdescr.field_size)s) - gc_store_indexed(p0, 0, p2, 1, %(tzdescr.offset)s, %(tzdescr.field_size)s) + gc_store(p0, %(tzdescr.offset)s, p1, %(tzdescr.field_size)s) + gc_store(p0, %(tzdescr.offset)s, p2, %(tzdescr.field_size)s) jump(p1, p2, p0) """) @@ -1036,20 +1049,20 @@ i2 = call_assembler_i(i0, f0, descr=casmdescr) """, """ [i0, f0] - i1 = gc_load_indexed_i(ConstClass(frame_info), 0, 1, 1, %(jfi_frame_size.field_size)s) + i1 = gc_load_i(ConstClass(frame_info), %(jfi_frame_size.offset)s, %(jfi_frame_size.field_size)s) p1 = call_malloc_nursery_varsize_frame(i1) gc_store(p1, 0, 0, %(tiddescr.field_size)s) - i2 = gc_load_indexed_i(ConstClass(frame_info), 0, 1, 1, %(jfi_frame_depth.field_size)s) - gc_store_indexed(p1, 0, 0, 1, 1, %(jf_extra_stack_depth.field_size)s) - gc_store_indexed(p1, 0, NULL, 1, 1, %(jf_savedata.field_size)s) - gc_store_indexed(p1, 0, NULL, 1, 1, %(jf_force_descr.field_size)s) - gc_store_indexed(p1, 0, NULL, 1, 1, %(jf_descr.field_size)s) - gc_store_indexed(p1, 0, NULL, 1, 1, %(jf_guard_exc.field_size)s) - gc_store_indexed(p1, 0, NULL, 1, 1, %(jf_forward.field_size)s) + i2 = gc_load_i(ConstClass(frame_info), %(jfi_frame_depth.offset)s, %(jfi_frame_depth.field_size)s) + %(setfield('p1', 0, jf_extra_stack_depth))s + %(setfield('p1', 'NULL', jf_savedata))s + %(setfield('p1', 'NULL', jf_force_descr))s + %(setfield('p1', 'NULL', jf_descr))s + %(setfield('p1', 'NULL', jf_guard_exc))s + %(setfield('p1', 'NULL', jf_forward))s gc_store(p1, 0, i2, %(framelendescr.field_size)s) - gc_store_indexed(p1, 0, ConstClass(frame_info), 1, 1, %(jf_frame_info.field_size)s) - gc_store_indexed(p1, 0, i0, 8, 3, 8) - gc_store_indexed(p1, 1, f0, 8, 5, 8) + %(setfield('p1', 'ConstClass(frame_info)', jf_frame_info))s + gc_store(p1, 3, i0, 8) + gc_store(p1, 13, f0, 8) i3 = call_assembler_i(p1, descr=casmdescr) """) @@ -1101,7 +1114,7 @@ p0 = call_malloc_nursery(%(tdescr.size)d) gc_store(p0, 0, 5678, %(tiddescr.field_size)s) gc_store(p0, %(tdescr.gc_fielddescrs[0].offset)s, 0, %(tdescr.gc_fielddescrs[0].offset)s) - p1 = gc_load_indexed_r(p0, 0, 1, %(tzdescr.field_size)s, %(tzdescr.field_size)s) + p1 = gc_load_r(p0, %(tzdescr.offset)s, %(tzdescr.field_size)s) jump(p1) """) @@ -1155,23 +1168,19 @@ # 'i5 = int_add(i1,%(raw_sfdescr.basesize)s);' # 'gc_store(p0,i5,i2,%(raw_sfdescr.itemsize)s)'], [True, (1,2,4,8), 'i3 = getfield_gc_f(p0,descr=ydescr)' '->' - 'i3 = gc_load_indexed_f(p0,0,1,%(ydescr.offset)s,%(ydescr.field_size)s)'], - [True, (1,2,4,8), 'i3 = getfield_gc_f(p0,descr=ydescr)' '->' - 'i3 = gc_load_indexed_f(p0,0,1,%(ydescr.offset)s,%(ydescr.field_size)s)'], - [True, (1,2,4,8), 'i3 = setfield_raw(p0,i1,descr=ydescr)' '->' - 'i3 = gc_store_indexed(p0,0,i1,1,' - '%(ydescr.offset)s,%(ydescr.field_size)s)'], - [True, (1,2,4,8), 'i3 = setfield_gc(p0,p0,descr=zdescr)' '->' + 'i3 = gc_load_f(p0,%(ydescr.offset)s,%(ydescr.field_size)s)'], + [True, (1,2,4,8), 'setfield_raw(p0,i1,descr=ydescr)' '->' + 'gc_store(p0,%(ydescr.offset)s,i1,%(ydescr.field_size)s)'], + [True, (1,2,4,8), 'setfield_gc(p0,p0,descr=zdescr)' '->' 'cond_call_gc_wb(p0, descr=wbdescr);' - 'i3 = gc_store_indexed(p0,0,p0,1,' - '%(zdescr.offset)s,%(zdescr.field_size)s)'], + 'gc_store(p0,%(zdescr.offset)s,p0,%(zdescr.field_size)s)'], [False, (1,), 'i3 = arraylen_gc(p0, descr=adescr)' '->' 'i3 = gc_load_i(p0,0,%(adescr.itemsize)s)'], #[False, (1,), 'i3 = strlen(p0)' '->' # 'i3 = gc_load_i(p0,' # '%(strlendescr.offset)s,%(strlendescr.field_size)s)'], [True, (1,), 'i3 = strlen(p0)' '->' - 'i3 = gc_load_indexed_i(p0,0,1,' + 'i3 = gc_load_i(p0,' '%(strlendescr.offset)s,' '%(strlendescr.field_size)s)'], #[False, (1,), 'i3 = unicodelen(p0)' '->' @@ -1179,7 +1188,7 @@ # '%(unicodelendescr.offset)s,' # '%(unicodelendescr.field_size)s)'], [True, (1,), 'i3 = unicodelen(p0)' '->' - 'i3 = gc_load_indexed_i(p0,0,1,' + 'i3 = gc_load_i(p0,' '%(unicodelendescr.offset)s,' '%(unicodelendescr.field_size)s)'], diff --git a/rpython/jit/backend/ppc/opassembler.py b/rpython/jit/backend/ppc/opassembler.py --- a/rpython/jit/backend/ppc/opassembler.py +++ b/rpython/jit/backend/ppc/opassembler.py @@ -20,7 +20,7 @@ PPCBuilder, PPCGuardToken) from rpython.jit.backend.ppc.regalloc import TempPtr, TempInt from rpython.jit.backend.llsupport import symbolic, jitframe -from rpython.jit.backend.llsupport.descr import InteriorFieldDescr, CallDescr +from rpython.jit.backend.llsupport.descr import CallDescr from rpython.jit.backend.llsupport.gcmap import allocate_gcmap from rpython.rtyper.lltypesystem import rstr, rffi, lltype from rpython.rtyper.annlowlevel import cast_instance_to_gcref @@ -706,8 +706,10 @@ _mixin_ = True - def _write_to_mem(self, value_loc, base_loc, ofs, size): - if size.value == 8: + def _write_to_mem(self, value_loc, base_loc, ofs, size_loc): + assert size_loc.is_imm() + size = size_loc.value + if size == 8: if value_loc.is_fp_reg(): if ofs.is_imm(): self.mc.stfd(value_loc.value, base_loc.value, ofs.value) @@ -718,17 +720,17 @@ self.mc.std(value_loc.value, base_loc.value, ofs.value) else: self.mc.stdx(value_loc.value, base_loc.value, ofs.value) - elif size.value == 4: + elif size == 4: if ofs.is_imm(): self.mc.stw(value_loc.value, base_loc.value, ofs.value) else: self.mc.stwx(value_loc.value, base_loc.value, ofs.value) - elif size.value == 2: + elif size == 2: if ofs.is_imm(): self.mc.sth(value_loc.value, base_loc.value, ofs.value) else: self.mc.sthx(value_loc.value, base_loc.value, ofs.value) - elif size.value == 1: + elif size == 1: if ofs.is_imm(): self.mc.stb(value_loc.value, base_loc.value, ofs.value) else: @@ -736,18 +738,35 @@ else: assert 0, "size not supported" - def emit_setfield_gc(self, op, arglocs, regalloc): - value_loc, base_loc, ofs, size = arglocs - self._write_to_mem(value_loc, base_loc, ofs, size) + def emit_gc_store(self, op, arglocs, regalloc): + value_loc, base_loc, ofs_loc, size_loc = arglocs + self._write_to_mem(value_loc, base_loc, ofs_loc, size_loc) - emit_setfield_raw = emit_setfield_gc - emit_zero_ptr_field = emit_setfield_gc + def _apply_offset(self, index_loc, ofs_loc): + # If offset != 0 then we have to add it here. Note that + # mc.addi() would not be valid with operand r0. + assert ofs_loc.is_imm() # must be an immediate... + assert _check_imm_arg(ofs_loc.getint()) # ...that fits 16 bits + assert index_loc is not r.SCRATCH2 + # (simplified version of _apply_scale()) + if ofs_loc.value > 0: + self.mc.addi(r.SCRATCH2.value, index_loc.value, ofs_loc.value) + index_loc = r.SCRATCH2 + return index_loc - def _load_from_mem(self, res, base_loc, ofs, size, signed): + def emit_gc_store_indexed(self, op, arglocs, regalloc): + base_loc, index_loc, value_loc, ofs_loc, size_loc = arglocs + index_loc = self._apply_offset(index_loc, ofs_loc) + self._write_to_mem(value_loc, base_loc, index_loc, size_loc) + + def _load_from_mem(self, res, base_loc, ofs, size_loc, sign_loc): # res, base_loc, ofs, size and signed are all locations assert base_loc is not r.SCRATCH - sign = signed.value - if size.value == 8: + assert size_loc.is_imm() + size = size_loc.value + assert sign_loc.is_imm() + sign = sign_loc.value + if size == 8: if res.is_fp_reg(): if ofs.is_imm(): self.mc.lfd(res.value, base_loc.value, ofs.value) @@ -758,7 +777,7 @@ self.mc.ld(res.value, base_loc.value, ofs.value) else: self.mc.ldx(res.value, base_loc.value, ofs.value) - elif size.value == 4: + elif size == 4: if IS_PPC_64 and sign: if ofs.is_imm(): self.mc.lwa(res.value, base_loc.value, ofs.value) @@ -769,7 +788,7 @@ self.mc.lwz(res.value, base_loc.value, ofs.value) else: self.mc.lwzx(res.value, base_loc.value, ofs.value) - elif size.value == 2: + elif size == 2: if sign: if ofs.is_imm(): self.mc.lha(res.value, base_loc.value, ofs.value) @@ -780,7 +799,7 @@ self.mc.lhz(res.value, base_loc.value, ofs.value) else: self.mc.lhzx(res.value, base_loc.value, ofs.value) - elif size.value == 1: + elif size == 1: if ofs.is_imm(): self.mc.lbz(res.value, base_loc.value, ofs.value) else: @@ -790,22 +809,28 @@ else: assert 0, "size not supported" - def _genop_getfield(self, op, arglocs, regalloc): - base_loc, ofs, res, size, sign = arglocs - self._load_from_mem(res, base_loc, ofs, size, sign) + def _genop_gc_load(self, op, arglocs, regalloc): + base_loc, ofs_loc, res_loc, size_loc, sign_loc = arglocs + self._load_from_mem(res_loc, base_loc, ofs_loc, size_loc, sign_loc) - emit_getfield_gc_i = _genop_getfield - emit_getfield_gc_r = _genop_getfield - emit_getfield_gc_f = _genop_getfield - emit_getfield_gc_pure_i = _genop_getfield - emit_getfield_gc_pure_r = _genop_getfield - emit_getfield_gc_pure_f = _genop_getfield - emit_getfield_raw_i = _genop_getfield - emit_getfield_raw_f = _genop_getfield + emit_gc_load_i = _genop_gc_load + emit_gc_load_r = _genop_gc_load + emit_gc_load_f = _genop_gc_load + + def _genop_gc_load_indexed(self, op, arglocs, regalloc): + base_loc, index_loc, res_loc, ofs_loc, size_loc, sign_loc = arglocs + index_loc = self._apply_offset(index_loc, ofs_loc) + self._load_from_mem(res_loc, base_loc, index_loc, size_loc, sign_loc) + + emit_gc_load_indexed_i = _genop_gc_load_indexed + emit_gc_load_indexed_r = _genop_gc_load_indexed + emit_gc_load_indexed_f = _genop_gc_load_indexed SIZE2SCALE = dict([(1<<_i, _i) for _i in range(32)]) def _multiply_by_constant(self, loc, multiply_by, scratch_loc): + # XXX should die together with _apply_scale() but can't because + # of emit_zero_array() and malloc_cond_varsize() at the moment assert loc.is_reg() if multiply_by == 1: return loc @@ -827,6 +852,9 @@ return scratch_loc def _apply_scale(self, ofs, index_loc, itemsize): + # XXX should die now that getarrayitem and getinteriorfield are gone + # but can't because of emit_zero_array() at the moment + # For arrayitem and interiorfield reads and writes: this returns an # offset suitable for use in ld/ldx or similar instructions. # The result will be either the register r2 or a 16-bit immediate. @@ -857,44 +885,6 @@ index_loc = r.SCRATCH2 return index_loc - def _genop_getarray_or_interiorfield(self, op, arglocs, regalloc): - (base_loc, index_loc, res_loc, ofs_loc, - itemsize, fieldsize, fieldsign) = arglocs - ofs_loc = self._apply_scale(ofs_loc, index_loc, itemsize) - self._load_from_mem(res_loc, base_loc, ofs_loc, fieldsize, fieldsign) - - emit_getinteriorfield_gc_i = _genop_getarray_or_interiorfield - emit_getinteriorfield_gc_r = _genop_getarray_or_interiorfield - emit_getinteriorfield_gc_f = _genop_getarray_or_interiorfield - - def emit_setinteriorfield_gc(self, op, arglocs, regalloc): - (base_loc, index_loc, value_loc, ofs_loc, - itemsize, fieldsize) = arglocs - ofs_loc = self._apply_scale(ofs_loc, index_loc, itemsize) - self._write_to_mem(value_loc, base_loc, ofs_loc, fieldsize) - - emit_setinteriorfield_raw = emit_setinteriorfield_gc - - def emit_arraylen_gc(self, op, arglocs, regalloc): - res, base_loc, ofs = arglocs - self.mc.load(res.value, base_loc.value, ofs.value) - - emit_setarrayitem_gc = emit_setinteriorfield_gc - emit_setarrayitem_raw = emit_setarrayitem_gc - - emit_getarrayitem_gc_i = _genop_getarray_or_interiorfield - emit_getarrayitem_gc_r = _genop_getarray_or_interiorfield - emit_getarrayitem_gc_f = _genop_getarray_or_interiorfield - emit_getarrayitem_gc_pure_i = _genop_getarray_or_interiorfield - emit_getarrayitem_gc_pure_r = _genop_getarray_or_interiorfield - emit_getarrayitem_gc_pure_f = _genop_getarray_or_interiorfield - emit_getarrayitem_raw_i = _genop_getarray_or_interiorfield - emit_getarrayitem_raw_f = _genop_getarray_or_interiorfield - - emit_raw_store = emit_setarrayitem_gc - emit_raw_load_i = _genop_getarray_or_interiorfield - emit_raw_load_f = _genop_getarray_or_interiorfield - def _copy_in_scratch2(self, loc): if loc.is_imm(): self.mc.li(r.SCRATCH2.value, loc.value) @@ -998,10 +988,6 @@ _mixin_ = True - emit_strlen = FieldOpAssembler._genop_getfield - emit_strgetitem = FieldOpAssembler._genop_getarray_or_interiorfield - emit_strsetitem = FieldOpAssembler.emit_setarrayitem_gc - def emit_copystrcontent(self, op, arglocs, regalloc): self._emit_copycontent(arglocs, is_unicode=False) @@ -1059,12 +1045,8 @@ class UnicodeOpAssembler(object): - _mixin_ = True - - emit_unicodelen = FieldOpAssembler._genop_getfield - emit_unicodegetitem = FieldOpAssembler._genop_getarray_or_interiorfield - emit_unicodesetitem = FieldOpAssembler.emit_setarrayitem_gc + # empty! class AllocOpAssembler(object): diff --git a/rpython/jit/backend/ppc/regalloc.py b/rpython/jit/backend/ppc/regalloc.py --- a/rpython/jit/backend/ppc/regalloc.py +++ b/rpython/jit/backend/ppc/regalloc.py @@ -17,12 +17,9 @@ from rpython.rtyper.lltypesystem.lloperation import llop from rpython.rtyper.annlowlevel import cast_instance_to_gcref from rpython.jit.backend.llsupport import symbolic -from rpython.jit.backend.llsupport.descr import ArrayDescr +from rpython.jit.backend.llsupport.descr import unpack_arraydescr import rpython.jit.backend.ppc.register as r import rpython.jit.backend.ppc.condition as c -from rpython.jit.backend.llsupport.descr import unpack_arraydescr -from rpython.jit.backend.llsupport.descr import unpack_fielddescr -from rpython.jit.backend.llsupport.descr import unpack_interiorfielddescr from rpython.jit.backend.llsupport.gcmap import allocate_gcmap from rpython.rlib.objectmodel import we_are_translated from rpython.rlib.debug import debug_print @@ -691,159 +688,69 @@ src_locations2, dst_locations2, fptmploc) return [] - def prepare_setfield_gc(self, op): - ofs, size, _ = unpack_fielddescr(op.getdescr()) + def prepare_gc_store(self, op): base_loc = self.ensure_reg(op.getarg(0)) - value_loc = self.ensure_reg(op.getarg(1)) - ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs)) - return [value_loc, base_loc, ofs_loc, imm(size)] + ofs_loc = self.ensure_reg_or_16bit_imm(op.getarg(1)) + value_loc = self.ensure_reg(op.getarg(2)) + size_loc = self.ensure_reg_or_any_imm(op.getarg(3)) + return [value_loc, base_loc, ofs_loc, size_loc] - prepare_setfield_raw = prepare_setfield_gc + def _prepare_gc_load(self, op): + base_loc = self.ensure_reg(op.getarg(0)) + ofs_loc = self.ensure_reg_or_16bit_imm(op.getarg(1)) + self.free_op_vars() + res_loc = self.force_allocate_reg(op) + size_box = op.getarg(2) + assert isinstance(size_box, ConstInt) + nsize = size_box.value # negative for "signed" + size_loc = imm(abs(nsize)) + if nsize < 0: + sign = 1 + else: + sign = 0 + return [base_loc, ofs_loc, res_loc, size_loc, imm(sign)] - def _prepare_getfield(self, op): - ofs, size, sign = unpack_fielddescr(op.getdescr()) + prepare_gc_load_i = _prepare_gc_load + prepare_gc_load_r = _prepare_gc_load + prepare_gc_load_f = _prepare_gc_load + + def prepare_gc_store_indexed(self, op): base_loc = self.ensure_reg(op.getarg(0)) - ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs)) + index_loc = self.ensure_reg_or_any_imm(op.getarg(1)) + value_loc = self.ensure_reg(op.getarg(2)) + assert op.getarg(3).getint() == 1 # scale + ofs_loc = self.ensure_reg_or_16bit_imm(op.getarg(4)) + assert ofs_loc.is_imm() # the arg(4) should always be a small constant + size_loc = self.ensure_reg_or_any_imm(op.getarg(5)) + return [base_loc, index_loc, value_loc, ofs_loc, size_loc] + + def _prepare_gc_load_indexed(self, op): + base_loc = self.ensure_reg(op.getarg(0)) + index_loc = self.ensure_reg_or_any_imm(op.getarg(1)) + assert op.getarg(2).getint() == 1 # scale + ofs_loc = self.ensure_reg_or_16bit_imm(op.getarg(3)) + assert ofs_loc.is_imm() # the arg(3) should always be a small constant self.free_op_vars() - res = self.force_allocate_reg(op) - return [base_loc, ofs_loc, res, imm(size), imm(sign)] + res_loc = self.force_allocate_reg(op) + size_box = op.getarg(4) + assert isinstance(size_box, ConstInt) + nsize = size_box.value # negative for "signed" + size_loc = imm(abs(nsize)) + if nsize < 0: + sign = 1 + else: + sign = 0 + return [base_loc, index_loc, res_loc, ofs_loc, size_loc, imm(sign)] - prepare_getfield_gc_i = _prepare_getfield - prepare_getfield_gc_r = _prepare_getfield - prepare_getfield_gc_f = _prepare_getfield - prepare_getfield_raw_i = _prepare_getfield - prepare_getfield_raw_f = _prepare_getfield - prepare_getfield_gc_pure_i = _prepare_getfield - prepare_getfield_gc_pure_r = _prepare_getfield - prepare_getfield_gc_pure_f = _prepare_getfield + prepare_gc_load_indexed_i = _prepare_gc_load_indexed + prepare_gc_load_indexed_r = _prepare_gc_load_indexed + prepare_gc_load_indexed_f = _prepare_gc_load_indexed def prepare_increment_debug_counter(self, op): base_loc = self.ensure_reg(op.getarg(0)) temp_loc = r.SCRATCH2 return [base_loc, temp_loc] - def _prepare_getinteriorfield(self, op): - t = unpack_interiorfielddescr(op.getdescr()) - ofs, itemsize, fieldsize, sign = t - base_loc = self.ensure_reg(op.getarg(0)) - index_loc = self.ensure_reg_or_any_imm(op.getarg(1)) - ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs)) - self.free_op_vars() - result_loc = self.force_allocate_reg(op) - return [base_loc, index_loc, result_loc, ofs_loc, - imm(itemsize), imm(fieldsize), imm(sign)] - - prepare_getinteriorfield_gc_i = _prepare_getinteriorfield - prepare_getinteriorfield_gc_r = _prepare_getinteriorfield - prepare_getinteriorfield_gc_f = _prepare_getinteriorfield - - def prepare_setinteriorfield_gc(self, op): - t = unpack_interiorfielddescr(op.getdescr()) - ofs, itemsize, fieldsize, _ = t - base_loc = self.ensure_reg(op.getarg(0)) - index_loc = self.ensure_reg_or_any_imm(op.getarg(1)) - value_loc = self.ensure_reg(op.getarg(2)) - ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs)) - return [base_loc, index_loc, value_loc, ofs_loc, - imm(itemsize), imm(fieldsize)] - - prepare_setinteriorfield_raw = prepare_setinteriorfield_gc - - def prepare_arraylen_gc(self, op): - arraydescr = op.getdescr() - assert isinstance(arraydescr, ArrayDescr) - ofs = arraydescr.lendescr.offset - assert _check_imm_arg(ofs) - base_loc = self.ensure_reg(op.getarg(0)) - self.free_op_vars() - res = self.force_allocate_reg(op) - return [res, base_loc, imm(ofs)] - - def prepare_setarrayitem_gc(self, op): - size, ofs, _ = unpack_arraydescr(op.getdescr()) - base_loc = self.ensure_reg(op.getarg(0)) - index_loc = self.ensure_reg_or_any_imm(op.getarg(1)) - value_loc = self.ensure_reg(op.getarg(2)) - ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs)) - imm_size = imm(size) - return [base_loc, index_loc, value_loc, ofs_loc, - imm_size, imm_size] - - prepare_setarrayitem_raw = prepare_setarrayitem_gc - - def prepare_raw_store(self, op): - size, ofs, _ = unpack_arraydescr(op.getdescr()) - base_loc = self.ensure_reg(op.getarg(0)) - index_loc = self.ensure_reg_or_any_imm(op.getarg(1)) - value_loc = self.ensure_reg(op.getarg(2)) - ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs)) - return [base_loc, index_loc, value_loc, ofs_loc, - imm(1), imm(size)] - - def _prepare_getarrayitem(self, op): - size, ofs, sign = unpack_arraydescr(op.getdescr()) - base_loc = self.ensure_reg(op.getarg(0)) - index_loc = self.ensure_reg_or_any_imm(op.getarg(1)) - ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs)) - self.free_op_vars() - result_loc = self.force_allocate_reg(op) - imm_size = imm(size) - return [base_loc, index_loc, result_loc, ofs_loc, - imm_size, imm_size, imm(sign)] - - prepare_getarrayitem_gc_i = _prepare_getarrayitem - prepare_getarrayitem_gc_r = _prepare_getarrayitem - prepare_getarrayitem_gc_f = _prepare_getarrayitem - prepare_getarrayitem_raw_i = _prepare_getarrayitem - prepare_getarrayitem_raw_f = _prepare_getarrayitem - prepare_getarrayitem_gc_pure_i = _prepare_getarrayitem - prepare_getarrayitem_gc_pure_r = _prepare_getarrayitem - prepare_getarrayitem_gc_pure_f = _prepare_getarrayitem - - def _prepare_raw_load(self, op): - size, ofs, sign = unpack_arraydescr(op.getdescr()) - base_loc = self.ensure_reg(op.getarg(0)) - index_loc = self.ensure_reg_or_any_imm(op.getarg(1)) - ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(ofs)) - self.free_op_vars() - result_loc = self.force_allocate_reg(op) - return [base_loc, index_loc, result_loc, ofs_loc, - imm(1), imm(size), imm(sign)] - - prepare_raw_load_i = _prepare_raw_load - prepare_raw_load_f = _prepare_raw_load - - def prepare_strlen(self, op): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR, - self.cpu.translate_support_code) - base_loc = self.ensure_reg(op.getarg(0)) - self.free_op_vars() - result_loc = self.force_allocate_reg(op) - return [base_loc, imm(ofs_length), result_loc, imm(WORD), imm(0)] - - def prepare_strgetitem(self, op): - basesize, itemsize, _ = symbolic.get_array_token(rstr.STR, - self.cpu.translate_support_code) - base_loc = self.ensure_reg(op.getarg(0)) - index_loc = self.ensure_reg_or_any_imm(op.getarg(1)) - ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(basesize)) - self.free_op_vars() - result_loc = self.force_allocate_reg(op) - imm_size = imm(itemsize) - return [base_loc, index_loc, result_loc, ofs_loc, - imm_size, imm_size, imm(0)] - - def prepare_strsetitem(self, op): - basesize, itemsize, _ = symbolic.get_array_token(rstr.STR, - self.cpu.translate_support_code) - base_loc = self.ensure_reg(op.getarg(0)) - index_loc = self.ensure_reg_or_any_imm(op.getarg(1)) - value_loc = self.ensure_reg(op.getarg(2)) - ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(basesize)) - imm_size = imm(itemsize) - return [base_loc, index_loc, value_loc, ofs_loc, - imm_size, imm_size] - def prepare_copystrcontent(self, op): src_ptr_loc = self.ensure_reg(op.getarg(0)) dst_ptr_loc = self.ensure_reg(op.getarg(1)) @@ -856,37 +763,6 @@ prepare_copyunicodecontent = prepare_copystrcontent - def prepare_unicodelen(self, op): - basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE, - self.cpu.translate_support_code) - base_loc = self.ensure_reg(op.getarg(0)) - self.free_op_vars() - result_loc = self.force_allocate_reg(op) - return [base_loc, imm(ofs_length), result_loc, imm(WORD), imm(0)] - - def prepare_unicodegetitem(self, op): - basesize, itemsize, _ = symbolic.get_array_token(rstr.UNICODE, - self.cpu.translate_support_code) - base_loc = self.ensure_reg(op.getarg(0)) - index_loc = self.ensure_reg_or_any_imm(op.getarg(1)) - ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(basesize)) - self.free_op_vars() - result_loc = self.force_allocate_reg(op) - imm_size = imm(itemsize) - return [base_loc, index_loc, result_loc, ofs_loc, - imm_size, imm_size, imm(0)] - - def prepare_unicodesetitem(self, op): - basesize, itemsize, _ = symbolic.get_array_token(rstr.UNICODE, - self.cpu.translate_support_code) - base_loc = self.ensure_reg(op.getarg(0)) - index_loc = self.ensure_reg_or_any_imm(op.getarg(1)) - value_loc = self.ensure_reg(op.getarg(2)) - ofs_loc = self.ensure_reg_or_16bit_imm(ConstInt(basesize)) - imm_size = imm(itemsize) - return [base_loc, index_loc, value_loc, ofs_loc, - imm_size, imm_size] - prepare_same_as_i = helper.prepare_unary_op prepare_same_as_r = helper.prepare_unary_op prepare_same_as_f = helper.prepare_unary_op @@ -1078,12 +954,6 @@ arglocs = self._prepare_guard(op) return arglocs - def prepare_zero_ptr_field(self, op): - base_loc = self.ensure_reg(op.getarg(0)) - ofs_loc = self.ensure_reg_or_16bit_imm(op.getarg(1)) - value_loc = self.ensure_reg(ConstInt(0)) - return [value_loc, base_loc, ofs_loc, imm(WORD)] - def prepare_zero_array(self, op): itemsize, ofs, _ = unpack_arraydescr(op.getdescr()) base_loc = self.ensure_reg(op.getarg(0)) diff --git a/rpython/jit/backend/ppc/runner.py b/rpython/jit/backend/ppc/runner.py --- a/rpython/jit/backend/ppc/runner.py +++ b/rpython/jit/backend/ppc/runner.py @@ -21,6 +21,9 @@ IS_64_BIT = True backend_name = 'ppc64' + # can an ISA instruction handle a factor to the offset? + load_supported_factors = (1,) + from rpython.jit.backend.ppc.register import JITFRAME_FIXED_SIZE frame_reg = r.SP all_reg_indexes = [-1] * 32 diff --git a/rpython/jit/backend/x86/regalloc.py b/rpython/jit/backend/x86/regalloc.py --- a/rpython/jit/backend/x86/regalloc.py +++ b/rpython/jit/backend/x86/regalloc.py @@ -4,8 +4,7 @@ import os, sys from rpython.jit.backend.llsupport import symbolic -from rpython.jit.backend.llsupport.descr import (ArrayDescr, CallDescr, - unpack_arraydescr, unpack_fielddescr, unpack_interiorfielddescr) +from rpython.jit.backend.llsupport.descr import CallDescr, unpack_arraydescr from rpython.jit.backend.llsupport.gcmap import allocate_gcmap from rpython.jit.backend.llsupport.regalloc import (FrameManager, BaseRegalloc, RegisterManager, TempVar, compute_vars_longevity, is_comparison_or_ovf_op, @@ -1039,7 +1038,8 @@ base_loc = self.rm.make_sure_var_in_reg(op.getarg(0), args) size_box = op.getarg(3) assert isinstance(size_box, ConstInt) - size = abs(size_box.value) + size = size_box.value + assert size >= 1 if size == 1: need_lower_byte = True else: @@ -1061,7 +1061,8 @@ assert isinstance(size_box, ConstInt) factor = scale_box.value offset = offset_box.value - size = abs(size_box.value) + size = size_box.value + assert size >= 1 if size == 1: need_lower_byte = True else: @@ -1083,9 +1084,9 @@ result_loc = self.force_allocate_reg(op) size_box = op.getarg(2) assert isinstance(size_box, ConstInt) - size = size_box.value - size_loc = imm(abs(size)) - if size < 0: + nsize = size_box.value # negative for "signed" + size_loc = imm(abs(nsize)) + if nsize < 0: sign_loc = imm1 else: sign_loc = imm0 @@ -1108,9 +1109,9 @@ assert isinstance(size_box, ConstInt) scale = scale_box.value offset = offset_box.value - size = size_box.value - size_loc = imm(abs(size)) - if size < 0: + nsize = size_box.value # negative for "signed" + size_loc = imm(abs(nsize)) + if nsize < 0: sign_loc = imm1 else: sign_loc = imm0 diff --git a/rpython/jit/codewriter/jtransform.py b/rpython/jit/codewriter/jtransform.py --- a/rpython/jit/codewriter/jtransform.py +++ b/rpython/jit/codewriter/jtransform.py @@ -1021,18 +1021,20 @@ kind = getkind(op.result.concretetype)[0] return SpaceOperation('getinteriorfield_gc_%s' % kind, args, op.result) - elif isinstance(op.args[0].concretetype.TO, lltype.GcStruct): - # special-case 2: GcStruct with Array field - v_inst, c_field, v_index = op.args - STRUCT = v_inst.concretetype.TO - ARRAY = getattr(STRUCT, c_field.value) - assert isinstance(ARRAY, lltype.Array) - arraydescr = self.cpu.arraydescrof(STRUCT) - kind = getkind(op.result.concretetype)[0] - assert kind in ('i', 'f') - return SpaceOperation('getarrayitem_gc_%s' % kind, - [op.args[0], v_index, arraydescr], - op.result) + #elif isinstance(op.args[0].concretetype.TO, lltype.GcStruct): + # # special-case 2: GcStruct with Array field + # ---was added in the faster-rstruct branch,--- + # ---no longer directly supported--- + # v_inst, c_field, v_index = op.args + # STRUCT = v_inst.concretetype.TO + # ARRAY = getattr(STRUCT, c_field.value) + # assert isinstance(ARRAY, lltype.Array) + # arraydescr = self.cpu.arraydescrof(STRUCT) + # kind = getkind(op.result.concretetype)[0] + # assert kind in ('i', 'f') + # return SpaceOperation('getarrayitem_gc_%s' % kind, + # [op.args[0], v_index, arraydescr], + # op.result) else: assert False, 'not supported' @@ -1084,6 +1086,25 @@ return SpaceOperation('raw_load_%s' % kind, [op.args[0], op.args[1], descr], op.result) + def rewrite_op_gc_load_indexed(self, op): + T = op.result.concretetype + kind = getkind(T)[0] + assert kind != 'r' + descr = self.cpu.arraydescrof(rffi.CArray(T)) + if (not isinstance(op.args[2], Constant) or + not isinstance(op.args[3], Constant)): + raise NotImplementedError("gc_load_indexed: 'scale' and 'base_ofs'" + " should be constants") + # xxx hard-code the size in bytes at translation time, which is + # probably fine and avoids lots of issues later + bytes = descr.get_item_size_in_bytes() + if descr.is_item_signed(): + bytes = -bytes + c_bytes = Constant(bytes, lltype.Signed) + return SpaceOperation('gc_load_indexed_%s' % kind, + [op.args[0], op.args[1], + op.args[2], op.args[3], c_bytes], op.result) + def _rewrite_equality(self, op, opname): arg0, arg1 = op.args if isinstance(arg0, Constant) and not arg0.value: diff --git a/rpython/jit/metainterp/blackhole.py b/rpython/jit/metainterp/blackhole.py --- a/rpython/jit/metainterp/blackhole.py +++ b/rpython/jit/metainterp/blackhole.py @@ -1434,6 +1434,13 @@ def bhimpl_raw_load_f(cpu, addr, offset, arraydescr): return cpu.bh_raw_load_f(addr, offset, arraydescr) + @arguments("cpu", "r", "i", "i", "i", "i", returns="i") + def bhimpl_gc_load_indexed_i(cpu, addr, index, scale, base_ofs, bytes): + return cpu.bh_gc_load_indexed_i(addr, index,scale,base_ofs, bytes) + @arguments("cpu", "r", "i", "i", "i", "i", returns="f") + def bhimpl_gc_load_indexed_f(cpu, addr, index, scale, base_ofs, bytes): + return cpu.bh_gc_load_indexed_f(addr, index,scale,base_ofs, bytes) + @arguments("r", "d", "d") def bhimpl_record_quasiimmut_field(struct, fielddescr, mutatefielddescr): pass diff --git a/rpython/jit/metainterp/history.py b/rpython/jit/metainterp/history.py --- a/rpython/jit/metainterp/history.py +++ b/rpython/jit/metainterp/history.py @@ -68,8 +68,8 @@ return box.value def repr_rpython(box, typechars): - return '%s/%s%d' % (box._get_hash_(), typechars, - compute_unique_id(box)) + return '%s/%s' % (box._get_hash_(), typechars, + ) #compute_unique_id(box)) class XxxAbstractValue(object): diff --git a/rpython/jit/metainterp/optimizeopt/heap.py b/rpython/jit/metainterp/optimizeopt/heap.py --- a/rpython/jit/metainterp/optimizeopt/heap.py +++ b/rpython/jit/metainterp/optimizeopt/heap.py @@ -526,16 +526,10 @@ cf.do_setfield(self, op) def optimize_GETARRAYITEM_GC_I(self, op): - # When using str_storage_getitem it might happen that op.getarg(0) is - # a virtual string, NOT an array. In that case, we cannot cache the - # getarrayitem as if it were an array, obviously. In theory we could - # improve by writing special code to interpter the buffer of the - # virtual string as if it were an array, but it looks complicate, - # fragile and not worth it. arrayinfo = self.ensure_ptr_info_arg0(op) indexb = self.getintbound(op.getarg(1)) cf = None - if indexb.is_constant() and not arrayinfo.is_vstring(): + if indexb.is_constant(): index = indexb.getint() arrayinfo.getlenbound(None).make_gt_const(index) # use the cache on (arraydescr, index), which is a constant @@ -552,7 +546,7 @@ self.make_nonnull(op.getarg(0)) self.emit_operation(op) # the remember the result of reading the array item - if cf is not None and not arrayinfo.is_vstring(): + if cf is not None: arrayinfo.setitem(op.getdescr(), indexb.getint(), self.get_box_replacement(op.getarg(0)), self.get_box_replacement(op), cf, diff --git a/rpython/jit/metainterp/optimizeopt/info.py b/rpython/jit/metainterp/optimizeopt/info.py --- a/rpython/jit/metainterp/optimizeopt/info.py +++ b/rpython/jit/metainterp/optimizeopt/info.py @@ -24,9 +24,6 @@ def is_virtual(self): return False - def is_vstring(self): - return False - def is_precise(self): return False diff --git a/rpython/jit/metainterp/optimizeopt/virtualize.py b/rpython/jit/metainterp/optimizeopt/virtualize.py --- a/rpython/jit/metainterp/optimizeopt/virtualize.py +++ b/rpython/jit/metainterp/optimizeopt/virtualize.py @@ -271,10 +271,8 @@ self.emit_operation(op) def optimize_GETARRAYITEM_GC_I(self, op): - # When using str_storage_getitem we op.getarg(0) is a string, NOT an - # array, hence the check. In that case, it will be forced opinfo = self.getptrinfo(op.getarg(0)) - if opinfo and opinfo.is_virtual() and not opinfo.is_vstring(): + if opinfo and opinfo.is_virtual(): indexbox = self.get_constant_box(op.getarg(1)) if indexbox is not None: item = opinfo.getitem(op.getdescr(), indexbox.getint()) diff --git a/rpython/jit/metainterp/optimizeopt/vstring.py b/rpython/jit/metainterp/optimizeopt/vstring.py --- a/rpython/jit/metainterp/optimizeopt/vstring.py +++ b/rpython/jit/metainterp/optimizeopt/vstring.py @@ -62,9 +62,6 @@ self.mode = mode self.length = length - def is_vstring(self): - return True - def getlenbound(self, mode): from rpython.jit.metainterp.optimizeopt import intutils diff --git a/rpython/jit/metainterp/pyjitpl.py b/rpython/jit/metainterp/pyjitpl.py --- a/rpython/jit/metainterp/pyjitpl.py +++ b/rpython/jit/metainterp/pyjitpl.py @@ -801,6 +801,27 @@ return self.execute_with_descr(rop.RAW_LOAD_F, arraydescr, addrbox, offsetbox) + def _remove_symbolics(self, c): + if not we_are_translated(): + from rpython.rtyper.lltypesystem import ll2ctypes + assert isinstance(c, ConstInt) + c = ConstInt(ll2ctypes.lltype2ctypes(c.value)) + return c + + @arguments("box", "box", "box", "box", "box") + def opimpl_gc_load_indexed_i(self, addrbox, indexbox, + scalebox, baseofsbox, bytesbox): + return self.execute(rop.GC_LOAD_INDEXED_I, addrbox, indexbox, + self._remove_symbolics(scalebox), + self._remove_symbolics(baseofsbox), bytesbox) + + @arguments("box", "box", "box", "box", "box") + def opimpl_gc_load_indexed_f(self, addrbox, indexbox, + scalebox, baseofsbox, bytesbox): + return self.execute(rop.GC_LOAD_INDEXED_F, addrbox, indexbox, + self._remove_symbolics(scalebox), + self._remove_symbolics(baseofsbox), bytesbox) + @arguments("box") def opimpl_hint_force_virtualizable(self, box): self.metainterp.gen_store_back_in_vable(box) diff --git a/rpython/jit/metainterp/resoperation.py b/rpython/jit/metainterp/resoperation.py --- a/rpython/jit/metainterp/resoperation.py +++ b/rpython/jit/metainterp/resoperation.py @@ -1212,8 +1212,12 @@ '_NOSIDEEFFECT_LAST', # ----- end of no_side_effect operations ----- # same paramters as GC_LOAD, but one additional for the value to store - # note that the itemsize is not signed! + # note that the itemsize is not signed (always > 0) # (gcptr, index, value, [scale, base_offset,] itemsize) + # invariants for GC_STORE: index is constant, but can be large + # invariants for GC_STORE_INDEXED: index is a non-constant box; + # scale is a constant; + # base_offset is a small constant 'GC_STORE/4d/n', 'GC_STORE_INDEXED/6d/n', diff --git a/rpython/jit/metainterp/test/test_strstorage.py b/rpython/jit/metainterp/test/test_strstorage.py --- a/rpython/jit/metainterp/test/test_strstorage.py +++ b/rpython/jit/metainterp/test/test_strstorage.py @@ -19,7 +19,7 @@ res = self.interp_operations(f, [], supports_singlefloats=True) # kind = getkind(TYPE)[0] # 'i' or 'f' - self.check_operations_history({'getarrayitem_gc_%s' % kind: 1, + self.check_operations_history({'gc_load_indexed_%s' % kind: 1, 'finish': 1}) # if TYPE == lltype.SingleFloat: @@ -29,8 +29,8 @@ return longlong.int2singlefloat(res) return res - def str_storage_supported(self, TYPE): - py.test.skip('this is not a JIT test') + #def str_storage_supported(self, TYPE): + # py.test.skip('this is not a JIT test') def test_force_virtual_str_storage(self): byteorder = sys.byteorder @@ -48,6 +48,6 @@ 'strsetitem': 1, # str forcing 'call_pure_r': 1, # str forcing (copystrcontent) 'guard_no_exception': 1, # str forcing - 'getarrayitem_gc_i': 1, # str_storage_getitem + 'gc_load_indexed_i': 1, # str_storage_getitem 'finish': 1 }) diff --git a/rpython/rlib/objectmodel.py b/rpython/rlib/objectmodel.py --- a/rpython/rlib/objectmodel.py +++ b/rpython/rlib/objectmodel.py @@ -114,6 +114,8 @@ specialize = _Specialize() +NOT_CONSTANT = object() # to use in enforceargs() + def enforceargs(*types_, **kwds): """ Decorate a function with forcing of RPython-level types on arguments. None means no enforcing. diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py --- a/rpython/rlib/rposix.py +++ b/rpython/rlib/rposix.py @@ -9,7 +9,7 @@ from rpython.translator.tool.cbuild import ExternalCompilationInfo from rpython.rlib.rarithmetic import intmask, widen from rpython.rlib.objectmodel import ( - specialize, enforceargs, register_replacement_for) + specialize, enforceargs, register_replacement_for, NOT_CONSTANT) from rpython.rlib.signature import signature from rpython.rlib import types from rpython.annotator.model import s_Str0 @@ -415,7 +415,7 @@ @replace_os_function('open') @specialize.argtype(0) -@enforceargs(None, int, int, typecheck=False) +@enforceargs(NOT_CONSTANT, int, int, typecheck=False) def open(path, flags, mode): if _prefer_unicode(path): fd = c_wopen(_as_unicode0(path), flags, mode) diff --git a/rpython/rlib/rstruct/nativefmttable.py b/rpython/rlib/rstruct/nativefmttable.py --- a/rpython/rlib/rstruct/nativefmttable.py +++ b/rpython/rlib/rstruct/nativefmttable.py @@ -11,7 +11,6 @@ from rpython.rlib.rstruct.standardfmttable import native_is_bigendian from rpython.rlib.rstruct.error import StructError from rpython.rlib.unroll import unrolling_iterable -from rpython.rlib.strstorage import str_storage_getitem from rpython.rtyper.lltypesystem import lltype, rffi from rpython.rtyper.tool import rffi_platform from rpython.translator.tool.cbuild import ExternalCompilationInfo diff --git a/rpython/rlib/rstruct/standardfmttable.py b/rpython/rlib/rstruct/standardfmttable.py --- a/rpython/rlib/rstruct/standardfmttable.py +++ b/rpython/rlib/rstruct/standardfmttable.py @@ -12,7 +12,7 @@ from rpython.rlib.rstruct import ieee from rpython.rlib.rstruct.error import StructError, StructOverflowError from rpython.rlib.unroll import unrolling_iterable -from rpython.rlib.strstorage import str_storage_getitem, str_storage_supported +from rpython.rlib.strstorage import str_storage_getitem from rpython.rlib import rarithmetic from rpython.rtyper.lltypesystem import rffi @@ -185,13 +185,14 @@ data = fmtiter.read(size) fmtiter.appendobj(ieee.unpack_float(data, fmtiter.bigendian)) return - if not str_storage_supported(TYPE): - # this happens e.g. on win32 and ARM32: we cannot read the string - # content as an array of doubles because it's not properly - # aligned. But we can read a longlong and convert to float - assert TYPE == rffi.DOUBLE - assert rffi.sizeof(TYPE) == 8 - return unpack_longlong2float(fmtiter) + ## XXX check if the following code is still needed + ## if not str_storage_supported(TYPE): + ## # this happens e.g. on win32 and ARM32: we cannot read the string + ## # content as an array of doubles because it's not properly + ## # aligned. But we can read a longlong and convert to float + ## assert TYPE == rffi.DOUBLE + ## assert rffi.sizeof(TYPE) == 8 + ## return unpack_longlong2float(fmtiter) try: # fast path val = unpack_fastpath(TYPE)(fmtiter) @@ -246,7 +247,7 @@ @specialize.argtype(0) def unpack_int_fastpath_maybe(fmtiter): - if fmtiter.bigendian != native_is_bigendian or not str_storage_supported(TYPE): + if fmtiter.bigendian != native_is_bigendian or not native_is_ieee754: ## or not str_storage_supported(TYPE): return False try: intvalue = unpack_fastpath(TYPE)(fmtiter) diff --git a/rpython/rlib/rurandom.py b/rpython/rlib/rurandom.py --- a/rpython/rlib/rurandom.py +++ b/rpython/rlib/rurandom.py @@ -86,27 +86,29 @@ else: # Posix implementation def init_urandom(): """NOT_RPYTHON - Return an array of one int, initialized to 0. - It is filled automatically the first time urandom() is called. """ - return lltype.malloc(rffi.CArray(lltype.Signed), 1, - immortal=True, zero=True) + return None def urandom(context, n): "Read n bytes from /dev/urandom." result = '' if n == 0: return result - if not context[0]: - context[0] = os.open("/dev/urandom", os.O_RDONLY, 0777) - while n > 0: - try: - data = os.read(context[0], n) - except OSError, e: - if e.errno != errno.EINTR: - raise - data = '' - result += data - n -= len(data) + # XXX should somehow cache the file descriptor. It's a mess. + # CPython has a 99% solution and hopes for the remaining 1% + # not to occur. For now, we just don't cache the file + # descriptor (any more... 6810f401d08e). + fd = os.open("/dev/urandom", os.O_RDONLY, 0777) + try: + while n > 0: + try: + data = os.read(fd, n) + except OSError, e: + if e.errno != errno.EINTR: + raise + data = '' + result += data + n -= len(data) + finally: + os.close(fd) return result - diff --git a/rpython/rlib/strstorage.py b/rpython/rlib/strstorage.py --- a/rpython/rlib/strstorage.py +++ b/rpython/rlib/strstorage.py @@ -9,54 +9,31 @@ # rstr.py:copy_string_contents), which has no chance to work during # tracing # -# 2. use llop.raw_load: despite the name, llop.raw_load DOES support reading -# from GC pointers. However: -# -# a. we would like to use a CompositeOffset as the offset (using the -# same logic as in rstr.py:_get_raw_str_buf), but this is not (yet) -# supported before translation: it works only if you pass an actual -# integer -# -# b. raw_load from a GC pointer is not (yet) supported by the -# JIT. There are plans to introduce a gc_load operation: when it -# will be there, we could fix the issue above and actually use it to -# implement str_storage_getitem -# -# 3. the actual solution: cast rpy_string to a GcStruct which has the very +# 2. cast rpy_string to a GcStruct which has the very # same layout, with the only difference that its 'chars' field is no # longer an Array(Char) but e.e. an Array(Signed). Then, we just need to -# read the appropriate index into the array +# read the appropriate index into the array. To support this solution, +# the JIT's optimizer needed a few workarounds. This was removed. +# +# 3. use the newly introduced 'llop.gc_load_indexed'. +# -from rpython.rtyper.lltypesystem import lltype, rffi, llmemory -from rpython.rtyper.lltypesystem.rstr import STR, _get_raw_str_buf + +from rpython.rtyper.lltypesystem import lltype, llmemory +from rpython.rtyper.lltypesystem.lloperation import llop +from rpython.rtyper.lltypesystem.rstr import STR from rpython.rtyper.annlowlevel import llstr -from rpython.rlib.objectmodel import specialize, we_are_translated +from rpython.rlib.objectmodel import specialize -@specialize.memo() -def _rpy_string_as_type(TP): - # sanity check that STR is actually what we think it is - assert STR._flds == { - 'hash': lltype.Signed, - 'chars': lltype.Array(lltype.Char, hints={'immutable': True}) - } - STR_AS_TP = lltype.GcStruct('rpy_string_as_%s' % TP, - ('hash', lltype.Signed), - ('chars', lltype.Array(TP, hints={'immutable': True}))) - return STR_AS_TP - -@specialize.arg(0) -def str_storage_supported(TP): - # on some architectures (e.g. win32 and arm32) an array of longlongs needs - # to be aligned at 8 bytes boundaries, so we cannot safely cast from STR - # to STR_AS_TP. In that case, we str_storage_getitem is simply not - # supported - return rffi.sizeof(TP) <= rffi.sizeof(lltype.Signed) @specialize.ll() -def str_storage_getitem(TP, s, index): - assert str_storage_supported(TP) # sanity check - STR_AS_TP = _rpy_string_as_type(TP) +def str_storage_getitem(TP, s, byte_offset): + # WARNING: the 'byte_offset' is, as its name says, measured in bytes; + # however, it should be aligned for TP, otherwise on some platforms this + # code will crash! lls = llstr(s) - str_as_tp = rffi.cast(lltype.Ptr(STR_AS_TP), lls) - index = index / rffi.sizeof(TP) - return str_as_tp.chars[index] + base_ofs = (llmemory.offsetof(STR, 'chars') + + llmemory.itemoffsetof(STR.chars, 0)) + scale_factor = llmemory.sizeof(lltype.Char) + return llop.gc_load_indexed(TP, lls, byte_offset, + scale_factor, base_ofs) diff --git a/rpython/rlib/test/test_objectmodel.py b/rpython/rlib/test/test_objectmodel.py --- a/rpython/rlib/test/test_objectmodel.py +++ b/rpython/rlib/test/test_objectmodel.py @@ -4,7 +4,7 @@ r_dict, UnboxedValue, Symbolic, compute_hash, compute_identity_hash, compute_unique_id, current_object_addr_as_int, we_are_translated, prepare_dict_update, reversed_dict, specialize, enforceargs, newlist_hint, - resizelist_hint, is_annotation_constant, always_inline, + resizelist_hint, is_annotation_constant, always_inline, NOT_CONSTANT, iterkeys_with_hash, iteritems_with_hash, contains_with_hash, setitem_with_hash, getitem_with_hash, delitem_with_hash, import_from_mixin) from rpython.translator.translator import TranslationContext, graphof @@ -529,6 +529,18 @@ TYPES = [v.concretetype for v in graph.getargs()] assert TYPES == [lltype.Signed, lltype.Float] +def test_enforceargs_not_constant(): + from rpython.translator.translator import TranslationContext, graphof + @enforceargs(NOT_CONSTANT) + def f(a): + return a + def f42(): + return f(42) + t = TranslationContext() + a = t.buildannotator() + s = a.build_types(f42, []) + assert not hasattr(s, 'const') + def getgraph(f, argtypes): from rpython.translator.translator import TranslationContext, graphof diff --git a/rpython/rlib/test/test_strstorage.py b/rpython/rlib/test/test_strstorage.py --- a/rpython/rlib/test/test_strstorage.py +++ b/rpython/rlib/test/test_strstorage.py @@ -2,7 +2,7 @@ import sys import struct from rpython.rtyper.lltypesystem import lltype, rffi -from rpython.rlib.strstorage import str_storage_getitem, str_storage_supported +from rpython.rlib.strstorage import str_storage_getitem from rpython.rlib.rarithmetic import r_singlefloat from rpython.rtyper.test.tool import BaseRtypingTest @@ -10,14 +10,14 @@ class BaseStrStorageTest: - def test_str_getitem_supported(self): - if IS_32BIT: - expected = False - else: - expected = True - # - assert self.str_storage_supported(rffi.LONGLONG) == expected - assert self.str_storage_supported(rffi.DOUBLE) == expected + ## def test_str_getitem_supported(self): + ## if IS_32BIT: + ## expected = False + ## else: + ## expected = True + ## # + ## assert self.str_storage_supported(rffi.LONGLONG) == expected + ## assert self.str_storage_supported(rffi.DOUBLE) == expected def test_signed(self): buf = struct.pack('@ll', 42, 43) @@ -34,8 +34,8 @@ assert int(x) == 43 def test_float(self): - if not str_storage_supported(lltype.Float): - py.test.skip('str_storage_getitem(lltype.Float) not supported on this machine') + ## if not str_storage_supported(lltype.Float): + ## py.test.skip('str_storage_getitem(lltype.Float) not supported on this machine') buf = struct.pack('@dd', 12.3, 45.6) size = struct.calcsize('@d') assert self.str_storage_getitem(lltype.Float, buf, 0) == 12.3 @@ -52,20 +52,45 @@ class TestDirect(BaseStrStorageTest): - def str_storage_supported(self, TYPE): - return str_storage_supported(TYPE) + ## def str_storage_supported(self, TYPE): + ## return str_storage_supported(TYPE) def str_storage_getitem(self, TYPE, buf, offset): return str_storage_getitem(TYPE, buf, offset) class TestRTyping(BaseStrStorageTest, BaseRtypingTest): - def str_storage_supported(self, TYPE): - def fn(): - return str_storage_supported(TYPE) - return self.interpret(fn, []) + ## def str_storage_supported(self, TYPE): + ## def fn(): + ## return str_storage_supported(TYPE) + ## return self.interpret(fn, []) def str_storage_getitem(self, TYPE, buf, offset): def fn(offset): return str_storage_getitem(TYPE, buf, offset) return self.interpret(fn, [offset]) + + +class TestCompiled(BaseStrStorageTest): + cache = {} + + def str_storage_getitem(self, TYPE, buf, offset): + if TYPE not in self.cache: + from rpython.translator.c.test.test_genc import compile + + assert isinstance(TYPE, lltype.Primitive) + if TYPE in (lltype.Float, lltype.SingleFloat): + TARGET_TYPE = lltype.Float + else: + TARGET_TYPE = lltype.Signed + + def llf(buf, offset): + x = str_storage_getitem(TYPE, buf, offset) + return lltype.cast_primitive(TARGET_TYPE, x) + + fn = compile(llf, [str, int]) + self.cache[TYPE] = fn + # + fn = self.cache[TYPE] + x = fn(buf, offset) + return lltype.cast_primitive(TYPE, x) diff --git a/rpython/rtyper/lltypesystem/ll2ctypes.py b/rpython/rtyper/lltypesystem/ll2ctypes.py --- a/rpython/rtyper/lltypesystem/ll2ctypes.py +++ b/rpython/rtyper/lltypesystem/ll2ctypes.py @@ -902,6 +902,14 @@ llobj = ctypes.sizeof(get_ctypes_type(llobj.TYPE)) * llobj.repeat elif isinstance(llobj, ComputedIntSymbolic): llobj = llobj.compute_fn() + elif isinstance(llobj, llmemory.CompositeOffset): + llobj = sum([lltype2ctypes(c) for c in llobj.offsets]) + elif isinstance(llobj, llmemory.FieldOffset): + CSTRUCT = get_ctypes_type(llobj.TYPE) + llobj = getattr(CSTRUCT, llobj.fldname).offset + elif isinstance(llobj, llmemory.ArrayItemsOffset): + CARRAY = get_ctypes_type(llobj.TYPE) + llobj = CARRAY.items.offset else: raise NotImplementedError(llobj) # don't know about symbolic value 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 @@ -417,6 +417,7 @@ 'raw_load': LLOp(sideeffects=False, canrun=True), _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit