Author: Philip Jenvey <pjen...@underboss.org> Branch: py3k Changeset: r70292:e1951a6821db Date: 2014-03-25 16:53 -0700 http://bitbucket.org/pypy/pypy/changeset/e1951a6821db/
Log: merge default diff --git a/lib-python/2.7/test/test_genericpath.py b/lib-python/2.7/test/test_genericpath.py --- a/lib-python/2.7/test/test_genericpath.py +++ b/lib-python/2.7/test/test_genericpath.py @@ -231,9 +231,14 @@ unicwd = u'\xe7w\xf0' try: fsencoding = test_support.TESTFN_ENCODING or "ascii" - unicwd.encode(fsencoding) + asciival = unicwd.encode(fsencoding) + if fsencoding == "mbcs": + # http://bugs.python.org/issue850997 + v = asciival.find('?') + if v >= 0: + raise UnicodeEncodeError(fsencoding, unicwd, v, v, asciival) except (AttributeError, UnicodeEncodeError): - # FS encoding is probably ASCII + # FS encoding is probably ASCII or windows and codepage is non-Latin1 pass else: with test_support.temp_cwd(unicwd): diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst --- a/pypy/doc/whatsnew-head.rst +++ b/pypy/doc/whatsnew-head.rst @@ -117,3 +117,13 @@ .. branch: improve-consecutive-dict-lookups Improve the situation when dict lookups of the same key are performed in a chain + +.. branch: add_PyErr_SetFromErrnoWithFilenameObject_try_2 +.. branch: test_SetFromErrnoWithFilename_NULL +.. branch: test_SetFromErrnoWithFilename__tweaks + +.. branch: refactor_PyErr_SetFromErrnoWithFilename +Add support for PyErr_SetFromErrnoWithFilenameObject to cpyext + +.. branch: win32-fixes4 +fix more tests for win32 diff --git a/pypy/module/_codecs/test/test_codecs.py b/pypy/module/_codecs/test/test_codecs.py --- a/pypy/module/_codecs/test/test_codecs.py +++ b/pypy/module/_codecs/test/test_codecs.py @@ -1,3 +1,5 @@ +import sys + class AppTestCodecs: spaceconfig = { "usemodules": ['unicodedata', 'struct', 'binascii'], @@ -138,7 +140,9 @@ class AppTestPartialEvaluation: - spaceconfig = dict(usemodules=('array',)) + spaceconfig = dict(usemodules=['array',]) + if sys.platform == 'win32': + spaceconfig['usemodules'].append('_winreg') def test_partial_utf8(self): import _codecs @@ -753,9 +757,25 @@ import sys if sys.platform != 'win32': return - assert 'test'.encode('mbcs') == b'test' - assert 'caf\xe9'.encode('mbcs') == b'caf\xe9' - raises(UnicodeEncodeError, '\u040a'.encode, 'mbcs') - raises(UnicodeEncodeError, - "-\u5171\u0141\u2661\u0363\uDC80".encode, 'mbcs') - assert b'cafx\e9'.decode('mbcs') == 'cafx\e9' + toencode = u'caf\xe9', b'caf\xe9' + try: + # test for non-latin1 codepage, more general test needed + import _winreg + key = _winreg.OpenKey(_winreg.HKEY_LOCAL_MACHINE, + r'System\CurrentControlSet\Control\Nls\CodePage') + if _winreg.QueryValueEx(key, 'ACP')[0] == u'1255': # non-latin1 + toencode = u'caf\xbf',b'caf\xbf' + except: + assert False, 'cannot test mbcs on this windows system, check code page' + assert u'test'.encode('mbcs') == b'test' + assert toencode[0].encode('mbcs') == toencode[1] + assert u'\u040a'.encode('mbcs') == b'?' # some cyrillic letter + assert b'cafx\e9'.decode('mbcs') == u'cafx\e9' + + def test_bad_handler_string_result(self): + import _codecs + def f(exc): + return (b'foo', exc.end) + _codecs.register_error("test.test_codecs_not_a_string", f) + raises(TypeError, u'\u1234'.encode, 'ascii', + 'test.test_codecs_not_a_string') diff --git a/pypy/module/cpyext/pyerrors.py b/pypy/module/cpyext/pyerrors.py --- a/pypy/module/cpyext/pyerrors.py +++ b/pypy/module/cpyext/pyerrors.py @@ -146,14 +146,29 @@ this is used to define the filename attribute of the exception instance. Return value: always NULL.""" # XXX Doesn't actually do anything with PyErr_CheckSignals. + if llfilename: + w_filename = rffi.charp2str(llfilename) + filename = space.wrap(w_filename) + else: + filename = space.w_None + + PyErr_SetFromErrnoWithFilenameObject(space, w_type, filename) + +@cpython_api([PyObject, PyObject], PyObject) +def PyErr_SetFromErrnoWithFilenameObject(space, w_type, w_value): + """Similar to PyErr_SetFromErrno(), with the additional behavior that if + w_value is not NULL, it is passed to the constructor of type as a + third parameter. In the case of exceptions such as IOError and OSError, + this is used to define the filename attribute of the exception instance. + Return value: always NULL.""" + # XXX Doesn't actually do anything with PyErr_CheckSignals. errno = get_errno() msg = os.strerror(errno) - if llfilename: - w_filename = rffi.charp2str(llfilename) + if w_value: w_error = space.call_function(w_type, space.wrap(errno), space.wrap(msg), - space.wrap(w_filename)) + w_value) else: w_error = space.call_function(w_type, space.wrap(errno), diff --git a/pypy/module/cpyext/test/test_eval.py b/pypy/module/cpyext/test/test_eval.py --- a/pypy/module/cpyext/test/test_eval.py +++ b/pypy/module/cpyext/test/test_eval.py @@ -312,8 +312,9 @@ ("get_flags", "METH_NOARGS", """ PyCompilerFlags flags; + int result; flags.cf_flags = 0; - int result = PyEval_MergeCompilerFlags(&flags); + result = PyEval_MergeCompilerFlags(&flags); return Py_BuildValue("ii", result, flags.cf_flags); """), ]) diff --git a/pypy/module/cpyext/test/test_pyerrors.py b/pypy/module/cpyext/test/test_pyerrors.py --- a/pypy/module/cpyext/test/test_pyerrors.py +++ b/pypy/module/cpyext/test/test_pyerrors.py @@ -186,29 +186,136 @@ except OSError as e: assert e.errno == errno.EBADF assert e.strerror == os.strerror(errno.EBADF) - assert e.filename == None + assert e.filename is None def test_SetFromErrnoWithFilename(self): - import sys - if sys.platform != 'win32': - skip("callbacks through ll2ctypes modify errno") import errno, os module = self.import_extension('foo', [ ("set_from_errno", "METH_NOARGS", ''' errno = EBADF; - PyErr_SetFromErrnoWithFilename(PyExc_OSError, "blyf"); + PyErr_SetFromErrnoWithFilename(PyExc_OSError, "/path/to/file"); return NULL; '''), ], prologue="#include <errno.h>") - try: - module.set_from_errno() - except OSError as e: - assert e.filename == "blyf" - assert e.errno == errno.EBADF - assert e.strerror == os.strerror(errno.EBADF) + exc_info = raises(OSError, module.set_from_errno) + assert exc_info.value.filename == "/path/to/file" + assert exc_info.value.errno == errno.EBADF + assert exc_info.value.strerror == os.strerror(errno.EBADF) + + def test_SetFromErrnoWithFilename_NULL(self): + import errno, os + + module = self.import_extension('foo', [ + ("set_from_errno", "METH_NOARGS", + ''' + errno = EBADF; + PyErr_SetFromErrnoWithFilename(PyExc_OSError, NULL); + return NULL; + '''), + ], + prologue="#include <errno.h>") + exc_info = raises(OSError, module.set_from_errno) + assert exc_info.value.filename is None + assert exc_info.value.errno == errno.EBADF + assert exc_info.value.strerror == os.strerror(errno.EBADF) + + def test_SetFromErrnoWithFilenameObject__PyString(self): + import errno, os + + module = self.import_extension('foo', [ + ("set_from_errno", "METH_NOARGS", + ''' + errno = EBADF; + PyObject *filenameObject = PyString_FromString("/path/to/file"); + PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, filenameObject); + Py_DECREF(filenameObject); + return NULL; + '''), + ], + prologue="#include <errno.h>") + exc_info = raises(OSError, module.set_from_errno) + assert exc_info.value.filename == "/path/to/file" + assert exc_info.value.errno == errno.EBADF + assert exc_info.value.strerror == os.strerror(errno.EBADF) + + def test_SetFromErrnoWithFilenameObject__PyInt(self): + import errno, os + + module = self.import_extension('foo', [ + ("set_from_errno", "METH_NOARGS", + ''' + errno = EBADF; + PyObject *intObject = PyInt_FromLong(3); + PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, intObject); + Py_DECREF(intObject); + return NULL; + '''), + ], + prologue="#include <errno.h>") + exc_info = raises(OSError, module.set_from_errno) + assert exc_info.value.filename == 3 + assert exc_info.value.errno == errno.EBADF + assert exc_info.value.strerror == os.strerror(errno.EBADF) + + def test_SetFromErrnoWithFilenameObject__PyList(self): + import errno, os + + module = self.import_extension('foo', [ + ("set_from_errno", "METH_NOARGS", + ''' + errno = EBADF; + PyObject *lst = Py_BuildValue("[iis]", 1, 2, "three"); + PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, lst); + Py_DECREF(lst); + return NULL; + '''), + ], + prologue="#include <errno.h>") + exc_info = raises(OSError, module.set_from_errno) + assert exc_info.value.filename == [1, 2, "three"] + assert exc_info.value.errno == errno.EBADF + assert exc_info.value.strerror == os.strerror(errno.EBADF) + + def test_SetFromErrnoWithFilenameObject__PyTuple(self): + import errno, os + + module = self.import_extension('foo', [ + ("set_from_errno", "METH_NOARGS", + ''' + errno = EBADF; + PyObject *tuple = Py_BuildValue("(iis)", 1, 2, "three"); + PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, tuple); + Py_DECREF(tuple); + return NULL; + '''), + ], + prologue="#include <errno.h>") + exc_info = raises(OSError, module.set_from_errno) + assert exc_info.value.filename == (1, 2, "three") + assert exc_info.value.errno == errno.EBADF + assert exc_info.value.strerror == os.strerror(errno.EBADF) + + def test_SetFromErrnoWithFilenameObject__Py_None(self): + import errno, os + + module = self.import_extension('foo', [ + ("set_from_errno", "METH_NOARGS", + ''' + errno = EBADF; + PyObject *none = Py_BuildValue(""); + PyErr_SetFromErrnoWithFilenameObject(PyExc_OSError, none); + Py_DECREF(none); + return NULL; + '''), + ], + prologue="#include <errno.h>") + exc_info = raises(OSError, module.set_from_errno) + assert exc_info.value.filename is None + assert exc_info.value.errno == errno.EBADF + assert exc_info.value.strerror == os.strerror(errno.EBADF) def test_PyErr_Display(self): module = self.import_extension('foo', [ diff --git a/pypy/module/micronumpy/ndarray.py b/pypy/module/micronumpy/ndarray.py --- a/pypy/module/micronumpy/ndarray.py +++ b/pypy/module/micronumpy/ndarray.py @@ -185,7 +185,7 @@ return chunks.apply(space, self) shape = res_shape + self.get_shape()[len(indexes):] w_res = W_NDimArray.from_shape(space, shape, self.get_dtype(), - self.get_order(), w_instance=self) + self.get_order(), w_instance=self) if not w_res.get_size(): return w_res return loop.getitem_array_int(space, self, w_res, iter_shape, indexes, @@ -201,6 +201,8 @@ view = chunks.apply(space, self) view.implementation.setslice(space, val_arr) return + if support.product(iter_shape) == 0: + return loop.setitem_array_int(space, self, iter_shape, indexes, val_arr, prefix) @@ -1159,7 +1161,7 @@ raise OperationError(space.w_TypeError, space.wrap( "numpy scalars from buffers not supported yet")) totalsize = support.product(shape) * dtype.elsize - if totalsize+offset > buf.getlength(): + if totalsize + offset > buf.getlength(): raise OperationError(space.w_TypeError, space.wrap( "buffer is too small for requested array")) storage = rffi.cast(RAW_STORAGE_PTR, raw_ptr) diff --git a/pypy/module/micronumpy/test/test_ndarray.py b/pypy/module/micronumpy/test/test_ndarray.py --- a/pypy/module/micronumpy/test/test_ndarray.py +++ b/pypy/module/micronumpy/test/test_ndarray.py @@ -2360,6 +2360,19 @@ assert b.shape == b[...].shape assert (b == b[...]).all() + def test_empty_indexing(self): + import numpy as np + r = np.ones(3) + ind = np.array([], np.int32) + tmp = np.array([], np.float64) + assert r[ind].shape == (0,) + r[ind] = 0 + assert (r == np.ones(3)).all() + r[ind] = tmp + assert (r == np.ones(3)).all() + r[[]] = 0 + assert (r == np.ones(3)).all() + class AppTestNumArrayFromBuffer(BaseNumpyAppTest): spaceconfig = dict(usemodules=["micronumpy", "array", "mmap"]) diff --git a/pypy/module/pypyjit/test_pypy_c/test_containers.py b/pypy/module/pypyjit/test_pypy_c/test_containers.py --- a/pypy/module/pypyjit/test_pypy_c/test_containers.py +++ b/pypy/module/pypyjit/test_pypy_c/test_containers.py @@ -70,14 +70,14 @@ p13 = new(descr=...) p15 = new_array(8, descr=<ArrayX .*>) setfield_gc(p13, p15, descr=<FieldP dicttable.entries .*>) - i17 = call(ConstClass(ll_dict_lookup_trampoline), p13, p10, i12, descr=<Calli . rri EF=4>) + i17 = call(ConstClass(ll_dict_lookup_trampoline), p13, p10, i12, descr=<Calli . rri EF=4 OS=4>) setfield_gc(p13, 16, descr=<FieldS dicttable.resize_counter .*>) guard_no_exception(descr=...) p20 = new_with_vtable(ConstClass(W_IntObject)) call(ConstClass(_ll_dict_setitem_lookup_done_trampoline), p13, p10, p20, i12, i17, descr=<Callv 0 rrrii EF=4>) setfield_gc(p20, i5, descr=<FieldS .*W_IntObject.inst_intval .*>) guard_no_exception(descr=...) - i23 = call(ConstClass(ll_dict_lookup_trampoline), p13, p10, i12, descr=<Calli . rri EF=4>) + i23 = call(ConstClass(ll_dict_lookup_trampoline), p13, p10, i12, descr=<Calli . rri EF=4 OS=4>) guard_no_exception(descr=...) i26 = int_and(i23, .*) i27 = int_is_true(i26) diff --git a/pypy/module/pypyjit/test_pypy_c/test_instance.py b/pypy/module/pypyjit/test_pypy_c/test_instance.py --- a/pypy/module/pypyjit/test_pypy_c/test_instance.py +++ b/pypy/module/pypyjit/test_pypy_c/test_instance.py @@ -141,15 +141,16 @@ i = 0 b = B(1) while i < 100: - b.x - v = b.x # ID: loadattr + v = b.x # ID: loadattr1 + v = b.x # ID: loadattr2 i += v return i log = self.run(main, [], threshold=80) loop, = log.loops_by_filename(self.filepath) - assert loop.match_by_id('loadattr', + assert loop.match_by_id('loadattr1', ''' + guard_not_invalidated(descr=...) i19 = call(ConstClass(ll_dict_lookup), _, _, _, descr=...) guard_no_exception(descr=...) i21 = int_and(i19, _) @@ -161,6 +162,7 @@ i29 = int_is_true(i28) guard_true(i29, descr=...) ''') + assert loop.match_by_id('loadattr2', "") # completely folded away def test_python_contains(self): def main(): diff --git a/pypy/sandbox/test/test_pypy_interact.py b/pypy/sandbox/test/test_pypy_interact.py --- a/pypy/sandbox/test/test_pypy_interact.py +++ b/pypy/sandbox/test/test_pypy_interact.py @@ -1,4 +1,4 @@ -import os, sys, stat, errno +import os, stat, errno, py from pypy.sandbox.pypy_interact import PyPySandboxedProc from rpython.translator.interactive import Translation @@ -9,6 +9,9 @@ SITE_PY_CONTENT = LIB_PYTHON.join('site.py').read() ERROR_TEXT = os.strerror(errno.ENOENT) +if os.name == 'nt': + py.test.skip('sandbox not supported on windows') + def assert_(cond, text): if not cond: print "assert failed:", text diff --git a/rpython/jit/backend/arm/opassembler.py b/rpython/jit/backend/arm/opassembler.py --- a/rpython/jit/backend/arm/opassembler.py +++ b/rpython/jit/backend/arm/opassembler.py @@ -584,7 +584,10 @@ emit_op_getfield_gc_pure = emit_op_getfield_gc def emit_op_increment_debug_counter(self, op, arglocs, regalloc, fcond): - # XXX implement me + base_loc, value_loc = arglocs + self.mc.LDR_ri(value_loc.value, base_loc.value, 0, cond=fcond) + self.mc.ADD_ri(value_loc.value, value_loc.value, 1, cond=fcond) + self.mc.STR_ri(value_loc.value, base_loc.value, 0, cond=fcond) return fcond def emit_op_getinteriorfield_gc(self, op, arglocs, regalloc, fcond): 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 @@ -850,8 +850,12 @@ prepare_op_getfield_gc_pure = prepare_op_getfield_gc def prepare_op_increment_debug_counter(self, op, fcond): - # XXX implement me - return [] + boxes = op.getarglist() + a0, = boxes + base_loc = self.make_sure_var_in_reg(a0, boxes) + value_loc = self.get_scratch_reg(INT, boxes) + self.free_temp_vars() + return [base_loc, value_loc] def prepare_op_getinteriorfield_gc(self, op, fcond): t = unpack_interiorfielddescr(op.getdescr()) diff --git a/rpython/jit/backend/detect_cpu.py b/rpython/jit/backend/detect_cpu.py --- a/rpython/jit/backend/detect_cpu.py +++ b/rpython/jit/backend/detect_cpu.py @@ -20,10 +20,11 @@ def detect_model_from_c_compiler(): # based on http://sourceforge.net/p/predef/wiki/Architectures/ + # and http://msdn.microsoft.com/en-us/library/b0084kay.aspx mapping = { - MODEL_X86_64: ['__amd64__', '__amd64', '__x86_64__', '__x86_64'], - MODEL_ARM: ['__arm__', '__thumb__'], - MODEL_X86: ['i386', '__i386', '__i386__', '__i686__'], + MODEL_X86_64: ['__amd64__', '__amd64', '__x86_64__', '__x86_64', '_M_X64', '_M_AMD64'], + MODEL_ARM: ['__arm__', '__thumb__','_M_ARM_EP'], + MODEL_X86: ['i386', '__i386', '__i386__', '__i686__','_M_IX86'], MODEL_PPC_64: ['__powerpc64__'], } for k, v in mapping.iteritems(): 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, rclass, rstr +from rpython.rlib.clibffi import FFI_DEFAULT_ABI from rpython.rlib.rarithmetic import ovfcheck, r_uint, r_ulonglong from rpython.rlib.rtimer import read_timestamp @@ -66,9 +67,10 @@ self.args = args class CallDescr(AbstractDescr): - def __init__(self, RESULT, ARGS, extrainfo): + def __init__(self, RESULT, ARGS, extrainfo, ABI=FFI_DEFAULT_ABI): self.RESULT = RESULT self.ARGS = ARGS + self.ABI = ABI self.extrainfo = extrainfo def __repr__(self): @@ -428,7 +430,7 @@ try: return self.descrs[key] except KeyError: - descr = CallDescr(RESULT, ARGS, extrainfo) + descr = CallDescr(RESULT, ARGS, extrainfo, ABI=cif_description.abi) self.descrs[key] = descr return descr @@ -949,7 +951,7 @@ # graph, not to directly execute the python function result = self.cpu.maybe_on_top_of_llinterp(func, call_args, descr.RESULT) else: - FUNC = lltype.FuncType(descr.ARGS, descr.RESULT) + FUNC = lltype.FuncType(descr.ARGS, descr.RESULT, descr.ABI) func_to_call = rffi.cast(lltype.Ptr(FUNC), func) result = func_to_call(*call_args) del self.force_guard_op 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 @@ -545,7 +545,7 @@ p1 = int_add(p0, %(strdescr.basesize + 16 * strdescr.itemsize)d) setfield_gc(p1, %(unicodedescr.tid)d, descr=tiddescr) setfield_gc(p1, 10, descr=unicodelendescr) - p2 = call_malloc_nursery_varsize(2, 4, i2, \ + p2 = call_malloc_nursery_varsize(2, %(unicodedescr.itemsize)d, i2,\ descr=unicodedescr) setfield_gc(p2, i2, descr=unicodelendescr) p3 = call_malloc_nursery_varsize(1, 1, i2, \ diff --git a/rpython/jit/backend/x86/arch.py b/rpython/jit/backend/x86/arch.py --- a/rpython/jit/backend/x86/arch.py +++ b/rpython/jit/backend/x86/arch.py @@ -15,12 +15,12 @@ # # +--------------------+ <== aligned to 16 bytes # | return address | -# +--------------------+ -# | saved regs | -# +--------------------+ -# | scratch | -# | space | -# +--------------------+ <== aligned to 16 bytes +# +--------------------+ ----------------------. +# | saved regs | FRAME_FIXED_SIZE | +# +--------------------+ --------------------. | +# | scratch | PASS_ON_MY_FRAME | | +# | space | | | +# +--------------------+ <== aligned to 16 -----' ----' # All the rest of the data is in a GC-managed variable-size "frame". # This frame object's address is always stored in the register EBP/RBP. @@ -30,14 +30,14 @@ # start of every frame: the saved value of some registers if WORD == 4: - # ebp + ebx + esi + edi + 14 extra words + return address = 19 words + # ebp + ebx + esi + edi + 15 extra words = 19 words FRAME_FIXED_SIZE = 19 - PASS_ON_MY_FRAME = 14 + PASS_ON_MY_FRAME = 15 JITFRAME_FIXED_SIZE = 6 + 8 * 2 # 6 GPR + 8 XMM * 2 WORDS/float else: - # rbp + rbx + r12 + r13 + r14 + r15 + 12 extra words + return address = 19 + # rbp + rbx + r12 + r13 + r14 + r15 + 13 extra words = 19 FRAME_FIXED_SIZE = 19 - PASS_ON_MY_FRAME = 12 + PASS_ON_MY_FRAME = 13 JITFRAME_FIXED_SIZE = 28 # 13 GPR + 15 XMM assert PASS_ON_MY_FRAME >= 12 # asmgcc needs at least JIT_USE_WORDS + 3 diff --git a/rpython/jit/codewriter/effectinfo.py b/rpython/jit/codewriter/effectinfo.py --- a/rpython/jit/codewriter/effectinfo.py +++ b/rpython/jit/codewriter/effectinfo.py @@ -103,8 +103,10 @@ extradescrs=None): key = (frozenset_or_none(readonly_descrs_fields), frozenset_or_none(readonly_descrs_arrays), + frozenset_or_none(readonly_descrs_interiorfields), frozenset_or_none(write_descrs_fields), frozenset_or_none(write_descrs_arrays), + frozenset_or_none(write_descrs_interiorfields), extraeffect, oopspecindex, can_invalidate) @@ -222,6 +224,18 @@ descr = cpu.interiorfielddescrof(T, fieldname) descrs_interiorfields.append(descr) + # a read or a write to an interiorfield, inside an array of + # structs, is additionally recorded as a read or write of + # the array itself + extraef = set() + for tup in effects: + if tup[0] == "interiorfield" or tup[0] == "readinteriorfield": + T = deref(tup[1]) + if isinstance(T, lltype.Array) and consider_array(T): + extraef.add((tup[0].replace("interiorfield", "array"), + tup[1])) + effects |= extraef + for tup in effects: if tup[0] == "struct": add_struct(write_descrs_fields, tup) 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 @@ -1854,8 +1854,7 @@ def _handle_dict_lookup_call(self, op, oopspec_name, args): extradescr1 = self.cpu.fielddescrof(op.args[1].concretetype.TO, 'entries') - extradescr2 = self.cpu.interiorfielddescrof( - op.args[1].concretetype.TO.entries.TO, 'key') + extradescr2 = self.cpu.arraydescrof(op.args[1].concretetype.TO.entries.TO) return self._handle_oopspec_call(op, args, EffectInfo.OS_DICT_LOOKUP, extradescr=[extradescr1, extradescr2]) 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 @@ -73,7 +73,7 @@ def guess_call_kind(self, op): return 'residual' def getcalldescr(self, op, oopspecindex=EffectInfo.OS_NONE, - extraeffect=None): + extraeffect=None, extradescr=None): try: name = op.args[0].value._obj._name if 'cannot_raise' in name or name.startswith('cast_'): diff --git a/rpython/jit/codewriter/test/test_longlong.py b/rpython/jit/codewriter/test/test_longlong.py --- a/rpython/jit/codewriter/test/test_longlong.py +++ b/rpython/jit/codewriter/test/test_longlong.py @@ -17,7 +17,7 @@ class FakeBuiltinCallControl: def guess_call_kind(self, op): return 'builtin' - def getcalldescr(self, op, oopspecindex=None, extraeffect=None): + def getcalldescr(self, op, oopspecindex=None, extraeffect=None, extradescr=None): assert oopspecindex is not None # in this test return 'calldescr-%d' % oopspecindex def calldescr_canraise(self, calldescr): 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 @@ -108,6 +108,7 @@ raise NotImplementedError def getaddr(self): + "Only for raw addresses (BoxInt & ConstInt), not for GC addresses" raise NotImplementedError def sort_key(self): @@ -321,9 +322,6 @@ else: return 0 - def getaddr(self): - return llmemory.cast_ptr_to_adr(self.value) - def same_constant(self, other): if isinstance(other, ConstPtr): return self.value == other.value @@ -494,9 +492,6 @@ return lltype.cast_opaque_ptr(PTR, self.getref_base()) getref._annspecialcase_ = 'specialize:arg(1)' - def getaddr(self): - return llmemory.cast_ptr_to_adr(self.value) - def _get_hash_(self): if self.value: return lltype.identityhash(self.value) diff --git a/rpython/jit/metainterp/logger.py b/rpython/jit/metainterp/logger.py --- a/rpython/jit/metainterp/logger.py +++ b/rpython/jit/metainterp/logger.py @@ -72,6 +72,9 @@ def _make_log_operations(self): return LogOperations(self.metainterp_sd, self.guard_number) + def repr_of_resop(self, op): + return LogOperations(self.metainterp_sd, self.guard_number).repr_of_resop(op) + class LogOperations(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 @@ -177,7 +177,7 @@ self.cached_arrayitems = {} # cached dict items: {dict descr: {(optval, index): box-or-const}} self.cached_dict_reads = {} - # cache of corresponding array descrs + # cache of corresponding {array descrs: dict 'entries' field descr} self.corresponding_array_descrs = {} # self._lazy_setfields_and_arrayitems = [] @@ -346,9 +346,8 @@ self.force_lazy_setfield(fielddescr, can_cache=False) for arraydescr in effectinfo.write_descrs_arrays: self.force_lazy_setarrayitem(arraydescr, can_cache=False) - for descr in effectinfo.write_descrs_interiorfields: - if descr in self.corresponding_array_descrs: - dictdescr = self.corresponding_array_descrs.pop(descr) + if arraydescr in self.corresponding_array_descrs: + dictdescr = self.corresponding_array_descrs.pop(arraydescr) try: del self.cached_dict_reads[dictdescr] except KeyError: diff --git a/rpython/jit/metainterp/optimizeopt/rewrite.py b/rpython/jit/metainterp/optimizeopt/rewrite.py --- a/rpython/jit/metainterp/optimizeopt/rewrite.py +++ b/rpython/jit/metainterp/optimizeopt/rewrite.py @@ -242,8 +242,9 @@ box = value.box assert isinstance(box, Const) if not box.same_constant(constbox): - raise InvalidLoop('A GUARD_{VALUE,TRUE,FALSE} was proven to' + - 'always fail') + r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op) + raise InvalidLoop('A GUARD_{VALUE,TRUE,FALSE} (%s) was proven ' + 'to always fail' % r) return if emit_operation: self.emit_operation(op) @@ -255,7 +256,9 @@ if value.is_null(): return elif value.is_nonnull(): - raise InvalidLoop('A GUARD_ISNULL was proven to always fail') + r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op) + raise InvalidLoop('A GUARD_ISNULL (%s) was proven to always fail' + % r) self.emit_operation(op) value.make_constant(self.optimizer.cpu.ts.CONST_NULL) @@ -264,7 +267,9 @@ if value.is_nonnull(): return elif value.is_null(): - raise InvalidLoop('A GUARD_NONNULL was proven to always fail') + r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op) + raise InvalidLoop('A GUARD_NONNULL (%s) was proven to always fail' + % r) self.emit_operation(op) value.make_nonnull(op) @@ -292,7 +297,8 @@ assert previous_classbox is not None assert expected_classbox is not None if not previous_classbox.same_constant(expected_classbox): - raise InvalidLoop('A GUARD_VALUE was proven to always fail') + r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op) + raise InvalidLoop('A GUARD_VALUE (%s) was proven to always fail' % r) op = old_guard_op.copy_and_change(rop.GUARD_VALUE, args = [old_guard_op.getarg(0), op.getarg(1)]) self.optimizer.replaces_guard[op] = old_guard_op @@ -333,7 +339,9 @@ if realclassbox is not None: if realclassbox.same_constant(expectedclassbox): return - raise InvalidLoop('A GUARD_CLASS was proven to always fail') + r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op) + raise InvalidLoop('A GUARD_CLASS (%s) was proven to always fail' + % r) if value.last_guard: # there already has been a guard_nonnull or guard_class or # guard_nonnull_class on this value. @@ -356,8 +364,9 @@ def optimize_GUARD_NONNULL_CLASS(self, op): value = self.getvalue(op.getarg(0)) if value.is_null(): - raise InvalidLoop('A GUARD_NONNULL_CLASS was proven to always ' + - 'fail') + r = self.optimizer.metainterp_sd.logger_ops.repr_of_resop(op) + raise InvalidLoop('A GUARD_NONNULL_CLASS (%s) was proven to ' + 'always fail' % r) self.optimize_GUARD_CLASS(op) def optimize_CALL_LOOPINVARIANT(self, op): diff --git a/rpython/jit/metainterp/optimizeopt/test/test_util.py b/rpython/jit/metainterp/optimizeopt/test/test_util.py --- a/rpython/jit/metainterp/optimizeopt/test/test_util.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_util.py @@ -319,6 +319,9 @@ def log_loop(*args): pass + class logger_ops: + repr_of_resop = repr + class warmrunnerdesc: class memory_manager: retrace_limit = 5 diff --git a/rpython/jit/metainterp/optimizeopt/util.py b/rpython/jit/metainterp/optimizeopt/util.py --- a/rpython/jit/metainterp/optimizeopt/util.py +++ b/rpython/jit/metainterp/optimizeopt/util.py @@ -139,7 +139,13 @@ txt1 = str(op1) txt2 = str(op2) while txt1 or txt2: - print '%s| %s' % (txt1[:width].ljust(width), txt2[:width]) + part1 = txt1[:width] + part2 = txt2[:width] + if part1 == part2: + sep = '| ' + else: + sep = '<>' + print '%s%s%s' % (part1.ljust(width), sep, part2) txt1 = txt1[width:] txt2 = txt2[width:] print '-' * totwidth 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 @@ -14,6 +14,7 @@ from rpython.rlib.longlong2float import float2longlong, longlong2float from rpython.rlib.rarithmetic import ovfcheck, is_valid_int from rpython.rtyper.lltypesystem import lltype, rffi +from rpython.translator.tool.cbuild import ExternalCompilationInfo class BasicTests: @@ -3228,11 +3229,12 @@ self.check_resops(arraylen_gc=2) def test_release_gil_flush_heap_cache(self): + eci = ExternalCompilationInfo() if sys.platform == "win32": - py.test.skip("needs 'time'") + eci = ExternalCompilationInfo(libraries=["msvcrt"]) T = rffi.CArrayPtr(rffi.TIME_T) - external = rffi.llexternal("time", [T], rffi.TIME_T, releasegil=True) + external = rffi.llexternal("time", [T], rffi.TIME_T, releasegil=True, compilation_info=eci) # Not a real lock, has all the same properties with respect to GIL # release though, so good for this test. class Lock(object): @@ -3920,10 +3922,13 @@ self.interp_operations(f, []) def test_external_call(self): + eci = ExternalCompilationInfo() + if sys.platform == "win32": + eci = ExternalCompilationInfo(libraries=["msvcrt"]) from rpython.rlib.objectmodel import invoke_around_extcall T = rffi.CArrayPtr(rffi.TIME_T) - external = rffi.llexternal("time", [T], rffi.TIME_T) + external = rffi.llexternal("time", [T], rffi.TIME_T, compilation_info=eci) class Oups(Exception): pass diff --git a/rpython/jit/metainterp/test/test_dict.py b/rpython/jit/metainterp/test/test_dict.py --- a/rpython/jit/metainterp/test/test_dict.py +++ b/rpython/jit/metainterp/test/test_dict.py @@ -294,6 +294,54 @@ assert res == f(10) self.check_simple_loop(call=3) + def test_dict_eq_can_release_gil(self): + from rpython.rtyper.lltypesystem import lltype, rffi + if type(self.newdict()) is not dict: + py.test.skip("this is an r_dict test") + T = rffi.CArrayPtr(rffi.TIME_T) + external = rffi.llexternal("time", [T], rffi.TIME_T, releasegil=True) + myjitdriver = JitDriver(greens = [], reds = ['total', 'dct']) + def key(x): + return x % 2 + def eq(x, y): + external(lltype.nullptr(T.TO)) + return (x % 2) == (y % 2) + + def f(n): + dct = objectmodel.r_dict(eq, key) + total = n + x = 44444 + y = 55555 + z = 66666 + while total: + myjitdriver.jit_merge_point(total=total, dct=dct) + dct[total] = total + x = dct[total] + y = dct[total] + z = dct[total] + total -= 1 + return len(dct) + x + y + z + + res = self.meta_interp(f, [10], listops=True) + assert res == 2 + 1 + 1 + 1 + self.check_simple_loop(call_may_force=4, # ll_dict_lookup_trampoline + call=1) # ll_dict_setitem_lookup_done_trampoline + + def test_bug42(self): + myjitdriver = JitDriver(greens = [], reds = 'auto') + def f(n): + mdict = {0: None, 1: None, 2: None, 3: None, 4: None, + 5: None, 6: None, 7: None, 8: None, 9: None} + while n > 0: + myjitdriver.jit_merge_point() + n -= 1 + if n in mdict: + del mdict[n] + if n in mdict: + raise Exception + self.meta_interp(f, [10]) + self.check_simple_loop(call_may_force=0, call=3) + class TestLLtype(DictTests, LLJitMixin): pass diff --git a/rpython/rlib/test/test_clibffi.py b/rpython/rlib/test/test_clibffi.py --- a/rpython/rlib/test/test_clibffi.py +++ b/rpython/rlib/test/test_clibffi.py @@ -423,11 +423,12 @@ def setup_class(cls): if sys.platform != 'win32': py.test.skip("Handle to libc library, Win-only test") - BaseFfiTest.setup_class(cls) + BaseFfiTest.setup_class() def test_get_libc_handle(self): handle = get_libc_handle() print get_libc_name() - print hex(handle) - assert handle != 0 - assert handle % 0x1000 == 0 + print dir(handle) + addr = rffi.cast(rffi.INT, handle) + assert addr != 0 + assert addr % 0x1000 == 0 diff --git a/rpython/rlib/test/test_rposix.py b/rpython/rlib/test/test_rposix.py --- a/rpython/rlib/test/test_rposix.py +++ b/rpython/rlib/test/test_rposix.py @@ -25,7 +25,7 @@ def as_unicode(self): return self.unistr -class BasePosixUnicode: +class BasePosixUnicodeOrAscii: def setup_method(self, method): self.ufilename = self._get_filename() try: @@ -34,9 +34,12 @@ py.test.skip("encoding not good enough") f.write("test") f.close() - - self.path = UnicodeWithEncoding(self.ufilename) - self.path2 = UnicodeWithEncoding(self.ufilename + ".new") + if sys.platform == 'win32' and isinstance(self.ufilename, str): + self.path = self.ufilename + self.path2 = self.ufilename + ".new" + else: + self.path = UnicodeWithEncoding(self.ufilename) + self.path2 = UnicodeWithEncoding(self.ufilename + ".new") def test_open(self): def f(): @@ -55,8 +58,11 @@ def test_stat(self): def f(): return rposix.stat(self.path).st_mtime - - assert interpret(f, []) == os.stat(self.ufilename).st_mtime + if sys.platform == 'win32': + # double vs. float, be satisfied with sub-millisec resolution + assert abs(interpret(f, []) - os.stat(self.ufilename).st_mtime) < 1e-4 + else: + assert interpret(f, []) == os.stat(self.ufilename).st_mtime def test_access(self): def f(): @@ -96,7 +102,11 @@ if sys.platform == 'win32': def f(): - return u', '.join(rposix.listdir(udir)) + if isinstance(udir.as_unicode(), str): + _udir = udir.as_unicode() + else: + _udir = udir + return u', '.join(rposix.listdir(_udir)) result = interpret(f, []) assert os.path.basename(self.ufilename) in ll_to_string(result) else: @@ -149,11 +159,11 @@ interpret(f, []) # does not crash -class TestPosixAscii(BasePosixUnicode): +class TestPosixAscii(BasePosixUnicodeOrAscii): def _get_filename(self): return str(udir.join('test_open_ascii')) -class TestPosixUnicode(BasePosixUnicode): +class TestPosixUnicode(BasePosixUnicodeOrAscii): def _get_filename(self): return (unicode(udir.join('test_open')) + u'\u65e5\u672c.txt') # "Japan" 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 @@ -358,6 +358,12 @@ if isinstance(T, lltype.Ptr): if isinstance(T.TO, lltype.FuncType): + functype = ctypes.CFUNCTYPE + if sys.platform == 'win32': + from rpython.rlib.clibffi import FFI_STDCALL, FFI_DEFAULT_ABI + if getattr(T.TO, 'ABI', FFI_DEFAULT_ABI) == FFI_STDCALL: + # for win32 system call + functype = ctypes.WINFUNCTYPE argtypes = [get_ctypes_type(ARG) for ARG in T.TO.ARGS if ARG is not lltype.Void] if T.TO.RESULT is lltype.Void: @@ -366,10 +372,10 @@ restype = get_ctypes_type(T.TO.RESULT) try: kwds = {'use_errno': True} - return ctypes.CFUNCTYPE(restype, *argtypes, **kwds) + return functype(restype, *argtypes, **kwds) except TypeError: # unexpected 'use_errno' argument, old ctypes version - return ctypes.CFUNCTYPE(restype, *argtypes) + return functype(restype, *argtypes) elif isinstance(T.TO, lltype.OpaqueType): return ctypes.c_void_p else: diff --git a/rpython/rtyper/lltypesystem/lltype.py b/rpython/rtyper/lltypesystem/lltype.py --- a/rpython/rtyper/lltypesystem/lltype.py +++ b/rpython/rtyper/lltypesystem/lltype.py @@ -537,7 +537,7 @@ class FuncType(ContainerType): _gckind = 'raw' __name__ = 'func' - def __init__(self, args, result): + def __init__(self, args, result, abi='FFI_DEFAULT_ABI'): for arg in args: assert isinstance(arg, LowLevelType) # There are external C functions eating raw structures, not @@ -547,6 +547,7 @@ if isinstance(result, ContainerType): raise TypeError, "function result can only be primitive or pointer" self.RESULT = result + self.ABI = abi def __str__(self): args = ', '.join(map(str, self.ARGS)) _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit