Author: Maciej Fijalkowski <fij...@gmail.com> Branch: Changeset: r76114:6d8fc302e70c Date: 2015-02-24 20:14 +0200 http://bitbucket.org/pypy/pypy/changeset/6d8fc302e70c/
Log: merge diff --git a/pypy/module/_rawffi/array.py b/pypy/module/_rawffi/array.py --- a/pypy/module/_rawffi/array.py +++ b/pypy/module/_rawffi/array.py @@ -15,7 +15,7 @@ from pypy.module._rawffi.interp_rawffi import unpack_shape_with_length from pypy.module._rawffi.interp_rawffi import read_ptr, write_ptr from rpython.rlib.rarithmetic import r_uint -from rpython.rlib import rgc +from rpython.rlib import rgc, clibffi class W_Array(W_DataShape): @@ -84,14 +84,11 @@ class W_ArrayInstance(W_DataInstance): def __init__(self, space, shape, length, address=r_uint(0)): - # Workaround for a strange behavior of libffi: make sure that - # we always have at least 8 bytes. For W_ArrayInstances that are - # used as the result value of a function call, ffi_call() writes - # 8 bytes into it even if the function's result type asks for less. - # This strange behavior is documented. memsize = shape.size * length - if memsize < 8: - memsize = 8 + # For W_ArrayInstances that are used as the result value of a + # function call, ffi_call() writes 8 bytes into it even if the + # function's result type asks for less. + memsize = clibffi.adjust_return_size(memsize) W_DataInstance.__init__(self, space, memsize, address) self.length = length self.shape = shape diff --git a/pypy/module/_rawffi/interp_rawffi.py b/pypy/module/_rawffi/interp_rawffi.py --- a/pypy/module/_rawffi/interp_rawffi.py +++ b/pypy/module/_rawffi/interp_rawffi.py @@ -495,6 +495,7 @@ try: if self.resshape is not None: result = self.resshape.allocate(space, 1, autofree=True) + # adjust_return_size() was used here on result.ll_buffer self.ptr.call(args_ll, result.ll_buffer) return space.wrap(result) else: 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 @@ -199,10 +199,6 @@ self._clear_caches_arraycopy(opnum, descr, argboxes, effectinfo) return else: - # first escape arguments: - for argbox in argboxes: - self._escape_box(argbox) - # Only invalidate things that are escaped # XXX can do better, only do it for the descrs in the effectinfo for descr, cache in self.heap_cache.iteritems(): diff --git a/rpython/jit/metainterp/optimizeopt/intbounds.py b/rpython/jit/metainterp/optimizeopt/intbounds.py --- a/rpython/jit/metainterp/optimizeopt/intbounds.py +++ b/rpython/jit/metainterp/optimizeopt/intbounds.py @@ -495,19 +495,15 @@ if v2.getintbound().intersect(v1.getintbound()): self.propagate_bounds_backward(op.getarg(1)) - def propagate_bounds_INT_IS_TRUE(self, op): + def _propagate_int_is_true_or_zero(self, op, constnonzero, constzero): r = self.getvalue(op.result) if r.is_constant(): - if r.box.same_constant(CONST_1): + if r.box.same_constant(constnonzero): v1 = self.getvalue(op.getarg(0)) if v1.getintbound().known_ge(IntBound(0, 0)): v1.getintbound().make_gt(IntBound(0, 0)) self.propagate_bounds_backward(op.getarg(0)) - - def propagate_bounds_INT_IS_ZERO(self, op): - r = self.getvalue(op.result) - if r.is_constant(): - if r.box.same_constant(CONST_1): + elif r.box.same_constant(constzero): v1 = self.getvalue(op.getarg(0)) # Clever hack, we can't use self.make_constant_int yet because # the args aren't in the values dictionary yet so it runs into @@ -516,6 +512,12 @@ v1.getintbound().make_lt(IntBound(1, 1)) self.propagate_bounds_backward(op.getarg(0)) + def propagate_bounds_INT_IS_TRUE(self, op): + self._propagate_int_is_true_or_zero(op, CONST_1, CONST_0) + + def propagate_bounds_INT_IS_ZERO(self, op): + self._propagate_int_is_true_or_zero(op, CONST_0, CONST_1) + def propagate_bounds_INT_ADD(self, op): v1 = self.getvalue(op.getarg(0)) v2 = self.getvalue(op.getarg(1)) diff --git a/rpython/jit/metainterp/optimizeopt/intutils.py b/rpython/jit/metainterp/optimizeopt/intutils.py --- a/rpython/jit/metainterp/optimizeopt/intutils.py +++ b/rpython/jit/metainterp/optimizeopt/intutils.py @@ -252,42 +252,21 @@ guards.append(op) -class IntUpperBound(IntBound): - def __init__(self, upper): - self.has_upper = True - self.has_lower = False - self.upper = upper - self.lower = 0 +def IntUpperBound(upper): + b = IntBound(lower=0, upper=upper) + b.has_lower = False + return b -class IntLowerBound(IntBound): - def __init__(self, lower): - self.has_upper = False - self.has_lower = True - self.upper = 0 - self.lower = lower +def IntLowerBound(lower): + b = IntBound(upper=0, lower=lower) + b.has_upper = False + return b -class IntUnbounded(IntBound): - def __init__(self): - self.has_upper = False - self.has_lower = False - self.upper = 0 - self.lower = 0 - -class ImmutableIntUnbounded(IntUnbounded): - def _raise(self): - raise TypeError('ImmutableIntUnbounded is immutable') - def make_le(self, other): - self._raise() - def make_lt(self, other): - self._raise() - def make_ge(self, other): - self._raise() - def make_gt(self, other): - self._raise() - def make_constant(self, value): - self._raise() - def intersect(self, other): - self._raise() +def IntUnbounded(): + b = IntBound(upper=0, lower=0) + b.has_lower = False + b.has_upper = False + return b def min4(t): return min(min(t[0], t[1]), min(t[2], t[3])) diff --git a/rpython/jit/metainterp/optimizeopt/optimizer.py b/rpython/jit/metainterp/optimizeopt/optimizer.py --- a/rpython/jit/metainterp/optimizeopt/optimizer.py +++ b/rpython/jit/metainterp/optimizeopt/optimizer.py @@ -3,7 +3,6 @@ from rpython.jit.metainterp.history import BoxInt, BoxFloat, Const, ConstInt,\ REF, BoxPtr, ConstPtr, ConstFloat from rpython.jit.metainterp.optimizeopt.intutils import IntBound, IntUnbounded,\ - ImmutableIntUnbounded, \ IntLowerBound, MININT,\ MAXINT from rpython.jit.metainterp.optimizeopt.util import make_dispatcher_method @@ -60,6 +59,17 @@ self.make_constant(box) # invariant: box is a Const if and only if level == LEVEL_CONSTANT + def __repr__(self): + level = {LEVEL_UNKNOWN: 'UNKNOWN', + LEVEL_NONNULL: 'NONNULL', + LEVEL_KNOWNCLASS: 'KNOWNCLASS', + LEVEL_CONSTANT: 'CONSTANT'}.get(self.getlevel(), + self.getlevel()) + return '<%s %s %s>' % ( + self.__class__.__name__, + level, + self.box) + def getlevel(self): return self._tag & 0x3 @@ -323,19 +333,17 @@ class IntOptValue(OptValue): _attrs_ = ('intbound',) - intbound = ImmutableIntUnbounded() - def __init__(self, box, level=None, known_class=None, intbound=None): OptValue.__init__(self, box, level, None, None) if isinstance(box, Const): + value = box.getint() + self.intbound = IntBound(value, value) return if intbound: self.intbound = intbound else: - if isinstance(box, BoxInt): - self.intbound = IntBound(MININT, MAXINT) - else: - self.intbound = IntUnbounded() + assert isinstance(box, BoxInt) + self.intbound = IntBound(MININT, MAXINT) def copy_from(self, other_value): assert isinstance(other_value, IntOptValue) diff --git a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py --- a/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py +++ b/rpython/jit/metainterp/optimizeopt/test/test_optimizebasic.py @@ -512,7 +512,7 @@ [i] i1 = int_is_true(i) guard_false(i1) [i] - jump(i) + jump(0) """ self.optimize_loop(ops, expected) @@ -4774,6 +4774,25 @@ """ self.optimize_strunicode_loop(ops, expected) + def test_int_is_zero_bounds(self): + ops = """ + [p0] + i0 = strlen(p0) + i1 = int_is_zero(i0) + guard_false(i1) [] + i2 = int_ge(0, i0) + guard_false(i2) [] + jump(p0) + """ + expected = """ + [p0] + i0 = strlen(p0) + i1 = int_is_zero(i0) + guard_false(i1) [] + jump(p0) + """ + self.optimize_strunicode_loop(ops, expected) + def test_strslice_subtraction_folds(self): ops = """ [p0, i0] 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 @@ -669,11 +669,11 @@ [i] i1 = int_is_true(i) guard_false(i1) [i] - jump(i) - """ - expected = """ - [i] - jump(i) + jump() + """ + expected = """ + [] + jump() """ self.optimize_loop(ops, expected, preamble) diff --git a/rpython/rlib/clibffi.py b/rpython/rlib/clibffi.py --- a/rpython/rlib/clibffi.py +++ b/rpython/rlib/clibffi.py @@ -564,6 +564,7 @@ self.funcsym = funcsym def call(self, args_ll, ll_result): + # adjust_return_size() should always be used here on ll_result assert len(args_ll) == len(self.argtypes), ( "wrong number of arguments in call to %s(): " "%d instead of %d" % (self.name, len(args_ll), len(self.argtypes))) @@ -594,8 +595,8 @@ intmask(argtypes[i].c_size), flavor='raw') if restype != ffi_type_void: - self.ll_result = lltype.malloc(rffi.VOIDP.TO, - intmask(restype.c_size), + size = adjust_return_size(intmask(restype.c_size)) + self.ll_result = lltype.malloc(rffi.VOIDP.TO, size, flavor='raw') def push_arg(self, value): @@ -693,3 +694,12 @@ dlclose(self.lib) self.lib = rffi.cast(DLLHANDLE, -1) + +def adjust_return_size(memsize): + # Workaround for a strange behavior of libffi: make sure that + # we always have at least 8 bytes. ffi_call() writes 8 bytes + # into the buffer even if the function's result type asks for + # less. This strange behavior is documented. + if memsize < 8: + memsize = 8 + return memsize diff --git a/rpython/rlib/libffi.py b/rpython/rlib/libffi.py --- a/rpython/rlib/libffi.py +++ b/rpython/rlib/libffi.py @@ -9,7 +9,8 @@ from rpython.rlib import jit from rpython.rlib import clibffi from rpython.rlib.clibffi import FUNCFLAG_CDECL, FUNCFLAG_STDCALL, \ - AbstractFuncPtr, push_arg_as_ffiptr, c_ffi_call, FFI_TYPE_STRUCT + AbstractFuncPtr, push_arg_as_ffiptr, c_ffi_call, FFI_TYPE_STRUCT, \ + adjust_return_size from rpython.rlib.rdynload import dlopen, dlclose, dlsym, dlsym_byordinal from rpython.rlib.rdynload import DLLHANDLE @@ -369,8 +370,8 @@ # XXX: check len(args)? ll_result = lltype.nullptr(rffi.CCHARP.TO) if self.restype != types.void: - ll_result = lltype.malloc(rffi.CCHARP.TO, - intmask(self.restype.c_size), + size = adjust_return_size(intmask(self.restype.c_size)) + ll_result = lltype.malloc(rffi.CCHARP.TO, size, flavor='raw') ffires = c_ffi_call(self.ll_cif, self.funcsym, _______________________________________________ pypy-commit mailing list pypy-commit@python.org https://mail.python.org/mailman/listinfo/pypy-commit