[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