Author: Richard Plangger <planri...@gmail.com> Branch: memoryview-attributes Changeset: r86455:4ec423c97a35 Date: 2016-08-24 09:10 +0200 http://bitbucket.org/pypy/pypy/changeset/4ec423c97a35/
Log: merge default diff --git a/lib_pypy/cffi/recompiler.py b/lib_pypy/cffi/recompiler.py --- a/lib_pypy/cffi/recompiler.py +++ b/lib_pypy/cffi/recompiler.py @@ -515,7 +515,7 @@ tovar, errcode) return # - elif isinstance(tp, (model.StructOrUnion, model.EnumType)): + elif isinstance(tp, model.StructOrUnionOrEnum): # a struct (not a struct pointer) as a function argument self._prnt(' if (_cffi_to_c((char *)&%s, _cffi_type(%d), %s) < 0)' % (tovar, self._gettypenum(tp), fromvar)) @@ -572,7 +572,7 @@ elif isinstance(tp, model.ArrayType): return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( var, self._gettypenum(model.PointerType(tp.item))) - elif isinstance(tp, model.StructType): + elif isinstance(tp, model.StructOrUnion): if tp.fldnames is None: raise TypeError("'%s' is used as %s, but is opaque" % ( tp._get_c_name(), context)) diff --git a/lib_pypy/cffi/vengine_cpy.py b/lib_pypy/cffi/vengine_cpy.py --- a/lib_pypy/cffi/vengine_cpy.py +++ b/lib_pypy/cffi/vengine_cpy.py @@ -308,7 +308,7 @@ elif isinstance(tp, model.ArrayType): return '_cffi_from_c_pointer((char *)%s, _cffi_type(%d))' % ( var, self._gettypenum(model.PointerType(tp.item))) - elif isinstance(tp, model.StructType): + elif isinstance(tp, model.StructOrUnion): if tp.fldnames is None: raise TypeError("'%s' is used as %s, but is opaque" % ( tp._get_c_name(), context)) 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 @@ -144,3 +144,9 @@ ``type.__dict__`` now returns a ``dict_proxy`` object, like on CPython. Previously it returned what looked like a regular dict object (but it was already read-only). + + +.. branch: const-fold-we-are-jitted + +Reduce the size of the generated C code by constant-folding ``we_are_jitted`` +in non-jitcode. diff --git a/pypy/module/posix/interp_posix.py b/pypy/module/posix/interp_posix.py --- a/pypy/module/posix/interp_posix.py +++ b/pypy/module/posix/interp_posix.py @@ -590,6 +590,8 @@ "decode", w_fs_encoding) except OperationError as e: # fall back to the original byte string + if e.async(space): + raise result_w[i] = w_bytes return space.newlist(result_w) else: diff --git a/pypy/module/pypyjit/test_pypy_c/test_ffi.py b/pypy/module/pypyjit/test_pypy_c/test_ffi.py --- a/pypy/module/pypyjit/test_pypy_c/test_ffi.py +++ b/pypy/module/pypyjit/test_pypy_c/test_ffi.py @@ -423,7 +423,7 @@ guard_false(i114, descr=...) --TICK-- i123 = arraylen_gc(p67, descr=<ArrayP .>) - i119 = call_i(ConstClass(_ll_1_raw_malloc_varsize__Signed), 6, descr=<Calli . i EF=5 OS=110>) + i119 = call_i(ConstClass(_ll_1_raw_malloc_varsize_zero__Signed), 6, descr=<Calli . i EF=5 OS=110>) check_memory_error(i119) raw_store(i119, 0, i160, descr=<ArrayS 2>) raw_store(i119, 2, i160, descr=<ArrayS 2>) diff --git a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py --- a/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py +++ b/pypy/module/test_lib_pypy/cffi_tests/cffi1/test_recompiler.py @@ -1963,3 +1963,21 @@ ffi, "test_function_returns_opaque", "?") assert str(e.value) == ("function foo: 'struct a' is used as result type," " but is opaque") + +def test_function_returns_union(): + ffi = FFI() + ffi.cdef("union u1 { int a, b; }; union u1 f1(int);") + lib = verify(ffi, "test_function_returns_union", """ + union u1 { int a, b; }; + static union u1 f1(int x) { union u1 u; u.b = x; return u; } + """) + assert lib.f1(51).a == 51 + +def test_function_returns_partial_struct(): + ffi = FFI() + ffi.cdef("struct a { int a; ...; }; struct a f1(int);") + lib = verify(ffi, "test_function_returns_partial_struct", """ + struct a { int b, a, c; }; + static struct a f1(int x) { struct a s = {0}; s.a = x; return s; } + """) + assert lib.f1(52).a == 52 diff --git a/pypy/objspace/std/bytesobject.py b/pypy/objspace/std/bytesobject.py --- a/pypy/objspace/std/bytesobject.py +++ b/pypy/objspace/std/bytesobject.py @@ -466,8 +466,6 @@ def descr_getbuffer(self, space, w_flags): #from pypy.objspace.std.bufferobject import W_Buffer #return W_Buffer(StringBuffer(self._value)) - # XXX handle flags, figure out why returning a W_Buffer - # makes upstream ctypes tests fail return self charbuf_w = str_w diff --git a/pypy/objspace/std/intobject.py b/pypy/objspace/std/intobject.py --- a/pypy/objspace/std/intobject.py +++ b/pypy/objspace/std/intobject.py @@ -362,11 +362,10 @@ return _new_int(space, w_inttype, w_x, w_base) def descr_hash(self, space): - # unlike CPython, we don't special-case the value -1 in most of - # our hash functions, so there is not much sense special-casing - # it here either. Make sure this is consistent with the hash of - # floats and longs. - return self.int(space) + # For compatibility with CPython, we special-case -1 + h = self.intval + h -= (h == -1) # No explicit condition, to avoid JIT bridges + return wrapint(space, h) def _int(self, space): return self.int(space) diff --git a/pypy/objspace/std/longobject.py b/pypy/objspace/std/longobject.py --- a/pypy/objspace/std/longobject.py +++ b/pypy/objspace/std/longobject.py @@ -130,7 +130,12 @@ descr_repr = _make_descr_unaryop('repr') descr_str = _make_descr_unaryop('str') - descr_hash = _make_descr_unaryop('hash') + + def descr_hash(self, space): + h = self.asbigint().hash() + h -= (h == -1) + return space.newint(h) + descr_oct = _make_descr_unaryop('oct') descr_hex = _make_descr_unaryop('hex') @@ -387,12 +392,12 @@ def _make_generic_descr_binop(opname): if opname not in COMMUTATIVE_OPS: raise Exception("Not supported") - + methname = opname + '_' if opname in ('and', 'or') else opname descr_rname = 'descr_r' + opname op = getattr(rbigint, methname) intop = getattr(rbigint, "int_" + methname) - + @func_renamer('descr_' + opname) def descr_binop(self, space, w_other): if isinstance(w_other, W_AbstractIntObject): @@ -412,7 +417,7 @@ return W_LongObject(op(w_other.asbigint(), self.num)) return descr_binop, descr_rbinop - + descr_add, descr_radd = _make_generic_descr_binop('add') descr_sub, descr_rsub = _make_generic_descr_binop_noncommutative('sub') descr_mul, descr_rmul = _make_generic_descr_binop('mul') @@ -454,12 +459,12 @@ except OverflowError: # b too big raise oefmt(space.w_OverflowError, "shift count too large") return W_LongObject(self.num.lshift(shift)) - + def _int_lshift(self, space, w_other): if w_other < 0: raise oefmt(space.w_ValueError, "negative shift count") return W_LongObject(self.num.lshift(w_other)) - + descr_lshift, descr_rlshift = _make_descr_binop(_lshift, _int_lshift) def _rshift(self, space, w_other): @@ -470,7 +475,7 @@ except OverflowError: # b too big # XXX maybe just return 0L instead? raise oefmt(space.w_OverflowError, "shift count too large") return newlong(space, self.num.rshift(shift)) - + def _int_rshift(self, space, w_other): if w_other < 0: raise oefmt(space.w_ValueError, "negative shift count") @@ -485,7 +490,7 @@ raise oefmt(space.w_ZeroDivisionError, "long division or modulo by zero") return newlong(space, z) - + def _floordiv(self, space, w_other): try: z = self.num.floordiv(w_other.asbigint()) @@ -505,7 +510,7 @@ raise oefmt(space.w_ZeroDivisionError, "long division or modulo by zero") return newlong(space, z) - + def _int_mod(self, space, w_other): try: z = self.num.int_mod(w_other) diff --git a/pypy/objspace/std/test/test_intobject.py b/pypy/objspace/std/test/test_intobject.py --- a/pypy/objspace/std/test/test_intobject.py +++ b/pypy/objspace/std/test/test_intobject.py @@ -295,7 +295,11 @@ assert self.space.unwrap(result) == hex(x) -class AppTestInt: +class AppTestInt(object): + def test_hash(self): + assert hash(-1) == (-1).__hash__() == -2 + assert hash(-2) == (-2).__hash__() == -2 + def test_conjugate(self): assert (1).conjugate() == 1 assert (-1).conjugate() == -1 @@ -454,11 +458,11 @@ return None inst = a() raises(TypeError, int, inst) - assert inst.ar == True + assert inst.ar == True class b(object): - pass - raises((AttributeError,TypeError), int, b()) + pass + raises((AttributeError,TypeError), int, b()) def test_special_long(self): class a(object): diff --git a/pypy/objspace/std/test/test_longobject.py b/pypy/objspace/std/test/test_longobject.py --- a/pypy/objspace/std/test/test_longobject.py +++ b/pypy/objspace/std/test/test_longobject.py @@ -228,7 +228,7 @@ def test_hash(self): # ints have the same hash as equal longs for i in range(-4, 14): - assert hash(i) == hash(long(i)) + assert hash(i) == hash(long(i)) == long(i).__hash__() # might check too much -- it's ok to change the hashing algorithm assert hash(123456789L) == 123456789 assert hash(1234567890123456789L) in ( diff --git a/rpython/config/translationoption.py b/rpython/config/translationoption.py --- a/rpython/config/translationoption.py +++ b/rpython/config/translationoption.py @@ -261,6 +261,9 @@ "stack based virtual machines (only for backends that support it)", default=True), BoolOption("storesink", "Perform store sinking", default=True), + BoolOption("replace_we_are_jitted", + "Replace we_are_jitted() calls by False", + default=False, cmdline=None), BoolOption("none", "Do not run any backend optimizations", requires=[('translation.backendopt.inline', False), 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 @@ -833,9 +833,6 @@ result_adr = llmemory.cast_ptr_to_adr(struct.typeptr) return heaptracker.adr2int(result_adr) - def bh_new_raw_buffer(self, size): - return lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') - # vector operations vector_arith_code = """ def bh_vec_{0}_{1}(self, vx, vy, count): 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 @@ -757,9 +757,6 @@ self.write_int_at_mem(res, self.vtable_offset, WORD, sizedescr.get_vtable()) return res - def bh_new_raw_buffer(self, size): - return lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') - def bh_classof(self, struct): struct = lltype.cast_opaque_ptr(rclass.OBJECTPTR, struct) result_adr = llmemory.cast_ptr_to_adr(struct.typeptr) diff --git a/rpython/jit/backend/model.py b/rpython/jit/backend/model.py --- a/rpython/jit/backend/model.py +++ b/rpython/jit/backend/model.py @@ -229,8 +229,6 @@ raise NotImplementedError def bh_newunicode(self, length): raise NotImplementedError - def bh_new_raw_buffer(self, size): - raise NotImplementedError def bh_arraylen_gc(self, array, arraydescr): raise NotImplementedError diff --git a/rpython/jit/codewriter/support.py b/rpython/jit/codewriter/support.py --- a/rpython/jit/codewriter/support.py +++ b/rpython/jit/codewriter/support.py @@ -582,6 +582,14 @@ return lltype.malloc(ARRAY, n, flavor='raw', zero=zero, add_memory_pressure=add_memory_pressure, track_allocation=track_allocation) + name = '_ll_1_raw_malloc_varsize' + if zero: + name += '_zero' + if add_memory_pressure: + name += '_mpressure' + if not track_allocation: + name += '_notrack' + _ll_1_raw_malloc_varsize.func_name = name return _ll_1_raw_malloc_varsize return build_ll_1_raw_malloc_varsize @@ -610,6 +618,14 @@ return lltype.malloc(STRUCT, flavor='raw', zero=zero, add_memory_pressure=add_memory_pressure, track_allocation=track_allocation) + name = '_ll_0_raw_malloc_fixedsize' + if zero: + name += '_zero' + if add_memory_pressure: + name += '_mpressure' + if not track_allocation: + name += '_notrack' + _ll_0_raw_malloc_fixedsize.func_name = name return _ll_0_raw_malloc_fixedsize return build_ll_0_raw_malloc_fixedsize 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 @@ -367,8 +367,9 @@ class RawBufferPtrInfo(AbstractRawPtrInfo): buffer = None - - def __init__(self, cpu, size=-1): + + def __init__(self, cpu, func, size=-1): + self.func = func self.size = size if self.size != -1: self.buffer = RawBuffer(cpu, None) @@ -425,7 +426,8 @@ @specialize.argtype(1) def visitor_dispatch_virtual_type(self, visitor): buffer = self._get_buffer() - return visitor.visit_vrawbuffer(self.size, + return visitor.visit_vrawbuffer(self.func, + self.size, buffer.offsets[:], buffer.descrs[:]) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizeopt.py @@ -1770,7 +1770,7 @@ def test_virtual_raw_malloc_basic(self): ops = """ [i1] - i2 = call_i('malloc', 10, descr=raw_malloc_descr) + i2 = call_i(12345, 10, descr=raw_malloc_descr) # 12345 = malloc func guard_no_exception() [] setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) i3 = getarrayitem_raw_i(i2, 0, descr=rawarraydescr) @@ -1787,7 +1787,7 @@ ops = """ [i1] i5 = int_mul(10, 1) - i2 = call_i('malloc', i5, descr=raw_malloc_descr) + i2 = call_i(12345, i5, descr=raw_malloc_descr) guard_no_exception() [] setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) i3 = getarrayitem_raw_i(i2, 0, descr=rawarraydescr) @@ -1803,7 +1803,7 @@ def test_virtual_raw_malloc_force(self): ops = """ [i1] - i2 = call_i('malloc', 20, descr=raw_malloc_descr) + i2 = call_i(12345, 20, descr=raw_malloc_descr) guard_no_exception() [] setarrayitem_raw(i2, 0, i1, descr=rawarraydescr_char) setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) @@ -1817,7 +1817,7 @@ expected = """ [i1] label(i1) - i2 = call_i('malloc', 20, descr=raw_malloc_descr) + i2 = call_i(12345, 20, descr=raw_malloc_descr) check_memory_error(i2) raw_store(i2, 0, i1, descr=rawarraydescr_char) raw_store(i2, 1, 123, descr=rawarraydescr_char) @@ -1832,7 +1832,7 @@ def test_virtual_raw_malloc_invalid_write_force(self): ops = """ [i1] - i2 = call_i('malloc', 10, descr=raw_malloc_descr) + i2 = call_i(12345, 10, descr=raw_malloc_descr) guard_no_exception() [] setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) label(i1) # we expect the buffer to be forced *after* the label @@ -1843,7 +1843,7 @@ expected = """ [i1] label(i1) - i2 = call_i('malloc', 10, descr=raw_malloc_descr) + i2 = call_i(12345, 10, descr=raw_malloc_descr) check_memory_error(i2) raw_store(i2, 0, i1, descr=rawarraydescr) setarrayitem_raw(i2, 2, 456, descr=rawarraydescr_char) @@ -1855,7 +1855,7 @@ def test_virtual_raw_malloc_invalid_read_force(self): ops = """ [i1] - i2 = call_i('malloc', 10, descr=raw_malloc_descr) + i2 = call_i(12345, 10, descr=raw_malloc_descr) guard_no_exception() [] setarrayitem_raw(i2, 0, i1, descr=rawarraydescr) label(i1) # we expect the buffer to be forced *after* the label @@ -1866,7 +1866,7 @@ expected = """ [i1] label(i1) - i2 = call_i('malloc', 10, descr=raw_malloc_descr) + i2 = call_i(12345, 10, descr=raw_malloc_descr) check_memory_error(i2) raw_store(i2, 0, i1, descr=rawarraydescr) i3 = getarrayitem_raw_i(i2, 0, descr=rawarraydescr_char) @@ -1878,7 +1878,7 @@ def test_virtual_raw_slice(self): ops = """ [i0, i1] - i2 = call_i('malloc', 10, descr=raw_malloc_descr) + i2 = call_i(12345, 10, descr=raw_malloc_descr) guard_no_exception() [] setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char) i3 = int_add(i2, 1) # get a slice of the original buffer @@ -1898,7 +1898,7 @@ def test_virtual_raw_slice_of_a_raw_slice(self): ops = """ [i0, i1] - i2 = call_i('malloc', 10, descr=raw_malloc_descr) + i2 = call_i(12345, 10, descr=raw_malloc_descr) guard_no_exception() [] i3 = int_add(i2, 1) # get a slice of the original buffer i4 = int_add(i3, 1) # get a slice of a slice @@ -1916,7 +1916,7 @@ def test_virtual_raw_slice_force(self): ops = """ [i0, i1] - i2 = call_i('malloc', 10, descr=raw_malloc_descr) + i2 = call_i(12345, 10, descr=raw_malloc_descr) guard_no_exception() [] setarrayitem_raw(i2, 0, 42, descr=rawarraydescr_char) i3 = int_add(i2, 1) # get a slice of the original buffer @@ -1929,7 +1929,7 @@ [i0, i1] label(i0, i1) # these ops are generated by VirtualRawBufferValue._really_force - i2 = call_i('malloc', 10, descr=raw_malloc_descr) + i2 = call_i(12345, 10, descr=raw_malloc_descr) check_memory_error(i2) raw_store(i2, 0, 42, descr=rawarraydescr_char) raw_store(i2, 5, 4242, descr=rawarraydescr_char) @@ -1946,7 +1946,7 @@ i1 = getarrayitem_raw_i(i0, 0, descr=rawarraydescr) i2 = int_add(i1, 1) call_n('free', i0, descr=raw_free_descr) - i3 = call_i('malloc', 10, descr=raw_malloc_descr) + i3 = call_i(12345, 10, descr=raw_malloc_descr) guard_no_exception() [] setarrayitem_raw(i3, 0, i2, descr=rawarraydescr) label(i2) @@ -1958,7 +1958,7 @@ i2 = int_add(i1, 1) call_n('free', i0, descr=raw_free_descr) label(i2) - i3 = call_i('malloc', 10, descr=raw_malloc_descr) + i3 = call_i(12345, 10, descr=raw_malloc_descr) check_memory_error(i3) raw_store(i3, 0, i2, descr=rawarraydescr) jump(i3) @@ -1968,7 +1968,7 @@ def test_virtual_raw_store_raw_load(self): ops = """ [i1] - i0 = call_i('malloc', 10, descr=raw_malloc_descr) + i0 = call_i(12345, 10, descr=raw_malloc_descr) guard_no_exception() [] raw_store(i0, 0, i1, descr=rawarraydescr) i2 = raw_load_i(i0, 0, descr=rawarraydescr) @@ -1986,7 +1986,7 @@ def test_virtual_raw_store_getarrayitem_raw(self): ops = """ [f1] - i0 = call_i('malloc', 16, descr=raw_malloc_descr) + i0 = call_i(12345, 16, descr=raw_malloc_descr) guard_no_exception() [] raw_store(i0, 8, f1, descr=rawarraydescr_float) f2 = getarrayitem_raw_f(i0, 1, descr=rawarraydescr_float) @@ -2004,7 +2004,7 @@ def test_virtual_setarrayitem_raw_raw_load(self): ops = """ [f1] - i0 = call_i('malloc', 16, descr=raw_malloc_descr) + i0 = call_i(12345, 16, descr=raw_malloc_descr) guard_no_exception() [] setarrayitem_raw(i0, 1, f1, descr=rawarraydescr_float) f2 = raw_load_f(i0, 8, descr=rawarraydescr_float) @@ -2022,7 +2022,7 @@ def test_virtual_raw_buffer_forced_but_slice_not_forced(self): ops = """ [f1] - i0 = call_i('malloc', 16, descr=raw_malloc_descr) + i0 = call_i(12345, 16, descr=raw_malloc_descr) guard_no_exception() [] i1 = int_add(i0, 8) escape_n(i0) @@ -2031,7 +2031,7 @@ """ expected = """ [f1] - i0 = call_i('malloc', 16, descr=raw_malloc_descr) + i0 = call_i(12345, 16, descr=raw_malloc_descr) check_memory_error(i0) escape_n(i0) i1 = int_add(i0, 8) @@ -8886,7 +8886,7 @@ def test_resume_forced_raw_ptr(self): ops = """ [i0] - i = call_i('malloc', 10, descr=raw_malloc_descr) + i = call_i(12345, 10, descr=raw_malloc_descr) guard_no_exception() [] is = int_add(i, 8) escape_n(i) @@ -8898,7 +8898,7 @@ """ expected = """ [i0] - i = call_i('malloc', 10, descr=raw_malloc_descr) + i = call_i(12345, 10, descr=raw_malloc_descr) check_memory_error(i) escape_n(i) i1 = int_add(i0, 1) @@ -8966,7 +8966,7 @@ def test_pending_setfield_delayed_malloc(self): ops = """ [i0, p0] - i2 = call_i('malloc', 10, descr=raw_malloc_descr) + i2 = call_i(12345, 10, descr=raw_malloc_descr) guard_no_exception() [] setarrayitem_raw(i2, 0, 13, descr=rawarraydescr) setfield_gc(p0, i2, descr=valuedescr) @@ -8988,14 +8988,14 @@ def test_raw_buffer_ptr_info_intbounds_bug(self): ops = """ [] - i2 = call_i('malloc', 10, descr=raw_malloc_descr) + i2 = call_i(12345, 10, descr=raw_malloc_descr) guard_no_exception() [] guard_value(i2, 12345) [] jump() """ expected = """ [] - i2 = call_i('malloc', 10, descr=raw_malloc_descr) + i2 = call_i(12345, 10, descr=raw_malloc_descr) check_memory_error(i2) guard_value(i2, 12345) [] jump() 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 @@ -45,7 +45,8 @@ return opinfo def make_virtual_raw_memory(self, size, source_op): - opinfo = info.RawBufferPtrInfo(self.optimizer.cpu, size) + func = source_op.getarg(0).getint() + opinfo = info.RawBufferPtrInfo(self.optimizer.cpu, func, size) newop = self.replace_op_with(source_op, source_op.getopnum(), args=[source_op.getarg(0), ConstInt(size)]) newop.set_forwarded(opinfo) diff --git a/rpython/jit/metainterp/resume.py b/rpython/jit/metainterp/resume.py --- a/rpython/jit/metainterp/resume.py +++ b/rpython/jit/metainterp/resume.py @@ -364,8 +364,8 @@ def visit_varraystruct(self, arraydescr, size, fielddescrs): return VArrayStructInfo(arraydescr, size, fielddescrs) - def visit_vrawbuffer(self, size, offsets, descrs): - return VRawBufferInfo(size, offsets, descrs) + def visit_vrawbuffer(self, func, size, offsets, descrs): + return VRawBufferInfo(func, size, offsets, descrs) def visit_vrawslice(self, offset): return VRawSliceInfo(offset) @@ -703,7 +703,8 @@ class VRawBufferInfo(VAbstractRawInfo): - def __init__(self, size, offsets, descrs): + def __init__(self, func, size, offsets, descrs): + self.func = func self.size = size self.offsets = offsets self.descrs = descrs @@ -711,7 +712,7 @@ @specialize.argtype(1) def allocate_int(self, decoder, index): length = len(self.fieldnums) - buffer = decoder.allocate_raw_buffer(self.size) + buffer = decoder.allocate_raw_buffer(self.func, self.size) decoder.virtuals_cache.set_int(index, buffer) for i in range(len(self.offsets)): offset = self.offsets[i] @@ -1130,9 +1131,13 @@ lengthbox) return self.metainterp.execute_new_array(arraydescr, lengthbox) - def allocate_raw_buffer(self, size): + def allocate_raw_buffer(self, func, size): cic = self.metainterp.staticdata.callinfocollection - calldescr, func = cic.callinfo_for_oopspec(EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR) + calldescr, _ = cic.callinfo_for_oopspec(EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR) + # Can't use 'func' from callinfo_for_oopspec(), because we have + # several variants (zero/non-zero, memory-pressure or not, etc.) + # and we have to pick the correct one here; that's why we save + # it in the VRawBufferInfo. return self.metainterp.execute_and_record_varargs( rop.CALL_I, [ConstInt(func), ConstInt(size)], calldescr) @@ -1461,10 +1466,11 @@ def allocate_string(self, length): return self.cpu.bh_newstr(length) - def allocate_raw_buffer(self, size): - buffer = self.cpu.bh_new_raw_buffer(size) - adr = llmemory.cast_ptr_to_adr(buffer) - return llmemory.cast_adr_to_int(adr, "symbolic") + def allocate_raw_buffer(self, func, size): + from rpython.jit.codewriter import heaptracker + cic = self.callinfocollection + calldescr, _ = cic.callinfo_for_oopspec(EffectInfo.OS_RAW_MALLOC_VARSIZE_CHAR) + return self.cpu.bh_call_i(func, [size], None, None, calldescr) def string_setitem(self, str, index, charnum): char = self.decode_int(charnum) diff --git a/rpython/jit/metainterp/walkvirtual.py b/rpython/jit/metainterp/walkvirtual.py --- a/rpython/jit/metainterp/walkvirtual.py +++ b/rpython/jit/metainterp/walkvirtual.py @@ -17,7 +17,7 @@ def visit_varraystruct(self, arraydescr, fielddescrs): raise NotImplementedError("abstract base class") - def visit_vrawbuffer(self, size, offsets, descrs): + def visit_vrawbuffer(self, func, size, offsets, descrs): raise NotImplementedError("abstract base class") def visit_vrawslice(self, offset): diff --git a/rpython/jit/metainterp/warmspot.py b/rpython/jit/metainterp/warmspot.py --- a/rpython/jit/metainterp/warmspot.py +++ b/rpython/jit/metainterp/warmspot.py @@ -452,7 +452,8 @@ merge_if_blocks=True, constfold=True, remove_asserts=True, - really_remove_asserts=True) + really_remove_asserts=True, + replace_we_are_jitted=False) def prejit_optimizations_minimal_inline(self, policy, graphs): from rpython.translator.backendopt.inline import auto_inline_graphs diff --git a/rpython/rlib/rmmap.py b/rpython/rlib/rmmap.py --- a/rpython/rlib/rmmap.py +++ b/rpython/rlib/rmmap.py @@ -799,8 +799,8 @@ rffi.cast(size_t, map_size), rffi.cast(rffi.INT, use_flag)) else: - def madvice_free(addr, map_size): - "No madvice() on this platform" + def madvise_free(addr, map_size): + "No madvise() on this platform" elif _MS_WINDOWS: def mmap(fileno, length, tagname="", access=_ACCESS_DEFAULT, offset=0): diff --git a/rpython/rlib/rposix.py b/rpython/rlib/rposix.py --- a/rpython/rlib/rposix.py +++ b/rpython/rlib/rposix.py @@ -250,6 +250,7 @@ OFF_T_SIZE = rffi_platform.SizeOf('off_t') HAVE_UTIMES = rffi_platform.Has('utimes') + HAVE_D_TYPE = rffi_platform.Has('DT_UNKNOWN') UTIMBUF = rffi_platform.Struct('struct %sutimbuf' % UNDERSCORE_ON_WIN32, [('actime', rffi.INT), ('modtime', rffi.INT)]) @@ -603,23 +604,34 @@ class CConfig: _compilation_info_ = eci DIRENT = rffi_platform.Struct('struct dirent', - [('d_name', lltype.FixedSizeArray(rffi.CHAR, 1))]) + [('d_name', lltype.FixedSizeArray(rffi.CHAR, 1))] + + [('d_type', rffi.INT)] if HAVE_D_TYPE else []) + if HAVE_D_TYPE: + DT_UNKNOWN = rffi_platform.ConstantInteger('DT_UNKNOWN') + DT_REG = rffi_platform.ConstantInteger('DT_REG') + DT_DIR = rffi_platform.ConstantInteger('DT_DIR') + DT_LNK = rffi_platform.ConstantInteger('DT_LNK') DIRP = rffi.COpaquePtr('DIR') - config = rffi_platform.configure(CConfig) - DIRENT = config['DIRENT'] + dirent_config = rffi_platform.configure(CConfig) + DIRENT = dirent_config['DIRENT'] DIRENTP = lltype.Ptr(DIRENT) c_opendir = external('opendir', [rffi.CCHARP], DIRP, save_err=rffi.RFFI_SAVE_ERRNO) c_fdopendir = external('fdopendir', [rffi.INT], DIRP, save_err=rffi.RFFI_SAVE_ERRNO) + c_rewinddir = external('rewinddir', + [DIRP], lltype.Void, releasegil=False) # XXX macro=True is hack to make sure we get the correct kind of # dirent struct (which depends on defines) c_readdir = external('readdir', [DIRP], DIRENTP, macro=True, save_err=rffi.RFFI_FULL_ERRNO_ZERO) - c_closedir = external('closedir', [DIRP], rffi.INT) + c_closedir = external('closedir', [DIRP], rffi.INT, releasegil=False) + c_dirfd = external('dirfd', [DIRP], rffi.INT, releasegil=False) +else: + dirent_config = {} -def _listdir(dirp): +def _listdir(dirp, rewind=False): result = [] while True: direntp = c_readdir(dirp) @@ -630,6 +642,8 @@ name = rffi.charp2str(namep) if name != '.' and name != '..': result.append(name) + if rewind: + c_rewinddir(dirp) c_closedir(dirp) if error: raise OSError(error, "readdir failed") @@ -640,12 +654,16 @@ Like listdir(), except that the directory is specified as an open file descriptor. - Note: fdlistdir() closes the file descriptor. + Note: fdlistdir() closes the file descriptor. To emulate the + Python 3.x 'os.opendir(dirfd)', you must first duplicate the + file descriptor. """ dirp = c_fdopendir(dirfd) if not dirp: - raise OSError(get_saved_errno(), "opendir failed") - return _listdir(dirp) + error = get_saved_errno() + c_close(dirfd) + raise OSError(error, "opendir failed") + return _listdir(dirp, rewind=True) @replace_os_function('listdir') @specialize.argtype(0) @@ -1782,12 +1800,7 @@ # Support for f... and ...at families of POSIX functions class CConfig: - _compilation_info_ = ExternalCompilationInfo( - includes=['sys/stat.h', - 'sys/time.h', - 'unistd.h', - 'fcntl.h'], - ) + _compilation_info_ = eci for _name in """faccessat fchdir fchmod fchmodat fchown fchownat fexecve fdopendir fpathconf fstat fstatat fstatvfs ftruncate futimens futimes futimesat linkat chflags lchflags lchmod lchown diff --git a/rpython/rlib/rposix_scandir.py b/rpython/rlib/rposix_scandir.py new file mode 100644 --- /dev/null +++ b/rpython/rlib/rposix_scandir.py @@ -0,0 +1,52 @@ +from rpython.rlib import rposix +from rpython.rlib.objectmodel import specialize +from rpython.rtyper.lltypesystem import lltype, rffi + + +@specialize.argtype(0) +def opendir(path): + path = rposix._as_bytes0(path) + return opendir_bytes(path) + +def opendir_bytes(path): + dirp = rposix.c_opendir(path) + if not dirp: + raise OSError(rposix.get_saved_errno(), "opendir failed") + return dirp + +def closedir(dirp): + rposix.c_closedir(dirp) + +NULL_DIRP = lltype.nullptr(rposix.DIRP.TO) + +def nextentry(dirp): + """Read the next entry and returns an opaque object. + Use the methods has_xxx() and get_xxx() to read from that + opaque object. The opaque object is valid until the next + time nextentry() or closedir() is called. This may raise + OSError, or return a NULL pointer when exhausted. Note + that this doesn't filter out the "." and ".." entries. + """ + direntp = rposix.c_readdir(dirp) + if direntp: + error = rposix.get_saved_errno() + if error: + raise OSError(error, "readdir failed") + return direntp + +def has_name_bytes(direntp): + return True + +def get_name_bytes(direntp): + namep = rffi.cast(rffi.CCHARP, direntp.c_d_name) + return rffi.charp2str(namep) + +DT_UNKNOWN = rposix.dirent_config.get('DT_UNKNOWN', 0) +DT_REG = rposix.dirent_config.get('DT_REG', 255) +DT_DIR = rposix.dirent_config.get('DT_DIR', 255) +DT_LNK = rposix.dirent_config.get('DT_LNK', 255) + +def get_known_type(direntp): + if rposix.HAVE_D_TYPE: + return rffi.getintfield(direntp, 'c_d_type') + return DT_UNKNOWN diff --git a/rpython/rlib/rvmprof/rvmprof.py b/rpython/rlib/rvmprof/rvmprof.py --- a/rpython/rlib/rvmprof/rvmprof.py +++ b/rpython/rlib/rvmprof/rvmprof.py @@ -90,6 +90,9 @@ CodeClass._vmprof_unique_id = 0 # default value: "unknown" immut = CodeClass.__dict__.get('_immutable_fields_', []) CodeClass._immutable_fields_ = list(immut) + ['_vmprof_unique_id'] + attrs = CodeClass.__dict__.get('_attrs_', None) + if attrs is not None: + CodeClass._attrs_ = list(attrs) + ['_vmprof_unique_id'] self._code_classes.add(CodeClass) # class WeakCodeObjectList(RWeakListMixin): @@ -189,7 +192,7 @@ def decorated_function(*args): unique_id = get_code_fn(*args)._vmprof_unique_id - unique_id = rffi.cast(lltype.Signed, unique_id) + unique_id = rffi.cast(lltype.Signed, unique_id) # ^^^ removes the "known non-negative" hint for annotation if not jit.we_are_jitted(): x = enter_code(unique_id) 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 @@ -552,6 +552,14 @@ # Note: fdlistdir() always closes dirfd assert result == ['file'] +@rposix_requires('fdlistdir') +def test_fdlistdir_rewinddir(tmpdir): + tmpdir.join('file').write('text') + dirfd = os.open(str(tmpdir), os.O_RDONLY) + result1 = rposix.fdlistdir(os.dup(dirfd)) + result2 = rposix.fdlistdir(dirfd) + assert result1 == result2 == ['file'] + @rposix_requires('symlinkat') def test_symlinkat(tmpdir): tmpdir.join('file').write('text') diff --git a/rpython/rlib/test/test_rposix_scandir.py b/rpython/rlib/test/test_rposix_scandir.py new file mode 100644 --- /dev/null +++ b/rpython/rlib/test/test_rposix_scandir.py @@ -0,0 +1,21 @@ +import sys, os +import py +from rpython.rlib import rposix_scandir + + +class TestScanDir(object): + + @py.test.mark.skipif("sys.platform == 'win32'") # XXX + def test_name_bytes(self): + scan = rposix_scandir.opendir('/') + found = [] + while True: + p = rposix_scandir.nextentry(scan) + if not p: + break + assert rposix_scandir.has_name_bytes(p) + found.append(rposix_scandir.get_name_bytes(p)) + rposix_scandir.closedir(scan) + found.remove('.') + found.remove('..') + assert sorted(found) == sorted(os.listdir('/')) 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 @@ -648,6 +648,7 @@ @staticmethod @jit.elidable + @signature(types.any(), types.any(), types.int(), types.int(), returns=types.int()) def ll_rfind_char(s, ch, start, end): if end > len(s.chars): end = len(s.chars) diff --git a/rpython/translator/backendopt/all.py b/rpython/translator/backendopt/all.py --- a/rpython/translator/backendopt/all.py +++ b/rpython/translator/backendopt/all.py @@ -2,6 +2,7 @@ from rpython.translator.backendopt import inline from rpython.translator.backendopt.malloc import remove_mallocs from rpython.translator.backendopt.constfold import constant_fold_graph +from rpython.translator.backendopt.constfold import replace_we_are_jitted from rpython.translator.backendopt.stat import print_statistics from rpython.translator.backendopt.merge_if_blocks import merge_if_blocks from rpython.translator import simplify @@ -36,6 +37,7 @@ # inline_threshold, mallocs # merge_if_blocks, constfold, heap2stack # clever_malloc_removal, remove_asserts + # replace_we_are_jitted config = translator.config.translation.backendopt.copy(as_default=True) config.set(**kwds) @@ -49,6 +51,10 @@ print "before optimizations:" print_statistics(translator.graphs[0], translator, "per-graph.txt") + if config.replace_we_are_jitted: + for graph in graphs: + replace_we_are_jitted(graph) + if config.remove_asserts: constfold(config, graphs) remove_asserts(translator, graphs) diff --git a/rpython/translator/backendopt/constfold.py b/rpython/translator/backendopt/constfold.py --- a/rpython/translator/backendopt/constfold.py +++ b/rpython/translator/backendopt/constfold.py @@ -276,3 +276,25 @@ rewire_links(splitblocks, graph) if not diffused and not splitblocks: break # finished + +def replace_symbolic(graph, symbolic, value): + result = False + for block in graph.iterblocks(): + for op in block.operations: + for i, arg in enumerate(op.args): + if isinstance(arg, Constant) and arg.value is symbolic: + op.args[i] = value + result = True + if block.exitswitch is symbolic: + block.exitswitch = value + result = True + return result + +def replace_we_are_jitted(graph): + from rpython.rlib import jit + replacement = Constant(0) + replacement.concretetype = lltype.Signed + did_replacement = replace_symbolic(graph, jit._we_are_jitted, replacement) + if did_replacement: + constant_fold_graph(graph) + return did_replacement diff --git a/rpython/translator/backendopt/test/test_all.py b/rpython/translator/backendopt/test/test_all.py --- a/rpython/translator/backendopt/test/test_all.py +++ b/rpython/translator/backendopt/test/test_all.py @@ -289,3 +289,19 @@ llinterp = LLInterpreter(t.rtyper) res = llinterp.eval_graph(later_graph, [10]) assert res == 1 + + def test_replace_we_are_jitted(self): + from rpython.rlib import jit + def f(): + if jit.we_are_jitted(): + return 1 + return 2 + jit.we_are_jitted() + + t = self.translateopt(f, []) + graph = graphof(t, f) + # by default, replace_we_are_jitted is off + assert graph.startblock.operations[0].args[0].value is jit._we_are_jitted + + t = self.translateopt(f, [], replace_we_are_jitted=True) + graph = graphof(t, f) + assert graph.startblock.exits[0].args[0].value == 2 diff --git a/rpython/translator/backendopt/test/test_constfold.py b/rpython/translator/backendopt/test/test_constfold.py --- a/rpython/translator/backendopt/test/test_constfold.py +++ b/rpython/translator/backendopt/test/test_constfold.py @@ -7,6 +7,7 @@ from rpython.rtyper import rclass from rpython.rlib import objectmodel from rpython.translator.backendopt.constfold import constant_fold_graph +from rpython.translator.backendopt.constfold import replace_we_are_jitted from rpython.conftest import option def get_graph(fn, signature): @@ -343,3 +344,18 @@ merge_if_blocks.merge_if_blocks_once(graph) constant_fold_graph(graph) check_graph(graph, [], 66, t) + +def test_replace_we_are_jitted(): + from rpython.rlib import jit + def fn(): + if jit.we_are_jitted(): + return 1 + return 2 + jit.we_are_jitted() + graph, t = get_graph(fn, []) + result = replace_we_are_jitted(graph) + assert result + checkgraph(graph) + # check shape of graph + assert len(graph.startblock.operations) == 0 + assert graph.startblock.exitswitch is None + assert graph.startblock.exits[0].target.exits[0].args[0].value == 2 diff --git a/rpython/translator/driver.py b/rpython/translator/driver.py --- a/rpython/translator/driver.py +++ b/rpython/translator/driver.py @@ -381,7 +381,7 @@ """ Run all backend optimizations - lltype version """ from rpython.translator.backendopt.all import backend_optimizations - backend_optimizations(self.translator) + backend_optimizations(self.translator, replace_we_are_jitted=True) STACKCHECKINSERTION = 'stackcheckinsertion_lltype' diff --git a/rpython/translator/test/test_interactive.py b/rpython/translator/test/test_interactive.py --- a/rpython/translator/test/test_interactive.py +++ b/rpython/translator/test/test_interactive.py @@ -78,3 +78,15 @@ dll = ctypes.CDLL(str(t.driver.c_entryp)) f = dll.pypy_g_f assert f(2, 3) == 5 + +def test_check_that_driver_uses_replace_we_are_jitted(): + from rpython.rlib import jit + def f(): + if jit.we_are_jitted(): + return 1 + return 2 + jit.we_are_jitted() + + t = Translation(f, []) + t.backendopt() + graph = t.driver.translator.graphs[0] + assert graph.startblock.exits[0].args[0].value == 2 _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit