Author: Brian Kearns <bdkea...@gmail.com> Branch: Changeset: r67593:db7a73ea7e32 Date: 2013-10-24 22:59 -0400 http://bitbucket.org/pypy/pypy/changeset/db7a73ea7e32/
Log: merge diff --git a/lib_pypy/numpypy/lib/utils.py b/lib_pypy/numpypy/lib/utils.py --- a/lib_pypy/numpypy/lib/utils.py +++ b/lib_pypy/numpypy/lib/utils.py @@ -21,14 +21,4 @@ ... """ - try: - import numpy - except: - # running from pypy source directory - head, tail = os.path.split(os.path.dirname(os.path.abspath(__file__))) - return os.path.join(head, '../include') - else: - # using installed numpy core headers - import numpy.core as core - d = os.path.join(os.path.dirname(core.__file__), 'include') - return d + return os.path.join(os.path.dirname(__file__), '../../../include') diff --git a/pypy/interpreter/nestedscope.py b/pypy/interpreter/nestedscope.py --- a/pypy/interpreter/nestedscope.py +++ b/pypy/interpreter/nestedscope.py @@ -125,8 +125,7 @@ if len(cellvars) != ncellvars: raise OperationError(self.space.w_TypeError, self.space.wrap("bad cellvars")) - if self.cells is not None: - self.cells[:ncellvars] = cellvars + self.cells[:ncellvars] = cellvars @jit.dont_look_inside def fast2locals(self): @@ -165,8 +164,6 @@ @jit.unroll_safe def init_cells(self): - if self.cells is None: - return args_to_copy = self.pycode._args_as_cellvars for i in range(len(args_to_copy)): argnum = args_to_copy[i] diff --git a/pypy/module/_cffi_backend/cdataobj.py b/pypy/module/_cffi_backend/cdataobj.py --- a/pypy/module/_cffi_backend/cdataobj.py +++ b/pypy/module/_cffi_backend/cdataobj.py @@ -283,10 +283,18 @@ return self.ctype.iter(self) def unpackiterable_int(self, space): - return self.ctype.aslist_int(self) + from pypy.module._cffi_backend import ctypearray + ctype = self.ctype + if isinstance(ctype, ctypearray.W_CTypeArray): + return ctype.ctitem.unpack_list_of_int_items(self) + return None def unpackiterable_float(self, space): - return self.ctype.aslist_float(self) + from pypy.module._cffi_backend import ctypearray + ctype = self.ctype + if isinstance(ctype, ctypearray.W_CTypeArray): + return ctype.ctitem.unpack_list_of_float_items(self) + return None @specialize.argtype(1) def write_raw_signed_data(self, source): diff --git a/pypy/module/_cffi_backend/ctypearray.py b/pypy/module/_cffi_backend/ctypearray.py --- a/pypy/module/_cffi_backend/ctypearray.py +++ b/pypy/module/_cffi_backend/ctypearray.py @@ -105,26 +105,6 @@ def iter(self, cdata): return W_CDataIter(self.space, self.ctitem, cdata) - def aslist_int(self, cdata): - from rpython.rlib.rarray import populate_list_from_raw_array - if self.ctitem.is_long(): - res = [] - buf = rffi.cast(rffi.LONGP, cdata._cdata) - length = cdata.get_array_length() - populate_list_from_raw_array(res, buf, length) - return res - return None - - def aslist_float(self, cdata): - from rpython.rlib.rarray import populate_list_from_raw_array - if self.ctitem.is_double(): - res = [] - buf = rffi.cast(rffi.DOUBLEP, cdata._cdata) - length = cdata.get_array_length() - populate_list_from_raw_array(res, buf, length) - return res - return None - def get_vararg_type(self): return self.ctptr diff --git a/pypy/module/_cffi_backend/ctypeobj.py b/pypy/module/_cffi_backend/ctypeobj.py --- a/pypy/module/_cffi_backend/ctypeobj.py +++ b/pypy/module/_cffi_backend/ctypeobj.py @@ -43,10 +43,13 @@ def is_unichar_ptr_or_array(self): return False - def is_long(self): - return False + def unpack_list_of_int_items(self, cdata): + return None - def is_double(self): + def unpack_list_of_float_items(self, cdata): + return None + + def pack_list_of_items(self, cdata, w_ob): return False def newp(self, w_init): diff --git a/pypy/module/_cffi_backend/ctypeprim.py b/pypy/module/_cffi_backend/ctypeprim.py --- a/pypy/module/_cffi_backend/ctypeprim.py +++ b/pypy/module/_cffi_backend/ctypeprim.py @@ -2,6 +2,7 @@ Primitives. """ +import sys from pypy.interpreter.error import operationerrfmt from rpython.rlib.rarithmetic import r_uint, r_ulonglong, intmask @@ -169,9 +170,9 @@ sh = self.size * 8 self.vmin = r_uint(-1) << (sh - 1) self.vrangemax = (r_uint(1) << sh) - 1 - - def is_long(self): - return self.size == rffi.sizeof(lltype.Signed) + else: + self.vmin = r_uint(0) + self.vrangemax = r_uint(-1) def cast_to_int(self, cdata): return self.convert_to_object(cdata) @@ -204,6 +205,35 @@ def write_raw_integer_data(self, w_cdata, value): w_cdata.write_raw_signed_data(value) + def unpack_list_of_int_items(self, w_cdata): + if self.size == rffi.sizeof(rffi.LONG): + from rpython.rlib.rarray import populate_list_from_raw_array + res = [] + buf = rffi.cast(rffi.LONGP, w_cdata._cdata) + length = w_cdata.get_array_length() + populate_list_from_raw_array(res, buf, length) + return res + elif self.value_fits_long: + res = [0] * w_cdata.get_array_length() + misc.unpack_list_from_raw_array(res, w_cdata._cdata, self.size) + return res + return None + + def pack_list_of_items(self, cdata, w_ob): + int_list = self.space.listview_int(w_ob) + if int_list is not None: + if self.size == rffi.sizeof(rffi.LONG): # fastest path + from rpython.rlib.rarray import copy_list_to_raw_array + cdata = rffi.cast(rffi.LONGP, cdata) + copy_list_to_raw_array(int_list, cdata) + else: + overflowed = misc.pack_list_to_raw_array_bounds( + int_list, cdata, self.size, self.vmin, self.vrangemax) + if overflowed != 0: + self._overflow(self.space.wrap(overflowed)) + return True + return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob) + class W_CTypePrimitiveUnsigned(W_CTypePrimitive): _attrs_ = ['value_fits_long', 'value_fits_ulong', 'vrangemax'] @@ -216,6 +246,8 @@ self.value_fits_ulong = self.size <= rffi.sizeof(lltype.Unsigned) if self.value_fits_long: self.vrangemax = self._compute_vrange_max() + else: + self.vrangemax = r_uint(sys.maxint) def _compute_vrange_max(self): sh = self.size * 8 @@ -255,6 +287,24 @@ def write_raw_integer_data(self, w_cdata, value): w_cdata.write_raw_unsigned_data(value) + def unpack_list_of_int_items(self, w_cdata): + if self.value_fits_long: + res = [0] * w_cdata.get_array_length() + misc.unpack_unsigned_list_from_raw_array(res, w_cdata._cdata, + self.size) + return res + return None + + def pack_list_of_items(self, cdata, w_ob): + int_list = self.space.listview_int(w_ob) + if int_list is not None: + overflowed = misc.pack_list_to_raw_array_bounds( + int_list, cdata, self.size, r_uint(0), self.vrangemax) + if overflowed != 0: + self._overflow(self.space.wrap(overflowed)) + return True + return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob) + class W_CTypePrimitiveBool(W_CTypePrimitiveUnsigned): _attrs_ = [] @@ -276,9 +326,6 @@ class W_CTypePrimitiveFloat(W_CTypePrimitive): _attrs_ = [] - def is_double(self): - return self.size == rffi.sizeof(lltype.Float) - def cast(self, w_ob): space = self.space if isinstance(w_ob, cdataobj.W_CData): @@ -318,6 +365,34 @@ value = space.float_w(space.float(w_ob)) misc.write_raw_float_data(cdata, value, self.size) + def unpack_list_of_float_items(self, w_cdata): + if self.size == rffi.sizeof(rffi.DOUBLE): + from rpython.rlib.rarray import populate_list_from_raw_array + res = [] + buf = rffi.cast(rffi.DOUBLEP, w_cdata._cdata) + length = w_cdata.get_array_length() + populate_list_from_raw_array(res, buf, length) + return res + elif self.size == rffi.sizeof(rffi.FLOAT): + res = [0.0] * w_cdata.get_array_length() + misc.unpack_cfloat_list_from_raw_array(res, w_cdata._cdata) + return res + return None + + def pack_list_of_items(self, cdata, w_ob): + float_list = self.space.listview_float(w_ob) + if float_list is not None: + if self.size == rffi.sizeof(rffi.DOUBLE): # fastest path + from rpython.rlib.rarray import copy_list_to_raw_array + cdata = rffi.cast(rffi.DOUBLEP, cdata) + copy_list_to_raw_array(float_list, cdata) + return True + elif self.size == rffi.sizeof(rffi.FLOAT): + misc.pack_float_list_to_raw_array(float_list, cdata, + rffi.FLOAT, rffi.FLOATP) + return True + return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob) + class W_CTypePrimitiveLongDouble(W_CTypePrimitiveFloat): _attrs_ = [] @@ -328,7 +403,6 @@ return misc.longdouble2str(lvalue) def cast(self, w_ob): - space = self.space if (isinstance(w_ob, cdataobj.W_CData) and isinstance(w_ob.ctype, W_CTypePrimitiveLongDouble)): w_cdata = self.convert_to_object(w_ob._cdata) @@ -372,3 +446,15 @@ else: value = space.float_w(space.float(w_ob)) self._to_longdouble_and_write(value, cdata) + + # Cannot have unpack_list_of_float_items() here: + # 'list(array-of-longdouble)' returns a list of cdata objects, + # not a list of floats. + + def pack_list_of_items(self, cdata, w_ob): + float_list = self.space.listview_float(w_ob) + if float_list is not None: + misc.pack_float_list_to_raw_array(float_list, cdata, + rffi.LONGDOUBLE, rffi.LONGDOUBLEP) + return True + return W_CTypePrimitive.pack_list_of_items(self, cdata, w_ob) diff --git a/pypy/module/_cffi_backend/ctypeptr.py b/pypy/module/_cffi_backend/ctypeptr.py --- a/pypy/module/_cffi_backend/ctypeptr.py +++ b/pypy/module/_cffi_backend/ctypeptr.py @@ -42,12 +42,6 @@ def is_char_or_unichar_ptr_or_array(self): return isinstance(self.ctitem, ctypeprim.W_CTypePrimitiveCharOrUniChar) - def aslist_int(self, cdata): - return None - - def aslist_float(self, cdata): - return None - def cast(self, w_ob): # cast to a pointer, to a funcptr, or to an array. # Note that casting to an array is an extension to the C language, @@ -64,24 +58,10 @@ value = rffi.cast(rffi.CCHARP, value) return cdataobj.W_CData(space, value, self) - def _convert_array_from_list_strategy_maybe(self, cdata, w_ob): - from rpython.rlib.rarray import copy_list_to_raw_array - int_list = self.space.listview_int(w_ob) - float_list = self.space.listview_float(w_ob) + def _convert_array_from_listview(self, cdata, w_ob): + if self.ctitem.pack_list_of_items(cdata, w_ob): # fast path + return # - if self.ctitem.is_long() and int_list is not None: - cdata = rffi.cast(rffi.LONGP, cdata) - copy_list_to_raw_array(int_list, cdata) - return True - # - if self.ctitem.is_double() and float_list is not None: - cdata = rffi.cast(rffi.DOUBLEP, cdata) - copy_list_to_raw_array(float_list, cdata) - return True - # - return False - - def _convert_array_from_listview(self, cdata, w_ob): space = self.space lst_w = space.listview(w_ob) if self.length >= 0 and len(lst_w) > self.length: @@ -95,11 +75,6 @@ def convert_array_from_object(self, cdata, w_ob): space = self.space - if self._convert_array_from_list_strategy_maybe(cdata, w_ob): - # the fast path worked, we are done now - return - # - # continue with the slow path if (space.isinstance_w(w_ob, space.w_list) or space.isinstance_w(w_ob, space.w_tuple)): self._convert_array_from_listview(cdata, w_ob) diff --git a/pypy/module/_cffi_backend/misc.py b/pypy/module/_cffi_backend/misc.py --- a/pypy/module/_cffi_backend/misc.py +++ b/pypy/module/_cffi_backend/misc.py @@ -315,3 +315,47 @@ _raw_memclear_tp(TP, TPP, dest) return raise NotImplementedError("bad clear size") + +# ____________________________________________________________ + +def pack_list_to_raw_array_bounds(int_list, target, size, vmin, vrangemax): + for TP, TPP in _prim_signed_types: + if size == rffi.sizeof(TP): + ptr = rffi.cast(TPP, target) + for i in range(len(int_list)): + x = int_list[i] + if r_uint(x) - vmin > vrangemax: + return x # overflow + ptr[i] = rffi.cast(TP, x) + return 0 + raise NotImplementedError("bad integer size") + +@specialize.arg(2) +def pack_float_list_to_raw_array(float_list, target, TP, TPP): + target = rffi.cast(TPP, target) + for i in range(len(float_list)): + x = float_list[i] + target[i] = rffi.cast(TP, x) + +def unpack_list_from_raw_array(int_list, source, size): + for TP, TPP in _prim_signed_types: + if size == rffi.sizeof(TP): + ptr = rffi.cast(TPP, source) + for i in range(len(int_list)): + int_list[i] = rffi.cast(lltype.Signed, ptr[i]) + return + raise NotImplementedError("bad integer size") + +def unpack_unsigned_list_from_raw_array(int_list, source, size): + for TP, TPP in _prim_unsigned_types: + if size == rffi.sizeof(TP): + ptr = rffi.cast(TPP, source) + for i in range(len(int_list)): + int_list[i] = rffi.cast(lltype.Signed, ptr[i]) + return + raise NotImplementedError("bad integer size") + +def unpack_cfloat_list_from_raw_array(float_list, source): + ptr = rffi.cast(rffi.FLOATP, source) + for i in range(len(float_list)): + float_list[i] = rffi.cast(lltype.Float, ptr[i]) diff --git a/pypy/module/_cffi_backend/newtype.py b/pypy/module/_cffi_backend/newtype.py --- a/pypy/module/_cffi_backend/newtype.py +++ b/pypy/module/_cffi_backend/newtype.py @@ -117,13 +117,17 @@ SF_MSVC_BITFIELDS = 1 SF_GCC_ARM_BITFIELDS = 2 +SF_GCC_BIG_ENDIAN = 4 if sys.platform == 'win32': DEFAULT_SFLAGS = SF_MSVC_BITFIELDS -elif rffi_platform.getdefined('__arm__', ''): - DEFAULT_SFLAGS = SF_GCC_ARM_BITFIELDS else: - DEFAULT_SFLAGS = 0 + if rffi_platform.getdefined('__arm__', ''): + DEFAULT_SFLAGS = SF_GCC_ARM_BITFIELDS + else: + DEFAULT_SFLAGS = 0 + if sys.byteorder == 'big': + DEFAULT_SFLAGS |= SF_GCC_BIG_ENDIAN @unwrap_spec(name=str) def new_struct_type(space, name): @@ -325,6 +329,9 @@ prev_bitfield_free -= fbitsize field_offset_bytes = boffset / 8 - ftype.size + if sflags & SF_GCC_BIG_ENDIAN: + bitshift = 8 * ftype.size - fbitsize- bitshift + fld = ctypestruct.W_CField(ftype, field_offset_bytes, bitshift, fbitsize) fields_list.append(fld) diff --git a/pypy/module/_cffi_backend/test/_backend_test_c.py b/pypy/module/_cffi_backend/test/_backend_test_c.py --- a/pypy/module/_cffi_backend/test/_backend_test_c.py +++ b/pypy/module/_cffi_backend/test/_backend_test_c.py @@ -2949,8 +2949,6 @@ _test_bitfield_details(flag=2) def test_bitfield_as_big_endian(): - if '__pypy__' in sys.builtin_module_names: - py.test.skip("no big endian machine supported on pypy for now") _test_bitfield_details(flag=4) diff --git a/pypy/module/_cffi_backend/test/test_fastpath.py b/pypy/module/_cffi_backend/test/test_fastpath.py --- a/pypy/module/_cffi_backend/test/test_fastpath.py +++ b/pypy/module/_cffi_backend/test/test_fastpath.py @@ -1,18 +1,19 @@ -# side-effect: FORMAT_LONGDOUBLE must be built before test_checkmodule() +# side-effect: FORMAT_LONGDOUBLE must be built before the first test from pypy.module._cffi_backend import misc -from pypy.module._cffi_backend.ctypeptr import W_CTypePtrOrArray +from pypy.module._cffi_backend.ctypeobj import W_CType + class AppTest_fast_path_from_list(object): spaceconfig = dict(usemodules=('_cffi_backend', 'cStringIO')) def setup_method(self, meth): - def forbidden(self, *args): + def forbidden(*args): assert False, 'The slow path is forbidden' - self._original = W_CTypePtrOrArray._convert_array_from_listview.im_func - W_CTypePtrOrArray._convert_array_from_listview = forbidden + self._original = W_CType.pack_list_of_items.im_func + W_CType.pack_list_of_items = forbidden def teardown_method(self, meth): - W_CTypePtrOrArray._convert_array_from_listview = self._original + W_CType.pack_list_of_items = self._original def test_fast_init_from_list(self): import _cffi_backend @@ -34,6 +35,101 @@ assert buf[1] == 2.2 assert buf[2] == 3.3 + def test_fast_init_short_from_list(self): + import _cffi_backend + SHORT = _cffi_backend.new_primitive_type('short') + P_SHORT = _cffi_backend.new_pointer_type(SHORT) + SHORT_ARRAY = _cffi_backend.new_array_type(P_SHORT, None) + buf = _cffi_backend.newp(SHORT_ARRAY, [1, -2, 3]) + assert buf[0] == 1 + assert buf[1] == -2 + assert buf[2] == 3 + raises(OverflowError, _cffi_backend.newp, SHORT_ARRAY, [40000]) + raises(OverflowError, _cffi_backend.newp, SHORT_ARRAY, [-40000]) + + def test_fast_init_longlong_from_list(self): + if type(2 ** 50) is long: + large_int = 2 ** 30 + else: + large_int = 2 ** 50 + import _cffi_backend + LONGLONG = _cffi_backend.new_primitive_type('long long') + P_LONGLONG = _cffi_backend.new_pointer_type(LONGLONG) + LONGLONG_ARRAY = _cffi_backend.new_array_type(P_LONGLONG, None) + buf = _cffi_backend.newp(LONGLONG_ARRAY, [1, -2, 3, large_int]) + assert buf[0] == 1 + assert buf[1] == -2 + assert buf[2] == 3 + assert buf[3] == large_int + + def test_fast_init_ushort_from_list(self): + import _cffi_backend + USHORT = _cffi_backend.new_primitive_type('unsigned short') + P_USHORT = _cffi_backend.new_pointer_type(USHORT) + USHORT_ARRAY = _cffi_backend.new_array_type(P_USHORT, None) + buf = _cffi_backend.newp(USHORT_ARRAY, [1, 2, 40000]) + assert buf[0] == 1 + assert buf[1] == 2 + assert buf[2] == 40000 + raises(OverflowError, _cffi_backend.newp, USHORT_ARRAY, [70000]) + raises(OverflowError, _cffi_backend.newp, USHORT_ARRAY, [-1]) + + def test_fast_init_ulong_from_list(self): + import sys + import _cffi_backend + ULONG = _cffi_backend.new_primitive_type('unsigned long') + P_ULONG = _cffi_backend.new_pointer_type(ULONG) + ULONG_ARRAY = _cffi_backend.new_array_type(P_ULONG, None) + buf = _cffi_backend.newp(ULONG_ARRAY, [1, 2, sys.maxint]) + assert buf[0] == 1 + assert buf[1] == 2 + assert buf[2] == sys.maxint + raises(OverflowError, _cffi_backend.newp, ULONG_ARRAY, [-1]) + raises(OverflowError, _cffi_backend.newp, ULONG_ARRAY, [-sys.maxint]) + + def test_fast_init_cfloat_from_list(self): + import _cffi_backend + FLOAT = _cffi_backend.new_primitive_type('float') + P_FLOAT = _cffi_backend.new_pointer_type(FLOAT) + FLOAT_ARRAY = _cffi_backend.new_array_type(P_FLOAT, None) + buf = _cffi_backend.newp(FLOAT_ARRAY, [1.25, -3.5]) + assert buf[0] == 1.25 + assert buf[1] == -3.5 + + def test_fast_init_clongdouble_from_list(self): + import _cffi_backend + LONGDOUBLE = _cffi_backend.new_primitive_type('long double') + P_LONGDOUBLE = _cffi_backend.new_pointer_type(LONGDOUBLE) + LONGDOUBLE_ARRAY = _cffi_backend.new_array_type(P_LONGDOUBLE, None) + buf = _cffi_backend.newp(LONGDOUBLE_ARRAY, [1.25, -3.5]) + assert float(buf[0]) == 1.25 + assert float(buf[1]) == -3.5 + + def test_fast_init_bool_from_list(self): + import _cffi_backend + BOOL = _cffi_backend.new_primitive_type('_Bool') + P_BOOL = _cffi_backend.new_pointer_type(BOOL) + BOOL_ARRAY = _cffi_backend.new_array_type(P_BOOL, None) + buf = _cffi_backend.newp(BOOL_ARRAY, [1, 0]) + assert buf[0] == 1 + assert buf[1] == 0 + assert type(buf[1]) is int + raises(OverflowError, _cffi_backend.newp, BOOL_ARRAY, [2]) + raises(OverflowError, _cffi_backend.newp, BOOL_ARRAY, [-1]) + + +class AppTest_fast_path_bug(object): + spaceconfig = dict(usemodules=('_cffi_backend', 'cStringIO')) + + def test_bug_not_list_or_tuple(self): + import _cffi_backend + LONG = _cffi_backend.new_primitive_type('long') + P_LONG = _cffi_backend.new_pointer_type(LONG) + LONG_ARRAY_2 = _cffi_backend.new_array_type(P_LONG, 2) + P_LONG_ARRAY_2 = _cffi_backend.new_pointer_type(LONG_ARRAY_2) + LONG_ARRAY_ARRAY = _cffi_backend.new_array_type(P_LONG_ARRAY_2, None) + raises(TypeError, _cffi_backend.newp, LONG_ARRAY_ARRAY, [set([4, 5])]) + class AppTest_fast_path_to_list(object): spaceconfig = dict(usemodules=('_cffi_backend', 'cStringIO')) @@ -54,12 +150,38 @@ self._original = original rarray.populate_list_from_raw_array = populate_list_from_raw_array # + original2 = misc.unpack_list_from_raw_array + def unpack_list_from_raw_array(*args): + self.count += 1 + return original2(*args) + self._original2 = original2 + misc.unpack_list_from_raw_array = unpack_list_from_raw_array + # + original3 = misc.unpack_cfloat_list_from_raw_array + def unpack_cfloat_list_from_raw_array(*args): + self.count += 1 + return original3(*args) + self._original3 = original3 + misc.unpack_cfloat_list_from_raw_array = ( + unpack_cfloat_list_from_raw_array) + # + original4 = misc.unpack_unsigned_list_from_raw_array + def unpack_unsigned_list_from_raw_array(*args): + self.count += 1 + return original4(*args) + self._original4 = original4 + misc.unpack_unsigned_list_from_raw_array = ( + unpack_unsigned_list_from_raw_array) + # self.w_runappdirect = self.space.wrap(self.runappdirect) def teardown_method(self, meth): from rpython.rlib import rarray rarray.populate_list_from_raw_array = self._original + misc.unpack_list_from_raw_array = self._original2 + misc.unpack_cfloat_list_from_raw_array = self._original3 + misc.unpack_unsigned_list_from_raw_array = self._original4 def test_list_int(self): import _cffi_backend @@ -84,6 +206,14 @@ pbuf = _cffi_backend.cast(P_LONG, buf) raises(TypeError, "list(pbuf)") + def test_bug(self): + import _cffi_backend + LONG = _cffi_backend.new_primitive_type('long') + five = _cffi_backend.cast(LONG, 5) + raises(TypeError, list, five) + DOUBLE = _cffi_backend.new_primitive_type('double') + five_and_a_half = _cffi_backend.cast(DOUBLE, 5.5) + raises(TypeError, list, five_and_a_half) def test_list_float(self): import _cffi_backend @@ -98,3 +228,45 @@ assert lst == [1.1, 2.2, 3.3] if not self.runappdirect: assert self.get_count() == 1 + + def test_list_short(self): + import _cffi_backend + SHORT = _cffi_backend.new_primitive_type('short') + P_SHORT = _cffi_backend.new_pointer_type(SHORT) + SHORT_ARRAY = _cffi_backend.new_array_type(P_SHORT, 3) + buf = _cffi_backend.newp(SHORT_ARRAY) + buf[0] = 1 + buf[1] = 2 + buf[2] = 3 + lst = list(buf) + assert lst == [1, 2, 3] + if not self.runappdirect: + assert self.get_count() == 1 + + def test_list_ushort(self): + import _cffi_backend + USHORT = _cffi_backend.new_primitive_type('unsigned short') + P_USHORT = _cffi_backend.new_pointer_type(USHORT) + USHORT_ARRAY = _cffi_backend.new_array_type(P_USHORT, 3) + buf = _cffi_backend.newp(USHORT_ARRAY) + buf[0] = 1 + buf[1] = 2 + buf[2] = 50505 + lst = list(buf) + assert lst == [1, 2, 50505] + if not self.runappdirect: + assert self.get_count() == 1 + + def test_list_cfloat(self): + import _cffi_backend + FLOAT = _cffi_backend.new_primitive_type('float') + P_FLOAT = _cffi_backend.new_pointer_type(FLOAT) + FLOAT_ARRAY = _cffi_backend.new_array_type(P_FLOAT, 3) + buf = _cffi_backend.newp(FLOAT_ARRAY) + buf[0] = 1.25 + buf[1] = -2.5 + buf[2] = 3.75 + lst = list(buf) + assert lst == [1.25, -2.5, 3.75] + if not self.runappdirect: + assert self.get_count() == 1 diff --git a/pypy/module/micronumpy/interp_dtype.py b/pypy/module/micronumpy/interp_dtype.py --- a/pypy/module/micronumpy/interp_dtype.py +++ b/pypy/module/micronumpy/interp_dtype.py @@ -84,6 +84,7 @@ def build_and_convert(self, space, box): return self.itemtype.build_and_convert(space, self, box) + def coerce(self, space, w_item): return self.itemtype.coerce(space, self, w_item) diff --git a/pypy/module/rctime/test/test_rctime.py b/pypy/module/rctime/test/test_rctime.py --- a/pypy/module/rctime/test/test_rctime.py +++ b/pypy/module/rctime/test/test_rctime.py @@ -140,7 +140,7 @@ ltime = rctime.localtime() assert rctime.asctime(tuple(ltime)) == rctime.asctime(ltime) try: - assert rctime.asctime((12345,) + (0,) * 8).split()[-1] == '12345' + rctime.asctime((12345,) + (0,) * 8) # assert this doesn't crash except ValueError: pass # some OS (ie POSIXes besides Linux) reject year > 9999 diff --git a/rpython/jit/codewriter/call.py b/rpython/jit/codewriter/call.py --- a/rpython/jit/codewriter/call.py +++ b/rpython/jit/codewriter/call.py @@ -11,6 +11,7 @@ from rpython.rtyper.lltypesystem import lltype, llmemory from rpython.translator.backendopt.canraise import RaiseAnalyzer from rpython.translator.backendopt.writeanalyze import ReadWriteAnalyzer +from rpython.translator.backendopt.graphanalyze import DependencyTracker class CallControl(object): @@ -32,6 +33,9 @@ self.virtualizable_analyzer = VirtualizableAnalyzer(translator) self.quasiimmut_analyzer = QuasiImmutAnalyzer(translator) self.randomeffects_analyzer = RandomEffectsAnalyzer(translator) + self.seen = DependencyTracker(self.readwrite_analyzer) + else: + self.seen = None # for index, jd in enumerate(jitdrivers_sd): jd.index = index @@ -231,8 +235,8 @@ extraeffect = EffectInfo.EF_CANNOT_RAISE # effectinfo = effectinfo_from_writeanalyze( - self.readwrite_analyzer.analyze(op), self.cpu, extraeffect, - oopspecindex, can_invalidate, call_release_gil_target, + self.readwrite_analyzer.analyze(op, self.seen), self.cpu, + extraeffect, oopspecindex, can_invalidate, call_release_gil_target, ) # assert effectinfo is not None 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 @@ -93,6 +93,8 @@ block.exitswitch = renamings.get(block.exitswitch, block.exitswitch) self.follow_constant_exit(block) self.optimize_goto_if_not(block) + if isinstance(block.exitswitch, tuple): + self._check_no_vable_array(block.exitswitch) for link in block.exits: self._check_no_vable_array(link.args) self._do_renaming_on_link(renamings, link) diff --git a/rpython/jit/codewriter/test/test_flatten.py b/rpython/jit/codewriter/test/test_flatten.py --- a/rpython/jit/codewriter/test/test_flatten.py +++ b/rpython/jit/codewriter/test/test_flatten.py @@ -84,6 +84,8 @@ def calldescr_canraise(self, calldescr): return calldescr is not self._descr_cannot_raise and calldescr.oopspecindex == EffectInfo.OS_NONE def get_vinfo(self, VTYPEPTR): + if hasattr(VTYPEPTR.TO, 'inst_vlist'): + return FakeVInfo() return None class FakeCallControlWithVRefInfo: @@ -100,6 +102,13 @@ def calldescr_canraise(self, calldescr): return False +class FakeVInfo: + static_field_to_extra_box = {} + array_fields = {'inst_vlist': '?'} + array_field_counter = {'inst_vlist': 0} + array_field_descrs = [FakeDescr()] + array_descrs = [FakeDescr()] + # ____________________________________________________________ def test_reorder_renaming_list(): @@ -1001,6 +1010,22 @@ float_return %(result_var)s """ % {"result_var": result_var, "tmp_var": tmp_var}, transform=True) + def test_vable_attribute_list_is_not_None(self): + class F: + _virtualizable_ = ['vlist[*]'] + vlist = None + def __init__(self, x): + self.vlist = [x] + def g(): + return F(42) + def f(): + f = g() + if f.vlist is not None: + pass + e = py.test.raises(AssertionError, self.encoding_test, f, [], "!", + transform=True) + assert str(e.value).startswith("A virtualizable array is passed aroun") + def check_force_cast(FROM, TO, operations, value): """Check that the test is correctly written...""" diff --git a/rpython/jit/metainterp/heapcache.py b/rpython/jit/metainterp/heapcache.py --- a/rpython/jit/metainterp/heapcache.py +++ b/rpython/jit/metainterp/heapcache.py @@ -82,6 +82,7 @@ # GETFIELD_GC, MARK_OPAQUE_PTR, PTR_EQ, and PTR_NE don't escape their # arguments elif (opnum != rop.GETFIELD_GC and + opnum != rop.GETFIELD_GC_PURE and opnum != rop.MARK_OPAQUE_PTR and opnum != rop.PTR_EQ and opnum != rop.PTR_NE and 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 @@ -1398,7 +1398,7 @@ assembler_call_jd) if resbox is not None: self.make_result_of_lastop(resbox) - self.metainterp.vable_after_residual_call() + self.metainterp.vable_after_residual_call(funcbox) self.metainterp.generate_guard(rop.GUARD_NOT_FORCED, None) if vablebox is not None: self.metainterp.history.record(rop.KEEPALIVE, [vablebox], None) @@ -2437,7 +2437,7 @@ # it by ConstPtr(NULL). self.stop_tracking_virtualref(i) - def vable_after_residual_call(self): + def vable_after_residual_call(self, funcbox): vinfo = self.jitdriver_sd.virtualizable_info if vinfo is not None: virtualizable_box = self.virtualizable_boxes[-1] @@ -2445,6 +2445,14 @@ if vinfo.tracing_after_residual_call(virtualizable): # the virtualizable escaped during CALL_MAY_FORCE. self.load_fields_from_virtualizable() + target_name = self.staticdata.get_name_from_address(funcbox.getaddr()) + if target_name: + target_name = "ConstClass(%s)" % target_name + else: + target_name = str(funcbox.getaddr()) + debug_print('vable escaped during a call in %s to %s' % ( + self.framestack[-1].jitcode.name, target_name + )) raise SwitchToBlackhole(Counters.ABORT_ESCAPE, raising_exception=True) # ^^^ we set 'raising_exception' to True because we must still diff --git a/rpython/jit/metainterp/test/test_ajit.py b/rpython/jit/metainterp/test/test_ajit.py --- a/rpython/jit/metainterp/test/test_ajit.py +++ b/rpython/jit/metainterp/test/test_ajit.py @@ -3360,21 +3360,28 @@ self.check_resops(call=0, getfield_gc=0) def test_isvirtual_call_assembler(self): - driver = JitDriver(greens = ['code'], reds = ['n']) + driver = JitDriver(greens = ['code'], reds = ['n', 's']) @look_inside_iff(lambda t1, t2: isvirtual(t1)) def g(t1, t2): return t1[0] == t2[0] + def create(n): + return (1, 2, n) + create._dont_inline_ = True + def f(code, n): + s = 0 while n > 0: - driver.can_enter_jit(code=code, n=n) - driver.jit_merge_point(code=code, n=n) - t = (1, 2, n) + driver.can_enter_jit(code=code, n=n, s=s) + driver.jit_merge_point(code=code, n=n, s=s) + t = create(n) if code: f(0, 3) + s += t[2] g(t, (1, 2, n)) n -= 1 + return s self.meta_interp(f, [1, 10], inline=True) self.check_resops(call=0, call_may_force=0, call_assembler=2) diff --git a/rpython/rlib/rstack.py b/rpython/rlib/rstack.py --- a/rpython/rlib/rstack.py +++ b/rpython/rlib/rstack.py @@ -67,6 +67,7 @@ # Else call the slow path stack_check_slowpath(current) stack_check._always_inline_ = True +stack_check._dont_insert_stackcheck_ = True @rgc.no_collect def stack_check_slowpath(current): @@ -74,3 +75,4 @@ from rpython.rlib.rstackovf import _StackOverflow raise _StackOverflow stack_check_slowpath._dont_inline_ = True +stack_check_slowpath._dont_insert_stackcheck_ = True diff --git a/rpython/rtyper/test/test_rdict.py b/rpython/rtyper/test/test_rdict.py --- a/rpython/rtyper/test/test_rdict.py +++ b/rpython/rtyper/test/test_rdict.py @@ -1078,6 +1078,13 @@ res = self.interpret(func, [42]) assert res == 42 + def test_dict_with_empty_tuple_key(self): + def func(i): + d = {(): i} + return d[()] + res = self.interpret(func, [42]) + assert res == 42 + class TestStress: diff --git a/rpython/translator/backendopt/writeanalyze.py b/rpython/translator/backendopt/writeanalyze.py --- a/rpython/translator/backendopt/writeanalyze.py +++ b/rpython/translator/backendopt/writeanalyze.py @@ -4,6 +4,7 @@ top_set = object() empty_set = frozenset() +CUTOFF = 1000 class WriteAnalyzer(graphanalyze.GraphAnalyzer): def bottom_result(self): @@ -21,6 +22,8 @@ def add_to_result(self, result, other): if other is top_set: return top_set + if len(other) + len(result) > CUTOFF: + return top_set result.update(other) return result diff --git a/rpython/translator/transform.py b/rpython/translator/transform.py --- a/rpython/translator/transform.py +++ b/rpython/translator/transform.py @@ -213,6 +213,10 @@ insert_in = set() block2graph = {} for caller in translator.graphs: + pyobj = getattr(caller, 'func', None) + if pyobj is not None: + if getattr(pyobj, '_dont_insert_stackcheck_', False): + continue for block, callee in find_calls_from(translator, caller): if getattr(getattr(callee, 'func', None), 'insert_stack_check_here', False): @@ -269,4 +273,4 @@ transform_dead_op_vars(ann, block_subset) if ann.translator: checkgraphs(ann, block_subset) - + _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit