[pypy-commit] pypy default: merge

cfbolz noreply at buildbot.pypy.org
Thu Nov 10 13:44:42 CET 2011


Author: Carl Friedrich Bolz <cfbolz at gmx.de>
Branch: 
Changeset: r49135:3b7fdd2b26ba
Date: 2011-11-10 13:44 +0100
http://bitbucket.org/pypy/pypy/changeset/3b7fdd2b26ba/

Log:	merge

diff --git a/lib-python/2.7/test/test_os.py b/lib-python/2.7/test/test_os.py
--- a/lib-python/2.7/test/test_os.py
+++ b/lib-python/2.7/test/test_os.py
@@ -74,7 +74,8 @@
         self.assertFalse(os.path.exists(name),
                     "file already exists for temporary file")
         # make sure we can create the file
-        open(name, "w")
+        f = open(name, "w")
+        f.close()
         self.files.append(name)
 
     def test_tempnam(self):
diff --git a/lib-python/conftest.py b/lib-python/conftest.py
--- a/lib-python/conftest.py
+++ b/lib-python/conftest.py
@@ -201,7 +201,7 @@
     RegrTest('test_difflib.py'),
     RegrTest('test_dircache.py', core=True),
     RegrTest('test_dis.py'),
-    RegrTest('test_distutils.py'),
+    RegrTest('test_distutils.py', skip=True),
     RegrTest('test_dl.py', skip=True),
     RegrTest('test_doctest.py', usemodules="thread"),
     RegrTest('test_doctest2.py'),
diff --git a/lib-python/modified-2.7/ctypes/test/test_simplesubclasses.py b/lib-python/modified-2.7/ctypes/test/test_simplesubclasses.py
--- a/lib-python/modified-2.7/ctypes/test/test_simplesubclasses.py
+++ b/lib-python/modified-2.7/ctypes/test/test_simplesubclasses.py
@@ -1,6 +1,5 @@
 import unittest
 from ctypes import *
-from ctypes.test import xfail
 
 class MyInt(c_int):
     def __cmp__(self, other):
@@ -27,7 +26,6 @@
         self.assertEqual(None, cb())
 
 
-    @xfail
     def test_int_callback(self):
         args = []
         def func(arg):
diff --git a/lib-python/2.7/pkgutil.py b/lib-python/modified-2.7/pkgutil.py
copy from lib-python/2.7/pkgutil.py
copy to lib-python/modified-2.7/pkgutil.py
--- a/lib-python/2.7/pkgutil.py
+++ b/lib-python/modified-2.7/pkgutil.py
@@ -244,7 +244,8 @@
         return mod
 
     def get_data(self, pathname):
-        return open(pathname, "rb").read()
+        with open(pathname, "rb") as f:
+            return f.read()
 
     def _reopen(self):
         if self.file and self.file.closed:
diff --git a/lib_pypy/_ctypes/pointer.py b/lib_pypy/_ctypes/pointer.py
--- a/lib_pypy/_ctypes/pointer.py
+++ b/lib_pypy/_ctypes/pointer.py
@@ -124,7 +124,8 @@
     # for now, we always allow types.pointer, else a lot of tests
     # break. We need to rethink how pointers are represented, though
     if my_ffitype is not ffitype and ffitype is not _ffi.types.void_p:
-        raise ArgumentError, "expected %s instance, got %s" % (type(value), ffitype)
+        raise ArgumentError("expected %s instance, got %s" % (type(value),
+                                                              ffitype))
     return value._get_buffer_value()
 
 def _cast_addr(obj, _, tp):
diff --git a/lib_pypy/_ctypes/structure.py b/lib_pypy/_ctypes/structure.py
--- a/lib_pypy/_ctypes/structure.py
+++ b/lib_pypy/_ctypes/structure.py
@@ -17,7 +17,7 @@
         if len(f) == 3:
             if (not hasattr(tp, '_type_')
                 or not isinstance(tp._type_, str)
-                or tp._type_ not in "iIhHbBlL"):
+                or tp._type_ not in "iIhHbBlLqQ"):
                 #XXX: are those all types?
                 #     we just dont get the type name
                 #     in the interp levle thrown TypeError
diff --git a/lib_pypy/pyrepl/commands.py b/lib_pypy/pyrepl/commands.py
--- a/lib_pypy/pyrepl/commands.py
+++ b/lib_pypy/pyrepl/commands.py
@@ -33,10 +33,9 @@
 class Command(object):
     finish = 0
     kills_digit_arg = 1
-    def __init__(self, reader, (event_name, event)):
+    def __init__(self, reader, cmd):
         self.reader = reader
-        self.event = event
-        self.event_name = event_name
+        self.event_name, self.event = cmd
     def do(self):
         pass
 
diff --git a/lib_pypy/pyrepl/pygame_console.py b/lib_pypy/pyrepl/pygame_console.py
--- a/lib_pypy/pyrepl/pygame_console.py
+++ b/lib_pypy/pyrepl/pygame_console.py
@@ -130,7 +130,7 @@
         s.fill(c, [0, 600 - bmargin, 800, bmargin])
         s.fill(c, [800 - rmargin, 0, lmargin, 600])
 
-    def refresh(self, screen, (cx, cy)):
+    def refresh(self, screen, cxy):
         self.screen = screen
         self.pygame_screen.fill(colors.bg,
                                 [0, tmargin + self.cur_top + self.scroll,
@@ -139,8 +139,8 @@
 
         line_top = self.cur_top
         width, height = self.fontsize
-        self.cxy = (cx, cy)
-        cp = self.char_pos(cx, cy)
+        self.cxy = cxy
+        cp = self.char_pos(*cxy)
         if cp[1] < tmargin:
             self.scroll = - (cy*self.fh + self.cur_top)
             self.repaint()
@@ -148,7 +148,7 @@
             self.scroll += (600 - bmargin) - (cp[1] + self.fh)
             self.repaint()
         if self.curs_vis:
-            self.pygame_screen.blit(self.cursor, self.char_pos(cx, cy))
+            self.pygame_screen.blit(self.cursor, self.char_pos(*cxy))
         for line in screen:
             if 0 <= line_top + self.scroll <= (600 - bmargin - tmargin - self.fh):
                 if line:
diff --git a/lib_pypy/pyrepl/unix_console.py b/lib_pypy/pyrepl/unix_console.py
--- a/lib_pypy/pyrepl/unix_console.py
+++ b/lib_pypy/pyrepl/unix_console.py
@@ -163,7 +163,7 @@
     def change_encoding(self, encoding):
         self.encoding = encoding
     
-    def refresh(self, screen, (cx, cy)):
+    def refresh(self, screen, cxy):
         # this function is still too long (over 90 lines)
 
         if not self.__gone_tall:
@@ -198,6 +198,7 @@
 
         # we make sure the cursor is on the screen, and that we're
         # using all of the screen if we can
+        cx, cy = cxy
         if cy < offset:
             offset = cy
         elif cy >= offset + height:
diff --git a/pypy/interpreter/test/test_typedef.py b/pypy/interpreter/test/test_typedef.py
--- a/pypy/interpreter/test/test_typedef.py
+++ b/pypy/interpreter/test/test_typedef.py
@@ -2,7 +2,7 @@
 from pypy.interpreter import typedef
 from pypy.tool.udir import udir
 from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.gateway import ObjSpace
+from pypy.interpreter.gateway import ObjSpace, interp2app
 
 # this test isn't so much to test that the objspace interface *works*
 # -- it's more to test that it's *there*
@@ -260,6 +260,50 @@
         gc.collect(); gc.collect()
         assert space.unwrap(w_seen) == [6, 2]
 
+    def test_multiple_inheritance(self):
+        class W_A(Wrappable):
+            a = 1
+            b = 2
+        class W_C(W_A):
+            b = 3
+        W_A.typedef = typedef.TypeDef("A",
+            a = typedef.interp_attrproperty("a", cls=W_A),
+            b = typedef.interp_attrproperty("b", cls=W_A),
+        )
+        class W_B(Wrappable):
+            pass
+        def standalone_method(space, w_obj):
+            if isinstance(w_obj, W_A):
+                return space.w_True
+            else:
+                return space.w_False
+        W_B.typedef = typedef.TypeDef("B",
+            c = interp2app(standalone_method)
+        )
+        W_C.typedef = typedef.TypeDef("C", (W_A.typedef, W_B.typedef,))
+
+        w_o1 = self.space.wrap(W_C())
+        w_o2 = self.space.wrap(W_B())
+        w_c = self.space.gettypefor(W_C)
+        w_b = self.space.gettypefor(W_B)
+        w_a = self.space.gettypefor(W_A)
+        assert w_c.mro_w == [
+            w_c,
+            w_a,
+            w_b,
+            self.space.w_object,
+        ]
+        for w_tp in w_c.mro_w:
+            assert self.space.isinstance_w(w_o1, w_tp)
+        def assert_attr(w_obj, name, value):
+            assert self.space.unwrap(self.space.getattr(w_obj, self.space.wrap(name))) == value
+        def assert_method(w_obj, name, value):
+            assert self.space.unwrap(self.space.call_method(w_obj, name)) == value
+        assert_attr(w_o1, "a", 1)
+        assert_attr(w_o1, "b", 3)
+        assert_method(w_o1, "c", True)
+        assert_method(w_o2, "c", False)
+
 
 class AppTestTypeDef:
 
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -15,13 +15,19 @@
     def __init__(self, __name, __base=None, **rawdict):
         "NOT_RPYTHON: initialization-time only"
         self.name = __name
-        self.base = __base
+        if __base is None:
+            bases = []
+        elif isinstance(__base, tuple):
+            bases = list(__base)
+        else:
+            bases = [__base]
+        self.bases = bases
         self.hasdict = '__dict__' in rawdict
         self.weakrefable = '__weakref__' in rawdict
         self.doc = rawdict.pop('__doc__', None)
-        if __base is not None:
-            self.hasdict     |= __base.hasdict
-            self.weakrefable |= __base.weakrefable
+        for base in bases:
+            self.hasdict     |= base.hasdict
+            self.weakrefable |= base.weakrefable
         self.rawdict = {}
         self.acceptable_as_base_class = '__new__' in rawdict
         self.applevel_subclasses_base = None
diff --git a/pypy/jit/backend/llsupport/descr.py b/pypy/jit/backend/llsupport/descr.py
--- a/pypy/jit/backend/llsupport/descr.py
+++ b/pypy/jit/backend/llsupport/descr.py
@@ -305,12 +305,16 @@
     _clsname = ''
     loop_token = None
     arg_classes = ''     # <-- annotation hack
-    ffi_flags = 0
+    ffi_flags = 1
 
-    def __init__(self, arg_classes, extrainfo=None, ffi_flags=0):
+    def __init__(self, arg_classes, extrainfo=None, ffi_flags=1):
         self.arg_classes = arg_classes    # string of "r" and "i" (ref/int)
         self.extrainfo = extrainfo
         self.ffi_flags = ffi_flags
+        # NB. the default ffi_flags is 1, meaning FUNCFLAG_CDECL, which
+        # makes sense on Windows as it's the one for all the C functions
+        # we are compiling together with the JIT.  On non-Windows platforms
+        # it is just ignored anyway.
 
     def __repr__(self):
         res = '%s(%s)' % (self.__class__.__name__, self.arg_classes)
@@ -351,6 +355,10 @@
         return False    # unless overridden
 
     def create_call_stub(self, rtyper, RESULT):
+        from pypy.rlib.clibffi import FFI_DEFAULT_ABI
+        assert self.get_call_conv() == FFI_DEFAULT_ABI, (
+            "%r: create_call_stub() with a non-default call ABI" % (self,))
+
         def process(c):
             if c == 'L':
                 assert longlong.supports_longlong
@@ -445,7 +453,7 @@
     """
     _clsname = 'DynamicIntCallDescr'
 
-    def __init__(self, arg_classes, result_size, result_sign, extrainfo=None, ffi_flags=0):
+    def __init__(self, arg_classes, result_size, result_sign, extrainfo, ffi_flags):
         BaseIntCallDescr.__init__(self, arg_classes, extrainfo, ffi_flags)
         assert isinstance(result_sign, bool)
         self._result_size = chr(result_size)
diff --git a/pypy/jit/backend/llsupport/ffisupport.py b/pypy/jit/backend/llsupport/ffisupport.py
--- a/pypy/jit/backend/llsupport/ffisupport.py
+++ b/pypy/jit/backend/llsupport/ffisupport.py
@@ -8,7 +8,7 @@
 class UnsupportedKind(Exception):
     pass
 
-def get_call_descr_dynamic(cpu, ffi_args, ffi_result, extrainfo=None, ffi_flags=0):
+def get_call_descr_dynamic(cpu, ffi_args, ffi_result, extrainfo, ffi_flags):
     """Get a call descr: the types of result and args are represented by
     rlib.libffi.types.*"""
     try:
diff --git a/pypy/jit/backend/llsupport/test/test_ffisupport.py b/pypy/jit/backend/llsupport/test/test_ffisupport.py
--- a/pypy/jit/backend/llsupport/test/test_ffisupport.py
+++ b/pypy/jit/backend/llsupport/test/test_ffisupport.py
@@ -13,44 +13,46 @@
 
 def test_call_descr_dynamic():
     args = [types.sint, types.pointer]
-    descr = get_call_descr_dynamic(FakeCPU(), args, types.sint, ffi_flags=42)
+    descr = get_call_descr_dynamic(FakeCPU(), args, types.sint, None,
+                                   ffi_flags=42)
     assert isinstance(descr, DynamicIntCallDescr)
     assert descr.arg_classes == 'ii'
     assert descr.get_ffi_flags() == 42
 
     args = [types.sint, types.double, types.pointer]
-    descr = get_call_descr_dynamic(FakeCPU(), args, types.void)
+    descr = get_call_descr_dynamic(FakeCPU(), args, types.void, None, 42)
     assert descr is None    # missing floats
     descr = get_call_descr_dynamic(FakeCPU(supports_floats=True),
-                                   args, types.void, ffi_flags=43)
+                                   args, types.void, None, ffi_flags=43)
     assert isinstance(descr, VoidCallDescr)
     assert descr.arg_classes == 'ifi'
     assert descr.get_ffi_flags() == 43
 
-    descr = get_call_descr_dynamic(FakeCPU(), [], types.sint8)
+    descr = get_call_descr_dynamic(FakeCPU(), [], types.sint8, None, 42)
     assert isinstance(descr, DynamicIntCallDescr)
     assert descr.get_result_size(False) == 1
     assert descr.is_result_signed() == True
 
-    descr = get_call_descr_dynamic(FakeCPU(), [], types.uint8)
+    descr = get_call_descr_dynamic(FakeCPU(), [], types.uint8, None, 42)
     assert isinstance(descr, DynamicIntCallDescr)
     assert descr.get_result_size(False) == 1
     assert descr.is_result_signed() == False
 
     if not is_64_bit:
-        descr = get_call_descr_dynamic(FakeCPU(), [], types.slonglong)
+        descr = get_call_descr_dynamic(FakeCPU(), [], types.slonglong,
+                                       None, 42)
         assert descr is None   # missing longlongs
         descr = get_call_descr_dynamic(FakeCPU(supports_longlong=True),
-                                       [], types.slonglong, ffi_flags=43)
+                                       [], types.slonglong, None, ffi_flags=43)
         assert isinstance(descr, LongLongCallDescr)
         assert descr.get_ffi_flags() == 43
     else:
         assert types.slonglong is types.slong
 
-    descr = get_call_descr_dynamic(FakeCPU(), [], types.float)
+    descr = get_call_descr_dynamic(FakeCPU(), [], types.float, None, 42)
     assert descr is None   # missing singlefloats
     descr = get_call_descr_dynamic(FakeCPU(supports_singlefloats=True),
-                                   [], types.float, ffi_flags=44)
+                                   [], types.float, None, ffi_flags=44)
     SingleFloatCallDescr = getCallDescrClass(rffi.FLOAT)
     assert isinstance(descr, SingleFloatCallDescr)
     assert descr.get_ffi_flags() == 44
diff --git a/pypy/jit/backend/x86/test/test_runner.py b/pypy/jit/backend/x86/test/test_runner.py
--- a/pypy/jit/backend/x86/test/test_runner.py
+++ b/pypy/jit/backend/x86/test/test_runner.py
@@ -455,6 +455,9 @@
                                                 EffectInfo.MOST_GENERAL,
                                                 ffi_flags=-1)
             calldescr.get_call_conv = lambda: ffi      # <==== hack
+            # ^^^ we patch get_call_conv() so that the test also makes sense
+            #     on Linux, because clibffi.get_call_conv() would always
+            #     return FFI_DEFAULT_ABI on non-Windows platforms.
             funcbox = ConstInt(rawstart)
             i1 = BoxInt()
             i2 = BoxInt()
diff --git a/pypy/jit/codewriter/effectinfo.py b/pypy/jit/codewriter/effectinfo.py
--- a/pypy/jit/codewriter/effectinfo.py
+++ b/pypy/jit/codewriter/effectinfo.py
@@ -78,6 +78,9 @@
     #
     OS_MATH_SQRT                = 100
 
+    # for debugging:
+    _OS_CANRAISE = set([OS_NONE, OS_STR2UNICODE, OS_LIBFFI_CALL])
+
     def __new__(cls, readonly_descrs_fields, readonly_descrs_arrays,
                 write_descrs_fields, write_descrs_arrays,
                 extraeffect=EF_CAN_RAISE,
@@ -116,6 +119,8 @@
         result.extraeffect = extraeffect
         result.can_invalidate = can_invalidate
         result.oopspecindex = oopspecindex
+        if result.check_can_raise():
+            assert oopspecindex in cls._OS_CANRAISE
         cls._cache[key] = result
         return result
 
@@ -125,6 +130,10 @@
     def check_can_invalidate(self):
         return self.can_invalidate
 
+    def check_is_elidable(self):
+        return (self.extraeffect == self.EF_ELIDABLE_CAN_RAISE or
+                self.extraeffect == self.EF_ELIDABLE_CANNOT_RAISE)
+
     def check_forces_virtual_or_virtualizable(self):
         return self.extraeffect >= self.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
 
diff --git a/pypy/jit/codewriter/test/test_flatten.py b/pypy/jit/codewriter/test/test_flatten.py
--- a/pypy/jit/codewriter/test/test_flatten.py
+++ b/pypy/jit/codewriter/test/test_flatten.py
@@ -5,7 +5,7 @@
 from pypy.jit.codewriter.format import assert_format
 from pypy.jit.codewriter import longlong
 from pypy.jit.metainterp.history import AbstractDescr
-from pypy.rpython.lltypesystem import lltype, rclass, rstr
+from pypy.rpython.lltypesystem import lltype, rclass, rstr, rffi
 from pypy.objspace.flow.model import SpaceOperation, Variable, Constant
 from pypy.translator.unsimplify import varoftype
 from pypy.rlib.rarithmetic import ovfcheck, r_uint, r_longlong, r_ulonglong
@@ -743,7 +743,6 @@
         """, transform=True)
 
     def test_force_cast(self):
-        from pypy.rpython.lltypesystem import rffi
         # NB: we don't need to test for INT here, the logic in jtransform is
         # general enough so that if we have the below cases it should
         # generalize also to INT
@@ -849,7 +848,6 @@
                                        transform=True)
 
     def test_force_cast_pointer(self):
-        from pypy.rpython.lltypesystem import rffi
         def h(p):
             return rffi.cast(rffi.VOIDP, p)
         self.encoding_test(h, [lltype.nullptr(rffi.CCHARP.TO)], """
@@ -857,7 +855,6 @@
         """, transform=True)
 
     def test_force_cast_floats(self):
-        from pypy.rpython.lltypesystem import rffi
         # Caststs to lltype.Float
         def f(n):
             return rffi.cast(lltype.Float, n)
@@ -964,7 +961,6 @@
             """, transform=True)
 
     def test_direct_ptradd(self):
-        from pypy.rpython.lltypesystem import rffi
         def f(p, n):
             return lltype.direct_ptradd(p, n)
         self.encoding_test(f, [lltype.nullptr(rffi.CCHARP.TO), 123], """
@@ -975,7 +971,6 @@
 
 def check_force_cast(FROM, TO, operations, value):
     """Check that the test is correctly written..."""
-    from pypy.rpython.lltypesystem import rffi
     import re
     r = re.compile('(\w+) \%i\d, \$(-?\d+)')
     #
diff --git a/pypy/jit/metainterp/optimizeopt/__init__.py b/pypy/jit/metainterp/optimizeopt/__init__.py
--- a/pypy/jit/metainterp/optimizeopt/__init__.py
+++ b/pypy/jit/metainterp/optimizeopt/__init__.py
@@ -55,7 +55,7 @@
 
 
 def optimize_loop_1(metainterp_sd, loop, enable_opts,
-                    inline_short_preamble=True, retraced=False, bridge=False):
+                    inline_short_preamble=True, retraced=False):
     """Optimize loop.operations to remove internal overheadish operations.
     """
 
@@ -64,7 +64,7 @@
     if unroll:
         optimize_unroll(metainterp_sd, loop, optimizations)
     else:
-        optimizer = Optimizer(metainterp_sd, loop, optimizations, bridge)
+        optimizer = Optimizer(metainterp_sd, loop, optimizations)
         optimizer.propagate_all_forward()
 
 def optimize_bridge_1(metainterp_sd, bridge, enable_opts,
@@ -76,7 +76,7 @@
     except KeyError:
         pass
     optimize_loop_1(metainterp_sd, bridge, enable_opts,
-                    inline_short_preamble, retraced, bridge=True)
+                    inline_short_preamble, retraced)
 
 if __name__ == '__main__':
     print ALL_OPTS_NAMES
diff --git a/pypy/jit/metainterp/optimizeopt/heap.py b/pypy/jit/metainterp/optimizeopt/heap.py
--- a/pypy/jit/metainterp/optimizeopt/heap.py
+++ b/pypy/jit/metainterp/optimizeopt/heap.py
@@ -234,7 +234,7 @@
             or op.is_ovf()):
             self.posponedop = op
         else:
-            self.next_optimization.propagate_forward(op)
+            Optimization.emit_operation(self, op)
 
     def emitting_operation(self, op):
         if op.has_no_side_effect():
diff --git a/pypy/jit/metainterp/optimizeopt/intbounds.py b/pypy/jit/metainterp/optimizeopt/intbounds.py
--- a/pypy/jit/metainterp/optimizeopt/intbounds.py
+++ b/pypy/jit/metainterp/optimizeopt/intbounds.py
@@ -6,6 +6,7 @@
     IntUpperBound)
 from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
 from pypy.jit.metainterp.resoperation import rop
+from pypy.jit.metainterp.optimize import InvalidLoop
 from pypy.rlib.rarithmetic import LONG_BIT
 
 
@@ -13,30 +14,10 @@
     """Keeps track of the bounds placed on integers by guards and remove
        redundant guards"""
 
-    def setup(self):
-        self.posponedop = None
-        self.nextop = None
-
     def new(self):
-        assert self.posponedop is None
         return OptIntBounds()
-        
-    def flush(self):
-        assert self.posponedop is None
-
-    def setup(self):
-        self.posponedop = None
-        self.nextop = None
 
     def propagate_forward(self, op):
-        if op.is_ovf():
-            self.posponedop = op
-            return
-        if self.posponedop:
-            self.nextop = op
-            op = self.posponedop
-            self.posponedop = None
-
         dispatch_opt(self, op)
 
     def opt_default(self, op):
@@ -179,68 +160,75 @@
             r = self.getvalue(op.result)
             r.intbound.intersect(b)
 
+    def optimize_GUARD_NO_OVERFLOW(self, op):
+        lastop = self.last_emitted_operation
+        if lastop is not None:
+            opnum = lastop.getopnum()
+            args = lastop.getarglist()
+            result = lastop.result
+            # If the INT_xxx_OVF was replaced with INT_xxx, then we can kill
+            # the GUARD_NO_OVERFLOW.
+            if (opnum == rop.INT_ADD or
+                opnum == rop.INT_SUB or
+                opnum == rop.INT_MUL):
+                return
+            # Else, synthesize the non overflowing op for optimize_default to
+            # reuse, as well as the reverse op
+            elif opnum == rop.INT_ADD_OVF:
+                self.pure(rop.INT_ADD, args[:], result)
+                self.pure(rop.INT_SUB, [result, args[1]], args[0])
+                self.pure(rop.INT_SUB, [result, args[0]], args[1])
+            elif opnum == rop.INT_SUB_OVF:
+                self.pure(rop.INT_SUB, args[:], result)
+                self.pure(rop.INT_ADD, [result, args[1]], args[0])
+                self.pure(rop.INT_SUB, [args[0], result], args[1])
+            elif opnum == rop.INT_MUL_OVF:
+                self.pure(rop.INT_MUL, args[:], result)
+        self.emit_operation(op)
+
+    def optimize_GUARD_OVERFLOW(self, op):
+        # If INT_xxx_OVF was replaced by INT_xxx, *but* we still see
+        # GUARD_OVERFLOW, then the loop is invalid.
+        lastop = self.last_emitted_operation
+        if lastop is None:
+            raise InvalidLoop
+        opnum = lastop.getopnum()
+        if opnum not in (rop.INT_ADD_OVF, rop.INT_SUB_OVF, rop.INT_MUL_OVF):
+            raise InvalidLoop
+        self.emit_operation(op)
+
     def optimize_INT_ADD_OVF(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
         resbound = v1.intbound.add_bound(v2.intbound)
-        if resbound.has_lower and resbound.has_upper and \
-           self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
-            # Transform into INT_ADD and remove guard
+        if resbound.bounded():
+            # Transform into INT_ADD.  The following guard will be killed
+            # by optimize_GUARD_NO_OVERFLOW; if we see instead an
+            # optimize_GUARD_OVERFLOW, then InvalidLoop.
             op = op.copy_and_change(rop.INT_ADD)
-            self.optimize_INT_ADD(op) # emit the op
-        else:
-            self.emit_operation(op)
-            r = self.getvalue(op.result)
-            r.intbound.intersect(resbound)
-            self.emit_operation(self.nextop)
-            if self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
-                # Synthesize the non overflowing op for optimize_default to reuse
-                self.pure(rop.INT_ADD, op.getarglist()[:], op.result)
-                # Synthesize the reverse op for optimize_default to reuse
-                self.pure(rop.INT_SUB, [op.result, op.getarg(1)], op.getarg(0))
-                self.pure(rop.INT_SUB, [op.result, op.getarg(0)], op.getarg(1))
-
+        self.emit_operation(op) # emit the op
+        r = self.getvalue(op.result)
+        r.intbound.intersect(resbound)
 
     def optimize_INT_SUB_OVF(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
         resbound = v1.intbound.sub_bound(v2.intbound)
-        if resbound.has_lower and resbound.has_upper and \
-               self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
-            # Transform into INT_SUB and remove guard
+        if resbound.bounded():
             op = op.copy_and_change(rop.INT_SUB)
-            self.optimize_INT_SUB(op) # emit the op
-        else:
-            self.emit_operation(op)
-            r = self.getvalue(op.result)
-            r.intbound.intersect(resbound)
-            self.emit_operation(self.nextop)
-            if self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
-                # Synthesize the non overflowing op for optimize_default to reuse
-                self.pure(rop.INT_SUB, op.getarglist()[:], op.result)
-                # Synthesize the reverse ops for optimize_default to reuse
-                self.pure(rop.INT_ADD, [op.result, op.getarg(1)], op.getarg(0))
-                self.pure(rop.INT_SUB, [op.getarg(0), op.result], op.getarg(1))
-
+        self.emit_operation(op) # emit the op
+        r = self.getvalue(op.result)
+        r.intbound.intersect(resbound)
 
     def optimize_INT_MUL_OVF(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
         resbound = v1.intbound.mul_bound(v2.intbound)
-        if resbound.has_lower and resbound.has_upper and \
-               self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
-            # Transform into INT_MUL and remove guard
+        if resbound.bounded():
             op = op.copy_and_change(rop.INT_MUL)
-            self.optimize_INT_MUL(op) # emit the op
-        else:
-            self.emit_operation(op)
-            r = self.getvalue(op.result)
-            r.intbound.intersect(resbound)
-            self.emit_operation(self.nextop)
-            if self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
-                # Synthesize the non overflowing op for optimize_default to reuse
-                self.pure(rop.INT_MUL, op.getarglist()[:], op.result)
-
+        self.emit_operation(op)
+        r = self.getvalue(op.result)
+        r.intbound.intersect(resbound)
 
     def optimize_INT_LT(self, op):
         v1 = self.getvalue(op.getarg(0))
diff --git a/pypy/jit/metainterp/optimizeopt/intutils.py b/pypy/jit/metainterp/optimizeopt/intutils.py
--- a/pypy/jit/metainterp/optimizeopt/intutils.py
+++ b/pypy/jit/metainterp/optimizeopt/intutils.py
@@ -1,4 +1,4 @@
-from pypy.rlib.rarithmetic import ovfcheck, ovfcheck_lshift, LONG_BIT
+from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.jit.metainterp.resoperation import rop, ResOperation
 from pypy.jit.metainterp.history import BoxInt, ConstInt
@@ -174,10 +174,10 @@
            other.known_ge(IntBound(0, 0)) and \
            other.known_lt(IntBound(LONG_BIT, LONG_BIT)):
             try:
-                vals = (ovfcheck_lshift(self.upper, other.upper),
-                        ovfcheck_lshift(self.upper, other.lower),
-                        ovfcheck_lshift(self.lower, other.upper),
-                        ovfcheck_lshift(self.lower, other.lower))
+                vals = (ovfcheck(self.upper << other.upper),
+                        ovfcheck(self.upper << other.lower),
+                        ovfcheck(self.lower << other.upper),
+                        ovfcheck(self.lower << other.lower))
                 return IntBound(min4(vals), max4(vals))
             except (OverflowError, ValueError):
                 return IntUnbounded()
diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py b/pypy/jit/metainterp/optimizeopt/optimizer.py
--- a/pypy/jit/metainterp/optimizeopt/optimizer.py
+++ b/pypy/jit/metainterp/optimizeopt/optimizer.py
@@ -6,7 +6,7 @@
                                                      IntLowerBound, MININT, MAXINT
 from pypy.jit.metainterp.optimizeopt.util import (make_dispatcher_method,
     args_dict)
-from pypy.jit.metainterp.resoperation import rop, ResOperation
+from pypy.jit.metainterp.resoperation import rop, ResOperation, AbstractResOp
 from pypy.jit.metainterp.typesystem import llhelper, oohelper
 from pypy.tool.pairtype import extendabletype
 from pypy.rlib.debug import debug_start, debug_stop, debug_print
@@ -247,9 +247,10 @@
 CONST_1      = ConstInt(1)
 CVAL_ZERO    = ConstantValue(CONST_0)
 CVAL_ZERO_FLOAT = ConstantValue(Const._new(0.0))
-CVAL_UNINITIALIZED_ZERO = ConstantValue(CONST_0)
 llhelper.CVAL_NULLREF = ConstantValue(llhelper.CONST_NULL)
 oohelper.CVAL_NULLREF = ConstantValue(oohelper.CONST_NULL)
+REMOVED = AbstractResOp(None)
+
 
 class Optimization(object):
     next_optimization = None
@@ -261,6 +262,7 @@
         raise NotImplementedError
 
     def emit_operation(self, op):
+        self.last_emitted_operation = op
         self.next_optimization.propagate_forward(op)
 
     # FIXME: Move some of these here?
@@ -328,13 +330,13 @@
     def forget_numberings(self, box):
         self.optimizer.forget_numberings(box)
 
+
 class Optimizer(Optimization):
 
-    def __init__(self, metainterp_sd, loop, optimizations=None, bridge=False):
+    def __init__(self, metainterp_sd, loop, optimizations=None):
         self.metainterp_sd = metainterp_sd
         self.cpu = metainterp_sd.cpu
         self.loop = loop
-        self.bridge = bridge
         self.values = {}
         self.interned_refs = self.cpu.ts.new_ref_dict()
         self.interned_ints = {}
@@ -342,7 +344,6 @@
         self.bool_boxes = {}
         self.producer = {}
         self.pendingfields = []
-        self.exception_might_have_happened = False
         self.quasi_immutable_deps = None
         self.opaque_pointers = {}
         self.replaces_guard = {}
@@ -364,6 +365,7 @@
             optimizations[-1].next_optimization = self
             for o in optimizations:
                 o.optimizer = self
+                o.last_emitted_operation = None
                 o.setup()
         else:
             optimizations = []
@@ -498,7 +500,6 @@
             return CVAL_ZERO
 
     def propagate_all_forward(self):
-        self.exception_might_have_happened = self.bridge
         self.clear_newoperations()
         for op in self.loop.operations:
             self.first_optimization.propagate_forward(op)
diff --git a/pypy/jit/metainterp/optimizeopt/pure.py b/pypy/jit/metainterp/optimizeopt/pure.py
--- a/pypy/jit/metainterp/optimizeopt/pure.py
+++ b/pypy/jit/metainterp/optimizeopt/pure.py
@@ -1,4 +1,4 @@
-from pypy.jit.metainterp.optimizeopt.optimizer import Optimization
+from pypy.jit.metainterp.optimizeopt.optimizer import Optimization, REMOVED
 from pypy.jit.metainterp.resoperation import rop, ResOperation
 from pypy.jit.metainterp.optimizeopt.util import (make_dispatcher_method,
     args_dict)
@@ -61,7 +61,10 @@
         oldop = self.pure_operations.get(args, None)
         if oldop is not None and oldop.getdescr() is op.getdescr():
             assert oldop.getopnum() == op.getopnum()
+            # this removes a CALL_PURE that has the same (non-constant)
+            # arguments as a previous CALL_PURE.
             self.make_equal_to(op.result, self.getvalue(oldop.result))
+            self.last_emitted_operation = REMOVED
             return
         else:
             self.pure_operations[args] = op
@@ -72,6 +75,13 @@
         self.emit_operation(ResOperation(rop.CALL, args, op.result,
                                          op.getdescr()))
 
+    def optimize_GUARD_NO_EXCEPTION(self, op):
+        if self.last_emitted_operation is REMOVED:
+            # it was a CALL_PURE that was killed; so we also kill the
+            # following GUARD_NO_EXCEPTION
+            return
+        self.emit_operation(op)
+
     def flush(self):
         assert self.posponedop is None
 
diff --git a/pypy/jit/metainterp/optimizeopt/rewrite.py b/pypy/jit/metainterp/optimizeopt/rewrite.py
--- a/pypy/jit/metainterp/optimizeopt/rewrite.py
+++ b/pypy/jit/metainterp/optimizeopt/rewrite.py
@@ -294,12 +294,6 @@
             raise InvalidLoop
         self.optimize_GUARD_CLASS(op)
 
-    def optimize_GUARD_NO_EXCEPTION(self, op):
-        if not self.optimizer.exception_might_have_happened:
-            return
-        self.emit_operation(op)
-        self.optimizer.exception_might_have_happened = False
-
     def optimize_CALL_LOOPINVARIANT(self, op):
         arg = op.getarg(0)
         # 'arg' must be a Const, because residual_call in codewriter
@@ -310,6 +304,7 @@
         resvalue = self.loop_invariant_results.get(key, None)
         if resvalue is not None:
             self.make_equal_to(op.result, resvalue)
+            self.last_emitted_operation = REMOVED
             return
         # change the op to be a normal call, from the backend's point of view
         # there is no reason to have a separate operation for this
@@ -444,10 +439,19 @@
             except KeyError:
                 pass
             else:
+                # this removes a CALL_PURE with all constant arguments.
                 self.make_constant(op.result, result)
+                self.last_emitted_operation = REMOVED
                 return
         self.emit_operation(op)
 
+    def optimize_GUARD_NO_EXCEPTION(self, op):
+        if self.last_emitted_operation is REMOVED:
+            # it was a CALL_PURE or a CALL_LOOPINVARIANT that was killed;
+            # so we also kill the following GUARD_NO_EXCEPTION
+            return
+        self.emit_operation(op)
+
     def optimize_INT_FLOORDIV(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizebasic.py
@@ -681,25 +681,60 @@
 
     # ----------
 
-    def test_fold_guard_no_exception(self):
-        ops = """
-        [i]
-        guard_no_exception() []
-        i1 = int_add(i, 3)
-        guard_no_exception() []
+    def test_keep_guard_no_exception(self):
+        ops = """
+        [i1]
         i2 = call(i1, descr=nonwritedescr)
         guard_no_exception() [i1, i2]
-        guard_no_exception() []
-        i3 = call(i2, descr=nonwritedescr)
-        jump(i1)       # the exception is considered lost when we loop back
-        """
-        expected = """
-        [i]
-        i1 = int_add(i, 3)
-        i2 = call(i1, descr=nonwritedescr)
+        jump(i2)
+        """
+        self.optimize_loop(ops, ops)
+
+    def test_keep_guard_no_exception_with_call_pure_that_is_not_folded(self):
+        ops = """
+        [i1]
+        i2 = call_pure(123456, i1, descr=nonwritedescr)
         guard_no_exception() [i1, i2]
-        i3 = call(i2, descr=nonwritedescr)
-        jump(i1)
+        jump(i2)
+        """
+        expected = """
+        [i1]
+        i2 = call(123456, i1, descr=nonwritedescr)
+        guard_no_exception() [i1, i2]
+        jump(i2)
+        """
+        self.optimize_loop(ops, expected)
+
+    def test_remove_guard_no_exception_with_call_pure_on_constant_args(self):
+        arg_consts = [ConstInt(i) for i in (123456, 81)]
+        call_pure_results = {tuple(arg_consts): ConstInt(5)}
+        ops = """
+        [i1]
+        i3 = same_as(81)
+        i2 = call_pure(123456, i3, descr=nonwritedescr)
+        guard_no_exception() [i1, i2]
+        jump(i2)
+        """
+        expected = """
+        [i1]
+        jump(5)
+        """
+        self.optimize_loop(ops, expected, call_pure_results)
+
+    def test_remove_guard_no_exception_with_duplicated_call_pure(self):
+        ops = """
+        [i1]
+        i2 = call_pure(123456, i1, descr=nonwritedescr)
+        guard_no_exception() [i1, i2]
+        i3 = call_pure(123456, i1, descr=nonwritedescr)
+        guard_no_exception() [i1, i2, i3]
+        jump(i3)
+        """
+        expected = """
+        [i1]
+        i2 = call(123456, i1, descr=nonwritedescr)
+        guard_no_exception() [i1, i2]
+        jump(i2)
         """
         self.optimize_loop(ops, expected)
 
@@ -4123,6 +4158,38 @@
         """
         self.optimize_strunicode_loop(ops, expected)
 
+    def test_str_concat_constant_lengths(self):
+        ops = """
+        [i0]
+        p0 = newstr(1)
+        strsetitem(p0, 0, i0)
+        p1 = newstr(0)
+        p2 = call(0, p0, p1, descr=strconcatdescr)
+        i1 = call(0, p2, p0, descr=strequaldescr)
+        finish(i1)
+        """
+        expected = """
+        [i0]
+        finish(1)
+        """
+        self.optimize_strunicode_loop(ops, expected)
+
+    def test_str_concat_constant_lengths_2(self):
+        ops = """
+        [i0]
+        p0 = newstr(0)
+        p1 = newstr(1)
+        strsetitem(p1, 0, i0)
+        p2 = call(0, p0, p1, descr=strconcatdescr)
+        i1 = call(0, p2, p1, descr=strequaldescr)
+        finish(i1)
+        """
+        expected = """
+        [i0]
+        finish(1)
+        """
+        self.optimize_strunicode_loop(ops, expected)
+
     def test_str_slice_1(self):
         ops = """
         [p1, i1, i2]
@@ -4883,6 +4950,27 @@
 
     def test_plain_virtual_string_copy_content(self):
         ops = """
+        [i1]
+        p0 = newstr(6)
+        copystrcontent(s"hello!", p0, 0, 0, 6)
+        p1 = call(0, p0, s"abc123", descr=strconcatdescr)
+        i0 = strgetitem(p1, i1)
+        finish(i0)
+        """
+        expected = """
+        [i1]
+        p0 = newstr(6)
+        copystrcontent(s"hello!", p0, 0, 0, 6)
+        p1 = newstr(12)
+        copystrcontent(p0, p1, 0, 0, 6)
+        copystrcontent(s"abc123", p1, 0, 6, 6)
+        i0 = strgetitem(p1, i1)
+        finish(i0)
+        """
+        self.optimize_strunicode_loop(ops, expected)
+
+    def test_plain_virtual_string_copy_content_2(self):
+        ops = """
         []
         p0 = newstr(6)
         copystrcontent(s"hello!", p0, 0, 0, 6)
@@ -4894,10 +4982,7 @@
         []
         p0 = newstr(6)
         copystrcontent(s"hello!", p0, 0, 0, 6)
-        p1 = newstr(12)
-        copystrcontent(p0, p1, 0, 0, 6)
-        copystrcontent(s"abc123", p1, 0, 6, 6)
-        i0 = strgetitem(p1, 0)
+        i0 = strgetitem(p0, 0)
         finish(i0)
         """
         self.optimize_strunicode_loop(ops, expected)
@@ -4914,6 +4999,34 @@
         """
         self.optimize_loop(ops, expected)
 
+    def test_known_equal_ints(self):
+        py.test.skip("in-progress")
+        ops = """
+        [i0, i1, i2, p0]
+        i3 = int_eq(i0, i1)
+        guard_true(i3) []
+
+        i4 = int_lt(i2, i0)
+        guard_true(i4) []
+        i5 = int_lt(i2, i1)
+        guard_true(i5) []
+
+        i6 = getarrayitem_gc(p0, i2)
+        finish(i6)
+        """
+        expected = """
+        [i0, i1, i2, p0]
+        i3 = int_eq(i0, i1)
+        guard_true(i3) []
+
+        i4 = int_lt(i2, i0)
+        guard_true(i4) []
+
+        i6 = getarrayitem_gc(p0, i3)
+        finish(i6)
+        """
+        self.optimize_loop(ops, expected)
+
 
 class TestLLtype(BaseTestOptimizeBasic, LLtypeMixin):
     pass
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -931,17 +931,14 @@
         [i]
         guard_no_exception() []
         i1 = int_add(i, 3)
-        guard_no_exception() []
         i2 = call(i1, descr=nonwritedescr)
         guard_no_exception() [i1, i2]
-        guard_no_exception() []
         i3 = call(i2, descr=nonwritedescr)
         jump(i1)       # the exception is considered lost when we loop back
         """
-        # note that 'guard_no_exception' at the very start is kept around
-        # for bridges, but not for loops
         preamble = """
         [i]
+        guard_no_exception() []    # occurs at the start of bridges, so keep it
         i1 = int_add(i, 3)
         i2 = call(i1, descr=nonwritedescr)
         guard_no_exception() [i1, i2]
@@ -950,6 +947,7 @@
         """
         expected = """
         [i]
+        guard_no_exception() []    # occurs at the start of bridges, so keep it
         i1 = int_add(i, 3)
         i2 = call(i1, descr=nonwritedescr)
         guard_no_exception() [i1, i2]
@@ -958,6 +956,23 @@
         """
         self.optimize_loop(ops, expected, preamble)
 
+    def test_bug_guard_no_exception(self):
+        ops = """
+        []
+        i0 = call(123, descr=nonwritedescr)
+        p0 = call(0, "xy", descr=s2u_descr)      # string -> unicode
+        guard_no_exception() []
+        escape(p0)
+        jump()
+        """
+        expected = """
+        []
+        i0 = call(123, descr=nonwritedescr)
+        escape(u"xy")
+        jump()
+        """
+        self.optimize_loop(ops, expected)
+
     # ----------
 
     def test_call_loopinvariant(self):
@@ -6281,12 +6296,15 @@
     def test_str2unicode_constant(self):
         ops = """
         []
+        escape(1213)
         p0 = call(0, "xy", descr=s2u_descr)      # string -> unicode
+        guard_no_exception() []
         escape(p0)
         jump()
         """
         expected = """
         []
+        escape(1213)
         escape(u"xy")
         jump()
         """
@@ -6296,6 +6314,7 @@
         ops = """
         [p0]
         p1 = call(0, p0, descr=s2u_descr)      # string -> unicode
+        guard_no_exception() []
         escape(p1)
         jump(p1)
         """
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_util.py b/pypy/jit/metainterp/optimizeopt/test/test_util.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_util.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_util.py
@@ -183,6 +183,7 @@
                             can_invalidate=True))
     arraycopydescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
              EffectInfo([], [arraydescr], [], [arraydescr],
+                        EffectInfo.EF_CANNOT_RAISE,
                         oopspecindex=EffectInfo.OS_ARRAYCOPY))
 
 
@@ -212,12 +213,14 @@
         _oopspecindex = getattr(EffectInfo, _os)
         locals()[_name] = \
             cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                EffectInfo([], [], [], [], oopspecindex=_oopspecindex))
+                EffectInfo([], [], [], [], EffectInfo.EF_CANNOT_RAISE,
+                           oopspecindex=_oopspecindex))
         #
         _oopspecindex = getattr(EffectInfo, _os.replace('STR', 'UNI'))
         locals()[_name.replace('str', 'unicode')] = \
             cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                EffectInfo([], [], [], [], oopspecindex=_oopspecindex))
+                EffectInfo([], [], [], [], EffectInfo.EF_CANNOT_RAISE,
+                           oopspecindex=_oopspecindex))
 
     s2u_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
             EffectInfo([], [], [], [], oopspecindex=EffectInfo.OS_STR2UNICODE))
diff --git a/pypy/jit/metainterp/optimizeopt/vstring.py b/pypy/jit/metainterp/optimizeopt/vstring.py
--- a/pypy/jit/metainterp/optimizeopt/vstring.py
+++ b/pypy/jit/metainterp/optimizeopt/vstring.py
@@ -2,7 +2,8 @@
 from pypy.jit.metainterp.history import (BoxInt, Const, ConstInt, ConstPtr,
     get_const_ptr_for_string, get_const_ptr_for_unicode, BoxPtr, REF, INT)
 from pypy.jit.metainterp.optimizeopt import optimizer, virtualize
-from pypy.jit.metainterp.optimizeopt.optimizer import CONST_0, CONST_1, llhelper
+from pypy.jit.metainterp.optimizeopt.optimizer import CONST_0, CONST_1
+from pypy.jit.metainterp.optimizeopt.optimizer import llhelper, REMOVED
 from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
 from pypy.jit.metainterp.resoperation import rop, ResOperation
 from pypy.rlib.objectmodel import specialize, we_are_translated
@@ -106,46 +107,33 @@
         if not we_are_translated():
             op.name = 'FORCE'
         optforce.emit_operation(op)
-        self.string_copy_parts(optforce, box, CONST_0, self.mode)
+        self.initialize_forced_string(optforce, box, CONST_0, self.mode)
+
+    def initialize_forced_string(self, string_optimizer, targetbox,
+                                 offsetbox, mode):
+        return self.string_copy_parts(string_optimizer, targetbox,
+                                      offsetbox, mode)
 
 
 class VStringPlainValue(VAbstractStringValue):
     """A string built with newstr(const)."""
     _lengthbox = None     # cache only
 
-    # Warning: an issue with VStringPlainValue is that sometimes it is
-    # initialized unpredictably by some copystrcontent.  When this occurs
-    # we set self._chars to None.  Be careful to check for is_valid().
-
-    def is_valid(self):
-        return self._chars is not None
-
-    def _invalidate(self):
-        assert self.is_valid()
-        if self._lengthbox is None:
-            self._lengthbox = ConstInt(len(self._chars))
-        self._chars = None
-
-    def _really_force(self, optforce):
-        VAbstractStringValue._really_force(self, optforce)
-        assert self.box is not None
-        if self.is_valid():
-            for c in self._chars:
-                if c is optimizer.CVAL_UNINITIALIZED_ZERO:
-                    # the string has uninitialized null bytes in it, so
-                    # assume that it is forced for being further mutated
-                    # (e.g. by copystrcontent).  So it becomes invalid
-                    # as a VStringPlainValue: the _chars must not be used
-                    # any longer.
-                    self._invalidate()
-                    break
-
     def setup(self, size):
-        self._chars = [optimizer.CVAL_UNINITIALIZED_ZERO] * size
+        # in this list, None means: "it's probably uninitialized so far,
+        # but maybe it was actually filled."  So to handle this case,
+        # strgetitem cannot be virtual-ized and must be done as a residual
+        # operation.  By contrast, any non-None value means: we know it
+        # is initialized to this value; strsetitem() there makes no sense.
+        # Also, as long as self.is_virtual(), then we know that no-one else
+        # could have written to the string, so we know that in this case
+        # "None" corresponds to "really uninitialized".
+        self._chars = [None] * size
 
     def setup_slice(self, longerlist, start, stop):
         assert 0 <= start <= stop <= len(longerlist)
         self._chars = longerlist[start:stop]
+        # slice the 'longerlist', which may also contain Nones
 
     def getstrlen(self, _, mode):
         if self._lengthbox is None:
@@ -153,44 +141,66 @@
         return self._lengthbox
 
     def getitem(self, index):
-        return self._chars[index]
+        return self._chars[index]     # may return None!
 
     def setitem(self, index, charvalue):
         assert isinstance(charvalue, optimizer.OptValue)
+        assert self._chars[index] is None, (
+            "setitem() on an already-initialized location")
         self._chars[index] = charvalue
 
+    def is_completely_initialized(self):
+        for c in self._chars:
+            if c is None:
+                return False
+        return True
+
     @specialize.arg(1)
     def get_constant_string_spec(self, mode):
-        if not self.is_valid():
-            return None
         for c in self._chars:
-            if c is optimizer.CVAL_UNINITIALIZED_ZERO or not c.is_constant():
+            if c is None or not c.is_constant():
                 return None
         return mode.emptystr.join([mode.chr(c.box.getint())
                                    for c in self._chars])
 
     def string_copy_parts(self, string_optimizer, targetbox, offsetbox, mode):
-        if not self.is_valid():
+        if not self.is_virtual() and not self.is_completely_initialized():
             return VAbstractStringValue.string_copy_parts(
                 self, string_optimizer, targetbox, offsetbox, mode)
+        else:
+            return self.initialize_forced_string(string_optimizer, targetbox,
+                                                 offsetbox, mode)
+
+    def initialize_forced_string(self, string_optimizer, targetbox,
+                                 offsetbox, mode):
         for i in range(len(self._chars)):
             assert isinstance(targetbox, BoxPtr)   # ConstPtr never makes sense
-            charbox = self._chars[i].force_box(string_optimizer)
-            if not (isinstance(charbox, Const) and charbox.same_constant(CONST_0)):
-                string_optimizer.emit_operation(ResOperation(mode.STRSETITEM, [targetbox,
-                                                                               offsetbox,
-                                                                               charbox],
-                                                  None))
+            charvalue = self.getitem(i)
+            if charvalue is not None:
+                charbox = charvalue.force_box(string_optimizer)
+                if not (isinstance(charbox, Const) and
+                        charbox.same_constant(CONST_0)):
+                    op = ResOperation(mode.STRSETITEM, [targetbox,
+                                                        offsetbox,
+                                                        charbox],
+                                      None)
+                    string_optimizer.emit_operation(op)
             offsetbox = _int_add(string_optimizer, offsetbox, CONST_1)
         return offsetbox
 
     def get_args_for_fail(self, modifier):
         if self.box is None and not modifier.already_seen_virtual(self.keybox):
-            assert self.is_valid()
-            charboxes = [value.get_key_box() for value in self._chars]
+            charboxes = []
+            for value in self._chars:
+                if value is not None:
+                    box = value.get_key_box()
+                else:
+                    box = None
+                charboxes.append(box)
             modifier.register_virtual_fields(self.keybox, charboxes)
             for value in self._chars:
-                value.get_args_for_fail(modifier)
+                if value is not None:
+                    value.get_args_for_fail(modifier)
 
     def _make_virtual(self, modifier):
         return modifier.make_vstrplain(self.mode is mode_unicode)
@@ -198,6 +208,7 @@
 
 class VStringConcatValue(VAbstractStringValue):
     """The concatenation of two other strings."""
+    _attrs_ = ('left', 'right', 'lengthbox')
 
     lengthbox = None     # or the computed length
 
@@ -405,8 +416,7 @@
     def optimize_STRSETITEM(self, op):
         value = self.getvalue(op.getarg(0))
         assert not value.is_constant() # strsetitem(ConstPtr) never makes sense
-        if (value.is_virtual() and isinstance(value, VStringPlainValue)
-            and value.is_valid()):
+        if value.is_virtual() and isinstance(value, VStringPlainValue):
             indexbox = self.get_constant_box(op.getarg(1))
             if indexbox is not None:
                 value.setitem(indexbox.getint(), self.getvalue(op.getarg(2)))
@@ -437,10 +447,22 @@
             value = value.vstr
             vindex = self.getvalue(fullindexbox)
         #
-        if (isinstance(value, VStringPlainValue)  # even if no longer virtual
-            and value.is_valid()):                # but make sure it is valid
+        if isinstance(value, VStringPlainValue):  # even if no longer virtual
             if vindex.is_constant():
-                return value.getitem(vindex.box.getint())
+                result = value.getitem(vindex.box.getint())
+                if result is not None:
+                    return result
+        #
+        if isinstance(value, VStringConcatValue) and vindex.is_constant():
+            len1box = value.left.getstrlen(self, mode)
+            if isinstance(len1box, ConstInt):
+                index = vindex.box.getint()
+                len1 = len1box.getint()
+                if index < len1:
+                    return self.strgetitem(value.left, vindex, mode)
+                else:
+                    vindex = optimizer.ConstantValue(ConstInt(index - len1))
+                    return self.strgetitem(value.right, vindex, mode)
         #
         resbox = _strgetitem(self, value.force_box(self), vindex.force_box(self), mode)
         return self.getvalue(resbox)
@@ -508,6 +530,11 @@
 
     optimize_CALL_PURE = optimize_CALL
 
+    def optimize_GUARD_NO_EXCEPTION(self, op):
+        if self.last_emitted_operation is REMOVED:
+            return
+        self.emit_operation(op)
+
     def opt_call_str_STR2UNICODE(self, op):
         # Constant-fold unicode("constant string").
         # More generally, supporting non-constant but virtual cases is
@@ -522,6 +549,7 @@
         except UnicodeDecodeError:
             return False
         self.make_constant(op.result, get_const_ptr_for_unicode(u))
+        self.last_emitted_operation = REMOVED
         return True
 
     def opt_call_stroruni_STR_CONCAT(self, op, mode):
@@ -538,12 +566,12 @@
         vstart = self.getvalue(op.getarg(2))
         vstop = self.getvalue(op.getarg(3))
         #
-        if (isinstance(vstr, VStringPlainValue) and vstr.is_valid()
-            and vstart.is_constant() and vstop.is_constant()):
-            value = self.make_vstring_plain(op.result, op, mode)
-            value.setup_slice(vstr._chars, vstart.box.getint(),
-                              vstop.box.getint())
-            return True
+        #if (isinstance(vstr, VStringPlainValue) and vstart.is_constant()
+        #    and vstop.is_constant()):
+        #    value = self.make_vstring_plain(op.result, op, mode)
+        #    value.setup_slice(vstr._chars, vstart.box.getint(),
+        #                      vstop.box.getint())
+        #    return True
         #
         vstr.ensure_nonnull()
         lengthbox = _int_sub(self, vstop.force_box(self),
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -1345,10 +1345,8 @@
             if effect == effectinfo.EF_LOOPINVARIANT:
                 return self.execute_varargs(rop.CALL_LOOPINVARIANT, allboxes,
                                             descr, False, False)
-            exc = (effect != effectinfo.EF_CANNOT_RAISE and
-                   effect != effectinfo.EF_ELIDABLE_CANNOT_RAISE)
-            pure = (effect == effectinfo.EF_ELIDABLE_CAN_RAISE or
-                    effect == effectinfo.EF_ELIDABLE_CANNOT_RAISE)
+            exc = effectinfo.check_can_raise()
+            pure = effectinfo.check_is_elidable()
             return self.execute_varargs(rop.CALL, allboxes, descr, exc, pure)
 
     def do_residual_or_indirect_call(self, funcbox, calldescr, argboxes):
diff --git a/pypy/jit/metainterp/resoperation.py b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -90,7 +90,10 @@
         return op
 
     def __repr__(self):
-        return self.repr()
+        try:
+            return self.repr()
+        except NotImplementedError:
+            return object.__repr__(self)
 
     def repr(self, graytext=False):
         # RPython-friendly version
diff --git a/pypy/jit/metainterp/resume.py b/pypy/jit/metainterp/resume.py
--- a/pypy/jit/metainterp/resume.py
+++ b/pypy/jit/metainterp/resume.py
@@ -126,6 +126,7 @@
 UNASSIGNED = tag(-1<<13, TAGBOX)
 UNASSIGNEDVIRTUAL = tag(-1<<13, TAGVIRTUAL)
 NULLREF = tag(-1, TAGCONST)
+UNINITIALIZED = tag(-2, TAGCONST)   # used for uninitialized string characters
 
 
 class ResumeDataLoopMemo(object):
@@ -439,6 +440,8 @@
         self.storage.rd_pendingfields = rd_pendingfields
 
     def _gettagged(self, box):
+        if box is None:
+            return UNINITIALIZED
         if isinstance(box, Const):
             return self.memo.getconst(box)
         else:
@@ -572,7 +575,9 @@
         string = decoder.allocate_string(length)
         decoder.virtuals_cache[index] = string
         for i in range(length):
-            decoder.string_setitem(string, i, self.fieldnums[i])
+            charnum = self.fieldnums[i]
+            if not tagged_eq(charnum, UNINITIALIZED):
+                decoder.string_setitem(string, i, charnum)
         return string
 
     def debug_prints(self):
@@ -625,7 +630,9 @@
         string = decoder.allocate_unicode(length)
         decoder.virtuals_cache[index] = string
         for i in range(length):
-            decoder.unicode_setitem(string, i, self.fieldnums[i])
+            charnum = self.fieldnums[i]
+            if not tagged_eq(charnum, UNINITIALIZED):
+                decoder.unicode_setitem(string, i, charnum)
         return string
 
     def debug_prints(self):
diff --git a/pypy/jit/metainterp/test/test_ajit.py b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -3678,3 +3678,16 @@
         assert x == -42
         x = self.interp_operations(f, [1000, 1], translationoptions=topt)
         assert x == 999
+
+    def test_ll_arraycopy(self):
+        from pypy.rlib import rgc
+        A = lltype.GcArray(lltype.Char)
+        a = lltype.malloc(A, 10)
+        for i in range(10): a[i] = chr(i)
+        b = lltype.malloc(A, 10)
+        #
+        def f(c, d, e):
+            rgc.ll_arraycopy(a, b, c, d, e)
+            return 42
+        self.interp_operations(f, [1, 2, 3])
+        self.check_operations_history(call=1, guard_no_exception=0)
diff --git a/pypy/jit/metainterp/test/test_resume.py b/pypy/jit/metainterp/test/test_resume.py
--- a/pypy/jit/metainterp/test/test_resume.py
+++ b/pypy/jit/metainterp/test/test_resume.py
@@ -1135,16 +1135,11 @@
     assert ptr2.parent.next == ptr
 
 class CompareableConsts(object):
-    def __init__(self):
-        self.oldeq = None
-        
     def __enter__(self):
-        assert self.oldeq is None
-        self.oldeq = Const.__eq__
         Const.__eq__ = Const.same_box
-        
+
     def __exit__(self, type, value, traceback):
-        Const.__eq__ = self.oldeq
+        del Const.__eq__
 
 def test_virtual_adder_make_varray():
     b2s, b4s = [BoxPtr(), BoxInt(4)]
diff --git a/pypy/jit/metainterp/test/test_virtualstate.py b/pypy/jit/metainterp/test/test_virtualstate.py
--- a/pypy/jit/metainterp/test/test_virtualstate.py
+++ b/pypy/jit/metainterp/test/test_virtualstate.py
@@ -847,7 +847,8 @@
         i5 = arraylen_gc(p2, descr=arraydescr)
         i6 = int_ge(i5, 1)
         guard_true(i6) []
-        jump(p0, p1, p2)
+        p3 = getarrayitem_gc(p2, 0, descr=arraydescr)
+        jump(p0, p1, p3, p2)
         """
         self.optimize_bridge(loop, bridge, expected, p0=self.myptr)
 
diff --git a/pypy/module/__builtin__/functional.py b/pypy/module/__builtin__/functional.py
--- a/pypy/module/__builtin__/functional.py
+++ b/pypy/module/__builtin__/functional.py
@@ -312,11 +312,10 @@
 
 
 class W_XRange(Wrappable):
-    def __init__(self, space, start, stop, step):
+    def __init__(self, space, start, len, step):
         self.space = space
         self.start = start
-        self.stop = stop
-        self.len = get_len_of_range(space, start, stop, step)
+        self.len   = len
         self.step  = step
 
     def descr_new(space, w_subtype, w_start, w_stop=None, w_step=1):
@@ -326,8 +325,9 @@
             start, stop = 0, start
         else:
             stop = _toint(space, w_stop)
+        howmany = get_len_of_range(space, start, stop, step)
         obj = space.allocate_instance(W_XRange, w_subtype)
-        W_XRange.__init__(obj, space, start, stop, step)
+        W_XRange.__init__(obj, space, start, howmany, step)
         return space.wrap(obj)
 
     def descr_repr(self):
@@ -357,12 +357,12 @@
 
     def descr_iter(self):
         return self.space.wrap(W_XRangeIterator(self.space, self.start,
-                                                self.stop, self.step))
+                                                self.len, self.step))
 
     def descr_reversed(self):
         lastitem = self.start + (self.len-1) * self.step
         return self.space.wrap(W_XRangeIterator(self.space, lastitem,
-                                                self.start, -self.step, True))
+                                                self.len, -self.step))
 
     def descr_reduce(self):
         space = self.space
@@ -389,29 +389,25 @@
 )
 
 class W_XRangeIterator(Wrappable):
-    def __init__(self, space, start, stop, step, inclusive=False):
+    def __init__(self, space, current, remaining, step):
         self.space = space
-        self.current = start
-        self.stop = stop
+        self.current = current
+        self.remaining = remaining
         self.step = step
-        self.inclusive = inclusive
 
     def descr_iter(self):
         return self.space.wrap(self)
 
     def descr_next(self):
-        if self.inclusive:
-            if not ((self.step > 0 and self.current <= self.stop) or (self.step < 0 and self.current >= self.stop)):
-                raise OperationError(self.space.w_StopIteration, self.space.w_None)
-        else:
-            if not ((self.step > 0 and self.current < self.stop) or (self.step < 0 and self.current > self.stop)):
-                raise OperationError(self.space.w_StopIteration, self.space.w_None)
-        item = self.current
-        self.current = item + self.step
-        return self.space.wrap(item)
+        if self.remaining > 0:
+            item = self.current
+            self.current = item + self.step
+            self.remaining -= 1
+            return self.space.wrap(item)
+        raise OperationError(self.space.w_StopIteration, self.space.w_None)
 
-    #def descr_len(self):
-    #    return self.space.wrap(self.remaining)
+    def descr_len(self):
+        return self.space.wrap(self.remaining)
 
     def descr_reduce(self):
         from pypy.interpreter.mixedmodule import MixedModule
@@ -422,7 +418,7 @@
         w        = space.wrap
         nt = space.newtuple
 
-        tup = [w(self.current), w(self.stop), w(self.step)]
+        tup = [w(self.current), w(self.remaining), w(self.step)]
         return nt([new_inst, nt(tup)])
 
 W_XRangeIterator.typedef = TypeDef("rangeiterator",
diff --git a/pypy/module/__builtin__/test/test_functional.py b/pypy/module/__builtin__/test/test_functional.py
--- a/pypy/module/__builtin__/test/test_functional.py
+++ b/pypy/module/__builtin__/test/test_functional.py
@@ -157,8 +157,7 @@
        raises(OverflowError, xrange, a)
        raises(OverflowError, xrange, 0, a)
        raises(OverflowError, xrange, 0, 1, a)
-       assert list(reversed(xrange(-sys.maxint-1, -sys.maxint-1, -2))) == []
-       
+
    def test_xrange_reduce(self):
       x = xrange(2, 9, 3)
       callable, args = x.__reduce__()
diff --git a/pypy/module/_pickle_support/maker.py b/pypy/module/_pickle_support/maker.py
--- a/pypy/module/_pickle_support/maker.py
+++ b/pypy/module/_pickle_support/maker.py
@@ -66,10 +66,10 @@
     new_generator.running = running
     return space.wrap(new_generator)
 
- at unwrap_spec(current=int, stop=int, step=int)
-def xrangeiter_new(space, current, stop, step):
+ at unwrap_spec(current=int, remaining=int, step=int)
+def xrangeiter_new(space, current, remaining, step):
     from pypy.module.__builtin__.functional import W_XRangeIterator
-    new_iter = W_XRangeIterator(space, current, stop, step)
+    new_iter = W_XRangeIterator(space, current, remaining, step)
     return space.wrap(new_iter)
 
 @unwrap_spec(identifier=str)
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -392,6 +392,7 @@
         'Slice': 'space.gettypeobject(W_SliceObject.typedef)',
         'StaticMethod': 'space.gettypeobject(StaticMethod.typedef)',
         'CFunction': 'space.gettypeobject(cpyext.methodobject.W_PyCFunctionObject.typedef)',
+        'WrapperDescr': 'space.gettypeobject(cpyext.methodobject.W_PyCMethodObject.typedef)'
         }.items():
         GLOBALS['Py%s_Type#' % (cpyname, )] = ('PyTypeObject*', pypyexpr)
 
diff --git a/pypy/module/cpyext/include/patchlevel.h b/pypy/module/cpyext/include/patchlevel.h
--- a/pypy/module/cpyext/include/patchlevel.h
+++ b/pypy/module/cpyext/include/patchlevel.h
@@ -29,7 +29,7 @@
 #define PY_VERSION		"2.7.1"
 
 /* PyPy version as a string */
-#define PYPY_VERSION "1.6.1"
+#define PYPY_VERSION "1.7.1"
 
 /* Subversion Revision number of this file (not of the repository).
  * Empty since Mercurial migration. */
diff --git a/pypy/module/cpyext/methodobject.py b/pypy/module/cpyext/methodobject.py
--- a/pypy/module/cpyext/methodobject.py
+++ b/pypy/module/cpyext/methodobject.py
@@ -240,6 +240,7 @@
 def PyStaticMethod_New(space, w_func):
     return space.wrap(StaticMethod(w_func))
 
+ at cpython_api([PyObject, lltype.Ptr(PyMethodDef)], PyObject)
 def PyDescr_NewMethod(space, w_type, method):
     return space.wrap(W_PyCMethodObject(space, method, w_type))
 
diff --git a/pypy/module/cpyext/pyobject.py b/pypy/module/cpyext/pyobject.py
--- a/pypy/module/cpyext/pyobject.py
+++ b/pypy/module/cpyext/pyobject.py
@@ -116,8 +116,8 @@
     try:
         return typedescr_cache[typedef]
     except KeyError:
-        if typedef.base is not None:
-            return _get_typedescr_1(typedef.base)
+        if typedef.bases:
+            return _get_typedescr_1(typedef.bases[0])
         return typedescr_cache[None]
 
 def get_typedescr(typedef):
diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py
--- a/pypy/module/cpyext/stubs.py
+++ b/pypy/module/cpyext/stubs.py
@@ -586,10 +586,6 @@
 def PyDescr_NewMember(space, type, meth):
     raise NotImplementedError
 
- at cpython_api([PyTypeObjectPtr, PyMethodDef], PyObject)
-def PyDescr_NewMethod(space, type, meth):
-    raise NotImplementedError
-
 @cpython_api([PyTypeObjectPtr, wrapperbase, rffi.VOIDP], PyObject)
 def PyDescr_NewWrapper(space, type, wrapper, wrapped):
     raise NotImplementedError
@@ -610,14 +606,6 @@
 def PyWrapper_New(space, w_d, w_self):
     raise NotImplementedError
 
- at cpython_api([PyObject], PyObject)
-def PyDictProxy_New(space, dict):
-    """Return a proxy object for a mapping which enforces read-only behavior.
-    This is normally used to create a proxy to prevent modification of the
-    dictionary for non-dynamic class types.
-    """
-    raise NotImplementedError
-
 @cpython_api([PyObject, PyObject, rffi.INT_real], rffi.INT_real, error=-1)
 def PyDict_Merge(space, a, b, override):
     """Iterate over mapping object b adding key-value pairs to dictionary a.
@@ -2293,15 +2281,6 @@
     changes in your code for properly supporting 64-bit systems."""
     raise NotImplementedError
 
- at cpython_api([rffi.CWCHARP, Py_ssize_t, rffi.CCHARP], PyObject)
-def PyUnicode_EncodeUTF8(space, s, size, errors):
-    """Encode the Py_UNICODE buffer of the given size using UTF-8 and return a
-    Python string object.  Return NULL if an exception was raised by the codec.
-
-    This function used an int type for size. This might require
-    changes in your code for properly supporting 64-bit systems."""
-    raise NotImplementedError
-
 @cpython_api([rffi.CCHARP, Py_ssize_t, rffi.CCHARP, rffi.INTP], PyObject)
 def PyUnicode_DecodeUTF32(space, s, size, errors, byteorder):
     """Decode length bytes from a UTF-32 encoded buffer string and return the
@@ -2481,31 +2460,6 @@
     was raised by the codec."""
     raise NotImplementedError
 
- at cpython_api([rffi.CCHARP, Py_ssize_t, rffi.CCHARP], PyObject)
-def PyUnicode_DecodeLatin1(space, s, size, errors):
-    """Create a Unicode object by decoding size bytes of the Latin-1 encoded string
-    s.  Return NULL if an exception was raised by the codec.
-
-    This function used an int type for size. This might require
-    changes in your code for properly supporting 64-bit systems."""
-    raise NotImplementedError
-
- at cpython_api([rffi.CWCHARP, Py_ssize_t, rffi.CCHARP], PyObject)
-def PyUnicode_EncodeLatin1(space, s, size, errors):
-    """Encode the Py_UNICODE buffer of the given size using Latin-1 and return
-    a Python string object.  Return NULL if an exception was raised by the codec.
-
-    This function used an int type for size. This might require
-    changes in your code for properly supporting 64-bit systems."""
-    raise NotImplementedError
-
- at cpython_api([PyObject], PyObject)
-def PyUnicode_AsLatin1String(space, unicode):
-    """Encode a Unicode object using Latin-1 and return the result as Python string
-    object.  Error handling is "strict".  Return NULL if an exception was raised
-    by the codec."""
-    raise NotImplementedError
-
 @cpython_api([rffi.CCHARP, Py_ssize_t, PyObject, rffi.CCHARP], PyObject)
 def PyUnicode_DecodeCharmap(space, s, size, mapping, errors):
     """Create a Unicode object by decoding size bytes of the encoded string s using
@@ -2564,13 +2518,6 @@
     """
     raise NotImplementedError
 
- at cpython_api([PyObject], PyObject)
-def PyUnicode_AsMBCSString(space, unicode):
-    """Encode a Unicode object using MBCS and return the result as Python string
-    object.  Error handling is "strict".  Return NULL if an exception was raised
-    by the codec."""
-    raise NotImplementedError
-
 @cpython_api([PyObject, PyObject], PyObject)
 def PyUnicode_Concat(space, left, right):
     """Concat two strings giving a new Unicode string."""
@@ -2912,16 +2859,3 @@
     """Return true if ob is a proxy object.
     """
     raise NotImplementedError
-
- at cpython_api([PyObject, PyObject], PyObject)
-def PyWeakref_NewProxy(space, ob, callback):
-    """Return a weak reference proxy object for the object ob.  This will always
-    return a new reference, but is not guaranteed to create a new object; an
-    existing proxy object may be returned.  The second parameter, callback, can
-    be a callable object that receives notification when ob is garbage
-    collected; it should accept a single parameter, which will be the weak
-    reference object itself. callback may also be None or NULL.  If ob
-    is not a weakly-referencable object, or if callback is not callable,
-    None, or NULL, this will return NULL and raise TypeError.
-    """
-    raise NotImplementedError
diff --git a/pypy/module/cpyext/test/test_methodobject.py b/pypy/module/cpyext/test/test_methodobject.py
--- a/pypy/module/cpyext/test/test_methodobject.py
+++ b/pypy/module/cpyext/test/test_methodobject.py
@@ -79,7 +79,7 @@
         raises(TypeError, mod.isSameFunction, 1)
 
 class TestPyCMethodObject(BaseApiTest):
-    def test_repr(self, space):
+    def test_repr(self, space, api):
         """
         W_PyCMethodObject has a repr string which describes it as a method
         and gives its name and the name of its class.
@@ -94,7 +94,7 @@
         ml.c_ml_meth = rffi.cast(PyCFunction_typedef,
                                  c_func.get_llhelper(space))
 
-        method = PyDescr_NewMethod(space, space.w_str, ml)
+        method = api.PyDescr_NewMethod(space.w_str, ml)
         assert repr(method).startswith(
             "<built-in method 'func' of 'str' object ")
 
diff --git a/pypy/module/cpyext/test/test_unicodeobject.py b/pypy/module/cpyext/test/test_unicodeobject.py
--- a/pypy/module/cpyext/test/test_unicodeobject.py
+++ b/pypy/module/cpyext/test/test_unicodeobject.py
@@ -188,6 +188,12 @@
         assert space.unwrap(w_u) == 'sp'
         rffi.free_charp(u)
 
+    def test_encode_utf8(self, space, api):
+        u = rffi.unicode2wcharp(u'sp&#65533;m')
+        w_s = api.PyUnicode_EncodeUTF8(u, 4, None)
+        assert space.unwrap(w_s) == u'sp&#65533;m'.encode('utf-8')
+        rffi.free_wcharp(u)
+
     def test_IS(self, space, api):
         for char in [0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x1c, 0x1d, 0x1e, 0x1f,
                      0x20, 0x85, 0xa0, 0x1680, 0x2000, 0x2001, 0x2002,
@@ -385,6 +391,24 @@
                     data, len(u), lltype.nullptr(rffi.CCHARP.TO))
         rffi.free_wcharp(data)
 
+    def test_latin1(self, space, api):
+        s = 'abcdefg'
+        data = rffi.str2charp(s)
+        w_u = api.PyUnicode_DecodeLatin1(data, len(s), lltype.nullptr(rffi.CCHARP.TO))
+        assert space.eq_w(w_u, space.wrap(u"abcdefg"))
+        rffi.free_charp(data)
+
+        uni = u'abcdefg'
+        data = rffi.unicode2wcharp(uni)
+        w_s = api.PyUnicode_EncodeLatin1(data, len(uni), lltype.nullptr(rffi.CCHARP.TO))
+        assert space.eq_w(space.wrap("abcdefg"), w_s)
+        rffi.free_wcharp(data)
+
+        ustr = "abcdef"
+        w_ustr = space.wrap(ustr.decode("ascii"))
+        result = api.PyUnicode_AsLatin1String(w_ustr)
+        assert space.eq_w(space.wrap(ustr), result)
+
     def test_format(self, space, api):
         w_format = space.wrap(u'hi %s')
         w_args = space.wrap((u'test',))
diff --git a/pypy/module/cpyext/test/test_weakref.py b/pypy/module/cpyext/test/test_weakref.py
--- a/pypy/module/cpyext/test/test_weakref.py
+++ b/pypy/module/cpyext/test/test_weakref.py
@@ -15,6 +15,12 @@
         assert api.PyErr_Occurred() is space.w_TypeError
         api.PyErr_Clear()
 
+    def test_proxy(self, space, api):
+        w_obj = space.w_Warning # some weakrefable object
+        w_proxy = api.PyWeakref_NewProxy(w_obj, None)
+        assert space.unwrap(space.str(w_proxy)) == "<type 'exceptions.Warning'>"
+        assert space.unwrap(space.repr(w_proxy)).startswith('<weak')
+
     def test_weakref_lockobject(self, space, api):
         # some new weakrefable object
         w_obj = space.call_function(space.w_type, space.wrap("newtype"),
diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py
--- a/pypy/module/cpyext/unicodeobject.py
+++ b/pypy/module/cpyext/unicodeobject.py
@@ -14,6 +14,7 @@
 from pypy.module.sys.interp_encoding import setdefaultencoding
 from pypy.objspace.std import unicodeobject, unicodetype
 from pypy.rlib import runicode
+from pypy.tool.sourcetools import func_renamer
 import sys
 
 ## See comment in stringobject.py.
@@ -417,26 +418,49 @@
     ref[0] = rffi.cast(PyObject, py_newuni)
     return 0
 
- at cpython_api([PyObject], PyObject)
-def PyUnicode_AsUTF8String(space, w_unicode):
-    """Encode a Unicode object using UTF-8 and return the result as Python string
-    object.  Error handling is "strict".  Return NULL if an exception was raised
-    by the codec."""
-    if not PyUnicode_Check(space, w_unicode):
-        PyErr_BadArgument(space)
-    return unicodetype.encode_object(space, w_unicode, "utf-8", "strict")
+def make_conversion_functions(suffix, encoding):
+    @cpython_api([PyObject], PyObject)
+    @func_renamer('PyUnicode_As%sString' % suffix)
+    def PyUnicode_AsXXXString(space, w_unicode):
+        """Encode a Unicode object and return the result as Python
+        string object.  Error handling is "strict".  Return NULL if an
+        exception was raised by the codec."""
+        if not PyUnicode_Check(space, w_unicode):
+            PyErr_BadArgument(space)
+        return unicodetype.encode_object(space, w_unicode, encoding, "strict")
 
- at cpython_api([CONST_STRING, Py_ssize_t, CONST_STRING], PyObject)
-def PyUnicode_DecodeUTF8(space, s, size, errors):
-    """Create a Unicode object by decoding size bytes of the UTF-8 encoded string
-    s. Return NULL if an exception was raised by the codec.
-    """
-    w_str = space.wrap(rffi.charpsize2str(s, size))
-    if errors:
-        w_errors = space.wrap(rffi.charp2str(errors))
-    else:
-        w_errors = space.w_None
-    return space.call_method(w_str, 'decode', space.wrap("utf-8"), w_errors)
+    @cpython_api([CONST_STRING, Py_ssize_t, CONST_STRING], PyObject)
+    @func_renamer('PyUnicode_Decode%s' % suffix)
+    def PyUnicode_DecodeXXX(space, s, size, errors):
+        """Create a Unicode object by decoding size bytes of the
+        encoded string s. Return NULL if an exception was raised by
+        the codec.
+        """
+        w_s = space.wrap(rffi.charpsize2str(s, size))
+        if errors:
+            w_errors = space.wrap(rffi.charp2str(errors))
+        else:
+            w_errors = space.w_None
+        return space.call_method(w_s, 'decode', space.wrap(encoding), w_errors)
+
+    @cpython_api([CONST_WSTRING, Py_ssize_t, CONST_STRING], PyObject)
+    @func_renamer('PyUnicode_Encode%s' % suffix)
+    def PyUnicode_EncodeXXX(space, s, size, errors):
+        """Encode the Py_UNICODE buffer of the given size and return a
+        Python string object.  Return NULL if an exception was raised
+        by the codec."""
+        w_u = space.wrap(rffi.wcharpsize2unicode(s, size))
+        if errors:
+            w_errors = space.wrap(rffi.charp2str(errors))
+        else:
+            w_errors = space.w_None
+        return space.call_method(w_u, 'encode', space.wrap(encoding), w_errors)
+
+make_conversion_functions('UTF8', 'utf-8')
+make_conversion_functions('ASCII', 'ascii')
+make_conversion_functions('Latin1', 'latin-1')
+if sys.platform == 'win32':
+    make_conversion_functions('MBCS', 'mbcs')
 
 @cpython_api([rffi.CCHARP, Py_ssize_t, rffi.CCHARP, rffi.INTP], PyObject)
 def PyUnicode_DecodeUTF16(space, s, size, llerrors, pbyteorder):
@@ -493,56 +517,6 @@
 
     return space.wrap(result)
 
- at cpython_api([PyObject], PyObject)
-def PyUnicode_AsASCIIString(space, w_unicode):
-    """Encode a Unicode object using ASCII and return the result as Python string
-    object.  Error handling is "strict".  Return NULL if an exception was raised
-    by the codec."""
-    return space.call_method(w_unicode, 'encode', space.wrap('ascii')) #space.w_None for errors?
-
- at cpython_api([rffi.CCHARP, Py_ssize_t, rffi.CCHARP], PyObject)
-def PyUnicode_DecodeASCII(space, s, size, errors):
-    """Create a Unicode object by decoding size bytes of the ASCII encoded string
-    s.  Return NULL if an exception was raised by the codec."""
-    w_s = space.wrap(rffi.charpsize2str(s, size))
-    return space.call_method(w_s, 'decode', space.wrap('ascii'))
-
- at cpython_api([rffi.CWCHARP, Py_ssize_t, rffi.CCHARP], PyObject)
-def PyUnicode_EncodeASCII(space, s, size, errors):
-    """Encode the Py_UNICODE buffer of the given size using ASCII and return a
-    Python string object.  Return NULL if an exception was raised by the codec.
-    """
-
-    w_s = space.wrap(rffi.wcharpsize2unicode(s, size))
-    return space.call_method(w_s, 'encode', space.wrap('ascii'))
-
-if sys.platform == 'win32':
-    @cpython_api([CONST_WSTRING, Py_ssize_t, CONST_STRING], PyObject)
-    def PyUnicode_EncodeMBCS(space, wchar_p, length, errors):
-        """Encode the Py_UNICODE buffer of the given size using MBCS and return a
-        Python string object.  Return NULL if an exception was raised by the codec.
-        """
-        w_unicode = space.wrap(rffi.wcharpsize2unicode(wchar_p, length))
-        if errors:
-            w_errors = space.wrap(rffi.charp2str(errors))
-        else:
-            w_errors = space.w_None
-        return space.call_method(w_unicode, "encode",
-                                 space.wrap("mbcs"), w_errors)
-
-    @cpython_api([CONST_STRING, Py_ssize_t, CONST_STRING], PyObject)
-    def PyUnicode_DecodeMBCS(space, s, size, errors):
-        """Create a Unicode object by decoding size bytes of the MBCS encoded string s.
-        Return NULL if an exception was raised by the codec.
-        """
-        w_str = space.wrap(rffi.charpsize2str(s, size))
-        w_encoding = space.wrap("mbcs")
-        if errors:
-            w_errors = space.wrap(rffi.charp2str(errors))
-        else:
-            w_errors = space.w_None
-        return space.call_method(w_str, 'decode', w_encoding, w_errors)
-
 @cpython_api([PyObject, PyObject], rffi.INT_real, error=-2)
 def PyUnicode_Compare(space, w_left, w_right):
     """Compare two strings and return -1, 0, 1 for less than, equal, and greater
diff --git a/pypy/module/cpyext/weakrefobject.py b/pypy/module/cpyext/weakrefobject.py
--- a/pypy/module/cpyext/weakrefobject.py
+++ b/pypy/module/cpyext/weakrefobject.py
@@ -1,6 +1,6 @@
 from pypy.module.cpyext.api import cpython_api
 from pypy.module.cpyext.pyobject import PyObject, borrow_from
-from pypy.module._weakref.interp__weakref import W_Weakref
+from pypy.module._weakref.interp__weakref import W_Weakref, proxy
 
 @cpython_api([PyObject, PyObject], PyObject)
 def PyWeakref_NewRef(space, w_obj, w_callback):
@@ -16,6 +16,20 @@
     w_weakref = space.gettypeobject(W_Weakref.typedef)
     return space.call_function(w_weakref, w_obj, w_callback)
 
+ at cpython_api([PyObject, PyObject], PyObject)
+def PyWeakref_NewProxy(space, w_obj, w_callback):
+    """Return a weak reference proxy object for the object *ob*.  This will
+    alwas return a new reference, but is not guaranteed to create a new
+    object; an existing proxy object may be returned.  The second parameter,
+    *callback*, can be a callable object that receives notification when *ob*
+    is garbage collected; it should accept a single parameter, which will be
+    the weak reference object itself. *callback* may also be ``None`` or
+    *NULL*.  If *ob* is not a weakly-referencable object, or if *callback* is
+    not callable, ``None``, or *NULL*, this will return *NULL* and raise
+    :exc:`TypeError`.
+    """
+    return proxy(space, w_obj, w_callback)
+
 @cpython_api([PyObject], PyObject)
 def PyWeakref_GetObject(space, w_ref):
     """Return the referenced object from a weak reference.  If the referent is
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -201,6 +201,9 @@
     def descr_get_shape(self, space):
         return space.newtuple([self.descr_len(space)])
 
+    def descr_get_size(self, space):
+        return space.wrap(self.find_size())
+
     def descr_copy(self, space):
         return space.call_function(space.gettypefor(BaseArray), self, self.find_dtype())
 
@@ -607,6 +610,7 @@
 
     dtype = GetSetProperty(BaseArray.descr_get_dtype),
     shape = GetSetProperty(BaseArray.descr_get_shape),
+    size = GetSetProperty(BaseArray.descr_get_size),
 
     mean = interp2app(BaseArray.descr_mean),
     sum = interp2app(BaseArray.descr_sum),
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -17,6 +17,14 @@
         a[13] = 5.3
         assert a[13] == 5.3
 
+    def test_size(self):
+        from numpy import array
+        # XXX fixed on multidim branch
+        #assert array(3).size == 1
+        a = array([1, 2, 3])
+        assert a.size == 3
+        assert (a + a).size == 3
+
     def test_empty(self):
         """
         Test that empty() works.
diff --git a/pypy/module/select/test/test_select.py b/pypy/module/select/test/test_select.py
--- a/pypy/module/select/test/test_select.py
+++ b/pypy/module/select/test/test_select.py
@@ -214,11 +214,15 @@
 
     def test_poll(self):
         import select
-        class A(object):
-            def __int__(self):
-                return 3
-        
-        select.poll().poll(A()) # assert did not crash
+        readend, writeend = self.getpair()
+        try:
+            class A(object):
+                def __int__(self):
+                    return readend.fileno()
+            select.poll().poll(A()) # assert did not crash
+        finally:
+            readend.close()
+            writeend.close()
 
 class AppTestSelectWithPipes(_AppTestSelect):
     "Use a pipe to get pairs of file descriptors"
diff --git a/pypy/module/signal/__init__.py b/pypy/module/signal/__init__.py
--- a/pypy/module/signal/__init__.py
+++ b/pypy/module/signal/__init__.py
@@ -20,7 +20,7 @@
         interpleveldefs['pause'] = 'interp_signal.pause'
         interpleveldefs['siginterrupt'] = 'interp_signal.siginterrupt'
 
-    if hasattr(cpy_signal, 'setitimer'):
+    if os.name == 'posix':
         interpleveldefs['setitimer'] = 'interp_signal.setitimer'
         interpleveldefs['getitimer'] = 'interp_signal.getitimer'
         for name in ['ITIMER_REAL', 'ITIMER_VIRTUAL', 'ITIMER_PROF']:
diff --git a/pypy/module/signal/test/test_signal.py b/pypy/module/signal/test/test_signal.py
--- a/pypy/module/signal/test/test_signal.py
+++ b/pypy/module/signal/test/test_signal.py
@@ -1,4 +1,4 @@
-import os, py
+import os, py, sys
 import signal as cpy_signal
 from pypy.conftest import gettestobjspace
 
@@ -264,6 +264,10 @@
 class AppTestItimer:
     spaceconfig = dict(usemodules=['signal'])
 
+    def setup_class(cls):
+        if sys.platform == 'win32':
+            py.test.skip("Unix only")
+
     def test_itimer_real(self):
         import signal
 
diff --git a/pypy/module/sys/version.py b/pypy/module/sys/version.py
--- a/pypy/module/sys/version.py
+++ b/pypy/module/sys/version.py
@@ -10,7 +10,7 @@
 CPYTHON_VERSION            = (2, 7, 1, "final", 42)   #XXX # sync patchlevel.h
 CPYTHON_API_VERSION        = 1013   #XXX # sync with include/modsupport.h
 
-PYPY_VERSION               = (1, 6, 1, "dev", 0)    #XXX # sync patchlevel.h
+PYPY_VERSION               = (1, 7, 1, "dev", 0)    #XXX # sync patchlevel.h
 
 if platform.name == 'msvc':
     COMPILER_INFO = 'MSC v.%d 32 bit' % (platform.version * 10 + 600)
diff --git a/pypy/objspace/flow/operation.py b/pypy/objspace/flow/operation.py
--- a/pypy/objspace/flow/operation.py
+++ b/pypy/objspace/flow/operation.py
@@ -11,7 +11,7 @@
 from pypy.interpreter.baseobjspace import ObjSpace
 from pypy.interpreter.error import OperationError
 from pypy.tool.sourcetools import compile2
-from pypy.rlib.rarithmetic import ovfcheck, ovfcheck_lshift
+from pypy.rlib.rarithmetic import ovfcheck
 from pypy.objspace.flow import model
 
 
@@ -144,7 +144,7 @@
     return ovfcheck(x % y)
 
 def lshift_ovf(x, y):
-    return ovfcheck_lshift(x, y)
+    return ovfcheck(x << y)
 
 # slicing: operator.{get,set,del}slice() don't support b=None or c=None
 def do_getslice(a, b, c):
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
@@ -6,7 +6,7 @@
 from pypy.objspace.std.noneobject import W_NoneObject
 from pypy.objspace.std.register_all import register_all
 from pypy.rlib import jit
-from pypy.rlib.rarithmetic import ovfcheck, ovfcheck_lshift, LONG_BIT, r_uint
+from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT, r_uint
 from pypy.rlib.rbigint import rbigint
 
 """
@@ -245,7 +245,7 @@
     b = w_int2.intval
     if r_uint(b) < LONG_BIT: # 0 <= b < LONG_BIT
         try:
-            c = ovfcheck_lshift(a, b)
+            c = ovfcheck(a << b)
         except OverflowError:
             raise FailedToImplementArgs(space.w_OverflowError,
                                     space.wrap("integer left shift"))
diff --git a/pypy/objspace/std/stdtypedef.py b/pypy/objspace/std/stdtypedef.py
--- a/pypy/objspace/std/stdtypedef.py
+++ b/pypy/objspace/std/stdtypedef.py
@@ -32,11 +32,14 @@
     from pypy.objspace.std.objecttype import object_typedef
     if b is object_typedef:
         return True
-    while a is not b:
-        if a is None:
-            return False
-        a = a.base
-    return True
+    if a is None:
+        return False
+    if a is b:
+        return True
+    for a1 in a.bases:
+        if issubtypedef(a1, b):
+            return True
+    return False
 
 std_dict_descr = GetSetProperty(descr_get_dict, descr_set_dict, descr_del_dict,
                     doc="dictionary for instance variables (if defined)")
@@ -75,8 +78,8 @@
         if typedef is object_typedef:
             bases_w = []
         else:
-            base = typedef.base or object_typedef
-            bases_w = [space.gettypeobject(base)]
+            bases = typedef.bases or [object_typedef]
+            bases_w = [space.gettypeobject(base) for base in bases]
 
         # wrap everything
         dict_w = {}
diff --git a/pypy/objspace/std/test/test_stdobjspace.py b/pypy/objspace/std/test/test_stdobjspace.py
--- a/pypy/objspace/std/test/test_stdobjspace.py
+++ b/pypy/objspace/std/test/test_stdobjspace.py
@@ -1,5 +1,6 @@
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.gateway import app2interp
+from pypy.conftest import gettestobjspace
 
 class TestW_StdObjSpace:
 
@@ -60,3 +61,10 @@
             typedef = None
 
         assert space.isinstance_w(X(), space.w_str)
+
+    def test_withstrbuf_fastpath_isinstance(self):
+        from pypy.objspace.std.stringobject import W_StringObject
+
+        space = gettestobjspace(withstrbuf=True) 
+        assert space._get_interplevel_cls(space.w_str) is W_StringObject
+        
diff --git a/pypy/rlib/listsort.py b/pypy/rlib/listsort.py
--- a/pypy/rlib/listsort.py
+++ b/pypy/rlib/listsort.py
@@ -1,4 +1,4 @@
-from pypy.rlib.rarithmetic import ovfcheck, ovfcheck_lshift
+from pypy.rlib.rarithmetic import ovfcheck
 
 
 ## ------------------------------------------------------------------------
@@ -136,7 +136,7 @@
                     if lower(a.list[p + ofs], key):
                         lastofs = ofs
                         try:
-                            ofs = ovfcheck_lshift(ofs, 1)
+                            ofs = ovfcheck(ofs << 1)
                         except OverflowError:
                             ofs = maxofs
                         else:
@@ -161,7 +161,7 @@
                         # key <= a[hint - ofs]
                         lastofs = ofs
                         try:
-                            ofs = ovfcheck_lshift(ofs, 1)
+                            ofs = ovfcheck(ofs << 1)
                         except OverflowError:
                             ofs = maxofs
                         else:
diff --git a/pypy/rlib/rarithmetic.py b/pypy/rlib/rarithmetic.py
--- a/pypy/rlib/rarithmetic.py
+++ b/pypy/rlib/rarithmetic.py
@@ -12,9 +12,6 @@
          back to a signed int value
 ovfcheck check on CPython whether the result of a signed
          integer operation did overflow
-ovfcheck_lshift
-         << with oveflow checking
-         catering to 2.3/2.4 differences about <<
 ovfcheck_float_to_int
          convert to an integer or raise OverflowError
 r_longlong
@@ -111,18 +108,6 @@
         raise OverflowError, "signed integer expression did overflow"
     return r
 
-def _local_ovfcheck(r):
-    # a copy of the above, because we cannot call ovfcheck
-    # in a context where no primitiveoperator is involved.
-    assert not isinstance(r, r_uint), "unexpected ovf check on unsigned"
-    if isinstance(r, long):
-        raise OverflowError, "signed integer expression did overflow"
-    return r
-
-def ovfcheck_lshift(a, b):
-    "NOT_RPYTHON"
-    return _local_ovfcheck(int(long(a) << b))
-
 # Strange things happening for float to int on 64 bit:
 # int(float(i)) != i  because of rounding issues.
 # These are the minimum and maximum float value that can
diff --git a/pypy/rlib/rgc.py b/pypy/rlib/rgc.py
--- a/pypy/rlib/rgc.py
+++ b/pypy/rlib/rgc.py
@@ -163,8 +163,10 @@
                                                 source_start, dest_start,
                                                 length):
             # if the write barrier is not supported, copy by hand
-            for i in range(length):
+            i = 0
+            while i < length:
                 dest[i + dest_start] = source[i + source_start]
+                i += 1
             return
     source_addr = llmemory.cast_ptr_to_adr(source)
     dest_addr   = llmemory.cast_ptr_to_adr(dest)
@@ -214,8 +216,8 @@
     func._gc_no_collect_ = True
     return func
 
-def is_light_finalizer(func):
-    func._is_light_finalizer_ = True
+def must_be_light_finalizer(func):
+    func._must_be_light_finalizer_ = True
     return func
 
 # ____________________________________________________________
diff --git a/pypy/rpython/llinterp.py b/pypy/rpython/llinterp.py
--- a/pypy/rpython/llinterp.py
+++ b/pypy/rpython/llinterp.py
@@ -1,6 +1,6 @@
 from pypy.objspace.flow.model import FunctionGraph, Constant, Variable, c_last_exception
 from pypy.rlib.rarithmetic import intmask, r_uint, ovfcheck, r_longlong
-from pypy.rlib.rarithmetic import r_ulonglong, ovfcheck_lshift
+from pypy.rlib.rarithmetic import r_ulonglong
 from pypy.rpython.lltypesystem import lltype, llmemory, lloperation, llheap
 from pypy.rpython.lltypesystem import rclass
 from pypy.rpython.ootypesystem import ootype
@@ -1035,7 +1035,7 @@
         assert isinstance(x, int)
         assert isinstance(y, int)
         try:
-            return ovfcheck_lshift(x, y)
+            return ovfcheck(x << y)
         except OverflowError:
             self.make_llexception()
 
diff --git a/pypy/rpython/lltypesystem/module/ll_math.py b/pypy/rpython/lltypesystem/module/ll_math.py
--- a/pypy/rpython/lltypesystem/module/ll_math.py
+++ b/pypy/rpython/lltypesystem/module/ll_math.py
@@ -11,15 +11,17 @@
 from pypy.translator.platform import platform
 from pypy.rlib.rfloat import isfinite, isinf, isnan, INFINITY, NAN
 
+use_library_isinf_isnan = False
 if sys.platform == "win32":
     if platform.name == "msvc":
         # When compiled with /O2 or /Oi (enable intrinsic functions)
         # It's no more possible to take the address of some math functions.
         # Ensure that the compiler chooses real functions instead.
         eci = ExternalCompilationInfo(
-            includes = ['math.h'],
+            includes = ['math.h', 'float.h'],
             post_include_bits = ['#pragma function(floor)'],
             )
+        use_library_isinf_isnan = True
     else:
         eci = ExternalCompilationInfo()
     # Some math functions are C99 and not defined by the Microsoft compiler
@@ -108,18 +110,32 @@
 #
 # Custom implementations
 
+VERY_LARGE_FLOAT = 1.0
+while VERY_LARGE_FLOAT * 100.0 != INFINITY:
+    VERY_LARGE_FLOAT *= 64.0
+
+_lib_isnan = rffi.llexternal("_isnan", [lltype.Float], lltype.Signed,
+                             compilation_info=eci)
+_lib_finite = rffi.llexternal("_finite", [lltype.Float], lltype.Signed,
+                             compilation_info=eci)
+
 def ll_math_isnan(y):
     # By not calling into the external function the JIT can inline this.
     # Floats are awesome.
+    if use_library_isinf_isnan and not jit.we_are_jitted():
+        return bool(_lib_isnan(y))
     return y != y
 
 def ll_math_isinf(y):
-    # Use a bitwise OR so the JIT doesn't produce 2 different guards.
-    return (y == INFINITY) | (y == -INFINITY)
+    if use_library_isinf_isnan and not jit.we_are_jitted():
+        return not _lib_finite(y) and not _lib_isnan(y)
+    return (y + VERY_LARGE_FLOAT) == y
 
 def ll_math_isfinite(y):
     # Use a custom hack that is reasonably well-suited to the JIT.
     # Floats are awesome (bis).
+    if use_library_isinf_isnan and not jit.we_are_jitted():
+        return bool(_lib_finite(y))
     z = 0.0 * y
     return z == z       # i.e.: z is not a NaN
 
@@ -136,10 +152,12 @@
     Windows, FreeBSD and alpha Tru64 are amongst platforms that don't
     always follow C99.
     """
-    if isnan(x) or isnan(y):
+    if isnan(x):
         return NAN
 
-    if isinf(y):
+    if not isfinite(y):
+        if isnan(y):
+            return NAN
         if isinf(x):
             if math_copysign(1.0, x) == 1.0:
                 # atan2(+-inf, +inf) == +-pi/4
@@ -168,7 +186,7 @@
 
 def ll_math_frexp(x):
     # deal with special cases directly, to sidestep platform differences
-    if isnan(x) or isinf(x) or not x:
+    if not isfinite(x) or not x:
         mantissa = x
         exponent = 0
     else:
@@ -185,7 +203,7 @@
 INT_MIN = int(-2**31)
 
 def ll_math_ldexp(x, exp):
-    if x == 0.0 or isinf(x) or isnan(x):
+    if x == 0.0 or not isfinite(x):
         return x    # NaNs, zeros and infinities are returned unchanged
     if exp > INT_MAX:
         # overflow (64-bit platforms only)
@@ -209,10 +227,11 @@
 def ll_math_modf(x):
     # some platforms don't do the right thing for NaNs and
     # infinities, so we take care of special cases directly.
-    if isinf(x):
-        return (math_copysign(0.0, x), x)
-    elif isnan(x):
-        return (x, x)
+    if not isfinite(x):
+        if isnan(x):
+            return (x, x)
+        else:   # isinf(x)
+            return (math_copysign(0.0, x), x)
     intpart_p = lltype.malloc(rffi.DOUBLEP.TO, 1, flavor='raw')
     try:
         fracpart = math_modf(x, intpart_p)
@@ -223,13 +242,21 @@
 
 
 def ll_math_fmod(x, y):
-    if isinf(x) and not isnan(y):
-        raise ValueError("math domain error")
+    # fmod(x, +/-Inf) returns x for finite x.
+    if isinf(y) and isfinite(x):
+        return x
 
-    if y == 0:
-        raise ValueError("math domain error")
-
-    return math_fmod(x, y)
+    _error_reset()
+    r = math_fmod(x, y)
+    errno = rposix.get_errno()
+    if isnan(r):
+        if isnan(x) or isnan(y):
+            errno = 0
+        else:
+            errno = EDOM
+    if errno:
+        _likely_raise(errno, r)
+    return r
 
 
 def ll_math_hypot(x, y):
@@ -242,16 +269,17 @@
     _error_reset()
     r = math_hypot(x, y)
     errno = rposix.get_errno()
-    if isnan(r):
-        if isnan(x) or isnan(y):
-            errno = 0
-        else:
-            errno = EDOM
-    elif isinf(r):
-        if isinf(x) or isnan(x) or isinf(y) or isnan(y):
-            errno = 0
-        else:
-            errno = ERANGE
+    if not isfinite(r):
+        if isnan(r):
+            if isnan(x) or isnan(y):
+                errno = 0
+            else:
+                errno = EDOM
+        else:  # isinf(r)
+            if isfinite(x) and isfinite(y):
+                errno = ERANGE
+            else:
+                errno = 0
     if errno:
         _likely_raise(errno, r)
     return r
@@ -261,30 +289,30 @@
     # deal directly with IEEE specials, to cope with problems on various
     # platforms whose semantics don't exactly match C99
 
-    if isnan(x):
-        if y == 0.0:
-            return 1.0   # NaN**0 = 1
-        return x
-
-    elif isnan(y):
+    if isnan(y):
         if x == 1.0:
             return 1.0   # 1**Nan = 1
         return y
 
-    elif isinf(x):
-        odd_y = not isinf(y) and math_fmod(math_fabs(y), 2.0) == 1.0
-        if y > 0.0:
-            if odd_y:
-                return x
-            return math_fabs(x)
-        elif y == 0.0:
-            return 1.0
-        else:   # y < 0.0
-            if odd_y:
-                return math_copysign(0.0, x)
-            return 0.0
+    if not isfinite(x):
+        if isnan(x):
+            if y == 0.0:
+                return 1.0   # NaN**0 = 1
+            return x
+        else:   # isinf(x)
+            odd_y = not isinf(y) and math_fmod(math_fabs(y), 2.0) == 1.0
+            if y > 0.0:
+                if odd_y:
+                    return x
+                return math_fabs(x)
+            elif y == 0.0:
+                return 1.0
+            else:   # y < 0.0
+                if odd_y:
+                    return math_copysign(0.0, x)
+                return 0.0
 
-    elif isinf(y):
+    if isinf(y):
         if math_fabs(x) == 1.0:
             return 1.0
         elif y > 0.0 and math_fabs(x) > 1.0:
@@ -299,17 +327,18 @@
     _error_reset()
     r = math_pow(x, y)
     errno = rposix.get_errno()
-    if isnan(r):
-        # a NaN result should arise only from (-ve)**(finite non-integer)
-        errno = EDOM
-    elif isinf(r):
-        # an infinite result here arises either from:
-        # (A) (+/-0.)**negative (-> divide-by-zero)
-        # (B) overflow of x**y with x and y finite
-        if x == 0.0:
+    if not isfinite(r):
+        if isnan(r):
+            # a NaN result should arise only from (-ve)**(finite non-integer)
             errno = EDOM
-        else:
-            errno = ERANGE
+        else:   # isinf(r)
+            # an infinite result here arises either from:
+            # (A) (+/-0.)**negative (-> divide-by-zero)
+            # (B) overflow of x**y with x and y finite
+            if x == 0.0:
+                errno = EDOM
+            else:
+                errno = ERANGE
     if errno:
         _likely_raise(errno, r)
     return r
@@ -358,18 +387,19 @@
         r = c_func(x)
         # Error checking fun.  Copied from CPython 2.6
         errno = rposix.get_errno()
-        if isnan(r):
-            if isnan(x):
-                errno = 0
-            else:
-                errno = EDOM
-        elif isinf(r):
-            if isinf(x) or isnan(x):
-                errno = 0
-            elif can_overflow:
-                errno = ERANGE
-            else:
-                errno = EDOM
+        if not isfinite(r):
+            if isnan(r):
+                if isnan(x):
+                    errno = 0
+                else:
+                    errno = EDOM
+            else:  # isinf(r)
+                if not isfinite(x):
+                    errno = 0
+                elif can_overflow:
+                    errno = ERANGE
+                else:
+                    errno = EDOM
         if errno:
             _likely_raise(errno, r)
         return r
diff --git a/pypy/rpython/lltypesystem/rffi.py b/pypy/rpython/lltypesystem/rffi.py
--- a/pypy/rpython/lltypesystem/rffi.py
+++ b/pypy/rpython/lltypesystem/rffi.py
@@ -245,8 +245,14 @@
     wrapper._always_inline_ = True
     # for debugging, stick ll func ptr to that
     wrapper._ptr = funcptr
+    wrapper = func_with_new_name(wrapper, name)
 
-    return func_with_new_name(wrapper, name)
+    if calling_conv != "c":
+        from pypy.rlib.jit import dont_look_inside
+        wrapper = dont_look_inside(wrapper)
+
+    return wrapper
+
 
 class CallbackHolder:
     def __init__(self):
diff --git a/pypy/translator/backendopt/finalizer.py b/pypy/translator/backendopt/finalizer.py
--- a/pypy/translator/backendopt/finalizer.py
+++ b/pypy/translator/backendopt/finalizer.py
@@ -4,7 +4,7 @@
 
 class FinalizerError(Exception):
     """ __del__ marked as lightweight finalizer, but the analyzer did
-    not agreed
+    not agree
     """
 
 class FinalizerAnalyzer(graphanalyze.BoolGraphAnalyzer):
@@ -23,7 +23,7 @@
     def analyze_light_finalizer(self, graph):
         result = self.analyze_direct_call(graph)
         if (result is self.top_result() and
-            getattr(graph.func, '_is_light_finalizer_', False)):
+            getattr(graph.func, '_must_be_light_finalizer_', False)):
             raise FinalizerError(FinalizerError.__doc__, graph)
         return result
     
diff --git a/pypy/translator/backendopt/test/test_canraise.py b/pypy/translator/backendopt/test/test_canraise.py
--- a/pypy/translator/backendopt/test/test_canraise.py
+++ b/pypy/translator/backendopt/test/test_canraise.py
@@ -201,6 +201,16 @@
         result = ra.can_raise(ggraph.startblock.operations[0])
         assert result
 
+    def test_ll_arraycopy(self):
+        from pypy.rpython.lltypesystem import rffi
+        from pypy.rlib.rgc import ll_arraycopy
+        def f(a, b, c, d, e):
+            ll_arraycopy(a, b, c, d, e)
+        t, ra = self.translate(f, [rffi.CCHARP, rffi.CCHARP, int, int, int])
+        fgraph = graphof(t, f)
+        result = ra.can_raise(fgraph.startblock.operations[0])
+        assert not result
+
 
 class TestOOType(OORtypeMixin, BaseTestCanRaise):
     def test_can_raise_recursive(self):
diff --git a/pypy/translator/backendopt/test/test_finalizer.py b/pypy/translator/backendopt/test/test_finalizer.py
--- a/pypy/translator/backendopt/test/test_finalizer.py
+++ b/pypy/translator/backendopt/test/test_finalizer.py
@@ -126,13 +126,13 @@
         r = self.analyze(f, [], A.__del__.im_func)
         assert r
 
-    def test_is_light_finalizer_decorator(self):
+    def test_must_be_light_finalizer_decorator(self):
         S = lltype.GcStruct('S')
 
-        @rgc.is_light_finalizer
+        @rgc.must_be_light_finalizer
         def f():
             lltype.malloc(S)
-        @rgc.is_light_finalizer
+        @rgc.must_be_light_finalizer
         def g():
             pass
         self.analyze(g, []) # did not explode
diff --git a/pypy/translator/c/genc.py b/pypy/translator/c/genc.py
--- a/pypy/translator/c/genc.py
+++ b/pypy/translator/c/genc.py
@@ -521,13 +521,13 @@
         rules = [
             ('clean', '', 'rm -f $(OBJECTS) $(TARGET) $(GCMAPFILES) $(ASMFILES) *.gc?? ../module_cache/*.gc??'),
             ('clean_noprof', '', 'rm -f $(OBJECTS) $(TARGET) $(GCMAPFILES) $(ASMFILES)'),
-            ('debug', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT" $(TARGET)'),
-            ('debug_exc', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DDO_LOG_EXC" $(TARGET)'),
-            ('debug_mem', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DTRIVIAL_MALLOC_DEBUG" $(TARGET)'),
+            ('debug', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT" debug_target'),
+            ('debug_exc', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DDO_LOG_EXC" debug_target'),
+            ('debug_mem', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DTRIVIAL_MALLOC_DEBUG" debug_target'),
             ('no_obmalloc', '', '$(MAKE) CFLAGS="-g -O2 -DRPY_ASSERT -DNO_OBMALLOC" $(TARGET)'),
-            ('linuxmemchk', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DLINUXMEMCHK" $(TARGET)'),
+            ('linuxmemchk', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DLINUXMEMCHK" debug_target'),
             ('llsafer', '', '$(MAKE) CFLAGS="-O2 -DRPY_LL_ASSERT" $(TARGET)'),
-            ('lldebug', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DRPY_LL_ASSERT" $(TARGET)'),
+            ('lldebug', '', '$(MAKE) CFLAGS="$(DEBUGFLAGS) -DRPY_ASSERT -DRPY_LL_ASSERT" debug_target'),
             ('profile', '', '$(MAKE) CFLAGS="-g -O1 -pg $(CFLAGS) -fno-omit-frame-pointer" LDFLAGS="-pg $(LDFLAGS)" $(TARGET)'),
             ]
         if self.has_profopt():
@@ -554,7 +554,7 @@
             mk.definition('ASMLBLFILES', lblsfiles)
             mk.definition('GCMAPFILES', gcmapfiles)
             if sys.platform == 'win32':
-                mk.definition('DEBUGFLAGS', '/Zi')
+                mk.definition('DEBUGFLAGS', '/MD /Zi')
             else:
                 mk.definition('DEBUGFLAGS', '-O2 -fomit-frame-pointer -g')
 
@@ -618,9 +618,13 @@
 
         else:
             if sys.platform == 'win32':
-                mk.definition('DEBUGFLAGS', '/Zi')
+                mk.definition('DEBUGFLAGS', '/MD /Zi')
             else:
                 mk.definition('DEBUGFLAGS', '-O1 -g')
+        if sys.platform == 'win32':
+            mk.rule('debug_target', 'debugmode_$(DEFAULT_TARGET)', 'rem')
+        else:
+            mk.rule('debug_target', '$(TARGET)', '#')
         mk.write()
         #self.translator.platform,
         #                           ,
diff --git a/pypy/translator/cli/test/test_snippet.py b/pypy/translator/cli/test/test_snippet.py
--- a/pypy/translator/cli/test/test_snippet.py
+++ b/pypy/translator/cli/test/test_snippet.py
@@ -28,14 +28,14 @@
         res = self.interpret(fn, [], backendopt=False)
         
     def test_link_vars_overlapping(self):
-        from pypy.rlib.rarithmetic import ovfcheck, ovfcheck_lshift
+        from pypy.rlib.rarithmetic import ovfcheck
         def fn(maxofs):
             lastofs = 0
             ofs = 1
             while ofs < maxofs:
                 lastofs = ofs
                 try:
-                    ofs = ovfcheck_lshift(ofs, 1)
+                    ofs = ovfcheck(ofs << 1)
                 except OverflowError:
                     ofs = maxofs
                 else:
diff --git a/pypy/translator/platform/__init__.py b/pypy/translator/platform/__init__.py
--- a/pypy/translator/platform/__init__.py
+++ b/pypy/translator/platform/__init__.py
@@ -102,6 +102,8 @@
         bits = [self.__class__.__name__, 'cc=%r' % self.cc]
         for varname in self.relevant_environ:
             bits.append('%s=%r' % (varname, os.environ.get(varname)))
+        # adding sys.maxint to disambiguate windows
+        bits.append('%s=%r' % ('sys.maxint', sys.maxint))
         return ' '.join(bits)
 
     # some helpers which seem to be cross-platform enough
@@ -238,10 +240,13 @@
     else:
         host_factory = Linux64
 elif sys.platform == 'darwin':
-    from pypy.translator.platform.darwin import Darwin_i386, Darwin_x86_64
+    from pypy.translator.platform.darwin import Darwin_i386, Darwin_x86_64, Darwin_PowerPC
     import platform
-    assert platform.machine() in ('i386', 'x86_64')
-    if sys.maxint <= 2147483647:
+    assert platform.machine() in ('Power Macintosh', 'i386', 'x86_64')
+
+    if  platform.machine() == 'Power Macintosh':
+        host_factory = Darwin_PowerPC
+    elif sys.maxint <= 2147483647:
         host_factory = Darwin_i386
     else:
         host_factory = Darwin_x86_64
diff --git a/pypy/translator/platform/darwin.py b/pypy/translator/platform/darwin.py
--- a/pypy/translator/platform/darwin.py
+++ b/pypy/translator/platform/darwin.py
@@ -71,6 +71,11 @@
     link_flags = ('-arch', 'i386')
     cflags = ('-arch', 'i386', '-O3', '-fomit-frame-pointer')
 
+class Darwin_PowerPC(Darwin):#xxx fixme, mwp
+    name = "darwin_powerpc"
+    link_flags = ()
+    cflags = ('-O3', '-fomit-frame-pointer')
+
 class Darwin_x86_64(Darwin):
     name = "darwin_x86_64"
     link_flags = ('-arch', 'x86_64')
diff --git a/pypy/translator/platform/test/test_darwin.py b/pypy/translator/platform/test/test_darwin.py
--- a/pypy/translator/platform/test/test_darwin.py
+++ b/pypy/translator/platform/test/test_darwin.py
@@ -7,7 +7,7 @@
     py.test.skip("Darwin only")
 
 from pypy.tool.udir import udir
-from pypy.translator.platform.darwin import Darwin_i386, Darwin_x86_64
+from pypy.translator.platform.darwin import Darwin_i386, Darwin_x86_64, Darwin_PowerPC
 from pypy.translator.platform.test.test_platform import TestPlatform as BasicTest
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 
@@ -17,7 +17,7 @@
     else:
         host_factory = Darwin_x86_64
 else:
-    host_factory = Darwin
+    host_factory = Darwin_PowerPC
 
 class TestDarwin(BasicTest):
     platform = host_factory()
diff --git a/pypy/translator/platform/windows.py b/pypy/translator/platform/windows.py
--- a/pypy/translator/platform/windows.py
+++ b/pypy/translator/platform/windows.py
@@ -294,6 +294,9 @@
                    ['$(CC_LINK) /nologo $(LDFLAGS) $(LDFLAGSEXTRA) $(OBJECTS) $(LINKFILES) /out:$@ $(LIBDIRS) $(LIBS) /MANIFEST /MANIFESTFILE:$*.manifest',
                     'mt.exe -nologo -manifest $*.manifest -outputresource:$@;1',
                     ])
+        m.rule('debugmode_$(TARGET)', '$(OBJECTS)',
+               ['$(CC_LINK) /nologo /DEBUG $(LDFLAGS) $(LDFLAGSEXTRA) $(OBJECTS) $(LINKFILES) /out:$@ $(LIBDIRS) $(LIBS)',
+                ])
 
         if shared:
             m.definition('SHARED_IMPORT_LIB', so_name.new(ext='lib').basename)
@@ -307,6 +310,9 @@
                    ['$(CC_LINK) /nologo main.obj $(SHARED_IMPORT_LIB) /out:$@ /MANIFEST /MANIFESTFILE:$*.manifest',
                     'mt.exe -nologo -manifest $*.manifest -outputresource:$@;1',
                     ])
+            m.rule('debugmode_$(DEFAULT_TARGET)', ['debugmode_$(TARGET)', 'main.obj'],
+                   ['$(CC_LINK) /nologo /DEBUG main.obj $(SHARED_IMPORT_LIB) /out:$@'
+                    ])
 
         return m
 
diff --git a/pypy/translator/simplify.py b/pypy/translator/simplify.py
--- a/pypy/translator/simplify.py
+++ b/pypy/translator/simplify.py
@@ -111,16 +111,13 @@
                 # the while loop above will simplify recursively the new link
 
 def transform_ovfcheck(graph):
-    """The special function calls ovfcheck and ovfcheck_lshift need to
+    """The special function calls ovfcheck needs to
     be translated into primitive operations. ovfcheck is called directly
     after an operation that should be turned into an overflow-checked
     version. It is considered a syntax error if the resulting <op>_ovf
     is not defined in objspace/flow/objspace.py.
-    ovfcheck_lshift is special because there is no preceding operation.
-    Instead, it will be replaced by an OP_LSHIFT_OVF operation.
     """
     covf = Constant(rarithmetic.ovfcheck)
-    covfls = Constant(rarithmetic.ovfcheck_lshift)
 
     def check_syntax(opname):
         exlis = operation.implicit_exceptions.get("%s_ovf" % (opname,), [])
@@ -154,9 +151,6 @@
                 op1.opname += '_ovf'
                 del block.operations[i]
                 block.renamevariables({op.result: op1.result})
-            elif op.args[0] == covfls:
-                op.opname = 'lshift_ovf'
-                del op.args[0]
 
 def simplify_exceptions(graph):
     """The exception handling caused by non-implicit exceptions
diff --git a/pypy/translator/test/snippet.py b/pypy/translator/test/snippet.py
--- a/pypy/translator/test/snippet.py
+++ b/pypy/translator/test/snippet.py
@@ -1210,7 +1210,7 @@
     return istk.top(), sstk.top()
 
 
-from pypy.rlib.rarithmetic import ovfcheck, ovfcheck_lshift
+from pypy.rlib.rarithmetic import ovfcheck
 
 def add_func(i=numtype):
     try:
@@ -1253,7 +1253,7 @@
 def lshift_func(i=numtype):
     try:
         hugo(2, 3, 5)
-        return ovfcheck_lshift((-maxint-1), i)
+        return ovfcheck((-maxint-1) << i)
     except (hugelmugel, OverflowError, StandardError, ValueError):
         raise
 


More information about the pypy-commit mailing list