[pypy-commit] pypy jit-short_from_state: hg merge c3cdcacec880

hakanardo noreply at buildbot.pypy.org
Mon Jul 25 23:21:39 CEST 2011


Author: Hakan Ardo <hakan at debian.org>
Branch: jit-short_from_state
Changeset: r45987:26de1fba7350
Date: 2011-07-25 19:36 +0200
http://bitbucket.org/pypy/pypy/changeset/26de1fba7350/

Log:	hg merge c3cdcacec880

diff too long, truncating to 10000 out of 15314 lines

diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -1,6 +1,7 @@
 syntax: glob
 *.py[co]
 *~
+.*.swp
 
 syntax: regexp
 ^testresult$
@@ -38,6 +39,8 @@
 ^pypy/translator/benchmark/shootout_benchmarks$
 ^pypy/translator/goal/pypy-translation-snapshot$
 ^pypy/translator/goal/pypy-c
+^pypy/translator/goal/pypy-jvm
+^pypy/translator/goal/pypy-jvm.jar
 ^pypy/translator/goal/.+\.exe$
 ^pypy/translator/goal/.+\.dll$
 ^pypy/translator/goal/target.+-c$
diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -185,6 +185,7 @@
     Jim Baker
     Philip Jenvey
     Rodrigo Ara&#250;jo
+    Brett Cannon
 
     Heinrich-Heine University, Germany 
     Open End AB (formerly AB Strakt), Sweden
diff --git a/lib-python/modified-2.7/distutils/cygwinccompiler.py b/lib-python/modified-2.7/distutils/cygwinccompiler.py
--- a/lib-python/modified-2.7/distutils/cygwinccompiler.py
+++ b/lib-python/modified-2.7/distutils/cygwinccompiler.py
@@ -75,6 +75,9 @@
         elif msc_ver == '1500':
             # VS2008 / MSVC 9.0
             return ['msvcr90']
+        elif msc_ver == '1600':
+            # VS2010 / MSVC 10.0
+            return ['msvcr100']
         else:
             raise ValueError("Unknown MS Compiler version %s " % msc_ver)
 
diff --git a/lib-python/modified-2.7/distutils/sysconfig_pypy.py b/lib-python/modified-2.7/distutils/sysconfig_pypy.py
--- a/lib-python/modified-2.7/distutils/sysconfig_pypy.py
+++ b/lib-python/modified-2.7/distutils/sysconfig_pypy.py
@@ -116,6 +116,12 @@
     if compiler.compiler_type == "unix":
         compiler.compiler_so.extend(['-fPIC', '-Wimplicit'])
         compiler.shared_lib_extension = get_config_var('SO')
+        if "CFLAGS" in os.environ:
+            cflags = os.environ["CFLAGS"]
+            compiler.compiler.append(cflags)
+            compiler.compiler_so.append(cflags)
+            compiler.linker_so.append(cflags)
+
 
 from sysconfig_cpython import (
     parse_makefile, _variable_rx, expand_makefile_vars)
diff --git a/lib-python/modified-2.7/pickle.py b/lib-python/modified-2.7/pickle.py
--- a/lib-python/modified-2.7/pickle.py
+++ b/lib-python/modified-2.7/pickle.py
@@ -168,7 +168,7 @@
 
 # Pickling machinery
 
-class Pickler:
+class Pickler(object):
 
     def __init__(self, file, protocol=None):
         """This takes a file-like object for writing a pickle data stream.
diff --git a/lib-python/2.7/test/test_sets.py b/lib-python/modified-2.7/test/test_sets.py
copy from lib-python/2.7/test/test_sets.py
copy to lib-python/modified-2.7/test/test_sets.py
--- a/lib-python/2.7/test/test_sets.py
+++ b/lib-python/modified-2.7/test/test_sets.py
@@ -686,7 +686,9 @@
         set_list = sorted(self.set)
         self.assertEqual(len(dup_list), len(set_list))
         for i, el in enumerate(dup_list):
-            self.assertIs(el, set_list[i])
+            # Object identity is not guarnteed for immutable objects, so we
+            # can't use assertIs here.
+            self.assertEqual(el, set_list[i])
 
     def test_deep_copy(self):
         dup = copy.deepcopy(self.set)
diff --git a/lib-python/2.7/test/test_tarfile.py b/lib-python/modified-2.7/test/test_tarfile.py
copy from lib-python/2.7/test/test_tarfile.py
copy to lib-python/modified-2.7/test/test_tarfile.py
--- a/lib-python/2.7/test/test_tarfile.py
+++ b/lib-python/modified-2.7/test/test_tarfile.py
@@ -169,6 +169,7 @@
         except tarfile.ReadError:
             self.fail("tarfile.open() failed on empty archive")
         self.assertListEqual(tar.getmembers(), [])
+        tar.close()
 
     def test_null_tarfile(self):
         # Test for issue6123: Allow opening empty archives.
@@ -207,16 +208,21 @@
         fobj = open(self.tarname, "rb")
         tar = tarfile.open(fileobj=fobj, mode=self.mode)
         self.assertEqual(tar.name, os.path.abspath(fobj.name))
+        tar.close()
 
     def test_no_name_attribute(self):
-        data = open(self.tarname, "rb").read()
+        f = open(self.tarname, "rb")
+        data = f.read()
+        f.close()
         fobj = StringIO.StringIO(data)
         self.assertRaises(AttributeError, getattr, fobj, "name")
         tar = tarfile.open(fileobj=fobj, mode=self.mode)
         self.assertEqual(tar.name, None)
 
     def test_empty_name_attribute(self):
-        data = open(self.tarname, "rb").read()
+        f = open(self.tarname, "rb")
+        data = f.read()
+        f.close()
         fobj = StringIO.StringIO(data)
         fobj.name = ""
         tar = tarfile.open(fileobj=fobj, mode=self.mode)
@@ -515,6 +521,7 @@
         self.tar = tarfile.open(self.tarname, mode=self.mode, encoding="iso8859-1")
         tarinfo = self.tar.getmember("pax/umlauts-&#65533;&#65533;&#65533;&#65533;&#65533;&#65533;&#65533;")
         self._test_member(tarinfo, size=7011, chksum=md5_regtype)
+        self.tar.close()
 
 
 class LongnameTest(ReadTest):
@@ -675,6 +682,7 @@
             tar = tarfile.open(tmpname, self.mode)
             tarinfo = tar.gettarinfo(path)
             self.assertEqual(tarinfo.size, 0)
+            tar.close()
         finally:
             os.rmdir(path)
 
@@ -692,6 +700,7 @@
                 tar.gettarinfo(target)
                 tarinfo = tar.gettarinfo(link)
                 self.assertEqual(tarinfo.size, 0)
+                tar.close()
             finally:
                 os.remove(target)
                 os.remove(link)
@@ -704,6 +713,7 @@
                 tar = tarfile.open(tmpname, self.mode)
                 tarinfo = tar.gettarinfo(path)
                 self.assertEqual(tarinfo.size, 0)
+                tar.close()
             finally:
                 os.remove(path)
 
@@ -722,6 +732,7 @@
         tar.add(dstname)
         os.chdir(cwd)
         self.assertTrue(tar.getnames() == [], "added the archive to itself")
+        tar.close()
 
     def test_exclude(self):
         tempdir = os.path.join(TEMPDIR, "exclude")
@@ -742,6 +753,7 @@
             tar = tarfile.open(tmpname, "r")
             self.assertEqual(len(tar.getmembers()), 1)
             self.assertEqual(tar.getnames()[0], "empty_dir")
+            tar.close()
         finally:
             shutil.rmtree(tempdir)
 
@@ -859,7 +871,9 @@
             fobj.close()
         elif self.mode.endswith("bz2"):
             dec = bz2.BZ2Decompressor()
-            data = open(tmpname, "rb").read()
+            f = open(tmpname, "rb")
+            data = f.read()
+            f.close()
             data = dec.decompress(data)
             self.assertTrue(len(dec.unused_data) == 0,
                     "found trailing data")
@@ -938,6 +952,7 @@
                 "unable to read longname member")
         self.assertEqual(tarinfo.linkname, member.linkname,
                 "unable to read longname member")
+        tar.close()
 
     def test_longname_1023(self):
         self._test(("longnam/" * 127) + "longnam")
@@ -1030,6 +1045,7 @@
         else:
             n = tar.getmembers()[0].name
             self.assertTrue(name == n, "PAX longname creation failed")
+        tar.close()
 
     def test_pax_global_header(self):
         pax_headers = {
@@ -1058,6 +1074,7 @@
                     tarfile.PAX_NUMBER_FIELDS[key](val)
                 except (TypeError, ValueError):
                     self.fail("unable to convert pax header field")
+        tar.close()
 
     def test_pax_extended_header(self):
         # The fields from the pax header have priority over the
@@ -1077,6 +1094,7 @@
         self.assertEqual(t.pax_headers, pax_headers)
         self.assertEqual(t.name, "foo")
         self.assertEqual(t.uid, 123)
+        tar.close()
 
 
 class UstarUnicodeTest(unittest.TestCase):
@@ -1120,6 +1138,7 @@
         tarinfo.name = "foo"
         tarinfo.uname = u"&#65533;&#65533;&#65533;"
         self.assertRaises(UnicodeError, tar.addfile, tarinfo)
+        tar.close()
 
     def test_unicode_argument(self):
         tar = tarfile.open(tarname, "r", encoding="iso8859-1", errors="strict")
@@ -1174,6 +1193,7 @@
             tar = tarfile.open(tmpname, format=self.format, encoding="ascii",
                     errors=handler)
             self.assertEqual(tar.getnames()[0], name)
+            tar.close()
 
         self.assertRaises(UnicodeError, tarfile.open, tmpname,
                 encoding="ascii", errors="strict")
@@ -1186,6 +1206,7 @@
         tar = tarfile.open(tmpname, format=self.format, encoding="iso8859-1",
                 errors="utf-8")
         self.assertEqual(tar.getnames()[0], "&#65533;&#65533;&#65533;/" + u"&#65533;".encode("utf8"))
+        tar.close()
 
 
 class AppendTest(unittest.TestCase):
@@ -1213,6 +1234,7 @@
     def _test(self, names=["bar"], fileobj=None):
         tar = tarfile.open(self.tarname, fileobj=fileobj)
         self.assertEqual(tar.getnames(), names)
+        tar.close()
 
     def test_non_existing(self):
         self._add_testfile()
@@ -1231,7 +1253,9 @@
 
     def test_fileobj(self):
         self._create_testtar()
-        data = open(self.tarname).read()
+        f = open(self.tarname)
+        data = f.read()
+        f.close()
         fobj = StringIO.StringIO(data)
         self._add_testfile(fobj)
         fobj.seek(0)
@@ -1257,7 +1281,9 @@
     # Append mode is supposed to fail if the tarfile to append to
     # does not end with a zero block.
     def _test_error(self, data):
-        open(self.tarname, "wb").write(data)
+        f = open(self.tarname, "wb")
+        f.write(data)
+        f.close()
         self.assertRaises(tarfile.ReadError, self._add_testfile)
 
     def test_null(self):
diff --git a/lib_pypy/_ctypes/__init__.py b/lib_pypy/_ctypes/__init__.py
--- a/lib_pypy/_ctypes/__init__.py
+++ b/lib_pypy/_ctypes/__init__.py
@@ -18,7 +18,16 @@
 if _os.name in ("nt", "ce"):
     from _rawffi import FormatError
     from _rawffi import check_HRESULT as _check_HRESULT
-    CopyComPointer = None # XXX
+
+    def CopyComPointer(src, dst):
+        from ctypes import c_void_p, cast
+        if src:
+            hr = src[0][0].AddRef(src)
+            if hr & 0x80000000:
+                return hr
+        dst[0] = cast(src, c_void_p).value
+        return 0
+
     LoadLibrary = dlopen
 
 from _rawffi import FUNCFLAG_STDCALL, FUNCFLAG_CDECL, FUNCFLAG_PYTHONAPI
diff --git a/lib_pypy/_ctypes/basics.py b/lib_pypy/_ctypes/basics.py
--- a/lib_pypy/_ctypes/basics.py
+++ b/lib_pypy/_ctypes/basics.py
@@ -48,7 +48,8 @@
             return self.from_param(as_parameter)
 
     def get_ffi_param(self, value):
-        return self.from_param(value)._to_ffi_param()
+        cdata = self.from_param(value)
+        return cdata, cdata._to_ffi_param()
 
     def get_ffi_argtype(self):
         if self._ffiargtype:
@@ -139,7 +140,10 @@
         return buffer(self._buffer)
 
     def _get_b_base(self):
-        return self._base
+        try:
+            return self._base
+        except AttributeError:
+            return None
     _b_base_ = property(_get_b_base)
     _b_needsfree_ = False
 
@@ -218,5 +222,7 @@
     'z' : _ffi.types.void_p,
     'O' : _ffi.types.void_p,
     'Z' : _ffi.types.void_p,
+    'X' : _ffi.types.void_p,
+    'v' : _ffi.types.sshort,
     }
 
diff --git a/lib_pypy/_ctypes/function.py b/lib_pypy/_ctypes/function.py
--- a/lib_pypy/_ctypes/function.py
+++ b/lib_pypy/_ctypes/function.py
@@ -322,20 +322,20 @@
                           RuntimeWarning, stacklevel=2)
 
         if self._com_index:
-            assert False, 'TODO2'
             from ctypes import cast, c_void_p, POINTER
             if not args:
                 raise ValueError(
                     "native COM method call without 'this' parameter"
                     )
-            thisarg = cast(args[0], POINTER(POINTER(c_void_p))).contents
-            argtypes = [c_void_p] + list(argtypes)
-            args = list(args)
-            args[0] = args[0].value
+            thisarg = cast(args[0], POINTER(POINTER(c_void_p)))
+            keepalives, newargs, argtypes, outargs = self._convert_args(argtypes,
+                                                                        args[1:], kwargs)
+            newargs.insert(0, args[0].value)
+            argtypes.insert(0, c_void_p)
         else:
             thisarg = None
-            
-        newargs, argtypes, outargs = self._convert_args(argtypes, args, kwargs)
+            keepalives, newargs, argtypes, outargs = self._convert_args(argtypes,
+                                                                        args, kwargs)
 
         funcptr = self._getfuncptr(argtypes, self._restype_, thisarg)
         result = self._call_funcptr(funcptr, *newargs)
@@ -343,6 +343,11 @@
 
         if not outargs:
             return result
+
+        simple_cdata = type(c_void_p()).__bases__[0]
+        outargs = [x.value if type(x).__bases__[0] is simple_cdata else x
+                   for x in outargs]
+
         if len(outargs) == 1:
             return outargs[0]
         return tuple(outargs)
@@ -398,10 +403,10 @@
             # extract the address from the object's virtual table
             if not thisarg:
                 raise ValueError("COM method call without VTable")
-            ptr = thisarg[self._com_index - 0x1000]
-            argshapes = [arg._ffiargshape for arg in argtypes]
-            resshape = restype._ffiargshape
-            return _rawffi.FuncPtr(ptr, argshapes, resshape, self._flags_)
+            ptr = thisarg[0][self._com_index - 0x1000]
+            ffiargs = [argtype.get_ffi_argtype() for argtype in argtypes]
+            ffires = restype.get_ffi_argtype()
+            return _ffi.FuncPtr.fromaddr(ptr, '', ffiargs, ffires)
         
         cdll = self.dll._handle
         try:
@@ -434,16 +439,15 @@
     @classmethod
     def _conv_param(cls, argtype, arg):
         if isinstance(argtype, _CDataMeta):
-            #arg = argtype.from_param(arg)
-            arg = argtype.get_ffi_param(arg)
-            return arg, argtype
+            cobj, ffiparam = argtype.get_ffi_param(arg)
+            return cobj, ffiparam, argtype
         
         if argtype is not None:
             arg = argtype.from_param(arg)
         if hasattr(arg, '_as_parameter_'):
             arg = arg._as_parameter_
         if isinstance(arg, _CData):
-            return arg._to_ffi_param(), type(arg)
+            return arg, arg._to_ffi_param(), type(arg)
         #
         # non-usual case: we do the import here to save a lot of code in the
         # jit trace of the normal case
@@ -460,19 +464,16 @@
         else:
             raise TypeError("Don't know how to handle %s" % (arg,))
 
-        return cobj._to_ffi_param(), type(cobj)
+        return cobj, cobj._to_ffi_param(), type(cobj)
 
     def _convert_args(self, argtypes, args, kwargs, marker=object()):
         newargs = []
         outargs = []
+        keepalives = []
         newargtypes = []
         total = len(args)
         paramflags = self._paramflags
-
-        if self._com_index:
-            inargs_idx = 1
-        else:
-            inargs_idx = 0
+        inargs_idx = 0
 
         if not paramflags and total < len(argtypes):
             raise TypeError("not enough arguments")
@@ -496,7 +497,8 @@
                     val = defval
                     if val is marker:
                         val = 0
-                    newarg, newargtype = self._conv_param(argtype, val)
+                    keepalive, newarg, newargtype = self._conv_param(argtype, val)
+                    keepalives.append(keepalive)
                     newargs.append(newarg)
                     newargtypes.append(newargtype)
                 elif flag in (0, PARAMFLAG_FIN):
@@ -512,28 +514,32 @@
                         raise TypeError("required argument '%s' missing" % name)
                     else:
                         raise TypeError("not enough arguments")
-                    newarg, newargtype = self._conv_param(argtype, val)
+                    keepalive, newarg, newargtype = self._conv_param(argtype, val)
+                    keepalives.append(keepalive)
                     newargs.append(newarg)
                     newargtypes.append(newargtype)
                 elif flag == PARAMFLAG_FOUT:
                     if defval is not marker:
                         outargs.append(defval)
-                        newarg, newargtype = self._conv_param(argtype, defval)
+                        keepalive, newarg, newargtype = self._conv_param(argtype, defval)
                     else:
                         import ctypes
                         val = argtype._type_()
                         outargs.append(val)
+                        keepalive = None
                         newarg = ctypes.byref(val)
                         newargtype = type(newarg)
+                    keepalives.append(keepalive)
                     newargs.append(newarg)
                     newargtypes.append(newargtype)
                 else:
                     raise ValueError("paramflag %d not yet implemented" % flag)
             else:
                 try:
-                    newarg, newargtype = self._conv_param(argtype, args[i])
+                    keepalive, newarg, newargtype = self._conv_param(argtype, args[i])
                 except (UnicodeError, TypeError, ValueError), e:
                     raise ArgumentError(str(e))
+                keepalives.append(keepalive)
                 newargs.append(newarg)
                 newargtypes.append(newargtype)
                 inargs_idx += 1
@@ -542,12 +548,13 @@
             extra = args[len(newargs):]
             for i, arg in enumerate(extra):
                 try:
-                    newarg, newargtype = self._conv_param(None, arg)
+                    keepalive, newarg, newargtype = self._conv_param(None, arg)
                 except (UnicodeError, TypeError, ValueError), e:
                     raise ArgumentError(str(e))
+                keepalives.append(keepalive)
                 newargs.append(newarg)
                 newargtypes.append(newargtype)
-        return newargs, newargtypes, outargs
+        return keepalives, newargs, newargtypes, outargs
 
     
     def _wrap_result(self, restype, result):
@@ -587,13 +594,7 @@
 
         retval = None
 
-        if self._com_index:
-            if resbuffer[0] & 0x80000000:
-                raise get_com_error(resbuffer[0],
-                                    self._com_iid, argsandobjs[0])
-            else:
-                retval = int(resbuffer[0])
-        elif restype is not None:
+        if restype is not None:
             checker = getattr(self.restype, '_check_retval_', None)
             if checker:
                 val = restype(result)
@@ -601,7 +602,13 @@
                 # classes defining a new type, and their subclasses
                 if '_type_' in restype.__dict__:
                     val = val.value
-                retval = checker(val)
+                # XXX Raise a COMError when restype is HRESULT and
+                # checker(val) fails.  How to check for restype == HRESULT?
+                if self._com_index:
+                    if result & 0x80000000:
+                        raise get_com_error(result, None, None)
+                else:
+                    retval = checker(val)
             elif not isinstance(restype, _CDataMeta):
                 retval = restype(result)
             else:
diff --git a/lib_pypy/_ctypes/primitive.py b/lib_pypy/_ctypes/primitive.py
--- a/lib_pypy/_ctypes/primitive.py
+++ b/lib_pypy/_ctypes/primitive.py
@@ -216,10 +216,15 @@
             result.value = property(_getvalue, _setvalue)
 
         elif tp == 'X':
-            from ctypes import windll
-            SysAllocStringLen = windll.oleaut32.SysAllocStringLen
-            SysStringLen = windll.oleaut32.SysStringLen
-            SysFreeString = windll.oleaut32.SysFreeString
+            from ctypes import WinDLL
+            # Use WinDLL("oleaut32") instead of windll.oleaut32
+            # because the latter is a shared (cached) object; and
+            # other code may set their own restypes. We need out own
+            # restype here.
+            oleaut32 = WinDLL("oleaut32")
+            SysAllocStringLen = oleaut32.SysAllocStringLen
+            SysStringLen = oleaut32.SysStringLen
+            SysFreeString = oleaut32.SysFreeString
             def _getvalue(self):
                 addr = self._buffer[0]
                 if addr == 0:
diff --git a/lib_pypy/binascii.py b/lib_pypy/binascii.py
--- a/lib_pypy/binascii.py
+++ b/lib_pypy/binascii.py
@@ -659,7 +659,7 @@
         crc = crc_32_tab[(crc ^ long(ord(c))) & 0xffL] ^ (crc >> 8)
         #/* Note:  (crc >> 8) MUST zero fill on left
 
-        result = crc ^ 0xffffffffL
+    result = crc ^ 0xffffffffL
     
     if result > 2**31:
         result = ((result + 2**31) % 2**32) - 2**31
diff --git a/lib_pypy/cPickle.py b/lib_pypy/cPickle.py
--- a/lib_pypy/cPickle.py
+++ b/lib_pypy/cPickle.py
@@ -27,9 +27,9 @@
             PythonPickler.__init__(self, self.__f, args[0], **kw)
         else:
             PythonPickler.__init__(self, *args, **kw)
-            
+
     def memoize(self, obj):
-        self.memo[None] = None   # cPickle starts counting at one
+        self.memo[id(None)] = None   # cPickle starts counting at one
         return PythonPickler.memoize(self, obj)
 
     def getvalue(self):
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
@@ -384,15 +384,19 @@
 
         self.__maybe_write_code(self._smkx)
 
-        self.old_sigwinch = signal.signal(
-            signal.SIGWINCH, self.__sigwinch)
+        try:
+            self.old_sigwinch = signal.signal(
+                signal.SIGWINCH, self.__sigwinch)
+        except ValueError:
+            pass
 
     def restore(self):
         self.__maybe_write_code(self._rmkx)
         self.flushoutput()
         tcsetattr(self.input_fd, termios.TCSADRAIN, self.__svtermstate)
 
-        signal.signal(signal.SIGWINCH, self.old_sigwinch)
+        if hasattr(self, 'old_sigwinch'):
+            signal.signal(signal.SIGWINCH, self.old_sigwinch)
 
     def __sigwinch(self, signum, frame):
         self.height, self.width = self.getheightwidth()
diff --git a/pypy/config/config.py b/pypy/config/config.py
--- a/pypy/config/config.py
+++ b/pypy/config/config.py
@@ -81,6 +81,12 @@
                                  (self.__class__, name))
         return self._cfgimpl_values[name]
 
+    def __dir__(self):
+        from_type = dir(type(self))
+        from_dict = list(self.__dict__)
+        extras = list(self._cfgimpl_values)
+        return sorted(set(extras + from_type + from_dict))
+
     def __delattr__(self, name):
         # XXX if you use delattr you are responsible for all bad things
         # happening
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -327,6 +327,9 @@
         BoolOption("mutable_builtintypes",
                    "Allow the changing of builtin types", default=False,
                    requires=[("objspace.std.builtinshortcut", True)]),
+        BoolOption("withidentitydict",
+                   "track types that override __hash__, __eq__ or __cmp__ and use a special dict strategy for those which do not",
+                   default=True),
      ]),
 ])
 
diff --git a/pypy/config/support.py b/pypy/config/support.py
--- a/pypy/config/support.py
+++ b/pypy/config/support.py
@@ -9,7 +9,7 @@
         return 1    # don't override MAKEFLAGS.  This will call 'make' without any '-j' option
     if sys.platform == 'darwin':
         return darwin_get_cpu_count()
-    elif sys.platform != 'linux2':
+    elif not sys.platform.startswith('linux'):
         return 1    # implement me
     try:
         if isinstance(filename_or_file, str):
diff --git a/pypy/config/test/test_config.py b/pypy/config/test/test_config.py
--- a/pypy/config/test/test_config.py
+++ b/pypy/config/test/test_config.py
@@ -63,6 +63,20 @@
     py.test.raises(ConfigError, 'config.gc.name = "ref"')
     config.gc.name = "framework"
 
+def test___dir__():
+    descr = make_description()
+    config = Config(descr, bool=False)
+    attrs = dir(config)
+    assert '__repr__' in attrs        # from the type
+    assert '_cfgimpl_values' in attrs # from self
+    assert 'gc' in attrs              # custom attribute
+    assert 'objspace' in attrs        # custom attribute
+    #
+    attrs = dir(config.gc)
+    assert 'name' in attrs
+    assert 'dummy' in attrs
+    assert 'float' in attrs
+
 def test_arbitrary_option():
     descr = OptionDescription("top", "", [
         ArbitraryOption("a", "no help", default=None)
diff --git a/pypy/config/test/test_support.py b/pypy/config/test/test_support.py
--- a/pypy/config/test/test_support.py
+++ b/pypy/config/test/test_support.py
@@ -40,7 +40,7 @@
         return self._value
 
 def test_cpuinfo_linux():
-    if sys.platform != 'linux2':
+    if not sys.platform.startswith('linux'):
         py.test.skip("linux only")
     saved = os.environ
     try:
diff --git a/pypy/config/translationoption.py b/pypy/config/translationoption.py
--- a/pypy/config/translationoption.py
+++ b/pypy/config/translationoption.py
@@ -140,7 +140,10 @@
                  ["annotate", "rtype", "backendopt", "database", "source",
                   "pyjitpl"],
                  default=None, cmdline="--fork-before"),
-
+    BoolOption("dont_write_c_files",
+               "Make the C backend write everyting to /dev/null. " +
+               "Useful for benchmarking, so you don't actually involve the disk",
+               default=False, cmdline="--dont-write-c-files"),
     ArbitraryOption("instrumentctl", "internal",
                default=None),
     StrOption("output", "Output file name", cmdline="--output"),
diff --git a/pypy/doc/coding-guide.rst b/pypy/doc/coding-guide.rst
--- a/pypy/doc/coding-guide.rst
+++ b/pypy/doc/coding-guide.rst
@@ -929,6 +929,19 @@
 located in the ``py/bin/`` directory.  For switches to
 modify test execution pass the ``-h`` option.
 
+Coverage reports
+----------------
+
+In order to get coverage reports the `pytest-cov`_ plugin is included.
+it adds some extra requirements ( coverage_ and `cov-core`_ )
+and can once they are installed coverage testing can be invoked via::
+
+  python test_all.py --cov file_or_direcory_to_cover file_or_directory
+
+.. _`pytest-cov`: http://pypi.python.org/pypi/pytest-cov
+.. _`coverage`: http://pypi.python.org/pypi/coverage
+.. _`cov-core`: http://pypi.python.org/pypi/cov-core
+
 Test conventions
 ----------------
 
diff --git a/pypy/doc/config/objspace.std.withidentitydict.txt b/pypy/doc/config/objspace.std.withidentitydict.txt
new file mode 100644
--- /dev/null
+++ b/pypy/doc/config/objspace.std.withidentitydict.txt
@@ -0,0 +1,21 @@
+=============================
+objspace.std.withidentitydict
+=============================
+
+* **name:** withidentitydict
+
+* **description:** enable a dictionary strategy for "by identity" comparisons
+
+* **command-line:** --objspace-std-withidentitydict
+
+* **command-line for negation:** --no-objspace-std-withidentitydict
+
+* **option type:** boolean option
+
+* **default:** True
+
+
+Enable a dictionary strategy specialized for instances of classes which
+compares "by identity", which is the default unless you override ``__hash__``,
+``__eq__`` or ``__cmp__``.  This strategy will be used only with new-style
+classes.
diff --git a/pypy/doc/config/translation.dont_write_c_files.txt b/pypy/doc/config/translation.dont_write_c_files.txt
new file mode 100644
--- /dev/null
+++ b/pypy/doc/config/translation.dont_write_c_files.txt
@@ -0,0 +1,4 @@
+write the generated C files to ``/dev/null`` instead of to the disk. Useful if
+you want to use translate.py as a benchmark and don't want to access the disk.
+
+.. _`translation documentation`: ../translation.html
diff --git a/pypy/doc/config/translation.gc.txt b/pypy/doc/config/translation.gc.txt
--- a/pypy/doc/config/translation.gc.txt
+++ b/pypy/doc/config/translation.gc.txt
@@ -1,4 +1,6 @@
-Choose the Garbage Collector used by the translated program:
+Choose the Garbage Collector used by the translated program.
+The good performing collectors are "hybrid" and "minimark".
+The default is "minimark".
 
   - "ref": reference counting. Takes very long to translate and the result is
     slow.
@@ -11,3 +13,12 @@
     older generation.
 
   - "boehm": use the Boehm conservative GC.
+
+  - "hybrid": a hybrid collector of "generation" together with a
+    mark-n-sweep old space
+
+  - "markcompact": a slow, but memory-efficient collector,
+    influenced e.g. by Smalltalk systems.
+
+  - "minimark": a generational mark-n-sweep collector with good
+    performance.  Includes page marking for large arrays.
diff --git a/pypy/doc/cpython_differences.rst b/pypy/doc/cpython_differences.rst
--- a/pypy/doc/cpython_differences.rst
+++ b/pypy/doc/cpython_differences.rst
@@ -211,6 +211,38 @@
     >>>> print d1['a']
     42
 
+Mutating classes of objects which are already used as dictionary keys
+---------------------------------------------------------------------
+
+Consider the following snippet of code::
+
+    class X(object):
+        pass
+
+    def __evil_eq__(self, other):
+        print 'hello world'
+        return False
+
+    def evil(y):
+        d = {x(): 1}
+        X.__eq__ = __evil_eq__
+        d[y] # might trigger a call to __eq__?
+
+In CPython, __evil_eq__ **might** be called, although there is no way to write
+a test which reliably calls it.  It happens if ``y is not x`` and ``hash(y) ==
+hash(x)``, where ``hash(x)`` is computed when ``x`` is inserted into the
+dictionary.  If **by chance** the condition is satisfied, then ``__evil_eq__``
+is called.
+
+PyPy uses a special strategy to optimize dictionaries whose keys are instances
+of user-defined classes which do not override the default ``__hash__``,
+``__eq__`` and ``__cmp__``: when using this strategy, ``__eq__`` and
+``__cmp__`` are never called, but instead the lookup is done by identity, so
+in the case above it is guaranteed that ``__eq__`` won't be called.
+
+Note that in all other cases (e.g., if you have a custom ``__hash__`` and
+``__eq__`` in ``y``) the behavior is exactly the same as CPython.
+
 
 Ignored exceptions
 -----------------------
diff --git a/pypy/doc/extending.rst b/pypy/doc/extending.rst
--- a/pypy/doc/extending.rst
+++ b/pypy/doc/extending.rst
@@ -19,12 +19,12 @@
   section
 
 * Write them in pure python and use direct libffi low-level bindings, See
-  \_rawffi_ module description.
+  \_ffi_ module description.
 
 * Write them in RPython as mixedmodule_, using *rffi* as bindings.
 
 .. _ctypes: #CTypes
-.. _\_rawffi: #LibFFI
+.. _\_ffi: #LibFFI
 .. _mixedmodule: #Mixed Modules
 
 CTypes
@@ -42,41 +42,50 @@
 platform-dependent details (compiling small snippets of C code and running
 them), so it'll benefit not pypy-related ctypes-based modules as well.
 
+ctypes call are optimized by the JIT and the resulting machine code contains a
+direct call to the target C function.  However, due to the very dynamic nature
+of ctypes, some overhead over a bare C call is still present, in particular to
+check/convert the types of the parameters.  Moreover, even if most calls are
+optimized, some cannot and thus need to follow the slow path, not optimized by
+the JIT.
+
 .. _`ctypes-configure`: ctypes-implementation.html#ctypes-configure
+.. _`CPython ctypes`: http://docs.python.org/library/ctypes.html
 
 Pros
 ----
 
-Stable, CPython-compatible API
+Stable, CPython-compatible API.  Most calls are fast, optimized by JIT.
 
 Cons
 ----
 
-Only pure-python code (slow), problems with platform-dependency (although
-we partially solve those). PyPy implementation is now very slow.
+Problems with platform-dependency (although we partially solve
+those). Although the JIT optimizes ctypes calls, some overhead is still
+present.  The slow-path is very slow.
 
-_`CPython ctypes`: http://python.net/crew/theller/ctypes/
 
 LibFFI
 ======
 
 Mostly in order to be able to write a ctypes module, we developed a very
-low-level libffi bindings. (libffi is a C-level library for dynamic calling,
+low-level libffi bindings called ``_ffi``. (libffi is a C-level library for dynamic calling,
 which is used by CPython ctypes). This library provides stable and usable API,
 although it's API is a very low-level one. It does not contain any
-magic.
+magic.  It is also optimized by the JIT, but has much less overhead than ctypes.
 
 Pros
 ----
 
-Works. Combines disadvantages of using ctypes with disadvantages of
-using mixed modules. Probably more suitable for a delicate code
-where ctypes magic goes in a way.
+It Works. Probably more suitable for a delicate code where ctypes magic goes
+in a way.  All calls are optimized by the JIT, there is no slow path as in
+ctypes.
 
 Cons
 ----
 
-Slow. CPython-incompatible API, very rough and low-level
+It combines disadvantages of using ctypes with disadvantages of using mixed
+modules. CPython-incompatible API, very rough and low-level.
 
 Mixed Modules
 =============
@@ -87,15 +96,15 @@
 * a mixed module needs to be written in RPython, which is far more
   complicated than Python (XXX link)
 
-* due to lack of separate compilation (as of April 2008), each
+* due to lack of separate compilation (as of July 2011), each
   compilation-check requires to recompile whole PyPy python interpreter,
   which takes 0.5-1h. We plan to solve this at some point in near future.
 
 * although rpython is a garbage-collected language, the border between
   C and RPython needs to be managed by hand (each object that goes into the
-  C level must be explicitly freed) XXX we try to solve this
+  C level must be explicitly freed).
 
-Some document is available `here`_
+Some documentation is available `here`_
 
 .. _`here`: rffi.html
 
diff --git a/pypy/doc/getting-started.rst b/pypy/doc/getting-started.rst
--- a/pypy/doc/getting-started.rst
+++ b/pypy/doc/getting-started.rst
@@ -51,7 +51,7 @@
 ---------------
 
 PyPy is ready to be executed as soon as you unpack the tarball or the zip
-file, with no need install it in any specific location::
+file, with no need to install it in any specific location::
 
     $ tar xf pypy-1.5-linux.tar.bz2
 
diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst
--- a/pypy/doc/index.rst
+++ b/pypy/doc/index.rst
@@ -11,6 +11,10 @@
 Getting into PyPy ... 
 =============================================
 
+* `Getting started`_: how to install and run the PyPy Python interpreter
+
+* `FAQ`_: some frequently asked questions.
+
 * `Release 1.5`_: the latest official release
 
 * `PyPy Blog`_: news and status info about PyPy 
@@ -26,13 +30,6 @@
 Documentation for the PyPy Python Interpreter
 ===============================================
 
-`getting started`_ provides hands-on instructions 
-including a two-liner to run the PyPy Python interpreter 
-on your system, examples on advanced features and 
-entry points for using the `RPython toolchain`_.
-
-`FAQ`_ contains some frequently asked questions.
-
 New features of PyPy's Python Interpreter and 
 Translation Framework: 
 
diff --git a/pypy/doc/interpreter-optimizations.rst b/pypy/doc/interpreter-optimizations.rst
--- a/pypy/doc/interpreter-optimizations.rst
+++ b/pypy/doc/interpreter-optimizations.rst
@@ -157,32 +157,6 @@
 A more advanced version of sharing dicts, called *map dicts,* is available
 with the :config:`objspace.std.withmapdict` option.
 
-Builtin-Shadowing
-+++++++++++++++++
-
-Usually the calling of builtins in Python requires two dictionary lookups: first
-to see whether the current global dictionary contains an object with the same
-name, then a lookup in the ``__builtin__`` dictionary. This is somehow
-circumvented by storing an often used builtin into a local variable to get
-the fast local lookup (which is a rather strange and ugly hack).
-
-The same problem is solved in a different way by "wary" dictionaries. They are
-another dictionary representation used together with multidicts. This
-representation is used only for module dictionaries. The representation checks on
-every setitem whether the key that is used is the name of a builtin. If this is
-the case, the dictionary is marked as shadowing that particular builtin.
-
-To identify calls to builtins easily, a new bytecode (``CALL_LIKELY_BUILTIN``)
-is introduced. Whenever it is executed, the globals dictionary is checked
-to see whether it masks the builtin (which is possible without a dictionary
-lookup).  Then the ``__builtin__`` dict is checked in the same way,
-to see whether somebody replaced the real builtin with something else. In the
-common case, the program didn't do any of these; the proper builtin can then
-be called without using any dictionary lookup at all.
-
-You can enable this feature with the
-:config:`objspace.opcodes.CALL_LIKELY_BUILTIN` option.
-
 
 List Optimizations
 ------------------
@@ -289,34 +263,6 @@
 You can enable this feature with the :config:`objspace.opcodes.CALL_METHOD`
 option.
 
-.. _`call likely builtin`:
-
-CALL_LIKELY_BUILTIN
-+++++++++++++++++++
-
-A often heard "tip" for speeding up Python programs is to give an often used
-builtin a local name, since local lookups are faster than lookups of builtins,
-which involve doing two dictionary lookups: one in the globals dictionary and
-one in the the builtins dictionary. PyPy approaches this problem at the
-implementation level, with the introduction of the new ``CALL_LIKELY_BUILTIN``
-bytecode. This bytecode is produced by the compiler for a call whose target is
-the name of a builtin.  Since such a syntactic construct is very often actually
-invoking the expected builtin at run-time, this information can be used to make
-the call to the builtin directly, without going through any dictionary lookup.
-
-However, it can occur that the name is shadowed by a global name from the
-current module.  To catch this case, a special dictionary implementation for
-multidicts is introduced, which is used for the dictionaries of modules. This
-implementation keeps track which builtin name is shadowed by it.  The
-``CALL_LIKELY_BUILTIN`` bytecode asks the dictionary whether it is shadowing the
-builtin that is about to be called and asks the dictionary of ``__builtin__``
-whether the original builtin was changed.  These two checks are cheaper than
-full lookups.  In the common case, neither of these cases is true, so the
-builtin can be directly invoked.
-
-You can enable this feature with the
-:config:`objspace.opcodes.CALL_LIKELY_BUILTIN` option.
-
 .. more here?
 
 Overall Effects
diff --git a/pypy/doc/windows.rst b/pypy/doc/windows.rst
--- a/pypy/doc/windows.rst
+++ b/pypy/doc/windows.rst
@@ -32,6 +32,24 @@
 modules that relies on third-party libraries.  See below how to get
 and build them.
 
+Preping Windows for the Large Build
+-----------------------------------
+
+Normally 32bit programs are limited to 2GB of memory on Windows. It is
+possible to raise this limit, to 3GB on Windows 32bit, and almost 4GB
+on Windows 64bit.
+
+On Windows 32bit, it is necessary to modify the system: follow
+http://usa.autodesk.com/adsk/servlet/ps/dl/item?siteID=123112&id=9583842&linkID=9240617
+to enable the "3GB" feature, and reboot. This step is not necessary on
+Windows 64bit.
+
+Then you need to execute::
+
+    editbin /largeaddressaware pypy.exe
+
+on the pypy.exe file you compiled.
+
 Installing external packages
 ----------------------------
 
diff --git a/pypy/interpreter/astcompiler/ast.py b/pypy/interpreter/astcompiler/ast.py
--- a/pypy/interpreter/astcompiler/ast.py
+++ b/pypy/interpreter/astcompiler/ast.py
@@ -2541,8 +2541,9 @@
 class ASTVisitor(object):
 
     def visit_sequence(self, seq):
-        for node in seq:
-            node.walkabout(self)
+        if seq is not None:
+            for node in seq:
+                node.walkabout(self)
 
     def default_visitor(self, node):
         raise NodeVisitorNotImplemented
@@ -2673,46 +2674,36 @@
 class GenericASTVisitor(ASTVisitor):
 
     def visit_Module(self, node):
-        if node.body:
-            self.visit_sequence(node.body)
+        self.visit_sequence(node.body)
 
     def visit_Interactive(self, node):
-        if node.body:
-            self.visit_sequence(node.body)
+        self.visit_sequence(node.body)
 
     def visit_Expression(self, node):
         node.body.walkabout(self)
 
     def visit_Suite(self, node):
-        if node.body:
-            self.visit_sequence(node.body)
+        self.visit_sequence(node.body)
 
     def visit_FunctionDef(self, node):
         node.args.walkabout(self)
-        if node.body:
-            self.visit_sequence(node.body)
-        if node.decorator_list:
-            self.visit_sequence(node.decorator_list)
+        self.visit_sequence(node.body)
+        self.visit_sequence(node.decorator_list)
 
     def visit_ClassDef(self, node):
-        if node.bases:
-            self.visit_sequence(node.bases)
-        if node.body:
-            self.visit_sequence(node.body)
-        if node.decorator_list:
-            self.visit_sequence(node.decorator_list)
+        self.visit_sequence(node.bases)
+        self.visit_sequence(node.body)
+        self.visit_sequence(node.decorator_list)
 
     def visit_Return(self, node):
         if node.value:
             node.value.walkabout(self)
 
     def visit_Delete(self, node):
-        if node.targets:
-            self.visit_sequence(node.targets)
+        self.visit_sequence(node.targets)
 
     def visit_Assign(self, node):
-        if node.targets:
-            self.visit_sequence(node.targets)
+        self.visit_sequence(node.targets)
         node.value.walkabout(self)
 
     def visit_AugAssign(self, node):
@@ -2722,37 +2713,29 @@
     def visit_Print(self, node):
         if node.dest:
             node.dest.walkabout(self)
-        if node.values:
-            self.visit_sequence(node.values)
+        self.visit_sequence(node.values)
 
     def visit_For(self, node):
         node.target.walkabout(self)
         node.iter.walkabout(self)
-        if node.body:
-            self.visit_sequence(node.body)
-        if node.orelse:
-            self.visit_sequence(node.orelse)
+        self.visit_sequence(node.body)
+        self.visit_sequence(node.orelse)
 
     def visit_While(self, node):
         node.test.walkabout(self)
-        if node.body:
-            self.visit_sequence(node.body)
-        if node.orelse:
-            self.visit_sequence(node.orelse)
+        self.visit_sequence(node.body)
+        self.visit_sequence(node.orelse)
 
     def visit_If(self, node):
         node.test.walkabout(self)
-        if node.body:
-            self.visit_sequence(node.body)
-        if node.orelse:
-            self.visit_sequence(node.orelse)
+        self.visit_sequence(node.body)
+        self.visit_sequence(node.orelse)
 
     def visit_With(self, node):
         node.context_expr.walkabout(self)
         if node.optional_vars:
             node.optional_vars.walkabout(self)
-        if node.body:
-            self.visit_sequence(node.body)
+        self.visit_sequence(node.body)
 
     def visit_Raise(self, node):
         if node.type:
@@ -2763,18 +2746,13 @@
             node.tback.walkabout(self)
 
     def visit_TryExcept(self, node):
-        if node.body:
-            self.visit_sequence(node.body)
-        if node.handlers:
-            self.visit_sequence(node.handlers)
-        if node.orelse:
-            self.visit_sequence(node.orelse)
+        self.visit_sequence(node.body)
+        self.visit_sequence(node.handlers)
+        self.visit_sequence(node.orelse)
 
     def visit_TryFinally(self, node):
-        if node.body:
-            self.visit_sequence(node.body)
-        if node.finalbody:
-            self.visit_sequence(node.finalbody)
+        self.visit_sequence(node.body)
+        self.visit_sequence(node.finalbody)
 
     def visit_Assert(self, node):
         node.test.walkabout(self)
@@ -2782,12 +2760,10 @@
             node.msg.walkabout(self)
 
     def visit_Import(self, node):
-        if node.names:
-            self.visit_sequence(node.names)
+        self.visit_sequence(node.names)
 
     def visit_ImportFrom(self, node):
-        if node.names:
-            self.visit_sequence(node.names)
+        self.visit_sequence(node.names)
 
     def visit_Exec(self, node):
         node.body.walkabout(self)
@@ -2812,8 +2788,7 @@
         pass
 
     def visit_BoolOp(self, node):
-        if node.values:
-            self.visit_sequence(node.values)
+        self.visit_sequence(node.values)
 
     def visit_BinOp(self, node):
         node.left.walkabout(self)
@@ -2832,35 +2807,28 @@
         node.orelse.walkabout(self)
 
     def visit_Dict(self, node):
-        if node.keys:
-            self.visit_sequence(node.keys)
-        if node.values:
-            self.visit_sequence(node.values)
+        self.visit_sequence(node.keys)
+        self.visit_sequence(node.values)
 
     def visit_Set(self, node):
-        if node.elts:
-            self.visit_sequence(node.elts)
+        self.visit_sequence(node.elts)
 
     def visit_ListComp(self, node):
         node.elt.walkabout(self)
-        if node.generators:
-            self.visit_sequence(node.generators)
+        self.visit_sequence(node.generators)
 
     def visit_SetComp(self, node):
         node.elt.walkabout(self)
-        if node.generators:
-            self.visit_sequence(node.generators)
+        self.visit_sequence(node.generators)
 
     def visit_DictComp(self, node):
         node.key.walkabout(self)
         node.value.walkabout(self)
-        if node.generators:
-            self.visit_sequence(node.generators)
+        self.visit_sequence(node.generators)
 
     def visit_GeneratorExp(self, node):
         node.elt.walkabout(self)
-        if node.generators:
-            self.visit_sequence(node.generators)
+        self.visit_sequence(node.generators)
 
     def visit_Yield(self, node):
         if node.value:
@@ -2868,15 +2836,12 @@
 
     def visit_Compare(self, node):
         node.left.walkabout(self)
-        if node.comparators:
-            self.visit_sequence(node.comparators)
+        self.visit_sequence(node.comparators)
 
     def visit_Call(self, node):
         node.func.walkabout(self)
-        if node.args:
-            self.visit_sequence(node.args)
-        if node.keywords:
-            self.visit_sequence(node.keywords)
+        self.visit_sequence(node.args)
+        self.visit_sequence(node.keywords)
         if node.starargs:
             node.starargs.walkabout(self)
         if node.kwargs:
@@ -2902,12 +2867,10 @@
         pass
 
     def visit_List(self, node):
-        if node.elts:
-            self.visit_sequence(node.elts)
+        self.visit_sequence(node.elts)
 
     def visit_Tuple(self, node):
-        if node.elts:
-            self.visit_sequence(node.elts)
+        self.visit_sequence(node.elts)
 
     def visit_Const(self, node):
         pass
@@ -2924,8 +2887,7 @@
             node.step.walkabout(self)
 
     def visit_ExtSlice(self, node):
-        if node.dims:
-            self.visit_sequence(node.dims)
+        self.visit_sequence(node.dims)
 
     def visit_Index(self, node):
         node.value.walkabout(self)
@@ -2933,22 +2895,18 @@
     def visit_comprehension(self, node):
         node.target.walkabout(self)
         node.iter.walkabout(self)
-        if node.ifs:
-            self.visit_sequence(node.ifs)
+        self.visit_sequence(node.ifs)
 
     def visit_ExceptHandler(self, node):
         if node.type:
             node.type.walkabout(self)
         if node.name:
             node.name.walkabout(self)
-        if node.body:
-            self.visit_sequence(node.body)
+        self.visit_sequence(node.body)
 
     def visit_arguments(self, node):
-        if node.args:
-            self.visit_sequence(node.args)
-        if node.defaults:
-            self.visit_sequence(node.defaults)
+        self.visit_sequence(node.args)
+        self.visit_sequence(node.defaults)
 
     def visit_keyword(self, node):
         node.value.walkabout(self)
@@ -3069,6 +3027,7 @@
             raise
         w_self.setdictvalue(space, 'body', w_new_value)
         return
+    w_self.deldictvalue(space, 'body')
     w_self.initialization_state |= 1
 
 _Expression_field_unroller = unrolling_iterable(['body'])
@@ -3157,6 +3116,7 @@
             raise
         w_self.setdictvalue(space, 'lineno', w_new_value)
         return
+    w_self.deldictvalue(space, 'lineno')
     w_self.initialization_state |= w_self._lineno_mask
 
 def stmt_get_col_offset(space, w_self):
@@ -3178,6 +3138,7 @@
             raise
         w_self.setdictvalue(space, 'col_offset', w_new_value)
         return
+    w_self.deldictvalue(space, 'col_offset')
     w_self.initialization_state |= w_self._col_offset_mask
 
 stmt.typedef = typedef.TypeDef("stmt",
@@ -3208,6 +3169,7 @@
             raise
         w_self.setdictvalue(space, 'name', w_new_value)
         return
+    w_self.deldictvalue(space, 'name')
     w_self.initialization_state |= 1
 
 def FunctionDef_get_args(space, w_self):
@@ -3229,6 +3191,7 @@
             raise
         w_self.setdictvalue(space, 'args', w_new_value)
         return
+    w_self.deldictvalue(space, 'args')
     w_self.initialization_state |= 2
 
 def FunctionDef_get_body(space, w_self):
@@ -3315,6 +3278,7 @@
             raise
         w_self.setdictvalue(space, 'name', w_new_value)
         return
+    w_self.deldictvalue(space, 'name')
     w_self.initialization_state |= 1
 
 def ClassDef_get_bases(space, w_self):
@@ -3420,6 +3384,7 @@
             raise
         w_self.setdictvalue(space, 'value', w_new_value)
         return
+    w_self.deldictvalue(space, 'value')
     w_self.initialization_state |= 1
 
 _Return_field_unroller = unrolling_iterable(['value'])
@@ -3526,6 +3491,7 @@
             raise
         w_self.setdictvalue(space, 'value', w_new_value)
         return
+    w_self.deldictvalue(space, 'value')
     w_self.initialization_state |= 2
 
 _Assign_field_unroller = unrolling_iterable(['targets', 'value'])
@@ -3573,6 +3539,7 @@
             raise
         w_self.setdictvalue(space, 'target', w_new_value)
         return
+    w_self.deldictvalue(space, 'target')
     w_self.initialization_state |= 1
 
 def AugAssign_get_op(space, w_self):
@@ -3590,13 +3557,13 @@
     try:
         obj = space.interp_w(operator, w_new_value)
         w_self.op = obj.to_simple_int(space)
-        # need to save the original object too
-        w_self.setdictvalue(space, 'op', w_new_value)
     except OperationError, e:
         if not e.match(space, space.w_TypeError):
             raise
         w_self.setdictvalue(space, 'op', w_new_value)
         return
+    # need to save the original object too
+    w_self.setdictvalue(space, 'op', w_new_value)
     w_self.initialization_state |= 2
 
 def AugAssign_get_value(space, w_self):
@@ -3618,6 +3585,7 @@
             raise
         w_self.setdictvalue(space, 'value', w_new_value)
         return
+    w_self.deldictvalue(space, 'value')
     w_self.initialization_state |= 4
 
 _AugAssign_field_unroller = unrolling_iterable(['target', 'op', 'value'])
@@ -3665,6 +3633,7 @@
             raise
         w_self.setdictvalue(space, 'dest', w_new_value)
         return
+    w_self.deldictvalue(space, 'dest')
     w_self.initialization_state |= 1
 
 def Print_get_values(space, w_self):
@@ -3704,6 +3673,7 @@
             raise
         w_self.setdictvalue(space, 'nl', w_new_value)
         return
+    w_self.deldictvalue(space, 'nl')
     w_self.initialization_state |= 4
 
 _Print_field_unroller = unrolling_iterable(['dest', 'values', 'nl'])
@@ -3752,6 +3722,7 @@
             raise
         w_self.setdictvalue(space, 'target', w_new_value)
         return
+    w_self.deldictvalue(space, 'target')
     w_self.initialization_state |= 1
 
 def For_get_iter(space, w_self):
@@ -3773,6 +3744,7 @@
             raise
         w_self.setdictvalue(space, 'iter', w_new_value)
         return
+    w_self.deldictvalue(space, 'iter')
     w_self.initialization_state |= 2
 
 def For_get_body(space, w_self):
@@ -3859,6 +3831,7 @@
             raise
         w_self.setdictvalue(space, 'test', w_new_value)
         return
+    w_self.deldictvalue(space, 'test')
     w_self.initialization_state |= 1
 
 def While_get_body(space, w_self):
@@ -3944,6 +3917,7 @@
             raise
         w_self.setdictvalue(space, 'test', w_new_value)
         return
+    w_self.deldictvalue(space, 'test')
     w_self.initialization_state |= 1
 
 def If_get_body(space, w_self):
@@ -4029,6 +4003,7 @@
             raise
         w_self.setdictvalue(space, 'context_expr', w_new_value)
         return
+    w_self.deldictvalue(space, 'context_expr')
     w_self.initialization_state |= 1
 
 def With_get_optional_vars(space, w_self):
@@ -4050,6 +4025,7 @@
             raise
         w_self.setdictvalue(space, 'optional_vars', w_new_value)
         return
+    w_self.deldictvalue(space, 'optional_vars')
     w_self.initialization_state |= 2
 
 def With_get_body(space, w_self):
@@ -4116,6 +4092,7 @@
             raise
         w_self.setdictvalue(space, 'type', w_new_value)
         return
+    w_self.deldictvalue(space, 'type')
     w_self.initialization_state |= 1
 
 def Raise_get_inst(space, w_self):
@@ -4137,6 +4114,7 @@
             raise
         w_self.setdictvalue(space, 'inst', w_new_value)
         return
+    w_self.deldictvalue(space, 'inst')
     w_self.initialization_state |= 2
 
 def Raise_get_tback(space, w_self):
@@ -4158,6 +4136,7 @@
             raise
         w_self.setdictvalue(space, 'tback', w_new_value)
         return
+    w_self.deldictvalue(space, 'tback')
     w_self.initialization_state |= 4
 
 _Raise_field_unroller = unrolling_iterable(['type', 'inst', 'tback'])
@@ -4351,6 +4330,7 @@
             raise
         w_self.setdictvalue(space, 'test', w_new_value)
         return
+    w_self.deldictvalue(space, 'test')
     w_self.initialization_state |= 1
 
 def Assert_get_msg(space, w_self):
@@ -4372,6 +4352,7 @@
             raise
         w_self.setdictvalue(space, 'msg', w_new_value)
         return
+    w_self.deldictvalue(space, 'msg')
     w_self.initialization_state |= 2
 
 _Assert_field_unroller = unrolling_iterable(['test', 'msg'])
@@ -4464,6 +4445,7 @@
             raise
         w_self.setdictvalue(space, 'module', w_new_value)
         return
+    w_self.deldictvalue(space, 'module')
     w_self.initialization_state |= 1
 
 def ImportFrom_get_names(space, w_self):
@@ -4503,6 +4485,7 @@
             raise
         w_self.setdictvalue(space, 'level', w_new_value)
         return
+    w_self.deldictvalue(space, 'level')
     w_self.initialization_state |= 4
 
 _ImportFrom_field_unroller = unrolling_iterable(['module', 'names', 'level'])
@@ -4551,6 +4534,7 @@
             raise
         w_self.setdictvalue(space, 'body', w_new_value)
         return
+    w_self.deldictvalue(space, 'body')
     w_self.initialization_state |= 1
 
 def Exec_get_globals(space, w_self):
@@ -4572,6 +4556,7 @@
             raise
         w_self.setdictvalue(space, 'globals', w_new_value)
         return
+    w_self.deldictvalue(space, 'globals')
     w_self.initialization_state |= 2
 
 def Exec_get_locals(space, w_self):
@@ -4593,6 +4578,7 @@
             raise
         w_self.setdictvalue(space, 'locals', w_new_value)
         return
+    w_self.deldictvalue(space, 'locals')
     w_self.initialization_state |= 4
 
 _Exec_field_unroller = unrolling_iterable(['body', 'globals', 'locals'])
@@ -4683,6 +4669,7 @@
             raise
         w_self.setdictvalue(space, 'value', w_new_value)
         return
+    w_self.deldictvalue(space, 'value')
     w_self.initialization_state |= 1
 
 _Expr_field_unroller = unrolling_iterable(['value'])
@@ -4779,6 +4766,7 @@
             raise
         w_self.setdictvalue(space, 'lineno', w_new_value)
         return
+    w_self.deldictvalue(space, 'lineno')
     w_self.initialization_state |= w_self._lineno_mask
 
 def expr_get_col_offset(space, w_self):
@@ -4800,6 +4788,7 @@
             raise
         w_self.setdictvalue(space, 'col_offset', w_new_value)
         return
+    w_self.deldictvalue(space, 'col_offset')
     w_self.initialization_state |= w_self._col_offset_mask
 
 expr.typedef = typedef.TypeDef("expr",
@@ -4826,13 +4815,13 @@
     try:
         obj = space.interp_w(boolop, w_new_value)
         w_self.op = obj.to_simple_int(space)
-        # need to save the original object too
-        w_self.setdictvalue(space, 'op', w_new_value)
     except OperationError, e:
         if not e.match(space, space.w_TypeError):
             raise
         w_self.setdictvalue(space, 'op', w_new_value)
         return
+    # need to save the original object too
+    w_self.setdictvalue(space, 'op', w_new_value)
     w_self.initialization_state |= 1
 
 def BoolOp_get_values(space, w_self):
@@ -4898,6 +4887,7 @@
             raise
         w_self.setdictvalue(space, 'left', w_new_value)
         return
+    w_self.deldictvalue(space, 'left')
     w_self.initialization_state |= 1
 
 def BinOp_get_op(space, w_self):
@@ -4915,13 +4905,13 @@
     try:
         obj = space.interp_w(operator, w_new_value)
         w_self.op = obj.to_simple_int(space)
-        # need to save the original object too
-        w_self.setdictvalue(space, 'op', w_new_value)
     except OperationError, e:
         if not e.match(space, space.w_TypeError):
             raise
         w_self.setdictvalue(space, 'op', w_new_value)
         return
+    # need to save the original object too
+    w_self.setdictvalue(space, 'op', w_new_value)
     w_self.initialization_state |= 2
 
 def BinOp_get_right(space, w_self):
@@ -4943,6 +4933,7 @@
             raise
         w_self.setdictvalue(space, 'right', w_new_value)
         return
+    w_self.deldictvalue(space, 'right')
     w_self.initialization_state |= 4
 
 _BinOp_field_unroller = unrolling_iterable(['left', 'op', 'right'])
@@ -4986,13 +4977,13 @@
     try:
         obj = space.interp_w(unaryop, w_new_value)
         w_self.op = obj.to_simple_int(space)
-        # need to save the original object too
-        w_self.setdictvalue(space, 'op', w_new_value)
     except OperationError, e:
         if not e.match(space, space.w_TypeError):
             raise
         w_self.setdictvalue(space, 'op', w_new_value)
         return
+    # need to save the original object too
+    w_self.setdictvalue(space, 'op', w_new_value)
     w_self.initialization_state |= 1
 
 def UnaryOp_get_operand(space, w_self):
@@ -5014,6 +5005,7 @@
             raise
         w_self.setdictvalue(space, 'operand', w_new_value)
         return
+    w_self.deldictvalue(space, 'operand')
     w_self.initialization_state |= 2
 
 _UnaryOp_field_unroller = unrolling_iterable(['op', 'operand'])
@@ -5060,6 +5052,7 @@
             raise
         w_self.setdictvalue(space, 'args', w_new_value)
         return
+    w_self.deldictvalue(space, 'args')
     w_self.initialization_state |= 1
 
 def Lambda_get_body(space, w_self):
@@ -5081,6 +5074,7 @@
             raise
         w_self.setdictvalue(space, 'body', w_new_value)
         return
+    w_self.deldictvalue(space, 'body')
     w_self.initialization_state |= 2
 
 _Lambda_field_unroller = unrolling_iterable(['args', 'body'])
@@ -5127,6 +5121,7 @@
             raise
         w_self.setdictvalue(space, 'test', w_new_value)
         return
+    w_self.deldictvalue(space, 'test')
     w_self.initialization_state |= 1
 
 def IfExp_get_body(space, w_self):
@@ -5148,6 +5143,7 @@
             raise
         w_self.setdictvalue(space, 'body', w_new_value)
         return
+    w_self.deldictvalue(space, 'body')
     w_self.initialization_state |= 2
 
 def IfExp_get_orelse(space, w_self):
@@ -5169,6 +5165,7 @@
             raise
         w_self.setdictvalue(space, 'orelse', w_new_value)
         return
+    w_self.deldictvalue(space, 'orelse')
     w_self.initialization_state |= 4
 
 _IfExp_field_unroller = unrolling_iterable(['test', 'body', 'orelse'])
@@ -5322,6 +5319,7 @@
             raise
         w_self.setdictvalue(space, 'elt', w_new_value)
         return
+    w_self.deldictvalue(space, 'elt')
     w_self.initialization_state |= 1
 
 def ListComp_get_generators(space, w_self):
@@ -5387,6 +5385,7 @@
             raise
         w_self.setdictvalue(space, 'elt', w_new_value)
         return
+    w_self.deldictvalue(space, 'elt')
     w_self.initialization_state |= 1
 
 def SetComp_get_generators(space, w_self):
@@ -5452,6 +5451,7 @@
             raise
         w_self.setdictvalue(space, 'key', w_new_value)
         return
+    w_self.deldictvalue(space, 'key')
     w_self.initialization_state |= 1
 
 def DictComp_get_value(space, w_self):
@@ -5473,6 +5473,7 @@
             raise
         w_self.setdictvalue(space, 'value', w_new_value)
         return
+    w_self.deldictvalue(space, 'value')
     w_self.initialization_state |= 2
 
 def DictComp_get_generators(space, w_self):
@@ -5539,6 +5540,7 @@
             raise
         w_self.setdictvalue(space, 'elt', w_new_value)
         return
+    w_self.deldictvalue(space, 'elt')
     w_self.initialization_state |= 1
 
 def GeneratorExp_get_generators(space, w_self):
@@ -5604,6 +5606,7 @@
             raise
         w_self.setdictvalue(space, 'value', w_new_value)
         return
+    w_self.deldictvalue(space, 'value')
     w_self.initialization_state |= 1
 
 _Yield_field_unroller = unrolling_iterable(['value'])
@@ -5649,6 +5652,7 @@
             raise
         w_self.setdictvalue(space, 'left', w_new_value)
         return
+    w_self.deldictvalue(space, 'left')
     w_self.initialization_state |= 1
 
 def Compare_get_ops(space, w_self):
@@ -5734,6 +5738,7 @@
             raise
         w_self.setdictvalue(space, 'func', w_new_value)
         return
+    w_self.deldictvalue(space, 'func')
     w_self.initialization_state |= 1
 
 def Call_get_args(space, w_self):
@@ -5791,6 +5796,7 @@
             raise
         w_self.setdictvalue(space, 'starargs', w_new_value)
         return
+    w_self.deldictvalue(space, 'starargs')
     w_self.initialization_state |= 8
 
 def Call_get_kwargs(space, w_self):
@@ -5812,6 +5818,7 @@
             raise
         w_self.setdictvalue(space, 'kwargs', w_new_value)
         return
+    w_self.deldictvalue(space, 'kwargs')
     w_self.initialization_state |= 16
 
 _Call_field_unroller = unrolling_iterable(['func', 'args', 'keywords', 'starargs', 'kwargs'])
@@ -5863,6 +5870,7 @@
             raise
         w_self.setdictvalue(space, 'value', w_new_value)
         return
+    w_self.deldictvalue(space, 'value')
     w_self.initialization_state |= 1
 
 _Repr_field_unroller = unrolling_iterable(['value'])
@@ -5908,6 +5916,7 @@
             raise
         w_self.setdictvalue(space, 'n', w_new_value)
         return
+    w_self.deldictvalue(space, 'n')
     w_self.initialization_state |= 1
 
 _Num_field_unroller = unrolling_iterable(['n'])
@@ -5953,6 +5962,7 @@
             raise
         w_self.setdictvalue(space, 's', w_new_value)
         return
+    w_self.deldictvalue(space, 's')
     w_self.initialization_state |= 1
 
 _Str_field_unroller = unrolling_iterable(['s'])
@@ -5998,6 +6008,7 @@
             raise
         w_self.setdictvalue(space, 'value', w_new_value)
         return
+    w_self.deldictvalue(space, 'value')
     w_self.initialization_state |= 1
 
 def Attribute_get_attr(space, w_self):
@@ -6019,6 +6030,7 @@
             raise
         w_self.setdictvalue(space, 'attr', w_new_value)
         return
+    w_self.deldictvalue(space, 'attr')
     w_self.initialization_state |= 2
 
 def Attribute_get_ctx(space, w_self):
@@ -6036,13 +6048,13 @@
     try:
         obj = space.interp_w(expr_context, w_new_value)
         w_self.ctx = obj.to_simple_int(space)
-        # need to save the original object too
-        w_self.setdictvalue(space, 'ctx', w_new_value)
     except OperationError, e:
         if not e.match(space, space.w_TypeError):
             raise
         w_self.setdictvalue(space, 'ctx', w_new_value)
         return
+    # need to save the original object too
+    w_self.setdictvalue(space, 'ctx', w_new_value)
     w_self.initialization_state |= 4
 
 _Attribute_field_unroller = unrolling_iterable(['value', 'attr', 'ctx'])
@@ -6090,6 +6102,7 @@
             raise
         w_self.setdictvalue(space, 'value', w_new_value)
         return
+    w_self.deldictvalue(space, 'value')
     w_self.initialization_state |= 1
 
 def Subscript_get_slice(space, w_self):
@@ -6111,6 +6124,7 @@
             raise
         w_self.setdictvalue(space, 'slice', w_new_value)
         return
+    w_self.deldictvalue(space, 'slice')
     w_self.initialization_state |= 2
 
 def Subscript_get_ctx(space, w_self):
@@ -6128,13 +6142,13 @@
     try:
         obj = space.interp_w(expr_context, w_new_value)
         w_self.ctx = obj.to_simple_int(space)
-        # need to save the original object too
-        w_self.setdictvalue(space, 'ctx', w_new_value)
     except OperationError, e:
         if not e.match(space, space.w_TypeError):
             raise
         w_self.setdictvalue(space, 'ctx', w_new_value)
         return
+    # need to save the original object too
+    w_self.setdictvalue(space, 'ctx', w_new_value)
     w_self.initialization_state |= 4
 
 _Subscript_field_unroller = unrolling_iterable(['value', 'slice', 'ctx'])
@@ -6182,6 +6196,7 @@
             raise
         w_self.setdictvalue(space, 'id', w_new_value)
         return
+    w_self.deldictvalue(space, 'id')
     w_self.initialization_state |= 1
 
 def Name_get_ctx(space, w_self):
@@ -6199,13 +6214,13 @@
     try:
         obj = space.interp_w(expr_context, w_new_value)
         w_self.ctx = obj.to_simple_int(space)
-        # need to save the original object too
-        w_self.setdictvalue(space, 'ctx', w_new_value)
     except OperationError, e:
         if not e.match(space, space.w_TypeError):
             raise
         w_self.setdictvalue(space, 'ctx', w_new_value)
         return
+    # need to save the original object too
+    w_self.setdictvalue(space, 'ctx', w_new_value)
     w_self.initialization_state |= 2
 
 _Name_field_unroller = unrolling_iterable(['id', 'ctx'])
@@ -6266,13 +6281,13 @@
     try:
         obj = space.interp_w(expr_context, w_new_value)
         w_self.ctx = obj.to_simple_int(space)
-        # need to save the original object too
-        w_self.setdictvalue(space, 'ctx', w_new_value)
     except OperationError, e:
         if not e.match(space, space.w_TypeError):
             raise
         w_self.setdictvalue(space, 'ctx', w_new_value)
         return
+    # need to save the original object too
+    w_self.setdictvalue(space, 'ctx', w_new_value)
     w_self.initialization_state |= 2
 
 _List_field_unroller = unrolling_iterable(['elts', 'ctx'])
@@ -6334,13 +6349,13 @@
     try:
         obj = space.interp_w(expr_context, w_new_value)
         w_self.ctx = obj.to_simple_int(space)
-        # need to save the original object too
-        w_self.setdictvalue(space, 'ctx', w_new_value)
     except OperationError, e:
         if not e.match(space, space.w_TypeError):
             raise
         w_self.setdictvalue(space, 'ctx', w_new_value)
         return
+    # need to save the original object too
+    w_self.setdictvalue(space, 'ctx', w_new_value)
     w_self.initialization_state |= 2
 
 _Tuple_field_unroller = unrolling_iterable(['elts', 'ctx'])
@@ -6388,6 +6403,7 @@
             raise
         w_self.setdictvalue(space, 'value', w_new_value)
         return
+    w_self.deldictvalue(space, 'value')
     w_self.initialization_state |= 1
 
 _Const_field_unroller = unrolling_iterable(['value'])
@@ -6506,6 +6522,7 @@
             raise
         w_self.setdictvalue(space, 'lower', w_new_value)
         return
+    w_self.deldictvalue(space, 'lower')
     w_self.initialization_state |= 1
 
 def Slice_get_upper(space, w_self):
@@ -6527,6 +6544,7 @@
             raise
         w_self.setdictvalue(space, 'upper', w_new_value)
         return
+    w_self.deldictvalue(space, 'upper')
     w_self.initialization_state |= 2
 
 def Slice_get_step(space, w_self):
@@ -6548,6 +6566,7 @@
             raise
         w_self.setdictvalue(space, 'step', w_new_value)
         return
+    w_self.deldictvalue(space, 'step')
     w_self.initialization_state |= 4
 
 _Slice_field_unroller = unrolling_iterable(['lower', 'upper', 'step'])
@@ -6638,6 +6657,7 @@
             raise
         w_self.setdictvalue(space, 'value', w_new_value)
         return
+    w_self.deldictvalue(space, 'value')
     w_self.initialization_state |= 1
 
 _Index_field_unroller = unrolling_iterable(['value'])
@@ -6907,6 +6927,7 @@
             raise
         w_self.setdictvalue(space, 'target', w_new_value)
         return
+    w_self.deldictvalue(space, 'target')
     w_self.initialization_state |= 1
 
 def comprehension_get_iter(space, w_self):
@@ -6928,6 +6949,7 @@
             raise
         w_self.setdictvalue(space, 'iter', w_new_value)
         return
+    w_self.deldictvalue(space, 'iter')
     w_self.initialization_state |= 2
 
 def comprehension_get_ifs(space, w_self):
@@ -6994,6 +7016,7 @@
             raise
         w_self.setdictvalue(space, 'lineno', w_new_value)
         return
+    w_self.deldictvalue(space, 'lineno')
     w_self.initialization_state |= w_self._lineno_mask
 
 def excepthandler_get_col_offset(space, w_self):
@@ -7015,6 +7038,7 @@
             raise
         w_self.setdictvalue(space, 'col_offset', w_new_value)
         return
+    w_self.deldictvalue(space, 'col_offset')
     w_self.initialization_state |= w_self._col_offset_mask
 
 excepthandler.typedef = typedef.TypeDef("excepthandler",
@@ -7045,6 +7069,7 @@
             raise
         w_self.setdictvalue(space, 'type', w_new_value)
         return
+    w_self.deldictvalue(space, 'type')
     w_self.initialization_state |= 1
 
 def ExceptHandler_get_name(space, w_self):
@@ -7066,6 +7091,7 @@
             raise
         w_self.setdictvalue(space, 'name', w_new_value)
         return
+    w_self.deldictvalue(space, 'name')
     w_self.initialization_state |= 2
 
 def ExceptHandler_get_body(space, w_self):
@@ -7153,6 +7179,7 @@
             raise
         w_self.setdictvalue(space, 'vararg', w_new_value)
         return
+    w_self.deldictvalue(space, 'vararg')
     w_self.initialization_state |= 2
 
 def arguments_get_kwarg(space, w_self):
@@ -7177,6 +7204,7 @@
             raise
         w_self.setdictvalue(space, 'kwarg', w_new_value)
         return
+    w_self.deldictvalue(space, 'kwarg')
     w_self.initialization_state |= 4
 
 def arguments_get_defaults(space, w_self):
@@ -7245,6 +7273,7 @@
             raise
         w_self.setdictvalue(space, 'arg', w_new_value)
         return
+    w_self.deldictvalue(space, 'arg')
     w_self.initialization_state |= 1
 
 def keyword_get_value(space, w_self):
@@ -7266,6 +7295,7 @@
             raise
         w_self.setdictvalue(space, 'value', w_new_value)
         return
+    w_self.deldictvalue(space, 'value')
     w_self.initialization_state |= 2
 
 _keyword_field_unroller = unrolling_iterable(['arg', 'value'])
@@ -7312,6 +7342,7 @@
             raise
         w_self.setdictvalue(space, 'name', w_new_value)
         return
+    w_self.deldictvalue(space, 'name')
     w_self.initialization_state |= 1
 
 def alias_get_asname(space, w_self):
@@ -7336,6 +7367,7 @@
             raise
         w_self.setdictvalue(space, 'asname', w_new_value)
         return
+    w_self.deldictvalue(space, 'asname')
     w_self.initialization_state |= 2
 
 _alias_field_unroller = unrolling_iterable(['name', 'asname'])
diff --git a/pypy/interpreter/astcompiler/codegen.py b/pypy/interpreter/astcompiler/codegen.py
--- a/pypy/interpreter/astcompiler/codegen.py
+++ b/pypy/interpreter/astcompiler/codegen.py
@@ -295,15 +295,11 @@
     def visit_FunctionDef(self, func):
         self.update_position(func.lineno, True)
         # Load decorators first, but apply them after the function is created.
-        if func.decorator_list:
-            self.visit_sequence(func.decorator_list)
+        self.visit_sequence(func.decorator_list)
         args = func.args
         assert isinstance(args, ast.arguments)
-        if args.defaults:
-            self.visit_sequence(args.defaults)
-            num_defaults = len(args.defaults)
-        else:
-            num_defaults = 0
+        self.visit_sequence(args.defaults)
+        num_defaults = len(args.defaults) if args.defaults is not None else 0
         code = self.sub_scope(FunctionCodeGenerator, func.name, func,
                               func.lineno)
         self._make_function(code, num_defaults)
@@ -317,24 +313,17 @@
         self.update_position(lam.lineno)
         args = lam.args
         assert isinstance(args, ast.arguments)
-        if args.defaults:
-            self.visit_sequence(args.defaults)
-            default_count = len(args.defaults)
-        else:
-            default_count = 0
+        self.visit_sequence(args.defaults)
+        default_count = len(args.defaults) if args.defaults is not None else 0
         code = self.sub_scope(LambdaCodeGenerator, "<lambda>", lam, lam.lineno)
         self._make_function(code, default_count)
 
     def visit_ClassDef(self, cls):
         self.update_position(cls.lineno, True)
-        if cls.decorator_list:
-            self.visit_sequence(cls.decorator_list)
+        self.visit_sequence(cls.decorator_list)
         self.load_const(self.space.wrap(cls.name))
-        if cls.bases:
-            bases_count = len(cls.bases)
-            self.visit_sequence(cls.bases)
-        else:
-            bases_count = 0
+        self.visit_sequence(cls.bases)
+        bases_count = len(cls.bases) if cls.bases is not None else 0
         self.emit_op_arg(ops.BUILD_TUPLE, bases_count)
         code = self.sub_scope(ClassCodeGenerator, cls.name, cls, cls.lineno)
         self._make_function(code, 0)
@@ -446,8 +435,7 @@
         end = self.new_block()
         test_constant = if_.test.as_constant_truth(self.space)
         if test_constant == optimize.CONST_FALSE:
-            if if_.orelse:
-                self.visit_sequence(if_.orelse)
+            self.visit_sequence(if_.orelse)
         elif test_constant == optimize.CONST_TRUE:
             self.visit_sequence(if_.body)
         else:
@@ -515,16 +503,14 @@
         self.use_next_block(cleanup)
         self.emit_op(ops.POP_BLOCK)
         self.pop_frame_block(F_BLOCK_LOOP, start)
-        if fr.orelse:
-            self.visit_sequence(fr.orelse)
+        self.visit_sequence(fr.orelse)
         self.use_next_block(end)
 
     def visit_While(self, wh):
         self.update_position(wh.lineno, True)
         test_constant = wh.test.as_constant_truth(self.space)
         if test_constant == optimize.CONST_FALSE:
-            if wh.orelse:
-                self.visit_sequence(wh.orelse)
+            self.visit_sequence(wh.orelse)
         else:
             end = self.new_block()
             anchor = None
@@ -544,8 +530,7 @@
                 self.use_next_block(anchor)
                 self.emit_op(ops.POP_BLOCK)
             self.pop_frame_block(F_BLOCK_LOOP, loop)
-            if wh.orelse:
-                self.visit_sequence(wh.orelse)
+            self.visit_sequence(wh.orelse)
             self.use_next_block(end)
 
     def visit_TryExcept(self, te):
@@ -581,8 +566,7 @@
             self.use_next_block(next_except)
         self.emit_op(ops.END_FINALLY)
         self.use_next_block(otherwise)
-        if te.orelse:
-            self.visit_sequence(te.orelse)
+        self.visit_sequence(te.orelse)
         self.use_next_block(end)
 
     def visit_TryFinally(self, tf):
@@ -893,27 +877,19 @@
 
     def visit_Tuple(self, tup):
         self.update_position(tup.lineno)
-        if tup.elts:
-            elt_count = len(tup.elts)
-        else:
-            elt_count = 0
+        elt_count = len(tup.elts) if tup.elts is not None else 0
         if tup.ctx == ast.Store:
             self.emit_op_arg(ops.UNPACK_SEQUENCE, elt_count)
-        if elt_count:
-            self.visit_sequence(tup.elts)
+        self.visit_sequence(tup.elts)
         if tup.ctx == ast.Load:
             self.emit_op_arg(ops.BUILD_TUPLE, elt_count)
 
     def visit_List(self, l):
         self.update_position(l.lineno)
-        if l.elts:
-            elt_count = len(l.elts)
-        else:
-            elt_count = 0
+        elt_count = len(l.elts) if l.elts is not None else 0
         if l.ctx == ast.Store:
             self.emit_op_arg(ops.UNPACK_SEQUENCE, elt_count)
-        if elt_count:
-            self.visit_sequence(l.elts)
+        self.visit_sequence(l.elts)
         if l.ctx == ast.Load:
             self.emit_op_arg(ops.BUILD_LIST, elt_count)
 
@@ -944,11 +920,9 @@
         if self._optimize_method_call(call):
             return
         call.func.walkabout(self)
-        arg = 0
+        arg = len(call.args) if call.args is not None else 0
         call_type = 0
-        if call.args:
-            arg = len(call.args)
-            self.visit_sequence(call.args)
+        self.visit_sequence(call.args)
         if call.keywords:
             self.visit_sequence(call.keywords)
             arg |= len(call.keywords) << 8
@@ -984,16 +958,10 @@
         assert isinstance(attr_lookup, ast.Attribute)
         attr_lookup.value.walkabout(self)
         self.emit_op_name(ops.LOOKUP_METHOD, self.names, attr_lookup.attr)
-        if call.args:
-            self.visit_sequence(call.args)
-            arg_count = len(call.args)
-        else:
-            arg_count = 0
-        if call.keywords:
-            self.visit_sequence(call.keywords)
-            kwarg_count = len(call.keywords)
-        else:
-            kwarg_count = 0
+        self.visit_sequence(call.args)
+        arg_count = len(call.args) if call.args is not None else 0
+        self.visit_sequence(call.keywords)
+        kwarg_count = len(call.keywords) if call.keywords is not None else 0
         self.emit_op_arg(ops.CALL_METHOD, (kwarg_count << 8) | arg_count)
         return True
 
@@ -1251,7 +1219,10 @@
     def _compile(self, func):
         assert isinstance(func, ast.FunctionDef)
         # If there's a docstring, store it as the first constant.
-        doc_expr = self.possible_docstring(func.body[0])
+        if func.body:
+            doc_expr = self.possible_docstring(func.body[0])
+        else:
+            doc_expr = None
         if doc_expr is not None:
             self.add_const(doc_expr.s)
             start = 1
@@ -1263,8 +1234,9 @@
         if args.args:
             self._handle_nested_args(args.args)
             self.argcount = len(args.args)
-        for i in range(start, len(func.body)):
-            func.body[i].walkabout(self)
+        if func.body:
+            for i in range(start, len(func.body)):
+                func.body[i].walkabout(self)
 
 
 class LambdaCodeGenerator(AbstractFunctionCodeGenerator):
diff --git a/pypy/interpreter/astcompiler/misc.py b/pypy/interpreter/astcompiler/misc.py
--- a/pypy/interpreter/astcompiler/misc.py
+++ b/pypy/interpreter/astcompiler/misc.py
@@ -27,9 +27,10 @@
     _emit_syntax_warning(space, w_msg, w_filename, w_lineno, w_offset)
 
 
-def parse_future(tree):
+def parse_future(tree, feature_flags):
     future_lineno = 0
     future_column = 0
+    flags = 0
     have_docstring = False
     body = None
     if isinstance(tree, ast.Module):
@@ -37,7 +38,7 @@
     elif isinstance(tree, ast.Interactive):
         body = tree.body
     if body is None:
-        return 0, 0
+        return 0, 0, 0
     for stmt in body:
         if isinstance(stmt, ast.Expr) and isinstance(stmt.value, ast.Str):
             if have_docstring:
@@ -48,11 +49,16 @@
             if stmt.module == "__future__":
                 future_lineno = stmt.lineno
                 future_column = stmt.col_offset
+                for alias in stmt.names:
+                    assert isinstance(alias, ast.alias)
+                    # If this is an invalid flag, it will be caught later in
+                    # codegen.py.
+                    flags |= feature_flags.get(alias.name, 0)
             else:
                 break
         else:
             break
-    return future_lineno, future_column
+    return flags, future_lineno, future_column
 
 
 class ForbiddenNameAssignment(Exception):
diff --git a/pypy/interpreter/astcompiler/symtable.py b/pypy/interpreter/astcompiler/symtable.py
--- a/pypy/interpreter/astcompiler/symtable.py
+++ b/pypy/interpreter/astcompiler/symtable.py
@@ -356,10 +356,8 @@
         # Function defaults and decorators happen in the outer scope.
         args = func.args
         assert isinstance(args, ast.arguments)
-        if args.defaults:
-            self.visit_sequence(args.defaults)
-        if func.decorator_list:
-            self.visit_sequence(func.decorator_list)
+        self.visit_sequence(args.defaults)
+        self.visit_sequence(func.decorator_list)
         new_scope = FunctionScope(func.name, func.lineno, func.col_offset)
         self.push_scope(new_scope, func)
         func.args.walkabout(self)
@@ -372,10 +370,8 @@
 
     def visit_ClassDef(self, clsdef):
         self.note_symbol(clsdef.name, SYM_ASSIGNED)
-        if clsdef.bases:
-            self.visit_sequence(clsdef.bases)
-        if clsdef.decorator_list:
-            self.visit_sequence(clsdef.decorator_list)
+        self.visit_sequence(clsdef.bases)
+        self.visit_sequence(clsdef.decorator_list)
         self.push_scope(ClassScope(clsdef), clsdef)
         self.visit_sequence(clsdef.body)
         self.pop_scope()
@@ -431,8 +427,7 @@
     def visit_Lambda(self, lamb):
         args = lamb.args
         assert isinstance(args, ast.arguments)
-        if args.defaults:
-            self.visit_sequence(args.defaults)
+        self.visit_sequence(args.defaults)
         new_scope = FunctionScope("lambda", lamb.lineno, lamb.col_offset)
         self.push_scope(new_scope, lamb)
         lamb.args.walkabout(self)
@@ -447,8 +442,7 @@
         self.push_scope(new_scope, node)
         self.implicit_arg(0)
         outer.target.walkabout(self)
-        if outer.ifs:
-            self.visit_sequence(outer.ifs)
+        self.visit_sequence(outer.ifs)
         self.visit_sequence(comps[1:])
         for item in list(consider):
             item.walkabout(self)
diff --git a/pypy/interpreter/astcompiler/tools/asdl_py.py b/pypy/interpreter/astcompiler/tools/asdl_py.py
--- a/pypy/interpreter/astcompiler/tools/asdl_py.py
+++ b/pypy/interpreter/astcompiler/tools/asdl_py.py
@@ -221,8 +221,9 @@
         self.emit("class ASTVisitor(object):")
         self.emit("")
         self.emit("def visit_sequence(self, seq):", 1)
-        self.emit("for node in seq:", 2)
-        self.emit("node.walkabout(self)", 3)
+        self.emit("if seq is not None:", 2)
+        self.emit("for node in seq:", 3)
+        self.emit("node.walkabout(self)", 4)
         self.emit("")
         self.emit("def default_visitor(self, node):", 1)
         self.emit("raise NodeVisitorNotImplemented", 2)
@@ -280,15 +281,13 @@
     def visitField(self, field):
         if field.type.value not in asdl.builtin_types and \
                 field.type.value not in self.data.simple_types:
-            if field.seq or field.opt:
+            level = 2
+            template = "node.%s.walkabout(self)"
+            if field.seq:
+                template = "self.visit_sequence(node.%s)"
+            elif field.opt:
                 self.emit("if node.%s:" % (field.name,), 2)
                 level = 3
-            else:
-                level = 2
-            if field.seq:
-                template = "self.visit_sequence(node.%s)"
-            else:
-                template = "node.%s.walkabout(self)"
             self.emit(template % (field.name,), level)
             return True
         return False
@@ -446,6 +445,7 @@
         if field.seq:
             self.emit("w_self.w_%s = w_new_value" % (field.name,), 1)
         else:
+            save_original_object = False
             self.emit("try:", 1)
             if field.type.value not in asdl.builtin_types:
                 # These are always other AST nodes.
@@ -454,9 +454,7 @@
                                   (field.type,), 2)
                     self.emit("w_self.%s = obj.to_simple_int(space)" %
                               (field.name,), 2)
-                    self.emit("# need to save the original object too", 2)
-                    self.emit("w_self.setdictvalue(space, '%s', w_new_value)"
-                              % (field.name,), 2)
+                    save_original_object = True
                 else:
                     config = (field.name, field.type, repr(field.opt))
                     self.emit("w_self.%s = space.interp_w(%s, w_new_value, %s)" %
@@ -480,6 +478,12 @@
             self.emit("    w_self.setdictvalue(space, '%s', w_new_value)"
                       % (field.name,), 1)
             self.emit("    return", 1)
+            if save_original_object:
+                self.emit("# need to save the original object too", 1)
+                self.emit("w_self.setdictvalue(space, '%s', w_new_value)"
+                          % (field.name,), 1)
+            else:
+                self.emit("w_self.deldictvalue(space, '%s')" %(field.name,), 1)
         self.emit("w_self.initialization_state |= %s" % (flag,), 1)
         self.emit("")
 
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -44,11 +44,11 @@
             return True
         return False
 
-    def deldictvalue(self, space, w_name):
+    def deldictvalue(self, space, attr):
         w_dict = self.getdict(space)
         if w_dict is not None:
             try:
-                space.delitem(w_dict, w_name)
+                space.delitem(w_dict, space.wrap(attr))
                 return True
             except OperationError, ex:
                 if not ex.match(space, space.w_KeyError):
@@ -130,6 +130,9 @@
         raise operationerrfmt(space.w_TypeError,
             "cannot create weak reference to '%s' object", typename)
 
+    def delweakref(self):
+        pass
+
     def clear_all_weakrefs(self):
         """Call this at the beginning of interp-level __del__() methods
         in subclasses.  It ensures that weakrefs (if any) are cleared
@@ -143,29 +146,28 @@
             # app-level, e.g. a user-defined __del__(), and this code
             # tries to use weakrefs again, it won't reuse the broken
             # (already-cleared) weakrefs from this lifeline.
-            self.setweakref(lifeline.space, None)
+            self.delweakref()
             lifeline.clear_all_weakrefs()
 
-    __already_enqueued_for_destruction = False
+    __already_enqueued_for_destruction = ()
 
-    def _enqueue_for_destruction(self, space, call_user_del=True):
+    def enqueue_for_destruction(self, space, callback, descrname):
         """Put the object in the destructor queue of the space.
-        At a later, safe point in time, UserDelAction will use
-        space.userdel() to call the object's app-level __del__ method.
+        At a later, safe point in time, UserDelAction will call
+        callback(self).  If that raises OperationError, prints it
+        to stderr with the descrname string.
+
+        Note that 'callback' will usually need to start with:
+            assert isinstance(self, W_SpecificClass)
         """
         # this function always resurect the object, so when
         # running on top of CPython we must manually ensure that
         # we enqueue it only once
         if not we_are_translated():
-            if self.__already_enqueued_for_destruction:
+            if callback in self.__already_enqueued_for_destruction:
                 return
-            self.__already_enqueued_for_destruction = True
-        self.clear_all_weakrefs()
-        if call_user_del:
-            space.user_del_action.register_dying_object(self)
-
-    def _call_builtin_destructor(self):
-        pass     # method overridden in typedef.py
+            self.__already_enqueued_for_destruction += (callback,)
+        space.user_del_action.register_callback(self, callback, descrname)
 
     # hooks that the mapdict implementations needs:
     def _get_mapdict_map(self):
@@ -237,7 +239,7 @@
 
 class ObjSpace(object):
     """Base class for the interpreter-level implementations of object spaces.
-    http://codespeak.net/pypy/dist/pypy/doc/objspace.html"""
+    http://pypy.readthedocs.org/en/latest/objspace.html"""
 
     full_exceptions = True  # full support for exceptions (normalization & more)
 
@@ -925,6 +927,9 @@
                 return self.w_True
         return self.w_False
 
+    def issequence_w(self, w_obj):
+        return (self.findattr(w_obj, self.wrap("__getitem__")) is not None)
+
     def isinstance_w(self, w_obj, w_type):
         return self.is_true(self.isinstance(w_obj, w_type))
 
@@ -1279,6 +1284,17 @@
                                  self.wrap("expected a 32-bit integer"))
         return value
 
+    def truncatedint(self, w_obj):
+        # Like space.gateway_int_w(), but return the integer truncated
+        # instead of raising OverflowError.  For obscure cases only.
+        try:
+            return self.int_w(w_obj)
+        except OperationError, e:
+            if not e.match(self, self.w_OverflowError):
+                raise
+            from pypy.rlib.rarithmetic import intmask
+            return intmask(self.bigint_w(w_obj).uintmask())
+
     def c_filedescriptor_w(self, w_fd):
         # This is only used sometimes in CPython, e.g. for os.fsync() but
         # not os.close().  It's likely designed for 'select'.  It's irregular
diff --git a/pypy/interpreter/error.py b/pypy/interpreter/error.py
--- a/pypy/interpreter/error.py
+++ b/pypy/interpreter/error.py
@@ -189,7 +189,7 @@
             if space.is_w(w_value, space.w_None):
                 # raise Type: we assume we have to instantiate Type
                 w_value = space.call_function(w_type)
-                w_type = space.exception_getclass(w_value)
+                w_type = self._exception_getclass(space, w_value)
             else:
                 w_valuetype = space.exception_getclass(w_value)
                 if space.exception_issubclass_w(w_valuetype, w_type):
@@ -204,18 +204,12 @@
                     else:
                         # raise Type, X: assume X is the constructor argument
                         w_value = space.call_function(w_type, w_value)
-                    w_type = space.exception_getclass(w_value)
+                    w_type = self._exception_getclass(space, w_value)
 
         else:
             # the only case left here is (inst, None), from a 'raise inst'.
             w_inst = w_type
-            w_instclass = space.exception_getclass(w_inst)
-            if not space.exception_is_valid_class_w(w_instclass):
-                instclassname = w_instclass.getname(space)
-                msg = ("exceptions must be old-style classes or derived "
-                       "from BaseException, not %s")
-                raise operationerrfmt(space.w_TypeError, msg, instclassname)
-
+            w_instclass = self._exception_getclass(space, w_inst)
             if not space.is_w(w_value, space.w_None):
                 raise OperationError(space.w_TypeError,
                                      space.wrap("instance exception may not "
@@ -226,6 +220,15 @@
         self.w_type   = w_type
         self._w_value = w_value
 
+    def _exception_getclass(self, space, w_inst):
+        w_type = space.exception_getclass(w_inst)
+        if not space.exception_is_valid_class_w(w_type):
+            typename = w_type.getname(space)
+            msg = ("exceptions must be old-style classes or derived "
+                   "from BaseException, not %s")
+            raise operationerrfmt(space.w_TypeError, msg, typename)
+        return w_type
+
     def write_unraisable(self, space, where, w_object=None):
         if w_object is None:
             objrepr = ''
diff --git a/pypy/interpreter/executioncontext.py b/pypy/interpreter/executioncontext.py
--- a/pypy/interpreter/executioncontext.py
+++ b/pypy/interpreter/executioncontext.py
@@ -484,44 +484,31 @@
 
     def __init__(self, space):
         AsyncAction.__init__(self, space)
-        self.dying_objects_w = []
-        self.weakrefs_w = []
+        self.dying_objects = []
         self.finalizers_lock_count = 0
 
-    def register_dying_object(self, w_obj):
-        self.dying_objects_w.append(w_obj)
-        self.fire()
-
-    def register_weakref_callback(self, w_ref):
-        self.weakrefs_w.append(w_ref)
+    def register_callback(self, w_obj, callback, descrname):
+        self.dying_objects.append((w_obj, callback, descrname))
         self.fire()
 
     def perform(self, executioncontext, frame):
         if self.finalizers_lock_count > 0:
             return
-        # Each call to perform() first grabs the self.dying_objects_w
+        # Each call to perform() first grabs the self.dying_objects
         # and replaces it with an empty list.  We do this to try to
         # avoid too deep recursions of the kind of __del__ being called
         # while in the middle of another __del__ call.
-        pending_w = self.dying_objects_w
-        self.dying_objects_w = []
+        pending = self.dying_objects
+        self.dying_objects = []
         space = self.space
-        for i in range(len(pending_w)):
-            w_obj = pending_w[i]
-            pending_w[i] = None
+        for i in range(len(pending)):
+            w_obj, callback, descrname = pending[i]
+            pending[i] = (None, None, None)
             try:
-                space.userdel(w_obj)
+                callback(w_obj)
             except OperationError, e:
-                e.write_unraisable(space, 'method __del__ of ', w_obj)
+                e.write_unraisable(space, descrname, w_obj)
                 e.clear(space)   # break up reference cycles
-            # finally, this calls the interp-level destructor for the
-            # cases where there is both an app-level and a built-in __del__.
-            w_obj._call_builtin_destructor()
-        pending_w = self.weakrefs_w
-        self.weakrefs_w = []
-        for i in range(len(pending_w)):
-            w_ref = pending_w[i]
-            w_ref.activate_callback()
 
 class FrameTraceAction(AsyncAction):
     """An action that calls the local trace functions (w_f_trace)."""
diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -31,7 +31,8 @@
     _immutable_fields_ = ['code?',
                           'w_func_globals?',
                           'closure?',
-                          'defs_w?[*]']
+                          'defs_w?[*]',
+                          'name?']
 
     def __init__(self, space, code, w_globals=None, defs_w=[], closure=None,
                  forcename=None):
diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -140,6 +140,9 @@
     def visit_c_nonnegint(self, el, app_sig):
         self.checked_space_method(el, app_sig)
 
+    def visit_truncatedint(self, el, app_sig):
+        self.checked_space_method(el, app_sig)
+
     def visit__Wrappable(self, el, app_sig):
         name = el.__name__
         argname = self.orig_arg()
@@ -257,6 +260,9 @@
     def visit_c_nonnegint(self, typ):
         self.run_args.append("space.c_nonnegint_w(%s)" % (self.scopenext(),))
 
+    def visit_truncatedint(self, typ):
+        self.run_args.append("space.truncatedint(%s)" % (self.scopenext(),))
+
     def _make_unwrap_activation_class(self, unwrap_spec, cache={}):
         try:
             key = tuple(unwrap_spec)
@@ -387,6 +393,9 @@
     def visit_c_nonnegint(self, typ):
         self.unwrap.append("space.c_nonnegint_w(%s)" % (self.nextarg(),))
 
+    def visit_truncatedint(self, typ):
+        self.unwrap.append("space.truncatedint(%s)" % (self.nextarg(),))
+
     def make_fastfunc(unwrap_spec, func):
         unwrap_info = UnwrapSpec_FastFunc_Unwrap()
         unwrap_info.apply_over(unwrap_spec)
@@ -396,11 +405,14 @@
             fastfunc = func
         else:
             # try to avoid excessive bloat
-            if func.__module__ == 'pypy.interpreter.astcompiler.ast':
+            mod = func.__module__
+            if mod is None:
+                mod = ""
+            if mod == 'pypy.interpreter.astcompiler.ast':
                 raise FastFuncNotSupported
-            if (not func.__module__.startswith('pypy.module.__builtin__') and
-                not func.__module__.startswith('pypy.module.sys') and
-                not func.__module__.startswith('pypy.module.math')):
+            if (not mod.startswith('pypy.module.__builtin__') and
+                not mod.startswith('pypy.module.sys') and
+                not mod.startswith('pypy.module.math')):
                 if not func.__name__.startswith('descr'):
                     raise FastFuncNotSupported
             d = {}
diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -114,6 +114,7 @@
  
     def descr_close(self):
         """x.close(arg) -> raise GeneratorExit inside generator."""
+        assert isinstance(self, GeneratorIterator)
         space = self.space
         try:
             w_retval = self.throw(space.w_GeneratorExit, space.w_None,
@@ -141,22 +142,16 @@
         code_name = self.pycode.co_name
         return space.wrap(code_name)
 
-    def descr__del__(self):        
-        """
-        applevel __del__, which is called at a safe point after the
-        interp-level __del__ enqueued the object for destruction
-        """
-        self.descr_close()
-
     def __del__(self):
         # Only bother enqueuing self to raise an exception if the frame is
         # still not finished and finally or except blocks are present.
-        must_call_close = False
+        self.clear_all_weakrefs()
         if self.frame is not None:
             block = self.frame.lastblock
             while block is not None:
                 if not isinstance(block, LoopBlock):
-                    must_call_close = True
+                    self.enqueue_for_destruction(self.space,
+                                                 GeneratorIterator.descr_close,
+                                                 "interrupting generator of ")
                     break
                 block = block.previous
-        self._enqueue_for_destruction(self.space, must_call_close)
diff --git a/pypy/interpreter/module.py b/pypy/interpreter/module.py
--- a/pypy/interpreter/module.py
+++ b/pypy/interpreter/module.py
@@ -9,6 +9,8 @@
 class Module(Wrappable):
     """A module."""
 
+    _immutable_fields_ = ["w_dict?"]
+
     _frozen = False
 
     def __init__(self, space, w_name, w_dict=None, add_package=True):
diff --git a/pypy/interpreter/pycompiler.py b/pypy/interpreter/pycompiler.py
--- a/pypy/interpreter/pycompiler.py
+++ b/pypy/interpreter/pycompiler.py
@@ -119,7 +119,10 @@
             raise OperationError(self.space.w_TypeError, self.space.wrap(
                 "invalid node type"))
 
-        future_pos = misc.parse_future(node)
+        fut = misc.parse_future(node, self.future_flags.compiler_features)
+        f_flags, f_lineno, f_col = fut
+        future_pos = f_lineno, f_col
+        flags |= f_flags
         info = pyparse.CompileInfo(filename, mode, flags, future_pos)
         return self._compile_ast(node, info)
 
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -905,16 +905,15 @@
 
     def SETUP_WITH(self, offsettoend, next_instr):
         w_manager = self.peekvalue()
+        w_enter = self.space.lookup(w_manager, "__enter__")
         w_descr = self.space.lookup(w_manager, "__exit__")
-        if w_descr is None:
-            raise OperationError(self.space.w_AttributeError,
-                                 self.space.wrap("__exit__"))
+        if w_enter is None or w_descr is None:
+            typename = self.space.type(w_manager).getname(self.space)
+            raise operationerrfmt(self.space.w_AttributeError,
+                "'%s' object is not a context manager"
+                " (no __enter__/__exit__ method)", typename)
         w_exit = self.space.get(w_descr, w_manager)
         self.settopvalue(w_exit)
-        w_enter = self.space.lookup(w_manager, "__enter__")
-        if w_enter is None:
-            raise OperationError(self.space.w_AttributeError,
-                                 self.space.wrap("__enter__"))
         w_result = self.space.get_and_call_function(w_enter, w_manager)
         block = WithBlock(self, next_instr + offsettoend)
         self.append_block(block)
diff --git a/pypy/interpreter/test/test_raise.py b/pypy/interpreter/test/test_raise.py
--- a/pypy/interpreter/test/test_raise.py
+++ b/pypy/interpreter/test/test_raise.py
@@ -274,3 +274,9 @@
             pass
         except A:
             pass
+
+    def test_new_returns_bad_instance(self):
+        class MyException(Exception):
+            def __new__(cls, *args):
+                return object()
+        raises(TypeError, "raise MyException")
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
@@ -1,3 +1,4 @@
+import gc
 from pypy.interpreter import typedef
 from pypy.tool.udir import udir
 from pypy.interpreter.baseobjspace import Wrappable
@@ -180,6 +181,85 @@
             assert err.value.message == "'some_type' objects are unhashable"
             """)
 
+    def test_destructor(self):
+        space = self.space
+        class W_Level1(Wrappable):
+            def __init__(self, space1):
+                assert space1 is space
+            def __del__(self):
+                space.call_method(w_seen, 'append', space.wrap(1))
+        class W_Level2(Wrappable):
+            def __init__(self, space1):
+                assert space1 is space
+            def __del__(self):
+                self.enqueue_for_destruction(space, W_Level2.destructormeth,
+                                             'FOO ')
+            def destructormeth(self):
+                space.call_method(w_seen, 'append', space.wrap(2))
+        W_Level1.typedef = typedef.TypeDef(
+            'level1',
+            __new__ = typedef.generic_new_descr(W_Level1))
+        W_Level2.typedef = typedef.TypeDef(
+            'level2',
+            __new__ = typedef.generic_new_descr(W_Level2))
+        #
+        w_seen = space.newlist([])
+        W_Level1(space)
+        gc.collect(); gc.collect()
+        assert space.unwrap(w_seen) == [1]
+        #
+        w_seen = space.newlist([])
+        W_Level2(space)
+        gc.collect(); gc.collect()
+        assert space.str_w(space.repr(w_seen)) == "[]"  # not called yet
+        ec = space.getexecutioncontext()
+        self.space.user_del_action.perform(ec, None)
+        assert space.unwrap(w_seen) == [2]
+        #
+        w_seen = space.newlist([])
+        self.space.appexec([self.space.gettypeobject(W_Level1.typedef)],
+        """(level1):
+            class A3(level1):
+                pass
+            A3()
+        """)
+        gc.collect(); gc.collect()
+        assert space.unwrap(w_seen) == [1]
+        #
+        w_seen = space.newlist([])
+        self.space.appexec([self.space.gettypeobject(W_Level1.typedef),
+                            w_seen],
+        """(level1, seen):
+            class A4(level1):
+                def __del__(self):
+                    seen.append(4)
+            A4()
+        """)
+        gc.collect(); gc.collect()
+        assert space.unwrap(w_seen) == [4, 1]
+        #
+        w_seen = space.newlist([])
+        self.space.appexec([self.space.gettypeobject(W_Level2.typedef)],
+        """(level2):
+            class A5(level2):
+                pass
+            A5()
+        """)
+        gc.collect(); gc.collect()
+        assert space.unwrap(w_seen) == [2]
+        #
+        w_seen = space.newlist([])
+        self.space.appexec([self.space.gettypeobject(W_Level2.typedef),
+                            w_seen],
+        """(level2, seen):
+            class A6(level2):
+                def __del__(self):
+                    seen.append(6)
+            A6()
+        """)
+        gc.collect(); gc.collect()
+        assert space.unwrap(w_seen) == [6, 2]
+
 
 class AppTestTypeDef:
 
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -23,7 +23,7 @@
             self.hasdict     |= __base.hasdict
             self.weakrefable |= __base.weakrefable
         self.rawdict = {}
-        self.acceptable_as_base_class = True
+        self.acceptable_as_base_class = '__new__' in rawdict
         self.applevel_subclasses_base = None
         # xxx used by faking
         self.fakedcpytype = None
@@ -228,21 +228,26 @@
                 return self._lifeline_
             def setweakref(self, space, weakreflifeline):
                 self._lifeline_ = weakreflifeline
+            def delweakref(self):
+                self._lifeline_ = None
         add(Proto)
 
     if "del" in features:
+        parent_destructor = getattr(supercls, '__del__', None)
+        def call_parent_del(self):
+            assert isinstance(self, subcls)
+            parent_destructor(self)
+        def call_applevel_del(self):
+            assert isinstance(self, subcls)
+            self.space.userdel(self)
         class Proto(object):
             def __del__(self):
-                self._enqueue_for_destruction(self.space)
-        # if the base class needs its own interp-level __del__,
-        # we override the _call_builtin_destructor() method to invoke it
-        # after the app-level destructor.
-        parent_destructor = getattr(supercls, '__del__', None)
-        if parent_destructor is not None:
-            def _call_builtin_destructor(self):
-                parent_destructor(self)
-            Proto._call_builtin_destructor = _call_builtin_destructor
-
+                self.clear_all_weakrefs()
+                self.enqueue_for_destruction(self.space, call_applevel_del,
+                                             'method __del__ of ')
+                if parent_destructor is not None:
+                    self.enqueue_for_destruction(self.space, call_parent_del,
+                                                 'internal destructor of ')
         add(Proto)
 
     if "slots" in features:
@@ -630,9 +635,12 @@
         return self._lifeline_
     def setweakref(self, space, weakreflifeline):
         self._lifeline_ = weakreflifeline
+    def delweakref(self):
+        self._lifeline_ = None
     cls._lifeline_ = None
     cls.getweakref = getweakref
     cls.setweakref = setweakref
+    cls.delweakref = delweakref
     return weakref_descr
 
 
@@ -858,8 +866,6 @@
                             descrmismatch='close'),
     __iter__   = interp2app(GeneratorIterator.descr__iter__,
                             descrmismatch='__iter__'),
-    __del__    = interp2app(GeneratorIterator.descr__del__,
-                            descrmismatch='__del__'),
     gi_running = interp_attrproperty('running', cls=GeneratorIterator),
     gi_frame   = GetSetProperty(GeneratorIterator.descr_gi_frame),
     gi_code    = GetSetProperty(GeneratorIterator.descr_gi_code),
diff --git a/pypy/jit/backend/llsupport/gc.py b/pypy/jit/backend/llsupport/gc.py
--- a/pypy/jit/backend/llsupport/gc.py
+++ b/pypy/jit/backend/llsupport/gc.py
@@ -453,21 +453,33 @@
 
 class WriteBarrierDescr(AbstractDescr):
     def __init__(self, gc_ll_descr):
+        GCClass = gc_ll_descr.GCClass
         self.llop1 = gc_ll_descr.llop1
         self.WB_FUNCPTR = gc_ll_descr.WB_FUNCPTR
         self.WB_ARRAY_FUNCPTR = gc_ll_descr.WB_ARRAY_FUNCPTR
-        self.fielddescr_tid = get_field_descr(gc_ll_descr,
-                                              gc_ll_descr.GCClass.HDR, 'tid')
-        self.jit_wb_if_flag = gc_ll_descr.GCClass.JIT_WB_IF_FLAG
-        # if convenient for the backend, we also compute the info about
+        self.fielddescr_tid = get_field_descr(gc_ll_descr, GCClass.HDR, 'tid')
+        #
+        self.jit_wb_if_flag = GCClass.JIT_WB_IF_FLAG
+        self.jit_wb_if_flag_byteofs, self.jit_wb_if_flag_singlebyte = (
+            self.extract_flag_byte(self.jit_wb_if_flag))
+        #
+        if hasattr(GCClass, 'JIT_WB_CARDS_SET'):
+            self.jit_wb_cards_set = GCClass.JIT_WB_CARDS_SET
+            self.jit_wb_card_page_shift = GCClass.JIT_WB_CARD_PAGE_SHIFT
+            self.jit_wb_cards_set_byteofs, self.jit_wb_cards_set_singlebyte = (
+                self.extract_flag_byte(self.jit_wb_cards_set))
+        else:
+            self.jit_wb_cards_set = 0
+
+    def extract_flag_byte(self, flag_word):
+        # if convenient for the backend, we compute the info about
         # the flag as (byte-offset, single-byte-flag).
         import struct
-        value = struct.pack("l", self.jit_wb_if_flag)
+        value = struct.pack("l", flag_word)
         assert value.count('\x00') == len(value) - 1    # only one byte is != 0
         i = 0
         while value[i] == '\x00': i += 1
-        self.jit_wb_if_flag_byteofs = i
-        self.jit_wb_if_flag_singlebyte = struct.unpack('b', value[i])[0]
+        return (i, struct.unpack('b', value[i])[0])
 
     def get_write_barrier_fn(self, cpu):
         llop1 = self.llop1
diff --git a/pypy/jit/backend/llvm/llvm_rffi.py b/pypy/jit/backend/llvm/llvm_rffi.py
--- a/pypy/jit/backend/llvm/llvm_rffi.py
+++ b/pypy/jit/backend/llvm/llvm_rffi.py
@@ -3,7 +3,7 @@
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.translator.tool.cbuild import ExternalCompilationInfo, log
 
-if sys.platform != 'linux2':
+if not sys.platform.startswith('linux'):
     py.test.skip("Linux only for now")
 
 # ____________________________________________________________
diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py
--- a/pypy/jit/backend/test/runner_test.py
+++ b/pypy/jit/backend/test/runner_test.py
@@ -1707,6 +1707,7 @@
             jit_wb_if_flag = 4096
             jit_wb_if_flag_byteofs = struct.pack("i", 4096).index('\x10')
             jit_wb_if_flag_singlebyte = 0x10
+            jit_wb_cards_set = 0
             def get_write_barrier_from_array_fn(self, cpu):
                 return funcbox.getint()
         #
@@ -1728,6 +1729,72 @@
             else:
                 assert record == []
 
+    def test_cond_call_gc_wb_array_card_marking_fast_path(self):
+        def func_void(a, b, c):
+            record.append((a, b, c))
+        record = []
+        #
+        S = lltype.Struct('S', ('tid', lltype.Signed))
+        S_WITH_CARDS = lltype.Struct('S_WITH_CARDS',
+                                     ('card0', lltype.Char),
+                                     ('card1', lltype.Char),
+                                     ('card2', lltype.Char),
+                                     ('card3', lltype.Char),
+                                     ('card4', lltype.Char),
+                                     ('card5', lltype.Char),
+                                     ('card6', lltype.Char),
+                                     ('card7', lltype.Char),
+                                     ('data',  S))
+        FUNC = self.FuncType([lltype.Ptr(S), lltype.Signed, lltype.Ptr(S)],
+                             lltype.Void)
+        func_ptr = llhelper(lltype.Ptr(FUNC), func_void)
+        funcbox = self.get_funcbox(self.cpu, func_ptr)
+        class WriteBarrierDescr(AbstractDescr):
+            jit_wb_if_flag = 4096
+            jit_wb_if_flag_byteofs = struct.pack("i", 4096).index('\x10')
+            jit_wb_if_flag_singlebyte = 0x10
+            jit_wb_cards_set = 8192
+            jit_wb_cards_set_byteofs = struct.pack("i", 8192).index('\x20')
+            jit_wb_cards_set_singlebyte = 0x20
+            jit_wb_card_page_shift = 7
+            def get_write_barrier_from_array_fn(self, cpu):
+                return funcbox.getint()
+        #
+        for BoxIndexCls in [BoxInt, ConstInt]:
+            for cond in [False, True]:
+                print
+                print '_'*79
+                print 'BoxIndexCls =', BoxIndexCls
+                print 'JIT_WB_CARDS_SET =', cond
+                print
+                value = random.randrange(-sys.maxint, sys.maxint)
+                value |= 4096
+                if cond:
+                    value |= 8192
+                else:
+                    value &= ~8192
+                s = lltype.malloc(S_WITH_CARDS, immortal=True, zero=True)
+                s.data.tid = value
+                sgcref = rffi.cast(llmemory.GCREF, s.data)
+                del record[:]
+                box_index = BoxIndexCls((9<<7) + 17)
+                self.execute_operation(rop.COND_CALL_GC_WB_ARRAY,
+                           [BoxPtr(sgcref), box_index, BoxPtr(sgcref)],
+                           'void', descr=WriteBarrierDescr())
+                if cond:
+                    assert record == []
+                    assert s.card6 == '\x02'
+                else:
+                    assert record == [(s.data, (9<<7) + 17, s.data)]
+                    assert s.card6 == '\x00'
+                assert s.card0 == '\x00'
+                assert s.card1 == '\x00'
+                assert s.card2 == '\x00'
+                assert s.card3 == '\x00'
+                assert s.card4 == '\x00'
+                assert s.card5 == '\x00'
+                assert s.card7 == '\x00'
+
     def test_force_operations_returning_void(self):
         values = []
         def maybe_force(token, flag):
diff --git a/pypy/jit/backend/x86/assembler.py b/pypy/jit/backend/x86/assembler.py
--- a/pypy/jit/backend/x86/assembler.py
+++ b/pypy/jit/backend/x86/assembler.py
@@ -416,10 +416,13 @@
         fullsize = self.mc.get_relative_pos()
         #
         rawstart = self.materialize_loop(looptoken)
-        debug_print("Loop #%d (%s) has address %x to %x" % (
+        debug_start("jit-backend-addr")
+        debug_print("Loop %d (%s) has address %x to %x (bootstrap %x)" % (
             looptoken.number, loopname,
             rawstart + self.looppos,
-            rawstart + directbootstrappos))
+            rawstart + directbootstrappos,
+            rawstart))
+        debug_stop("jit-backend-addr")
         self._patch_stackadjust(rawstart + stackadjustpos,
                                 frame_depth + param_depth)
         self.patch_pending_failure_recoveries(rawstart)
@@ -478,9 +481,10 @@
         fullsize = self.mc.get_relative_pos()
         #
         rawstart = self.materialize_loop(original_loop_token)
-
-        debug_print("Bridge out of guard %d has address %x to %x" %
+        debug_start("jit-backend-addr")
+        debug_print("bridge out of Guard %d has address %x to %x" %
                     (descr_number, rawstart, rawstart + codeendpos))
+        debug_stop("jit-backend-addr")
         self._patch_stackadjust(rawstart + stackadjustpos,
                                 frame_depth + param_depth)
         self.patch_pending_failure_recoveries(rawstart)
@@ -2242,10 +2246,12 @@
         if opnum == rop.COND_CALL_GC_WB:
             N = 2
             func = descr.get_write_barrier_fn(self.cpu)
+            card_marking = False
         elif opnum == rop.COND_CALL_GC_WB_ARRAY:
             N = 3
             func = descr.get_write_barrier_from_array_fn(self.cpu)
             assert func != 0
+            card_marking = descr.jit_wb_cards_set != 0
         else:
             raise AssertionError(opnum)
         #
@@ -2254,6 +2260,18 @@
                       imm(descr.jit_wb_if_flag_singlebyte))
         self.mc.J_il8(rx86.Conditions['Z'], 0) # patched later
         jz_location = self.mc.get_relative_pos()
+
+        # for cond_call_gc_wb_array, also add another fast path:
+        # if GCFLAG_CARDS_SET, then we can just set one bit and be done
+        if card_marking:
+            self.mc.TEST8(addr_add_const(loc_base,
+                                         descr.jit_wb_cards_set_byteofs),
+                          imm(descr.jit_wb_cards_set_singlebyte))
+            self.mc.J_il8(rx86.Conditions['NZ'], 0) # patched later
+            jnz_location = self.mc.get_relative_pos()
+        else:
+            jnz_location = 0
+
         # the following is supposed to be the slow path, so whenever possible
         # we choose the most compact encoding over the most efficient one.
         if IS_X86_32:
@@ -2293,6 +2311,43 @@
             loc = arglocs[i]
             assert isinstance(loc, RegLoc)
             self.mc.POP_r(loc.value)
+
+        # if GCFLAG_CARDS_SET, then we can do the whole thing that would
+        # be done in the CALL above with just four instructions, so here
+        # is an inline copy of them
+        if card_marking:
+            self.mc.JMP_l8(0) # jump to the exit, patched later
+            jmp_location = self.mc.get_relative_pos()
+            # patch the JNZ above
+            offset = self.mc.get_relative_pos() - jnz_location
+            assert 0 < offset <= 127
+            self.mc.overwrite(jnz_location-1, chr(offset))
+            #
+            loc_index = arglocs[1]
+            if isinstance(loc_index, RegLoc):
+                # choose a scratch register
+                tmp1 = loc_index
+                self.mc.PUSH_r(tmp1.value)
+                # SHR tmp, card_page_shift
+                self.mc.SHR_ri(tmp1.value, descr.jit_wb_card_page_shift)
+                # XOR tmp, -8
+                self.mc.XOR_ri(tmp1.value, -8)
+                # BTS [loc_base], tmp
+                self.mc.BTS(addr_add_const(loc_base, 0), tmp1)
+                # done
+                self.mc.POP_r(tmp1.value)
+            elif isinstance(loc_index, ImmedLoc):
+                byte_index = loc_index.value >> descr.jit_wb_card_page_shift
+                byte_ofs = ~(byte_index >> 3)
+                byte_val = 1 << (byte_index & 7)
+                self.mc.OR8(addr_add_const(loc_base, byte_ofs), imm(byte_val))
+            else:
+                raise AssertionError("index is neither RegLoc nor ImmedLoc")
+            # patch the JMP above
+            offset = self.mc.get_relative_pos() - jmp_location
+            assert 0 < offset <= 127
+            self.mc.overwrite(jmp_location-1, chr(offset))
+        #
         # patch the JZ above
         offset = self.mc.get_relative_pos() - jz_location
         assert 0 < offset <= 127
diff --git a/pypy/jit/backend/x86/regloc.py b/pypy/jit/backend/x86/regloc.py
--- a/pypy/jit/backend/x86/regloc.py
+++ b/pypy/jit/backend/x86/regloc.py
@@ -476,6 +476,7 @@
 
     AND = _binaryop('AND')
     OR  = _binaryop('OR')
+    OR8 = _binaryop('OR8')
     XOR = _binaryop('XOR')
     NOT = _unaryop('NOT')
     SHL = _binaryop('SHL')
@@ -483,6 +484,7 @@
     SAR = _binaryop('SAR')
     TEST = _binaryop('TEST')
     TEST8 = _binaryop('TEST8')
+    BTS = _binaryop('BTS')
 
     ADD = _binaryop('ADD')
     SUB = _binaryop('SUB')
diff --git a/pypy/jit/backend/x86/rx86.py b/pypy/jit/backend/x86/rx86.py
--- a/pypy/jit/backend/x86/rx86.py
+++ b/pypy/jit/backend/x86/rx86.py
@@ -464,7 +464,7 @@
 
     # ------------------------------ MOV ------------------------------
 
-    MOV_ri = insn(rex_w, register(1), '\xB8', immediate(2, 'q'))
+    MOV_ri = insn(register(1), '\xB8', immediate(2))
     MOV8_ri = insn(rex_fw, byte_register(1), '\xB0', immediate(2, 'b'))
 
     # ------------------------------ Arithmetic ------------------------------
@@ -496,6 +496,10 @@
     AND8_rr = insn(rex_fw, '\x20', byte_register(1), byte_register(2,8), '\xC0')
 
     OR8_rr = insn(rex_fw, '\x08', byte_register(1), byte_register(2,8), '\xC0')
+    OR8_mi = insn(rex_fw, '\x80', orbyte(1<<3), mem_reg_plus_const(1),
+                  immediate(2, 'b'))
+    OR8_ji = insn(rex_fw, '\x80', orbyte(1<<3), abs_, immediate(1),
+                  immediate(2, 'b'))
 
     NEG_r = insn(rex_w, '\xF7', register(1), '\xD8')
 
@@ -565,6 +569,9 @@
     TEST8_ji = insn(rex_nw, '\xF6', orbyte(0<<3), abs_, immediate(1), immediate(2, 'b'))
     TEST_rr = insn(rex_w, '\x85', register(2,8), register(1), '\xC0')
 
+    BTS_mr = insn(rex_w, '\x0F\xAB', register(2,8), mem_reg_plus_const(1))
+    BTS_jr = insn(rex_w, '\x0F\xAB', register(2,8), abs_, immediate(1))
+
     # x87 instructions
     FSTP_b = insn('\xDD', orbyte(3<<3), stack_bp(1))
 
@@ -632,16 +639,20 @@
 
     CQO = insn(rex_w, '\x99')
 
-    # MOV_ri from the parent class is not wrong, but here is a better encoding
-    # for the common case where the immediate fits in 32 bits
+    # Three different encodings... following what gcc does.  From the
+    # shortest encoding to the longest one.
+    MOV_riu32 = insn(rex_nw, register(1), '\xB8', immediate(2, 'i'))
     MOV_ri32 = insn(rex_w, '\xC7', register(1), '\xC0', immediate(2, 'i'))
-    MOV_ri64 = AbstractX86CodeBuilder.MOV_ri
+    MOV_ri64 = insn(rex_w, register(1), '\xB8', immediate(2, 'q'))
 
     def MOV_ri(self, reg, immed):
-        if fits_in_32bits(immed):
+        if 0 <= immed <= 4294967295:
+            immed = intmask(rffi.cast(rffi.INT, immed))
+            self.MOV_riu32(reg, immed)
+        elif fits_in_32bits(immed):    # for negative values that fit in 32 bit
             self.MOV_ri32(reg, immed)
         else:
-            AbstractX86CodeBuilder.MOV_ri(self, reg, immed)
+            self.MOV_ri64(reg, immed)
 
 def define_modrm_modes(insnname_template, before_modrm, after_modrm=[], regtype='GPR'):
     def add_insn(code, *modrm):
diff --git a/pypy/jit/backend/x86/test/test_regloc.py b/pypy/jit/backend/x86/test/test_regloc.py
--- a/pypy/jit/backend/x86/test/test_regloc.py
+++ b/pypy/jit/backend/x86/test/test_regloc.py
@@ -24,9 +24,14 @@
     assert_encodes_as(cb64, "MOV16", (r8, ebx), '\x66\x41\x89\xD8')  # 11 011 000
     assert_encodes_as(cb64, "MOV16", (ebx, r8), '\x66\x44\x89\xC3')  # 11 000 011
     assert_encodes_as(cb64, "MOV16", (ecx, ebx), '\x66\x40\x89\xD9')
-    # XXX: What we are testing for here is actually not the most compact
-    # encoding.
-    assert_encodes_as(cb64, "MOV16", (ecx, ImmedLoc(12345)), '\x66\x40\xC7\xC1\x39\x30')
+    assert_encodes_as(cb64, "MOV16", (ecx, ImmedLoc(12345)), '\x66\xB9\x39\x30')
+    # for the next case we don't pick the most efficient encoding, but well
+    expected = '\x66\x40\xC7\xC1\xC7\xCF'  # could be '\x66\xB9\xC7\xCF'
+    assert_encodes_as(cb64, "MOV16", (ecx, ImmedLoc(-12345)), expected)
+    assert_encodes_as(cb64, "MOV16", (r9, ImmedLoc(12345)), '\x66\x41\xB9\x39\x30')
+    # for the next case we don't pick the most efficient encoding, but well
+    expected = '\x66\x41\xC7\xC1\xC7\xCF'  # could be '\x66\x41\xB9\xC7\xCF'
+    assert_encodes_as(cb64, "MOV16", (r9, ImmedLoc(-12345)), expected)
     assert_encodes_as(cb64, "MOV16", (AddressLoc(r13, ImmedLoc(0), 0, 0), ImmedLoc(12345)), '\x66\x41\xC7\x45\x00\x39\x30')
 
 def test_cmp_16():
@@ -44,7 +49,7 @@
 def test_relocation():
     from pypy.rpython.lltypesystem import lltype, rffi
     from pypy.jit.backend.x86 import codebuf
-    for target in [0x01020304, 0x0102030405060708]:
+    for target in [0x01020304, -0x05060708, 0x0102030405060708]:
         if target > sys.maxint:
             continue
         mc = codebuf.MachineCodeBlockWrapper()
@@ -58,10 +63,15 @@
             expected = "\xE8" + struct.pack('<i', target - (rawstart + 5))
         elif IS_X86_64:
             assert mc.relocations == []
-            if target <= 0x7fffffff:
+            if 0 <= target <= 0xffffffff:
+                assert length == 9
+                expected = (
+                    "\x41\xBB\x04\x03\x02\x01"      # MOV %r11, target
+                    "\x41\xFF\xD3")                 # CALL *%r11
+            elif -0x80000000 <= target < 0:
                 assert length == 10
                 expected = (
-                    "\x49\xC7\xC3\x04\x03\x02\x01"  # MOV %r11, target
+                    "\x49\xC7\xC3\xF8\xF8\xF9\xFA"  # MOV %r11, target
                     "\x41\xFF\xD3")                 # CALL *%r11
             else:
                 assert length == 13
diff --git a/pypy/jit/backend/x86/test/test_rx86.py b/pypy/jit/backend/x86/test/test_rx86.py
--- a/pypy/jit/backend/x86/test/test_rx86.py
+++ b/pypy/jit/backend/x86/test/test_rx86.py
@@ -198,9 +198,19 @@
 def test_mov_ri_64():
     s = CodeBuilder64()
     s.MOV_ri(ecx, -2)
+    s.MOV_ri(r15, -3)
+    s.MOV_ri(ebx, -0x80000003)
+    s.MOV_ri(r13, -0x80000002)
+    s.MOV_ri(ecx, 42)
     s.MOV_ri(r12, 0x80000042)
+    s.MOV_ri(r12, 0x100000007)
     assert s.getvalue() == ('\x48\xC7\xC1\xFE\xFF\xFF\xFF' +
-                            '\x49\xBC\x42\x00\x00\x80\x00\x00\x00\x00')
+                            '\x49\xC7\xC7\xFD\xFF\xFF\xFF' +
+                            '\x48\xBB\xFD\xFF\xFF\x7F\xFF\xFF\xFF\xFF' +
+                            '\x49\xBD\xFE\xFF\xFF\x7F\xFF\xFF\xFF\xFF' +
+                            '\xB9\x2A\x00\x00\x00' +
+                            '\x41\xBC\x42\x00\x00\x80' +
+                            '\x49\xBC\x07\x00\x00\x00\x01\x00\x00\x00')
 
 def test_mov_rm_64():
     s = CodeBuilder64()
diff --git a/pypy/jit/backend/x86/test/test_rx86_32_auto_encoding.py b/pypy/jit/backend/x86/test/test_rx86_32_auto_encoding.py
--- a/pypy/jit/backend/x86/test/test_rx86_32_auto_encoding.py
+++ b/pypy/jit/backend/x86/test/test_rx86_32_auto_encoding.py
@@ -212,6 +212,17 @@
             for mode, v in zip(argmodes, args):
                 ops.append(assembler_operand[mode](v))
             ops.reverse()
+            #
+            if (instrname.lower() == 'mov' and suffix == 'q' and
+                ops[0].startswith('$') and 0 <= int(ops[0][1:]) <= 4294967295
+                and ops[1].startswith('%r')):
+                # movq $xxx, %rax => movl $xxx, %eax
+                suffix = 'l'
+                if ops[1][2:].isdigit():
+                    ops[1] += 'd'
+                else:
+                    ops[1] = '%e' + ops[1][2:]
+            #
             op = '\t%s%s %s%s' % (instrname.lower(), suffix,
                                   ', '.join(ops), following)
             g.write('%s\n' % op)
diff --git a/pypy/jit/backend/x86/test/test_zrpy_gc.py b/pypy/jit/backend/x86/test/test_zrpy_gc.py
--- a/pypy/jit/backend/x86/test/test_zrpy_gc.py
+++ b/pypy/jit/backend/x86/test/test_zrpy_gc.py
@@ -524,6 +524,76 @@
     def test_compile_framework_8(self):
         self.run('compile_framework_8')
 
+    def define_compile_framework_9(cls):
+        # Like compile_framework_8, but with variable indexes and large
+        # arrays, testing the card_marking case
+        def before(n, x):
+            return n, x, None, None, None, None, None, None, None, None, [X(123)], None
+        def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+            if n < 1900:
+                check(l[0].x == 123)
+                num = 512 + (n & 7)
+                l = [None] * num
+                l[0] = X(123)
+                l[1] = X(n)
+                l[2] = X(n+10)
+                l[3] = X(n+20)
+                l[4] = X(n+30)
+                l[5] = X(n+40)
+                l[6] = X(n+50)
+                l[7] = X(n+60)
+                l[num-8] = X(n+70)
+                l[num-9] = X(n+80)
+                l[num-10] = X(n+90)
+                l[num-11] = X(n+100)
+                l[-12] = X(n+110)
+                l[-13] = X(n+120)
+                l[-14] = X(n+130)
+                l[-15] = X(n+140)
+            if n < 1800:
+                num = 512 + (n & 7)
+                check(len(l) == num)
+                check(l[0].x == 123)
+                check(l[1].x == n)
+                check(l[2].x == n+10)
+                check(l[3].x == n+20)
+                check(l[4].x == n+30)
+                check(l[5].x == n+40)
+                check(l[6].x == n+50)
+                check(l[7].x == n+60)
+                check(l[num-8].x == n+70)
+                check(l[num-9].x == n+80)
+                check(l[num-10].x == n+90)
+                check(l[num-11].x == n+100)
+                check(l[-12].x == n+110)
+                check(l[-13].x == n+120)
+                check(l[-14].x == n+130)
+                check(l[-15].x == n+140)
+            n -= x.foo
+            return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
+        def after(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+            check(len(l) >= 512)
+            check(l[0].x == 123)
+            check(l[1].x == 2)
+            check(l[2].x == 12)
+            check(l[3].x == 22)
+            check(l[4].x == 32)
+            check(l[5].x == 42)
+            check(l[6].x == 52)
+            check(l[7].x == 62)
+            check(l[-8].x == 72)
+            check(l[-9].x == 82)
+            check(l[-10].x == 92)
+            check(l[-11].x == 102)
+            check(l[-12].x == 112)
+            check(l[-13].x == 122)
+            check(l[-14].x == 132)
+            check(l[-15].x == 142)
+        return before, f, after
+
+    def test_compile_framework_9(self):
+        self.run('compile_framework_9')
+
     def define_compile_framework_external_exception_handling(cls):
         def before(n, x):
             x = X(0)
diff --git a/pypy/jit/codewriter/call.py b/pypy/jit/codewriter/call.py
--- a/pypy/jit/codewriter/call.py
+++ b/pypy/jit/codewriter/call.py
@@ -5,10 +5,9 @@
 
 from pypy.jit.codewriter import support
 from pypy.jit.codewriter.jitcode import JitCode
-from pypy.jit.codewriter.effectinfo import VirtualizableAnalyzer
-from pypy.jit.codewriter.effectinfo import QuasiImmutAnalyzer
-from pypy.jit.codewriter.effectinfo import effectinfo_from_writeanalyze
-from pypy.jit.codewriter.effectinfo import EffectInfo, CallInfoCollection
+from pypy.jit.codewriter.effectinfo import (VirtualizableAnalyzer,
+    QuasiImmutAnalyzer, CanReleaseGILAnalyzer, effectinfo_from_writeanalyze,
+    EffectInfo, CallInfoCollection)
 from pypy.translator.simplify import get_funcobj, get_functype
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.translator.backendopt.canraise import RaiseAnalyzer
@@ -32,6 +31,7 @@
             self.readwrite_analyzer = ReadWriteAnalyzer(translator)
             self.virtualizable_analyzer = VirtualizableAnalyzer(translator)
             self.quasiimmut_analyzer = QuasiImmutAnalyzer(translator)
+            self.canreleasegil_analyzer = CanReleaseGILAnalyzer(translator)
         #
         for index, jd in enumerate(jitdrivers_sd):
             jd.index = index
@@ -219,7 +219,9 @@
                 assert not NON_VOID_ARGS, ("arguments not supported for "
                                            "loop-invariant function!")
         # build the extraeffect
-        can_invalidate = self.quasiimmut_analyzer.analyze(op)
+        can_release_gil = self.canreleasegil_analyzer.analyze(op)
+        # can_release_gil implies can_invalidate
+        can_invalidate = can_release_gil or self.quasiimmut_analyzer.analyze(op)
         if extraeffect is None:
             if self.virtualizable_analyzer.analyze(op):
                 extraeffect = EffectInfo.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
@@ -235,7 +237,7 @@
         #
         effectinfo = effectinfo_from_writeanalyze(
             self.readwrite_analyzer.analyze(op), self.cpu, extraeffect,
-            oopspecindex, can_invalidate)
+            oopspecindex, can_invalidate, can_release_gil)
         #
         if oopspecindex != EffectInfo.OS_NONE:
             assert effectinfo is not None
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
@@ -79,13 +79,15 @@
                 write_descrs_fields, write_descrs_arrays,
                 extraeffect=EF_CAN_RAISE,
                 oopspecindex=OS_NONE,
-                can_invalidate=False):
+                can_invalidate=False, can_release_gil=False):
         key = (frozenset(readonly_descrs_fields),
                frozenset(readonly_descrs_arrays),
                frozenset(write_descrs_fields),
                frozenset(write_descrs_arrays),
                extraeffect,
-               oopspecindex)
+               oopspecindex,
+               can_invalidate,
+               can_release_gil)
         if key in cls._cache:
             return cls._cache[key]
         result = object.__new__(cls)
@@ -100,6 +102,7 @@
             result.write_descrs_arrays = write_descrs_arrays
         result.extraeffect = extraeffect
         result.can_invalidate = can_invalidate
+        result.can_release_gil = can_release_gil
         result.oopspecindex = oopspecindex
         cls._cache[key] = result
         return result
@@ -111,12 +114,13 @@
         return self.extraeffect >= self.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
 
     def has_random_effects(self):
-        return self.oopspecindex == self.OS_LIBFFI_CALL
+        return self.oopspecindex == self.OS_LIBFFI_CALL or self.can_release_gil
 
 def effectinfo_from_writeanalyze(effects, cpu,
                                  extraeffect=EffectInfo.EF_CAN_RAISE,
                                  oopspecindex=EffectInfo.OS_NONE,
-                                 can_invalidate=False):
+                                 can_invalidate=False,
+                                 can_release_gil=False):
     from pypy.translator.backendopt.writeanalyze import top_set
     if effects is top_set:
         return None
@@ -158,7 +162,8 @@
                       write_descrs_arrays,
                       extraeffect,
                       oopspecindex,
-                      can_invalidate)
+                      can_invalidate,
+                      can_release_gil)
 
 def consider_struct(TYPE, fieldname):
     if fieldType(TYPE, fieldname) is lltype.Void:
@@ -194,6 +199,16 @@
     def analyze_simple_operation(self, op, graphinfo):
         return op.opname == 'jit_force_quasi_immutable'
 
+class CanReleaseGILAnalyzer(BoolGraphAnalyzer):
+    def analyze_direct_call(self, graph, seen=None):
+        releases_gil = False
+        if hasattr(graph, "func") and hasattr(graph.func, "_ptr"):
+            releases_gil = graph.func._ptr._obj.releases_gil
+        return releases_gil or super(CanReleaseGILAnalyzer, self).analyze_direct_call(graph, seen)
+
+    def analyze_simple_operation(self, op, graphinfo):
+        return False
+
 # ____________________________________________________________
 
 class CallInfoCollection(object):
diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -765,13 +765,65 @@
             raise NotImplementedError("cast_ptr_to_int")
 
     def rewrite_op_force_cast(self, op):
-        from pypy.rpython.lltypesystem.rffi import size_and_sign, sizeof
+        assert not self._is_gc(op.args[0])
+        fromll = longlong.is_longlong(op.args[0].concretetype)
+        toll   = longlong.is_longlong(op.result.concretetype)
+        if fromll and toll:
+            return
+        if fromll:
+            args = op.args
+            opname = 'truncate_longlong_to_int'
+            RESULT = lltype.Signed
+            v = varoftype(RESULT)
+            op1 = SpaceOperation(opname, args, v)
+            op2 = self.rewrite_operation(op1)
+            oplist = self.force_cast_without_longlong(op2.result, op.result)
+            if oplist:
+                return [op2] + oplist
+            #
+            # force a renaming to put the correct result in place, even though
+            # it might be slightly mistyped (e.g. Signed versus Unsigned)
+            assert op2.result is v
+            op2.result = op.result
+            return op2
+        elif toll:
+            from pypy.rpython.lltypesystem import rffi
+            size, unsigned = rffi.size_and_sign(op.args[0].concretetype)
+            if unsigned:
+                INTERMEDIATE = lltype.Unsigned
+            else:
+                INTERMEDIATE = lltype.Signed
+            v = varoftype(INTERMEDIATE)
+            oplist = self.force_cast_without_longlong(op.args[0], v)
+            if not oplist:
+                v = op.args[0]
+                oplist = []
+            if unsigned:
+                opname = 'cast_uint_to_longlong'
+            else:
+                opname = 'cast_int_to_longlong'
+            op1 = SpaceOperation(opname, [v], op.result)
+            op2 = self.rewrite_operation(op1)
+            return oplist + [op2]
+        else:
+            return self.force_cast_without_longlong(op.args[0], op.result)
+
+    def force_cast_without_longlong(self, v_arg, v_result):
+        from pypy.rpython.lltypesystem.rffi import size_and_sign, sizeof, FLOAT
         from pypy.rlib.rarithmetic import intmask
-        assert not self._is_gc(op.args[0])
-        size2, unsigned2 = size_and_sign(op.result.concretetype)
-        if size2 >= sizeof(lltype.Signed):
+        #
+        if (v_result.concretetype in (FLOAT, lltype.Float) or
+            v_arg.concretetype in (FLOAT, lltype.Float)):
+            assert (v_result.concretetype == lltype.Float and
+                    v_arg.concretetype == lltype.Float), "xxx unsupported cast"
+            return
+        #
+        size2, unsigned2 = size_and_sign(v_result.concretetype)
+        assert size2 <= sizeof(lltype.Signed)
+        if size2 == sizeof(lltype.Signed):
             return     # the target type is LONG or ULONG
-        size1, unsigned1 = size_and_sign(op.args[0].concretetype)
+        size1, unsigned1 = size_and_sign(v_arg.concretetype)
+        assert size1 <= sizeof(lltype.Signed)
         #
         def bounds(size, unsigned):
             if unsigned:
@@ -784,22 +836,28 @@
             return     # the target type includes the source range
         #
         result = []
-        v1 = op.args[0]
         if min2:
             c_min2 = Constant(min2, lltype.Signed)
-            v2 = Variable(); v2.concretetype = lltype.Signed
-            result.append(SpaceOperation('int_sub', [v1, c_min2], v2))
+            v2 = varoftype(lltype.Signed)
+            result.append(SpaceOperation('int_sub', [v_arg, c_min2], v2))
         else:
-            v2 = v1
+            v2 = v_arg
         c_mask = Constant(int((1<<(8*size2))-1), lltype.Signed)
-        v3 = Variable(); v3.concretetype = lltype.Signed
+        v3 = varoftype(lltype.Signed)
         result.append(SpaceOperation('int_and', [v2, c_mask], v3))
         if min2:
-            result.append(SpaceOperation('int_add', [v3, c_min2], op.result))
+            result.append(SpaceOperation('int_add', [v3, c_min2], v_result))
         else:
-            result[-1].result = op.result
+            result[-1].result = v_result
         return result
 
+    def rewrite_op_direct_ptradd(self, op):
+        from pypy.rpython.lltypesystem import rffi
+        # xxx otherwise, not implemented:
+        assert op.args[0].concretetype == rffi.CCHARP
+        #
+        return SpaceOperation('int_add', [op.args[0], op.args[1]], op.result)
+
     # ----------
     # Long longs, for 32-bit only.  Supported operations are left unmodified,
     # and unsupported ones are turned into a call to a function from
@@ -883,30 +941,7 @@
     rewrite_op_ullong_is_true = rewrite_op_llong_is_true
 
     def rewrite_op_cast_primitive(self, op):
-        fromll = longlong.is_longlong(op.args[0].concretetype)
-        toll   = longlong.is_longlong(op.result.concretetype)
-        if fromll != toll:
-            args = op.args
-            if fromll:
-                opname = 'truncate_longlong_to_int'
-                RESULT = lltype.Signed
-            else:
-                from pypy.rpython.lltypesystem import rffi
-                if rffi.cast(op.args[0].concretetype, -1) < 0:
-                    opname = 'cast_int_to_longlong'
-                else:
-                    opname = 'cast_uint_to_longlong'
-                RESULT = lltype.SignedLongLong
-            v = varoftype(RESULT)
-            op1 = SpaceOperation(opname, args, v)
-            op2 = self.rewrite_operation(op1)
-            #
-            # force a renaming to put the correct result in place, even though
-            # it might be slightly mistyped (e.g. Signed versus Unsigned)
-            assert op2.result is v
-            op2.result = op.result
-            #
-            return op2
+        return self.rewrite_op_force_cast(op)
 
     # ----------
     # Renames, from the _old opname to the _new one.
@@ -1083,6 +1118,9 @@
         return meth(op, args, *descrs)
 
     def _get_list_nonneg_canraise_flags(self, op):
+        # XXX as far as I can see, this function will always return True
+        # because functions that are neither nonneg nor fast don't have an
+        # oopspec any more
         # xxx break of abstraction:
         func = get_funcobj(op.args[0].value)._callable
         # base hints on the name of the ll function, which is a bit xxx-ish
@@ -1240,7 +1278,7 @@
         calldescr = self.callcontrol.getcalldescr(op, oopspecindex,
                                                   extraeffect)
         if extraeffect is not None:
-            assert (type(calldescr) is str      # for tests
+            assert (is_test_calldescr(calldescr)      # for tests
                     or calldescr.get_extra_info().extraeffect == extraeffect)
         if isinstance(op.args[0].value, str):
             pass  # for tests only
@@ -1401,6 +1439,9 @@
         return "using virtualizable array in illegal way in %r" % (
             self.args[0],)
 
+def is_test_calldescr(calldescr):
+    return type(calldescr) is str or getattr(calldescr, '_for_tests_only', False)
+
 def _with_prefix(prefix):
     result = {}
     for name in dir(Transformer):
diff --git a/pypy/jit/codewriter/regalloc.py b/pypy/jit/codewriter/regalloc.py
--- a/pypy/jit/codewriter/regalloc.py
+++ b/pypy/jit/codewriter/regalloc.py
@@ -96,6 +96,7 @@
 
     def _try_coalesce(self, v, w):
         if isinstance(v, Variable) and getkind(v.concretetype) == self.kind:
+            assert getkind(w.concretetype) == self.kind
             dg = self._depgraph
             uf = self._unionfind
             v0 = uf.find_rep(v)
diff --git a/pypy/jit/codewriter/support.py b/pypy/jit/codewriter/support.py
--- a/pypy/jit/codewriter/support.py
+++ b/pypy/jit/codewriter/support.py
@@ -185,7 +185,7 @@
     return llop.int_floordiv(lltype.Signed, x, y)
 
 def _ll_2_int_floordiv_ovf(x, y):
-    if x == -sys.maxint - 1 and y == -1:        
+    if x == -sys.maxint - 1 and y == -1:
         raise OverflowError
     return llop.int_floordiv(lltype.Signed, x, y)
 
@@ -222,7 +222,7 @@
         return -x
     else:
         return x
-        
+
 # math support
 # ------------
 
@@ -395,7 +395,7 @@
     ('int_lshift_ovf',       [lltype.Signed, lltype.Signed], lltype.Signed),
     ('int_abs',              [lltype.Signed],                lltype.Signed),
     ('ll_math.ll_math_sqrt', [lltype.Float],                 lltype.Float),
-    ]
+]
 
 
 class LLtypeHelpers:
diff --git a/pypy/jit/codewriter/test/test_call.py b/pypy/jit/codewriter/test/test_call.py
--- a/pypy/jit/codewriter/test/test_call.py
+++ b/pypy/jit/codewriter/test/test_call.py
@@ -1,6 +1,6 @@
 import py
 from pypy.objspace.flow.model import SpaceOperation, Constant, Variable
-from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.translator.unsimplify import varoftype
 from pypy.rlib import jit
 from pypy.jit.codewriter.call import CallControl
@@ -103,7 +103,7 @@
 
     op = SpaceOperation('direct_call', [Constant(object())],
                         Variable())
-    assert cc.guess_call_kind(op) == 'residual'        
+    assert cc.guess_call_kind(op) == 'residual'
 
     class funcptr:
         class graph:
@@ -118,7 +118,7 @@
     op = SpaceOperation('direct_call', [Constant(funcptr)],
                         Variable())
     res = cc.graphs_from(op)
-    assert res == [g]        
+    assert res == [g]
     assert cc.guess_call_kind(op) == 'regular'
 
     class funcptr:
@@ -126,7 +126,7 @@
     op = SpaceOperation('direct_call', [Constant(funcptr)],
                         Variable())
     res = cc.graphs_from(op)
-    assert res is None        
+    assert res is None
     assert cc.guess_call_kind(op) == 'residual'
 
     h = object()
@@ -142,7 +142,7 @@
                         Variable())
     res = cc.graphs_from(op)
     assert res is None
-    assert cc.guess_call_kind(op) == 'residual'        
+    assert cc.guess_call_kind(op) == 'residual'
 
 # ____________________________________________________________
 
@@ -171,3 +171,24 @@
 
 def test_jit_force_virtualizable_effectinfo():
     py.test.skip("XXX add a test for CallControl.getcalldescr() -> EF_xxx")
+
+def test_releases_gil_analyzer():
+    from pypy.jit.backend.llgraph.runner import LLtypeCPU
+
+    T = rffi.CArrayPtr(rffi.TIME_T)
+    external = rffi.llexternal("time", [T], rffi.TIME_T, threadsafe=True)
+
+    @jit.dont_look_inside
+    def f():
+        return external(lltype.nullptr(T.TO))
+
+    rtyper = support.annotate(f, [])
+    jitdriver_sd = FakeJitDriverSD(rtyper.annotator.translator.graphs[0])
+    cc = CallControl(LLtypeCPU(rtyper), jitdrivers_sd=[jitdriver_sd])
+    res = cc.find_all_graphs(FakePolicy())
+
+    [f_graph] = [x for x in res if x.func is f]
+    [block, _] = list(f_graph.iterblocks())
+    [op] = block.operations
+    call_descr = cc.getcalldescr(op)
+    assert call_descr.extrainfo.can_release_gil
\ No newline at end of file
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
@@ -3,6 +3,7 @@
 from pypy.jit.codewriter.flatten import flatten_graph, reorder_renaming_list
 from pypy.jit.codewriter.flatten import GraphFlattener, ListOfKind, Register
 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.objspace.flow.model import SpaceOperation, Variable, Constant
@@ -30,6 +31,9 @@
             'float': FakeRegAlloc()}
 
 class FakeDescr(AbstractDescr):
+    _for_tests_only = True
+    def __init__(self, oopspecindex=None):
+        self.oopspecindex = oopspecindex
     def __repr__(self):
         return '<Descr>'
     def as_vtable_size_descr(self):
@@ -55,19 +59,24 @@
     def arraydescrof(self, ARRAY):
         return FakeDescr()
 
+class FakeCallInfoCollection:
+    def add(self, *args):
+        pass
+
 class FakeCallControl:
     _descr_cannot_raise = FakeDescr()
+    callinfocollection = FakeCallInfoCollection()
     def guess_call_kind(self, op):
         return 'residual'
-    def getcalldescr(self, op):
+    def getcalldescr(self, op, oopspecindex=None, extraeffect=None):
         try:
             if 'cannot_raise' in op.args[0].value._obj.graph.name:
                 return self._descr_cannot_raise
         except AttributeError:
             pass
-        return FakeDescr()
+        return FakeDescr(oopspecindex)
     def calldescr_canraise(self, calldescr):
-        return calldescr is not self._descr_cannot_raise
+        return calldescr is not self._descr_cannot_raise and calldescr.oopspecindex is None
     def get_vinfo(self, VTYPEPTR):
         return None
 
@@ -734,7 +743,9 @@
 
     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
         for FROM, TO, expected in [
             (rffi.SIGNEDCHAR, rffi.SIGNEDCHAR, ""),
             (rffi.SIGNEDCHAR, rffi.UCHAR, "int_and %i0, $255 -> %i1"),
@@ -797,14 +808,44 @@
             expected = [s.strip() for s in expected.splitlines()]
             check_force_cast(FROM, TO, expected, 42)
             check_force_cast(FROM, TO, expected, -42)
-            expected.append('int_return %i' + str(len(expected)))
-            expected = '\n'.join(expected)
+            returnvar = "%i" + str(len(expected))
+            expected.append('int_return ' + returnvar)
+            expectedstr = '\n'.join(expected)
             #
             def f(n):
                 return rffi.cast(TO, n)
-            self.encoding_test(f, [rffi.cast(FROM, 42)], expected,
+            self.encoding_test(f, [rffi.cast(FROM, 42)], expectedstr,
                                transform=True)
 
+            if not longlong.is_64_bit:
+                if FROM in (rffi.LONG, rffi.ULONG):
+                    if FROM == rffi.LONG:
+                        FROM = rffi.LONGLONG
+                    else:
+                        FROM = rffi.ULONGLONG
+                    expected.insert(0,
+                        "residual_call_irf_i $<* fn llong_to_int>, <Descr>, I[], R[], F[%f0] -> %i0")
+                    expectedstr = '\n'.join(expected)
+                    self.encoding_test(f, [rffi.cast(FROM, 42)], expectedstr,
+                                       transform=True)
+                elif TO in (rffi.LONG, rffi.ULONG):
+                    if TO == rffi.LONG:
+                        TO = rffi.LONGLONG
+                    else:
+                        TO = rffi.ULONGLONG
+                    if rffi.cast(FROM, -1) < 0:
+                        fnname = "llong_from_int"
+                    else:
+                        fnname = "llong_from_uint"
+                    expected.pop()   # remove int_return
+                    expected.append(
+                        "residual_call_irf_f $<* fn %s>, <Descr>, I[%s], R[], F[] -> %%f0"
+                        % (fnname, returnvar))
+                    expected.append("float_return %f0")
+                    expectedstr = '\n'.join(expected)
+                    self.encoding_test(f, [rffi.cast(FROM, 42)], expectedstr,
+                                       transform=True)
+
     def test_force_cast_pointer(self):
         from pypy.rpython.lltypesystem import rffi
         def h(p):
@@ -813,6 +854,23 @@
             int_return %i0
         """, transform=True)
 
+    def test_force_cast_float(self):
+        from pypy.rpython.lltypesystem import rffi
+        def f(n):
+            return rffi.cast(lltype.Float, n)
+        self.encoding_test(f, [12.456], """
+            float_return %f0
+        """, 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], """
+            int_add %i0, %i1 -> %i2
+            int_return %i2
+        """, transform=True)
+
 
 def check_force_cast(FROM, TO, operations, value):
     """Check that the test is correctly written..."""
diff --git a/pypy/jit/codewriter/test/test_longlong.py b/pypy/jit/codewriter/test/test_longlong.py
--- a/pypy/jit/codewriter/test/test_longlong.py
+++ b/pypy/jit/codewriter/test/test_longlong.py
@@ -37,7 +37,7 @@
 
 class TestLongLong:
     def setup_class(cls):
-        if sys.maxint > 2147483647:
+        if longlong.is_64_bit:
             py.test.skip("only for 32-bit platforms")
 
     def do_check(self, opname, oopspecindex, ARGS, RESULT):
@@ -46,6 +46,8 @@
         op = SpaceOperation(opname, vlist, v_result)
         tr = Transformer(FakeCPU(), FakeBuiltinCallControl())
         op1 = tr.rewrite_operation(op)
+        if isinstance(op1, list):
+            [op1] = op1
         #
         def is_llf(TYPE):
             return (TYPE == lltype.SignedLongLong or
@@ -196,6 +198,23 @@
             for T2 in [lltype.Signed, lltype.Unsigned]:
                 self.do_check('cast_primitive', EffectInfo.OS_LLONG_TO_INT,
                               [T1], T2)
+                self.do_check('force_cast', EffectInfo.OS_LLONG_TO_INT,
+                              [T1], T2)
+                if T2 == lltype.Signed:
+                    expected = EffectInfo.OS_LLONG_FROM_INT
+                else:
+                    expected = EffectInfo.OS_LLONG_FROM_UINT
+                self.do_check('cast_primitive', expected, [T2], T1)
+                self.do_check('force_cast', expected, [T2], T1)
+        #
+        for T1 in [lltype.SignedLongLong, lltype.UnsignedLongLong]:
+            for T2 in [lltype.SignedLongLong, lltype.UnsignedLongLong]:
+                vlist = [varoftype(T1)]
+                v_result = varoftype(T2)
+                op = SpaceOperation('force_cast', vlist, v_result)
+                tr = Transformer(FakeCPU(), FakeBuiltinCallControl())
+                op1 = tr.rewrite_operation(op)
+                assert op1 is None
 
     def test_constants(self):
         for TYPE in [lltype.SignedLongLong, lltype.UnsignedLongLong]:
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
@@ -57,7 +57,6 @@
 
     optimizations, unroll = build_opt_chain(metainterp_sd, enable_opts,
                                             inline_short_preamble, retraced)
-
     if unroll:
         optimize_unroll(metainterp_sd, loop, optimizations)
     else:
diff --git a/pypy/jit/metainterp/optimizeopt/fficall.py b/pypy/jit/metainterp/optimizeopt/fficall.py
--- a/pypy/jit/metainterp/optimizeopt/fficall.py
+++ b/pypy/jit/metainterp/optimizeopt/fficall.py
@@ -4,7 +4,7 @@
 from pypy.rlib.debug import debug_start, debug_stop, debug_print, have_debug_prints
 from pypy.jit.codewriter.effectinfo import EffectInfo
 from pypy.jit.metainterp.resoperation import rop, ResOperation
-from pypy.jit.metainterp.optimizeopt.util import _findall
+from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
 from pypy.jit.metainterp.optimizeopt.optimizer import Optimization
 from pypy.jit.backend.llsupport.ffisupport import UnsupportedKind
 
@@ -207,13 +207,7 @@
     def propagate_forward(self, op):
         if self.logops is not None:
             debug_print(self.logops.repr_of_resop(op))
-        opnum = op.getopnum()
-        for value, func in optimize_ops:
-            if opnum == value:
-                func(self, op)
-                break
-        else:
-            self.emit_operation(op)
+        dispatch_opt(self, op)
 
     def _get_oopspec(self, op):
         effectinfo = op.getdescr().get_extra_info()
@@ -224,4 +218,5 @@
     def _get_funcval(self, op):
         return self.getvalue(op.getarg(1))
 
-optimize_ops = _findall(OptFfiCall, 'optimize_')
+dispatch_opt = make_dispatcher_method(OptFfiCall, 'optimize_',
+        default=OptFfiCall.emit_operation)
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
@@ -1,5 +1,5 @@
 import os
-from pypy.jit.metainterp.optimizeopt.util import _findall
+from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
 from pypy.jit.metainterp.resoperation import rop, ResOperation
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.jit.metainterp.jitexc import JitException
@@ -76,7 +76,7 @@
         self._cached_fields[structvalue] = fieldvalue
         self._cached_fields_getfield_op[structvalue] = getfield_op        
 
-    def force_lazy_setfield(self, optheap):
+    def force_lazy_setfield(self, optheap, can_cache=True):
         op = self._lazy_setfield
         if op is not None:
             # This is the way _lazy_setfield is usually reset to None.
@@ -86,12 +86,16 @@
             self.clear()
             self._lazy_setfield = None
             optheap.next_optimization.propagate_forward(op)
+            if not can_cache:
+                return
             # Once it is done, we can put at least one piece of information
             # back in the cache: the value of this particular structure's
             # field.
             structvalue = optheap.getvalue(op.getarg(0))
             fieldvalue  = optheap.getvalue(op.getarglist()[-1])
             self.remember_field_value(structvalue, fieldvalue, op)
+        elif not can_cache:
+            self.clear()
 
     def clear(self):
         self._cached_fields.clear()
@@ -248,20 +252,9 @@
                 for arraydescr in effectinfo.readonly_descrs_arrays:
                     self.force_lazy_setarrayitem(arraydescr)
                 for fielddescr in effectinfo.write_descrs_fields:
-                    self.force_lazy_setfield(fielddescr)
-                    try:
-                        cf = self.cached_fields[fielddescr]
-                        cf.clear()
-                    except KeyError:
-                        pass
+                    self.force_lazy_setfield(fielddescr, can_cache=False)
                 for arraydescr in effectinfo.write_descrs_arrays:
-                    self.force_lazy_setarrayitem(arraydescr)
-                    try:
-                        submap = self.cached_arrayitems[arraydescr]
-                        for cf in submap.itervalues():
-                            cf.clear()
-                    except KeyError:
-                        pass
+                    self.force_lazy_setarrayitem(arraydescr, can_cache=False)
                 if effectinfo.check_forces_virtual_or_virtualizable():
                     vrefinfo = self.optimizer.metainterp_sd.virtualref_info
                     self.force_lazy_setfield(vrefinfo.descr_forced)
@@ -284,20 +277,20 @@
                     if value in cf._cached_fields:
                         cf.turned_constant(newvalue, value)
 
-    def force_lazy_setfield(self, descr):
+    def force_lazy_setfield(self, descr, can_cache=True):
         try:
             cf = self.cached_fields[descr]
         except KeyError:
             return
-        cf.force_lazy_setfield(self)
+        cf.force_lazy_setfield(self, can_cache)
 
-    def force_lazy_setarrayitem(self, arraydescr):
+    def force_lazy_setarrayitem(self, arraydescr, can_cache=True):
         try:
             submap = self.cached_arrayitems[arraydescr]
         except KeyError:
             return
         for cf in submap.values():
-            cf.force_lazy_setfield(self)
+            cf.force_lazy_setfield(self, can_cache)
 
     def fixup_guard_situation(self):
         # hackish: reverse the order of the last two operations if it makes
@@ -436,7 +429,7 @@
             cf.do_setfield(self, op)
         else:
             # variable index, so make sure the lazy setarrayitems are done
-            self.force_lazy_setarrayitem(op.getdescr())
+            self.force_lazy_setarrayitem(op.getdescr(), can_cache=False)
             # and then emit the operation
             self.emit_operation(op)
 
@@ -480,13 +473,7 @@
         self._seen_guard_not_invalidated = True
         self.emit_operation(op)
 
-    def propagate_forward(self, op):
-        opnum = op.getopnum()
-        for value, func in optimize_ops:
-            if opnum == value:
-                func(self, op)
-                break
-        else:
-            self.emit_operation(op)
 
-optimize_ops = _findall(OptHeap, 'optimize_')
+dispatch_opt = make_dispatcher_method(OptHeap, 'optimize_',
+        default=OptHeap.emit_operation)
+OptHeap.propagate_forward = dispatch_opt
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
@@ -1,6 +1,6 @@
 from pypy.jit.metainterp.optimizeopt.optimizer import Optimization, CONST_1, CONST_0, \
                                                   MODE_ARRAY, MODE_STR, MODE_UNICODE
-from pypy.jit.metainterp.optimizeopt.util import _findall
+from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
 from pypy.jit.metainterp.optimizeopt.intutils import (IntBound, IntUnbounded,
     IntLowerBound, IntUpperBound)
 from pypy.jit.metainterp.history import Const, ConstInt
@@ -39,14 +39,11 @@
             op = self.posponedop
             self.posponedop = None
 
-        opnum = op.getopnum()
-        for value, func in optimize_ops:
-            if opnum == value:
-                func(self, op)
-                break
-        else:
-            assert not op.is_ovf()
-            self.emit_operation(op)
+        dispatch_opt(self, op)
+
+    def opt_default(self, op):
+        assert not op.is_ovf()
+        self.emit_operation(op)
 
 
     def propagate_bounds_backward(self, box):
@@ -62,11 +59,7 @@
             op = self.optimizer.producer[box]
         except KeyError:
             return
-        opnum = op.getopnum()
-        for value, func in propagate_bounds_ops:
-            if opnum == value:
-                func(self, op)
-                break
+        dispatch_bounds_ops(self, op)
 
     def optimize_GUARD_TRUE(self, op):
         self.emit_operation(op)
@@ -462,5 +455,6 @@
     propagate_bounds_INT_MUL_OVF  = propagate_bounds_INT_MUL
 
 
-optimize_ops = _findall(OptIntBounds, 'optimize_')
-propagate_bounds_ops = _findall(OptIntBounds, 'propagate_bounds_')
+dispatch_opt = make_dispatcher_method(OptIntBounds, 'optimize_',
+        default=OptIntBounds.opt_default)
+dispatch_bounds_ops = make_dispatcher_method(OptIntBounds, 'propagate_bounds_')
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
@@ -4,7 +4,7 @@
 from pypy.jit.metainterp.resoperation import rop, ResOperation
 from pypy.jit.metainterp import jitprof
 from pypy.jit.metainterp.executor import execute_nonspec
-from pypy.jit.metainterp.optimizeopt.util import _findall, sort_descrs
+from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method, sort_descrs
 from pypy.jit.metainterp.optimizeopt.util import descrlist_dict, args_dict
 from pypy.jit.metainterp.optimize import InvalidLoop
 from pypy.jit.metainterp import resume, compile
@@ -564,14 +564,7 @@
 
     def propagate_forward(self, op):
         self.producer[op.result] = op
-        opnum = op.getopnum()
-        for value, func in optimize_ops:
-            if opnum == value:
-                func(self, op)
-                break
-        else:
-            self.optimize_default(op)
-        #print '\n'.join([str(o) for o in self.newoperations]) + '\n---\n'
+        dispatch_opt(self, op)
 
     def test_emittable(self, op):
         return True
@@ -723,7 +716,8 @@
 
     
 
-optimize_ops = _findall(Optimizer, 'optimize_')
+dispatch_opt = make_dispatcher_method(Optimizer, 'optimize_',
+        default=Optimizer.optimize_default)
 
 
 
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
@@ -1,7 +1,7 @@
 from pypy.jit.metainterp.optimizeopt.optimizer import *
 from pypy.jit.metainterp.resoperation import opboolinvers, opboolreflex
 from pypy.jit.metainterp.history import ConstInt
-from pypy.jit.metainterp.optimizeopt.util import _findall
+from pypy.jit.metainterp.optimizeopt.util import _findall, make_dispatcher_method
 from pypy.jit.metainterp.resoperation import rop, ResOperation
 from pypy.jit.codewriter.effectinfo import EffectInfo
 from pypy.jit.metainterp.optimizeopt.intutils import IntBound
@@ -36,18 +36,13 @@
         if self.find_rewritable_bool(op, args):
             return
 
-        opnum = op.getopnum()
-        for value, func in optimize_ops:
-            if opnum == value:
-                func(self, op)
-                break
-        else:
-            self.emit_operation(op)
+        dispatch_opt(self, op)
 
     def test_emittable(self, op):
         opnum = op.getopnum()
-        for value, func in optimize_guards:
+        for value, cls, func in optimize_guards:
             if opnum == value:
+                assert isinstance(op, cls)
                 try:
                     func(self, op, dryrun=True)
                     return self.is_emittable(op)
@@ -219,6 +214,7 @@
                     ))
                     return
         self.emit_operation(op)
+        self.pure(rop.FLOAT_MUL, [arg2, arg1], op.result)
 
     def optimize_FLOAT_NEG(self, op):
         v1 = op.getarg(0)
@@ -494,5 +490,6 @@
         self.emit_operation(op)
 
 
-optimize_ops = _findall(OptRewrite, 'optimize_')
+dispatch_opt = make_dispatcher_method(OptRewrite, 'optimize_',
+        default=OptRewrite.emit_operation)
 optimize_guards = _findall(OptRewrite, 'optimize_', 'GUARD')
diff --git a/pypy/jit/metainterp/optimizeopt/simplify.py b/pypy/jit/metainterp/optimizeopt/simplify.py
--- a/pypy/jit/metainterp/optimizeopt/simplify.py
+++ b/pypy/jit/metainterp/optimizeopt/simplify.py
@@ -1,7 +1,7 @@
 
 from pypy.jit.metainterp.resoperation import ResOperation, rop
 from pypy.jit.metainterp.optimizeopt.optimizer import Optimization
-from pypy.jit.metainterp.optimizeopt.util import _findall
+from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
 
 class OptSimplify(Optimization):
     def optimize_CALL_PURE(self, op):
@@ -25,13 +25,7 @@
         #     but it's a bit hard to implement robustly if heap.py is also run
         pass
 
-    def propagate_forward(self, op):
-        opnum = op.getopnum()
-        for value, func in optimize_ops:
-            if opnum == value:
-                func(self, op)
-                break
-        else:
-            self.emit_operation(op)
 
-optimize_ops = _findall(OptSimplify, 'optimize_')
+dispatch_opt = make_dispatcher_method(OptSimplify, 'optimize_',
+        default=OptSimplify.emit_operation)
+OptSimplify.propagate_forward = dispatch_opt
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
@@ -1755,6 +1755,48 @@
         """
         self.optimize_loop(ops, expected)
 
+    def test_duplicate_getarrayitem_after_setarrayitem_bug(self):
+        ops = """
+        [p0, i0, i1]
+        setarrayitem_gc(p0, 0, i0, descr=arraydescr)
+        i6 = int_add(i0, 1)
+        setarrayitem_gc(p0, i1, i6, descr=arraydescr)
+        i10 = getarrayitem_gc(p0, 0, descr=arraydescr)
+        i11 = int_add(i10, i0)
+        jump(p0, i11, i1)
+        """
+        expected = """
+        [p0, i0, i1]
+        i6 = int_add(i0, 1)
+        setarrayitem_gc(p0, 0, i0, descr=arraydescr)
+        setarrayitem_gc(p0, i1, i6, descr=arraydescr)
+        i10 = getarrayitem_gc(p0, 0, descr=arraydescr)
+        i11 = int_add(i10, i0)
+        jump(p0, i11, i1)
+        """
+        self.optimize_loop(ops, expected)
+
+    def test_duplicate_getarrayitem_after_setarrayitem_bug2(self):
+        ops = """
+        [p0, i0, i1]
+        i2 = getarrayitem_gc(p0, 0, descr=arraydescr)
+        i6 = int_add(i0, 1)
+        setarrayitem_gc(p0, i1, i6, descr=arraydescr)
+        i10 = getarrayitem_gc(p0, 0, descr=arraydescr)
+        i11 = int_add(i10, i2)
+        jump(p0, i11, i1)
+        """
+        expected = """
+        [p0, i0, i1]
+        i2 = getarrayitem_gc(p0, 0, descr=arraydescr)
+        i6 = int_add(i0, 1)
+        setarrayitem_gc(p0, i1, i6, descr=arraydescr)
+        i10 = getarrayitem_gc(p0, 0, descr=arraydescr)
+        i11 = int_add(i10, i2)
+        jump(p0, i11, i1)
+        """
+        self.optimize_loop(ops, expected)
+
     def test_bug_1(self):
         ops = """
         [i0, p1]
@@ -3916,11 +3958,8 @@
         i2 = strlen(p2)
         i3 = int_add(i1, i2)
         p3 = newstr(i3)
-        i4 = strlen(p1)
-        copystrcontent(p1, p3, 0, 0, i4)
-        i5 = strlen(p2)
-        i6 = int_add(i4, i5)      # will be killed by the backend
-        copystrcontent(p2, p3, 0, i4, i5)
+        copystrcontent(p1, p3, 0, 0, i1)
+        copystrcontent(p2, p3, 0, i1, i2)
         jump(p2, p3)
         """
         self.optimize_strunicode_loop(ops, expected)
@@ -3941,9 +3980,7 @@
         p3 = newstr(i3)
         strsetitem(p3, 0, i0)
         strsetitem(p3, 1, i1)
-        i4 = strlen(p2)
-        i5 = int_add(2, i4)      # will be killed by the backend
-        copystrcontent(p2, p3, 0, 2, i4)
+        copystrcontent(p2, p3, 0, 2, i2)
         jump(i1, i0, p3)
         """
         self.optimize_strunicode_loop(ops, expected)
@@ -3962,10 +3999,9 @@
         i2 = strlen(p2)
         i3 = int_add(i2, 2)
         p3 = newstr(i3)
-        i4 = strlen(p2)
-        copystrcontent(p2, p3, 0, 0, i4)
-        strsetitem(p3, i4, i0)
-        i5 = int_add(i4, 1)
+        copystrcontent(p2, p3, 0, 0, i2)
+        strsetitem(p3, i2, i0)
+        i5 = int_add(i2, 1)
         strsetitem(p3, i5, i1)
         i6 = int_add(i5, 1)      # will be killed by the backend
         jump(i1, i0, p3)
@@ -3987,14 +4023,9 @@
         i3 = strlen(p3)
         i123 = int_add(i12, i3)
         p5 = newstr(i123)
-        i1b = strlen(p1)
-        copystrcontent(p1, p5, 0, 0, i1b)
-        i2b = strlen(p2)
-        i12b = int_add(i1b, i2b)
-        copystrcontent(p2, p5, 0, i1b, i2b)
-        i3b = strlen(p3)
-        i123b = int_add(i12b, i3b)      # will be killed by the backend
-        copystrcontent(p3, p5, 0, i12b, i3b)
+        copystrcontent(p1, p5, 0, 0, i1)
+        copystrcontent(p2, p5, 0, i1, i2)
+        copystrcontent(p3, p5, 0, i12, i3)
         jump(p2, p3, p5)
         """
         self.optimize_strunicode_loop(ops, expected)
@@ -4010,10 +4041,8 @@
         i2 = strlen(p2)
         i3 = int_add(i2, 1)
         p3 = newstr(i3)
-        i4 = strlen(p2)
-        copystrcontent(p2, p3, 0, 0, i4)
-        strsetitem(p3, i4, 120)     # == ord('x')
-        i5 = int_add(i4, 1)      # will be killed by the backend
+        copystrcontent(p2, p3, 0, 0, i2)
+        strsetitem(p3, i2, 120)     # == ord('x')
         jump(p3)
         """
         self.optimize_strunicode_loop(ops, expected)
@@ -4131,9 +4160,7 @@
         i5 = int_add(i3, i4)
         p4 = newstr(i5)
         copystrcontent(p1, p4, i1, 0, i3)
-        i4b = strlen(p2)
-        i6 = int_add(i3, i4b)    # killed by the backend
-        copystrcontent(p2, p4, 0, i3, i4b)
+        copystrcontent(p2, p4, 0, i3, i4)
         jump(p4, i1, i2, p2)
         """
         self.optimize_strunicode_loop(ops, expected)
@@ -4178,11 +4205,8 @@
         i2 = strlen(p2)
         i3 = int_add(i1, i2)
         p4 = newstr(i3)
-        i4 = strlen(p1)
-        copystrcontent(p1, p4, 0, 0, i4)
-        i5 = strlen(p2)
-        i6 = int_add(i4, i5)      # will be killed by the backend
-        copystrcontent(p2, p4, 0, i4, i5)
+        copystrcontent(p1, p4, 0, 0, i1)
+        copystrcontent(p2, p4, 0, i1, i2)
         i0 = call(0, p3, p4, descr=strequaldescr)
         escape(i0)
         jump(p1, p2, p3)
@@ -4374,11 +4398,8 @@
         i2 = strlen(p2)
         i3 = int_add(i1, i2)
         p4 = newstr(i3)
-        i4 = strlen(p1)
-        copystrcontent(p1, p4, 0, 0, i4)
-        i5 = strlen(p2)
-        i6 = int_add(i4, i5)      # will be killed by the backend
-        copystrcontent(p2, p4, 0, i4, i5)
+        copystrcontent(p1, p4, 0, 0, i1)
+        copystrcontent(p2, p4, 0, i1, i2)
         i0 = call(0, s"hello world", p4, descr=streq_nonnull_descr)
         escape(i0)
         jump(p1, p2)
@@ -4532,6 +4553,39 @@
         """
         self.optimize_loop(ops, expected)
 
+    def test_strslice_subtraction_folds(self):
+        ops = """
+        [p0, i0]
+        i1 = int_add(i0, 1)
+        p1 = call(0, p0, i0, i1, descr=strslicedescr)
+        escape(p1)
+        jump(p0, i1)
+        """
+        expected = """
+        [p0, i0]
+        i1 = int_add(i0, 1)
+        p1 = newstr(1)
+        i2 = strgetitem(p0, i0)
+        strsetitem(p1, 0, i2)
+        escape(p1)
+        jump(p0, i1)
+        """
+        self.optimize_strunicode_loop(ops, expected)
+
+    def test_float_mul_reversed(self):
+        ops = """
+        [f0, f1]
+        f2 = float_mul(f0, f1)
+        f3 = float_mul(f1, f0)
+        jump(f2, f3)
+        """
+        expected = """
+        [f0, f1]
+        f2 = float_mul(f0, f1)
+        jump(f2, f2)
+        """
+        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
@@ -3074,11 +3074,11 @@
     def test_residual_call_invalidate_some_arrays(self):
         ops = """
         [p1, p2, i1]
-        p3 = getarrayitem_gc(p1, 0, descr=arraydescr2)
+        p3 = getarrayitem_gc(p2, 0, descr=arraydescr2)
         p4 = getarrayitem_gc(p2, 1, descr=arraydescr2)
         i2 = getarrayitem_gc(p1, 1, descr=arraydescr)
         i3 = call(i1, descr=writearraydescr)
-        p5 = getarrayitem_gc(p1, 0, descr=arraydescr2)
+        p5 = getarrayitem_gc(p2, 0, descr=arraydescr2)
         p6 = getarrayitem_gc(p2, 1, descr=arraydescr2)
         i4 = getarrayitem_gc(p1, 1, descr=arraydescr)
         escape(p3)
@@ -3091,7 +3091,7 @@
         """
         expected = """
         [p1, p2, i1]
-        p3 = getarrayitem_gc(p1, 0, descr=arraydescr2)
+        p3 = getarrayitem_gc(p2, 0, descr=arraydescr2)
         p4 = getarrayitem_gc(p2, 1, descr=arraydescr2)
         i2 = getarrayitem_gc(p1, 1, descr=arraydescr)
         i3 = call(i1, descr=writearraydescr)
@@ -5343,11 +5343,8 @@
         i2 = strlen(p2)
         i3 = int_add(i1, i2)
         p3 = newstr(i3)
-        i4 = strlen(p1)
-        copystrcontent(p1, p3, 0, 0, i4)
-        i5 = strlen(p2)
-        i6 = int_add(i4, i5)      # will be killed by the backend
-        copystrcontent(p2, p3, 0, i4, i5)
+        copystrcontent(p1, p3, 0, 0, i1)
+        copystrcontent(p2, p3, 0, i1, i2)
         jump(p2, p3)
         """
         self.optimize_strunicode_loop(ops, expected, expected)
@@ -5368,9 +5365,7 @@
         p3 = newstr(i3)
         strsetitem(p3, 0, i0)
         strsetitem(p3, 1, i1)
-        i4 = strlen(p2)
-        i5 = int_add(2, i4)      # will be killed by the backend
-        copystrcontent(p2, p3, 0, 2, i4)
+        copystrcontent(p2, p3, 0, 2, i2)
         jump(i1, i0, p3)
         """
         self.optimize_strunicode_loop(ops, expected, expected)
@@ -5389,10 +5384,9 @@
         i2 = strlen(p2)
         i3 = int_add(i2, 2)
         p3 = newstr(i3)
-        i4 = strlen(p2)
-        copystrcontent(p2, p3, 0, 0, i4)
-        strsetitem(p3, i4, i0)
-        i5 = int_add(i4, 1)
+        copystrcontent(p2, p3, 0, 0, i2)
+        strsetitem(p3, i2, i0)
+        i5 = int_add(i2, 1)
         strsetitem(p3, i5, i1)
         i6 = int_add(i5, 1)      # will be killed by the backend
         jump(i1, i0, p3)
@@ -5414,14 +5408,9 @@
         i3 = strlen(p3)
         i123 = int_add(i12, i3)
         p5 = newstr(i123)
-        i1b = strlen(p1)
-        copystrcontent(p1, p5, 0, 0, i1b)
-        i2b = strlen(p2)
-        i12b = int_add(i1b, i2b)
-        copystrcontent(p2, p5, 0, i1b, i2b)
-        i3b = strlen(p3)
-        i123b = int_add(i12b, i3b)      # will be killed by the backend
-        copystrcontent(p3, p5, 0, i12b, i3b)
+        copystrcontent(p1, p5, 0, 0, i1)
+        copystrcontent(p2, p5, 0, i1, i2)
+        copystrcontent(p3, p5, 0, i12, i3)
         jump(p2, p3, p5)
         """
         self.optimize_strunicode_loop(ops, expected, expected)
@@ -5437,10 +5426,8 @@
         i2 = strlen(p2)
         i3 = int_add(i2, 1)
         p3 = newstr(i3)
-        i4 = strlen(p2)
-        copystrcontent(p2, p3, 0, 0, i4)
-        strsetitem(p3, i4, 120)     # == ord('x')
-        i5 = int_add(i4, 1)      # will be killed by the backend
+        copystrcontent(p2, p3, 0, 0, i2)
+        strsetitem(p3, i2, 120)     # == ord('x')
         jump(p3)
         """
         self.optimize_strunicode_loop(ops, expected, expected)
@@ -5599,9 +5586,7 @@
         i5 = int_add(i3, i4)
         p4 = newstr(i5)
         copystrcontent(p1, p4, i1, 0, i3)
-        i4b = strlen(p2)
-        i6 = int_add(i3, i4b)    # killed by the backend
-        copystrcontent(p2, p4, 0, i3, i4b)
+        copystrcontent(p2, p4, 0, i3, i4)
         jump(p4, i1, i2, p2)
         """
         self.optimize_strunicode_loop(ops, expected, expected)
@@ -5711,11 +5696,8 @@
         i2 = strlen(p2)
         i3 = int_add(i1, i2)
         p4 = newstr(i3)
-        i4 = strlen(p1)
-        copystrcontent(p1, p4, 0, 0, i4)
-        i5 = strlen(p2)
-        i6 = int_add(i4, i5)      # will be killed by the backend
-        copystrcontent(p2, p4, 0, i4, i5)
+        copystrcontent(p1, p4, 0, 0, i1)
+        copystrcontent(p2, p4, 0, i1, i2)
         i0 = call(0, p3, p4, descr=strequaldescr)
         escape(i0)
         jump(p1, p2, p3)
@@ -5939,11 +5921,8 @@
         i2 = strlen(p2)
         i3 = int_add(i1, i2)
         p4 = newstr(i3)
-        i4 = strlen(p1)
-        copystrcontent(p1, p4, 0, 0, i4)
-        i5 = strlen(p2)
-        i6 = int_add(i4, i5)      # will be killed by the backend
-        copystrcontent(p2, p4, 0, i4, i5)
+        copystrcontent(p1, p4, 0, 0, i1)
+        copystrcontent(p2, p4, 0, i1, i2)
         i0 = call(0, s"hello world", p4, descr=streq_nonnull_descr)
         escape(i0)
         jump(p1, p2)
diff --git a/pypy/jit/metainterp/optimizeopt/util.py b/pypy/jit/metainterp/optimizeopt/util.py
--- a/pypy/jit/metainterp/optimizeopt/util.py
+++ b/pypy/jit/metainterp/optimizeopt/util.py
@@ -20,9 +20,25 @@
         if op_prefix and not name.startswith(op_prefix):
             continue
         if hasattr(Class, name_prefix + name):
-            result.append((value, getattr(Class, name_prefix + name)))
+            opclass = resoperation.opclasses[getattr(rop, name)]
+            assert name in opclass.__name__
+            result.append((value, opclass, getattr(Class, name_prefix + name)))
     return unrolling_iterable(result)
 
+def make_dispatcher_method(Class, name_prefix, op_prefix=None, default=None):
+    ops = _findall(Class, name_prefix, op_prefix)
+    def dispatch(self, op, *args):
+        opnum = op.getopnum()
+        for value, cls, func in ops:
+            if opnum == value:
+                assert isinstance(op, cls)
+                return func(self, op, *args)
+        if default:
+            return default(self, op, *args)
+    dispatch.func_name = "dispatch_" + name_prefix
+    return dispatch
+
+
 def partition(array, left, right):
     last_item = array[right]
     pivot = last_item.sort_key()
diff --git a/pypy/jit/metainterp/optimizeopt/virtualize.py b/pypy/jit/metainterp/optimizeopt/virtualize.py
--- a/pypy/jit/metainterp/optimizeopt/virtualize.py
+++ b/pypy/jit/metainterp/optimizeopt/virtualize.py
@@ -1,7 +1,7 @@
 from pypy.jit.metainterp.history import Const, ConstInt, BoxInt
 from pypy.jit.metainterp.resoperation import rop, ResOperation
-from pypy.jit.metainterp.optimizeopt.util import _findall, sort_descrs
-from pypy.jit.metainterp.optimizeopt.util import descrlist_dict
+from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
+from pypy.jit.metainterp.optimizeopt.util import descrlist_dict, sort_descrs
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.jit.metainterp.optimizeopt import optimizer
 from pypy.jit.metainterp.optimizeopt.optimizer import OptValue
@@ -475,13 +475,8 @@
         ###self.heap_op_optimizer.optimize_SETARRAYITEM_GC(op, value, fieldvalue)
         self.emit_operation(op)
 
-    def propagate_forward(self, op):
-        opnum = op.getopnum()
-        for value, func in optimize_ops:
-            if opnum == value:
-                func(self, op)
-                break
-        else:
-            self.emit_operation(op)
 
-optimize_ops = _findall(OptVirtualize, 'optimize_')
+dispatch_opt = make_dispatcher_method(OptVirtualize, 'optimize_',
+        default=OptVirtualize.emit_operation)
+
+OptVirtualize.propagate_forward = dispatch_opt
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
@@ -8,7 +8,7 @@
 from pypy.jit.metainterp.optimizeopt import optimizer, virtualize
 from pypy.jit.metainterp.optimizeopt.optimizer import CONST_0, CONST_1
 from pypy.jit.metainterp.optimizeopt.optimizer import llhelper
-from pypy.jit.metainterp.optimizeopt.util import _findall
+from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
 from pypy.jit.codewriter.effectinfo import EffectInfo
 from pypy.jit.codewriter import heaptracker
 from pypy.rlib.unroll import unrolling_iterable
@@ -61,7 +61,7 @@
         self.ensure_nonnull()
         box = self.force_box()
         lengthbox = BoxInt()
-        optimization.emit_operation(ResOperation(mode.STRLEN, [box], lengthbox))
+        optimization.optimize_default(ResOperation(mode.STRLEN, [box], lengthbox))
         return lengthbox
 
     @specialize.arg(1)
@@ -72,13 +72,13 @@
         else:
             return None
 
-    def string_copy_parts(self, optimization, targetbox, offsetbox, mode):
+    def string_copy_parts(self, optimizer, targetbox, offsetbox, mode):
         # Copies the pointer-to-string 'self' into the target string
         # given by 'targetbox', at the specified offset.  Returns the offset
         # at the end of the copy.
-        lengthbox = self.getstrlen(optimization, mode)
+        lengthbox = self.getstrlen(optimizer, mode)
         srcbox = self.force_box()
-        return copy_str_content(optimization, srcbox, targetbox,
+        return copy_str_content(optimizer, srcbox, targetbox,
                                 CONST_0, offsetbox, lengthbox, mode)
 
 
@@ -335,7 +335,7 @@
     if optimizer is None:
         return None
     resbox = BoxInt()
-    optimizer.emit_operation(ResOperation(rop.INT_ADD, [box1, box2], resbox))
+    optimizer.optimize_default(ResOperation(rop.INT_ADD, [box1, box2], resbox))
     return resbox
 
 def _int_sub(optimizer, box1, box2):
@@ -345,10 +345,10 @@
         if isinstance(box1, ConstInt):
             return ConstInt(box1.value - box2.value)
     resbox = BoxInt()
-    optimizer.emit_operation(ResOperation(rop.INT_SUB, [box1, box2], resbox))
+    optimizer.optimize_default(ResOperation(rop.INT_SUB, [box1, box2], resbox))
     return resbox
 
-def _strgetitem(optimization, strbox, indexbox, mode):
+def _strgetitem(optimizer, strbox, indexbox, mode):
     if isinstance(strbox, ConstPtr) and isinstance(indexbox, ConstInt):
         if mode is mode_string:
             s = strbox.getref(lltype.Ptr(rstr.STR))
@@ -357,7 +357,7 @@
             s = strbox.getref(lltype.Ptr(rstr.UNICODE))
             return ConstInt(ord(s.chars[indexbox.getint()]))
     resbox = BoxInt()
-    optimization.emit_operation(ResOperation(mode.STRGETITEM, [strbox, indexbox],
+    optimizer.optimize_default(ResOperation(mode.STRGETITEM, [strbox, indexbox],
                                       resbox))
     return resbox
 
@@ -443,7 +443,7 @@
             if vindex.is_constant():
                 return value.getitem(vindex.box.getint())
         #
-        resbox = _strgetitem(self, value.force_box(), vindex.force_box(), mode)
+        resbox = _strgetitem(self.optimizer, value.force_box(), vindex.force_box(), mode)
         return self.getvalue(resbox)
 
     def optimize_STRLEN(self, op):
@@ -453,7 +453,7 @@
 
     def _optimize_STRLEN(self, op, mode):
         value = self.getvalue(op.getarg(0))
-        lengthbox = value.getstrlen(self, mode)
+        lengthbox = value.getstrlen(self.optimizer, mode)
         self.make_equal_to(op.result, self.getvalue(lengthbox))
 
     def optimize_CALL(self, op):
@@ -652,16 +652,11 @@
             self.emit_operation(op)
             return
 
-        opnum = op.getopnum()
-        for value, func in optimize_ops:
-            if opnum == value:
-                func(self, op)
-                break
-        else:
-            self.emit_operation(op)
+        dispatch_opt(self, op)
 
 
-optimize_ops = _findall(OptString, 'optimize_')
+dispatch_opt = make_dispatcher_method(OptString, 'optimize_',
+        default=OptString.emit_operation)
 
 def _findall_call_oopspec():
     prefix = 'opt_call_stroruni_'
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
@@ -56,6 +56,8 @@
         # for resume.py operation
         self.parent_resumedata_snapshot = None
         self.parent_resumedata_frame_info_list = None
+        # counter for unrolling inlined loops
+        self.unroll_iterations = 1
 
     @specialize.arg(3)
     def copy_constants(self, registers, constants, ConstClass):
@@ -310,26 +312,27 @@
                 self.opimpl_goto_if_not(condbox, target)
         ''' % (_opimpl, _opimpl.upper())).compile()
 
+
+    def _establish_nullity(self, box, orgpc):
+        value = box.nonnull()
+        if value:
+            if box not in self.metainterp.known_class_boxes:
+                self.generate_guard(rop.GUARD_NONNULL, box, resumepc=orgpc)
+        else:
+            if not isinstance(box, Const):
+                self.generate_guard(rop.GUARD_ISNULL, box, resumepc=orgpc)
+                promoted_box = box.constbox()
+                self.metainterp.replace_box(box, promoted_box)
+        return value
+
     @arguments("orgpc", "box", "label")
     def opimpl_goto_if_not_ptr_nonzero(self, orgpc, box, target):
-        value = box.nonnull()
-        if value:
-            opnum = rop.GUARD_NONNULL
-        else:
-            opnum = rop.GUARD_ISNULL
-        self.generate_guard(opnum, box, resumepc=orgpc)
-        if not value:
+        if not self._establish_nullity(box, orgpc):
             self.pc = target
 
     @arguments("orgpc", "box", "label")
     def opimpl_goto_if_not_ptr_iszero(self, orgpc, box, target):
-        value = box.nonnull()
-        if value:
-            opnum = rop.GUARD_NONNULL
-        else:
-            opnum = rop.GUARD_ISNULL
-        self.generate_guard(opnum, box, resumepc=orgpc)
-        if value:
+        if self._establish_nullity(box, orgpc):
             self.pc = target
 
     @arguments("box", "box", "box")
@@ -364,7 +367,9 @@
     def opimpl_new_with_vtable(self, sizedescr):
         cpu = self.metainterp.cpu
         cls = heaptracker.descr2vtable(cpu, sizedescr)
-        return self.execute(rop.NEW_WITH_VTABLE, ConstInt(cls))
+        resbox = self.execute(rop.NEW_WITH_VTABLE, ConstInt(cls))
+        self.metainterp.known_class_boxes[resbox] = None
+        return resbox
 
 ##    @FixME  #arguments("box")
 ##    def opimpl_runtimenew(self, classbox):
@@ -387,8 +392,21 @@
 
     @arguments("box", "descr", "box")
     def _opimpl_getarrayitem_gc_any(self, arraybox, arraydescr, indexbox):
-        return self.execute_with_descr(rop.GETARRAYITEM_GC,
-                                       arraydescr, arraybox, indexbox)
+        cache = self.metainterp.heap_array_cache.get(arraydescr, None)
+        if cache and isinstance(indexbox, ConstInt):
+            index = indexbox.getint()
+            frombox, tobox = cache.get(index, (None, None))
+            if frombox is arraybox:
+                return tobox
+        resbox = self.execute_with_descr(rop.GETARRAYITEM_GC,
+                                         arraydescr, arraybox, indexbox)
+        if isinstance(indexbox, ConstInt):
+            if not cache:
+                cache = self.metainterp.heap_array_cache[arraydescr] = {}
+            index = indexbox.getint()
+            cache[index] = arraybox, resbox
+        return resbox
+
 
     opimpl_getarrayitem_gc_i = _opimpl_getarrayitem_gc_any
     opimpl_getarrayitem_gc_r = _opimpl_getarrayitem_gc_any
@@ -416,6 +434,13 @@
                                     indexbox, itembox):
         self.execute_with_descr(rop.SETARRAYITEM_GC, arraydescr, arraybox,
                                 indexbox, itembox)
+        if isinstance(indexbox, ConstInt):
+            cache = self.metainterp.heap_array_cache.setdefault(arraydescr, {})
+            cache[indexbox.getint()] = arraybox, itembox
+        else:
+            cache = self.metainterp.heap_array_cache.get(arraydescr, None)
+            if cache:
+                cache.clear()
 
     opimpl_setarrayitem_gc_i = _opimpl_setarrayitem_gc_any
     opimpl_setarrayitem_gc_r = _opimpl_setarrayitem_gc_any
@@ -451,21 +476,17 @@
     def opimpl_newlist(self, structdescr, lengthdescr, itemsdescr, arraydescr,
                        sizebox):
         sbox = self.metainterp.execute_and_record(rop.NEW, structdescr)
-        self.metainterp.execute_and_record(rop.SETFIELD_GC, lengthdescr,
-                                           sbox, sizebox)
+        self._opimpl_setfield_gc_any(sbox, lengthdescr, sizebox)
         abox = self.metainterp.execute_and_record(rop.NEW_ARRAY, arraydescr,
                                                   sizebox)
-        self.metainterp.execute_and_record(rop.SETFIELD_GC, itemsdescr,
-                                           sbox, abox)
+        self._opimpl_setfield_gc_any(sbox, itemsdescr, abox)
         return sbox
 
     @arguments("box", "descr", "descr", "box")
     def _opimpl_getlistitem_gc_any(self, listbox, itemsdescr, arraydescr,
                                    indexbox):
-        arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC,
-                                                      itemsdescr, listbox)
-        return self.execute_with_descr(rop.GETARRAYITEM_GC,
-                                       arraydescr, arraybox, indexbox)
+        arraybox = self._opimpl_getfield_gc_any(listbox, itemsdescr)
+        return self._opimpl_getarrayitem_gc_any(arraybox, arraydescr, indexbox)
 
     opimpl_getlistitem_gc_i = _opimpl_getlistitem_gc_any
     opimpl_getlistitem_gc_r = _opimpl_getlistitem_gc_any
@@ -474,10 +495,9 @@
     @arguments("box", "descr", "descr", "box", "box")
     def _opimpl_setlistitem_gc_any(self, listbox, itemsdescr, arraydescr,
                                    indexbox, valuebox):
-        arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC,
-                                                      itemsdescr, listbox)
-        self.execute_with_descr(rop.SETARRAYITEM_GC, arraydescr, arraybox,
-                                indexbox, valuebox)
+        arraybox = self._opimpl_getfield_gc_any(listbox, itemsdescr)
+        self._opimpl_setarrayitem_gc_any(arraybox, arraydescr, indexbox,
+                                         valuebox)
 
     opimpl_setlistitem_gc_i = _opimpl_setlistitem_gc_any
     opimpl_setlistitem_gc_r = _opimpl_setlistitem_gc_any
@@ -499,18 +519,29 @@
 
     @arguments("box", "descr")
     def _opimpl_getfield_gc_any(self, box, fielddescr):
-        return self.execute_with_descr(rop.GETFIELD_GC, fielddescr, box)
+        return self._opimpl_getfield_gc_any_pureornot(
+                rop.GETFIELD_GC, box, fielddescr)
     opimpl_getfield_gc_i = _opimpl_getfield_gc_any
     opimpl_getfield_gc_r = _opimpl_getfield_gc_any
     opimpl_getfield_gc_f = _opimpl_getfield_gc_any
 
     @arguments("box", "descr")
     def _opimpl_getfield_gc_pure_any(self, box, fielddescr):
-        return self.execute_with_descr(rop.GETFIELD_GC_PURE, fielddescr, box)
+        return self._opimpl_getfield_gc_any_pureornot(
+                rop.GETFIELD_GC_PURE, box, fielddescr)
     opimpl_getfield_gc_i_pure = _opimpl_getfield_gc_pure_any
     opimpl_getfield_gc_r_pure = _opimpl_getfield_gc_pure_any
     opimpl_getfield_gc_f_pure = _opimpl_getfield_gc_pure_any
 
+    @specialize.arg(1)
+    def _opimpl_getfield_gc_any_pureornot(self, opnum, box, fielddescr):
+        frombox, tobox = self.metainterp.heap_cache.get(fielddescr, (None, None))
+        if frombox is box:
+            return tobox
+        resbox = self.execute_with_descr(opnum, fielddescr, box)
+        self.metainterp.heap_cache[fielddescr] = (box, resbox)
+        return resbox
+
     @arguments("orgpc", "box", "descr")
     def _opimpl_getfield_gc_greenfield_any(self, pc, box, fielddescr):
         ginfo = self.metainterp.jitdriver_sd.greenfield_info
@@ -529,7 +560,11 @@
 
     @arguments("box", "descr", "box")
     def _opimpl_setfield_gc_any(self, box, fielddescr, valuebox):
+        frombox, tobox = self.metainterp.heap_cache.get(fielddescr, (None, None))
+        if frombox is box and tobox is valuebox:
+            return
         self.execute_with_descr(rop.SETFIELD_GC, fielddescr, box, valuebox)
+        self.metainterp.heap_cache[fielddescr] = (box, valuebox)
     opimpl_setfield_gc_i = _opimpl_setfield_gc_any
     opimpl_setfield_gc_r = _opimpl_setfield_gc_any
     opimpl_setfield_gc_f = _opimpl_setfield_gc_any
@@ -593,12 +628,16 @@
         standard_box = self.metainterp.virtualizable_boxes[-1]
         if standard_box is box:
             return False
+        if box in self.metainterp.nonstandard_virtualizables:
+            return True
         eqbox = self.metainterp.execute_and_record(rop.PTR_EQ, None,
                                                    box, standard_box)
         eqbox = self.implement_guard_value(pc, eqbox)
         isstandard = eqbox.getint()
         if isstandard:
             self.metainterp.replace_box(box, standard_box)
+        else:
+            self.metainterp.nonstandard_virtualizables[box] = None
         return not isstandard
 
     def _get_virtualizable_field_index(self, fielddescr):
@@ -610,7 +649,7 @@
     @arguments("orgpc", "box", "descr")
     def _opimpl_getfield_vable(self, pc, box, fielddescr):
         if self._nonstandard_virtualizable(pc, box):
-            return self.execute_with_descr(rop.GETFIELD_GC, fielddescr, box)
+            return self._opimpl_getfield_gc_any(box, fielddescr)
         self.metainterp.check_synchronized_virtualizable()
         index = self._get_virtualizable_field_index(fielddescr)
         return self.metainterp.virtualizable_boxes[index]
@@ -622,8 +661,7 @@
     @arguments("orgpc", "box", "descr", "box")
     def _opimpl_setfield_vable(self, pc, box, fielddescr, valuebox):
         if self._nonstandard_virtualizable(pc, box):
-            self.execute_with_descr(rop.SETFIELD_GC, fielddescr, box, valuebox)
-            return
+            return self._opimpl_setfield_gc_any(box, fielddescr, valuebox)
         index = self._get_virtualizable_field_index(fielddescr)
         self.metainterp.virtualizable_boxes[index] = valuebox
         self.metainterp.synchronize_virtualizable()
@@ -653,10 +691,8 @@
     @arguments("orgpc", "box", "descr", "descr", "box")
     def _opimpl_getarrayitem_vable(self, pc, box, fdescr, adescr, indexbox):
         if self._nonstandard_virtualizable(pc, box):
-            arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC,
-                                                          fdescr, box)
-            return self.execute_with_descr(rop.GETARRAYITEM_GC, adescr,
-                                           arraybox, indexbox)
+            arraybox = self._opimpl_getfield_gc_any(box, fdescr)
+            return self._opimpl_getarrayitem_gc_any(arraybox, adescr, indexbox)
         self.metainterp.check_synchronized_virtualizable()
         index = self._get_arrayitem_vable_index(pc, fdescr, indexbox)
         return self.metainterp.virtualizable_boxes[index]
@@ -669,10 +705,9 @@
     def _opimpl_setarrayitem_vable(self, pc, box, fdescr, adescr, indexbox,
                                   valuebox):
         if self._nonstandard_virtualizable(pc, box):
-            arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC,
-                                                          fdescr, box)
-            self.execute_with_descr(rop.SETARRAYITEM_GC, adescr,
-                                    arraybox, indexbox, valuebox)
+            arraybox = self._opimpl_getfield_gc_any(box, fdescr)
+            self._opimpl_setarrayitem_gc_any(arraybox, adescr,
+                                             indexbox, valuebox)
             return
         index = self._get_arrayitem_vable_index(pc, fdescr, indexbox)
         self.metainterp.virtualizable_boxes[index] = valuebox
@@ -686,8 +721,7 @@
     @arguments("orgpc", "box", "descr", "descr")
     def opimpl_arraylen_vable(self, pc, box, fdescr, adescr):
         if self._nonstandard_virtualizable(pc, box):
-            arraybox = self.metainterp.execute_and_record(rop.GETFIELD_GC,
-                                                          fdescr, box)
+            arraybox = self._opimpl_getfield_gc_any(box, fdescr)
             return self.execute_with_descr(rop.ARRAYLEN_GC, adescr, arraybox)
         vinfo = self.metainterp.jitdriver_sd.virtualizable_info
         virtualizable_box = self.metainterp.virtualizable_boxes[-1]
@@ -845,7 +879,9 @@
     @arguments("orgpc", "box")
     def opimpl_guard_class(self, orgpc, box):
         clsbox = self.cls_of_box(box)
-        self.generate_guard(rop.GUARD_CLASS, box, [clsbox], resumepc=orgpc)
+        if box not in self.metainterp.known_class_boxes:
+            self.generate_guard(rop.GUARD_CLASS, box, [clsbox], resumepc=orgpc)
+            self.metainterp.known_class_boxes[box] = None
         return clsbox
 
     @arguments("int", "orgpc")
@@ -897,6 +933,10 @@
             # 'redboxes' back into the registers where it comes from.
             put_back_list_of_boxes3(self, jcposition, redboxes)
         else:
+            if jitdriver_sd.warmstate.should_unroll_one_iteration(greenboxes):
+                if self.unroll_iterations > 0:
+                    self.unroll_iterations -= 1
+                    return
             # warning! careful here.  We have to return from the current
             # frame containing the jit_merge_point, and then use
             # do_recursive_call() to follow the recursive call.  This is
@@ -1128,13 +1168,11 @@
             metainterp.jitdriver_sd.greenfield_info is not None):
             virtualizable_boxes = metainterp.virtualizable_boxes
         saved_pc = self.pc
-        try:
-            if resumepc >= 0:
-                self.pc = resumepc
-            resume.capture_resumedata(metainterp.framestack, virtualizable_boxes,
-                                      metainterp.virtualref_boxes, resumedescr)
-        finally:
-            self.pc = saved_pc
+        if resumepc >= 0:
+            self.pc = resumepc
+        resume.capture_resumedata(metainterp.framestack, virtualizable_boxes,
+                                  metainterp.virtualref_boxes, resumedescr)
+        self.pc = saved_pc
 
     def implement_guard_value(self, orgpc, box):
         """Promote the given Box into a Const.  Note: be careful, it's a
@@ -1449,6 +1487,16 @@
         self.last_exc_value_box = None
         self.retracing_loop_from = None
         self.call_pure_results = args_dict_box()
+        # contains boxes where the class is already known
+        self.known_class_boxes = {}
+        # contains frame boxes that are not virtualizables
+        self.nonstandard_virtualizables = {}
+        # heap cache
+        # maps descrs to (from_box, to_box) tuples
+        self.heap_cache = {}
+        # heap array cache
+        # maps descrs to {index: (from_box, to_box)} dicts
+        self.heap_array_cache = {}
 
     def perform_call(self, jitcode, boxes, greenkey=None):
         # causes the metainterp to enter the given subfunction
@@ -1624,10 +1672,27 @@
         # record the operation
         profiler = self.staticdata.profiler
         profiler.count_ops(opnum, RECORDED_OPS)
+        self._invalidate_caches(opnum, descr)
         op = self.history.record(opnum, argboxes, resbox, descr)
         self.attach_debug_info(op)
         return resbox
 
+    def _invalidate_caches(self, opnum, descr):
+        if opnum == rop.SETFIELD_GC:
+            return
+        if opnum == rop.SETARRAYITEM_GC:
+            return
+        if rop._NOSIDEEFFECT_FIRST <= opnum <= rop._NOSIDEEFFECT_LAST:
+            return
+        if opnum == rop.CALL:
+            effectinfo = descr.get_extra_info()
+            if effectinfo.extraeffect == effectinfo.EF_ELIDABLE:
+                return
+        if self.heap_cache:
+            self.heap_cache.clear()
+        if self.heap_array_cache:
+            self.heap_array_cache.clear()
+
     def attach_debug_info(self, op):
         if (not we_are_translated() and op is not None
             and getattr(self, 'framestack', None)):
@@ -1789,6 +1854,11 @@
                 duplicates[box] = None
 
     def reached_loop_header(self, greenboxes, redboxes, resumedescr):
+        self.known_class_boxes = {}
+        self.nonstandard_virtualizables = {} # XXX maybe not needed?
+        self.heap_cache = {}
+        self.heap_array_cache = {}
+
         duplicates = {}
         self.remove_consts_and_duplicates(redboxes, len(redboxes),
                                           duplicates)
@@ -2295,6 +2365,16 @@
             for i in range(len(boxes)):
                 if boxes[i] is oldbox:
                     boxes[i] = newbox
+        for descr, (frombox, tobox) in self.heap_cache.iteritems():
+            change = False
+            if frombox is oldbox:
+                change = True
+                frombox = newbox
+            if tobox is oldbox:
+                change = True
+                tobox = newbox
+            if change:
+                self.heap_cache[descr] = frombox, tobox
 
     def find_biggest_function(self):
         start_stack = []
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
@@ -281,9 +281,6 @@
         assert len(args) == 2
         self._arg0, self._arg1 = args
 
-    def getarglist(self):
-        return [self._arg0, self._arg1, self._arg2]
-
     def numargs(self):
         return 2
 
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
@@ -11,7 +11,7 @@
 from pypy import conftest
 from pypy.rlib.rarithmetic import ovfcheck
 from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper
-from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.lltypesystem import lltype, llmemory, rffi
 from pypy.rpython.ootypesystem import ootype
 from pypy.jit.metainterp.optimizeopt import ALL_OPTS_DICT
 from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
@@ -542,6 +542,32 @@
         assert res == 84 - 61 - 62
         self.check_history(call=1)   # because the trace starts immediately
 
+    def test_unroll_one_loop_iteration(self):
+        def unroll(code):
+            return code == 0
+        myjitdriver = JitDriver(greens = ['code'],
+                                reds = ['loops', 'inner_loops', 's'],
+                                should_unroll_one_iteration=unroll)
+
+        def f(code, loops, inner_loops):
+            s = 0
+            while loops > 0:
+                myjitdriver.jit_merge_point(code=code, loops=loops,
+                                            inner_loops=inner_loops, s=s)
+                if code == 1:
+                    s += f(0, inner_loops, 0)
+                loops -= 1
+                s += 1
+            return s
+
+        res = self.meta_interp(f, [1, 4, 1], enable_opts="", inline=True)
+        assert res == f(1, 4, 1)
+        self.check_history(call_assembler=0)
+
+        res = self.meta_interp(f, [1, 4, 2], enable_opts="", inline=True)
+        assert res == f(1, 4, 2)
+        self.check_history(call_assembler=1)
+
     def test_format(self):
         def f(n):
             return len("<%d>" % n)
@@ -1018,11 +1044,14 @@
             pass
         class B(A):
             pass
+        @dont_look_inside
+        def extern(n):
+            if n:
+                return A()
+            else:
+                return B()
         def fn(n):
-            if n:
-                obj = A()
-            else:
-                obj = B()
+            obj = extern(n)
             return isinstance(obj, B)
         res = self.interp_operations(fn, [0])
         assert res
@@ -1055,6 +1084,7 @@
         res = self.meta_interp(main, [])
         assert res == 55
 
+
     def test_assert_isinstance(self):
         class A:
             pass
@@ -1215,7 +1245,7 @@
             return tup[1]
         res = self.interp_operations(f, [3, 5])
         assert res == 5
-        self.check_operations_history(setfield_gc=2, getfield_gc_pure=1)
+        self.check_operations_history(setfield_gc=2, getfield_gc_pure=0)
 
     def test_oosend_look_inside_only_one(self):
         class A:
@@ -1583,8 +1613,6 @@
         assert res == 1
 
     def test_raw_malloc_and_access(self):
-        from pypy.rpython.lltypesystem import rffi
-
         TP = rffi.CArray(lltype.Signed)
 
         def f(n):
@@ -1598,8 +1626,6 @@
         assert res == 10
 
     def test_raw_malloc_and_access_float(self):
-        from pypy.rpython.lltypesystem import rffi
-
         TP = rffi.CArray(lltype.Float)
 
         def f(n, f):
@@ -2130,7 +2156,7 @@
                 myjitdriver.jit_merge_point(a=a, b=b, n=n, sa=sa)
                 if 0 < a <= 5: pass
                 if 0 < b <= 5: pass
-                sa += (((((a << b) << b) << b) >> b) >> b) >> b                
+                sa += (((((a << b) << b) << b) >> b) >> b) >> b
                 n += 1
             return sa
 
@@ -2140,10 +2166,10 @@
                 myjitdriver.jit_merge_point(a=a, b=b, n=n, sa=sa)
                 if 0 < a < promote(sys.maxint/2): pass
                 if 0 < b < 100: pass
-                sa += (((((a << b) << b) << b) >> b) >> b) >> b                
+                sa += (((((a << b) << b) << b) >> b) >> b) >> b
                 n += 1
             return sa
-        
+
         assert self.meta_interp(f1, [5, 5]) == 50
         self.check_loops(int_rshift=0, everywhere=True)
 
@@ -2175,7 +2201,7 @@
                 myjitdriver.jit_merge_point(a=a, b=b, n=n, sa=sa)
                 if -5 <= a < 0: pass
                 if 0 < b <= 5: pass
-                sa += (((((a << b) << b) << b) >> b) >> b) >> b                
+                sa += (((((a << b) << b) << b) >> b) >> b) >> b
                 n += 1
             return sa
 
@@ -2185,10 +2211,10 @@
                 myjitdriver.jit_merge_point(a=a, b=b, n=n, sa=sa)
                 if -promote(sys.maxint/2) < a < 0: pass
                 if 0 < b < 100: pass
-                sa += (((((a << b) << b) << b) >> b) >> b) >> b                
+                sa += (((((a << b) << b) << b) >> b) >> b) >> b
                 n += 1
             return sa
-        
+
         assert self.meta_interp(f1, [-5, 5]) == -50
         self.check_loops(int_rshift=0, everywhere=True)
 
@@ -2243,7 +2269,7 @@
 
         def get_printable_location(i):
             return str(i)
-        
+
         myjitdriver = JitDriver(greens = ['i'], reds = ['j', 'c', 'a'],
                                 get_printable_location=get_printable_location)
         bytecode = "0j10jc20a3"
@@ -2352,7 +2378,7 @@
         assert self.meta_interp(build, []) == 7
         self.check_loops(getfield_gc_pure=0)
         self.check_loops(getfield_gc_pure=2, everywhere=True)
-        
+
     def test_args_becomming_equal(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa', 'a', 'b'])
         def f(n, a, b):
@@ -2707,7 +2733,7 @@
             return sa
         res = self.meta_interp(f, [])
         assert res == f()
-        
+
     def test_frame_finished_during_continued_retrace(self):
         class Base(object):
             pass
@@ -2758,7 +2784,67 @@
         assert res == -2
         #self.check_loops(getarrayitem_gc=0, setarrayitem_gc=0) -- xxx?
 
-    def test_continue_tracing_with_boxes_in_start_snapshot_replaced_by_optimizer(self):
+    def test_retrace_ending_up_retracing_another_loop(self):
+
+        myjitdriver = JitDriver(greens = ['pc'], reds = ['n', 'i', 'sa'])
+        bytecode = "0+sI0+SI"
+        def f(n):
+            myjitdriver.set_param('threshold', 3)
+            myjitdriver.set_param('trace_eagerness', 1)
+            myjitdriver.set_param('retrace_limit', 5)
+            myjitdriver.set_param('function_threshold', -1)
+            pc = sa = i = 0
+            while pc < len(bytecode):
+                myjitdriver.jit_merge_point(pc=pc, n=n, sa=sa, i=i)
+                n = hint(n, promote=True)
+                op = bytecode[pc]
+                if op == '0':
+                    i = 0
+                elif op == '+':
+                    i += 1
+                elif op == 's':
+                    sa += i
+                elif op == 'S':
+                    sa += 2
+                elif op == 'I':
+                    if i < n:
+                        pc -= 2
+                        myjitdriver.can_enter_jit(pc=pc, n=n, sa=sa, i=i)
+                        continue
+                pc += 1
+            return sa
+
+        def g(n1, n2):
+            for i in range(10):
+                f(n1)
+            for i in range(10):
+                f(n2)
+
+        nn = [10, 3]
+        assert self.meta_interp(g, nn) == g(*nn)
+
+        # The attempts of retracing first loop will end up retracing the
+        # second and thus fail 5 times, saturating the retrace_count. Instead a
+        # bridge back to the preamble of the first loop is produced. A guard in
+        # this bridge is later traced resulting in a retrace of the second loop.
+        # Thus we end up with:
+        #   1 preamble and 1 specialized version of first loop
+        #   1 preamble and 2 specialized version of second loop
+        self.check_tree_loop_count(2 + 3)
+
+        # FIXME: Add a gloabl retrace counter and test that we are not trying more than 5 times.
+
+        def g(n):
+            for i in range(n):
+                for j in range(10):
+                    f(n-i)
+
+        res = self.meta_interp(g, [10])
+        assert res == g(10)
+        # 1 preamble and 6 speciealized versions of each loop
+        self.check_tree_loop_count(2*(1 + 6))
+
+   def test_continue_tracing_with_boxes_in_start_snapshot_replaced_by_optimizer(self):
         myjitdriver = JitDriver(greens = [], reds = ['sa', 'n', 'a', 'b'])
         def f(n):
             sa = a = 0
@@ -2798,6 +2884,11 @@
         assert res == f(32)
         self.check_loops(arraylen_gc=1)
 
+
+
+
+        
+        
 class TestOOtype(BasicTests, OOJitMixin):
 
     def test_oohash(self):
@@ -3066,6 +3157,59 @@
         res = self.meta_interp(f, [32])
         assert res == f(32)
         self.check_loops(arraylen_gc=1, everywhere=True)
+        
+    def test_release_gil_flush_heap_cache(self):
+        T = rffi.CArrayPtr(rffi.TIME_T)
+
+        external = rffi.llexternal("time", [T], rffi.TIME_T, threadsafe=True)
+        # Not a real lock, has all the same properties with respect to GIL
+        # release though, so good for this test.
+        class Lock(object):
+            @dont_look_inside
+            def acquire(self):
+                external(lltype.nullptr(T.TO))
+            @dont_look_inside
+            def release(self):
+                external(lltype.nullptr(T.TO))
+        class X(object):
+            def __init__(self, idx):
+                self.field = idx
+        @dont_look_inside
+        def get_obj(z):
+            return X(z)
+        myjitdriver = JitDriver(greens=[], reds=["n", "l", "z", "lock"])
+        def f(n, z):
+            lock = Lock()
+            l = 0
+            while n > 0:
+                myjitdriver.jit_merge_point(lock=lock, l=l, n=n, z=z)
+                x = get_obj(z)
+                l += x.field
+                lock.acquire()
+                # This must not reuse the previous one.
+                n -= x.field
+                lock.release()
+            return n
+        res = self.meta_interp(f, [10, 1])
+        self.check_loops(getfield_gc=2)
+        assert res == f(10, 1)
+
+    def test_jit_merge_point_with_raw_pointer(self):
+        driver = JitDriver(greens = [], reds = ['n', 'x'])
+
+        TP = lltype.Array(lltype.Signed, hints={'nolength': True})
+
+        def f(n):
+            x = lltype.malloc(TP, 10, flavor='raw')
+            x[0] = 1
+            while n > 0:
+                driver.jit_merge_point(n=n, x=x)
+                n -= x[0]
+            lltype.free(x, flavor='raw')
+            return n
+
+        self.meta_interp(f, [10], repeat=3)
+        
 
 class TestLLtype(BaseLLtypeTests, LLJitMixin):
     pass
diff --git a/pypy/jit/metainterp/test/test_immutable.py b/pypy/jit/metainterp/test/test_immutable.py
--- a/pypy/jit/metainterp/test/test_immutable.py
+++ b/pypy/jit/metainterp/test/test_immutable.py
@@ -1,5 +1,9 @@
+from pypy.rlib import jit
 from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 
+ at jit.dont_look_inside
+def escape(x):
+    return x
 
 class ImmutableFieldsTests:
 
@@ -11,7 +15,7 @@
                 self.x = x
 
         def f(x):
-            y = X(x)
+            y = escape(X(x))
             return y.x + 5
         res = self.interp_operations(f, [23])
         assert res == 28
@@ -33,7 +37,7 @@
 
         def f(x, y):
             X(x)     # force the field 'x' to be on class 'X'
-            z = Y(x, y)
+            z = escape(Y(x, y))
             return z.x + z.y + 5
         res = self.interp_operations(f, [23, 11])
         assert res == 39
@@ -42,7 +46,7 @@
 
         def f(x, y):
             # this time, the field 'x' only shows up on subclass 'Y'
-            z = Y(x, y)
+            z = escape(Y(x, y))
             return z.x + z.y + 5
         res = self.interp_operations(f, [23, 11])
         assert res == 39
@@ -58,7 +62,7 @@
         def f(index):
             l = [1, 2, 3, 4]
             l[2] = 30
-            a = X(l)
+            a = escape(X(l))
             return a.y[index]
         res = self.interp_operations(f, [2], listops=True)
         assert res == 30
@@ -76,7 +80,7 @@
                 self.y = y
 
         def f(x, index):
-            y = X([x], x+1)
+            y = escape(X([x], x+1))
             return y.lst[index] + y.y + 5
         res = self.interp_operations(f, [23, 0], listops=True)
         assert res == 23 + 24 + 5
diff --git a/pypy/jit/metainterp/test/test_tracingopts.py b/pypy/jit/metainterp/test/test_tracingopts.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/metainterp/test/test_tracingopts.py
@@ -0,0 +1,407 @@
+import py
+import sys
+from pypy.rlib import jit
+from pypy.jit.metainterp.test.support import LLJitMixin
+
+
+class TestLLtype(LLJitMixin):
+    def test_dont_record_repeated_guard_class(self):
+        class A:
+            pass
+        class B(A):
+            pass
+        @jit.dont_look_inside
+        def extern(n):
+            if n == -7:
+                return None
+            elif n:
+                return A()
+            else:
+                return B()
+        def fn(n):
+            obj = extern(n)
+            return isinstance(obj, B) + isinstance(obj, B) + isinstance(obj, B) + isinstance(obj, B)
+        res = self.interp_operations(fn, [0])
+        assert res == 4
+        self.check_operations_history(guard_class=1, guard_nonnull=1)
+        res = self.interp_operations(fn, [1])
+        assert not res
+
+    def test_dont_record_guard_class_after_new(self):
+        class A:
+            pass
+        class B(A):
+            pass
+        def fn(n):
+            if n == -7:
+                obj = None
+            elif n:
+                obj = A()
+            else:
+                obj = B()
+            return isinstance(obj, B) + isinstance(obj, B) + isinstance(obj, B) + isinstance(obj, B)
+        res = self.interp_operations(fn, [0])
+        assert res == 4
+        self.check_operations_history(guard_class=0, guard_nonnull=0)
+        res = self.interp_operations(fn, [1])
+        assert not res
+
+    def test_guard_isnull_nullifies(self):
+        class A:
+            pass
+        a = A()
+        a.x = None
+        def fn(n):
+            if n == -7:
+                a.x = ""
+            obj = a.x
+            res = 0
+            if not obj:
+                res += 1
+            if obj:
+                res += 1
+            if obj is None:
+                res += 1
+            if obj is not None:
+                res += 1
+            return res
+        res = self.interp_operations(fn, [0])
+        assert res == 2
+        self.check_operations_history(guard_isnull=1)
+
+    def test_heap_caching_while_tracing(self):
+        class A:
+            pass
+        a1 = A()
+        a2 = A()
+        def fn(n):
+            if n > 0:
+                a = a1
+            else:
+                a = a2
+            a.x = n
+            return a.x
+        res = self.interp_operations(fn, [7])
+        assert res == 7
+        self.check_operations_history(getfield_gc=0)
+        res = self.interp_operations(fn, [-7])
+        assert res == -7
+        self.check_operations_history(getfield_gc=0)
+
+        def fn(n, ca, cb):
+            a1.x = n
+            a2.x = n
+            a = a1
+            if ca:
+                a = a2
+            b = a1
+            if cb:
+                b = a
+            return a.x + b.x
+        res = self.interp_operations(fn, [7, 0, 1])
+        assert res == 7 * 2
+        self.check_operations_history(getfield_gc=1)
+        res = self.interp_operations(fn, [-7, 1, 1])
+        assert res == -7 * 2
+        self.check_operations_history(getfield_gc=1)
+
+    def test_heap_caching_while_tracing_invalidation(self):
+        class A:
+            pass
+        a1 = A()
+        a2 = A()
+        @jit.dont_look_inside
+        def f(a):
+            a.x = 5
+        l = [1]
+        def fn(n):
+            if n > 0:
+                a = a1
+            else:
+                a = a2
+            a.x = n
+            x1 = a.x
+            f(a)
+            x2 = a.x
+            l[0] = x2
+            return a.x + x1 + x2
+        res = self.interp_operations(fn, [7])
+        assert res == 5 * 2 + 7
+        self.check_operations_history(getfield_gc=1)
+
+    def test_heap_caching_dont_store_same(self):
+        class A:
+            pass
+        a1 = A()
+        a2 = A()
+        def fn(n):
+            if n > 0:
+                a = a1
+            else:
+                a = a2
+            a.x = n
+            a.x = n
+            return a.x
+        res = self.interp_operations(fn, [7])
+        assert res == 7
+        self.check_operations_history(getfield_gc=0, setfield_gc=1)
+        res = self.interp_operations(fn, [-7])
+        assert res == -7
+        self.check_operations_history(getfield_gc=0)
+
+    def test_array_caching(self):
+        a1 = [0, 0]
+        a2 = [0, 0]
+        def fn(n):
+            if n > 0:
+                a = a1
+            else:
+                a = a2
+            a[0] = n
+            x1 = a[0]
+            a[n - n] = n + 1
+            return a[0] + x1
+        res = self.interp_operations(fn, [7])
+        assert res == 7 + 7 + 1
+        self.check_operations_history(getarrayitem_gc=1)
+        res = self.interp_operations(fn, [-7])
+        assert res == -7 - 7 + 1
+        self.check_operations_history(getarrayitem_gc=1)
+
+        def fn(n, ca, cb):
+            a1[0] = n
+            a2[0] = n
+            a = a1
+            if ca:
+                a = a2
+            b = a1
+            if cb:
+                b = a
+            return a[0] + b[0]
+        res = self.interp_operations(fn, [7, 0, 1])
+        assert res == 7 * 2
+        self.check_operations_history(getarrayitem_gc=1)
+        res = self.interp_operations(fn, [-7, 1, 1])
+        assert res == -7 * 2
+        self.check_operations_history(getarrayitem_gc=1)
+
+    def test_array_caching_while_tracing_invalidation(self):
+        a1 = [0, 0]
+        a2 = [0, 0]
+        @jit.dont_look_inside
+        def f(a):
+            a[0] = 5
+        class A: pass
+        l = A()
+        def fn(n):
+            if n > 0:
+                a = a1
+            else:
+                a = a2
+            a[0] = n
+            x1 = a[0]
+            f(a)
+            x2 = a[0]
+            l.x = x2
+            return a[0] + x1 + x2
+        res = self.interp_operations(fn, [7])
+        assert res == 5 * 2 + 7
+        self.check_operations_history(getarrayitem_gc=1)
+
+    def test_array_and_getfield_interaction(self):
+        class A: pass
+        a1 = A()
+        a2 = A()
+        a1.l = a2.l = [0, 0]
+        def fn(n):
+            if n > 0:
+                a = a1
+            else:
+                a = a2
+                a.l = [0, 0]
+            a.x = 0
+            a.l[a.x] = n
+            a.x += 1
+            a.l[a.x] = n + 1
+            x1 = a.l[a.x]
+            a.x -= 1
+            x2 = a.l[a.x]
+            return x1 + x2
+        res = self.interp_operations(fn, [7])
+        assert res == 7 * 2 + 1
+        self.check_operations_history(setarrayitem_gc=2, setfield_gc=3,
+                                      getarrayitem_gc=0, getfield_gc=1)
+
+    def test_promote_changes_heap_cache(self):
+        class A: pass
+        a1 = A()
+        a2 = A()
+        a1.l = a2.l = [0, 0]
+        a1.x = a2.x = 0
+        def fn(n):
+            if n > 0:
+                a = a1
+            else:
+                a = a2
+                a.l = [0, 0]
+            jit.promote(a.x)
+            a.l[a.x] = n
+            a.x += 1
+            a.l[a.x] = n + 1
+            x1 = a.l[a.x]
+            a.x -= 1
+            x2 = a.l[a.x]
+            return x1 + x2
+        res = self.interp_operations(fn, [7])
+        assert res == 7 * 2 + 1
+        self.check_operations_history(setarrayitem_gc=2, setfield_gc=2,
+                                      getarrayitem_gc=0, getfield_gc=2)
+
+    def test_list_caching(self):
+        a1 = [0, 0]
+        a2 = [0, 0]
+        def fn(n):
+            if n > 0:
+                a = a1
+            else:
+                a = a2
+                if n < -1000:
+                    a.append(5)
+            a[0] = n
+            x1 = a[0]
+            a[n - n] = n + 1
+            return a[0] + x1
+        res = self.interp_operations(fn, [7])
+        assert res == 7 + 7 + 1
+        self.check_operations_history(getarrayitem_gc=1,
+                getfield_gc=1)
+        res = self.interp_operations(fn, [-7])
+        assert res == -7 - 7 + 1
+        self.check_operations_history(getarrayitem_gc=1,
+                getfield_gc=1)
+
+        def fn(n, ca, cb):
+            a1[0] = n
+            a2[0] = n
+            a = a1
+            if ca:
+                a = a2
+                if n < -100:
+                    a.append(5)
+            b = a1
+            if cb:
+                b = a
+            return a[0] + b[0]
+        res = self.interp_operations(fn, [7, 0, 1])
+        assert res == 7 * 2
+        self.check_operations_history(getarrayitem_gc=1,
+                getfield_gc=3)
+        res = self.interp_operations(fn, [-7, 1, 1])
+        assert res == -7 * 2
+        self.check_operations_history(getarrayitem_gc=1,
+                getfield_gc=3)
+
+    def test_list_caching_negative(self):
+        def fn(n):
+            a = [0] * n
+            if n > 1000:
+                a.append(0)
+            a[-1] = n
+            x1 = a[-1]
+            a[n - n - 1] = n + 1
+            return a[-1] + x1
+        res = self.interp_operations(fn, [7])
+        assert res == 7 + 7 + 1
+        self.check_operations_history(setarrayitem_gc=2,
+                setfield_gc=2)
+
+    def test_virtualizable_with_array_heap_cache(self):
+        myjitdriver = jit.JitDriver(greens = [], reds = ['n', 'x', 'i', 'frame'],
+                                    virtualizables = ['frame'])
+
+        class Frame(object):
+            _virtualizable2_ = ['l[*]', 's']
+
+            def __init__(self, a, s):
+                self = jit.hint(self, access_directly=True, fresh_virtualizable=True)
+                self.l = [0] * (4 + a)
+                self.s = s
+
+        def f(n, a, i):
+            frame = Frame(a, 0)
+            frame.l[0] = a
+            frame.l[1] = a + 1
+            frame.l[2] = a + 2
+            frame.l[3] = a + 3
+            if not i:
+                return frame.l[0] + len(frame.l)
+            x = 0
+            while n > 0:
+                myjitdriver.can_enter_jit(frame=frame, n=n, x=x, i=i)
+                myjitdriver.jit_merge_point(frame=frame, n=n, x=x, i=i)
+                frame.s = jit.promote(frame.s)
+                n -= 1
+                s = frame.s
+                assert s >= 0
+                x += frame.l[s]
+                frame.s += 1
+                s = frame.s
+                assert s >= 0
+                x += frame.l[s]
+                x += len(frame.l)
+                x += f(n, n, 0)
+                frame.s -= 1
+            return x
+
+        res = self.meta_interp(f, [10, 1, 1], listops=True)
+        assert res == f(10, 1, 1)
+        self.check_history(getarrayitem_gc=0, getfield_gc=0)
+
+    def test_heap_caching_pure(self):
+        class A(object):
+            pass
+        p1 = A()
+        p2 = A()
+        def fn(n):
+            if n >= 0:
+                a = (n, n + 1)
+                p = p1
+            else:
+                a = (n + 1, n)
+                p = p2
+            p.x = a
+
+            return p.x[0] + p.x[1]
+        res = self.interp_operations(fn, [7])
+        assert res == 7 + 7 + 1
+        self.check_operations_history(getfield_gc=0, getfield_gc_pure=0)
+        res = self.interp_operations(fn, [-7])
+        assert res == -7 - 7 + 1
+        self.check_operations_history(getfield_gc=0, getfield_gc_pure=0)
+
+    def test_heap_caching_and_elidable_function(self):
+        class A:
+            pass
+        class B: pass
+        a1 = A()
+        a1.y = 6
+        a2 = A()
+        a2.y = 13
+        @jit.elidable
+        def f(b):
+            return b + 1
+        def fn(n):
+            if n > 0:
+                a = a1
+            else:
+                a = A()
+            a.x = n
+            z = f(6)
+            return z + a.x
+        res = self.interp_operations(fn, [7])
+        assert res == 7 + 7
+        self.check_operations_history(getfield_gc=0)
+        res = self.interp_operations(fn, [-7])
+        assert res == -7 + 7
+        self.check_operations_history(getfield_gc=0)
+        return
diff --git a/pypy/jit/metainterp/test/test_virtualizable.py b/pypy/jit/metainterp/test/test_virtualizable.py
--- a/pypy/jit/metainterp/test/test_virtualizable.py
+++ b/pypy/jit/metainterp/test/test_virtualizable.py
@@ -377,7 +377,7 @@
         expected = f(20)
         res = self.meta_interp(f, [20], enable_opts='')
         assert res == expected
-        self.check_loops(getfield_gc=3, setfield_gc=0,
+        self.check_loops(getfield_gc=1, setfield_gc=0,
                          arraylen_gc=1, getarrayitem_gc=1, setarrayitem_gc=1)
 
     # ------------------------------
@@ -1133,6 +1133,7 @@
          res = self.meta_interp(f, [10])
          assert res == 55
          self.check_loops(new_with_vtable=0, ptr_eq=1, everywhere=True)
+         self.check_history(ptr_eq=2)
 
     def test_virtual_child_frame_with_arrays(self):
         myjitdriver = JitDriver(greens = [], reds = ['frame'],
diff --git a/pypy/jit/metainterp/warmspot.py b/pypy/jit/metainterp/warmspot.py
--- a/pypy/jit/metainterp/warmspot.py
+++ b/pypy/jit/metainterp/warmspot.py
@@ -10,6 +10,7 @@
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.rlib.debug import fatalerror
+from pypy.rlib.rstackovf import StackOverflow
 from pypy.translator.simplify import get_functype
 from pypy.translator.unsimplify import call_final_function
 
@@ -408,21 +409,28 @@
         jd.warmstate = state
 
         def crash_in_jit(e):
-            if not we_are_translated():
-                print "~~~ Crash in JIT!"
-                print '~~~ %s: %s' % (e.__class__, e)
-                if sys.stdout == sys.__stdout__:
-                    import pdb; pdb.post_mortem(sys.exc_info()[2])
-                raise
-            fatalerror('~~~ Crash in JIT! %s' % (e,), traceback=True)
+            try:
+                raise e
+            except JitException:
+                raise     # go through
+            except MemoryError:
+                raise     # go through
+            except StackOverflow:
+                raise     # go through
+            except Exception, e:
+                if not we_are_translated():
+                    print "~~~ Crash in JIT!"
+                    print '~~~ %s: %s' % (e.__class__, e)
+                    if sys.stdout == sys.__stdout__:
+                        import pdb; pdb.post_mortem(sys.exc_info()[2])
+                    raise
+                fatalerror('~~~ Crash in JIT! %s' % (e,), traceback=True)
         crash_in_jit._dont_inline_ = True
 
         if self.translator.rtyper.type_system.name == 'lltypesystem':
             def maybe_enter_jit(*args):
                 try:
                     maybe_compile_and_run(state.increment_threshold, *args)
-                except JitException:
-                    raise     # go through
                 except Exception, e:
                     crash_in_jit(e)
             maybe_enter_jit._always_inline_ = True
@@ -460,6 +468,9 @@
                 onlygreens=False)
             jd._can_never_inline_ptr = self._make_hook_graph(jd,
                 annhelper, jd.jitdriver.can_never_inline, annmodel.s_Bool)
+            jd._should_unroll_one_iteration_ptr = self._make_hook_graph(jd,
+                annhelper, jd.jitdriver.should_unroll_one_iteration,
+                annmodel.s_Bool)
         annhelper.finish()
 
     def _make_hook_graph(self, jitdriver_sd, annhelper, func,
diff --git a/pypy/jit/metainterp/warmstate.py b/pypy/jit/metainterp/warmstate.py
--- a/pypy/jit/metainterp/warmstate.py
+++ b/pypy/jit/metainterp/warmstate.py
@@ -138,7 +138,10 @@
         refvalue = cpu.ts.cast_to_ref(value)
         cpu.set_future_value_ref(j, refvalue)
     elif typecode == 'int':
-        intvalue = lltype.cast_primitive(lltype.Signed, value)
+        if isinstance(lltype.typeOf(value), lltype.Ptr):
+            intvalue = llmemory.AddressAsInt(llmemory.cast_ptr_to_adr(value))
+        else:
+            intvalue = lltype.cast_primitive(lltype.Signed, value)
         cpu.set_future_value_int(j, intvalue)
     elif typecode == 'float':
         if lltype.typeOf(value) is lltype.Float:
@@ -569,6 +572,19 @@
             return can_inline_greenargs(*greenargs)
         self.can_inline_greenargs = can_inline_greenargs
         self.can_inline_callable = can_inline_callable
+
+        if jd._should_unroll_one_iteration_ptr is None:
+            def should_unroll_one_iteration(greenkey):
+                return False
+        else:
+            rtyper = self.warmrunnerdesc.rtyper
+            inline_ptr = jd._should_unroll_one_iteration_ptr
+            def should_unroll_one_iteration(greenkey):
+                greenargs = unwrap_greenkey(greenkey)
+                fn = support.maybe_on_top_of_llinterp(rtyper, inline_ptr)
+                return fn(*greenargs)
+        self.should_unroll_one_iteration = should_unroll_one_iteration
+        
         if hasattr(jd.jitdriver, 'on_compile'):
             def on_compile(logger, token, operations, type, greenkey):
                 greenargs = unwrap_greenkey(greenkey)
diff --git a/pypy/jit/tool/oparser.py b/pypy/jit/tool/oparser.py
--- a/pypy/jit/tool/oparser.py
+++ b/pypy/jit/tool/oparser.py
@@ -337,6 +337,11 @@
                 num += 1
         return num, ops, last_offset
 
+    def postprocess(self, loop):
+        """ A hook that can be overloaded to do some postprocessing
+        """
+        return loop
+
     def parse_offset(self, line):
         if line.startswith('+'):
             # it begins with an offset, like: "+10: i1 = int_add(...)"
diff --git a/pypy/module/__builtin__/abstractinst.py b/pypy/module/__builtin__/abstractinst.py
--- a/pypy/module/__builtin__/abstractinst.py
+++ b/pypy/module/__builtin__/abstractinst.py
@@ -58,7 +58,10 @@
 
     # -- case (anything, type)
     try:
-        w_result = space.isinstance(w_obj, w_klass_or_tuple, allow_override)
+        if allow_override:
+            w_result = space.isinstance_allow_override(w_obj, w_klass_or_tuple)
+        else:
+            w_result = space.isinstance(w_obj, w_klass_or_tuple)
     except OperationError, e:   # if w_klass_or_tuple was not a type, ignore it
         if not e.match(space, space.w_TypeError):
             raise       # propagate other errors
@@ -72,8 +75,11 @@
             w_pretendtype = space.getattr(w_obj, space.wrap('__class__'))
             if space.is_w(w_pretendtype, space.type(w_obj)):
                 return False     # common case: obj.__class__ is type(obj)
-            w_result = space.issubtype(w_pretendtype, w_klass_or_tuple,
-                                       allow_override)
+            if allow_override:
+                w_result = space.issubtype_allow_override(w_pretendtype,
+                                                          w_klass_or_tuple)
+            else:
+                w_result = space.issubtype(w_pretendtype, w_klass_or_tuple)
         except OperationError, e:
             if e.async(space):
                 raise
@@ -134,7 +140,11 @@
 
     # -- case (type, type)
     try:
-        w_result = space.issubtype(w_derived, w_klass_or_tuple, allow_override)
+        if allow_override:
+            w_result = space.issubtype_allow_override(w_derived,
+                                                      w_klass_or_tuple)
+        else:
+            w_result = space.issubtype(w_derived, w_klass_or_tuple)
     except OperationError, e:   # if one of the args was not a type, ignore it
         if not e.match(space, space.w_TypeError):
             raise       # propagate other errors
diff --git a/pypy/module/__builtin__/compiling.py b/pypy/module/__builtin__/compiling.py
--- a/pypy/module/__builtin__/compiling.py
+++ b/pypy/module/__builtin__/compiling.py
@@ -5,7 +5,7 @@
 from pypy.interpreter.pycode import PyCode
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.astcompiler import consts, ast
-from pypy.interpreter.gateway import NoneNotWrapped, unwrap_spec
+from pypy.interpreter.gateway import unwrap_spec
 
 @unwrap_spec(filename=str, mode=str, flags=int, dont_inherit=int)
 def compile(space, w_source, filename, mode, flags=0, dont_inherit=0):
diff --git a/pypy/module/__builtin__/descriptor.py b/pypy/module/__builtin__/descriptor.py
--- a/pypy/module/__builtin__/descriptor.py
+++ b/pypy/module/__builtin__/descriptor.py
@@ -1,12 +1,10 @@
-
-from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.error import OperationError
+from pypy.interpreter.function import StaticMethod, ClassMethod
 from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.interpreter.error import OperationError, operationerrfmt
-from pypy.objspace.descroperation import object_getattribute, object_setattr
-from pypy.interpreter.function import StaticMethod, ClassMethod
-from pypy.interpreter.typedef import GetSetProperty, descr_get_dict, \
-     descr_set_dict, interp_attrproperty_w, generic_new_descr
+from pypy.interpreter.typedef import (TypeDef, interp_attrproperty_w,
+    generic_new_descr)
+from pypy.objspace.descroperation import object_getattribute
 
 class W_Super(Wrappable):
     def __init__(self, space, w_starttype, w_objtype, w_self):
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
@@ -4,13 +4,12 @@
 """
 
 from pypy.interpreter.error import OperationError
-from pypy.interpreter.gateway import NoneNotWrapped, applevel
+from pypy.interpreter.gateway import NoneNotWrapped
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.rlib.rarithmetic import r_uint, intmask
 from pypy.rlib.objectmodel import specialize
-from inspect import getsource, getfile
 from pypy.rlib.rbigint import rbigint
 
 
@@ -662,7 +661,6 @@
 
     def descr_reduce(self):
         from pypy.interpreter.mixedmodule import MixedModule
-        from pypy.module._pickle_support import maker # helper fns
         space    = self.space
         w_mod    = space.getbuiltinmodule('_pickle_support')
         mod      = space.interp_w(MixedModule, w_mod)
diff --git a/pypy/module/__builtin__/interp_classobj.py b/pypy/module/__builtin__/interp_classobj.py
--- a/pypy/module/__builtin__/interp_classobj.py
+++ b/pypy/module/__builtin__/interp_classobj.py
@@ -1,11 +1,9 @@
 import new
 from pypy.interpreter.error import OperationError, operationerrfmt
-from pypy.interpreter.gateway import NoneNotWrapped, applevel, interp2app
+from pypy.interpreter.gateway import interp2app
 from pypy.interpreter.typedef import TypeDef, make_weakref_descr
 from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.typedef import GetSetProperty, descr_get_dict
-from pypy.interpreter.typedef import descr_set_dict
-from pypy.rlib.rarithmetic import r_uint, intmask
+from pypy.interpreter.typedef import GetSetProperty, descr_get_dict, descr_set_dict
 from pypy.rlib.objectmodel import compute_identity_hash
 from pypy.rlib.debug import make_sure_not_resized
 from pypy.rlib import jit
@@ -420,7 +418,7 @@
         if w_meth is not None:
             space.call_function(w_meth, w_name)
         else:
-            if not self.deldictvalue(space, w_name):
+            if not self.deldictvalue(space, name):
                 raise operationerrfmt(
                     space.w_AttributeError,
                     "%s instance has no attribute '%s'",
diff --git a/pypy/module/__builtin__/interp_memoryview.py b/pypy/module/__builtin__/interp_memoryview.py
--- a/pypy/module/__builtin__/interp_memoryview.py
+++ b/pypy/module/__builtin__/interp_memoryview.py
@@ -2,7 +2,7 @@
 Implementation of the 'buffer' and 'memoryview' types.
 """
 from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter import gateway, buffer
+from pypy.interpreter import buffer
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from pypy.interpreter.error import OperationError
diff --git a/pypy/module/__builtin__/operation.py b/pypy/module/__builtin__/operation.py
--- a/pypy/module/__builtin__/operation.py
+++ b/pypy/module/__builtin__/operation.py
@@ -4,12 +4,10 @@
 
 from pypy.interpreter import gateway
 from pypy.interpreter.error import OperationError
-from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.interpreter.typedef import TypeDef
+from pypy.interpreter.gateway import unwrap_spec
 from pypy.rlib.runicode import UNICHR
 from pypy.rlib.rfloat import isnan, isinf, round_double
 from pypy.rlib import rfloat
-import math
 import __builtin__
 NoneNotWrapped = gateway.NoneNotWrapped
 
diff --git a/pypy/module/__pypy__/__init__.py b/pypy/module/__pypy__/__init__.py
--- a/pypy/module/__pypy__/__init__.py
+++ b/pypy/module/__pypy__/__init__.py
@@ -25,6 +25,7 @@
         'debug_print_once'          : 'interp_debug.debug_print_once',
         'builtinify'                : 'interp_magic.builtinify',
         'lookup_special'            : 'interp_magic.lookup_special',
+        'do_what_I_mean'            : 'interp_magic.do_what_I_mean',
     }
 
     submodules = {
diff --git a/pypy/module/__pypy__/interp_debug.py b/pypy/module/__pypy__/interp_debug.py
--- a/pypy/module/__pypy__/interp_debug.py
+++ b/pypy/module/__pypy__/interp_debug.py
@@ -1,5 +1,4 @@
-from pypy.interpreter.gateway import interp2app, NoneNotWrapped, unwrap_spec
-from pypy.interpreter.error import OperationError
+from pypy.interpreter.gateway import unwrap_spec
 from pypy.rlib import debug, jit
 
 
diff --git a/pypy/module/__pypy__/interp_identitydict.py b/pypy/module/__pypy__/interp_identitydict.py
--- a/pypy/module/__pypy__/interp_identitydict.py
+++ b/pypy/module/__pypy__/interp_identitydict.py
@@ -1,6 +1,6 @@
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.typedef import TypeDef
-from pypy.interpreter.gateway import NoneNotWrapped, interp2app, unwrap_spec
+from pypy.interpreter.gateway import interp2app
 from pypy.interpreter.baseobjspace import Wrappable
 
 class W_IdentityDict(Wrappable):
diff --git a/pypy/module/__pypy__/interp_magic.py b/pypy/module/__pypy__/interp_magic.py
--- a/pypy/module/__pypy__/interp_magic.py
+++ b/pypy/module/__pypy__/interp_magic.py
@@ -70,3 +70,6 @@
     if w_descr is None:
         return space.w_None
     return space.get(w_descr, w_obj)
+
+def do_what_I_mean(space):
+    return space.wrap(42)
diff --git a/pypy/module/__pypy__/test/test_special.py b/pypy/module/__pypy__/test/test_special.py
--- a/pypy/module/__pypy__/test/test_special.py
+++ b/pypy/module/__pypy__/test/test_special.py
@@ -49,3 +49,8 @@
         class X:
             pass
         raises(TypeError, lookup_special, X(), "foo")
+
+    def test_do_what_I_mean(self):
+        from __pypy__ import do_what_I_mean
+        x = do_what_I_mean()
+        assert x == 42
diff --git a/pypy/module/_ast/test/test_ast.py b/pypy/module/_ast/test/test_ast.py
--- a/pypy/module/_ast/test/test_ast.py
+++ b/pypy/module/_ast/test/test_ast.py
@@ -186,6 +186,11 @@
         mod = self.get_ast("from __future__ import with_statement; import y; " \
                                "from __future__ import nested_scopes")
         raises(SyntaxError, compile, mod, "<test>", "exec")
+        mod = self.get_ast("from __future__ import division\nx = 1/2")
+        co = compile(mod, "<test>", "exec")
+        ns = {}
+        exec co in ns
+        assert ns["x"] == .5
 
     def test_field_attr_writable(self):
         import _ast as ast
@@ -245,3 +250,38 @@
         assert x.left == n1
         assert x.op == addop
         assert x.right == n3
+
+    def test_functiondef(self):
+        import _ast as ast
+        fAst = ast.FunctionDef(
+            name="foo",
+            args=ast.arguments(
+                args=[], vararg=None, kwarg=None, defaults=[],
+                kwonlyargs=[], kw_defaults=[]),
+            body=[], decorator_list=[], lineno=5, col_offset=0)
+        exprAst = ast.Interactive(body=[fAst])
+        compiled = compile(exprAst, "<foo>", "single")
+        #
+        d = {}
+        eval(compiled, d, d)
+        assert type(d['foo']) is type(lambda: 42)
+        assert d['foo']() is None
+
+    def test_missing_name(self):
+        import _ast as ast
+        n = ast.FunctionDef(name=None)
+        n.name = "foo"
+        n.name = "foo"
+        n.name = "foo"
+        assert n.name == "foo"
+
+    def test_issue793(self):
+        import _ast as ast
+        body = ast.Module([
+            ast.TryExcept([ast.Pass(lineno=2, col_offset=4)],
+                [ast.ExceptHandler(ast.Name('Exception', ast.Load(),
+                                            lineno=3, col_offset=0),
+                                   None, [], lineno=4, col_offset=0)],
+                [], lineno=1, col_offset=0)
+        ])
+        exec compile(body, '<string>', 'exec')
diff --git a/pypy/module/_codecs/interp_codecs.py b/pypy/module/_codecs/interp_codecs.py
--- a/pypy/module/_codecs/interp_codecs.py
+++ b/pypy/module/_codecs/interp_codecs.py
@@ -1,6 +1,6 @@
 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter.gateway import NoneNotWrapped, interp2app, unwrap_spec
-from pypy.rlib.rstring import StringBuilder, UnicodeBuilder
+from pypy.rlib.rstring import UnicodeBuilder
 from pypy.rlib.objectmodel import we_are_translated
 
 class CodecState(object):
diff --git a/pypy/module/_ffi/interp_ffi.py b/pypy/module/_ffi/interp_ffi.py
--- a/pypy/module/_ffi/interp_ffi.py
+++ b/pypy/module/_ffi/interp_ffi.py
@@ -1,9 +1,8 @@
-import sys
-from pypy.interpreter.baseobjspace import Wrappable, Arguments
+from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.error import OperationError, wrap_oserror, \
     operationerrfmt
-from pypy.interpreter.gateway import interp2app, NoneNotWrapped, unwrap_spec
-from pypy.interpreter.typedef import TypeDef, GetSetProperty
+from pypy.interpreter.gateway import interp2app, unwrap_spec
+from pypy.interpreter.typedef import TypeDef
 from pypy.module._rawffi.structure import W_StructureInstance, W_Structure
 #
 from pypy.rpython.lltypesystem import lltype, rffi
@@ -16,7 +15,7 @@
 class W_FFIType(Wrappable):
 
     _immutable_fields_ = ['name', 'ffitype', 'w_datashape', 'w_pointer_to']
-    
+
     def __init__(self, name, ffitype, w_datashape=None, w_pointer_to=None):
         self.name = name
         self.ffitype = ffitype
@@ -83,7 +82,6 @@
 
 
 def build_ffi_types():
-    from pypy.rlib.clibffi import FFI_TYPE_P
     types = [
         # note: most of the type name directly come from the C equivalent,
         # with the exception of bytes: in C, ubyte and char are equivalent,
@@ -149,13 +147,19 @@
         raise OperationError(space.w_TypeError, space.wrap(msg))
     return res
 
+def unwrap_truncate_int(TP, space, w_arg):
+    if space.is_true(space.isinstance(w_arg, space.w_int)):
+        return rffi.cast(TP, space.int_w(w_arg))
+    else:
+        return rffi.cast(TP, space.bigint_w(w_arg).ulonglongmask())
+unwrap_truncate_int._annspecialcase_ = 'specialize:arg(0)'
 
 # ========================================================================
 
 class W_FuncPtr(Wrappable):
 
     _immutable_fields_ = ['func', 'argtypes_w[*]', 'w_restype']
-    
+
     def __init__(self, func, argtypes_w, w_restype):
         self.func = func
         self.argtypes_w = argtypes_w
@@ -181,15 +185,14 @@
                 # note that we must check for longlong first, because either
                 # is_signed or is_unsigned returns true anyway
                 assert libffi.IS_32_BIT
-                kind = libffi.types.getkind(w_argtype.ffitype) # XXX: remove the kind
-                self.arg_longlong(space, argchain, kind, w_arg)
+                self.arg_longlong(space, argchain, w_arg)
             elif w_argtype.is_signed():
-                argchain.arg(space.int_w(w_arg))
+                argchain.arg(unwrap_truncate_int(rffi.LONG, space, w_arg))
             elif w_argtype.is_pointer():
                 w_arg = self.convert_pointer_arg_maybe(space, w_arg, w_argtype)
                 argchain.arg(intmask(space.uint_w(w_arg)))
             elif w_argtype.is_unsigned():
-                argchain.arg(intmask(space.uint_w(w_arg)))
+                argchain.arg(unwrap_truncate_int(rffi.ULONG, space, w_arg))
             elif w_argtype.is_char():
                 w_arg = space.ord(w_arg)
                 argchain.arg(space.int_w(w_arg))
@@ -202,7 +205,7 @@
                 argchain.arg_singlefloat(space.float_w(w_arg))
             elif w_argtype.is_struct():
                 # arg_raw directly takes value to put inside ll_args
-                w_arg = space.interp_w(W_StructureInstance, w_arg)                
+                w_arg = space.interp_w(W_StructureInstance, w_arg)
                 ptrval = w_arg.ll_buffer
                 argchain.arg_raw(ptrval)
             else:
@@ -220,15 +223,10 @@
             return w_arg
 
     @jit.dont_look_inside
-    def arg_longlong(self, space, argchain, kind, w_arg):
+    def arg_longlong(self, space, argchain, w_arg):
         bigarg = space.bigint_w(w_arg)
-        if kind == 'I':
-            llval = bigarg.tolonglong()
-        elif kind == 'U':
-            ullval = bigarg.toulonglong()
-            llval = rffi.cast(rffi.LONGLONG, ullval)
-        else:
-            assert False
+        ullval = bigarg.ulonglongmask()
+        llval = rffi.cast(rffi.LONGLONG, ullval)
         # this is a hack: we store the 64 bits of the long long into the
         # 64 bits of a float (i.e., a C double)
         floatval = libffi.longlong2float(llval)
@@ -404,7 +402,7 @@
         except KeyError:
             raise operationerrfmt(space.w_AttributeError,
                                   "No symbol %s found in library %s", name, self.name)
-            
+
         return W_FuncPtr(func, argtypes_w, w_restype)
 
     @unwrap_spec(name=str)
diff --git a/pypy/module/_ffi/test/test__ffi.py b/pypy/module/_ffi/test/test__ffi.py
--- a/pypy/module/_ffi/test/test__ffi.py
+++ b/pypy/module/_ffi/test/test__ffi.py
@@ -111,7 +111,6 @@
                                types.double)
         assert pow(2, 3) == 8
 
-
     def test_int_args(self):
         """
             DLLEXPORT int sum_xy(int x, int y)
@@ -119,10 +118,12 @@
                 return x+y;
             }
         """
+        import sys
         from _ffi import CDLL, types
         libfoo = CDLL(self.libfoo_name)
         sum_xy = libfoo.getfunc('sum_xy', [types.sint, types.sint], types.sint)
         assert sum_xy(30, 12) == 42
+        assert sum_xy(sys.maxint*2, 0) == -2
 
     def test_void_result(self):
         """
@@ -247,6 +248,9 @@
                                 types.ulong)
         assert sum_xy(sys.maxint, 12) == sys.maxint+12
         assert sum_xy(sys.maxint+1, 12) == sys.maxint+13
+        #
+        res = sum_xy(sys.maxint*2+3, 0)
+        assert res == 1
 
     def test_unsigned_short_args(self):
         """
@@ -375,6 +379,9 @@
         res = sum_xy(x, y)
         expected = maxint64 + 3
         assert res == expected
+        #
+        res = sum_xy(maxint64*2+3, 0)
+        assert res == 1
 
     def test_byval_argument(self):
         """
diff --git a/pypy/module/_file/interp_file.py b/pypy/module/_file/interp_file.py
--- a/pypy/module/_file/interp_file.py
+++ b/pypy/module/_file/interp_file.py
@@ -43,11 +43,17 @@
         # assume that the file and stream objects are only visible in the
         # thread that runs __del__, so no race condition should be possible
         self.clear_all_weakrefs()
+        if self.stream is not None:
+            self.enqueue_for_destruction(self.space, W_File.destructor,
+                                         'close() method of ')
+
+    def destructor(self):
+        assert isinstance(self, W_File)
         try:
             self.direct_close()
         except StreamErrors, e:
             operr = wrap_streamerror(self.space, e, self.w_name)
-            operr.write_unraisable(self.space, '__del__ of ', self)
+            raise operr
 
     def fdopenstream(self, stream, fd, mode, w_name=None):
         self.fd = fd
diff --git a/pypy/module/_file/interp_stream.py b/pypy/module/_file/interp_stream.py
--- a/pypy/module/_file/interp_stream.py
+++ b/pypy/module/_file/interp_stream.py
@@ -3,12 +3,10 @@
 from pypy.rlib.streamio import StreamErrors
 
 from pypy.interpreter.error import OperationError, wrap_oserror2
-from pypy.interpreter.gateway import ObjSpace
-from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.baseobjspace import ObjSpace, Wrappable
 from pypy.interpreter.typedef import TypeDef
 from pypy.interpreter.gateway import interp2app
 
-import os
 
 def wrap_streamerror(space, e, w_filename=None):
     if isinstance(e, streamio.StreamError):
diff --git a/pypy/module/_io/interp_bufferedio.py b/pypy/module/_io/interp_bufferedio.py
--- a/pypy/module/_io/interp_bufferedio.py
+++ b/pypy/module/_io/interp_bufferedio.py
@@ -4,7 +4,6 @@
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter.buffer import RWBuffer
-from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.rlib.rstring import StringBuilder
 from pypy.rlib.rarithmetic import r_longlong, intmask
 from pypy.tool.sourcetools import func_renamer
diff --git a/pypy/module/_io/interp_fileio.py b/pypy/module/_io/interp_fileio.py
--- a/pypy/module/_io/interp_fileio.py
+++ b/pypy/module/_io/interp_fileio.py
@@ -1,5 +1,4 @@
-from pypy.interpreter.typedef import (
-    TypeDef, interp_attrproperty, interp_attrproperty_w, GetSetProperty)
+from pypy.interpreter.typedef import TypeDef, interp_attrproperty, GetSetProperty
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.error import OperationError, wrap_oserror, wrap_oserror2
 from pypy.rlib.rarithmetic import r_longlong
diff --git a/pypy/module/_io/interp_io.py b/pypy/module/_io/interp_io.py
--- a/pypy/module/_io/interp_io.py
+++ b/pypy/module/_io/interp_io.py
@@ -6,7 +6,6 @@
     TypeDef, interp_attrproperty, generic_new_descr)
 from pypy.module.exceptions.interp_exceptions import W_IOError
 from pypy.module._io.interp_fileio import W_FileIO
-from pypy.module._io.interp_iobase import W_IOBase
 from pypy.module._io.interp_textio import W_TextIOWrapper
 from pypy.rpython.module.ll_os_stat import STAT_FIELD_TYPES
 
diff --git a/pypy/module/_io/interp_iobase.py b/pypy/module/_io/interp_iobase.py
--- a/pypy/module/_io/interp_iobase.py
+++ b/pypy/module/_io/interp_iobase.py
@@ -57,6 +57,11 @@
 
     def __del__(self):
         self.clear_all_weakrefs()
+        self.enqueue_for_destruction(self.space, W_IOBase.destructor,
+                                     'internal __del__ of ')
+
+    def destructor(self):
+        assert isinstance(self, W_IOBase)
         space = self.space
         w_closed = space.findattr(self, space.wrap('closed'))
         try:
diff --git a/pypy/module/_io/interp_textio.py b/pypy/module/_io/interp_textio.py
--- a/pypy/module/_io/interp_textio.py
+++ b/pypy/module/_io/interp_textio.py
@@ -4,7 +4,7 @@
     generic_new_descr)
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.interpreter.error import OperationError
 from pypy.rlib.rarithmetic import intmask, r_ulonglong, r_uint
 from pypy.rlib.rbigint import rbigint
 from pypy.rlib.rstring import UnicodeBuilder
diff --git a/pypy/module/_locale/interp_locale.py b/pypy/module/_locale/interp_locale.py
--- a/pypy/module/_locale/interp_locale.py
+++ b/pypy/module/_locale/interp_locale.py
@@ -1,4 +1,3 @@
-from pypy.rpython.tool import rffi_platform as platform
 from pypy.rlib import rposix
 from pypy.rlib.rarithmetic import intmask
 
diff --git a/pypy/module/_minimal_curses/fficurses.py b/pypy/module/_minimal_curses/fficurses.py
--- a/pypy/module/_minimal_curses/fficurses.py
+++ b/pypy/module/_minimal_curses/fficurses.py
@@ -2,12 +2,10 @@
 """ The ffi for rpython, need to be imported for side effects
 """
 
-import sys
 from pypy.rpython.lltypesystem import rffi
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.tool import rffi_platform
 from pypy.rpython.extfunc import register_external
-from pypy.rpython.extregistry import ExtRegistryEntry
 from pypy.module._minimal_curses import interp_curses
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 
@@ -82,7 +80,7 @@
         return res
     finally:
         rffi.free_charp(ll_cap)
-    
+
 register_external(interp_curses._curses_tigetstr, [str], str,
                   export_name='_curses.tigetstr', llimpl=tigetstr_llimpl)
 
diff --git a/pypy/module/_multibytecodec/c_codecs.py b/pypy/module/_multibytecodec/c_codecs.py
--- a/pypy/module/_multibytecodec/c_codecs.py
+++ b/pypy/module/_multibytecodec/c_codecs.py
@@ -1,4 +1,4 @@
-import py, sys
+import py
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.tool.autopath import pypydir
@@ -55,10 +55,12 @@
         "pypy_cjk_dec_init", "pypy_cjk_dec_free", "pypy_cjk_dec_chunk",
         "pypy_cjk_dec_outbuf", "pypy_cjk_dec_outlen",
         "pypy_cjk_dec_inbuf_remaining", "pypy_cjk_dec_inbuf_consumed",
+        "pypy_cjk_dec_replace_on_error",
 
         "pypy_cjk_enc_init", "pypy_cjk_enc_free", "pypy_cjk_enc_chunk",
         "pypy_cjk_enc_reset", "pypy_cjk_enc_outbuf", "pypy_cjk_enc_outlen",
         "pypy_cjk_enc_inbuf_remaining", "pypy_cjk_enc_inbuf_consumed",
+        "pypy_cjk_enc_replace_on_error",
     ] + ["pypy_cjkcodec_%s" % codec for codec in codecs],
 )
 
diff --git a/pypy/module/_multibytecodec/interp_multibytecodec.py b/pypy/module/_multibytecodec/interp_multibytecodec.py
--- a/pypy/module/_multibytecodec/interp_multibytecodec.py
+++ b/pypy/module/_multibytecodec/interp_multibytecodec.py
@@ -1,5 +1,5 @@
 from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.gateway import ObjSpace, interp2app, unwrap_spec
+from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef
 from pypy.interpreter.error import OperationError
 from pypy.module._multibytecodec import c_codecs
diff --git a/pypy/module/_multiprocessing/interp_connection.py b/pypy/module/_multiprocessing/interp_connection.py
--- a/pypy/module/_multiprocessing/interp_connection.py
+++ b/pypy/module/_multiprocessing/interp_connection.py
@@ -4,7 +4,7 @@
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.error import (
     OperationError, wrap_oserror, operationerrfmt)
-from pypy.rpython.lltypesystem import rffi, lltype, llmemory
+from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.rlib.rarithmetic import intmask
 from pypy.rlib import rpoll
 import sys
diff --git a/pypy/module/_multiprocessing/interp_semaphore.py b/pypy/module/_multiprocessing/interp_semaphore.py
--- a/pypy/module/_multiprocessing/interp_semaphore.py
+++ b/pypy/module/_multiprocessing/interp_semaphore.py
@@ -15,7 +15,6 @@
 
 if sys.platform == 'win32':
     from pypy.rlib import rwin32
-    from pypy.interpreter.error import wrap_windowserror
     from pypy.module._multiprocessing.interp_win32 import (
         handle_w, _GetTickCount)
 
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
@@ -1,4 +1,4 @@
-from pypy.interpreter.error import OperationError 
+from pypy.interpreter.error import OperationError
 from pypy.interpreter.nestedscope import Cell
 from pypy.interpreter.pycode import PyCode
 from pypy.interpreter.function import Function, Method
@@ -8,7 +8,6 @@
 from pypy.interpreter.generator import GeneratorIterator
 from pypy.rlib.objectmodel import instantiate
 from pypy.interpreter.gateway import unwrap_spec
-from pypy.objspace.std.dicttype import dictiter_typedef
 from pypy.objspace.std.iterobject import W_SeqIterObject, W_ReverseSeqIterObject
 
 
@@ -79,7 +78,7 @@
     try:
         return gateway.BuiltinCode.find(identifier)
     except KeyError:
-        raise OperationError(space.w_RuntimeError, 
+        raise OperationError(space.w_RuntimeError,
                              space.wrap("cannot unpickle builtin code: "+
                                         identifier))
 
@@ -89,7 +88,7 @@
     try:
         return function.Function.find(identifier)
     except KeyError:
-        raise OperationError(space.w_RuntimeError, 
+        raise OperationError(space.w_RuntimeError,
                              space.wrap("cannot unpickle builtin function: "+
                                         identifier))
 
diff --git a/pypy/module/_rawffi/callback.py b/pypy/module/_rawffi/callback.py
--- a/pypy/module/_rawffi/callback.py
+++ b/pypy/module/_rawffi/callback.py
@@ -2,10 +2,10 @@
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from pypy.rpython.lltypesystem import lltype, rffi
-from pypy.module._rawffi.array import get_elem, push_elem
+from pypy.module._rawffi.array import push_elem
 from pypy.module._rawffi.structure import W_Structure
-from pypy.module._rawffi.interp_rawffi import W_DataInstance, letter2tp, \
-     wrap_value, unwrap_value, unwrap_truncate_int, unpack_argshapes
+from pypy.module._rawffi.interp_rawffi import (W_DataInstance, letter2tp,
+     unwrap_value, unpack_argshapes)
 from pypy.rlib.clibffi import USERDATA_P, CallbackFuncPtr, FUNCFLAG_CDECL
 from pypy.rlib.clibffi import ffi_type_void
 from pypy.rlib import rweakref
diff --git a/pypy/module/_rawffi/interp_rawffi.py b/pypy/module/_rawffi/interp_rawffi.py
--- a/pypy/module/_rawffi/interp_rawffi.py
+++ b/pypy/module/_rawffi/interp_rawffi.py
@@ -1,7 +1,6 @@
-import sys
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.error import OperationError, wrap_oserror, operationerrfmt
-from pypy.interpreter.gateway import interp2app, NoneNotWrapped, unwrap_spec
+from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 
 from pypy.rlib.clibffi import *
@@ -15,7 +14,7 @@
     from pypy.rlib import rwin32
 
 from pypy.tool.sourcetools import func_with_new_name
-from pypy.rlib.rarithmetic import intmask, r_uint, r_singlefloat
+from pypy.rlib.rarithmetic import intmask, r_uint
 from pypy.module._rawffi.tracker import tracker
 
 TYPEMAP = {
diff --git a/pypy/module/_socket/interp_func.py b/pypy/module/_socket/interp_func.py
--- a/pypy/module/_socket/interp_func.py
+++ b/pypy/module/_socket/interp_func.py
@@ -1,9 +1,8 @@
-from pypy.interpreter.gateway import NoneNotWrapped, unwrap_spec
+from pypy.interpreter.gateway import unwrap_spec
 from pypy.module._socket.interp_socket import converted_error, W_RSocket
 from pypy.rlib import rsocket
 from pypy.rlib.rsocket import SocketError
-from pypy.rlib.rarithmetic import r_uint
-from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.interpreter.error import OperationError
 
 def gethostname(space):
     """gethostname() -> string
diff --git a/pypy/module/_ssl/interp_ssl.py b/pypy/module/_ssl/interp_ssl.py
--- a/pypy/module/_ssl/interp_ssl.py
+++ b/pypy/module/_ssl/interp_ssl.py
@@ -1,7 +1,7 @@
 from __future__ import with_statement
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.interpreter.error import OperationError
-from pypy.interpreter.baseobjspace import W_Root, ObjSpace, Wrappable
+from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.typedef import TypeDef
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 
@@ -11,7 +11,6 @@
 
 from pypy.module._socket import interp_socket
 
-import sys
 
 ## user defined constants
 X509_NAME_MAXLEN = 256
@@ -131,13 +130,13 @@
         self._issuer = lltype.malloc(rffi.CCHARP.TO, X509_NAME_MAXLEN, flavor='raw')
         self._issuer[0] = '\0'
         self.shutdown_seen_zero = False
-    
+
     def server(self):
         return self.space.wrap(rffi.charp2str(self._server))
-    
+
     def issuer(self):
         return self.space.wrap(rffi.charp2str(self._issuer))
-    
+
     def __del__(self):
         if self.peer_cert:
             libssl_X509_free(self.peer_cert)
@@ -147,7 +146,7 @@
             libssl_SSL_CTX_free(self.ctx)
         lltype.free(self._server, flavor='raw')
         lltype.free(self._issuer, flavor='raw')
-    
+
     @unwrap_spec(data='bufferstr')
     def write(self, data):
         """write(s) -> len
@@ -230,10 +229,10 @@
         raw_buf, gc_buf = rffi.alloc_buffer(num_bytes)
         while True:
             err = 0
-            
+
             count = libssl_SSL_read(self.ssl, raw_buf, num_bytes)
             err = libssl_SSL_get_error(self.ssl, count)
-        
+
             if err == SSL_ERROR_WANT_READ:
                 sockstate = check_socket_and_wait_for_timeout(self.space,
                     self.w_socket, False)
@@ -245,17 +244,17 @@
                 return self.space.wrap("")
             else:
                 sockstate = SOCKET_OPERATION_OK
-        
+
             if sockstate == SOCKET_HAS_TIMED_OUT:
                 raise ssl_error(self.space, "The read operation timed out")
             elif sockstate == SOCKET_IS_NONBLOCKING:
                 break
-        
+
             if err == SSL_ERROR_WANT_READ or err == SSL_ERROR_WANT_WRITE:
                 continue
             else:
                 break
-                
+
         if count <= 0:
             raise _ssl_seterror(self.space, self, count)
 
@@ -351,7 +350,7 @@
                 self.shutdown_seen_zero = True
                 continue
 
-            # Possibly retry shutdown until timeout or failure 
+            # Possibly retry shutdown until timeout or failure
             ssl_err = libssl_SSL_get_error(self.ssl, ret)
             if ssl_err == SSL_ERROR_WANT_READ:
                 sockstate = check_socket_and_wait_for_timeout(
@@ -397,7 +396,7 @@
         else:
             w_proto = space.w_None
 
-        bits = libssl_SSL_CIPHER_get_bits(current, 
+        bits = libssl_SSL_CIPHER_get_bits(current,
                                           lltype.nullptr(rffi.INTP.TO))
         w_bits = space.newint(bits)
 
@@ -552,7 +551,7 @@
             ext = libssl_X509_get_ext(certificate, i)
             method = libssl_X509V3_EXT_get(ext)
             if not method:
-                raise ssl_error(space, 
+                raise ssl_error(space,
                                 "No method for internalizing subjectAltName!'")
 
             with lltype.scoped_alloc(rffi.CCHARPP.TO, 1) as p_ptr:
@@ -858,7 +857,7 @@
     cert = libssl_BIO_new(libssl_BIO_s_file())
     if not cert:
         raise ssl_error(space, "Can't malloc memory to read file")
-    
+
     try:
         if libssl_BIO_read_filename(cert, filename) <= 0:
             raise ssl_error(space, "Can't open file")
@@ -873,7 +872,7 @@
             libssl_X509_free(x)
     finally:
         libssl_BIO_free(cert)
-    
+
 # this function is needed to perform locking on shared data
 # structures. (Note that OpenSSL uses a number of global data
 # structures that will be implicitly shared whenever multiple threads
diff --git a/pypy/module/_stackless/interp_coroutine.py b/pypy/module/_stackless/interp_coroutine.py
--- a/pypy/module/_stackless/interp_coroutine.py
+++ b/pypy/module/_stackless/interp_coroutine.py
@@ -15,13 +15,10 @@
 experience to decide where to set the limits.
 """
 
-from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.argument import Arguments
 from pypy.interpreter.typedef import GetSetProperty, TypeDef
-from pypy.interpreter.typedef import interp_attrproperty, interp_attrproperty_w
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.error import OperationError, operationerrfmt
-from pypy.interpreter.function import StaticMethod
 
 from pypy.module._stackless.stackless_flags import StacklessFlags
 from pypy.module._stackless.rcoroutine import Coroutine, BaseCoState, AbstractThunk, CoroutineExit
@@ -38,7 +35,7 @@
         self.costate = costate
         if not space.is_true(space.callable(w_obj)):
             raise operationerrfmt(
-                space.w_TypeError, 
+                space.w_TypeError,
                 "'%s' object is not callable",
                 space.type(w_obj).getname(space))
         self.w_func = w_obj
@@ -65,7 +62,7 @@
 
 # Should be moved to interp_stackless.py if it's ever implemented... Currently
 # used by pypy/lib/stackless.py.
-W_TaskletExit = _new_exception('TaskletExit', W_SystemExit, 
+W_TaskletExit = _new_exception('TaskletExit', W_SystemExit,
             """Tasklet killed manually.""")
 
 class AppCoroutine(Coroutine): # XXX, StacklessFlags):
@@ -90,7 +87,7 @@
     def _get_state(space):
         return space.fromcache(AppCoState)
     _get_state = staticmethod(_get_state)
- 
+
     def w_bind(self, w_func, __args__):
         space = self.space
         if self.frame is not None:
@@ -127,7 +124,7 @@
             w_excvalue = operror.get_w_value(space)
             w_exctraceback = operror.get_traceback()
             w_excinfo = space.newtuple([w_exctype, w_excvalue, w_exctraceback])
-            
+
             if w_exctype is self.costate.w_CoroutineExit:
                 self.coroutine_exit = True
         else:
@@ -146,22 +143,22 @@
 
     def w_kill(self):
         self.kill()
-            
+
     def w_throw(self, w_type, w_value=None, w_traceback=None):
         space = self.space
 
         operror = OperationError(w_type, w_value)
         operror.normalize_exception(space)
-        
+
         if not space.is_w(w_traceback, space.w_None):
             from pypy.interpreter import pytraceback
             tb = space.interpclass_w(w_traceback)
-            if tb is None or not space.is_true(space.isinstance(tb, 
+            if tb is None or not space.is_true(space.isinstance(tb,
                 space.gettypeobject(pytraceback.PyTraceback.typedef))):
                 raise OperationError(space.w_TypeError,
                       space.wrap("throw: arg 3 must be a traceback or None"))
             operror.set_traceback(tb)
-        
+
         self._kill(operror)
 
     def _userdel(self):
@@ -280,7 +277,7 @@
     assert isinstance(w_klass, W_TypeObject)
     old_flag = w_klass.flag_heaptype
     w_klass.flag_heaptype = True
-    
+
     space.appexec([w_klass, space.wrap(funcname)], """
         (klass, funcname):
             func = getattr(klass, funcname)
@@ -332,23 +329,23 @@
         # Exporting new exception to space
         self.w_CoroutineExit = space.gettypefor(W_CoroutineExit)
         space.setitem(
-                      space.exceptions_module.w_dict, 
-                      space.new_interned_str('CoroutineExit'), 
-                      self.w_CoroutineExit) 
-        space.setitem(space.builtin.w_dict, 
-                      space.new_interned_str('CoroutineExit'), 
+                      space.exceptions_module.w_dict,
+                      space.new_interned_str('CoroutineExit'),
                       self.w_CoroutineExit)
-        
+        space.setitem(space.builtin.w_dict,
+                      space.new_interned_str('CoroutineExit'),
+                      self.w_CoroutineExit)
+
         # Should be moved to interp_stackless.py if it's ever implemented...
         self.w_TaskletExit = space.gettypefor(W_TaskletExit)
         space.setitem(
-                      space.exceptions_module.w_dict, 
-                      space.new_interned_str('TaskletExit'), 
-                      self.w_TaskletExit) 
-        space.setitem(space.builtin.w_dict, 
-                      space.new_interned_str('TaskletExit'), 
-                      self.w_TaskletExit)  
-        
+                      space.exceptions_module.w_dict,
+                      space.new_interned_str('TaskletExit'),
+                      self.w_TaskletExit)
+        space.setitem(space.builtin.w_dict,
+                      space.new_interned_str('TaskletExit'),
+                      self.w_TaskletExit)
+
     def post_install(self):
         self.current = self.main = AppCoroutine(self.space, state=self)
         self.main.subctx.clear_framestack()      # wack
@@ -378,7 +375,7 @@
         instr = frame.last_instr
         opcode = ord(code[instr])
         map = pythonopcode.opmap
-        call_ops = [map['CALL_FUNCTION'], map['CALL_FUNCTION_KW'], map['CALL_FUNCTION_VAR'], 
+        call_ops = [map['CALL_FUNCTION'], map['CALL_FUNCTION_KW'], map['CALL_FUNCTION_VAR'],
                     map['CALL_FUNCTION_VAR_KW'], map['CALL_METHOD']]
         assert opcode in call_ops
         instr += 1
diff --git a/pypy/module/_stackless/interp_stackless.py b/pypy/module/_stackless/interp_stackless.py
--- a/pypy/module/_stackless/interp_stackless.py
+++ b/pypy/module/_stackless/interp_stackless.py
@@ -1,9 +1,6 @@
 from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.typedef import GetSetProperty, TypeDef
-from pypy.interpreter.typedef import interp_attrproperty, interp_attrproperty_w
+from pypy.interpreter.typedef import TypeDef
 from pypy.interpreter.gateway import interp2app
-from pypy.interpreter.error import OperationError
-from pypy.rlib.rarithmetic import intmask
 import os
 
 
diff --git a/pypy/module/_stackless/rclonable.py b/pypy/module/_stackless/rclonable.py
--- a/pypy/module/_stackless/rclonable.py
+++ b/pypy/module/_stackless/rclonable.py
@@ -1,7 +1,6 @@
 from pypy.module._stackless.interp_coroutine import AbstractThunk, Coroutine
 from pypy.rlib.rgc import gc_swap_pool, gc_clone
 from pypy.rlib.objectmodel import we_are_translated
-from pypy.interpreter.error import OperationError
 
 
 class InterpClonableMixin:
@@ -76,7 +75,7 @@
     if not isinstance(current, InterpClonableCoroutine):
         raise RuntimeError("fork() in a non-clonable coroutine")
     thunk = ForkThunk(current)
-    coro_fork = InterpClonableCoroutine() 
+    coro_fork = InterpClonableCoroutine()
     coro_fork.bind(thunk)
     coro_fork.switch()
     # we resume here twice.  The following would need explanations about
diff --git a/pypy/module/_weakref/interp__weakref.py b/pypy/module/_weakref/interp__weakref.py
--- a/pypy/module/_weakref/interp__weakref.py
+++ b/pypy/module/_weakref/interp__weakref.py
@@ -1,16 +1,15 @@
 import py
-from pypy.interpreter.argument import Arguments
 from pypy.interpreter.baseobjspace import Wrappable, W_Root
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.gateway import interp2app, ObjSpace
-from pypy.interpreter.typedef import GetSetProperty, TypeDef
+from pypy.interpreter.typedef import TypeDef
 from pypy.rlib import jit
 import weakref
 
 
 class WeakrefLifeline(W_Root):
     def __init__(self, space):
-        self.space = space       # this is here for W_Root.clear_all_weakrefs()
+        self.space = space
         self.refs_weak = []
         self.cached_weakref_index = -1
         self.cached_proxy_index = -1
@@ -23,8 +22,10 @@
         """
         for i in range(len(self.refs_weak) - 1, -1, -1):
             w_ref = self.refs_weak[i]()
-            if w_ref is not None:
-                self.space.user_del_action.register_weakref_callback(w_ref)
+            if w_ref is not None and w_ref.w_callable is not None:
+                w_ref.enqueue_for_destruction(self.space,
+                                              W_WeakrefBase.activate_callback,
+                                              'weakref callback of ')
 
     def clear_all_weakrefs(self):
         """Clear all weakrefs.  This is called when an app-level object has
@@ -118,11 +119,8 @@
         self.w_obj_weak = dead_ref
 
     def activate_callback(w_self):
-        if not w_self.w_callable is None:
-            try:
-                w_self.space.call_function(w_self.w_callable, w_self)
-            except OperationError, e:
-                e.write_unraisable(w_self.space, 'weakref callback ', w_self.w_callable)
+        assert isinstance(w_self, W_WeakrefBase)
+        w_self.space.call_function(w_self.w_callable, w_self)
 
     def descr__repr__(self, space):
         w_obj = self.dereference()
diff --git a/pypy/module/_winreg/interp_winreg.py b/pypy/module/_winreg/interp_winreg.py
--- a/pypy/module/_winreg/interp_winreg.py
+++ b/pypy/module/_winreg/interp_winreg.py
@@ -1,6 +1,5 @@
 from __future__ import with_statement
 from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.baseobjspace import ObjSpace, W_Root
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
 from pypy.interpreter.error import OperationError, wrap_windowserror
diff --git a/pypy/module/array/interp_array.py b/pypy/module/array/interp_array.py
--- a/pypy/module/array/interp_array.py
+++ b/pypy/module/array/interp_array.py
@@ -1,18 +1,20 @@
 from __future__ import with_statement
 
+from pypy.interpreter.buffer import RWBuffer
 from pypy.interpreter.error import OperationError
-from pypy.interpreter.typedef import TypeDef, GetSetProperty, make_weakref_descr
-from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.rlib.unroll import unrolling_iterable
-from pypy.rlib.rarithmetic import ovfcheck
-from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.typedef import GetSetProperty, make_weakref_descr
+from pypy.module._file.interp_file import W_File
+from pypy.objspace.std.model import W_Object
+from pypy.objspace.std.multimethod import FailedToImplement
 from pypy.objspace.std.stdtypedef import SMM, StdTypeDef
 from pypy.objspace.std.register_all import register_all
-from pypy.objspace.std.model import W_Object
-from pypy.module._file.interp_file import W_File
-from pypy.interpreter.buffer import RWBuffer
-from pypy.objspace.std.multimethod import FailedToImplement
+from pypy.rlib.rarithmetic import ovfcheck
+from pypy.rlib.unroll import unrolling_iterable
+from pypy.rpython.lltypesystem import lltype, rffi
+
+
+memcpy = rffi.llexternal("memcpy", [rffi.VOIDP, rffi.VOIDP, rffi.SIZE_T], lltype.Void)
 
 @unwrap_spec(typecode=str)
 def w_array(space, w_cls, typecode, __args__):
@@ -37,7 +39,7 @@
             if len(__args__.arguments_w) > 0:
                 w_initializer = __args__.arguments_w[0]
                 if space.type(w_initializer) is space.w_str:
-                    a.fromstring(w_initializer)
+                    a.fromstring(space.str_w(w_initializer))
                 elif space.type(w_initializer) is space.w_unicode:
                     a.fromsequence(w_initializer)
                 elif space.type(w_initializer) is space.w_list:
@@ -73,6 +75,7 @@
 
 array_buffer_info = SMM('buffer_info', 1)
 array_reduce = SMM('__reduce__', 1)
+array_copy = SMM('__copy__', 1)
 array_byteswap = SMM('byteswap', 1)
 
 
@@ -96,7 +99,7 @@
     itemsize = GetSetProperty(descr_itemsize),
     typecode = GetSetProperty(descr_typecode),
     __weakref__ = make_weakref_descr(W_ArrayBase),
-    )
+)
 W_ArrayBase.typedef.registermethods(globals())
 
 
@@ -159,8 +162,6 @@
         self.data[index] = char
 
 
-
-
 def make_array(mytype):
     class W_Array(W_ArrayBase):
         itemsize = mytype.bytes
@@ -268,12 +269,10 @@
                 raise
             self.setlen(oldlen + i)
 
-        def fromstring(self, w_s):
-            space = self.space
-            s = space.str_w(w_s)
+        def fromstring(self, s):
             if len(s) % self.itemsize != 0:
                 msg = 'string length not a multiple of item size'
-                raise OperationError(space.w_ValueError, space.wrap(msg))
+                raise OperationError(self.space.w_ValueError, self.space.wrap(msg))
             oldlen = self.len
             new = len(s) / mytype.bytes
             self.setlen(oldlen + new)
@@ -311,6 +310,14 @@
         def charbuf(self):
             return  rffi.cast(rffi.CCHARP, self.buffer)
 
+        def w_getitem(self, space, idx):
+            item = self.buffer[idx]
+            if mytype.typecode in 'bBhHil':
+                item = rffi.cast(lltype.Signed, item)
+            elif mytype.typecode == 'f':
+                item = float(item)
+            return space.wrap(item)
+
     # Basic get/set/append/extend methods
 
     def len__Array(space, self):
@@ -319,12 +326,7 @@
     def getitem__Array_ANY(space, self, w_idx):
         idx, stop, step = space.decode_index(w_idx, self.len)
         assert step == 0
-        item = self.buffer[idx]
-        if mytype.typecode in 'bBhHil':
-            item = rffi.cast(lltype.Signed, item)
-        elif mytype.typecode == 'f':
-            item = float(item)
-        return self.space.wrap(item)
+        return self.w_getitem(space, idx)
 
     def getitem__Array_Slice(space, self, w_slice):
         start, stop, step, size = space.decode_index4(w_slice, self.len)
@@ -387,7 +389,7 @@
     def array_count__Array_ANY(space, self, w_val):
         cnt = 0
         for i in range(self.len):
-            w_item = getitem__Array_ANY(space, self, space.wrap(i))
+            w_item = self.w_getitem(space, i)
             if space.is_true(space.eq(w_item, w_val)):
                 cnt += 1
         return space.wrap(cnt)
@@ -395,7 +397,7 @@
     def array_index__Array_ANY(space, self, w_val):
         cnt = 0
         for i in range(self.len):
-            w_item = getitem__Array_ANY(space, self, space.wrap(i))
+            w_item = self.w_getitem(space, i)
             if space.is_true(space.eq(w_item, w_val)):
                 return space.wrap(i)
         msg = 'array.index(x): x not in list'
@@ -413,7 +415,7 @@
         if i < 0 or i >= self.len:
             msg = 'pop index out of range'
             raise OperationError(space.w_IndexError, space.wrap(msg))
-        w_val = getitem__Array_ANY(space, self, space.wrap(i))
+        w_val = self.w_getitem(space, i)
         while i < self.len - 1:
             self.buffer[i] = self.buffer[i + 1]
             i += 1
@@ -515,14 +517,14 @@
     def array_tolist__Array(space, self):
         w_l = space.newlist([])
         for i in range(self.len):
-            w_l.append(getitem__Array_ANY(space, self, space.wrap(i)))
+            w_l.append(self.w_getitem(space, i))
         return w_l
 
     def array_fromlist__Array_List(space, self, w_lst):
         self.fromlist(w_lst)
 
     def array_fromstring__Array_ANY(space, self, w_s):
-        self.fromstring(w_s)
+        self.fromstring(space.str_w(w_s))
 
     def array_tostring__Array(space, self):
         cbuf = self.charbuf()
@@ -569,10 +571,7 @@
             self.fromsequence(w_ustr)
 
         def array_tounicode__Array(space, self):
-            u = u""
-            for i in range(self.len):
-                u += self.buffer[i]
-            return space.wrap(u)
+            return space.wrap(rffi.wcharpsize2unicode(self.buffer, self.len))
     else:
 
         def array_fromunicode__Array_Unicode(space, self, w_ustr):
@@ -615,6 +614,16 @@
             dct = space.w_None
         return space.newtuple([space.type(self), space.newtuple(args), dct])
 
+    def array_copy__Array(space, self):
+        w_a = mytype.w_class(self.space)
+        w_a.setlen(self.len)
+        memcpy(
+            rffi.cast(rffi.VOIDP, w_a.buffer),
+            rffi.cast(rffi.VOIDP, self.buffer),
+            self.len * mytype.bytes
+        )
+        return w_a
+
     def array_byteswap__Array(space, self):
         if mytype.bytes not in [1, 2, 4, 8]:
             msg = "byteswap not supported for this array"
diff --git a/pypy/module/binascii/interp_crc32.py b/pypy/module/binascii/interp_crc32.py
--- a/pypy/module/binascii/interp_crc32.py
+++ b/pypy/module/binascii/interp_crc32.py
@@ -61,7 +61,7 @@
 crc_32_tab = map(r_uint, crc_32_tab)
 
 
- at unwrap_spec(data='bufferstr', oldcrc='c_int')
+ at unwrap_spec(data='bufferstr', oldcrc='truncatedint')
 def crc32(space, data, oldcrc=0):
     "Compute the CRC-32 incrementally."
 
diff --git a/pypy/module/binascii/test/test_binascii.py b/pypy/module/binascii/test/test_binascii.py
--- a/pypy/module/binascii/test/test_binascii.py
+++ b/pypy/module/binascii/test/test_binascii.py
@@ -374,6 +374,8 @@
             ('x', 10000, -1855256896),
             ('y', 10000, -429115818),
             ('z', 10000, 2137352172),
+            ('foo', 99999999999999999999999999, -1932704816),
+            ('bar', -99999999999999999999999999, 2000545409),
             ]:
             assert self.binascii.crc32(input, initial) == expected
 
diff --git a/pypy/module/bz2/interp_bz2.py b/pypy/module/bz2/interp_bz2.py
--- a/pypy/module/bz2/interp_bz2.py
+++ b/pypy/module/bz2/interp_bz2.py
@@ -4,9 +4,8 @@
 from pypy.rpython.lltypesystem import lltype
 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.typedef import TypeDef, GetSetProperty
-from pypy.interpreter.typedef import interp_attrproperty
-from pypy.interpreter.gateway import NoneNotWrapped, interp2app, unwrap_spec
+from pypy.interpreter.typedef import TypeDef, interp_attrproperty
+from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.rlib.streamio import Stream
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.translator.platform import platform as compiler
@@ -67,7 +66,7 @@
     'BZ_OUTBUFF_FULL', 'BZ_CONFIG_ERROR']
 for name in constant_names:
     setattr(CConfig, name, platform.DefinedConstantInteger(name))
-    
+
 class cConfig(object):
     pass
 for k, v in platform.configure(CConfig).items():
@@ -100,7 +99,7 @@
     SMALLCHUNK = 8192
 else:
     SMALLCHUNK = BUFSIZ
-    
+
 if rffi.sizeof(rffi.INT) > 4:
     BIGCHUNK = 512 * 32
 else:
@@ -505,7 +504,7 @@
         self.bzs = lltype.malloc(bz_stream.TO, flavor='raw', zero=True)
         self.running = False
         self._init_bz2comp(compresslevel)
-        
+
     def _init_bz2comp(self, compresslevel):
         if compresslevel < 1 or compresslevel > 9:
             raise OperationError(self.space.w_ValueError,
@@ -514,13 +513,13 @@
         bzerror = intmask(BZ2_bzCompressInit(self.bzs, compresslevel, 0, 0))
         if bzerror != BZ_OK:
             _catch_bz2_error(self.space, bzerror)
-        
+
         self.running = True
-        
+
     def __del__(self):
         BZ2_bzCompressEnd(self.bzs)
         lltype.free(self.bzs, flavor='raw')
-    
+
     @unwrap_spec(data='bufferstr')
     def compress(self, data):
         """compress(data) -> string
@@ -529,12 +528,12 @@
         compressed data whenever possible. When you've finished providing data
         to compress, call the flush() method to finish the compression process,
         and return what is left in the internal buffers."""
-        
+
         datasize = len(data)
-        
+
         if datasize == 0:
             return self.space.wrap("")
-        
+
         if not self.running:
             raise OperationError(self.space.w_ValueError,
                 self.space.wrap("this object was already flushed"))
@@ -562,7 +561,7 @@
 
                 res = out.make_result_string()
                 return self.space.wrap(res)
-    
+
     def flush(self):
         if not self.running:
             raise OperationError(self.space.w_ValueError,
@@ -576,7 +575,7 @@
                     break
                 elif bzerror != BZ_FINISH_OK:
                     _catch_bz2_error(self.space, bzerror)
-                
+
                 if rffi.getintfield(self.bzs, 'c_avail_out') == 0:
                     out.prepare_next_chunk()
 
@@ -603,23 +602,23 @@
     Create a new decompressor object. This object may be used to decompress
     data sequentially. If you want to decompress data in one shot, use the
     decompress() function instead."""
-    
+
     def __init__(self, space):
         self.space = space
 
         self.bzs = lltype.malloc(bz_stream.TO, flavor='raw', zero=True)
         self.running = False
         self.unused_data = ""
-        
+
         self._init_bz2decomp()
-    
+
     def _init_bz2decomp(self):
         bzerror = BZ2_bzDecompressInit(self.bzs, 0, 0)
         if bzerror != BZ_OK:
             _catch_bz2_error(self.space, bzerror)
-        
+
         self.running = True
-    
+
     def __del__(self):
         BZ2_bzDecompressEnd(self.bzs)
         lltype.free(self.bzs, flavor='raw')
@@ -687,7 +686,7 @@
     Compress data in one shot. If you want to compress data sequentially,
     use an instance of BZ2Compressor instead. The compresslevel parameter, if
     given, must be a number between 1 and 9."""
-    
+
     if compresslevel < 1 or compresslevel > 9:
         raise OperationError(space.w_ValueError,
             space.wrap("compresslevel must be between 1 and 9"))
@@ -731,7 +730,7 @@
 
     Decompress data in one shot. If you want to decompress data sequentially,
     use an instance of BZ2Decompressor instead."""
-    
+
     in_bufsize = len(data)
     if in_bufsize == 0:
         return space.wrap("")
diff --git a/pypy/module/bz2/test/test_bz2_file.py b/pypy/module/bz2/test/test_bz2_file.py
--- a/pypy/module/bz2/test/test_bz2_file.py
+++ b/pypy/module/bz2/test/test_bz2_file.py
@@ -133,6 +133,7 @@
         
         bz2f.seek(0)
         assert bz2f.tell() == 0
+        del bz2f   # delete from this frame, which is captured in the traceback
 
     def test_open_close_del(self):
         from bz2 import BZ2File
@@ -246,11 +247,18 @@
         assert text_read == self.TEXT
         bz2f.close()
 
+    def test_silently_closes(self):
+        from bz2 import BZ2File
+        self.create_broken_temp_file()
+        BZ2File(self.temppath)
+        # check that no C-level malloc is left behind
+
     def test_read_broken_file(self):
         from bz2 import BZ2File
         self.create_broken_temp_file()
         bz2f = BZ2File(self.temppath)
         raises(EOFError, bz2f.read)
+        del bz2f   # delete from this frame, which is captured in the traceback
 
     def test_subsequent_read_broken_file(self):
         from bz2 import BZ2File
@@ -264,6 +272,7 @@
                 raise Exception("should generate EOFError earlier")
         except EOFError:
             pass
+        del bz2f   # delete from this frame, which is captured in the traceback
 
     def test_read_chunk10(self):
         from bz2 import BZ2File
@@ -416,6 +425,7 @@
         bz2f.close()
         bz2f = BZ2File(self.temppath, 'r')
         assert bz2f.read() == self.random_data
+        del bz2f   # delete from this frame, which is captured in the traceback
 
     def test_context_manager(self):
         from bz2 import BZ2File
diff --git a/pypy/module/cStringIO/interp_stringio.py b/pypy/module/cStringIO/interp_stringio.py
--- a/pypy/module/cStringIO/interp_stringio.py
+++ b/pypy/module/cStringIO/interp_stringio.py
@@ -1,4 +1,3 @@
-import sys
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
diff --git a/pypy/module/cmath/interp_cmath.py b/pypy/module/cmath/interp_cmath.py
--- a/pypy/module/cmath/interp_cmath.py
+++ b/pypy/module/cmath/interp_cmath.py
@@ -5,7 +5,7 @@
 from pypy.tool.sourcetools import func_with_new_name
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.gateway import NoneNotWrapped
-from pypy.module.cmath import Module, names_and_docstrings
+from pypy.module.cmath import names_and_docstrings
 from pypy.module.cmath.constant import DBL_MIN, CM_SCALE_UP, CM_SCALE_DOWN
 from pypy.module.cmath.constant import CM_LARGE_DOUBLE, DBL_MANT_DIG
 from pypy.module.cmath.constant import M_LN2, M_LN10
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
@@ -337,7 +337,7 @@
     'PyCapsule_SetContext', 'PyCapsule_Import', 'PyCapsule_Type', 'init_capsule',
 
     'PyObject_AsReadBuffer', 'PyObject_AsWriteBuffer', 'PyObject_CheckReadBuffer',
-    
+
     'PyOS_getsig', 'PyOS_setsig',
 
     'PyStructSequence_InitType', 'PyStructSequence_New',
@@ -745,7 +745,7 @@
             ctypes.c_void_p)
 
     setup_va_functions(eci)
-   
+
     setup_init_functions(eci)
     return modulename.new(ext='')
 
@@ -771,7 +771,7 @@
         export_symbols[:] = renamed_symbols
     else:
         export_symbols[:] = [sym.replace("#", "") for sym in export_symbols]
-    
+
     # Generate defines
     for macro_name, size in [
         ("SIZEOF_LONG_LONG", rffi.LONGLONG),
@@ -784,7 +784,7 @@
     ]:
         pypy_macros.append("#define %s %s" % (macro_name, rffi.sizeof(size)))
     pypy_macros.append('')
-    
+
     pypy_macros_h = udir.join('pypy_macros.h')
     pypy_macros_h.write('\n'.join(pypy_macros))
 
@@ -852,7 +852,7 @@
             # Sometimes the library is wrapped into another DLL, ensure that
             # the correct bootstrap code is installed
             kwds["link_extra"] = ["msvcrt.lib"]
-        elif sys.platform == 'linux2':
+        elif sys.platform.startswith('linux'):
             compile_extra.append("-Werror=implicit-function-declaration")
         export_symbols_eci.append('pypyAPI')
     else:
@@ -1007,7 +1007,7 @@
     FT = lltype.typeOf(func).TO
     return make_generic_cpy_call(FT, False, False)(space, func, *args)
 
- at specialize.ll()    
+ at specialize.ll()
 def generic_cpy_call_expect_null(space, func, *args):
     FT = lltype.typeOf(func).TO
     return make_generic_cpy_call(FT, True, True)(space, func, *args)
diff --git a/pypy/module/cpyext/cdatetime.py b/pypy/module/cpyext/cdatetime.py
--- a/pypy/module/cpyext/cdatetime.py
+++ b/pypy/module/cpyext/cdatetime.py
@@ -1,8 +1,7 @@
 from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.rlib.objectmodel import we_are_translated
-from pypy.module.cpyext.pyobject import PyObject, make_ref, Py_DecRef
-from pypy.module.cpyext.api import (
-    cpython_api, CANNOT_FAIL, cpython_struct, PyObjectFields)
+from pypy.module.cpyext.pyobject import PyObject, make_ref
+from pypy.module.cpyext.api import (cpython_api, CANNOT_FAIL, cpython_struct,
+    PyObjectFields)
 from pypy.module.cpyext.import_ import PyImport_Import
 from pypy.module.cpyext.typeobject import PyTypeObjectPtr
 from pypy.interpreter.error import OperationError
diff --git a/pypy/module/cpyext/complexobject.py b/pypy/module/cpyext/complexobject.py
--- a/pypy/module/cpyext/complexobject.py
+++ b/pypy/module/cpyext/complexobject.py
@@ -1,7 +1,6 @@
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.module.cpyext.api import (
     cpython_api, cpython_struct, PyObject, build_type_checkers)
-from pypy.module.cpyext.pyerrors import PyErr_BadArgument
 from pypy.module.cpyext.floatobject import PyFloat_AsDouble
 from pypy.objspace.std.complexobject import W_ComplexObject
 from pypy.interpreter.error import OperationError
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.5.0"
+#define PYPY_VERSION "1.6.0"
 
 /* Subversion Revision number of this file (not of the repository) */
 #define PY_PATCHLEVEL_REVISION  "$Revision: 77872 $"
diff --git a/pypy/module/cpyext/sequence.py b/pypy/module/cpyext/sequence.py
--- a/pypy/module/cpyext/sequence.py
+++ b/pypy/module/cpyext/sequence.py
@@ -22,7 +22,7 @@
 def PySequence_Check(space, w_obj):
     """Return 1 if the object provides sequence protocol, and 0 otherwise.
     This function always succeeds."""
-    return int(space.findattr(w_obj, space.wrap("__getitem__")) is not None)
+    return int(space.issequence_w(w_obj))
 
 @cpython_api([PyObject], Py_ssize_t, error=-1)
 def PySequence_Size(space, w_obj):
diff --git a/pypy/module/cpyext/stringobject.py b/pypy/module/cpyext/stringobject.py
--- a/pypy/module/cpyext/stringobject.py
+++ b/pypy/module/cpyext/stringobject.py
@@ -268,3 +268,7 @@
     if errors:
         w_errors = space.wrap(rffi.charp2str(errors))
     return space.call_method(w_str, 'encode', w_encoding, w_errors)
+
+ at cpython_api([PyObject, PyObject], PyObject)
+def _PyString_Join(space, w_sep, w_seq):
+    return space.call_method(w_sep, 'join', w_seq)
diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -188,7 +188,7 @@
             kwds["compile_extra"] = ["/we4013"]
         else:
             kwds["link_files"] = [str(api_library + '.so')]
-            if sys.platform == 'linux2':
+            if sys.platform.startswith('linux'):
                 kwds["compile_extra"]=["-Werror=implicit-function-declaration"]
         return compile_module(self.space, name, **kwds)
 
diff --git a/pypy/module/cpyext/test/test_stringobject.py b/pypy/module/cpyext/test/test_stringobject.py
--- a/pypy/module/cpyext/test/test_stringobject.py
+++ b/pypy/module/cpyext/test/test_stringobject.py
@@ -287,3 +287,9 @@
     def test_eq(self, space, api):
         assert 1 == api._PyString_Eq(space.wrap("hello"), space.wrap("hello"))
         assert 0 == api._PyString_Eq(space.wrap("hello"), space.wrap("world"))
+
+    def test_join(self, space, api):
+        w_sep = space.wrap('<sep>')
+        w_seq = space.wrap(['a', 'b'])
+        w_joined = api._PyString_Join(w_sep, w_seq)
+        assert space.unwrap(w_joined) == 'a<sep>b'
diff --git a/pypy/module/crypt/interp_crypt.py b/pypy/module/crypt/interp_crypt.py
--- a/pypy/module/crypt/interp_crypt.py
+++ b/pypy/module/crypt/interp_crypt.py
@@ -1,6 +1,5 @@
-from pypy.interpreter.error import OperationError
 from pypy.interpreter.gateway import unwrap_spec
-from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.rpython.lltypesystem import rffi
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 import sys
 
@@ -22,4 +21,4 @@
     if not res:
         return space.w_None
     str_res = rffi.charp2str(res)
-    return space.wrap(str_res) 
+    return space.wrap(str_res)
diff --git a/pypy/module/exceptions/interp_exceptions.py b/pypy/module/exceptions/interp_exceptions.py
--- a/pypy/module/exceptions/interp_exceptions.py
+++ b/pypy/module/exceptions/interp_exceptions.py
@@ -73,9 +73,8 @@
 """
 
 from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.typedef import TypeDef, interp_attrproperty_w,\
-     GetSetProperty, interp_attrproperty, descr_get_dict, descr_set_dict,\
-     descr_del_dict
+from pypy.interpreter.typedef import (TypeDef, GetSetProperty, descr_get_dict,
+    descr_set_dict, descr_del_dict)
 from pypy.interpreter.gateway import interp2app
 from pypy.interpreter.error import OperationError
 from pypy.rlib import rwin32
diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -11,9 +11,8 @@
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.eval import Code
 from pypy.interpreter.pycode import PyCode
-from pypy.rlib import streamio, jit, rposix
+from pypy.rlib import streamio, jit
 from pypy.rlib.streamio import StreamErrors
-from pypy.rlib.rarithmetic import intmask
 from pypy.rlib.objectmodel import we_are_translated, specialize
 from pypy.module.sys.version import PYPY_VERSION
 
@@ -86,7 +85,7 @@
 
     return SEARCH_ERROR, None, None
 
-if sys.platform == 'linux2' or 'freebsd' in sys.platform:
+if sys.platform.startswith('linux') or 'freebsd' in sys.platform:
     def case_ok(filename):
         return True
 else:
diff --git a/pypy/module/imp/interp_imp.py b/pypy/module/imp/interp_imp.py
--- a/pypy/module/imp/interp_imp.py
+++ b/pypy/module/imp/interp_imp.py
@@ -3,9 +3,9 @@
 from pypy.rlib import streamio
 from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter.module import Module
-from pypy.interpreter.gateway import NoneNotWrapped, unwrap_spec
+from pypy.interpreter.gateway import unwrap_spec
 from pypy.module._file.interp_stream import StreamErrors, wrap_streamerror
-import struct
+
 
 def get_suffixes(space):
     w = space.wrap
diff --git a/pypy/module/itertools/interp_itertools.py b/pypy/module/itertools/interp_itertools.py
--- a/pypy/module/itertools/interp_itertools.py
+++ b/pypy/module/itertools/interp_itertools.py
@@ -2,7 +2,6 @@
 from pypy.interpreter.error import OperationError
 from pypy.interpreter.typedef import TypeDef, make_weakref_descr
 from pypy.interpreter.gateway import interp2app, unwrap_spec
-from pypy.rlib.rarithmetic import ovfcheck
 
 class W_Count(Wrappable):
 
@@ -87,7 +86,7 @@
     def __init__(self, space, w_obj, w_times):
         self.space = space
         self.w_obj = w_obj
-        
+
         if space.is_w(w_times, space.w_None):
             self.counting = False
             self.count = 0
@@ -181,7 +180,7 @@
     long as the predicate is true.
 
     Equivalent to :
-    
+
     def takewhile(predicate, iterable):
         for x in iterable:
             if predicate(x):
@@ -316,7 +315,7 @@
     None, return the items that are false.
 
     Equivalent to :
-    
+
     def ifilterfalse(predicate, iterable):
         if predicate is None:
             predicate = bool
@@ -380,16 +379,23 @@
             self.start = -1
         else:                             # all following calls
             consume = self.step
+        if consume > 1:
+            self._ignore_items(consume-1)
         if self.stop >= 0:
             if self.stop < consume:
+                self.stop = 0   # reset the state so that a following next_w()
+                self.step = 1   # has no effect any more
                 raise OperationError(self.space.w_StopIteration,
                                      self.space.w_None)
             self.stop -= consume
+        return self.space.next(self.iterable)
+
+    def _ignore_items(self, num):
         while True:
-            w_obj = self.space.next(self.iterable)
-            consume -= 1
-            if consume <= 0:
-                return w_obj
+            self.space.next(self.iterable)
+            num -= 1
+            if num <= 0:
+                break
 
 def W_ISlice___new__(space, w_subtype, w_iterable, w_startstop, args_w):
     r = space.allocate_instance(W_ISlice, w_subtype)
@@ -570,7 +576,7 @@
                 yield tuple(args)
             else:
                 yield function(*args)
-    
+
     """)
 
 
@@ -728,9 +734,9 @@
         __doc__  = """Make an iterator returning elements from the iterable and
     saving a copy of each. When the iterable is exhausted, return
     elements from the saved copy. Repeats indefinitely.
-    
+
     Equivalent to :
-    
+
     def cycle(iterable):
         saved = []
         for element in iterable:
@@ -738,7 +744,7 @@
             saved.append(element)
         while saved:
             for element in saved:
-                yield element    
+                yield element
     """)
 
 class W_StarMap(Wrappable):
@@ -778,7 +784,7 @@
     def starmap(function, iterable):
         iterable = iter(iterable)
         while True:
-            yield function(*iterable.next())    
+            yield function(*iterable.next())
     """)
 
 
@@ -788,15 +794,15 @@
     Note : once tee() has made a split, the original iterable
     should not be used anywhere else; otherwise, the iterable could get
     advanced without the tee objects being informed.
-    
+
     Note : this member of the toolkit may require significant auxiliary
     storage (depending on how much temporary data needs to be stored).
     In general, if one iterator is going to use most or all of the
     data before the other iterator, it is faster to use list() instead
     of tee()
-    
+
     Equivalent to :
-    
+
     def tee(iterable, n=2):
         def gen(next, data={}, cnt=[0]):
             for i in count():
@@ -888,7 +894,7 @@
         self.exhausted = False
         self.started = False
         # new_group - new group not started yet, next should not skip any items
-        self.new_group = True 
+        self.new_group = True
         self.w_lookahead = self.space.w_None
         self.w_key = self.space.w_None
 
diff --git a/pypy/module/itertools/test/test_itertools.py b/pypy/module/itertools/test/test_itertools.py
--- a/pypy/module/itertools/test/test_itertools.py
+++ b/pypy/module/itertools/test/test_itertools.py
@@ -227,6 +227,45 @@
         assert list(itertools.islice(xrange(10), None,None)) == range(10)
         assert list(itertools.islice(xrange(10), None,None,None)) == range(10)
 
+    def test_islice_dropitems_exact(self):
+        import itertools
+
+        it = iter("abcdefghij")
+        itertools.islice(it, 2, 2)    # doesn't eagerly drop anything
+        assert it.next() == "a"
+        itertools.islice(it, 3, 8, 2)    # doesn't eagerly drop anything
+        assert it.next() == "b"
+        assert it.next() == "c"
+
+        it = iter("abcdefghij")
+        x = next(itertools.islice(it, 2, 3), None)    # drops 2 items
+        assert x == "c"
+        assert it.next() == "d"
+
+        it = iter("abcdefghij")
+        x = next(itertools.islice(it, 3, 8, 2), None)    # drops 3 items
+        assert x == "d"
+        assert it.next() == "e"
+
+        it = iter("abcdefghij")
+        x = next(itertools.islice(it, None, 8), None)    # drops 0 items
+        assert x == "a"
+        assert it.next() == "b"
+
+        it = iter("abcdefghij")
+        x = next(itertools.islice(it, 3, 2), None)    # drops 3 items
+        assert x is None
+        assert it.next() == "d"
+
+        it = iter("abcdefghij")
+        islc = itertools.islice(it, 3, 7, 2)
+        assert islc.next() == "d"    # drops 0, 1, 2, returns item #3
+        assert it.next() == "e"
+        assert islc.next() == "g"    # drops the 4th and return item #5
+        assert it.next() == "h"
+        raises(StopIteration, islc.next)  # drops the 6th and raise
+        assert it.next() == "j"
+
     def test_islice_overflow(self):
         import itertools
         import sys
diff --git a/pypy/module/marshal/interp_marshal.py b/pypy/module/marshal/interp_marshal.py
--- a/pypy/module/marshal/interp_marshal.py
+++ b/pypy/module/marshal/interp_marshal.py
@@ -1,10 +1,8 @@
-from pypy.interpreter.baseobjspace import ObjSpace
 from pypy.interpreter.error import OperationError
 from pypy.rlib.rarithmetic import intmask
 from pypy.rlib import rstackovf
 from pypy.module._file.interp_file import W_File
-from pypy.module._file.interp_stream import StreamErrors, wrap_streamerror
-import sys
+
 
 Py_MARSHAL_VERSION = 2
 
diff --git a/pypy/module/micronumpy/__init__.py b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -10,18 +10,27 @@
         'zeros': 'interp_numarray.zeros',
         'empty': 'interp_numarray.zeros',
         'ones': 'interp_numarray.ones',
+        'fromstring': 'interp_support.fromstring',
 
         # ufuncs
         'abs': 'interp_ufuncs.absolute',
         'absolute': 'interp_ufuncs.absolute',
+        'add': 'interp_ufuncs.add',
         'copysign': 'interp_ufuncs.copysign',
+        'divide': 'interp_ufuncs.divide',
         'exp': 'interp_ufuncs.exp',
+        'fabs': 'interp_ufuncs.fabs',
         'floor': 'interp_ufuncs.floor',
         'maximum': 'interp_ufuncs.maximum',
         'minimum': 'interp_ufuncs.minimum',
+        'multiply': 'interp_ufuncs.multiply',
         'negative': 'interp_ufuncs.negative',
         'reciprocal': 'interp_ufuncs.reciprocal',
         'sign': 'interp_ufuncs.sign',
+        'subtract': 'interp_ufuncs.subtract',
+        'sin': 'interp_ufuncs.sin',
+        'cos': 'interp_ufuncs.cos',
+        'tan': 'interp_ufuncs.tan',
     }
 
     appleveldefs = {
diff --git a/pypy/module/micronumpy/compile.py b/pypy/module/micronumpy/compile.py
--- a/pypy/module/micronumpy/compile.py
+++ b/pypy/module/micronumpy/compile.py
@@ -3,7 +3,7 @@
 It should not be imported by the module itself
 """
 
-from pypy.module.micronumpy.interp_numarray import FloatWrapper, SingleDimArray
+from pypy.module.micronumpy.interp_numarray import FloatWrapper, SingleDimArray, BaseArray
 
 class BogusBytecode(Exception):
     pass
@@ -18,6 +18,14 @@
     def wrap(self, x):
         return x
 
+    def issequence_w(self, w_obj):
+        # Completley wrong in the general case, but good enough for this.
+        return isinstance(w_obj, BaseArray)
+
+    def float_w(self, w_obj):
+        assert isinstance(w_obj, float)
+        return w_obj
+
 def numpy_compile(bytecode, array_size):
     space = TrivialSpace()
     stack = []
@@ -40,6 +48,11 @@
         elif b == '/':
             right = stack.pop()
             stack.append(stack.pop().descr_div(space, right))
+        elif b == '%':
+            right = stack.pop()
+            stack.append(stack.pop().descr_mod(space, right))
+        elif b == '|':
+            stack.append(stack.pop().descr_abs(space))
         else:
             print "Unknown opcode: %s" % b
             raise BogusBytecode()
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
@@ -1,43 +1,36 @@
-from pypy.interpreter.baseobjspace import ObjSpace, W_Root, Wrappable
-from pypy.interpreter.error import operationerrfmt
+from pypy.interpreter.baseobjspace import Wrappable
+from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.typedef import TypeDef, GetSetProperty
+from pypy.module.micronumpy.interp_support import Signature
+from pypy.module.micronumpy import interp_ufuncs
+from pypy.objspace.std.floatobject import float2string as float2string_orig
 from pypy.rlib import jit
+from pypy.rlib.rfloat import DTSF_STR_PRECISION
 from pypy.rpython.lltypesystem import lltype
 from pypy.tool.sourcetools import func_with_new_name
-
-
-def dummy1(v):
-    assert isinstance(v, float)
-    return v
-
-def dummy2(v):
-    assert isinstance(v, float)
-    return v
+import math
 
 TP = lltype.Array(lltype.Float, hints={'nolength': True})
 
 numpy_driver = jit.JitDriver(greens = ['signature'],
                              reds = ['result_size', 'i', 'self', 'result'])
-
-class Signature(object):
-    def __init__(self):
-        self.transitions = {}
-
-    def transition(self, target):
-        if target in self.transitions:
-            return self.transitions[target]
-        self.transitions[target] = new = Signature()
-        return new
+all_driver = jit.JitDriver(greens=['signature'], reds=['i', 'size', 'self'])
+any_driver = jit.JitDriver(greens=['signature'], reds=['i', 'size', 'self'])
+slice_driver1 = jit.JitDriver(greens=['signature'], reds=['i', 'j', 'step', 'stop', 'source', 'dest'])
+slice_driver2 = jit.JitDriver(greens=['signature'], reds=['i', 'j', 'step', 'stop', 'source', 'dest'])
 
 def add(v1, v2):
     return v1 + v2
-def sub(v1, v2):
-    return v1 - v2
 def mul(v1, v2):
     return v1 * v2
-def div(v1, v2):
-    return v1 / v2
+def maximum(v1, v2):
+    return max(v1, v2)
+def minimum(v1, v2):
+    return min(v1, v2)
+
+def float2string(x):
+    return float2string_orig(x, 'g', DTSF_STR_PRECISION)
 
 class BaseArray(Wrappable):
     def __init__(self):
@@ -52,44 +45,185 @@
             arr.force_if_needed()
         del self.invalidates[:]
 
-    def _binop_impl(function):
-        signature = Signature()
+    def _unaryop_impl(w_ufunc):
+        def impl(self, space):
+            return w_ufunc(space, self)
+        return func_with_new_name(impl, "unaryop_%s_impl" % w_ufunc.__name__)
+
+    descr_pos = _unaryop_impl(interp_ufuncs.positive)
+    descr_neg = _unaryop_impl(interp_ufuncs.negative)
+    descr_abs = _unaryop_impl(interp_ufuncs.absolute)
+
+    def _binop_impl(w_ufunc):
         def impl(self, space, w_other):
-            new_sig = self.signature.transition(signature)
-            if isinstance(w_other, BaseArray):
-                res = Call2(
-                    function,
-                    self,
-                    w_other,
-                    new_sig.transition(w_other.signature)
-                )
-                w_other.invalidates.append(res)
-            else:
-                w_other = FloatWrapper(space.float_w(w_other))
-                res = Call2(
-                    function,
-                    self,
-                    w_other,
-                    new_sig.transition(w_other.signature)
-                )
-            self.invalidates.append(res)
-            return space.wrap(res)
-        return func_with_new_name(impl, "binop_%s_impl" % function.__name__)
+            return w_ufunc(space, self, w_other)
+        return func_with_new_name(impl, "binop_%s_impl" % w_ufunc.__name__)
 
-    descr_add = _binop_impl(add)
-    descr_sub = _binop_impl(sub)
-    descr_mul = _binop_impl(mul)
-    descr_div = _binop_impl(div)
+    descr_add = _binop_impl(interp_ufuncs.add)
+    descr_sub = _binop_impl(interp_ufuncs.subtract)
+    descr_mul = _binop_impl(interp_ufuncs.multiply)
+    descr_div = _binop_impl(interp_ufuncs.divide)
+    descr_pow = _binop_impl(interp_ufuncs.power)
+    descr_mod = _binop_impl(interp_ufuncs.mod)
+
+    def _binop_right_impl(w_ufunc):
+        def impl(self, space, w_other):
+            w_other = FloatWrapper(space.float_w(w_other))
+            return w_ufunc(space, w_other, self)
+        return func_with_new_name(impl, "binop_right_%s_impl" % w_ufunc.__name__)
+
+    descr_radd = _binop_right_impl(interp_ufuncs.add)
+    descr_rsub = _binop_right_impl(interp_ufuncs.subtract)
+    descr_rmul = _binop_right_impl(interp_ufuncs.multiply)
+    descr_rdiv = _binop_right_impl(interp_ufuncs.divide)
+    descr_rpow = _binop_right_impl(interp_ufuncs.power)
+    descr_rmod = _binop_right_impl(interp_ufuncs.mod)
+
+    def _reduce_sum_prod_impl(function, init):
+        reduce_driver = jit.JitDriver(greens=['signature'],
+                         reds = ['i', 'size', 'self', 'result'])
+
+        def loop(self, result, size):
+            i = 0
+            while i < size:
+                reduce_driver.jit_merge_point(signature=self.signature,
+                                              self=self, size=size, i=i,
+                                              result=result)
+                result = function(result, self.eval(i))
+                i += 1
+            return result
+
+        def impl(self, space):
+            return space.wrap(loop(self, init, self.find_size()))
+        return func_with_new_name(impl, "reduce_%s_impl" % function.__name__)
+
+    def _reduce_max_min_impl(function):
+        reduce_driver = jit.JitDriver(greens=['signature'],
+                         reds = ['i', 'size', 'self', 'result'])
+        def loop(self, result, size):
+            i = 1
+            while i < size:
+                reduce_driver.jit_merge_point(signature=self.signature,
+                                              self=self, size=size, i=i,
+                                              result=result)
+                result = function(result, self.eval(i))
+                i += 1
+            return result
+
+        def impl(self, space):
+            size = self.find_size()
+            if size == 0:
+                raise OperationError(space.w_ValueError,
+                    space.wrap("Can't call %s on zero-size arrays" \
+                            % function.__name__))
+            return space.wrap(loop(self, self.eval(0), size))
+        return func_with_new_name(impl, "reduce_%s_impl" % function.__name__)
+
+    def _reduce_argmax_argmin_impl(function):
+        reduce_driver = jit.JitDriver(greens=['signature'],
+                         reds = ['i', 'size', 'result', 'self', 'cur_best'])
+        def loop(self, size):
+            result = 0
+            cur_best = self.eval(0)
+            i = 1
+            while i < size:
+                reduce_driver.jit_merge_point(signature=self.signature,
+                                              self=self, size=size, i=i,
+                                              result=result, cur_best=cur_best)
+                new_best = function(cur_best, self.eval(i))
+                if new_best != cur_best:
+                    result = i
+                    cur_best = new_best
+                i += 1
+            return result
+        def impl(self, space):
+            size = self.find_size()
+            if size == 0:
+                raise OperationError(space.w_ValueError,
+                    space.wrap("Can't call %s on zero-size arrays" \
+                            % function.__name__))
+            return space.wrap(loop(self, size))
+        return func_with_new_name(impl, "reduce_arg%s_impl" % function.__name__)
+
+    def _all(self):
+        size = self.find_size()
+        i = 0
+        while i < size:
+            all_driver.jit_merge_point(signature=self.signature, self=self, size=size, i=i)
+            if not self.eval(i):
+                return False
+            i += 1
+        return True
+    def descr_all(self, space):
+        return space.wrap(self._all())
+
+    def _any(self):
+        size = self.find_size()
+        i = 0
+        while i < size:
+            any_driver.jit_merge_point(signature=self.signature, self=self, size=size, i=i)
+            if self.eval(i):
+                return True
+            i += 1
+        return False
+    def descr_any(self, space):
+        return space.wrap(self._any())
+
+    descr_sum = _reduce_sum_prod_impl(add, 0.0)
+    descr_prod = _reduce_sum_prod_impl(mul, 1.0)
+    descr_max = _reduce_max_min_impl(maximum)
+    descr_min = _reduce_max_min_impl(minimum)
+    descr_argmax = _reduce_argmax_argmin_impl(maximum)
+    descr_argmin = _reduce_argmax_argmin_impl(minimum)
+
+    def descr_dot(self, space, w_other):
+        if isinstance(w_other, BaseArray):
+            w_res = self.descr_mul(space, w_other)
+            assert isinstance(w_res, BaseArray)
+            return w_res.descr_sum(space)
+        else:
+            return self.descr_mul(space, w_other)
+
+    def _getnums(self, comma):
+        if self.find_size() > 1000:
+            nums = [
+                float2string(self.getitem(index))
+                for index in range(3)
+            ]
+            nums.append("..." + "," * comma)
+            nums.extend([
+                float2string(self.getitem(index))
+                for index in range(self.find_size() - 3, self.find_size())
+            ])
+        else:
+            nums = [
+                float2string(self.getitem(index))
+                for index in range(self.find_size())
+            ]
+        return nums
 
     def get_concrete(self):
         raise NotImplementedError
 
+    def descr_copy(self, space):
+        return new_numarray(space, self)
+
     def descr_get_shape(self, space):
         return space.newtuple([self.descr_len(space)])
 
     def descr_len(self, space):
         return self.get_concrete().descr_len(space)
 
+    def descr_repr(self, space):
+        # Simple implementation so that we can see the array. Needs work.
+        concrete = self.get_concrete()
+        return space.wrap("array([" + ", ".join(concrete._getnums(False)) + "])")
+
+    def descr_str(self, space):
+        # Simple implementation so that we can see the array. Needs work.
+        concrete = self.get_concrete()
+        return space.wrap("[" + " ".join(concrete._getnums(True)) + "]")
+
     def descr_getitem(self, space, w_idx):
         # TODO: indexing by tuples
         start, stop, step, slice_length = space.decode_index4(w_idx, self.find_size())
@@ -101,19 +235,61 @@
             res = SingleDimSlice(start, stop, step, slice_length, self, self.signature.transition(SingleDimSlice.static_signature))
             return space.wrap(res)
 
-    @unwrap_spec(item=int, value=float)
-    def descr_setitem(self, space, item, value):
+    def descr_setitem(self, space, w_idx, w_value):
+        # TODO: indexing by tuples and lists
         self.invalidated()
-        return self.get_concrete().descr_setitem(space, item, value)
+        start, stop, step, slice_length = space.decode_index4(w_idx,
+                                                              self.find_size())
+        if step == 0:
+            # Single index
+            self.get_concrete().setitem(start, space.float_w(w_value))
+        else:
+            concrete = self.get_concrete()
+            if isinstance(w_value, BaseArray):
+                # for now we just copy if setting part of an array from 
+                # part of itself. can be improved.
+                if (concrete.get_root_storage() ==
+                    w_value.get_concrete().get_root_storage()):
+                    w_value = new_numarray(space, w_value)
+            else:
+                w_value = convert_to_array(space, w_value)
+            concrete.setslice(space, start, stop, step, 
+                                               slice_length, w_value)
 
     def descr_mean(self, space):
-        s = 0
-        concrete = self.get_concrete()
-        size = concrete.find_size()
-        for i in xrange(size):
-            s += concrete.getitem(i)
-        return space.wrap(s / size)
+        return space.wrap(space.float_w(self.descr_sum(space))/self.find_size())
 
+    def _sliceloop1(self, start, stop, step, source, dest):
+        i = start
+        j = 0
+        while i < stop:
+            slice_driver1.jit_merge_point(signature=source.signature,
+                    step=step, stop=stop, i=i, j=j, source=source,
+                    dest=dest)
+            dest.storage[i] = source.eval(j)
+            j += 1
+            i += step
+
+    def _sliceloop2(self, start, stop, step, source, dest):
+        i = start
+        j = 0
+        while i > stop:
+            slice_driver2.jit_merge_point(signature=source.signature,
+                    step=step, stop=stop, i=i, j=j, source=source,
+                    dest=dest)
+            dest.storage[i] = source.eval(j)
+            j += 1
+            i += step
+
+def convert_to_array (space, w_obj):
+    if isinstance(w_obj, BaseArray):
+        return w_obj
+    elif space.issequence_w(w_obj):
+        # Convert to array.
+        return new_numarray(space, w_obj)
+    else:
+        # If it's a scalar
+        return FloatWrapper(space.float_w(w_obj))
 
 class FloatWrapper(BaseArray):
     """
@@ -249,8 +425,8 @@
         return self.parent.getitem(self.calc_index(item))
 
     @unwrap_spec(item=int, value=float)
-    def descr_setitem(self, space, item, value):
-        return self.parent.descr_setitem(space, self.calc_index(item), value)
+    def setitem(self, item, value):
+        return self.parent.setitem(self.calc_index(item), value)
 
     def descr_len(self, space):
         return space.wrap(self.find_size())
@@ -264,14 +440,34 @@
 
     def __init__(self, start, stop, step, slice_length, parent, signature):
         ViewArray.__init__(self, parent, signature)
-        self.start = start
-        self.stop = stop
-        self.step = step
+        if isinstance(parent, SingleDimSlice):
+            self.start = parent.calc_index(start)
+            self.stop = parent.calc_index(stop)
+            self.step = parent.step * step
+            self.parent = parent.parent
+        else:
+            self.start = start
+            self.stop = stop
+            self.step = step
+            self.parent = parent
         self.size = slice_length
 
+    def get_root_storage(self):
+        return self.parent.storage
+
     def find_size(self):
         return self.size
 
+    def setslice(self, space, start, stop, step, slice_length, arr):
+        start = self.calc_index(start)
+        if stop != -1:
+            stop = self.calc_index(stop)
+        step = self.step * step
+        if step > 0:
+            self._sliceloop1(start, stop, step, arr, self.parent)
+        else:
+            self._sliceloop2(start, stop, step, arr, self.parent)
+
     def calc_index(self, item):
         return (self.start + item * self.step)
 
@@ -289,46 +485,45 @@
     def get_concrete(self):
         return self
 
+    def get_root_storage(self):
+        return self.storage
+
     def find_size(self):
         return self.size
 
     def eval(self, i):
         return self.storage[i]
 
-    def getindex(self, space, item):
-        if item >= self.size:
-            raise operationerrfmt(space.w_IndexError,
-              '%d above array size', item)
-        if item < 0:
-            item += self.size
-        if item < 0:
-            raise operationerrfmt(space.w_IndexError,
-              '%d below zero', item)
-        return item
-
     def descr_len(self, space):
         return space.wrap(self.size)
 
     def getitem(self, item):
         return self.storage[item]
 
-    @unwrap_spec(item=int, value=float)
-    def descr_setitem(self, space, item, value):
-        item = self.getindex(space, item)
+    def setitem(self, item, value):
         self.invalidated()
         self.storage[item] = value
 
+    def setslice(self, space, start, stop, step, slice_length, arr):
+        if step > 0:
+            self._sliceloop1(start, stop, step, arr, self)
+        else:
+            self._sliceloop2(start, stop, step, arr, self)
+
     def __del__(self):
         lltype.free(self.storage, flavor='raw')
 
-def descr_new_numarray(space, w_type, w_size_or_iterable):
+def new_numarray(space, w_size_or_iterable):
     l = space.listview(w_size_or_iterable)
     arr = SingleDimArray(len(l))
     i = 0
     for w_elem in l:
         arr.storage[i] = space.float_w(space.float(w_elem))
         i += 1
-    return space.wrap(arr)
+    return arr
+
+def descr_new_numarray(space, w_type, w_size_or_iterable):
+    return space.wrap(new_numarray(space, w_size_or_iterable))
 
 @unwrap_spec(size=int)
 def zeros(space, size):
@@ -345,16 +540,39 @@
     'numarray',
     __new__ = interp2app(descr_new_numarray),
 
+    copy = interp2app(BaseArray.descr_copy),
     shape = GetSetProperty(BaseArray.descr_get_shape),
 
     __len__ = interp2app(BaseArray.descr_len),
     __getitem__ = interp2app(BaseArray.descr_getitem),
     __setitem__ = interp2app(BaseArray.descr_setitem),
 
+    __pos__ = interp2app(BaseArray.descr_pos),
+    __neg__ = interp2app(BaseArray.descr_neg),
+    __abs__ = interp2app(BaseArray.descr_abs),
     __add__ = interp2app(BaseArray.descr_add),
     __sub__ = interp2app(BaseArray.descr_sub),
     __mul__ = interp2app(BaseArray.descr_mul),
     __div__ = interp2app(BaseArray.descr_div),
+    __pow__ = interp2app(BaseArray.descr_pow),
+    __mod__ = interp2app(BaseArray.descr_mod),
+    __radd__ = interp2app(BaseArray.descr_radd),
+    __rsub__ = interp2app(BaseArray.descr_rsub),
+    __rmul__ = interp2app(BaseArray.descr_rmul),
+    __rdiv__ = interp2app(BaseArray.descr_rdiv),
+    __rpow__ = interp2app(BaseArray.descr_rpow),
+    __rmod__ = interp2app(BaseArray.descr_rmod),
+    __repr__ = interp2app(BaseArray.descr_repr),
+    __str__ = interp2app(BaseArray.descr_str),
 
     mean = interp2app(BaseArray.descr_mean),
+    sum = interp2app(BaseArray.descr_sum),
+    prod = interp2app(BaseArray.descr_prod),
+    max = interp2app(BaseArray.descr_max),
+    min = interp2app(BaseArray.descr_min),
+    argmax = interp2app(BaseArray.descr_argmax),
+    argmin = interp2app(BaseArray.descr_argmin),
+    all = interp2app(BaseArray.descr_all),
+    any = interp2app(BaseArray.descr_any),
+    dot = interp2app(BaseArray.descr_dot),
 )
diff --git a/pypy/module/micronumpy/interp_support.py b/pypy/module/micronumpy/interp_support.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/interp_support.py
@@ -0,0 +1,42 @@
+from pypy.rlib.rstruct.runpack import runpack
+from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.interpreter.error import OperationError
+from pypy.interpreter.gateway import unwrap_spec
+
+
+FLOAT_SIZE = rffi.sizeof(lltype.Float)
+
+ at unwrap_spec(s=str)
+def fromstring(space, s):
+    from pypy.module.micronumpy.interp_numarray import SingleDimArray
+    length = len(s)
+
+    if length % FLOAT_SIZE == 0:
+        number = length/FLOAT_SIZE
+    else:
+        raise OperationError(space.w_ValueError, space.wrap(
+            "string length %d not divisable by %d" % (length, FLOAT_SIZE)))
+
+    a = SingleDimArray(number)
+
+    start = 0
+    end = FLOAT_SIZE
+    i = 0
+    while i < number:
+        part = s[start:end]
+        a.storage[i] = runpack('d', part)
+        i += 1
+        start += FLOAT_SIZE
+        end += FLOAT_SIZE
+
+    return space.wrap(a)
+
+class Signature(object):
+    def __init__(self):
+        self.transitions = {}
+
+    def transition(self, target):
+        if target in self.transitions:
+            return self.transitions[target]
+        self.transitions[target] = new = Signature()
+        return new
\ No newline at end of file
diff --git a/pypy/module/micronumpy/interp_ufuncs.py b/pypy/module/micronumpy/interp_ufuncs.py
--- a/pypy/module/micronumpy/interp_ufuncs.py
+++ b/pypy/module/micronumpy/interp_ufuncs.py
@@ -1,31 +1,36 @@
 import math
 
-from pypy.interpreter.gateway import unwrap_spec
-from pypy.module.micronumpy.interp_numarray import BaseArray, Call1, Call2, Signature
+from pypy.module.micronumpy.interp_support import Signature
 from pypy.rlib import rfloat
 from pypy.tool.sourcetools import func_with_new_name
 
-
 def ufunc(func):
     signature = Signature()
     def impl(space, w_obj):
-        if isinstance(w_obj, BaseArray):
-            w_res = Call1(func, w_obj, w_obj.signature.transition(signature))
-            w_obj.invalidates.append(w_res)
+        from pypy.module.micronumpy.interp_numarray import Call1, convert_to_array
+        if space.issequence_w(w_obj):
+            w_obj_arr = convert_to_array(space, w_obj)
+            w_res = Call1(func, w_obj_arr, w_obj_arr.signature.transition(signature))
+            w_obj_arr.invalidates.append(w_res)
             return w_res
-        return space.wrap(func(space.float_w(w_obj)))
+        else:
+            return space.wrap(func(space.float_w(w_obj)))
     return func_with_new_name(impl, "%s_dispatcher" % func.__name__)
 
 def ufunc2(func):
     signature = Signature()
     def impl(space, w_lhs, w_rhs):
-        if isinstance(w_lhs, BaseArray) and isinstance(w_rhs, BaseArray):
-            new_sig = w_lhs.signature.transition(signature).transition(w_rhs.signature)
-            w_res = Call2(func, w_lhs, w_rhs, new_sig)
-            w_lhs.invalidates.append(w_res)
-            w_rhs.invalidates.append(w_res)
+        from pypy.module.micronumpy.interp_numarray import Call2, convert_to_array
+        if space.issequence_w(w_lhs) or space.issequence_w(w_rhs):
+            w_lhs_arr = convert_to_array(space, w_lhs)
+            w_rhs_arr = convert_to_array(space, w_rhs)
+            new_sig = w_lhs_arr.signature.transition(signature).transition(w_rhs_arr.signature)
+            w_res = Call2(func, w_lhs_arr, w_rhs_arr, new_sig)
+            w_lhs_arr.invalidates.append(w_res)
+            w_rhs_arr.invalidates.append(w_res)
             return w_res
-        return space.wrap(func(space.float_w(w_lhs), space.float_w(w_rhs)))
+        else:
+            return space.wrap(func(space.float_w(w_lhs), space.float_w(w_rhs)))
     return func_with_new_name(impl, "%s_dispatcher" % func.__name__)
 
 @ufunc
@@ -33,9 +38,17 @@
     return abs(value)
 
 @ufunc2
+def add(lvalue, rvalue):
+    return lvalue + rvalue
+
+ at ufunc2
 def copysign(lvalue, rvalue):
     return rfloat.copysign(lvalue, rvalue)
 
+ at ufunc2
+def divide(lvalue, rvalue):
+    return lvalue / rvalue
+
 @ufunc
 def exp(value):
     try:
@@ -43,6 +56,10 @@
     except OverflowError:
         return rfloat.INFINITY
 
+ at ufunc
+def fabs(value):
+    return math.fabs(value)
+
 @ufunc2
 def maximum(lvalue, rvalue):
     return max(lvalue, rvalue)
@@ -51,6 +68,15 @@
 def minimum(lvalue, rvalue):
     return min(lvalue, rvalue)
 
+ at ufunc2
+def multiply(lvalue, rvalue):
+    return lvalue * rvalue
+
+# Used by numarray for __pos__. Not visible from numpy application space.
+ at ufunc
+def positive(value):
+    return value
+
 @ufunc
 def negative(value):
     return -value
@@ -61,6 +87,10 @@
         return rfloat.copysign(rfloat.INFINITY, value)
     return 1.0 / value
 
+ at ufunc2
+def subtract(lvalue, rvalue):
+    return lvalue - rvalue
+
 @ufunc
 def floor(value):
     return math.floor(value)
@@ -70,3 +100,23 @@
     if value == 0.0:
         return 0.0
     return rfloat.copysign(1.0, value)
+
+ at ufunc
+def sin(value):
+    return math.sin(value)
+
+ at ufunc
+def cos(value):
+    return math.cos(value)
+
+ at ufunc
+def tan(value):
+    return math.tan(value)
+
+ at ufunc2
+def power(lvalue, rvalue):
+    return math.pow(lvalue, rvalue)
+
+ at ufunc2
+def mod(lvalue, rvalue):
+    return math.fmod(lvalue, rvalue)
diff --git a/pypy/module/micronumpy/test/test_base.py b/pypy/module/micronumpy/test/test_base.py
--- a/pypy/module/micronumpy/test/test_base.py
+++ b/pypy/module/micronumpy/test/test_base.py
@@ -1,12 +1,10 @@
 from pypy.conftest import gettestobjspace
 from pypy.module.micronumpy.interp_numarray import SingleDimArray, FloatWrapper
 
-
 class BaseNumpyAppTest(object):
     def setup_class(cls):
         cls.space = gettestobjspace(usemodules=('micronumpy',))
 
-
 class TestSignature(object):
     def test_binop_signature(self, space):
         ar = SingleDimArray(10)
@@ -26,4 +24,4 @@
 
         v3 = ar.descr_add(space, v1)
         v4 = ar.descr_add(space, v2)
-        assert v3.signature is v4.signature
\ No newline at end of file
+        assert v3.signature is v4.signature
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
@@ -1,6 +1,7 @@
 import py
 
 from pypy.module.micronumpy.test.test_base import BaseNumpyAppTest
+from pypy.conftest import gettestobjspace
 
 
 class AppTestNumArray(BaseNumpyAppTest):
@@ -37,11 +38,50 @@
         a[2] = 4
         assert a[2] == 4
 
+    def test_copy(self):
+        from numpy import array
+        a = array(range(5))
+        b = a.copy()
+        for i in xrange(5):
+            assert b[i] == a[i]
+
     def test_iterator_init(self):
         from numpy import array
         a = array(range(5))
         assert a[3] == 3
 
+    def test_repr(self):
+        from numpy import array, zeros
+        a = array(range(5))
+        assert repr(a) == "array([0.0, 1.0, 2.0, 3.0, 4.0])"
+        a = zeros(1001)
+        assert repr(a) == "array([0.0, 0.0, 0.0, ..., 0.0, 0.0, 0.0])"
+
+    def test_repr_slice(self):
+        from numpy import array, zeros
+        a = array(range(5))
+        b = a[1::2]
+        assert repr(b) == "array([1.0, 3.0])"
+        a = zeros(2002)
+        b = a[::2]
+        assert repr(b) == "array([0.0, 0.0, 0.0, ..., 0.0, 0.0, 0.0])"
+
+    def test_str(self):
+        from numpy import array, zeros
+        a = array(range(5))
+        assert str(a) == "[0.0 1.0 2.0 3.0 4.0]"
+        a = zeros(1001)
+        assert str(a) == "[0.0 0.0 0.0 ..., 0.0 0.0 0.0]"
+
+    def test_str_slice(self):
+        from numpy import array, zeros
+        a = array(range(5))
+        b = a[1::2]
+        assert str(b) == "[1.0 3.0]"
+        a = zeros(2002)
+        b = a[::2]
+        assert str(b) == "[0.0 0.0 0.0 ..., 0.0 0.0 0.0]"
+
     def test_getitem(self):
         from numpy import array
         a = array(range(5))
@@ -59,6 +99,51 @@
         raises(IndexError, "a[5] = 0.0")
         raises(IndexError, "a[-6] = 3.0")
 
+    def test_setslice_array(self):
+        from numpy import array
+        a = array(range(5))
+        b = array(range(2))
+        a[1:4:2] = b
+        assert a[1] == 0.
+        assert a[3] == 1.
+        b[::-1] = b
+        assert b[0] == 1.
+        assert b[1] == 0.
+
+    def test_setslice_of_slice_array(self):
+        from numpy import array, zeros
+        a = zeros(5)
+        a[::2] = array([9., 10., 11.])
+        assert a[0] == 9.
+        assert a[2] == 10.
+        assert a[4] == 11.
+        a[1:4:2][::-1] = array([1., 2.])
+        assert a[0] == 9.
+        assert a[1] == 2.
+        assert a[2] == 10.
+        assert a[3] == 1.
+        assert a[4] == 11.
+        a = zeros(10)
+        a[::2][::-1][::2] = array(range(1,4))
+        assert a[8] == 1.
+        assert a[4] == 2.
+        assert a[0] == 3.
+
+    def test_setslice_list(self):
+        from numpy import array
+        a = array(range(5))
+        b = [0., 1.]
+        a[1:4:2] = b
+        assert a[1] == 0.
+        assert a[3] == 1.
+
+    def test_setslice_constant(self):
+        from numpy import array
+        a = array(range(5))
+        a[1:4:2] = 0.
+        assert a[1] == 0.
+        assert a[3] == 0.
+
     def test_len(self):
         from numpy import array
         a = array(range(5))
@@ -96,6 +181,21 @@
         for i in range(5):
             assert b[i] == i + 5
 
+    def test_radd(self):
+        from numpy import array
+        r = 3 + array(range(3))
+        for i in range(3):
+            assert r[i] == i + 3
+
+    def test_add_list(self):
+        from numpy import array
+        a = array(range(5))
+        b = list(reversed(range(5)))
+        c = a + b
+        assert isinstance(c, array)
+        for i in range(5):
+            assert c[i] == 4
+
     def test_subtract(self):
         from numpy import array
         a = array(range(5))
@@ -154,6 +254,72 @@
         for i in range(5):
             assert b[i] == i / 5.0
 
+    def test_pow(self):
+        from numpy import array
+        a = array(range(5))
+        b = a ** a
+        for i in range(5):
+            print b[i], i**i
+            assert b[i] == i**i
+
+    def test_pow_other(self):
+        from numpy import array
+        a = array(range(5))
+        b = array([2, 2, 2, 2, 2])
+        c = a ** b
+        for i in range(5):
+            assert c[i] == i ** 2
+
+    def test_pow_constant(self):
+        from numpy import array
+        a = array(range(5))
+        b = a ** 2
+        for i in range(5):
+            assert b[i] == i ** 2
+
+    def test_mod(self):
+        from numpy import array
+        a = array(range(1,6))
+        b = a % a
+        for i in range(5):
+            assert b[i] == 0
+
+    def test_mod_other(self):
+        from numpy import array
+        a = array(range(5))
+        b = array([2, 2, 2, 2, 2])
+        c = a % b
+        for i in range(5):
+            assert c[i] == i % 2
+
+    def test_mod_constant(self):
+        from numpy import array
+        a = array(range(5))
+        b = a % 2
+        for i in range(5):
+            assert b[i] == i % 2
+
+    def test_pos(self):
+        from numpy import array
+        a = array([1.,-2.,3.,-4.,-5.])
+        b = +a
+        for i in range(5):
+            assert b[i] == a[i]
+
+    def test_neg(self):
+        from numpy import array
+        a = array([1.,-2.,3.,-4.,-5.])
+        b = -a
+        for i in range(5):
+            assert b[i] == -a[i]
+
+    def test_abs(self):
+        from numpy import array
+        a = array([1.,-2.,3.,-4.,-5.])
+        b = abs(a)
+        for i in range(5):
+            assert b[i] == abs(a[i])
+
     def test_auto_force(self):
         from numpy import array
         a = array(range(5))
@@ -210,7 +376,97 @@
         assert d[1] == 12
 
     def test_mean(self):
-        from numpy import array, mean
+        from numpy import array
         a = array(range(5))
         assert a.mean() == 2.0
-        assert a[:4].mean() == 1.5
\ No newline at end of file
+        assert a[:4].mean() == 1.5
+
+    def test_sum(self):
+        from numpy import array
+        a = array(range(5))
+        assert a.sum() == 10.0
+        assert a[:4].sum() == 6.0
+
+    def test_prod(self):
+        from numpy import array
+        a = array(range(1,6))
+        assert a.prod() == 120.0
+        assert a[:4].prod() == 24.0
+
+    def test_max(self):
+        from numpy import array
+        a = array([-1.2, 3.4, 5.7, -3.0, 2.7])
+        assert a.max() == 5.7
+        b = array([])
+        raises(ValueError, "b.max()")
+
+    def test_max_add(self):
+        from numpy import array
+        a = array([-1.2, 3.4, 5.7, -3.0, 2.7])
+        assert (a+a).max() == 11.4
+
+    def test_min(self):
+        from numpy import array
+        a = array([-1.2, 3.4, 5.7, -3.0, 2.7])
+        assert a.min() == -3.0
+        b = array([])
+        raises(ValueError, "b.min()")
+
+    def test_argmax(self):
+        from numpy import array
+        a = array([-1.2, 3.4, 5.7, -3.0, 2.7])
+        assert a.argmax() == 2
+        b = array([])
+        raises(ValueError, "b.argmax()")
+
+    def test_argmin(self):
+        from numpy import array
+        a = array([-1.2, 3.4, 5.7, -3.0, 2.7])
+        assert a.argmin() == 3
+        b = array([])
+        raises(ValueError, "b.argmin()")
+
+    def test_all(self):
+        from numpy import array
+        a = array(range(5))
+        assert a.all() == False
+        a[0] = 3.0
+        assert a.all() == True
+        b = array([])
+        assert b.all() == True
+
+    def test_any(self):
+        from numpy import array, zeros
+        a = array(range(5))
+        assert a.any() == True
+        b = zeros(5)
+        assert b.any() == False
+        c = array([])
+        assert c.any() == False
+
+    def test_dot(self):
+        from numpy import array
+        a = array(range(5))
+        assert a.dot(a) == 30.0
+
+    def test_dot_constant(self):
+        from numpy import array
+        a = array(range(5))
+        b = a.dot(2.5)
+        for i in xrange(5):
+            assert b[i] == 2.5*a[i]
+
+
+class AppTestSupport(object):
+    def setup_class(cls):
+        import struct
+        cls.space = gettestobjspace(usemodules=('micronumpy',))
+        cls.w_data = cls.space.wrap(struct.pack('dddd', 1, 2, 3, 4))
+
+    def test_fromstring(self):
+        from numpy import fromstring
+        a = fromstring(self.data)
+        for i in range(4):
+            assert a[i] == i + 1
+        raises(ValueError, fromstring, "abc")
+
diff --git a/pypy/module/micronumpy/test/test_ufuncs.py b/pypy/module/micronumpy/test/test_ufuncs.py
--- a/pypy/module/micronumpy/test/test_ufuncs.py
+++ b/pypy/module/micronumpy/test/test_ufuncs.py
@@ -10,6 +10,40 @@
         assert sign(-0.0) == 0.0
         assert minimum(2.0, 3.0) == 2.0
 
+    def test_sequence(self):
+        from numpy import array, negative, minimum
+        a = array(range(3))
+        b = [2.0, 1.0, 0.0]
+        c = 1.0
+        b_neg = negative(b)
+        assert isinstance(b_neg, array)
+        for i in range(3):
+            assert b_neg[i] == -b[i]
+        min_a_b = minimum(a, b)
+        assert isinstance(min_a_b, array)
+        for i in range(3):
+            assert min_a_b[i] == min(a[i], b[i])
+        min_b_a = minimum(b, a)
+        assert isinstance(min_b_a, array)
+        for i in range(3):
+            assert min_b_a[i] == min(a[i], b[i])
+        min_a_c = minimum(a, c)
+        assert isinstance(min_a_c, array)
+        for i in range(3):
+            assert min_a_c[i] == min(a[i], c)
+        min_c_a = minimum(c, a)
+        assert isinstance(min_c_a, array)
+        for i in range(3):
+            assert min_c_a[i] == min(a[i], c)
+        min_b_c = minimum(b, c)
+        assert isinstance(min_b_c, array)
+        for i in range(3):
+            assert min_b_c[i] == min(b[i], c)
+        min_c_b = minimum(c, b)
+        assert isinstance(min_c_b, array)
+        for i in range(3):
+            assert min_c_b[i] == min(b[i], c)
+
     def test_negative(self):
         from numpy import array, negative
 
@@ -31,6 +65,33 @@
         for i in range(3):
             assert b[i] == abs(a[i])
 
+    def test_add(self):
+        from numpy import array, add
+
+        a = array([-5.0, -0.0, 1.0])
+        b = array([ 3.0, -2.0,-3.0])
+        c = add(a, b)
+        for i in range(3):
+            assert c[i] == a[i] + b[i]
+
+    def test_divide(self):
+        from numpy import array, divide
+
+        a = array([-5.0, -0.0, 1.0])
+        b = array([ 3.0, -2.0,-3.0])
+        c = divide(a, b)
+        for i in range(3):
+            assert c[i] == a[i] / b[i]
+
+    def test_fabs(self):
+        from numpy import array, fabs
+        from math import fabs as math_fabs
+        
+        a = array([-5.0, -0.0, 1.0])
+        b = fabs(a)
+        for i in range(3):
+            assert b[i] == math_fabs(a[i])
+
     def test_minimum(self):
         from numpy import array, minimum
 
@@ -49,6 +110,15 @@
         for i in range(3):
             assert c[i] == max(a[i], b[i])
 
+    def test_multiply(self):
+        from numpy import array, multiply
+
+        a = array([-5.0, -0.0, 1.0])
+        b = array([ 3.0, -2.0,-3.0])
+        c = multiply(a, b)
+        for i in range(3):
+            assert c[i] == a[i] * b[i]
+
     def test_sign(self):
         from numpy import array, sign
 
@@ -67,6 +137,15 @@
         for i in range(4):
             assert b[i] == reference[i]
 
+    def test_subtract(self):
+        from numpy import array, subtract
+
+        a = array([-5.0, -0.0, 1.0])
+        b = array([ 3.0, -2.0,-3.0])
+        c = subtract(a, b)
+        for i in range(3):
+            assert c[i] == a[i] - b[i]
+
     def test_floor(self):
         from numpy import array, floor
 
@@ -99,3 +178,30 @@
             except OverflowError:
                 res = float('inf')
             assert b[i] == res
+
+    def test_sin(self):
+        import math
+        from numpy import array, sin
+
+        a = array([0, 1, 2, 3, math.pi, math.pi*1.5, math.pi*2])
+        b = sin(a)
+        for i in range(len(a)):
+            assert b[i] == math.sin(a[i])
+
+    def test_cos(self):
+        import math
+        from numpy import array, cos
+
+        a = array([0, 1, 2, 3, math.pi, math.pi*1.5, math.pi*2])
+        b = cos(a)
+        for i in range(len(a)):
+            assert b[i] == math.cos(a[i])
+
+    def test_tan(self):
+        import math
+        from numpy import array, tan
+
+        a = array([0, 1, 2, 3, math.pi, math.pi*1.5, math.pi*2])
+        b = tan(a)
+        for i in range(len(a)):
+            assert b[i] == math.tan(a[i])
diff --git a/pypy/module/micronumpy/test/test_zjit.py b/pypy/module/micronumpy/test/test_zjit.py
--- a/pypy/module/micronumpy/test/test_zjit.py
+++ b/pypy/module/micronumpy/test/test_zjit.py
@@ -1,20 +1,30 @@
 from pypy.jit.metainterp.test.support import LLJitMixin
 from pypy.rpython.test.test_llinterp import interpret
 from pypy.module.micronumpy.interp_numarray import (SingleDimArray, Signature,
-    FloatWrapper, Call1, Call2, SingleDimSlice, add, mul)
+    FloatWrapper, Call2, SingleDimSlice, add, mul, Call1)
 from pypy.module.micronumpy.interp_ufuncs import negative
 from pypy.module.micronumpy.compile import numpy_compile
+from pypy.rlib.objectmodel import specialize
+from pypy.rlib.nonconst import NonConstant
 
 class FakeSpace(object):
-    pass
+    w_ValueError = None
+
+    def issequence_w(self, w_obj):
+        return True
+
+    @specialize.argtype(1)
+    def wrap(self, w_obj):
+        return w_obj
+
+    def float_w(self, w_obj):
+        return float(w_obj)
 
 class TestNumpyJIt(LLJitMixin):
     def setup_class(cls):
         cls.space = FakeSpace()
 
     def test_add(self):
-        space = self.space
-
         def f(i):
             ar = SingleDimArray(i)
             v = Call2(add, ar, ar, Signature())
@@ -27,8 +37,6 @@
         assert result == f(5)
 
     def test_floatadd(self):
-        space = self.space
-
         def f(i):
             ar = SingleDimArray(i)
             v = Call2(add, ar, FloatWrapper(4.5), Signature())
@@ -40,11 +48,118 @@
                           "int_lt": 1, "guard_true": 1, "jump": 1})
         assert result == f(5)
 
-    def test_already_forecd(self):
+    def test_sum(self):
         space = self.space
 
         def f(i):
             ar = SingleDimArray(i)
+            return ar.descr_add(space, ar).descr_sum(space)
+
+        result = self.meta_interp(f, [5], listops=True, backendopt=True)
+        self.check_loops({"getarrayitem_raw": 2, "float_add": 2,
+                          "int_add": 1,
+                          "int_lt": 1, "guard_true": 1, "jump": 1})
+        assert result == f(5)
+
+    def test_prod(self):
+        space = self.space
+
+        def f(i):
+            ar = SingleDimArray(i)
+            return ar.descr_add(space, ar).descr_prod(space)
+
+        result = self.meta_interp(f, [5], listops=True, backendopt=True)
+        self.check_loops({"getarrayitem_raw": 2, "float_add": 1,
+                          "float_mul": 1, "int_add": 1,
+                          "int_lt": 1, "guard_true": 1, "jump": 1})
+        assert result == f(5)
+
+    def test_max(self):
+        space = self.space
+
+        def f(i):
+            ar = SingleDimArray(i)
+            j = 0
+            while j < i:
+                ar.get_concrete().storage[j] = float(j)
+                j += 1
+            return ar.descr_add(space, ar).descr_max(space)
+
+        result = self.meta_interp(f, [5], listops=True, backendopt=True)
+        self.check_loops({"getarrayitem_raw": 2, "float_add": 1,
+                          "float_gt": 1, "int_add": 1,
+                          "int_lt": 1, "guard_true": 1, 
+                          "guard_false": 1, "jump": 1})
+        assert result == f(5)
+
+    def test_min(self):
+        space = self.space
+
+        def f(i):
+            ar = SingleDimArray(i)
+            j = 0
+            while j < i:
+                ar.get_concrete().storage[j] = float(j)
+                j += 1
+            return ar.descr_add(space, ar).descr_min(space)
+
+        result = self.meta_interp(f, [5], listops=True, backendopt=True)
+        self.check_loops({"getarrayitem_raw": 2, "float_add": 1,
+                           "float_lt": 1, "int_add": 1,
+                           "int_lt": 1, "guard_true": 2,
+                           "jump": 1})
+        assert result == f(5)
+
+    def test_argmin(self):
+        space = self.space
+
+        def f(i):
+            ar = SingleDimArray(i)
+            j = 0
+            while j < i:
+                ar.get_concrete().storage[j] = float(j)
+                j += 1
+            return ar.descr_add(space, ar).descr_argmin(space)
+
+        result = self.meta_interp(f, [5], listops=True, backendopt=True)
+        self.check_loops({"getarrayitem_raw": 2, "float_add": 1,
+                           "float_lt": 1, "int_add": 1,
+                           "int_lt": 1, "guard_true": 2,
+                           "jump": 1})
+        assert result == f(5)
+
+    def test_all(self):
+        space = self.space
+
+        def f(i):
+            ar = SingleDimArray(i)
+            j = 0
+            while j < i:
+                ar.get_concrete().storage[j] = 1.0
+                j += 1
+            return ar.descr_add(space, ar).descr_all(space)
+        result = self.meta_interp(f, [5], listops=True, backendopt=True)
+        self.check_loops({"getarrayitem_raw": 2, "float_add": 1,
+                          "int_add": 1, "float_ne": 1,
+                          "int_lt": 1, "guard_true": 2, "jump": 1})
+        assert result == f(5)
+
+    def test_any(self):
+        space = self.space
+
+        def f(i):
+            ar = SingleDimArray(i)
+            return ar.descr_add(space, ar).descr_any(space)
+
+        result = self.meta_interp(f, [5], listops=True, backendopt=True)
+        self.check_loops({"getarrayitem_raw": 2, "float_add": 1,
+                          "int_add": 1, "float_ne": 1, "guard_false": 1,
+                          "int_lt": 1, "guard_true": 1, "jump": 1})
+        assert result == f(5)
+
+    def test_already_forecd(self):
+        def f(i):
+            ar = SingleDimArray(i)
             v1 = Call2(add, ar, FloatWrapper(4.5), Signature())
             v2 = Call2(mul, v1, FloatWrapper(4.5), Signature())
             v1.force_if_needed()
@@ -95,8 +210,6 @@
         self.check_loop_count(3)
 
     def test_slice(self):
-        space = self.space
-
         def f(i):
             step = 3
             ar = SingleDimArray(step*i)
@@ -111,8 +224,6 @@
         assert result == f(5)
 
     def test_slice2(self):
-        space = self.space
-
         def f(i):
             step1 = 2
             step2 = 3
@@ -128,6 +239,28 @@
                           'int_lt': 1, 'guard_true': 1, 'jump': 1})
         assert result == f(5)
 
+    def test_setslice(self):
+        space = self.space
+
+        def f(i):
+            step = NonConstant(3)
+            ar = SingleDimArray(step*i)
+            ar2 = SingleDimArray(i)
+            ar2.storage[1] = 5.5
+            if NonConstant(False):
+                arg = ar2
+            else:
+                arg = ar2.descr_add(space, ar2)
+            ar.setslice(space, 0, step*i, step, i, arg)
+            return ar.get_concrete().storage[3]
+
+        result = self.meta_interp(f, [5], listops=True, backendopt=True)
+        self.check_loops({'getarrayitem_raw': 2,
+                          'float_add' : 1,
+                          'setarrayitem_raw': 1, 'int_add': 2,
+                          'int_lt': 1, 'guard_true': 1, 'jump': 1})
+        assert result == 11.0
+
 class TestTranslation(object):
     def test_compile(self):
         x = numpy_compile('aa+f*f/a-', 10)
diff --git a/pypy/module/mmap/interp_mmap.py b/pypy/module/mmap/interp_mmap.py
--- a/pypy/module/mmap/interp_mmap.py
+++ b/pypy/module/mmap/interp_mmap.py
@@ -1,21 +1,16 @@
-from pypy.rpython.tool import rffi_platform
-from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.interpreter.error import OperationError, wrap_oserror
 from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.typedef import TypeDef
 from pypy.interpreter.gateway import interp2app, unwrap_spec, NoneNotWrapped
 from pypy.rlib import rmmap
 from pypy.rlib.rmmap import RValueError, RTypeError, ROverflowError
-import sys
-import os
-import platform
-import stat
+
 
 class W_MMap(Wrappable):
     def __init__(self, space, mmap_obj):
         self.space = space
         self.mmap = mmap_obj
-        
+
     def close(self):
         self.mmap.close()
 
diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py
--- a/pypy/module/posix/test/test_posix2.py
+++ b/pypy/module/posix/test/test_posix2.py
@@ -125,13 +125,13 @@
         assert st.st_size == 14
         assert st.st_nlink == 1
 
-        #if sys.platform.startswith('linux2'):
+        #if sys.platform.startswith('linux'):
         #    # expects non-integer timestamps - it's unlikely that they are
         #    # all three integers
         #    assert ((st.st_atime, st.st_mtime, st.st_ctime) !=
         #            (st[7],       st[8],       st[9]))
         #    assert st.st_blksize * st.st_blocks >= st.st_size
-        if sys.platform.startswith('linux2'):
+        if sys.platform.startswith('linux'):
             assert hasattr(st, 'st_rdev')
 
     def test_stat_float_times(self):
diff --git a/pypy/module/pypyjit/interp_jit.py b/pypy/module/pypyjit/interp_jit.py
--- a/pypy/module/pypyjit/interp_jit.py
+++ b/pypy/module/pypyjit/interp_jit.py
@@ -15,7 +15,6 @@
 from pypy.interpreter.gateway import unwrap_spec
 from pypy.interpreter.baseobjspace import ObjSpace, W_Root
 from opcode import opmap
-from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.nonconst import NonConstant
 from pypy.jit.metainterp.resoperation import rop
 from pypy.module.pypyjit.interp_resop import debug_merge_point_from_boxes
@@ -45,9 +44,11 @@
             ec.w_tracefunc is None)
 
 def can_never_inline(next_instr, is_being_profiled, bytecode):
+    return False
+
+def should_unroll_one_iteration(next_instr, is_being_profiled, bytecode):
     return (bytecode.co_flags & CO_GENERATOR) != 0
 
-
 def wrap_oplist(space, logops, operations):
     list_w = []
     for op in operations:
@@ -66,7 +67,7 @@
     def on_compile(self, logger, looptoken, operations, type, next_instr,
                    is_being_profiled, ll_pycode):
         from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
-        
+
         space = self.space
         cache = space.fromcache(Cache)
         if cache.in_recursion:
@@ -111,7 +112,9 @@
                               get_jitcell_at = get_jitcell_at,
                               set_jitcell_at = set_jitcell_at,
                               confirm_enter_jit = confirm_enter_jit,
-                              can_never_inline = can_never_inline)
+                              can_never_inline = can_never_inline,
+                              should_unroll_one_iteration =
+                              should_unroll_one_iteration)
 
 class __extend__(PyFrame):
 
@@ -170,7 +173,7 @@
 
 # ____________________________________________________________
 #
-# Public interface    
+# Public interface
 
 def set_param(space, __args__):
     '''Configure the tunable JIT parameters.
@@ -212,7 +215,7 @@
 
 class Cache(object):
     in_recursion = False
-    
+
     def __init__(self, space):
         self.w_compile_hook = space.w_None
 
diff --git a/pypy/module/pypyjit/interp_resop.py b/pypy/module/pypyjit/interp_resop.py
--- a/pypy/module/pypyjit/interp_resop.py
+++ b/pypy/module/pypyjit/interp_resop.py
@@ -1,9 +1,9 @@
 
 from pypy.interpreter.typedef import TypeDef, interp_attrproperty
-from pypy.interpreter.baseobjspace import Wrappable, ObjSpace, W_Root
+from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.gateway import unwrap_spec, interp2app
 from pypy.interpreter.pycode import PyCode
-from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
 from pypy.rpython.lltypesystem.rclass import OBJECT
 
diff --git a/pypy/module/pypyjit/test_pypy_c/test__ffi.py b/pypy/module/pypyjit/test_pypy_c/test__ffi.py
--- a/pypy/module/pypyjit/test_pypy_c/test__ffi.py
+++ b/pypy/module/pypyjit/test_pypy_c/test__ffi.py
@@ -30,7 +30,6 @@
         assert res == 8.0 * 300
         loop, = log.loops_by_filename(self.filepath)
         assert loop.match_by_id('fficall', """
-            p16 = getfield_gc(ConstPtr(ptr15), descr=<.* .*Function.inst_name .*>)
             guard_not_invalidated(descr=...)
             i17 = force_token()
             setfield_gc(p0, i17, descr=<.* .*PyFrame.vable_token .*>)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_array.py b/pypy/module/pypyjit/test_pypy_c/test_array.py
--- a/pypy/module/pypyjit/test_pypy_c/test_array.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_array.py
@@ -19,7 +19,7 @@
         loop, = log.loops_by_filename(self.filepath)
         assert loop.match("""
             i7 = int_lt(i5, i6)
-            guard_true(i7, descr=<Guard3>)
+            guard_true(i7, descr=...)
             i9 = int_add(i5, 1)
             --TICK--
             jump(p0, p1, p2, p3, p4, i9, i6, descr=<Loop0>)
@@ -39,11 +39,12 @@
         assert log.result == 19507200
         loop, = log.loops_by_filename(self.filepath)
         assert loop.match("""
+            guard_not_invalidated(descr=...)
             i13 = int_lt(i7, i9)
-            guard_true(i13, descr=<Guard3>)
+            guard_true(i13, descr=...)
             i15 = getarrayitem_raw(i10, i7, descr=<.*ArrayNoLengthDescr>)
             i16 = int_add_ovf(i8, i15)
-            guard_no_overflow(descr=<Guard4>)
+            guard_no_overflow(descr=...)
             i18 = int_add(i7, 1)
             --TICK--
             jump(p0, p1, p2, p3, p4, p5, i18, i16, p8, i9, i10, descr=<Loop0>)
@@ -68,16 +69,17 @@
         loop, = log.loops_by_filename(self.filepath)
         assert loop.match("""
             i13 = int_lt(i8, 307200)
-            guard_true(i13, descr=<Guard3>)
+            guard_true(i13, descr=...)
+            guard_not_invalidated(descr=...)
         # the bound check guard on img has been killed (thanks to the asserts)
             i14 = getarrayitem_raw(i10, i8, descr=<.*ArrayNoLengthDescr>)
             i15 = int_add_ovf(i9, i14)
-            guard_no_overflow(descr=<Guard4>)
+            guard_no_overflow(descr=...)
             i17 = int_sub(i8, 640)
         # the bound check guard on intimg has been killed (thanks to the asserts)
             i18 = getarrayitem_raw(i11, i17, descr=<.*ArrayNoLengthDescr>)
             i19 = int_add_ovf(i18, i15)
-            guard_no_overflow(descr=<Guard5>)
+            guard_no_overflow(descr=...)
         # on 64bit, there is a guard checking that i19 actually fits into 32bit
             ...
             setarrayitem_raw(i11, i8, _, descr=<.*ArrayNoLengthDescr>)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_call.py b/pypy/module/pypyjit/test_pypy_c/test_call.py
--- a/pypy/module/pypyjit/test_pypy_c/test_call.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_call.py
@@ -80,19 +80,19 @@
         #
         assert entry_bridge.match_by_id('call', """
             p29 = getfield_gc(ConstPtr(ptr28), descr=<GcPtrFieldDescr pypy.objspace.std.celldict.ModuleCell.inst_w_value .*>)
-            guard_nonnull_class(p29, ConstClass(Function), descr=<Guard18>)
+            guard_nonnull_class(p29, ConstClass(Function), descr=...)
             p33 = getfield_gc(p29, descr=<GcPtrFieldDescr pypy.interpreter.function.Function.inst_code .*>)
-            guard_value(p33, ConstPtr(ptr34), descr=<Guard19>)
+            guard_value(p33, ConstPtr(ptr34), descr=...)
             p35 = getfield_gc(p29, descr=<GcPtrFieldDescr pypy.interpreter.function.Function.inst_w_func_globals .*>)
             p36 = getfield_gc(p29, descr=<GcPtrFieldDescr pypy.interpreter.function.Function.inst_closure .*>)
             p38 = call(ConstClass(getexecutioncontext), descr=<GcPtrCallDescr>)
             p39 = getfield_gc(p38, descr=<GcPtrFieldDescr pypy.interpreter.executioncontext.ExecutionContext.inst_topframeref .*>)
             i40 = force_token()
             p41 = getfield_gc(p38, descr=<GcPtrFieldDescr pypy.interpreter.executioncontext.ExecutionContext.inst_w_tracefunc .*>)
-            guard_isnull(p41, descr=<Guard20>)
+            guard_isnull(p41, descr=...)
             i42 = getfield_gc(p38, descr=<NonGcPtrFieldDescr pypy.interpreter.executioncontext.ExecutionContext.inst_profilefunc .*>)
             i43 = int_is_zero(i42)
-            guard_true(i43, descr=<Guard21>)
+            guard_true(i43, descr=...)
             i50 = force_token()
         """)
         #
@@ -101,16 +101,16 @@
         loop, = log.loops_by_id('call')
         assert loop.match("""
             i12 = int_lt(i5, i6)
-            guard_true(i12, descr=<Guard3>)
+            guard_true(i12, descr=...)
             i13 = force_token()
             i15 = int_add(i5, 1)
             i16 = int_add_ovf(i15, i7)
-            guard_no_overflow(descr=<Guard4>)
+            guard_no_overflow(descr=...)
             i18 = force_token()
             i20 = int_add_ovf(i16, 1)
-            guard_no_overflow(descr=<Guard5>)
+            guard_no_overflow(descr=...)
             i21 = int_add_ovf(i20, i7)
-            guard_no_overflow(descr=<Guard6>)
+            guard_no_overflow(descr=...)
             --TICK--
             jump(p0, p1, p2, p3, p4, i21, i6, i7, p8, p9, p10, p11, descr=<Loop0>)
         """)
@@ -146,14 +146,14 @@
         loop, = log.loops_by_filename(self.filepath)
         assert loop.match("""
             i15 = int_lt(i6, i9)
-            guard_true(i15, descr=<Guard3>)
-            guard_not_invalidated(descr=<Guard4>)
+            guard_true(i15, descr=...)
+            guard_not_invalidated(descr=...)
             i16 = force_token()
             i17 = int_add_ovf(i10, i6)
-            guard_no_overflow(descr=<Guard5>)
+            guard_no_overflow(descr=...)
             i18 = force_token()
             i19 = int_add_ovf(i10, i17)
-            guard_no_overflow(descr=<Guard6>)
+            guard_no_overflow(descr=...)
             --TICK--
             jump(p0, p1, p2, p3, p4, p5, i19, p7, i17, i9, i10, p11, p12, p13, descr=<Loop0>)
         """)
@@ -180,11 +180,11 @@
         loop, = log.loops_by_filename(self.filepath)
         assert loop.match("""
             i14 = int_lt(i6, i9)
-            guard_true(i14, descr=<Guard3>)
-            guard_not_invalidated(descr=<Guard4>)
+            guard_true(i14, descr=...)
+            guard_not_invalidated(descr=...)
             i15 = force_token()
             i17 = int_add_ovf(i8, 1)
-            guard_no_overflow(descr=<Guard5>)
+            guard_no_overflow(descr=...)
             i18 = force_token()
             --TICK--
             jump(p0, p1, p2, p3, p4, i8, p7, i17, p8, i9, p10, p11, p12, descr=<Loop0>)
@@ -282,32 +282,30 @@
         loop0, = log.loops_by_id('g1')
         assert loop0.match_by_id('g1', """
             i20 = force_token()
-            setfield_gc(p4, i19, descr=<.*W_AbstractSeqIterObject.inst_index .*>)
             i22 = int_add_ovf(i8, 3)
-            guard_no_overflow(descr=<Guard.*>)
+            guard_no_overflow(descr=...)
         """)
         assert loop0.match_by_id('h1', """
             i20 = force_token()
             i22 = int_add_ovf(i8, 2)
-            guard_no_overflow(descr=<Guard.*>)
+            guard_no_overflow(descr=...)
         """)
         assert loop0.match_by_id('g2', """
             i27 = force_token()
             i29 = int_add_ovf(i26, 3)
-            guard_no_overflow(descr=<Guard.*>)
+            guard_no_overflow(descr=...)
         """)
         #
         loop1, = log.loops_by_id('g3')
         assert loop1.match_by_id('g3', """
             i21 = force_token()
-            setfield_gc(p4, i20, descr=<.* .*W_AbstractSeqIterObject.inst_index .*>)
             i23 = int_add_ovf(i9, 3)
-            guard_no_overflow(descr=<Guard.*>)
+            guard_no_overflow(descr=...)
         """)
         assert loop1.match_by_id('h2', """
             i25 = force_token()
             i27 = int_add_ovf(i23, 2)
-            guard_no_overflow(descr=<Guard.*>)
+            guard_no_overflow(descr=...)
         """)
 
     def test_stararg(self):
@@ -353,7 +351,7 @@
             i13 = getfield_gc(p8, descr=<SignedFieldDescr list.length .*>)
             i15 = int_add(i13, 1)
             call(ConstClass(_ll_list_resize_ge__listPtr_Signed), p8, i15, descr=<VoidCallDescr>)
-            guard_no_exception(descr=<Guard4>)
+            guard_no_exception(descr=...)
             p17 = getfield_gc(p8, descr=<GcPtrFieldDescr list.items .*>)
             p19 = new_with_vtable(ConstClass(W_IntObject))
             setfield_gc(p19, i12, descr=<SignedFieldDescr .*W_IntObject.inst_intval .*>)
@@ -405,9 +403,9 @@
         loop, = log.loops_by_filename(self.filepath)
         assert loop.match("""
             i10 = int_lt(i5, i6)
-            guard_true(i10, descr=<Guard3>)
+            guard_true(i10, descr=...)
+            guard_not_invalidated(descr=...)
             i120 = int_add(i5, 1)
-            guard_not_invalidated(descr=<Guard4>)
             --TICK--
             jump(..., descr=<Loop0>)
         """)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_containers.py b/pypy/module/pypyjit/test_pypy_c/test_containers.py
--- a/pypy/module/pypyjit/test_pypy_c/test_containers.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_containers.py
@@ -23,3 +23,29 @@
         ops = loop.ops_by_id('look')
         assert log.opnames(ops) == ['setfield_gc',
                                     'guard_not_invalidated']
+
+    def test_identitydict(self):
+        def fn(n):
+            class X(object):
+                pass
+            x = X()
+            d = {}
+            d[x] = 1
+            res = 0
+            for i in range(300):
+                value = d[x]  # ID: getitem
+                res += value
+            return res
+        #
+        log = self.run(fn, [1000])
+        assert log.result == 300
+        loop, = log.loops_by_filename(self.filepath)
+        # check that the call to ll_dict_lookup is not a call_may_force
+        assert loop.match_by_id("getitem", """
+            i25 = call(ConstClass(_ll_1_gc_identityhash__objectPtr), p6, descr=...)
+            ...
+            i28 = call(ConstClass(ll_dict_lookup__dicttablePtr_objectPtr_Signed), p18, p6, i25, descr=...)
+            ...
+            p33 = call(ConstClass(ll_get_value__dicttablePtr_Signed), p18, i28, descr=...)
+            ...
+        """)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_exception.py b/pypy/module/pypyjit/test_pypy_c/test_exception.py
--- a/pypy/module/pypyjit/test_pypy_c/test_exception.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_exception.py
@@ -36,11 +36,11 @@
         loop, = log.loops_by_filename(self.filepath)
         assert loop.match("""
         i5 = int_is_true(i3)
-        guard_true(i5, descr=<Guard3>)
-        guard_not_invalidated(descr=<Guard4>)
+        guard_true(i5, descr=...)
+        guard_not_invalidated(descr=...)
         --EXC-TICK--
         i12 = int_sub_ovf(i3, 1)
-        guard_no_overflow(descr=<Guard6>)
+        guard_no_overflow(descr=...)
         --TICK--
         jump(..., descr=<Loop0>)
         """)
@@ -84,8 +84,8 @@
         loop, = log.loops_by_filename(self.filepath)
         assert loop.match("""
             i7 = int_lt(i4, i5)
-            guard_true(i7, descr=<Guard3>)
-            guard_not_invalidated(descr=<Guard4>)
+            guard_true(i7, descr=...)
+            guard_not_invalidated(descr=...)
             --EXC-TICK--
             i14 = int_add(i4, 1)
             --TICK--
diff --git a/pypy/module/pypyjit/test_pypy_c/test_generators.py b/pypy/module/pypyjit/test_pypy_c/test_generators.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/pypyjit/test_pypy_c/test_generators.py
@@ -0,0 +1,25 @@
+from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC
+
+
+class TestGenerators(BaseTestPyPyC):
+    def test_simple_generator(self):
+        def main(n):
+            def f():
+                for i in range(10000):
+                    yield i
+
+            def g():
+                for i in f():  # ID: generator
+                    pass
+
+            g()
+
+        log = self.run(main, [500])
+        loop, = log.loops_by_filename(self.filepath)
+        assert loop.match_by_id("generator", """
+            i16 = force_token()
+            p45 = new_with_vtable(ConstClass(W_IntObject))
+            setfield_gc(p45, i29, descr=<SignedFieldDescr .*>)
+            setarrayitem_gc(p8, 0, p45, descr=<GcPtrArrayDescr>)
+            jump(..., descr=...)
+            """)
diff --git a/pypy/module/pypyjit/test_pypy_c/test_globals.py b/pypy/module/pypyjit/test_pypy_c/test_globals.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/pypyjit/test_pypy_c/test_globals.py
@@ -0,0 +1,30 @@
+from pypy.module.pypyjit.test_pypy_c.test_00_model import BaseTestPyPyC
+
+
+class TestGlobals(BaseTestPyPyC):
+    def test_load_builtin(self):
+        def main(n):
+            import pypyjit
+
+            i = 0
+            while i < n:
+                l = len # ID: loadglobal
+                i += pypyjit.residual_call(l, "a")
+            return i
+        #
+        log = self.run(main, [500])
+        assert log.result == 500
+        loop, = log.loops_by_filename(self.filepath)
+        assert loop.match_by_id("loadglobal", """
+            p10 = getfield_gc(p0, descr=<GcPtrFieldDescr .*Frame.inst_w_globals .*>)
+            guard_value(p10, ConstPtr(ptr11), descr=...)
+            p12 = getfield_gc(p10, descr=<GcPtrFieldDescr .*W_DictMultiObject.inst_strategy .*>)
+            guard_value(p12, ConstPtr(ptr13), descr=...)
+            p15 = getfield_gc(ConstPtr(ptr14), descr=<GcPtrFieldDescr .*ModuleCell.inst_w_value .*>)
+            guard_isnull(p15, descr=...)
+            guard_not_invalidated(descr=...)
+            p19 = getfield_gc(ConstPtr(p17), descr=<GcPtrFieldDescr .*W_DictMultiObject.inst_strategy .*>)
+            guard_value(p19, ConstPtr(ptr20), descr=...)
+            p22 = getfield_gc(ConstPtr(ptr21), descr=<GcPtrFieldDescr .*ModuleCell.inst_w_value .*>)
+            guard_nonnull(p22, descr=...)
+        """)
\ No newline at end of file
diff --git a/pypy/module/pypyjit/test_pypy_c/test_import.py b/pypy/module/pypyjit/test_pypy_c/test_import.py
--- a/pypy/module/pypyjit/test_pypy_c/test_import.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_import.py
@@ -15,13 +15,13 @@
         assert log.result == 500
         loop, = log.loops_by_id('import')
         assert loop.match_by_id('import', """
+            guard_not_invalidated(descr=...)
             p11 = getfield_gc(ConstPtr(ptr10), descr=<GcPtrFieldDescr pypy.objspace.std.celldict.ModuleCell.inst_w_value 8>)
-            guard_value(p11, ConstPtr(ptr12), descr=<Guard4>)
-            guard_not_invalidated(descr=<Guard5>)
+            guard_value(p11, ConstPtr(ptr12), descr=...)
             p14 = getfield_gc(ConstPtr(ptr13), descr=<GcPtrFieldDescr pypy.objspace.std.celldict.ModuleCell.inst_w_value 8>)
             p16 = getfield_gc(ConstPtr(ptr15), descr=<GcPtrFieldDescr pypy.objspace.std.celldict.ModuleCell.inst_w_value 8>)
-            guard_value(p14, ConstPtr(ptr17), descr=<Guard6>)
-            guard_isnull(p16, descr=<Guard7>)
+            guard_value(p14, ConstPtr(ptr17), descr=...)
+            guard_isnull(p16, descr=...)
         """)
 
     def test_import_fast_path(self, tmpdir):
diff --git a/pypy/module/pypyjit/test_pypy_c/test_instance.py b/pypy/module/pypyjit/test_pypy_c/test_instance.py
--- a/pypy/module/pypyjit/test_pypy_c/test_instance.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_instance.py
@@ -22,10 +22,10 @@
         loop, = log.loops_by_filename(self.filepath)
         assert loop.match("""
             i7 = int_lt(i5, i6)
-            guard_true(i7, descr=<Guard3>)
-            guard_not_invalidated(descr=<Guard4>)
+            guard_true(i7, descr=...)
+            guard_not_invalidated(descr=...)
             i9 = int_add_ovf(i5, 2)
-            guard_no_overflow(descr=<Guard5>)
+            guard_no_overflow(descr=...)
             --TICK--
             jump(p0, p1, p2, p3, p4, i9, i6, descr=<Loop0>)
         """)
@@ -47,10 +47,10 @@
         loop, = log.loops_by_filename(self.filepath)
         assert loop.match("""
             i9 = int_lt(i5, i6)
-            guard_true(i9, descr=<Guard3>)
-            guard_not_invalidated(descr=<Guard4>)
+            guard_true(i9, descr=...)
+            guard_not_invalidated(descr=...)
             i10 = int_add_ovf(i5, i7)
-            guard_no_overflow(descr=<Guard5>)
+            guard_no_overflow(descr=...)
             --TICK--
             jump(p0, p1, p2, p3, p4, i10, i6, p7, i7, p8, descr=<Loop0>)
         """)
@@ -115,7 +115,7 @@
         # ----------------------
         loop, = log.loops_by_filename(self.filepath)
         assert loop.match("""
-            i9 = int_lt(i7, i8)
+            i9 = int_lt(i8, i7)
             guard_true(i9, descr=.*)
             guard_not_invalidated(descr=.*)
             i11 = int_add(i8, 1)
@@ -124,7 +124,7 @@
             p20 = new_with_vtable(ConstClass(W_IntObject))


More information about the pypy-commit mailing list