[pypy-commit] pypy SpecialisedTuples: hg merge default

arigo noreply at buildbot.pypy.org
Thu Dec 8 15:02:03 CET 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: SpecialisedTuples
Changeset: r50300:4f1c5b700152
Date: 2011-12-08 14:59 +0100
http://bitbucket.org/pypy/pypy/changeset/4f1c5b700152/

Log:	hg merge default

diff too long, truncating to 10000 out of 28312 lines

diff --git a/.hgtags b/.hgtags
--- a/.hgtags
+++ b/.hgtags
@@ -1,3 +1,4 @@
 b590cf6de4190623aad9aa698694c22e614d67b9 release-1.5
 b48df0bf4e75b81d98f19ce89d4a7dc3e1dab5e5 benchmarked
 d8ac7d23d3ec5f9a0fa1264972f74a010dbfd07f release-1.6
+ff4af8f318821f7f5ca998613a60fca09aa137da release-1.7
diff --git a/lib-python/2.7/test/test_os.py b/lib-python/2.7/test/test_os.py
--- a/lib-python/2.7/test/test_os.py
+++ b/lib-python/2.7/test/test_os.py
@@ -74,7 +74,8 @@
         self.assertFalse(os.path.exists(name),
                     "file already exists for temporary file")
         # make sure we can create the file
-        open(name, "w")
+        f = open(name, "w")
+        f.close()
         self.files.append(name)
 
     def test_tempnam(self):
diff --git a/lib-python/conftest.py b/lib-python/conftest.py
--- a/lib-python/conftest.py
+++ b/lib-python/conftest.py
@@ -201,7 +201,7 @@
     RegrTest('test_difflib.py'),
     RegrTest('test_dircache.py', core=True),
     RegrTest('test_dis.py'),
-    RegrTest('test_distutils.py'),
+    RegrTest('test_distutils.py', skip=True),
     RegrTest('test_dl.py', skip=True),
     RegrTest('test_doctest.py', usemodules="thread"),
     RegrTest('test_doctest2.py'),
diff --git a/lib-python/modified-2.7/ctypes/__init__.py b/lib-python/modified-2.7/ctypes/__init__.py
--- a/lib-python/modified-2.7/ctypes/__init__.py
+++ b/lib-python/modified-2.7/ctypes/__init__.py
@@ -351,7 +351,7 @@
         self._FuncPtr = _FuncPtr
 
         if handle is None:
-            self._handle = _ffi.CDLL(name)
+            self._handle = _ffi.CDLL(name, mode)
         else:
             self._handle = handle
 
diff --git a/lib-python/modified-2.7/ctypes/test/test_simplesubclasses.py b/lib-python/modified-2.7/ctypes/test/test_simplesubclasses.py
--- a/lib-python/modified-2.7/ctypes/test/test_simplesubclasses.py
+++ b/lib-python/modified-2.7/ctypes/test/test_simplesubclasses.py
@@ -1,6 +1,5 @@
 import unittest
 from ctypes import *
-from ctypes.test import xfail
 
 class MyInt(c_int):
     def __cmp__(self, other):
@@ -27,7 +26,6 @@
         self.assertEqual(None, cb())
 
 
-    @xfail
     def test_int_callback(self):
         args = []
         def func(arg):
diff --git a/lib-python/2.7/pkgutil.py b/lib-python/modified-2.7/pkgutil.py
copy from lib-python/2.7/pkgutil.py
copy to lib-python/modified-2.7/pkgutil.py
--- a/lib-python/2.7/pkgutil.py
+++ b/lib-python/modified-2.7/pkgutil.py
@@ -244,7 +244,8 @@
         return mod
 
     def get_data(self, pathname):
-        return open(pathname, "rb").read()
+        with open(pathname, "rb") as f:
+            return f.read()
 
     def _reopen(self):
         if self.file and self.file.closed:
diff --git a/lib-python/modified-2.7/test/test_import.py b/lib-python/modified-2.7/test/test_import.py
--- a/lib-python/modified-2.7/test/test_import.py
+++ b/lib-python/modified-2.7/test/test_import.py
@@ -64,6 +64,7 @@
             except ImportError, err:
                 self.fail("import from %s failed: %s" % (ext, err))
             else:
+                # XXX importing .pyw is missing on Windows
                 self.assertEqual(mod.a, a,
                     "module loaded (%s) but contents invalid" % mod)
                 self.assertEqual(mod.b, b,
diff --git a/lib-python/modified-2.7/test/test_repr.py b/lib-python/modified-2.7/test/test_repr.py
--- a/lib-python/modified-2.7/test/test_repr.py
+++ b/lib-python/modified-2.7/test/test_repr.py
@@ -254,8 +254,14 @@
         eq = self.assertEqual
         touch(os.path.join(self.subpkgname, self.pkgname + os.extsep + 'py'))
         from areallylongpackageandmodulenametotestreprtruncation.areallylongpackageandmodulenametotestreprtruncation import areallylongpackageandmodulenametotestreprtruncation
-        eq(repr(areallylongpackageandmodulenametotestreprtruncation),
-           "<module '%s' from '%s'>" % (areallylongpackageandmodulenametotestreprtruncation.__name__, areallylongpackageandmodulenametotestreprtruncation.__file__))
+        # On PyPy, we use %r to format the file name; on CPython it is done
+        # with '%s'.  It seems to me that %r is safer <arigo>.
+        if '__pypy__' in sys.builtin_module_names:
+            eq(repr(areallylongpackageandmodulenametotestreprtruncation),
+               "<module %r from %r>" % (areallylongpackageandmodulenametotestreprtruncation.__name__, areallylongpackageandmodulenametotestreprtruncation.__file__))
+        else:
+            eq(repr(areallylongpackageandmodulenametotestreprtruncation),
+               "<module '%s' from '%s'>" % (areallylongpackageandmodulenametotestreprtruncation.__name__, areallylongpackageandmodulenametotestreprtruncation.__file__))
         eq(repr(sys), "<module 'sys' (built-in)>")
 
     def test_type(self):
diff --git a/lib-python/2.7/test/test_subprocess.py b/lib-python/modified-2.7/test/test_subprocess.py
copy from lib-python/2.7/test/test_subprocess.py
copy to lib-python/modified-2.7/test/test_subprocess.py
--- a/lib-python/2.7/test/test_subprocess.py
+++ b/lib-python/modified-2.7/test/test_subprocess.py
@@ -16,11 +16,11 @@
 # Depends on the following external programs: Python
 #
 
-if mswindows:
-    SETBINARY = ('import msvcrt; msvcrt.setmode(sys.stdout.fileno(), '
-                                                'os.O_BINARY);')
-else:
-    SETBINARY = ''
+#if mswindows:
+#    SETBINARY = ('import msvcrt; msvcrt.setmode(sys.stdout.fileno(), '
+#                                                'os.O_BINARY);')
+#else:
+#    SETBINARY = ''
 
 
 try:
@@ -420,8 +420,9 @@
         self.assertStderrEqual(stderr, "")
 
     def test_universal_newlines(self):
-        p = subprocess.Popen([sys.executable, "-c",
-                          'import sys,os;' + SETBINARY +
+        # NB. replaced SETBINARY with the -u flag
+        p = subprocess.Popen([sys.executable, "-u", "-c",
+                          'import sys,os;' + #SETBINARY +
                           'sys.stdout.write("line1\\n");'
                           'sys.stdout.flush();'
                           'sys.stdout.write("line2\\r");'
@@ -448,8 +449,9 @@
 
     def test_universal_newlines_communicate(self):
         # universal newlines through communicate()
-        p = subprocess.Popen([sys.executable, "-c",
-                          'import sys,os;' + SETBINARY +
+        # NB. replaced SETBINARY with the -u flag
+        p = subprocess.Popen([sys.executable, "-u", "-c",
+                          'import sys,os;' + #SETBINARY +
                           'sys.stdout.write("line1\\n");'
                           'sys.stdout.flush();'
                           'sys.stdout.write("line2\\r");'
diff --git a/lib_pypy/_collections.py b/lib_pypy/_collections.py
--- a/lib_pypy/_collections.py
+++ b/lib_pypy/_collections.py
@@ -379,12 +379,14 @@
 class defaultdict(dict):
     
     def __init__(self, *args, **kwds):
-        self.default_factory = None
-        if 'default_factory' in kwds:
-            self.default_factory = kwds.pop('default_factory')
-        elif len(args) > 0 and (callable(args[0]) or args[0] is None):
-            self.default_factory = args[0]
+        if len(args) > 0:
+            default_factory = args[0]
             args = args[1:]
+            if not callable(default_factory) and default_factory is not None:
+                raise TypeError("first argument must be callable")
+        else:
+            default_factory = None
+        self.default_factory = default_factory
         super(defaultdict, self).__init__(*args, **kwds)
  
     def __missing__(self, key):
@@ -404,7 +406,7 @@
             recurse.remove(id(self))
 
     def copy(self):
-        return type(self)(self, default_factory=self.default_factory)
+        return type(self)(self.default_factory, self)
     
     def __copy__(self):
         return self.copy()
diff --git a/lib_pypy/_ctypes/pointer.py b/lib_pypy/_ctypes/pointer.py
--- a/lib_pypy/_ctypes/pointer.py
+++ b/lib_pypy/_ctypes/pointer.py
@@ -124,7 +124,8 @@
     # for now, we always allow types.pointer, else a lot of tests
     # break. We need to rethink how pointers are represented, though
     if my_ffitype is not ffitype and ffitype is not _ffi.types.void_p:
-        raise ArgumentError, "expected %s instance, got %s" % (type(value), ffitype)
+        raise ArgumentError("expected %s instance, got %s" % (type(value),
+                                                              ffitype))
     return value._get_buffer_value()
 
 def _cast_addr(obj, _, tp):
diff --git a/lib_pypy/_ctypes/structure.py b/lib_pypy/_ctypes/structure.py
--- a/lib_pypy/_ctypes/structure.py
+++ b/lib_pypy/_ctypes/structure.py
@@ -17,7 +17,7 @@
         if len(f) == 3:
             if (not hasattr(tp, '_type_')
                 or not isinstance(tp._type_, str)
-                or tp._type_ not in "iIhHbBlL"):
+                or tp._type_ not in "iIhHbBlLqQ"):
                 #XXX: are those all types?
                 #     we just dont get the type name
                 #     in the interp levle thrown TypeError
diff --git a/lib_pypy/_pypy_irc_topic.py b/lib_pypy/_pypy_irc_topic.py
--- a/lib_pypy/_pypy_irc_topic.py
+++ b/lib_pypy/_pypy_irc_topic.py
@@ -1,117 +1,6 @@
-"""qvfgbcvna naq hgbcvna punvef
-qlfgbcvna naq hgbcvna punvef
-V'z fbeel, pbhyq lbh cyrnfr abg nterr jvgu gur png nf jryy?
-V'z fbeel, pbhyq lbh cyrnfr abg nterr jvgu gur punve nf jryy?
-jr cnffrq gur RH erivrj
-cbfg RhebClguba fcevag fgnegf 12.IVV.2007, 10nz
-RhebClguba raqrq
-n Pyrna Ragrecevfrf cebqhpgvba
-npnqrzl vf n pbzcyvpngrq ebyr tnzr
-npnqrzvn vf n pbzcyvpngrq ebyr tnzr
-jbexvat pbqr vf crn fbhc
-abg lbhe snhyg, zber yvxr vg'f n zbivat gnetrg
-guvf fragrapr vf snyfr
-abguvat vf gehr
-Yncfnat Fbhpubat
-Oenpunzhgnaqn
-fbeel, V'yy grnpu gur pnpghf ubj gb fjvz yngre
-Jul fb znal znal znal znal znal ivbyvaf?
-Jul fb znal znal znal znal znal bowrpgf?
-"eha njnl naq yvir ba n snez" nccebnpu gb fbsgjner qrirybczrag
-"va snpg, lbh zvtug xabj zber nobhg gur genafyngvba gbbypunva nsgre znfgrevat eclguba guna fbzr angvir fcrnxre xabjf nobhg uvf zbgure gbathr" - kbeNkNk
-"jurer qvq nyy gur ivbyvaf tb?"
-- ClCl fgnghf oybt: uggc://zberclcl.oybtfcbg.pbz/
-uggc://kxpq.pbz/353/
-pnfhnyvgl ivbyngvbaf naq sylvat
-wrgmg abpu fpubxbynqvtre
-R09 2X @PNN:85?
-vs lbh'er gelvat gb oybj hc fghss, jub pnerf?
-vs fghss oybjf hc, lbh pner
-2008 jvyy or gur lrne bs clcl ba gur qrfxgbc
-2008 jvyy or gur lrne bs gur qrfxgbc ba #clcl
-2008 jvyy or gur lrne bs gur qrfxgbc ba #clcl, Wnahnel jvyy or gur zbagu bs gur nyc gbcf
-lrf, ohg jung'g gur frafr bs 0 < "qhena qhena"
-eclguba: flagnk naq frznagvpf bs clguba, fcrrq bs p, erfgevpgvbaf bs wnin naq pbzcvyre reebe zrffntrf nf crargenoyr nf ZHZCF
+"""eclguba: flagnk naq frznagvpf bs clguba, fcrrq bs p, erfgevpgvbaf bs wnin naq pbzcvyre reebe zrffntrf nf crargenoyr nf ZHZCF
 pglcrf unf n fcva bs 1/3
 ' ' vf n fcnpr gbb
-2009 jvyy or gur lrne bs WVG ba gur qrfxgbc
-N ynathntr vf n qvnyrpg jvgu na nezl naq anil
-gbcvpf ner sbe gur srroyr zvaqrq
-2009 vf gur lrne bs ersyrpgvba ba gur qrfxgbc
-gur tybor vf bhe cbal, gur pbfzbf bhe erny ubefr
-jub nz V naq vs lrf, ubj znal?
-cebtenzzvat va orq vf n cresrpgyl svar npgvivgl
-zbber'f ynj vf n qeht jvgu gur jbefg pbzr qbja
-EClguba: jr hfr vg fb lbh qba'g unir gb
-Zbber'f ynj vf n qeht jvgu gur jbefg pbzr qbja. EClguba: haqrpvqrq.
-guvatf jvyy or avpr naq fghss
-qba'g cbfg yvaxf gb cngragf urer
-Abg lbhe hfhny nanylfrf.
-Gur Neg bs gur Punaary
-Clguba 300
-V fhccbfr ZO bs UGZY cre frpbaq vf abg gur hfhny fcrrq zrnfher crbcyr jbhyq rkcrpg sbe n wvg
-gur fha arire frgf ba gur ClCl rzcver
-ghegyrf ner snfgre guna lbh guvax
-cebtenzzvat vf na nrfgrguvp raqrnibhe
-P vf tbbq sbe fbzrguvat, whfg abg sbe jevgvat fbsgjner
-trezna vf tbbq sbe fbzrguvat, whfg abg sbe jevgvat fbsgjner
-trezna vf tbbq sbe artngvbaf, whfg abg sbe jevgvat fbsgjner
-# nffreg qvq abg penfu
-lbh fubhyq fgneg n cresrpg fbsgjner zbirzrag
-lbh fubhyq fgneg n cresrpg punaary gbcvp zbirzrag
-guvf vf n cresrpg punaary gbcvp
-guvf vf n frys-ersreragvny punaary gbcvp
-crrcubcr bcgvzvmngvbaf ner jung n Fhssvpvragyl Fzneg Pbzcvyre hfrf
-"crrcubcr" bcgvzvmngvbaf ner jung na bcgvzvfgvp Pbzcvyre hfrf
-pubbfr lbhe unpx
-gur 'fhcre' xrljbeq vf abg gung uhttnoyr
-wlguba cngpurf ner abg rabhtu sbe clcl
-- qb lbh xabj oreyva? - nyy bs vg? - jryy, whfg oreyva
-- ubj jvyy gur snpg gung gurl ner hfrq va bhe ercy punatr bhe gbcvpf?
-- ubj pna vg rire unir jbexrq?
-- jurer fubhyq gur unpx or fgberq?
-- Vg'f uneq gb fnl rknpgyl jung pbafgvghgrf erfrnepu va gur pbzchgre jbeyq, ohg nf n svefg nccebkvzngvba, vg'f fbsgjner gung qbrfa'g unir hfref.
-- Cebtenzzvat vf nyy nobhg xabjvat jura gb obvy gur benatr fcbatr qbaxrl npebff gur cuvyyvcvarf
-- Jul fb znal, znal, znal, znal, znal, znal qhpxyvatf?
-- ab qrgnvy vf bofpher rabhtu gb abg unir fbzr pbqr qrcraqvat ba vg.
-- jung V trarenyyl jnag vf serr fcrrqhcf
-- nyy bs ClCl vf kv-dhnyvgl
-"lbh pna nyjnlf xvyy -9 be bf._rkvg() vs lbh'er va n uheel"
-Ohernhpengf ohvyq npnqrzvp rzcverf juvpu puhea bhg zrnavatyrff fbyhgvbaf gb veeryrinag ceboyrzf.
-vg'f abg n unpx, vg'f n jbexnebhaq
-ClCl qbrfa'g unir pbcbylinevnqvp qrcraqragyl-zbabzbecurq ulcresyhknqf
-ClCl qbrfa'g punatr gur shaqnzragny culfvpf pbafgnagf
-Qnapr bs gur Fhtnecyhz Snvel
-Wnin vf whfg tbbq rabhtu gb or cenpgvpny, ohg abg tbbq rabhtu gb or hfnoyr.
-RhebClguba vf unccravat, qba'g rkcrpg nal dhvpx erfcbafr gvzrf.
-"V jbhyq yvxr gb fgnl njnl sebz ernyvgl gura"
-"gung'f jul gur 'be' vf ernyyl na 'naq' "
-jvgu nyy nccebcevngr pbagrkghnyvfngvbavat
-qba'g gevc ba gur cbjre pbeq
-vzcyrzragvat YBTB va YBTB: "ghegyrf nyy gur jnl qbja"
-gur ohooyrfbeg jbhyq or gur jebat jnl gb tb
-gur cevapvcyr bs pbafreingvba bs zrff
-gb fnir n gerr, rng n ornire
-Qre Ovore znpugf evpugvt: Antg nyyrf xnchgg.
-"Nal jbeyqivrj gung vfag jenpxrq ol frys-qbhog naq pbashfvba bire vgf bja vqragvgl vf abg n jbeyqivrj sbe zr." - Fpbgg Nnebafba
-jr oryvrir va cnapnxrf, znlor
-jr oryvrir va ghegyrf, znlor
-jr qrsvavgryl oryvrir va zrgn
-gur zngevk unf lbh
-"Yvsr vf uneq, gura lbh anc" - n png
-Vf Nezva ubzr jura gur havirefr prnfrf gb rkvfg?
-Qhrffryqbes fcevag fgnegrq
-frys.nobeeg("pnaabg ybnq negvpyrf")
-QRAGVFGEL FLZOBY YVTUG IREGVPNY NAQ JNIR
-"Gur UUH pnzchf vf n tbbq Dhnxr yriry" - Nezva
-"Gur UUH pnzchf jbhyq or n greevoyr dhnxr yriry - lbh'q arire unir n pyhr jurer lbh ner" - zvpunry
-N enqvbnpgvir png unf 18 unys-yvirf.
-<rfp> : j  [fvtu] <onpxfcnpr> <onpxfcnpr> <pgey>-f
-pbybe-pbqrq oyhrf
-"Neebtnapr va pbzchgre fpvrapr vf zrnfherq va anab-Qvwxfgenf."
-ClCl arrqf n Whfg-va-Gvzr WVG
-"Lbh pna'g gvzr geniry whfg ol frggvat lbhe pybpxf jebat"
-Gjb guernqf jnyx vagb n one. Gur onexrrcre ybbxf hc naq lryyf, "url, V jnag qba'g nal pbaqvgvbaf enpr yvxr gvzr ynfg!"
 Clguba 2.k rfg cerfdhr zbeg, ivir Clguba!
 Clguba 2.k vf abg qrnq
 Riregvzr fbzrbar nethrf jvgu "Fznyygnyx unf nyjnlf qbar K", vg vf  nyjnlf n tbbq uvag gung fbzrguvat arrqf gb or punatrq snfg. - Znephf Qraxre
@@ -119,7 +8,6 @@
 __kkk__ naq __ekkk__ if bcrengvba fybgf: cnegvpyr dhnaghz fhcrecbfvgvba xvaq bs sha
 ClCl vf na rkpvgvat grpuabybtl gung yrgf lbh gb jevgr snfg, cbegnoyr, zhygv-cyngsbez vagrecergref jvgu yrff rssbeg
 Nezva: "Cebybt vf n zrff.", PS: "Ab, vg'f irel pbby!", Nezva: "Vfa'g guvf jung V fnvq?"
-<nevtngb> tbbq, grfgf ner hfrshy fbzrgvzrf :-)
 ClCl vf yvxr nofheq gurngre
 jr unir ab nagv-vzcbffvoyr fgvpx gung znxrf fher gung nyy lbhe cebtenzf unyg
 clcl vf n enpr orgjrra crbcyr funivat lnxf naq gur havirefr cebqhpvat zber orneqrq lnxf. Fb sne, gur havirefr vf jvaavat
@@ -136,14 +24,14 @@
 ClCl 1.1.0orgn eryrnfrq: uggc://pbqrfcrnx.arg/clcl/qvfg/clcl/qbp/eryrnfr-1.1.0.ugzy
 "gurer fubhyq or bar naq bayl bar boivbhf jnl gb qb vg". ClCl inevnag: "gurer pna or A unys-ohttl jnlf gb qb vg"
 1.1 svany eryrnfrq: uggc://pbqrfcrnx.arg/clcl/qvfg/clcl/qbp/eryrnfr-1.1.0.ugzy
-1.1 svany eryrnfrq | <svwny> nzq64 naq ccp ner bayl ninvynoyr va ragrecevfr irefvba
+<svwny> nzq64 naq ccp ner bayl ninvynoyr va ragrecevfr irefvba
 Vf gurer n clcl gvzr? - vs lbh pna srry vg (?) gura gurer vf
 <nevtngb> ab, abezny jbex vf fhpu zhpu yrff gvevat guna inpngvbaf
 <nevtngb> ab, abezny jbex vf fb zhpu yrff gvevat guna inpngvbaf
-SVEFG gurl vtaber lbh, gura gurl ynhtu ng lbh, gura gurl svtug lbh, gura lbh jva.
+-SVEFG gurl vtaber lbh, gura gurl ynhtu ng lbh, gura gurl svtug lbh, gura lbh jva.-
 vg'f Fhaqnl, znlor
 vg'f Fhaqnl, ntnva
-"3 + 3 = 8"  Nagb va gur WVG gnyx
+"3 + 3 = 8" - Nagb va gur WVG gnyx
 RPBBC vf unccravat
 RPBBC vf svavfurq
 cflpb rngf bar oenva cre vapu bs cebterff
@@ -175,10 +63,108 @@
 "nu, whfg va gvzr qbphzragngvba" (__nc__)
 ClCl vf abg n erny IZ: ab frtsnhyg unaqyref gb qb gur ener pnfrf
 lbh pna'g unir obgu pbairavrapr naq fcrrq
-gur WVG qbrfa'g jbex ba BF/K (abi'09)
-ab fhccbeg sbe BF/K evtug abj! (abi'09)
 fyvccref urvtug pna or zrnfherq va k86 ertvfgref
 clcl vf n enpr orgjrra gur vaqhfgel gelvat gb ohvyq znpuvarf jvgu zber naq zber erfbheprf, naq gur clcl qrirybcref gelvat gb rng nyy bs gurz. Fb sne, gur jvaare vf fgvyy hapyrne
+"znl pbagnva ahgf naq/be lbhat cbvagref"
+vg'f nyy irel fvzcyr, yvxr gur ubyvqnlf
+unccl ClCl'f lrne 2010!
+fnzhryr fnlf gung jr ybfg n enmbe. fb jr pna'g funir lnxf
+"yrg'f abg or bofpher, hayrff jr ernyyl arrq gb"
+<nevtngb> (abg guernq-fnsr, ohg jryy, abguvat vf)
+clcl unf znal ceboyrzf, ohg rnpu bar unf znal fbyhgvbaf
+whfg nabgure vgrz (1.333...) ba bhe erny-ahzorerq gbqb yvfg
+ClCl vf Fuveg Bevtnzv erfrnepu
+<svwny> nafjrevat n dhrfgvba: "ab -- sbe ng yrnfg bar cbffvoyr vagrecergngvba bs lbhe fragrapr"
+eryrnfr 1.2 hcpbzvat
+ClCl 1.2 eryrnfrq - uggc://clcl.bet/
+AB IPF QVFPHFFVBAF
+EClguba vf n svar pnzry unve oehfu
+ClCl vf n npghnyyl n ivfhnyvmngvba cebwrpg, jr whfg ohvyq vagrecergref gb unir vagrerfgvat qngn gb ivfhnyvmr
+clcl vf yvxr fnhfntrf
+naq abj sbe fbzrguvat pbzcyrgryl qvssrerag
+n 10gu bs sberire vf 1u45
+pbeerpg pbqr qbrfag arrq nal grfgf <qhpx>
+cbfgfgehpghenyvfz rgp.
+clcl UVG trarengbe
+gur arj clcl fcbeg vf gb cnff clcl ohtf nf pclguba ohtf
+jr unir zhpu zber vagrecergref guna hfref
+ClCl 1.3 njnvgvat eryrnfr
+ClCl 1.3 eryrnfrq
+vg frrzf gb zr gung bapr lbh frggyr ba na rkrphgvba / bowrpg zbqry naq / be olgrpbqr sbezng, lbh'ir nyernql qrpvqrq jung ynathntrf (jurer gur 'f' frrzf fhcresyhbhf) fhccbeg vf tbvat gb or svefg pynff sbe
+"Nyy ceboyrzf va ClCl pna or fbyirq ol nabgure yriry bs vagrecergngvba"
+ClCl 1.3 eryrnfrq (jvaqbjf ovanevrf vapyhqrq)
+jul qvq lbh thlf unir gb znxr gur ohvygva sbeghar zber vagrerfgvat guna npghny jbex? v whfg pngpurq zlfrys erfgnegvat clcl 20 gvzrf
+"jr hfrq gb unir n zrff jvgu na bofpher vagresnpr, abj jr unir zrff urer naq bofpher vagresnpr gurer. cebterff" crqebavf ba n clcl fcevag
+"phcf bs pbssrr ner yvxr nanybtvrf va gung V'z znxvat bar evtug abj"
+"vg'f nyjnlf hc gb hf, va n jnl be gur bgure"
+ClCl vf infg, naq pbagnvaf zhygvghqrf
+qravny vf eneryl n tbbq qrohttvat grpuavdhr
+"Yrg'f tb." - "Jr pna'g" - "Jul abg?" - "Jr'er jnvgvat sbe n Genafyngvba." - (qrfcnvevatyl) "Nu!"
+'gung'f qrsvavgryl n pnfr bs "hu????"'
+va gurbel gurer vf gur Ybbc, va cenpgvpr gurer ner oevqtrf
+gur uneqqevir - pbafgnag qngn cvytevzntr
+ClCl vf n gbby gb xrrc bgurejvfr qnatrebhf zvaqf fnsryl bpphcvrq.
+jr ner n trareny senzrjbex ohvyg ba pbafvfgrag nccyvpngvba bs nqubp-arff
+gur jnl gb nibvq n jbexnebhaq vf gb vagebqhpr n fgebatre jbexnebhaq fbzrjurer ryfr
+pnyyvat gur genafyngvba gbby punva n 'fpevcg' vf xvaq bs bssrafvir
+ehaavat clcl-p genafyngr.cl vf n ovg yvxr jngpuvat n guevyyre zbivr, vg pbhyq pbafhzr nyy gur zrzbel ng nal gvzr
+ehaavat clcl-p genafyngr.cl vf n ovg yvxr jngpuvat n guevyyre zbivr, vg pbhyq qvr ng nal gvzr orpnhfr bs gur 32-ovg 4TO yvzvg bs ENZ
+Qh jvefg rora tranh qnf reervpura, jbena xrvare tynhog
+vs fjvgmreynaq jrer jurer terrpr vf (ba vfynaqf) jbhyq gurl nyy or pbaarpgrq ol oevqtrf?
+genafyngvat clcl jvgu pclguba vf fbbbbbb fybj
+ClCl 1.4 eryrnfrq!
+Jr ner abg urebrf, whfg irel cngvrag.
+QBAR zrnaf vg'f qbar
+jul gurer vf ab "ClCl 1.4 eryrnfrq" va gbcvp nal zber?
+fabj! fabj!
+svanyyl, zrephevny zvtengvba vf unccravat!
+Gur zvtengvba gb zrephevny vf pbzcyrgrq! uggc://ovgohpxrg.bet/clcl/clcl
+fabj! fabj! (gre)
+unccl arj lrne
+naq anaanaw gb lbh nf jryy
+Frrvat nf gur ynjf bs culfvpf ner ntnvafg lbh, lbh unir gb pnershyyl pbafvqre lbhe fpbcr fb gung lbhe tbnyf ner ernfbanoyr.
+nf hfhny va clcl, gur fbyhgvba nccrnef pbzcyrgryl qvfcebcbegvbangr gb gur ceboyrz naq vafgrnq jr'yy tb sbe n pbzcyrgryl qvssrerag fvzcyre nccebnpu gb gur bevtvany ceboyrz
+fabj, fabj!
+va clcl lbh ner nyjnlf ng gur jebat yriry, va bar jnl be gur bgure
+jryy, vg'f jebat ohg abg fb "irel jebat" nf vg ybbxrq
+<svwny> V ybir clcl
+ynmvarff vzcngvrapr naq uhoevf
+fabj, fabj
+EClguba: guvatf lbh jbhyqa'g qb va Clguba, naq pna'g qb va P.
+vg vf gur rkcrpgrq orunivbe, rkprcg jura lbh qba'g rkcrpg vg
+erqrsvavat lryybj frrzf yvxr n orggre vqrn
+"gung'f ubjrire whfg ratvarrevat" (svwny)
+"[vg] whfg fubjf ntnva gung eclguba vf bofpher" (psobym)
+"naljnl, clguba vf n infg ynathntr" (svwny)
+bhg-bs-yvr-thneqf
+"gurer ner qnlf ba juvpu lbh ybbx nebhaq naq abguvat fubhyq unir rire jbexrq" (svwny)
+clcl vf n orggre xvaq bs sbbyvfuarff - ynp
+ehaavat grfgf vf rffragvny sbe qrirybcvat clcl -- hu? qvq V oernx gur grfg? (svwny)
+V'ir tbg guvf sybbe jnk gung'f nyfb n TERNG qrffreg gbccvat!!
+rknexha: "gur cneg gung V gubhtug jnf tbvat gb or uneq jnf gevivny, fb abj V whfg unir guvf cneg gung V qvqa'g rira guvax bs gung vf uneq"
+V fhccbfr jr pna yvir jvgu gur bofphevgl, nf ybat nf gurer vf n pbzzrag znxvat vg yvtugre
+V nz n ovt oryvrire va ernfbaf. ohg gur nccnerag xvaq ner zl snibevgr.
+clcl: trg n WVG sbe serr (jryy gur svefg qnl lbh jba'g znantr naq vg jvyy or irel sehfgengvat)
+<Nyrk_Tnlabe> thgjbegu: bu, jr fubhyq znxr gur WVG zntvpnyyl orggre, jvgu qrpbengbef naq fghss
+vg'f n pbzcyrgr unpx, ohg n irel zvavzny bar (nevtngb)
+svefg gurl ynhtu ng lbh, gura gurl vtaber lbh, gura gurl svtug lbh, gura lbh jva
+ClCl vf snzvyl sevraqyl
+jr yvxr pbzcynvagf
+gbqnl jr'er snfgre guna lrfgreqnl (hfhnyyl)
+ClCl naq PClguba: gurl ner zbegny rarzvrf vagrag ba xvyyvat rnpu bgure
+nethnoyl, rirelguvat vf n avpur
+clcl unf ynlref yvxr bavbaf: crryvat gurz onpx jvyy znxr lbh pel
+EClguba zntvpnyyl znxrf lbh evpu naq snzbhf (fnlf fb ba gur gva)
+Vf evtbobg nebhaq jura gur havirefr prnfrf gb rkvfg?
+ClCl vf gbb pbby sbe dhrelfgevatf.
+< nevtngb> gura jung bpphef? < svwny> tbbq fghss V oryvrir
+ClCl 1.6 eryrnfrq!
+<psobym> jurer ner gur grfgf?
+uggc://gjvgcvp.pbz/52nr8s
+N enaqbz dhbgr
+Nyy rkprcgoybpxf frrz fnar.
+N cvax tyvggrel ebgngvat ynzoqn
+"vg'f yvxryl grzcbenel hagvy sberire" nevtb
 """
 
 def some_topic():
diff --git a/lib_pypy/_sha.py b/lib_pypy/_sha.py
--- a/lib_pypy/_sha.py
+++ b/lib_pypy/_sha.py
@@ -1,5 +1,5 @@
 #!/usr/bin/env python
-# -*- coding: iso-8859-1
+# -*- coding: iso-8859-1 -*-
 
 # Note that PyPy contains also a built-in module 'sha' which will hide
 # this one if compiled in.
diff --git a/lib_pypy/_sqlite3.py b/lib_pypy/_sqlite3.py
--- a/lib_pypy/_sqlite3.py
+++ b/lib_pypy/_sqlite3.py
@@ -231,6 +231,9 @@
 sqlite.sqlite3_result_text.argtypes = [c_void_p, c_char_p, c_int, c_void_p]
 sqlite.sqlite3_result_text.restype = None
 
+sqlite.sqlite3_enable_load_extension.argtypes = [c_void_p, c_int]
+sqlite.sqlite3_enable_load_extension.restype = c_int
+
 ##########################################
 # END Wrapped SQLite C API and constants
 ##########################################
@@ -705,6 +708,14 @@
         from sqlite3.dump import _iterdump
         return _iterdump(self)
 
+    def enable_load_extension(self, enabled):
+        self._check_thread()
+        self._check_closed()
+
+        rc = sqlite.sqlite3_enable_load_extension(self.db, int(enabled))
+        if rc != SQLITE_OK:
+            raise OperationalError("Error enabling load extension")
+
 DML, DQL, DDL = range(3)
 
 class Cursor(object):
diff --git a/lib_pypy/itertools.py b/lib_pypy/itertools.py
--- a/lib_pypy/itertools.py
+++ b/lib_pypy/itertools.py
@@ -25,7 +25,7 @@
 
 __all__ = ['chain', 'count', 'cycle', 'dropwhile', 'groupby', 'ifilter',
            'ifilterfalse', 'imap', 'islice', 'izip', 'repeat', 'starmap',
-           'takewhile', 'tee']
+           'takewhile', 'tee', 'compress', 'product']
 
 try: from __pypy__ import builtinify
 except ImportError: builtinify = lambda f: f
diff --git a/lib_pypy/pyrepl/commands.py b/lib_pypy/pyrepl/commands.py
--- a/lib_pypy/pyrepl/commands.py
+++ b/lib_pypy/pyrepl/commands.py
@@ -33,10 +33,9 @@
 class Command(object):
     finish = 0
     kills_digit_arg = 1
-    def __init__(self, reader, (event_name, event)):
+    def __init__(self, reader, cmd):
         self.reader = reader
-        self.event = event
-        self.event_name = event_name
+        self.event_name, self.event = cmd
     def do(self):
         pass
 
diff --git a/lib_pypy/pyrepl/pygame_console.py b/lib_pypy/pyrepl/pygame_console.py
--- a/lib_pypy/pyrepl/pygame_console.py
+++ b/lib_pypy/pyrepl/pygame_console.py
@@ -130,7 +130,7 @@
         s.fill(c, [0, 600 - bmargin, 800, bmargin])
         s.fill(c, [800 - rmargin, 0, lmargin, 600])
 
-    def refresh(self, screen, (cx, cy)):
+    def refresh(self, screen, cxy):
         self.screen = screen
         self.pygame_screen.fill(colors.bg,
                                 [0, tmargin + self.cur_top + self.scroll,
@@ -139,8 +139,8 @@
 
         line_top = self.cur_top
         width, height = self.fontsize
-        self.cxy = (cx, cy)
-        cp = self.char_pos(cx, cy)
+        self.cxy = cxy
+        cp = self.char_pos(*cxy)
         if cp[1] < tmargin:
             self.scroll = - (cy*self.fh + self.cur_top)
             self.repaint()
@@ -148,7 +148,7 @@
             self.scroll += (600 - bmargin) - (cp[1] + self.fh)
             self.repaint()
         if self.curs_vis:
-            self.pygame_screen.blit(self.cursor, self.char_pos(cx, cy))
+            self.pygame_screen.blit(self.cursor, self.char_pos(*cxy))
         for line in screen:
             if 0 <= line_top + self.scroll <= (600 - bmargin - tmargin - self.fh):
                 if line:
diff --git a/lib_pypy/pyrepl/readline.py b/lib_pypy/pyrepl/readline.py
--- a/lib_pypy/pyrepl/readline.py
+++ b/lib_pypy/pyrepl/readline.py
@@ -231,7 +231,11 @@
         return ''.join(chars)
 
     def _histline(self, line):
-        return unicode(line.rstrip('\n'), ENCODING)
+        line = line.rstrip('\n')
+        try:
+            return unicode(line, ENCODING)
+        except UnicodeDecodeError:   # bah, silently fall back...
+            return unicode(line, 'utf-8')
 
     def get_history_length(self):
         return self.saved_history_length
@@ -268,7 +272,10 @@
         f = open(os.path.expanduser(filename), 'w')
         for entry in history:
             if isinstance(entry, unicode):
-                entry = entry.encode(ENCODING)
+                try:
+                    entry = entry.encode(ENCODING)
+                except UnicodeEncodeError:   # bah, silently fall back...
+                    entry = entry.encode('utf-8')
             entry = entry.replace('\n', '\r\n')   # multiline history support
             f.write(entry + '\n')
         f.close()
diff --git a/lib_pypy/pyrepl/unix_console.py b/lib_pypy/pyrepl/unix_console.py
--- a/lib_pypy/pyrepl/unix_console.py
+++ b/lib_pypy/pyrepl/unix_console.py
@@ -163,7 +163,7 @@
     def change_encoding(self, encoding):
         self.encoding = encoding
     
-    def refresh(self, screen, (cx, cy)):
+    def refresh(self, screen, cxy):
         # this function is still too long (over 90 lines)
 
         if not self.__gone_tall:
@@ -198,6 +198,7 @@
 
         # we make sure the cursor is on the screen, and that we're
         # using all of the screen if we can
+        cx, cy = cxy
         if cy < offset:
             offset = cy
         elif cy >= offset + height:
@@ -411,7 +412,12 @@
                    e.args[4] == 'unexpected end of data':
                 pass
             else:
-                raise
+                # was: "raise".  But it crashes pyrepl, and by extension the
+                # pypy currently running, in which we are e.g. in the middle
+                # of some debugging session.  Argh.  Instead just print an
+                # error message to stderr and continue running, for now.
+                self.partial_char = ''
+                sys.stderr.write('\n%s: %s\n' % (e.__class__.__name__, e))
         else:
             self.partial_char = ''
             self.event_queue.push(c)
diff --git a/lib_pypy/syslog.py b/lib_pypy/syslog.py
--- a/lib_pypy/syslog.py
+++ b/lib_pypy/syslog.py
@@ -38,9 +38,27 @@
 _setlogmask.argtypes = (c_int,)
 _setlogmask.restype = c_int
 
+_S_log_open = False
+_S_ident_o = None
+
+def _get_argv():
+    try:
+        import sys
+        script = sys.argv[0]
+        if isinstance(script, str):
+            return script[script.rfind('/')+1:] or None
+    except Exception:
+        pass
+    return None
+
 @builtinify
-def openlog(ident, option, facility):
-    _openlog(ident, option, facility)
+def openlog(ident=None, logoption=0, facility=LOG_USER):
+    global _S_ident_o, _S_log_open
+    if ident is None:
+        ident = _get_argv()
+    _S_ident_o = c_char_p(ident)    # keepalive
+    _openlog(_S_ident_o, logoption, facility)
+    _S_log_open = True
 
 @builtinify
 def syslog(arg1, arg2=None):
@@ -48,11 +66,18 @@
         priority, message = arg1, arg2
     else:
         priority, message = LOG_INFO, arg1
+    # if log is not opened, open it now
+    if not _S_log_open:
+        openlog()
     _syslog(priority, "%s", message)
 
 @builtinify
 def closelog():
-    _closelog()
+    global _S_log_open, S_ident_o
+    if _S_log_open:
+        _closelog()
+        _S_log_open = False
+        _S_ident_o = None
 
 @builtinify
 def setlogmask(mask):
diff --git a/py/_code/code.py b/py/_code/code.py
--- a/py/_code/code.py
+++ b/py/_code/code.py
@@ -164,6 +164,7 @@
         #   if something:  # assume this causes a NameError
         #      # _this_ lines and the one
                #        below we don't want from entry.getsource()
+        end = min(end, len(source))
         for i in range(self.lineno, end):
             if source[i].rstrip().endswith(':'):
                 end = i + 1
@@ -307,7 +308,7 @@
                     self._striptext = 'AssertionError: '
         self._excinfo = tup
         self.type, self.value, tb = self._excinfo
-        self.typename = self.type.__name__
+        self.typename = getattr(self.type, "__name__", "???")
         self.traceback = py.code.Traceback(tb)
 
     def __repr__(self):
diff --git a/pypy/annotation/binaryop.py b/pypy/annotation/binaryop.py
--- a/pypy/annotation/binaryop.py
+++ b/pypy/annotation/binaryop.py
@@ -252,7 +252,26 @@
     # unsignedness is considered a rare and contagious disease
 
     def union((int1, int2)):
-        knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
+        if int1.unsigned == int2.unsigned:
+            knowntype = rarithmetic.compute_restype(int1.knowntype, int2.knowntype)
+        else:
+            t1 = int1.knowntype
+            if t1 is bool:
+                t1 = int
+            t2 = int2.knowntype
+            if t2 is bool:
+                t2 = int
+
+            if t2 is int:
+                if int2.nonneg == False:
+                    raise UnionError, "Merging %s and a possibly negative int is not allowed" % t1
+                knowntype = t1
+            elif t1 is int:
+                if int1.nonneg == False:
+                    raise UnionError, "Merging %s and a possibly negative int is not allowed" % t2
+                knowntype = t2
+            else:
+                raise UnionError, "Merging these types (%s, %s) is not supported" % (t1, t2)
         return SomeInteger(nonneg=int1.nonneg and int2.nonneg,
                            knowntype=knowntype)
 
diff --git a/pypy/annotation/model.py b/pypy/annotation/model.py
--- a/pypy/annotation/model.py
+++ b/pypy/annotation/model.py
@@ -591,13 +591,11 @@
     immutable = True
     def __init__(self, method):
         self.method = method
-        
-NUMBER = object()
+
 annotation_to_ll_map = [
     (SomeSingleFloat(), lltype.SingleFloat),
     (s_None, lltype.Void),   # also matches SomeImpossibleValue()
     (s_Bool, lltype.Bool),
-    (SomeInteger(knowntype=r_ulonglong), NUMBER),    
     (SomeFloat(), lltype.Float),
     (SomeLongFloat(), lltype.LongFloat),
     (SomeChar(), lltype.Char),
@@ -623,10 +621,11 @@
             return lltype.Ptr(p.PARENTTYPE)
     if isinstance(s_val, SomePtr):
         return s_val.ll_ptrtype
+    if type(s_val) is SomeInteger:
+        return lltype.build_number(None, s_val.knowntype)
+
     for witness, T in annotation_to_ll_map:
         if witness.contains(s_val):
-            if T is NUMBER:
-                return lltype.build_number(None, s_val.knowntype)
             return T
     if info is None:
         info = ''
@@ -635,7 +634,7 @@
     raise ValueError("%sshould return a low-level type,\ngot instead %r" % (
         info, s_val))
 
-ll_to_annotation_map = dict([(ll, ann) for ann, ll in annotation_to_ll_map if ll is not NUMBER])
+ll_to_annotation_map = dict([(ll, ann) for ann, ll in annotation_to_ll_map])
 
 def lltype_to_annotation(T):
     try:
diff --git a/pypy/annotation/specialize.py b/pypy/annotation/specialize.py
--- a/pypy/annotation/specialize.py
+++ b/pypy/annotation/specialize.py
@@ -36,9 +36,7 @@
             newtup = SpaceOperation('newtuple', starargs, argscopy[-1])
             newstartblock.operations.append(newtup)
             newstartblock.closeblock(Link(argscopy, graph.startblock))
-            graph.startblock.isstartblock = False
             graph.startblock = newstartblock
-            newstartblock.isstartblock = True
             argnames = argnames + ['.star%d' % i for i in range(nb_extra_args)]
             graph.signature = Signature(argnames)
             # note that we can mostly ignore defaults: if nb_extra_args > 0, 
diff --git a/pypy/annotation/test/test_annrpython.py b/pypy/annotation/test/test_annrpython.py
--- a/pypy/annotation/test/test_annrpython.py
+++ b/pypy/annotation/test/test_annrpython.py
@@ -856,6 +856,46 @@
         py.test.raises(Exception, a.build_types, f, [])
         # if you want to get a r_uint, you have to be explicit about it
 
+    def test_add_different_ints(self):
+        def f(a, b):
+            return a + b
+        a = self.RPythonAnnotator()
+        py.test.raises(Exception, a.build_types, f, [r_uint, int])
+
+    def test_merge_different_ints(self):
+        def f(a, b):
+            if a:
+                c = a
+            else:
+                c = b
+            return c
+        a = self.RPythonAnnotator()
+        py.test.raises(Exception, a.build_types, f, [r_uint, int])
+
+    def test_merge_ruint_zero(self):
+        def f(a):
+            if a:
+                c = a
+            else:
+                c = 0
+            return c
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [r_uint])
+        assert s == annmodel.SomeInteger(nonneg = True, unsigned = True)
+
+    def test_merge_ruint_nonneg_signed(self):
+        def f(a, b):
+            if a:
+                c = a
+            else:
+                assert b >= 0
+                c = b
+            return c
+        a = self.RPythonAnnotator()
+        s = a.build_types(f, [r_uint, int])
+        assert s == annmodel.SomeInteger(nonneg = True, unsigned = True)
+
+
     def test_prebuilt_long_that_is_not_too_long(self):
         small_constant = 12L
         def f():
@@ -3029,7 +3069,7 @@
             if g(x, y):
                 g(x, r_uint(y))
         a = self.RPythonAnnotator()
-        a.build_types(f, [int, int])
+        py.test.raises(Exception, a.build_types, f, [int, int])
 
     def test_compare_with_zero(self):
         def g():
diff --git a/pypy/bin/checkmodule.py b/pypy/bin/checkmodule.py
--- a/pypy/bin/checkmodule.py
+++ b/pypy/bin/checkmodule.py
@@ -1,43 +1,45 @@
 #! /usr/bin/env python
 """
-Usage:  checkmodule.py [-b backend] <module-name>
+Usage:  checkmodule.py <module-name>
 
-Compiles the PyPy extension module from pypy/module/<module-name>/
-into a fake program which does nothing. Useful for testing whether a
-modules compiles without doing a full translation. Default backend is cli.
-
-WARNING: this is still incomplete: there are chances that the
-compilation fails with strange errors not due to the module. If a
-module is known to compile during a translation but don't pass
-checkmodule.py, please report the bug (or, better, correct it :-).
+Check annotation and rtyping of the PyPy extension module from
+pypy/module/<module-name>/.  Useful for testing whether a
+modules compiles without doing a full translation.
 """
 import autopath
-import sys
+import sys, os
 
 from pypy.objspace.fake.checkmodule import checkmodule
 
 def main(argv):
-    try:
-        assert len(argv) in (2, 4)
-        if len(argv) == 2:
-            backend = 'cli'
-            modname = argv[1]
-            if modname in ('-h', '--help'):
-                print >> sys.stderr, __doc__
-                sys.exit(0)
-            if modname.startswith('-'):
-                print >> sys.stderr, "Bad command line"
-                print >> sys.stderr, __doc__
-                sys.exit(1)
-        else:
-            _, b, backend, modname = argv
-            assert b == '-b'
-    except AssertionError:
+    if len(argv) != 2:
         print >> sys.stderr, __doc__
         sys.exit(2)
+    modname = argv[1]
+    if modname in ('-h', '--help'):
+        print >> sys.stderr, __doc__
+        sys.exit(0)
+    if modname.startswith('-'):
+        print >> sys.stderr, "Bad command line"
+        print >> sys.stderr, __doc__
+        sys.exit(1)
+    if os.path.sep in modname:
+        if os.path.basename(modname) == '':
+            modname = os.path.dirname(modname)
+        if os.path.basename(os.path.dirname(modname)) != 'module':
+            print >> sys.stderr, "Must give '../module/xxx', or just 'xxx'."
+            sys.exit(1)
+        modname = os.path.basename(modname)
+    try:
+        checkmodule(modname)
+    except Exception, e:
+        import traceback, pdb
+        traceback.print_exc()
+        pdb.post_mortem(sys.exc_info()[2])
+        return 1
     else:
-        checkmodule(modname, backend, interactive=True)
-        print 'Module compiled succesfully'
+        print 'Passed.'
+        return 0
 
 if __name__ == '__main__':
-    main(sys.argv)
+    sys.exit(main(sys.argv))
diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -92,7 +92,7 @@
 
 module_import_dependencies = {
     # no _rawffi if importing pypy.rlib.clibffi raises ImportError
-    # or CompilationError
+    # or CompilationError or py.test.skip.Exception
     "_rawffi"   : ["pypy.rlib.clibffi"],
     "_ffi"      : ["pypy.rlib.clibffi"],
 
@@ -113,7 +113,7 @@
             try:
                 for name in modlist:
                     __import__(name)
-            except (ImportError, CompilationError), e:
+            except (ImportError, CompilationError, py.test.skip.Exception), e:
                 errcls = e.__class__.__name__
                 config.add_warning(
                     "The module %r is disabled\n" % (modname,) +
@@ -285,6 +285,9 @@
                    "actually create the full list until the resulting "
                    "list is mutated",
                    default=False),
+        BoolOption("withliststrategies",
+                   "enable optimized ways to store lists of primitives ",
+                   default=True),
 
         BoolOption("withtypeversion",
                    "version type objects when changing them",
diff --git a/pypy/config/test/test_translationoption.py b/pypy/config/test/test_translationoption.py
new file mode 100644
--- /dev/null
+++ b/pypy/config/test/test_translationoption.py
@@ -0,0 +1,10 @@
+import py
+from pypy.config.translationoption import get_combined_translation_config
+from pypy.config.translationoption import set_opt_level
+from pypy.config.config import ConflictConfigError
+
+
+def test_no_gcrootfinder_with_boehm():
+    config = get_combined_translation_config()
+    config.translation.gcrootfinder = "shadowstack"
+    py.test.raises(ConflictConfigError, set_opt_level, config, '0')
diff --git a/pypy/config/translationoption.py b/pypy/config/translationoption.py
--- a/pypy/config/translationoption.py
+++ b/pypy/config/translationoption.py
@@ -69,8 +69,8 @@
                      "statistics": [("translation.gctransformer", "framework")],
                      "generation": [("translation.gctransformer", "framework")],
                      "hybrid": [("translation.gctransformer", "framework")],
-                     "boehm": [("translation.gctransformer", "boehm"),
-                               ("translation.continuation", False)],  # breaks
+                     "boehm": [("translation.continuation", False),  # breaks
+                               ("translation.gctransformer", "boehm")],
                      "markcompact": [("translation.gctransformer", "framework")],
                      "minimark": [("translation.gctransformer", "framework")],
                      },
@@ -398,6 +398,10 @@
     # make_sure_not_resized often relies on it, so we always enable them
     config.translation.suggest(list_comprehension_operations=True)
 
+    # finally, make the choice of the gc definitive.  This will fail
+    # if we have specified strange inconsistent settings.
+    config.translation.gc = config.translation.gc
+
 # ----------------------------------------------------------------
 
 def set_platform(config):
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
@@ -270,7 +270,12 @@
   - *slicing*:
     the slice start must be within bounds. The stop doesn't need to, but it must
     not be smaller than the start.  All negative indexes are disallowed, except for
-    the [:-1] special case.  No step.
+    the [:-1] special case.  No step.  Slice deletion follows the same rules.
+    
+  - *slice assignment*:
+    only supports ``lst[x:y] = sublist``, if ``len(sublist) == y - x``.
+    In other words, slice assignment cannot change the total length of the list,
+    but just replace items.
 
   - *other operators*:
     ``+``, ``+=``, ``in``, ``*``, ``*=``, ``==``, ``!=`` work as expected.
diff --git a/pypy/doc/config/objspace.std.withliststrategies.txt b/pypy/doc/config/objspace.std.withliststrategies.txt
new file mode 100644
--- /dev/null
+++ b/pypy/doc/config/objspace.std.withliststrategies.txt
@@ -0,0 +1,2 @@
+Enable list strategies: Use specialized representations for lists of primitive
+objects, such as ints.
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
@@ -262,6 +262,26 @@
 documented as such (as e.g. for hasattr()), in most cases PyPy
 lets the exception propagate instead.
 
+Object Identity of Primitive Values, ``is`` and ``id``
+-------------------------------------------------------
+
+Object identity of primitive values works by value equality, not by identity of
+the wrapper. This means that ``x + 1 is x + 1`` is always true, for arbitrary
+integers ``x``. The rule applies for the following types:
+
+ - ``int``
+
+ - ``float``
+
+ - ``long``
+
+ - ``complex``
+
+This change requires some changes to ``id`` as well. ``id`` fulfills the
+following condition: ``x is y <=> id(x) == id(y)``. Therefore ``id`` of the
+above types will return a value that is computed from the argument, and can
+thus be larger than ``sys.maxint`` (i.e. it can be an arbitrary long).
+
 
 Miscellaneous
 -------------
@@ -284,14 +304,14 @@
   never a dictionary as it sometimes is in CPython. Assigning to
   ``__builtins__`` has no effect.
 
-* Do not compare immutable objects with ``is``.  For example on CPython
-  it is true that ``x is 0`` works, i.e. does the same as ``type(x) is
-  int and x == 0``, but it is so by accident.  If you do instead
-  ``x is 1000``, then it stops working, because 1000 is too large and
-  doesn't come from the internal cache.  In PyPy it fails to work in
-  both cases, because we have no need for a cache at all.
+* directly calling the internal magic methods of a few built-in types
+  with invalid arguments may have a slightly different result.  For
+  example, ``[].__add__(None)`` and ``(2).__add__(None)`` both return
+  ``NotImplemented`` on PyPy; on CPython, only the later does, and the
+  former raises ``TypeError``.  (Of course, ``[]+None`` and ``2+None``
+  both raise ``TypeError`` everywhere.)  This difference is an
+  implementation detail that shows up because of internal C-level slots
+  that PyPy does not have.
 
-* Also, object identity of immutable keys in dictionaries is not necessarily
-  preserved.
 
 .. include:: _ref.txt
diff --git a/pypy/doc/how-to-release.rst b/pypy/doc/how-to-release.rst
--- a/pypy/doc/how-to-release.rst
+++ b/pypy/doc/how-to-release.rst
@@ -1,6 +1,3 @@
-.. include:: needswork.txt
-
-.. needs work, it talks about svn. also, it is not really user documentation
 
 Making a PyPy Release
 =======================
@@ -12,11 +9,8 @@
 forgetting things. A set of todo files may also work.
 
 Check and prioritize all issues for the release, postpone some if necessary,
-create new  issues also as necessary. A meeting (or meetings) should be
-organized to decide what things are priorities, should go in and work for
-the release. 
-
-An important thing is to get the documentation into an up-to-date state!
+create new  issues also as necessary. An important thing is to get
+the documentation into an up-to-date state!
 
 Release Steps
 ----------------
diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst
--- a/pypy/doc/index.rst
+++ b/pypy/doc/index.rst
@@ -15,7 +15,7 @@
 
 * `FAQ`_: some frequently asked questions.
 
-* `Release 1.6`_: the latest official release
+* `Release 1.7`_: the latest official release
 
 * `PyPy Blog`_: news and status info about PyPy 
 
@@ -75,7 +75,7 @@
 .. _`Getting Started`: getting-started.html
 .. _`Papers`: extradoc.html
 .. _`Videos`: video-index.html
-.. _`Release 1.6`: http://pypy.org/download.html
+.. _`Release 1.7`: http://pypy.org/download.html
 .. _`speed.pypy.org`: http://speed.pypy.org
 .. _`RPython toolchain`: translation.html
 .. _`potential project ideas`: project-ideas.html
@@ -120,9 +120,9 @@
 Windows, on top of .NET, and on top of Java.
 To dig into PyPy it is recommended to try out the current
 Mercurial default branch, which is always working or mostly working,
-instead of the latest release, which is `1.6`__.
+instead of the latest release, which is `1.7`__.
 
-.. __: release-1.6.0.html
+.. __: release-1.7.0.html
 
 PyPy is mainly developed on Linux and Mac OS X.  Windows is supported,
 but platform-specific bugs tend to take longer before we notice and fix
diff --git a/pypy/doc/project-ideas.rst b/pypy/doc/project-ideas.rst
--- a/pypy/doc/project-ideas.rst
+++ b/pypy/doc/project-ideas.rst
@@ -23,17 +23,20 @@
 PyPy's implementation of the Python ``long`` type is slower than CPython's.
 Find out why and optimize them.
 
+Make bytearray type fast
+------------------------
+
+PyPy's bytearray type is very inefficient. It would be an interesting
+task to look into possible optimizations on this.
+
 Numpy improvements
 ------------------
 
-This is more of a project-container than a single project. Possible ideas:
+The numpy is rapidly progressing in pypy, so feel free to come to IRC and
+ask for proposed topic. A not necesarilly up-to-date `list of topics`_
+is also available.
 
-* experiment with auto-vectorization using SSE or implement vectorization
-  without automatically detecting it for array operations.
-
-* improve numpy, for example implement memory views.
-
-* interface with fortran/C libraries.
+.. _`list of topics`: https://bitbucket.org/pypy/extradoc/src/extradoc/planning/micronumpy.txt
 
 Improving the jitviewer
 ------------------------
diff --git a/pypy/doc/release-1.7.0.rst b/pypy/doc/release-1.7.0.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/release-1.7.0.rst
@@ -0,0 +1,94 @@
+==================================
+PyPy 1.7 - widening the sweet spot
+==================================
+
+We're pleased to announce the 1.7 release of PyPy. As became a habit, this
+release brings a lot of bugfixes and performance improvements over the 1.6
+release. However, unlike the previous releases, the focus has been on widening
+the "sweet spot" of PyPy. That is, classes of Python code that PyPy can greatly
+speed up should be vastly improved with this release. You can download the 1.7
+release here:
+
+    http://pypy.org/download.html
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7. It's fast (`pypy 1.7 and cpython 2.7.1`_ performance comparison)
+due to its integrated tracing JIT compiler.
+
+This release supports x86 machines running Linux 32/64, Mac OS X 32/64 or
+Windows 32. Windows 64 work is ongoing, but not yet natively supported.
+
+The main topic of this release is widening the range of code which PyPy
+can greatly speed up. On average on
+our benchmark suite, PyPy 1.7 is around **30%** faster than PyPy 1.6 and up
+to **20 times** faster on some benchmarks.
+
+.. _`pypy 1.7 and cpython 2.7.1`: http://speed.pypy.org
+
+
+Highlights
+==========
+
+* Numerous performance improvements. There are too many examples which python
+  constructs now should behave faster to list them.
+
+* Bugfixes and compatibility fixes with CPython.
+
+* Windows fixes.
+
+* PyPy now comes with stackless features enabled by default. However,
+  any loop using stackless features will interrupt the JIT for now, so no real
+  performance improvement for stackless-based programs. Contact pypy-dev for
+  info how to help on removing this restriction.
+
+* NumPy effort in PyPy was renamed numpypy. In order to try using it, simply
+  write::
+
+    import numpypy as numpy
+
+  at the beginning of your program. There is a huge progress on numpy in PyPy
+  since 1.6, the main feature being implementation of dtypes.
+
+* JSON encoder (but not decoder) has been replaced with a new one. This one
+  is written in pure Python, but is known to outperform CPython's C extension
+  up to **2 times** in some cases. It's about **20 times** faster than
+  the one that we had in 1.6.
+
+* The memory footprint of some of our RPython modules has been drastically
+  improved. This should impact any applications using for example cryptography,
+  like tornado.
+
+* There was some progress in exposing even more CPython C API via cpyext.
+
+Things that didn't make it, expect in 1.8 soon
+==============================================
+
+There is an ongoing work, which while didn't make it to the release, is
+probably worth mentioning here. This is what you should probably expect in
+1.8 some time soon:
+
+* Specialized list implementation. There is a branch that implements lists of
+  integers/floats/strings as compactly as array.array. This should drastically
+  improve performance/memory impact of some applications
+
+* NumPy effort is progressing forward, with multi-dimensional arrays coming
+  soon.
+
+* There are two brand new JIT assembler backends, notably for the PowerPC and
+  ARM processors.
+
+Fundraising
+===========
+
+It's maybe worth mentioning that we're running fundraising campaigns for
+NumPy effort in PyPy and for Python 3 in PyPy. In case you want to see any
+of those happen faster, we urge you to donate to `numpy proposal`_ or
+`py3k proposal`_. In case you want PyPy to progress, but you trust us with
+the general direction, you can always donate to the `general pot`_.
+
+.. _`numpy proposal`: http://pypy.org/numpydonate.html
+.. _`py3k proposal`: http://pypy.org/py3donate.html
+.. _`general pot`: http://pypy.org
diff --git a/pypy/interpreter/astcompiler/optimize.py b/pypy/interpreter/astcompiler/optimize.py
--- a/pypy/interpreter/astcompiler/optimize.py
+++ b/pypy/interpreter/astcompiler/optimize.py
@@ -1,6 +1,5 @@
 """codegen helpers and AST constant folding."""
 import sys
-import itertools
 
 from pypy.interpreter.astcompiler import ast, consts, misc
 from pypy.tool import stdlib_opcode as ops
@@ -146,8 +145,7 @@
 }
 unrolling_unary_folders = unrolling_iterable(unary_folders.items())
 
-for folder in itertools.chain(binary_folders.itervalues(),
-                              unary_folders.itervalues()):
+for folder in binary_folders.values() + unary_folders.values():
     folder._always_inline_ = True
 del folder
 
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -1,4 +1,3 @@
-import itertools
 import pypy
 from pypy.interpreter.executioncontext import ExecutionContext, ActionFlag
 from pypy.interpreter.executioncontext import UserDelAction, FrameTraceAction
@@ -188,6 +187,12 @@
 
     # -------------------------------------------------------------------
 
+    def is_w(self, space, w_other):
+        return self is w_other
+
+    def unique_id(self, space):
+        return space.wrap(compute_unique_id(self))
+
     def str_w(self, space):
         w_msg = typed_unwrap_error_msg(space, "string", self)
         raise OperationError(space.w_TypeError, w_msg)
@@ -513,8 +518,8 @@
         exception_types_w = self.export_builtin_exceptions()
 
         # initialize with "bootstrap types" from objspace  (e.g. w_None)
-        types_w = itertools.chain(self.get_builtin_types().iteritems(),
-                                  exception_types_w.iteritems())
+        types_w = (self.get_builtin_types().items() +
+                   exception_types_w.items())
         for name, w_type in types_w:
             self.setitem(self.builtin.w_dict, self.wrap(name), w_type)
 
@@ -681,9 +686,17 @@
         """shortcut for space.is_true(space.eq(w_obj1, w_obj2))"""
         return self.is_w(w_obj1, w_obj2) or self.is_true(self.eq(w_obj1, w_obj2))
 
-    def is_w(self, w_obj1, w_obj2):
-        """shortcut for space.is_true(space.is_(w_obj1, w_obj2))"""
-        return self.is_true(self.is_(w_obj1, w_obj2))
+    def is_(self, w_one, w_two):
+        return self.newbool(self.is_w(w_one, w_two))
+
+    def is_w(self, w_one, w_two):
+        # done by a method call on w_two (and not on w_one, because of the
+        # expected programming style where we say "if x is None" or
+        # "if x is object").
+        return w_two.is_w(self, w_one)
+
+    def id(self, w_obj):
+        return w_obj.unique_id(self)
 
     def hash_w(self, w_obj):
         """shortcut for space.int_w(space.hash(w_obj))"""
@@ -777,22 +790,63 @@
         """Unpack an iterable object into a real (interpreter-level) list.
         Raise an OperationError(w_ValueError) if the length is wrong."""
         w_iterator = self.iter(w_iterable)
-        # If we know the expected length we can preallocate.
         if expected_length == -1:
+            # xxx special hack for speed
+            from pypy.interpreter.generator import GeneratorIterator
+            if isinstance(w_iterator, GeneratorIterator):
+                lst_w = []
+                w_iterator.unpack_into(lst_w)
+                return lst_w
+            # /xxx
+            return self._unpackiterable_unknown_length(w_iterator, w_iterable)
+        else:
+            lst_w = self._unpackiterable_known_length(w_iterator,
+                                                      expected_length)
+            return lst_w[:]     # make the resulting list resizable
+
+    @jit.dont_look_inside
+    def _unpackiterable_unknown_length(self, w_iterator, w_iterable):
+        # Unpack a variable-size list of unknown length.
+        # The JIT does not look inside this function because it
+        # contains a loop (made explicit with the decorator above).
+        #
+        # If we can guess the expected length we can preallocate.
+        try:
+            lgt_estimate = self.len_w(w_iterable)
+        except OperationError, o:
+            if (not o.match(self, self.w_AttributeError) and
+                not o.match(self, self.w_TypeError)):
+                raise
+            items = []
+        else:
             try:
-                lgt_estimate = self.len_w(w_iterable)
-            except OperationError, o:
-                if (not o.match(self, self.w_AttributeError) and
-                    not o.match(self, self.w_TypeError)):
+                items = newlist(lgt_estimate)
+            except MemoryError:
+                items = [] # it might have lied
+        #
+        while True:
+            try:
+                w_item = self.next(w_iterator)
+            except OperationError, e:
+                if not e.match(self, self.w_StopIteration):
                     raise
-                items = []
-            else:
-                try:
-                    items = newlist(lgt_estimate)
-                except MemoryError:
-                    items = [] # it might have lied
-        else:
-            items = [None] * expected_length
+                break  # done
+            items.append(w_item)
+        #
+        return items
+
+    @jit.dont_look_inside
+    def _unpackiterable_known_length(self, w_iterator, expected_length):
+        # Unpack a known length list, without letting the JIT look inside.
+        # Implemented by just calling the @jit.unroll_safe version, but
+        # the JIT stopped looking inside already.
+        return self._unpackiterable_known_length_jitlook(w_iterator,
+                                                         expected_length)
+
+    @jit.unroll_safe
+    def _unpackiterable_known_length_jitlook(self, w_iterator,
+                                             expected_length):
+        items = [None] * expected_length
         idx = 0
         while True:
             try:
@@ -801,26 +855,29 @@
                 if not e.match(self, self.w_StopIteration):
                     raise
                 break  # done
-            if expected_length != -1 and idx == expected_length:
+            if idx == expected_length:
                 raise OperationError(self.w_ValueError,
-                                     self.wrap("too many values to unpack"))
-            if expected_length == -1:
-                items.append(w_item)
-            else:
-                items[idx] = w_item
+                                    self.wrap("too many values to unpack"))
+            items[idx] = w_item
             idx += 1
-        if expected_length != -1 and idx < expected_length:
+        if idx < expected_length:
             if idx == 1:
                 plural = ""
             else:
                 plural = "s"
-            raise OperationError(self.w_ValueError,
-                      self.wrap("need more than %d value%s to unpack" %
-                                (idx, plural)))
+            raise operationerrfmt(self.w_ValueError,
+                                  "need more than %d value%s to unpack",
+                                  idx, plural)
         return items
 
-    unpackiterable_unroll = jit.unroll_safe(func_with_new_name(unpackiterable,
-                                            'unpackiterable_unroll'))
+    def unpackiterable_unroll(self, w_iterable, expected_length):
+        # Like unpackiterable(), but for the cases where we have
+        # an expected_length and want to unroll when JITted.
+        # Returns a fixed-size list.
+        w_iterator = self.iter(w_iterable)
+        assert expected_length != -1
+        return self._unpackiterable_known_length_jitlook(w_iterator,
+                                                         expected_length)
 
     def fixedview(self, w_iterable, expected_length=-1):
         """ A fixed list view of w_iterable. Don't modify the result
@@ -835,6 +892,16 @@
         """
         return self.unpackiterable(w_iterable, expected_length)
 
+    def listview_str(self, w_list):
+        """ Return a list of unwrapped strings out of a list of strings. If the
+        argument is not a list or does not contain only strings, return None.
+        May return None anyway.
+        """
+        return None
+
+    def newlist_str(self, list_s):
+        return self.newlist([self.wrap(s) for s in list_s])
+
     @jit.unroll_safe
     def exception_match(self, w_exc_type, w_check_class):
         """Checks if the given exception type matches 'w_check_class'."""
@@ -969,9 +1036,6 @@
     def isinstance_w(self, w_obj, w_type):
         return self.is_true(self.isinstance(w_obj, w_type))
 
-    def id(self, w_obj):
-        return self.wrap(compute_unique_id(w_obj))
-
     # The code below only works
     # for the simple case (new-style instance).
     # These methods are patched with the full logic by the __builtin__
@@ -1543,6 +1607,8 @@
     'UnicodeError',
     'ValueError',
     'ZeroDivisionError',
+    'UnicodeEncodeError',
+    'UnicodeDecodeError',
     ]
 
 ## Irregular part of the interface:
diff --git a/pypy/interpreter/generator.py b/pypy/interpreter/generator.py
--- a/pypy/interpreter/generator.py
+++ b/pypy/interpreter/generator.py
@@ -1,14 +1,15 @@
+from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.error import OperationError
-from pypy.interpreter.baseobjspace import Wrappable
 from pypy.interpreter.gateway import NoneNotWrapped
+from pypy.interpreter.pyopcode import LoopBlock
 from pypy.rlib import jit
-from pypy.interpreter.pyopcode import LoopBlock
+from pypy.rlib.objectmodel import specialize
 
 
 class GeneratorIterator(Wrappable):
     "An iterator created by a generator."
     _immutable_fields_ = ['pycode']
-    
+
     def __init__(self, frame):
         self.space = frame.space
         self.frame = frame     # turned into None when frame_finished_execution
@@ -81,7 +82,7 @@
             # if the frame is now marked as finished, it was RETURNed from
             if frame.frame_finished_execution:
                 self.frame = None
-                raise OperationError(space.w_StopIteration, space.w_None) 
+                raise OperationError(space.w_StopIteration, space.w_None)
             else:
                 return w_result     # YIELDed
         finally:
@@ -97,21 +98,21 @@
     def throw(self, w_type, w_val, w_tb):
         from pypy.interpreter.pytraceback import check_traceback
         space = self.space
-        
+
         msg = "throw() third argument must be a traceback object"
         if space.is_w(w_tb, space.w_None):
             tb = None
         else:
             tb = check_traceback(space, w_tb, msg)
-       
+
         operr = OperationError(w_type, w_val, tb)
         operr.normalize_exception(space)
         return self.send_ex(space.w_None, operr)
-             
+
     def descr_next(self):
         """x.next() -> the next value, or raise StopIteration"""
         return self.send_ex(self.space.w_None)
- 
+
     def descr_close(self):
         """x.close(arg) -> raise GeneratorExit inside generator."""
         assert isinstance(self, GeneratorIterator)
@@ -124,7 +125,7 @@
                     e.match(space, space.w_GeneratorExit):
                 return space.w_None
             raise
-        
+
         if w_retval is not None:
             msg = "generator ignored GeneratorExit"
             raise OperationError(space.w_RuntimeError, space.wrap(msg))
@@ -155,3 +156,44 @@
                                                  "interrupting generator of ")
                     break
                 block = block.previous
+
+    # Results can be either an RPython list of W_Root, or it can be an
+    # app-level W_ListObject, which also has an append() method, that's why we
+    # generate 2 versions of the function and 2 jit drivers.
+    def _create_unpack_into():
+        jitdriver = jit.JitDriver(greens=['pycode'],
+                                  reds=['self', 'frame', 'results'])
+        def unpack_into(self, results):
+            """This is a hack for performance: runs the generator and collects
+            all produced items in a list."""
+            # XXX copied and simplified version of send_ex()
+            space = self.space
+            if self.running:
+                raise OperationError(space.w_ValueError,
+                                     space.wrap('generator already executing'))
+            frame = self.frame
+            if frame is None:    # already finished
+                return
+            self.running = True
+            try:
+                pycode = self.pycode
+                while True:
+                    jitdriver.jit_merge_point(self=self, frame=frame,
+                                              results=results, pycode=pycode)
+                    try:
+                        w_result = frame.execute_frame(space.w_None)
+                    except OperationError, e:
+                        if not e.match(space, space.w_StopIteration):
+                            raise
+                        break
+                    # if the frame is now marked as finished, it was RETURNed from
+                    if frame.frame_finished_execution:
+                        break
+                    results.append(w_result)     # YIELDed
+            finally:
+                frame.f_backref = jit.vref_None
+                self.running = False
+                self.frame = None
+        return unpack_into
+    unpack_into = _create_unpack_into()
+    unpack_into_w = _create_unpack_into()
\ No newline at end of file
diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -10,7 +10,7 @@
 from pypy.rlib.objectmodel import we_are_translated, instantiate
 from pypy.rlib.jit import hint
 from pypy.rlib.debug import make_sure_not_resized, check_nonneg
-from pypy.rlib.rarithmetic import intmask
+from pypy.rlib.rarithmetic import intmask, r_uint
 from pypy.rlib import jit
 from pypy.tool import stdlib_opcode
 from pypy.tool.stdlib_opcode import host_bytecode_spec
@@ -167,7 +167,7 @@
                 # Execution starts just after the last_instr.  Initially,
                 # last_instr is -1.  After a generator suspends it points to
                 # the YIELD_VALUE instruction.
-                next_instr = self.last_instr + 1
+                next_instr = r_uint(self.last_instr + 1)
                 if next_instr != 0:
                     self.pushvalue(w_inputvalue)
             #
@@ -691,6 +691,7 @@
     handlerposition = space.int_w(w_handlerposition)
     valuestackdepth = space.int_w(w_valuestackdepth)
     assert valuestackdepth >= 0
+    assert handlerposition >= 0
     blk = instantiate(get_block_class(opname))
     blk.handlerposition = handlerposition
     blk.valuestackdepth = valuestackdepth
diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -837,6 +837,7 @@
         raise Yield
 
     def jump_absolute(self, jumpto, next_instr, ec):
+        check_nonneg(jumpto)
         return jumpto
 
     def JUMP_FORWARD(self, jumpby, next_instr):
@@ -1278,7 +1279,7 @@
 
     def handle(self, frame, unroller):
         next_instr = self.really_handle(frame, unroller)   # JIT hack
-        return next_instr
+        return r_uint(next_instr)
 
     def really_handle(self, frame, unroller):
         """ Purely abstract method
diff --git a/pypy/interpreter/test/test_executioncontext.py b/pypy/interpreter/test/test_executioncontext.py
--- a/pypy/interpreter/test/test_executioncontext.py
+++ b/pypy/interpreter/test/test_executioncontext.py
@@ -292,7 +292,7 @@
         import os, sys
         print sys.executable, self.tmpfile
         if sys.platform == "win32":
-            cmdformat = '""%s" "%s""'    # excellent! tons of "!
+            cmdformat = '"%s" "%s"'
         else:
             cmdformat = "'%s' '%s'"
         g = os.popen(cmdformat % (sys.executable, self.tmpfile), 'r')
diff --git a/pypy/interpreter/test/test_function.py b/pypy/interpreter/test/test_function.py
--- a/pypy/interpreter/test/test_function.py
+++ b/pypy/interpreter/test/test_function.py
@@ -587,7 +587,7 @@
         assert isinstance(meth2, Method)
         assert meth2.call_args(args) == obj1
         # Check method returned from unbound_method.__get__()
-        w_meth3 = descr_function_get(space, func, None, space.type(obj2))
+        w_meth3 = descr_function_get(space, func, space.w_None, space.type(obj2))
         meth3 = space.unwrap(w_meth3)
         w_meth4 = meth3.descr_method_get(obj2, space.w_None)
         meth4 = space.unwrap(w_meth4)
diff --git a/pypy/interpreter/test/test_generator.py b/pypy/interpreter/test/test_generator.py
--- a/pypy/interpreter/test/test_generator.py
+++ b/pypy/interpreter/test/test_generator.py
@@ -117,7 +117,7 @@
         g = f()
         raises(NameError, g.throw, NameError, "Error", None)
 
-    
+
     def test_throw_fail(self):
         def f():
             yield 1
@@ -129,7 +129,7 @@
             yield 1
         g = f()
         raises(TypeError, g.throw, list())
- 
+
     def test_throw_fail3(self):
         def f():
             yield 1
@@ -188,7 +188,7 @@
         g = f()
         g.next()
         raises(NameError, g.close)
- 
+
     def test_close_fail(self):
         def f():
             try:
@@ -267,3 +267,15 @@
         assert r.startswith("<generator object myFunc at 0x")
         assert list(g) == [1]
         assert repr(g) == r
+
+    def test_unpackiterable_gen(self):
+        g = (i*i for i in range(-5, 3))
+        assert set(g) == set([0, 1, 4, 9, 16, 25])
+        assert set(g) == set()
+        assert set(i for i in range(0)) == set()
+
+    def test_explicit_stop_iteration_unpackiterable(self):
+        def f():
+            yield 1
+            raise StopIteration
+        assert tuple(f()) == (1,)
\ No newline at end of file
diff --git a/pypy/interpreter/test/test_objspace.py b/pypy/interpreter/test/test_objspace.py
--- a/pypy/interpreter/test/test_objspace.py
+++ b/pypy/interpreter/test/test_objspace.py
@@ -63,10 +63,13 @@
     def test_unpackiterable(self):
         space = self.space
         w = space.wrap
-        l = [w(1), w(2), w(3), w(4)]
+        l = [space.newlist([]) for l in range(4)]
         w_l = space.newlist(l)
-        assert space.unpackiterable(w_l) == l
-        assert space.unpackiterable(w_l, 4) == l
+        l1 = space.unpackiterable(w_l)
+        l2 = space.unpackiterable(w_l, 4)
+        for i in range(4):
+            assert space.is_w(l1[i], l[i])
+            assert space.is_w(l2[i], l[i])
         err = raises(OperationError, space.unpackiterable, w_l, 3)
         assert err.value.match(space, space.w_ValueError)
         err = raises(OperationError, space.unpackiterable, w_l, 5)
diff --git a/pypy/interpreter/test/test_typedef.py b/pypy/interpreter/test/test_typedef.py
--- a/pypy/interpreter/test/test_typedef.py
+++ b/pypy/interpreter/test/test_typedef.py
@@ -2,7 +2,7 @@
 from pypy.interpreter import typedef
 from pypy.tool.udir import udir
 from pypy.interpreter.baseobjspace import Wrappable
-from pypy.interpreter.gateway import ObjSpace
+from pypy.interpreter.gateway import ObjSpace, interp2app
 
 # this test isn't so much to test that the objspace interface *works*
 # -- it's more to test that it's *there*
@@ -260,6 +260,50 @@
         gc.collect(); gc.collect()
         assert space.unwrap(w_seen) == [6, 2]
 
+    def test_multiple_inheritance(self):
+        class W_A(Wrappable):
+            a = 1
+            b = 2
+        class W_C(W_A):
+            b = 3
+        W_A.typedef = typedef.TypeDef("A",
+            a = typedef.interp_attrproperty("a", cls=W_A),
+            b = typedef.interp_attrproperty("b", cls=W_A),
+        )
+        class W_B(Wrappable):
+            pass
+        def standalone_method(space, w_obj):
+            if isinstance(w_obj, W_A):
+                return space.w_True
+            else:
+                return space.w_False
+        W_B.typedef = typedef.TypeDef("B",
+            c = interp2app(standalone_method)
+        )
+        W_C.typedef = typedef.TypeDef("C", (W_A.typedef, W_B.typedef,))
+
+        w_o1 = self.space.wrap(W_C())
+        w_o2 = self.space.wrap(W_B())
+        w_c = self.space.gettypefor(W_C)
+        w_b = self.space.gettypefor(W_B)
+        w_a = self.space.gettypefor(W_A)
+        assert w_c.mro_w == [
+            w_c,
+            w_a,
+            w_b,
+            self.space.w_object,
+        ]
+        for w_tp in w_c.mro_w:
+            assert self.space.isinstance_w(w_o1, w_tp)
+        def assert_attr(w_obj, name, value):
+            assert self.space.unwrap(self.space.getattr(w_obj, self.space.wrap(name))) == value
+        def assert_method(w_obj, name, value):
+            assert self.space.unwrap(self.space.call_method(w_obj, name)) == value
+        assert_attr(w_o1, "a", 1)
+        assert_attr(w_o1, "b", 3)
+        assert_method(w_o1, "c", True)
+        assert_method(w_o2, "c", False)
+
 
 class AppTestTypeDef:
 
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -15,13 +15,19 @@
     def __init__(self, __name, __base=None, **rawdict):
         "NOT_RPYTHON: initialization-time only"
         self.name = __name
-        self.base = __base
+        if __base is None:
+            bases = []
+        elif isinstance(__base, tuple):
+            bases = list(__base)
+        else:
+            bases = [__base]
+        self.bases = bases
         self.hasdict = '__dict__' in rawdict
         self.weakrefable = '__weakref__' in rawdict
         self.doc = rawdict.pop('__doc__', None)
-        if __base is not None:
-            self.hasdict     |= __base.hasdict
-            self.weakrefable |= __base.weakrefable
+        for base in bases:
+            self.hasdict     |= base.hasdict
+            self.weakrefable |= base.weakrefable
         self.rawdict = {}
         self.acceptable_as_base_class = '__new__' in rawdict
         self.applevel_subclasses_base = None
diff --git a/pypy/jit/backend/conftest.py b/pypy/jit/backend/conftest.py
--- a/pypy/jit/backend/conftest.py
+++ b/pypy/jit/backend/conftest.py
@@ -12,7 +12,7 @@
                     help="choose a fixed random seed")
     group.addoption('--backend', action="store",
                     default='llgraph',
-                    choices=['llgraph', 'x86'],
+                    choices=['llgraph', 'cpu'],
                     dest="backend",
                     help="select the backend to run the functions with")
     group.addoption('--block-length', action="store", type="int",
diff --git a/pypy/jit/backend/llgraph/llimpl.py b/pypy/jit/backend/llgraph/llimpl.py
--- a/pypy/jit/backend/llgraph/llimpl.py
+++ b/pypy/jit/backend/llgraph/llimpl.py
@@ -20,6 +20,7 @@
 from pypy.jit.backend.llgraph import symbolic
 from pypy.jit.codewriter import longlong
 
+from pypy.rlib import libffi, clibffi
 from pypy.rlib.objectmodel import ComputedIntSymbolic, we_are_translated
 from pypy.rlib.rarithmetic import ovfcheck
 from pypy.rlib.rarithmetic import r_longlong, r_ulonglong, r_uint
@@ -325,12 +326,12 @@
     loop = _from_opaque(loop)
     loop.operations.append(Operation(opnum))
 
-def compile_add_descr(loop, ofs, type, arg_types):
+def compile_add_descr(loop, ofs, type, arg_types, extrainfo, width):
     from pypy.jit.backend.llgraph.runner import Descr
     loop = _from_opaque(loop)
     op = loop.operations[-1]
     assert isinstance(type, str) and len(type) == 1
-    op.descr = Descr(ofs, type, arg_types=arg_types)
+    op.descr = Descr(ofs, type, arg_types=arg_types, extrainfo=extrainfo, width=width)
 
 def compile_add_descr_arg(loop, ofs, type, arg_types):
     from pypy.jit.backend.llgraph.runner import Descr
@@ -825,6 +826,16 @@
         else:
             raise NotImplementedError
 
+    def op_getinteriorfield_raw(self, descr, array, index):
+        if descr.typeinfo == REF:
+            return do_getinteriorfield_raw_ptr(array, index, descr.width, descr.ofs)
+        elif descr.typeinfo == INT:
+            return do_getinteriorfield_raw_int(array, index, descr.width, descr.ofs)
+        elif descr.typeinfo == FLOAT:
+            return do_getinteriorfield_raw_float(array, index, descr.width, descr.ofs)
+        else:
+            raise NotImplementedError
+
     def op_setinteriorfield_gc(self, descr, array, index, newvalue):
         if descr.typeinfo == REF:
             return do_setinteriorfield_gc_ptr(array, index, descr.ofs,
@@ -838,6 +849,16 @@
         else:
             raise NotImplementedError
 
+    def op_setinteriorfield_raw(self, descr, array, index, newvalue):
+        if descr.typeinfo == REF:
+            return do_setinteriorfield_raw_ptr(array, index, newvalue, descr.width, descr.ofs)
+        elif descr.typeinfo == INT:
+            return do_setinteriorfield_raw_int(array, index, newvalue, descr.width, descr.ofs)
+        elif descr.typeinfo == FLOAT:
+            return do_setinteriorfield_raw_float(array, index, newvalue, descr.width, descr.ofs)
+        else:
+            raise NotImplementedError
+
     def op_setfield_gc(self, fielddescr, struct, newvalue):
         if fielddescr.typeinfo == REF:
             do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue)
@@ -1114,7 +1135,9 @@
     if isinstance(TYPE, lltype.Ptr):
         if isinstance(x, (int, long, llmemory.AddressAsInt)):
             x = llmemory.cast_int_to_adr(x)
-        if TYPE is rffi.VOIDP or TYPE.TO._hints.get("uncast_on_llgraph"):
+        if TYPE is rffi.VOIDP or (
+                hasattr(TYPE.TO, '_hints') and
+                TYPE.TO._hints.get("uncast_on_llgraph")):
             # assume that we want a "C-style" cast, without typechecking the value
             return rffi.cast(TYPE, x)
         return llmemory.cast_adr_to_ptr(x, TYPE)
@@ -1401,6 +1424,18 @@
     struct = array._obj.container.getitem(index)
     return cast_to_ptr(_getinteriorfield_gc(struct, fieldnum))
 
+def _getinteriorfield_raw(ffitype, array, index, width, ofs):
+    addr = rffi.cast(rffi.VOIDP, array)
+    return libffi.array_getitem(ffitype, width, addr, index, ofs)
+
+def do_getinteriorfield_raw_int(array, index, width, ofs):
+    res = _getinteriorfield_raw(libffi.types.slong, array, index, width, ofs)
+    return res
+
+def do_getinteriorfield_raw_float(array, index, width, ofs):
+    res = _getinteriorfield_raw(libffi.types.double, array, index, width, ofs)
+    return res
+
 def _getfield_raw(struct, fieldnum):
     STRUCT, fieldname = symbolic.TokenToField[fieldnum]
     ptr = cast_from_int(lltype.Ptr(STRUCT), struct)
@@ -1477,7 +1512,19 @@
     return do_setinteriorfield_gc
 do_setinteriorfield_gc_int = new_setinteriorfield_gc(cast_from_int)
 do_setinteriorfield_gc_float = new_setinteriorfield_gc(cast_from_floatstorage)
-do_setinteriorfield_gc_ptr = new_setinteriorfield_gc(cast_from_ptr)        
+do_setinteriorfield_gc_ptr = new_setinteriorfield_gc(cast_from_ptr)
+
+def new_setinteriorfield_raw(cast_func, ffitype):
+    def do_setinteriorfield_raw(array, index, newvalue, width, ofs):
+        addr = rffi.cast(rffi.VOIDP, array)
+        for TYPE, ffitype2 in clibffi.ffitype_map:
+            if ffitype2 is ffitype:
+                newvalue = cast_func(TYPE, newvalue)
+                break
+        return libffi.array_setitem(ffitype, width, addr, index, ofs, newvalue)
+    return do_setinteriorfield_raw
+do_setinteriorfield_raw_int = new_setinteriorfield_raw(cast_from_int, libffi.types.slong)
+do_setinteriorfield_raw_float = new_setinteriorfield_raw(cast_from_floatstorage, libffi.types.double)
 
 def do_setfield_raw_int(struct, fieldnum, newvalue):
     STRUCT, fieldname = symbolic.TokenToField[fieldnum]
diff --git a/pypy/jit/backend/llgraph/runner.py b/pypy/jit/backend/llgraph/runner.py
--- a/pypy/jit/backend/llgraph/runner.py
+++ b/pypy/jit/backend/llgraph/runner.py
@@ -23,8 +23,10 @@
 class Descr(history.AbstractDescr):
 
     def __init__(self, ofs, typeinfo, extrainfo=None, name=None,
-                 arg_types=None, count_fields_if_immut=-1, ffi_flags=0):
+                 arg_types=None, count_fields_if_immut=-1, ffi_flags=0, width=-1):
+
         self.ofs = ofs
+        self.width = width
         self.typeinfo = typeinfo
         self.extrainfo = extrainfo
         self.name = name
@@ -119,14 +121,14 @@
         return False
 
     def getdescr(self, ofs, typeinfo='?', extrainfo=None, name=None,
-                 arg_types=None, count_fields_if_immut=-1, ffi_flags=0):
+                 arg_types=None, count_fields_if_immut=-1, ffi_flags=0, width=-1):
         key = (ofs, typeinfo, extrainfo, name, arg_types,
-               count_fields_if_immut, ffi_flags)
+               count_fields_if_immut, ffi_flags, width)
         try:
             return self._descrs[key]
         except KeyError:
             descr = Descr(ofs, typeinfo, extrainfo, name, arg_types,
-                          count_fields_if_immut, ffi_flags)
+                          count_fields_if_immut, ffi_flags, width)
             self._descrs[key] = descr
             return descr
 
@@ -179,7 +181,8 @@
             descr = op.getdescr()
             if isinstance(descr, Descr):
                 llimpl.compile_add_descr(c, descr.ofs, descr.typeinfo,
-                                         descr.arg_types)
+                                         descr.arg_types, descr.extrainfo,
+                                         descr.width)
             if (isinstance(descr, history.LoopToken) and
                 op.getopnum() != rop.JUMP):
                 llimpl.compile_add_loop_token(c, descr)
@@ -324,10 +327,22 @@
 
     def interiorfielddescrof(self, A, fieldname):
         S = A.OF
-        ofs2 = symbolic.get_size(A)
+        width = symbolic.get_size(A)
         ofs, size = symbolic.get_field_token(S, fieldname)
         token = history.getkind(getattr(S, fieldname))
-        return self.getdescr(ofs, token[0], name=fieldname, extrainfo=ofs2)
+        return self.getdescr(ofs, token[0], name=fieldname, width=width)
+
+    def interiorfielddescrof_dynamic(self, offset, width, fieldsize,
+        is_pointer, is_float, is_signed):
+
+        if is_pointer:
+            typeinfo = REF
+        elif is_float:
+            typeinfo = FLOAT
+        else:
+            typeinfo = INT
+        # we abuse the arg_types field to distinguish dynamic and static descrs
+        return Descr(offset, typeinfo, arg_types='dynamic', name='<dynamic interior field>', width=width)
 
     def calldescrof(self, FUNC, ARGS, RESULT, extrainfo):
         arg_types = []
@@ -365,6 +380,7 @@
 
     def arraydescrof(self, A):
         assert A.OF != lltype.Void
+        assert isinstance(A, lltype.GcArray) or A._hints.get('nolength', False)
         size = symbolic.get_size(A)
         if isinstance(A.OF, lltype.Ptr) or isinstance(A.OF, lltype.Primitive):
             token = history.getkind(A.OF)[0]
diff --git a/pypy/jit/backend/llsupport/asmmemmgr.py b/pypy/jit/backend/llsupport/asmmemmgr.py
--- a/pypy/jit/backend/llsupport/asmmemmgr.py
+++ b/pypy/jit/backend/llsupport/asmmemmgr.py
@@ -37,25 +37,25 @@
             self._add_free_block(smaller_stop, stop)
             stop = smaller_stop
             result = (start, stop)
-        self.total_mallocs += stop - start
+        self.total_mallocs += r_uint(stop - start)
         return result   # pair (start, stop)
 
     def free(self, start, stop):
         """Free a block (start, stop) returned by a previous malloc()."""
-        self.total_mallocs -= (stop - start)
+        self.total_mallocs -= r_uint(stop - start)
         self._add_free_block(start, stop)
 
     def open_malloc(self, minsize):
         """Allocate at least minsize bytes.  Returns (start, stop)."""
         result = self._allocate_block(minsize)
         (start, stop) = result
-        self.total_mallocs += stop - start
+        self.total_mallocs += r_uint(stop - start)
         return result
 
     def open_free(self, middle, stop):
         """Used for freeing the end of an open-allocated block of memory."""
         if stop - middle >= self.min_fragment:
-            self.total_mallocs -= (stop - middle)
+            self.total_mallocs -= r_uint(stop - middle)
             self._add_free_block(middle, stop)
             return True
         else:
@@ -77,7 +77,7 @@
                 # Hack to make sure that mcs are not within 32-bits of one
                 # another for testing purposes
                 rmmap.hint.pos += 0x80000000 - size
-        self.total_memory_allocated += size
+        self.total_memory_allocated += r_uint(size)
         data = rffi.cast(lltype.Signed, data)
         return self._add_free_block(data, data + size)
 
diff --git a/pypy/jit/backend/llsupport/descr.py b/pypy/jit/backend/llsupport/descr.py
--- a/pypy/jit/backend/llsupport/descr.py
+++ b/pypy/jit/backend/llsupport/descr.py
@@ -111,6 +111,16 @@
     def repr_of_descr(self):
         return '<%s %s %s>' % (self._clsname, self.name, self.offset)
 
+class DynamicFieldDescr(BaseFieldDescr):
+    def __init__(self, offset, fieldsize, is_pointer, is_float, is_signed):
+        self.offset = offset
+        self._fieldsize = fieldsize
+        self._is_pointer_field = is_pointer
+        self._is_float_field = is_float
+        self._is_field_signed = is_signed
+
+    def get_field_size(self, translate_support_code):
+        return self._fieldsize
 
 class NonGcPtrFieldDescr(BaseFieldDescr):
     _clsname = 'NonGcPtrFieldDescr'
@@ -182,6 +192,7 @@
     def repr_of_descr(self):
         return '<%s>' % self._clsname
 
+
 class NonGcPtrArrayDescr(BaseArrayDescr):
     _clsname = 'NonGcPtrArrayDescr'
     def get_item_size(self, translate_support_code):
@@ -211,6 +222,13 @@
     def get_ofs_length(self, translate_support_code):
         return -1
 
+class DynamicArrayNoLengthDescr(BaseArrayNoLengthDescr):
+    def __init__(self, itemsize):
+        self.itemsize = itemsize
+
+    def get_item_size(self, translate_support_code):
+        return self.itemsize
+
 class NonGcPtrArrayNoLengthDescr(BaseArrayNoLengthDescr):
     _clsname = 'NonGcPtrArrayNoLengthDescr'
     def get_item_size(self, translate_support_code):
@@ -305,12 +323,16 @@
     _clsname = ''
     loop_token = None
     arg_classes = ''     # <-- annotation hack
-    ffi_flags = 0
+    ffi_flags = 1
 
-    def __init__(self, arg_classes, extrainfo=None, ffi_flags=0):
+    def __init__(self, arg_classes, extrainfo=None, ffi_flags=1):
         self.arg_classes = arg_classes    # string of "r" and "i" (ref/int)
         self.extrainfo = extrainfo
         self.ffi_flags = ffi_flags
+        # NB. the default ffi_flags is 1, meaning FUNCFLAG_CDECL, which
+        # makes sense on Windows as it's the one for all the C functions
+        # we are compiling together with the JIT.  On non-Windows platforms
+        # it is just ignored anyway.
 
     def __repr__(self):
         res = '%s(%s)' % (self.__class__.__name__, self.arg_classes)
@@ -351,6 +373,10 @@
         return False    # unless overridden
 
     def create_call_stub(self, rtyper, RESULT):
+        from pypy.rlib.clibffi import FFI_DEFAULT_ABI
+        assert self.get_call_conv() == FFI_DEFAULT_ABI, (
+            "%r: create_call_stub() with a non-default call ABI" % (self,))
+
         def process(c):
             if c == 'L':
                 assert longlong.supports_longlong
@@ -445,7 +471,7 @@
     """
     _clsname = 'DynamicIntCallDescr'
 
-    def __init__(self, arg_classes, result_size, result_sign, extrainfo=None, ffi_flags=0):
+    def __init__(self, arg_classes, result_size, result_sign, extrainfo, ffi_flags):
         BaseIntCallDescr.__init__(self, arg_classes, extrainfo, ffi_flags)
         assert isinstance(result_sign, bool)
         self._result_size = chr(result_size)
diff --git a/pypy/jit/backend/llsupport/ffisupport.py b/pypy/jit/backend/llsupport/ffisupport.py
--- a/pypy/jit/backend/llsupport/ffisupport.py
+++ b/pypy/jit/backend/llsupport/ffisupport.py
@@ -8,7 +8,7 @@
 class UnsupportedKind(Exception):
     pass
 
-def get_call_descr_dynamic(cpu, ffi_args, ffi_result, extrainfo=None, ffi_flags=0):
+def get_call_descr_dynamic(cpu, ffi_args, ffi_result, extrainfo, ffi_flags):
     """Get a call descr: the types of result and args are represented by
     rlib.libffi.types.*"""
     try:
diff --git a/pypy/jit/backend/llsupport/gc.py b/pypy/jit/backend/llsupport/gc.py
--- a/pypy/jit/backend/llsupport/gc.py
+++ b/pypy/jit/backend/llsupport/gc.py
@@ -648,14 +648,10 @@
         # make a malloc function, with two arguments
         def malloc_basic(size, tid):
             type_id = llop.extract_ushort(llgroup.HALFWORD, tid)
-            has_finalizer = bool(tid & (1<<llgroup.HALFSHIFT))
-            has_light_finalizer = bool(tid & (1<<(llgroup.HALFSHIFT + 1)))
             check_typeid(type_id)
             res = llop1.do_malloc_fixedsize_clear(llmemory.GCREF,
                                                   type_id, size,
-                                                  has_finalizer,
-                                                  has_light_finalizer,
-                                                  False)
+                                                  False, False, False)
             # In case the operation above failed, we are returning NULL
             # from this function to assembler.  There is also an RPython
             # exception set, typically MemoryError; but it's easier and
@@ -749,11 +745,8 @@
     def init_size_descr(self, S, descr):
         type_id = self.layoutbuilder.get_type_id(S)
         assert not self.layoutbuilder.is_weakref_type(S)
-        has_finalizer = bool(self.layoutbuilder.has_finalizer(S))
-        has_light_finalizer = bool(self.layoutbuilder.has_light_finalizer(S))
-        flags = (int(has_finalizer) << llgroup.HALFSHIFT |
-                 int(has_light_finalizer) << (llgroup.HALFSHIFT + 1))
-        descr.tid = llop.combine_ushort(lltype.Signed, type_id, flags)
+        assert not self.layoutbuilder.has_finalizer(S)
+        descr.tid = llop.combine_ushort(lltype.Signed, type_id, 0)
 
     def init_array_descr(self, A, descr):
         type_id = self.layoutbuilder.get_type_id(A)
@@ -830,6 +823,15 @@
                                             bool(v.value)): # store a non-NULL
                         self._gen_write_barrier(newops, op.getarg(0), v)
                         op = op.copy_and_change(rop.SETFIELD_RAW)
+            # ---------- write barrier for SETINTERIORFIELD_GC ------
+            if op.getopnum() == rop.SETINTERIORFIELD_GC:
+                val = op.getarg(0)
+                if val is not last_malloc:
+                    v = op.getarg(2)
+                    if isinstance(v, BoxPtr) or (isinstance(v, ConstPtr) and
+                                            bool(v.value)): # store a non-NULL
+                        self._gen_write_barrier(newops, op.getarg(0), v)
+                        op = op.copy_and_change(rop.SETINTERIORFIELD_RAW)
             # ---------- write barrier for SETARRAYITEM_GC ----------
             if op.getopnum() == rop.SETARRAYITEM_GC:
                 val = op.getarg(0)
diff --git a/pypy/jit/backend/llsupport/llmodel.py b/pypy/jit/backend/llsupport/llmodel.py
--- a/pypy/jit/backend/llsupport/llmodel.py
+++ b/pypy/jit/backend/llsupport/llmodel.py
@@ -9,9 +9,10 @@
 from pypy.jit.backend.llsupport import symbolic
 from pypy.jit.backend.llsupport.symbolic import WORD, unroll_basic_sizes
 from pypy.jit.backend.llsupport.descr import (get_size_descr,
-     get_field_descr, BaseFieldDescr, get_array_descr, BaseArrayDescr,
-     get_call_descr, BaseIntCallDescr, GcPtrCallDescr, FloatCallDescr,
-     VoidCallDescr, InteriorFieldDescr, get_interiorfield_descr)
+     get_field_descr, BaseFieldDescr, DynamicFieldDescr, get_array_descr,
+     BaseArrayDescr, DynamicArrayNoLengthDescr, get_call_descr,
+     BaseIntCallDescr, GcPtrCallDescr, FloatCallDescr, VoidCallDescr,
+     InteriorFieldDescr, get_interiorfield_descr)
 from pypy.jit.backend.llsupport.asmmemmgr import AsmMemoryManager
 
 
@@ -238,6 +239,12 @@
     def interiorfielddescrof(self, A, fieldname):
         return get_interiorfield_descr(self.gc_ll_descr, A, A.OF, fieldname)
 
+    def interiorfielddescrof_dynamic(self, offset, width, fieldsize,
+        is_pointer, is_float, is_signed):
+        arraydescr = DynamicArrayNoLengthDescr(width)
+        fielddescr = DynamicFieldDescr(offset, fieldsize, is_pointer, is_float, is_signed)
+        return InteriorFieldDescr(arraydescr, fielddescr)
+
     def unpack_arraydescr(self, arraydescr):
         assert isinstance(arraydescr, BaseArrayDescr)
         return arraydescr.get_base_size(self.translate_support_code)
diff --git a/pypy/jit/backend/llsupport/test/test_ffisupport.py b/pypy/jit/backend/llsupport/test/test_ffisupport.py
--- a/pypy/jit/backend/llsupport/test/test_ffisupport.py
+++ b/pypy/jit/backend/llsupport/test/test_ffisupport.py
@@ -13,44 +13,46 @@
 
 def test_call_descr_dynamic():
     args = [types.sint, types.pointer]
-    descr = get_call_descr_dynamic(FakeCPU(), args, types.sint, ffi_flags=42)
+    descr = get_call_descr_dynamic(FakeCPU(), args, types.sint, None,
+                                   ffi_flags=42)
     assert isinstance(descr, DynamicIntCallDescr)
     assert descr.arg_classes == 'ii'
     assert descr.get_ffi_flags() == 42
 
     args = [types.sint, types.double, types.pointer]
-    descr = get_call_descr_dynamic(FakeCPU(), args, types.void)
+    descr = get_call_descr_dynamic(FakeCPU(), args, types.void, None, 42)
     assert descr is None    # missing floats
     descr = get_call_descr_dynamic(FakeCPU(supports_floats=True),
-                                   args, types.void, ffi_flags=43)
+                                   args, types.void, None, ffi_flags=43)
     assert isinstance(descr, VoidCallDescr)
     assert descr.arg_classes == 'ifi'
     assert descr.get_ffi_flags() == 43
 
-    descr = get_call_descr_dynamic(FakeCPU(), [], types.sint8)
+    descr = get_call_descr_dynamic(FakeCPU(), [], types.sint8, None, 42)
     assert isinstance(descr, DynamicIntCallDescr)
     assert descr.get_result_size(False) == 1
     assert descr.is_result_signed() == True
 
-    descr = get_call_descr_dynamic(FakeCPU(), [], types.uint8)
+    descr = get_call_descr_dynamic(FakeCPU(), [], types.uint8, None, 42)
     assert isinstance(descr, DynamicIntCallDescr)
     assert descr.get_result_size(False) == 1
     assert descr.is_result_signed() == False
 
     if not is_64_bit:
-        descr = get_call_descr_dynamic(FakeCPU(), [], types.slonglong)
+        descr = get_call_descr_dynamic(FakeCPU(), [], types.slonglong,
+                                       None, 42)
         assert descr is None   # missing longlongs
         descr = get_call_descr_dynamic(FakeCPU(supports_longlong=True),
-                                       [], types.slonglong, ffi_flags=43)
+                                       [], types.slonglong, None, ffi_flags=43)
         assert isinstance(descr, LongLongCallDescr)
         assert descr.get_ffi_flags() == 43
     else:
         assert types.slonglong is types.slong
 
-    descr = get_call_descr_dynamic(FakeCPU(), [], types.float)
+    descr = get_call_descr_dynamic(FakeCPU(), [], types.float, None, 42)
     assert descr is None   # missing singlefloats
     descr = get_call_descr_dynamic(FakeCPU(supports_singlefloats=True),
-                                   [], types.float, ffi_flags=44)
+                                   [], types.float, None, ffi_flags=44)
     SingleFloatCallDescr = getCallDescrClass(rffi.FLOAT)
     assert isinstance(descr, SingleFloatCallDescr)
     assert descr.get_ffi_flags() == 44
diff --git a/pypy/jit/backend/llsupport/test/test_gc.py b/pypy/jit/backend/llsupport/test/test_gc.py
--- a/pypy/jit/backend/llsupport/test/test_gc.py
+++ b/pypy/jit/backend/llsupport/test/test_gc.py
@@ -570,6 +570,28 @@
             assert operations[1].getarg(2) == v_value
             assert operations[1].getdescr() == array_descr
 
+    def test_rewrite_assembler_5(self):
+        S = lltype.GcStruct('S')
+        A = lltype.GcArray(lltype.Struct('A', ('x', lltype.Ptr(S))))
+        interiordescr = get_interiorfield_descr(self.gc_ll_descr, A,
+                                                A.OF, 'x')
+        wbdescr = self.gc_ll_descr.write_barrier_descr
+        ops = parse("""
+        [p1, p2]
+        setinteriorfield_gc(p1, 0, p2, descr=interiordescr)
+        jump(p1, p2)
+        """, namespace=locals())
+        expected = parse(""" 
+        [p1, p2]
+        cond_call_gc_wb(p1, p2, descr=wbdescr)
+        setinteriorfield_raw(p1, 0, p2, descr=interiordescr)
+        jump(p1, p2)
+        """, namespace=locals())
+        operations = get_deep_immutable_oplist(ops.operations)
+        operations = self.gc_ll_descr.rewrite_assembler(self.fake_cpu,
+                                                        operations, [])
+        equaloplists(operations, expected.operations)
+
     def test_rewrite_assembler_initialization_store(self):
         S = lltype.GcStruct('S', ('parent', OBJECT),
                             ('x', lltype.Signed))
diff --git a/pypy/jit/backend/llsupport/test/test_regalloc.py b/pypy/jit/backend/llsupport/test/test_regalloc.py
--- a/pypy/jit/backend/llsupport/test/test_regalloc.py
+++ b/pypy/jit/backend/llsupport/test/test_regalloc.py
@@ -2,6 +2,8 @@
 from pypy.jit.metainterp.history import BoxInt, ConstInt, BoxFloat, INT, FLOAT
 from pypy.jit.backend.llsupport.regalloc import FrameManager
 from pypy.jit.backend.llsupport.regalloc import RegisterManager as BaseRegMan
+from pypy.jit.tool.oparser import parse
+from pypy.jit.backend.detect_cpu import getcpuclass
 
 def newboxes(*values):
     return [BoxInt(v) for v in values]
diff --git a/pypy/jit/backend/model.py b/pypy/jit/backend/model.py
--- a/pypy/jit/backend/model.py
+++ b/pypy/jit/backend/model.py
@@ -183,38 +183,35 @@
             lst[n] = None
         self.fail_descr_free_list.extend(faildescr_indices)
 
-    @staticmethod
-    def sizeof(S):
+    def sizeof(self, S):
         raise NotImplementedError
 
-    @staticmethod
-    def fielddescrof(S, fieldname):
+    def fielddescrof(self, S, fieldname):
         """Return the Descr corresponding to field 'fieldname' on the
         structure 'S'.  It is important that this function (at least)
         caches the results."""
         raise NotImplementedError
 
-    @staticmethod
-    def arraydescrof(A):
+    def interiorfielddescrof(self, A, fieldname):
         raise NotImplementedError
 
-    @staticmethod
-    def calldescrof(FUNC, ARGS, RESULT):
+    def interiorfielddescrof_dynamic(self, offset, width, fieldsize, is_pointer,
+        is_float, is_signed):
+        raise NotImplementedError
+
+    def arraydescrof(self, A):
+        raise NotImplementedError
+
+    def calldescrof(self, FUNC, ARGS, RESULT):
         # FUNC is the original function type, but ARGS is a list of types
         # with Voids removed
         raise NotImplementedError
 
-    @staticmethod
-    def methdescrof(SELFTYPE, methname):
+    def methdescrof(self, SELFTYPE, methname):
         # must return a subclass of history.AbstractMethDescr
         raise NotImplementedError
 
-    @staticmethod
-    def typedescrof(TYPE):
-        raise NotImplementedError
-
-    @staticmethod
-    def interiorfielddescrof(A, fieldname):
+    def typedescrof(self, TYPE):
         raise NotImplementedError
 
     # ---------- the backend-dependent operations ----------
diff --git a/pypy/jit/backend/test/test_random.py b/pypy/jit/backend/test/test_random.py
--- a/pypy/jit/backend/test/test_random.py
+++ b/pypy/jit/backend/test/test_random.py
@@ -495,9 +495,9 @@
     if pytest.config.option.backend == 'llgraph':
         from pypy.jit.backend.llgraph.runner import LLtypeCPU
         return LLtypeCPU(None)
-    elif pytest.config.option.backend == 'x86':
-        from pypy.jit.backend.x86.runner import CPU386
-        return CPU386(None, None)
+    elif pytest.config.option.backend == 'cpu':
+        from pypy.jit.backend.detect_cpu import getcpuclass
+        return getcpuclass()(None, None)
     else:
         assert 0, "unknown backend %r" % pytest.config.option.backend
 
diff --git a/pypy/jit/backend/x86/test/test_zll_random.py b/pypy/jit/backend/test/test_zll_stress.py
rename from pypy/jit/backend/x86/test/test_zll_random.py
rename to pypy/jit/backend/test/test_zll_stress.py
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
@@ -8,8 +8,8 @@
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.annlowlevel import llhelper
 from pypy.jit.backend.model import CompiledLoopToken
-from pypy.jit.backend.x86.regalloc import (RegAlloc, get_ebp_ofs,
-                                           _get_scale, gpr_reg_mgr_cls)
+from pypy.jit.backend.x86.regalloc import (RegAlloc, get_ebp_ofs, _get_scale,
+    gpr_reg_mgr_cls, _valid_addressing_size)
 
 from pypy.jit.backend.x86.arch import (FRAME_FIXED_SIZE, FORCE_INDEX_OFS, WORD,
                                        IS_X86_32, IS_X86_64)
@@ -1601,10 +1601,13 @@
         assert isinstance(itemsize_loc, ImmedLoc)
         if isinstance(index_loc, ImmedLoc):
             temp_loc = imm(index_loc.value * itemsize_loc.value)
+        elif _valid_addressing_size(itemsize_loc.value):
+            return AddressLoc(base_loc, index_loc, _get_scale(itemsize_loc.value), ofs_loc.value)
         else:
-            # XXX should not use IMUL in most cases
+            # XXX should not use IMUL in more cases, it can use a clever LEA
             assert isinstance(temp_loc, RegLoc)
             assert isinstance(index_loc, RegLoc)
+            assert not temp_loc.is_xmm
             self.mc.IMUL_rri(temp_loc.value, index_loc.value,
                              itemsize_loc.value)
         assert isinstance(ofs_loc, ImmedLoc)
@@ -1612,12 +1615,14 @@
 
     def genop_getinteriorfield_gc(self, op, arglocs, resloc):
         (base_loc, ofs_loc, itemsize_loc, fieldsize_loc,
-            index_loc, sign_loc) = arglocs
-        src_addr = self._get_interiorfield_addr(resloc, index_loc,
+            index_loc, temp_loc, sign_loc) = arglocs
+        src_addr = self._get_interiorfield_addr(temp_loc, index_loc,
                                                 itemsize_loc, base_loc,
                                                 ofs_loc)
         self.load_from_mem(resloc, src_addr, fieldsize_loc, sign_loc)
 
+    genop_getinteriorfield_raw = genop_getinteriorfield_gc
+
 
     def genop_discard_setfield_gc(self, op, arglocs):
         base_loc, ofs_loc, size_loc, value_loc = arglocs
@@ -1633,6 +1638,8 @@
                                                  ofs_loc)
         self.save_into_mem(dest_addr, value_loc, fieldsize_loc)
 
+    genop_discard_setinteriorfield_raw = genop_discard_setinteriorfield_gc
+
     def genop_discard_setarrayitem_gc(self, op, arglocs):
         base_loc, ofs_loc, value_loc, size_loc, baseofs = arglocs
         assert isinstance(baseofs, ImmedLoc)
diff --git a/pypy/jit/backend/x86/regalloc.py b/pypy/jit/backend/x86/regalloc.py
--- a/pypy/jit/backend/x86/regalloc.py
+++ b/pypy/jit/backend/x86/regalloc.py
@@ -167,26 +167,22 @@
         operations = cpu.gc_ll_descr.rewrite_assembler(cpu, operations,
                                                        allgcrefs)
         # compute longevity of variables
-        longevity = self._compute_vars_longevity(inputargs, operations)
+        longevity, useful = self._compute_vars_longevity(inputargs, operations)
         self.longevity = longevity
         self.rm = gpr_reg_mgr_cls(longevity,
                                   frame_manager = self.fm,
                                   assembler = self.assembler)
         self.xrm = xmm_reg_mgr_cls(longevity, frame_manager = self.fm,
                                    assembler = self.assembler)
-        return operations
+        return operations, useful
 
     def prepare_loop(self, inputargs, operations, looptoken, allgcrefs):
-        operations = self._prepare(inputargs, operations, allgcrefs)
-        jump = operations[-1]
-        loop_consts = self._compute_loop_consts(inputargs, jump, looptoken)
-        self.loop_consts = loop_consts
-        return self._process_inputargs(inputargs), operations
+        operations, useful = self._prepare(inputargs, operations, allgcrefs)
+        return self._process_inputargs(inputargs, useful), operations
 
     def prepare_bridge(self, prev_depths, inputargs, arglocs, operations,
                        allgcrefs):
-        operations = self._prepare(inputargs, operations, allgcrefs)
-        self.loop_consts = {}
+        operations, _ = self._prepare(inputargs, operations, allgcrefs)
         self._update_bindings(arglocs, inputargs)
         self.fm.frame_depth = prev_depths[0]
         self.param_depth = prev_depths[1]
@@ -195,7 +191,7 @@
     def reserve_param(self, n):
         self.param_depth = max(self.param_depth, n)
 
-    def _process_inputargs(self, inputargs):
+    def _process_inputargs(self, inputargs, useful):
         # XXX we can sort out here by longevity if we need something
         # more optimal
         floatlocs = [None] * len(inputargs)
@@ -211,7 +207,7 @@
             arg = inputargs[i]
             assert not isinstance(arg, Const)
             reg = None
-            if arg not in self.loop_consts and self.longevity[arg][1] > -1:
+            if self.longevity[arg][1] > -1 and arg in useful:
                 if arg.type == FLOAT:
                     # xxx is it really a good idea?  at the first CALL they
                     # will all be flushed anyway
@@ -287,15 +283,15 @@
         else:
             return self.xrm.make_sure_var_in_reg(var, forbidden_vars)
 
-    def _compute_loop_consts(self, inputargs, jump, looptoken):
-        if jump.getopnum() != rop.JUMP or jump.getdescr() is not looptoken:
-            loop_consts = {}
-        else:
-            loop_consts = {}
-            for i in range(len(inputargs)):
-                if inputargs[i] is jump.getarg(i):
-                    loop_consts[inputargs[i]] = i
-        return loop_consts
+    #def _compute_loop_consts(self, inputargs, jump, looptoken):
+    #    if jump.getopnum() != rop.JUMP or jump.getdescr() is not looptoken:
+    #        loop_consts = {}
+    #    else:
+    #        loop_consts = {}
+    #        for i in range(len(inputargs)):
+    #            if inputargs[i] is jump.getarg(i):
+    #                loop_consts[inputargs[i]] = i
+    #    return loop_consts
 
     def _update_bindings(self, locs, inputargs):
         # XXX this should probably go to llsupport/regalloc.py
@@ -450,8 +446,14 @@
     def _compute_vars_longevity(self, inputargs, operations):
         # compute a dictionary that maps variables to index in
         # operations that is a "last-time-seen"
+
+        # returns a pair longevity/useful. Non-useful variables are ones that
+        # never appear in the assembler or it does not matter if they appear on
+        # stack or in registers. Main example is loop arguments that go
+        # only to guard operations or to jump or to finish
         produced = {}
         last_used = {}
+        useful = {}
         for i in range(len(operations)-1, -1, -1):
             op = operations[i]
             if op.result:
@@ -459,8 +461,11 @@
                     continue
                 assert op.result not in produced
                 produced[op.result] = i
+            opnum = op.getopnum()
             for j in range(op.numargs()):
                 arg = op.getarg(j)
+                if opnum != rop.JUMP and opnum != rop.FINISH:
+                    useful[arg] = None
                 if isinstance(arg, Box) and arg not in last_used:
                     last_used[arg] = i
             if op.is_guard():
@@ -486,7 +491,7 @@
                 longevity[arg] = (0, last_used[arg])
                 del last_used[arg]
         assert len(last_used) == 0
-        return longevity
+        return longevity, useful
 
     def loc(self, v):
         if v is None: # xxx kludgy
@@ -1067,6 +1072,8 @@
         self.PerformDiscard(op, [base_loc, ofs, itemsize, fieldsize,
                                  index_loc, temp_loc, value_loc])
 
+    consider_setinteriorfield_raw = consider_setinteriorfield_gc
+
     def consider_strsetitem(self, op):
         args = op.getarglist()
         base_loc = self.rm.make_sure_var_in_reg(op.getarg(0), args)
@@ -1143,9 +1150,22 @@
         # 'index' but must be in a different register than 'base'.
         self.rm.possibly_free_var(op.getarg(1))
         result_loc = self.force_allocate_reg(op.result, [op.getarg(0)])
+        assert isinstance(result_loc, RegLoc)
+        # two cases: 1) if result_loc is a normal register, use it as temp_loc
+        if not result_loc.is_xmm:
+            temp_loc = result_loc
+        else:
+            # 2) if result_loc is an xmm register, we (likely) need another
+            # temp_loc that is a normal register.  It can be in the same
+            # register as 'index' but not 'base'.
+            tempvar = TempBox()
+            temp_loc = self.rm.force_allocate_reg(tempvar, [op.getarg(0)])
+            self.rm.possibly_free_var(tempvar)
         self.rm.possibly_free_var(op.getarg(0))
         self.Perform(op, [base_loc, ofs, itemsize, fieldsize,
-                          index_loc, sign_loc], result_loc)
+                          index_loc, temp_loc, sign_loc], result_loc)
+
+    consider_getinteriorfield_raw = consider_getinteriorfield_gc
 
     def consider_int_is_true(self, op, guard_op):
         # doesn't need arg to be in a register
@@ -1419,8 +1439,11 @@
     # i.e. the n'th word beyond the fixed frame size.
     return -WORD * (FRAME_FIXED_SIZE + position)
 
+def _valid_addressing_size(size):
+    return size == 1 or size == 2 or size == 4 or size == 8
+
 def _get_scale(size):
-    assert size == 1 or size == 2 or size == 4 or size == 8
+    assert _valid_addressing_size(size)
     if size < 4:
         return size - 1         # 1, 2 => 0, 1
     else:
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
@@ -17,7 +17,7 @@
 
 class AssemblerLocation(object):
     # XXX: Is adding "width" here correct?
-    __slots__ = ('value', 'width')
+    _attrs_ = ('value', 'width', '_location_code')
     _immutable_ = True
     def _getregkey(self):
         return self.value
@@ -25,6 +25,9 @@
     def is_memory_reference(self):
         return self.location_code() in ('b', 's', 'j', 'a', 'm')
 
+    def location_code(self):
+        return self._location_code
+
     def value_r(self): return self.value
     def value_b(self): return self.value
     def value_s(self): return self.value
@@ -38,6 +41,8 @@
 
 class StackLoc(AssemblerLocation):
     _immutable_ = True
+    _location_code = 'b'
+
     def __init__(self, position, ebp_offset, num_words, type):
         assert ebp_offset < 0   # so no confusion with RegLoc.value
         self.position = position
@@ -49,9 +54,6 @@
     def __repr__(self):
         return '%d(%%ebp)' % (self.value,)
 
-    def location_code(self):
-        return 'b'
-
     def assembler(self):
         return repr(self)
 
@@ -63,8 +65,10 @@
         self.is_xmm = is_xmm
         if self.is_xmm:
             self.width = 8
+            self._location_code = 'x'
         else:
             self.width = WORD
+            self._location_code = 'r'
     def __repr__(self):
         if self.is_xmm:
             return rx86.R.xmmnames[self.value]
@@ -79,12 +83,6 @@
         assert not self.is_xmm
         return RegLoc(rx86.high_byte(self.value), False)
 
-    def location_code(self):
-        if self.is_xmm:
-            return 'x'
-        else:
-            return 'r'
-
     def assembler(self):
         return '%' + repr(self)
 
@@ -97,14 +95,13 @@
 class ImmedLoc(AssemblerLocation):
     _immutable_ = True
     width = WORD
+    _location_code = 'i'
+
     def __init__(self, value):
         from pypy.rpython.lltypesystem import rffi, lltype
         # force as a real int
         self.value = rffi.cast(lltype.Signed, value)
 
-    def location_code(self):
-        return 'i'
-
     def getint(self):
         return self.value
 
@@ -149,9 +146,6 @@
         info = getattr(self, attr, '?')
         return '<AddressLoc %r: %s>' % (self._location_code, info)
 
-    def location_code(self):
-        return self._location_code
-
     def value_a(self):
         return self.loc_a
 
@@ -191,6 +185,7 @@
     # we want a width of 8  (... I think.  Check this!)
     _immutable_ = True
     width = 8
+    _location_code = 'j'
 
     def __init__(self, address):
         self.value = address
@@ -198,9 +193,6 @@
     def __repr__(self):
         return '<ConstFloatLoc @%s>' % (self.value,)
 
-    def location_code(self):
-        return 'j'
-
 if IS_X86_32:
     class FloatImmedLoc(AssemblerLocation):
         # This stands for an immediate float.  It cannot be directly used in
@@ -209,6 +201,7 @@
         # instead; see below.
         _immutable_ = True
         width = 8
+        _location_code = '#'     # don't use me
 
         def __init__(self, floatstorage):
             self.aslonglong = floatstorage
@@ -229,9 +222,6 @@
             floatvalue = longlong.getrealfloat(self.aslonglong)
             return '<FloatImmedLoc(%s)>' % (floatvalue,)
 
-        def location_code(self):
-            raise NotImplementedError
-
 if IS_X86_64:
     def FloatImmedLoc(floatstorage):
         from pypy.rlib.longlong2float import float2longlong
@@ -270,6 +260,11 @@
     else:
         raise AssertionError(methname + " undefined")
 
+def _missing_binary_insn(name, code1, code2):
+    raise AssertionError(name + "_" + code1 + code2 + " missing")
+_missing_binary_insn._dont_inline_ = True
+
+
 class LocationCodeBuilder(object):
     _mixin_ = True
 
@@ -303,6 +298,8 @@
             else:
                 # For this case, we should not need the scratch register more than here.
                 self._load_scratch(val2)
+                if name == 'MOV' and loc1 is X86_64_SCRATCH_REG:
+                    return     # don't need a dummy "MOV r11, r11"
                 INSN(self, loc1, X86_64_SCRATCH_REG)
 
         def invoke(self, codes, val1, val2):
@@ -310,6 +307,23 @@
             _rx86_getattr(self, methname)(val1, val2)
         invoke._annspecialcase_ = 'specialize:arg(1)'
 
+        def has_implementation_for(loc1, loc2):
+            # A memo function that returns True if there is any NAME_xy that could match.
+            # If it returns False we know the whole subcase can be omitted from translated
+            # code.  Without this hack, the size of most _binaryop INSN functions ends up
+            # quite large in C code.
+            if loc1 == '?':
+                return any([has_implementation_for(loc1, loc2)
+                            for loc1 in unrolling_location_codes])
+            methname = name + "_" + loc1 + loc2
+            if not hasattr(rx86.AbstractX86CodeBuilder, methname):
+                return False
+            # any NAME_j should have a NAME_m as a fallback, too.  Check it
+            if loc1 == 'j': assert has_implementation_for('m', loc2), methname
+            if loc2 == 'j': assert has_implementation_for(loc1, 'm'), methname
+            return True
+        has_implementation_for._annspecialcase_ = 'specialize:memo'
+
         def INSN(self, loc1, loc2):
             code1 = loc1.location_code()
             code2 = loc2.location_code()
@@ -325,6 +339,8 @@
                 assert code2 not in ('j', 'i')
 
             for possible_code2 in unrolling_location_codes:
+                if not has_implementation_for('?', possible_code2):
+                    continue
                 if code2 == possible_code2:
                     val2 = getattr(loc2, "value_" + possible_code2)()
                     #
@@ -335,28 +351,32 @@
                     #
                     # Regular case
                     for possible_code1 in unrolling_location_codes:
+                        if not has_implementation_for(possible_code1,
+                                                      possible_code2):
+                            continue
                         if code1 == possible_code1:
                             val1 = getattr(loc1, "value_" + possible_code1)()
                             # More faking out of certain operations for x86_64
-                            if possible_code1 == 'j' and not rx86.fits_in_32bits(val1):
+                            fits32 = rx86.fits_in_32bits
+                            if possible_code1 == 'j' and not fits32(val1):
                                 val1 = self._addr_as_reg_offset(val1)
                                 invoke(self, "m" + possible_code2, val1, val2)
-                            elif possible_code2 == 'j' and not rx86.fits_in_32bits(val2):
+                                return
+                            if possible_code2 == 'j' and not fits32(val2):
                                 val2 = self._addr_as_reg_offset(val2)
                                 invoke(self, possible_code1 + "m", val1, val2)
-                            elif possible_code1 == 'm' and not rx86.fits_in_32bits(val1[1]):
+                                return
+                            if possible_code1 == 'm' and not fits32(val1[1]):
                                 val1 = self._fix_static_offset_64_m(val1)
-                                invoke(self, "a" + possible_code2, val1, val2)
-                            elif possible_code2 == 'm' and not rx86.fits_in_32bits(val2[1]):
+                            if possible_code2 == 'm' and not fits32(val2[1]):
                                 val2 = self._fix_static_offset_64_m(val2)
-                                invoke(self, possible_code1 + "a", val1, val2)
-                            else:
-                                if possible_code1 == 'a' and not rx86.fits_in_32bits(val1[3]):
-                                    val1 = self._fix_static_offset_64_a(val1)
-                                if possible_code2 == 'a' and not rx86.fits_in_32bits(val2[3]):
-                                    val2 = self._fix_static_offset_64_a(val2)
-                                invoke(self, possible_code1 + possible_code2, val1, val2)
+                            if possible_code1 == 'a' and not fits32(val1[3]):
+                                val1 = self._fix_static_offset_64_a(val1)
+                            if possible_code2 == 'a' and not fits32(val2[3]):
+                                val2 = self._fix_static_offset_64_a(val2)
+                            invoke(self, possible_code1 + possible_code2, val1, val2)
                             return
+            _missing_binary_insn(name, code1, code2)
 
         return func_with_new_name(INSN, "INSN_" + name)
 
@@ -431,12 +451,14 @@
     def _fix_static_offset_64_m(self, (basereg, static_offset)):
         # For cases where an AddressLoc has the location_code 'm', but
         # where the static offset does not fit in 32-bits.  We have to fall
-        # back to the X86_64_SCRATCH_REG.  Note that this returns a location
-        # encoded as mode 'a'.  These are all possibly rare cases; don't try
+        # back to the X86_64_SCRATCH_REG.  Returns a new location encoded
+        # as mode 'm' too.  These are all possibly rare cases; don't try
         # to reuse a past value of the scratch register at all.
         self._scratch_register_known = False
         self.MOV_ri(X86_64_SCRATCH_REG.value, static_offset)
-        return (basereg, X86_64_SCRATCH_REG.value, 0, 0)
+        self.LEA_ra(X86_64_SCRATCH_REG.value,
+                    (basereg, X86_64_SCRATCH_REG.value, 0, 0))
+        return (X86_64_SCRATCH_REG.value, 0)
 
     def _fix_static_offset_64_a(self, (basereg, scalereg,
                                        scale, static_offset)):
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
@@ -745,6 +745,7 @@
     assert insnname_template.count('*') == 1
     add_insn('x', register(2), '\xC0')
     add_insn('j', abs_, immediate(2))
+    add_insn('m', mem_reg_plus_const(2))
 
 define_pxmm_insn('PADDQ_x*',     '\xD4')
 define_pxmm_insn('PSUBQ_x*',     '\xFB')
diff --git a/pypy/jit/backend/x86/test/test_fficall.py b/pypy/jit/backend/x86/test/test_fficall.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/backend/x86/test/test_fficall.py
@@ -0,0 +1,8 @@
+import py
+from pypy.jit.metainterp.test import test_fficall
+from pypy.jit.backend.x86.test.test_basic import Jit386Mixin
+
+class TestFfiLookups(Jit386Mixin, test_fficall.FfiLookupTests):
+    # for the individual tests see
+    # ====> ../../../metainterp/test/test_fficall.py
+    supports_all = True
diff --git a/pypy/jit/backend/x86/test/test_regalloc.py b/pypy/jit/backend/x86/test/test_regalloc.py
--- a/pypy/jit/backend/x86/test/test_regalloc.py
+++ b/pypy/jit/backend/x86/test/test_regalloc.py
@@ -149,6 +149,13 @@
             self.cpu.execute_token(loop.token)
         return loop
 
+    def prepare_loop(self, ops):
+        loop = self.parse(ops)
+        regalloc = RegAlloc(self.cpu.assembler, False)
+        regalloc.prepare_loop(loop.inputargs, loop.operations,
+                              loop.token, [])
+        return regalloc
+
     def getint(self, index):
         return self.cpu.get_latest_value_int(index)
 
@@ -422,6 +429,35 @@
         self.run(loop)
         assert self.getints(9) == range(9)
 
+    def test_loopargs(self):
+        ops = """
+        [i0, i1, i2, i3]
+        i4 = int_add(i0, i1)
+        jump(i4, i1, i2, i3)
+        """
+        regalloc = self.prepare_loop(ops)
+        assert len(regalloc.rm.reg_bindings) == 2
+
+    def test_loopargs_2(self):
+        ops = """
+        [i0, i1, i2, i3]
+        i4 = int_add(i0, i1)
+        finish(i4, i1, i2, i3)
+        """
+        regalloc = self.prepare_loop(ops)
+        assert len(regalloc.rm.reg_bindings) == 2
+
+    def test_loopargs_3(self):
+        ops = """
+        [i0, i1, i2, i3]
+        i4 = int_add(i0, i1)
+        guard_true(i4) [i0, i1, i2, i3, i4]
+        jump(i4, i1, i2, i3)
+        """
+        regalloc = self.prepare_loop(ops)
+        assert len(regalloc.rm.reg_bindings) == 2
+    
+
 class TestRegallocCompOps(BaseTestRegalloc):
     
     def test_cmp_op_0(self):
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
@@ -146,8 +146,10 @@
         expected_instructions = (
                 # mov r11, 0xFEDCBA9876543210
                 '\x49\xBB\x10\x32\x54\x76\x98\xBA\xDC\xFE'
-                # mov rcx, [rdx+r11]
-                '\x4A\x8B\x0C\x1A'
+                # lea r11, [rdx+r11]
+                '\x4E\x8D\x1C\x1A'
+                # mov rcx, [r11]
+                '\x49\x8B\x0B'
         )
         assert cb.getvalue() == expected_instructions
 
@@ -174,6 +176,30 @@
 
     # ------------------------------------------------------------
 
+    def test_MOV_64bit_constant_into_r11(self):
+        base_constant = 0xFEDCBA9876543210
+        cb = LocationCodeBuilder64()
+        cb.MOV(r11, imm(base_constant))
+
+        expected_instructions = (
+                # mov r11, 0xFEDCBA9876543210
+                '\x49\xBB\x10\x32\x54\x76\x98\xBA\xDC\xFE'
+        )
+        assert cb.getvalue() == expected_instructions
+
+    def test_MOV_64bit_address_into_r11(self):
+        base_addr = 0xFEDCBA9876543210
+        cb = LocationCodeBuilder64()
+        cb.MOV(r11, heap(base_addr))
+
+        expected_instructions = (
+                # mov r11, 0xFEDCBA9876543210
+                '\x49\xBB\x10\x32\x54\x76\x98\xBA\xDC\xFE' +
+                # mov r11, [r11]
+                '\x4D\x8B\x1B'
+        )
+        assert cb.getvalue() == expected_instructions
+
     def test_MOV_immed32_into_64bit_address_1(self):
         immed = -0x01234567
         base_addr = 0xFEDCBA9876543210
@@ -217,8 +243,10 @@
         expected_instructions = (
                 # mov r11, 0xFEDCBA9876543210
                 '\x49\xBB\x10\x32\x54\x76\x98\xBA\xDC\xFE'
-                # mov [rdx+r11], -0x01234567
-                '\x4A\xC7\x04\x1A\x99\xBA\xDC\xFE'
+                # lea r11, [rdx+r11]
+                '\x4E\x8D\x1C\x1A'
+                # mov [r11], -0x01234567
+                '\x49\xC7\x03\x99\xBA\xDC\xFE'
         )
         assert cb.getvalue() == expected_instructions
 
@@ -300,8 +328,10 @@
                 '\x48\xBA\xEF\xCD\xAB\x89\x67\x45\x23\x01'
                 # mov r11, 0xFEDCBA9876543210
                 '\x49\xBB\x10\x32\x54\x76\x98\xBA\xDC\xFE'
-                # mov [rax+r11], rdx
-                '\x4A\x89\x14\x18'
+                # lea r11, [rax+r11]
+                '\x4E\x8D\x1C\x18'
+                # mov [r11], rdx
+                '\x49\x89\x13'
                 # pop rdx
                 '\x5A'
         )
diff --git a/pypy/jit/backend/x86/test/test_runner.py b/pypy/jit/backend/x86/test/test_runner.py
--- a/pypy/jit/backend/x86/test/test_runner.py
+++ b/pypy/jit/backend/x86/test/test_runner.py
@@ -455,6 +455,9 @@
                                                 EffectInfo.MOST_GENERAL,
                                                 ffi_flags=-1)
             calldescr.get_call_conv = lambda: ffi      # <==== hack
+            # ^^^ we patch get_call_conv() so that the test also makes sense
+            #     on Linux, because clibffi.get_call_conv() would always
+            #     return FFI_DEFAULT_ABI on non-Windows platforms.
             funcbox = ConstInt(rawstart)
             i1 = BoxInt()
             i2 = BoxInt()
diff --git a/pypy/jit/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
@@ -457,6 +457,46 @@
     def test_compile_framework_7(self):
         self.run('compile_framework_7')
 
+    def define_compile_framework_7_interior(cls):
+        # Array of structs containing pointers (test the write barrier
+        # for setinteriorfield_gc)
+        S = lltype.GcStruct('S', ('i', lltype.Signed))
+        A = lltype.GcArray(lltype.Struct('entry', ('x', lltype.Ptr(S)),
+                                                  ('y', lltype.Ptr(S)),
+                                                  ('z', lltype.Ptr(S))))
+        class Glob:
+            a = lltype.nullptr(A)
+        glob = Glob()
+        #
+        def make_s(i):
+            s = lltype.malloc(S)
+            s.i = i
+            return s
+        #
+        @unroll_safe
+        def f(n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s):
+            a = glob.a
+            if not a:
+                a = glob.a = lltype.malloc(A, 10)
+            i = 0
+            while i < 10:
+                a[i].x = make_s(n + i * 100 + 1)
+                a[i].y = make_s(n + i * 100 + 2)
+                a[i].z = make_s(n + i * 100 + 3)
+                i += 1
+            i = 0
+            while i < 10:
+                check(a[i].x.i == n + i * 100 + 1)
+                check(a[i].y.i == n + i * 100 + 2)
+                check(a[i].z.i == n + i * 100 + 3)
+                i += 1
+            n -= x.foo
+            return n, x, x0, x1, x2, x3, x4, x5, x6, x7, l, s
+        return None, f, None
+
+    def test_compile_framework_7_interior(self):
+        self.run('compile_framework_7_interior')
+
     def define_compile_framework_8(cls):
         # Array of pointers, of unknown length (test write_barrier_from_array)
         def before(n, x):
diff --git a/pypy/jit/backend/x86/test/test_ztranslation.py b/pypy/jit/backend/x86/test/test_ztranslation.py
--- a/pypy/jit/backend/x86/test/test_ztranslation.py
+++ b/pypy/jit/backend/x86/test/test_ztranslation.py
@@ -1,6 +1,6 @@
 import py, os, sys
 from pypy.tool.udir import udir
-from pypy.rlib.jit import JitDriver, unroll_parameters
+from pypy.rlib.jit import JitDriver, unroll_parameters, set_param
 from pypy.rlib.jit import PARAMETERS, dont_look_inside
 from pypy.rlib.jit import promote
 from pypy.jit.metainterp.jitprof import Profiler
@@ -47,9 +47,9 @@
         def f(i, j):
             for param, _ in unroll_parameters:
                 defl = PARAMETERS[param]
-                jitdriver.set_param(param, defl)
-            jitdriver.set_param("threshold", 3)
-            jitdriver.set_param("trace_eagerness", 2)
+                set_param(jitdriver, param, defl)
+            set_param(jitdriver, "threshold", 3)
+            set_param(jitdriver, "trace_eagerness", 2)
             total = 0
             frame = Frame(i)
             while frame.i > 3:
@@ -213,8 +213,8 @@
             else:
                 return Base()
         def myportal(i):
-            jitdriver.set_param("threshold", 3)
-            jitdriver.set_param("trace_eagerness", 2)
+            set_param(jitdriver, "threshold", 3)
+            set_param(jitdriver, "trace_eagerness", 2)
             total = 0
             n = i
             while True:
diff --git a/pypy/jit/backend/x86/tool/viewcode.py b/pypy/jit/backend/x86/tool/viewcode.py
--- a/pypy/jit/backend/x86/tool/viewcode.py
+++ b/pypy/jit/backend/x86/tool/viewcode.py
@@ -58,7 +58,7 @@
     assert not p.returncode, ('Encountered an error running objdump: %s' %
                               stderr)
     # drop some objdump cruft
-    lines = stdout.splitlines()[6:]
+    lines = stdout.splitlines(True)[6:]     # drop some objdump cruft
     return format_code_dump_with_labels(originaddr, lines, label_list)
 
 def format_code_dump_with_labels(originaddr, lines, label_list):
@@ -97,7 +97,7 @@
     stdout, stderr = p.communicate()
     assert not p.returncode, ('Encountered an error running nm: %s' %
                               stderr)
-    for line in stdout.splitlines():
+    for line in stdout.splitlines(True):
         match = re_symbolentry.match(line)
         if match:
             addr = long(match.group(1), 16)
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
@@ -212,7 +212,10 @@
         elidable = False
         loopinvariant = False
         if op.opname == "direct_call":
-            func = getattr(get_funcobj(op.args[0].value), '_callable', None)
+            funcobj = get_funcobj(op.args[0].value)
+            assert getattr(funcobj, 'calling_conv', 'c') == 'c', (
+                "%r: getcalldescr() with a non-default call ABI" % (op,))
+            func = getattr(funcobj, '_callable', None)
             elidable = getattr(func, "_elidable_function_", False)
             loopinvariant = getattr(func, "_jit_loop_invariant_", False)
             if loopinvariant:
diff --git a/pypy/jit/codewriter/codewriter.py b/pypy/jit/codewriter/codewriter.py
--- a/pypy/jit/codewriter/codewriter.py
+++ b/pypy/jit/codewriter/codewriter.py
@@ -104,6 +104,8 @@
         else:
             name = 'unnamed' % id(ssarepr)
         i = 1
+        # escape <lambda> names for windows
+        name = name.replace('<lambda>', '_(lambda)_')
         extra = ''
         while name+extra in self._seen_files:
             i += 1
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
@@ -48,6 +48,8 @@
     OS_LIBFFI_PREPARE           = 60
     OS_LIBFFI_PUSH_ARG          = 61
     OS_LIBFFI_CALL              = 62
+    OS_LIBFFI_GETARRAYITEM      = 63
+    OS_LIBFFI_SETARRAYITEM      = 64
     #
     OS_LLONG_INVERT             = 69
     OS_LLONG_ADD                = 70
@@ -78,6 +80,9 @@
     #
     OS_MATH_SQRT                = 100
 
+    # for debugging:
+    _OS_CANRAISE = set([OS_NONE, OS_STR2UNICODE, OS_LIBFFI_CALL])
+
     def __new__(cls, readonly_descrs_fields, readonly_descrs_arrays,
                 write_descrs_fields, write_descrs_arrays,
                 extraeffect=EF_CAN_RAISE,
@@ -116,6 +121,8 @@
         result.extraeffect = extraeffect
         result.can_invalidate = can_invalidate
         result.oopspecindex = oopspecindex
+        if result.check_can_raise():
+            assert oopspecindex in cls._OS_CANRAISE
         cls._cache[key] = result
         return result
 
@@ -125,6 +132,10 @@
     def check_can_invalidate(self):
         return self.can_invalidate
 
+    def check_is_elidable(self):
+        return (self.extraeffect == self.EF_ELIDABLE_CAN_RAISE or
+                self.extraeffect == self.EF_ELIDABLE_CANNOT_RAISE)
+
     def check_forces_virtual_or_virtualizable(self):
         return self.extraeffect >= self.EF_FORCES_VIRTUAL_OR_VIRTUALIZABLE
 
@@ -230,12 +241,15 @@
         return op.opname == 'jit_force_quasi_immutable'
 
 class RandomEffectsAnalyzer(BoolGraphAnalyzer):
-    def analyze_direct_call(self, graph, seen=None):
-        if hasattr(graph, "func") and hasattr(graph.func, "_ptr"):
-            if graph.func._ptr._obj.random_effects_on_gcobjs:
+    def analyze_external_call(self, op, seen=None):
+        try:
+            funcobj = op.args[0].value._obj
+            if funcobj.random_effects_on_gcobjs:
                 return True
-        return super(RandomEffectsAnalyzer, self).analyze_direct_call(graph,
-                                                                      seen)
+        except (AttributeError, lltype.DelayedPointer):
+            return True   # better safe than sorry
+        return super(RandomEffectsAnalyzer, self).analyze_external_call(
+            op, seen)
 
     def analyze_simple_operation(self, op, graphinfo):
         return False
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
@@ -15,6 +15,8 @@
 from pypy.translator.simplify import get_funcobj
 from pypy.translator.unsimplify import varoftype
 
+class UnsupportedMallocFlags(Exception):
+    pass
 
 def transform_graph(graph, cpu=None, callcontrol=None, portal_jd=None):
     """Transform a control flow graph to make it suitable for
@@ -205,7 +207,24 @@
         if op.args[0] in self.vable_array_vars:
             self.vable_array_vars[op.result]= self.vable_array_vars[op.args[0]]
 
-    rewrite_op_cast_pointer = rewrite_op_same_as
+    def rewrite_op_cast_pointer(self, op):
+        newop = self.rewrite_op_same_as(op)
+        assert newop is None
+        return
+        # disabled for now
+        if (self._is_rclass_instance(op.args[0]) and
+                self._is_rclass_instance(op.result)):
+            FROM = op.args[0].concretetype.TO
+            TO = op.result.concretetype.TO
+            if lltype._castdepth(TO, FROM) > 0:
+                vtable = heaptracker.get_vtable_for_gcstruct(self.cpu, TO)
+                const_vtable = Constant(vtable, lltype.typeOf(vtable))
+                return [None, # hack, do the right renaming from op.args[0] to op.result
+                        SpaceOperation("record_known_class", [op.args[0], const_vtable], None)]
+
+    def rewrite_op_jit_record_known_class(self, op):
+        return SpaceOperation("record_known_class", [op.args[0], op.args[1]], None)
+
     def rewrite_op_cast_bool_to_int(self, op): pass
     def rewrite_op_cast_bool_to_uint(self, op): pass
     def rewrite_op_cast_char_to_int(self, op): pass
@@ -481,8 +500,22 @@
 
     def rewrite_op_malloc_varsize(self, op):
         if op.args[1].value['flavor'] == 'raw':
+            d = op.args[1].value.copy()
+            d.pop('flavor')
+            add_memory_pressure = d.pop('add_memory_pressure', False)
+            zero = d.pop('zero', False)
+            track_allocation = d.pop('track_allocation', True)
+            if d:
+                raise UnsupportedMallocFlags(d)
             ARRAY = op.args[0].value
-            return self._do_builtin_call(op, 'raw_malloc',
+            name = 'raw_malloc'
+            if zero:
+                name += '_zero'
+            if add_memory_pressure:
+                name += '_add_memory_pressure'
+            if not track_allocation:
+                name += '_no_track_allocation'
+            return self._do_builtin_call(op, name,
                                          [op.args[2]],
                                          extra = (ARRAY,),
                                          extrakey = ARRAY)
@@ -1053,35 +1086,20 @@
     # jit.codewriter.support.
 
     for _op, _oopspec in [('llong_invert',  'INVERT'),
-                          ('ullong_invert', 'INVERT'),
                           ('llong_lt',      'LT'),
                           ('llong_le',      'LE'),
                           ('llong_eq',      'EQ'),
                           ('llong_ne',      'NE'),
                           ('llong_gt',      'GT'),
                           ('llong_ge',      'GE'),
-                          ('ullong_lt',     'ULT'),
-                          ('ullong_le',     'ULE'),
-                          ('ullong_eq',     'EQ'),
-                          ('ullong_ne',     'NE'),
-                          ('ullong_gt',     'UGT'),
-                          ('ullong_ge',     'UGE'),
                           ('llong_add',     'ADD'),
                           ('llong_sub',     'SUB'),
                           ('llong_mul',     'MUL'),
                           ('llong_and',     'AND'),
                           ('llong_or',      'OR'),
                           ('llong_xor',     'XOR'),
-                          ('ullong_add',    'ADD'),
-                          ('ullong_sub',    'SUB'),
-                          ('ullong_mul',    'MUL'),
-                          ('ullong_and',    'AND'),
-                          ('ullong_or',     'OR'),
-                          ('ullong_xor',    'XOR'),
                           ('llong_lshift',  'LSHIFT'),
                           ('llong_rshift',  'RSHIFT'),
-                          ('ullong_lshift', 'LSHIFT'),
-                          ('ullong_rshift', 'URSHIFT'),
                           ('cast_int_to_longlong',     'FROM_INT'),
                           ('truncate_longlong_to_int', 'TO_INT'),
                           ('cast_float_to_longlong',   'FROM_FLOAT'),
@@ -1104,6 +1122,21 @@
                           ('cast_uint_to_ulonglong',    'FROM_UINT'),
                           ('cast_float_to_ulonglong',   'FROM_FLOAT'),
                           ('cast_ulonglong_to_float',   'U_TO_FLOAT'),
+                          ('ullong_invert', 'INVERT'),
+                          ('ullong_lt',     'ULT'),
+                          ('ullong_le',     'ULE'),
+                          ('ullong_eq',     'EQ'),
+                          ('ullong_ne',     'NE'),
+                          ('ullong_gt',     'UGT'),
+                          ('ullong_ge',     'UGE'),
+                          ('ullong_add',    'ADD'),
+                          ('ullong_sub',    'SUB'),
+                          ('ullong_mul',    'MUL'),
+                          ('ullong_and',    'AND'),
+                          ('ullong_or',     'OR'),
+                          ('ullong_xor',    'XOR'),
+                          ('ullong_lshift', 'LSHIFT'),
+                          ('ullong_rshift', 'URSHIFT'),
                          ]:
         exec py.code.Source('''
             def rewrite_op_%s(self, op):
@@ -1134,7 +1167,7 @@
 
     def rewrite_op_llong_is_true(self, op):
         v = varoftype(op.args[0].concretetype)
-        op0 = SpaceOperation('cast_int_to_longlong',
+        op0 = SpaceOperation('cast_primitive',
                              [Constant(0, lltype.Signed)],
                              v)
         args = [op.args[0], v]
@@ -1615,6 +1648,12 @@
         elif oopspec_name.startswith('libffi_call_'):
             oopspecindex = EffectInfo.OS_LIBFFI_CALL
             extraeffect = EffectInfo.EF_RANDOM_EFFECTS
+        elif oopspec_name == 'libffi_array_getitem':
+            oopspecindex = EffectInfo.OS_LIBFFI_GETARRAYITEM
+            extraeffect = EffectInfo.EF_CANNOT_RAISE
+        elif oopspec_name == 'libffi_array_setitem':
+            oopspecindex = EffectInfo.OS_LIBFFI_SETARRAYITEM
+            extraeffect = EffectInfo.EF_CANNOT_RAISE
         else:
             assert False, 'unsupported oopspec: %s' % oopspec_name
         return self._handle_oopspec_call(op, args, oopspecindex, extraeffect)
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
@@ -37,9 +37,11 @@
     return a.typeannotation(t)
 
 def annotate(func, values, inline=None, backendoptimize=True,
-             type_system="lltype"):
+             type_system="lltype", translationoptions={}):
     # build the normal ll graphs for ll_function
     t = TranslationContext()
+    for key, value in translationoptions.items():
+        setattr(t.config.translation, key, value)
     annpolicy = AnnotatorPolicy()
     annpolicy.allow_someobjects = False
     a = t.buildannotator(policy=annpolicy)
@@ -256,6 +258,9 @@
     y = ~r_ulonglong(xll)
     return u_to_longlong(y)
 
+def _ll_1_ullong_invert(xull):
+    return ~xull
+
 def _ll_2_llong_lt(xll, yll):
     return xll < yll
 
@@ -274,16 +279,22 @@
 def _ll_2_llong_ge(xll, yll):
     return xll >= yll
 
-def _ll_2_llong_ult(xull, yull):
+def _ll_2_ullong_eq(xull, yull):
+    return xull == yull
+
+def _ll_2_ullong_ne(xull, yull):
+    return xull != yull
+
+def _ll_2_ullong_ult(xull, yull):
     return xull < yull
 
-def _ll_2_llong_ule(xull, yull):
+def _ll_2_ullong_ule(xull, yull):
     return xull <= yull
 
-def _ll_2_llong_ugt(xull, yull):
+def _ll_2_ullong_ugt(xull, yull):
     return xull > yull
 
-def _ll_2_llong_uge(xull, yull):
+def _ll_2_ullong_uge(xull, yull):
     return xull >= yull
 
 def _ll_2_llong_add(xll, yll):
@@ -310,14 +321,41 @@
     z = r_ulonglong(xll) ^ r_ulonglong(yll)
     return u_to_longlong(z)
 
+def _ll_2_ullong_add(xull, yull):
+    z = (xull) + (yull)
+    return (z)
+
+def _ll_2_ullong_sub(xull, yull):
+    z = (xull) - (yull)
+    return (z)
+
+def _ll_2_ullong_mul(xull, yull):
+    z = (xull) * (yull)
+    return (z)
+
+def _ll_2_ullong_and(xull, yull):
+    z = (xull) & (yull)
+    return (z)
+
+def _ll_2_ullong_or(xull, yull):
+    z = (xull) | (yull)
+    return (z)
+
+def _ll_2_ullong_xor(xull, yull):
+    z = (xull) ^ (yull)
+    return (z)
+
 def _ll_2_llong_lshift(xll, y):
     z = r_ulonglong(xll) << y
     return u_to_longlong(z)
 
+def _ll_2_ullong_lshift(xull, y):
+    return xull << y
+
 def _ll_2_llong_rshift(xll, y):
     return xll >> y
 
-def _ll_2_llong_urshift(xull, y):
+def _ll_2_ullong_urshift(xull, y):
     return xull >> y
 
 def _ll_1_llong_from_int(x):
@@ -561,10 +599,21 @@
             return p
         return _ll_0_alloc_with_del
 
-    def build_ll_1_raw_malloc(ARRAY):
-        def _ll_1_raw_malloc(n):
-            return lltype.malloc(ARRAY, n, flavor='raw')
-        return _ll_1_raw_malloc
+    def build_raw_malloc_builder(zero=False, add_memory_pressure=False, track_allocation=True):
+        def build_ll_1_raw_malloc(ARRAY):
+            def _ll_1_raw_malloc(n):
+                return lltype.malloc(ARRAY, n, flavor='raw', zero=zero, add_memory_pressure=add_memory_pressure)
+            return _ll_1_raw_malloc
+        return build_ll_1_raw_malloc
+
+    build_ll_1_raw_malloc = build_raw_malloc_builder()
+    build_ll_1_raw_malloc_zero = build_raw_malloc_builder(zero=True)
+    build_ll_1_raw_malloc_zero_add_memory_pressure = build_raw_malloc_builder(zero=True, add_memory_pressure=True)
+    build_ll_1_raw_malloc_add_memory_pressure = build_raw_malloc_builder(add_memory_pressure=True)
+    build_ll_1_raw_malloc_no_track_allocation = build_raw_malloc_builder(track_allocation=False)
+    build_ll_1_raw_malloc_zero_no_track_allocation = build_raw_malloc_builder(zero=True, track_allocation=False)
+    build_ll_1_raw_malloc_zero_add_memory_pressure_no_track_allocation = build_raw_malloc_builder(zero=True, add_memory_pressure=True, track_allocation=False)
+    build_ll_1_raw_malloc_add_memory_pressure_no_track_allocation = build_raw_malloc_builder(add_memory_pressure=True, track_allocation=False)
 
     def build_ll_1_raw_free(ARRAY):
         def _ll_1_raw_free(p):
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
@@ -192,3 +192,21 @@
     [op] = block.operations
     call_descr = cc.getcalldescr(op)
     assert call_descr.extrainfo.has_random_effects()
+
+def test_random_effects_on_stacklet_switch():
+    from pypy.jit.backend.llgraph.runner import LLtypeCPU
+    from pypy.rlib._rffi_stacklet import switch, thread_handle, handle
+    @jit.dont_look_inside
+    def f():
+        switch(rffi.cast(thread_handle, 0), rffi.cast(handle, 0))
+
+    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[-1]
+    call_descr = cc.getcalldescr(op)
+    assert call_descr.extrainfo.has_random_effects()
diff --git a/pypy/jit/codewriter/test/test_flatten.py b/pypy/jit/codewriter/test/test_flatten.py
--- a/pypy/jit/codewriter/test/test_flatten.py
+++ b/pypy/jit/codewriter/test/test_flatten.py
@@ -5,7 +5,7 @@
 from pypy.jit.codewriter.format import assert_format
 from pypy.jit.codewriter import longlong
 from pypy.jit.metainterp.history import AbstractDescr
-from pypy.rpython.lltypesystem import lltype, rclass, rstr
+from pypy.rpython.lltypesystem import lltype, rclass, rstr, rffi
 from pypy.objspace.flow.model import SpaceOperation, Variable, Constant
 from pypy.translator.unsimplify import varoftype
 from pypy.rlib.rarithmetic import ovfcheck, r_uint, r_longlong, r_ulonglong
@@ -743,7 +743,6 @@
         """, transform=True)
 
     def test_force_cast(self):
-        from pypy.rpython.lltypesystem import rffi
         # NB: we don't need to test for INT here, the logic in jtransform is
         # general enough so that if we have the below cases it should
         # generalize also to INT
@@ -849,7 +848,6 @@
                                        transform=True)
 
     def test_force_cast_pointer(self):
-        from pypy.rpython.lltypesystem import rffi
         def h(p):
             return rffi.cast(rffi.VOIDP, p)
         self.encoding_test(h, [lltype.nullptr(rffi.CCHARP.TO)], """
@@ -857,7 +855,6 @@
         """, transform=True)
 
     def test_force_cast_floats(self):
-        from pypy.rpython.lltypesystem import rffi
         # Caststs to lltype.Float
         def f(n):
             return rffi.cast(lltype.Float, n)
@@ -964,7 +961,6 @@
             """, transform=True)
 
     def test_direct_ptradd(self):
-        from pypy.rpython.lltypesystem import rffi
         def f(p, n):
             return lltype.direct_ptradd(p, n)
         self.encoding_test(f, [lltype.nullptr(rffi.CCHARP.TO), 123], """
@@ -975,7 +971,6 @@
 
 def check_force_cast(FROM, TO, operations, value):
     """Check that the test is correctly written..."""
-    from pypy.rpython.lltypesystem import rffi
     import re
     r = re.compile('(\w+) \%i\d, \$(-?\d+)')
     #
diff --git a/pypy/jit/codewriter/test/test_jtransform.py b/pypy/jit/codewriter/test/test_jtransform.py
--- a/pypy/jit/codewriter/test/test_jtransform.py
+++ b/pypy/jit/codewriter/test/test_jtransform.py
@@ -1,3 +1,5 @@
+
+import py
 import random
 try:
     from itertools import product
@@ -15,12 +17,12 @@
 
 from pypy.objspace.flow.model import FunctionGraph, Block, Link
 from pypy.objspace.flow.model import SpaceOperation, Variable, Constant
-from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr
+from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr, rffi
 from pypy.rpython.lltypesystem.module import ll_math
 from pypy.translator.unsimplify import varoftype
 from pypy.jit.codewriter import heaptracker, effectinfo
 from pypy.jit.codewriter.flatten import ListOfKind
-from pypy.jit.codewriter.jtransform import Transformer
+from pypy.jit.codewriter.jtransform import Transformer, UnsupportedMallocFlags
 from pypy.jit.metainterp.history import getkind
 
 def const(x):
@@ -538,6 +540,44 @@
     assert op1.opname == '-live-'
     assert op1.args == []
 
+def test_raw_malloc():
+    S = rffi.CArray(lltype.Signed)
+    v1 = varoftype(lltype.Signed)
+    v = varoftype(lltype.Ptr(S))
+    flags = Constant({'flavor': 'raw'}, lltype.Void)
+    op = SpaceOperation('malloc_varsize', [Constant(S, lltype.Void), flags,
+                                           v1], v)
+    tr = Transformer(FakeCPU(), FakeResidualCallControl())
+    op0, op1 = tr.rewrite_operation(op)
+    assert op0.opname == 'residual_call_ir_i'
+    assert op0.args[0].value == 'raw_malloc'    # pseudo-function as a str
+    assert op1.opname == '-live-'
+    assert op1.args == []
+
+def test_raw_malloc_zero():
+    S = rffi.CArray(lltype.Signed)
+    v1 = varoftype(lltype.Signed)
+    v = varoftype(lltype.Ptr(S))
+    flags = Constant({'flavor': 'raw', 'zero': True}, lltype.Void)
+    op = SpaceOperation('malloc_varsize', [Constant(S, lltype.Void), flags,
+                                           v1], v)
+    tr = Transformer(FakeCPU(), FakeResidualCallControl())
+    op0, op1 = tr.rewrite_operation(op)
+    assert op0.opname == 'residual_call_ir_i'
+    assert op0.args[0].value == 'raw_malloc_zero'    # pseudo-function as a str
+    assert op1.opname == '-live-'
+    assert op1.args == []
+
+def test_raw_malloc_unsupported_flag():
+    S = rffi.CArray(lltype.Signed)
+    v1 = varoftype(lltype.Signed)
+    v = varoftype(lltype.Ptr(S))
+    flags = Constant({'flavor': 'raw', 'unsupported_flag': True}, lltype.Void)
+    op = SpaceOperation('malloc_varsize', [Constant(S, lltype.Void), flags,
+                                           v1], v)
+    tr = Transformer(FakeCPU(), FakeResidualCallControl())
+    py.test.raises(UnsupportedMallocFlags, tr.rewrite_operation, op)
+
 def test_rename_on_links():
     v1 = Variable()
     v2 = Variable(); v2.concretetype = llmemory.Address
@@ -1140,4 +1180,4 @@
     assert op1.opname == 'mark_opaque_ptr'
     assert op1.args == [v1]
     assert op1.result is None
-    assert op2 is None
\ No newline at end of file
+    assert op2 is None
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
@@ -78,7 +78,7 @@
             oplist = tr.rewrite_operation(op)
             assert len(oplist) == 2
             assert oplist[0].opname == 'residual_call_irf_f'
-            assert oplist[0].args[0].value == 'llong_from_int'
+            assert oplist[0].args[0].value == opname.split('_')[0]+'_from_int'
             assert oplist[0].args[1] == 'calldescr-84'
             assert list(oplist[0].args[2]) == [const(0)]
             assert list(oplist[0].args[3]) == []
diff --git a/pypy/jit/metainterp/blackhole.py b/pypy/jit/metainterp/blackhole.py
--- a/pypy/jit/metainterp/blackhole.py
+++ b/pypy/jit/metainterp/blackhole.py
@@ -518,6 +518,9 @@
     @arguments("r")
     def bhimpl_mark_opaque_ptr(a):
         pass
+    @arguments("r", "i")
+    def bhimpl_record_known_class(a, b):
+        pass
 
     @arguments("i", returns="i")
     def bhimpl_int_copy(a):
diff --git a/pypy/jit/metainterp/compile.py b/pypy/jit/metainterp/compile.py
--- a/pypy/jit/metainterp/compile.py
+++ b/pypy/jit/metainterp/compile.py
@@ -298,7 +298,7 @@
     pass
 
 class ResumeGuardDescr(ResumeDescr):
-    _counter = 0        # if < 0, there is one counter per value;
+    _counter = 0        # on a GUARD_VALUE, there is one counter per value;
     _counters = None    # they get stored in _counters then.
 
     # this class also gets the following attributes stored by resume.py code
@@ -309,10 +309,13 @@
     rd_virtuals = None
     rd_pendingfields = lltype.nullptr(PENDINGFIELDSP.TO)
 
-    CNT_INT   = -0x20000000
-    CNT_REF   = -0x40000000
-    CNT_FLOAT = -0x60000000
-    CNT_MASK  =  0x1FFFFFFF
+    CNT_BASE_MASK  =  0x0FFFFFFF     # the base counter value
+    CNT_BUSY_FLAG  =  0x10000000     # if set, busy tracing from the guard
+    CNT_TYPE_MASK  =  0x60000000     # mask for the type
+
+    CNT_INT        =  0x20000000
+    CNT_REF        =  0x40000000
+    CNT_FLOAT      =  0x60000000
 
     def store_final_boxes(self, guard_op, boxes):
         guard_op.setfailargs(boxes)
@@ -326,6 +329,8 @@
         except ValueError:
             return     # xxx probably very rare
         else:
+            if i > self.CNT_BASE_MASK:
+                return    # probably never, but better safe than sorry
             if box.type == history.INT:
                 cnt = self.CNT_INT
             elif box.type == history.REF:
@@ -334,14 +339,17 @@
                 cnt = self.CNT_FLOAT
             else:
                 assert 0, box.type
-            # we build the following value for _counter, which is always
-            # a negative value
+            assert cnt > self.CNT_BASE_MASK
             self._counter = cnt | i
 
     def handle_fail(self, metainterp_sd, jitdriver_sd):
         if self.must_compile(metainterp_sd, jitdriver_sd):
-            return self._trace_and_compile_from_bridge(metainterp_sd,
-                                                       jitdriver_sd)
+            self.start_compiling()
+            try:
+                return self._trace_and_compile_from_bridge(metainterp_sd,
+                                                           jitdriver_sd)
+            finally:
+                self.done_compiling()
         else:
             from pypy.jit.metainterp.blackhole import resume_in_blackhole
             resume_in_blackhole(metainterp_sd, jitdriver_sd, self)
@@ -359,12 +367,22 @@
 
     def must_compile(self, metainterp_sd, jitdriver_sd):
         trace_eagerness = jitdriver_sd.warmstate.trace_eagerness
-        if self._counter >= 0:
+        #
+        if self._counter <= self.CNT_BASE_MASK:
+            # simple case: just counting from 0 to trace_eagerness
             self._counter += 1
             return self._counter >= trace_eagerness
-        else:
-            index = self._counter & self.CNT_MASK
-            typetag = self._counter & ~ self.CNT_MASK
+        #
+        # do we have the BUSY flag?  If so, we're tracing right now, e.g. in an
+        # outer invocation of the same function, so don't trace again for now.
+        elif self._counter & self.CNT_BUSY_FLAG:
+            return False
+        #
+        else: # we have a GUARD_VALUE that fails.  Make a _counters instance
+            # (only now, when the guard is actually failing at least once),
+            # and use it to record some statistics about the failing values.
+            index = self._counter & self.CNT_BASE_MASK
+            typetag = self._counter & self.CNT_TYPE_MASK
             counters = self._counters
             if typetag == self.CNT_INT:
                 intvalue = metainterp_sd.cpu.get_latest_value_int(index)
@@ -391,7 +409,16 @@
                 assert 0, typetag
             return counter >= trace_eagerness
 
-    def reset_counter_from_failure(self):
+    def start_compiling(self):
+        # start tracing and compiling from this guard.
+        self._counter |= self.CNT_BUSY_FLAG
+
+    def done_compiling(self):
+        # done tracing and compiling from this guard.  Either the bridge has
+        # been successfully compiled, in which case whatever value we store
+        # in self._counter will not be seen any more, or not, in which case
+        # we should reset the counter to 0, in order to wait a bit until the
+        # next attempt.
         if self._counter >= 0:
             self._counter = 0
         self._counters = None
@@ -608,9 +635,6 @@
         metainterp.set_compiled_merge_points(self.original_greenkey,
                                              old_loop_tokens)
 
-    def reset_counter_from_failure(self):
-        pass
-
 
 def compile_new_bridge(metainterp, old_loop_tokens, resumekey, retraced=False):
     """Try to compile a new bridge leading from the beginning of the history
diff --git a/pypy/jit/metainterp/executor.py b/pypy/jit/metainterp/executor.py
--- a/pypy/jit/metainterp/executor.py
+++ b/pypy/jit/metainterp/executor.py
@@ -340,6 +340,8 @@
                          rop.DEBUG_MERGE_POINT,
                          rop.JIT_DEBUG,
                          rop.SETARRAYITEM_RAW,
+                         rop.GETINTERIORFIELD_RAW,
+                         rop.SETINTERIORFIELD_RAW,
                          rop.CALL_RELEASE_GIL,
                          rop.QUASIIMMUT_FIELD,
                          ):      # list of opcodes never executed by pyjitpl
diff --git a/pypy/jit/metainterp/gc.py b/pypy/jit/metainterp/gc.py
--- a/pypy/jit/metainterp/gc.py
+++ b/pypy/jit/metainterp/gc.py
@@ -7,6 +7,9 @@
         self.config = config
 
 
+class GC_none(GcDescription):
+    malloc_zero_filled = True
+
 class GC_boehm(GcDescription):
     malloc_zero_filled = True
 
diff --git a/pypy/jit/metainterp/history.py b/pypy/jit/metainterp/history.py
--- a/pypy/jit/metainterp/history.py
+++ b/pypy/jit/metainterp/history.py
@@ -999,13 +999,13 @@
                 "found %d %r, expected %d" % (found, insn, expected_count))
         return insns
 
-    def check_loops(self, expected=None, everywhere=False, **check):
+    def check_resops(self, expected=None, **check):
         insns = {}
         for loop in self.loops:
-            if not everywhere:
-                if getattr(loop, '_ignore_during_counting', False):
-                    continue
             insns = loop.summary(adding_insns=insns)
+        return self._check_insns(insns, expected, check)
+
+    def _check_insns(self, insns, expected, check):
         if expected is not None:
             insns.pop('debug_merge_point', None)
             assert insns == expected
@@ -1016,6 +1016,25 @@
                 "found %d %r, expected %d" % (found, insn, expected_count))
         return insns
 
+    def check_simple_loop(self, expected=None, **check):
+        # Usefull in the simplest case when we have only one trace ending with
+        # a jump back to itself and possibly a few bridges ending with finnish.
+        # Only the operations within the loop formed by that single jump will
+        # be counted.
+
+        # XXX hacked version, ignore and remove me when jit-targets is merged.
+        loops = self.get_all_loops()
+        loops = [loop for loop in loops if 'Preamble' not in repr(loop)] #XXX
+        assert len(loops) == 1
+        loop, = loops
+        jumpop = loop.operations[-1]
+        assert jumpop.getopnum() == rop.JUMP
+        insns = {}
+        for op in loop.operations:
+            opname = op.getopname()
+            insns[opname] = insns.get(opname, 0) + 1
+        return self._check_insns(insns, expected, check)
+        
     def check_consistency(self):
         "NOT_RPYTHON"
         for loop in self.loops:
diff --git a/pypy/jit/metainterp/optimizeopt/__init__.py b/pypy/jit/metainterp/optimizeopt/__init__.py
--- a/pypy/jit/metainterp/optimizeopt/__init__.py
+++ b/pypy/jit/metainterp/optimizeopt/__init__.py
@@ -55,7 +55,7 @@
 
 
 def optimize_loop_1(metainterp_sd, loop, enable_opts,
-                    inline_short_preamble=True, retraced=False, bridge=False):
+                    inline_short_preamble=True, retraced=False):
     """Optimize loop.operations to remove internal overheadish operations.
     """
 
@@ -64,7 +64,7 @@
     if unroll:
         optimize_unroll(metainterp_sd, loop, optimizations)
     else:
-        optimizer = Optimizer(metainterp_sd, loop, optimizations, bridge)
+        optimizer = Optimizer(metainterp_sd, loop, optimizations)
         optimizer.propagate_all_forward()
 
 def optimize_bridge_1(metainterp_sd, bridge, enable_opts,
@@ -76,7 +76,7 @@
     except KeyError:
         pass
     optimize_loop_1(metainterp_sd, bridge, enable_opts,
-                    inline_short_preamble, retraced, bridge=True)
+                    inline_short_preamble, retraced)
 
 if __name__ == '__main__':
     print ALL_OPTS_NAMES
diff --git a/pypy/jit/metainterp/optimizeopt/fficall.py b/pypy/jit/metainterp/optimizeopt/fficall.py
--- a/pypy/jit/metainterp/optimizeopt/fficall.py
+++ b/pypy/jit/metainterp/optimizeopt/fficall.py
@@ -1,11 +1,13 @@
+from pypy.jit.codewriter.effectinfo import EffectInfo
+from pypy.jit.metainterp.optimizeopt.optimizer import Optimization
+from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
+from pypy.jit.metainterp.resoperation import rop, ResOperation
+from pypy.rlib import clibffi, libffi
+from pypy.rlib.debug import debug_print
+from pypy.rlib.libffi import Func
+from pypy.rlib.objectmodel import we_are_translated
 from pypy.rpython.annlowlevel import cast_base_ptr_to_instance
-from pypy.rlib.objectmodel import we_are_translated
-from pypy.rlib.libffi import Func
-from pypy.rlib.debug import debug_print
-from pypy.jit.codewriter.effectinfo import EffectInfo
-from pypy.jit.metainterp.resoperation import rop, ResOperation
-from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
-from pypy.jit.metainterp.optimizeopt.optimizer import Optimization
+from pypy.rpython.lltypesystem import llmemory, rffi
 
 
 class FuncInfo(object):
@@ -78,7 +80,7 @@
 
     def new(self):
         return OptFfiCall()
-    
+
     def begin_optimization(self, funcval, op):
         self.rollback_maybe('begin_optimization', op)
         self.funcinfo = FuncInfo(funcval, self.optimizer.cpu, op)
@@ -116,6 +118,9 @@
             ops = self.do_push_arg(op)
         elif oopspec == EffectInfo.OS_LIBFFI_CALL:
             ops = self.do_call(op)
+        elif (oopspec == EffectInfo.OS_LIBFFI_GETARRAYITEM or
+            oopspec == EffectInfo.OS_LIBFFI_SETARRAYITEM):
+            ops = self.do_getsetarrayitem(op, oopspec)
         #
         for op in ops:
             self.emit_operation(op)
@@ -190,6 +195,56 @@
         ops.append(newop)
         return ops
 
+    def do_getsetarrayitem(self, op, oopspec):
+        ffitypeval = self.getvalue(op.getarg(1))
+        widthval = self.getvalue(op.getarg(2))
+        offsetval = self.getvalue(op.getarg(5))
+        if not ffitypeval.is_constant() or not widthval.is_constant() or not offsetval.is_constant():
+            return [op]
+
+        ffitypeaddr = ffitypeval.box.getaddr()
+        ffitype = llmemory.cast_adr_to_ptr(ffitypeaddr, clibffi.FFI_TYPE_P)
+        offset = offsetval.box.getint()
+        width = widthval.box.getint()
+        descr = self._get_interior_descr(ffitype, width, offset)
+
+        arglist = [
+            self.getvalue(op.getarg(3)).force_box(self.optimizer),
+            self.getvalue(op.getarg(4)).force_box(self.optimizer),
+        ]
+        if oopspec == EffectInfo.OS_LIBFFI_GETARRAYITEM:
+            opnum = rop.GETINTERIORFIELD_RAW
+        elif oopspec == EffectInfo.OS_LIBFFI_SETARRAYITEM:
+            opnum = rop.SETINTERIORFIELD_RAW
+            arglist.append(self.getvalue(op.getarg(6)).force_box(self.optimizer))
+        else:
+            assert False
+        return [
+            ResOperation(opnum, arglist, op.result, descr=descr),
+        ]
+
+    def _get_interior_descr(self, ffitype, width, offset):
+        kind = libffi.types.getkind(ffitype)
+        is_pointer = is_float = is_signed = False
+        if ffitype is libffi.types.pointer:
+            is_pointer = True
+        elif kind == 'i':
+            is_signed = True
+        elif kind == 'f' or kind == 'I' or kind == 'U':
+            # longlongs are treated as floats, see
+            # e.g. llsupport/descr.py:getDescrClass
+            is_float = True
+        elif kind == 'u':
+            # they're all False
+            pass
+        else:
+            assert False, "unsupported ffitype or kind"
+        #
+        fieldsize = rffi.getintfield(ffitype, 'c_size')
+        return self.optimizer.cpu.interiorfielddescrof_dynamic(
+            offset, width, fieldsize, is_pointer, is_float, is_signed
+        )
+
     def propagate_forward(self, op):
         if self.logops is not None:
             debug_print(self.logops.repr_of_resop(op))
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
@@ -43,7 +43,7 @@
             optheap.optimizer.ensure_imported(cached_fieldvalue)
             cached_fieldvalue = self._cached_fields.get(structvalue, None)
 
-        if cached_fieldvalue is not fieldvalue:
+        if not fieldvalue.same_value(cached_fieldvalue):
             # common case: store the 'op' as lazy_setfield, and register
             # myself in the optheap's _lazy_setfields_and_arrayitems list
             self._lazy_setfield = op
@@ -140,6 +140,15 @@
                     getop = ResOperation(rop.GETFIELD_GC, [op.getarg(0)],
                                          result, op.getdescr())
                     shortboxes.add_potential(getop, synthetic=True)
+                if op.getopnum() == rop.SETARRAYITEM_GC:
+                    result = op.getarg(2)
+                    if isinstance(result, Const):
+                        newresult = result.clonebox()
+                        optimizer.make_constant(newresult, result)
+                        result = newresult
+                    getop = ResOperation(rop.GETARRAYITEM_GC, [op.getarg(0), op.getarg(1)],
+                                         result, op.getdescr())
+                    shortboxes.add_potential(getop, synthetic=True)
                 elif op.result is not None:
                     shortboxes.add_potential(op)
 
@@ -225,7 +234,7 @@
             or op.is_ovf()):
             self.posponedop = op
         else:
-            self.next_optimization.propagate_forward(op)
+            Optimization.emit_operation(self, op)
 
     def emitting_operation(self, op):
         if op.has_no_side_effect():
diff --git a/pypy/jit/metainterp/optimizeopt/intbounds.py b/pypy/jit/metainterp/optimizeopt/intbounds.py
--- a/pypy/jit/metainterp/optimizeopt/intbounds.py
+++ b/pypy/jit/metainterp/optimizeopt/intbounds.py
@@ -1,3 +1,4 @@
+import sys
 from pypy.jit.metainterp.optimizeopt.optimizer import Optimization, CONST_1, CONST_0, \
                                                   MODE_ARRAY, MODE_STR, MODE_UNICODE
 from pypy.jit.metainterp.history import ConstInt
@@ -5,36 +6,18 @@
     IntUpperBound)
 from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
 from pypy.jit.metainterp.resoperation import rop
+from pypy.jit.metainterp.optimize import InvalidLoop
+from pypy.rlib.rarithmetic import LONG_BIT
 
 
 class OptIntBounds(Optimization):
     """Keeps track of the bounds placed on integers by guards and remove
        redundant guards"""
 
-    def setup(self):
-        self.posponedop = None
-        self.nextop = None
-
     def new(self):
-        assert self.posponedop is None
         return OptIntBounds()
-        
-    def flush(self):
-        assert self.posponedop is None
-
-    def setup(self):
-        self.posponedop = None
-        self.nextop = None
 
     def propagate_forward(self, op):
-        if op.is_ovf():
-            self.posponedop = op
-            return
-        if self.posponedop:
-            self.nextop = op
-            op = self.posponedop
-            self.posponedop = None
-
         dispatch_opt(self, op)
 
     def opt_default(self, op):
@@ -126,14 +109,29 @@
         r.intbound.intersect(v1.intbound.div_bound(v2.intbound))
 
     def optimize_INT_MOD(self, op):
+        v1 = self.getvalue(op.getarg(0))
+        v2 = self.getvalue(op.getarg(1))
+        known_nonneg = (v1.intbound.known_ge(IntBound(0, 0)) and 
+                        v2.intbound.known_ge(IntBound(0, 0)))
+        if known_nonneg and v2.is_constant():
+            val = v2.box.getint()
+            if (val & (val-1)) == 0:
+                # nonneg % power-of-two ==> nonneg & (power-of-two - 1)
+                arg1 = op.getarg(0)
+                arg2 = ConstInt(val-1)
+                op = op.copy_and_change(rop.INT_AND, args=[arg1, arg2])
         self.emit_operation(op)
-        v2 = self.getvalue(op.getarg(1))
         if v2.is_constant():
             val = v2.box.getint()
             r = self.getvalue(op.result)
             if val < 0:
+                if val == -sys.maxint-1:
+                    return     # give up
                 val = -val
-            r.intbound.make_gt(IntBound(-val, -val))
+            if known_nonneg:
+                r.intbound.make_ge(IntBound(0, 0))
+            else:
+                r.intbound.make_gt(IntBound(-val, -val))
             r.intbound.make_lt(IntBound(val, val))
 
     def optimize_INT_LSHIFT(self, op):
@@ -153,72 +151,84 @@
     def optimize_INT_RSHIFT(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
+        b = v1.intbound.rshift_bound(v2.intbound)
+        if b.has_lower and b.has_upper and b.lower == b.upper:
+            # constant result (likely 0, for rshifts that kill all bits)
+            self.make_constant_int(op.result, b.lower)
+        else:
+            self.emit_operation(op)
+            r = self.getvalue(op.result)
+            r.intbound.intersect(b)
+
+    def optimize_GUARD_NO_OVERFLOW(self, op):
+        lastop = self.last_emitted_operation
+        if lastop is not None:
+            opnum = lastop.getopnum()
+            args = lastop.getarglist()
+            result = lastop.result
+            # If the INT_xxx_OVF was replaced with INT_xxx, then we can kill
+            # the GUARD_NO_OVERFLOW.
+            if (opnum == rop.INT_ADD or
+                opnum == rop.INT_SUB or
+                opnum == rop.INT_MUL):
+                return
+            # Else, synthesize the non overflowing op for optimize_default to
+            # reuse, as well as the reverse op
+            elif opnum == rop.INT_ADD_OVF:
+                self.pure(rop.INT_ADD, args[:], result)
+                self.pure(rop.INT_SUB, [result, args[1]], args[0])
+                self.pure(rop.INT_SUB, [result, args[0]], args[1])
+            elif opnum == rop.INT_SUB_OVF:
+                self.pure(rop.INT_SUB, args[:], result)
+                self.pure(rop.INT_ADD, [result, args[1]], args[0])
+                self.pure(rop.INT_SUB, [args[0], result], args[1])
+            elif opnum == rop.INT_MUL_OVF:
+                self.pure(rop.INT_MUL, args[:], result)
         self.emit_operation(op)
-        r = self.getvalue(op.result)
-        r.intbound.intersect(v1.intbound.rshift_bound(v2.intbound))
+
+    def optimize_GUARD_OVERFLOW(self, op):
+        # If INT_xxx_OVF was replaced by INT_xxx, *but* we still see
+        # GUARD_OVERFLOW, then the loop is invalid.
+        lastop = self.last_emitted_operation
+        if lastop is None:
+            raise InvalidLoop
+        opnum = lastop.getopnum()
+        if opnum not in (rop.INT_ADD_OVF, rop.INT_SUB_OVF, rop.INT_MUL_OVF):
+            raise InvalidLoop
+        self.emit_operation(op)
 
     def optimize_INT_ADD_OVF(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
         resbound = v1.intbound.add_bound(v2.intbound)
-        if resbound.has_lower and resbound.has_upper and \
-           self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
-            # Transform into INT_ADD and remove guard
+        if resbound.bounded():
+            # Transform into INT_ADD.  The following guard will be killed
+            # by optimize_GUARD_NO_OVERFLOW; if we see instead an
+            # optimize_GUARD_OVERFLOW, then InvalidLoop.
             op = op.copy_and_change(rop.INT_ADD)
-            self.optimize_INT_ADD(op) # emit the op
-        else:
-            self.emit_operation(op)
-            r = self.getvalue(op.result)
-            r.intbound.intersect(resbound)
-            self.emit_operation(self.nextop)
-            if self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
-                # Synthesize the non overflowing op for optimize_default to reuse
-                self.pure(rop.INT_ADD, op.getarglist()[:], op.result)
-                # Synthesize the reverse op for optimize_default to reuse
-                self.pure(rop.INT_SUB, [op.result, op.getarg(1)], op.getarg(0))
-                self.pure(rop.INT_SUB, [op.result, op.getarg(0)], op.getarg(1))
-
+        self.emit_operation(op) # emit the op
+        r = self.getvalue(op.result)
+        r.intbound.intersect(resbound)
 
     def optimize_INT_SUB_OVF(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
         resbound = v1.intbound.sub_bound(v2.intbound)
-        if resbound.has_lower and resbound.has_upper and \
-               self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
-            # Transform into INT_SUB and remove guard
+        if resbound.bounded():
             op = op.copy_and_change(rop.INT_SUB)
-            self.optimize_INT_SUB(op) # emit the op
-        else:
-            self.emit_operation(op)
-            r = self.getvalue(op.result)
-            r.intbound.intersect(resbound)
-            self.emit_operation(self.nextop)
-            if self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
-                # Synthesize the non overflowing op for optimize_default to reuse
-                self.pure(rop.INT_SUB, op.getarglist()[:], op.result)
-                # Synthesize the reverse ops for optimize_default to reuse
-                self.pure(rop.INT_ADD, [op.result, op.getarg(1)], op.getarg(0))
-                self.pure(rop.INT_SUB, [op.getarg(0), op.result], op.getarg(1))
-
+        self.emit_operation(op) # emit the op
+        r = self.getvalue(op.result)
+        r.intbound.intersect(resbound)
 
     def optimize_INT_MUL_OVF(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
         resbound = v1.intbound.mul_bound(v2.intbound)
-        if resbound.has_lower and resbound.has_upper and \
-               self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
-            # Transform into INT_MUL and remove guard
+        if resbound.bounded():
             op = op.copy_and_change(rop.INT_MUL)
-            self.optimize_INT_MUL(op) # emit the op
-        else:
-            self.emit_operation(op)
-            r = self.getvalue(op.result)
-            r.intbound.intersect(resbound)
-            self.emit_operation(self.nextop)
-            if self.nextop.getopnum() == rop.GUARD_NO_OVERFLOW:
-                # Synthesize the non overflowing op for optimize_default to reuse
-                self.pure(rop.INT_MUL, op.getarglist()[:], op.result)
-
+        self.emit_operation(op)
+        r = self.getvalue(op.result)
+        r.intbound.intersect(resbound)
 
     def optimize_INT_LT(self, op):
         v1 = self.getvalue(op.getarg(0))
diff --git a/pypy/jit/metainterp/optimizeopt/intutils.py b/pypy/jit/metainterp/optimizeopt/intutils.py
--- a/pypy/jit/metainterp/optimizeopt/intutils.py
+++ b/pypy/jit/metainterp/optimizeopt/intutils.py
@@ -1,4 +1,5 @@
-from pypy.rlib.rarithmetic import ovfcheck, ovfcheck_lshift, LONG_BIT
+from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT
+from pypy.rlib.objectmodel import we_are_translated
 from pypy.jit.metainterp.resoperation import rop, ResOperation
 from pypy.jit.metainterp.history import BoxInt, ConstInt
 import sys
@@ -13,6 +14,10 @@
         self.has_lower = True
         self.upper = upper
         self.lower = lower
+        # check for unexpected overflows:
+        if not we_are_translated():
+            assert type(upper) is not long
+            assert type(lower) is not long
 
     # Returns True if the bound was updated
     def make_le(self, other):
@@ -169,10 +174,10 @@
            other.known_ge(IntBound(0, 0)) and \
            other.known_lt(IntBound(LONG_BIT, LONG_BIT)):
             try:
-                vals = (ovfcheck_lshift(self.upper, other.upper),
-                        ovfcheck_lshift(self.upper, other.lower),
-                        ovfcheck_lshift(self.lower, other.upper),
-                        ovfcheck_lshift(self.lower, other.lower))
+                vals = (ovfcheck(self.upper << other.upper),
+                        ovfcheck(self.upper << other.lower),
+                        ovfcheck(self.lower << other.upper),
+                        ovfcheck(self.lower << other.lower))
                 return IntBound(min4(vals), max4(vals))
             except (OverflowError, ValueError):
                 return IntUnbounded()
diff --git a/pypy/jit/metainterp/optimizeopt/optimizer.py b/pypy/jit/metainterp/optimizeopt/optimizer.py
--- a/pypy/jit/metainterp/optimizeopt/optimizer.py
+++ b/pypy/jit/metainterp/optimizeopt/optimizer.py
@@ -1,12 +1,12 @@
 from pypy.jit.metainterp import jitprof, resume, compile
 from pypy.jit.metainterp.executor import execute_nonspec
-from pypy.jit.metainterp.history import BoxInt, BoxFloat, Const, ConstInt, REF
+from pypy.jit.metainterp.history import BoxInt, BoxFloat, Const, ConstInt, REF, INT
 from pypy.jit.metainterp.optimizeopt.intutils import IntBound, IntUnbounded, \
                                                      ImmutableIntUnbounded, \
                                                      IntLowerBound, MININT, MAXINT
 from pypy.jit.metainterp.optimizeopt.util import (make_dispatcher_method,
     args_dict)
-from pypy.jit.metainterp.resoperation import rop, ResOperation
+from pypy.jit.metainterp.resoperation import rop, ResOperation, AbstractResOp
 from pypy.jit.metainterp.typesystem import llhelper, oohelper
 from pypy.tool.pairtype import extendabletype
 from pypy.rlib.debug import debug_start, debug_stop, debug_print
@@ -95,6 +95,10 @@
         return guards
 
     def import_from(self, other, optimizer):
+        if self.level == LEVEL_CONSTANT:
+            assert other.level == LEVEL_CONSTANT
+            assert other.box.same_constant(self.box)
+            return
         assert self.level <= LEVEL_NONNULL
         if other.level == LEVEL_CONSTANT:
             self.make_constant(other.get_key_box())
@@ -141,6 +145,13 @@
             return not box.nonnull()
         return False
 
+    def same_value(self, other):
+        if not other:
+            return False
+        if self.is_constant() and other.is_constant():
+            return self.box.same_constant(other.box)
+        return self is other
+
     def make_constant(self, constbox):
         """Replace 'self.box' with a Const box."""
         assert isinstance(constbox, Const)
@@ -236,9 +247,10 @@
 CONST_1      = ConstInt(1)
 CVAL_ZERO    = ConstantValue(CONST_0)
 CVAL_ZERO_FLOAT = ConstantValue(Const._new(0.0))
-CVAL_UNINITIALIZED_ZERO = ConstantValue(CONST_0)
 llhelper.CVAL_NULLREF = ConstantValue(llhelper.CONST_NULL)
 oohelper.CVAL_NULLREF = ConstantValue(oohelper.CONST_NULL)
+REMOVED = AbstractResOp(None)
+
 
 class Optimization(object):
     next_optimization = None
@@ -250,6 +262,7 @@
         raise NotImplementedError
 
     def emit_operation(self, op):
+        self.last_emitted_operation = op
         self.next_optimization.propagate_forward(op)
 
     # FIXME: Move some of these here?
@@ -317,24 +330,25 @@
     def forget_numberings(self, box):
         self.optimizer.forget_numberings(box)
 
+
 class Optimizer(Optimization):
 
-    def __init__(self, metainterp_sd, loop, optimizations=None, bridge=False):
+    def __init__(self, metainterp_sd, loop, optimizations=None):
         self.metainterp_sd = metainterp_sd
         self.cpu = metainterp_sd.cpu
         self.loop = loop
-        self.bridge = bridge
         self.values = {}
         self.interned_refs = self.cpu.ts.new_ref_dict()
+        self.interned_ints = {}
         self.resumedata_memo = resume.ResumeDataLoopMemo(metainterp_sd)
         self.bool_boxes = {}
         self.producer = {}
         self.pendingfields = []
-        self.exception_might_have_happened = False
         self.quasi_immutable_deps = None
         self.opaque_pointers = {}
         self.replaces_guard = {}
         self._newoperations = []
+        self.seen_results = {}
         self.optimizer = self
         self.optpure = None
         self.optearlyforce = None
@@ -352,6 +366,7 @@
             optimizations[-1].next_optimization = self
             for o in optimizations:
                 o.optimizer = self
+                o.last_emitted_operation = None
                 o.setup()
         else:
             optimizations = []
@@ -398,6 +413,9 @@
             if not value:
                 return box
             return self.interned_refs.setdefault(value, box)
+        #elif constbox.type == INT:
+        #    value = constbox.getint()
+        #    return self.interned_ints.setdefault(value, box)
         else:
             return box
 
@@ -483,7 +501,6 @@
             return CVAL_ZERO
 
     def propagate_all_forward(self):
-        self.exception_might_have_happened = self.bridge
         self.clear_newoperations()
         for op in self.loop.operations:
             self.first_optimization.propagate_forward(op)
@@ -526,6 +543,10 @@
                 op = self.store_final_boxes_in_guard(op)
         elif op.can_raise():
             self.exception_might_have_happened = True
+        if op.result:
+            if op.result in self.seen_results:
+                raise ValueError, "invalid optimization"
+            self.seen_results[op.result] = None
         self._newoperations.append(op)
 
     def replace_op(self, old_op, new_op):
@@ -543,9 +564,12 @@
         descr = op.getdescr()
         assert isinstance(descr, compile.ResumeGuardDescr)
         modifier = resume.ResumeDataVirtualAdder(descr, self.resumedata_memo)
-        newboxes = modifier.finish(self.values, self.pendingfields)
-        if len(newboxes) > self.metainterp_sd.options.failargs_limit: # XXX be careful here
-            compile.giveup()
+        try:
+            newboxes = modifier.finish(self.values, self.pendingfields)
+            if len(newboxes) > self.metainterp_sd.options.failargs_limit:
+                raise resume.TagOverflow
+        except resume.TagOverflow:
+            raise compile.giveup()
         descr.store_final_boxes(op, newboxes)
         #
         if op.getopnum() == rop.GUARD_VALUE:
diff --git a/pypy/jit/metainterp/optimizeopt/pure.py b/pypy/jit/metainterp/optimizeopt/pure.py
--- a/pypy/jit/metainterp/optimizeopt/pure.py
+++ b/pypy/jit/metainterp/optimizeopt/pure.py
@@ -1,4 +1,4 @@
-from pypy.jit.metainterp.optimizeopt.optimizer import Optimization
+from pypy.jit.metainterp.optimizeopt.optimizer import Optimization, REMOVED
 from pypy.jit.metainterp.resoperation import rop, ResOperation
 from pypy.jit.metainterp.optimizeopt.util import (make_dispatcher_method,
     args_dict)
@@ -61,7 +61,10 @@
         oldop = self.pure_operations.get(args, None)
         if oldop is not None and oldop.getdescr() is op.getdescr():
             assert oldop.getopnum() == op.getopnum()
+            # this removes a CALL_PURE that has the same (non-constant)
+            # arguments as a previous CALL_PURE.
             self.make_equal_to(op.result, self.getvalue(oldop.result))
+            self.last_emitted_operation = REMOVED
             return
         else:
             self.pure_operations[args] = op
@@ -72,6 +75,13 @@
         self.emit_operation(ResOperation(rop.CALL, args, op.result,
                                          op.getdescr()))
 
+    def optimize_GUARD_NO_EXCEPTION(self, op):
+        if self.last_emitted_operation is REMOVED:
+            # it was a CALL_PURE that was killed; so we also kill the
+            # following GUARD_NO_EXCEPTION
+            return
+        self.emit_operation(op)
+
     def flush(self):
         assert self.posponedop is None
 
diff --git a/pypy/jit/metainterp/optimizeopt/rewrite.py b/pypy/jit/metainterp/optimizeopt/rewrite.py
--- a/pypy/jit/metainterp/optimizeopt/rewrite.py
+++ b/pypy/jit/metainterp/optimizeopt/rewrite.py
@@ -260,6 +260,16 @@
     def optimize_GUARD_FALSE(self, op):
         self.optimize_guard(op, CONST_0)
 
+    def optimize_RECORD_KNOWN_CLASS(self, op):
+        value = self.getvalue(op.getarg(0))
+        expectedclassbox = op.getarg(1)
+        assert isinstance(expectedclassbox, Const)
+        realclassbox = value.get_constant_class(self.optimizer.cpu)
+        if realclassbox is not None:
+            assert realclassbox.same_constant(expectedclassbox)
+            return
+        value.make_constant_class(expectedclassbox, None)
+
     def optimize_GUARD_CLASS(self, op):
         value = self.getvalue(op.getarg(0))
         expectedclassbox = op.getarg(1)
@@ -294,12 +304,6 @@
             raise InvalidLoop
         self.optimize_GUARD_CLASS(op)
 
-    def optimize_GUARD_NO_EXCEPTION(self, op):
-        if not self.optimizer.exception_might_have_happened:
-            return
-        self.emit_operation(op)
-        self.optimizer.exception_might_have_happened = False
-
     def optimize_CALL_LOOPINVARIANT(self, op):
         arg = op.getarg(0)
         # 'arg' must be a Const, because residual_call in codewriter
@@ -310,6 +314,7 @@
         resvalue = self.loop_invariant_results.get(key, None)
         if resvalue is not None:
             self.make_equal_to(op.result, resvalue)
+            self.last_emitted_operation = REMOVED
             return
         # change the op to be a normal call, from the backend's point of view
         # there is no reason to have a separate operation for this
@@ -444,10 +449,19 @@
             except KeyError:
                 pass
             else:
+                # this removes a CALL_PURE with all constant arguments.
                 self.make_constant(op.result, result)
+                self.last_emitted_operation = REMOVED
                 return
         self.emit_operation(op)
 
+    def optimize_GUARD_NO_EXCEPTION(self, op):
+        if self.last_emitted_operation is REMOVED:
+            # it was a CALL_PURE or a CALL_LOOPINVARIANT that was killed;
+            # so we also kill the following GUARD_NO_EXCEPTION
+            return
+        self.emit_operation(op)
+
     def optimize_INT_FLOORDIV(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
@@ -477,6 +491,9 @@
         self.pure(rop.CAST_PTR_TO_INT, [op.result], op.getarg(0))
         self.emit_operation(op)
 
+    def optimize_SAME_AS(self, op):
+        self.make_equal_to(op.result, self.getvalue(op.getarg(0)))
+
 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
@@ -28,6 +28,9 @@
     def optimize_MARK_OPAQUE_PTR(self, op):
         pass
 
+    def optimize_RECORD_KNOWN_CLASS(self, op):
+        pass
+
 
 dispatch_opt = make_dispatcher_method(OptSimplify, 'optimize_',
         default=OptSimplify.emit_operation)
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
@@ -9,6 +9,7 @@
 from pypy.jit.metainterp.history import AbstractDescr, ConstInt, BoxInt
 from pypy.jit.metainterp import executor, compile, resume, history
 from pypy.jit.metainterp.resoperation import rop, opname, ResOperation
+from pypy.rlib.rarithmetic import LONG_BIT
 
 
 def test_store_final_boxes_in_guard():
@@ -680,25 +681,60 @@
 
     # ----------
 
-    def test_fold_guard_no_exception(self):
-        ops = """
-        [i]
-        guard_no_exception() []
-        i1 = int_add(i, 3)
-        guard_no_exception() []
+    def test_keep_guard_no_exception(self):
+        ops = """
+        [i1]
         i2 = call(i1, descr=nonwritedescr)
         guard_no_exception() [i1, i2]
-        guard_no_exception() []
-        i3 = call(i2, descr=nonwritedescr)
-        jump(i1)       # the exception is considered lost when we loop back
-        """
-        expected = """
-        [i]
-        i1 = int_add(i, 3)
-        i2 = call(i1, descr=nonwritedescr)
+        jump(i2)
+        """
+        self.optimize_loop(ops, ops)
+
+    def test_keep_guard_no_exception_with_call_pure_that_is_not_folded(self):
+        ops = """
+        [i1]
+        i2 = call_pure(123456, i1, descr=nonwritedescr)
         guard_no_exception() [i1, i2]
-        i3 = call(i2, descr=nonwritedescr)
-        jump(i1)
+        jump(i2)
+        """
+        expected = """
+        [i1]
+        i2 = call(123456, i1, descr=nonwritedescr)
+        guard_no_exception() [i1, i2]
+        jump(i2)
+        """
+        self.optimize_loop(ops, expected)
+
+    def test_remove_guard_no_exception_with_call_pure_on_constant_args(self):
+        arg_consts = [ConstInt(i) for i in (123456, 81)]
+        call_pure_results = {tuple(arg_consts): ConstInt(5)}
+        ops = """
+        [i1]
+        i3 = same_as(81)
+        i2 = call_pure(123456, i3, descr=nonwritedescr)
+        guard_no_exception() [i1, i2]
+        jump(i2)
+        """
+        expected = """
+        [i1]
+        jump(5)
+        """
+        self.optimize_loop(ops, expected, call_pure_results)
+
+    def test_remove_guard_no_exception_with_duplicated_call_pure(self):
+        ops = """
+        [i1]
+        i2 = call_pure(123456, i1, descr=nonwritedescr)
+        guard_no_exception() [i1, i2]
+        i3 = call_pure(123456, i1, descr=nonwritedescr)
+        guard_no_exception() [i1, i2, i3]
+        jump(i3)
+        """
+        expected = """
+        [i1]
+        i2 = call(123456, i1, descr=nonwritedescr)
+        guard_no_exception() [i1, i2]
+        jump(i2)
         """
         self.optimize_loop(ops, expected)
 
@@ -976,6 +1012,29 @@
         """
         self.optimize_loop(ops, expected)
 
+    def test_virtual_array_of_struct_forced(self):
+        ops = """
+        [f0, f1]
+        p0 = new_array(1, descr=complexarraydescr)
+        setinteriorfield_gc(p0, 0, f0, descr=complexrealdescr)
+        setinteriorfield_gc(p0, 0, f1, descr=compleximagdescr)
+        f2 = getinteriorfield_gc(p0, 0, descr=complexrealdescr)
+        f3 = getinteriorfield_gc(p0, 0, descr=compleximagdescr)
+        f4 = float_mul(f2, f3)
+        i0 = escape(f4, p0)
+        finish(i0)
+        """
+        expected = """
+        [f0, f1]
+        f2 = float_mul(f0, f1)
+        p0 = new_array(1, descr=complexarraydescr)
+        setinteriorfield_gc(p0, 0, f0, descr=complexrealdescr)
+        setinteriorfield_gc(p0, 0, f1, descr=compleximagdescr)
+        i0 = escape(f2, p0)
+        finish(i0)
+        """
+        self.optimize_loop(ops, expected)
+
     def test_nonvirtual_1(self):
         ops = """
         [i]
@@ -4099,6 +4158,38 @@
         """
         self.optimize_strunicode_loop(ops, expected)
 
+    def test_str_concat_constant_lengths(self):
+        ops = """
+        [i0]
+        p0 = newstr(1)
+        strsetitem(p0, 0, i0)
+        p1 = newstr(0)
+        p2 = call(0, p0, p1, descr=strconcatdescr)
+        i1 = call(0, p2, p0, descr=strequaldescr)
+        finish(i1)
+        """
+        expected = """
+        [i0]
+        finish(1)
+        """
+        self.optimize_strunicode_loop(ops, expected)
+
+    def test_str_concat_constant_lengths_2(self):
+        ops = """
+        [i0]
+        p0 = newstr(0)
+        p1 = newstr(1)
+        strsetitem(p1, 0, i0)
+        p2 = call(0, p0, p1, descr=strconcatdescr)
+        i1 = call(0, p2, p1, descr=strequaldescr)
+        finish(i1)
+        """
+        expected = """
+        [i0]
+        finish(1)
+        """
+        self.optimize_strunicode_loop(ops, expected)
+
     def test_str_slice_1(self):
         ops = """
         [p1, i1, i2]
@@ -4201,6 +4292,27 @@
         """
         self.optimize_strunicode_loop(ops, expected)
 
+    def test_str_slice_plain_virtual(self):
+        ops = """
+        []
+        p0 = newstr(11)
+        copystrcontent(s"hello world", p0, 0, 0, 11)
+        p1 = call(0, p0, 0, 5, descr=strslicedescr)
+        finish(p1)
+        """
+        expected = """
+        []
+        p0 = newstr(11)
+        copystrcontent(s"hello world", p0, 0, 0, 11)
+        # Eventually this should just return s"hello", but ATM this test is
+        # just verifying that it doesn't return "\0\0\0\0\0", so being
+        # slightly underoptimized is ok.
+        p1 = newstr(5)
+        copystrcontent(p0, p1, 0, 0, 5)
+        finish(p1)
+        """
+        self.optimize_strunicode_loop(ops, expected)
+
     # ----------
     def optimize_strunicode_loop_extradescrs(self, ops, optops):
         class FakeCallInfoCollection:
@@ -4691,11 +4803,11 @@
         i5 = int_ge(i0, 0)
         guard_true(i5) []
         i1 = int_mod(i0, 42)
-        i2 = int_rshift(i1, 63)
+        i2 = int_rshift(i1, %d)
         i3 = int_and(42, i2)
         i4 = int_add(i1, i3)
         finish(i4)
-        """
+        """ % (LONG_BIT-1)
         expected = """
         [i0]
         i5 = int_ge(i0, 0)
@@ -4703,21 +4815,41 @@
         i1 = int_mod(i0, 42)
         finish(i1)
         """
-        py.test.skip("in-progress")
         self.optimize_loop(ops, expected)
 
-        # Also, 'n % power-of-two' can be turned into int_and(),
-        # but that's a bit harder to detect here because it turns into
-        # several operations, and of course it is wrong to just turn
+        # 'n % power-of-two' can be turned into int_and(); at least that's
+        # easy to do now if n is known to be non-negative.
+        ops = """
+        [i0]
+        i5 = int_ge(i0, 0)
+        guard_true(i5) []
+        i1 = int_mod(i0, 8)
+        i2 = int_rshift(i1, %d)
+        i3 = int_and(42, i2)
+        i4 = int_add(i1, i3)
+        finish(i4)
+        """ % (LONG_BIT-1)
+        expected = """
+        [i0]
+        i5 = int_ge(i0, 0)
+        guard_true(i5) []
+        i1 = int_and(i0, 7)
+        finish(i1)
+        """
+        self.optimize_loop(ops, expected)
+
+        # Of course any 'maybe-negative % power-of-two' can be turned into
+        # int_and(), but that's a bit harder to detect here because it turns
+        # into several operations, and of course it is wrong to just turn
         # int_mod(i0, 16) into int_and(i0, 15).
         ops = """
         [i0]
         i1 = int_mod(i0, 16)
-        i2 = int_rshift(i1, 63)
+        i2 = int_rshift(i1, %d)
         i3 = int_and(16, i2)
         i4 = int_add(i1, i3)
         finish(i4)
-        """
+        """ % (LONG_BIT-1)
         expected = """
         [i0]
         i4 = int_and(i0, 15)
@@ -4726,6 +4858,16 @@
         py.test.skip("harder")
         self.optimize_loop(ops, expected)
 
+    def test_intmod_bounds_bug1(self):
+        ops = """
+        [i0]
+        i1 = int_mod(i0, %d)
+        i2 = int_eq(i1, 0)
+        guard_false(i2) []
+        finish()
+        """ % (-(1<<(LONG_BIT-1)),)
+        self.optimize_loop(ops, ops)
+
     def test_bounded_lazy_setfield(self):
         ops = """
         [p0, i0]
@@ -4808,6 +4950,27 @@
 
     def test_plain_virtual_string_copy_content(self):
         ops = """
+        [i1]
+        p0 = newstr(6)
+        copystrcontent(s"hello!", p0, 0, 0, 6)
+        p1 = call(0, p0, s"abc123", descr=strconcatdescr)
+        i0 = strgetitem(p1, i1)
+        finish(i0)
+        """
+        expected = """
+        [i1]
+        p0 = newstr(6)
+        copystrcontent(s"hello!", p0, 0, 0, 6)
+        p1 = newstr(12)
+        copystrcontent(p0, p1, 0, 0, 6)
+        copystrcontent(s"abc123", p1, 0, 6, 6)
+        i0 = strgetitem(p1, i1)
+        finish(i0)
+        """
+        self.optimize_strunicode_loop(ops, expected)
+
+    def test_plain_virtual_string_copy_content_2(self):
+        ops = """
         []
         p0 = newstr(6)
         copystrcontent(s"hello!", p0, 0, 0, 6)
@@ -4819,10 +4982,7 @@
         []
         p0 = newstr(6)
         copystrcontent(s"hello!", p0, 0, 0, 6)
-        p1 = newstr(12)
-        copystrcontent(p0, p1, 0, 0, 6)
-        copystrcontent(s"abc123", p1, 0, 6, 6)
-        i0 = strgetitem(p1, 0)
+        i0 = strgetitem(p0, 0)
         finish(i0)
         """
         self.optimize_strunicode_loop(ops, expected)
@@ -4839,6 +4999,34 @@
         """
         self.optimize_loop(ops, expected)
 
+    def test_known_equal_ints(self):
+        py.test.skip("in-progress")
+        ops = """
+        [i0, i1, i2, p0]
+        i3 = int_eq(i0, i1)
+        guard_true(i3) []
+
+        i4 = int_lt(i2, i0)
+        guard_true(i4) []
+        i5 = int_lt(i2, i1)
+        guard_true(i5) []
+
+        i6 = getarrayitem_gc(p0, i2)
+        finish(i6)
+        """
+        expected = """
+        [i0, i1, i2, p0]
+        i3 = int_eq(i0, i1)
+        guard_true(i3) []
+
+        i4 = int_lt(i2, i0)
+        guard_true(i4) []
+
+        i6 = getarrayitem_gc(p0, i3)
+        finish(i6)
+        """
+        self.optimize_loop(ops, expected)
+
 
 class TestLLtype(BaseTestOptimizeBasic, LLtypeMixin):
     pass
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -931,17 +931,14 @@
         [i]
         guard_no_exception() []
         i1 = int_add(i, 3)
-        guard_no_exception() []
         i2 = call(i1, descr=nonwritedescr)
         guard_no_exception() [i1, i2]
-        guard_no_exception() []
         i3 = call(i2, descr=nonwritedescr)
         jump(i1)       # the exception is considered lost when we loop back
         """
-        # note that 'guard_no_exception' at the very start is kept around
-        # for bridges, but not for loops
         preamble = """
         [i]
+        guard_no_exception() []    # occurs at the start of bridges, so keep it
         i1 = int_add(i, 3)
         i2 = call(i1, descr=nonwritedescr)
         guard_no_exception() [i1, i2]
@@ -950,6 +947,7 @@
         """
         expected = """
         [i]
+        guard_no_exception() []    # occurs at the start of bridges, so keep it
         i1 = int_add(i, 3)
         i2 = call(i1, descr=nonwritedescr)
         guard_no_exception() [i1, i2]
@@ -958,6 +956,23 @@
         """
         self.optimize_loop(ops, expected, preamble)
 
+    def test_bug_guard_no_exception(self):
+        ops = """
+        []
+        i0 = call(123, descr=nonwritedescr)
+        p0 = call(0, "xy", descr=s2u_descr)      # string -> unicode
+        guard_no_exception() []
+        escape(p0)
+        jump()
+        """
+        expected = """
+        []
+        i0 = call(123, descr=nonwritedescr)
+        escape(u"xy")
+        jump()
+        """
+        self.optimize_loop(ops, expected)
+
     # ----------
 
     def test_call_loopinvariant(self):
@@ -1176,6 +1191,75 @@
         """
         self.optimize_loop(ops, expected, preamble)
 
+    def test_virtual_recursive(self):
+        ops = """
+        [p0]
+        p41 = getfield_gc(p0, descr=nextdescr)
+        i0 = getfield_gc(p41, descr=valuedescr)
+        p1 = new_with_vtable(ConstClass(node_vtable2))
+        p2 = new_with_vtable(ConstClass(node_vtable2))
+        setfield_gc(p2, p1, descr=nextdescr)
+        setfield_gc(p1, p2, descr=nextdescr)
+        i1 = int_add(i0, 1)
+        setfield_gc(p2, i1, descr=valuedescr)
+        jump(p1)
+        """
+        preamble = """
+        [p0]
+        p41 = getfield_gc(p0, descr=nextdescr)
+        i0 = getfield_gc(p41, descr=valuedescr)
+        i3 = int_add(i0, 1)
+        jump(i3)
+        """
+        expected = """
+        [i0]
+        i1 = int_add(i0, 1)
+        jump(i1)
+        """
+        self.optimize_loop(ops, expected, preamble)
+
+    def test_virtual_recursive_forced(self):
+        ops = """
+        [p0]
+        p41 = getfield_gc(p0, descr=nextdescr)
+        i0 = getfield_gc(p41, descr=valuedescr)
+        p1 = new_with_vtable(ConstClass(node_vtable2))
+        p2 = new_with_vtable(ConstClass(node_vtable2))
+        setfield_gc(p2, p1, descr=nextdescr)
+        setfield_gc(p1, p2, descr=nextdescr)
+        i1 = int_add(i0, 1)
+        setfield_gc(p2, i1, descr=valuedescr)
+        setfield_gc(p0, p1, descr=nextdescr)
+        jump(p1)
+        """
+        preamble = """
+        [p0]
+        p41 = getfield_gc(p0, descr=nextdescr)
+        i0 = getfield_gc(p41, descr=valuedescr)
+        i1 = int_add(i0, 1)
+        p1 = new_with_vtable(ConstClass(node_vtable2))
+        p2 = new_with_vtable(ConstClass(node_vtable2))
+        setfield_gc(p2, i1, descr=valuedescr)
+        setfield_gc(p2, p1, descr=nextdescr)
+        setfield_gc(p1, p2, descr=nextdescr)
+        setfield_gc(p0, p1, descr=nextdescr)
+        jump(p1)
+        """
+        loop = """
+        [p0]
+        p41 = getfield_gc(p0, descr=nextdescr)
+        i0 = getfield_gc(p41, descr=valuedescr)
+        i1 = int_add(i0, 1)
+        p1 = new_with_vtable(ConstClass(node_vtable2))
+        p2 = new_with_vtable(ConstClass(node_vtable2))
+        setfield_gc(p0, p1, descr=nextdescr)
+        setfield_gc(p2, p1, descr=nextdescr)
+        setfield_gc(p1, p2, descr=nextdescr)
+        setfield_gc(p2, i1, descr=valuedescr)
+        jump(p1)
+        """
+        self.optimize_loop(ops, loop, preamble)
+
     def test_virtual_constant_isnull(self):
         ops = """
         [i0]
@@ -2168,13 +2252,13 @@
         ops = """
         [p0, i0, p1, i1, i2]
         setfield_gc(p0, i1, descr=valuedescr)
-        copystrcontent(p0, i0, p1, i1, i2)
+        copystrcontent(p0, p1, i0, i1, i2)
         escape()
         jump(p0, i0, p1, i1, i2)
         """
         expected = """
         [p0, i0, p1, i1, i2]
-        copystrcontent(p0, i0, p1, i1, i2)
+        copystrcontent(p0, p1, i0, i1, i2)
         setfield_gc(p0, i1, descr=valuedescr)
         escape()
         jump(p0, i0, p1, i1, i2)
@@ -4783,6 +4867,52 @@
         """
         self.optimize_loop(ops, expected)
 
+
+    def test_division_nonneg(self):
+        py.test.skip("harder")
+        # this is how an app-level division turns into right now
+        ops = """
+        [i4]
+        i1 = int_ge(i4, 0)
+        guard_true(i1) []
+        i16 = int_floordiv(i4, 3)
+        i18 = int_mul(i16, 3)
+        i19 = int_sub(i4, i18)
+        i21 = int_rshift(i19, %d)
+        i22 = int_add(i16, i21)
+        finish(i22)
+        """ % (LONG_BIT-1)
+        expected = """
+        [i4]
+        i1 = int_ge(i4, 0)
+        guard_true(i1) []
+        i16 = int_floordiv(i4, 3)
+        finish(i16)
+        """
+        self.optimize_loop(ops, expected)
+
+    def test_division_by_2(self):
+        py.test.skip("harder")
+        ops = """
+        [i4]
+        i1 = int_ge(i4, 0)
+        guard_true(i1) []
+        i16 = int_floordiv(i4, 2)
+        i18 = int_mul(i16, 2)
+        i19 = int_sub(i4, i18)
+        i21 = int_rshift(i19, %d)
+        i22 = int_add(i16, i21)
+        finish(i22)
+        """ % (LONG_BIT-1)
+        expected = """
+        [i4]
+        i1 = int_ge(i4, 0)
+        guard_true(i1) []
+        i16 = int_rshift(i4, 1)
+        finish(i16)
+        """
+        self.optimize_loop(ops, expected)
+
     def test_subsub_ovf(self):
         ops = """
         [i0]
@@ -5377,6 +5507,96 @@
         jump()
         """
         self.optimize_loop(ops, expected)
+        # ----------
+        ops = """
+        [p1]
+        p0 = new_with_vtable(ConstClass(ptrobj_immut_vtable))
+        setfield_gc(p0, p1, descr=immut_ptrval)
+        escape(p0)
+        jump(p1)
+        """
+        self.optimize_loop(ops, ops)
+        # ----------
+        ops = """
+        []
+        p0 = new_with_vtable(ConstClass(ptrobj_immut_vtable))
+        p1 = new_with_vtable(ConstClass(intobj_immut_vtable))
+        setfield_gc(p1, 1242, descr=immut_intval)
+        setfield_gc(p0, p1, descr=immut_ptrval)
+        escape(p0)
+        jump()
+        """
+        class PtrObj1242(object):
+            _TYPE = llmemory.GCREF.TO
+            def __eq__(slf, other):
+                if slf is other:
+                    return 1
+                p1 = other.container.ptrval
+                p1cast = lltype.cast_pointer(lltype.Ptr(self.INTOBJ_IMMUT), p1)
+                return p1cast.intval == 1242
+        self.namespace['ptrobj1242'] = lltype._ptr(llmemory.GCREF,
+                                                   PtrObj1242())
+        expected = """
+        []
+        escape(ConstPtr(ptrobj1242))
+        jump()
+        """
+        self.optimize_loop(ops, expected)
+
+    def test_immutable_constantfold_recursive(self):
+        ops = """
+        []
+        p0 = new_with_vtable(ConstClass(ptrobj_immut_vtable))
+        setfield_gc(p0, p0, descr=immut_ptrval)
+        escape(p0)
+        jump()
+        """
+        from pypy.rpython.lltypesystem import lltype, llmemory
+        class PtrObjSelf(object):
+            _TYPE = llmemory.GCREF.TO
+            def __eq__(slf, other):
+                if slf is other:
+                    return 1
+                p1 = other.container.ptrval
+                p1cast = lltype.cast_pointer(lltype.Ptr(self.PTROBJ_IMMUT), p1)
+                return p1cast.ptrval == p1
+        self.namespace['ptrobjself'] = lltype._ptr(llmemory.GCREF,
+                                                   PtrObjSelf())
+        expected = """
+        []
+        escape(ConstPtr(ptrobjself))
+        jump()
+        """
+        self.optimize_loop(ops, expected)
+        #
+        ops = """
+        []
+        p0 = new_with_vtable(ConstClass(ptrobj_immut_vtable))
+        p1 = new_with_vtable(ConstClass(ptrobj_immut_vtable))
+        setfield_gc(p0, p1, descr=immut_ptrval)
+        setfield_gc(p1, p0, descr=immut_ptrval)
+        escape(p0)
+        jump()
+        """
+        class PtrObjSelf2(object):
+            _TYPE = llmemory.GCREF.TO
+            def __eq__(slf, other):
+                if slf is other:
+                    return 1
+                p1 = other.container.ptrval
+                p1cast = lltype.cast_pointer(lltype.Ptr(self.PTROBJ_IMMUT), p1)
+                p2 = p1cast.ptrval
+                assert p2 != p1
+                p2cast = lltype.cast_pointer(lltype.Ptr(self.PTROBJ_IMMUT), p2)
+                return p2cast.ptrval == p1
+        self.namespace['ptrobjself2'] = lltype._ptr(llmemory.GCREF,
+                                                    PtrObjSelf2())
+        expected = """
+        []
+        escape(ConstPtr(ptrobjself2))
+        jump()
+        """
+        self.optimize_loop(ops, expected)
 
     # ----------
     def optimize_strunicode_loop(self, ops, optops, preamble):
@@ -6235,12 +6455,15 @@
     def test_str2unicode_constant(self):
         ops = """
         []
+        escape(1213)
         p0 = call(0, "xy", descr=s2u_descr)      # string -> unicode
+        guard_no_exception() []
         escape(p0)
         jump()
         """
         expected = """
         []
+        escape(1213)
         escape(u"xy")
         jump()
         """
@@ -6250,6 +6473,7 @@
         ops = """
         [p0]
         p1 = call(0, p0, descr=s2u_descr)      # string -> unicode
+        guard_no_exception() []
         escape(p1)
         jump(p1)
         """
@@ -6258,6 +6482,21 @@
         # not obvious, because of the exception UnicodeDecodeError that
         # can be raised by ll_str2unicode()
 
+    def test_record_known_class(self):
+        ops = """
+        [p0]
+        p1 = getfield_gc(p0, descr=nextdescr)
+        record_known_class(p1, ConstClass(node_vtable))
+        guard_class(p1, ConstClass(node_vtable)) []
+        jump(p1)
+        """
+        expected = """
+        [p0]
+        p1 = getfield_gc(p0, descr=nextdescr)
+        jump(p1)
+        """
+        self.optimize_loop(ops, expected)
+
     def test_quasi_immut(self):
         ops = """
         [p0, p1, i0]
@@ -7309,6 +7548,150 @@
         """
         self.optimize_loop(ops, expected)
 
+    def test_repeated_constant_setfield_mixed_with_guard(self):
+        ops = """
+        [p22, p18]
+        setfield_gc(p22, 2, descr=valuedescr)
+        guard_nonnull_class(p18, ConstClass(node_vtable)) []
+        setfield_gc(p22, 2, descr=valuedescr)
+        jump(p22, p18)
+        """
+        preamble = """
+        [p22, p18]
+        setfield_gc(p22, 2, descr=valuedescr)
+        guard_nonnull_class(p18, ConstClass(node_vtable)) []
+        jump(p22, p18)
+        """
+        short = """
+        [p22, p18]
+        i1 = getfield_gc(p22, descr=valuedescr)
+        guard_value(i1, 2) []
+        jump(p22, p18)
+        """
+        expected = """
+        [p22, p18]
+        jump(p22, p18)
+        """
+        self.optimize_loop(ops, expected, preamble, expected_short=short)
+
+    def test_repeated_setfield_mixed_with_guard(self):
+        ops = """
+        [p22, p18, i1]
+        i2 = getfield_gc(p22, descr=valuedescr)
+        call(i2, descr=nonwritedescr)
+        setfield_gc(p22, i1, descr=valuedescr)
+        guard_nonnull_class(p18, ConstClass(node_vtable)) []
+        setfield_gc(p22, i1, descr=valuedescr)
+        jump(p22, p18, i1)
+        """
+        preamble = """
+        [p22, p18, i1]
+        i2 = getfield_gc(p22, descr=valuedescr)
+        call(i2, descr=nonwritedescr)
+        setfield_gc(p22, i1, descr=valuedescr)
+        guard_nonnull_class(p18, ConstClass(node_vtable)) []
+        jump(p22, p18, i1, i1)
+        """
+        short = """
+        [p22, p18, i1]
+        i2 = getfield_gc(p22, descr=valuedescr)
+        jump(p22, p18, i1, i2)
+        """
+        expected = """
+        [p22, p18, i1, i2]
+        call(i2, descr=nonwritedescr)
+        setfield_gc(p22, i1, descr=valuedescr)
+        jump(p22, p18, i1, i1)
+        """
+        self.optimize_loop(ops, expected, preamble, expected_short=short)
+
+    def test_cache_setfield_across_loop_boundaries(self):
+        ops = """
+        [p1]
+        p2 = getfield_gc(p1, descr=valuedescr)
+        guard_nonnull_class(p2, ConstClass(node_vtable)) []
+        call(p2, descr=nonwritedescr)
+        p3 = new_with_vtable(ConstClass(node_vtable))
+        setfield_gc(p1, p3, descr=valuedescr)
+        jump(p1)
+        """
+        expected = """
+        [p1, p2]
+        call(p2, descr=nonwritedescr)
+        p3 = new_with_vtable(ConstClass(node_vtable))
+        setfield_gc(p1, p3, descr=valuedescr)
+        jump(p1, p3)
+        """
+        self.optimize_loop(ops, expected)
+
+    def test_cache_setarrayitem_across_loop_boundaries(self):
+        ops = """
+        [p1]
+        p2 = getarrayitem_gc(p1, 3, descr=arraydescr)
+        guard_nonnull_class(p2, ConstClass(node_vtable)) []
+        call(p2, descr=nonwritedescr)
+        p3 = new_with_vtable(ConstClass(node_vtable))
+        setarrayitem_gc(p1, 3, p3, descr=arraydescr)
+        jump(p1)
+        """
+        expected = """
+        [p1, p2]
+        call(p2, descr=nonwritedescr)
+        p3 = new_with_vtable(ConstClass(node_vtable))
+        setarrayitem_gc(p1, 3, p3, descr=arraydescr)
+        jump(p1, p3)
+        """
+        self.optimize_loop(ops, expected)
+
+    def test_setarrayitem_p0_p0(self):
+        ops = """
+        [i0, i1]
+        p0 = escape()
+        setarrayitem_gc(p0, 2, p0, descr=arraydescr)
+        jump(i0, i1)
+        """
+        expected = """
+        [i0, i1]
+        p0 = escape()
+        setarrayitem_gc(p0, 2, p0, descr=arraydescr)
+        jump(i0, i1)
+        """
+        self.optimize_loop(ops, expected)
+
+    def test_setfield_p0_p0(self):
+        ops = """
+        [i0, i1]
+        p0 = escape()
+        setfield_gc(p0, p0, descr=arraydescr)
+        jump(i0, i1)
+        """
+        expected = """
+        [i0, i1]
+        p0 = escape()
+        setfield_gc(p0, p0, descr=arraydescr)
+        jump(i0, i1)
+        """
+        self.optimize_loop(ops, expected)
+
+    def test_setfield_p0_p1_p0(self):
+        ops = """
+        [i0, i1]
+        p0 = escape()
+        p1 = escape()
+        setfield_gc(p0, p1, descr=adescr)
+        setfield_gc(p1, p0, descr=bdescr)
+        jump(i0, i1)
+        """
+        expected = """
+        [i0, i1]
+        p0 = escape()
+        p1 = escape()
+        setfield_gc(p0, p1, descr=adescr)
+        setfield_gc(p1, p0, descr=bdescr)
+        jump(i0, i1)
+        """
+        self.optimize_loop(ops, expected)
+
 class TestLLtype(OptimizeOptTest, LLtypeMixin):
     pass
 
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_util.py b/pypy/jit/metainterp/optimizeopt/test/test_util.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_util.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_util.py
@@ -139,6 +139,12 @@
     noimmut_intval = cpu.fielddescrof(INTOBJ_NOIMMUT, 'intval')
     immut_intval = cpu.fielddescrof(INTOBJ_IMMUT, 'intval')
 
+    PTROBJ_IMMUT = lltype.GcStruct('PTROBJ_IMMUT', ('parent', OBJECT),
+                                            ('ptrval', lltype.Ptr(OBJECT)),
+                                            hints={'immutable': True})
+    ptrobj_immut_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
+    immut_ptrval = cpu.fielddescrof(PTROBJ_IMMUT, 'ptrval')
+
     arraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Signed))
     floatarraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Float))
 
@@ -183,6 +189,7 @@
                             can_invalidate=True))
     arraycopydescr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
              EffectInfo([], [arraydescr], [], [arraydescr],
+                        EffectInfo.EF_CANNOT_RAISE,
                         oopspecindex=EffectInfo.OS_ARRAYCOPY))
 
 
@@ -212,12 +219,14 @@
         _oopspecindex = getattr(EffectInfo, _os)
         locals()[_name] = \
             cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                EffectInfo([], [], [], [], oopspecindex=_oopspecindex))
+                EffectInfo([], [], [], [], EffectInfo.EF_CANNOT_RAISE,
+                           oopspecindex=_oopspecindex))
         #
         _oopspecindex = getattr(EffectInfo, _os.replace('STR', 'UNI'))
         locals()[_name.replace('str', 'unicode')] = \
             cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
-                EffectInfo([], [], [], [], oopspecindex=_oopspecindex))
+                EffectInfo([], [], [], [], EffectInfo.EF_CANNOT_RAISE,
+                           oopspecindex=_oopspecindex))
 
     s2u_descr = cpu.calldescrof(FUNC, FUNC.ARGS, FUNC.RESULT,
             EffectInfo([], [], [], [], oopspecindex=EffectInfo.OS_STR2UNICODE))
@@ -243,6 +252,7 @@
     register_known_gctype(cpu, jit_virtual_ref_vtable,vrefinfo.JIT_VIRTUAL_REF)
     register_known_gctype(cpu, intobj_noimmut_vtable, INTOBJ_NOIMMUT)
     register_known_gctype(cpu, intobj_immut_vtable,   INTOBJ_IMMUT)
+    register_known_gctype(cpu, ptrobj_immut_vtable,   PTROBJ_IMMUT)
 
     namespace = locals()
 
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
@@ -87,14 +87,36 @@
     def _get_descr(self):
         raise NotImplementedError
 
-    def _is_immutable_and_filled_with_constants(self, optforce):
+    def _is_immutable_and_filled_with_constants(self, memo=None):
+        # check if it is possible to force the given structure into a
+        # compile-time constant: this is allowed only if it is declared
+        # immutable, if all fields are already filled, and if each field
+        # is either a compile-time constant or (recursively) a structure
+        # which also answers True to the same question.
+        #
+        # check that all fields are filled.  The following equality check
+        # also fails if count == -1, meaning "not an immutable at all".
         count = self._get_descr().count_fields_if_immutable()
-        if count != len(self._fields):    # always the case if count == -1
+        if count != len(self._fields):
             return False
+        #
+        # initialize 'memo'
+        if memo is None:
+            memo = {}
+        elif self in memo:
+            return True   # recursive case: assume yes
+        memo[self] = None
+        #
         for value in self._fields.itervalues():
-            subbox = value.force_box(optforce)
-            if not isinstance(subbox, Const):
-                return False
+            if value.is_constant():
+                pass            # it is a constant value: ok
+            elif (isinstance(value, AbstractVirtualStructValue)
+                  and value.is_virtual()):
+                # recursive check
+                if not value._is_immutable_and_filled_with_constants(memo):
+                    return False
+            else:
+                return False    # not a constant at all
         return True
 
     def force_at_end_of_preamble(self, already_forced, optforce):
@@ -114,7 +136,7 @@
         if not we_are_translated():
             op.name = 'FORCE ' + self.source_op.name
 
-        if self._is_immutable_and_filled_with_constants(optforce):
+        if self._is_immutable_and_filled_with_constants():
             box = optforce.optimizer.constant_fold(op)
             self.make_constant(box)
             for ofs, value in self._fields.iteritems():
@@ -294,7 +316,12 @@
         optforce.emit_operation(self.source_op)
         self.box = box = self.source_op.result
         for index in range(len(self._items)):
-            for descr, value in self._items[index].iteritems():
+            iteritems = self._items[index].iteritems()
+            # random order is fine, except for tests
+            if not we_are_translated():
+                iteritems = list(iteritems)
+                iteritems.sort(key = lambda (x, y): x.sort_key())
+            for descr, value in iteritems:
                 subbox = value.force_box(optforce)
                 op = ResOperation(rop.SETINTERIORFIELD_GC,
                     [box, ConstInt(index), subbox], None, descr=descr
diff --git a/pypy/jit/metainterp/optimizeopt/virtualstate.py b/pypy/jit/metainterp/optimizeopt/virtualstate.py
--- a/pypy/jit/metainterp/optimizeopt/virtualstate.py
+++ b/pypy/jit/metainterp/optimizeopt/virtualstate.py
@@ -551,6 +551,7 @@
         optimizer.produce_potential_short_preamble_ops(self)
 
         self.short_boxes = {}
+        self.short_boxes_in_production = {}
 
         for box in self.potential_ops.keys():
             try:
@@ -606,6 +607,10 @@
             return
         if isinstance(box, Const):
             return
+        if box in self.short_boxes_in_production:
+            raise BoxNotProducable
+        self.short_boxes_in_production[box] = True
+        
         if box in self.potential_ops:
             ops = self.prioritized_alternatives(box)
             produced_one = False
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
@@ -1,8 +1,9 @@
 from pypy.jit.codewriter.effectinfo import EffectInfo
 from pypy.jit.metainterp.history import (BoxInt, Const, ConstInt, ConstPtr,
-    get_const_ptr_for_string, get_const_ptr_for_unicode)
+    get_const_ptr_for_string, get_const_ptr_for_unicode, BoxPtr, REF, INT)
 from pypy.jit.metainterp.optimizeopt import optimizer, virtualize
-from pypy.jit.metainterp.optimizeopt.optimizer import CONST_0, CONST_1, llhelper
+from pypy.jit.metainterp.optimizeopt.optimizer import CONST_0, CONST_1
+from pypy.jit.metainterp.optimizeopt.optimizer import llhelper, REMOVED
 from pypy.jit.metainterp.optimizeopt.util import make_dispatcher_method
 from pypy.jit.metainterp.resoperation import rop, ResOperation
 from pypy.rlib.objectmodel import specialize, we_are_translated
@@ -106,7 +107,12 @@
         if not we_are_translated():
             op.name = 'FORCE'
         optforce.emit_operation(op)
-        self.string_copy_parts(optforce, box, CONST_0, self.mode)
+        self.initialize_forced_string(optforce, box, CONST_0, self.mode)
+
+    def initialize_forced_string(self, string_optimizer, targetbox,
+                                 offsetbox, mode):
+        return self.string_copy_parts(string_optimizer, targetbox,
+                                      offsetbox, mode)
 
 
 class VStringPlainValue(VAbstractStringValue):
@@ -114,11 +120,20 @@
     _lengthbox = None     # cache only
 
     def setup(self, size):
-        self._chars = [optimizer.CVAL_UNINITIALIZED_ZERO] * size
+        # in this list, None means: "it's probably uninitialized so far,
+        # but maybe it was actually filled."  So to handle this case,
+        # strgetitem cannot be virtual-ized and must be done as a residual
+        # operation.  By contrast, any non-None value means: we know it
+        # is initialized to this value; strsetitem() there makes no sense.
+        # Also, as long as self.is_virtual(), then we know that no-one else
+        # could have written to the string, so we know that in this case
+        # "None" corresponds to "really uninitialized".
+        self._chars = [None] * size
 
     def setup_slice(self, longerlist, start, stop):
         assert 0 <= start <= stop <= len(longerlist)
         self._chars = longerlist[start:stop]
+        # slice the 'longerlist', which may also contain Nones
 
     def getstrlen(self, _, mode):
         if self._lengthbox is None:
@@ -126,42 +141,66 @@
         return self._lengthbox
 
     def getitem(self, index):
-        return self._chars[index]
+        return self._chars[index]     # may return None!
 
     def setitem(self, index, charvalue):
         assert isinstance(charvalue, optimizer.OptValue)
+        assert self._chars[index] is None, (
+            "setitem() on an already-initialized location")
         self._chars[index] = charvalue
 
+    def is_completely_initialized(self):
+        for c in self._chars:
+            if c is None:
+                return False
+        return True
+
     @specialize.arg(1)
     def get_constant_string_spec(self, mode):
         for c in self._chars:
-            if c is optimizer.CVAL_UNINITIALIZED_ZERO or not c.is_constant():
+            if c is None or not c.is_constant():
                 return None
         return mode.emptystr.join([mode.chr(c.box.getint())
                                    for c in self._chars])
 
     def string_copy_parts(self, string_optimizer, targetbox, offsetbox, mode):
-        if not self.is_virtual() and targetbox is not self.box:
-            lengthbox = self.getstrlen(string_optimizer, mode)
-            srcbox = self.force_box(string_optimizer)
-            return copy_str_content(string_optimizer, srcbox, targetbox,
-                                CONST_0, offsetbox, lengthbox, mode)
+        if not self.is_virtual() and not self.is_completely_initialized():
+            return VAbstractStringValue.string_copy_parts(
+                self, string_optimizer, targetbox, offsetbox, mode)
+        else:
+            return self.initialize_forced_string(string_optimizer, targetbox,
+                                                 offsetbox, mode)
+
+    def initialize_forced_string(self, string_optimizer, targetbox,
+                                 offsetbox, mode):
         for i in range(len(self._chars)):
-            charbox = self._chars[i].force_box(string_optimizer)
-            if not (isinstance(charbox, Const) and charbox.same_constant(CONST_0)):
-                string_optimizer.emit_operation(ResOperation(mode.STRSETITEM, [targetbox,
-                                                                               offsetbox,
-                                                                               charbox],
-                                                  None))
+            assert isinstance(targetbox, BoxPtr)   # ConstPtr never makes sense
+            charvalue = self.getitem(i)
+            if charvalue is not None:
+                charbox = charvalue.force_box(string_optimizer)
+                if not (isinstance(charbox, Const) and
+                        charbox.same_constant(CONST_0)):
+                    op = ResOperation(mode.STRSETITEM, [targetbox,
+                                                        offsetbox,
+                                                        charbox],
+                                      None)
+                    string_optimizer.emit_operation(op)
             offsetbox = _int_add(string_optimizer, offsetbox, CONST_1)
         return offsetbox
 
     def get_args_for_fail(self, modifier):
         if self.box is None and not modifier.already_seen_virtual(self.keybox):
-            charboxes = [value.get_key_box() for value in self._chars]
+            charboxes = []
+            for value in self._chars:
+                if value is not None:
+                    box = value.get_key_box()
+                else:
+                    box = None
+                charboxes.append(box)
             modifier.register_virtual_fields(self.keybox, charboxes)
             for value in self._chars:
-                value.get_args_for_fail(modifier)
+                if value is not None:
+                    value.get_args_for_fail(modifier)
 
     def _make_virtual(self, modifier):
         return modifier.make_vstrplain(self.mode is mode_unicode)
@@ -169,6 +208,7 @@
 
 class VStringConcatValue(VAbstractStringValue):
     """The concatenation of two other strings."""
+    _attrs_ = ('left', 'right', 'lengthbox')
 
     lengthbox = None     # or the computed length
 
@@ -277,6 +317,7 @@
         for i in range(lengthbox.value):
             charbox = _strgetitem(string_optimizer, srcbox, srcoffsetbox, mode)
             srcoffsetbox = _int_add(string_optimizer, srcoffsetbox, CONST_1)
+            assert isinstance(targetbox, BoxPtr)   # ConstPtr never makes sense
             string_optimizer.emit_operation(ResOperation(mode.STRSETITEM, [targetbox,
                                                                            offsetbox,
                                                                            charbox],
@@ -287,6 +328,7 @@
             nextoffsetbox = _int_add(string_optimizer, offsetbox, lengthbox)
         else:
             nextoffsetbox = None
+        assert isinstance(targetbox, BoxPtr)   # ConstPtr never makes sense
         op = ResOperation(mode.COPYSTRCONTENT, [srcbox, targetbox,
                                                 srcoffsetbox, offsetbox,
                                                 lengthbox], None)
@@ -373,6 +415,7 @@
 
     def optimize_STRSETITEM(self, op):
         value = self.getvalue(op.getarg(0))
+        assert not value.is_constant() # strsetitem(ConstPtr) never makes sense
         if value.is_virtual() and isinstance(value, VStringPlainValue):
             indexbox = self.get_constant_box(op.getarg(1))
             if indexbox is not None:
@@ -406,11 +449,20 @@
         #
         if isinstance(value, VStringPlainValue):  # even if no longer virtual
             if vindex.is_constant():
-                res = value.getitem(vindex.box.getint())
-                # If it is uninitialized we can't return it, it was set by a
-                # COPYSTRCONTENT, not a STRSETITEM
-                if res is not optimizer.CVAL_UNINITIALIZED_ZERO:
-                    return res
+                result = value.getitem(vindex.box.getint())
+                if result is not None:
+                    return result
+        #
+        if isinstance(value, VStringConcatValue) and vindex.is_constant():
+            len1box = value.left.getstrlen(self, mode)
+            if isinstance(len1box, ConstInt):
+                index = vindex.box.getint()
+                len1 = len1box.getint()
+                if index < len1:
+                    return self.strgetitem(value.left, vindex, mode)
+                else:
+                    vindex = optimizer.ConstantValue(ConstInt(index - len1))
+                    return self.strgetitem(value.right, vindex, mode)
         #
         resbox = _strgetitem(self, value.force_box(self), vindex.force_box(self), mode)
         return self.getvalue(resbox)
@@ -432,6 +484,11 @@
 
     def _optimize_COPYSTRCONTENT(self, op, mode):
         # args: src dst srcstart dststart length
+        assert op.getarg(0).type == REF
+        assert op.getarg(1).type == REF
+        assert op.getarg(2).type == INT
+        assert op.getarg(3).type == INT
+        assert op.getarg(4).type == INT
         src = self.getvalue(op.getarg(0))
         dst = self.getvalue(op.getarg(1))
         srcstart = self.getvalue(op.getarg(2))
@@ -473,6 +530,11 @@
 
     optimize_CALL_PURE = optimize_CALL
 
+    def optimize_GUARD_NO_EXCEPTION(self, op):
+        if self.last_emitted_operation is REMOVED:
+            return
+        self.emit_operation(op)
+
     def opt_call_str_STR2UNICODE(self, op):
         # Constant-fold unicode("constant string").
         # More generally, supporting non-constant but virtual cases is
@@ -487,6 +549,7 @@
         except UnicodeDecodeError:
             return False
         self.make_constant(op.result, get_const_ptr_for_unicode(u))
+        self.last_emitted_operation = REMOVED
         return True
 
     def opt_call_stroruni_STR_CONCAT(self, op, mode):
@@ -503,13 +566,12 @@
         vstart = self.getvalue(op.getarg(2))
         vstop = self.getvalue(op.getarg(3))
         #
-        if (isinstance(vstr, VStringPlainValue) and vstart.is_constant()
-            and vstop.is_constant()):
-            # slicing with constant bounds of a VStringPlainValue
-            value = self.make_vstring_plain(op.result, op, mode)
-            value.setup_slice(vstr._chars, vstart.box.getint(),
-                                           vstop.box.getint())
-            return True
+        #if (isinstance(vstr, VStringPlainValue) and vstart.is_constant()
+        #    and vstop.is_constant()):
+        #    value = self.make_vstring_plain(op.result, op, mode)
+        #    value.setup_slice(vstr._chars, vstart.box.getint(),
+        #                      vstop.box.getint())
+        #    return True
         #
         vstr.ensure_nonnull()
         lengthbox = _int_sub(self, vstop.force_box(self),
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -243,6 +243,18 @@
     def opimpl_mark_opaque_ptr(self, box):
         return self.execute(rop.MARK_OPAQUE_PTR, box)
 
+    @arguments("box", "box")
+    def opimpl_record_known_class(self, box, clsbox):
+        from pypy.rpython.lltypesystem import llmemory
+        if self.metainterp.heapcache.is_class_known(box):
+            return
+        adr = clsbox.getaddr()
+        bounding_class = llmemory.cast_adr_to_ptr(adr, rclass.CLASSTYPE)
+        if bounding_class.subclassrange_max - bounding_class.subclassrange_min == 1:
+            # precise class knowledge, this can be used
+            self.execute(rop.RECORD_KNOWN_CLASS, box, clsbox)
+            self.metainterp.heapcache.class_now_known(box)
+
     @arguments("box")
     def _opimpl_any_return(self, box):
         self.metainterp.finishframe(box)
@@ -1345,10 +1357,8 @@
             if effect == effectinfo.EF_LOOPINVARIANT:
                 return self.execute_varargs(rop.CALL_LOOPINVARIANT, allboxes,
                                             descr, False, False)
-            exc = (effect != effectinfo.EF_CANNOT_RAISE and
-                   effect != effectinfo.EF_ELIDABLE_CANNOT_RAISE)
-            pure = (effect == effectinfo.EF_ELIDABLE_CAN_RAISE or
-                    effect == effectinfo.EF_ELIDABLE_CANNOT_RAISE)
+            exc = effectinfo.check_can_raise()
+            pure = effectinfo.check_is_elidable()
             return self.execute_varargs(rop.CALL, allboxes, descr, exc, pure)
 
     def do_residual_or_indirect_call(self, funcbox, calldescr, argboxes):
@@ -1780,7 +1790,6 @@
         self.staticdata.profiler.count(reason)
         debug_print('~~~ ABORTING TRACING')
         self.staticdata.stats.aborted()
-        self.resumekey.reset_counter_from_failure()
 
     def blackhole_if_trace_too_long(self):
         warmrunnerstate = self.jitdriver_sd.warmstate
diff --git a/pypy/jit/metainterp/resoperation.py b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -90,7 +90,10 @@
         return op
 
     def __repr__(self):
-        return self.repr()
+        try:
+            return self.repr()
+        except NotImplementedError:
+            return object.__repr__(self)
 
     def repr(self, graytext=False):
         # RPython-friendly version
@@ -458,6 +461,7 @@
     'GETARRAYITEM_GC/2d',
     'GETARRAYITEM_RAW/2d',
     'GETINTERIORFIELD_GC/2d',
+    'GETINTERIORFIELD_RAW/2d',
     'GETFIELD_GC/1d',
     'GETFIELD_RAW/1d',
     '_MALLOC_FIRST',
@@ -476,6 +480,7 @@
     'SETARRAYITEM_GC/3d',
     'SETARRAYITEM_RAW/3d',
     'SETINTERIORFIELD_GC/3d',
+    'SETINTERIORFIELD_RAW/3d',
     'SETFIELD_GC/2d',
     'SETFIELD_RAW/2d',
     'STRSETITEM/3',
@@ -489,6 +494,7 @@
     'COPYSTRCONTENT/5',       # src, dst, srcstart, dststart, length
     'COPYUNICODECONTENT/5',
     'QUASIIMMUT_FIELD/1d',    # [objptr], descr=SlowMutateDescr
+    'RECORD_KNOWN_CLASS/2',   # [objptr, clsptr]
 
     '_CANRAISE_FIRST', # ----- start of can_raise operations -----
     '_CALL_FIRST',
diff --git a/pypy/jit/metainterp/resume.py b/pypy/jit/metainterp/resume.py
--- a/pypy/jit/metainterp/resume.py
+++ b/pypy/jit/metainterp/resume.py
@@ -93,12 +93,14 @@
 
 TAGMASK = 3
 
+class TagOverflow(Exception):
+    pass
+
 def tag(value, tagbits):
-    if tagbits >> 2:
-        raise ValueError
+    assert 0 <= tagbits <= 3
     sx = value >> 13
     if sx != 0 and sx != -1:
-        raise ValueError
+        raise TagOverflow
     return rffi.r_short(value<<2|tagbits)
 
 def untag(value):
@@ -126,6 +128,7 @@
 UNASSIGNED = tag(-1<<13, TAGBOX)
 UNASSIGNEDVIRTUAL = tag(-1<<13, TAGVIRTUAL)
 NULLREF = tag(-1, TAGCONST)
+UNINITIALIZED = tag(-2, TAGCONST)   # used for uninitialized string characters
 
 
 class ResumeDataLoopMemo(object):
@@ -152,7 +155,7 @@
                 return self._newconst(const)
             try:
                 return tag(val, TAGINT)
-            except ValueError:
+            except TagOverflow:
                 pass
             tagged = self.large_ints.get(val, UNASSIGNED)
             if not tagged_eq(tagged, UNASSIGNED):
@@ -428,8 +431,7 @@
                 fieldnum = self._gettagged(fieldbox)
                 # the index is limited to 2147483647 (64-bit machines only)
                 if itemindex > 2147483647:
-                    from pypy.jit.metainterp import compile
-                    compile.giveup()
+                    raise TagOverflow
                 itemindex = rffi.cast(rffi.INT, itemindex)
                 #
                 rd_pendingfields[i].lldescr  = lldescr
@@ -439,6 +441,8 @@
         self.storage.rd_pendingfields = rd_pendingfields
 
     def _gettagged(self, box):
+        if box is None:
+            return UNINITIALIZED
         if isinstance(box, Const):
             return self.memo.getconst(box)
         else:
@@ -572,7 +576,9 @@
         string = decoder.allocate_string(length)
         decoder.virtuals_cache[index] = string
         for i in range(length):
-            decoder.string_setitem(string, i, self.fieldnums[i])
+            charnum = self.fieldnums[i]
+            if not tagged_eq(charnum, UNINITIALIZED):
+                decoder.string_setitem(string, i, charnum)
         return string
 
     def debug_prints(self):
@@ -625,7 +631,9 @@
         string = decoder.allocate_unicode(length)
         decoder.virtuals_cache[index] = string
         for i in range(length):
-            decoder.unicode_setitem(string, i, self.fieldnums[i])
+            charnum = self.fieldnums[i]
+            if not tagged_eq(charnum, UNINITIALIZED):
+                decoder.unicode_setitem(string, i, charnum)
         return string
 
     def debug_prints(self):
diff --git a/pypy/jit/metainterp/test/support.py b/pypy/jit/metainterp/test/support.py
--- a/pypy/jit/metainterp/test/support.py
+++ b/pypy/jit/metainterp/test/support.py
@@ -12,7 +12,7 @@
 from pypy.rlib.rfloat import isnan
 
 def _get_jitcodes(testself, CPUClass, func, values, type_system,
-                  supports_longlong=False, **kwds):
+                  supports_longlong=False, translationoptions={}, **kwds):
     from pypy.jit.codewriter import support
 
     class FakeJitCell(object):
@@ -42,7 +42,8 @@
         enable_opts = ALL_OPTS_DICT
 
     func._jit_unroll_safe_ = True
-    rtyper = support.annotate(func, values, type_system=type_system)
+    rtyper = support.annotate(func, values, type_system=type_system,
+                              translationoptions=translationoptions)
     graphs = rtyper.annotator.translator.graphs
     testself.all_graphs = graphs
     result_kind = history.getkind(graphs[0].getreturnvar().concretetype)[0]
@@ -154,9 +155,11 @@
 
 class JitMixin:
     basic = True
-    def check_loops(self, expected=None, everywhere=False, **check):
-        get_stats().check_loops(expected=expected, everywhere=everywhere,
-                                **check)
+    def check_resops(self, expected=None, **check):
+        get_stats().check_resops(expected=expected, **check)
+    def check_simple_loop(self, expected=None, **check):
+        get_stats().check_simple_loop(expected=expected, **check)
+
     def check_loop_count(self, count):
         """NB. This is a hack; use check_tree_loop_count() or
         check_enter_count() for the real thing.
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
@@ -14,7 +14,7 @@
 from pypy.rlib.jit import (JitDriver, we_are_jitted, hint, dont_look_inside,
     loop_invariant, elidable, promote, jit_debug, assert_green,
     AssertGreenFailed, unroll_safe, current_trace_length, look_inside_iff,
-    isconstant, isvirtual, promote_string)
+    isconstant, isvirtual, promote_string, set_param, record_known_class)
 from pypy.rlib.rarithmetic import ovfcheck
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi
 from pypy.rpython.ootypesystem import ootype
@@ -79,9 +79,8 @@
         res = self.meta_interp(f, [6, 7])
         assert res == 42
         self.check_loop_count(1)
-        self.check_loops({'guard_true': 1,
-                          'int_add': 1, 'int_sub': 1, 'int_gt': 1,
-                          'jump': 1})
+        self.check_resops({'jump': 2, 'int_gt': 2, 'int_add': 2, 'guard_true': 2, 'int_sub': 2})
+
         if self.basic:
             found = 0
             for op in get_stats().loops[0]._all_operations():
@@ -108,7 +107,7 @@
         res = self.meta_interp(f, [6, 7])
         assert res == 1323
         self.check_loop_count(1)
-        self.check_loops(int_mul=1)
+        self.check_simple_loop(int_mul=1)
 
     def test_loop_variant_mul_ovf(self):
         myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
@@ -125,7 +124,7 @@
         res = self.meta_interp(f, [6, 7])
         assert res == 1323
         self.check_loop_count(1)
-        self.check_loops(int_mul_ovf=1)
+        self.check_simple_loop(int_mul_ovf=1)
 
     def test_loop_invariant_mul1(self):
         myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
@@ -140,9 +139,10 @@
         res = self.meta_interp(f, [6, 7])
         assert res == 252
         self.check_loop_count(1)
-        self.check_loops({'guard_true': 1,
-                          'int_add': 1, 'int_sub': 1, 'int_gt': 1,
-                          'jump': 1})
+        self.check_simple_loop(int_mul=0)
+        self.check_resops({'jump': 2, 'int_gt': 2, 'int_add': 2,
+                           'int_mul': 1, 'guard_true': 2, 'int_sub': 2})
+
 
     def test_loop_invariant_mul_ovf(self):
         myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
@@ -158,10 +158,11 @@
         res = self.meta_interp(f, [6, 7])
         assert res == 308
         self.check_loop_count(1)
-        self.check_loops({'guard_true': 1,
-                          'int_add': 2, 'int_sub': 1, 'int_gt': 1,
-                          'int_lshift': 1,
-                          'jump': 1})
+        self.check_simple_loop(int_mul_ovf=0)
+        self.check_resops({'jump': 2, 'int_lshift': 2, 'int_gt': 2,
+                           'int_mul_ovf': 1, 'int_add': 4,
+                           'guard_true': 2, 'guard_no_overflow': 1,
+                           'int_sub': 2})
 
     def test_loop_invariant_mul_bridge1(self):
         myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
@@ -194,11 +195,9 @@
         res = self.meta_interp(f, [6, 32])
         assert res == 1167
         self.check_loop_count(3)
-        self.check_loops({'int_add': 3, 'int_lt': 2,
-                          'int_sub': 2, 'guard_false': 1,
-                          'jump': 2,
-                          'int_gt': 1, 'guard_true': 2})
-
+        self.check_resops({'int_lt': 3, 'int_gt': 2, 'int_add': 5,
+                           'guard_true': 3, 'int_sub': 4, 'jump': 4,
+                           'int_mul': 2, 'guard_false': 2})
 
     def test_loop_invariant_mul_bridge_maintaining2(self):
         myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
@@ -216,10 +215,9 @@
         res = self.meta_interp(f, [6, 32])
         assert res == 1692
         self.check_loop_count(3)
-        self.check_loops({'int_add': 3, 'int_lt': 2,
-                          'int_sub': 2, 'guard_false': 1,
-                          'jump': 2,
-                          'int_gt': 1, 'guard_true': 2})
+        self.check_resops({'int_lt': 3, 'int_gt': 2, 'int_add': 5,
+                           'guard_true': 3, 'int_sub': 4, 'jump': 4,
+                           'int_mul': 2, 'guard_false': 2})
 
     def test_loop_invariant_mul_bridge_maintaining3(self):
         myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x', 'm'])
@@ -237,10 +235,9 @@
         res = self.meta_interp(f, [6, 32, 16])
         assert res == 1692
         self.check_loop_count(3)
-        self.check_loops({'int_add': 2, 'int_lt': 1,
-                          'int_sub': 2, 'guard_false': 1,
-                          'jump': 2, 'int_mul': 1,
-                          'int_gt': 2, 'guard_true': 2})
+        self.check_resops({'int_lt': 2, 'int_gt': 4, 'guard_false': 2,
+                           'guard_true': 4, 'int_sub': 4, 'jump': 4,
+                           'int_mul': 3, 'int_add': 4})
 
     def test_loop_invariant_intbox(self):
         myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
@@ -261,9 +258,9 @@
         res = self.meta_interp(f, [6, 7])
         assert res == 252
         self.check_loop_count(1)
-        self.check_loops({'guard_true': 1,
-                          'int_add': 1, 'int_sub': 1, 'int_gt': 1,
-                          'jump': 1})
+        self.check_resops({'jump': 2, 'int_gt': 2, 'int_add': 2,
+                           'getfield_gc_pure': 1, 'int_mul': 1,
+                           'guard_true': 2, 'int_sub': 2})
 
     def test_loops_are_transient(self):
         import gc, weakref
@@ -381,7 +378,7 @@
         assert res == 0
         # CALL_PURE is recorded in the history, but turned into a CALL
         # by optimizeopt.py
-        self.check_loops(int_sub=0, call=1, call_pure=0)
+        self.check_resops(call_pure=0, call=2, int_sub=0)
 
     def test_constfold_call_elidable(self):
         myjitdriver = JitDriver(greens = ['m'], reds = ['n'])
@@ -397,7 +394,7 @@
         res = self.meta_interp(f, [21, 5])
         assert res == -1
         # the CALL_PURE is constant-folded away by optimizeopt.py
-        self.check_loops(int_sub=1, call=0, call_pure=0)
+        self.check_resops(call_pure=0, call=0, int_sub=2)
 
     def test_constfold_call_elidable_2(self):
         myjitdriver = JitDriver(greens = ['m'], reds = ['n'])
@@ -417,7 +414,7 @@
         res = self.meta_interp(f, [21, 5])
         assert res == -1
         # the CALL_PURE is constant-folded away by optimizeopt.py
-        self.check_loops(int_sub=1, call=0, call_pure=0)
+        self.check_resops(call_pure=0, call=0, int_sub=2)
 
     def test_elidable_function_returning_object(self):
         myjitdriver = JitDriver(greens = ['m'], reds = ['n'])
@@ -442,7 +439,7 @@
         res = self.meta_interp(f, [21, 5])
         assert res == -1
         # the CALL_PURE is constant-folded away by optimizeopt.py
-        self.check_loops(int_sub=1, call=0, call_pure=0, getfield_gc=0)
+        self.check_resops(call_pure=0, call=0, getfield_gc=1, int_sub=2)
 
     def test_elidable_raising(self):
         myjitdriver = JitDriver(greens = ['m'], reds = ['n'])
@@ -463,12 +460,12 @@
         res = self.meta_interp(f, [22, 6])
         assert res == -3
         # the CALL_PURE is constant-folded away during tracing
-        self.check_loops(int_sub=1, call=0, call_pure=0)
+        self.check_resops(call_pure=0, call=0, int_sub=2)
         #
         res = self.meta_interp(f, [22, -5])
         assert res == 0
         # raises: becomes CALL and is not constant-folded away
-        self.check_loops(int_sub=1, call=1, call_pure=0)
+        self.check_resops(call_pure=0, call=2, int_sub=2)
 
     def test_elidable_raising_2(self):
         myjitdriver = JitDriver(greens = ['m'], reds = ['n'])
@@ -489,12 +486,12 @@
         res = self.meta_interp(f, [22, 6])
         assert res == -3
         # the CALL_PURE is constant-folded away by optimizeopt.py
-        self.check_loops(int_sub=1, call=0, call_pure=0)
+        self.check_resops(call_pure=0, call=0, int_sub=2)
         #
         res = self.meta_interp(f, [22, -5])
         assert res == 0
         # raises: becomes CALL and is not constant-folded away
-        self.check_loops(int_sub=1, call=1, call_pure=0)
+        self.check_resops(call_pure=0, call=2, int_sub=2)
 
     def test_constant_across_mp(self):
         myjitdriver = JitDriver(greens = [], reds = ['n'])
@@ -533,7 +530,7 @@
         policy = StopAtXPolicy(externfn)
         res = self.meta_interp(f, [31], policy=policy)
         assert res == 42
-        self.check_loops(int_mul=1, int_mod=0)
+        self.check_resops(int_mul=2, int_mod=0)
 
     def test_we_are_jitted(self):
         myjitdriver = JitDriver(greens = [], reds = ['y'])
@@ -835,7 +832,7 @@
             return n
         res = self.meta_interp(f, [20, 1, 2])
         assert res == 0
-        self.check_loops(call=0)
+        self.check_resops(call=0)
 
     def test_abs(self):
         myjitdriver = JitDriver(greens = [], reds = ['i', 't'])
@@ -865,9 +862,8 @@
         res = self.meta_interp(f, [6, 7])
         assert res == 42.0
         self.check_loop_count(1)
-        self.check_loops({'guard_true': 1,
-                          'float_add': 1, 'float_sub': 1, 'float_gt': 1,
-                          'jump': 1})
+        self.check_resops({'jump': 2, 'float_gt': 2, 'float_add': 2,
+                           'float_sub': 2, 'guard_true': 2})
 
     def test_print(self):
         myjitdriver = JitDriver(greens = [], reds = ['n'])
@@ -1038,7 +1034,7 @@
             return x
         res = self.meta_interp(f, [20], enable_opts='')
         assert res == f(20)
-        self.check_loops(call=0)
+        self.check_resops(call=0)
 
     def test_zerodivisionerror(self):
         # test the case of exception-raising operation that is not delegated
@@ -1256,15 +1252,18 @@
                 n -= 1
                 x += n
             return x
-        def f(n, threshold):
-            myjitdriver.set_param('threshold', threshold)
+        def f(n, threshold, arg):
+            if arg:
+                set_param(myjitdriver, 'threshold', threshold)
+            else:
+                set_param(None, 'threshold', threshold)
             return g(n)
 
-        res = self.meta_interp(f, [10, 3])
+        res = self.meta_interp(f, [10, 3, 1])
         assert res == 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 0
         self.check_tree_loop_count(2)
 
-        res = self.meta_interp(f, [10, 13])
+        res = self.meta_interp(f, [10, 13, 0])
         assert res == 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 0
         self.check_tree_loop_count(0)
 
@@ -1348,7 +1347,7 @@
         res = self.meta_interp(f, [6, 7])
         assert res == 42
         self.check_loop_count(1)
-        self.check_loops(call=1)
+        self.check_resops(call=2)
 
     def test_merge_guardclass_guardvalue(self):
         from pypy.rlib.objectmodel import instantiate
@@ -1375,8 +1374,7 @@
             return x
         res = self.meta_interp(f, [299], listops=True)
         assert res == f(299)
-        self.check_loops(guard_class=0, guard_value=3)
-        self.check_loops(guard_class=0, guard_value=6, everywhere=True)
+        self.check_resops(guard_class=0, guard_value=6)
 
     def test_merge_guardnonnull_guardclass(self):
         from pypy.rlib.objectmodel import instantiate
@@ -1404,11 +1402,9 @@
             return x
         res = self.meta_interp(f, [299], listops=True)
         assert res == f(299)
-        self.check_loops(guard_class=0, guard_nonnull=2,
-                         guard_nonnull_class=2, guard_isnull=1)
-        self.check_loops(guard_class=0, guard_nonnull=4,
-                         guard_nonnull_class=4, guard_isnull=2,
-                         everywhere=True)
+        self.check_resops(guard_class=0, guard_nonnull=4,
+                          guard_nonnull_class=4, guard_isnull=2)
+        
 
     def test_merge_guardnonnull_guardvalue(self):
         from pypy.rlib.objectmodel import instantiate
@@ -1435,11 +1431,9 @@
             return x
         res = self.meta_interp(f, [299], listops=True)
         assert res == f(299)
-        self.check_loops(guard_class=0, guard_nonnull=2, guard_value=2,
-                         guard_nonnull_class=0, guard_isnull=1)
-        self.check_loops(guard_class=0, guard_nonnull=4, guard_value=4,
-                         guard_nonnull_class=0, guard_isnull=2,
-                         everywhere=True)
+        self.check_resops(guard_value=4, guard_class=0, guard_nonnull=4,
+                          guard_nonnull_class=0, guard_isnull=2)
+        
 
     def test_merge_guardnonnull_guardvalue_2(self):
         from pypy.rlib.objectmodel import instantiate
@@ -1466,11 +1460,9 @@
             return x
         res = self.meta_interp(f, [299], listops=True)
         assert res == f(299)
-        self.check_loops(guard_class=0, guard_nonnull=2, guard_value=2,
-                         guard_nonnull_class=0, guard_isnull=1)
-        self.check_loops(guard_class=0, guard_nonnull=4, guard_value=4,
-                         guard_nonnull_class=0, guard_isnull=2,
-                         everywhere=True)
+        self.check_resops(guard_value=4, guard_class=0, guard_nonnull=4,
+                          guard_nonnull_class=0, guard_isnull=2)
+        
 
     def test_merge_guardnonnull_guardclass_guardvalue(self):
         from pypy.rlib.objectmodel import instantiate
@@ -1500,11 +1492,9 @@
             return x
         res = self.meta_interp(f, [399], listops=True)
         assert res == f(399)
-        self.check_loops(guard_class=0, guard_nonnull=3, guard_value=3,
-                         guard_nonnull_class=0, guard_isnull=1)
-        self.check_loops(guard_class=0, guard_nonnull=6, guard_value=6,
-                         guard_nonnull_class=0, guard_isnull=2,
-                         everywhere=True)
+        self.check_resops(guard_class=0, guard_nonnull=6, guard_value=6,
+                          guard_nonnull_class=0, guard_isnull=2)
+
 
     def test_residual_call_doesnt_lose_info(self):
         myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'l'])
@@ -1530,8 +1520,7 @@
                 y.v = g(y.v) - y.v/y.v + lc/l[0] - 1
             return y.v
         res = self.meta_interp(f, [20], listops=True)
-        self.check_loops(getfield_gc=0, getarrayitem_gc=0)
-        self.check_loops(getfield_gc=1, getarrayitem_gc=0, everywhere=True)
+        self.check_resops(getarrayitem_gc=0, getfield_gc=1)
 
     def test_guard_isnull_nonnull(self):
         myjitdriver = JitDriver(greens = [], reds = ['x', 'res'])
@@ -1559,7 +1548,7 @@
             return res
         res = self.meta_interp(f, [21])
         assert res == 42
-        self.check_loops(guard_nonnull=1, guard_isnull=1)
+        self.check_resops(guard_nonnull=2, guard_isnull=2)
 
     def test_loop_invariant1(self):
         myjitdriver = JitDriver(greens = [], reds = ['x', 'res'])
@@ -1586,8 +1575,7 @@
             return res
         res = self.meta_interp(g, [21])
         assert res == 3 * 21
-        self.check_loops(call=0)
-        self.check_loops(call=1, everywhere=True)
+        self.check_resops(call=1)
 
     def test_bug_optimizeopt_mutates_ops(self):
         myjitdriver = JitDriver(greens = [], reds = ['x', 'res', 'const', 'a'])
@@ -1707,7 +1695,7 @@
             return x
         res = self.meta_interp(f, [8])
         assert res == 0
-        self.check_loops(jit_debug=2)
+        self.check_resops(jit_debug=4)
 
     def test_assert_green(self):
         def f(x, promote_flag):
@@ -1749,9 +1737,10 @@
         res = self.meta_interp(g, [6, 7])
         assert res == 6*8 + 6**8
         self.check_loop_count(5)
-        self.check_loops({'guard_true': 2,
-                          'int_add': 1, 'int_mul': 1, 'int_sub': 2,
-                          'int_gt': 2, 'jump': 2})
+        self.check_resops({'guard_class': 2, 'int_gt': 4,
+                           'getfield_gc': 4, 'guard_true': 4,
+                           'int_sub': 4, 'jump': 4, 'int_mul': 2,
+                           'int_add': 2})
 
     def test_multiple_specialied_versions_array(self):
         myjitdriver = JitDriver(greens = [], reds = ['idx', 'y', 'x', 'res',
@@ -1792,7 +1781,7 @@
         res = self.meta_interp(g, [6, 14])
         assert res == g(6, 14)
         self.check_loop_count(9)
-        self.check_loops(getarrayitem_gc=8, everywhere=True)
+        self.check_resops(getarrayitem_gc=8)
 
     def test_multiple_specialied_versions_bridge(self):
         myjitdriver = JitDriver(greens = [], reds = ['y', 'x', 'z', 'res'])
@@ -1980,8 +1969,8 @@
         res = self.meta_interp(g, [3, 23])
         assert res == 7068153
         self.check_loop_count(7)
-        self.check_loops(guard_true=4, guard_class=0, int_add=2, int_mul=2,
-                         guard_false=2)
+        self.check_resops(guard_true=6, guard_class=2, int_mul=3,
+                          int_add=3, guard_false=3)
 
     def test_dont_trace_every_iteration(self):
         myjitdriver = JitDriver(greens = [], reds = ['a', 'b', 'i', 'sa'])
@@ -2225,27 +2214,27 @@
             return sa
 
         assert self.meta_interp(f1, [5, 5]) == 50
-        self.check_loops(int_rshift=0, everywhere=True)
+        self.check_resops(int_rshift=0)
 
         for f in (f1, f2):
             assert self.meta_interp(f, [5, 6]) == 50
-            self.check_loops(int_rshift=3, everywhere=True)
+            self.check_resops(int_rshift=3)
 
             assert self.meta_interp(f, [10, 5]) == 100
-            self.check_loops(int_rshift=3, everywhere=True)
+            self.check_resops(int_rshift=3)
 
             assert self.meta_interp(f, [10, 6]) == 100
-            self.check_loops(int_rshift=3, everywhere=True)
+            self.check_resops(int_rshift=3)
 
             assert self.meta_interp(f, [5, 31]) == 0
-            self.check_loops(int_rshift=3, everywhere=True)
+            self.check_resops(int_rshift=3)
 
             bigval = 1
             while (bigval << 3).__class__ is int:
                 bigval = bigval << 1
 
             assert self.meta_interp(f, [bigval, 5]) == 0
-            self.check_loops(int_rshift=3, everywhere=True)
+            self.check_resops(int_rshift=3)
 
     def test_overflowing_shift_neg(self):
         myjitdriver = JitDriver(greens = [], reds = ['a', 'b', 'n', 'sa'])
@@ -2270,27 +2259,27 @@
             return sa
 
         assert self.meta_interp(f1, [-5, 5]) == -50
-        self.check_loops(int_rshift=0, everywhere=True)
+        self.check_resops(int_rshift=0)
 
         for f in (f1, f2):
             assert self.meta_interp(f, [-5, 6]) == -50
-            self.check_loops(int_rshift=3, everywhere=True)
+            self.check_resops(int_rshift=3)
 
             assert self.meta_interp(f, [-10, 5]) == -100
-            self.check_loops(int_rshift=3, everywhere=True)
+            self.check_resops(int_rshift=3)
 
             assert self.meta_interp(f, [-10, 6]) == -100
-            self.check_loops(int_rshift=3, everywhere=True)
+            self.check_resops(int_rshift=3)
 
             assert self.meta_interp(f, [-5, 31]) == 0
-            self.check_loops(int_rshift=3, everywhere=True)
+            self.check_resops(int_rshift=3)
 
             bigval = 1
             while (bigval << 3).__class__ is int:
                 bigval = bigval << 1
 
             assert self.meta_interp(f, [bigval, 5]) == 0
-            self.check_loops(int_rshift=3, everywhere=True)
+            self.check_resops(int_rshift=3)
 
     def test_pure_op_not_to_be_propagated(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'sa'])
@@ -2328,8 +2317,8 @@
                                 get_printable_location=get_printable_location)
         bytecode = "0j10jc20a3"
         def f():
-            myjitdriver.set_param('threshold', 7)
-            myjitdriver.set_param('trace_eagerness', 1)
+            set_param(myjitdriver, 'threshold', 7)
+            set_param(myjitdriver, 'trace_eagerness', 1)
             i = j = c = a = 1
             while True:
                 myjitdriver.jit_merge_point(i=i, j=j, c=c, a=a)
@@ -2430,8 +2419,7 @@
                 if counter > 10:
                     return 7
         assert self.meta_interp(build, []) == 7
-        self.check_loops(getfield_gc_pure=0)
-        self.check_loops(getfield_gc_pure=2, everywhere=True)
+        self.check_resops(getfield_gc_pure=2)
 
     def test_args_becomming_equal(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa', 'a', 'b'])
@@ -2564,7 +2552,7 @@
                 i += 1
             return sa
         assert self.meta_interp(f, [20]) == f(20)
-        self.check_loops(int_gt=1, int_lt=2, int_ge=0, int_le=0)
+        self.check_resops(int_lt=4, int_le=0, int_ge=0, int_gt=2)
 
     def test_intbounds_not_generalized1(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa'])
@@ -2581,7 +2569,8 @@
                 i += 1
             return sa
         assert self.meta_interp(f, [20]) == f(20)
-        self.check_loops(int_gt=1, int_lt=3, int_ge=2, int_le=1)
+        self.check_resops(int_lt=6, int_le=2, int_ge=4, int_gt=3)
+        
 
     def test_intbounds_not_generalized2(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa', 'node'])
@@ -2601,13 +2590,13 @@
                 i += 1
             return sa
         assert self.meta_interp(f, [20]) == f(20)
-        self.check_loops(int_gt=1, int_lt=2, int_ge=1, int_le=1)
+        self.check_resops(int_lt=4, int_le=3, int_ge=3, int_gt=2)
 
     def test_retrace_limit1(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa', 'a'])
 
         def f(n, limit):
-            myjitdriver.set_param('retrace_limit', limit)
+            set_param(myjitdriver, 'retrace_limit', limit)
             sa = i = a = 0
             while i < n:
                 myjitdriver.jit_merge_point(n=n, i=i, sa=sa, a=a)
@@ -2625,8 +2614,8 @@
         myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa', 'a'])
 
         def f(n, limit):
-            myjitdriver.set_param('retrace_limit', 3)
-            myjitdriver.set_param('max_retrace_guards', limit)
+            set_param(myjitdriver, 'retrace_limit', 3)
+            set_param(myjitdriver, 'max_retrace_guards', limit)
             sa = i = a = 0
             while i < n:
                 myjitdriver.jit_merge_point(n=n, i=i, sa=sa, a=a)
@@ -2645,7 +2634,7 @@
         myjitdriver = JitDriver(greens = [], reds = ['n', 'i', 'sa', 'a',
                                                      'node'])
         def f(n, limit):
-            myjitdriver.set_param('retrace_limit', limit)
+            set_param(myjitdriver, 'retrace_limit', limit)
             sa = i = a = 0
             node = [1, 2, 3]
             node[1] = n
@@ -2668,10 +2657,10 @@
         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)
+            set_param(None, 'threshold', 3)
+            set_param(None, 'trace_eagerness', 1)
+            set_param(None, 'retrace_limit', 5)
+            set_param(None, 'function_threshold', -1)
             pc = sa = i = 0
             while pc < len(bytecode):
                 myjitdriver.jit_merge_point(pc=pc, n=n, sa=sa, i=i)
@@ -2728,9 +2717,9 @@
         myjitdriver = JitDriver(greens = ['pc'], reds = ['n', 'a', 'i', 'j', 'sa'])
         bytecode = "ij+Jj+JI"
         def f(n, a):
-            myjitdriver.set_param('threshold', 5)
-            myjitdriver.set_param('trace_eagerness', 1)
-            myjitdriver.set_param('retrace_limit', 2)
+            set_param(None, 'threshold', 5)
+            set_param(None, 'trace_eagerness', 1)
+            set_param(None, 'retrace_limit', 2)
             pc = sa = i = j = 0
             while pc < len(bytecode):
                 myjitdriver.jit_merge_point(pc=pc, n=n, sa=sa, i=i, j=j, a=a)
@@ -2793,8 +2782,8 @@
                 return B(self.val + 1)
         myjitdriver = JitDriver(greens = [], reds = ['sa', 'a'])
         def f():
-            myjitdriver.set_param('threshold', 3)
-            myjitdriver.set_param('trace_eagerness', 2)
+            set_param(None, 'threshold', 3)
+            set_param(None, 'trace_eagerness', 2)
             a = A(0)
             sa = 0
             while a.val < 8:
@@ -2824,8 +2813,8 @@
                 return B(self.val + 1)
         myjitdriver = JitDriver(greens = [], reds = ['sa', 'b', 'a'])
         def f(b):
-            myjitdriver.set_param('threshold', 6)
-            myjitdriver.set_param('trace_eagerness', 4)
+            set_param(None, 'threshold', 6)
+            set_param(None, 'trace_eagerness', 4)
             a = A(0)
             sa = 0
             while a.val < 15:
@@ -2855,17 +2844,17 @@
             return a[0].intvalue
         res = self.meta_interp(f, [100])
         assert res == -2
-        #self.check_loops(getarrayitem_gc=0, setarrayitem_gc=0) -- xxx?
+        self.check_resops(setarrayitem_gc=2, getarrayitem_gc=1)
 
     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)
+            set_param(None, 'threshold', 3)
+            set_param(None, 'trace_eagerness', 1)
+            set_param(None, 'retrace_limit', 5)
+            set_param(None, 'function_threshold', -1)
             pc = sa = i = 0
             while pc < len(bytecode):
                 myjitdriver.jit_merge_point(pc=pc, n=n, sa=sa, i=i)
@@ -2955,7 +2944,7 @@
                 i += 1
         res = self.meta_interp(f, [32])
         assert res == f(32)
-        self.check_loops(arraylen_gc=2)
+        self.check_resops(arraylen_gc=3)
 
     def test_ulonglong_mod(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'sa', 'i'])
@@ -3142,9 +3131,9 @@
                 a = A(a.i + 1)
 
         self.meta_interp(f, [])
-        self.check_loops(new_with_vtable=0)
+        self.check_resops(new_with_vtable=0)
         self.meta_interp(f, [], enable_opts='')
-        self.check_loops(new_with_vtable=1)
+        self.check_resops(new_with_vtable=1)
 
     def test_two_loopinvariant_arrays1(self):
         from pypy.rpython.lltypesystem import lltype, llmemory, rffi
@@ -3236,7 +3225,7 @@
             return sa
         res = self.meta_interp(f, [32])
         assert res == f(32)
-        self.check_loops(arraylen_gc=2, everywhere=True)
+        self.check_resops(arraylen_gc=2)
 
     def test_release_gil_flush_heap_cache(self):
         if sys.platform == "win32":
@@ -3273,7 +3262,7 @@
                 lock.release()
             return n
         res = self.meta_interp(f, [10, 1])
-        self.check_loops(getfield_gc=2)
+        self.check_resops(getfield_gc=4)
         assert res == f(10, 1)
 
     def test_jit_merge_point_with_raw_pointer(self):
@@ -3337,10 +3326,10 @@
 
         res = self.meta_interp(main, [0, 10, 2], enable_opts='')
         assert res == main(0, 10, 2)
-        self.check_loops(call=1)
+        self.check_resops(call=1)
         res = self.meta_interp(main, [1, 10, 2], enable_opts='')
         assert res == main(1, 10, 2)
-        self.check_loops(call=0)
+        self.check_resops(call=0)
 
     def test_look_inside_iff_virtual(self):
         # There's no good reason for this to be look_inside_iff, but it's a test!
@@ -3365,10 +3354,10 @@
                     i += f(A(2), n)
         res = self.meta_interp(main, [0], enable_opts='')
         assert res == main(0)
-        self.check_loops(call=1, getfield_gc=0)
+        self.check_resops(call=1, getfield_gc=0)
         res = self.meta_interp(main, [1], enable_opts='')
         assert res == main(1)
-        self.check_loops(call=0, getfield_gc=0)
+        self.check_resops(call=0, getfield_gc=0)
 
     def test_reuse_elidable_result(self):
         driver = JitDriver(reds=['n', 's'], greens = [])
@@ -3381,10 +3370,9 @@
             return s
         res = self.meta_interp(main, [10])
         assert res == main(10)
-        self.check_loops({
-            'call': 1, 'guard_no_exception': 1, 'guard_true': 1, 'int_add': 2,
-            'int_gt': 1, 'int_sub': 1, 'strlen': 1, 'jump': 1,
-        })
+        self.check_resops({'int_gt': 2, 'strlen': 2, 'guard_true': 2,
+                           'int_sub': 2, 'jump': 2, 'call': 2,
+                           'guard_no_exception': 2, 'int_add': 4})
 
     def test_look_inside_iff_const_getarrayitem_gc_pure(self):
         driver = JitDriver(greens=['unroll'], reds=['s', 'n'])
@@ -3416,10 +3404,10 @@
         res = self.meta_interp(main, [0, 10])
         assert res == main(0, 10)
         # 2 calls, one for f() and one for char_mul
-        self.check_loops(call=2)
+        self.check_resops(call=4)
         res = self.meta_interp(main, [1, 10])
         assert res == main(1, 10)
-        self.check_loops(call=0)
+        self.check_resops(call=0)
 
     def test_setarrayitem_followed_by_arraycopy(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'sa', 'x', 'y'])
@@ -3513,12 +3501,15 @@
         def f(n):
             while n > 0:
                 myjitdriver.jit_merge_point(n=n)
-                n = g({"key": n})
+                x = {"key": n}
+                n = g(x)
+                del x["key"]
             return n
 
         res = self.meta_interp(f, [10])
         assert res == 0
-        self.check_loops({"int_sub": 1, "int_gt": 1, "guard_true": 1, "jump": 1})
+        self.check_resops({'jump': 2, 'guard_true': 2, 'int_gt': 2,
+                           'int_sub': 2})
 
     def test_virtual_opaque_ptr(self):
         myjitdriver = JitDriver(greens = [], reds = ["n"])
@@ -3537,7 +3528,9 @@
             return n
         res = self.meta_interp(f, [10])
         assert res == 0
-        self.check_loops({"int_sub": 1, "int_gt": 1, "guard_true": 1, "jump": 1})
+        self.check_resops({'jump': 2, 'guard_true': 2, 'int_gt': 2,
+                           'int_sub': 2})
+
 
     def test_virtual_opaque_dict(self):
         myjitdriver = JitDriver(greens = [], reds = ["n"])
@@ -3557,8 +3550,165 @@
             return n
         res = self.meta_interp(f, [10])
         assert res == 0
-        self.check_loops({"int_sub": 1, "int_gt": 1, "guard_true": 1, "jump": 1})
-
+        self.check_resops({'int_gt': 2, 'getfield_gc': 1, 'int_eq': 1,
+                           'guard_true': 2, 'int_sub': 2, 'jump': 2,
+                           'guard_false': 1})
+
+
+    def test_convert_from_SmallFunctionSetPBCRepr_to_FunctionsPBCRepr(self):
+        f1 = lambda n: n+1
+        f2 = lambda n: n+2
+        f3 = lambda n: n+3
+        f4 = lambda n: n+4
+        f5 = lambda n: n+5
+        f6 = lambda n: n+6
+        f7 = lambda n: n+7
+        f8 = lambda n: n+8
+        def h(n, x):
+            return x(n)
+        h._dont_inline = True
+        def g(n, x):
+            return h(n, x)
+        g._dont_inline = True
+        def f(n):
+            n = g(n, f1)
+            n = g(n, f2)
+            n = h(n, f3)
+            n = h(n, f4)
+            n = h(n, f5)
+            n = h(n, f6)
+            n = h(n, f7)
+            n = h(n, f8)
+            return n
+        assert f(5) == 41
+        translationoptions = {'withsmallfuncsets': 3}
+        self.interp_operations(f, [5], translationoptions=translationoptions)
+
+
+    def test_annotation_gives_class_knowledge_to_tracer(self):
+        py.test.skip("disabled")
+        class Base(object):
+            pass
+        class A(Base):
+            def f(self):
+                return self.a
+            def g(self):
+                return self.a + 1
+        class B(Base):
+            def f(self):
+                return self.b
+            def g(self):
+                return self.b + 1
+        class C(B):
+            def f(self):
+                self.c += 1
+                return self.c
+            def g(self):
+                return self.c + 1
+        @dont_look_inside
+        def make(x):
+            if x > 0:
+                a = A()
+                a.a = x + 1
+            elif x < 0:
+                a = B()
+                a.b = -x
+            else:
+                a = C()
+                a.c = 10
+            return a
+        def f(x):
+            a = make(x)
+            if x > 0:
+                assert isinstance(a, A)
+                z = a.f()
+            elif x < 0:
+                assert isinstance(a, B)
+                z = a.f()
+            else:
+                assert isinstance(a, C)
+                z = a.f()
+            return z + a.g()
+        res1 = f(6)
+        res2 = self.interp_operations(f, [6])
+        assert res1 == res2
+        self.check_operations_history(guard_class=0, record_known_class=1)
+
+        res1 = f(-6)
+        res2 = self.interp_operations(f, [-6])
+        assert res1 == res2
+        # cannot use record_known_class here, because B has a subclass
+        self.check_operations_history(guard_class=1)
+
+        res1 = f(0)
+        res2 = self.interp_operations(f, [0])
+        assert res1 == res2
+        # here it works again
+        self.check_operations_history(guard_class=0, record_known_class=1)
+
+    def test_give_class_knowledge_to_tracer_explicitly(self):
+        from pypy.rpython.lltypesystem.lloperation import llop
+        class Base(object):
+            def f(self):
+                raise NotImplementedError
+            def g(self):
+                raise NotImplementedError
+        class A(Base):
+            def f(self):
+                return self.a
+            def g(self):
+                return self.a + 1
+        class B(Base):
+            def f(self):
+                return self.b
+            def g(self):
+                return self.b + 1
+        class C(B):
+            def f(self):
+                self.c += 1
+                return self.c
+            def g(self):
+                return self.c + 1
+        @dont_look_inside
+        def make(x):
+            if x > 0:
+                a = A()
+                a.a = x + 1
+            elif x < 0:
+                a = B()
+                a.b = -x
+            else:
+                a = C()
+                a.c = 10
+            return a
+        def f(x):
+            a = make(x)
+            if x > 0:
+                record_known_class(a, A)
+                z = a.f()
+            elif x < 0:
+                record_known_class(a, B)
+                z = a.f()
+            else:
+                record_known_class(a, C)
+                z = a.f()
+            return z + a.g()
+        res1 = f(6)
+        res2 = self.interp_operations(f, [6])
+        assert res1 == res2
+        self.check_operations_history(guard_class=0, record_known_class=1)
+
+        res1 = f(-6)
+        res2 = self.interp_operations(f, [-6])
+        assert res1 == res2
+        # cannot use record_known_class here, because B has a subclass
+        self.check_operations_history(guard_class=1)
+
+        res1 = f(0)
+        res2 = self.interp_operations(f, [0])
+        assert res1 == res2
+        # here it works again
+        self.check_operations_history(guard_class=0, record_known_class=1)
 
 
 class TestLLtype(BaseLLtypeTests, LLJitMixin):
@@ -3613,7 +3763,9 @@
                     o = o.dec()
                 pc += 1
             return pc
-        res = self.meta_interp(main, [False, 100, True], taggedpointers=True)
+        topt = {'taggedpointers': True}
+        res = self.meta_interp(main, [False, 100, True],
+                               translationoptions=topt)
 
     def test_rerased(self):
         eraseX, uneraseX = rerased.new_erasing_pair("X")
@@ -3638,10 +3790,24 @@
             else:
                 return rerased.unerase_int(e)
         #
-        x = self.interp_operations(f, [-128, 0], taggedpointers=True)
+        topt = {'taggedpointers': True}
+        x = self.interp_operations(f, [-128, 0], translationoptions=topt)
         assert x == -128
         bigint = sys.maxint//2 + 1
-        x = self.interp_operations(f, [bigint, 0], taggedpointers=True)
+        x = self.interp_operations(f, [bigint, 0], translationoptions=topt)
         assert x == -42
-        x = self.interp_operations(f, [1000, 1], taggedpointers=True)
+        x = self.interp_operations(f, [1000, 1], translationoptions=topt)
         assert x == 999
+
+    def test_ll_arraycopy(self):
+        from pypy.rlib import rgc
+        A = lltype.GcArray(lltype.Char)
+        a = lltype.malloc(A, 10)
+        for i in range(10): a[i] = chr(i)
+        b = lltype.malloc(A, 10)
+        #
+        def f(c, d, e):
+            rgc.ll_arraycopy(a, b, c, d, e)
+            return 42
+        self.interp_operations(f, [1, 2, 3])
+        self.check_operations_history(call=1, guard_no_exception=0)
diff --git a/pypy/jit/metainterp/test/test_del.py b/pypy/jit/metainterp/test/test_del.py
--- a/pypy/jit/metainterp/test/test_del.py
+++ b/pypy/jit/metainterp/test/test_del.py
@@ -20,12 +20,12 @@
                 n -= 1
             return 42
         self.meta_interp(f, [20])
-        self.check_loops({'call': 2,      # calls to a helper function
-                          'guard_no_exception': 2,    # follows the calls
-                          'int_sub': 1,
-                          'int_gt': 1,
-                          'guard_true': 1,
-                          'jump': 1})
+        self.check_resops({'call': 4,      # calls to a helper function
+                           'guard_no_exception': 4,    # follows the calls
+                           'int_sub': 2,
+                           'int_gt': 2,
+                           'guard_true': 2,
+                           'jump': 2})
 
     def test_class_of_allocated(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'x'])
@@ -78,7 +78,7 @@
             return 1
         res = self.meta_interp(f, [20], enable_opts='')
         assert res == 1
-        self.check_loops(call=1)   # for the case B(), but not for the case A()
+        self.check_resops(call=1)   # for the case B(), but not for the case A()
 
 
 class TestLLtype(DelTests, LLJitMixin):
@@ -103,7 +103,7 @@
                     break
             return 42
         self.meta_interp(f, [20])
-        self.check_loops(getfield_raw=1, setfield_raw=1, call=0, call_pure=0)
+        self.check_resops(call_pure=0, setfield_raw=2, call=0, getfield_raw=2)
 
 class TestOOtype(DelTests, OOJitMixin):
     def setup_class(cls):
diff --git a/pypy/jit/metainterp/test/test_dict.py b/pypy/jit/metainterp/test/test_dict.py
--- a/pypy/jit/metainterp/test/test_dict.py
+++ b/pypy/jit/metainterp/test/test_dict.py
@@ -91,7 +91,7 @@
         res1 = f(100)
         res2 = self.meta_interp(f, [100], listops=True)
         assert res1 == res2
-        self.check_loops(int_mod=1) # the hash was traced and eq, but cached
+        self.check_resops(int_mod=2) # the hash was traced and eq, but cached
 
     def test_dict_setdefault(self):
         myjitdriver = JitDriver(greens = [], reds = ['total', 'dct'])
@@ -107,7 +107,7 @@
         assert f(100) == 50
         res = self.meta_interp(f, [100], listops=True)
         assert res == 50
-        self.check_loops(new=0, new_with_vtable=0)
+        self.check_resops(new=0, new_with_vtable=0)
 
     def test_dict_as_counter(self):
         myjitdriver = JitDriver(greens = [], reds = ['total', 'dct'])
@@ -128,7 +128,7 @@
         assert f(100) == 50
         res = self.meta_interp(f, [100], listops=True)
         assert res == 50
-        self.check_loops(int_mod=1) # key + eq, but cached
+        self.check_resops(int_mod=2) # key + eq, but cached
 
     def test_repeated_lookup(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'd'])
@@ -153,12 +153,13 @@
 
         res = self.meta_interp(f, [100], listops=True)
         assert res == f(50)
-        self.check_loops({"call": 5, "getfield_gc": 1, "getinteriorfield_gc": 1,
-                          "guard_false": 1, "guard_no_exception": 4,
-                          "guard_true": 1, "int_and": 1, "int_gt": 1,
-                          "int_is_true": 1, "int_sub": 1, "jump": 1,
-                          "new_with_vtable": 1, "new": 1, "new_array": 1,
-                          "setfield_gc": 3, })
+        self.check_resops({'new_array': 2, 'getfield_gc': 2,
+                           'guard_true': 2, 'jump': 2,
+                           'new_with_vtable': 2, 'getinteriorfield_gc': 2,
+                           'setfield_gc': 6, 'int_gt': 2, 'int_sub': 2,
+                           'call': 10, 'int_and': 2,
+                           'guard_no_exception': 8, 'new': 2,
+                           'guard_false': 2, 'int_is_true': 2})
 
 
 class TestOOtype(DictTests, OOJitMixin):
diff --git a/pypy/jit/metainterp/test/test_exception.py b/pypy/jit/metainterp/test/test_exception.py
--- a/pypy/jit/metainterp/test/test_exception.py
+++ b/pypy/jit/metainterp/test/test_exception.py
@@ -35,10 +35,8 @@
             return n
         res = self.meta_interp(f, [10])
         assert res == 0
-        self.check_loops({'jump': 1,
-                          'int_gt': 1, 'guard_true': 1,
-                          'int_sub': 1})
-
+        self.check_resops({'jump': 2, 'guard_true': 2,
+                           'int_gt': 2, 'int_sub': 2})
 
     def test_bridge_from_guard_exception(self):
         myjitdriver = JitDriver(greens = [], reds = ['n'])
diff --git a/pypy/jit/metainterp/test/test_fficall.py b/pypy/jit/metainterp/test/test_fficall.py
--- a/pypy/jit/metainterp/test/test_fficall.py
+++ b/pypy/jit/metainterp/test/test_fficall.py
@@ -1,19 +1,18 @@
+import py
 
-import py
+from pypy.jit.metainterp.test.support import LLJitMixin
+from pypy.rlib.jit import JitDriver, promote, dont_look_inside
+from pypy.rlib.libffi import (ArgChain, IS_32_BIT, array_getitem, array_setitem,
+    types)
+from pypy.rlib.objectmodel import specialize
 from pypy.rlib.rarithmetic import r_singlefloat, r_longlong, r_ulonglong
-from pypy.rlib.jit import JitDriver, promote, dont_look_inside
+from pypy.rlib.test.test_libffi import TestLibffiCall as _TestLibffiCall
 from pypy.rlib.unroll import unrolling_iterable
-from pypy.rlib.libffi import ArgChain
-from pypy.rlib.libffi import IS_32_BIT
-from pypy.rlib.test.test_libffi import TestLibffiCall as _TestLibffiCall
 from pypy.rpython.lltypesystem import lltype, rffi
-from pypy.rlib.objectmodel import specialize
 from pypy.tool.sourcetools import func_with_new_name
-from pypy.jit.metainterp.test.support import LLJitMixin
 
-class TestFfiCall(LLJitMixin, _TestLibffiCall):
-    supports_all = False     # supports_{floats,longlong,singlefloats}
 
+class FfiCallTests(_TestLibffiCall):
     # ===> ../../../rlib/test/test_libffi.py
 
     def call(self, funcspec, args, RESULT, is_struct=False, jitif=[]):
@@ -68,23 +67,23 @@
              'byval': False}
         supported = all(d[check] for check in jitif)
         if supported:
-            self.check_loops(
-                call_release_gil=1,   # a CALL_RELEASE_GIL, and no other CALLs
+            self.check_resops(
+                call_release_gil=2,   # a CALL_RELEASE_GIL, and no other CALLs
                 call=0,
                 call_may_force=0,
-                guard_no_exception=1,
-                guard_not_forced=1,
-                int_add=1,
-                int_lt=1,
-                guard_true=1,
-                jump=1)
+                guard_no_exception=2,
+                guard_not_forced=2,
+                int_add=2,
+                int_lt=2,
+                guard_true=2,
+                jump=2)
         else:
-            self.check_loops(
+            self.check_resops(
                 call_release_gil=0,   # no CALL_RELEASE_GIL
-                int_add=1,
-                int_lt=1,
-                guard_true=1,
-                jump=1)
+                int_add=2,
+                int_lt=2,
+                guard_true=2,
+                jump=2)
         return res
 
     def test_byval_result(self):
@@ -92,6 +91,90 @@
     test_byval_result.__doc__ = _TestLibffiCall.test_byval_result.__doc__
     test_byval_result.dont_track_allocations = True
 
+class FfiLookupTests(object):
+    def test_array_fields(self):
+        myjitdriver = JitDriver(
+            greens = [],
+            reds = ["n", "i", "points", "result_point"],
+        )
 
-class TestFfiCallSupportAll(TestFfiCall):
+        POINT = lltype.Struct("POINT",
+            ("x", lltype.Signed),
+            ("y", lltype.Signed),
+        )
+        def f(points, result_point, n):
+            i = 0
+            while i < n:
+                myjitdriver.jit_merge_point(i=i, points=points, n=n,
+                                            result_point=result_point)
+                x = array_getitem(
+                    types.slong, rffi.sizeof(lltype.Signed) * 2, points, i, 0
+                )
+                y = array_getitem(
+                    types.slong, rffi.sizeof(lltype.Signed) * 2, points, i, rffi.sizeof(lltype.Signed)
+                )
+
+                cur_x = array_getitem(
+                    types.slong, rffi.sizeof(lltype.Signed) * 2, result_point, 0, 0
+                )
+                cur_y = array_getitem(
+                    types.slong, rffi.sizeof(lltype.Signed) * 2, result_point, 0, rffi.sizeof(lltype.Signed)
+                )
+
+                array_setitem(
+                    types.slong, rffi.sizeof(lltype.Signed) * 2, result_point, 0, 0, cur_x + x
+                )
+                array_setitem(
+                    types.slong, rffi.sizeof(lltype.Signed) * 2, result_point, 0, rffi.sizeof(lltype.Signed), cur_y + y
+                )
+                i += 1
+
+        def main(n):
+            with lltype.scoped_alloc(rffi.CArray(POINT), n) as points:
+                with lltype.scoped_alloc(rffi.CArray(POINT), 1) as result_point:
+                    for i in xrange(n):
+                        points[i].x = i * 2
+                        points[i].y = i * 2 + 1
+                    points = rffi.cast(rffi.CArrayPtr(lltype.Char), points)
+                    result_point[0].x = 0
+                    result_point[0].y = 0
+                    result_point = rffi.cast(rffi.CArrayPtr(lltype.Char), result_point)
+                    f(points, result_point, n)
+                    result_point = rffi.cast(rffi.CArrayPtr(POINT), result_point)
+                    return result_point[0].x * result_point[0].y
+
+        assert self.meta_interp(main, [10]) == main(10) == 9000
+        self.check_resops({'jump': 2, 'int_lt': 2, 'setinteriorfield_raw': 4,
+                           'getinteriorfield_raw': 8, 'int_add': 6, 'guard_true': 2})
+
+    def test_array_getitem_uint8(self):
+        myjitdriver = JitDriver(
+            greens = [],
+            reds = ["n", "i", "s", "data"],
+        )
+        def f(data, n):
+            i = s = 0
+            while i < n:
+                myjitdriver.jit_merge_point(n=n, i=i, s=s, data=data)
+                s += rffi.cast(lltype.Signed, array_getitem(types.uchar, 1, data, 0, 0))
+                i += 1
+            return s
+
+        def main(n):
+            with lltype.scoped_alloc(rffi.CArray(rffi.UCHAR), 1) as data:
+                data[0] = rffi.cast(rffi.UCHAR, 200)
+                return f(data, n)
+
+        assert self.meta_interp(main, [10]) == 2000
+        self.check_resops({'jump': 2, 'int_lt': 2, 'getinteriorfield_raw': 2,
+                           'guard_true': 2, 'int_add': 4})
+
+
+class TestFfiCall(FfiCallTests, LLJitMixin):
+    supports_all = False
+
+class TestFfiCallSupportAll(FfiCallTests, LLJitMixin):
     supports_all = True     # supports_{floats,longlong,singlefloats}
+
+class TestFfiLookup(FfiLookupTests, LLJitMixin):
+    pass
diff --git a/pypy/jit/metainterp/test/test_greenfield.py b/pypy/jit/metainterp/test/test_greenfield.py
--- a/pypy/jit/metainterp/test/test_greenfield.py
+++ b/pypy/jit/metainterp/test/test_greenfield.py
@@ -25,7 +25,7 @@
         res = self.meta_interp(g, [7])
         assert res == -2
         self.check_loop_count(2)
-        self.check_loops(guard_value=0)
+        self.check_resops(guard_value=0)
 
     def test_green_field_2(self):
         myjitdriver = JitDriver(greens=['ctx.x'], reds=['ctx'])
@@ -50,7 +50,7 @@
         res = self.meta_interp(g, [7])
         assert res == -22
         self.check_loop_count(6)
-        self.check_loops(guard_value=0)
+        self.check_resops(guard_value=0)
 
 
 class TestLLtypeGreenFieldsTests(GreenFieldsTests, LLJitMixin):
diff --git a/pypy/jit/metainterp/test/test_jitdriver.py b/pypy/jit/metainterp/test/test_jitdriver.py
--- a/pypy/jit/metainterp/test/test_jitdriver.py
+++ b/pypy/jit/metainterp/test/test_jitdriver.py
@@ -1,5 +1,5 @@
 """Tests for multiple JitDrivers."""
-from pypy.rlib.jit import JitDriver, unroll_safe
+from pypy.rlib.jit import JitDriver, unroll_safe, set_param
 from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.jit.metainterp.warmspot import get_stats
 
@@ -88,7 +88,7 @@
         assert res == loop2(4, 40)
         # we expect only one int_sub, corresponding to the single
         # compiled instance of loop1()
-        self.check_loops(int_sub=1)
+        self.check_resops(int_sub=2)
         # the following numbers are not really expectations of the test
         # itself, but just the numbers that we got after looking carefully
         # at the generated machine code
@@ -113,7 +113,7 @@
             return n
         #
         def loop2(g, r):
-            myjitdriver1.set_param('function_threshold', 0)
+            set_param(None, 'function_threshold', 0)
             while r > 0:
                 myjitdriver2.can_enter_jit(g=g, r=r)
                 myjitdriver2.jit_merge_point(g=g, r=r)
@@ -154,7 +154,7 @@
         res = self.meta_interp(loop2, [4, 40], repeat=7, inline=True)
         assert res == loop2(4, 40)
         # we expect no int_sub, but a residual call
-        self.check_loops(int_sub=0, call=1)
+        self.check_resops(call=2, int_sub=0)
 
     def test_multiple_jits_trace_too_long(self):
         myjitdriver1 = JitDriver(greens=["n"], reds=["i", "box"])
diff --git a/pypy/jit/metainterp/test/test_list.py b/pypy/jit/metainterp/test/test_list.py
--- a/pypy/jit/metainterp/test/test_list.py
+++ b/pypy/jit/metainterp/test/test_list.py
@@ -6,8 +6,8 @@
 class ListTests:
 
     def check_all_virtualized(self):
-        self.check_loops(new_array=0, setarrayitem_gc=0, getarrayitem_gc=0,
-                         arraylen_gc=0)
+        self.check_resops(setarrayitem_gc=0, new_array=0, arraylen_gc=0,
+                          getarrayitem_gc=0)
 
     def test_simple_array(self):
         jitdriver = JitDriver(greens = [], reds = ['n'])
@@ -20,7 +20,7 @@
             return n
         res = self.meta_interp(f, [10], listops=True)
         assert res == 0
-        self.check_loops(int_sub=1)
+        self.check_resops(int_sub=2)
         self.check_all_virtualized()
 
     def test_list_pass_around(self):
@@ -56,7 +56,8 @@
         res = self.meta_interp(f, [10], listops=True)
         assert res == f(10)
         # one setitem should be gone by now
-        self.check_loops(call=1, setarrayitem_gc=2, getarrayitem_gc=1)
+        self.check_resops(setarrayitem_gc=4, getarrayitem_gc=2, call=2)
+
 
     def test_ll_fixed_setitem_fast(self):
         jitdriver = JitDriver(greens = [], reds = ['n', 'l'])
@@ -93,7 +94,7 @@
 
         res = self.meta_interp(f, [10], listops=True)
         assert res == f(10)
-        self.check_loops(setarrayitem_gc=0, getarrayitem_gc=0, call=0)
+        self.check_resops(setarrayitem_gc=0, call=0, getarrayitem_gc=0)
 
     def test_vlist_alloc_and_set(self):
         # the check_loops fails, because [non-null] * n is not supported yet
@@ -141,7 +142,7 @@
 
         res = self.meta_interp(f, [5], listops=True)
         assert res == 7
-        self.check_loops(call=0)
+        self.check_resops(call=0)
 
     def test_fold_getitem_1(self):
         jitdriver = JitDriver(greens = ['pc', 'n', 'l'], reds = ['total'])
@@ -161,7 +162,7 @@
 
         res = self.meta_interp(f, [4], listops=True)
         assert res == f(4)
-        self.check_loops(call=0)
+        self.check_resops(call=0)
 
     def test_fold_getitem_2(self):
         jitdriver = JitDriver(greens = ['pc', 'n', 'l'], reds = ['total', 'x'])
@@ -186,7 +187,7 @@
 
         res = self.meta_interp(f, [4], listops=True)
         assert res == f(4)
-        self.check_loops(call=0, getfield_gc=0)
+        self.check_resops(call=0, getfield_gc=0)
 
     def test_fold_indexerror(self):
         jitdriver = JitDriver(greens = [], reds = ['total', 'n', 'lst'])
@@ -206,7 +207,7 @@
 
         res = self.meta_interp(f, [15], listops=True)
         assert res == f(15)
-        self.check_loops(guard_exception=0)
+        self.check_resops(guard_exception=0)
 
     def test_virtual_resize(self):
         jitdriver = JitDriver(greens = [], reds = ['n', 's'])
@@ -224,9 +225,8 @@
             return s
         res = self.meta_interp(f, [15], listops=True)
         assert res == f(15)
-        self.check_loops({"int_add": 1, "int_sub": 1, "int_gt": 1,
-                          "guard_true": 1, "jump": 1})
-
+        self.check_resops({'jump': 2, 'int_gt': 2, 'int_add': 2,
+                           'guard_true': 2, 'int_sub': 2})
 
 class TestOOtype(ListTests, OOJitMixin):
     pass
@@ -258,4 +258,4 @@
         assert res == f(37)
         # There is the one actual field on a, plus several fields on the list
         # itself
-        self.check_loops(getfield_gc=10, everywhere=True)
+        self.check_resops(getfield_gc=10)
diff --git a/pypy/jit/metainterp/test/test_loop.py b/pypy/jit/metainterp/test/test_loop.py
--- a/pypy/jit/metainterp/test/test_loop.py
+++ b/pypy/jit/metainterp/test/test_loop.py
@@ -1,5 +1,5 @@
 import py
-from pypy.rlib.jit import JitDriver, hint
+from pypy.rlib.jit import JitDriver, hint, set_param
 from pypy.rlib.objectmodel import compute_hash
 from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats
 from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
@@ -60,7 +60,8 @@
         assert res == f(6, 13)
         self.check_loop_count(1)
         if self.enable_opts:
-            self.check_loops(getfield_gc = 0, setfield_gc = 1)
+            self.check_resops(setfield_gc=2, getfield_gc=0)
+
 
     def test_loop_with_two_paths(self):
         from pypy.rpython.lltypesystem import lltype
@@ -180,7 +181,10 @@
         assert res == 42
         self.check_loop_count(1)
         # the 'int_eq' and following 'guard' should be constant-folded
-        self.check_loops(int_eq=0, guard_true=1, guard_false=0)
+        if 'unroll' in self.enable_opts:
+            self.check_resops(int_eq=0, guard_true=2, guard_false=0)
+        else:
+            self.check_resops(int_eq=0, guard_true=1, guard_false=0)
         if self.basic:
             found = 0
             for op in get_stats().loops[0]._all_operations():
@@ -364,7 +368,7 @@
         myjitdriver = JitDriver(greens = ['pos'], reds = ['i', 'j', 'n', 'x'])
         bytecode = "IzJxji"
         def f(n, threshold):
-            myjitdriver.set_param('threshold', threshold)        
+            set_param(myjitdriver, 'threshold', threshold)        
             i = j = x = 0
             pos = 0
             op = '-'
@@ -411,7 +415,7 @@
         myjitdriver = JitDriver(greens = ['pos'], reds = ['i', 'j', 'n', 'x'])
         bytecode = "IzJxji"
         def f(nval, threshold):
-            myjitdriver.set_param('threshold', threshold)        
+            set_param(myjitdriver, 'threshold', threshold)        
             i, j, x = A(0), A(0), A(0)
             n = A(nval)
             pos = 0
@@ -643,8 +647,12 @@
         res = self.meta_interp(main_interpreter_loop, [1])
         assert res == 102
         self.check_loop_count(1)
-        self.check_loops({'int_add' : 3, 'int_gt' : 1,
-                          'guard_false' : 1, 'jump' : 1})
+        if 'unroll' in self.enable_opts:
+            self.check_resops({'int_add' : 6, 'int_gt' : 2,
+                               'guard_false' : 2, 'jump' : 2})
+        else:
+            self.check_resops({'int_add' : 3, 'int_gt' : 1,
+                               'guard_false' : 1, 'jump' : 1})
 
     def test_automatic_promotion(self):
         myjitdriver = JitDriver(greens = ['i'],
@@ -686,7 +694,7 @@
         self.check_loop_count(1)
         # These loops do different numbers of ops based on which optimizer we
         # are testing with.
-        self.check_loops(self.automatic_promotion_result)
+        self.check_resops(self.automatic_promotion_result)
 
     def test_can_enter_jit_outside_main_loop(self):
         myjitdriver = JitDriver(greens=[], reds=['i', 'j', 'a'])
diff --git a/pypy/jit/metainterp/test/test_loop_unroll.py b/pypy/jit/metainterp/test/test_loop_unroll.py
--- a/pypy/jit/metainterp/test/test_loop_unroll.py
+++ b/pypy/jit/metainterp/test/test_loop_unroll.py
@@ -8,7 +8,8 @@
     enable_opts = ALL_OPTS_NAMES
     
     automatic_promotion_result = {
-        'int_add' : 3, 'int_gt' : 1, 'guard_false' : 1, 'jump' : 1, 
+        'int_gt': 2, 'guard_false': 2, 'jump': 2, 'int_add': 6,
+        'guard_value': 1        
     }
 
     # ====> test_loop.py
diff --git a/pypy/jit/metainterp/test/test_math.py b/pypy/jit/metainterp/test/test_math.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/metainterp/test/test_math.py
@@ -0,0 +1,47 @@
+import math
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
+from pypy.rlib.rfloat import isinf, isnan, INFINITY, NAN
+
+class MathTests:
+    
+    def test_math_sqrt(self):
+        def f(x):
+            try:
+                return math.sqrt(x)
+            except ValueError:
+                return -INFINITY
+        
+        res = self.interp_operations(f, [0.0])
+        assert res == 0.0
+        self.check_operations_history(call_pure=1)
+        #
+        res = self.interp_operations(f, [25.0])
+        assert res == 5.0
+        self.check_operations_history(call_pure=1)
+        #
+        res = self.interp_operations(f, [-0.0])
+        assert str(res) == '-0.0'
+        self.check_operations_history(call_pure=1)
+        #
+        res = self.interp_operations(f, [1000000.0])
+        assert res == 1000.0
+        self.check_operations_history(call_pure=1)
+        #
+        res = self.interp_operations(f, [-1.0])
+        assert res == -INFINITY
+        self.check_operations_history(call_pure=0)
+        #
+        res = self.interp_operations(f, [INFINITY])
+        assert isinf(res) and not isnan(res) and res > 0.0
+        self.check_operations_history(call_pure=0)
+        #
+        res = self.interp_operations(f, [NAN])
+        assert isnan(res) and not isinf(res)
+        self.check_operations_history(call_pure=0)
+
+
+class TestOOtype(MathTests, OOJitMixin):
+    pass
+
+class TestLLtype(MathTests, LLJitMixin):
+    pass
diff --git a/pypy/jit/metainterp/test/test_quasiimmut.py b/pypy/jit/metainterp/test/test_quasiimmut.py
--- a/pypy/jit/metainterp/test/test_quasiimmut.py
+++ b/pypy/jit/metainterp/test/test_quasiimmut.py
@@ -73,8 +73,7 @@
         #
         res = self.meta_interp(f, [100, 7])
         assert res == 700
-        self.check_loops(guard_not_invalidated=2, getfield_gc=0,
-                         everywhere=True)
+        self.check_resops(guard_not_invalidated=2, getfield_gc=0)
         #
         from pypy.jit.metainterp.warmspot import get_stats
         loops = get_stats().loops
@@ -103,7 +102,7 @@
         assert f(100, 7) == 721
         res = self.meta_interp(f, [100, 7])
         assert res == 721
-        self.check_loops(guard_not_invalidated=0, getfield_gc=1)
+        self.check_resops(guard_not_invalidated=0, getfield_gc=3)
         #
         from pypy.jit.metainterp.warmspot import get_stats
         loops = get_stats().loops
@@ -134,8 +133,7 @@
         #
         res = self.meta_interp(f, [100, 7])
         assert res == 700
-        self.check_loops(guard_not_invalidated=2, getfield_gc=0,
-                         everywhere=True)
+        self.check_resops(guard_not_invalidated=2, getfield_gc=0)
 
     def test_change_during_tracing_1(self):
         myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
@@ -160,7 +158,7 @@
         assert f(100, 7) == 721
         res = self.meta_interp(f, [100, 7])
         assert res == 721
-        self.check_loops(guard_not_invalidated=0, getfield_gc=1)
+        self.check_resops(guard_not_invalidated=0, getfield_gc=2)
 
     def test_change_during_tracing_2(self):
         myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
@@ -186,7 +184,7 @@
         assert f(100, 7) == 700
         res = self.meta_interp(f, [100, 7])
         assert res == 700
-        self.check_loops(guard_not_invalidated=0, getfield_gc=1)
+        self.check_resops(guard_not_invalidated=0, getfield_gc=2)
 
     def test_change_invalidate_reentering(self):
         myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
@@ -212,7 +210,7 @@
         assert g(100, 7) == 700707
         res = self.meta_interp(g, [100, 7])
         assert res == 700707
-        self.check_loops(guard_not_invalidated=2, getfield_gc=0)
+        self.check_resops(guard_not_invalidated=4, getfield_gc=0)
 
     def test_invalidate_while_running(self):
         jitdriver = JitDriver(greens=['foo'], reds=['i', 'total'])
@@ -324,8 +322,8 @@
         assert f(100, 15) == 3009
         res = self.meta_interp(f, [100, 15])
         assert res == 3009
-        self.check_loops(guard_not_invalidated=4, getfield_gc=0,
-                         call_may_force=0, guard_not_forced=0)
+        self.check_resops(guard_not_invalidated=8, guard_not_forced=0,
+                          call_may_force=0, getfield_gc=0)
 
     def test_list_simple_1(self):
         myjitdriver = JitDriver(greens=['foo'], reds=['x', 'total'])
@@ -347,9 +345,8 @@
         #
         res = self.meta_interp(f, [100, 7])
         assert res == 700
-        self.check_loops(guard_not_invalidated=2, getfield_gc=0,
-                         getarrayitem_gc=0, getarrayitem_gc_pure=0,
-                         everywhere=True)
+        self.check_resops(getarrayitem_gc_pure=0, guard_not_invalidated=2,
+                          getarrayitem_gc=0, getfield_gc=0)
         #
         from pypy.jit.metainterp.warmspot import get_stats
         loops = get_stats().loops
@@ -385,9 +382,8 @@
         #
         res = self.meta_interp(f, [100, 7])
         assert res == 714
-        self.check_loops(guard_not_invalidated=2, getfield_gc=0,
-                         getarrayitem_gc=0, getarrayitem_gc_pure=0,
-                         arraylen_gc=0, everywhere=True)
+        self.check_resops(getarrayitem_gc_pure=0, guard_not_invalidated=2,
+                          arraylen_gc=0, getarrayitem_gc=0, getfield_gc=0)
         #
         from pypy.jit.metainterp.warmspot import get_stats
         loops = get_stats().loops
@@ -421,9 +417,8 @@
         #
         res = self.meta_interp(f, [100, 7])
         assert res == 700
-        self.check_loops(guard_not_invalidated=2, getfield_gc=0,
-                         getarrayitem_gc=0, getarrayitem_gc_pure=0,
-                         everywhere=True)
+        self.check_resops(guard_not_invalidated=2, getfield_gc=0,
+                          getarrayitem_gc=0, getarrayitem_gc_pure=0)
         #
         from pypy.jit.metainterp.warmspot import get_stats
         loops = get_stats().loops
@@ -460,9 +455,9 @@
         assert f(100, 15) == 3009
         res = self.meta_interp(f, [100, 15])
         assert res == 3009
-        self.check_loops(guard_not_invalidated=4, getfield_gc=0,
-                         getarrayitem_gc=0, getarrayitem_gc_pure=0,
-                         call_may_force=0, guard_not_forced=0)
+        self.check_resops(call_may_force=0, getfield_gc=0,
+                          getarrayitem_gc_pure=0, guard_not_forced=0,
+                          getarrayitem_gc=0, guard_not_invalidated=8)
 
     def test_invalidated_loop_is_not_used_any_more_as_target(self):
         myjitdriver = JitDriver(greens=['foo'], reds=['x'])
diff --git a/pypy/jit/metainterp/test/test_recursive.py b/pypy/jit/metainterp/test/test_recursive.py
--- a/pypy/jit/metainterp/test/test_recursive.py
+++ b/pypy/jit/metainterp/test/test_recursive.py
@@ -1,5 +1,5 @@
 import py
-from pypy.rlib.jit import JitDriver, we_are_jitted, hint
+from pypy.rlib.jit import JitDriver, hint, set_param
 from pypy.rlib.jit import unroll_safe, dont_look_inside, promote
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.debug import fatalerror
@@ -143,11 +143,11 @@
         f = self.get_interpreter(codes)
 
         assert self.meta_interp(f, [0, 0, 0], enable_opts='') == 42
-        self.check_loops(int_add = 1, call_may_force = 1, call = 0)
+        self.check_resops(call_may_force=1, int_add=1, call=0)
         assert self.meta_interp(f, [0, 0, 0], enable_opts='',
                                 inline=True) == 42
-        self.check_loops(int_add = 2, call_may_force = 0, call = 0,
-                         guard_no_exception = 0)
+        self.check_resops(call=0, int_add=2, call_may_force=0,
+                          guard_no_exception=0)
 
     def test_inline_jitdriver_check(self):
         code = "021"
@@ -160,7 +160,7 @@
                                 inline=True) == 42
         # the call is fully inlined, because we jump to subcode[1], thus
         # skipping completely the JUMP_BACK in subcode[0]
-        self.check_loops(call_may_force = 0, call_assembler = 0, call = 0)
+        self.check_resops(call=0, call_may_force=0, call_assembler=0)
 
     def test_guard_failure_in_inlined_function(self):
         def p(pc, code):
@@ -308,8 +308,8 @@
                 pc += 1
             return n
         def main(n):
-            myjitdriver.set_param('threshold', 3)
-            myjitdriver.set_param('trace_eagerness', 5)            
+            set_param(None, 'threshold', 3)
+            set_param(None, 'trace_eagerness', 5)            
             return f("c-l", n)
         expected = main(100)
         res = self.meta_interp(main, [100], enable_opts='', inline=True)
@@ -329,7 +329,7 @@
                 return recursive(n - 1) + 1
             return 0
         def loop(n):            
-            myjitdriver.set_param("threshold", 10)
+            set_param(myjitdriver, "threshold", 10)
             pc = 0
             while n:
                 myjitdriver.can_enter_jit(n=n)
@@ -351,8 +351,8 @@
             return 0
         myjitdriver = JitDriver(greens=[], reds=['n'])
         def loop(n):
-            myjitdriver.set_param("threshold", 4)
-            myjitdriver.set_param("trace_eagerness", 2)
+            set_param(None, "threshold", 4)
+            set_param(None, "trace_eagerness", 2)
             while n:
                 myjitdriver.can_enter_jit(n=n)
                 myjitdriver.jit_merge_point(n=n)
@@ -482,19 +482,19 @@
         TRACE_LIMIT = 66
  
         def main(inline):
-            myjitdriver.set_param("threshold", 10)
-            myjitdriver.set_param('function_threshold', 60)
+            set_param(None, "threshold", 10)
+            set_param(None, 'function_threshold', 60)
             if inline:
-                myjitdriver.set_param('inlining', True)
+                set_param(None, 'inlining', True)
             else:
-                myjitdriver.set_param('inlining', False)
+                set_param(None, 'inlining', False)
             return loop(100)
 
         res = self.meta_interp(main, [0], enable_opts='', trace_limit=TRACE_LIMIT)
-        self.check_loops(call_may_force=1, call=0)
+        self.check_resops(call=0, call_may_force=1)
 
         res = self.meta_interp(main, [1], enable_opts='', trace_limit=TRACE_LIMIT)
-        self.check_loops(call_may_force=0, call=0)
+        self.check_resops(call=0, call_may_force=0)
 
     def test_trace_from_start(self):
         def p(pc, code):
@@ -564,11 +564,11 @@
                 pc += 1
             return n
         def g(m):
-            myjitdriver.set_param('inlining', True)
+            set_param(None, 'inlining', True)
             # carefully chosen threshold to make sure that the inner function
             # cannot be inlined, but the inner function on its own is small
             # enough
-            myjitdriver.set_param('trace_limit', 40)
+            set_param(None, 'trace_limit', 40)
             if m > 1000000:
                 f('', 0)
             result = 0
@@ -576,7 +576,7 @@
                 result += f('-c-----------l-', i+100)
         self.meta_interp(g, [10], backendopt=True)
         self.check_aborted_count(1)
-        self.check_loops(call_assembler=1, call=0)
+        self.check_resops(call=0, call_assembler=2)        
         self.check_tree_loop_count(3)
 
     def test_directly_call_assembler(self):
@@ -625,8 +625,7 @@
         try:
             compile.compile_tmp_callback = my_ctc
             self.meta_interp(portal, [2, 5], inline=True)
-            self.check_loops(call_assembler=2, call_may_force=0,
-                             everywhere=True)
+            self.check_resops(call_may_force=0, call_assembler=2)
         finally:
             compile.compile_tmp_callback = original_ctc
         # check that we made a temporary callback
@@ -681,8 +680,7 @@
         try:
             compile.compile_tmp_callback = my_ctc
             self.meta_interp(main, [2, 5], inline=True)
-            self.check_loops(call_assembler=2, call_may_force=0,
-                             everywhere=True)
+            self.check_resops(call_may_force=0, call_assembler=2)
         finally:
             compile.compile_tmp_callback = original_ctc
         # check that we made a temporary callback
@@ -1021,7 +1019,7 @@
         res = self.meta_interp(portal, [2, 0], inline=True,
                                policy=StopAtXPolicy(residual))
         assert res == portal(2, 0)
-        self.check_loops(call_assembler=4, everywhere=True)
+        self.check_resops(call_assembler=4)
 
     def test_inline_without_hitting_the_loop(self):
         driver = JitDriver(greens = ['codeno'], reds = ['i'],
@@ -1045,7 +1043,7 @@
         assert portal(0) == 70
         res = self.meta_interp(portal, [0], inline=True)
         assert res == 70
-        self.check_loops(call_assembler=0)
+        self.check_resops(call_assembler=0)
 
     def test_inline_with_hitting_the_loop_sometimes(self):
         driver = JitDriver(greens = ['codeno'], reds = ['i', 'k'],
@@ -1071,7 +1069,7 @@
         assert portal(0, 1) == 2095
         res = self.meta_interp(portal, [0, 1], inline=True)
         assert res == 2095
-        self.check_loops(call_assembler=12, everywhere=True)
+        self.check_resops(call_assembler=12)
 
     def test_inline_with_hitting_the_loop_sometimes_exc(self):
         driver = JitDriver(greens = ['codeno'], reds = ['i', 'k'],
@@ -1109,7 +1107,7 @@
         assert main(0, 1) == 2095
         res = self.meta_interp(main, [0, 1], inline=True)
         assert res == 2095
-        self.check_loops(call_assembler=12, everywhere=True)
+        self.check_resops(call_assembler=12)
 
     def test_handle_jitexception_in_portal(self):
         # a test for _handle_jitexception_in_portal in blackhole.py
@@ -1207,9 +1205,9 @@
                     driver.can_enter_jit(c=c, i=i, v=v)
                 break
 
-        def main(c, i, set_param, v):
-            if set_param:
-                driver.set_param('function_threshold', 0)
+        def main(c, i, _set_param, v):
+            if _set_param:
+                set_param(driver, 'function_threshold', 0)
             portal(c, i, v)
 
         self.meta_interp(main, [10, 10, False, False], inline=True)
@@ -1238,7 +1236,32 @@
                 i += 1
 
         self.meta_interp(portal, [0, 0, 0], inline=True)
-        self.check_loops(call=0, call_may_force=0)
+        self.check_resops(call_may_force=0, call=0)
+
+    def test_dont_repeatedly_trace_from_the_same_guard(self):
+        driver = JitDriver(greens = [], reds = ['level', 'i'])
+
+        def portal(level):
+            if level == 0:
+                i = -10
+            else:
+                i = 0
+            #
+            while True:
+                driver.jit_merge_point(level=level, i=i)
+                if level == 25:
+                    return 42
+                i += 1
+                if i <= 0:      # <- guard
+                    continue    # first make a loop
+                else:
+                    # then we fail the guard above, doing a recursive call,
+                    # which will itself fail the same guard above, and so on
+                    return portal(level + 1)
+
+        self.meta_interp(portal, [0])
+        self.check_loop_count_at_most(2)   # and not, e.g., 24
+
 
 class TestLLtype(RecursiveTests, LLJitMixin):
     pass
diff --git a/pypy/jit/metainterp/test/test_resume.py b/pypy/jit/metainterp/test/test_resume.py
--- a/pypy/jit/metainterp/test/test_resume.py
+++ b/pypy/jit/metainterp/test/test_resume.py
@@ -23,11 +23,11 @@
     assert tag(-3, 2) == rffi.r_short(-3<<2|2)
     assert tag((1<<13)-1, 3) == rffi.r_short(((1<<15)-1)|3)
     assert tag(-1<<13, 3) == rffi.r_short((-1<<15)|3)
-    py.test.raises(ValueError, tag, 3, 5)
-    py.test.raises(ValueError, tag, 1<<13, 0)
-    py.test.raises(ValueError, tag, (1<<13)+1, 0)
-    py.test.raises(ValueError, tag, (-1<<13)-1, 0)
-    py.test.raises(ValueError, tag, (-1<<13)-5, 0)
+    py.test.raises(AssertionError, tag, 3, 5)
+    py.test.raises(TagOverflow, tag, 1<<13, 0)
+    py.test.raises(TagOverflow, tag, (1<<13)+1, 0)
+    py.test.raises(TagOverflow, tag, (-1<<13)-1, 0)
+    py.test.raises(TagOverflow, tag, (-1<<13)-5, 0)
 
 def test_untag():
     assert untag(tag(3, 1)) == (3, 1)
@@ -1135,16 +1135,11 @@
     assert ptr2.parent.next == ptr
 
 class CompareableConsts(object):
-    def __init__(self):
-        self.oldeq = None
-        
     def __enter__(self):
-        assert self.oldeq is None
-        self.oldeq = Const.__eq__
         Const.__eq__ = Const.same_box
-        
+
     def __exit__(self, type, value, traceback):
-        Const.__eq__ = self.oldeq
+        del Const.__eq__
 
 def test_virtual_adder_make_varray():
     b2s, b4s = [BoxPtr(), BoxInt(4)]
@@ -1323,8 +1318,7 @@
     assert rffi.cast(lltype.Signed, pf[1].fieldnum) == 1062
     assert rffi.cast(lltype.Signed, pf[1].itemindex) == 2147483647
     #
-    from pypy.jit.metainterp.pyjitpl import SwitchToBlackhole
-    py.test.raises(SwitchToBlackhole, modifier._add_pending_fields,
+    py.test.raises(TagOverflow, modifier._add_pending_fields,
                    [(array_a, 42, 63, 2147483648)])
 
 def test_resume_reader_fields_and_arrayitems():
diff --git a/pypy/jit/metainterp/test/test_send.py b/pypy/jit/metainterp/test/test_send.py
--- a/pypy/jit/metainterp/test/test_send.py
+++ b/pypy/jit/metainterp/test/test_send.py
@@ -20,9 +20,8 @@
             return c
         res = self.meta_interp(f, [1])
         assert res == 2
-        self.check_loops({'jump': 1,
-                          'int_sub': 1, 'int_gt' : 1,
-                          'guard_true': 1})    # all folded away
+        self.check_resops({'jump': 2, 'guard_true': 2, 'int_gt': 2,
+                           'int_sub': 2}) # all folded away
 
     def test_red_builtin_send(self):
         myjitdriver = JitDriver(greens = [], reds = ['i', 'counter'])
@@ -41,12 +40,9 @@
             return res
         res = self.meta_interp(f, [1], policy=StopAtXPolicy(externfn))
         assert res == 2
-        if self.type_system == 'ootype':
-            self.check_loops(call=1, oosend=1) # 'len' remains
-        else:
-            # 'len' becomes a getfield('num_items') for now in lltype,
-            # which is itself encoded as a 'getfield_gc'
-            self.check_loops(call=1, getfield_gc=1)
+        # 'len' becomes a getfield('num_items') for now in lltype,
+        # which is itself encoded as a 'getfield_gc'
+        self.check_resops(call=2, getfield_gc=2)
 
     def test_send_to_single_target_method(self):
         myjitdriver = JitDriver(greens = [], reds = ['i', 'counter'])
@@ -70,11 +66,10 @@
         res = self.meta_interp(f, [1], policy=StopAtXPolicy(externfn),
                                backendopt=True)
         assert res == 43
-        self.check_loops({'call': 1, 'guard_no_exception': 1,
-                          'getfield_gc': 1,
-                          'int_add': 1,
-                          'jump': 1, 'int_gt' : 1, 'guard_true' : 1,
-                          'int_sub' : 1})
+        self.check_resops({'int_gt': 2, 'getfield_gc': 2,
+                           'guard_true': 2, 'int_sub': 2, 'jump': 2,
+                           'call': 2, 'guard_no_exception': 2,
+                           'int_add': 2})
 
     def test_red_send_to_green_receiver(self):
         myjitdriver = JitDriver(greens = ['i'], reds = ['counter', 'j'])
@@ -97,7 +92,7 @@
             return res
         res = self.meta_interp(f, [4, -1])
         assert res == 145
-        self.check_loops(int_add = 1, everywhere=True)
+        self.check_resops(int_add=1)
 
     def test_oosend_base(self):
         myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'w'])
@@ -132,7 +127,7 @@
         assert res == 17
         res = self.meta_interp(f, [4, 14])
         assert res == 1404
-        self.check_loops(guard_class=0, new_with_vtable=0, new=0)
+        self.check_resops(guard_class=1, new=0, new_with_vtable=0)
 
     def test_three_receivers(self):
         myjitdriver = JitDriver(greens = [], reds = ['y'])
@@ -205,8 +200,7 @@
         # of the body in a single bigger loop with no failing guard except
         # the final one.
         self.check_loop_count(1)
-        self.check_loops(guard_class=0,
-                                int_add=2, int_sub=2)
+        self.check_resops(guard_class=1, int_add=4, int_sub=4)
         self.check_jumps(14)
 
     def test_oosend_guard_failure_2(self):
@@ -247,8 +241,7 @@
         res = self.meta_interp(f, [4, 28])
         assert res == f(4, 28)
         self.check_loop_count(1)
-        self.check_loops(guard_class=0,
-                                int_add=2, int_sub=2)
+        self.check_resops(guard_class=1, int_add=4, int_sub=4)
         self.check_jumps(14)
 
     def test_oosend_different_initial_class(self):
@@ -285,8 +278,8 @@
         # However, this doesn't match the initial value of 'w'.
         # XXX This not completely easy to check...
         self.check_loop_count(1)
-        self.check_loops(int_add=0, int_lshift=1, guard_class=0,
-                         new_with_vtable=0, new=0)
+        self.check_resops(guard_class=1, new_with_vtable=0, int_lshift=2,
+                          int_add=0, new=0)
 
     def test_indirect_call_unknown_object_1(self):
         myjitdriver = JitDriver(greens = [], reds = ['x', 'y'])
@@ -566,10 +559,7 @@
         policy = StopAtXPolicy(new, A.foo.im_func, B.foo.im_func)
         res = self.meta_interp(fn, [0, 20], policy=policy)
         assert res == 42
-        if self.type_system == 'ootype':
-            self.check_loops(oosend=1)
-        else:
-            self.check_loops(call=1)
+        self.check_resops(call=2)
 
 
     def test_residual_oosend_with_void(self):
@@ -597,10 +587,7 @@
         policy = StopAtXPolicy(new, A.foo.im_func)
         res = self.meta_interp(fn, [1, 20], policy=policy)
         assert res == 41
-        if self.type_system == 'ootype':
-            self.check_loops(oosend=1)
-        else:
-            self.check_loops(call=1)
+        self.check_resops(call=2)
 
     def test_constfold_pure_oosend(self):
         myjitdriver = JitDriver(greens=[], reds = ['i', 'obj'])
@@ -621,10 +608,7 @@
         policy = StopAtXPolicy(A.foo.im_func)
         res = self.meta_interp(fn, [1, 20], policy=policy)
         assert res == 42
-        if self.type_system == 'ootype':
-            self.check_loops(oosend=0)
-        else:
-            self.check_loops(call=0)
+        self.check_resops(call=0)
 
     def test_generalize_loop(self):
         myjitdriver = JitDriver(greens=[], reds = ['i', 'obj'])
diff --git a/pypy/jit/metainterp/test/test_slist.py b/pypy/jit/metainterp/test/test_slist.py
--- a/pypy/jit/metainterp/test/test_slist.py
+++ b/pypy/jit/metainterp/test/test_slist.py
@@ -76,7 +76,7 @@
             return lst[i]
         res = self.meta_interp(f, [21], listops=True)
         assert res == f(21)
-        self.check_loops(call=0)
+        self.check_resops(call=0)
 
     def test_getitem_neg(self):
         myjitdriver = JitDriver(greens = [], reds = ['i', 'n'])
@@ -92,7 +92,7 @@
             return x
         res = self.meta_interp(f, [-2], listops=True)
         assert res == 41
-        self.check_loops(call=0, guard_value=0)
+        self.check_resops(call=0, guard_value=0)
 
 # we don't support resizable lists on ootype
 #class TestOOtype(ListTests, OOJitMixin):
diff --git a/pypy/jit/metainterp/test/test_string.py b/pypy/jit/metainterp/test/test_string.py
--- a/pypy/jit/metainterp/test/test_string.py
+++ b/pypy/jit/metainterp/test/test_string.py
@@ -30,7 +30,7 @@
             return i
         res = self.meta_interp(f, [10, True, _str('h')], listops=True)
         assert res == 5
-        self.check_loops(**{self.CALL: 1, self.CALL_PURE: 0, 'everywhere': True})
+        self.check_resops(**{self.CALL: 1, self.CALL_PURE: 0})
 
     def test_eq_folded(self):
         _str = self._str
@@ -50,7 +50,7 @@
             return i
         res = self.meta_interp(f, [10, True, _str('h')], listops=True)
         assert res == 5
-        self.check_loops(**{self.CALL: 0, self.CALL_PURE: 0})
+        self.check_resops(**{self.CALL: 0, self.CALL_PURE: 0})
 
     def test_newstr(self):
         _str, _chr = self._str, self._chr
@@ -85,7 +85,7 @@
                 n -= 1
             return 42
         self.meta_interp(f, [6])
-        self.check_loops(newstr=0, strsetitem=0, strlen=0,
+        self.check_resops(newstr=0, strsetitem=0, strlen=0,
                          newunicode=0, unicodesetitem=0, unicodelen=0)
 
     def test_char2string_escape(self):
@@ -126,7 +126,7 @@
             return total
         res = self.meta_interp(f, [6])
         assert res == 21
-        self.check_loops(newstr=0, strgetitem=0, strsetitem=0, strlen=0,
+        self.check_resops(newstr=0, strgetitem=0, strsetitem=0, strlen=0,
                          newunicode=0, unicodegetitem=0, unicodesetitem=0,
                          unicodelen=0)
 
@@ -147,7 +147,7 @@
                 m -= 1
             return 42
         self.meta_interp(f, [6, 7])
-        self.check_loops(newstr=0, strsetitem=0,
+        self.check_resops(newstr=0, strsetitem=0,
                          newunicode=0, unicodesetitem=0,
                          call=0, call_pure=0)
 
@@ -168,12 +168,11 @@
             return 42
         self.meta_interp(f, [6, 7])
         if _str is str:
-            self.check_loops(newstr=1, strsetitem=0, copystrcontent=2,
-                             call=1, call_pure=0)   # escape
+            self.check_resops(call_pure=0, copystrcontent=4,
+                              strsetitem=0, call=2, newstr=2)
         else:
-            self.check_loops(newunicode=1, unicodesetitem=0,
-                             copyunicodecontent=2,
-                             call=1, call_pure=0)   # escape
+            self.check_resops(call_pure=0, unicodesetitem=0, call=2,
+                              copyunicodecontent=4, newunicode=2)
 
     def test_strconcat_escape_str_char(self):
         _str, _chr = self._str, self._chr
@@ -192,12 +191,11 @@
             return 42
         self.meta_interp(f, [6, 7])
         if _str is str:
-            self.check_loops(newstr=1, strsetitem=1, copystrcontent=1,
-                             call=1, call_pure=0)   # escape
+            self.check_resops(call_pure=0, copystrcontent=2, strsetitem=2,
+                              call=2, newstr=2)
         else:
-            self.check_loops(newunicode=1, unicodesetitem=1,
-                             copyunicodecontent=1,
-                             call=1, call_pure=0)   # escape
+            self.check_resops(call_pure=0, unicodesetitem=2, call=2,
+                              copyunicodecontent=2, newunicode=2)
 
     def test_strconcat_escape_char_str(self):
         _str, _chr = self._str, self._chr
@@ -216,12 +214,11 @@
             return 42
         self.meta_interp(f, [6, 7])
         if _str is str:
-            self.check_loops(newstr=1, strsetitem=1, copystrcontent=1,
-                             call=1, call_pure=0)   # escape
+            self.check_resops(call_pure=0, copystrcontent=2,
+                              strsetitem=2, call=2, newstr=2)
         else:
-            self.check_loops(newunicode=1, unicodesetitem=1,
-                             copyunicodecontent=1,
-                             call=1, call_pure=0)   # escape
+            self.check_resops(call_pure=0, unicodesetitem=2, call=2,
+                              copyunicodecontent=2, newunicode=2)
 
     def test_strconcat_escape_char_char(self):
         _str, _chr = self._str, self._chr
@@ -239,12 +236,11 @@
             return 42
         self.meta_interp(f, [6, 7])
         if _str is str:
-            self.check_loops(newstr=1, strsetitem=2, copystrcontent=0,
-                             call=1, call_pure=0)   # escape
+            self.check_resops(call_pure=0, copystrcontent=0,
+                              strsetitem=4, call=2, newstr=2)
         else:
-            self.check_loops(newunicode=1, unicodesetitem=2,
-                             copyunicodecontent=0,
-                             call=1, call_pure=0)   # escape
+            self.check_resops(call_pure=0, unicodesetitem=4, call=2,
+                              copyunicodecontent=0, newunicode=2)
 
     def test_strconcat_escape_str_char_str(self):
         _str, _chr = self._str, self._chr
@@ -263,12 +259,11 @@
             return 42
         self.meta_interp(f, [6, 7])
         if _str is str:
-            self.check_loops(newstr=1, strsetitem=1, copystrcontent=2,
-                             call=1, call_pure=0)   # escape
+            self.check_resops(call_pure=0, copystrcontent=4, strsetitem=2,
+                              call=2, newstr=2)
         else:
-            self.check_loops(newunicode=1, unicodesetitem=1,
-                             copyunicodecontent=2,
-                             call=1, call_pure=0)   # escape
+            self.check_resops(call_pure=0, unicodesetitem=2, call=2,
+                              copyunicodecontent=4, newunicode=2)
 
     def test_strconcat_guard_fail(self):
         _str = self._str
@@ -325,7 +320,7 @@
                 m -= 1
             return 42
         self.meta_interp(f, [6, 7])
-        self.check_loops(newstr=0, newunicode=0)
+        self.check_resops(newunicode=0, newstr=0)
 
     def test_str_slice_len_surviving(self):
         _str = self._str
@@ -491,7 +486,7 @@
             def __init__(self, s):
                 self.defaultencoding = s
         _str = self._str
-        sys = Sys(_str('ascii'))        
+        sys = Sys(_str('ascii'))
         mydriver = JitDriver(reds = ['n', 'sa'], greens = [])
         def f(n):
             sa = 0
@@ -504,13 +499,13 @@
             sys.defaultencoding = _str('utf-8')
             return sa
         assert self.meta_interp(f, [8]) == f(8)
-        self.check_loops({'int_add': 1, 'guard_true': 1, 'int_sub': 1,
-                          'jump': 1, 'int_is_true': 1,
-                          'guard_not_invalidated': 1})
+        self.check_resops({'jump': 2, 'int_is_true': 2, 'int_add': 2,
+                           'guard_true': 2, 'guard_not_invalidated': 2,
+                           'int_sub': 2})
 
     def test_promote_string(self):
         driver = JitDriver(greens = [], reds = ['n'])
-        
+
         def f(n):
             while n < 21:
                 driver.jit_merge_point(n=n)
@@ -519,7 +514,7 @@
             return 0
 
         self.meta_interp(f, [0])
-        self.check_loops(call=3 + 1) # one for int2str
+        self.check_resops(call=7)
 
 #class TestOOtype(StringTests, OOJitMixin):
 #    CALL = "oosend"
@@ -552,9 +547,8 @@
                 m -= 1
             return 42
         self.meta_interp(f, [6, 7])
-        self.check_loops(call=1,    # escape()
-                         newunicode=1, unicodegetitem=0,
-                         unicodesetitem=1, copyunicodecontent=1)
+        self.check_resops(unicodesetitem=2, newunicode=2, call=4,
+                          copyunicodecontent=2, unicodegetitem=0)
 
     def test_str2unicode_fold(self):
         _str = self._str
@@ -572,9 +566,9 @@
                 m -= 1
             return 42
         self.meta_interp(f, [6, 7])
-        self.check_loops(call_pure=0, call=1,
-                         newunicode=0, unicodegetitem=0,
-                         unicodesetitem=0, copyunicodecontent=0)
+        self.check_resops(call_pure=0, unicodesetitem=0, call=2,
+                          newunicode=0, unicodegetitem=0,
+                          copyunicodecontent=0)
 
     def test_join_chars(self):
         jitdriver = JitDriver(reds=['a', 'b', 'c', 'i'], greens=[])
@@ -596,9 +590,8 @@
         # The "".join should be unrolled, since the length of x is known since
         # it is virtual, ensure there are no calls to ll_join_chars, or
         # allocations.
-        self.check_loops({
-            "guard_true": 5, "int_is_true": 3, "int_lt": 2, "int_add": 2, "jump": 2,
-        }, everywhere=True)
+        self.check_resops({'jump': 2, 'guard_true': 5, 'int_lt': 2,
+                           'int_add': 2, 'int_is_true': 3})
 
     def test_virtual_copystringcontent(self):
         jitdriver = JitDriver(reds=['n', 'result'], greens=[])
diff --git a/pypy/jit/metainterp/test/test_tl.py b/pypy/jit/metainterp/test/test_tl.py
--- a/pypy/jit/metainterp/test/test_tl.py
+++ b/pypy/jit/metainterp/test/test_tl.py
@@ -72,16 +72,16 @@
         res = self.meta_interp(main, [0, 6], listops=True,
                                backendopt=True)
         assert res == 5040
-        self.check_loops({'int_mul':1, 'jump':1,
-                          'int_sub':1, 'int_le':1, 'guard_false':1})
+        self.check_resops({'jump': 2, 'int_le': 2, 'guard_value': 1,
+                           'int_mul': 2, 'guard_false': 2, 'int_sub': 2})
 
     def test_tl_2(self):
         main = self._get_main()
         res = self.meta_interp(main, [1, 10], listops=True,
                                backendopt=True)
         assert res == main(1, 10)
-        self.check_loops({'int_sub':1, 'int_le':1,
-                          'guard_false':1, 'jump':1})
+        self.check_resops({'int_le': 2, 'int_sub': 2, 'jump': 2,
+                           'guard_false': 2, 'guard_value': 1})
 
     def test_tl_call(self, listops=True, policy=None):
         from pypy.jit.tl.tl import interp
diff --git a/pypy/jit/metainterp/test/test_tracingopts.py b/pypy/jit/metainterp/test/test_tracingopts.py
--- a/pypy/jit/metainterp/test/test_tracingopts.py
+++ b/pypy/jit/metainterp/test/test_tracingopts.py
@@ -593,6 +593,32 @@
         res = self.interp_operations(fn, [sys.maxint])
         assert res == 12
 
+    def test_opaque_list(self):
+        from pypy.rlib.rerased import new_erasing_pair
+        erase, unerase = new_erasing_pair("test_opaque_list")
+        def fn(n, ca, cb):
+            l1 = [n]
+            l2 = [n]
+            a1 = erase(l1)
+            a2 = erase(l1)
+            a = a1
+            if ca:
+                a = a2
+                if n < -100:
+                    unerase(a).append(5)
+            b = a1
+            if cb:
+                b = a
+            return unerase(a)[0] + unerase(b)[0]
+        res = self.interp_operations(fn, [7, 0, 1])
+        assert res == 7 * 2
+        self.check_operations_history(getarrayitem_gc=0,
+                getfield_gc=0)
+        res = self.interp_operations(fn, [-7, 1, 1])
+        assert res == -7 * 2
+        self.check_operations_history(getarrayitem_gc=0,
+                getfield_gc=0)
+
     def test_copy_str_content(self):
         def fn(n):
             a = StringBuilder()
@@ -601,4 +627,4 @@
             return x[0]
         res = self.interp_operations(fn, [0])
         assert res == 1
-        self.check_operations_history(getarrayitem_gc=0, getarrayitem_gc_pure=0 )
\ No newline at end of file
+        self.check_operations_history(getarrayitem_gc=0, getarrayitem_gc_pure=0)
diff --git a/pypy/jit/metainterp/test/test_virtual.py b/pypy/jit/metainterp/test/test_virtual.py
--- a/pypy/jit/metainterp/test/test_virtual.py
+++ b/pypy/jit/metainterp/test/test_virtual.py
@@ -31,8 +31,9 @@
         res = self.meta_interp(f, [10])
         assert res == 55 * 10
         self.check_loop_count(1)
-        self.check_loops(new=0, new_with_vtable=0,
-                                getfield_gc=0, setfield_gc=0)
+        self.check_resops(new_with_vtable=0, setfield_gc=0,
+                          getfield_gc=2, new=0)
+
 
     def test_virtualized2(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'node1', 'node2'])
@@ -53,8 +54,8 @@
                 n -= 1
             return node1.value * node2.value
         assert f(10) == self.meta_interp(f, [10])
-        self.check_loops(new=0, new_with_vtable=0,
-                         getfield_gc=0, setfield_gc=0)
+        self.check_resops(new_with_vtable=0, setfield_gc=0, getfield_gc=2,
+                          new=0)
 
     def test_virtualized_circular1(self):
         class MyNode():
@@ -79,8 +80,8 @@
         res = self.meta_interp(f, [10])
         assert res == 55 * 10
         self.check_loop_count(1)
-        self.check_loops(new=0, new_with_vtable=0,
-                                getfield_gc=0, setfield_gc=0)
+        self.check_resops(new_with_vtable=0, setfield_gc=0,
+                          getfield_gc=3, new=0)
 
     def test_virtualized_float(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'node'])
@@ -97,7 +98,7 @@
         res = self.meta_interp(f, [10])
         assert res == f(10)
         self.check_loop_count(1)
-        self.check_loops(new=0, float_add=0)
+        self.check_resops(new=0, float_add=1)
 
     def test_virtualized_float2(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'node'])
@@ -115,7 +116,8 @@
         res = self.meta_interp(f, [10])
         assert res == f(10)
         self.check_loop_count(1)
-        self.check_loops(new=0, float_add=1)
+        self.check_resops(new=0, float_add=2)
+
 
     def test_virtualized_2(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'node'])
@@ -139,8 +141,8 @@
         res = self.meta_interp(f, [10])
         assert res == 55 * 30
         self.check_loop_count(1)
-        self.check_loops(new=0, new_with_vtable=0,
-                                getfield_gc=0, setfield_gc=0)
+        self.check_resops(new_with_vtable=0, setfield_gc=0, getfield_gc=2,
+                          new=0)
 
     def test_nonvirtual_obj_delays_loop(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'node'])
@@ -160,8 +162,8 @@
         res = self.meta_interp(f, [500])
         assert res == 640
         self.check_loop_count(1)
-        self.check_loops(new=0, new_with_vtable=0,
-                                getfield_gc=0, setfield_gc=0)
+        self.check_resops(new_with_vtable=0, setfield_gc=0,
+                          getfield_gc=1, new=0)
 
     def test_two_loops_with_virtual(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'node'])
@@ -184,8 +186,9 @@
         res = self.meta_interp(f, [18])
         assert res == f(18)
         self.check_loop_count(2)
-        self.check_loops(new=0, new_with_vtable=0,
-                                getfield_gc=0, setfield_gc=0)
+        self.check_resops(new_with_vtable=0, setfield_gc=0,
+                          getfield_gc=2, new=0)
+
         
     def test_two_loops_with_escaping_virtual(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'node'])
@@ -212,8 +215,8 @@
         res = self.meta_interp(f, [20], policy=StopAtXPolicy(externfn))
         assert res == f(20)
         self.check_loop_count(3)
-        self.check_loops(**{self._new_op: 1})
-        self.check_loops(int_mul=0, call=1)
+        self.check_resops(**{self._new_op: 1})
+        self.check_resops(int_mul=0, call=1)
 
     def test_two_virtuals(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'prev'])
@@ -236,7 +239,7 @@
 
         res = self.meta_interp(f, [12])
         assert res == 78
-        self.check_loops(new_with_vtable=0, new=0)
+        self.check_resops(new_with_vtable=0, new=0)
 
     def test_specialied_bridge(self):
         myjitdriver = JitDriver(greens = [], reds = ['y', 'x', 'res'])
@@ -281,7 +284,7 @@
 
         res = self.meta_interp(f, [20])
         assert res == 9
-        self.check_loops(new_with_vtable=0, new=0)
+        self.check_resops(new_with_vtable=0, new=0)
 
     def test_immutable_constant_getfield(self):
         myjitdriver = JitDriver(greens = ['stufflist'], reds = ['n', 'i'])
@@ -307,7 +310,7 @@
 
         res = self.meta_interp(f, [10, 1, 0], listops=True)
         assert res == 0
-        self.check_loops(getfield_gc=0)
+        self.check_resops(getfield_gc=0)
 
     def test_escapes(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'parent'])
@@ -336,7 +339,7 @@
 
         res = self.meta_interp(f, [10], policy=StopAtXPolicy(g))
         assert res == 3
-        self.check_loops(**{self._new_op: 1}) 
+        self.check_resops(**{self._new_op: 1}) 
 
     def test_virtual_on_virtual(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'parent'])
@@ -366,7 +369,7 @@
 
         res = self.meta_interp(f, [10])
         assert res == 2
-        self.check_loops(new=0, new_with_vtable=0) 
+        self.check_resops(new=0, new_with_vtable=0)
 
     def test_bridge_from_interpreter(self):
         mydriver = JitDriver(reds = ['n', 'f'], greens = [])
@@ -609,7 +612,7 @@
             return node.value
         res = self.meta_interp(f, [48, 3], policy=StopAtXPolicy(externfn))
         assert res == f(48, 3)
-        self.check_loop_count(3)
+        self.check_loop_count(5)
         res = self.meta_interp(f, [40, 3], policy=StopAtXPolicy(externfn))
         assert res == f(40, 3)
         self.check_loop_count(3)
@@ -758,6 +761,27 @@
         res = self.meta_interp(f, [0x1F, 0x11])
         assert res == f(0x1F, 0x11)
 
+    def test_duplicated_virtual(self):
+        myjitdriver = JitDriver(greens = [], reds = ['n', 'node1', 'node2'])
+        def f(n):
+            node1 = self._new()
+            node1.value = 0
+            node2 = self._new()
+            node2.value = 1
+            while n > 0:
+                myjitdriver.jit_merge_point(n=n, node1=node1, node2=node2)
+                next = self._new()
+                next.value = node1.value + node2.value + n
+                node1 = next
+                node2 = next
+                n -= 1
+            return node1.value 
+        res = self.meta_interp(f, [10])
+        assert res == f(10)
+        self.check_resops(new_with_vtable=0, new=0)
+
+        
+
 class VirtualMiscTests:
 
     def test_multiple_equal_virtuals(self):
@@ -841,7 +865,7 @@
                 del t2
             return i
         assert self.meta_interp(f, []) == 10
-        self.check_loops(new_array=0)
+        self.check_resops(new_array=0)
 
     def test_virtual_streq_bug(self):
         mydriver = JitDriver(reds = ['i', 's', 'a'], greens = [])
@@ -942,8 +966,8 @@
 
         res = self.meta_interp(f, [16])
         assert res == f(16)
-        self.check_loops(getfield_gc=2)
-        
+        self.check_resops(getfield_gc=7)
+     
 
 # ____________________________________________________________
 # Run 1: all the tests instantiate a real RPython class
@@ -985,10 +1009,8 @@
         res = self.meta_interp(f, [10])
         assert res == 20
         self.check_loop_count(1)
-        self.check_loops(new=0, new_with_vtable=0,
-                                getfield_gc=0, setfield_gc=0)
-
-
+        self.check_resops(new_with_vtable=0, setfield_gc=0, getfield_gc=0,
+                          new=0)
 
 class TestOOtype_Instance(VirtualTests, OOJitMixin):
     _new_op = 'new_with_vtable'
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
@@ -77,7 +77,7 @@
             return xy.inst_x
         res = self.meta_interp(f, [20])
         assert res == 30
-        self.check_loops(getfield_gc=0, setfield_gc=0)
+        self.check_resops(setfield_gc=0, getfield_gc=0)
 
     def test_preexisting_access_2(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'xy'],
@@ -102,7 +102,7 @@
         assert f(5) == 185
         res = self.meta_interp(f, [5])
         assert res == 185
-        self.check_loops(getfield_gc=0, setfield_gc=0)
+        self.check_resops(setfield_gc=0, getfield_gc=0)
 
     def test_two_paths_access(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'xy'],
@@ -124,7 +124,7 @@
             return xy.inst_x
         res = self.meta_interp(f, [18])
         assert res == 10118
-        self.check_loops(getfield_gc=0, setfield_gc=0)
+        self.check_resops(setfield_gc=0, getfield_gc=0)
 
     def test_synchronize_in_return(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'xy'],
@@ -146,7 +146,7 @@
             return xy.inst_x
         res = self.meta_interp(f, [18])
         assert res == 10180
-        self.check_loops(getfield_gc=0, setfield_gc=0)
+        self.check_resops(setfield_gc=0, getfield_gc=0)
 
     def test_virtualizable_and_greens(self):
         myjitdriver = JitDriver(greens = ['m'], reds = ['n', 'xy'],
@@ -174,7 +174,7 @@
             return res
         res = self.meta_interp(f, [40])
         assert res == 50 * 4
-        self.check_loops(getfield_gc=0, setfield_gc=0)
+        self.check_resops(setfield_gc=0, getfield_gc=0)
 
     def test_double_frame(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'xy', 'other'],
@@ -197,8 +197,7 @@
             return xy.inst_x
         res = self.meta_interp(f, [20])
         assert res == 134
-        self.check_loops(getfield_gc=0, setfield_gc=1)
-        self.check_loops(getfield_gc=1, setfield_gc=2, everywhere=True)
+        self.check_resops(setfield_gc=2, getfield_gc=1)
 
     # ------------------------------
 
@@ -248,8 +247,8 @@
             return xy2.inst_l1[2]
         res = self.meta_interp(f, [16])
         assert res == 3001 + 16 * 80
-        self.check_loops(getfield_gc=0, setfield_gc=0,
-                         getarrayitem_gc=0, setarrayitem_gc=0)
+        self.check_resops(setarrayitem_gc=0, setfield_gc=0,
+                          getarrayitem_gc=0, getfield_gc=0)
 
     def test_synchronize_arrays_in_return(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'xy2'],
@@ -279,8 +278,7 @@
         assert f(18) == 10360
         res = self.meta_interp(f, [18])
         assert res == 10360
-        self.check_loops(getfield_gc=0, setfield_gc=0,
-                         getarrayitem_gc=0)
+        self.check_resops(setfield_gc=0, getarrayitem_gc=0, getfield_gc=0)
 
     def test_array_length(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'xy2'],
@@ -306,8 +304,8 @@
             return xy2.inst_l1[1]
         res = self.meta_interp(f, [18])
         assert res == 2941309 + 18
-        self.check_loops(getfield_gc=0, setfield_gc=0,
-                         getarrayitem_gc=0, arraylen_gc=0)
+        self.check_resops(setfield_gc=0, getarrayitem_gc=0,
+                          arraylen_gc=0, getfield_gc=0)
 
     def test_residual_function(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'xy2'],
@@ -340,8 +338,8 @@
             return xy2.inst_l1[1]
         res = self.meta_interp(f, [18])
         assert res == 2941309 + 18
-        self.check_loops(getfield_gc=0, setfield_gc=0,
-                         getarrayitem_gc=0, arraylen_gc=1, call=1)
+        self.check_resops(call=2, setfield_gc=0, getarrayitem_gc=0,
+                          arraylen_gc=2, getfield_gc=0)
 
     def test_double_frame_array(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'xy2', 'other'],
@@ -377,8 +375,8 @@
         expected = f(20)
         res = self.meta_interp(f, [20], enable_opts='')
         assert res == expected
-        self.check_loops(getfield_gc=1, setfield_gc=0,
-                         arraylen_gc=1, getarrayitem_gc=1, setarrayitem_gc=1)
+        self.check_resops(setarrayitem_gc=1, setfield_gc=0,
+                          getarrayitem_gc=1, arraylen_gc=1, getfield_gc=1)
 
     # ------------------------------
 
@@ -425,8 +423,7 @@
         assert f(18) == 10360
         res = self.meta_interp(f, [18])
         assert res == 10360
-        self.check_loops(getfield_gc=0, setfield_gc=0,
-                         getarrayitem_gc=0)
+        self.check_resops(setfield_gc=0, getarrayitem_gc=0, getfield_gc=0)
 
     # ------------------------------
 
@@ -460,8 +457,7 @@
 
         res = self.meta_interp(f, [10])
         assert res == 55
-        self.check_loops(getfield_gc=0, setfield_gc=0)
-
+        self.check_resops(setfield_gc=0, getfield_gc=0)
 
     def test_virtualizable_with_array(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'x', 'frame'],
@@ -495,8 +491,7 @@
 
         res = self.meta_interp(f, [10, 1], listops=True)
         assert res == f(10, 1)
-        self.check_loops(getarrayitem_gc=0)
-
+        self.check_resops(getarrayitem_gc=0)
 
     def test_subclass_of_virtualizable(self):
         myjitdriver = JitDriver(greens = [], reds = ['frame'],
@@ -524,8 +519,7 @@
 
         res = self.meta_interp(f, [10])
         assert res == 55
-        self.check_loops(getfield_gc=0, setfield_gc=0)
-
+        self.check_resops(setfield_gc=0, getfield_gc=0)
 
     def test_external_pass(self):
         jitdriver = JitDriver(greens = [], reds = ['n', 'z', 'frame'],
@@ -1011,8 +1005,8 @@
 
         res = self.meta_interp(f, [70], listops=True)
         assert res == intmask(42 ** 70)
-        self.check_loops(int_add=0,
-                         int_sub=1)   # for 'n -= 1' only
+        self.check_resops(int_add=0,
+                          int_sub=2)   # for 'n -= 1' only
 
     def test_simple_access_directly(self):
         myjitdriver = JitDriver(greens = [], reds = ['frame'],
@@ -1043,7 +1037,7 @@
 
         res = self.meta_interp(f, [10])
         assert res == 55
-        self.check_loops(getfield_gc=0, setfield_gc=0)
+        self.check_resops(setfield_gc=0, getfield_gc=0)
 
         from pypy.jit.backend.test.support import BaseCompiledMixin
         if isinstance(self, BaseCompiledMixin):
@@ -1098,42 +1092,42 @@
 
         res = self.meta_interp(f, [10])
         assert res == 55
-        self.check_loops(new_with_vtable=0)
+        self.check_resops(new_with_vtable=0)
 
     def test_check_for_nonstandardness_only_once(self):
-         myjitdriver = JitDriver(greens = [], reds = ['frame'],
-                                 virtualizables = ['frame'])
+        myjitdriver = JitDriver(greens = [], reds = ['frame'],
+                                virtualizables = ['frame'])
 
-         class Frame(object):
-             _virtualizable2_ = ['x', 'y', 'z']
+        class Frame(object):
+            _virtualizable2_ = ['x', 'y', 'z']
 
-             def __init__(self, x, y, z=1):
-                 self = hint(self, access_directly=True)
-                 self.x = x
-                 self.y = y
-                 self.z = z
+            def __init__(self, x, y, z=1):
+                self = hint(self, access_directly=True)
+                self.x = x
+                self.y = y
+                self.z = z
 
-         class SomewhereElse:
-             pass
-         somewhere_else = SomewhereElse()
+        class SomewhereElse:
+            pass
+        somewhere_else = SomewhereElse()
 
-         def f(n):
-             frame = Frame(n, 0)
-             somewhere_else.top_frame = frame        # escapes
-             frame = hint(frame, access_directly=True)
-             while frame.x > 0:
-                 myjitdriver.can_enter_jit(frame=frame)
-                 myjitdriver.jit_merge_point(frame=frame)
-                 top_frame = somewhere_else.top_frame
-                 child_frame = Frame(frame.x, top_frame.z, 17)
-                 frame.y += child_frame.x
-                 frame.x -= top_frame.z
-             return somewhere_else.top_frame.y
- 
-         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 f(n):
+            frame = Frame(n, 0)
+            somewhere_else.top_frame = frame        # escapes
+            frame = hint(frame, access_directly=True)
+            while frame.x > 0:
+                myjitdriver.can_enter_jit(frame=frame)
+                myjitdriver.jit_merge_point(frame=frame)
+                top_frame = somewhere_else.top_frame
+                child_frame = Frame(frame.x, top_frame.z, 17)
+                frame.y += child_frame.x
+                frame.x -= top_frame.z
+            return somewhere_else.top_frame.y
+
+        res = self.meta_interp(f, [10])
+        assert res == 55
+        self.check_resops(new_with_vtable=0, ptr_eq=1)
+        self.check_history(ptr_eq=2)
 
     def test_virtual_child_frame_with_arrays(self):
         myjitdriver = JitDriver(greens = [], reds = ['frame'],
@@ -1165,7 +1159,7 @@
 
         res = self.meta_interp(f, [10], listops=True)
         assert res == 55
-        self.check_loops(new_with_vtable=0)
+        self.check_resops(new_with_vtable=0)
 
     def test_blackhole_should_not_pay_attention(self):
         myjitdriver = JitDriver(greens = [], reds = ['frame'],
@@ -1203,7 +1197,7 @@
 
         res = self.meta_interp(f, [10])
         assert res == 155
-        self.check_loops(getfield_gc=0, setfield_gc=0)
+        self.check_resops(setfield_gc=0, getfield_gc=0)
 
     def test_blackhole_should_synchronize(self):
         myjitdriver = JitDriver(greens = [], reds = ['frame'],
@@ -1239,7 +1233,7 @@
 
         res = self.meta_interp(f, [10])
         assert res == 155
-        self.check_loops(getfield_gc=0, setfield_gc=0)
+        self.check_resops(setfield_gc=0, getfield_gc=0)
 
     def test_blackhole_should_not_reenter(self):
         if not self.basic:
diff --git a/pypy/jit/metainterp/test/test_virtualref.py b/pypy/jit/metainterp/test/test_virtualref.py
--- a/pypy/jit/metainterp/test/test_virtualref.py
+++ b/pypy/jit/metainterp/test/test_virtualref.py
@@ -171,7 +171,7 @@
             return 1
         #
         self.meta_interp(f, [10])
-        self.check_loops(new_with_vtable=1)   # the vref
+        self.check_resops(new_with_vtable=2) # the vref
         self.check_aborted_count(0)
 
     def test_simple_all_removed(self):
@@ -205,8 +205,7 @@
                 virtual_ref_finish(vref, xy)
         #
         self.meta_interp(f, [15])
-        self.check_loops(new_with_vtable=0,     # all virtualized
-                         new_array=0)
+        self.check_resops(new_with_vtable=0, new_array=0)
         self.check_aborted_count(0)
 
     def test_simple_no_access(self):
@@ -242,7 +241,7 @@
                 virtual_ref_finish(vref, xy)
         #
         self.meta_interp(f, [15])
-        self.check_loops(new_with_vtable=1,     # the vref: xy doesn't need to be forced
+        self.check_resops(new_with_vtable=2,     # the vref: xy doesn't need to be forced
                          new_array=0)           # and neither xy.next1/2/3
         self.check_aborted_count(0)
 
@@ -280,8 +279,8 @@
                 exctx.topframeref = vref_None
         #
         self.meta_interp(f, [15])
-        self.check_loops(new_with_vtable=2,   # XY(), the vref
-                         new_array=3)         # next1/2/3
+        self.check_resops(new_with_vtable=4,   # XY(), the vref
+                          new_array=6)         # next1/2/3
         self.check_aborted_count(0)
 
     def test_simple_force_sometimes(self):
@@ -320,8 +319,8 @@
         #
         res = self.meta_interp(f, [30])
         assert res == 13
-        self.check_loops(new_with_vtable=1,   # the vref, but not XY()
-                         new_array=0)         # and neither next1/2/3
+        self.check_resops(new_with_vtable=2,   # the vref, but not XY()
+                          new_array=0)         # and neither next1/2/3
         self.check_loop_count(1)
         self.check_aborted_count(0)
 
@@ -362,7 +361,7 @@
         #
         res = self.meta_interp(f, [30])
         assert res == 13
-        self.check_loops(new_with_vtable=0, # all virtualized in the n!=13 loop
+        self.check_resops(new_with_vtable=0, # all virtualized in the n!=13 loop
                          new_array=0)
         self.check_loop_count(1)
         self.check_aborted_count(0)
@@ -412,7 +411,7 @@
         res = self.meta_interp(f, [72])
         assert res == 6
         self.check_loop_count(2)     # the loop and the bridge
-        self.check_loops(new_with_vtable=2,  # loop: nothing; bridge: vref, xy
+        self.check_resops(new_with_vtable=2,  # loop: nothing; bridge: vref, xy
                          new_array=2)        # bridge: next4, next5
         self.check_aborted_count(0)
 
@@ -442,8 +441,8 @@
         #
         res = self.meta_interp(f, [15])
         assert res == 1
-        self.check_loops(new_with_vtable=2,     # vref, xy
-                         new_array=1)           # next1
+        self.check_resops(new_with_vtable=4,     # vref, xy
+                          new_array=2)           # next1
         self.check_aborted_count(0)
 
     def test_recursive_call_1(self):
@@ -543,7 +542,7 @@
         #
         res = self.meta_interp(f, [15])
         assert res == 1
-        self.check_loops(new_with_vtable=2)     # vref, xy
+        self.check_resops(new_with_vtable=4)     # vref, xy
 
     def test_cannot_use_invalid_virtualref(self):
         myjitdriver = JitDriver(greens = [], reds = ['n'])
diff --git a/pypy/jit/metainterp/test/test_virtualstate.py b/pypy/jit/metainterp/test/test_virtualstate.py
--- a/pypy/jit/metainterp/test/test_virtualstate.py
+++ b/pypy/jit/metainterp/test/test_virtualstate.py
@@ -847,7 +847,8 @@
         i5 = arraylen_gc(p2, descr=arraydescr)
         i6 = int_ge(i5, 1)
         guard_true(i6) []
-        jump(p0, p1, p2)
+        p3 = getarrayitem_gc(p2, 0, descr=arraydescr)
+        jump(p0, p1, p3, p2)
         """
         self.optimize_bridge(loop, bridge, expected, p0=self.myptr)
 
diff --git a/pypy/jit/metainterp/test/test_warmspot.py b/pypy/jit/metainterp/test/test_warmspot.py
--- a/pypy/jit/metainterp/test/test_warmspot.py
+++ b/pypy/jit/metainterp/test/test_warmspot.py
@@ -1,10 +1,7 @@
 import py
-from pypy.jit.metainterp.warmspot import ll_meta_interp
 from pypy.jit.metainterp.warmspot import get_stats
-from pypy.rlib.jit import JitDriver
-from pypy.rlib.jit import unroll_safe
+from pypy.rlib.jit import JitDriver, set_param, unroll_safe
 from pypy.jit.backend.llgraph import runner
-from pypy.jit.metainterp.history import BoxInt
 
 from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.jit.metainterp.optimizeopt import ALL_OPTS_NAMES
@@ -97,18 +94,18 @@
                 n = A().m(n)
             return n
         def f(n, enable_opts):
-            myjitdriver.set_param('enable_opts', hlstr(enable_opts))
+            set_param(None, 'enable_opts', hlstr(enable_opts))
             return g(n)
 
         # check that the set_param will override the default
         res = self.meta_interp(f, [10, llstr('')])
         assert res == 0
-        self.check_loops(new_with_vtable=1)
+        self.check_resops(new_with_vtable=1)
 
         res = self.meta_interp(f, [10, llstr(ALL_OPTS_NAMES)],
                                enable_opts='')
         assert res == 0
-        self.check_loops(new_with_vtable=0)
+        self.check_resops(new_with_vtable=0)
 
     def test_unwanted_loops(self):
         mydriver = JitDriver(reds = ['n', 'total', 'm'], greens = [])
@@ -163,7 +160,7 @@
             return n
         self.meta_interp(f, [50], backendopt=True)
         self.check_enter_count_at_most(2)
-        self.check_loops(call=0)
+        self.check_resops(call=0)
 
     def test_loop_header(self):
         # artificial test: we enter into the JIT only when can_enter_jit()
@@ -187,7 +184,7 @@
         assert f(15) == 1
         res = self.meta_interp(f, [15], backendopt=True)
         assert res == 1
-        self.check_loops(int_add=1)   # I get 13 without the loop_header()
+        self.check_resops(int_add=2)   # I get 13 without the loop_header()
 
     def test_omit_can_enter_jit(self):
         # Simple test comparing the effects of always giving a can_enter_jit(),
@@ -249,8 +246,8 @@
                 m = m - 1
         self.meta_interp(f1, [8])
         self.check_loop_count(1)
-        self.check_loops({'int_sub': 1, 'int_gt': 1, 'guard_true': 1,
-                          'jump': 1})
+        self.check_resops({'jump': 2, 'guard_true': 2, 'int_gt': 2,
+                           'int_sub': 2})
 
     def test_void_red_variable(self):
         mydriver = JitDriver(greens=[], reds=['a', 'm'])
diff --git a/pypy/jit/metainterp/test/test_ztranslation.py b/pypy/jit/metainterp/test/test_ztranslation.py
--- a/pypy/jit/metainterp/test/test_ztranslation.py
+++ b/pypy/jit/metainterp/test/test_ztranslation.py
@@ -1,7 +1,7 @@
 import py
 from pypy.jit.metainterp.warmspot import rpython_ll_meta_interp, ll_meta_interp
 from pypy.jit.backend.llgraph import runner
-from pypy.rlib.jit import JitDriver, unroll_parameters
+from pypy.rlib.jit import JitDriver, unroll_parameters, set_param
 from pypy.rlib.jit import PARAMETERS, dont_look_inside, hint
 from pypy.jit.metainterp.jitprof import Profiler
 from pypy.rpython.lltypesystem import lltype, llmemory
@@ -57,9 +57,9 @@
                               get_printable_location=get_printable_location)
         def f(i):
             for param, defl in unroll_parameters:
-                jitdriver.set_param(param, defl)
-            jitdriver.set_param("threshold", 3)
-            jitdriver.set_param("trace_eagerness", 2)
+                set_param(jitdriver, param, defl)
+            set_param(jitdriver, "threshold", 3)
+            set_param(jitdriver, "trace_eagerness", 2)
             total = 0
             frame = Frame(i)
             while frame.l[0] > 3:
@@ -117,8 +117,8 @@
                 raise ValueError
             return 2
         def main(i):
-            jitdriver.set_param("threshold", 3)
-            jitdriver.set_param("trace_eagerness", 2)
+            set_param(jitdriver, "threshold", 3)
+            set_param(jitdriver, "trace_eagerness", 2)
             total = 0
             n = i
             while n > 3:
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
@@ -48,13 +48,13 @@
     translator.warmrunnerdesc = warmrunnerdesc    # for later debugging
 
 def ll_meta_interp(function, args, backendopt=False, type_system='lltype',
-                   listcomp=False, **kwds):
+                   listcomp=False, translationoptions={}, **kwds):
     if listcomp:
         extraconfigopts = {'translation.list_comprehension_operations': True}
     else:
         extraconfigopts = {}
-    if kwds.pop("taggedpointers", False):
-        extraconfigopts["translation.taggedpointers"] = True
+    for key, value in translationoptions.items():
+        extraconfigopts['translation.' + key] = value
     interp, graph = get_interpreter(function, args,
                                     backendopt=False,  # will be done below
                                     type_system=type_system,
@@ -120,7 +120,8 @@
                 op = block.operations[i]
                 if (op.opname == 'jit_marker' and
                     op.args[0].value == marker_name and
-                    op.args[1].value.active):   # the jitdriver
+                    (op.args[1].value is None or
+                    op.args[1].value.active)):   # the jitdriver
                     results.append((graph, block, i))
     return results
 
@@ -254,10 +255,8 @@
         s_binding = self.translator.annotator.binding
         jd._portal_args_s = [s_binding(v) for v in args]
         graph = copygraph(graph)
-        graph.startblock.isstartblock = False
         [jmpp] = find_jit_merge_points([graph])
         graph.startblock = support.split_before_jit_merge_point(*jmpp)
-        graph.startblock.isstartblock = True
         # a crash in the following checkgraph() means that you forgot
         # to list some variable in greens=[] or reds=[] in JitDriver,
         # or that a jit_merge_point() takes a constant as an argument.
@@ -846,11 +845,18 @@
         _, PTR_SET_PARAM_STR_FUNCTYPE = self.cpu.ts.get_FuncType(
             [lltype.Ptr(STR)], lltype.Void)
         def make_closure(jd, fullfuncname, is_string):
-            state = jd.warmstate
-            def closure(i):
-                if is_string:
-                    i = hlstr(i)
-                getattr(state, fullfuncname)(i)
+            if jd is None:
+                def closure(i):
+                    if is_string:
+                        i = hlstr(i)
+                    for jd in self.jitdrivers_sd:
+                        getattr(jd.warmstate, fullfuncname)(i)
+            else:
+                state = jd.warmstate
+                def closure(i):
+                    if is_string:
+                        i = hlstr(i)
+                    getattr(state, fullfuncname)(i)
             if is_string:
                 TP = PTR_SET_PARAM_STR_FUNCTYPE
             else:
@@ -859,12 +865,16 @@
             return Constant(funcptr, TP)
         #
         for graph, block, i in find_set_param(graphs):
+            
             op = block.operations[i]
-            for jd in self.jitdrivers_sd:
-                if jd.jitdriver is op.args[1].value:
-                    break
+            if op.args[1].value is not None:
+                for jd in self.jitdrivers_sd:
+                    if jd.jitdriver is op.args[1].value:
+                        break
+                else:
+                    assert 0, "jitdriver of set_param() not found"
             else:
-                assert 0, "jitdriver of set_param() not found"
+                jd = None
             funcname = op.args[2].value
             key = jd, funcname
             if key not in closures:
diff --git a/pypy/jit/tl/spli/test/test_jit.py b/pypy/jit/tl/spli/test/test_jit.py
--- a/pypy/jit/tl/spli/test/test_jit.py
+++ b/pypy/jit/tl/spli/test/test_jit.py
@@ -36,7 +36,7 @@
                 i = i + 1
             return i
         self.interpret(f, [])
-        self.check_loops(new_with_vtable=0)
+        self.check_resops(new_with_vtable=0)
 
     def test_bridge(self):
         py.test.skip('We currently cant virtualize across bridges')
@@ -52,7 +52,7 @@
             return total
 
         self.interpret(f, [1, 10])
-        self.check_loops(new_with_vtable=0)
+        self.check_resops(new_with_vtable=0)
 
     def test_bridge_bad_case(self):
         py.test.skip('We currently cant virtualize across bridges')
@@ -67,7 +67,7 @@
             return a + b
 
         self.interpret(f, [1, 10])
-        self.check_loops(new_with_vtable=1) # XXX should eventually be 0?
+        self.check_resops(new_with_vtable=1) # XXX should eventually be 0?
         # I think it should be either 0 or 2, 1 makes little sense
         # If the loop after entering goes first time to the bridge, a
         # is rewrapped again, without preserving the identity. I'm not
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
@@ -95,17 +95,17 @@
     return space.newlist(res_w)
 
 
-def range_withspecialized_implementation(space, start, step, howmany):
+def range_withspecialized_implementation(space, start, step, length):
     assert space.config.objspace.std.withrangelist
-    from pypy.objspace.std.rangeobject import W_RangeListObject
-    return W_RangeListObject(start, step, howmany)
+    from pypy.objspace.std.listobject import make_range_list
+    return make_range_list(space, start, step, length)
 
 bigint_one = rbigint.fromint(1)
 
 def range_with_longs(space, w_start, w_stop, w_step):
 
     start = lo = space.bigint_w(w_start)
-    stop  = hi = space.bigint_w(w_stop)
+    hi = space.bigint_w(w_stop)
     step  = st = space.bigint_w(w_step)
 
     if not step.tobool():
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
@@ -27,6 +27,7 @@
         'builtinify'                : 'interp_magic.builtinify',
         'lookup_special'            : 'interp_magic.lookup_special',
         'do_what_I_mean'            : 'interp_magic.do_what_I_mean',
+        'list_strategy'             : 'interp_magic.list_strategy',
     }
 
     submodules = {
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
@@ -5,7 +5,6 @@
 from pypy.objspace.std.typeobject import MethodCache
 from pypy.objspace.std.mapdict import IndexCache
 
-
 def internal_repr(space, w_object):
     return space.wrap('%r' % (w_object,))
 
@@ -73,3 +72,11 @@
 
 def do_what_I_mean(space):
     return space.wrap(42)
+
+def list_strategy(space, w_list):
+    from pypy.objspace.std.listobject import W_ListObject
+    if isinstance(w_list, W_ListObject):
+        return space.wrap(w_list.strategy._applevel_repr)
+    else:
+        w_msg = space.wrap("Can only get the list strategy of a list")
+        raise OperationError(space.w_TypeError, w_msg)
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
@@ -5,7 +5,7 @@
     def setup_class(cls):
         if option.runappdirect:
             py.test.skip("does not make sense on pypy-c")
-        cls.space = gettestobjspace(**{"objspace.usemodules.select": False})
+        cls.space = gettestobjspace(**{"objspace.usemodules.select": False, "objspace.std.withrangelist": True})
 
     def test__isfake(self):
         from __pypy__ import isfake
@@ -54,3 +54,21 @@
         from __pypy__ import do_what_I_mean
         x = do_what_I_mean()
         assert x == 42
+
+    def test_list_strategy(self):
+        from __pypy__ import list_strategy
+
+        l = [1, 2, 3]
+        assert list_strategy(l) == "int"
+        l = ["a", "b", "c"]
+        assert list_strategy(l) == "str"
+        l = [1.1, 2.2, 3.3]
+        assert list_strategy(l) == "float"
+        l = range(3)
+        assert list_strategy(l) == "range"
+        l = [1, "b", 3]
+        assert list_strategy(l) == "object"
+        l = []
+        assert list_strategy(l) == "empty"
+        o = 5
+        raises(TypeError, list_strategy, 5)
diff --git a/pypy/module/_bisect/test/test_ztranslation.py b/pypy/module/_bisect/test/test_ztranslation.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_bisect/test/test_ztranslation.py
@@ -0,0 +1,4 @@
+from pypy.objspace.fake.checkmodule import checkmodule
+
+def test_checkmodule():
+    checkmodule('_bisect')
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
@@ -67,10 +67,7 @@
         if self.unicodedata_handler:
             return self.unicodedata_handler
         try:
-            w_builtin = space.getbuiltinmodule('__builtin__')
-            w_import = space.getattr(w_builtin, space.wrap("__import__"))
-            w_unicodedata = space.call_function(w_import,
-                                                space.wrap("unicodedata"))
+            w_unicodedata = space.getbuiltinmodule("unicodedata")
             w_getcode = space.getattr(w_unicodedata, space.wrap("_get_code"))
         except OperationError:
             return None
diff --git a/pypy/module/_collections/app_defaultdict.py b/pypy/module/_collections/app_defaultdict.py
--- a/pypy/module/_collections/app_defaultdict.py
+++ b/pypy/module/_collections/app_defaultdict.py
@@ -13,12 +13,14 @@
 class defaultdict(dict):
     
     def __init__(self, *args, **kwds):
-        self.default_factory = None
-        if 'default_factory' in kwds:
-            self.default_factory = kwds.pop('default_factory')
-        elif len(args) > 0 and (callable(args[0]) or args[0] is None):
-            self.default_factory = args[0]
+        if len(args) > 0:
+            default_factory = args[0]
             args = args[1:]
+            if not callable(default_factory) and default_factory is not None:
+                raise TypeError("first argument must be callable")
+        else:
+            default_factory = None
+        self.default_factory = default_factory
         super(defaultdict, self).__init__(*args, **kwds)
  
     def __missing__(self, key):
@@ -36,7 +38,7 @@
             recurse.remove(id(self))
 
     def copy(self):
-        return type(self)(self, default_factory=self.default_factory)
+        return type(self)(self.default_factory, self)
     
     def __copy__(self):
         return self.copy()
diff --git a/pypy/module/_collections/test/test_defaultdict.py b/pypy/module/_collections/test/test_defaultdict.py
--- a/pypy/module/_collections/test/test_defaultdict.py
+++ b/pypy/module/_collections/test/test_defaultdict.py
@@ -19,11 +19,41 @@
 
     def test_keyerror_without_factory(self):
         from _collections import defaultdict
-        d1 = defaultdict()
-        for key in ['foo', (1,)]:
-            try:
-                d1[key]
-            except KeyError, err:
-                assert err.args[0] == key
-            else:
-                assert 0, "expected KeyError"
+        for d1 in [defaultdict(), defaultdict(None)]:
+            for key in ['foo', (1,)]:
+                try:
+                    d1[key]
+                except KeyError, err:
+                    assert err.args[0] == key
+                else:
+                    assert 0, "expected KeyError"
+
+    def test_noncallable(self):
+        from _collections import defaultdict
+        raises(TypeError, defaultdict, [('a', 5)])
+        d = defaultdict(None, [('a', 5)])
+        assert d.items() == [('a', 5)]
+
+    def test_kwds(self):
+        from _collections import defaultdict
+        d = defaultdict(default_factory=5)
+        assert d.keys() == ['default_factory']
+
+    def test_copy(self):
+        import _collections
+        def f():
+            return 42
+        d = _collections.defaultdict(f, {2: 3})
+        #
+        d1 = d.copy()
+        assert type(d1) is _collections.defaultdict
+        assert len(d1) == 1
+        assert d1[2] == 3
+        assert d1[3] == 42
+        #
+        import copy
+        d2 = copy.deepcopy(d)
+        assert type(d2) is _collections.defaultdict
+        assert len(d2) == 1
+        assert d2[2] == 3
+        assert d2[3] == 42
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
@@ -457,14 +457,14 @@
 # ========================================================================
 
 class W_CDLL(Wrappable):
-    def __init__(self, space, name):
+    def __init__(self, space, name, mode):
         self.space = space
         if name is None:
             self.name = "<None>"
         else:
             self.name = name
         try:
-            self.cdll = libffi.CDLL(name)
+            self.cdll = libffi.CDLL(name, mode)
         except DLOpenError, e:
             raise operationerrfmt(space.w_OSError, '%s: %s', self.name,
                                   e.msg or 'unspecified error')
@@ -492,9 +492,9 @@
                                   "No symbol %s found in library %s", name, self.name)
         return space.wrap(address_as_uint)
 
- at unwrap_spec(name='str_or_None')
-def descr_new_cdll(space, w_type, name):
-    return space.wrap(W_CDLL(space, name))
+ at unwrap_spec(name='str_or_None', mode=int)
+def descr_new_cdll(space, w_type, name, mode=-1):
+    return space.wrap(W_CDLL(space, name, mode))
 
 
 W_CDLL.typedef = TypeDef(
@@ -509,6 +509,6 @@
 def get_libc(space):
     from pypy.rlib.clibffi import get_libc_name
     try:
-        return space.wrap(W_CDLL(space, get_libc_name()))
+        return space.wrap(W_CDLL(space, get_libc_name(), -1))
     except OSError, e:
         raise wrap_oserror(space, e)
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
@@ -206,24 +206,28 @@
     @unwrap_spec(size=int)
     def direct_readlines(self, size=0):
         stream = self.getstream()
-        # NB. this implementation is very inefficient for unbuffered
-        # streams, but ok if stream.readline() is efficient.
+        # this is implemented as: .read().split('\n')
+        # except that it keeps the \n in the resulting strings
         if size <= 0:
-            result = []
-            while True:
-                line = stream.readline()
-                if not line:
-                    break
-                result.append(line)
-                size -= len(line)
+            data = stream.readall()
         else:
-            result = []
-            while size > 0:
-                line = stream.readline()
-                if not line:
-                    break
-                result.append(line)
-                size -= len(line)
+            data = stream.read(size)
+        result = []
+        splitfrom = 0
+        for i in range(len(data)):
+            if data[i] == '\n':
+                result.append(data[splitfrom : i + 1])
+                splitfrom = i + 1
+        #
+        if splitfrom < len(data):
+            # there is a partial line at the end.  If size > 0, it is likely
+            # to be because the 'read(size)' returned data up to the middle
+            # of a line.  In that case, use 'readline()' to read until the
+            # end of the current line.
+            data = data[splitfrom:]
+            if size > 0:
+                data += stream.readline()
+            result.append(data)
         return result
 
     @unwrap_spec(offset=r_longlong, whence=int)
diff --git a/pypy/module/_hashlib/interp_hashlib.py b/pypy/module/_hashlib/interp_hashlib.py
--- a/pypy/module/_hashlib/interp_hashlib.py
+++ b/pypy/module/_hashlib/interp_hashlib.py
@@ -4,32 +4,44 @@
 from pypy.interpreter.error import OperationError
 from pypy.tool.sourcetools import func_renamer
 from pypy.interpreter.baseobjspace import Wrappable
-from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.rpython.lltypesystem import lltype, llmemory, rffi
+from pypy.rlib import rgc, ropenssl
 from pypy.rlib.objectmodel import keepalive_until_here
-from pypy.rlib import ropenssl
 from pypy.rlib.rstring import StringBuilder
 from pypy.module.thread.os_lock import Lock
 
 algorithms = ('md5', 'sha1', 'sha224', 'sha256', 'sha384', 'sha512')
 
+# HASH_MALLOC_SIZE is the size of EVP_MD, EVP_MD_CTX plus their points
+# Used for adding memory pressure. Last number is an (under?)estimate of
+# EVP_PKEY_CTX's size.
+# XXX: Make a better estimate here
+HASH_MALLOC_SIZE = ropenssl.EVP_MD_SIZE + ropenssl.EVP_MD_CTX_SIZE \
+        + rffi.sizeof(ropenssl.EVP_MD) * 2 + 208
+
 class W_Hash(Wrappable):
     ctx = lltype.nullptr(ropenssl.EVP_MD_CTX.TO)
+    _block_size = -1
 
     def __init__(self, space, name):
         self.name = name
+        self.digest_size = self.compute_digest_size()
 
         # Allocate a lock for each HASH object.
         # An optimization would be to not release the GIL on small requests,
         # and use a custom lock only when needed.
         self.lock = Lock(space)
 
+        ctx = lltype.malloc(ropenssl.EVP_MD_CTX.TO, flavor='raw')
+        rgc.add_memory_pressure(HASH_MALLOC_SIZE + self.digest_size)
+        self.ctx = ctx
+
+    def initdigest(self, space, name):
         digest = ropenssl.EVP_get_digestbyname(name)
         if not digest:
             raise OperationError(space.w_ValueError,
                                  space.wrap("unknown hash function"))
-        ctx = lltype.malloc(ropenssl.EVP_MD_CTX.TO, flavor='raw')
-        ropenssl.EVP_DigestInit(ctx, digest)
-        self.ctx = ctx
+        ropenssl.EVP_DigestInit(self.ctx, digest)
 
     def __del__(self):
         # self.lock.free()
@@ -65,33 +77,29 @@
         "Return the digest value as a string of hexadecimal digits."
         digest = self._digest(space)
         hexdigits = '0123456789abcdef'
-        result = StringBuilder(self._digest_size() * 2)
+        result = StringBuilder(self.digest_size * 2)
         for c in digest:
             result.append(hexdigits[(ord(c) >> 4) & 0xf])
             result.append(hexdigits[ ord(c)       & 0xf])
         return space.wrap(result.build())
 
     def get_digest_size(self, space):
-        return space.wrap(self._digest_size())
+        return space.wrap(self.digest_size)
 
     def get_block_size(self, space):
-        return space.wrap(self._block_size())
+        return space.wrap(self.compute_block_size())
 
     def _digest(self, space):
-        copy = self.copy(space)
-        ctx = copy.ctx
-        digest_size = self._digest_size()
-        digest = lltype.malloc(rffi.CCHARP.TO, digest_size, flavor='raw')
+        with lltype.scoped_alloc(ropenssl.EVP_MD_CTX.TO) as ctx:
+            with self.lock:
+                ropenssl.EVP_MD_CTX_copy(ctx, self.ctx)
+            digest_size = self.digest_size
+            with lltype.scoped_alloc(rffi.CCHARP.TO, digest_size) as digest:
+                ropenssl.EVP_DigestFinal(ctx, digest, None)
+                ropenssl.EVP_MD_CTX_cleanup(ctx)
+                return rffi.charpsize2str(digest, digest_size)
 
-        try:
-            ropenssl.EVP_DigestFinal(ctx, digest, None)
-            return rffi.charpsize2str(digest, digest_size)
-        finally:
-            keepalive_until_here(copy)
-            lltype.free(digest, flavor='raw')
-
-
-    def _digest_size(self):
+    def compute_digest_size(self):
         # XXX This isn't the nicest way, but the EVP_MD_size OpenSSL
         # XXX function is defined as a C macro on OS X and would be
         # XXX significantly harder to implement in another way.
@@ -105,12 +113,14 @@
             'sha512': 64, 'SHA512': 64,
             }.get(self.name, 0)
 
-    def _block_size(self):
+    def compute_block_size(self):
+        if self._block_size != -1:
+            return self._block_size
         # XXX This isn't the nicest way, but the EVP_MD_CTX_block_size
         # XXX OpenSSL function is defined as a C macro on some systems
         # XXX and would be significantly harder to implement in
         # XXX another way.
-        return {
+        self._block_size = {
             'md5':     64, 'MD5':     64,
             'sha1':    64, 'SHA1':    64,
             'sha224':  64, 'SHA224':  64,
@@ -118,6 +128,7 @@
             'sha384': 128, 'SHA384': 128,
             'sha512': 128, 'SHA512': 128,
             }.get(self.name, 0)
+        return self._block_size
 
 W_Hash.typedef = TypeDef(
     'HASH',
@@ -135,6 +146,7 @@
 @unwrap_spec(name=str, string='bufferstr')
 def new(space, name, string=''):
     w_hash = W_Hash(space, name)
+    w_hash.initdigest(space, name)
     w_hash.update(space, string)
     return space.wrap(w_hash)
 
diff --git a/pypy/module/_minimal_curses/__init__.py b/pypy/module/_minimal_curses/__init__.py
--- a/pypy/module/_minimal_curses/__init__.py
+++ b/pypy/module/_minimal_curses/__init__.py
@@ -4,7 +4,8 @@
     try:
         import _minimal_curses as _curses   # when running on top of pypy-c
     except ImportError:
-        raise ImportError("no _curses or _minimal_curses module")  # no _curses at all
+        import py
+        py.test.skip("no _curses or _minimal_curses module") #no _curses at all
 
 from pypy.interpreter.mixedmodule import MixedModule
 from pypy.module._minimal_curses import fficurses
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
@@ -100,7 +100,6 @@
 
         res, newbuf = self.do_recv_string(
             space, self.BUFFER_SIZE, maxlength)
-        res = intmask(res) # XXX why?
         try:
             if newbuf:
                 return space.wrap(rffi.charpsize2str(newbuf, res))
@@ -117,7 +116,6 @@
 
         res, newbuf = self.do_recv_string(
             space, length - offset, PY_SSIZE_T_MAX)
-        res = intmask(res) # XXX why?
         try:
             if newbuf:
                 raise BufferTooShort(space, space.wrap(
@@ -148,7 +146,6 @@
 
         res, newbuf = self.do_recv_string(
             space, self.BUFFER_SIZE, PY_SSIZE_T_MAX)
-        res = intmask(res) # XXX why?
         try:
             if newbuf:
                 w_received = space.wrap(rffi.charpsize2str(newbuf, res))
@@ -413,7 +410,7 @@
                                self.buffer, min(self.BUFFER_SIZE, buflength),
                                read_ptr, rffi.NULL)
             if result:
-                return read_ptr[0], lltype.nullptr(rffi.CCHARP.TO)
+                return intmask(read_ptr[0]), lltype.nullptr(rffi.CCHARP.TO)
 
             err = rwin32.GetLastError()
             if err == ERROR_BROKEN_PIPE:
@@ -476,7 +473,7 @@
         block = timeout < 0
         if not block:
             # XXX does not check for overflow
-            deadline = _GetTickCount() + int(1000 * timeout + 0.5)
+            deadline = intmask(_GetTickCount()) + int(1000 * timeout + 0.5)
         else:
             deadline = 0
 
@@ -500,7 +497,7 @@
                 return True
 
             if not block:
-                now = _GetTickCount()
+                now = intmask(_GetTickCount())
                 if now > deadline:
                     return False
                 diff = deadline - now
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
@@ -4,6 +4,7 @@
 from pypy.interpreter.gateway import interp2app, unwrap_spec
 from pypy.interpreter.error import wrap_oserror, OperationError
 from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.rlib import rgc
 from pypy.rlib.rarithmetic import r_uint
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.rpython.tool import rffi_platform as platform
@@ -23,6 +24,8 @@
     _CreateSemaphore = rwin32.winexternal(
         'CreateSemaphoreA', [rffi.VOIDP, rffi.LONG, rffi.LONG, rwin32.LPCSTR],
         rwin32.HANDLE)
+    _CloseHandle = rwin32.winexternal('CloseHandle', [rwin32.HANDLE],
+        rwin32.BOOL, threadsafe=False)
     _ReleaseSemaphore = rwin32.winexternal(
         'ReleaseSemaphore', [rwin32.HANDLE, rffi.LONG, rffi.LONGP],
         rwin32.BOOL)
@@ -51,6 +54,7 @@
         SEM_FAILED = platform.ConstantInteger('SEM_FAILED')
         SEM_VALUE_MAX = platform.ConstantInteger('SEM_VALUE_MAX')
         SEM_TIMED_WAIT = platform.Has('sem_timedwait')
+        SEM_T_SIZE = platform.SizeOf('sem_t')
 
     config = platform.configure(CConfig)
     TIMEVAL        = config['TIMEVAL']
@@ -61,18 +65,21 @@
     SEM_FAILED     = config['SEM_FAILED'] # rffi.cast(SEM_T, config['SEM_FAILED'])
     SEM_VALUE_MAX  = config['SEM_VALUE_MAX']
     SEM_TIMED_WAIT = config['SEM_TIMED_WAIT']
+    SEM_T_SIZE = config['SEM_T_SIZE']
     if sys.platform == 'darwin':
         HAVE_BROKEN_SEM_GETVALUE = True
     else:
         HAVE_BROKEN_SEM_GETVALUE = False
 
-    def external(name, args, result):
+    def external(name, args, result, **kwargs):
         return rffi.llexternal(name, args, result,
-                               compilation_info=eci)
+                               compilation_info=eci, **kwargs)
 
     _sem_open = external('sem_open',
                          [rffi.CCHARP, rffi.INT, rffi.INT, rffi.UINT],
                          SEM_T)
+    # tread sem_close as not threadsafe for now to be able to use the __del__
+    _sem_close = external('sem_close', [SEM_T], rffi.INT, threadsafe=False)
     _sem_unlink = external('sem_unlink', [rffi.CCHARP], rffi.INT)
     _sem_wait = external('sem_wait', [SEM_T], rffi.INT)
     _sem_trywait = external('sem_trywait', [SEM_T], rffi.INT)
@@ -90,6 +97,11 @@
             raise OSError(rposix.get_errno(), "sem_open failed")
         return res
 
+    def sem_close(handle):
+        res = _sem_close(handle)
+        if res < 0:
+            raise OSError(rposix.get_errno(), "sem_close failed")
+
     def sem_unlink(name):
         res = _sem_unlink(name)
         if res < 0:
@@ -205,6 +217,11 @@
             raise WindowsError(err, "CreateSemaphore")
         return handle
 
+    def delete_semaphore(handle):
+        if not _CloseHandle(handle):
+            err = rwin32.GetLastError()
+            raise WindowsError(err, "CloseHandle")
+
     def semlock_acquire(self, space, block, w_timeout):
         if not block:
             full_msecs = 0
@@ -218,7 +235,7 @@
             elif timeout >= 0.5 * rwin32.INFINITE: # 25 days
                 raise OperationError(space.w_OverflowError,
                                      space.wrap("timeout is too large"))
-            full_msecs = int(timeout + 0.5)
+            full_msecs = r_uint(int(timeout + 0.5))
 
         # check whether we can acquire without blocking
         res = rwin32.WaitForSingleObject(self.handle, 0)
@@ -226,7 +243,7 @@
         if res != rwin32.WAIT_TIMEOUT:
             return True
 
-        msecs = r_uint(full_msecs)
+        msecs = full_msecs
         start = _GetTickCount()
 
         while True:
@@ -252,7 +269,7 @@
                 ticks = _GetTickCount()
                 if r_uint(ticks - start) >= full_msecs:
                     return False
-                msecs = r_uint(full_msecs - (ticks - start))
+                msecs = full_msecs - r_uint(ticks - start)
 
         # handle result
         if res != rwin32.WAIT_TIMEOUT:
@@ -291,8 +308,13 @@
             sem_unlink(name)
         except OSError:
             pass
+        else:
+            rgc.add_memory_pressure(SEM_T_SIZE)
         return sem
 
+    def delete_semaphore(handle):
+        sem_close(handle)
+
     def semlock_acquire(self, space, block, w_timeout):
         if not block:
             deadline = lltype.nullptr(TIMESPECP.TO)
@@ -483,6 +505,9 @@
     def exit(self, space, __args__):
         self.release(space)
 
+    def __del__(self):
+        delete_semaphore(self.handle)
+
 @unwrap_spec(kind=int, value=int, maxvalue=int)
 def descr_new(space, w_subtype, kind, value, maxvalue):
     if kind != RECURSIVE_MUTEX and kind != SEMAPHORE:
diff --git a/pypy/module/_multiprocessing/test/test_semaphore.py b/pypy/module/_multiprocessing/test/test_semaphore.py
--- a/pypy/module/_multiprocessing/test/test_semaphore.py
+++ b/pypy/module/_multiprocessing/test/test_semaphore.py
@@ -70,8 +70,10 @@
         maxvalue = 1
         sem = SemLock(kind, value, maxvalue)
 
-        assert sem.acquire()
-        assert not sem.acquire(timeout=0.1)
+        res = sem.acquire()
+        assert res == True
+        res = sem.acquire(timeout=0.1)
+        assert res == False
 
     def test_semaphore_rebuild(self):
         from _multiprocessing import SemLock
diff --git a/pypy/module/_random/test/test_ztranslation.py b/pypy/module/_random/test/test_ztranslation.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/_random/test/test_ztranslation.py
@@ -0,0 +1,4 @@
+from pypy.objspace.fake.checkmodule import checkmodule
+
+def test_checkmodule():
+    checkmodule('_random')
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
@@ -543,6 +543,7 @@
     from pypy.rlib.rwin32 import GetLastError
     return space.wrap(GetLastError())
 
-def set_last_error(space, w_error):
+ at unwrap_spec(error=int)
+def set_last_error(space, error):
     from pypy.rlib.rwin32 import SetLastError
-    SetLastError(space.uint_w(w_error))
+    SetLastError(error)
diff --git a/pypy/module/_rawffi/structure.py b/pypy/module/_rawffi/structure.py
--- a/pypy/module/_rawffi/structure.py
+++ b/pypy/module/_rawffi/structure.py
@@ -212,6 +212,8 @@
                 while count + basic_size <= total_size:
                     fieldtypes.append(basic_ffi_type)
                     count += basic_size
+                    if basic_size == 0: # corner case. get out of this infinite
+                        break           # loop after 1 iteration ("why not")
             self.ffi_struct = clibffi.make_struct_ffitype_e(self.size,
                                                            self.alignment,
                                                            fieldtypes)
diff --git a/pypy/module/_rawffi/test/test__rawffi.py b/pypy/module/_rawffi/test/test__rawffi.py
--- a/pypy/module/_rawffi/test/test__rawffi.py
+++ b/pypy/module/_rawffi/test/test__rawffi.py
@@ -1022,6 +1022,12 @@
         assert ret.y == 1234500, "ret.y == %d" % (ret.y,)
         s.free()
 
+    def test_ffi_type(self):
+        import _rawffi
+        EMPTY = _rawffi.Structure([])
+        S2E = _rawffi.Structure([('bah', (EMPTY, 1))])
+        S2E.get_ffi_type()     # does not hang
+
 class AppTestAutoFree:
     def setup_class(cls):
         space = gettestobjspace(usemodules=('_rawffi', 'struct'))
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,7 +1,7 @@
 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.rsocket import SocketError, INVALID_SOCKET
 from pypy.interpreter.error import OperationError
 
 def gethostname(space):
@@ -284,7 +284,7 @@
                             space.wrap(socktype),
                             space.wrap(protocol),
                             space.wrap(canonname),
-                            addr.as_object(-1, space)]) # -1 as per cpython
+                            addr.as_object(INVALID_SOCKET, space)]) # -1 as per cpython
             for (family, socktype, protocol, canonname, addr) in lst]
     return space.newlist(lst1)
 
diff --git a/pypy/module/_weakref/test/test_weakref.py b/pypy/module/_weakref/test/test_weakref.py
--- a/pypy/module/_weakref/test/test_weakref.py
+++ b/pypy/module/_weakref/test/test_weakref.py
@@ -324,6 +324,7 @@
         class A(object): pass
         a = A()
         assert _weakref.proxy(a) is _weakref.proxy(a)
+        assert _weakref.proxy(a) is _weakref.proxy(a, None)
 
     def test_callable_proxy(self):
         import _weakref, gc
diff --git a/pypy/module/array/test/test_array.py b/pypy/module/array/test/test_array.py
--- a/pypy/module/array/test/test_array.py
+++ b/pypy/module/array/test/test_array.py
@@ -835,7 +835,7 @@
         a.append(3.0)
         r = weakref.ref(a, lambda a: l.append(a()))
         del a
-        gc.collect()
+        gc.collect(); gc.collect()   # XXX needs two of them right now...
         assert l
         assert l[0] is None or len(l[0]) == 0
 
diff --git a/pypy/module/bz2/test/test_large.py b/pypy/module/bz2/test/test_large.py
--- a/pypy/module/bz2/test/test_large.py
+++ b/pypy/module/bz2/test/test_large.py
@@ -8,7 +8,7 @@
             py.test.skip("skipping this very slow test; try 'pypy-c -A'")
         cls.space = gettestobjspace(usemodules=('bz2',))
         largetest_bz2 = py.path.local(__file__).dirpath().join("largetest.bz2")
-        cls.w_compressed_data = cls.space.wrap(largetest_bz2.read())
+        cls.w_compressed_data = cls.space.wrap(largetest_bz2.read('rb'))
 
     def test_decompress(self):
         from bz2 import decompress
diff --git a/pypy/module/cStringIO/test/test_ztranslation.py b/pypy/module/cStringIO/test/test_ztranslation.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cStringIO/test/test_ztranslation.py
@@ -0,0 +1,4 @@
+from pypy.objspace.fake.checkmodule import checkmodule
+
+def test_checkmodule():
+    checkmodule('cStringIO')
diff --git a/pypy/module/clr/boxing_rules.py b/pypy/module/clr/boxing_rules.py
--- a/pypy/module/clr/boxing_rules.py
+++ b/pypy/module/clr/boxing_rules.py
@@ -43,11 +43,11 @@
     def tocli(self):
         return box(self._value)
 
-from pypy.objspace.fake.objspace import W_Object as W_Object_Fake
-from pypy.rlib.nonconst import NonConstant
+##from pypy.objspace.fake.objspace import W_Object as W_Object_Fake
+##from pypy.rlib.nonconst import NonConstant
 
-class __extend__(W_Object_Fake):
-    __metaclass__ = extendabletype
+##class __extend__(W_Object_Fake):
+##    __metaclass__ = extendabletype
 
-    def tocli(self):
-        return NonConstant(None)
+##    def tocli(self):
+##        return NonConstant(None)
diff --git a/pypy/module/cpyext/api.py b/pypy/module/cpyext/api.py
--- a/pypy/module/cpyext/api.py
+++ b/pypy/module/cpyext/api.py
@@ -392,6 +392,7 @@
         'Slice': 'space.gettypeobject(W_SliceObject.typedef)',
         'StaticMethod': 'space.gettypeobject(StaticMethod.typedef)',
         'CFunction': 'space.gettypeobject(cpyext.methodobject.W_PyCFunctionObject.typedef)',
+        'WrapperDescr': 'space.gettypeobject(cpyext.methodobject.W_PyCMethodObject.typedef)'
         }.items():
         GLOBALS['Py%s_Type#' % (cpyname, )] = ('PyTypeObject*', pypyexpr)
 
diff --git a/pypy/module/cpyext/include/eval.h b/pypy/module/cpyext/include/eval.h
--- a/pypy/module/cpyext/include/eval.h
+++ b/pypy/module/cpyext/include/eval.h
@@ -14,8 +14,8 @@
 
 PyObject * PyEval_CallFunction(PyObject *obj, const char *format, ...);
 PyObject * PyEval_CallMethod(PyObject *obj, const char *name, const char *format, ...);
-PyObject * PyObject_CallFunction(PyObject *obj, char *format, ...);
-PyObject * PyObject_CallMethod(PyObject *obj, char *name, char *format, ...);
+PyObject * PyObject_CallFunction(PyObject *obj, const char *format, ...);
+PyObject * PyObject_CallMethod(PyObject *obj, const char *name, const char *format, ...);
 PyObject * PyObject_CallFunctionObjArgs(PyObject *callable, ...);
 PyObject * PyObject_CallMethodObjArgs(PyObject *callable, PyObject *name, ...);
 
diff --git a/pypy/module/cpyext/include/modsupport.h b/pypy/module/cpyext/include/modsupport.h
--- a/pypy/module/cpyext/include/modsupport.h
+++ b/pypy/module/cpyext/include/modsupport.h
@@ -48,7 +48,11 @@
 /*
  * This is from pyport.h.  Perhaps it belongs elsewhere.
  */
+#ifdef __cplusplus
+#define PyMODINIT_FUNC extern "C" void
+#else
 #define PyMODINIT_FUNC void
+#endif
 
 
 #ifdef __cplusplus
diff --git a/pypy/module/cpyext/include/patchlevel.h b/pypy/module/cpyext/include/patchlevel.h
--- a/pypy/module/cpyext/include/patchlevel.h
+++ b/pypy/module/cpyext/include/patchlevel.h
@@ -29,7 +29,7 @@
 #define PY_VERSION		"2.7.1"
 
 /* PyPy version as a string */
-#define PYPY_VERSION "1.6.1"
+#define PYPY_VERSION "1.7.1"
 
 /* Subversion Revision number of this file (not of the repository).
  * Empty since Mercurial migration. */
diff --git a/pypy/module/cpyext/include/pycobject.h b/pypy/module/cpyext/include/pycobject.h
--- a/pypy/module/cpyext/include/pycobject.h
+++ b/pypy/module/cpyext/include/pycobject.h
@@ -33,7 +33,7 @@
 PyAPI_FUNC(void *) PyCObject_GetDesc(PyObject *);
 
 /* Import a pointer to a C object from a module using a PyCObject. */
-PyAPI_FUNC(void *) PyCObject_Import(char *module_name, char *cobject_name);
+PyAPI_FUNC(void *) PyCObject_Import(const char *module_name, const char *cobject_name);
 
 /* Modify a C object. Fails (==0) if object has a destructor. */
 PyAPI_FUNC(int) PyCObject_SetVoidPtr(PyObject *self, void *cobj);
diff --git a/pypy/module/cpyext/include/pyerrors.h b/pypy/module/cpyext/include/pyerrors.h
--- a/pypy/module/cpyext/include/pyerrors.h
+++ b/pypy/module/cpyext/include/pyerrors.h
@@ -11,8 +11,8 @@
     (PyClass_Check((x)) || (PyType_Check((x)) &&                        \
       PyObject_IsSubclass((x), PyExc_BaseException)))
 
-PyObject *PyErr_NewException(char *name, PyObject *base, PyObject *dict);
-PyObject *PyErr_NewExceptionWithDoc(char *name, char *doc, PyObject *base, PyObject *dict);
+PyObject *PyErr_NewException(const char *name, PyObject *base, PyObject *dict);
+PyObject *PyErr_NewExceptionWithDoc(const char *name, const char *doc, PyObject *base, PyObject *dict);
 PyObject *PyErr_Format(PyObject *exception, const char *format, ...);
 
 /* These APIs aren't really part of the error implementation, but
diff --git a/pypy/module/cpyext/listobject.py b/pypy/module/cpyext/listobject.py
--- a/pypy/module/cpyext/listobject.py
+++ b/pypy/module/cpyext/listobject.py
@@ -32,7 +32,7 @@
     Py_DecRef(space, w_item)
     if not isinstance(w_list, W_ListObject):
         PyErr_BadInternalCall(space)
-    wrappeditems = w_list.wrappeditems
+    wrappeditems = w_list.getitems()
     if index < 0 or index >= len(wrappeditems):
         raise OperationError(space.w_IndexError, space.wrap(
             "list assignment index out of range"))
@@ -47,7 +47,7 @@
     IndexError exception."""
     if not isinstance(w_list, W_ListObject):
         PyErr_BadInternalCall(space)
-    wrappeditems = w_list.wrappeditems
+    wrappeditems = w_list.getitems()
     if index < 0 or index >= len(wrappeditems):
         raise OperationError(space.w_IndexError, space.wrap(
             "list index out of range"))
@@ -74,7 +74,7 @@
     """Macro form of PyList_Size() without error checking.
     """
     assert isinstance(w_list, W_ListObject)
-    return len(w_list.wrappeditems)
+    return len(w_list.getitems())
 
 
 @cpython_api([PyObject], Py_ssize_t, error=-1)
diff --git a/pypy/module/cpyext/methodobject.py b/pypy/module/cpyext/methodobject.py
--- a/pypy/module/cpyext/methodobject.py
+++ b/pypy/module/cpyext/methodobject.py
@@ -240,6 +240,7 @@
 def PyStaticMethod_New(space, w_func):
     return space.wrap(StaticMethod(w_func))
 
+ at cpython_api([PyObject, lltype.Ptr(PyMethodDef)], PyObject)
 def PyDescr_NewMethod(space, w_type, method):
     return space.wrap(W_PyCMethodObject(space, method, w_type))
 
diff --git a/pypy/module/cpyext/modsupport.py b/pypy/module/cpyext/modsupport.py
--- a/pypy/module/cpyext/modsupport.py
+++ b/pypy/module/cpyext/modsupport.py
@@ -54,9 +54,15 @@
     modname = rffi.charp2str(name)
     state = space.fromcache(State)
     f_name, f_path = state.package_context
-    w_mod = PyImport_AddModule(space, f_name)
+    if f_name is not None:
+        modname = f_name
+    w_mod = PyImport_AddModule(space, modname)
+    state.package_context = None, None


More information about the pypy-commit mailing list