Author: Maciej Fijalkowski <fij...@gmail.com> Branch: Changeset: r67352:6f41123c181b Date: 2013-10-14 12:56 +0200 http://bitbucket.org/pypy/pypy/changeset/6f41123c181b/
Log: merge diff --git a/pypy/module/cpyext/include/numpy/arrayobject.h b/pypy/module/cpyext/include/numpy/arrayobject.h --- a/pypy/module/cpyext/include/numpy/arrayobject.h +++ b/pypy/module/cpyext/include/numpy/arrayobject.h @@ -1,5 +1,8 @@ -/* NDArray object interface - S. H. Muller, 2013/07/26 */ +/* NDArray object interface - S. H. Muller, 2013/07/26 + * It will be copied by numpy/core/setup.py by install_data to + * site-packages/numpy/core/includes/numpy +*/ #ifndef Py_NDARRAYOBJECT_H #define Py_NDARRAYOBJECT_H @@ -9,7 +12,6 @@ #include "old_defines.h" -#define NPY_INLINE #define NPY_UNUSED(x) x #define PyArray_MAX(a,b) (((a)>(b))?(a):(b)) #define PyArray_MIN(a,b) (((a)<(b))?(a):(b)) @@ -22,11 +24,12 @@ typedef unsigned char npy_bool; typedef unsigned char npy_uint8; +typedef unsigned short npy_uint16; +typedef signed short npy_int16; +typedef signed char npy_int8; typedef int npy_int; -#ifndef npy_intp -#define npy_intp long -#endif +typedef long npy_intp; #ifndef NPY_INTP_FMT #define NPY_INTP_FMT "ld" #endif diff --git a/pypy/module/cpyext/include/numpy/npy_3kcompat.h b/pypy/module/cpyext/include/numpy/npy_3kcompat.h --- a/pypy/module/cpyext/include/numpy/npy_3kcompat.h +++ b/pypy/module/cpyext/include/numpy/npy_3kcompat.h @@ -0,0 +1,41 @@ +/* + * In numpy this is a convenience header file providing compatibility utilities + * for supporting Python 2 and Python 3 in the same code base. + * + * PyPy uses it as a convenient place to add compatability declarations + * It will be copied by numpy/core/setup.py by install_data to + * site-packages/numpy/core/includes/numpy +*/ + +#ifndef _NPY_3KCOMPAT_H_ +#define _NPY_3KCOMPAT_H_ + +#include <numpy/npy_common.h> + +#define npy_PyFile_Dup(file, mode) (NULL) +#define npy_PyFile_DupClose(file, handle) (0) + +static NPY_INLINE PyObject* +npy_PyFile_OpenFile(PyObject *filename, const char *mode) +{ + PyObject *open; + open = PyDict_GetItemString(PyEval_GetBuiltins(), "open"); + if (open == NULL) { + return NULL; + } + return PyObject_CallFunction(open, "Os", filename, mode); +} + +static NPY_INLINE int +npy_PyFile_CloseFile(PyObject *file) +{ + PyObject *ret; + + ret = PyObject_CallMethod(file, "close", NULL); + if (ret == NULL) { + return -1; + } + Py_DECREF(ret); + return 0; +} +#endif diff --git a/pypy/module/cpyext/ndarrayobject.py b/pypy/module/cpyext/ndarrayobject.py --- a/pypy/module/cpyext/ndarrayobject.py +++ b/pypy/module/cpyext/ndarrayobject.py @@ -171,6 +171,15 @@ w_array.implementation.shape = [] return w_array +@cpython_api([Py_ssize_t], PyObject) +def _PyArray_DescrFromType(space, typenum): + try: + dtype = get_dtype_cache(space).dtypes_by_num[typenum] + return dtype + except KeyError: + raise OperationError(space.w_ValueError, space.wrap( + '_PyArray_DescrFromType called with invalid dtype %d' % typenum)) + @cpython_api([PyObject, Py_ssize_t, Py_ssize_t, Py_ssize_t], PyObject) def _PyArray_FromObject(space, w_obj, typenum, min_depth, max_depth): try: diff --git a/pypy/module/cpyext/test/test_ndarrayobject.py b/pypy/module/cpyext/test/test_ndarrayobject.py --- a/pypy/module/cpyext/test/test_ndarrayobject.py +++ b/pypy/module/cpyext/test/test_ndarrayobject.py @@ -265,6 +265,12 @@ return obj2; ''' ), + ("test_DescrFromType", "METH_O", + """ + Signed typenum = PyInt_AsLong(args); + return _PyArray_DescrFromType(typenum); + """ + ), ], prologue='#include <numpy/arrayobject.h>') arr = mod.test_simplenew() assert arr.shape == (2, 3) @@ -278,3 +284,5 @@ #Make sure these work without errors arr = mod.test_FromAny() arr = mod.test_FromObject() + dt = mod.test_DescrFromType(11) + assert dt.num == 11 diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py --- a/pypy/module/micronumpy/interp_numarray.py +++ b/pypy/module/micronumpy/interp_numarray.py @@ -954,6 +954,13 @@ def descr___array_finalize__(self, space, w_obj): pass + def descr___array_wrap__(self, space, w_obj, w_context=None): + return w_obj + + def descr___array_prepare__(self, space, w_obj, w_context=None): + return w_obj + pass + @unwrap_spec(offset=int, order=str) def descr_new_array(space, w_subtype, w_shape, w_dtype=None, w_buffer=None, offset=0, w_strides=None, order='C'): @@ -1144,7 +1151,8 @@ __reduce__ = interp2app(W_NDimArray.descr_reduce), __setstate__ = interp2app(W_NDimArray.descr_setstate), __array_finalize__ = interp2app(W_NDimArray.descr___array_finalize__), - + __array_prepare__ = interp2app(W_NDimArray.descr___array_prepare__), + __array_wrap__ = interp2app(W_NDimArray.descr___array_wrap__), __array__ = interp2app(W_NDimArray.descr___array__), ) diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py --- a/pypy/module/micronumpy/interp_ufuncs.py +++ b/pypy/module/micronumpy/interp_ufuncs.py @@ -342,6 +342,9 @@ if w_ldtype.is_str_type() and w_rdtype.is_str_type() and \ self.comparison_func: pass + elif (w_ldtype.is_str_type() or w_rdtype.is_str_type()) and \ + self.comparison_func and w_out is None: + return space.wrap(False) elif (w_ldtype.is_flexible_type() or \ w_rdtype.is_flexible_type()): raise OperationError(space.w_TypeError, space.wrap( diff --git a/pypy/module/micronumpy/test/test_ufuncs.py b/pypy/module/micronumpy/test/test_ufuncs.py --- a/pypy/module/micronumpy/test/test_ufuncs.py +++ b/pypy/module/micronumpy/test/test_ufuncs.py @@ -712,7 +712,8 @@ def test_comparisons(self): import operator - from numpypy import equal, not_equal, less, less_equal, greater, greater_equal + from numpypy import (equal, not_equal, less, less_equal, greater, + greater_equal, arange) for ufunc, func in [ (equal, operator.eq), @@ -735,7 +736,9 @@ (3, 3.5), ]: assert ufunc(a, b) == func(a, b) - + c = arange(10) + val = c == 'abcdefg' + assert val == False def test_count_nonzero(self): from numpypy import count_nonzero diff --git a/pypy/module/mmap/interp_mmap.py b/pypy/module/mmap/interp_mmap.py --- a/pypy/module/mmap/interp_mmap.py +++ b/pypy/module/mmap/interp_mmap.py @@ -290,9 +290,6 @@ self.space = space self.mmap = mmap - def get_raw_address(self): - return self.mmap.data - def getlength(self): return self.mmap.size 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 @@ -51,10 +51,10 @@ return self.output_indirections.get(box, box) def invalidate_caches(self, opnum, descr, argboxes): - self.mark_escaped(opnum, argboxes) + self.mark_escaped(opnum, descr, argboxes) self.clear_caches(opnum, descr, argboxes) - def mark_escaped(self, opnum, argboxes): + def mark_escaped(self, opnum, descr, argboxes): if opnum == rop.SETFIELD_GC: assert len(argboxes) == 2 box, valuebox = argboxes @@ -69,6 +69,15 @@ self.dependencies.setdefault(box, []).append(valuebox) else: self._escape(valuebox) + elif (opnum == rop.CALL and + descr.get_extra_info().oopspecindex == descr.get_extra_info().OS_ARRAYCOPY and + isinstance(argboxes[3], ConstInt) and + isinstance(argboxes[4], ConstInt) and + isinstance(argboxes[5], ConstInt) and + len(descr.get_extra_info().write_descrs_arrays) == 1): + # ARRAYCOPY with constant starts and constant length doesn't escape + # its argument + pass # GETFIELD_GC, MARK_OPAQUE_PTR, PTR_EQ, and PTR_NE don't escape their # arguments elif (opnum != rop.GETFIELD_GC and @@ -118,16 +127,50 @@ # A special case for ll_arraycopy, because it is so common, and its # effects are so well defined. elif effectinfo.oopspecindex == effectinfo.OS_ARRAYCOPY: - # The destination box if ( + isinstance(argboxes[3], ConstInt) and + isinstance(argboxes[4], ConstInt) and + isinstance(argboxes[5], ConstInt) and + len(effectinfo.write_descrs_arrays) == 1 + ): + descr = effectinfo.write_descrs_arrays[0] + cache = self.heap_array_cache.get(descr, None) + srcstart = argboxes[3].getint() + dststart = argboxes[4].getint() + length = argboxes[5].getint() + for i in xrange(length): + value = self.getarrayitem( + argboxes[1], + ConstInt(srcstart + i), + descr, + ) + if value is not None: + self.setarrayitem( + argboxes[2], + ConstInt(dststart + i), + value, + descr, + ) + elif cache is not None: + if argboxes[2] in self.new_boxes: + try: + idx_cache = cache[dststart + i] + except KeyError: + pass + else: + for frombox in idx_cache.keys(): + if not self.is_unescaped(frombox): + del idx_cache[frombox] + else: + cache[dststart + i].clear() + return + elif ( argboxes[2] in self.new_boxes and len(effectinfo.write_descrs_arrays) == 1 ): # Fish the descr out of the effectinfo cache = self.heap_array_cache.get(effectinfo.write_descrs_arrays[0], None) if cache is not None: - # XXX: in theory the indices of the copy could be - # looked at for idx, cache in cache.iteritems(): for frombox in cache.keys(): if not self.is_unescaped(frombox): @@ -210,9 +253,9 @@ return new_d def getarrayitem(self, box, indexbox, descr): - box = self._input_indirection(box) if not isinstance(indexbox, ConstInt): return + box = self._input_indirection(box) index = indexbox.getint() cache = self.heap_array_cache.get(descr, None) if cache: @@ -221,10 +264,10 @@ return self._output_indirection(indexcache.get(box, None)) def getarrayitem_now_known(self, box, indexbox, valuebox, descr): + if not isinstance(indexbox, ConstInt): + return box = self._input_indirection(box) valuebox = self._input_indirection(valuebox) - if not isinstance(indexbox, ConstInt): - return index = indexbox.getint() cache = self.heap_array_cache.setdefault(descr, {}) indexcache = cache.get(index, None) diff --git a/rpython/jit/metainterp/test/test_heapcache.py b/rpython/jit/metainterp/test/test_heapcache.py --- a/rpython/jit/metainterp/test/test_heapcache.py +++ b/rpython/jit/metainterp/test/test_heapcache.py @@ -1,6 +1,6 @@ from rpython.jit.metainterp.heapcache import HeapCache from rpython.jit.metainterp.resoperation import rop -from rpython.jit.metainterp.history import ConstInt +from rpython.jit.metainterp.history import ConstInt, BoxInt box1 = "box1" box2 = "box2" @@ -73,7 +73,6 @@ assert not h.is_nonstandard_virtualizable(1) assert not h.is_nonstandard_virtualizable(2) - def test_heapcache_fields(self): h = HeapCache() assert h.getfield(box1, descr1) is None @@ -278,7 +277,6 @@ assert h.getarrayitem(box1, index1, descr1) is None assert h.getarrayitem(box1, index2, descr1) is None - def test_replace_box(self): h = HeapCache() h.setfield(box1, box2, descr1) @@ -372,22 +370,22 @@ h.invalidate_caches( rop.CALL, FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr1]), - [None, None, box2, None, None] + [None, box5, box2, index1, index1, index1] ) assert h.getarrayitem(box1, index1, descr1) is box2 h.invalidate_caches( rop.CALL, FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr1]), - [None, None, box3, None, None] + [None, box5, box3, index1, index1, index1] ) - assert h.getarrayitem(box1, index1, descr1) is None + assert h.getarrayitem(box1, index1, descr1) is box2 h.setarrayitem(box4, index1, box2, descr1) assert h.getarrayitem(box4, index1, descr1) is box2 h.invalidate_caches( rop.CALL, FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr1]), - [None, None, box2, None, None] + [None, box3, box5, index1, index1, index2] ) assert h.getarrayitem(box4, index1, descr1) is None @@ -399,10 +397,48 @@ h.invalidate_caches( rop.CALL, FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr2]), - [None, None, box2, None, None] + [None, box3, box2, index1, index1, index2] ) assert h.getarrayitem(box1, index1, descr1) is box2 + def test_ll_arraycopy_result_propogated(self): + h = HeapCache() + h.setarrayitem(box1, index1, box2, descr1) + h.invalidate_caches( + rop.CALL, + FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr1]), + [None, box1, box3, index1, index1, index2] + ) + assert h.getarrayitem(box3, index1, descr1) is box2 + + def test_ll_arraycopy_dest_new(self): + h = HeapCache() + h.new_array(box1, lengthbox1) + h.setarrayitem(box3, index1, box4, descr1) + h.invalidate_caches( + rop.CALL, + FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr1]), + [None, box2, box1, index1, index1, index2] + ) + + def test_ll_arraycopy_doesnt_escape_arrays(self): + h = HeapCache() + h.new_array(box1, lengthbox1) + h.new_array(box2, lengthbox2) + h.invalidate_caches( + rop.CALL, + FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr1]), + [None, box2, box1, index1, index1, index2] + ) + assert h.is_unescaped(box1) + assert h.is_unescaped(box2) + h.invalidate_caches( + rop.CALL, + FakeCallDescr(FakeEffectinfo.EF_CANNOT_RAISE, FakeEffectinfo.OS_ARRAYCOPY, write_descrs_arrays=[descr1]), + [None, box2, box1, index1, index1, BoxInt()] + ) + assert not h.is_unescaped(box1) + assert not h.is_unescaped(box2) def test_unescaped(self): h = HeapCache() diff --git a/rpython/rtyper/lltypesystem/rdict.py b/rpython/rtyper/lltypesystem/rdict.py --- a/rpython/rtyper/lltypesystem/rdict.py +++ b/rpython/rtyper/lltypesystem/rdict.py @@ -162,6 +162,9 @@ fasthashfn = None else: fasthashfn = self.key_repr.get_ll_fasthash_function() + if getattr(self.key_repr.get_ll_eq_function(), + 'no_direct_compare', False): + entrymeths['no_direct_compare'] = True if fasthashfn is None: entryfields.append(("f_hash", lltype.Signed)) entrymeths['hash'] = ll_hash_from_cache diff --git a/rpython/rtyper/lltypesystem/rstr.py b/rpython/rtyper/lltypesystem/rstr.py --- a/rpython/rtyper/lltypesystem/rstr.py +++ b/rpython/rtyper/lltypesystem/rstr.py @@ -577,9 +577,7 @@ return -1 m = len(s2.chars) - if m == 0: - return start - elif m == 1: + if m == 1: return cls.ll_find_char(s1, s2.chars[0], start, end) return cls.ll_search(s1, s2, start, end, FAST_FIND) @@ -594,9 +592,7 @@ return -1 m = len(s2.chars) - if m == 0: - return end - elif m == 1: + if m == 1: return cls.ll_rfind_char(s1, s2.chars[0], start, end) return cls.ll_search(s1, s2, start, end, FAST_RFIND) @@ -611,9 +607,7 @@ return 0 m = len(s2.chars) - if m == 0: - return end - start + 1 - elif m == 1: + if m == 1: return cls.ll_count_char(s1, s2.chars[0], start, end) res = cls.ll_search(s1, s2, start, end, FAST_COUNT) @@ -629,6 +623,14 @@ n = end - start m = len(s2.chars) + if m == 0: + if mode == FAST_COUNT: + return end - start + 1 + elif mode == FAST_RFIND: + return end + else: + return start + w = n - m if w < 0: diff --git a/rpython/rtyper/rint.py b/rpython/rtyper/rint.py --- a/rpython/rtyper/rint.py +++ b/rpython/rtyper/rint.py @@ -251,14 +251,15 @@ raise TyperError("not an integer: %r" % (value,)) def get_ll_eq_function(self): + if getattr(self, '_opprefix', '?') is None: + return ll_eq_shortint return None - get_ll_gt_function = get_ll_eq_function - get_ll_lt_function = get_ll_eq_function - get_ll_ge_function = get_ll_eq_function - get_ll_le_function = get_ll_eq_function def get_ll_ge_function(self): return None + get_ll_gt_function = get_ll_ge_function + get_ll_lt_function = get_ll_ge_function + get_ll_le_function = get_ll_ge_function def get_ll_hash_function(self): if (sys.maxint == 2147483647 and @@ -390,6 +391,10 @@ def ll_hash_long_long(n): return intmask(intmask(n) + 9 * intmask(n >> 32)) +def ll_eq_shortint(n, m): + return intmask(n) == intmask(m) +ll_eq_shortint.no_direct_compare = True + def ll_check_chr(n): if 0 <= n <= 255: return 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 @@ -999,6 +999,26 @@ res = f() assert res == 1 + def test_dict_with_SHORT_keys(self): + def func(x): + d = {} + d[rffi.cast(rffi.SHORT, 42)] = 123 + d[rffi.cast(rffi.SHORT, -43)] = 321 + return d[rffi.cast(rffi.SHORT, x)] + + assert self.interpret(func, [42]) == 123 + assert self.interpret(func, [2**16 - 43]) == 321 + + def test_dict_with_bool_keys(self): + def func(x): + d = {} + d[False] = 123 + d[True] = 321 + return d[x == 42] + + assert self.interpret(func, [5]) == 123 + assert self.interpret(func, [42]) == 321 + def test_nonnull_hint(self): def eq(a, b): return a == b _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit