[pypy-commit] pypy default: merge
fijal
noreply at buildbot.pypy.org
Tue Feb 24 19:16:03 CET 2015
Author: Maciej Fijalkowski <fijall at 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,
More information about the pypy-commit
mailing list