[pypy-svn] pypy 32ptr-on-64bit: hg merge default

arigo commits-noreply at bitbucket.org
Tue Apr 12 22:19:44 CEST 2011


Author: Armin Rigo <arigo at tunes.org>
Branch: 32ptr-on-64bit
Changeset: r43314:1fb8995fe302
Date: 2011-04-12 21:14 +0200
http://bitbucket.org/pypy/pypy/changeset/1fb8995fe302/

Log:	hg merge default

diff --git a/pypy/module/cpyext/pyerrors.py b/pypy/module/cpyext/pyerrors.py
--- a/pypy/module/cpyext/pyerrors.py
+++ b/pypy/module/cpyext/pyerrors.py
@@ -39,6 +39,10 @@
     state = space.fromcache(State)
     state.clear_exception()
 
+ at cpython_api([PyObject], PyObject)
+def PyExceptionInstance_Class(space, w_obj):
+    return space.type(w_obj)
+
 @cpython_api([PyObjectP, PyObjectP, PyObjectP], lltype.Void)
 def PyErr_Fetch(space, ptype, pvalue, ptraceback):
     """Retrieve the error indicator into three variables whose addresses are passed.
@@ -303,3 +307,11 @@
     operror = state.clear_exception()
     if operror:
         operror.write_unraisable(space, space.str_w(space.repr(w_where)))
+
+ at cpython_api([], lltype.Void)
+def PyErr_SetInterrupt(space):
+    """This function simulates the effect of a SIGINT signal arriving --- the
+    next time PyErr_CheckSignals() is called, KeyboardInterrupt will be raised.
+    It may be called without holding the interpreter lock."""
+    space.check_signal_action.set_interrupt()
+


diff --git a/pypy/interpreter/test/test_eval.py b/pypy/interpreter/test/test_eval.py
--- a/pypy/interpreter/test/test_eval.py
+++ b/pypy/interpreter/test/test_eval.py
@@ -13,7 +13,8 @@
             
             def __init__(self, space, code, numlocals):
                 self.code = code
-                Frame.__init__(self, space, numlocals=numlocals)
+                Frame.__init__(self, space)
+                self.numlocals = numlocals
                 self.fastlocals_w = [None] * self.numlocals
 
             def getcode(self):
@@ -24,7 +25,10 @@
 
             def getfastscope(self):
                 return self.fastlocals_w
-        
+
+            def getfastscopelength(self):
+                return self.numlocals
+
         self.f = ConcreteFastscopeFrame(self.space, code, numlocals=5)
         
 

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
@@ -179,6 +179,9 @@
         """
         raise NotImplementedError
 
+    def count_fields_if_immutable(self):
+        return -1
+
     def _clone_if_mutable(self):
         return self
     def clone_if_mutable(self):

diff --git a/pypy/translator/backendopt/constfold.py b/pypy/translator/backendopt/constfold.py
--- a/pypy/translator/backendopt/constfold.py
+++ b/pypy/translator/backendopt/constfold.py
@@ -1,19 +1,16 @@
 from pypy.objspace.flow.model import Constant, Variable, SpaceOperation
 from pypy.objspace.flow.model import c_last_exception
 from pypy.objspace.flow.model import mkentrymap
-from pypy.translator.backendopt.support import split_block_with_keepalive
 from pypy.translator.backendopt.support import log
 from pypy.translator.simplify import eliminate_empty_blocks
-from pypy.translator.unsimplify import insert_empty_block
+from pypy.translator.unsimplify import insert_empty_block, split_block
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.lltypesystem import lltype
 
 
 def fold_op_list(operations, constants, exit_early=False, exc_catch=False):
     newops = []
-    keepalives = []
     folded_count = 0
-    first_sideeffect_index = None
     for spaceop in operations:
         vargsmodif = False
         vargs = []
@@ -29,10 +26,9 @@
         try:
             op = getattr(llop, spaceop.opname)
         except AttributeError:
-            sideeffects = True
+            pass
         else:
-            sideeffects = op.sideeffects
-            if not sideeffects and len(args) == len(vargs):
+            if not op.sideeffects and len(args) == len(vargs):
                 RESTYPE = spaceop.result.concretetype
                 try:
                     result = op(RESTYPE, *args)
@@ -53,10 +49,6 @@
         # failed to fold an operation, exit early if requested
         if exit_early:
             return folded_count
-        if spaceop.opname == 'keepalive' and first_sideeffect_index is None:
-            if vargsmodif:
-                continue    # keepalive(constant) is not useful
-            keepalives.append(spaceop)
         else:
             if vargsmodif:
                 if (spaceop.opname == 'indirect_call'
@@ -66,20 +58,11 @@
                 else:
                     spaceop = SpaceOperation(spaceop.opname, vargs,
                                              spaceop.result)
-            if sideeffects and first_sideeffect_index is None:
-                first_sideeffect_index = len(newops)
             newops.append(spaceop)
     # end
     if exit_early:
         return folded_count
     else:
-        # move the keepalives to the end of the block, which makes the life
-        # of prepare_constant_fold_link() easier.  Don't put them past the
-        # exception-raising operation, though.  There is also no point in
-        # moving them past the first sideeffect-ing operation.
-        if first_sideeffect_index is None:
-            first_sideeffect_index = len(newops) - exc_catch
-        newops[first_sideeffect_index:first_sideeffect_index] = keepalives
         return newops
 
 def constant_fold_block(block):
@@ -177,33 +160,23 @@
     if block.exitswitch == c_last_exception:
         n -= 1
     # is the next, non-folded operation an indirect_call?
-    m = folded_count
-    while m < n and block.operations[m].opname == 'keepalive':
-        m += 1
-    if m < n:
-        nextop = block.operations[m]
+    if folded_count < n:
+        nextop = block.operations[folded_count]
         if nextop.opname == 'indirect_call' and nextop.args[0] in constants:
             # indirect_call -> direct_call
             callargs = [constants[nextop.args[0]]]
             constants1 = constants.copy()
             complete_constants(link, constants1)
-            newkeepalives = []
-            for i in range(folded_count, m):
-                [v] = block.operations[i].args
-                v = constants1.get(v, v)
-                v_void = Variable()
-                v_void.concretetype = lltype.Void
-                newkeepalives.append(SpaceOperation('keepalive', [v], v_void))
             for v in nextop.args[1:-1]:
                 callargs.append(constants1.get(v, v))
             v_result = Variable(nextop.result)
             v_result.concretetype = nextop.result.concretetype
             constants[nextop.result] = v_result
             callop = SpaceOperation('direct_call', callargs, v_result)
-            newblock = insert_empty_block(None, link, newkeepalives + [callop])
+            newblock = insert_empty_block(None, link, [callop])
             [link] = newblock.exits
             assert link.target is block
-            folded_count = m+1
+            folded_count += 1
 
     if folded_count > 0:
         splits = splitblocks.setdefault(block, [])
@@ -226,7 +199,7 @@
                 splitlink = block.exits[0]
             else:
                 # split the block at the given position
-                splitlink = split_block_with_keepalive(block, position)
+                splitlink = split_block(None, block, position)
                 assert list(block.exits) == [splitlink]
             assert link.target is block
             assert splitlink.prevblock is block

diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -108,6 +108,7 @@
     Anders Qvist
     Alan McIntyre
     Bert Freudenberg
+    Tav
 
     Heinrich-Heine University, Germany 
     Open End AB (formerly AB Strakt), Sweden
@@ -118,13 +119,16 @@
     Impara, Germany
     Change Maker, Sweden 
 
+The PyPy Logo as used by http://speed.pypy.org and others was created
+by Samuel Reis and is distributed on terms of Creative Commons Share Alike
+License.
  
-License for 'lib-python/2.5.2' and 'lib-python/2.5.2-modified'
+License for 'lib-python/2.7.0' and 'lib-python/2.7.0-modified'
 ============================================================== 
 
 Except when otherwise stated (look for LICENSE files or
 copyright/license information at the beginning of each file) the files
-in the 'lib-python/2.5.2' and 'lib-python/2.5.2-modified' directories
+in the 'lib-python/2.7.0' and 'lib-python/2.7.0-modified' directories
 are all copyrighted by the Python Software Foundation and licensed under
 the Python Software License of which you can find a copy here:
 http://www.python.org/doc/Copyright.html 
@@ -157,21 +161,12 @@
 ======================================
 
 The following files are from the website of The Unicode Consortium
-at http://www.unicode.org/. For the terms of use of these files, see
-http://www.unicode.org/terms_of_use.html
+at http://www.unicode.org/.  For the terms of use of these files, see
+http://www.unicode.org/terms_of_use.html .  Or they are derived from
+files from the above website, and the same terms of use apply.
 
-    CompositionExclusions-3.2.0.txt
-    CompositionExclusions-4.1.0.txt
-    CompositionExclusions-5.0.0.txt
-    EastAsianWidth-3.2.0.txt
-    EastAsianWidth-4.1.0.txt
-    EastAsianWidth-5.0.0.txt
-    UnicodeData-3.2.0.txt
-    UnicodeData-4.1.0.txt
-    UnicodeData-5.0.0.txt
-    
-The following files are derived from files from the above website. The same
-terms of use apply.
-    UnihanNumeric-3.2.0.txt
-    UnihanNumeric-4.1.0.txt
-    UnihanNumeric-5.0.0.txt
+    CompositionExclusions-*.txt
+    EastAsianWidth-*.txt
+    LineBreak-*.txt
+    UnicodeData-*.txt
+    UnihanNumeric-*.txt

diff --git a/pypy/rpython/llinterp.py b/pypy/rpython/llinterp.py
--- a/pypy/rpython/llinterp.py
+++ b/pypy/rpython/llinterp.py
@@ -870,6 +870,9 @@
     def op_gc_adr_of_nursery_free(self):
         raise NotImplementedError
 
+    def op_gc_adr_of_root_stack_top(self):
+        raise NotImplementedError
+
     def op_gc_call_rtti_destructor(self, rtti, addr):
         if hasattr(rtti._obj, 'destructor_funcptr'):
             d = rtti._obj.destructor_funcptr

diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -103,6 +103,7 @@
     except KeyError:
         subcls = _getusercls(config, cls, hasdict, wants_slots, needsdel,
                              weakrefable)
+        assert key not in _subclass_cache
         _subclass_cache[key] = subcls
         return subcls
 get_unique_interplevel_subclass._annspecialcase_ = "specialize:memo"

diff --git a/pypy/module/sys/interp_encoding.py b/pypy/module/sys/interp_encoding.py
--- a/pypy/module/sys/interp_encoding.py
+++ b/pypy/module/sys/interp_encoding.py
@@ -37,6 +37,10 @@
     base_encoding = None
 
 def _getfilesystemencoding(space):
+    if (space.config.translation.type_system == 'ootype'):
+        # XXX: fix this for ootype
+        return base_encoding
+    #
     encoding = base_encoding
     if rlocale.HAVE_LANGINFO and rlocale.CODESET:
         oldlocale = rlocale.setlocale(rlocale.LC_CTYPE, None)

diff --git a/pypy/translator/jvm/database.py b/pypy/translator/jvm/database.py
--- a/pypy/translator/jvm/database.py
+++ b/pypy/translator/jvm/database.py
@@ -4,7 +4,7 @@
 """
 
 from cStringIO import StringIO
-from pypy.rpython.lltypesystem import lltype
+from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.rpython.ootypesystem import ootype, rclass
 from pypy.rpython.ootypesystem.module import ll_os
 from pypy.translator.jvm import node, methods
@@ -229,9 +229,15 @@
                 if not ootype.isSubclass(OOTYPE, SELF): continue
                 mobj = self._function_for_graph(
                     clsobj, mname, False, mimpl.graph)
-                graphs = OOTYPE._lookup_graphs(mname)
-                if len(graphs) == 1:
-                    mobj.is_final = True
+                # XXX: this logic is broken: it might happen that there are
+                # ootype.Instance which contains a meth whose graph is exactly
+                # the same as the meth in the superclass: in this case,
+                # len(graphs) == 1 but we cannot just mark the method as final
+                # (or we can, but we should avoid to emit the method in the
+                # subclass, then)
+                ## graphs = OOTYPE._lookup_graphs(mname)
+                ## if len(graphs) == 1:
+                ##     mobj.is_final = True
                 clsobj.add_method(mobj)
 
         # currently, we always include a special "dump" method for debugging
@@ -359,6 +365,7 @@
         ootype.UniChar:jvm.PYPYESCAPEDUNICHAR,
         ootype.String:jvm.PYPYESCAPEDSTRING,
         ootype.Unicode:jvm.PYPYESCAPEDUNICODE,
+        rffi.SHORT:jvm.SHORTTOSTRINGS,
         }
 
     def toString_method_for_ootype(self, OOTYPE):
@@ -406,6 +413,7 @@
         ootype.UniChar:          jvm.jChar,
         ootype.Class:            jvm.jClass,
         ootype.ROOT:             jvm.jObject,  # treat like a scalar
+        rffi.SHORT:              jvm.jShort,
     }
 
     # Dictionary for non-scalar types; in this case, if we see the key, we

diff --git a/lib-python/TODO b/lib-python/TODO
--- a/lib-python/TODO
+++ b/lib-python/TODO
@@ -2,7 +2,7 @@
 ===================
 
 You can find the results of the most recent buildbot run at:
-http://buildbot.pypy.org/summary?branch=fast-forward
+http://buildbot.pypy.org/
 
 
 Probably easy tasks
@@ -39,18 +39,8 @@
 Medium tasks
 ------------
 
-- Ast objects should be picklable, see in pypy/module/_ast/test/test_ast.py:
-  test_pickle()
-
 - socket module has a couple of changes (including AF_TIPC packet range)
 
-- (test_lib2to3) When a "for" loop runs a generator function, if the loop is
-  exited before the end, the "finally" clause of the generator is not called
-  until the next gc collection.  In our case, in lib2to3/pytree.py,
-  WildcardPattern.match_seq() does not exhaust the generate_matches() generator,
-  and stderr is not restored.
-
-
 Longer tasks
 ------------
 

diff --git a/pypy/module/imp/test/test_import.py b/pypy/module/imp/test/test_import.py
--- a/pypy/module/imp/test/test_import.py
+++ b/pypy/module/imp/test/test_import.py
@@ -6,6 +6,7 @@
 from pypy.tool.udir import udir
 from pypy.rlib import streamio
 from pypy.conftest import gettestobjspace
+import pytest
 import sys, os
 import tempfile, marshal
 
@@ -109,6 +110,14 @@
             p.join('lone.pyc').write(p.join('x.pyc').read(mode='rb'),
                                      mode='wb')
 
+    # create a .pyw file
+    p = setuppkg("windows", x = "x = 78")
+    try:
+        p.join('x.pyw').remove()
+    except py.error.ENOENT:
+        pass
+    p.join('x.py').rename(p.join('x.pyw'))
+
     return str(root)
 
 
@@ -177,6 +186,14 @@
         import a
         assert a == a0
 
+    def test_trailing_slash(self):
+        import sys
+        try:
+            sys.path[0] += '/'
+            import a
+        finally:
+            sys.path[0] = sys.path[0].rstrip('/')
+
     def test_import_pkg(self):
         import sys
         import pkg
@@ -325,6 +342,11 @@
         import compiled.x
         assert compiled.x == sys.modules.get('compiled.x')
 
+    @pytest.mark.skipif("sys.platform != 'win32'")
+    def test_pyw(self):
+        import windows.x
+        assert windows.x.__file__.endswith('x.pyw')
+
     def test_cannot_write_pyc(self):
         import sys, os
         p = os.path.join(sys.path[-1], 'readonly')
@@ -985,7 +1007,8 @@
 
 class AppTestPyPyExtension(object):
     def setup_class(cls):
-        cls.space = gettestobjspace(usemodules=['imp', 'zipimport'])
+        cls.space = gettestobjspace(usemodules=['imp', 'zipimport',
+                                                '__pypy__'])
         cls.w_udir = cls.space.wrap(str(udir))
 
     def test_run_compiled_module(self):

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
@@ -1,7 +1,7 @@
 import py
 from pypy.rlib.jit import JitDriver, hint, purefunction
 from pypy.jit.codewriter.policy import StopAtXPolicy
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 
 class SendTests(object):
     

diff --git a/pypy/rlib/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -457,6 +457,12 @@
             args_s.append(s_arg)
         bk.emulate_pbc_call(uniquekey, s_func, args_s)
 
+    def get_getfield_op(self, rtyper):
+        if rtyper.type_system.name == 'ootypesystem':
+            return 'oogetfield'
+        else:
+            return 'getfield'
+
     def specialize_call(self, hop, **kwds_i):
         # XXX to be complete, this could also check that the concretetype
         # of the variables are the same for each of the calls.
@@ -471,8 +477,8 @@
                 r_green = hop.args_r[i]
                 v_green = hop.inputarg(r_green, arg=i)
             else:
-                if hop.rtyper.type_system.name == 'ootypesystem':
-                    py.test.skip("lltype only")
+                #if hop.rtyper.type_system.name == 'ootypesystem':
+                    #py.test.skip("lltype only")
                 objname, fieldname = name.split('.')   # see test_green_field
                 assert objname in driver.reds
                 i = kwds_i['i_' + objname]
@@ -488,7 +494,10 @@
                         "field %r not found in %r" % (name,
                                                       r_red.lowleveltype.TO))
                     r_red = r_red.rbase
-                GTYPE = r_red.lowleveltype.TO
+                if hop.rtyper.type_system.name == 'ootypesystem':
+                    GTYPE = r_red.lowleveltype
+                else:
+                    GTYPE = r_red.lowleveltype.TO
                 assert GTYPE._immutable_field(mangled_name), (
                     "field %r must be declared as immutable" % name)
                 if not hasattr(driver, 'll_greenfields'):
@@ -497,7 +506,8 @@
                 #
                 v_red = hop.inputarg(r_red, arg=i)
                 c_llname = hop.inputconst(lltype.Void, mangled_name)
-                v_green = hop.genop('getfield', [v_red, c_llname],
+                getfield_op = self.get_getfield_op(hop.rtyper)
+                v_green = hop.genop(getfield_op, [v_red, c_llname],
                                     resulttype = r_field)
                 s_green = s_red.classdef.about_attribute(fieldname)
                 assert s_green is not None

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
@@ -1,6 +1,7 @@
 import py
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.rlib.jit import JitDriver
+from pypy.rlib import objectmodel
 
 class DictTests:
 
@@ -69,6 +70,66 @@
             res = self.meta_interp(f, [10], listops=True)
             assert res == expected
 
+    def test_dict_trace_hash(self):
+        myjitdriver = JitDriver(greens = [], reds = ['total', 'dct'])
+        def key(x):
+            return x % 2
+        def eq(x, y):
+            return (x % 2) == (y % 2)
+
+        def f(n):
+            dct = objectmodel.r_dict(eq, key)
+            total = n
+            while total:
+                myjitdriver.jit_merge_point(total=total, dct=dct)
+                if total not in dct:
+                    dct[total] = []
+                dct[total].append(total)
+                total -= 1
+            return len(dct[0])
+
+        res1 = f(100)
+        res2 = self.meta_interp(f, [100], listops=True)
+        assert res1 == res2
+        self.check_loops(int_mod=1) # the hash was traced
+
+    def test_dict_setdefault(self):
+        myjitdriver = JitDriver(greens = [], reds = ['total', 'dct'])
+        def f(n):
+            dct = {}
+            total = n
+            while total:
+                myjitdriver.jit_merge_point(total=total, dct=dct)
+                dct.setdefault(total % 2, []).append(total)
+                total -= 1
+            return len(dct[0])
+
+        assert f(100) == 50
+        res = self.meta_interp(f, [100], listops=True)
+        assert res == 50
+        self.check_loops(new=0, new_with_vtable=0)
+
+    def test_dict_as_counter(self):
+        myjitdriver = JitDriver(greens = [], reds = ['total', 'dct'])
+        def key(x):
+            return x % 2
+        def eq(x, y):
+            return (x % 2) == (y % 2)
+
+        def f(n):
+            dct = objectmodel.r_dict(eq, key)
+            total = n
+            while total:
+                myjitdriver.jit_merge_point(total=total, dct=dct)
+                dct[total] = dct.get(total, 0) + 1
+                total -= 1
+            return dct[0]
+
+        assert f(100) == 50
+        res = self.meta_interp(f, [100], listops=True)
+        assert res == 50
+        self.check_loops(int_mod=1)
+
 
 class TestOOtype(DictTests, OOJitMixin):
     pass

diff --git a/pypy/rpython/memory/test/test_transformed_gc.py b/pypy/rpython/memory/test/test_transformed_gc.py
--- a/pypy/rpython/memory/test/test_transformed_gc.py
+++ b/pypy/rpython/memory/test/test_transformed_gc.py
@@ -13,7 +13,6 @@
 from pypy.rlib import rgc
 from pypy import conftest
 from pypy.rlib.rstring import StringBuilder
-from pypy.rlib.objectmodel import keepalive_until_here
 from pypy.rlib.rarithmetic import LONG_BIT
 
 WORD = LONG_BIT // 8

diff --git a/pypy/translator/backendopt/test/test_support.py b/pypy/translator/backendopt/test/test_support.py
--- a/pypy/translator/backendopt/test/test_support.py
+++ b/pypy/translator/backendopt/test/test_support.py
@@ -1,94 +1,7 @@
-from pypy.translator.unsimplify import varoftype
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.translator.backendopt.support import \
-     needs_conservative_livevar_calculation, split_block_with_keepalive, \
      find_loop_blocks, find_backedges, compute_reachability
 
-from pypy.rpython.rtyper import LowLevelOpList
-from pypy.rpython.lltypesystem import lltype
-from pypy.objspace.flow import model
-
-NonGcB = lltype.Struct("B", ('x', lltype.Signed))
-GcA = lltype.GcStruct("A", ('b', NonGcB), ('c', lltype.Ptr(lltype.FuncType([], lltype.Void))))
-
-def test_nclc_should_be_true():
-    # this is testing a block like:
-    # +--- inputargs: pointer_to_gc
-    # | v0 <- op_getsubstruct pointer_to_gc 'b'
-    # +--- exitargs: v0 (i.e. pointer to non-gc)
-    llops = LowLevelOpList()
-    ptr_a = varoftype(lltype.Ptr(GcA))
-    v_res = llops.genop("getsubstruct", [ptr_a, model.Constant('b', lltype.Void)],
-                        resulttype=lltype.Ptr(NonGcB))
-    block = model.Block([ptr_a])
-    block.operations.extend(llops)
-    block.closeblock(model.Link([v_res], None))
-    assert needs_conservative_livevar_calculation(block)
-
-def test_nclc_nongc_not_passed_on():
-    # +--- inputargs: pointer_to_gc
-    # | v0 <- op_getsubstruct pointer_to_gc 'b'
-    # +--- exitargs: pointer_to_gc (i.e. the pointer to non-gc doesn't leave the block)
-    llops = LowLevelOpList()
-    ptr_a = varoftype(lltype.Ptr(GcA))
-    v_res = llops.genop("getsubstruct", [ptr_a, model.Constant('b', lltype.Void)],
-                        resulttype=lltype.Ptr(NonGcB))
-    block = model.Block([ptr_a])
-    block.operations.extend(llops)
-    block.closeblock(model.Link([ptr_a], None))
-    assert not needs_conservative_livevar_calculation(block)
-
-def test_nclc_ignore_functype():
-    # +--- inputargs: pointer_to_gc
-    # | v0 <- op_getfield pointer_to_gc 'c'
-    # +--- exitargs: v0 (i.e. a pointer to function)
-    # pointers to functions are 'not gc' but functions are also
-    # immortal so you don't need to muck around inserting keepalives
-    # so *they* don't die!
-    llops = LowLevelOpList()
-    ptr_a = varoftype(lltype.Ptr(GcA))
-    v_res = llops.genop("getfield", [ptr_a, model.Constant('c', lltype.Void)],
-                        resulttype=GcA.c)
-    block = model.Block([ptr_a])
-    block.operations.extend(llops)
-    block.closeblock(model.Link([v_res], None))
-    assert not needs_conservative_livevar_calculation(block)
-
-def test_sbwk_should_insert_keepalives():
-    # this is testing something like:
-    # v0 <- op_producing_non_gc
-    # v1 <- op_using_v0        <- split here
-    llops = LowLevelOpList()
-    ptr_a = varoftype(lltype.Ptr(GcA))
-    v_res = llops.genop("getfield", [ptr_a, model.Constant('b', lltype.Void)],
-                        resulttype=lltype.Ptr(NonGcB))
-    llops.genop("direct_call", [model.Constant(None, lltype.Void), v_res],
-                resulttype=lltype.Void)
-    block = model.Block([ptr_a])
-    block.operations.extend(llops)
-    block.closeblock(model.Link([], None))
-    link = split_block_with_keepalive(block, 1)
-    assert 'keepalive' in [op.opname for op in link.target.operations]
-
-def test_sbwk_should_insert_keepalives_2():
-    # this is testing something like:
-    # v0 <- op_producing_non_gc
-    # v1 <- op_not_using_v0        <- split here
-    # v2 <- op_using_v0
-    llops = LowLevelOpList()
-    ptr_a = varoftype(lltype.Ptr(GcA))
-    v_res = llops.genop("getfield", [ptr_a, model.Constant('b', lltype.Void)],
-                        resulttype=lltype.Ptr(NonGcB))
-    llops.genop("direct_call", [model.Constant(None, lltype.Void)],
-                resulttype=lltype.Void)
-    llops.genop("direct_call", [model.Constant(None, lltype.Void), v_res],
-                resulttype=lltype.Void)
-    block = model.Block([ptr_a])
-    block.operations.extend(llops)
-    block.closeblock(model.Link([], None))
-    link = split_block_with_keepalive(block, 1)
-    assert 'keepalive' in [op.opname for op in link.target.operations]
-
 #__________________________________________________________
 # test compute_reachability
 

diff --git a/pypy/jit/metainterp/test/test_optimizeutil.py b/pypy/jit/metainterp/test/test_optimizeutil.py
--- a/pypy/jit/metainterp/test/test_optimizeutil.py
+++ b/pypy/jit/metainterp/test/test_optimizeutil.py
@@ -68,6 +68,16 @@
     nodeobjvalue = lltype.cast_opaque_ptr(llmemory.GCREF, nodeobj)
     refdescr = cpu.fielddescrof(NODEOBJ, 'ref')
 
+    INTOBJ_NOIMMUT = lltype.GcStruct('INTOBJ_NOIMMUT', ('parent', OBJECT),
+                                                ('intval', lltype.Signed))
+    INTOBJ_IMMUT = lltype.GcStruct('INTOBJ_IMMUT', ('parent', OBJECT),
+                                            ('intval', lltype.Signed),
+                                            hints={'immutable': True})
+    intobj_noimmut_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
+    intobj_immut_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
+    noimmut_intval = cpu.fielddescrof(INTOBJ_NOIMMUT, 'intval')
+    immut_intval = cpu.fielddescrof(INTOBJ_IMMUT, 'intval')
+
     arraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Signed))
     floatarraydescr = cpu.arraydescrof(lltype.GcArray(lltype.Float))
 
@@ -147,7 +157,6 @@
     FakeWarmRunnerDesc.cpu = cpu
     vrefinfo = VirtualRefInfo(FakeWarmRunnerDesc)
     virtualtokendescr = vrefinfo.descr_virtual_token
-    virtualrefindexdescr = vrefinfo.descr_virtualref_index
     virtualforceddescr = vrefinfo.descr_forced
     jit_virtual_ref_vtable = vrefinfo.jit_virtual_ref_vtable
     jvr_vtable_adr = llmemory.cast_ptr_to_adr(jit_virtual_ref_vtable)
@@ -156,6 +165,8 @@
     register_known_gctype(cpu, node_vtable2, NODE2)
     register_known_gctype(cpu, u_vtable,     U)
     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)
 
     namespace = locals()
 

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
@@ -1,6 +1,8 @@
+import os
 from pypy.rlib import rgc
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.debug import fatalerror
+from pypy.rlib.rarithmetic import ovfcheck
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi, rclass, rstr
 from pypy.rpython.lltypesystem import llgroup
 from pypy.rpython.lltypesystem.lloperation import llop
@@ -21,6 +23,8 @@
 
 class GcLLDescription(GcCache):
     minimal_size_in_nursery = 0
+    get_malloc_slowpath_addr = None
+
     def __init__(self, gcdescr, translator=None, rtyper=None):
         GcCache.__init__(self, translator is not None, rtyper)
         self.gcdescr = gcdescr
@@ -34,6 +38,8 @@
         pass
     def can_inline_malloc(self, descr):
         return False
+    def can_inline_malloc_varsize(self, descr, num_elem):
+        return False
     def has_write_barrier_class(self):
         return None
     def freeing_block(self, start, stop):
@@ -212,10 +218,12 @@
         return addr_ref
 
 
-class GcRootMap_asmgcc:
+class GcRootMap_asmgcc(object):
     """Handles locating the stack roots in the assembler.
     This is the class supporting --gcrootfinder=asmgcc.
     """
+    is_shadow_stack = False
+
     LOC_REG       = 0
     LOC_ESP_PLUS  = 1
     LOC_EBP_PLUS  = 2
@@ -224,7 +232,7 @@
     GCMAP_ARRAY = rffi.CArray(lltype.Signed)
     CALLSHAPE_ARRAY_PTR = rffi.CArrayPtr(rffi.UCHAR)
 
-    def __init__(self):
+    def __init__(self, gcdescr=None):
         # '_gcmap' is an array of length '_gcmap_maxlength' of addresses.
         # '_gcmap_curlength' tells how full the array really is.
         # The addresses are actually grouped in pairs:
@@ -237,6 +245,13 @@
         self._gcmap_deadentries = 0
         self._gcmap_sorted = True
 
+    def add_jit2gc_hooks(self, jit2gc):
+        jit2gc.update({
+            'gcmapstart': lambda: self.gcmapstart(),
+            'gcmapend': lambda: self.gcmapend(),
+            'gcmarksorted': lambda: self.gcmarksorted(),
+            })
+
     def initialize(self):
         # hack hack hack.  Remove these lines and see MissingRTypeAttribute
         # when the rtyper tries to annotate these methods only when GC-ing...
@@ -365,7 +380,7 @@
             number >>= 7
         shape.append(chr(number | flag))
 
-    def add_ebp_offset(self, shape, offset):
+    def add_frame_offset(self, shape, offset):
         assert (offset & 3) == 0
         if offset >= 0:
             num = self.LOC_EBP_PLUS | offset
@@ -388,6 +403,126 @@
         return rawaddr
 
 
+class GcRootMap_shadowstack(object):
+    """Handles locating the stack roots in the assembler.
+    This is the class supporting --gcrootfinder=shadowstack.
+    """
+    is_shadow_stack = True
+    MARKER = 8
+
+    # The "shadowstack" is a portable way in which the GC finds the
+    # roots that live in the stack.  Normally it is just a list of
+    # pointers to GC objects.  The pointers may be moved around by a GC
+    # collection.  But with the JIT, an entry can also be MARKER, in
+    # which case the next entry points to an assembler stack frame.
+    # During a residual CALL from the assembler (which may indirectly
+    # call the GC), we use the force_index stored in the assembler
+    # stack frame to identify the call: we can go from the force_index
+    # to a list of where the GC pointers are in the frame (this is the
+    # purpose of the present class).
+    #
+    # Note that across CALL_MAY_FORCE or CALL_ASSEMBLER, we can also go
+    # from the force_index to a ResumeGuardForcedDescr instance, which
+    # is used if the virtualizable or the virtualrefs need to be forced
+    # (see pypy.jit.backend.model).  The force_index number in the stack
+    # frame is initially set to a non-negative value x, but it is
+    # occasionally turned into (~x) in case of forcing.
+
+    INTARRAYPTR = rffi.CArrayPtr(rffi.INT)
+    CALLSHAPES_ARRAY = rffi.CArray(INTARRAYPTR)
+
+    def __init__(self, gcdescr):
+        self._callshapes = lltype.nullptr(self.CALLSHAPES_ARRAY)
+        self._callshapes_maxlength = 0
+        self.force_index_ofs = gcdescr.force_index_ofs
+
+    def add_jit2gc_hooks(self, jit2gc):
+        #
+        def collect_jit_stack_root(callback, gc, addr):
+            if addr.signed[0] != GcRootMap_shadowstack.MARKER:
+                # common case
+                if gc.points_to_valid_gc_object(addr):
+                    callback(gc, addr)
+                return WORD
+            else:
+                # case of a MARKER followed by an assembler stack frame
+                follow_stack_frame_of_assembler(callback, gc, addr)
+                return 2 * WORD
+        #
+        def follow_stack_frame_of_assembler(callback, gc, addr):
+            frame_addr = addr.signed[1]
+            addr = llmemory.cast_int_to_adr(frame_addr + self.force_index_ofs)
+            force_index = addr.signed[0]
+            if force_index < 0:
+                force_index = ~force_index
+            callshape = self._callshapes[force_index]
+            n = 0
+            while True:
+                offset = rffi.cast(lltype.Signed, callshape[n])
+                if offset == 0:
+                    break
+                addr = llmemory.cast_int_to_adr(frame_addr + offset)
+                if gc.points_to_valid_gc_object(addr):
+                    callback(gc, addr)
+                n += 1
+        #
+        jit2gc.update({
+            'rootstackhook': collect_jit_stack_root,
+            })
+
+    def initialize(self):
+        pass
+
+    def get_basic_shape(self, is_64_bit=False):
+        return []
+
+    def add_frame_offset(self, shape, offset):
+        assert offset != 0
+        shape.append(offset)
+
+    def add_callee_save_reg(self, shape, register):
+        msg = "GC pointer in %s was not spilled" % register
+        os.write(2, '[llsupport/gc] %s\n' % msg)
+        raise AssertionError(msg)
+
+    def compress_callshape(self, shape, datablockwrapper):
+        length = len(shape)
+        SZINT = rffi.sizeof(rffi.INT)
+        rawaddr = datablockwrapper.malloc_aligned((length + 1) * SZINT, SZINT)
+        p = rffi.cast(self.INTARRAYPTR, rawaddr)
+        for i in range(length):
+            p[i] = rffi.cast(rffi.INT, shape[i])
+        p[length] = rffi.cast(rffi.INT, 0)
+        return p
+
+    def write_callshape(self, p, force_index):
+        if force_index >= self._callshapes_maxlength:
+            self._enlarge_callshape_list(force_index + 1)
+        self._callshapes[force_index] = p
+
+    def _enlarge_callshape_list(self, minsize):
+        newlength = 250 + (self._callshapes_maxlength // 3) * 4
+        if newlength < minsize:
+            newlength = minsize
+        newarray = lltype.malloc(self.CALLSHAPES_ARRAY, newlength,
+                                 flavor='raw', track_allocation=False)
+        if self._callshapes:
+            i = self._callshapes_maxlength - 1
+            while i >= 0:
+                newarray[i] = self._callshapes[i]
+                i -= 1
+            lltype.free(self._callshapes, flavor='raw')
+        self._callshapes = newarray
+        self._callshapes_maxlength = newlength
+
+    def freeing_block(self, start, stop):
+        pass     # nothing needed here
+
+    def get_root_stack_top_addr(self):
+        rst_addr = llop.gc_adr_of_root_stack_top(llmemory.Address)
+        return rffi.cast(lltype.Signed, rst_addr)
+
+
 class WriteBarrierDescr(AbstractDescr):
     def __init__(self, gc_ll_descr):
         self.llop1 = gc_ll_descr.llop1
@@ -437,7 +572,7 @@
         except KeyError:
             raise NotImplementedError("--gcrootfinder=%s not implemented"
                                       " with the JIT" % (name,))
-        gcrootmap = cls()
+        gcrootmap = cls(gcdescr)
         self.gcrootmap = gcrootmap
         self.gcrefs = GcRefList()
         self.single_gcref_descr = GcPtrFieldDescr('', 0)
@@ -446,12 +581,9 @@
         # where it can be fished and reused by the FrameworkGCTransformer
         self.layoutbuilder = framework.TransformerLayoutBuilder(translator)
         self.layoutbuilder.delay_encoding()
-        self.translator._jit2gc = {
-            'layoutbuilder': self.layoutbuilder,
-            'gcmapstart': lambda: gcrootmap.gcmapstart(),
-            'gcmapend': lambda: gcrootmap.gcmapend(),
-            'gcmarksorted': lambda: gcrootmap.gcmarksorted(),
-            }
+        self.translator._jit2gc = {'layoutbuilder': self.layoutbuilder}
+        gcrootmap.add_jit2gc_hooks(self.translator._jit2gc)
+
         self.GCClass = self.layoutbuilder.GCClass
         self.moving_gc = self.GCClass.moving_gc
         self.HDRPTR = lltype.Ptr(self.GCClass.HDR)
@@ -461,6 +593,10 @@
         self.max_size_of_young_obj = self.GCClass.JIT_max_size_of_young_obj()
         self.minimal_size_in_nursery=self.GCClass.JIT_minimal_size_in_nursery()
 
+        # for the fast path of mallocs, the following must be true, at least
+        assert self.GCClass.inline_simple_malloc
+        assert self.GCClass.inline_simple_malloc_varsize
+
         # make a malloc function, with three arguments
         def malloc_basic(size, tid):
             type_id = llop.extract_ushort(llgroup.HALFWORD, tid)
@@ -539,20 +675,23 @@
             x3 = x0 * 0.3
             for_test_only.x = x0 + x1 + x2 + x3
         #
-        def malloc_fixedsize_slowpath(size):
+        def malloc_slowpath(size):
             if self.DEBUG:
                 random_usage_of_xmm_registers()
             assert size >= self.minimal_size_in_nursery
             try:
+                # NB. although we call do_malloc_fixedsize_clear() here,
+                # it's a bit of a hack because we set tid to 0 and may
+                # also use it to allocate varsized objects.  The tid
+                # and possibly the length are both set afterward.
                 gcref = llop1.do_malloc_fixedsize_clear(llmemory.GCREF,
                                             0, size, True, False, False)
             except MemoryError:
                 fatalerror("out of memory (from JITted code)")
                 return 0
             return rffi.cast(lltype.Signed, gcref)
-        self.malloc_fixedsize_slowpath = malloc_fixedsize_slowpath
-        self.MALLOC_FIXEDSIZE_SLOWPATH = lltype.FuncType([lltype.Signed],
-                                                         lltype.Signed)
+        self.malloc_slowpath = malloc_slowpath
+        self.MALLOC_SLOWPATH = lltype.FuncType([lltype.Signed], lltype.Signed)
 
     def get_nursery_free_addr(self):
         nurs_addr = llop.gc_adr_of_nursery_free(llmemory.Address)
@@ -562,9 +701,8 @@
         nurs_top_addr = llop.gc_adr_of_nursery_top(llmemory.Address)
         return rffi.cast(lltype.Signed, nurs_top_addr)
 
-    def get_malloc_fixedsize_slowpath_addr(self):
-        fptr = llhelper(lltype.Ptr(self.MALLOC_FIXEDSIZE_SLOWPATH),
-                        self.malloc_fixedsize_slowpath)
+    def get_malloc_slowpath_addr(self):
+        fptr = llhelper(lltype.Ptr(self.MALLOC_SLOWPATH), self.malloc_slowpath)
         return rffi.cast(lltype.Signed, fptr)
 
     def initialize(self):
@@ -710,6 +848,16 @@
             return True
         return False
 
+    def can_inline_malloc_varsize(self, arraydescr, num_elem):
+        assert isinstance(arraydescr, BaseArrayDescr)
+        basesize = arraydescr.get_base_size(self.translate_support_code)
+        itemsize = arraydescr.get_item_size(self.translate_support_code)
+        try:
+            size = ovfcheck(basesize + ovfcheck(itemsize * num_elem))
+            return size < self.max_size_of_young_obj
+        except OverflowError:
+            return False
+
     def has_write_barrier_class(self):
         return WriteBarrierDescr
 

diff --git a/pypy/translator/backendopt/malloc.py b/pypy/translator/backendopt/malloc.py
--- a/pypy/translator/backendopt/malloc.py
+++ b/pypy/translator/backendopt/malloc.py
@@ -1,5 +1,5 @@
 from pypy.objspace.flow.model import Variable, Constant, Block, Link
-from pypy.objspace.flow.model import SpaceOperation, traverse
+from pypy.objspace.flow.model import SpaceOperation
 from pypy.tool.algo.unionfind import UnionFind
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.ootypesystem import ootype
@@ -67,7 +67,6 @@
         # in this 'block', follow where the 'var' goes to and replace
         # it by a flattened-out family of variables.  This family is given
         # by newvarsmap, whose keys are the 'flatnames'.
-        self.last_removed_access = None
 
         def list_newvars():
             return [newvarsmap[key] for key in self.flatnames]
@@ -115,7 +114,6 @@
                     newargs.append(arg)
             link.args[:] = newargs
 
-        self.insert_keepalives(list_newvars())
         block.operations[:] = self.newops
 
     def compute_lifetimes(self, graph):
@@ -149,8 +147,7 @@
         set_use_point(graph.exceptblock, graph.exceptblock.inputargs[0], "except")
         set_use_point(graph.exceptblock, graph.exceptblock.inputargs[1], "except")
 
-        def visit(node):
-            if isinstance(node, Block):
+        for node in graph.iterblocks():
                 for op in node.operations:
                     if op.opname in self.IDENTITY_OPS:
                         # special-case these operations to identify their input
@@ -167,7 +164,7 @@
                 if isinstance(node.exitswitch, Variable):
                     set_use_point(node, node.exitswitch, "exitswitch", node)
 
-            if isinstance(node, Link):
+        for node in graph.iterlinks():
                 if isinstance(node.last_exception, Variable):
                     set_creation_point(node.prevblock, node.last_exception,
                                        "last_exception")
@@ -187,7 +184,6 @@
                         else:
                             d[arg] = True
 
-        traverse(visit, graph)
         return lifetimes.infos()
 
     def _try_inline_malloc(self, info):
@@ -213,7 +209,7 @@
         STRUCT = self.get_STRUCT(lltypes.keys()[0])
 
         # must be only ever accessed via getfield/setfield/getsubstruct/
-        # direct_fieldptr, or touched by keepalive or ptr_iszero/ptr_nonzero.
+        # direct_fieldptr, or touched by ptr_iszero/ptr_nonzero.
         # Note that same_as and cast_pointer are not recorded in usepoints.
         self.accessed_substructs = {}
 
@@ -333,7 +329,6 @@
     MALLOC_OP = "malloc"
     FIELD_ACCESS =     dict.fromkeys(["getfield",
                                       "setfield",
-                                      "keepalive",
                                       "ptr_iszero",
                                       "ptr_nonzero",
                                       "getarrayitem",
@@ -484,7 +479,6 @@
                                        [newvarsmap[key]],
                                        op.result)
             self.newops.append(newop)
-            self.last_removed_access = len(self.newops)
         elif op.opname in ("setfield", "setarrayitem"):
             S = op.args[0].concretetype.TO
             fldname = op.args[1].value
@@ -500,15 +494,12 @@
                 self.newops.append(newop)
             else:
                 newvarsmap[key] = op.args[2]
-                self.last_removed_access = len(self.newops)
         elif op.opname in ("same_as", "cast_pointer"):
             vars[op.result] = True
             # Consider the two pointers (input and result) as
             # equivalent.  We can, and indeed must, use the same
             # flattened list of variables for both, as a "setfield"
             # via one pointer must be reflected in the other.
-        elif op.opname == 'keepalive':
-            self.last_removed_access = len(self.newops)
         elif op.opname in ("getsubstruct", "getarraysubstruct",
                            "direct_fieldptr"):
             S = op.args[0].concretetype.TO
@@ -546,18 +537,6 @@
         else:
             raise AssertionError, op.opname
 
-        
-    def insert_keepalives(self, newvars):
-        if self.last_removed_access is not None:
-            keepalives = []
-            for v in newvars:
-                T = v.concretetype
-                if isinstance(T, lltype.Ptr) and T._needsgc():
-                    v0 = Variable()
-                    v0.concretetype = lltype.Void
-                    newop = SpaceOperation('keepalive', [v], v0)
-                    keepalives.append(newop)
-            self.newops[self.last_removed_access:self.last_removed_access] = keepalives
 
 class OOTypeMallocRemover(BaseMallocRemover):
 
@@ -616,14 +595,12 @@
                                    [newvarsmap[key]],
                                    op.result)
             self.newops.append(newop)
-            last_removed_access = len(self.newops)
         elif op.opname == "oosetfield":
             S = op.args[0].concretetype
             fldname = op.args[1].value
             key = self.key_for_field_access(S, fldname)
             assert key in newvarsmap
             newvarsmap[key] = op.args[2]
-            last_removed_access = len(self.newops)
         elif op.opname in ("same_as", "oodowncast", "ooupcast"):
             vars[op.result] = True
             # Consider the two pointers (input and result) as
@@ -639,8 +616,6 @@
         else:
             raise AssertionError, op.opname
 
-    def insert_keepalives(self, newvars):
-        pass
 
 def remove_simple_mallocs(graph, type_system='lltypesystem', verbose=True):
     if type_system == 'lltypesystem':

diff --git a/pypy/doc/getting-started-python.rst b/pypy/doc/getting-started-python.rst
--- a/pypy/doc/getting-started-python.rst
+++ b/pypy/doc/getting-started-python.rst
@@ -79,7 +79,8 @@
 
    possibly replacing ``--opt=jit`` with another `optimization level`_
    of your choice like ``--opt=2`` if you do not want the included JIT
-   compiler.  As of March 2011, Intel **32-bit** environment needs ``4GB``.
+   compiler.  As of March 2011, Intel 32-bit environment needs **at
+   least** 2GB, and 64-bit needs 4GB.
 
 .. _`optimization level`: config/opt.html
 

diff --git a/pypy/rlib/rlocale.py b/pypy/rlib/rlocale.py
--- a/pypy/rlib/rlocale.py
+++ b/pypy/rlib/rlocale.py
@@ -7,6 +7,7 @@
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.rpython.tool import rffi_platform as platform
+from pypy.rpython.extfunc import register_external
 
 class LocaleError(Exception):
     def __init__(self, message):
@@ -156,23 +157,35 @@
 
 HAVE_BIND_TEXTDOMAIN_CODESET = cConfig.HAVE_BIND_TEXTDOMAIN_CODESET
 
-def external(name, args, result, calling_conv='c'):
+def external(name, args, result, calling_conv='c', **kwds):
     return rffi.llexternal(name, args, result,
                            compilation_info=CConfig._compilation_info_,
                            calling_conv=calling_conv,
-                           sandboxsafe=True)
+                           sandboxsafe=True, **kwds)
 
 _lconv = lltype.Ptr(cConfig.lconv)
 localeconv = external('localeconv', [], _lconv)
 
 def numeric_formatting():
     """Specialized function to get formatting for numbers"""
+    return numeric_formatting_impl()
+
+def numeric_formatting_impl():
     conv = localeconv()
     decimal_point = rffi.charp2str(conv.c_decimal_point)
     thousands_sep = rffi.charp2str(conv.c_thousands_sep)
     grouping = rffi.charp2str(conv.c_grouping)
     return decimal_point, thousands_sep, grouping
 
+def oo_numeric_formatting():
+    return '.', '', ''
+
+register_external(numeric_formatting, [], (str, str, str),
+                  llimpl=numeric_formatting_impl,
+                  ooimpl=oo_numeric_formatting,
+                  sandboxsafe=True)
+
+
 _setlocale = external('setlocale', [rffi.INT, rffi.CCHARP], rffi.CCHARP)
 
 def setlocale(category, locale):
@@ -184,11 +197,11 @@
         raise LocaleError("unsupported locale setting")
     return rffi.charp2str(ll_result)
 
-isalpha = external('isalpha', [rffi.INT], rffi.INT)
-isupper = external('isupper', [rffi.INT], rffi.INT)
-islower = external('islower', [rffi.INT], rffi.INT)
-tolower = external('tolower', [rffi.INT], rffi.INT)
-isalnum = external('isalnum', [rffi.INT], rffi.INT)
+isalpha = external('isalpha', [rffi.INT], rffi.INT, oo_primitive='locale_isalpha')
+isupper = external('isupper', [rffi.INT], rffi.INT, oo_primitive='locale_isupper')
+islower = external('islower', [rffi.INT], rffi.INT, oo_primitive='locale_islower')
+tolower = external('tolower', [rffi.INT], rffi.INT, oo_primitive='locale_tolower')
+isalnum = external('isalnum', [rffi.INT], rffi.INT, oo_primitive='locale_isalnum')
 
 if HAVE_LANGINFO:
     _nl_langinfo = external('nl_langinfo', [rffi.INT], rffi.CCHARP)

diff --git a/pypy/jit/metainterp/test/test_jitprof.py b/pypy/jit/metainterp/test/test_jitprof.py
--- a/pypy/jit/metainterp/test/test_jitprof.py
+++ b/pypy/jit/metainterp/test/test_jitprof.py
@@ -1,7 +1,7 @@
 
 from pypy.jit.metainterp.warmspot import ll_meta_interp
 from pypy.rlib.jit import JitDriver, dont_look_inside, purefunction
-from pypy.jit.metainterp.test.test_basic import LLJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin
 from pypy.jit.metainterp import pyjitpl
 from pypy.jit.metainterp.jitprof import *
 

diff --git a/pypy/translator/backendopt/test/test_constfold.py b/pypy/translator/backendopt/test/test_constfold.py
--- a/pypy/translator/backendopt/test/test_constfold.py
+++ b/pypy/translator/backendopt/test/test_constfold.py
@@ -185,27 +185,6 @@
     check_graph(graph, [0], 61, t)
 
 
-def test_keepalive_const_substruct():
-    py.test.skip("do we want partial folding of getinteriorfield?")
-    S2 = lltype.Struct('S2', ('x', lltype.Signed))
-    S1 = lltype.GcStruct('S1', ('sub', S2))
-    s1 = lltype.malloc(S1)
-    s1.sub.x = 1234
-    def fn():
-        return s1.sub.x
-    graph, t = get_graph(fn, [])
-    assert summary(graph) == {'getinteriorfield': 1}
-    constant_fold_graph(graph)
-
-    # kill all references to 's1'
-    s1 = fn = None
-    del graph.func
-    import gc; gc.collect()
-
-    assert summary(graph) == {'getfield': 1}
-    check_graph(graph, [], 1234, t)
-
-
 def test_keepalive_const_fieldptr():
     S1 = lltype.GcStruct('S1', ('x', lltype.Signed))
     s1 = lltype.malloc(S1)

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
@@ -127,12 +127,15 @@
                                checks[2], checks[3]))
         subclasses = {}
         for key, subcls in typedef._subclass_cache.items():
+            if key[0] is not space.config:
+                continue
             cls = key[1]
             subclasses.setdefault(cls, {})
-            subclasses[cls][subcls] = True
+            prevsubcls = subclasses[cls].setdefault(subcls.__name__, subcls)
+            assert subcls is prevsubcls
         for cls, set in subclasses.items():
             assert len(set) <= 6, "%s has %d subclasses:\n%r" % (
-                cls, len(set), [subcls.__name__ for subcls in set])
+                cls, len(set), list(set))
 
     def test_getsetproperty(self):
         class W_SomeType(Wrappable):

diff --git a/.gitignore b/.gitignore
--- a/.gitignore
+++ b/.gitignore
@@ -12,6 +12,8 @@
 pypy/doc/*.html
 pypy/doc/config/*.html
 pypy/doc/discussion/*.html
+pypy/module/cpyext/src/*.o
+pypy/module/cpyext/test/*.o
 pypy/module/test_lib_pypy/ctypes_tests/*.o
 pypy/translator/c/src/dtoa.o
 pypy/translator/goal/pypy-c

diff --git a/_pytest/resultlog.py b/_pytest/resultlog.py
--- a/_pytest/resultlog.py
+++ b/_pytest/resultlog.py
@@ -74,7 +74,7 @@
         elif report.failed:
             longrepr = str(report.longrepr)
         elif report.skipped:
-            longrepr = str(report.longrepr[2])
+            longrepr = str(report.longrepr)
         self.log_outcome(report, code, longrepr)
 
     def pytest_collectreport(self, report):

diff --git a/pypy/translator/c/test/test_lltyped.py b/pypy/translator/c/test/test_lltyped.py
--- a/pypy/translator/c/test/test_lltyped.py
+++ b/pypy/translator/c/test/test_lltyped.py
@@ -895,3 +895,10 @@
         fn = self.getcompiled(llf)
         assert fn() == 45
 
+    def test_rstring_to_float(self):
+        from pypy.rlib.rfloat import rstring_to_float
+        def llf(i):
+            s = ['42.3', '123.4'][i]
+            return rstring_to_float(s)
+        fn = self.getcompiled(llf, [int])
+        assert fn(0) == 42.3

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
@@ -717,6 +717,7 @@
 def test_random_function(BuilderClass=OperationBuilder):
     r = Random()
     cpu = get_cpu()
+    cpu.setup_once()
     if pytest.config.option.repeat == -1:
         while 1:
             check_random_function(cpu, BuilderClass, r)

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
@@ -9,7 +9,6 @@
 from pypy.jit.tool.oparser import parse
 from pypy.rpython.lltypesystem.rclass import OBJECT, OBJECT_VTABLE
 from pypy.jit.metainterp.test.test_optimizeopt import equaloplists
-from pypy.rpython.memory.gctransform import asmgcroot
 
 def test_boehm():
     gc_ll_descr = GcLLDescr_boehm(None, None, None)
@@ -75,8 +74,8 @@
         num2a = ((-num2|3) >> 7) | 128
         num2b = (-num2|3) & 127
         shape = gcrootmap.get_basic_shape()
-        gcrootmap.add_ebp_offset(shape, num1)
-        gcrootmap.add_ebp_offset(shape, num2)
+        gcrootmap.add_frame_offset(shape, num1)
+        gcrootmap.add_frame_offset(shape, num2)
         assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a])
         gcrootmap.add_callee_save_reg(shape, 1)
         assert shape == map(chr, [6, 7, 11, 15, 2, 0, num1a, num2b, num2a,
@@ -228,6 +227,33 @@
             gc.asmgcroot = saved
 
 
+class TestGcRootMapShadowStack:
+    class FakeGcDescr:
+        force_index_ofs = 92
+
+    def test_make_shapes(self):
+        gcrootmap = GcRootMap_shadowstack(self.FakeGcDescr())
+        shape = gcrootmap.get_basic_shape()
+        gcrootmap.add_frame_offset(shape, 16)
+        gcrootmap.add_frame_offset(shape, -24)
+        assert shape == [16, -24]
+
+    def test_compress_callshape(self):
+        class FakeDataBlockWrapper:
+            def malloc_aligned(self, size, alignment):
+                assert alignment == 4    # even on 64-bits
+                assert size == 12        # 4*3, even on 64-bits
+                return rffi.cast(lltype.Signed, p)
+        datablockwrapper = FakeDataBlockWrapper()
+        p = lltype.malloc(rffi.CArray(rffi.INT), 3, immortal=True)
+        gcrootmap = GcRootMap_shadowstack(self.FakeGcDescr())
+        shape = [16, -24]
+        gcrootmap.compress_callshape(shape, datablockwrapper)
+        assert rffi.cast(lltype.Signed, p[0]) == 16
+        assert rffi.cast(lltype.Signed, p[1]) == -24
+        assert rffi.cast(lltype.Signed, p[2]) == 0
+
+
 class FakeLLOp(object):
     def __init__(self):
         self.record = []

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
@@ -5,8 +5,8 @@
 soon as possible (at least in a simple case).
 """
 
-import weakref, random, sys
-import py
+import weakref, sys
+import py, os
 from pypy.annotation import policy as annpolicy
 from pypy.rlib import rgc
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi
@@ -71,6 +71,20 @@
     return entrypoint
 
 
+def get_functions_to_patch():
+    from pypy.jit.backend.llsupport import gc
+    #
+    can_inline_malloc1 = gc.GcLLDescr_framework.can_inline_malloc
+    def can_inline_malloc2(*args):
+        try:
+            if os.environ['PYPY_NO_INLINE_MALLOC']:
+                return False
+        except KeyError:
+            pass
+        return can_inline_malloc1(*args)
+    #
+    return {(gc.GcLLDescr_framework, 'can_inline_malloc'): can_inline_malloc2}
+
 def compile(f, gc, **kwds):
     from pypy.annotation.listdef import s_list_of_strings
     from pypy.translator.translator import TranslationContext
@@ -86,8 +100,21 @@
     ann = t.buildannotator(policy=annpolicy.StrictAnnotatorPolicy())
     ann.build_types(f, [s_list_of_strings], main_entry_point=True)
     t.buildrtyper().specialize()
+
     if kwds['jit']:
-        apply_jit(t, enable_opts='')
+        patch = get_functions_to_patch()
+        old_value = {}
+        try:
+            for (obj, attr), value in patch.items():
+                old_value[obj, attr] = getattr(obj, attr)
+                setattr(obj, attr, value)
+            #
+            apply_jit(t, enable_opts='')
+            #
+        finally:
+            for (obj, attr), oldvalue in old_value.items():
+                setattr(obj, attr, oldvalue)
+
     cbuilder = genc.CStandaloneBuilder(t, f, t.config)
     cbuilder.generate_source()
     cbuilder.compile()
@@ -126,7 +153,7 @@
 
 # ______________________________________________________________________
 
-class TestCompileFramework(object):
+class CompileFrameworkTests(object):
     # Test suite using (so far) the minimark GC.
     EXTRA_PARAMS = {}
 
@@ -179,16 +206,22 @@
         try:
             GcLLDescr_framework.DEBUG = True
             cls.cbuilder = compile(get_entry(allfuncs), DEFL_GC,
-                                   gcrootfinder="asmgcc", jit=True,
+                                   gcrootfinder=cls.gcrootfinder, jit=True,
                                    **cls.EXTRA_PARAMS)
         finally:
             GcLLDescr_framework.DEBUG = OLD_DEBUG
 
+    def _run(self, name, n, env):
+        res = self.cbuilder.cmdexec("%s %d" %(name, n), env=env)
+        assert int(res) == 20
+
     def run(self, name, n=2000):
         pypylog = udir.join('TestCompileFramework.log')
-        res = self.cbuilder.cmdexec("%s %d" %(name, n),
-                                    env={'PYPYLOG': ':%s' % pypylog})
-        assert int(res) == 20
+        env = {'PYPYLOG': ':%s' % pypylog,
+               'PYPY_NO_INLINE_MALLOC': '1'}
+        self._run(name, n, env)
+        env['PYPY_NO_INLINE_MALLOC'] = ''
+        self._run(name, n, env)
 
     def run_orig(self, name, n, x):
         self.main_allfuncs(name, n, x)
@@ -580,10 +613,15 @@
         self.run('compile_framework_minimal_size_in_nursery')
 
 
-class TestCompressPtr(TestCompileFramework):
+class TestShadowStack(CompileFrameworkTests):
+    gcrootfinder = "shadowstack"
+
+class TestCompressPtr(TestShadowStack):
     EXTRA_PARAMS = {'compressptr': True}
-
     def setup_class(cls):
         if sys.maxint == 2147483647:
             py.test.skip("for 64-bit only")
-        TestCompileFramework.setup_class.im_func(cls)
+        TestShadowStack.setup_class.im_func(cls)
+
+class TestAsmGcc(CompileFrameworkTests):
+    gcrootfinder = "asmgcc"

diff --git a/pypy/rlib/rdtoa.py b/pypy/rlib/rdtoa.py
--- a/pypy/rlib/rdtoa.py
+++ b/pypy/rlib/rdtoa.py
@@ -5,16 +5,33 @@
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.rlib import jit
 from pypy.rlib.rstring import StringBuilder
-import py
+import py, sys
 
 cdir = py.path.local(pypydir) / 'translator' / 'c'
 include_dirs = [cdir]
 
+# set the word endianness based on the host's endianness
+# and the C double's endianness (which should be equal)
+if hasattr(float, '__getformat__'):
+    assert float.__getformat__('double') == 'IEEE, %s-endian' % sys.byteorder
+if sys.byteorder == 'little':
+    source_file = ['#define DOUBLE_IS_LITTLE_ENDIAN_IEEE754']
+elif sys.byteorder == 'big':
+    source_file = ['#define WORDS_BIGENDIAN',
+                   '#define DOUBLE_IS_BIG_ENDIAN_IEEE754']
+else:
+    raise AssertionError(sys.byteorder)
+
+source_file.append('#include "src/dtoa.c"')
+source_file = '\n\n'.join(source_file)
+
+# ____________________________________________________________
+
 eci = ExternalCompilationInfo(
     include_dirs = [cdir],
     includes = ['src/dtoa.h'],
     libraries = [],
-    separate_module_files = [cdir / 'src' / 'dtoa.c'],
+    separate_module_sources = [source_file],
     export_symbols = ['_PyPy_dg_strtod',
                       '_PyPy_dg_dtoa',
                       '_PyPy_dg_freedtoa',

diff --git a/pypy/translator/goal/targetpypystandalone.py b/pypy/translator/goal/targetpypystandalone.py
--- a/pypy/translator/goal/targetpypystandalone.py
+++ b/pypy/translator/goal/targetpypystandalone.py
@@ -105,13 +105,6 @@
         return parser
 
     def handle_config(self, config, translateconfig):
-        if config.translation.type_system == 'ootype':
-            print
-            print 'Translation to cli and jvm is known to be broken at the moment'
-            print 'Please try the "cli-jit" branch at:'
-            print 'http://codespeak.net/svn/pypy/branch/cli-jit/'
-            sys.exit(1)
-
         self.translateconfig = translateconfig
         # set up the objspace optimizations based on the --opt argument
         from pypy.config.pypyoption import set_pypy_opt_level
@@ -159,8 +152,8 @@
             from pypy.config.pypyoption import enable_translationmodules
             enable_translationmodules(config)
 
-        if config.translation.type_system == 'ootype':
-            config.objspace.usemodules.suggest(rbench=True)
+        ## if config.translation.type_system == 'ootype':
+        ##     config.objspace.usemodules.suggest(rbench=True)
 
         if config.translation.thread:
             config.objspace.usemodules.thread = True


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
@@ -1,6 +1,6 @@
 import py
 from pypy.rlib.jit import JitDriver
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 
 
 class DelTests:

diff --git a/pypy/module/thread/__init__.py b/pypy/module/thread/__init__.py
--- a/pypy/module/thread/__init__.py
+++ b/pypy/module/thread/__init__.py
@@ -12,12 +12,13 @@
         'get_ident':              'os_thread.get_ident',
         'exit':                   'os_thread.exit',
         'exit_thread':            'os_thread.exit', # obsolete synonym
+        'interrupt_main':         'os_thread.interrupt_main',
         'stack_size':             'os_thread.stack_size',
         '_count':                 'os_thread._count',
         'allocate_lock':          'os_lock.allocate_lock',
         'allocate':               'os_lock.allocate_lock',  # obsolete synonym
-        'LockType':               'os_lock.getlocktype(space)',
-        '_local':                 'os_local.getlocaltype(space)',
+        'LockType':               'os_lock.Lock',
+        '_local':                 'os_local.Local',
         'error':                  'space.fromcache(error.Cache).w_error',
     }
 

diff --git a/lib_pypy/_pypy_wait.py b/lib_pypy/_pypy_wait.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/_pypy_wait.py
@@ -0,0 +1,51 @@
+from ctypes import CDLL, c_int, POINTER, byref
+from ctypes.util import find_library
+from resource import _struct_rusage, struct_rusage
+
+__all__ = ["wait3", "wait4"]
+
+libc = CDLL(find_library("c"))
+c_wait3 = libc.wait3
+
+c_wait3.argtypes = [POINTER(c_int), c_int, POINTER(_struct_rusage)]
+
+c_wait4 = libc.wait4
+
+c_wait4.argtypes = [c_int, POINTER(c_int), c_int, POINTER(_struct_rusage)]
+
+def create_struct_rusage(c_struct):
+    return struct_rusage((
+        float(c_struct.ru_utime),
+        float(c_struct.ru_stime),
+        c_struct.ru_maxrss,
+        c_struct.ru_ixrss,
+        c_struct.ru_idrss,
+        c_struct.ru_isrss,
+        c_struct.ru_minflt,
+        c_struct.ru_majflt,
+        c_struct.ru_nswap,
+        c_struct.ru_inblock,
+        c_struct.ru_oublock,
+        c_struct.ru_msgsnd,
+        c_struct.ru_msgrcv,
+        c_struct.ru_nsignals,
+        c_struct.ru_nvcsw,
+        c_struct.ru_nivcsw))
+
+def wait3(options):
+    status = c_int()
+    _rusage = _struct_rusage()
+    pid = c_wait3(byref(status), c_int(options), byref(_rusage))
+
+    rusage = create_struct_rusage(_rusage)
+
+    return pid, status.value, rusage
+
+def wait4(pid, options):
+    status = c_int()
+    _rusage = _struct_rusage()
+    pid = c_wait4(c_int(pid), byref(status), c_int(options), byref(_rusage))
+
+    rusage = create_struct_rusage(_rusage)
+
+    return pid, status.value, rusage

diff --git a/pypy/objspace/std/celldict.py b/pypy/objspace/std/celldict.py
--- a/pypy/objspace/std/celldict.py
+++ b/pypy/objspace/std/celldict.py
@@ -34,11 +34,7 @@
 
     @jit.purefunction
     def _getcell_makenew(self, key):
-        res = self.content.get(key, None)
-        if res is not None:
-            return res
-        result = self.content[key] = ModuleCell()
-        return result
+        return self.content.setdefault(key, ModuleCell())
 
     def impl_setitem(self, w_key, w_value):
         space = self.space
@@ -50,6 +46,16 @@
     def impl_setitem_str(self, name, w_value):
         self.getcell(name, True).w_value = w_value
 
+    def impl_setdefault(self, w_key, w_default):
+        space = self.space
+        if space.is_w(space.type(w_key), space.w_str):
+            cell = self.getcell(space.str_w(w_key), True)
+            if cell.w_value is None:
+                cell.w_value = w_default
+            return cell.w_value
+        else:
+            return self._as_rdict().impl_fallback_setdefault(w_key, w_default)
+
     def impl_delitem(self, w_key):
         space = self.space
         w_key_type = space.type(w_key)

diff --git a/pypy/module/cpyext/pyobject.py b/pypy/module/cpyext/pyobject.py
--- a/pypy/module/cpyext/pyobject.py
+++ b/pypy/module/cpyext/pyobject.py
@@ -7,6 +7,7 @@
     CANNOT_FAIL, Py_TPFLAGS_HEAPTYPE, PyTypeObjectPtr)
 from pypy.module.cpyext.state import State
 from pypy.objspace.std.typeobject import W_TypeObject
+from pypy.objspace.std.objectobject import W_ObjectObject
 from pypy.rlib.objectmodel import specialize, we_are_translated
 from pypy.rlib.rweakref import RWeakKeyDictionary
 from pypy.rpython.annlowlevel import llhelper
@@ -370,6 +371,15 @@
 @cpython_api([PyObject], lltype.Void)
 def _Py_NewReference(space, obj):
     obj.c_ob_refcnt = 1
+    w_type = from_ref(space, rffi.cast(PyObject, obj.c_ob_type))
+    assert isinstance(w_type, W_TypeObject)
+    if w_type.is_cpytype():
+        w_obj = space.allocate_instance(W_ObjectObject, w_type)
+        track_reference(space, obj, w_obj)
+        state = space.fromcache(RefcountState)
+        state.set_lifeline(w_obj, obj)
+    else:
+        assert False, "Please add more cases in _Py_NewReference()"
 
 def _Py_Dealloc(space, obj):
     from pypy.module.cpyext.api import generic_cpy_call_dont_decref

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
@@ -27,7 +27,10 @@
 from pyrepl.console import Console, Event
 from pyrepl import unix_eventqueue
 
-_error = (termios.error, curses.error)
+class InvalidTerminal(RuntimeError):
+    pass
+
+_error = (termios.error, curses.error, InvalidTerminal)
 
 # there are arguments for changing this to "refresh"
 SIGWINCH_EVENT = 'repaint'
@@ -38,7 +41,7 @@
 def _my_getstr(cap, optional=0):
     r = curses.tigetstr(cap)
     if not optional and r is None:
-        raise RuntimeError, \
+        raise InvalidTerminal, \
               "terminal doesn't have the required '%s' capability"%cap
     return r
 
@@ -289,6 +292,12 @@
                 self.__write_code(self._el)
             self.__write(newline[x:])
             self.__posxy = len(newline), y
+        
+        if '\x1b' in newline:
+            # ANSI escape characters are present, so we can't assume
+            # anything about the position of the cursor.  Moving the cursor
+            # to the left margin should work to get to a known position.
+            self.move_cursor(0, y)
 
     def __write(self, text):
         self.__buffer.append((text, 0))


diff --git a/pypy/module/cpyext/test/test_object.py b/pypy/module/cpyext/test/test_object.py
--- a/pypy/module/cpyext/test/test_object.py
+++ b/pypy/module/cpyext/test/test_object.py
@@ -174,6 +174,17 @@
         assert api.PyObject_Compare(space.wrap(72), space.wrap(42)) == 1
         assert api.PyObject_Compare(space.wrap("a"), space.wrap("a")) == 0
 
+    def test_cmp(self, space, api):
+        w = space.wrap
+        with lltype.scoped_alloc(rffi.INTP.TO, 1) as ptr:
+            assert api.PyObject_Cmp(w(42), w(72), ptr) == 0
+            assert ptr[0] == -1
+            assert api.PyObject_Cmp(w("a"), w("a"), ptr) == 0
+            assert ptr[0] == 0
+            assert api.PyObject_Cmp(w(u"\xe9"), w("\xe9"), ptr) < 0
+            assert api.PyErr_Occurred()
+            api.PyErr_Clear()
+
     def test_unicode(self, space, api):
         assert space.unwrap(api.PyObject_Unicode(space.wrap([]))) == u"[]"
         assert space.unwrap(api.PyObject_Unicode(space.wrap("e"))) == u"e"

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
@@ -278,6 +278,22 @@
             rex_mem_reg_plus_scaled_reg_plus_const)
 
 # ____________________________________________________________
+# Emit a mod/rm referencing an immediate address that fits in 32-bit
+# (the immediate address itself must be explicitely encoded as well,
+# with immediate(argnum)).
+
+def encode_abs(mc, _1, _2, orbyte):
+    # expands to either '\x05' on 32-bit, or '\x04\x25' or 64-bit
+    if mc.WORD == 8:
+        mc.writechar(chr(0x04 | orbyte))
+        mc.writechar(chr(0x25))
+    else:
+        mc.writechar(chr(0x05 | orbyte))
+    return 0
+
+abs_ = encode_abs, 0, None, None
+
+# ____________________________________________________________
 # For 64-bits mode: the REX.W, REX.R, REX.X, REG.B prefixes
 
 REX_W = 8
@@ -348,7 +364,9 @@
     INSN_br = insn(rex_w, chr(base+1), register(2,8), stack_bp(1))
     INSN_rb = insn(rex_w, chr(base+3), register(1,8), stack_bp(2))
     INSN_rm = insn(rex_w, chr(base+3), register(1,8), mem_reg_plus_const(2))
-    INSN_rj = insn(rex_w, chr(base+3), register(1,8), '\x05', immediate(2))
+    INSN_rj = insn(rex_w, chr(base+3), register(1,8), abs_, immediate(2))
+    INSN_ji8 = insn(rex_w, '\x83', orbyte(base), abs_, immediate(1),
+                    immediate(2,'b'))
     INSN_bi8 = insn(rex_w, '\x83', orbyte(base), stack_bp(1), immediate(2,'b'))
     INSN_bi32= insn(rex_w, '\x81', orbyte(base), stack_bp(1), immediate(2))
 
@@ -366,7 +384,8 @@
             INSN_bi32(mc, offset, immed)
     INSN_bi._always_inline_ = True      # try to constant-fold single_byte()
 
-    return INSN_ri, INSN_rr, INSN_rb, INSN_bi, INSN_br, INSN_rm, INSN_rj
+    return (INSN_ri, INSN_rr, INSN_rb, INSN_bi, INSN_br, INSN_rm, INSN_rj,
+            INSN_ji8)
 
 def select_8_or_32_bit_immed(insn_8, insn_32):
     def INSN(*args):
@@ -444,23 +463,25 @@
 
     # ------------------------------ Arithmetic ------------------------------
 
-    ADD_ri, ADD_rr, ADD_rb, _, _, ADD_rm, ADD_rj = common_modes(0)
-    OR_ri,  OR_rr,  OR_rb,  _, _, OR_rm,  OR_rj  = common_modes(1)
-    AND_ri, AND_rr, AND_rb, _, _, AND_rm, AND_rj = common_modes(4)
-    SUB_ri, SUB_rr, SUB_rb, _, _, SUB_rm, SUB_rj = common_modes(5)
-    SBB_ri, SBB_rr, SBB_rb, _, _, SBB_rm, SBB_rj = common_modes(3)
-    XOR_ri, XOR_rr, XOR_rb, _, _, XOR_rm, XOR_rj = common_modes(6)
-    CMP_ri, CMP_rr, CMP_rb, CMP_bi, CMP_br, CMP_rm, CMP_rj = common_modes(7)
+    ADD_ri, ADD_rr, ADD_rb, _, _, ADD_rm, ADD_rj, _ = common_modes(0)
+    OR_ri,  OR_rr,  OR_rb,  _, _, OR_rm,  OR_rj,  _ = common_modes(1)
+    AND_ri, AND_rr, AND_rb, _, _, AND_rm, AND_rj, _ = common_modes(4)
+    SUB_ri, SUB_rr, SUB_rb, _, _, SUB_rm, SUB_rj, SUB_ji8 = common_modes(5)
+    SBB_ri, SBB_rr, SBB_rb, _, _, SBB_rm, SBB_rj, _ = common_modes(3)
+    XOR_ri, XOR_rr, XOR_rb, _, _, XOR_rm, XOR_rj, _ = common_modes(6)
+    CMP_ri, CMP_rr, CMP_rb, CMP_bi, CMP_br, CMP_rm, CMP_rj, _ = common_modes(7)
 
     CMP_mi8 = insn(rex_w, '\x83', orbyte(7<<3), mem_reg_plus_const(1), immediate(2, 'b'))
     CMP_mi32 = insn(rex_w, '\x81', orbyte(7<<3), mem_reg_plus_const(1), immediate(2))
     CMP_mi = select_8_or_32_bit_immed(CMP_mi8, CMP_mi32)
     CMP_mr = insn(rex_w, '\x39', register(2, 8), mem_reg_plus_const(1))
 
-    CMP_ji8 = insn(rex_w, '\x83', '\x3D', immediate(1), immediate(2, 'b'))
-    CMP_ji32 = insn(rex_w, '\x81', '\x3D', immediate(1), immediate(2))
+    CMP_ji8 = insn(rex_w, '\x83', orbyte(7<<3), abs_,
+                   immediate(1), immediate(2, 'b'))
+    CMP_ji32 = insn(rex_w, '\x81', orbyte(7<<3), abs_,
+                    immediate(1), immediate(2))
     CMP_ji = select_8_or_32_bit_immed(CMP_ji8, CMP_ji32)
-    CMP_jr = insn(rex_w, '\x39', register(2, 8), '\x05', immediate(1))
+    CMP_jr = insn(rex_w, '\x39', register(2, 8), abs_, immediate(1))
 
     CMP32_mi = insn(rex_nw, '\x81', orbyte(7<<3), mem_reg_plus_const(1), immediate(2))
 
@@ -508,7 +529,7 @@
     LEA32_rb = insn(rex_w, '\x8D', register(1,8),stack_bp(2,force_32bits=True))
     LEA_ra = insn(rex_w, '\x8D', register(1, 8), mem_reg_plus_scaled_reg_plus_const(2))
     LEA_rm = insn(rex_w, '\x8D', register(1, 8), mem_reg_plus_const(2))
-    LEA_rj = insn(rex_w, '\x8D', register(1, 8), '\x05', immediate(2))
+    LEA_rj = insn(rex_w, '\x8D', register(1, 8), abs_, immediate(2))
 
     CALL_l = insn('\xE8', relative(1))
     CALL_r = insn(rex_nw, '\xFF', register(1), chr(0xC0 | (2<<3)))
@@ -534,12 +555,15 @@
     CDQ = insn(rex_nw, '\x99')
 
     TEST8_mi = insn(rex_nw, '\xF6', orbyte(0<<3), mem_reg_plus_const(1), immediate(2, 'b'))
-    TEST8_ji = insn(rex_nw, '\xF6', orbyte(0<<3), '\x05', immediate(1), immediate(2, 'b'))
+    TEST8_ji = insn(rex_nw, '\xF6', orbyte(0<<3), abs_, immediate(1), immediate(2, 'b'))
     TEST_rr = insn(rex_w, '\x85', register(2,8), register(1), '\xC0')
 
     # x87 instructions
     FSTP_b = insn('\xDD', orbyte(3<<3), stack_bp(1))
 
+    # reserved as an illegal instruction
+    UD2 = insn('\x0F\x0B')
+
     # ------------------------------ SSE2 ------------------------------
 
     # Conversion
@@ -639,7 +663,7 @@
     add_insn('s', stack_sp(modrm_argnum))
     add_insn('m', mem_reg_plus_const(modrm_argnum))
     add_insn('a', mem_reg_plus_scaled_reg_plus_const(modrm_argnum))
-    add_insn('j', '\x05', immediate(modrm_argnum))
+    add_insn('j', abs_, immediate(modrm_argnum))
 
 # Define a regular MOV, and a variant MOV32 that only uses the low 4 bytes of a
 # register
@@ -680,7 +704,7 @@
     #
     assert insnname_template.count('*') == 1
     add_insn('x', register(2), '\xC0')
-    add_insn('j', '\x05', immediate(2))
+    add_insn('j', abs_, immediate(2))
 
 define_pxmm_insn('PADDQ_x*',     '\xD4')
 define_pxmm_insn('PSUBQ_x*',     '\xFB')

diff --git a/pypy/jit/metainterp/virtualref.py b/pypy/jit/metainterp/virtualref.py
--- a/pypy/jit/metainterp/virtualref.py
+++ b/pypy/jit/metainterp/virtualref.py
@@ -13,7 +13,6 @@
         self.JIT_VIRTUAL_REF = lltype.GcStruct('JitVirtualRef',
             ('super', rclass.OBJECT),
             ('virtual_token', lltype.Signed),
-            ('virtualref_index', lltype.Signed),
             ('forced', rclass.OBJECTPTR))
         self.jit_virtual_ref_vtable = lltype.malloc(rclass.OBJECT_VTABLE,
                                                     zero=True, flavor='raw',
@@ -27,8 +26,6 @@
         fielddescrof = self.cpu.fielddescrof
         self.descr_virtual_token = fielddescrof(self.JIT_VIRTUAL_REF,
                                                 'virtual_token')
-        self.descr_virtualref_index = fielddescrof(self.JIT_VIRTUAL_REF,
-                                                   'virtualref_index')
         self.descr_forced = fielddescrof(self.JIT_VIRTUAL_REF, 'forced')
         #
         # record the type JIT_VIRTUAL_REF explicitly in the rtyper, too

diff --git a/pypy/interpreter/executioncontext.py b/pypy/interpreter/executioncontext.py
--- a/pypy/interpreter/executioncontext.py
+++ b/pypy/interpreter/executioncontext.py
@@ -519,7 +519,7 @@
             return
         code = frame.pycode
         if frame.instr_lb <= frame.last_instr < frame.instr_ub:
-            if frame.last_instr <= frame.instr_prev:
+            if frame.last_instr < frame.instr_prev_plus_one:
                 # We jumped backwards in the same line.
                 executioncontext._trace(frame, 'line', self.space.w_None)
         else:
@@ -557,5 +557,5 @@
                 frame.f_lineno = line
                 executioncontext._trace(frame, 'line', self.space.w_None)
 
-        frame.instr_prev = frame.last_instr
+        frame.instr_prev_plus_one = frame.last_instr + 1
         self.space.frame_trace_action.fire()     # continue tracing

diff --git a/pypy/translator/backendopt/test/test_merge_if_blocks.py b/pypy/translator/backendopt/test/test_merge_if_blocks.py
--- a/pypy/translator/backendopt/test/test_merge_if_blocks.py
+++ b/pypy/translator/backendopt/test/test_merge_if_blocks.py
@@ -2,7 +2,7 @@
 from pypy.translator.backendopt.merge_if_blocks import merge_if_blocks
 from pypy.translator.backendopt.all import backend_optimizations
 from pypy.translator.translator import TranslationContext, graphof as tgraphof
-from pypy.objspace.flow.model import flatten, Block
+from pypy.objspace.flow.model import Block
 from pypy.translator.backendopt.removenoops import remove_same_as
 from pypy.rpython.llinterp import LLInterpreter
 from pypy.rlib.rarithmetic import r_uint, r_ulonglong, r_longlong, r_int

diff --git a/pypy/jit/metainterp/test/test_immutable.py b/pypy/jit/metainterp/test/test_immutable.py
--- a/pypy/jit/metainterp/test/test_immutable.py
+++ b/pypy/jit/metainterp/test/test_immutable.py
@@ -1,4 +1,4 @@
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 
 
 class ImmutableFieldsTests:

diff --git a/pypy/translator/test/test_simplify.py b/pypy/translator/test/test_simplify.py
--- a/pypy/translator/test/test_simplify.py
+++ b/pypy/translator/test/test_simplify.py
@@ -3,7 +3,7 @@
 from pypy.translator.backendopt.all import backend_optimizations
 from pypy.translator.simplify import (get_graph, transform_dead_op_vars,
                                       desugar_isinstance)
-from pypy.objspace.flow.model import traverse, Block, Constant, summary
+from pypy.objspace.flow.model import Block, Constant, summary
 from pypy import conftest
 
 def translate(func, argtypes, backend_optimize=True):
@@ -156,36 +156,6 @@
     assert graph.startblock.operations[-1].opname == 'direct_call'
 
 
-def test_remove_pointless_keepalive():
-    from pypy.rlib import objectmodel
-    class C:
-        y = None
-        z1 = None
-        z2 = None
-
-    def g():
-        return C()
-
-    def f(i):
-        c = g()
-        c.y
-        if i:
-            n = c.z1
-        else:
-            n = c.z2
-        objectmodel.keepalive_until_here(c, n)
-
-    graph, t = translate(f, [bool])
-
-    #t.view()
-
-    for block in graph.iterblocks():
-        for op in block.operations:
-            assert op.opname != 'getfield'
-            if op.opname == 'keepalive':
-                assert op.args[0] in graph.getargs()
-
-
 def test_remove_identical_variables():
     def g(code):
         pc = 0

diff --git a/pypy/tool/jitlogparser/parser.py b/pypy/tool/jitlogparser/parser.py
--- a/pypy/tool/jitlogparser/parser.py
+++ b/pypy/tool/jitlogparser/parser.py
@@ -107,7 +107,8 @@
                 self.bytecode_no = int(bytecode_no)
         self.operations = operations
         self.storage = storage
-        self.code = storage.disassemble_code(self.filename, self.startlineno)
+        self.code = storage.disassemble_code(self.filename, self.startlineno,
+                                             self.name)
 
     def repr(self):
         if self.filename is None:

diff --git a/lib_pypy/pypy_test/test_os_wait.py b/lib_pypy/pypy_test/test_os_wait.py
new file mode 100644
--- /dev/null
+++ b/lib_pypy/pypy_test/test_os_wait.py
@@ -0,0 +1,44 @@
+# Generates the resource cache
+from __future__ import absolute_import
+from lib_pypy.ctypes_config_cache import rebuild
+rebuild.rebuild_one('resource.ctc.py')
+
+import os
+
+from lib_pypy._pypy_wait import wait3, wait4
+
+if hasattr(os, 'wait3'):
+    def test_os_wait3():
+        exit_status = 0x33
+
+        if not hasattr(os, "fork"):
+            skip("Need fork() to test wait3()")
+
+        child = os.fork()
+        if child == 0: # in child
+            os._exit(exit_status)
+        else:
+            pid, status, rusage = wait3(0)
+            assert child == pid
+            assert os.WIFEXITED(status)
+            assert os.WEXITSTATUS(status) == exit_status
+            assert isinstance(rusage.ru_utime, float)
+            assert isinstance(rusage.ru_maxrss, int)
+
+if hasattr(os, 'wait4'):
+    def test_os_wait4():
+        exit_status = 0x33
+
+        if not hasattr(os, "fork"):
+            skip("Need fork() to test wait4()")
+
+        child = os.fork()
+        if child == 0: # in child
+            os._exit(exit_status)
+        else:
+            pid, status, rusage = wait4(child, 0)
+            assert child == pid
+            assert os.WIFEXITED(status)
+            assert os.WEXITSTATUS(status) == exit_status
+            assert isinstance(rusage.ru_utime, float)
+            assert isinstance(rusage.ru_maxrss, int)

diff --git a/pypy/jit/metainterp/test/test_memmgr.py b/pypy/jit/metainterp/test/test_memmgr.py
--- a/pypy/jit/metainterp/test/test_memmgr.py
+++ b/pypy/jit/metainterp/test/test_memmgr.py
@@ -12,7 +12,7 @@
 
 import py
 from pypy.jit.metainterp.memmgr import MemoryManager
-from pypy.jit.metainterp.test.test_basic import LLJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin
 from pypy.rlib.jit import JitDriver, dont_look_inside
 
 

diff --git a/pypy/doc/config/confrest.py b/pypy/doc/config/confrest.py
--- a/pypy/doc/config/confrest.py
+++ b/pypy/doc/config/confrest.py
@@ -7,7 +7,6 @@
 all_optiondescrs = [pypyoption.pypy_optiondescription,
                     translationoption.translation_optiondescription,
                    ]
-
 start_to_descr = dict([(descr._name, descr) for descr in all_optiondescrs])
 
 class PyPyPage(PyPyPage): 
@@ -29,7 +28,7 @@
     Page = PyPyPage 
 
     def get_content(self, txtpath, encoding):
-        if txtpath.basename == "commandline.txt":
+        if txtpath.basename == "commandline.rst":
             result = []
             for line in txtpath.read().splitlines():
                 if line.startswith('.. GENERATE:'):

diff --git a/pypy/jit/metainterp/test/test_float.py b/pypy/jit/metainterp/test/test_float.py
--- a/pypy/jit/metainterp/test/test_float.py
+++ b/pypy/jit/metainterp/test/test_float.py
@@ -1,5 +1,5 @@
 import math
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 
 
 class FloatTests:

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
@@ -382,7 +382,7 @@
         send_bridge_to_backend(metainterp.staticdata, self, inputargs,
                                new_loop.operations, new_loop.token)
 
-    def copy_all_attrbutes_into(self, res):
+    def copy_all_attributes_into(self, res):
         # XXX a bit ugly to have to list them all here
         res.rd_snapshot = self.rd_snapshot
         res.rd_frame_info_list = self.rd_frame_info_list
@@ -393,13 +393,13 @@
 
     def _clone_if_mutable(self):
         res = ResumeGuardDescr()
-        self.copy_all_attrbutes_into(res)
+        self.copy_all_attributes_into(res)
         return res
 
 class ResumeAtPositionDescr(ResumeGuardDescr):
     def _clone_if_mutable(self):
         res = ResumeAtPositionDescr()
-        self.copy_all_attrbutes_into(res)
+        self.copy_all_attributes_into(res)
         return res
 
 class ResumeGuardForcedDescr(ResumeGuardDescr):
@@ -473,7 +473,7 @@
     def _clone_if_mutable(self):
         res = ResumeGuardForcedDescr(self.metainterp_sd,
                                      self.jitdriver_sd)
-        self.copy_all_attrbutes_into(res)
+        self.copy_all_attributes_into(res)
         return res
 
 

diff --git a/pypy/module/cpyext/test/test_arraymodule.py b/pypy/module/cpyext/test/test_arraymodule.py
--- a/pypy/module/cpyext/test/test_arraymodule.py
+++ b/pypy/module/cpyext/test/test_arraymodule.py
@@ -42,3 +42,13 @@
         assert arr[1:].tolist() == [2,3,4]
         assert arr[:2].tolist() == [1,2]
         assert arr[1:3].tolist() == [2,3]
+
+    def test_buffer(self):
+        module = self.import_module(name='array')
+        arr = module.array('i', [1,2,3,4])
+        # XXX big-endian
+        assert str(buffer(arr)) == ('\x01\0\0\0'
+                                    '\x02\0\0\0'
+                                    '\x03\0\0\0'
+                                    '\x04\0\0\0')
+

diff --git a/pypy/rpython/lltypesystem/rdict.py b/pypy/rpython/lltypesystem/rdict.py
--- a/pypy/rpython/lltypesystem/rdict.py
+++ b/pypy/rpython/lltypesystem/rdict.py
@@ -4,13 +4,16 @@
 from pypy.rpython.rdict import AbstractDictRepr, AbstractDictIteratorRepr,\
      rtype_newdict
 from pypy.rpython.lltypesystem import lltype, llmemory
-from pypy.rlib.rarithmetic import r_uint, intmask
+from pypy.rlib.rarithmetic import r_uint, intmask, LONG_BIT
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rlib.objectmodel import hlinvoke
 from pypy.rpython import robject
-from pypy.rlib import objectmodel
+from pypy.rlib import objectmodel, jit
 from pypy.rpython import rmodel
 
+HIGHEST_BIT = intmask(1 << (LONG_BIT - 1))
+MASK = intmask(HIGHEST_BIT - 1)
+
 # ____________________________________________________________
 #
 #  generic implementation of RPython dictionary, with parametric DICTKEY and
@@ -405,6 +408,10 @@
     ENTRIES = lltype.typeOf(entries).TO
     return ENTRIES.fasthashfn(entries[i].key)
 
+ at jit.dont_look_inside
+def ll_get_value(d, i):
+    return d.entries[i].value
+
 def ll_keyhash_custom(d, key):
     DICT = lltype.typeOf(d).TO
     return hlinvoke(DICT.r_rdict_hashfn, d.fnkeyhash, key)
@@ -422,18 +429,21 @@
 
 def ll_dict_getitem(d, key):
     i = ll_dict_lookup(d, key, d.keyhash(key))
-    entries = d.entries
-    if entries.valid(i):
-        return entries[i].value 
-    else: 
-        raise KeyError 
-ll_dict_getitem.oopspec = 'dict.getitem(d, key)'
+    if not i & HIGHEST_BIT:
+        return ll_get_value(d, i)
+    else:
+        raise KeyError
 
 def ll_dict_setitem(d, key, value):
     hash = d.keyhash(key)
     i = ll_dict_lookup(d, key, hash)
+    return _ll_dict_setitem_lookup_done(d, key, value, hash, i)
+
+ at jit.dont_look_inside
+def _ll_dict_setitem_lookup_done(d, key, value, hash, i):
+    valid = (i & HIGHEST_BIT) == 0
+    i = i & MASK
     everused = d.entries.everused(i)
-    valid    = d.entries.valid(i)
     # set up the new entry
     ENTRY = lltype.typeOf(d.entries).TO.OF
     entry = d.entries[i]
@@ -449,7 +459,6 @@
         d.num_pristine_entries -= 1
         if d.num_pristine_entries <= len(d.entries) / 3:
             ll_dict_resize(d)
-ll_dict_setitem.oopspec = 'dict.setitem(d, key, value)'
 
 def ll_dict_insertclean(d, key, value, hash):
     # Internal routine used by ll_dict_resize() to insert an item which is
@@ -470,7 +479,7 @@
 
 def ll_dict_delitem(d, key):
     i = ll_dict_lookup(d, key, d.keyhash(key))
-    if not d.entries.valid(i):
+    if i & HIGHEST_BIT:
         raise KeyError
     _ll_dict_del(d, i)
 ll_dict_delitem.oopspec = 'dict.delitem(d, key)'
@@ -542,7 +551,7 @@
     elif entries.everused(i):
         freeslot = i
     else:
-        return i    # pristine entry -- lookup failed
+        return i | HIGHEST_BIT # pristine entry -- lookup failed
 
     # In the loop, a deleted entry (everused and not valid) is by far
     # (factor of 100s) the least likely outcome, so test for that last.
@@ -557,7 +566,7 @@
         if not entries.everused(i):
             if freeslot == -1:
                 freeslot = i
-            return freeslot
+            return freeslot | HIGHEST_BIT
         elif entries.valid(i):
             checkingkey = entries[i].key
             if direct_compare and checkingkey == key:
@@ -711,22 +720,19 @@
 
 def ll_get(dict, key, default):
     i = ll_dict_lookup(dict, key, dict.keyhash(key))
-    entries = dict.entries
-    if entries.valid(i):
-        return entries[i].value
-    else: 
+    if not i & HIGHEST_BIT:
+        return ll_get_value(dict, i)
+    else:
         return default
-ll_get.oopspec = 'dict.get(dict, key, default)'
 
 def ll_setdefault(dict, key, default):
-    i = ll_dict_lookup(dict, key, dict.keyhash(key))
-    entries = dict.entries
-    if entries.valid(i):
-        return entries[i].value
+    hash = dict.keyhash(key)
+    i = ll_dict_lookup(dict, key, hash)
+    if not i & HIGHEST_BIT:
+        return ll_get_value(dict, i)
     else:
-        ll_dict_setitem(dict, key, default)
+        _ll_dict_setitem_lookup_done(dict, key, default, hash, i)
         return default
-ll_setdefault.oopspec = 'dict.setdefault(dict, key, default)'
 
 def ll_copy(dict):
     DICT = lltype.typeOf(dict).TO
@@ -768,7 +774,10 @@
     while i < d2len:
         if entries.valid(i):
             entry = entries[i]
-            ll_dict_setitem(dic1, entry.key, entry.value)
+            hash = entries.hash(i)
+            key = entry.key
+            j = ll_dict_lookup(dic1, key, hash)
+            _ll_dict_setitem_lookup_done(dic1, key, entry.value, hash, j)
         i += 1
 ll_update.oopspec = 'dict.update(dic1, dic2)'
 
@@ -833,8 +842,7 @@
 
 def ll_contains(d, key):
     i = ll_dict_lookup(d, key, d.keyhash(key))
-    return d.entries.valid(i)
-ll_contains.oopspec = 'dict.contains(d, key)'
+    return not i & HIGHEST_BIT
 
 POPITEMINDEX = lltype.Struct('PopItemIndex', ('nextindex', lltype.Signed))
 global_popitem_index = lltype.malloc(POPITEMINDEX, zero=True, immortal=True)

diff --git a/pypy/rpython/lltypesystem/module/test/test_ll_math.py b/pypy/rpython/lltypesystem/module/test/test_ll_math.py
--- a/pypy/rpython/lltypesystem/module/test/test_ll_math.py
+++ b/pypy/rpython/lltypesystem/module/test/test_ll_math.py
@@ -11,6 +11,7 @@
         nan = inf / inf
         assert not ll_math.ll_math_isinf(0)
         assert ll_math.ll_math_isinf(inf)
+        assert ll_math.ll_math_isinf(-inf)
         assert not ll_math.ll_math_isinf(nan)
 
     def test_isnan(self):

diff --git a/pypy/module/cpyext/stringobject.py b/pypy/module/cpyext/stringobject.py
--- a/pypy/module/cpyext/stringobject.py
+++ b/pypy/module/cpyext/stringobject.py
@@ -15,7 +15,7 @@
 ## The problem
 ## -----------
 ##
-## PyString_AsString() must returns a (non-movable) pointer to the underlying
+## PyString_AsString() must return a (non-movable) pointer to the underlying
 ## buffer, whereas pypy strings are movable.  C code may temporarily store
 ## this address and use it, as long as it owns a reference to the PyObject.
 ## There is no "release" function to specify that the pointer is not needed

diff --git a/pypy/translator/c/src/ll_math.h b/pypy/translator/c/src/ll_math.h
--- a/pypy/translator/c/src/ll_math.h
+++ b/pypy/translator/c/src/ll_math.h
@@ -1,9 +1,6 @@
 /* Definitions of some C99 math library functions, for those platforms
    that don't implement these functions already. */
 
-int _pypy_math_isinf(double x);
-int _pypy_math_isnan(double x);
-
 double _pypy_math_acosh(double x);
 double _pypy_math_asinh(double x);
 double _pypy_math_atanh(double x);

diff --git a/pypy/rpython/ootypesystem/rdict.py b/pypy/rpython/ootypesystem/rdict.py
--- a/pypy/rpython/ootypesystem/rdict.py
+++ b/pypy/rpython/ootypesystem/rdict.py
@@ -153,6 +153,13 @@
         hop.exception_cannot_occur()
         return self.send_message(hop, 'll_clear')
 
+    def rtype_method_popitem(self, hop):
+        v_dict, = hop.inputargs(self)
+        r_tuple = hop.r_result
+        cTUPLE = hop.inputconst(ootype.Void, r_tuple.lowleveltype)
+        hop.exception_is_here()
+        return hop.gendirectcall(ll_popitem, cTUPLE, v_dict)
+
     def __get_func(self, interp, r_func, fn, TYPE):
         if isinstance(r_func, MethodOfFrozenPBCRepr):
             obj = r_func.r_im_self.convert_const(fn.im_self)
@@ -353,6 +360,16 @@
 ll_dict_values = _make_ll_keys_values_items('values')
 ll_dict_items  = _make_ll_keys_values_items('items')
 
+def ll_popitem(ELEM, d):
+    it = d.ll_get_items_iterator()
+    if it.ll_go_next():
+        res = ootype.new(ELEM)
+        key = res.item0 = it.ll_current_key()
+        res.item1 = it.ll_current_value()
+        d.ll_remove(key)
+        return res
+    raise KeyError
+
 # ____________________________________________________________
 #
 #  Iteration.

diff --git a/pypy/translator/cli/opcodes.py b/pypy/translator/cli/opcodes.py
--- a/pypy/translator/cli/opcodes.py
+++ b/pypy/translator/cli/opcodes.py
@@ -71,6 +71,8 @@
     'hint':                     [PushArg(0), StoreResult],
     'direct_call':              [Call],
     'indirect_call':            [IndirectCall],
+    'int_between':              [PushAllArgs, 'call bool [pypylib]pypy.runtime.Utils::IntBetween(int32, int32, int32)'],
+
 
     'cast_ptr_to_weakadr':      [PushAllArgs, 'newobj instance void class %s::.ctor(object)' % WEAKREF],
     'gc__collect':              'call void class [mscorlib]System.GC::Collect()',
@@ -147,7 +149,10 @@
     'cast_float_to_uint':       'conv.u4',
     'cast_longlong_to_float':   'conv.r8',
     'cast_float_to_longlong':   'conv.i8',
+    'cast_ulonglong_to_float':  'conv.r8',
+    'cast_float_to_ulonglong':  'conv.u8',
     'cast_primitive':           [PushAllArgs, CastPrimitive],
+    'force_cast':               [PushAllArgs, CastPrimitive],
     'truncate_longlong_to_int': 'conv.i4',
     }
 
@@ -266,6 +271,8 @@
     'ullong_ge':                _not('clt.un'),
     'ullong_lshift':            [PushAllArgs, 'conv.u4', 'shl'],
     'ullong_rshift':            [PushAllArgs, 'conv.i4', 'shr'],
+    'ullong_and':               'and',
+    'ullong_or':                'or',
 
     'oois':                     'ceq',
     'ooisnot':                  _not('ceq'),

diff --git a/pypy/module/cpyext/test/test_typeobject.py b/pypy/module/cpyext/test/test_typeobject.py
--- a/pypy/module/cpyext/test/test_typeobject.py
+++ b/pypy/module/cpyext/test/test_typeobject.py
@@ -201,6 +201,23 @@
         assert cmpr == 3
         assert cmpr != 42
 
+    def test_richcompare(self):
+        module = self.import_module("comparisons")
+        cmpr = module.CmpType()
+
+        # should not crash
+        cmpr < 4
+        cmpr <= 4
+        cmpr > 4
+        cmpr >= 4
+
+        assert cmpr.__le__(4) is NotImplemented
+
+    def test_tpcompare(self):
+        module = self.import_module("comparisons")
+        cmpr = module.OldCmpType()
+        assert cmpr < cmpr
+
     def test_hash(self):
         module = self.import_module("comparisons")
         cmpr = module.CmpType()
@@ -245,6 +262,11 @@
         obj = foo.new()
         assert module.read_tp_dict(obj) == foo.fooType.copy
 
+    def test_custom_allocation(self):
+        foo = self.import_module("foo")
+        obj = foo.newCustom()
+        assert type(obj) is foo.Custom
+        assert type(foo.Custom) is foo.MetaType
 
 class TestTypes(BaseApiTest):
     def test_type_attributes(self, space, api):

diff --git a/pypy/module/cpyext/test/test_pystate.py b/pypy/module/cpyext/test/test_pystate.py
--- a/pypy/module/cpyext/test/test_pystate.py
+++ b/pypy/module/cpyext/test/test_pystate.py
@@ -29,20 +29,14 @@
         state = api.PyInterpreterState_Head()
         assert nullptr(PyInterpreterState.TO) == api.PyInterpreterState_Next(state)
 
-def clear_threadstate(space):
-    # XXX: this should collect the ThreadState memory
-    del space.getexecutioncontext().cpyext_threadstate
-
 class TestThreadState(BaseApiTest):
     def test_thread_state_get(self, space, api):
         ts = api.PyThreadState_Get()
         assert ts != nullptr(PyThreadState.TO)
-        clear_threadstate(space)
 
     def test_thread_state_interp(self, space, api):
         ts = api.PyThreadState_Get()
         assert ts.c_interp == api.PyInterpreterState_Head()
-        clear_threadstate(space)
 
     def test_basic_threadstate_dance(self, space, api):
         # Let extension modules call these functions,
@@ -54,5 +48,3 @@
 
         api.PyEval_AcquireThread(tstate)
         api.PyEval_ReleaseThread(tstate)
-
-        clear_threadstate(space)

diff --git a/pypy/interpreter/eval.py b/pypy/interpreter/eval.py
--- a/pypy/interpreter/eval.py
+++ b/pypy/interpreter/eval.py
@@ -56,13 +56,10 @@
     """A frame is an environment supporting the execution of a code object.
     Abstract base class."""
 
-    def __init__(self, space, w_globals=None, numlocals=-1):
+    def __init__(self, space, w_globals=None):
         self.space      = space
         self.w_globals  = w_globals  # wrapped dict of globals
         self.w_locals   = None       # wrapped dict of locals
-        if numlocals < 0:  # compute the minimal size based on arguments
-            numlocals = len(self.getcode().getvarnames())
-        self.numlocals = numlocals
 
     def run(self):
         "Abstract method to override. Runs the frame"
@@ -96,6 +93,10 @@
         where the order is according to self.getcode().signature()."""
         raise TypeError, "abstract"
 
+    def getfastscopelength(self):
+        "Abstract. Get the expected number of locals."
+        raise TypeError, "abstract"
+
     def fast2locals(self):
         # Copy values from self.fastlocals_w to self.w_locals
         if self.w_locals is None:
@@ -113,10 +114,11 @@
         # Copy values from self.w_locals to self.fastlocals_w
         assert self.w_locals is not None
         varnames = self.getcode().getvarnames()
+        numlocals = self.getfastscopelength()
 
-        new_fastlocals_w = [None]*self.numlocals
-        
-        for i in range(min(len(varnames), self.numlocals)):
+        new_fastlocals_w = [None] * numlocals
+
+        for i in range(min(len(varnames), numlocals)):
             w_name = self.space.wrap(varnames[i])
             try:
                 w_value = self.space.getitem(self.w_locals, w_name)

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
@@ -399,12 +399,7 @@
         return ll_rdict.ll_newdict(DICT)
     _ll_0_newdict.need_result_type = True
 
-    _ll_2_dict_getitem = ll_rdict.ll_dict_getitem
-    _ll_3_dict_setitem = ll_rdict.ll_dict_setitem
     _ll_2_dict_delitem = ll_rdict.ll_dict_delitem
-    _ll_3_dict_setdefault = ll_rdict.ll_setdefault
-    _ll_2_dict_contains = ll_rdict.ll_contains
-    _ll_3_dict_get = ll_rdict.ll_get
     _ll_1_dict_copy = ll_rdict.ll_copy
     _ll_1_dict_clear = ll_rdict.ll_clear
     _ll_2_dict_update = ll_rdict.ll_update

diff --git a/pypy/rlib/_jit_vref.py b/pypy/rlib/_jit_vref.py
--- a/pypy/rlib/_jit_vref.py
+++ b/pypy/rlib/_jit_vref.py
@@ -8,6 +8,8 @@
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.error import TyperError
 
+from pypy.rpython.ootypesystem import ootype
+
 
 class SomeVRef(annmodel.SomeObject):
 
@@ -24,7 +26,10 @@
         return self.s_instance
 
     def rtyper_makerepr(self, rtyper):
-        return vrefrepr
+        if rtyper.type_system.name == 'lltypesystem':
+            return vrefrepr
+        elif rtyper.type_system.name == 'ootypesystem':
+            return oovrefrepr
 
     def rtyper_makekey(self):
         return self.__class__,
@@ -54,4 +59,20 @@
                              " prebuilt virtual_ref")
         return lltype.nullptr(OBJECTPTR.TO)
 
+from pypy.rpython.ootypesystem.rclass import OBJECT
+
+class OOVRefRepr(VRefRepr):
+    lowleveltype = OBJECT
+    def rtype_simple_call(self, hop):
+        [v] = hop.inputargs(self)
+        v = hop.genop('jit_force_virtual', [v], resulttype = OBJECT)
+        return hop.genop('oodowncast', [v], resulttype = hop.r_result)
+    
+    def convert_const(self, value):
+        if value() is not None:
+            raise TypeError("only supports virtual_ref_None as a"
+                            " prebuilt virtual_ref")
+        return ootype.ROOT._null
+
 vrefrepr = VRefRepr()
+oovrefrepr = OOVRefRepr()

diff --git a/pypy/translator/cli/test/test_class.py b/pypy/translator/cli/test/test_class.py
--- a/pypy/translator/cli/test/test_class.py
+++ b/pypy/translator/cli/test/test_class.py
@@ -1,11 +1,8 @@
 import py
 from pypy.translator.cli.test.runtest import CliTest
-from pypy.translator.oosupport.test_template.class_ import BaseTestClass, BaseTestSpecialcase
+from pypy.translator.oosupport.test_template.class_ import BaseTestClass
 
 # ====> ../../oosupport/test_template/class_.py
 
 class TestCliClass(CliTest, BaseTestClass):    
     pass
-
-class TestCliSpecialCase(CliTest, BaseTestSpecialcase):
-    pass

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
@@ -1,5 +1,5 @@
 import py, sys
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.rlib.jit import JitDriver, dont_look_inside
 from pypy.rlib.rarithmetic import ovfcheck, LONG_BIT, intmask
 from pypy.jit.codewriter.policy import StopAtXPolicy

diff --git a/pypy/jit/backend/x86/arch.py b/pypy/jit/backend/x86/arch.py
--- a/pypy/jit/backend/x86/arch.py
+++ b/pypy/jit/backend/x86/arch.py
@@ -1,17 +1,29 @@
 # Constants that depend on whether we are on 32-bit or 64-bit
 
+# The frame size gives the standard fixed part at the start of
+# every assembler frame: the saved value of some registers,
+# one word for the force_index, and some extra space used only
+# during a malloc that needs to go via its slow path.
+
 import sys
 if sys.maxint == (2**31 - 1):
     WORD = 4
-    # ebp + ebx + esi + edi + force_index = 5 words
-    FRAME_FIXED_SIZE = 5
+    # ebp + ebx + esi + edi + 4 extra words + force_index = 9 words
+    FRAME_FIXED_SIZE = 9
+    FORCE_INDEX_OFS = -8*WORD
+    MY_COPY_OF_REGS = -7*WORD
     IS_X86_32 = True
     IS_X86_64 = False
 else:
     WORD = 8
-    # rbp + rbx + r12 + r13 + r14 + r15 + force_index = 7 words
-    FRAME_FIXED_SIZE = 7
+    # rbp + rbx + r12 + r13 + r14 + r15 + 11 extra words + force_index = 18
+    FRAME_FIXED_SIZE = 18
+    FORCE_INDEX_OFS = -17*WORD
+    MY_COPY_OF_REGS = -16*WORD
     IS_X86_32 = False
     IS_X86_64 = True
 
-FORCE_INDEX_OFS = -(FRAME_FIXED_SIZE-1)*WORD
+# The extra space has room for almost all registers, apart from eax and edx
+# which are used in the malloc itself.  They are:
+#   ecx, ebx, esi, edi               [32 and 64 bits]
+#   r8, r9, r10, r12, r13, r14, r15    [64 bits only]

diff --git a/pypy/config/translationoption.py b/pypy/config/translationoption.py
--- a/pypy/config/translationoption.py
+++ b/pypy/config/translationoption.py
@@ -350,7 +350,11 @@
     }
 
 def final_check_config(config):
-    pass
+    # XXX: this should be a real config option, but it is hard to refactor it;
+    # instead, we "just" patch it from here
+    from pypy.rlib import rfloat
+    if config.translation.type_system == 'ootype':
+        rfloat.USE_SHORT_FLOAT_REPR = False
 
 def set_opt_level(config, level):
     """Apply optimization suggestions on the 'config'.

diff --git a/pypy/module/itertools/interp_itertools.py b/pypy/module/itertools/interp_itertools.py
--- a/pypy/module/itertools/interp_itertools.py
+++ b/pypy/module/itertools/interp_itertools.py
@@ -486,6 +486,7 @@
 
 class W_IMap(Wrappable):
     _error_name = "imap"
+    _immutable_fields_ = ["w_fun", "iterators_w"]
 
     def __init__(self, space, w_fun, args_w):
         self.space = space

diff --git a/pypy/rlib/rfloat.py b/pypy/rlib/rfloat.py
--- a/pypy/rlib/rfloat.py
+++ b/pypy/rlib/rfloat.py
@@ -4,6 +4,8 @@
 from pypy.rpython.tool import rffi_platform
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.rlib import objectmodel
+from pypy.rpython.extfunc import register_external
+from pypy.annotation.model import SomeString
 
 USE_SHORT_FLOAT_REPR = True # XXX make it a translation option?
 
@@ -24,16 +26,28 @@
 globals().update(rffi_platform.configure(CConfig))
 
 def rstring_to_float(s):
+    return rstring_to_float_impl(s)
+
+def rstring_to_float_impl(s):
     if USE_SHORT_FLOAT_REPR:
         from pypy.rlib.rdtoa import strtod
         return strtod(s)
-
     sign, before_point, after_point, exponent = break_up_float(s)
-
     if not before_point and not after_point:
         raise ValueError
+    return parts_to_float(sign, before_point, after_point, exponent)
 
-    return parts_to_float(sign, before_point, after_point, exponent)
+def oo_rstring_to_float(s):
+    from pypy.rpython.annlowlevel import oostr
+    from pypy.rpython.ootypesystem import ootype
+    lls = oostr(s)
+    return ootype.ooparse_float(lls)
+
+register_external(rstring_to_float, [SomeString(can_be_None=False)], float,
+                  llimpl=rstring_to_float_impl,
+                  ooimpl=oo_rstring_to_float,
+                  sandboxsafe=True)
+
 
 # float as string  -> sign, beforept, afterpt, exponent
 def break_up_float(s):
@@ -153,128 +167,132 @@
     result = formatd(value, tp, precision, flags)
     return result, special
 
-if USE_SHORT_FLOAT_REPR:
-    def round_double(value, ndigits):
-        # The basic idea is very simple: convert and round the double to
-        # a decimal string using _Py_dg_dtoa, then convert that decimal
-        # string back to a double with _Py_dg_strtod.  There's one minor
-        # difficulty: Python 2.x expects round to do
-        # round-half-away-from-zero, while _Py_dg_dtoa does
-        # round-half-to-even.  So we need some way to detect and correct
-        # the halfway cases.
+def round_double(value, ndigits):
+    if USE_SHORT_FLOAT_REPR:
+        return round_double_short_repr(value, ndigits)
+    else:
+        return round_double_fallback_repr(value, ndigits)
 
-        # a halfway value has the form k * 0.5 * 10**-ndigits for some
-        # odd integer k.  Or in other words, a rational number x is
-        # exactly halfway between two multiples of 10**-ndigits if its
-        # 2-valuation is exactly -ndigits-1 and its 5-valuation is at
-        # least -ndigits.  For ndigits >= 0 the latter condition is
-        # automatically satisfied for a binary float x, since any such
-        # float has nonnegative 5-valuation.  For 0 > ndigits >= -22, x
-        # needs to be an integral multiple of 5**-ndigits; we can check
-        # this using fmod.  For -22 > ndigits, there are no halfway
-        # cases: 5**23 takes 54 bits to represent exactly, so any odd
-        # multiple of 0.5 * 10**n for n >= 23 takes at least 54 bits of
-        # precision to represent exactly.
+def round_double_short_repr(value, ndigits):
+    # The basic idea is very simple: convert and round the double to
+    # a decimal string using _Py_dg_dtoa, then convert that decimal
+    # string back to a double with _Py_dg_strtod.  There's one minor
+    # difficulty: Python 2.x expects round to do
+    # round-half-away-from-zero, while _Py_dg_dtoa does
+    # round-half-to-even.  So we need some way to detect and correct
+    # the halfway cases.
 
-        sign = copysign(1.0, value)
-        value = abs(value)
+    # a halfway value has the form k * 0.5 * 10**-ndigits for some
+    # odd integer k.  Or in other words, a rational number x is
+    # exactly halfway between two multiples of 10**-ndigits if its
+    # 2-valuation is exactly -ndigits-1 and its 5-valuation is at
+    # least -ndigits.  For ndigits >= 0 the latter condition is
+    # automatically satisfied for a binary float x, since any such
+    # float has nonnegative 5-valuation.  For 0 > ndigits >= -22, x
+    # needs to be an integral multiple of 5**-ndigits; we can check
+    # this using fmod.  For -22 > ndigits, there are no halfway
+    # cases: 5**23 takes 54 bits to represent exactly, so any odd
+    # multiple of 0.5 * 10**n for n >= 23 takes at least 54 bits of
+    # precision to represent exactly.
 
-        # find 2-valuation value
-        m, expo = math.frexp(value)
-        while m != math.floor(m):
-            m *= 2.0
-            expo -= 1
+    sign = copysign(1.0, value)
+    value = abs(value)
 
-        # determine whether this is a halfway case.
-        halfway_case = 0
-        if expo == -ndigits - 1:
-            if ndigits >= 0:
+    # find 2-valuation value
+    m, expo = math.frexp(value)
+    while m != math.floor(m):
+        m *= 2.0
+        expo -= 1
+
+    # determine whether this is a halfway case.
+    halfway_case = 0
+    if expo == -ndigits - 1:
+        if ndigits >= 0:
+            halfway_case = 1
+        elif ndigits >= -22:
+            # 22 is the largest k such that 5**k is exactly
+            # representable as a double
+            five_pow = 1.0
+            for i in range(-ndigits):
+                five_pow *= 5.0
+            if math.fmod(value, five_pow) == 0.0:
                 halfway_case = 1
-            elif ndigits >= -22:
-                # 22 is the largest k such that 5**k is exactly
-                # representable as a double
-                five_pow = 1.0
-                for i in range(-ndigits):
-                    five_pow *= 5.0
-                if math.fmod(value, five_pow) == 0.0:
-                    halfway_case = 1
 
-        # round to a decimal string; use an extra place for halfway case
-        strvalue = formatd(value, 'f', ndigits + halfway_case)
+    # round to a decimal string; use an extra place for halfway case
+    strvalue = formatd(value, 'f', ndigits + halfway_case)
 
-        if halfway_case:
-            buf = [c for c in strvalue]
-            if ndigits >= 0:
-                endpos = len(buf) - 1
-            else:
-                endpos = len(buf) + ndigits
-            # Sanity checks: there should be exactly ndigits+1 places
-            # following the decimal point, and the last digit in the
-            # buffer should be a '5'
-            if not objectmodel.we_are_translated():
-                assert buf[endpos] == '5'
-                if '.' in buf:
-                    assert endpos == len(buf) - 1
-                    assert buf.index('.') == len(buf) - ndigits - 2
+    if halfway_case:
+        buf = [c for c in strvalue]
+        if ndigits >= 0:
+            endpos = len(buf) - 1
+        else:
+            endpos = len(buf) + ndigits
+        # Sanity checks: there should be exactly ndigits+1 places
+        # following the decimal point, and the last digit in the
+        # buffer should be a '5'
+        if not objectmodel.we_are_translated():
+            assert buf[endpos] == '5'
+            if '.' in buf:
+                assert endpos == len(buf) - 1
+                assert buf.index('.') == len(buf) - ndigits - 2
 
-            # increment and shift right at the same time
-            i = endpos - 1
-            carry = 1
-            while i >= 0:
+        # increment and shift right at the same time
+        i = endpos - 1
+        carry = 1
+        while i >= 0:
+            digit = ord(buf[i])
+            if digit == ord('.'):
+                buf[i+1] = chr(digit)
+                i -= 1
                 digit = ord(buf[i])
-                if digit == ord('.'):
-                    buf[i+1] = chr(digit)
-                    i -= 1
-                    digit = ord(buf[i])
 
-                carry += digit - ord('0')
-                buf[i+1] = chr(carry % 10 + ord('0'))
-                carry /= 10
-                i -= 1
-            buf[0] = chr(carry + ord('0'))
-            if ndigits < 0:
-                buf.append('0')
+            carry += digit - ord('0')
+            buf[i+1] = chr(carry % 10 + ord('0'))
+            carry /= 10
+            i -= 1
+        buf[0] = chr(carry + ord('0'))
+        if ndigits < 0:
+            buf.append('0')
 
-            strvalue = ''.join(buf)
+        strvalue = ''.join(buf)
 
-        return sign * rstring_to_float(strvalue)
+    return sign * rstring_to_float(strvalue)
 
-else:
-    # fallback version, to be used when correctly rounded
-    # binary<->decimal conversions aren't available
-    def round_double(value, ndigits):
-        if ndigits >= 0:
-            if ndigits > 22:
-                # pow1 and pow2 are each safe from overflow, but
-                # pow1*pow2 ~= pow(10.0, ndigits) might overflow
-                pow1 = math.pow(10.0, ndigits - 22)
-                pow2 = 1e22
-            else:
-                pow1 = math.pow(10.0, ndigits)
-                pow2 = 1.0
+# fallback version, to be used when correctly rounded
+# binary<->decimal conversions aren't available
+def round_double_fallback_repr(value, ndigits):
+    if ndigits >= 0:
+        if ndigits > 22:
+            # pow1 and pow2 are each safe from overflow, but
+            # pow1*pow2 ~= pow(10.0, ndigits) might overflow
+            pow1 = math.pow(10.0, ndigits - 22)
+            pow2 = 1e22
+        else:
+            pow1 = math.pow(10.0, ndigits)
+            pow2 = 1.0
 
-            y = (value * pow1) * pow2
-            # if y overflows, then rounded value is exactly x
-            if isinf(y):
-                return value
+        y = (value * pow1) * pow2
+        # if y overflows, then rounded value is exactly x
+        if isinf(y):
+            return value
 
-        else:
-            pow1 = math.pow(10.0, -ndigits);
-            pow2 = 1.0 # unused; for translation
-            y = value / pow1
+    else:
+        pow1 = math.pow(10.0, -ndigits);
+        pow2 = 1.0 # unused; for translation
+        y = value / pow1
 
-        if y >= 0.0:
-            z = math.floor(y + 0.5)
-        else:
-            z = math.ceil(y - 0.5)
-        if math.fabs(y-z) == 1.0:   # obscure case, see the test
-            z = y
+    if y >= 0.0:
+        z = math.floor(y + 0.5)
+    else:
+        z = math.ceil(y - 0.5)
+    if math.fabs(y-z) == 1.0:   # obscure case, see the test
+        z = y
 
-        if ndigits >= 0:
-            z = (z / pow2) / pow1
-        else:
-            z *= pow1
-        return z
+    if ndigits >= 0:
+        z = (z / pow2) / pow1
+    else:
+        z *= pow1
+    return z
 
 INFINITY = 1e200 * 1e200
 NAN = INFINITY / INFINITY

diff --git a/pypy/translator/cli/src/debug.cs b/pypy/translator/cli/src/debug.cs
--- a/pypy/translator/cli/src/debug.cs
+++ b/pypy/translator/cli/src/debug.cs
@@ -1,5 +1,6 @@
 using System;
 using System.IO;
+using System.Collections.Generic;
 using System.Diagnostics;
 
 // this code is modeled after translator/c/src/debug.h
@@ -21,7 +22,7 @@
         static int have_debug_prints = -1;
         static bool debug_ready = false;
         static bool debug_profile = false;
-        static string debug_prefix = null;
+        static string[] active_categories = null;
 
         public static void close_file()
         {
@@ -29,6 +30,14 @@
                 debug_file.Close();
         }
 
+        public static bool startswithoneof(string category, string[] active_categories)
+        {
+            foreach(string cat in active_categories)
+                if (category.StartsWith(cat))
+                    return true;
+            return false;
+        }
+
         public static bool HAVE_DEBUG_PRINTS()
         {
             if ((have_debug_prints & 1) != 0) {
@@ -48,7 +57,8 @@
             have_debug_prints <<= 1;
             if (!debug_profile) {
                 /* non-profiling version */
-                if (debug_prefix == null || !category.StartsWith(debug_prefix)) {
+                if (active_categories == null || 
+                    !startswithoneof(category, active_categories)) {
                     /* wrong section name, or no PYPYLOG at all, skip it */
                     return;
                 }
@@ -83,7 +93,8 @@
                 }
                 else {
                     /* PYPYLOG=prefix:filename --- conditional logging */
-                    debug_prefix = filename.Substring(0, colon);
+                    string debug_prefix = filename.Substring(0, colon);
+                    active_categories = debug_prefix.Split(',');
                     filename = filename.Substring(colon+1);
                 }
                 if (filename != "-")

diff --git a/pypy/objspace/std/test/test_dictmultiobject.py b/pypy/objspace/std/test/test_dictmultiobject.py
--- a/pypy/objspace/std/test/test_dictmultiobject.py
+++ b/pypy/objspace/std/test/test_dictmultiobject.py
@@ -1,3 +1,4 @@
+import sys
 from pypy.interpreter.error import OperationError
 from pypy.objspace.std.dictmultiobject import \
      W_DictMultiObject, setitem__DictMulti_ANY_ANY, getitem__DictMulti_ANY, \
@@ -151,6 +152,8 @@
 
 
 class AppTest_DictObject:
+    def setup_class(cls):
+        cls.w_on_pypy = cls.space.wrap("__pypy__" in sys.builtin_module_names)
 
     def test_equality(self):
         d = {1:2} 
@@ -259,7 +262,29 @@
         d[33] = 99
         assert d == dd
         assert x == 99
-    
+
+    def test_setdefault_fast(self):
+        class Key(object):
+            calls = 0
+            def __hash__(self):
+                self.calls += 1
+                return object.__hash__(self)
+
+        k = Key()
+        d = {}
+        d.setdefault(k, [])
+        if self.on_pypy:
+            assert k.calls == 1
+
+        d.setdefault(k, 1)
+        if self.on_pypy:
+            assert k.calls == 2
+
+        k = Key()
+        d.setdefault(k, 42)
+        if self.on_pypy:
+            assert k.calls == 1
+
     def test_update(self):
         d = {1:2, 3:4}
         dd = d.copy()
@@ -704,13 +729,20 @@
 
 
 class FakeString(str):
+    hash_count = 0
     def unwrap(self, space):
         self.unwrapped = True
         return str(self)
 
+    def __hash__(self):
+        self.hash_count += 1
+        return str.__hash__(self)
+
 # the minimal 'space' needed to use a W_DictMultiObject
 class FakeSpace:
+    hash_count = 0
     def hash_w(self, obj):
+        self.hash_count += 1
         return hash(obj)
     def unwrap(self, x):
         return x
@@ -726,6 +758,8 @@
         return []
     DictObjectCls = W_DictMultiObject
     def type(self, w_obj):
+        if isinstance(w_obj, FakeString):
+            return str
         return type(w_obj)
     w_str = str
     def str_w(self, string):
@@ -890,6 +924,19 @@
             impl.setitem(x, x)
         assert impl.r_dict_content is not None
 
+    def test_setdefault_fast(self):
+        on_pypy = "__pypy__" in sys.builtin_module_names
+        impl = self.impl
+        key = FakeString(self.string)
+        x = impl.setdefault(key, 1)
+        assert x == 1
+        if on_pypy:
+            assert key.hash_count == 1
+        x = impl.setdefault(key, 2)
+        assert x == 1
+        if on_pypy:
+            assert key.hash_count == 2
+
 class TestStrDictImplementation(BaseTestRDictImplementation):
     ImplementionClass = StrDictImplementation
 

diff --git a/pypy/module/cpyext/test/test_pyerrors.py b/pypy/module/cpyext/test/test_pyerrors.py
--- a/pypy/module/cpyext/test/test_pyerrors.py
+++ b/pypy/module/cpyext/test/test_pyerrors.py
@@ -96,6 +96,10 @@
         out, err = capfd.readouterr()
         assert "Exception ValueError: 'message' in 'location' ignored" == err.strip()
 
+    def test_ExceptionInstance_Class(self, space, api):
+        instance = space.call_function(space.w_ValueError)
+        assert api.PyExceptionInstance_Class(instance) is space.w_ValueError
+
 class AppTestFetch(AppTestCpythonExtensionBase):
     def setup_class(cls):
         AppTestCpythonExtensionBase.setup_class.im_func(cls)

diff --git a/pypy/rpython/rstr.py b/pypy/rpython/rstr.py
--- a/pypy/rpython/rstr.py
+++ b/pypy/rpython/rstr.py
@@ -221,14 +221,33 @@
 
     def rtype_method_split(self, hop):
         rstr = hop.args_r[0].repr
-        v_str, v_chr = hop.inputargs(rstr.repr, rstr.char_repr)
+        if hop.nb_args == 3:
+            v_str, v_chr, v_max = hop.inputargs(rstr.repr, rstr.char_repr, Signed)
+        else:
+            v_str, v_chr = hop.inputargs(rstr.repr, rstr.char_repr)
+            v_max = hop.inputconst(Signed, -1)
         try:
             list_type = hop.r_result.lowleveltype.TO
         except AttributeError:
             list_type = hop.r_result.lowleveltype
         cLIST = hop.inputconst(Void, list_type)
         hop.exception_cannot_occur()
-        return hop.gendirectcall(self.ll.ll_split_chr, cLIST, v_str, v_chr)
+        return hop.gendirectcall(self.ll.ll_split_chr, cLIST, v_str, v_chr, v_max)
+
+    def rtype_method_rsplit(self, hop):
+        rstr = hop.args_r[0].repr
+        if hop.nb_args == 3:
+            v_str, v_chr, v_max = hop.inputargs(rstr.repr, rstr.char_repr, Signed)
+        else:
+            v_str, v_chr = hop.inputargs(rstr.repr, rstr.char_repr)
+            v_max = hop.inputconst(Signed, -1)
+        try:
+            list_type = hop.r_result.lowleveltype.TO
+        except AttributeError:
+            list_type = hop.r_result.lowleveltype
+        cLIST = hop.inputconst(Void, list_type)
+        hop.exception_cannot_occur()
+        return hop.gendirectcall(self.ll.ll_rsplit_chr, cLIST, v_str, v_chr, v_max)
 
     def rtype_method_replace(self, hop):
         rstr = hop.args_r[0].repr

diff --git a/pypy/translator/backendopt/merge_if_blocks.py b/pypy/translator/backendopt/merge_if_blocks.py
--- a/pypy/translator/backendopt/merge_if_blocks.py
+++ b/pypy/translator/backendopt/merge_if_blocks.py
@@ -1,4 +1,4 @@
-from pypy.objspace.flow.model import Block, Constant, Variable, flatten
+from pypy.objspace.flow.model import Block, Constant, Variable
 from pypy.objspace.flow.model import checkgraph, mkentrymap
 from pypy.translator.backendopt.support import log
 
@@ -75,14 +75,19 @@
             # False link
             checkvar = [var for var in current.operations[-1].args
                            if isinstance(var, Variable)][0]
+            resvar = current.operations[-1].result
             case = [var for var in current.operations[-1].args
                        if isinstance(var, Constant)][0]
-            chain.append((current, case))
             checkvars.append(checkvar)
             falseexit = current.exits[0]
             assert not falseexit.exitcase
             trueexit = current.exits[1]
             targetblock = falseexit.target
+            # if the result of the check is also passed through the link, we
+            # cannot construct the chain
+            if resvar in falseexit.args or resvar in trueexit.args:
+                break
+            chain.append((current, case))
             if len(entrymap[targetblock]) != 1:
                 break
             if checkvar not in falseexit.args:

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
@@ -6,7 +6,7 @@
 from pypy.jit.codewriter import heaptracker
 from pypy.rlib.jit import JitDriver, hint, dont_look_inside
 from pypy.rlib.rarithmetic import intmask
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.rpython.rclass import FieldListAccessor
 from pypy.jit.metainterp.warmspot import get_stats, get_translator
 from pypy.jit.metainterp import history

diff --git a/pypy/jit/metainterp/test/test_optimizeopt.py b/pypy/jit/metainterp/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/test/test_optimizeopt.py
@@ -135,7 +135,7 @@
         return type(self) is type(other)      # xxx obscure
     def clone_if_mutable(self):
         res = Storage(self.metainterp_sd, self.original_greenkey)
-        self.copy_all_attrbutes_into(res)
+        self.copy_all_attributes_into(res)
         return res
 
 def _sortboxes(boxes):
@@ -816,6 +816,52 @@
         """
         self.optimize_loop(ops, expected, preamble)
 
+    def test_compare_with_itself(self):
+        ops = """
+        []
+        i0 = escape()
+        i1 = int_lt(i0, i0)
+        guard_false(i1) []
+        i2 = int_le(i0, i0)
+        guard_true(i2) []
+        i3 = int_eq(i0, i0)
+        guard_true(i3) []
+        i4 = int_ne(i0, i0)
+        guard_false(i4) []
+        i5 = int_gt(i0, i0)
+        guard_false(i5) []
+        i6 = int_ge(i0, i0)
+        guard_true(i6) []
+        jump()
+        """
+        expected = """
+        []
+        i0 = escape()
+        jump()
+        """
+        self.optimize_loop(ops, expected)
+
+    def test_compare_with_itself_uint(self):
+        py.test.skip("implement me")
+        ops = """
+        []
+        i0 = escape()
+        i7 = uint_lt(i0, i0)
+        guard_false(i7) []
+        i8 = uint_le(i0, i0)
+        guard_true(i8) []
+        i9 = uint_gt(i0, i0)
+        guard_false(i9) []
+        i10 = uint_ge(i0, i0)
+        guard_true(i10) []
+        jump()
+        """
+        expected = """
+        []
+        i0 = escape()
+        jump()
+        """
+        self.optimize_loop(ops, expected)
 
 
 
@@ -1791,7 +1837,7 @@
         """
         self.optimize_loop(ops, ops)
 
-    def test_duplicate_setfield_1(self):
+    def test_duplicate_setfield_0(self):
         ops = """
         [p1, i1, i2]
         setfield_gc(p1, i1, descr=valuedescr)
@@ -1800,8 +1846,27 @@
         """
         expected = """
         [p1, i1, i2]
+        jump(p1, i1, i2)
+        """
+        # in this case, all setfields are removed, because we can prove
+        # that in the loop it will always have the same value
+        self.optimize_loop(ops, expected)
+
+    def test_duplicate_setfield_1(self):
+        ops = """
+        [p1]
+        i1 = escape()
+        i2 = escape()
+        setfield_gc(p1, i1, descr=valuedescr)
         setfield_gc(p1, i2, descr=valuedescr)
-        jump(p1, i1, i2)
+        jump(p1)
+        """
+        expected = """
+        [p1]
+        i1 = escape()
+        i2 = escape()
+        setfield_gc(p1, i2, descr=valuedescr)
+        jump(p1)
         """
         self.optimize_loop(ops, expected)
 
@@ -1848,6 +1913,7 @@
         setfield_gc(p1, i4, descr=nextdescr)
         #
         setfield_gc(p1, i2, descr=valuedescr)
+        escape()
         jump(p1, i1, i2, p3)
         """
         preamble = """
@@ -1860,6 +1926,7 @@
         #
         setfield_gc(p1, i2, descr=valuedescr)
         setfield_gc(p1, i4, descr=nextdescr)
+        escape()
         jump(p1, i1, i2, p3, i3)
         """
         expected = """
@@ -1871,6 +1938,7 @@
         #
         setfield_gc(p1, i2, descr=valuedescr)
         setfield_gc(p1, i4, descr=nextdescr)
+        escape()
         jump(p1, i1, i2, p3, i3)
         """
         self.optimize_loop(ops, expected, preamble)
@@ -1943,6 +2011,7 @@
         guard_true(i3) []
         i4 = int_neg(i2)
         setfield_gc(p1, NULL, descr=nextdescr)
+        escape()
         jump(p1, i2, i4)
         """
         preamble = """
@@ -1950,12 +2019,14 @@
         guard_true(i3) [p1]
         i4 = int_neg(i2)
         setfield_gc(p1, NULL, descr=nextdescr)
+        escape()
         jump(p1, i2, i4)
         """
         expected = """
         [p1, i2, i4]
         guard_true(i4) [p1]
         setfield_gc(p1, NULL, descr=nextdescr)
+        escape()
         jump(p1, i2, 1)
         """
         self.optimize_loop(ops, expected, preamble)
@@ -1969,6 +2040,7 @@
         guard_true(i3) []
         i4 = int_neg(i2)
         setfield_gc(p1, NULL, descr=nextdescr)
+        escape()
         jump(p1, i2, i4)
         """
         preamble = """
@@ -1976,12 +2048,14 @@
         guard_true(i3) [i2, p1]
         i4 = int_neg(i2)
         setfield_gc(p1, NULL, descr=nextdescr)
+        escape()
         jump(p1, i2, i4)
         """
         expected = """
         [p1, i2, i4]
         guard_true(i4) [i2, p1]
         setfield_gc(p1, NULL, descr=nextdescr)
+        escape()
         jump(p1, i2, 1)
         """
         self.optimize_loop(ops, expected)
@@ -2027,15 +2101,34 @@
         guard_value(p1, ConstPtr(myptr)) []
         setfield_gc(p1, i1, descr=valuedescr)
         setfield_gc(ConstPtr(myptr), i2, descr=valuedescr)
+        escape()
         jump(p1, i1, i2)
         """
         expected = """
         [i1, i2]
         setfield_gc(ConstPtr(myptr), i2, descr=valuedescr)
+        escape()
         jump(i1, i2)
         """
         self.optimize_loop(ops, expected)
 
+    def test_dont_force_setfield_around_copystrcontent(self):
+        ops = """
+        [p0, i0, p1, i1, i2]
+        setfield_gc(p0, i1, descr=valuedescr)
+        copystrcontent(p0, i0, p1, i1, i2)
+        escape()
+        jump(p0, i0, p1, i1, i2)
+        """
+        expected = """
+        [p0, i0, p1, i1, i2]
+        copystrcontent(p0, i0, p1, i1, i2)
+        setfield_gc(p0, i1, descr=valuedescr)
+        escape()
+        jump(p0, i0, p1, i1, i2)
+        """
+        self.optimize_loop(ops, expected)
+
     def test_duplicate_getarrayitem_1(self):
         ops = """
         [p1]
@@ -2356,6 +2449,33 @@
         """
         self.optimize_loop(ops, expected, preamble)
 
+    def test_bug_5(self):
+        ops = """
+        [p0]
+        i0 = escape()
+        i2 = getfield_gc(p0, descr=valuedescr)
+        i4 = int_add(i2, 1)
+        setfield_gc(p0, i4, descr=valuedescr)
+        guard_true(i0) []
+        i6 = getfield_gc(p0, descr=valuedescr)
+        i8 = int_sub(i6, 1)
+        setfield_gc(p0, i8, descr=valuedescr)
+        escape()
+        jump(p0)
+        """
+        expected = """
+        [p0]
+        i0 = escape()
+        i2 = getfield_gc(p0, descr=valuedescr)
+        i4 = int_add(i2, 1)
+        setfield_gc(p0, i4, descr=valuedescr)
+        guard_true(i0) []
+        setfield_gc(p0, i2, descr=valuedescr)
+        escape()
+        jump(p0)
+        """
+        self.optimize_loop(ops, expected)
+
     def test_invalid_loop_1(self):
         ops = """
         [p1]
@@ -2637,7 +2757,7 @@
         """
         self.optimize_loop(ops, expected)
 
-    def test_fold_partially_constant_ops(self):
+    def test_fold_partially_constant_add_sub(self):
         ops = """
         [i0]
         i1 = int_sub(i0, 0)
@@ -2671,7 +2791,7 @@
         """
         self.optimize_loop(ops, expected)
 
-    def test_fold_partially_constant_ops_ovf(self):
+    def test_fold_partially_constant_add_sub_ovf(self):
         ops = """
         [i0]
         i1 = int_sub_ovf(i0, 0)
@@ -2708,6 +2828,21 @@
         """
         self.optimize_loop(ops, expected)
 
+    def test_fold_partially_constant_shift(self):
+        ops = """
+        [i0]
+        i1 = int_lshift(i0, 0)
+        i2 = int_rshift(i1, 0)
+        i3 = int_eq(i2, i0)
+        guard_true(i3) []
+        jump(i2)
+        """
+        expected = """
+        [i0]
+        jump(i0)
+        """
+        self.optimize_loop(ops, expected)
+
     # ----------
 
 class TestLLtype(OptimizeOptTest, LLtypeMixin):
@@ -2992,7 +3127,6 @@
         i0 = force_token()
         p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
         setfield_gc(p2, i0, descr=virtualtokendescr)
-        setfield_gc(p2, 5, descr=virtualrefindexdescr)
         escape(p2)
         setfield_gc(p2, p1, descr=virtualforceddescr)
         setfield_gc(p2, -3, descr=virtualtokendescr)
@@ -3025,7 +3159,6 @@
         #
         p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
         setfield_gc(p2, i3, descr=virtualtokendescr)
-        setfield_gc(p2, 3, descr=virtualrefindexdescr)
         setfield_gc(p0, p2, descr=nextdescr)
         #
         call_may_force(i1, descr=mayforcevirtdescr)
@@ -3065,7 +3198,6 @@
         #
         p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
         setfield_gc(p2, i3, descr=virtualtokendescr)
-        setfield_gc(p2, 2, descr=virtualrefindexdescr)
         setfield_gc(p0, p2, descr=nextdescr)
         #
         call_may_force(i1, descr=mayforcevirtdescr)
@@ -3103,6 +3235,7 @@
         guard_no_exception(descr=fdescr) [p2, p1]
         virtual_ref_finish(p2, p1)
         setfield_gc(p0, NULL, descr=refdescr)
+        escape()
         jump(p0, i1)
         """
         preamble = """
@@ -3111,6 +3244,7 @@
         call(i1, descr=nonwritedescr)
         guard_no_exception(descr=fdescr) [i3, i1, p0]
         setfield_gc(p0, NULL, descr=refdescr)
+        escape()
         jump(p0, i1)
         """
         expected = """
@@ -3119,6 +3253,7 @@
         call(i1, descr=nonwritedescr)
         guard_no_exception(descr=fdescr2) [i3, i1, p0]
         setfield_gc(p0, NULL, descr=refdescr)
+        escape()
         jump(p0, i1)
         """
         self.optimize_loop(ops, expected, preamble)
@@ -3129,7 +3264,7 @@
         #self.loop.inputargs[0].value = self.nodeobjvalue
         #self.check_expanded_fail_descr('''p2, p1
         #    p0.refdescr = p2
-        #    where p2 is a jit_virtual_ref_vtable, virtualtokendescr=i3, virtualrefindexdescr=2
+        #    where p2 is a jit_virtual_ref_vtable, virtualtokendescr=i3
         #    where p1 is a node_vtable, nextdescr=p1b
         #    where p1b is a node_vtable, valuedescr=i1
         #    ''', rop.GUARD_NO_EXCEPTION)
@@ -3150,7 +3285,6 @@
         i3 = force_token()
         p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
         setfield_gc(p2, i3, descr=virtualtokendescr)
-        setfield_gc(p2, 7, descr=virtualrefindexdescr)
         escape(p2)
         p1 = new_with_vtable(ConstClass(node_vtable))
         setfield_gc(p2, p1, descr=virtualforceddescr)
@@ -3176,7 +3310,6 @@
         i3 = force_token()
         p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
         setfield_gc(p2, i3, descr=virtualtokendescr)
-        setfield_gc(p2, 23, descr=virtualrefindexdescr)
         escape(p2)
         setfield_gc(p2, p1, descr=virtualforceddescr)
         setfield_gc(p2, -3, descr=virtualtokendescr)
@@ -4842,6 +4975,58 @@
         p2 = new_with_vtable(ConstClass(node_vtable))
         setfield_gc(p2, i1, descr=nextdescr)
         """
+        py.test.skip("no test here")
+
+    def test_immutable_not(self):
+        ops = """
+        []
+        p0 = new_with_vtable(ConstClass(intobj_noimmut_vtable))
+        setfield_gc(p0, 42, descr=noimmut_intval)
+        escape(p0)
+        jump()
+        """
+        self.optimize_loop(ops, ops)
+
+    def test_immutable_variable(self):
+        ops = """
+        [i0]
+        p0 = new_with_vtable(ConstClass(intobj_immut_vtable))
+        setfield_gc(p0, i0, descr=immut_intval)
+        escape(p0)
+        jump(i0)
+        """
+        self.optimize_loop(ops, ops)
+
+    def test_immutable_incomplete(self):
+        ops = """
+        []
+        p0 = new_with_vtable(ConstClass(intobj_immut_vtable))
+        escape(p0)
+        jump()
+        """
+        self.optimize_loop(ops, ops)
+
+    def test_immutable_constantfold(self):
+        ops = """
+        []
+        p0 = new_with_vtable(ConstClass(intobj_immut_vtable))
+        setfield_gc(p0, 1242, descr=immut_intval)
+        escape(p0)
+        jump()
+        """
+        from pypy.rpython.lltypesystem import lltype, llmemory
+        class IntObj1242(object):
+            _TYPE = llmemory.GCREF.TO
+            def __eq__(self, other):
+                return other.container.intval == 1242
+        self.namespace['intobj1242'] = lltype._ptr(llmemory.GCREF,
+                                                   IntObj1242())
+        expected = """
+        []
+        escape(ConstPtr(intobj1242))
+        jump()
+        """
+        self.optimize_loop(ops, expected)
 
     # ----------
     def optimize_strunicode_loop(self, ops, optops, preamble=None):

diff --git a/pypy/module/cpyext/eval.py b/pypy/module/cpyext/eval.py
--- a/pypy/module/cpyext/eval.py
+++ b/pypy/module/cpyext/eval.py
@@ -112,6 +112,7 @@
     try:
         while True:
             count = fread(buf, 1, BUF_SIZE, fp)
+            count = rffi.cast(lltype.Signed, count)
             source += rffi.charpsize2str(buf, count)
             if count < BUF_SIZE:
                 if feof(fp):

diff --git a/pypy/rpython/test/test_rfloat.py b/pypy/rpython/test/test_rfloat.py
--- a/pypy/rpython/test/test_rfloat.py
+++ b/pypy/rpython/test/test_rfloat.py
@@ -156,6 +156,37 @@
                 return x
         self.interpret(fn, [1.0, 2.0, 3.0])
 
+    def test_copysign(self):
+        import math
+        def fn(x, y):
+            return math.copysign(x, y)
+        assert self.interpret(fn, [42, -1]) == -42
+        assert self.interpret(fn, [42, -0.0]) == -42
+        assert self.interpret(fn, [42, 0.0]) == 42
+
+    def test_rstring_to_float(self):
+        from pypy.rlib.rfloat import rstring_to_float
+        def fn(i):
+            s = ['42.3', '123.4'][i]
+            return rstring_to_float(s)
+        assert self.interpret(fn, [0]) == 42.3
+
+    def test_isnan(self):
+        import math
+        def fn(x):
+            inf = x * x
+            nan = inf / inf
+            return math.isnan(nan)
+        assert self.interpret(fn, [1e200])
+
+    def test_isinf(self):
+        import math
+        def fn(x):
+            inf = x * x
+            return math.isinf(inf)
+        assert self.interpret(fn, [1e200])
+
+        
 class TestLLtype(BaseTestRfloat, LLRtypeMixin):
 
     def test_hash(self):

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
@@ -514,12 +514,10 @@
                     break
             else:
                 # all constant arguments: constant-fold away
-                argboxes = [self.get_constant_box(op.getarg(i))
-                            for i in range(op.numargs())]
-                resbox = execute_nonspec(self.cpu, None,
-                                         op.getopnum(), argboxes, op.getdescr())
-                # FIXME: Don't we need to check for an overflow here?
-                self.make_constant(op.result, resbox.constbox())
+                resbox = self.constant_fold(op)
+                # note that INT_xxx_OVF is not done from here, and the
+                # overflows in the INT_xxx operations are ignored
+                self.make_constant(op.result, resbox)
                 return
 
             # did we do the exact same operation already?
@@ -538,6 +536,13 @@
         if nextop:
             self.emit_operation(nextop)
 
+    def constant_fold(self, op):
+        argboxes = [self.get_constant_box(op.getarg(i))
+                    for i in range(op.numargs())]
+        resbox = execute_nonspec(self.cpu, None,
+                                 op.getopnum(), argboxes, op.getdescr())
+        return resbox.constbox()
+
     #def optimize_GUARD_NO_OVERFLOW(self, op):
     #    # otherwise the default optimizer will clear fields, which is unwanted
     #    # in this case

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,6 +1,6 @@
 """Tests for multiple JitDrivers."""
 from pypy.rlib.jit import JitDriver, unroll_safe
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.jit.metainterp.warmspot import get_stats
 
 

diff --git a/pypy/jit/metainterp/test/test_basic.py b/pypy/jit/metainterp/test/test_basic.py
deleted file mode 100644
--- a/pypy/jit/metainterp/test/test_basic.py
+++ /dev/null
@@ -1,2411 +0,0 @@
-import py
-import sys
-from pypy.rlib.jit import JitDriver, we_are_jitted, hint, dont_look_inside
-from pypy.rlib.jit import loop_invariant
-from pypy.rlib.jit import jit_debug, assert_green, AssertGreenFailed
-from pypy.rlib.jit import unroll_safe, current_trace_length
-from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats
-from pypy.jit.backend.llgraph import runner
-from pypy.jit.metainterp import pyjitpl, history
-from pypy.jit.metainterp.warmstate import set_future_value
-from pypy.jit.codewriter.policy import JitPolicy, StopAtXPolicy
-from pypy.jit.codewriter import longlong
-from pypy import conftest
-from pypy.rlib.rarithmetic import ovfcheck
-from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper
-from pypy.rpython.lltypesystem import lltype, llmemory
-from pypy.rpython.ootypesystem import ootype
-from pypy.jit.metainterp.optimizeopt import ALL_OPTS_DICT
-
-def _get_jitcodes(testself, CPUClass, func, values, type_system,
-                  supports_longlong=False, **kwds):
-    from pypy.jit.codewriter import support, codewriter
-
-    class FakeJitCell:
-        __compiled_merge_points = []
-        def get_compiled_merge_points(self):
-            return self.__compiled_merge_points[:]
-        def set_compiled_merge_points(self, lst):
-            self.__compiled_merge_points = lst
-
-    class FakeWarmRunnerState:
-        def attach_unoptimized_bridge_from_interp(self, greenkey, newloop):
-            pass
-
-        def jit_cell_at_key(self, greenkey):
-            assert greenkey == []
-            return self._cell
-        _cell = FakeJitCell()
-
-        trace_limit = sys.maxint
-        enable_opts = ALL_OPTS_DICT
-
-    func._jit_unroll_safe_ = True
-    rtyper = support.annotate(func, values, type_system=type_system)
-    graphs = rtyper.annotator.translator.graphs
-    result_kind = history.getkind(graphs[0].getreturnvar().concretetype)[0]
-
-    class FakeJitDriverSD:
-        num_green_args = 0
-        portal_graph = graphs[0]
-        virtualizable_info = None
-        greenfield_info = None
-        result_type = result_kind
-        portal_runner_ptr = "???"
-
-    stats = history.Stats()
-    cpu = CPUClass(rtyper, stats, None, False)
-    cw = codewriter.CodeWriter(cpu, [FakeJitDriverSD()])
-    testself.cw = cw
-    policy = JitPolicy()
-    policy.set_supports_longlong(supports_longlong)
-    cw.find_all_graphs(policy)
-    #
-    testself.warmrunnerstate = FakeWarmRunnerState()
-    testself.warmrunnerstate.cpu = cpu
-    FakeJitDriverSD.warmstate = testself.warmrunnerstate
-    if hasattr(testself, 'finish_setup_for_interp_operations'):
-        testself.finish_setup_for_interp_operations()
-    #
-    cw.make_jitcodes(verbose=True)
-
-def _run_with_blackhole(testself, args):
-    from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder
-    cw = testself.cw
-    blackholeinterpbuilder = BlackholeInterpBuilder(cw)
-    blackholeinterp = blackholeinterpbuilder.acquire_interp()
-    count_i = count_r = count_f = 0
-    for value in args:
-        T = lltype.typeOf(value)
-        if T == lltype.Signed:
-            blackholeinterp.setarg_i(count_i, value)
-            count_i += 1
-        elif T == llmemory.GCREF:
-            blackholeinterp.setarg_r(count_r, value)
-            count_r += 1
-        elif T == lltype.Float:
-            value = longlong.getfloatstorage(value)
-            blackholeinterp.setarg_f(count_f, value)
-            count_f += 1
-        else:
-            raise TypeError(T)
-    [jitdriver_sd] = cw.callcontrol.jitdrivers_sd
-    blackholeinterp.setposition(jitdriver_sd.mainjitcode, 0)
-    blackholeinterp.run()
-    return blackholeinterp._final_result_anytype()
-
-def _run_with_pyjitpl(testself, args):
-
-    class DoneWithThisFrame(Exception):
-        pass
-
-    class DoneWithThisFrameRef(DoneWithThisFrame):
-        def __init__(self, cpu, *args):
-            DoneWithThisFrame.__init__(self, *args)
-
-    cw = testself.cw
-    opt = history.Options(listops=True)
-    metainterp_sd = pyjitpl.MetaInterpStaticData(cw.cpu, opt)
-    metainterp_sd.finish_setup(cw)
-    [jitdriver_sd] = metainterp_sd.jitdrivers_sd
-    metainterp = pyjitpl.MetaInterp(metainterp_sd, jitdriver_sd)
-    metainterp_sd.DoneWithThisFrameInt = DoneWithThisFrame
-    metainterp_sd.DoneWithThisFrameRef = DoneWithThisFrameRef
-    metainterp_sd.DoneWithThisFrameFloat = DoneWithThisFrame
-    testself.metainterp = metainterp
-    try:
-        metainterp.compile_and_run_once(jitdriver_sd, *args)
-    except DoneWithThisFrame, e:
-        #if conftest.option.view:
-        #    metainterp.stats.view()
-        return e.args[0]
-    else:
-        raise Exception("FAILED")
-
-def _run_with_machine_code(testself, args):
-    metainterp = testself.metainterp
-    num_green_args = metainterp.jitdriver_sd.num_green_args
-    loop_tokens = metainterp.get_compiled_merge_points(args[:num_green_args])
-    if len(loop_tokens) != 1:
-        return NotImplemented
-    # a loop was successfully created by _run_with_pyjitpl(); call it
-    cpu = metainterp.cpu
-    for i in range(len(args) - num_green_args):
-        x = args[num_green_args + i]
-        typecode = history.getkind(lltype.typeOf(x))
-        set_future_value(cpu, i, x, typecode)
-    faildescr = cpu.execute_token(loop_tokens[0])
-    assert faildescr.__class__.__name__.startswith('DoneWithThisFrameDescr')
-    if metainterp.jitdriver_sd.result_type == history.INT:
-        return cpu.get_latest_value_int(0)
-    elif metainterp.jitdriver_sd.result_type == history.REF:
-        return cpu.get_latest_value_ref(0)
-    elif metainterp.jitdriver_sd.result_type == history.FLOAT:
-        return cpu.get_latest_value_float(0)
-    else:
-        return None
-
-
-class JitMixin:
-    basic = True
-    def check_loops(self, expected=None, everywhere=False, **check):
-        get_stats().check_loops(expected=expected, everywhere=everywhere,
-                                **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.
-        This counts as 1 every bridge in addition to every loop; and it does
-        not count at all the entry bridges from interpreter, although they
-        are TreeLoops as well."""
-        assert get_stats().compiled_count == count
-    def check_tree_loop_count(self, count):
-        assert len(get_stats().loops) == count
-    def check_loop_count_at_most(self, count):
-        assert get_stats().compiled_count <= count
-    def check_enter_count(self, count):
-        assert get_stats().enter_count == count
-    def check_enter_count_at_most(self, count):
-        assert get_stats().enter_count <= count
-    def check_jumps(self, maxcount):
-        assert get_stats().exec_jumps <= maxcount
-    def check_aborted_count(self, count):
-        assert get_stats().aborted_count == count
-    def check_aborted_count_at_least(self, count):
-        assert get_stats().aborted_count >= count
-
-    def meta_interp(self, *args, **kwds):
-        kwds['CPUClass'] = self.CPUClass
-        kwds['type_system'] = self.type_system
-        if "backendopt" not in kwds:
-            kwds["backendopt"] = False
-        return ll_meta_interp(*args, **kwds)
-
-    def interp_operations(self, f, args, **kwds):
-        # get the JitCodes for the function f
-        _get_jitcodes(self, self.CPUClass, f, args, self.type_system, **kwds)
-        # try to run it with blackhole.py
-        result1 = _run_with_blackhole(self, args)
-        # try to run it with pyjitpl.py
-        result2 = _run_with_pyjitpl(self, args)
-        assert result1 == result2
-        # try to run it by running the code compiled just before
-        result3 = _run_with_machine_code(self, args)
-        assert result1 == result3 or result3 == NotImplemented
-        #
-        if (longlong.supports_longlong and
-            isinstance(result1, longlong.r_float_storage)):
-            result1 = longlong.getrealfloat(result1)
-        return result1
-
-    def check_history(self, expected=None, **isns):
-        # this can be used after calling meta_interp
-        get_stats().check_history(expected, **isns)
-
-    def check_operations_history(self, expected=None, **isns):
-        # this can be used after interp_operations
-        if expected is not None:
-            expected = dict(expected)
-            expected['jump'] = 1
-        self.metainterp.staticdata.stats.check_history(expected, **isns)
-
-
-class LLJitMixin(JitMixin):
-    type_system = 'lltype'
-    CPUClass = runner.LLtypeCPU
-
-    @staticmethod
-    def Ptr(T):
-        return lltype.Ptr(T)
-
-    @staticmethod
-    def GcStruct(name, *fields, **kwds):
-        S = lltype.GcStruct(name, *fields, **kwds)
-        return S
-
-    malloc = staticmethod(lltype.malloc)
-    nullptr = staticmethod(lltype.nullptr)
-
-    @staticmethod
-    def malloc_immortal(T):
-        return lltype.malloc(T, immortal=True)
-
-    def _get_NODE(self):
-        NODE = lltype.GcForwardReference()
-        NODE.become(lltype.GcStruct('NODE', ('value', lltype.Signed),
-                                            ('next', lltype.Ptr(NODE))))
-        return NODE
-    
-class OOJitMixin(JitMixin):
-    type_system = 'ootype'
-    #CPUClass = runner.OOtypeCPU
-
-    def setup_class(cls):
-        py.test.skip("ootype tests skipped for now")
-
-    @staticmethod
-    def Ptr(T):
-        return T
-
-    @staticmethod
-    def GcStruct(name, *fields, **kwds):
-        if 'hints' in kwds:
-            kwds['_hints'] = kwds['hints']
-            del kwds['hints']
-        I = ootype.Instance(name, ootype.ROOT, dict(fields), **kwds)
-        return I
-
-    malloc = staticmethod(ootype.new)
-    nullptr = staticmethod(ootype.null)
-
-    @staticmethod
-    def malloc_immortal(T):
-        return ootype.new(T)
-
-    def _get_NODE(self):
-        NODE = ootype.Instance('NODE', ootype.ROOT, {})
-        NODE._add_fields({'value': ootype.Signed,
-                          'next': NODE})
-        return NODE
-
-
-class BasicTests:    
-
-    def test_basic(self):
-        def f(x, y):
-            return x + y
-        res = self.interp_operations(f, [40, 2])
-        assert res == 42
-
-    def test_basic_inst(self):
-        class A:
-            pass
-        def f(n):
-            a = A()
-            a.x = n
-            return a.x
-        res = self.interp_operations(f, [42])
-        assert res == 42
-
-    def test_uint_floordiv(self):
-        from pypy.rlib.rarithmetic import r_uint
-        
-        def f(a, b):
-            a = r_uint(a)
-            b = r_uint(b)
-            return a/b
-
-        res = self.interp_operations(f, [-4, 3])
-        assert res == long(r_uint(-4)) // 3
-
-    def test_direct_call(self):
-        def g(n):
-            return n + 2
-        def f(a, b):
-            return g(a) + g(b)
-        res = self.interp_operations(f, [8, 98])
-        assert res == 110
-
-    def test_direct_call_with_guard(self):
-        def g(n):
-            if n < 0:
-                return 0
-            return n + 2
-        def f(a, b):
-            return g(a) + g(b)
-        res = self.interp_operations(f, [8, 98])
-        assert res == 110
-
-    def test_loop(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res'])
-        def f(x, y):
-            res = 0
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res)
-                res += x
-                y -= 1
-            return res
-        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})
-        if self.basic:
-            found = 0
-            for op in get_stats().loops[0]._all_operations():
-                if op.getopname() == 'guard_true':
-                    liveboxes = op.getfailargs()
-                    assert len(liveboxes) == 3
-                    for box in liveboxes:
-                        assert isinstance(box, history.BoxInt)
-                    found += 1
-            assert found == 1
-
-    def test_loop_invariant_mul1(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
-        def f(x, y):
-            res = 0
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res)
-                res += x * x
-                y -= 1
-            return res
-        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})
-
-    def test_loop_invariant_mul_ovf(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
-        def f(x, y):
-            res = 0
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res)
-                b = y * 2
-                res += ovfcheck(x * x) + b
-                y -= 1
-            return res
-        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})
-
-    def test_loop_invariant_mul_bridge1(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
-        def f(x, y):
-            res = 0
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res)
-                res += x * x
-                if y<16:
-                    x += 1
-                y -= 1
-            return res
-        res = self.meta_interp(f, [6, 32])
-        assert res == 3427
-        self.check_loop_count(3)
-
-    def test_loop_invariant_mul_bridge_maintaining1(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
-        def f(x, y):
-            res = 0
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res)
-                res += x * x
-                if y<16:
-                    res += 1
-                y -= 1
-            return res
-        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})
-
-
-    def test_loop_invariant_mul_bridge_maintaining2(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
-        def f(x, y):
-            res = 0
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res)
-                z = x * x
-                res += z
-                if y<16:
-                    res += z
-                y -= 1
-            return res
-        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})
-
-    def test_loop_invariant_mul_bridge_maintaining3(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x', 'm'])
-        def f(x, y, m):
-            res = 0
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res, m=m)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res, m=m)
-                z = x * x
-                res += z
-                if y<m:
-                    res += z
-                y -= 1
-            return res
-        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})
-
-    def test_loop_invariant_intbox(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'res', 'x'])
-        class I:
-            __slots__ = 'intval'
-            _immutable_ = True
-            def __init__(self, intval):
-                self.intval = intval
-        def f(i, y):
-            res = 0
-            x = I(i)
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res)
-                res += x.intval * x.intval
-                y -= 1
-            return res
-        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})
-
-    def test_loops_are_transient(self):
-        import gc, weakref
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res'])
-        def f(x, y):
-            res = 0
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res)
-                res += x
-                if y%2:
-                    res *= 2
-                y -= 1
-            return res
-        wr_loops = []
-        old_init = history.TreeLoop.__init__.im_func
-        try:
-            def track_init(self, name):
-                old_init(self, name)
-                wr_loops.append(weakref.ref(self))
-            history.TreeLoop.__init__ = track_init
-            res = self.meta_interp(f, [6, 15], no_stats=True)
-        finally:
-            history.TreeLoop.__init__ = old_init
-            
-        assert res == f(6, 15)
-        gc.collect()
-
-        #assert not [wr for wr in wr_loops if wr()]
-        for loop in [wr for wr in wr_loops if wr()]:
-            assert loop().name == 'short preamble'
-
-    def test_string(self):
-        def f(n):
-            bytecode = 'adlfkj' + chr(n)
-            if n < len(bytecode):
-                return bytecode[n]
-            else:
-                return "?"
-        res = self.interp_operations(f, [1])
-        assert res == ord("d") # XXX should be "d"
-        res = self.interp_operations(f, [6])
-        assert res == 6
-        res = self.interp_operations(f, [42])
-        assert res == ord("?")
-
-    def test_chr2str(self):
-        def f(n):
-            s = chr(n)
-            return s[0]
-        res = self.interp_operations(f, [3])
-        assert res == 3
-
-    def test_unicode(self):
-        def f(n):
-            bytecode = u'adlfkj' + unichr(n)
-            if n < len(bytecode):
-                return bytecode[n]
-            else:
-                return u"?"
-        res = self.interp_operations(f, [1])
-        assert res == ord(u"d") # XXX should be "d"
-        res = self.interp_operations(f, [6])
-        assert res == 6
-        res = self.interp_operations(f, [42])
-        assert res == ord(u"?")
-
-    def test_residual_call(self):
-        @dont_look_inside
-        def externfn(x, y):
-            return x * y
-        def f(n):
-            return externfn(n, n+1)
-        res = self.interp_operations(f, [6])
-        assert res == 42
-        self.check_operations_history(int_add=1, int_mul=0, call=1, guard_no_exception=0)
-
-    def test_residual_call_pure(self):
-        def externfn(x, y):
-            return x * y
-        externfn._pure_function_ = True
-        def f(n):
-            n = hint(n, promote=True)
-            return externfn(n, n+1)
-        res = self.interp_operations(f, [6])
-        assert res == 42
-        # CALL_PURE is not recorded in the history if all-constant args
-        self.check_operations_history(int_add=0, int_mul=0,
-                                      call=0, call_pure=0)
-
-    def test_residual_call_pure_1(self):
-        def externfn(x, y):
-            return x * y
-        externfn._pure_function_ = True
-        def f(n):
-            return externfn(n, n+1)
-        res = self.interp_operations(f, [6])
-        assert res == 42
-        # CALL_PURE is recorded in the history if not-all-constant args
-        self.check_operations_history(int_add=1, int_mul=0,
-                                      call=0, call_pure=1)
-
-    def test_residual_call_pure_2(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n'])
-        def externfn(x):
-            return x - 1
-        externfn._pure_function_ = True
-        def f(n):
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n)
-                myjitdriver.jit_merge_point(n=n)
-                n = externfn(n)
-            return n
-        res = self.meta_interp(f, [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)
-
-    def test_constfold_call_pure(self):
-        myjitdriver = JitDriver(greens = ['m'], reds = ['n'])
-        def externfn(x):
-            return x - 3
-        externfn._pure_function_ = True
-        def f(n, m):
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, m=m)
-                myjitdriver.jit_merge_point(n=n, m=m)
-                n -= externfn(m)
-            return n
-        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)
-
-    def test_constfold_call_pure_2(self):
-        myjitdriver = JitDriver(greens = ['m'], reds = ['n'])
-        def externfn(x):
-            return x - 3
-        externfn._pure_function_ = True
-        class V:
-            def __init__(self, value):
-                self.value = value
-        def f(n, m):
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, m=m)
-                myjitdriver.jit_merge_point(n=n, m=m)
-                v = V(m)
-                n -= externfn(v.value)
-            return n
-        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)
-
-    def test_pure_function_returning_object(self):
-        myjitdriver = JitDriver(greens = ['m'], reds = ['n'])
-        class V:
-            def __init__(self, x):
-                self.x = x
-        v1 = V(1)
-        v2 = V(2)
-        def externfn(x):
-            if x:
-                return v1
-            else:
-                return v2
-        externfn._pure_function_ = True
-        def f(n, m):
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, m=m)
-                myjitdriver.jit_merge_point(n=n, m=m)
-                m = V(m).x
-                n -= externfn(m).x + externfn(m + m - m).x
-            return n
-        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)
-
-    def test_constant_across_mp(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n'])
-        class X(object):
-            pass
-        def f(n):
-            while n > -100:
-                myjitdriver.can_enter_jit(n=n)
-                myjitdriver.jit_merge_point(n=n)
-                x = X()
-                x.arg = 5
-                if n <= 0: break
-                n -= x.arg
-                x.arg = 6   # prevents 'x.arg' from being annotated as constant
-            return n
-        res = self.meta_interp(f, [31])
-        assert res == -4
-
-    def test_stopatxpolicy(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y'])
-        def internfn(y):
-            return y * 3
-        def externfn(y):
-            return y % 4
-        def f(y):
-            while y >= 0:
-                myjitdriver.can_enter_jit(y=y)
-                myjitdriver.jit_merge_point(y=y)
-                if y & 7:
-                    f = internfn
-                else:
-                    f = externfn
-                f(y)
-                y -= 1
-            return 42
-        policy = StopAtXPolicy(externfn)
-        res = self.meta_interp(f, [31], policy=policy)
-        assert res == 42
-        self.check_loops(int_mul=1, int_mod=0)
-
-    def test_we_are_jitted(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y'])
-        def f(y):
-            while y >= 0:
-                myjitdriver.can_enter_jit(y=y)
-                myjitdriver.jit_merge_point(y=y)
-                if we_are_jitted():
-                    x = 1
-                else:
-                    x = 10
-                y -= x
-            return y
-        assert f(55) == -5
-        res = self.meta_interp(f, [55])
-        assert res == -1
-
-    def test_confirm_enter_jit(self):
-        def confirm_enter_jit(x, y):
-            return x <= 5
-        myjitdriver = JitDriver(greens = ['x'], reds = ['y'],
-                                confirm_enter_jit = confirm_enter_jit)
-        def f(x, y):
-            while y >= 0:
-                myjitdriver.can_enter_jit(x=x, y=y)
-                myjitdriver.jit_merge_point(x=x, y=y)
-                y -= x
-            return y
-        #
-        res = self.meta_interp(f, [10, 84])
-        assert res == -6
-        self.check_loop_count(0)
-        #
-        res = self.meta_interp(f, [3, 19])
-        assert res == -2
-        self.check_loop_count(1)
-
-    def test_can_never_inline(self):
-        def can_never_inline(x):
-            return x > 50
-        myjitdriver = JitDriver(greens = ['x'], reds = ['y'],
-                                can_never_inline = can_never_inline)
-        @dont_look_inside
-        def marker():
-            pass
-        def f(x, y):
-            while y >= 0:
-                myjitdriver.can_enter_jit(x=x, y=y)
-                myjitdriver.jit_merge_point(x=x, y=y)
-                x += 1
-                if x == 4 or x == 61:
-                    marker()
-                y -= x
-            return y
-        #
-        res = self.meta_interp(f, [3, 6], repeat=7)
-        assert res == 6 - 4 - 5
-        self.check_history(call=0)   # because the trace starts in the middle
-        #
-        res = self.meta_interp(f, [60, 84], repeat=7)
-        assert res == 84 - 61 - 62
-        self.check_history(call=1)   # because the trace starts immediately
-
-    def test_format(self):
-        def f(n):
-            return len("<%d>" % n)
-        res = self.interp_operations(f, [421])
-        assert res == 5
-
-    def test_switch(self):
-        def f(n):
-            if n == -5:  return 12
-            elif n == 2: return 51
-            elif n == 7: return 1212
-            else:        return 42
-        res = self.interp_operations(f, [7])
-        assert res == 1212
-        res = self.interp_operations(f, [12311])
-        assert res == 42
-
-    def test_r_uint(self):
-        from pypy.rlib.rarithmetic import r_uint
-        myjitdriver = JitDriver(greens = [], reds = ['y'])
-        def f(y):
-            y = r_uint(y)
-            while y > 0:
-                myjitdriver.can_enter_jit(y=y)
-                myjitdriver.jit_merge_point(y=y)
-                y -= 1
-            return y
-        res = self.meta_interp(f, [10])
-        assert res == 0
-
-    def test_uint_operations(self):
-        from pypy.rlib.rarithmetic import r_uint
-        def f(n):
-            return ((r_uint(n) - 123) >> 1) <= r_uint(456)
-        res = self.interp_operations(f, [50])
-        assert res == False
-        self.check_operations_history(int_rshift=0, uint_rshift=1,
-                                      int_le=0, uint_le=1,
-                                      int_sub=1)
-
-    def test_uint_condition(self):
-        from pypy.rlib.rarithmetic import r_uint
-        def f(n):
-            if ((r_uint(n) - 123) >> 1) <= r_uint(456):
-                return 24
-            else:
-                return 12
-        res = self.interp_operations(f, [50])
-        assert res == 12
-        self.check_operations_history(int_rshift=0, uint_rshift=1,
-                                      int_le=0, uint_le=1,
-                                      int_sub=1)
-
-    def test_int_between(self):
-        #
-        def check(arg1, arg2, arg3, expect_result, **expect_operations):
-            from pypy.rpython.lltypesystem import lltype
-            from pypy.rpython.lltypesystem.lloperation import llop
-            loc = locals().copy()
-            exec py.code.Source("""
-                def f(n, m, p):
-                    arg1 = %(arg1)s
-                    arg2 = %(arg2)s
-                    arg3 = %(arg3)s
-                    return llop.int_between(lltype.Bool, arg1, arg2, arg3)
-            """ % locals()).compile() in loc
-            res = self.interp_operations(loc['f'], [5, 6, 7])
-            assert res == expect_result
-            self.check_operations_history(expect_operations)
-        #
-        check('n', 'm', 'p', True,  int_sub=2, uint_lt=1)
-        check('n', 'p', 'm', False, int_sub=2, uint_lt=1)
-        #
-        check('n', 'm', 6, False, int_sub=2, uint_lt=1)
-        #
-        check('n', 4, 'p', False, int_sub=2, uint_lt=1)
-        check('n', 5, 'p', True,  int_sub=2, uint_lt=1)
-        check('n', 8, 'p', False, int_sub=2, uint_lt=1)
-        #
-        check('n', 6, 7, True, int_sub=2, uint_lt=1)
-        #
-        check(-2, 'n', 'p', True,  int_sub=2, uint_lt=1)
-        check(-2, 'm', 'p', True,  int_sub=2, uint_lt=1)
-        check(-2, 'p', 'm', False, int_sub=2, uint_lt=1)
-        #check(0, 'n', 'p', True,  uint_lt=1)   xxx implement me
-        #check(0, 'm', 'p', True,  uint_lt=1)
-        #check(0, 'p', 'm', False, uint_lt=1)
-        #
-        check(2, 'n', 6, True,  int_sub=1, uint_lt=1)
-        check(2, 'm', 6, False, int_sub=1, uint_lt=1)
-        check(2, 'p', 6, False, int_sub=1, uint_lt=1)
-        check(5, 'n', 6, True,  int_eq=1)    # 6 == 5+1
-        check(5, 'm', 6, False, int_eq=1)    # 6 == 5+1
-        #
-        check(2, 6, 'm', False, int_sub=1, uint_lt=1)
-        check(2, 6, 'p', True,  int_sub=1, uint_lt=1)
-        #
-        check(2, 40, 6,  False)
-        check(2, 40, 60, True)
-
-    def test_getfield(self):
-        class A:
-            pass
-        a1 = A()
-        a1.foo = 5
-        a2 = A()
-        a2.foo = 8
-        def f(x):
-            if x > 5:
-                a = a1
-            else:
-                a = a2
-            return a.foo * x
-        res = self.interp_operations(f, [42])
-        assert res == 210
-        self.check_operations_history(getfield_gc=1)
-
-    def test_getfield_immutable(self):
-        class A:
-            _immutable_ = True
-        a1 = A()
-        a1.foo = 5
-        a2 = A()
-        a2.foo = 8
-        def f(x):
-            if x > 5:
-                a = a1
-            else:
-                a = a2
-            return a.foo * x
-        res = self.interp_operations(f, [42])
-        assert res == 210
-        self.check_operations_history(getfield_gc=0)
-
-    def test_setfield_bool(self):
-        class A:
-            def __init__(self):
-                self.flag = True
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'obj'])
-        def f(n):
-            obj = A()
-            res = False
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, obj=obj)
-                myjitdriver.jit_merge_point(n=n, obj=obj)
-                obj.flag = False
-                n -= 1
-            return res
-        res = self.meta_interp(f, [7])
-        assert type(res) == bool
-        assert not res
-
-    def test_switch_dict(self):
-        def f(x):
-            if   x == 1: return 61
-            elif x == 2: return 511
-            elif x == 3: return -22
-            elif x == 4: return 81
-            elif x == 5: return 17
-            elif x == 6: return 54
-            elif x == 7: return 987
-            elif x == 8: return -12
-            elif x == 9: return 321
-            return -1
-        res = self.interp_operations(f, [5])
-        assert res == 17
-        res = self.interp_operations(f, [15])
-        assert res == -1
-
-    def test_int_add_ovf(self):
-        def f(x, y):
-            try:
-                return ovfcheck(x + y)
-            except OverflowError:
-                return -42
-        res = self.interp_operations(f, [-100, 2])
-        assert res == -98
-        res = self.interp_operations(f, [1, sys.maxint])
-        assert res == -42
-
-    def test_int_sub_ovf(self):
-        def f(x, y):
-            try:
-                return ovfcheck(x - y)
-            except OverflowError:
-                return -42
-        res = self.interp_operations(f, [-100, 2])
-        assert res == -102
-        res = self.interp_operations(f, [1, -sys.maxint])
-        assert res == -42
-
-    def test_int_mul_ovf(self):
-        def f(x, y):
-            try:
-                return ovfcheck(x * y)
-            except OverflowError:
-                return -42
-        res = self.interp_operations(f, [-100, 2])
-        assert res == -200
-        res = self.interp_operations(f, [-3, sys.maxint//2])
-        assert res == -42
-
-    def test_mod_ovf(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'x', 'y'])
-        def f(n, x, y):
-            while n > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, n=n)
-                myjitdriver.jit_merge_point(x=x, y=y, n=n)
-                n -= ovfcheck(x % y)
-            return n
-        res = self.meta_interp(f, [20, 1, 2])
-        assert res == 0
-        self.check_loops(call=0)
-
-    def test_abs(self):
-        myjitdriver = JitDriver(greens = [], reds = ['i', 't'])
-        def f(i):
-            t = 0
-            while i < 10:
-                myjitdriver.can_enter_jit(i=i, t=t)
-                myjitdriver.jit_merge_point(i=i, t=t)
-                t += abs(i)
-                i += 1
-            return t
-        res = self.meta_interp(f, [-5])
-        assert res == 5+4+3+2+1+0+1+2+3+4+5+6+7+8+9
-
-    def test_float(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res'])
-        def f(x, y):
-            x = float(x)
-            y = float(y)
-            res = 0.0
-            while y > 0.0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res)
-                res += x
-                y -= 1.0
-            return res
-        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})
-
-    def test_print(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n'])
-        def f(n):
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n)
-                myjitdriver.jit_merge_point(n=n)
-                print n
-                n -= 1
-            return n
-        res = self.meta_interp(f, [7])
-        assert res == 0
-
-    def test_bridge_from_interpreter(self):
-        mydriver = JitDriver(reds = ['n'], greens = [])
-
-        def f(n):
-            while n > 0:
-                mydriver.can_enter_jit(n=n)
-                mydriver.jit_merge_point(n=n)
-                n -= 1
-
-        self.meta_interp(f, [20], repeat=7)
-        self.check_tree_loop_count(2)      # the loop and the entry path
-        # we get:
-        #    ENTER             - compile the new loop and the entry bridge
-        #    ENTER             - compile the leaving path
-        self.check_enter_count(2)
-
-    def test_bridge_from_interpreter_2(self):
-        # one case for backend - computing of framesize on guard failure
-        mydriver = JitDriver(reds = ['n'], greens = [])
-        glob = [1]
-
-        def f(n):
-            while n > 0:
-                mydriver.can_enter_jit(n=n)
-                mydriver.jit_merge_point(n=n)
-                if n == 17 and glob[0]:
-                    glob[0] = 0
-                    x = n + 1
-                    y = n + 2
-                    z = n + 3
-                    k = n + 4
-                    n -= 1
-                    n += x + y + z + k
-                    n -= x + y + z + k
-                n -= 1
-
-        self.meta_interp(f, [20], repeat=7)
-
-    def test_bridge_from_interpreter_3(self):
-        # one case for backend - computing of framesize on guard failure
-        mydriver = JitDriver(reds = ['n', 'x', 'y', 'z', 'k'], greens = [])
-        class Global:
-            pass
-        glob = Global()
-
-        def f(n):
-            glob.x = 1
-            x = 0
-            y = 0
-            z = 0
-            k = 0
-            while n > 0:
-                mydriver.can_enter_jit(n=n, x=x, y=y, z=z, k=k)
-                mydriver.jit_merge_point(n=n, x=x, y=y, z=z, k=k)
-                x += 10
-                y += 3
-                z -= 15
-                k += 4
-                if n == 17 and glob.x:
-                    glob.x = 0
-                    x += n + 1
-                    y += n + 2
-                    z += n + 3
-                    k += n + 4
-                    n -= 1
-                n -= 1
-            return x + 2*y + 3*z + 5*k + 13*n
-
-        res = self.meta_interp(f, [20], repeat=7)
-        assert res == f(20)
-
-    def test_bridge_from_interpreter_4(self):
-        jitdriver = JitDriver(reds = ['n', 'k'], greens = [])
-        
-        def f(n, k):
-            while n > 0:
-                jitdriver.can_enter_jit(n=n, k=k)
-                jitdriver.jit_merge_point(n=n, k=k)
-                if k:
-                    n -= 2
-                else:
-                    n -= 1
-            return n + k
-
-        from pypy.rpython.test.test_llinterp import get_interpreter, clear_tcache
-        from pypy.jit.metainterp.warmspot import WarmRunnerDesc
-        
-        interp, graph = get_interpreter(f, [0, 0], backendopt=False,
-                                        inline_threshold=0, type_system=self.type_system)
-        clear_tcache()
-        translator = interp.typer.annotator.translator
-        translator.config.translation.gc = "boehm"
-        warmrunnerdesc = WarmRunnerDesc(translator,
-                                        CPUClass=self.CPUClass)
-        state = warmrunnerdesc.jitdrivers_sd[0].warmstate
-        state.set_param_threshold(3)          # for tests
-        state.set_param_trace_eagerness(0)    # for tests
-        warmrunnerdesc.finish()
-        for n, k in [(20, 0), (20, 1)]:
-            interp.eval_graph(graph, [n, k])
-
-    def test_bridge_leaving_interpreter_5(self):
-        mydriver = JitDriver(reds = ['n', 'x'], greens = [])
-        class Global:
-            pass
-        glob = Global()
-
-        def f(n):
-            x = 0
-            glob.x = 1
-            while n > 0:
-                mydriver.can_enter_jit(n=n, x=x)
-                mydriver.jit_merge_point(n=n, x=x)
-                glob.x += 1
-                x += 3
-                n -= 1
-            glob.x += 100
-            return glob.x + x
-        res = self.meta_interp(f, [20], repeat=7)
-        assert res == f(20)
-
-    def test_instantiate_classes(self):
-        class Base: pass
-        class A(Base): foo = 72
-        class B(Base): foo = 8
-        def f(n):
-            if n > 5:
-                cls = A
-            else:
-                cls = B
-            return cls().foo
-        res = self.interp_operations(f, [3])
-        assert res == 8
-        res = self.interp_operations(f, [13])
-        assert res == 72
-
-    def test_instantiate_does_not_call(self):
-        mydriver = JitDriver(reds = ['n', 'x'], greens = [])
-        class Base: pass
-        class A(Base): foo = 72
-        class B(Base): foo = 8
-
-        def f(n):
-            x = 0
-            while n > 0:
-                mydriver.can_enter_jit(n=n, x=x)
-                mydriver.jit_merge_point(n=n, x=x)
-                if n % 2 == 0:
-                    cls = A
-                else:
-                    cls = B
-                inst = cls()
-                x += inst.foo
-                n -= 1
-            return x
-        res = self.meta_interp(f, [20], enable_opts='')
-        assert res == f(20)
-        self.check_loops(call=0)
-
-    def test_zerodivisionerror(self):
-        # test the case of exception-raising operation that is not delegated
-        # to the backend at all: ZeroDivisionError
-        #
-        def f(n):
-            assert n >= 0
-            try:
-                return ovfcheck(5 % n)
-            except ZeroDivisionError:
-                return -666
-            except OverflowError:
-                return -777
-        res = self.interp_operations(f, [0])
-        assert res == -666
-        #
-        def f(n):
-            assert n >= 0
-            try:
-                return ovfcheck(6 // n)
-            except ZeroDivisionError:
-                return -667
-            except OverflowError:
-                return -778
-        res = self.interp_operations(f, [0])
-        assert res == -667
-
-    def test_div_overflow(self):
-        import sys
-        from pypy.rpython.lltypesystem.lloperation import llop
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'res'])
-        def f(x, y):
-            res = 0
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res)
-                try:
-                    res += llop.int_floordiv_ovf(lltype.Signed,
-                                                 -sys.maxint-1, x)
-                    x += 5
-                except OverflowError:
-                    res += 100
-                y -= 1
-            return res
-        res = self.meta_interp(f, [-41, 16])
-        assert res == ((-sys.maxint-1) // (-41) +
-                       (-sys.maxint-1) // (-36) +
-                       (-sys.maxint-1) // (-31) +
-                       (-sys.maxint-1) // (-26) +
-                       (-sys.maxint-1) // (-21) +
-                       (-sys.maxint-1) // (-16) +
-                       (-sys.maxint-1) // (-11) +
-                       (-sys.maxint-1) // (-6) +
-                       100 * 8)
-
-    def test_isinstance(self):
-        class A:
-            pass
-        class B(A):
-            pass
-        def fn(n):
-            if n:
-                obj = A()
-            else:
-                obj = B()
-            return isinstance(obj, B)
-        res = self.interp_operations(fn, [0])
-        assert res
-        self.check_operations_history(guard_class=1)
-        res = self.interp_operations(fn, [1])
-        assert not res
-
-    def test_isinstance_2(self):
-        driver = JitDriver(greens = [], reds = ['n', 'sum', 'x'])
-        class A:
-            pass
-        class B(A):
-            pass
-        class C(B):
-            pass
-
-        def main():
-            return f(5, B()) * 10 + f(5, C()) + f(5, A()) * 100
-
-        def f(n, x):
-            sum = 0
-            while n > 0:
-                driver.can_enter_jit(x=x, n=n, sum=sum)
-                driver.jit_merge_point(x=x, n=n, sum=sum)
-                if isinstance(x, B):
-                    sum += 1
-                n -= 1
-            return sum
-
-        res = self.meta_interp(main, [])
-        assert res == 55
-
-    def test_assert_isinstance(self):
-        class A:
-            pass
-        class B(A):
-            pass
-        def fn(n):
-            # this should only be called with n != 0
-            if n:
-                obj = B()
-                obj.a = n
-            else:
-                obj = A()
-                obj.a = 17
-            assert isinstance(obj, B)
-            return obj.a
-        res = self.interp_operations(fn, [1])
-        assert res == 1
-        self.check_operations_history(guard_class=0)
-        if self.type_system == 'ootype':
-            self.check_operations_history(instanceof=0)
-
-    def test_r_dict(self):
-        from pypy.rlib.objectmodel import r_dict
-        class FooError(Exception):
-            pass
-        def myeq(n, m):
-            return n == m
-        def myhash(n):
-            if n < 0:
-                raise FooError
-            return -n
-        def f(n):
-            d = r_dict(myeq, myhash)
-            for i in range(10):
-                d[i] = i*i
-            try:
-                return d[n]
-            except FooError:
-                return 99
-        res = self.interp_operations(f, [5])
-        assert res == f(5)
-
-    def test_free_object(self):
-        import weakref
-        from pypy.rlib import rgc
-        from pypy.rpython.lltypesystem.lloperation import llop
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'x'])
-        class X(object):
-            pass
-        def main(n, x):
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, x=x)
-                myjitdriver.jit_merge_point(n=n, x=x)
-                n -= x.foo
-        def g(n):
-            x = X()
-            x.foo = 2
-            main(n, x)
-            x.foo = 5
-            return weakref.ref(x)
-        def f(n):
-            r = g(n)
-            rgc.collect(); rgc.collect(); rgc.collect()
-            return r() is None
-        #
-        assert f(30) == 1
-        res = self.meta_interp(f, [30], no_stats=True)
-        assert res == 1
-
-    def test_pass_around(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'x'])
-
-        def call():
-            pass
-
-        def f(n, x):
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, x=x)
-                myjitdriver.jit_merge_point(n=n, x=x)
-                if n % 2:
-                    call()
-                    if n == 8:
-                        return x
-                    x = 3
-                else:
-                    x = 5
-                n -= 1
-            return 0
-
-        self.meta_interp(f, [40, 0])
-
-    def test_const_inputargs(self):
-        myjitdriver = JitDriver(greens = ['m'], reds = ['n', 'x'])
-        def f(n, x):
-            m = 0x7FFFFFFF
-            while n > 0:
-                myjitdriver.can_enter_jit(m=m, n=n, x=x)
-                myjitdriver.jit_merge_point(m=m, n=n, x=x)
-                x = 42
-                n -= 1
-                m = m >> 1
-            return x
-
-        res = self.meta_interp(f, [50, 1], enable_opts='')
-        assert res == 42
-
-    def test_set_param(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'x'])
-        def g(n):
-            x = 0
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, x=x)
-                myjitdriver.jit_merge_point(n=n, x=x)
-                n -= 1
-                x += n
-            return x
-        def f(n, threshold):
-            myjitdriver.set_param('threshold', threshold)
-            return g(n)
-
-        res = self.meta_interp(f, [10, 3])
-        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])
-        assert res == 9 + 8 + 7 + 6 + 5 + 4 + 3 + 2 + 1 + 0
-        self.check_tree_loop_count(0)
-
-    def test_dont_look_inside(self):
-        @dont_look_inside
-        def g(a, b):
-            return a + b
-        def f(a, b):
-            return g(a, b)
-        res = self.interp_operations(f, [3, 5])
-        assert res == 8
-        self.check_operations_history(int_add=0, call=1)
-
-    def test_listcomp(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'lst'])
-        def f(x, y):
-            lst = [0, 0, 0]
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, lst=lst)
-                myjitdriver.jit_merge_point(x=x, y=y, lst=lst)
-                lst = [i+x for i in lst if i >=0]
-                y -= 1
-            return lst[0]
-        res = self.meta_interp(f, [6, 7], listcomp=True, backendopt=True, listops=True)
-        # XXX: the loop looks inefficient
-        assert res == 42
-
-    def test_tuple_immutable(self):
-        def new(a, b):
-            return a, b
-        def f(a, b):
-            tup = new(a, b)
-            return tup[1]
-        res = self.interp_operations(f, [3, 5])
-        assert res == 5
-        self.check_operations_history(setfield_gc=2, getfield_gc_pure=1)
-
-    def test_oosend_look_inside_only_one(self):
-        class A:
-            pass
-        class B(A):
-            def g(self):
-                return 123
-        class C(A):
-            @dont_look_inside
-            def g(self):
-                return 456
-        def f(n):
-            if n > 3:
-                x = B()
-            else:
-                x = C()
-            return x.g() + x.g()
-        res = self.interp_operations(f, [10])
-        assert res == 123 * 2
-        res = self.interp_operations(f, [-10])
-        assert res == 456 * 2
-
-    def test_residual_external_call(self):
-        import math
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'x', 'res'])
-        def f(x, y):
-            x = float(x)
-            res = 0.0
-            while y > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, res=res)
-                myjitdriver.jit_merge_point(x=x, y=y, res=res)
-                # this is an external call that the default policy ignores
-                rpart, ipart = math.modf(x)
-                res += ipart
-                y -= 1
-            return res
-        res = self.meta_interp(f, [6, 7])
-        assert res == 42
-        self.check_loop_count(1)
-        self.check_loops(call=1)
-
-    def test_merge_guardclass_guardvalue(self):
-        from pypy.rlib.objectmodel import instantiate
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'l'])
-
-        class A(object):
-            def g(self, x):
-                return x - 5
-        class B(A):
-            def g(self, y):
-                return y - 3
-
-        a1 = A()
-        a2 = A()
-        b = B()
-        def f(x):
-            l = [a1] * 100 + [a2] * 100 + [b] * 100
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x, l=l)
-                myjitdriver.jit_merge_point(x=x, l=l)
-                a = l[x]
-                x = a.g(x)
-                hint(a, promote=True)
-            return x
-        res = self.meta_interp(f, [299], listops=True)
-        assert res == f(299)
-        self.check_loops(guard_class=0, guard_value=2)        
-        self.check_loops(guard_class=0, guard_value=5, everywhere=True)
-
-    def test_merge_guardnonnull_guardclass(self):
-        from pypy.rlib.objectmodel import instantiate
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'l'])
-
-        class A(object):
-            def g(self, x):
-                return x - 3
-        class B(A):
-            def g(self, y):
-                return y - 5
-
-        a1 = A()
-        b1 = B()
-        def f(x):
-            l = [None] * 100 + [b1] * 100 + [a1] * 100
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x, l=l)
-                myjitdriver.jit_merge_point(x=x, l=l)
-                a = l[x]
-                if a:
-                    x = a.g(x)
-                else:
-                    x -= 7
-            return x
-        res = self.meta_interp(f, [299], listops=True)
-        assert res == f(299)
-        self.check_loops(guard_class=0, guard_nonnull=0,
-                         guard_nonnull_class=2, guard_isnull=0)
-        self.check_loops(guard_class=0, guard_nonnull=0,
-                         guard_nonnull_class=4, guard_isnull=1,
-                         everywhere=True)
-
-    def test_merge_guardnonnull_guardvalue(self):
-        from pypy.rlib.objectmodel import instantiate
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'l'])
-
-        class A(object):
-            pass
-        class B(A):
-            pass
-
-        a1 = A()
-        b1 = B()
-        def f(x):
-            l = [b1] * 100 + [None] * 100 + [a1] * 100
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x, l=l)
-                myjitdriver.jit_merge_point(x=x, l=l)
-                a = l[x]
-                if a:
-                    x -= 5
-                else:
-                    x -= 7
-                hint(a, promote=True)
-            return x
-        res = self.meta_interp(f, [299], listops=True)
-        assert res == f(299)
-        self.check_loops(guard_class=0, guard_nonnull=0, guard_value=1,
-                         guard_nonnull_class=0, guard_isnull=1)
-        self.check_loops(guard_class=0, guard_nonnull=0, guard_value=3,
-                         guard_nonnull_class=0, guard_isnull=2,
-                         everywhere=True)
-
-    def test_merge_guardnonnull_guardvalue_2(self):
-        from pypy.rlib.objectmodel import instantiate
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'l'])
-
-        class A(object):
-            pass
-        class B(A):
-            pass
-
-        a1 = A()
-        b1 = B()
-        def f(x):
-            l = [None] * 100 + [b1] * 100 + [a1] * 100
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x, l=l)
-                myjitdriver.jit_merge_point(x=x, l=l)
-                a = l[x]
-                if a:
-                    x -= 5
-                else:
-                    x -= 7
-                hint(a, promote=True)
-            return x
-        res = self.meta_interp(f, [299], listops=True)
-        assert res == f(299)
-        self.check_loops(guard_class=0, guard_nonnull=0, guard_value=2,
-                         guard_nonnull_class=0, guard_isnull=0)
-        self.check_loops(guard_class=0, guard_nonnull=0, guard_value=4,
-                         guard_nonnull_class=0, guard_isnull=1,
-                         everywhere=True)
-
-    def test_merge_guardnonnull_guardclass_guardvalue(self):
-        from pypy.rlib.objectmodel import instantiate
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'l'])
-
-        class A(object):
-            def g(self, x):
-                return x - 3
-        class B(A):
-            def g(self, y):
-                return y - 5
-
-        a1 = A()
-        a2 = A()
-        b1 = B()
-        def f(x):
-            l = [a2] * 100 + [None] * 100 + [b1] * 100 + [a1] * 100
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x, l=l)
-                myjitdriver.jit_merge_point(x=x, l=l)
-                a = l[x]
-                if a:
-                    x = a.g(x)
-                else:
-                    x -= 7
-                hint(a, promote=True)
-            return x
-        res = self.meta_interp(f, [399], listops=True)
-        assert res == f(399)
-        self.check_loops(guard_class=0, guard_nonnull=0, guard_value=2,
-                         guard_nonnull_class=0, guard_isnull=0)
-        self.check_loops(guard_class=0, guard_nonnull=0, guard_value=5,
-                         guard_nonnull_class=0, guard_isnull=1,
-                         everywhere=True)
-
-    def test_residual_call_doesnt_lose_info(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'y', 'l'])
-
-        class A(object):
-            pass
-
-        globall = [""]
-        @dont_look_inside
-        def g(x):
-            globall[0] = str(x)
-            return x
-
-        def f(x):
-            y = A()
-            y.v = x
-            l = [0]
-            while y.v > 0:
-                myjitdriver.can_enter_jit(x=x, y=y, l=l)
-                myjitdriver.jit_merge_point(x=x, y=y, l=l)
-                l[0] = y.v
-                lc = l[0]
-                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)
-
-    def test_guard_isnull_nonnull(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'res'])
-        class A(object):
-            pass
-
-        @dont_look_inside
-        def create(x):
-            if x >= -40:
-                return A()
-            return None
-
-        def f(x):
-            res = 0
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x, res=res)
-                myjitdriver.jit_merge_point(x=x, res=res)
-                obj = create(x-1)
-                if obj is not None:
-                    res += 1
-                obj2 = create(x-1000)
-                if obj2 is None:
-                    res += 1
-                x -= 1
-            return res
-        res = self.meta_interp(f, [21])
-        assert res == 42
-        self.check_loops(guard_nonnull=1, guard_isnull=1)
-
-    def test_loop_invariant1(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'res'])
-        class A(object):
-            pass
-        a = A()
-        a.current_a = A()
-        a.current_a.x = 1
-        @loop_invariant
-        def f():
-            return a.current_a
-
-        def g(x):
-            res = 0
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x, res=res)
-                myjitdriver.jit_merge_point(x=x, res=res)
-                res += f().x
-                res += f().x
-                res += f().x
-                x -= 1
-            a.current_a = A()
-            a.current_a.x = 2
-            return res
-        res = self.meta_interp(g, [21])
-        assert res == 3 * 21
-        self.check_loops(call=0)
-        self.check_loops(call=1, everywhere=True)
-
-    def test_bug_optimizeopt_mutates_ops(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'res', 'const', 'a'])
-        class A(object):
-            pass
-        class B(A):
-            pass
-
-        glob = A()
-        glob.a = None
-        def f(x):
-            res = 0
-            a = A()
-            a.x = 0
-            glob.a = A()
-            const = 2
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x, res=res, a=a, const=const)
-                myjitdriver.jit_merge_point(x=x, res=res, a=a, const=const)
-                if type(glob.a) is B:
-                    res += 1
-                if a is None:
-                    a = A()
-                    a.x = x
-                    glob.a = B()
-                    const = 2
-                else:
-                    const = hint(const, promote=True)
-                    x -= const
-                    res += a.x
-                    a = None
-                    glob.a = A()
-                    const = 1
-            return res
-        res = self.meta_interp(f, [21])
-        assert res == f(21)
-
-    def test_getitem_indexerror(self):
-        lst = [10, 4, 9, 16]
-        def f(n):
-            try:
-                return lst[n]
-            except IndexError:
-                return -2
-        res = self.interp_operations(f, [2])
-        assert res == 9
-        res = self.interp_operations(f, [4])
-        assert res == -2
-        res = self.interp_operations(f, [-4])
-        assert res == 10
-        res = self.interp_operations(f, [-5])
-        assert res == -2
-
-    def test_guard_always_changing_value(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x'])
-        class A:
-            pass
-        def f(x):
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x)
-                myjitdriver.jit_merge_point(x=x)
-                a = A()
-                hint(a, promote=True)
-                x -= 1
-        self.meta_interp(f, [50])
-        self.check_loop_count(1)
-        # this checks that the logic triggered by make_a_counter_per_value()
-        # works and prevents generating tons of bridges
-
-    def test_swap_values(self):
-        def f(x, y):
-            if x > 5:
-                x, y = y, x
-            return x - y
-        res = self.interp_operations(f, [10, 2])
-        assert res == -8
-        res = self.interp_operations(f, [3, 2])
-        assert res == 1
-
-    def test_raw_malloc_and_access(self):
-        from pypy.rpython.lltypesystem import rffi
-        
-        TP = rffi.CArray(lltype.Signed)
-        
-        def f(n):
-            a = lltype.malloc(TP, n, flavor='raw')
-            a[0] = n
-            res = a[0]
-            lltype.free(a, flavor='raw')
-            return res
-
-        res = self.interp_operations(f, [10])
-        assert res == 10
-
-    def test_raw_malloc_and_access_float(self):
-        from pypy.rpython.lltypesystem import rffi
-        
-        TP = rffi.CArray(lltype.Float)
-        
-        def f(n, f):
-            a = lltype.malloc(TP, n, flavor='raw')
-            a[0] = f
-            res = a[0]
-            lltype.free(a, flavor='raw')
-            return res
-
-        res = self.interp_operations(f, [10, 3.5])
-        assert res == 3.5
-
-    def test_jit_debug(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x'])
-        class A:
-            pass
-        def f(x):
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x)
-                myjitdriver.jit_merge_point(x=x)
-                jit_debug("hi there:", x)
-                jit_debug("foobar")
-                x -= 1
-            return x
-        res = self.meta_interp(f, [8])
-        assert res == 0
-        self.check_loops(jit_debug=2)
-
-    def test_assert_green(self):
-        def f(x, promote):
-            if promote:
-                x = hint(x, promote=True)
-            assert_green(x)
-            return x
-        res = self.interp_operations(f, [8, 1])
-        assert res == 8
-        py.test.raises(AssertGreenFailed, self.interp_operations, f, [8, 0])
-
-    def test_multiple_specialied_versions1(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'x', 'res'])
-        class Base:
-            def __init__(self, val):
-                self.val = val
-        class A(Base):
-            def binop(self, other):
-                return A(self.val + other.val)
-        class B(Base):
-            def binop(self, other):
-                return B(self.val * other.val)
-        def f(x, y):
-            res = x
-            while y > 0:
-                myjitdriver.can_enter_jit(y=y, x=x, res=res)
-                myjitdriver.jit_merge_point(y=y, x=x, res=res)
-                res = res.binop(x)
-                y -= 1
-            return res
-        def g(x, y):
-            a1 = f(A(x), y)
-            a2 = f(A(x), y)
-            b1 = f(B(x), y)
-            b2 = f(B(x), y)
-            assert a1.val == a2.val
-            assert b1.val == b2.val
-            return a1.val + b1.val
-        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})
-
-    def test_multiple_specialied_versions_array(self):
-        myjitdriver = JitDriver(greens = [], reds = ['idx', 'y', 'x', 'res',
-                                                     'array'])
-        class Base:
-            def __init__(self, val):
-                self.val = val
-        class A(Base):
-            def binop(self, other):
-                return A(self.val + other.val)
-        class B(Base):
-            def binop(self, other):
-                return B(self.val - other.val)
-        def f(x, y):
-            res = x
-            array = [1, 2, 3]
-            array[1] = 7
-            idx = 0
-            while y > 0:
-                myjitdriver.can_enter_jit(idx=idx, y=y, x=x, res=res,
-                                          array=array)
-                myjitdriver.jit_merge_point(idx=idx, y=y, x=x, res=res,
-                                            array=array)
-                res = res.binop(x)
-                res.val += array[idx] + array[1]
-                if y < 7:
-                    idx = 2
-                y -= 1
-            return res
-        def g(x, y):
-            a1 = f(A(x), y)
-            a2 = f(A(x), y)
-            b1 = f(B(x), y)
-            b2 = f(B(x), y)
-            assert a1.val == a2.val
-            assert b1.val == b2.val
-            return a1.val + b1.val
-        res = self.meta_interp(g, [6, 14])
-        assert res == g(6, 14)
-        self.check_loop_count(9)
-        self.check_loops(getarrayitem_gc=6, everywhere=True)
-
-    def test_multiple_specialied_versions_bridge(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'x', 'z', 'res'])
-        class Base:
-            def __init__(self, val):
-                self.val = val
-            def getval(self):
-                return self.val
-        class A(Base):
-            def binop(self, other):
-                return A(self.getval() + other.getval())
-        class B(Base):
-            def binop(self, other):
-                return B(self.getval() * other.getval())
-        def f(x, y, z):
-            res = x
-            while y > 0:
-                myjitdriver.can_enter_jit(y=y, x=x, z=z, res=res)
-                myjitdriver.jit_merge_point(y=y, x=x, z=z, res=res)
-                res = res.binop(x)
-                y -= 1
-                if y < 7:
-                    x = z
-            return res
-        def g(x, y):
-            a1 = f(A(x), y, A(x))
-            a2 = f(A(x), y, A(x))
-            assert a1.val == a2.val
-            b1 = f(B(x), y, B(x))
-            b2 = f(B(x), y, B(x))
-            assert b1.val == b2.val
-            c1 = f(B(x), y, A(x))
-            c2 = f(B(x), y, A(x))
-            assert c1.val == c2.val
-            d1 = f(A(x), y, B(x))
-            d2 = f(A(x), y, B(x))
-            assert d1.val == d2.val
-            return a1.val + b1.val + c1.val + d1.val
-        res = self.meta_interp(g, [3, 14])
-        assert res == g(3, 14)
-
-    def test_failing_inlined_guard(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'x', 'z', 'res'])
-        class Base:
-            def __init__(self, val):
-                self.val = val
-            def getval(self):
-                return self.val
-        class A(Base):
-            def binop(self, other):
-                return A(self.getval() + other.getval())
-        class B(Base):
-            def binop(self, other):
-                return B(self.getval() * other.getval())
-        def f(x, y, z):
-            res = x
-            while y > 0:
-                myjitdriver.can_enter_jit(y=y, x=x, z=z, res=res)
-                myjitdriver.jit_merge_point(y=y, x=x, z=z, res=res)
-                res = res.binop(x)
-                y -= 1
-                if y < 8:
-                    x = z
-            return res
-        def g(x, y):
-            c1 = f(A(x), y, B(x))
-            c2 = f(A(x), y, B(x))
-            assert c1.val == c2.val
-            return c1.val
-        res = self.meta_interp(g, [3, 16])
-        assert res == g(3, 16)
-
-    def test_inlined_guard_in_short_preamble(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'x', 'z', 'res'])
-        class A:
-            def __init__(self, val):
-                self.val = val
-            def getval(self):
-                return self.val
-            def binop(self, other):
-                return A(self.getval() + other.getval())
-        def f(x, y, z):
-            res = x
-            while y > 0:
-                myjitdriver.can_enter_jit(y=y, x=x, z=z, res=res)
-                myjitdriver.jit_merge_point(y=y, x=x, z=z, res=res)
-                res = res.binop(x)
-                y -= 1
-                if y < 7:
-                    x = z
-            return res
-        def g(x, y):
-            a1 = f(A(x), y, A(x))
-            a2 = f(A(x), y, A(x))
-            assert a1.val == a2.val
-            return a1.val
-        res = self.meta_interp(g, [3, 14])
-        assert res == g(3, 14)
-
-    def test_specialied_bridge(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'x', 'res'])
-        class A:
-            def __init__(self, val):
-                self.val = val
-            def binop(self, other):
-                return A(self.val + other.val)
-        def f(x, y):
-            res = A(0)
-            while y > 0:
-                myjitdriver.can_enter_jit(y=y, x=x, res=res)
-                myjitdriver.jit_merge_point(y=y, x=x, res=res)
-                res = res.binop(A(y))
-                if y<7:
-                    res = x
-                y -= 1
-            return res
-        def g(x, y):
-            a1 = f(A(x), y)
-            a2 = f(A(x), y)
-            assert a1.val == a2.val
-            return a1.val
-        res = self.meta_interp(g, [6, 14])
-        assert res == g(6, 14)
-
-    def test_specialied_bridge_const(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'const', 'x', 'res'])
-        class A:
-            def __init__(self, val):
-                self.val = val
-            def binop(self, other):
-                return A(self.val + other.val)
-        def f(x, y):
-            res = A(0)
-            const = 7
-            while y > 0:
-                myjitdriver.can_enter_jit(y=y, x=x, res=res, const=const)
-                myjitdriver.jit_merge_point(y=y, x=x, res=res, const=const)
-                const = hint(const, promote=True)
-                res = res.binop(A(const))
-                if y<7:
-                    res = x
-                y -= 1
-            return res
-        def g(x, y):
-            a1 = f(A(x), y)
-            a2 = f(A(x), y)
-            assert a1.val == a2.val
-            return a1.val
-        res = self.meta_interp(g, [6, 14])
-        assert res == g(6, 14)
-
-    def test_multiple_specialied_zigzag(self):
-        myjitdriver = JitDriver(greens = [], reds = ['y', 'x', 'res'])
-        class Base:
-            def __init__(self, val):
-                self.val = val
-        class A(Base):
-            def binop(self, other):
-                return A(self.val + other.val)
-            def switch(self):
-                return B(self.val)
-        class B(Base):
-            def binop(self, other):
-                return B(self.val * other.val)
-            def switch(self):
-                return A(self.val)
-        def f(x, y):
-            res = x
-            while y > 0:
-                myjitdriver.can_enter_jit(y=y, x=x, res=res)
-                myjitdriver.jit_merge_point(y=y, x=x, res=res)
-                if y % 4 == 0:
-                    res = res.switch()
-                res = res.binop(x)
-                y -= 1
-            return res
-        def g(x, y):
-            a1 = f(A(x), y)
-            a2 = f(A(x), y)
-            b1 = f(B(x), y)
-            b2 = f(B(x), y)
-            assert a1.val == a2.val
-            assert b1.val == b2.val
-            return a1.val + b1.val
-        res = self.meta_interp(g, [3, 23])
-        assert res == 7068153
-        self.check_loop_count(6)
-        self.check_loops(guard_true=4, guard_class=0, int_add=2, int_mul=2,
-                         guard_false=2)
-
-    def test_dont_trace_every_iteration(self):
-        myjitdriver = JitDriver(greens = [], reds = ['a', 'b', 'i', 'sa'])
-        
-        def main(a, b):
-            i = sa = 0
-            #while i < 200:
-            while i < 200:
-                myjitdriver.can_enter_jit(a=a, b=b, i=i, sa=sa)
-                myjitdriver.jit_merge_point(a=a, b=b, i=i, sa=sa)
-                if a > 0: pass
-                if b < 2: pass
-                sa += a % b
-                i += 1
-            return sa
-        def g():
-            return main(10, 20) + main(-10, -20)
-        res = self.meta_interp(g, [])
-        assert res == g()
-        self.check_enter_count(2)
-
-    def test_current_trace_length(self):
-        myjitdriver = JitDriver(greens = ['g'], reds = ['x'])
-        @dont_look_inside
-        def residual():
-            print "hi there"
-        @unroll_safe
-        def loop(g):
-            y = 0
-            while y < g:
-                residual()
-                y += 1
-        def f(x, g):
-            n = 0
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x, g=g)
-                myjitdriver.jit_merge_point(x=x, g=g)
-                loop(g)
-                x -= 1
-                n = current_trace_length()
-            return n
-        res = self.meta_interp(f, [5, 8])
-        assert 14 < res < 42
-        res = self.meta_interp(f, [5, 2])
-        assert 4 < res < 14
-
-    def test_compute_identity_hash(self):
-        from pypy.rlib.objectmodel import compute_identity_hash
-        class A(object):
-            pass
-        def f():
-            a = A()
-            return compute_identity_hash(a) == compute_identity_hash(a)
-        res = self.interp_operations(f, [])
-        assert res
-        # a "did not crash" kind of test
-
-    def test_compute_unique_id(self):
-        from pypy.rlib.objectmodel import compute_unique_id
-        class A(object):
-            pass
-        def f():
-            a1 = A()
-            a2 = A()
-            return (compute_unique_id(a1) == compute_unique_id(a1) and
-                    compute_unique_id(a1) != compute_unique_id(a2))
-        res = self.interp_operations(f, [])
-        assert res
-
-    def test_wrap_around_add(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'n'])
-        class A:
-            pass
-        def f(x):
-            n = 0
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x, n=n)
-                myjitdriver.jit_merge_point(x=x, n=n)
-                x += 1
-                n += 1
-            return n
-        res = self.meta_interp(f, [sys.maxint-10])
-        assert res == 11
-        self.check_tree_loop_count(2)
-
-    def test_wrap_around_mul(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'n'])
-        class A:
-            pass
-        def f(x):
-            n = 0
-            while x > 0:
-                myjitdriver.can_enter_jit(x=x, n=n)
-                myjitdriver.jit_merge_point(x=x, n=n)
-                x *= 2
-                n += 1
-            return n
-        res = self.meta_interp(f, [sys.maxint>>10])
-        assert res == 11
-        self.check_tree_loop_count(2)        
-
-    def test_wrap_around_sub(self):
-        myjitdriver = JitDriver(greens = [], reds = ['x', 'n'])
-        class A:
-            pass
-        def f(x):
-            n = 0
-            while x < 0:
-                myjitdriver.can_enter_jit(x=x, n=n)
-                myjitdriver.jit_merge_point(x=x, n=n)
-                x -= 1
-                n += 1
-            return n
-        res = self.meta_interp(f, [10-sys.maxint])
-        assert res == 12
-        self.check_tree_loop_count(2)        
-
-
-
-class TestOOtype(BasicTests, OOJitMixin):
-
-    def test_oohash(self):
-        def f(n):
-            s = ootype.oostring(n, -1)
-            return s.ll_hash()
-        res = self.interp_operations(f, [5])
-        assert res == ootype.oostring(5, -1).ll_hash()
-
-    def test_identityhash(self):
-        A = ootype.Instance("A", ootype.ROOT)
-        def f():
-            obj1 = ootype.new(A)
-            obj2 = ootype.new(A)
-            return ootype.identityhash(obj1) == ootype.identityhash(obj2)
-        assert not f()
-        res = self.interp_operations(f, [])
-        assert not res
-
-    def test_oois(self):
-        A = ootype.Instance("A", ootype.ROOT)
-        def f(n):
-            obj1 = ootype.new(A)
-            if n:
-                obj2 = obj1
-            else:
-                obj2 = ootype.new(A)
-            return obj1 is obj2
-        res = self.interp_operations(f, [0])
-        assert not res
-        res = self.interp_operations(f, [1])
-        assert res
-
-    def test_oostring_instance(self):
-        A = ootype.Instance("A", ootype.ROOT)
-        B = ootype.Instance("B", ootype.ROOT)
-        def f(n):
-            obj1 = ootype.new(A)
-            obj2 = ootype.new(B)
-            s1 = ootype.oostring(obj1, -1)
-            s2 = ootype.oostring(obj2, -1)
-            ch1 = s1.ll_stritem_nonneg(1)
-            ch2 = s2.ll_stritem_nonneg(1)
-            return ord(ch1) + ord(ch2)
-        res = self.interp_operations(f, [0])
-        assert res == ord('A') + ord('B')
-
-    def test_subclassof(self):
-        A = ootype.Instance("A", ootype.ROOT)
-        B = ootype.Instance("B", A)
-        clsA = ootype.runtimeClass(A)
-        clsB = ootype.runtimeClass(B)
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'flag', 'res'])
-
-        def getcls(flag):
-            if flag:
-                return clsA
-            else:
-                return clsB
-
-        def f(flag, n):
-            res = True
-            while n > -100:
-                myjitdriver.can_enter_jit(n=n, flag=flag, res=res)
-                myjitdriver.jit_merge_point(n=n, flag=flag, res=res)
-                cls = getcls(flag)
-                n -= 1
-                res = ootype.subclassof(cls, clsB)
-            return res
-
-        res = self.meta_interp(f, [1, 100],
-                               policy=StopAtXPolicy(getcls),
-                               enable_opts='')
-        assert not res
-        
-        res = self.meta_interp(f, [0, 100],
-                               policy=StopAtXPolicy(getcls),
-                               enable_opts='')
-        assert res
-
-class BaseLLtypeTests(BasicTests):
-
-    def test_identityhash(self):
-        A = lltype.GcStruct("A")
-        def f():
-            obj1 = lltype.malloc(A)
-            obj2 = lltype.malloc(A)
-            return lltype.identityhash(obj1) == lltype.identityhash(obj2)
-        assert not f()
-        res = self.interp_operations(f, [])
-        assert not res
-
-    def test_oops_on_nongc(self):
-        from pypy.rpython.lltypesystem import lltype
-        
-        TP = lltype.Struct('x')
-        def f(i1, i2):
-            p1 = prebuilt[i1]
-            p2 = prebuilt[i2]
-            a = p1 is p2
-            b = p1 is not p2
-            c = bool(p1)
-            d = not bool(p2)
-            return 1000*a + 100*b + 10*c + d
-        prebuilt = [lltype.malloc(TP, flavor='raw', immortal=True)] * 2
-        expected = f(0, 1)
-        assert self.interp_operations(f, [0, 1]) == expected
-
-    def test_casts(self):
-        py.test.skip("xxx fix or kill")
-        if not self.basic:
-            py.test.skip("test written in a style that "
-                         "means it's frontend only")
-        from pypy.rpython.lltypesystem import lltype, llmemory, rffi
-
-        TP = lltype.GcStruct('S1')
-        def f(p):
-            n = lltype.cast_ptr_to_int(p)
-            return n
-        x = lltype.malloc(TP)
-        xref = lltype.cast_opaque_ptr(llmemory.GCREF, x)
-        res = self.interp_operations(f, [xref])
-        y = llmemory.cast_ptr_to_adr(x)
-        y = llmemory.cast_adr_to_int(y)
-        assert rffi.get_real_int(res) == rffi.get_real_int(y)
-        #
-        TP = lltype.Struct('S2')
-        prebuilt = [lltype.malloc(TP, immortal=True),
-                    lltype.malloc(TP, immortal=True)]
-        def f(x):
-            p = prebuilt[x]
-            n = lltype.cast_ptr_to_int(p)
-            return n
-        res = self.interp_operations(f, [1])
-        y = llmemory.cast_ptr_to_adr(prebuilt[1])
-        y = llmemory.cast_adr_to_int(y)
-        assert rffi.get_real_int(res) == rffi.get_real_int(y)
-
-    def test_collapsing_ptr_eq(self):
-        S = lltype.GcStruct('S')
-        p = lltype.malloc(S)
-        driver = JitDriver(greens = [], reds = ['n', 'x'])
-
-        def f(n, x):
-            while n > 0:
-                driver.can_enter_jit(n=n, x=x)
-                driver.jit_merge_point(n=n, x=x)
-                if x:
-                    n -= 1
-                n -= 1
-
-        def main():
-            f(10, p)
-            f(10, lltype.nullptr(S))
-
-        self.meta_interp(main, [])
-
-    def test_enable_opts(self):
-        jitdriver = JitDriver(greens = [], reds = ['a'])
-
-        class A(object):
-            def __init__(self, i):
-                self.i = i
-
-        def f():
-            a = A(0)
-            
-            while a.i < 10:
-                jitdriver.jit_merge_point(a=a)
-                jitdriver.can_enter_jit(a=a)
-                a = A(a.i + 1)
-
-        self.meta_interp(f, [])
-        self.check_loops(new_with_vtable=0)
-        self.meta_interp(f, [], enable_opts='')
-        self.check_loops(new_with_vtable=1)
-
-class TestLLtype(BaseLLtypeTests, LLJitMixin):
-    pass

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
@@ -205,7 +205,7 @@
         v2 = self.getvalue(op.getarg(1))
         if v1.intbound.known_lt(v2.intbound):
             self.make_constant_int(op.result, 1)
-        elif v1.intbound.known_ge(v2.intbound):
+        elif v1.intbound.known_ge(v2.intbound) or v1 is v2:
             self.make_constant_int(op.result, 0)
         else:
             self.emit_operation(op)
@@ -215,7 +215,7 @@
         v2 = self.getvalue(op.getarg(1))
         if v1.intbound.known_gt(v2.intbound):
             self.make_constant_int(op.result, 1)
-        elif v1.intbound.known_le(v2.intbound):
+        elif v1.intbound.known_le(v2.intbound) or v1 is v2:
             self.make_constant_int(op.result, 0)
         else:
             self.emit_operation(op)
@@ -223,7 +223,7 @@
     def optimize_INT_LE(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
-        if v1.intbound.known_le(v2.intbound):
+        if v1.intbound.known_le(v2.intbound) or v1 is v2:
             self.make_constant_int(op.result, 1)
         elif v1.intbound.known_gt(v2.intbound):
             self.make_constant_int(op.result, 0)
@@ -233,7 +233,7 @@
     def optimize_INT_GE(self, op):
         v1 = self.getvalue(op.getarg(0))
         v2 = self.getvalue(op.getarg(1))
-        if v1.intbound.known_ge(v2.intbound):
+        if v1.intbound.known_ge(v2.intbound) or v1 is v2:
             self.make_constant_int(op.result, 1)
         elif v1.intbound.known_lt(v2.intbound):
             self.make_constant_int(op.result, 0)

diff --git a/pypy/objspace/flow/test/test_objspace.py b/pypy/objspace/flow/test/test_objspace.py
--- a/pypy/objspace/flow/test/test_objspace.py
+++ b/pypy/objspace/flow/test/test_objspace.py
@@ -1,8 +1,8 @@
 from __future__ import with_statement
 import new
 import py
-from pypy.objspace.flow.model import Constant, Block, Link, Variable, traverse
-from pypy.objspace.flow.model import flatten, mkentrymap, c_last_exception
+from pypy.objspace.flow.model import Constant, Block, Link, Variable
+from pypy.objspace.flow.model import mkentrymap, c_last_exception
 from pypy.interpreter.argument import Arguments
 from pypy.translator.simplify import simplify_graph
 from pypy.objspace.flow.objspace import FlowObjSpace, error
@@ -37,12 +37,10 @@
 
     def all_operations(self, graph):
         result = {}
-        def visit(node):
-            if isinstance(node, Block):
-                for op in node.operations:
-                    result.setdefault(op.opname, 0)
-                    result[op.opname] += 1
-        traverse(visit, graph)
+        for node in graph.iterblocks():
+            for op in node.operations:
+                result.setdefault(op.opname, 0)
+                result[op.opname] += 1
         return result
 
 
@@ -246,12 +244,9 @@
         x = self.codetest(self.implicitException)
         simplify_graph(x)
         self.show(x)
-        def cannot_reach_exceptblock(link):
-            if isinstance(link, Link):
-                assert link.target is not x.exceptblock
-        traverse(cannot_reach_exceptblock, x)
+        for link in x.iterlinks():
+            assert link.target is not x.exceptblock
 
-    
     def implicitAttributeError(x):
         try:
             x = getattr(x, "y")
@@ -263,10 +258,8 @@
         x = self.codetest(self.implicitAttributeError)
         simplify_graph(x)
         self.show(x)
-        def cannot_reach_exceptblock(link):
-            if isinstance(link, Link):
-                assert link.target is not x.exceptblock
-        traverse(cannot_reach_exceptblock, x)
+        for link in x.iterlinks():
+            assert link.target is not x.exceptblock
 
     #__________________________________________________________
     def implicitException_int_and_id(x):
@@ -311,14 +304,12 @@
         simplify_graph(x)
         self.show(x)
         found = {}
-        def find_exceptions(link):
-            if isinstance(link, Link):
+        for link in x.iterlinks():
                 if link.target is x.exceptblock:
                     if isinstance(link.args[0], Constant):
                         found[link.args[0].value] = True
                     else:
                         found[link.exitcase] = None
-        traverse(find_exceptions, x)
         assert found == {IndexError: True, KeyError: True, Exception: None}
     
     def reraiseAnything(x):
@@ -332,12 +323,10 @@
         simplify_graph(x)
         self.show(x)
         found = {}
-        def find_exceptions(link):
-            if isinstance(link, Link):
+        for link in x.iterlinks():
                 if link.target is x.exceptblock:
                     assert isinstance(link.args[0], Constant)
                     found[link.args[0].value] = True
-        traverse(find_exceptions, x)
         assert found == {ValueError: True, ZeroDivisionError: True, OverflowError: True}
 
     def loop_in_bare_except_bug(lst):
@@ -521,11 +510,9 @@
 
     def test_jump_target_specialization(self):
         x = self.codetest(self.jump_target_specialization)
-        def visitor(node):
-            if isinstance(node, Block):
-                for op in node.operations:
-                    assert op.opname != 'mul', "mul should have disappeared"
-        traverse(visitor, x)
+        for block in x.iterblocks():
+            for op in block.operations:
+                assert op.opname != 'mul', "mul should have disappeared"
 
     #__________________________________________________________
     def highly_branching_example(a,b,c,d,e,f,g,h,i,j):
@@ -573,7 +560,8 @@
 
     def test_highly_branching_example(self):
         x = self.codetest(self.highly_branching_example)
-        assert len(flatten(x)) < 60   # roughly 20 blocks + 30 links
+        # roughly 20 blocks + 30 links
+        assert len(list(x.iterblocks())) + len(list(x.iterlinks())) < 60
 
     #__________________________________________________________
     def test_unfrozen_user_class1(self):
@@ -589,11 +577,9 @@
         graph = self.codetest(f)
 
         results = []
-        def visit(link):
-            if isinstance(link, Link):
-                if link.target == graph.returnblock:
-                    results.extend(link.args)
-        traverse(visit, graph)
+        for link in graph.iterlinks():
+            if link.target == graph.returnblock:
+                results.extend(link.args)
         assert len(results) == 2
 
     def test_unfrozen_user_class2(self):
@@ -607,11 +593,9 @@
         graph = self.codetest(f)
 
         results = []
-        def visit(link):
-            if isinstance(link, Link):
-                if link.target == graph.returnblock:
-                    results.extend(link.args)
-        traverse(visit, graph)
+        for link in graph.iterlinks():
+            if link.target == graph.returnblock:
+                results.extend(link.args)
         assert not isinstance(results[0], Constant)
 
     def test_frozen_user_class1(self):
@@ -630,11 +614,9 @@
         graph = self.codetest(f)
 
         results = []
-        def visit(link):
-            if isinstance(link, Link):
-                if link.target == graph.returnblock:
-                    results.extend(link.args)
-        traverse(visit, graph)
+        for link in graph.iterlinks():
+            if link.target == graph.returnblock:
+                results.extend(link.args)
         assert len(results) == 1
 
     def test_frozen_user_class2(self):
@@ -650,11 +632,9 @@
         graph = self.codetest(f)
 
         results = []
-        def visit(link):
-            if isinstance(link, Link):
-                if link.target == graph.returnblock:
-                    results.extend(link.args)
-        traverse(visit, graph)
+        for link in graph.iterlinks():
+            if link.target == graph.returnblock:
+                results.extend(link.args)
         assert results == [Constant(4)]
 
     def test_const_star_call(self):
@@ -663,14 +643,9 @@
         def f():
             return g(1,*(2,3))
         graph = self.codetest(f)
-        call_args = []
-        def visit(block):
-            if isinstance(block, Block):
-                for op in block.operations:
-                    if op.opname == "call_args":
-                        call_args.append(op)
-        traverse(visit, graph)
-        assert not call_args
+        for block in graph.iterblocks():
+            for op in block.operations:
+                assert not op.opname == "call_args"
 
     def test_catch_importerror_1(self):
         def f():
@@ -997,11 +972,9 @@
         simplify_graph(x)
         self.show(x)
         excfound = []
-        def check(link):
-            if isinstance(link, Link):
-                if link.target is x.exceptblock:
-                    excfound.append(link.exitcase)
-        traverse(check, x)
+        for link in x.iterlinks():
+            if link.target is x.exceptblock:
+                excfound.append(link.exitcase)
         assert len(excfound) == 2
         excfound.sort()
         expected = [Exception, AttributeError]
@@ -1019,11 +992,9 @@
         simplify_graph(x)
         self.show(x)
         excfound = []
-        def check(link):
-            if isinstance(link, Link):
-                if link.target is x.exceptblock:
-                    excfound.append(link.exitcase)
-        traverse(check, x)
+        for link in x.iterlinks():
+            if link.target is x.exceptblock:
+                excfound.append(link.exitcase)
         assert len(excfound) == 2
         excfound.sort()
         expected = [Exception, TypeError]

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
@@ -381,6 +381,9 @@
 
 def _setup():
     global _old_raw_input
+    if _old_raw_input is not None:
+        return # don't run _setup twice
+    
     try:
         f_in = sys.stdin.fileno()
         f_out = sys.stdout.fileno()
@@ -401,4 +404,5 @@
         _old_raw_input = __builtin__.raw_input
         __builtin__.raw_input = _wrapper.raw_input
 
+_old_raw_input = None
 _setup()

diff --git a/pypy/jit/backend/x86/test/test_assembler.py b/pypy/jit/backend/x86/test/test_assembler.py
--- a/pypy/jit/backend/x86/test/test_assembler.py
+++ b/pypy/jit/backend/x86/test/test_assembler.py
@@ -140,7 +140,7 @@
     xmmregisters = lltype.malloc(rffi.LONGP.TO, 16+ACTUAL_CPU.NUM_REGS+1,
                                  flavor='raw', immortal=True)
     registers = rffi.ptradd(xmmregisters, 16)
-    stacklen = baseloc + 10
+    stacklen = baseloc + 30
     stack = lltype.malloc(rffi.LONGP.TO, stacklen, flavor='raw',
                           immortal=True)
     expected_ints = [0] * len(content)

diff --git a/pypy/translator/backendopt/test/test_malloc.py b/pypy/translator/backendopt/test/test_malloc.py
--- a/pypy/translator/backendopt/test/test_malloc.py
+++ b/pypy/translator/backendopt/test/test_malloc.py
@@ -3,7 +3,7 @@
 from pypy.translator.backendopt.all import backend_optimizations
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.translator import simplify
-from pypy.objspace.flow.model import checkgraph, flatten, Block, mkentrymap
+from pypy.objspace.flow.model import checkgraph, Block, mkentrymap
 from pypy.rpython.llinterp import LLInterpreter
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython.ootypesystem import ootype
@@ -22,8 +22,7 @@
         remover = cls.MallocRemover()
         checkgraph(graph)
         count1 = count2 = 0
-        for node in flatten(graph):
-            if isinstance(node, Block):
+        for node in graph.iterblocks():
                 for op in node.operations:
                     if op.opname == cls.MallocRemover.MALLOC_OP:
                         S = op.args[0].value
@@ -47,7 +46,7 @@
             auto_inline_graphs(t, t.graphs, inline)
         if option.view:
             t.view()
-        # to detect missing keepalives and broken intermediate graphs,
+        # to detect broken intermediate graphs,
         # we do the loop ourselves instead of calling remove_simple_mallocs()
         while True:
             progress = remover.remove_mallocs_once(graph)
@@ -158,18 +157,6 @@
     type_system = 'lltype'
     MallocRemover = LLTypeMallocRemover
 
-    def test_with_keepalive(self):
-        from pypy.rlib.objectmodel import keepalive_until_here
-        def fn1(x, y):
-            if x > 0:
-                t = x+y, x-y
-            else:
-                t = x-y, x+y
-            s, d = t
-            keepalive_until_here(t)
-            return s*d
-        self.check(fn1, [int, int], [15, 10], 125)
-
     def test_dont_remove_with__del__(self):
         import os
         delcalls = [0]
@@ -199,50 +186,6 @@
         op = graph.startblock.exits[0].target.exits[1].target.operations[0]
         assert op.opname == "malloc"
 
-    def test_add_keepalives(self):
-        class A:
-            pass
-        SMALL = lltype.Struct('SMALL', ('x', lltype.Signed))
-        BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL))
-        def fn7(i):
-            big = lltype.malloc(BIG)
-            a = A()
-            a.big = big
-            a.small = big.s
-            a.small.x = 0
-            while i > 0:
-                a.small.x += i
-                i -= 1
-            return a.small.x
-        self.check(fn7, [int], [10], 55, must_be_removed=False)
-
-    def test_getsubstruct(self):
-        py.test.skip("fails because of the interior structure changes")
-        SMALL = lltype.Struct('SMALL', ('x', lltype.Signed))
-        BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL))
-
-        def fn(n1, n2):
-            b = lltype.malloc(BIG)
-            b.z = n1
-            b.s.x = n2
-            return b.z - b.s.x
-
-        self.check(fn, [int, int], [100, 58], 42)
-
-    def test_fixedsizearray(self):
-        py.test.skip("fails because of the interior structure changes")
-        A = lltype.FixedSizeArray(lltype.Signed, 3)
-        S = lltype.GcStruct('S', ('a', A))
-
-        def fn(n1, n2):
-            s = lltype.malloc(S)
-            a = s.a
-            a[0] = n1
-            a[2] = n2
-            return a[0]-a[2]
-
-        self.check(fn, [int, int], [100, 42], 58)
-
     def test_wrapper_cannot_be_removed(self):
         SMALL = lltype.OpaqueType('SMALL')
         BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL))

diff --git a/pypy/rlib/_rweakvaldict.py b/pypy/rlib/_rweakvaldict.py
--- a/pypy/rlib/_rweakvaldict.py
+++ b/pypy/rlib/_rweakvaldict.py
@@ -113,7 +113,7 @@
     @jit.dont_look_inside
     def ll_get(self, d, llkey):
         hash = self.ll_keyhash(llkey)
-        i = rdict.ll_dict_lookup(d, llkey, hash)
+        i = rdict.ll_dict_lookup(d, llkey, hash) & rdict.MASK
         #llop.debug_print(lltype.Void, i, 'get')
         valueref = d.entries[i].value
         if valueref:
@@ -132,7 +132,7 @@
     def ll_set_nonnull(self, d, llkey, llvalue):
         hash = self.ll_keyhash(llkey)
         valueref = weakref_create(llvalue)    # GC effects here, before the rest
-        i = rdict.ll_dict_lookup(d, llkey, hash)
+        i = rdict.ll_dict_lookup(d, llkey, hash) & rdict.MASK
         everused = d.entries.everused(i)
         d.entries[i].key = llkey
         d.entries[i].value = valueref
@@ -146,7 +146,7 @@
     @jit.dont_look_inside
     def ll_set_null(self, d, llkey):
         hash = self.ll_keyhash(llkey)
-        i = rdict.ll_dict_lookup(d, llkey, hash)
+        i = rdict.ll_dict_lookup(d, llkey, hash) & rdict.MASK
         if d.entries.everused(i):
             # If the entry was ever used, clean up its key and value.
             # We don't store a NULL value, but a dead weakref, because

diff --git a/pypy/translator/cli/test/test_list.py b/pypy/translator/cli/test/test_list.py
--- a/pypy/translator/cli/test/test_list.py
+++ b/pypy/translator/cli/test/test_list.py
@@ -7,7 +7,10 @@
     def test_recursive(self):
         py.test.skip("CLI doesn't support recursive lists")
 
-    def test_getitem_exc(self):
+    def test_getitem_exc_1(self):
+        py.test.skip('fixme!')
+
+    def test_getitem_exc_2(self):
         py.test.skip('fixme!')
 
     def test_list_unsigned(self):

diff --git a/pypy/rpython/memory/gctransform/framework.py b/pypy/rpython/memory/gctransform/framework.py
--- a/pypy/rpython/memory/gctransform/framework.py
+++ b/pypy/rpython/memory/gctransform/framework.py
@@ -9,6 +9,7 @@
 from pypy.rlib.rarithmetic import ovfcheck
 from pypy.rlib import rstack, rgc
 from pypy.rlib.debug import ll_assert
+from pypy.rlib.objectmodel import we_are_translated
 from pypy.translator.backendopt import graphanalyze
 from pypy.translator.backendopt.support import var_needsgc
 from pypy.annotation import model as annmodel
@@ -152,8 +153,13 @@
             # for regular translation: pick the GC from the config
             GCClass, GC_PARAMS = choose_gc_from_config(translator.config)
 
+        self.root_stack_jit_hook = None
         if hasattr(translator, '_jit2gc'):
             self.layoutbuilder = translator._jit2gc['layoutbuilder']
+            try:
+                self.root_stack_jit_hook = translator._jit2gc['rootstackhook']
+            except KeyError:
+                pass
         else:
             self.layoutbuilder = TransformerLayoutBuilder(translator, GCClass)
         self.layoutbuilder.transformer = self
@@ -501,6 +507,10 @@
         s_gc = self.translator.annotator.bookkeeper.valueoftype(GCClass)
         r_gc = self.translator.rtyper.getrepr(s_gc)
         self.c_const_gc = rmodel.inputconst(r_gc, self.gcdata.gc)
+        s_gc_data = self.translator.annotator.bookkeeper.valueoftype(
+            gctypelayout.GCData)
+        r_gc_data = self.translator.rtyper.getrepr(s_gc_data)
+        self.c_const_gcdata = rmodel.inputconst(r_gc_data, self.gcdata)
         self.malloc_zero_filled = GCClass.malloc_zero_filled
 
         HDR = self.HDR = self.gcdata.gc.gcheaderbuilder.HDR
@@ -794,6 +804,15 @@
                              resulttype=llmemory.Address)
         hop.genop('adr_add', [v_gc_adr, c_ofs], resultvar=op.result)
 
+    def gct_gc_adr_of_root_stack_top(self, hop):
+        op = hop.spaceop
+        ofs = llmemory.offsetof(self.c_const_gcdata.concretetype.TO,
+                                'inst_root_stack_top')
+        c_ofs = rmodel.inputconst(lltype.Signed, ofs)
+        v_gcdata_adr = hop.genop('cast_ptr_to_adr', [self.c_const_gcdata],
+                                 resulttype=llmemory.Address)
+        hop.genop('adr_add', [v_gcdata_adr, c_ofs], resultvar=op.result)
+
     def gct_gc_x_swap_pool(self, hop):
         op = hop.spaceop
         [v_malloced] = op.args
@@ -1363,6 +1382,14 @@
             return top
         self.decr_stack = decr_stack
 
+        self.rootstackhook = gctransformer.root_stack_jit_hook
+        if self.rootstackhook is None:
+            def collect_stack_root(callback, gc, addr):
+                if gc.points_to_valid_gc_object(addr):
+                    callback(gc, addr)
+                return sizeofaddr
+            self.rootstackhook = collect_stack_root
+
     def push_stack(self, addr):
         top = self.incr_stack(1)
         top.address[0] = addr
@@ -1372,10 +1399,7 @@
         return top.address[0]
 
     def allocate_stack(self):
-        result = llmemory.raw_malloc(self.rootstacksize)
-        if result:
-            llmemory.raw_memclear(result, self.rootstacksize)
-        return result
+        return llmemory.raw_malloc(self.rootstacksize)
 
     def setup_root_walker(self):
         stackbase = self.allocate_stack()
@@ -1387,12 +1411,11 @@
     def walk_stack_roots(self, collect_stack_root):
         gcdata = self.gcdata
         gc = self.gc
+        rootstackhook = self.rootstackhook
         addr = gcdata.root_stack_base
         end = gcdata.root_stack_top
         while addr != end:
-            if gc.points_to_valid_gc_object(addr):
-                collect_stack_root(gc, addr)
-            addr += sizeofaddr
+            addr += rootstackhook(collect_stack_root, gc, addr)
         if self.collect_stacks_from_other_threads is not None:
             self.collect_stacks_from_other_threads(collect_stack_root)
 
@@ -1499,12 +1522,11 @@
                 # collect all valid stacks from the dict (the entry
                 # corresponding to the current thread is not valid)
                 gc = self.gc
+                rootstackhook = self.rootstackhook
                 end = stacktop - sizeofaddr
                 addr = end.address[0]
                 while addr != end:
-                    if gc.points_to_valid_gc_object(addr):
-                        callback(gc, addr)
-                    addr += sizeofaddr
+                    addr += rootstackhook(callback, gc, addr)
 
         def collect_more_stacks(callback):
             ll_assert(get_aid() == gcdata.active_thread,

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
@@ -19,7 +19,8 @@
 from pypy.jit.backend.llsupport.descr import BaseCallDescr, BaseSizeDescr
 from pypy.jit.backend.llsupport.regalloc import FrameManager, RegisterManager,\
      TempBox
-from pypy.jit.backend.x86.arch import WORD, FRAME_FIXED_SIZE, IS_X86_32, IS_X86_64
+from pypy.jit.backend.x86.arch import WORD, FRAME_FIXED_SIZE
+from pypy.jit.backend.x86.arch import IS_X86_32, IS_X86_64, MY_COPY_OF_REGS
 from pypy.rlib.rarithmetic import r_longlong, r_uint
 
 class X86RegisterManager(RegisterManager):
@@ -34,6 +35,12 @@
         esi: 2,
         edi: 3,
     }
+    REGLOC_TO_COPY_AREA_OFS = {
+        ecx: MY_COPY_OF_REGS + 0 * WORD,
+        ebx: MY_COPY_OF_REGS + 1 * WORD,
+        esi: MY_COPY_OF_REGS + 2 * WORD,
+        edi: MY_COPY_OF_REGS + 3 * WORD,
+    }
 
     def call_result_location(self, v):
         return eax
@@ -61,6 +68,19 @@
         r14: 4,
         r15: 5,
     }
+    REGLOC_TO_COPY_AREA_OFS = {
+        ecx: MY_COPY_OF_REGS + 0 * WORD,
+        ebx: MY_COPY_OF_REGS + 1 * WORD,
+        esi: MY_COPY_OF_REGS + 2 * WORD,
+        edi: MY_COPY_OF_REGS + 3 * WORD,
+        r8:  MY_COPY_OF_REGS + 4 * WORD,
+        r9:  MY_COPY_OF_REGS + 5 * WORD,
+        r10: MY_COPY_OF_REGS + 6 * WORD,
+        r12: MY_COPY_OF_REGS + 7 * WORD,
+        r13: MY_COPY_OF_REGS + 8 * WORD,
+        r14: MY_COPY_OF_REGS + 9 * WORD,
+        r15: MY_COPY_OF_REGS + 10 * WORD,
+    }
 
 class X86XMMRegisterManager(RegisterManager):
 
@@ -117,6 +137,16 @@
         else:
             return 1
 
+if WORD == 4:
+    gpr_reg_mgr_cls = X86RegisterManager
+    xmm_reg_mgr_cls = X86XMMRegisterManager
+elif WORD == 8:
+    gpr_reg_mgr_cls = X86_64_RegisterManager
+    xmm_reg_mgr_cls = X86_64_XMMRegisterManager
+else:
+    raise AssertionError("Word size should be 4 or 8")
+
+
 class RegAlloc(object):
 
     def __init__(self, assembler, translate_support_code=False):
@@ -135,16 +165,6 @@
         # compute longevity of variables
         longevity = self._compute_vars_longevity(inputargs, operations)
         self.longevity = longevity
-        # XXX
-        if cpu.WORD == 4:
-            gpr_reg_mgr_cls = X86RegisterManager
-            xmm_reg_mgr_cls = X86XMMRegisterManager
-        elif cpu.WORD == 8:
-            gpr_reg_mgr_cls = X86_64_RegisterManager
-            xmm_reg_mgr_cls = X86_64_XMMRegisterManager
-        else:
-            raise AssertionError("Word size should be 4 or 8")
-            
         self.rm = gpr_reg_mgr_cls(longevity,
                                   frame_manager = self.fm,
                                   assembler = self.assembler)
@@ -738,8 +758,12 @@
 
     def _call(self, op, arglocs, force_store=[], guard_not_forced_op=None):
         save_all_regs = guard_not_forced_op is not None
+        self.xrm.before_call(force_store, save_all_regs=save_all_regs)
+        if not save_all_regs:
+            gcrootmap = gc_ll_descr = self.assembler.cpu.gc_ll_descr.gcrootmap
+            if gcrootmap and gcrootmap.is_shadow_stack:
+                save_all_regs = 2
         self.rm.before_call(force_store, save_all_regs=save_all_regs)
-        self.xrm.before_call(force_store, save_all_regs=save_all_regs)
         if op.result is not None:
             if op.result.type == FLOAT:
                 resloc = self.xrm.after_call(op.result)
@@ -836,31 +860,53 @@
         self.PerformDiscard(op, arglocs)
         self.rm.possibly_free_vars_for_op(op)
 
-    def _fastpath_malloc(self, op, descr):
+    def fastpath_malloc_fixedsize(self, op, descr):
         assert isinstance(descr, BaseSizeDescr)
+        self._do_fastpath_malloc(op, descr.size, descr.tid)
+
+    def fastpath_malloc_varsize(self, op, arraydescr, num_elem):
+        assert isinstance(arraydescr, BaseArrayDescr)
+        ofs_length = arraydescr.get_ofs_length(self.translate_support_code)
+        basesize = arraydescr.get_base_size(self.translate_support_code)
+        itemsize = arraydescr.get_item_size(self.translate_support_code)
+        size = basesize + itemsize * num_elem
+        self._do_fastpath_malloc(op, size, arraydescr.tid)
+        self.assembler.set_new_array_length(eax, ofs_length, imm(num_elem))
+
+    def _do_fastpath_malloc(self, op, size, tid):
         gc_ll_descr = self.assembler.cpu.gc_ll_descr
         self.rm.force_allocate_reg(op.result, selected_reg=eax)
-        # We need to force-allocate each of save_around_call_regs now.
-        # The alternative would be to save and restore them around the
-        # actual call to malloc(), in the rare case where we need to do
-        # it; however, mark_gc_roots() would need to be adapted to know
-        # where the variables end up being saved.  Messy.
-        for reg in self.rm.save_around_call_regs:
-            if reg is not eax:
-                tmp_box = TempBox()
-                self.rm.force_allocate_reg(tmp_box, selected_reg=reg)
-                self.rm.possibly_free_var(tmp_box)
 
-        self.assembler.malloc_cond_fixedsize(
+        if gc_ll_descr.gcrootmap and gc_ll_descr.gcrootmap.is_shadow_stack:
+            # ---- shadowstack ----
+            # We need edx as a temporary, but otherwise don't save any more
+            # register.  See comments in _build_malloc_slowpath().
+            tmp_box = TempBox()
+            self.rm.force_allocate_reg(tmp_box, selected_reg=edx)
+            self.rm.possibly_free_var(tmp_box)
+        else:
+            # ---- asmgcc ----
+            # We need to force-allocate each of save_around_call_regs now.
+            # The alternative would be to save and restore them around the
+            # actual call to malloc(), in the rare case where we need to do
+            # it; however, mark_gc_roots() would need to be adapted to know
+            # where the variables end up being saved.  Messy.
+            for reg in self.rm.save_around_call_regs:
+                if reg is not eax:
+                    tmp_box = TempBox()
+                    self.rm.force_allocate_reg(tmp_box, selected_reg=reg)
+                    self.rm.possibly_free_var(tmp_box)
+
+        self.assembler.malloc_cond(
             gc_ll_descr.get_nursery_free_addr(),
             gc_ll_descr.get_nursery_top_addr(),
-            descr.size, descr.tid,
+            size, tid,
             )
 
     def consider_new(self, op):
         gc_ll_descr = self.assembler.cpu.gc_ll_descr
         if gc_ll_descr.can_inline_malloc(op.getdescr()):
-            self._fastpath_malloc(op, op.getdescr())
+            self.fastpath_malloc_fixedsize(op, op.getdescr())
         else:
             args = gc_ll_descr.args_for_new(op.getdescr())
             arglocs = [imm(x) for x in args]
@@ -870,7 +916,7 @@
         classint = op.getarg(0).getint()
         descrsize = heaptracker.vtable2descr(self.assembler.cpu, classint)
         if self.assembler.cpu.gc_ll_descr.can_inline_malloc(descrsize):
-            self._fastpath_malloc(op, descrsize)
+            self.fastpath_malloc_fixedsize(op, descrsize)
             self.assembler.set_vtable(eax, imm(classint))
             # result of fastpath malloc is in eax
         else:
@@ -929,16 +975,25 @@
         gc_ll_descr = self.assembler.cpu.gc_ll_descr
         if gc_ll_descr.get_funcptr_for_newarray is not None:
             # framework GC
-            args = self.assembler.cpu.gc_ll_descr.args_for_new_array(op.getdescr())
+            box_num_elem = op.getarg(0)
+            if isinstance(box_num_elem, ConstInt):
+                num_elem = box_num_elem.value
+                if gc_ll_descr.can_inline_malloc_varsize(op.getdescr(),
+                                                         num_elem):
+                    self.fastpath_malloc_varsize(op, op.getdescr(), num_elem)
+                    return
+            args = self.assembler.cpu.gc_ll_descr.args_for_new_array(
+                op.getdescr())
             arglocs = [imm(x) for x in args]
-            arglocs.append(self.loc(op.getarg(0)))
-            return self._call(op, arglocs)
+            arglocs.append(self.loc(box_num_elem))
+            self._call(op, arglocs)
+            return
         # boehm GC (XXX kill the following code at some point)
         itemsize, basesize, ofs_length, _, _ = (
             self._unpack_arraydescr(op.getdescr()))
         scale_of_field = _get_scale(itemsize)
-        return self._malloc_varsize(basesize, ofs_length, scale_of_field,
-                                    op.getarg(0), op.result)
+        self._malloc_varsize(basesize, ofs_length, scale_of_field,
+                             op.getarg(0), op.result)
 
     def _unpack_arraydescr(self, arraydescr):
         assert isinstance(arraydescr, BaseArrayDescr)
@@ -1132,7 +1187,7 @@
         # call memcpy()
         self.rm.before_call()
         self.xrm.before_call()
-        self.assembler._emit_call(imm(self.assembler.memcpy_addr),
+        self.assembler._emit_call(-1, imm(self.assembler.memcpy_addr),
                                   [dstaddr_loc, srcaddr_loc, length_loc])
         self.rm.possibly_free_var(length_box)
         self.rm.possibly_free_var(dstaddr_box)
@@ -1200,18 +1255,24 @@
     def consider_jit_debug(self, op):
         pass
 
-    def get_mark_gc_roots(self, gcrootmap):
+    def get_mark_gc_roots(self, gcrootmap, use_copy_area=False):
         shape = gcrootmap.get_basic_shape(IS_X86_64)
         for v, val in self.fm.frame_bindings.items():
             if (isinstance(v, BoxPtr) and self.rm.stays_alive(v)):
                 assert isinstance(val, StackLoc)
-                gcrootmap.add_ebp_offset(shape, get_ebp_ofs(val.position))
+                gcrootmap.add_frame_offset(shape, get_ebp_ofs(val.position))
         for v, reg in self.rm.reg_bindings.items():
             if reg is eax:
                 continue      # ok to ignore this one
             if (isinstance(v, BoxPtr) and self.rm.stays_alive(v)):
-                assert reg in self.rm.REGLOC_TO_GCROOTMAP_REG_INDEX
-                gcrootmap.add_callee_save_reg(shape, self.rm.REGLOC_TO_GCROOTMAP_REG_INDEX[reg])
+                if use_copy_area:
+                    assert reg in self.rm.REGLOC_TO_COPY_AREA_OFS
+                    area_offset = self.rm.REGLOC_TO_COPY_AREA_OFS[reg]
+                    gcrootmap.add_frame_offset(shape, area_offset)
+                else:
+                    assert reg in self.rm.REGLOC_TO_GCROOTMAP_REG_INDEX
+                    gcrootmap.add_callee_save_reg(
+                        shape, self.rm.REGLOC_TO_GCROOTMAP_REG_INDEX[reg])
         return gcrootmap.compress_callshape(shape,
                                             self.assembler.datablockwrapper)
 

diff --git a/pypy/module/cpyext/__init__.py b/pypy/module/cpyext/__init__.py
--- a/pypy/module/cpyext/__init__.py
+++ b/pypy/module/cpyext/__init__.py
@@ -46,6 +46,7 @@
 import pypy.module.cpyext.complexobject
 import pypy.module.cpyext.weakrefobject
 import pypy.module.cpyext.funcobject
+import pypy.module.cpyext.frameobject
 import pypy.module.cpyext.classobject
 import pypy.module.cpyext.pypyintf
 import pypy.module.cpyext.memoryobject

diff --git a/pypy/translator/backendopt/mallocprediction.py b/pypy/translator/backendopt/mallocprediction.py
--- a/pypy/translator/backendopt/mallocprediction.py
+++ b/pypy/translator/backendopt/mallocprediction.py
@@ -176,7 +176,6 @@
             break
         count += newcount
     for graph in graphs:
-        removenoops.remove_superfluous_keep_alive(graph)
         removenoops.remove_duplicate_casts(graph, translator)
     return count
 

diff --git a/pypy/jit/tl/pypyjit_child.py b/pypy/jit/tl/pypyjit_child.py
--- a/pypy/jit/tl/pypyjit_child.py
+++ b/pypy/jit/tl/pypyjit_child.py
@@ -2,7 +2,6 @@
 from pypy.rpython.lltypesystem import lltype
 from pypy.jit.metainterp import warmspot
 from pypy.module.pypyjit.policy import PyPyJitPolicy
-from pypy.rlib.jit import OPTIMIZER_FULL, OPTIMIZER_NO_UNROLL
 
 
 def run_child(glob, loc):
@@ -34,6 +33,5 @@
     option.view = True
     warmspot.jittify_and_run(interp, graph, [], policy=policy,
                              listops=True, CPUClass=CPUClass,
-                             backendopt=True, inline=True,
-                             optimizer=OPTIMIZER_FULL)
+                             backendopt=True, inline=True)
 

diff --git a/pypy/translator/goal/translate.py b/pypy/translator/goal/translate.py
--- a/pypy/translator/goal/translate.py
+++ b/pypy/translator/goal/translate.py
@@ -285,6 +285,15 @@
         elif drv.exe_name is None and '__name__' in targetspec_dic:
             drv.exe_name = targetspec_dic['__name__'] + '-%(backend)s'
 
+        # Double check to ensure we are not overwriting the current interpreter
+        try:
+            exe_name = str(drv.compute_exe_name())
+            assert not os.path.samefile(exe_name, sys.executable), (
+                'Output file %r is the currently running '
+                'interpreter (use --output=...)'% exe_name)
+        except OSError:
+            pass
+
         goals = translateconfig.goals
         try:
             drv.proceed(goals)

diff --git a/pypy/doc/config/objspace.extmodules.rst b/pypy/doc/config/objspace.extmodules.rst
new file mode 100644
--- /dev/null
+++ b/pypy/doc/config/objspace.extmodules.rst
@@ -0,0 +1,12 @@
+You can pass a comma-separated list of third-party builtin modules
+which should be translated along with the standard modules within
+``pypy.module``.
+
+The module names need to be fully qualified (i.e. have a ``.`` in them),
+be on the ``$PYTHONPATH`` and not conflict with any existing ones, e.g.
+``mypkg.somemod``.
+
+Once translated, the module will be accessible with a simple::
+
+    import somemod
+

diff --git a/pypy/jit/codewriter/test/test_regalloc.py b/pypy/jit/codewriter/test/test_regalloc.py
--- a/pypy/jit/codewriter/test/test_regalloc.py
+++ b/pypy/jit/codewriter/test/test_regalloc.py
@@ -9,7 +9,6 @@
 from pypy.objspace.flow.model import c_last_exception
 from pypy.rpython.lltypesystem import lltype, llmemory, rclass
 from pypy.rlib.rarithmetic import ovfcheck
-from pypy.rlib.objectmodel import keepalive_until_here
 
 
 class TestRegAlloc:

diff --git a/pypy/rpython/test/test_rdict.py b/pypy/rpython/test/test_rdict.py
--- a/pypy/rpython/test/test_rdict.py
+++ b/pypy/rpython/test/test_rdict.py
@@ -592,6 +592,26 @@
             a.x = 5
         self.interpret(fn, [])
 
+    def test_dict_popitem(self):
+        def func():
+            d = {}
+            d[5] = 2
+            d[6] = 3
+            k1, v1 = d.popitem()
+            assert len(d) == 1
+            k2, v2 = d.popitem()
+            try:
+                d.popitem()
+            except KeyError:
+                pass
+            else:
+                assert 0, "should have raised KeyError"
+            assert len(d) == 0
+            return k1*1000 + v1*100 + k2*10 + v2
+
+        res = self.interpret(func, [])
+        assert res in [5263, 6352]
+
 
 class TestLLtype(BaseTestRdict, LLRtypeMixin):
     def test_dict_but_not_with_char_keys(self):
@@ -696,26 +716,6 @@
         # if it does not crash, we are fine. It crashes if you forget the hash field.
         self.interpret(func, [])
 
-    def test_dict_popitem(self):
-        def func():
-            d = {}
-            d[5] = 2
-            d[6] = 3
-            k1, v1 = d.popitem()
-            assert len(d) == 1
-            k2, v2 = d.popitem()
-            try:
-                d.popitem()
-            except KeyError:
-                pass
-            else:
-                assert 0, "should have raised KeyError"
-            assert len(d) == 0
-            return k1*1000 + v1*100 + k2*10 + v2
-
-        res = self.interpret(func, [])
-        assert res in [5263, 6352]
-
     # ____________________________________________________________
 
     def test_opt_nullkeymarker(self):

diff --git a/pypy/rpython/lltypesystem/rffi.py b/pypy/rpython/lltypesystem/rffi.py
--- a/pypy/rpython/lltypesystem/rffi.py
+++ b/pypy/rpython/lltypesystem/rffi.py
@@ -305,6 +305,15 @@
 stackcounter = StackCounter()
 stackcounter._freeze_()
 
+def llexternal_use_eci(compilation_info):
+    """Return a dummy function that, if called in a RPython program,
+    adds the given ExternalCompilationInfo to it."""
+    eci = ExternalCompilationInfo(post_include_bits=['#define PYPY_NO_OP()'])
+    eci = eci.merge(compilation_info)
+    return llexternal('PYPY_NO_OP', [], lltype.Void,
+                      compilation_info=eci, sandboxsafe=True, _nowrapper=True,
+                      _callable=lambda: None)
+
 # ____________________________________________________________
 # Few helpers for keeping callback arguments alive
 # this makes passing opaque objects possible (they don't even pass
@@ -737,6 +746,7 @@
     def charpsize2str(cp, size):
         l = [cp[i] for i in range(size)]
         return emptystr.join(l)
+    charpsize2str._annenforceargs_ = [None, int]
 
     return (str2charp, free_charp, charp2str,
             get_nonmovingbuffer, free_nonmovingbuffer,

diff --git a/pypy/module/cpyext/include/Python.h b/pypy/module/cpyext/include/Python.h
--- a/pypy/module/cpyext/include/Python.h
+++ b/pypy/module/cpyext/include/Python.h
@@ -110,6 +110,8 @@
 #include "intobject.h"
 #include "listobject.h"
 #include "unicodeobject.h"
+#include "compile.h"
+#include "frameobject.h"
 #include "eval.h"
 #include "pymem.h"
 #include "pycobject.h"

diff --git a/pypy/translator/backendopt/removenoops.py b/pypy/translator/backendopt/removenoops.py
--- a/pypy/translator/backendopt/removenoops.py
+++ b/pypy/translator/backendopt/removenoops.py
@@ -108,15 +108,3 @@
         for i, op in list(enumerate(block.operations))[::-1]:
             if op.opname == "debug_assert":
                 del block.operations[i]
-
-def remove_superfluous_keep_alive(graph):
-    for block in graph.iterblocks():
-        used = {}
-        for i, op in list(enumerate(block.operations))[::-1]:
-            if op.opname == "keepalive":
-                if op.args[0] in used:
-                    del block.operations[i]
-                else:
-                    used[op.args[0]] = True
- 
-

diff --git a/pypy/rpython/test/test_rbuiltin.py b/pypy/rpython/test/test_rbuiltin.py
--- a/pypy/rpython/test/test_rbuiltin.py
+++ b/pypy/rpython/test/test_rbuiltin.py
@@ -496,6 +496,13 @@
         res = self.interpret(llf, [rffi.r_short(123)], policy=LowLevelAnnotatorPolicy())
         assert res == 123
 
+    def test_force_cast(self):
+        def llfn(v):
+            return rffi.cast(rffi.SHORT, v)
+        res = self.interpret(llfn, [0x12345678])
+        assert res == 0x5678
+
+
 class TestLLtype(BaseTestRbuiltin, LLRtypeMixin):
 
     def test_isinstance_obj(self):

diff --git a/pypy/module/_io/interp_bufferedio.py b/pypy/module/_io/interp_bufferedio.py
--- a/pypy/module/_io/interp_bufferedio.py
+++ b/pypy/module/_io/interp_bufferedio.py
@@ -12,7 +12,6 @@
     W_IOBase, DEFAULT_BUFFER_SIZE, convert_size,
     check_readable_w, check_writable_w, check_seekable_w)
 from pypy.module._io.interp_io import W_BlockingIOError
-from pypy.module.thread.os_lock import Lock
 
 STATE_ZERO, STATE_OK, STATE_DETACHED = range(3)
 
@@ -121,7 +120,7 @@
         ## XXX cannot free a Lock?
         ## if self.lock:
         ##     self.lock.free()
-        self.lock = Lock(space)
+        self.lock = space.allocate_lock()
 
         try:
             self._raw_tell(space)

diff --git a/pypy/jit/backend/x86/test/test_gc_integration.py b/pypy/jit/backend/x86/test/test_gc_integration.py
--- a/pypy/jit/backend/x86/test/test_gc_integration.py
+++ b/pypy/jit/backend/x86/test/test_gc_integration.py
@@ -26,9 +26,10 @@
 CPU = getcpuclass()
 
 class MockGcRootMap(object):
+    is_shadow_stack = False
     def get_basic_shape(self, is_64_bit):
         return ['shape']
-    def add_ebp_offset(self, shape, offset):
+    def add_frame_offset(self, shape, offset):
         shape.append(offset)
     def add_callee_save_reg(self, shape, reg_index):
         index_to_name = { 1: 'ebx', 2: 'esi', 3: 'edi' }
@@ -44,7 +45,8 @@
     get_funcptr_for_newarray = get_funcptr_for_new
     get_funcptr_for_newstr = get_funcptr_for_new
     get_funcptr_for_newunicode = get_funcptr_for_new
-    
+    get_malloc_slowpath_addr = None
+
     moving_gc = True
     gcrootmap = MockGcRootMap()
 
@@ -166,26 +168,29 @@
 
 class GCDescrFastpathMalloc(GcLLDescription):
     gcrootmap = None
-    
+    expected_malloc_slowpath_size = WORD*2
+
     def __init__(self):
         GcCache.__init__(self, False)
         # create a nursery
         NTP = rffi.CArray(lltype.Signed)
         self.nursery = lltype.malloc(NTP, 16, flavor='raw')
-        self.addrs = lltype.malloc(rffi.CArray(lltype.Signed), 2,
+        self.addrs = lltype.malloc(rffi.CArray(lltype.Signed), 3,
                                    flavor='raw')
         self.addrs[0] = rffi.cast(lltype.Signed, self.nursery)
-        self.addrs[1] = self.addrs[0] + 64
-        # 64 bytes
+        self.addrs[1] = self.addrs[0] + 16*WORD
+        self.addrs[2] = 0
+        # 16 WORDs
         def malloc_slowpath(size):
-            assert size == WORD*2
+            assert size == self.expected_malloc_slowpath_size
             nadr = rffi.cast(lltype.Signed, self.nursery)
             self.addrs[0] = nadr + size
+            self.addrs[2] += 1
             return nadr
         self.malloc_slowpath = malloc_slowpath
         self.MALLOC_SLOWPATH = lltype.FuncType([lltype.Signed],
                                                lltype.Signed)
-        self._counter = 123
+        self._counter = 123000
 
     def can_inline_malloc(self, descr):
         return True
@@ -204,7 +209,7 @@
     def get_nursery_top_addr(self):
         return rffi.cast(lltype.Signed, self.addrs) + WORD
 
-    def get_malloc_fixedsize_slowpath_addr(self):
+    def get_malloc_slowpath_addr(self):
         fptr = llhelper(lltype.Ptr(self.MALLOC_SLOWPATH), self.malloc_slowpath)
         return rffi.cast(lltype.Signed, fptr)
 
@@ -220,9 +225,11 @@
         cpu.gc_ll_descr = GCDescrFastpathMalloc()
         cpu.setup_once()
 
-        NODE = lltype.Struct('node', ('tid', lltype.Signed),
-                                     ('value', lltype.Signed))
-        nodedescr = cpu.sizeof(NODE)     # xxx hack: NODE is not a GcStruct
+        # hack: specify 'tid' explicitly, because this test is not running
+        # with the gc transformer
+        NODE = lltype.GcStruct('node', ('tid', lltype.Signed),
+                                       ('value', lltype.Signed))
+        nodedescr = cpu.sizeof(NODE)
         valuedescr = cpu.fielddescrof(NODE, 'value')
 
         self.cpu = cpu
@@ -254,6 +261,7 @@
         assert gc_ll_descr.nursery[1] == 42
         nurs_adr = rffi.cast(lltype.Signed, gc_ll_descr.nursery)
         assert gc_ll_descr.addrs[0] == nurs_adr + (WORD*2)
+        assert gc_ll_descr.addrs[2] == 0   # slowpath never called
 
     def test_malloc_slowpath(self):
         ops = '''
@@ -274,6 +282,7 @@
         gc_ll_descr = self.cpu.gc_ll_descr
         nadr = rffi.cast(lltype.Signed, gc_ll_descr.nursery)
         assert gc_ll_descr.addrs[0] == nadr + (WORD*2)
+        assert gc_ll_descr.addrs[2] == 1   # slowpath called once
 
     def test_new_with_vtable(self):
         ops = '''
@@ -289,3 +298,93 @@
         assert gc_ll_descr.nursery[1] == self.vtable_int
         nurs_adr = rffi.cast(lltype.Signed, gc_ll_descr.nursery)
         assert gc_ll_descr.addrs[0] == nurs_adr + (WORD*3)
+        assert gc_ll_descr.addrs[2] == 0   # slowpath never called
+
+
+class Seen(Exception):
+    pass
+
+class GCDescrFastpathMallocVarsize(GCDescrFastpathMalloc):
+    def can_inline_malloc_varsize(self, arraydescr, num_elem):
+        return num_elem < 5
+    def get_funcptr_for_newarray(self):
+        return 52
+    def init_array_descr(self, A, descr):
+        descr.tid = self._counter
+        self._counter += 1
+    def args_for_new_array(self, descr):
+        raise Seen("args_for_new_array")
+
+class TestMallocVarsizeFastpath(BaseTestRegalloc):
+    def setup_method(self, method):
+        cpu = CPU(None, None)
+        cpu.vtable_offset = WORD
+        cpu.gc_ll_descr = GCDescrFastpathMallocVarsize()
+        cpu.setup_once()
+        self.cpu = cpu
+
+        ARRAY = lltype.GcArray(lltype.Signed)
+        arraydescr = cpu.arraydescrof(ARRAY)
+        self.arraydescr = arraydescr
+
+        self.namespace = locals().copy()
+
+    def test_malloc_varsize_fastpath(self):
+        # Hack.  Running the GcLLDescr_framework without really having
+        # a complete GC means that we end up with both the tid and the
+        # length being at offset 0.  In this case, so the length overwrites
+        # the tid.  This is of course only the case in this test class.
+        ops = '''
+        []
+        p0 = new_array(4, descr=arraydescr)
+        setarrayitem_gc(p0, 0, 142, descr=arraydescr)
+        setarrayitem_gc(p0, 3, 143, descr=arraydescr)
+        finish(p0)
+        '''
+        self.interpret(ops, [])
+        # check the nursery
+        gc_ll_descr = self.cpu.gc_ll_descr
+        assert gc_ll_descr.nursery[0] == 4
+        assert gc_ll_descr.nursery[1] == 142
+        assert gc_ll_descr.nursery[4] == 143
+        nurs_adr = rffi.cast(lltype.Signed, gc_ll_descr.nursery)
+        assert gc_ll_descr.addrs[0] == nurs_adr + (WORD*5)
+        assert gc_ll_descr.addrs[2] == 0   # slowpath never called
+
+    def test_malloc_varsize_slowpath(self):
+        ops = '''
+        []
+        p0 = new_array(4, descr=arraydescr)
+        setarrayitem_gc(p0, 0, 420, descr=arraydescr)
+        setarrayitem_gc(p0, 3, 430, descr=arraydescr)
+        p1 = new_array(4, descr=arraydescr)
+        setarrayitem_gc(p1, 0, 421, descr=arraydescr)
+        setarrayitem_gc(p1, 3, 431, descr=arraydescr)
+        p2 = new_array(4, descr=arraydescr)
+        setarrayitem_gc(p2, 0, 422, descr=arraydescr)
+        setarrayitem_gc(p2, 3, 432, descr=arraydescr)
+        p3 = new_array(4, descr=arraydescr)
+        setarrayitem_gc(p3, 0, 423, descr=arraydescr)
+        setarrayitem_gc(p3, 3, 433, descr=arraydescr)
+        finish(p0, p1, p2, p3)
+        '''
+        gc_ll_descr = self.cpu.gc_ll_descr
+        gc_ll_descr.expected_malloc_slowpath_size = 5*WORD
+        self.interpret(ops, [])
+        assert gc_ll_descr.addrs[2] == 1   # slowpath called once
+
+    def test_malloc_varsize_too_big(self):
+        ops = '''
+        []
+        p0 = new_array(5, descr=arraydescr)
+        finish(p0)
+        '''
+        py.test.raises(Seen, self.interpret, ops, [])
+
+    def test_malloc_varsize_variable(self):
+        ops = '''
+        [i0]
+        p0 = new_array(i0, descr=arraydescr)
+        finish(p0)
+        '''
+        py.test.raises(Seen, self.interpret, ops, [])

diff --git a/pypy/translator/cli/src/ll_math.cs b/pypy/translator/cli/src/ll_math.cs
--- a/pypy/translator/cli/src/ll_math.cs
+++ b/pypy/translator/cli/src/ll_math.cs
@@ -224,5 +224,25 @@
         {
             return Math.Tanh(x);
         }
+
+        static public bool ll_math_isnan(double x)
+        {
+            return double.IsNaN(x);
+        }
+
+        static public bool ll_math_isinf(double x)
+        {
+            return double.IsInfinity(x);
+        }
+
+        static public double ll_math_copysign(double x, double y)
+        {
+            if (x < 0.0)
+                x = -x;
+            if (y > 0.0 || (y == 0.0 && Math.Atan2(y, -1.0) > 0.0))
+                return x;
+            else
+                return -x;
+        }
     }
 }

diff --git a/pypy/interpreter/test/test_interpreter.py b/pypy/interpreter/test/test_interpreter.py
--- a/pypy/interpreter/test/test_interpreter.py
+++ b/pypy/interpreter/test/test_interpreter.py
@@ -283,9 +283,14 @@
         sys.stdout = out = Out()
         try:
             raises(UnicodeError, "print unichr(0xa2)")
+            assert out.data == []
             out.encoding = "cp424"
             print unichr(0xa2)
             assert out.data == [unichr(0xa2).encode("cp424"), "\n"]
+            del out.data[:]
+            del out.encoding
+            print u"foo\t", u"bar\n", u"trick", u"baz\n"  # softspace handling
+            assert out.data == ["foo\t", "bar\n", "trick", " ", "baz\n", "\n"]
         finally:
             sys.stdout = save
 

diff --git a/pypy/module/imp/test/test_app.py b/pypy/module/imp/test/test_app.py
--- a/pypy/module/imp/test/test_app.py
+++ b/pypy/module/imp/test/test_app.py
@@ -1,3 +1,4 @@
+from __future__ import with_statement
 MARKER = 42
 
 class AppTestImpModule:
@@ -34,7 +35,8 @@
 
     def test_load_dynamic(self):
         raises(ImportError, self.imp.load_dynamic, 'foo', 'bar')
-        raises(ImportError, self.imp.load_dynamic, 'foo', 'bar', 'baz.so')
+        raises(ImportError, self.imp.load_dynamic, 'foo', 'bar',
+               open(self.file_module))
 
     def test_suffixes(self):
         for suffix, mode, type in self.imp.get_suffixes():

diff --git a/pypy/translator/backendopt/support.py b/pypy/translator/backendopt/support.py
--- a/pypy/translator/backendopt/support.py
+++ b/pypy/translator/backendopt/support.py
@@ -39,74 +39,6 @@
         # assume PyObjPtr
         return True
 
-def needs_conservative_livevar_calculation(block):
-    from pypy.rpython.lltypesystem import rclass
-    vars = block.getvariables()
-    assert len(block.exits) == 1
-    exitingvars = block.exits[0].args
-    for var in vars:
-        TYPE = getattr(var, "concretetype", lltype.Ptr(lltype.PyObject))
-        if isinstance(TYPE, lltype.Ptr) and not var_needsgc(var):
-            if isinstance(TYPE.TO, lltype.FuncType):
-                continue
-            try:
-                lltype.castable(TYPE, rclass.CLASSTYPE)
-            except lltype.InvalidCast:
-                if var in exitingvars:
-                    return True
-    else:
-        return False
-
-def generate_keepalive(vars, annotator=None):
-    keepalive_ops = []
-    for v in vars:
-        if isinstance(v, Constant):
-            continue
-        if v.concretetype._is_atomic():
-            continue
-        v_keepalive = Variable()
-        v_keepalive.concretetype = lltype.Void
-        if annotator is not None:
-            annotator.setbinding(v_keepalive, s_ImpossibleValue)
-        keepalive_ops.append(SpaceOperation('keepalive', [v], v_keepalive))
-    return keepalive_ops
-
-def split_block_with_keepalive(block, index_operation,
-                               keep_alive_op_args=True,
-                               annotator=None):
-    splitlink = split_block(annotator, block, index_operation)
-    afterblock = splitlink.target
-    conservative_keepalives = needs_conservative_livevar_calculation(block)
-    if conservative_keepalives:
-        keep_alive_vars = [var for var in block.getvariables()
-                               if var_needsgc(var)]
-        # XXX you could maybe remove more, if the variables are kept
-        # alive by something else. but this is sometimes hard to know
-        for i, var in enumerate(keep_alive_vars):
-            try:
-                index = splitlink.args.index(var)
-                newvar = afterblock.inputargs[index]
-            except ValueError:
-                splitlink.args.append(var)
-                newvar = copyvar(annotator, var)
-                afterblock.inputargs.append(newvar)
-            keep_alive_vars[i] = newvar
-    elif keep_alive_op_args and afterblock.operations: 
-        keep_alive_vars = [var for var in afterblock.operations[0].args
-                               if isinstance(var, Variable) and var_needsgc(var)]
-        if len(afterblock.operations) > 1 or afterblock.exitswitch != c_last_exception:
-            afterblock.operations[1:1] = generate_keepalive(keep_alive_vars,
-                                                            annotator=annotator)
-            keep_alive_vars = []
-    else:
-        keep_alive_vars = []
-    pos = len(afterblock.operations)
-    if afterblock.exitswitch == c_last_exception:
-        pos -= 1    # insert the keepalives just before the last operation
-                    # in case of exception-catching
-    afterblock.operations[pos:pos] = generate_keepalive(keep_alive_vars)
-    return splitlink
-
 def find_calls_from(translator, graph, memo=None):
     if memo and graph in memo:
         return memo[graph]

diff --git a/pypy/module/cpyext/test/test_bufferobject.py b/pypy/module/cpyext/test/test_bufferobject.py
--- a/pypy/module/cpyext/test/test_bufferobject.py
+++ b/pypy/module/cpyext/test/test_bufferobject.py
@@ -46,4 +46,5 @@
                  return PyBuffer_New(150);
              """),
             ])
-        module.buffer_new()
+        b = module.buffer_new()
+        raises(AttributeError, getattr, b, 'x')

diff --git a/pypy/translator/jvm/metavm.py b/pypy/translator/jvm/metavm.py
--- a/pypy/translator/jvm/metavm.py
+++ b/pypy/translator/jvm/metavm.py
@@ -1,4 +1,5 @@
 from pypy.rpython.ootypesystem import ootype
+from pypy.rpython.lltypesystem import rffi
 from pypy.translator.oosupport.metavm import MicroInstruction
 from pypy.translator.jvm.typesystem import JvmScalarType, JvmClassType
 import pypy.translator.jvm.typesystem as jvm
@@ -94,14 +95,20 @@
     (ootype.SignedLongLong,   ootype.Signed):           jvm.L2I,
     (ootype.UnsignedLongLong, ootype.Unsigned):         jvm.L2I,
     (ootype.UnsignedLongLong, ootype.Signed):           jvm.L2I,
+    (ootype.Signed,           rffi.SHORT):              jvm.I2S,
+    (ootype.Unsigned,         ootype.SignedLongLong):   jvm.PYPYUINTTOLONG,
     (ootype.UnsignedLongLong, ootype.SignedLongLong):   None,
     (ootype.SignedLongLong,   ootype.UnsignedLongLong): None,
+    (ootype.Signed,           ootype.Unsigned):         None,
+    (ootype.Unsigned,         ootype.Signed):           None,
     }
 
 class _CastPrimitive(MicroInstruction):
     def render(self, generator, op):
         FROM = op.args[0].concretetype
         TO = op.result.concretetype
+        if TO == FROM:
+            return
         opcode = CASTS[(FROM, TO)]
         if opcode:
             generator.emit(opcode)

diff --git a/pypy/module/imp/importing.py b/pypy/module/imp/importing.py
--- a/pypy/module/imp/importing.py
+++ b/pypy/module/imp/importing.py
@@ -32,6 +32,7 @@
 else:
     SO = ".so"
 DEFAULT_SOABI = 'pypy-14'
+CHECK_FOR_PYW = sys.platform == 'win32'
 
 @specialize.memo()
 def get_so_extension(space):
@@ -58,6 +59,12 @@
     if os.path.exists(pyfile) and case_ok(pyfile):
         return PY_SOURCE, ".py", "U"
 
+    # on Windows, also check for a .pyw file
+    if CHECK_FOR_PYW:
+        pyfile = filepart + ".pyw"
+        if os.path.exists(pyfile) and case_ok(pyfile):
+            return PY_SOURCE, ".pyw", "U"
+
     # The .py file does not exist.  By default on PyPy, lonepycfiles
     # is False: if a .py file does not exist, we don't even try to
     # look for a lone .pyc file.
@@ -85,6 +92,9 @@
     # XXX that's slow
     def case_ok(filename):
         index = filename.rfind(os.sep)
+        if os.altsep is not None:
+            index2 = filename.rfind(os.altsep)
+            index = max(index, index2)
         if index < 0:
             directory = os.curdir
         else:

diff --git a/pypy/jit/backend/x86/test/test_rx86_64_auto_encoding.py b/pypy/jit/backend/x86/test/test_rx86_64_auto_encoding.py
--- a/pypy/jit/backend/x86/test/test_rx86_64_auto_encoding.py
+++ b/pypy/jit/backend/x86/test/test_rx86_64_auto_encoding.py
@@ -18,7 +18,6 @@
     def should_skip_instruction(self, instrname, argmodes):
         return (
                 super(TestRx86_64, self).should_skip_instruction(instrname, argmodes) or
-                ('j' in argmodes) or
                 # Not testing FSTP on 64-bit for now
                 (instrname == 'FSTP')
         )


diff --git a/pypy/objspace/flow/flowcontext.py b/pypy/objspace/flow/flowcontext.py
--- a/pypy/objspace/flow/flowcontext.py
+++ b/pypy/objspace/flow/flowcontext.py
@@ -311,8 +311,7 @@
         # EggBlocks reuse the variables of their previous block,
         # which is deemed not acceptable for simplicity of the operations
         # that will be performed later on the flow graph.
-        def fixegg(link):
-            if isinstance(link, Link):
+        for link in list(self.graph.iterlinks()):
                 block = link.target
                 if isinstance(block, EggBlock):
                     if (not block.operations and len(block.exits) == 1 and
@@ -324,15 +323,14 @@
                         link.args = list(link2.args)
                         link.target = link2.target
                         assert link2.exitcase is None
-                        fixegg(link)
                     else:
                         mapping = {}
                         for a in block.inputargs:
                             mapping[a] = Variable(a)
                         block.renamevariables(mapping)
-            elif isinstance(link, SpamBlock):
+        for block in self.graph.iterblocks():
+            if isinstance(link, SpamBlock):
                 del link.framestate     # memory saver
-        traverse(fixegg, self.graph)
 
     def mergeblock(self, currentblock, currentstate):
         next_instr = currentstate.next_instr

diff --git a/pypy/annotation/unaryop.py b/pypy/annotation/unaryop.py
--- a/pypy/annotation/unaryop.py
+++ b/pypy/annotation/unaryop.py
@@ -499,10 +499,14 @@
     def getanyitem(str):
         return str.basecharclass()
 
-    def method_split(str, patt): # XXX
+    def method_split(str, patt, max=-1):
         getbookkeeper().count("str_split", str, patt)
         return getbookkeeper().newlist(str.basestringclass())
 
+    def method_rsplit(str, patt, max=-1):
+        getbookkeeper().count("str_rsplit", str, patt)
+        return getbookkeeper().newlist(str.basestringclass())
+
     def method_replace(str, s1, s2):
         return str.basestringclass()
 

diff --git a/pypy/rpython/lltypesystem/rstr.py b/pypy/rpython/lltypesystem/rstr.py
--- a/pypy/rpython/lltypesystem/rstr.py
+++ b/pypy/rpython/lltypesystem/rstr.py
@@ -722,31 +722,75 @@
         newlen = len(s1.chars) - 1
         return LLHelpers._ll_stringslice(s1, 0, newlen)
 
-    def ll_split_chr(LIST, s, c):
+    def ll_split_chr(LIST, s, c, max):
         chars = s.chars
         strlen = len(chars)
         count = 1
         i = 0
+        if max == 0:
+            i = strlen
         while i < strlen:
             if chars[i] == c:
                 count += 1
+                if max >= 0 and count > max:
+                    break
             i += 1
         res = LIST.ll_newlist(count)
         items = res.ll_items()
         i = 0
         j = 0
         resindex = 0
+        if max == 0:
+            j = strlen
         while j < strlen:
             if chars[j] == c:
                 item = items[resindex] = s.malloc(j - i)
                 item.copy_contents(s, item, i, 0, j - i)
                 resindex += 1
                 i = j + 1
+                if max >= 0 and resindex >= max:
+                    j = strlen
+                    break
             j += 1
         item = items[resindex] = s.malloc(j - i)
         item.copy_contents(s, item, i, 0, j - i)
         return res
 
+    def ll_rsplit_chr(LIST, s, c, max):
+        chars = s.chars
+        strlen = len(chars)
+        count = 1
+        i = 0
+        if max == 0:
+            i = strlen
+        while i < strlen:
+            if chars[i] == c:
+                count += 1
+                if max >= 0 and count > max:
+                    break
+            i += 1
+        res = LIST.ll_newlist(count)
+        items = res.ll_items()
+        i = strlen
+        j = strlen
+        resindex = count - 1
+        assert resindex >= 0
+        if max == 0:
+            j = 0
+        while j > 0:
+            j -= 1
+            if chars[j] == c:
+                item = items[resindex] = s.malloc(i - j - 1)
+                item.copy_contents(s, item, j + 1, 0, i - j - 1)
+                resindex -= 1
+                i = j
+                if resindex == 0:
+                    j = 0
+                    break
+        item = items[resindex] = s.malloc(i - j)
+        item.copy_contents(s, item, j, 0, i - j)
+        return res
+
     @purefunction
     def ll_replace_chr_chr(s, c1, c2):
         length = len(s.chars)

diff --git a/pypy/translator/backendopt/mallocv.py b/pypy/translator/backendopt/mallocv.py
--- a/pypy/translator/backendopt/mallocv.py
+++ b/pypy/translator/backendopt/mallocv.py
@@ -846,22 +846,6 @@
         else:
             return self.handle_default(op)
 
-    def handle_op_keepalive(self, op):
-        node = self.getnode(op.args[0])
-        if isinstance(node, VirtualSpecNode):
-            rtnodes, vtnodes = find_all_nodes([node])
-            newops = []
-            for rtnode in rtnodes:
-                v = self.renamings[rtnode]
-                if isinstance(v, Variable):
-                    T = v.concretetype
-                    if isinstance(T, lltype.Ptr) and T._needsgc():
-                        v0 = varoftype(lltype.Void)
-                        newops.append(SpaceOperation('keepalive', [v], v0))
-            return newops
-        else:
-            return self.handle_default(op)
-
     def handle_op_ptr_nonzero(self, op):
         node = self.getnode(op.args[0])
         if isinstance(node, VirtualSpecNode):


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
@@ -43,9 +43,14 @@
 
 class SizeDescr(AbstractDescr):
     size = 0      # help translation
+    is_immutable = False
 
-    def __init__(self, size):
+    def __init__(self, size, count_fields_if_immut=-1):
         self.size = size
+        self.count_fields_if_immut = count_fields_if_immut
+
+    def count_fields_if_immutable(self):
+        return self.count_fields_if_immut
 
     def repr_of_descr(self):
         return '<SizeDescr %s>' % self.size
@@ -62,15 +67,15 @@
         return cache[STRUCT]
     except KeyError:
         size = symbolic.get_size(STRUCT, gccache.translate_support_code)
+        count_fields_if_immut = heaptracker.count_fields_if_immutable(STRUCT)
         if heaptracker.has_gcstruct_a_vtable(STRUCT):
-            sizedescr = SizeDescrWithVTable(size)
+            sizedescr = SizeDescrWithVTable(size, count_fields_if_immut)
         else:
-            sizedescr = SizeDescr(size)
+            sizedescr = SizeDescr(size, count_fields_if_immut)
         gccache.init_size_descr(STRUCT, sizedescr)
         cache[STRUCT] = sizedescr
         return sizedescr
 
-
 # ____________________________________________________________
 # FieldDescrs
 

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
@@ -283,9 +283,15 @@
             # These are the worst cases:
             val2 = loc2.value_i()
             code1 = loc1.location_code()
-            if (code1 == 'j'
-                or (code1 == 'm' and not rx86.fits_in_32bits(loc1.value_m()[1]))
-                or (code1 == 'a' and not rx86.fits_in_32bits(loc1.value_a()[3]))):
+            if code1 == 'j':
+                checkvalue = loc1.value_j()
+            elif code1 == 'm':
+                checkvalue = loc1.value_m()[1]
+            elif code1 == 'a':
+                checkvalue = loc1.value_a()[3]
+            else:
+                checkvalue = 0
+            if not rx86.fits_in_32bits(checkvalue):
                 # INSN_ji, and both operands are 64-bit; or INSN_mi or INSN_ai
                 # and the constant offset in the address is 64-bit.
                 # Hopefully this doesn't happen too often
@@ -330,10 +336,10 @@
                         if code1 == possible_code1:
                             val1 = getattr(loc1, "value_" + possible_code1)()
                             # More faking out of certain operations for x86_64
-                            if self.WORD == 8 and possible_code1 == 'j':
+                            if possible_code1 == 'j' and not rx86.fits_in_32bits(val1):
                                 val1 = self._addr_as_reg_offset(val1)
                                 invoke(self, "m" + possible_code2, val1, val2)
-                            elif self.WORD == 8 and possible_code2 == 'j':
+                            elif possible_code2 == 'j' and not rx86.fits_in_32bits(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]):
@@ -378,6 +384,10 @@
                             _rx86_getattr(self, name + "_l")(val)
                             self.add_pending_relocation()
                         else:
+                            # xxx can we avoid "MOV r11, $val; JMP/CALL *r11"
+                            # in case it would fit a 32-bit displacement?
+                            # Hard, because we don't know yet where this insn
+                            # will end up...
                             assert self.WORD == 8
                             self._load_scratch(val)
                             _rx86_getattr(self, name + "_r")(X86_64_SCRATCH_REG.value)

diff --git a/pypy/translator/backendopt/test/test_tailrecursion.py b/pypy/translator/backendopt/test/test_tailrecursion.py
--- a/pypy/translator/backendopt/test/test_tailrecursion.py
+++ b/pypy/translator/backendopt/test/test_tailrecursion.py
@@ -1,4 +1,4 @@
-from pypy.objspace.flow.model import traverse, Block, Link, Variable, Constant
+from pypy.objspace.flow.model import Block, Link, Variable, Constant
 from pypy.translator.backendopt.tailrecursion import remove_tail_calls_to_self
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.rpython.llinterp import LLInterpreter

diff --git a/pypy/module/cpyext/test/comparisons.c b/pypy/module/cpyext/test/comparisons.c
--- a/pypy/module/cpyext/test/comparisons.c
+++ b/pypy/module/cpyext/test/comparisons.c
@@ -69,12 +69,31 @@
 };
 
 
+static int cmp_compare(PyObject *self, PyObject *other) {
+    return -1;
+}
+
+PyTypeObject OldCmpType = {
+    PyVarObject_HEAD_INIT(NULL, 0)
+    "comparisons.OldCmpType",                       /* tp_name */
+    sizeof(CmpObject),                              /* tp_basicsize */
+    0,                                              /* tp_itemsize */
+    0,                                              /* tp_dealloc */
+    0,                                              /* tp_print */
+    0,                                              /* tp_getattr */
+    0,                                              /* tp_setattr */
+    (cmpfunc)cmp_compare,                           /* tp_compare */
+};
+
+
 void initcomparisons(void)
 {
     PyObject *m, *d;
 
     if (PyType_Ready(&CmpType) < 0)
         return;
+    if (PyType_Ready(&OldCmpType) < 0)
+        return;
     m = Py_InitModule("comparisons", NULL);
     if (m == NULL)
         return;
@@ -83,4 +102,6 @@
         return;
     if (PyDict_SetItemString(d, "CmpType", (PyObject *)&CmpType) < 0)
         return;
+    if (PyDict_SetItemString(d, "OldCmpType", (PyObject *)&OldCmpType) < 0)
+        return;
 }

diff --git a/pypy/module/signal/test/test_signal.py b/pypy/module/signal/test/test_signal.py
--- a/pypy/module/signal/test/test_signal.py
+++ b/pypy/module/signal/test/test_signal.py
@@ -262,6 +262,8 @@
             signal(SIGALRM, SIG_DFL)
 
 class AppTestItimer:
+    spaceconfig = dict(usemodules=['signal'])
+
     def test_itimer_real(self):
         import signal
 

diff --git a/pypy/translator/c/src/ll_math.c b/pypy/translator/c/src/ll_math.c
--- a/pypy/translator/c/src/ll_math.c
+++ b/pypy/translator/c/src/ll_math.c
@@ -22,18 +22,6 @@
 #endif
 #define PyPy_NAN (HUGE_VAL * 0.)
 
-int
-_pypy_math_isinf(double x)
-{
-    return PyPy_IS_INFINITY(x);
-}
-
-int
-_pypy_math_isnan(double x)
-{
-    return PyPy_IS_NAN(x);
-}
-
 /* The following copyright notice applies to the original
    implementations of acosh, asinh and atanh. */
 


diff --git a/pypy/module/pypyjit/test_pypy_c/model.py b/pypy/module/pypyjit/test_pypy_c/model.py
--- a/pypy/module/pypyjit/test_pypy_c/model.py
+++ b/pypy/module/pypyjit/test_pypy_c/model.py
@@ -250,7 +250,6 @@
         # this is the ticker check generated in PyFrame.handle_operation_error
         exc_ticker_check = """
             ticker2 = getfield_raw(ticker_address, descr=<SignedFieldDescr pypysig_long_struct.c_value .*>)
-            setfield_gc(_, _, descr=<GcPtrFieldDescr pypy.interpreter.pyframe.PyFrame.inst_w_f_trace .*>)
             ticker_cond1 = int_lt(ticker2, 0)
             guard_false(ticker_cond1, descr=...)
         """
@@ -260,13 +259,13 @@
     @classmethod
     def is_const(cls, v1):
         return isinstance(v1, str) and v1.startswith('ConstClass(')
-    
+
     def match_var(self, v1, exp_v2):
         assert v1 != '_'
         if exp_v2 == '_':
             return True
         if self.is_const(v1) or self.is_const(exp_v2):
-            return v1 == exp_v2
+            return v1[:-1].startswith(exp_v2[:-1])
         if v1 not in self.alpha_map:
             self.alpha_map[v1] = exp_v2
         return self.alpha_map[v1] == exp_v2
@@ -285,9 +284,9 @@
         self.match_var(op.res, exp_res)
         self._assert(len(op.args) == len(exp_args), "wrong number of arguments")
         for arg, exp_arg in zip(op.args, exp_args):
-            self._assert(self.match_var(arg, exp_arg), "variable mismatch")
+            self._assert(self.match_var(arg, exp_arg), "variable mismatch: %r instead of %r" % (arg, exp_arg))
         self.match_descr(op.descr, exp_descr)
-        
+
 
     def _next_op(self, iter_ops, assert_raises=False):
         try:

diff --git a/pypy/module/thread/ll_thread.py b/pypy/module/thread/ll_thread.py
--- a/pypy/module/thread/ll_thread.py
+++ b/pypy/module/thread/ll_thread.py
@@ -1,10 +1,10 @@
 
-from pypy.rpython.lltypesystem import rffi
-from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.lltypesystem import rffi, lltype, llmemory
 from pypy.rpython.tool import rffi_platform as platform
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 import py, os
 from pypy.rpython.extregistry import ExtRegistryEntry
+from pypy.rlib import jit
 from pypy.rlib.debug import ll_assert
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rpython.lltypesystem.lloperation import llop
@@ -79,6 +79,7 @@
 
 # wrappers...
 
+ at jit.loop_invariant
 def get_ident():
     return rffi.cast(lltype.Signed, c_thread_get_ident())
 
@@ -113,6 +114,12 @@
     def __del__(self):
         free_ll_lock(self._lock)
 
+    def __enter__(self):
+        self.acquire(True)
+        
+    def __exit__(self, *args):
+        self.release()
+
 # ____________________________________________________________
 #
 # Stack size

diff --git a/pypy/jit/backend/llsupport/regalloc.py b/pypy/jit/backend/llsupport/regalloc.py
--- a/pypy/jit/backend/llsupport/regalloc.py
+++ b/pypy/jit/backend/llsupport/regalloc.py
@@ -1,5 +1,5 @@
 
-from pypy.jit.metainterp.history import Const, Box
+from pypy.jit.metainterp.history import Const, Box, REF
 from pypy.rlib.objectmodel import we_are_translated
 
 class TempBox(Box):
@@ -313,11 +313,12 @@
             self.assembler.regalloc_mov(reg, to)
         # otherwise it's clean
 
-    def before_call(self, force_store=[], save_all_regs=False):
+    def before_call(self, force_store=[], save_all_regs=0):
         """ Spill registers before a call, as described by
         'self.save_around_call_regs'.  Registers are not spilled if
         they don't survive past the current operation, unless they
-        are listed in 'force_store'.
+        are listed in 'force_store'.  'save_all_regs' can be 0 (default),
+        1 (save all), or 2 (save default+PTRs).
         """
         for v, reg in self.reg_bindings.items():
             if v not in force_store and self.longevity[v][1] <= self.position:
@@ -325,9 +326,11 @@
                 del self.reg_bindings[v]
                 self.free_regs.append(reg)
                 continue
-            if not save_all_regs and reg not in self.save_around_call_regs:
-                # we don't have to
-                continue
+            if save_all_regs != 1 and reg not in self.save_around_call_regs:
+                if save_all_regs == 0:
+                    continue    # we don't have to
+                if v.type != REF:
+                    continue    # only save GC pointers
             self._sync_var(v)
             del self.reg_bindings[v]
             self.free_regs.append(reg)

diff --git a/pypy/module/pypyjit/test/test_pypy_c.py b/pypy/module/pypyjit/test/test_pypy_c.py
--- a/pypy/module/pypyjit/test/test_pypy_c.py
+++ b/pypy/module/pypyjit/test/test_pypy_c.py
@@ -3,6 +3,7 @@
 import py
 from py.test import skip
 import sys, os, re
+import subprocess
 
 class BytecodeTrace(list):
     def get_opnames(self, prefix=""):
@@ -116,13 +117,12 @@
         print >> f, "print 'OK :-)'"
         f.close()
 
-        if sys.platform.startswith('win'):
-            py.test.skip("XXX this is not Windows-friendly")
         print logfilepath
-        child_stdout = os.popen('PYPYLOG=":%s" "%s" "%s"' % (
-            logfilepath, self.pypy_c, filepath), 'r')
-        result = child_stdout.read()
-        child_stdout.close()
+        env = os.environ.copy()
+        env['PYPYLOG'] = ":%s" % (logfilepath,)
+        p = subprocess.Popen([self.pypy_c, str(filepath)],
+                             env=env, stdout=subprocess.PIPE)
+        result, _ = p.communicate()
         assert result
         if result.strip().startswith('SKIP:'):
             py.test.skip(result.strip())
@@ -1430,6 +1430,8 @@
                 res1 += dd(a, b, a1, b1)
                 res2 += dd(a, b, a2, b2)
                 res3 += dd(a, b, a3, b3)
+        # The purpose of this test is to check that we get
+        # the correct results, not really to count operations.
         self.run_source('''
         def main(a, b):
             i = sa = 0
@@ -1437,11 +1439,10 @@
 %s                
                 i += 1
             return sa
-        ''' % code, 179, ([a1, b1], 2000 * res1),
-                         ([a2, b2], 2000 * res2),
-                         ([a3, b3], 2000 * res3),
-                         count_debug_merge_point=False)
-        
+        ''' % code, sys.maxint, ([a1, b1], 2000 * res1),
+                                ([a2, b2], 2000 * res2),
+                                ([a3, b3], 2000 * res3))
+
     def test_mod(self):
         avalues = ('a', 'b', 7, -42, 8)
         bvalues = ['b'] + range(-10, 0) + range(1,10)
@@ -1462,6 +1463,8 @@
                 res1 += dd(a, b, a1, b1)
                 res2 += dd(a, b, a2, b2)
                 res3 += dd(a, b, a3, b3)
+        # The purpose of this test is to check that we get
+        # the correct results, not really to count operations.
         self.run_source('''
         def main(a, b):
             i = sa = 0
@@ -1471,11 +1474,10 @@
 %s
                 i += 1
             return sa
-        ''' % code, 450, ([a1, b1], 2000 * res1),
-                         ([a2, b2], 2000 * res2),
-                         ([a3, b3], 2000 * res3),
-                         count_debug_merge_point=False)
-        
+        ''' % code, sys.maxint, ([a1, b1], 2000 * res1),
+                                ([a2, b2], 2000 * res2),
+                                ([a3, b3], 2000 * res3))
+
     def test_dont_trace_every_iteration(self):
         self.run_source('''
         def main(a, b):

diff --git a/pypy/jit/backend/llsupport/test/test_descr.py b/pypy/jit/backend/llsupport/test/test_descr.py
--- a/pypy/jit/backend/llsupport/test/test_descr.py
+++ b/pypy/jit/backend/llsupport/test/test_descr.py
@@ -18,12 +18,33 @@
     descr_t = get_size_descr(c0, T)
     assert descr_s.size == symbolic.get_size(S, False)
     assert descr_t.size == symbolic.get_size(T, False)
+    assert descr_s.count_fields_if_immutable() == -1
+    assert descr_t.count_fields_if_immutable() == -1
     assert descr_s == get_size_descr(c0, S)
     assert descr_s != get_size_descr(c1, S)
     #
     descr_s = get_size_descr(c1, S)
     assert isinstance(descr_s.size, Symbolic)
+    assert descr_s.count_fields_if_immutable() == -1
 
+def test_get_size_descr_immut():
+    S = lltype.GcStruct('S', hints={'immutable': True})
+    T = lltype.GcStruct('T', ('parent', S),
+                        ('x', lltype.Char),
+                        hints={'immutable': True})
+    U = lltype.GcStruct('U', ('parent', T),
+                        ('u', lltype.Ptr(T)),
+                        ('v', lltype.Signed),
+                        hints={'immutable': True})
+    V = lltype.GcStruct('V', ('parent', U),
+                        ('miss1', lltype.Void),
+                        ('miss2', lltype.Void),
+                        hints={'immutable': True})
+    for STRUCT, expected in [(S, 0), (T, 1), (U, 3), (V, 3)]:
+        for translated in [False, True]:
+            c0 = GcCache(translated)
+            descr_s = get_size_descr(c0, STRUCT)
+            assert descr_s.count_fields_if_immutable() == expected
 
 def test_get_field_descr():
     U = lltype.Struct('U')

diff --git a/pypy/rpython/test/test_rint.py b/pypy/rpython/test/test_rint.py
--- a/pypy/rpython/test/test_rint.py
+++ b/pypy/rpython/test/test_rint.py
@@ -4,7 +4,7 @@
 from pypy.annotation import model as annmodel
 from pypy.rpython.test import snippet
 from pypy.rlib.rarithmetic import r_int, r_uint, r_longlong, r_ulonglong
-from pypy.rlib.rarithmetic import ovfcheck, r_int64, intmask
+from pypy.rlib.rarithmetic import ovfcheck, r_int64, intmask, int_between
 from pypy.rlib import objectmodel
 from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
 
@@ -215,6 +215,14 @@
             assert res == f(inttype(0))
             assert type(res) == inttype
 
+    def test_and_or(self):
+        inttypes = [int, r_uint, r_int64, r_ulonglong]
+        for inttype in inttypes:
+            def f(a, b, c):
+                return a&b|c
+            res = self.interpret(f, [inttype(0x1234), inttype(0x00FF), inttype(0x5600)])
+            assert res == f(0x1234, 0x00FF, 0x5600)
+
     def test_neg_abs_ovf(self):
         for op in (operator.neg, abs):
             def f(x):
@@ -266,6 +274,8 @@
                 x = inttype(random.randint(-100000, 100000))
                 y = inttype(random.randint(-100000, 100000))
                 if not y: continue
+                if (i & 31) == 0:
+                    x = (x//y) * y      # case where x is exactly divisible by y
                 res = self.interpret(d, [x, y])
                 assert res == d(x, y)
 
@@ -276,6 +286,8 @@
                 x = inttype(random.randint(-100000, 100000))
                 y = inttype(random.randint(-100000, 100000))
                 if not y: continue
+                if (i & 31) == 0:
+                    x = (x//y) * y      # case where x is exactly divisible by y
                 res = self.interpret(m, [x, y])
                 assert res == m(x, y)
 
@@ -384,6 +396,18 @@
         else:
             assert res == 123456789012345678
 
+    def test_int_between(self):
+        def fn(a, b, c):
+            return int_between(a, b, c)
+        assert self.interpret(fn, [1, 1, 3])
+        assert self.interpret(fn, [1, 2, 3])
+        assert not self.interpret(fn, [1, 0, 2])
+        assert not self.interpret(fn, [1, 5, 2])
+        assert not self.interpret(fn, [1, 2, 2])
+        assert not self.interpret(fn, [1, 1, 1])
+
+
+
 class TestLLtype(BaseTestRint, LLRtypeMixin):
     pass
 

diff --git a/pypy/translator/jvm/src/pypy/PyPy.java b/pypy/translator/jvm/src/pypy/PyPy.java
--- a/pypy/translator/jvm/src/pypy/PyPy.java
+++ b/pypy/translator/jvm/src/pypy/PyPy.java
@@ -38,6 +38,10 @@
     public final static int INT_MIN = Integer.MIN_VALUE;
     public final static double ULONG_MAX = 18446744073709551616.0;
 
+    public static boolean int_between(int a, int b, int c) {
+        return a <= b && b < c;
+    }
+
     /** 
      * Compares two unsigned integers (value1 and value2) and returns
      * a value greater than, equal to, or less than zero if value 1 is
@@ -163,6 +167,13 @@
             return ULONG_MAX + value;
         }
     }
+
+    public static long double_to_ulong(double value) {
+        if (value < 0)
+            return (long)(ULONG_MAX + value);
+        else
+            return (long)value;
+    }
     
     public static int double_to_uint(double value) {
         if (value <= Integer.MAX_VALUE)
@@ -746,11 +757,13 @@
         return str.substring(start, end);
     }
 
-    public static Object[] ll_split_chr(String str, char c) {
+    public static Object[] ll_split_chr(String str, char c, int max) {
         ArrayList list = new ArrayList();
         int lastidx = 0, idx = 0;
         while ((idx = str.indexOf(c, lastidx)) != -1)
         {
+            if (max >= 0 && list.size() >= max)
+                break;
             String sub = str.substring(lastidx, idx);
             list.add(sub);
             lastidx = idx+1;
@@ -759,6 +772,21 @@
         return list.toArray(new String[list.size()]);
     }
 
+    public static Object[] ll_rsplit_chr(String str, char c, int max) {
+        ArrayList list = new ArrayList();
+        int lastidx = str.length(), idx = 0;
+        while ((idx = str.lastIndexOf(c, lastidx - 1)) != -1)
+        {
+            if (max >= 0 && list.size() >= max)
+                break;
+            String sub = str.substring(idx + 1, lastidx);
+            list.add(0, sub);
+            lastidx = idx;
+        }
+        list.add(0, str.substring(0, lastidx));
+        return list.toArray(new String[list.size()]);
+    }
+
     public static String ll_substring(String str, int start, int cnt) {
         return str.substring(start,start+cnt);
     }
@@ -1158,6 +1186,18 @@
         return Math.tanh(x);
     }
 
+    public double ll_math_copysign(double x, double y) {
+        return Math.copySign(x, y);
+    }
+
+    public boolean ll_math_isnan(double x) {
+        return Double.isNaN(x);
+    }
+
+    public boolean ll_math_isinf(double x) {
+        return Double.isInfinite(x);
+    }
+
     private double check(double v) {
         if (Double.isNaN(v))
             interlink.throwValueError();
@@ -1170,9 +1210,42 @@
         return Character.toLowerCase(c);
     }
 
+    public int locale_tolower(int chr)
+    {
+        return Character.toLowerCase(chr);
+    }
+
+    public int locale_isupper(int chr)
+    {
+        return boolean2int(Character.isUpperCase(chr));
+    }
+
+    public int locale_islower(int chr)
+    {
+        return boolean2int(Character.isLowerCase(chr));
+    }
+
+    public int locale_isalpha(int chr)
+    {
+        return boolean2int(Character.isLetter(chr));
+    }
+
+    public int locale_isalnum(int chr)
+    {
+        return boolean2int(Character.isLetterOrDigit(chr));
+    }
+
+
     // ----------------------------------------------------------------------
     // Self Test
 
+    public static int boolean2int(boolean b)
+    {
+        if (b)
+            return 1;
+        return 0;
+    }
+
     public static int __counter = 0, __failures = 0;
     public static void ensure(boolean f) {
         if (f) {

diff --git a/pypy/jit/backend/x86/support.py b/pypy/jit/backend/x86/support.py
--- a/pypy/jit/backend/x86/support.py
+++ b/pypy/jit/backend/x86/support.py
@@ -38,11 +38,7 @@
 if sys.platform == 'win32':
     ensure_sse2_floats = lambda : None
 else:
-    _sse2_eci = ExternalCompilationInfo(
+    ensure_sse2_floats = rffi.llexternal_use_eci(ExternalCompilationInfo(
         compile_extra = ['-msse2', '-mfpmath=sse',
                          '-DPYPY_CPU_HAS_STANDARD_PRECISION'],
-        separate_module_sources = ['void PYPY_NO_OP(void) {}'],
-        )
-    ensure_sse2_floats = rffi.llexternal('PYPY_NO_OP', [], lltype.Void,
-                                         compilation_info=_sse2_eci,
-                                         sandboxsafe=True)
+        ))

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
@@ -2,7 +2,7 @@
 from pypy.rlib.jit import JitDriver, dont_look_inside, we_are_jitted
 from pypy.jit.codewriter.policy import StopAtXPolicy
 from pypy.rpython.ootypesystem import ootype
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 
 
 class StringTests:

diff --git a/pypy/translator/jvm/test/test_builtin.py b/pypy/translator/jvm/test/test_builtin.py
--- a/pypy/translator/jvm/test/test_builtin.py
+++ b/pypy/translator/jvm/test/test_builtin.py
@@ -37,6 +37,15 @@
     def test_cast_primitive(self):
         py.test.skip('fixme!')
 
+    def test_os_fstat(self):
+        import os, stat
+        def fn():
+            fd = os.open(__file__, os.O_RDONLY, 0)
+            st = os.fstat(fd)
+            os.close(fd)
+            return st.st_mode
+        res = self.interpret(fn, [])
+        assert stat.S_ISREG(res)
 
 class TestJvmTime(JvmTest, BaseTestTime):
 

diff --git a/pypy/jit/codewriter/heaptracker.py b/pypy/jit/codewriter/heaptracker.py
--- a/pypy/jit/codewriter/heaptracker.py
+++ b/pypy/jit/codewriter/heaptracker.py
@@ -10,6 +10,30 @@
 def int2adr(int):
     return llmemory.cast_int_to_adr(int)
 
+def count_fields_if_immutable(STRUCT):
+    assert isinstance(STRUCT, lltype.GcStruct)
+    if STRUCT._hints.get('immutable', False):
+        try:
+            return _count_fields(STRUCT)
+        except ValueError:
+            pass
+    return -1
+
+def _count_fields(STRUCT):
+    if STRUCT == rclass.OBJECT:
+        return 0    # don't count 'typeptr'
+    result = 0
+    for fieldname, TYPE in STRUCT._flds.items():
+        if TYPE is lltype.Void:
+            pass       # ignore Voids
+        elif not isinstance(TYPE, lltype.ContainerType):
+            result += 1
+        elif isinstance(TYPE, lltype.GcStruct):
+            result += _count_fields(TYPE)
+        else:
+            raise ValueError(TYPE)
+    return result
+
 # ____________________________________________________________
 
 def has_gcstruct_a_vtable(GCSTRUCT):

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
@@ -1,4 +1,4 @@
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.rlib.jit import JitDriver
 
 


diff --git a/pypy/objspace/flow/model.py b/pypy/objspace/flow/model.py
--- a/pypy/objspace/flow/model.py
+++ b/pypy/objspace/flow/model.py
@@ -379,27 +379,6 @@
     return result
 
 
-def traverse(visit, functiongraph):
-    block = functiongraph.startblock
-    visit(block)
-    seen = identity_dict()
-    seen[block] = True
-    stack = list(block.exits[::-1])
-    while stack:
-        link = stack.pop()
-        visit(link)
-        block = link.target
-        if block not in seen:
-            visit(block)
-            seen[block] = True
-            stack += block.exits[::-1]
-
-
-def flatten(funcgraph):
-    l = []
-    traverse(l.append, funcgraph)
-    return l
-
 def flattenobj(*args):
     for arg in args:
         try:
@@ -497,6 +476,19 @@
             assert block.operations == ()
             assert block.exits == ()
 
+        def definevar(v, only_in_link=None):
+            assert isinstance(v, Variable)
+            assert v not in vars, "duplicate variable %r" % (v,)
+            assert v not in vars_previous_blocks, (
+                "variable %r used in more than one block" % (v,))
+            vars[v] = only_in_link
+
+        def usevar(v, in_link=None):
+            assert v in vars
+            if in_link is not None:
+                assert vars[v] is None or vars[v] is in_link
+
+
         for block in graph.iterblocks():
             assert bool(block.isstartblock) == (block is graph.startblock)
             assert type(block.exits) is tuple, (
@@ -506,18 +498,6 @@
                 assert block in exitblocks
             vars = {}
 
-            def definevar(v, only_in_link=None):
-                assert isinstance(v, Variable)
-                assert v not in vars, "duplicate variable %r" % (v,)
-                assert v not in vars_previous_blocks, (
-                    "variable %r used in more than one block" % (v,))
-                vars[v] = only_in_link
-
-            def usevar(v, in_link=None):
-                assert v in vars
-                if in_link is not None:
-                    assert vars[v] is None or vars[v] is in_link
-
             for v in block.inputargs:
                 definevar(v)
 

diff --git a/.hgignore b/.hgignore
--- a/.hgignore
+++ b/.hgignore
@@ -17,7 +17,6 @@
 ^pypy/doc/.+\.html$
 ^pypy/doc/basicblock\.asc$
 ^pypy/doc/.+\.svninfo$
-^pypy/translator/c/src/dtoa.o$
 ^pypy/translator/c/src/libffi_msvc/.+\.obj$
 ^pypy/translator/c/src/libffi_msvc/.+\.dll$
 ^pypy/translator/c/src/libffi_msvc/.+\.lib$
@@ -64,4 +63,4 @@
 ^pypy/doc/image/parsing_example.+\.png$
 ^compiled
 ^.git/
-^release/
\ No newline at end of file
+^release/

diff --git a/pypy/config/pypyoption.py b/pypy/config/pypyoption.py
--- a/pypy/config/pypyoption.py
+++ b/pypy/config/pypyoption.py
@@ -13,7 +13,7 @@
                and not p.basename.startswith('test')]
 
 essential_modules = dict.fromkeys(
-    ["exceptions", "_file", "sys", "__builtin__", "posix", "signal"]
+    ["exceptions", "_file", "sys", "__builtin__", "posix"]
 )
 
 default_modules = essential_modules.copy()
@@ -39,7 +39,7 @@
 translation_modules = default_modules.copy()
 translation_modules.update(dict.fromkeys(
     ["fcntl", "rctime", "select", "signal", "_rawffi", "zlib",
-     "struct", "md5", "cStringIO", "array"]))
+     "struct", "_md5", "cStringIO", "array"]))
 
 working_oo_modules = default_modules.copy()
 working_oo_modules.update(dict.fromkeys(
@@ -159,6 +159,11 @@
                cmdline="--allworkingmodules",
                negation=True),
 
+    StrOption("extmodules",
+              "Comma-separated list of third-party builtin modules",
+              cmdline="--ext",
+              default=None),
+
     BoolOption("translationmodules",
           "use only those modules that are needed to run translate.py on pypy",
                default=False,
@@ -352,8 +357,8 @@
         config.objspace.std.suggest(optimized_list_getitem=True)
         config.objspace.std.suggest(getattributeshortcut=True)
         config.objspace.std.suggest(newshortcut=True)
-        if not IS_64_BITS:
-            config.objspace.std.suggest(withsmalllong=True)
+        #if not IS_64_BITS:
+        #    config.objspace.std.suggest(withsmalllong=True)
 
     # extra costly optimizations only go in level 3
     if level == '3':

diff --git a/pypy/translator/stackless/transform.py b/pypy/translator/stackless/transform.py
--- a/pypy/translator/stackless/transform.py
+++ b/pypy/translator/stackless/transform.py
@@ -2,7 +2,7 @@
 from pypy.rpython.lltypesystem.lloperation import LL_OPERATIONS
 from pypy.rlib import rarithmetic
 from pypy.rpython import rclass, rmodel
-from pypy.translator.backendopt import support
+from pypy.translator.unsimplify import split_block
 from pypy.objspace.flow import model
 from pypy.translator import unsimplify, simplify
 from pypy.translator.unsimplify import varoftype
@@ -598,7 +598,7 @@
             link = block.exits[0]
             nextblock = None
         else:
-            link = support.split_block_with_keepalive(block, i+1)
+            link = split_block(None, block, i+1)
             i = 0
             nextblock = link.target
 
@@ -765,7 +765,7 @@
             exitcases = dict.fromkeys([l.exitcase for l in block.exits])
             nextblock = None
         else:
-            link = support.split_block_with_keepalive(block, i+1)
+            link = split_block(None, block, i+1)
             nextblock = link.target
             block.exitswitch = model.c_last_exception
             link.llexitcase = None

diff --git a/pypy/module/posix/__init__.py b/pypy/module/posix/__init__.py
--- a/pypy/module/posix/__init__.py
+++ b/pypy/module/posix/__init__.py
@@ -5,6 +5,25 @@
 import os, sys
 exec 'import %s as posix' % os.name
 
+# this is the list of function which is *not* present in the posix module of
+# IronPython 2.6, and that we want to ignore for now
+lltype_only_defs = [
+    'chown', 'chroot', 'closerange', 'confstr', 'confstr_names', 'ctermid', 'dup',
+    'dup2', 'execv', 'execve', 'fchdir', 'fchmod', 'fchown', 'fdatasync', 'fork',
+    'forkpty', 'fpathconf', 'fstatvfs', 'fsync', 'ftruncate', 'getegid', 'geteuid',
+    'getgid', 'getgroups', 'getloadavg', 'getlogin', 'getpgid', 'getpgrp', 'getppid',
+    'getsid', 'getuid', 'kill', 'killpg', 'lchown', 'link', 'lseek', 'major',
+    'makedev', 'minor', 'mkfifo', 'mknod', 'nice', 'openpty', 'pathconf', 'pathconf_names',
+    'pipe', 'readlink', 'setegid', 'seteuid', 'setgid', 'setgroups', 'setpgid', 'setpgrp',
+    'setregid', 'setreuid', 'setsid', 'setuid', 'stat_float_times', 'statvfs',
+    'statvfs_result', 'symlink', 'sysconf', 'sysconf_names', 'tcgetpgrp', 'tcsetpgrp',
+    'ttyname', 'uname', 'wait', 'wait3', 'wait4'
+    ]
+
+# the Win32 urandom implementation isn't going to translate on JVM or CLI so
+# we have to remove it
+lltype_only_defs.append('urandom')
+
 class Module(MixedModule):
     """This module provides access to operating system functionality that is
 standardized by the C Standard and the POSIX standard (a thinly
@@ -31,6 +50,10 @@
 
     if hasattr(os, 'wait'):
         appleveldefs['wait'] = 'app_posix.wait'
+    if hasattr(os, 'wait3'):
+        appleveldefs['wait3'] = 'app_posix.wait3'
+    if hasattr(os, 'wait4'):
+        appleveldefs['wait4'] = 'app_posix.wait4'
         
     interpleveldefs = {
     'open'      : 'interp_posix.open',
@@ -156,11 +179,12 @@
             interpleveldefs[name] = 'interp_posix.' + name
 
     def __init__(self, space, w_name):
+        # if it's an ootype translation, remove all the defs that are lltype
+        # only
         backend = space.config.translation.backend
-        # the Win32 urandom implementation isn't going to translate on JVM or CLI
-        # so we have to remove it
-        if 'urandom' in self.interpleveldefs and (backend == 'cli' or backend == 'jvm'):
-            del self.interpleveldefs['urandom']
+        if backend == 'cli' or backend == 'jvm':
+            for name in lltype_only_defs:
+                self.interpleveldefs.pop(name, None)
         MixedModule.__init__(self, space, w_name)
 
     def startup(self, space):

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
@@ -1,6 +1,6 @@
 import py
 from pypy.rlib.jit import JitDriver
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 
 
 class ListTests:

diff --git a/pypy/objspace/std/mapdict.py b/pypy/objspace/std/mapdict.py
--- a/pypy/objspace/std/mapdict.py
+++ b/pypy/objspace/std/mapdict.py
@@ -641,6 +641,18 @@
         else:
             self._as_rdict().impl_fallback_setitem(w_key, w_value)
 
+    def impl_setdefault(self,  w_key, w_default):
+        space = self.space
+        if space.is_w(space.type(w_key), space.w_str):
+            key = space.str_w(w_key)
+            w_result = self.impl_getitem_str(key)
+            if w_result is not None:
+                return w_result
+            self.impl_setitem_str(key, w_default)
+            return w_default
+        else:
+            return self._as_rdict().impl_fallback_setdefault(w_key, w_default)
+
     def impl_delitem(self, w_key):
         space = self.space
         w_key_type = space.type(w_key)

diff --git a/pypy/rpython/extfunc.py b/pypy/rpython/extfunc.py
--- a/pypy/rpython/extfunc.py
+++ b/pypy/rpython/extfunc.py
@@ -249,6 +249,9 @@
     llfakeimpl, oofakeimpl: optional; if provided, they are called by the llinterpreter
     sandboxsafe: use True if the function performs no I/O (safe for --sandbox)
     """
+    
+    if export_name is None:
+        export_name = function.__name__
 
     class FunEntry(ExtFuncEntry):
         _about_ = function

diff --git a/pypy/translator/goal/query.py b/pypy/translator/goal/query.py
--- a/pypy/translator/goal/query.py
+++ b/pypy/translator/goal/query.py
@@ -30,15 +30,13 @@
 def polluted_qgen(translator):
     """list functions with still real SomeObject variables"""
     annotator = translator.annotator
-    def visit(block):
-        if isinstance(block, flowmodel.Block):
-            for v in block.getvariables():
-                s = annotator.binding(v, None)
-                if s and s.__class__ == annmodel.SomeObject and s.knowntype != type:
-                    raise Found
     for g in translator.graphs:
         try:
-            flowmodel.traverse(visit, g)
+            for block in g.iterblocks():
+                for v in block.getvariables():
+                    s = annotator.binding(v, None)
+                    if s and s.__class__ == annmodel.SomeObject and s.knowntype != type:
+                        raise Found
         except Found:
             line = "%s: %s" % (g, graph_sig(translator, g))
             yield line

diff --git a/pypy/tool/jitlogparser/storage.py b/pypy/tool/jitlogparser/storage.py
--- a/pypy/tool/jitlogparser/storage.py
+++ b/pypy/tool/jitlogparser/storage.py
@@ -30,18 +30,18 @@
             self.codes[fname] = res
             return res
 
-    def disassemble_code(self, fname, startlineno):
+    def disassemble_code(self, fname, startlineno, name):
         try:
             if py.path.local(fname).check(file=False):
                 return None # cannot find source file
         except py.error.EACCES:
             return None # cannot open the file
-        key = (fname, startlineno)
+        key = (fname, startlineno, name)
         try:
             return self.disassembled_codes[key]
         except KeyError:
             codeobjs = self.load_code(fname)
-            if startlineno not in codeobjs:
+            if (startlineno, name) not in codeobjs:
                 # cannot find the code obj at this line: this can happen for
                 # various reasons, e.g. because the .py files changed since
                 # the log was produced, or because the co_firstlineno
@@ -49,7 +49,7 @@
                 # produced by gateway.applevel(), such as the ones found in
                 # nanos.py)
                 return None
-            code = codeobjs[startlineno]
+            code = codeobjs[(startlineno, name)]
             res = dis(code)
             self.disassembled_codes[key] = res
             return res

diff --git a/pypy/jit/metainterp/test/test_longlong.py b/pypy/jit/metainterp/test/test_longlong.py
--- a/pypy/jit/metainterp/test/test_longlong.py
+++ b/pypy/jit/metainterp/test/test_longlong.py
@@ -1,6 +1,6 @@
 import py, sys
 from pypy.rlib.rarithmetic import r_longlong, r_ulonglong, r_uint, intmask
-from pypy.jit.metainterp.test.test_basic import LLJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin
 
 class WrongResult(Exception):
     pass

diff --git a/lib_pypy/_ctypes/builtin.py b/lib_pypy/_ctypes/builtin.py
--- a/lib_pypy/_ctypes/builtin.py
+++ b/lib_pypy/_ctypes/builtin.py
@@ -1,6 +1,9 @@
 
 import _rawffi, sys
-import threading
+try:
+    from thread import _local as local
+except ImportError:
+    local = object    # no threads
 
 class ConvMode:
     encoding = 'ascii'
@@ -28,7 +31,7 @@
     arg = cobj._get_buffer_value()
     return _rawffi.wcharp2rawunicode(arg, lgt)
 
-class ErrorObject(threading.local):
+class ErrorObject(local):
     def __init__(self):
         self.errno = 0
         self.winerror = 0

diff --git a/pypy/module/cpyext/test/test_stringobject.py b/pypy/module/cpyext/test/test_stringobject.py
--- a/pypy/module/cpyext/test/test_stringobject.py
+++ b/pypy/module/cpyext/test/test_stringobject.py
@@ -194,8 +194,8 @@
         c_buf = py_str.c_ob_type.c_tp_as_buffer
         assert c_buf
         py_obj = rffi.cast(PyObject, py_str)
-        assert c_buf.c_bf_getsegcount(py_obj, lltype.nullptr(rffi.INTP.TO)) == 1
-        ref = lltype.malloc(rffi.INTP.TO, 1, flavor='raw')
+        assert c_buf.c_bf_getsegcount(py_obj, lltype.nullptr(Py_ssize_tP.TO)) == 1
+        ref = lltype.malloc(Py_ssize_tP.TO, 1, flavor='raw')
         assert c_buf.c_bf_getsegcount(py_obj, ref) == 1
         assert ref[0] == 10
         lltype.free(ref, flavor='raw')

diff --git a/pypy/rlib/objectmodel.py b/pypy/rlib/objectmodel.py
--- a/pypy/rlib/objectmodel.py
+++ b/pypy/rlib/objectmodel.py
@@ -255,7 +255,7 @@
     x = ord(s[0]) << 7
     i = 0
     while i < length:
-        x = (1000003*x) ^ ord(s[i])
+        x = intmask((1000003*x) ^ ord(s[i]))
         i += 1
     x ^= length
     return intmask(x)


diff --git a/pypy/translator/jvm/typesystem.py b/pypy/translator/jvm/typesystem.py
--- a/pypy/translator/jvm/typesystem.py
+++ b/pypy/translator/jvm/typesystem.py
@@ -181,6 +181,7 @@
 
 jIntegerClass = JvmClassType('java.lang.Integer')
 jLongClass = JvmClassType('java.lang.Long')
+jShortClass = JvmClassType('java.lang.Short')
 jDoubleClass = JvmClassType('java.lang.Double')
 jByteClass = JvmClassType('java.lang.Byte')
 jCharClass = JvmClassType('java.lang.Character')
@@ -239,6 +240,7 @@
 jDouble = JvmScalarType('D', jDoubleClass, 'doubleValue')
 jByte = JvmScalarType('B', jByteClass, 'byteValue')
 jChar = JvmScalarType('C', jCharClass, 'charValue')
+jShort = JvmScalarType('S', jShortClass, 'shortValue')
 
 class Generifier(object):
 
@@ -527,6 +529,7 @@
         if desc == 'C':    return self._o("i")   # Characters
         if desc == 'B':    return self._o("i")   # Bytes
         if desc == 'Z':    return self._o("i")   # Boolean
+        if desc == 'S':    return self._o("i")   # Short
 
         assert False, "Unknown argtype=%s" % repr(argtype)
         raise NotImplementedError
@@ -625,6 +628,7 @@
 NOP =       Opcode('nop')
 I2D =       Opcode('i2d')
 I2L =       Opcode('i2l')
+I2S =       Opcode('i2s')
 D2I=        Opcode('d2i')
 #D2L=        Opcode('d2l') #PAUL
 L2I =       Opcode('l2i')
@@ -891,6 +895,7 @@
 SYSTEMIDENTITYHASH =    Method.s(jSystem, 'identityHashCode', (jObject,), jInt)
 SYSTEMGC =              Method.s(jSystem, 'gc', (), jVoid)
 INTTOSTRINGI =          Method.s(jIntegerClass, 'toString', (jInt,), jString)
+SHORTTOSTRINGS =        Method.s(jShortClass, 'toString', (jShort,), jString)
 LONGTOSTRINGL =         Method.s(jLongClass, 'toString', (jLong,), jString)
 DOUBLETOSTRINGD =       Method.s(jDoubleClass, 'toString', (jDouble,), jString)
 CHARTOSTRINGC =         Method.s(jCharClass, 'toString', (jChar,), jString)
@@ -922,15 +927,19 @@
 CLASSISASSIGNABLEFROM = Method.v(jClass, 'isAssignableFrom', (jClass,), jBool)
 STRINGBUILDERAPPEND =   Method.v(jStringBuilder, 'append',
                                  (jString,), jStringBuilder)
+PYPYINTBETWEEN =        Method.s(jPyPy, 'int_between', (jInt,jInt,jInt), jBool)
 PYPYUINTCMP =           Method.s(jPyPy, 'uint_cmp', (jInt,jInt,), jInt)
 PYPYULONGCMP =          Method.s(jPyPy, 'ulong_cmp', (jLong,jLong), jInt)
 PYPYUINTMOD =           Method.v(jPyPy, 'uint_mod', (jInt, jInt), jInt)
 PYPYUINTMUL =           Method.v(jPyPy, 'uint_mul', (jInt, jInt), jInt)
 PYPYUINTDIV =           Method.v(jPyPy, 'uint_div', (jInt, jInt), jInt)
 PYPYULONGMOD =          Method.v(jPyPy, 'ulong_mod', (jLong, jLong), jLong)
+PYPYUINTTOLONG =        Method.s(jPyPy, 'uint_to_long', (jInt,), jLong)
 PYPYUINTTODOUBLE =      Method.s(jPyPy, 'uint_to_double', (jInt,), jDouble)
 PYPYDOUBLETOUINT =      Method.s(jPyPy, 'double_to_uint', (jDouble,), jInt)
 PYPYDOUBLETOLONG =      Method.v(jPyPy, 'double_to_long', (jDouble,), jLong) #PAUL
+PYPYDOUBLETOULONG =     Method.s(jPyPy, 'double_to_ulong', (jDouble,), jLong)
+PYPYULONGTODOUBLE =     Method.s(jPyPy, 'ulong_to_double', (jLong,), jDouble)
 PYPYLONGBITWISENEGATE = Method.v(jPyPy, 'long_bitwise_negate', (jLong,), jLong)
 PYPYSTRTOINT =          Method.v(jPyPy, 'str_to_int', (jString,), jInt)
 PYPYSTRTOUINT =         Method.v(jPyPy, 'str_to_uint', (jString,), jInt)

diff --git a/pypy/translator/backendopt/test/test_removenoops.py b/pypy/translator/backendopt/test/test_removenoops.py
--- a/pypy/translator/backendopt/test/test_removenoops.py
+++ b/pypy/translator/backendopt/test/test_removenoops.py
@@ -1,12 +1,12 @@
 from pypy.translator.backendopt.removenoops import remove_same_as, \
-        remove_unaryops, remove_duplicate_casts, remove_superfluous_keep_alive
+        remove_unaryops, remove_duplicate_casts
 from pypy.translator.backendopt.inline import simple_inline_function
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.rpython.memory.gctransform.test.test_transform import getops
 from pypy.translator.test.snippet import simple_method
 from pypy.translator.backendopt.all import backend_optimizations
 from pypy.translator.backendopt.all import INLINE_THRESHOLD_FOR_TEST
-from pypy.objspace.flow.model import checkgraph, flatten, Block
+from pypy.objspace.flow.model import checkgraph, Block
 from pypy.rpython.lltypesystem import lltype
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.llinterp import LLInterpreter
@@ -115,20 +115,6 @@
     result = interp.eval_graph(f_graph, [-2])
     assert result == -1
 
-def test_remove_keepalive():
-    S = lltype.GcStruct("s", ("f", lltype.Signed))
-    def f():
-        s1 = lltype.malloc(S)
-        llop.keepalive(lltype.Void, s1)
-        s2 = lltype.malloc(S)
-        llop.keepalive(lltype.Void, s1)
-        llop.keepalive(lltype.Void, s2)
-        return lltype.cast_ptr_to_int(s1) + lltype.cast_ptr_to_int(s2)
-    graph, t = get_graph(f, [])
-    remove_superfluous_keep_alive(graph)
-    ops = getops(graph)
-    assert len(ops['keepalive']) == 2
-
 def test_remove_duplicate_casts():
     class A(object):
         def __init__(self, x, y):

diff --git a/pypy/translator/simplify.py b/pypy/translator/simplify.py
--- a/pypy/translator/simplify.py
+++ b/pypy/translator/simplify.py
@@ -9,7 +9,7 @@
 from pypy.objspace.flow import operation
 from pypy.objspace.flow.model import (SpaceOperation, Variable, Constant, Block,
                                       Link, c_last_exception, checkgraph,
-                                      traverse, mkentrymap)
+                                      mkentrymap)
 from pypy.rlib import rarithmetic
 from pypy.translator import unsimplify
 from pypy.translator.backendopt import ssa
@@ -76,23 +76,19 @@
 def desugar_isinstance(graph):
     """Replace isinstance operation with a call to isinstance."""
     constant_isinstance = Constant(isinstance)
-    def visit(block):
-        if not isinstance(block, Block):
-            return
+    for block in graph.iterblocks():
         for i in range(len(block.operations) - 1, -1, -1):
             op = block.operations[i]
             if op.opname == "isinstance":
                 args = [constant_isinstance, op.args[0], op.args[1]]
                 new_op = SpaceOperation("simple_call", args, op.result)
                 block.operations[i] = new_op
-    traverse(visit, graph)
 
 def eliminate_empty_blocks(graph):
     """Eliminate basic blocks that do not contain any operations.
     When this happens, we need to replace the preceeding link with the
     following link.  Arguments of the links should be updated."""
-    def visit(link):
-        if isinstance(link, Link):
+    for link in list(graph.iterlinks()):
             while not link.target.operations:
                 block1 = link.target
                 if block1.exitswitch is not None:
@@ -113,7 +109,6 @@
                 link.args = outputargs
                 link.target = exit.target
                 # the while loop above will simplify recursively the new link
-    traverse(visit, graph)
 
 def transform_ovfcheck(graph):
     """The special function calls ovfcheck and ovfcheck_lshift need to
@@ -174,11 +169,10 @@
     def rename(v):
         return renaming.get(v, v)
 
-    def visit(block):
-        if not (isinstance(block, Block)
-                and block.exitswitch == clastexc
+    for block in graph.iterblocks():
+        if not (block.exitswitch == clastexc
                 and block.exits[-1].exitcase is Exception):
-            return
+            continue
         covered = [link.exitcase for link in block.exits[1:-1]]
         seen = []
         preserve = list(block.exits[:-1])
@@ -233,8 +227,6 @@
             exits.append(link)
         block.recloseblock(*(preserve + exits))
 
-    traverse(visit, graph)
-
 def transform_xxxitem(graph):
     # xxx setitem too
     for block in graph.iterblocks():
@@ -262,9 +254,9 @@
                 return True
         return False
 
-    def visit(block):
-        if not (isinstance(block, Block) and block.exitswitch == clastexc):
-            return
+    for block in list(graph.iterblocks()):
+        if block.exitswitch != clastexc:
+            continue
         exits = []
         seen = []
         for link in block.exits:
@@ -283,8 +275,6 @@
             seen.append(case)
         block.recloseblock(*exits)
 
-    traverse(visit, graph)
-
 def join_blocks(graph):
     """Links can be deleted if they are the single exit of a block and
     the single entry point of the next block.  When this happens, we can
@@ -340,8 +330,7 @@
     this is how implicit exceptions are removed (see _implicit_ in
     flowcontext.py).
     """
-    def visit(block):
-        if isinstance(block, Block):
+    for block in list(graph.iterblocks()):
             for i in range(len(block.exits)-1, -1, -1):
                 exit = block.exits[i]
                 if not (exit.target is graph.exceptblock and
@@ -361,7 +350,6 @@
                 lst = list(block.exits)
                 del lst[i]
                 block.recloseblock(*lst)
-    traverse(visit, graph)
 
 
 # _____________________________________________________________________
@@ -627,12 +615,11 @@
                         tgts.append((exit.exitcase, tgt))
         return tgts
 
-    def visit(block):
-        if isinstance(block, Block) and block.operations and block.operations[-1].opname == 'is_true':
+    for block in graph.iterblocks():
+        if block.operations and block.operations[-1].opname == 'is_true':
             tgts = has_is_true_exitpath(block)
             if tgts:
                 candidates.append((block, tgts))
-    traverse(visit, graph)
 
     while candidates:
         cand, tgts = candidates.pop()

diff --git a/pypy/translator/cli/metavm.py b/pypy/translator/cli/metavm.py
--- a/pypy/translator/cli/metavm.py
+++ b/pypy/translator/cli/metavm.py
@@ -270,23 +270,38 @@
 
         generator.ilasm.call('void [pypylib]pypy.runtime.DebugPrint::DEBUG_PRINT(%s)' % signature)
 
+INT_SIZE = {
+    ootype.Bool: 1,
+    ootype.Char: 2,
+    ootype.UniChar: 2,
+    rffi.SHORT: 2,
+    ootype.Signed: 4,
+    ootype.Unsigned: 4,
+    ootype.SignedLongLong: 8,
+    ootype.UnsignedLongLong: 8
+    }
 
-OOTYPE_TO_MNEMONIC = {
-    ootype.Bool: 'i1', 
-    ootype.Char: 'i2',
-    ootype.UniChar: 'i2',
-    rffi.SHORT: 'i2',
-    ootype.Signed: 'i4',
-    ootype.SignedLongLong: 'i8',
-    ootype.Unsigned: 'u4',
-    ootype.UnsignedLongLong: 'u8',
-    ootype.Float: 'r8',
-    }
+UNSIGNED_TYPES = [ootype.Char, ootype.UniChar, rffi.USHORT,
+                  ootype.Unsigned, ootype.UnsignedLongLong]
+
+def ootype_to_mnemonic(FROM, TO, default=None):
+    if TO == ootype.Float:
+        return 'r8'
+    #
+    try:
+        size = str(INT_SIZE[TO])
+    except KeyError:
+        return default
+    if FROM in UNSIGNED_TYPES:
+        return 'u' + size
+    else:
+        return 'i' + size
 
 class _CastPrimitive(MicroInstruction):
     def render(self, generator, op):
+        FROM = op.args[0].concretetype
         TO = op.result.concretetype
-        mnemonic = OOTYPE_TO_MNEMONIC[TO]
+        mnemonic = ootype_to_mnemonic(FROM, TO)
         generator.ilasm.opcode('conv.%s' % mnemonic)
 
 Call = _Call()

diff --git a/pypy/module/cpyext/include/frameobject.h b/pypy/module/cpyext/include/frameobject.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/include/frameobject.h
@@ -0,0 +1,17 @@
+#ifndef Py_FRAMEOBJECT_H
+#define Py_FRAMEOBJECT_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+    PyObject_HEAD
+    PyCodeObject *f_code;
+    PyObject *f_globals;
+    int f_lineno;
+} PyFrameObject;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_FRAMEOBJECT_H */

diff --git a/pypy/doc/config/generate.py b/pypy/doc/config/generate.py
--- a/pypy/doc/config/generate.py
+++ b/pypy/doc/config/generate.py
@@ -8,8 +8,8 @@
 for descr in all_optiondescrs:
     prefix = descr._name
     c = config.Config(descr)
-    thisdir.join(prefix + ".txt").ensure()
+    thisdir.join(prefix + ".rst").ensure()
     for p in c.getpaths(include_groups=True):
-        basename = prefix + "." + p + ".txt"
+        basename = prefix + "." + p + ".rst"
         f = thisdir.join(basename)
         f.ensure()

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
@@ -5,7 +5,7 @@
 from pypy.rlib.libffi import ArgChain
 from pypy.rlib.test.test_libffi import TestLibffiCall as _TestLibffiCall
 from pypy.rpython.lltypesystem import lltype, rffi
-from pypy.jit.metainterp.test.test_basic import LLJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin
 
 
 class TestFfiCall(LLJitMixin, _TestLibffiCall):

diff --git a/pypy/interpreter/pyopcode.py b/pypy/interpreter/pyopcode.py
--- a/pypy/interpreter/pyopcode.py
+++ b/pypy/interpreter/pyopcode.py
@@ -138,11 +138,13 @@
                 # raised after the exception handler block was popped.
                 try:
                     trace = self.w_f_trace
-                    self.w_f_trace = None
+                    if trace is not None:
+                        self.w_f_trace = None
                     try:
                         ec.bytecode_trace_after_exception(self)
                     finally:
-                        self.w_f_trace = trace
+                        if trace is not None:
+                            self.w_f_trace = trace
                 except OperationError, e:
                     operr = e
             pytraceback.record_application_traceback(
@@ -1421,9 +1423,10 @@
 
         # add a softspace unless we just printed a string which ends in a '\t'
         # or '\n' -- or more generally any whitespace character but ' '
-        if isinstance(x, str) and x and x[-1].isspace() and x[-1]!=' ':
-            return
-        # XXX add unicode handling
+        if isinstance(x, (str, unicode)) and x:
+            lastchar = x[-1]
+            if lastchar.isspace() and lastchar != ' ':
+                return
         file_softspace(stream, True)
     print_item_to._annspecialcase_ = "specialize:argtype(0)"
 

diff --git a/pypy/translator/goal/old_queries.py b/pypy/translator/goal/old_queries.py
--- a/pypy/translator/goal/old_queries.py
+++ b/pypy/translator/goal/old_queries.py
@@ -415,12 +415,10 @@
         ops = 0
     count = Counter()
     def visit(block):
-        if isinstance(block, flowmodel.Block):
+    for block in graph.iterblocks():
             count.blocks += 1
             count.ops += len(block.operations)
-        elif isinstance(block, flowmodel.Link):
-            count.links += 1
-    flowmodel.traverse(visit, graph)
+    count.links = len(list(graph.iterlinks()))
     return count.blocks, count.links, count.ops
 
 # better used before backends opts

diff --git a/pypy/module/_multiprocessing/test/test_connection.py b/pypy/module/_multiprocessing/test/test_connection.py
--- a/pypy/module/_multiprocessing/test/test_connection.py
+++ b/pypy/module/_multiprocessing/test/test_connection.py
@@ -10,7 +10,7 @@
 
 class AppTestBufferTooShort:
     def setup_class(cls):
-        space = gettestobjspace(usemodules=('_multiprocessing', 'thread'))
+        space = gettestobjspace(usemodules=('_multiprocessing', 'thread', 'signal'))
         cls.space = space
 
         if option.runappdirect:
@@ -88,7 +88,7 @@
 
 class AppTestSocketConnection(BaseConnectionTest):
     def setup_class(cls):
-        space = gettestobjspace(usemodules=('_multiprocessing', 'thread'))
+        space = gettestobjspace(usemodules=('_multiprocessing', 'thread', 'signal'))
         cls.space = space
         cls.w_connections = space.newlist([])
 

diff --git a/pypy/module/thread/test/support.py b/pypy/module/thread/test/support.py
--- a/pypy/module/thread/test/support.py
+++ b/pypy/module/thread/test/support.py
@@ -32,7 +32,7 @@
 class GenericTestThread:
 
     def setup_class(cls):
-        space = gettestobjspace(usemodules=('thread', 'time'))
+        space = gettestobjspace(usemodules=('thread', 'time', 'signal'))
         cls.space = space
 
         if option.runappdirect:

diff --git a/pypy/interpreter/nestedscope.py b/pypy/interpreter/nestedscope.py
--- a/pypy/interpreter/nestedscope.py
+++ b/pypy/interpreter/nestedscope.py
@@ -219,12 +219,14 @@
             freevars = [self.space.interp_w(Cell, cell)
                         for cell in self.space.fixedview(w_freevarstuple)]
         else:
-            nfreevars = len(codeobj.co_freevars)
-            freevars = [self.space.interp_w(Cell, self.popvalue())
-                        for i in range(nfreevars)]
-            freevars.reverse()
-        defaultarguments = [self.popvalue() for i in range(numdefaults)]
-        defaultarguments.reverse()
+            n = len(codeobj.co_freevars)
+            freevars = [None] * n
+            while True:
+                n -= 1
+                if n < 0:
+                    break
+                freevars[n] = self.space.interp_w(Cell, self.popvalue())
+        defaultarguments = self.popvalues(numdefaults)
         fn = function.Function(self.space, codeobj, self.w_globals,
                                defaultarguments, freevars)
         self.pushvalue(self.space.wrap(fn))

diff --git a/pypy/translator/cli/src/pypylib.cs b/pypy/translator/cli/src/pypylib.cs
--- a/pypy/translator/cli/src/pypylib.cs
+++ b/pypy/translator/cli/src/pypylib.cs
@@ -26,7 +26,10 @@
             else {
                 string res = "";
                 foreach(char ch in x)
-                    res+= string.Format("\\x{0:X2}", (int)ch);
+                    if (ch >= 32 && ch < 128)
+                        res+= ch;
+                    else
+                        res+= string.Format("\\x{0:X2}", (int)ch);
                 return string.Format("'{0}'", res);
             }
         }
@@ -498,6 +501,11 @@
             }
         }
 
+        public static bool IntBetween(int a, int b, int c)
+        {
+            return a <= b && b < c;
+        }
+
         public static bool Equal<T>(T t1, T t2) 
         { 
             if (t1 == null)
@@ -717,9 +725,31 @@
             return s.Substring(start, count);
         }
 
-        public static string[] ll_split_chr(string s, char ch)
+        public static string[] ll_split_chr(string s, char ch, int max)
         {
-            return s.Split(ch);
+            if (max < 0)
+                return s.Split(ch);
+            else
+                return s.Split(new Char[] {ch}, max + 1);
+        }
+
+        public static string[] ll_rsplit_chr(string s, char ch, int max)
+        {
+            string[] splits = s.Split(ch);
+            if (max < 0 || splits.Length <= max + 1)
+                return splits;
+            else {
+                /* XXX not very efficient */
+                string first = splits[0];
+                // join the first (length - max - 1) items
+                int i;
+                for (i = 1; i < splits.Length - max; i++)
+                    first += ch + splits[i];
+                splits[0] = first;
+                Array.Copy(splits, i, splits, 1, max);
+                Array.Resize(ref splits, max + 1);
+                return splits;
+            }
         }
 
         public static bool ll_contains(string s, char ch)
@@ -1123,10 +1153,36 @@
 
     public class rffi
     {
-      public static int tolower(int chr)
-      {
-        return (int)Char.ToLower((char)chr);
-      }
+        public static int tolower(int chr)
+        {
+            return (int)Char.ToLower((char)chr);
+        }
+
+        public static int locale_tolower(int chr)
+        {
+            return (int)Char.ToLower((char)chr);
+        }
+
+        public static int locale_isupper(int chr)
+        {
+            return Convert.ToInt32(Char.IsUpper((char)chr));
+        }
+
+        public static int locale_islower(int chr)
+        {
+            return Convert.ToInt32(Char.IsLower((char)chr));
+        }
+
+        public static int locale_isalpha(int chr)
+        {
+            return Convert.ToInt32(Char.IsLetter((char)chr));
+        }
+
+        public static int locale_isalnum(int chr)
+        {
+            return Convert.ToInt32(Char.IsLetterOrDigit((char)chr));
+        }
+
     }
 
 }

diff --git a/pypy/jit/backend/x86/test/test_basic.py b/pypy/jit/backend/x86/test/test_basic.py
--- a/pypy/jit/backend/x86/test/test_basic.py
+++ b/pypy/jit/backend/x86/test/test_basic.py
@@ -1,18 +1,18 @@
 import py
 from pypy.jit.backend.detect_cpu import getcpuclass
 from pypy.jit.metainterp.warmspot import ll_meta_interp
-from pypy.jit.metainterp.test import test_basic
+from pypy.jit.metainterp.test import support, test_ajit
 from pypy.jit.codewriter.policy import StopAtXPolicy
 from pypy.rlib.jit import JitDriver
 
-class Jit386Mixin(test_basic.LLJitMixin):
+class Jit386Mixin(support.LLJitMixin):
     type_system = 'lltype'
     CPUClass = getcpuclass()
 
     def check_jumps(self, maxcount):
         pass
 
-class TestBasic(Jit386Mixin, test_basic.BaseLLtypeTests):
+class TestBasic(Jit386Mixin, test_ajit.BaseLLtypeTests):
     # for the individual tests see
     # ====> ../../../metainterp/test/test_basic.py
     def test_bug(self):

diff --git a/pypy/module/thread/os_local.py b/pypy/module/thread/os_local.py
--- a/pypy/module/thread/os_local.py
+++ b/pypy/module/thread/os_local.py
@@ -12,7 +12,7 @@
     def __init__(self, space, initargs):
         self.initargs = initargs
         ident = thread.get_ident()
-        self.dicts = {ident: space.newdict()}
+        self.dicts = {ident: space.newdict(instance=True)}
 
     def getdict(self, space):
         ident = thread.get_ident()
@@ -51,10 +51,6 @@
                         __dict__ = GetSetProperty(descr_get_dict, cls=Local),
                         )
 
-def getlocaltype(space):
-    return space.gettypeobject(Local.typedef)
-
-
 def finish_thread(w_obj):
     assert isinstance(w_obj, Local)
     ident = thread.get_ident()

diff --git a/pypy/rpython/module/ll_os.py b/pypy/rpython/module/ll_os.py
--- a/pypy/rpython/module/ll_os.py
+++ b/pypy/rpython/module/ll_os.py
@@ -29,7 +29,7 @@
 from pypy.rpython.lltypesystem.rstr import STR
 from pypy.rpython.annlowlevel import llstr
 from pypy.rlib import rgc
-from pypy.rlib.objectmodel import keepalive_until_here, specialize
+from pypy.rlib.objectmodel import specialize
 
 def monkeypatch_rposix(posixfunc, unicodefunc, signature):
     func_name = posixfunc.__name__

diff --git a/pypy/translator/jvm/src/pypy/StatResult.java b/pypy/translator/jvm/src/pypy/StatResult.java
--- a/pypy/translator/jvm/src/pypy/StatResult.java
+++ b/pypy/translator/jvm/src/pypy/StatResult.java
@@ -8,7 +8,7 @@
  *
  * <p>The actual stat() function is defined in PyPy.java.
  */
-class StatResult {
+public class StatResult {
     public int item0, item3, item4, item5;
     public long item1, item2, item6;
     public double item7, item8, item9;

diff --git a/pypy/jit/metainterp/test/test_basic.py b/pypy/jit/metainterp/test/test_ajit.py
copy from pypy/jit/metainterp/test/test_basic.py
copy to pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_basic.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -4,269 +4,17 @@
 from pypy.rlib.jit import loop_invariant
 from pypy.rlib.jit import jit_debug, assert_green, AssertGreenFailed
 from pypy.rlib.jit import unroll_safe, current_trace_length
-from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats
-from pypy.jit.backend.llgraph import runner
 from pypy.jit.metainterp import pyjitpl, history
 from pypy.jit.metainterp.warmstate import set_future_value
+from pypy.jit.metainterp.warmspot import get_stats
 from pypy.jit.codewriter.policy import JitPolicy, StopAtXPolicy
-from pypy.jit.codewriter import longlong
 from pypy import conftest
 from pypy.rlib.rarithmetic import ovfcheck
 from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper
 from pypy.rpython.lltypesystem import lltype, llmemory
 from pypy.rpython.ootypesystem import ootype
 from pypy.jit.metainterp.optimizeopt import ALL_OPTS_DICT
-
-def _get_jitcodes(testself, CPUClass, func, values, type_system,
-                  supports_longlong=False, **kwds):
-    from pypy.jit.codewriter import support, codewriter
-
-    class FakeJitCell:
-        __compiled_merge_points = []
-        def get_compiled_merge_points(self):
-            return self.__compiled_merge_points[:]
-        def set_compiled_merge_points(self, lst):
-            self.__compiled_merge_points = lst
-
-    class FakeWarmRunnerState:
-        def attach_unoptimized_bridge_from_interp(self, greenkey, newloop):
-            pass
-
-        def jit_cell_at_key(self, greenkey):
-            assert greenkey == []
-            return self._cell
-        _cell = FakeJitCell()
-
-        trace_limit = sys.maxint
-        enable_opts = ALL_OPTS_DICT
-
-    func._jit_unroll_safe_ = True
-    rtyper = support.annotate(func, values, type_system=type_system)
-    graphs = rtyper.annotator.translator.graphs
-    result_kind = history.getkind(graphs[0].getreturnvar().concretetype)[0]
-
-    class FakeJitDriverSD:
-        num_green_args = 0
-        portal_graph = graphs[0]
-        virtualizable_info = None
-        greenfield_info = None
-        result_type = result_kind
-        portal_runner_ptr = "???"
-
-    stats = history.Stats()
-    cpu = CPUClass(rtyper, stats, None, False)
-    cw = codewriter.CodeWriter(cpu, [FakeJitDriverSD()])
-    testself.cw = cw
-    policy = JitPolicy()
-    policy.set_supports_longlong(supports_longlong)
-    cw.find_all_graphs(policy)
-    #
-    testself.warmrunnerstate = FakeWarmRunnerState()
-    testself.warmrunnerstate.cpu = cpu
-    FakeJitDriverSD.warmstate = testself.warmrunnerstate
-    if hasattr(testself, 'finish_setup_for_interp_operations'):
-        testself.finish_setup_for_interp_operations()
-    #
-    cw.make_jitcodes(verbose=True)
-
-def _run_with_blackhole(testself, args):
-    from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder
-    cw = testself.cw
-    blackholeinterpbuilder = BlackholeInterpBuilder(cw)
-    blackholeinterp = blackholeinterpbuilder.acquire_interp()
-    count_i = count_r = count_f = 0
-    for value in args:
-        T = lltype.typeOf(value)
-        if T == lltype.Signed:
-            blackholeinterp.setarg_i(count_i, value)
-            count_i += 1
-        elif T == llmemory.GCREF:
-            blackholeinterp.setarg_r(count_r, value)
-            count_r += 1
-        elif T == lltype.Float:
-            value = longlong.getfloatstorage(value)
-            blackholeinterp.setarg_f(count_f, value)
-            count_f += 1
-        else:
-            raise TypeError(T)
-    [jitdriver_sd] = cw.callcontrol.jitdrivers_sd
-    blackholeinterp.setposition(jitdriver_sd.mainjitcode, 0)
-    blackholeinterp.run()
-    return blackholeinterp._final_result_anytype()
-
-def _run_with_pyjitpl(testself, args):
-
-    class DoneWithThisFrame(Exception):
-        pass
-
-    class DoneWithThisFrameRef(DoneWithThisFrame):
-        def __init__(self, cpu, *args):
-            DoneWithThisFrame.__init__(self, *args)
-
-    cw = testself.cw
-    opt = history.Options(listops=True)
-    metainterp_sd = pyjitpl.MetaInterpStaticData(cw.cpu, opt)
-    metainterp_sd.finish_setup(cw)
-    [jitdriver_sd] = metainterp_sd.jitdrivers_sd
-    metainterp = pyjitpl.MetaInterp(metainterp_sd, jitdriver_sd)
-    metainterp_sd.DoneWithThisFrameInt = DoneWithThisFrame
-    metainterp_sd.DoneWithThisFrameRef = DoneWithThisFrameRef
-    metainterp_sd.DoneWithThisFrameFloat = DoneWithThisFrame
-    testself.metainterp = metainterp
-    try:
-        metainterp.compile_and_run_once(jitdriver_sd, *args)
-    except DoneWithThisFrame, e:
-        #if conftest.option.view:
-        #    metainterp.stats.view()
-        return e.args[0]
-    else:
-        raise Exception("FAILED")
-
-def _run_with_machine_code(testself, args):
-    metainterp = testself.metainterp
-    num_green_args = metainterp.jitdriver_sd.num_green_args
-    loop_tokens = metainterp.get_compiled_merge_points(args[:num_green_args])
-    if len(loop_tokens) != 1:
-        return NotImplemented
-    # a loop was successfully created by _run_with_pyjitpl(); call it
-    cpu = metainterp.cpu
-    for i in range(len(args) - num_green_args):
-        x = args[num_green_args + i]
-        typecode = history.getkind(lltype.typeOf(x))
-        set_future_value(cpu, i, x, typecode)
-    faildescr = cpu.execute_token(loop_tokens[0])
-    assert faildescr.__class__.__name__.startswith('DoneWithThisFrameDescr')
-    if metainterp.jitdriver_sd.result_type == history.INT:
-        return cpu.get_latest_value_int(0)
-    elif metainterp.jitdriver_sd.result_type == history.REF:
-        return cpu.get_latest_value_ref(0)
-    elif metainterp.jitdriver_sd.result_type == history.FLOAT:
-        return cpu.get_latest_value_float(0)
-    else:
-        return None
-
-
-class JitMixin:
-    basic = True
-    def check_loops(self, expected=None, everywhere=False, **check):
-        get_stats().check_loops(expected=expected, everywhere=everywhere,
-                                **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.
-        This counts as 1 every bridge in addition to every loop; and it does
-        not count at all the entry bridges from interpreter, although they
-        are TreeLoops as well."""
-        assert get_stats().compiled_count == count
-    def check_tree_loop_count(self, count):
-        assert len(get_stats().loops) == count
-    def check_loop_count_at_most(self, count):
-        assert get_stats().compiled_count <= count
-    def check_enter_count(self, count):
-        assert get_stats().enter_count == count
-    def check_enter_count_at_most(self, count):
-        assert get_stats().enter_count <= count
-    def check_jumps(self, maxcount):
-        assert get_stats().exec_jumps <= maxcount
-    def check_aborted_count(self, count):
-        assert get_stats().aborted_count == count
-    def check_aborted_count_at_least(self, count):
-        assert get_stats().aborted_count >= count
-
-    def meta_interp(self, *args, **kwds):
-        kwds['CPUClass'] = self.CPUClass
-        kwds['type_system'] = self.type_system
-        if "backendopt" not in kwds:
-            kwds["backendopt"] = False
-        return ll_meta_interp(*args, **kwds)
-
-    def interp_operations(self, f, args, **kwds):
-        # get the JitCodes for the function f
-        _get_jitcodes(self, self.CPUClass, f, args, self.type_system, **kwds)
-        # try to run it with blackhole.py
-        result1 = _run_with_blackhole(self, args)
-        # try to run it with pyjitpl.py
-        result2 = _run_with_pyjitpl(self, args)
-        assert result1 == result2
-        # try to run it by running the code compiled just before
-        result3 = _run_with_machine_code(self, args)
-        assert result1 == result3 or result3 == NotImplemented
-        #
-        if (longlong.supports_longlong and
-            isinstance(result1, longlong.r_float_storage)):
-            result1 = longlong.getrealfloat(result1)
-        return result1
-
-    def check_history(self, expected=None, **isns):
-        # this can be used after calling meta_interp
-        get_stats().check_history(expected, **isns)
-
-    def check_operations_history(self, expected=None, **isns):
-        # this can be used after interp_operations
-        if expected is not None:
-            expected = dict(expected)
-            expected['jump'] = 1
-        self.metainterp.staticdata.stats.check_history(expected, **isns)
-
-
-class LLJitMixin(JitMixin):
-    type_system = 'lltype'
-    CPUClass = runner.LLtypeCPU
-
-    @staticmethod
-    def Ptr(T):
-        return lltype.Ptr(T)
-
-    @staticmethod
-    def GcStruct(name, *fields, **kwds):
-        S = lltype.GcStruct(name, *fields, **kwds)
-        return S
-
-    malloc = staticmethod(lltype.malloc)
-    nullptr = staticmethod(lltype.nullptr)
-
-    @staticmethod
-    def malloc_immortal(T):
-        return lltype.malloc(T, immortal=True)
-
-    def _get_NODE(self):
-        NODE = lltype.GcForwardReference()
-        NODE.become(lltype.GcStruct('NODE', ('value', lltype.Signed),
-                                            ('next', lltype.Ptr(NODE))))
-        return NODE
-    
-class OOJitMixin(JitMixin):
-    type_system = 'ootype'
-    #CPUClass = runner.OOtypeCPU
-
-    def setup_class(cls):
-        py.test.skip("ootype tests skipped for now")
-
-    @staticmethod
-    def Ptr(T):
-        return T
-
-    @staticmethod
-    def GcStruct(name, *fields, **kwds):
-        if 'hints' in kwds:
-            kwds['_hints'] = kwds['hints']
-            del kwds['hints']
-        I = ootype.Instance(name, ootype.ROOT, dict(fields), **kwds)
-        return I
-
-    malloc = staticmethod(ootype.new)
-    nullptr = staticmethod(ootype.null)
-
-    @staticmethod
-    def malloc_immortal(T):
-        return ootype.new(T)
-
-    def _get_NODE(self):
-        NODE = ootype.Instance('NODE', ootype.ROOT, {})
-        NODE._add_fields({'value': ootype.Signed,
-                          'next': NODE})
-        return NODE
-
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 
 class BasicTests:    
 

diff --git a/pypy/translator/jvm/src/pypy/ll_os.java b/pypy/translator/jvm/src/pypy/ll_os.java
--- a/pypy/translator/jvm/src/pypy/ll_os.java
+++ b/pypy/translator/jvm/src/pypy/ll_os.java
@@ -14,10 +14,22 @@
 
 abstract class FileWrapper
 {
+    private final String name;
+
+    public FileWrapper(String name)
+    {
+        this.name = name;
+    }
+
     public abstract void write(String buffer);
     public abstract String read(int count);
     public abstract void close();
     public abstract RandomAccessFile getFile();
+
+    public String getName()
+    {
+        return this.name;
+    }
 }
 
 class PrintStreamWrapper extends FileWrapper
@@ -25,8 +37,9 @@
     private final PrintStream stream;
     private final ll_os os;
 
-    public PrintStreamWrapper(PrintStream stream, ll_os os)
+    public PrintStreamWrapper(String name, PrintStream stream, ll_os os)
     {
+        super(name);
         this.stream = stream;
         this.os = os;
     }
@@ -58,8 +71,9 @@
     private final InputStream stream;
     private final ll_os os;
 
-    public InputStreamWrapper(InputStream stream, ll_os os)
+    public InputStreamWrapper(String name, InputStream stream, ll_os os)
     {
+        super(name);
         this.stream = stream;
         this.os = os;
     }
@@ -102,11 +116,13 @@
     private final boolean canWrite;
     private final ll_os os;
 
-    public RandomAccessFileWrapper(RandomAccessFile file, 
+    public RandomAccessFileWrapper(String name,
+                                   RandomAccessFile file, 
                                    boolean canRead, 
                                    boolean canWrite,
                                    ll_os os)
     {
+        super(name);
         this.file = file;
         this.canRead = canRead;
         this.canWrite = canWrite;
@@ -228,9 +244,9 @@
 
     public ll_os(Interlink interlink) {
         this.interlink = interlink;
-        FileDescriptors.put(0, new InputStreamWrapper(System.in, this));
-        FileDescriptors.put(1, new PrintStreamWrapper(System.out, this));
-        FileDescriptors.put(2, new PrintStreamWrapper(System.err, this));
+        FileDescriptors.put(0, new InputStreamWrapper("<stdin>", System.in, this));
+        FileDescriptors.put(1, new PrintStreamWrapper("<stdout>", System.out, this));
+        FileDescriptors.put(2, new PrintStreamWrapper("<stderr>", System.err, this));
         fdcount = 2;
     }
 
@@ -339,7 +355,7 @@
         // XXX: we ignore O_CREAT
         RandomAccessFile file = open_file(name, javaMode, flags);
         RandomAccessFileWrapper wrapper = 
-          new RandomAccessFileWrapper(file, canRead, canWrite, this);
+            new RandomAccessFileWrapper(name, file, canRead, canWrite, this);
 
         fdcount++;
         FileDescriptors.put(fdcount, wrapper);
@@ -418,6 +434,12 @@
         return ll_os_stat(path); // XXX
     }
 
+    public StatResult ll_os_fstat(int fd)
+    {
+        String name = getfd(fd).getName();
+        return ll_os_stat(name);
+    }
+
     public String ll_os_strerror(int errno)
     {
         String msg = ErrorMessages.remove(errno);

diff --git a/pypy/rpython/memory/test/test_gc.py b/pypy/rpython/memory/test/test_gc.py
--- a/pypy/rpython/memory/test/test_gc.py
+++ b/pypy/rpython/memory/test/test_gc.py
@@ -8,7 +8,7 @@
 from pypy.rpython.lltypesystem.rstr import STR
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rlib.objectmodel import we_are_translated
-from pypy.rlib.objectmodel import compute_unique_id, keepalive_until_here
+from pypy.rlib.objectmodel import compute_unique_id
 from pypy.rlib import rgc
 from pypy.rlib.rstring import StringBuilder
 from pypy.rlib.rarithmetic import LONG_BIT

diff --git a/pypy/translator/backendopt/test/test_mallocprediction.py b/pypy/translator/backendopt/test/test_mallocprediction.py
--- a/pypy/translator/backendopt/test/test_mallocprediction.py
+++ b/pypy/translator/backendopt/test/test_mallocprediction.py
@@ -4,7 +4,7 @@
 from pypy.translator.backendopt.all import backend_optimizations
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.rpython.llinterp import LLInterpreter
-from pypy.objspace.flow.model import checkgraph, flatten, Block
+from pypy.objspace.flow.model import checkgraph, Block
 from pypy.conftest import option
 import sys
 

diff --git a/pypy/module/cpyext/test/foo.c b/pypy/module/cpyext/test/foo.c
--- a/pypy/module/cpyext/test/foo.c
+++ b/pypy/module/cpyext/test/foo.c
@@ -435,14 +435,6 @@
     return (PyObject *)foop;
 }
 
-/* List of functions exported by this module */
-
-static PyMethodDef foo_functions[] = {
-    {"new",        (PyCFunction)foo_new, METH_NOARGS, NULL},
-    {NULL,        NULL}    /* Sentinel */
-};
-
-
 static int initerrtype_init(PyObject *self, PyObject *args, PyObject *kwargs) {
     PyErr_SetString(PyExc_ValueError, "init raised an error!");
     return -1;
@@ -592,6 +584,41 @@
     0           /*tp_weaklist*/
 };
 
+/* A type with a custom allocator */
+static void custom_dealloc(PyObject *ob)
+{
+    free(ob);
+}
+
+static PyTypeObject CustomType;
+
+static PyObject *newCustom(PyObject *self, PyObject *args)
+{
+    PyObject *obj = calloc(1, sizeof(PyObject));
+    obj->ob_type = &CustomType;
+    _Py_NewReference(obj);
+    return obj;
+}
+
+static PyTypeObject CustomType = {
+    PyObject_HEAD_INIT(NULL)
+    0,
+    "foo.Custom",            /*tp_name*/
+    sizeof(PyObject),        /*tp_size*/
+    0,                       /*tp_itemsize*/
+    /* methods */
+    (destructor)custom_dealloc, /*tp_dealloc*/
+};
+
+
+/* List of functions exported by this module */
+
+static PyMethodDef foo_functions[] = {
+    {"new",        (PyCFunction)foo_new, METH_NOARGS, NULL},
+    {"newCustom",  (PyCFunction)newCustom, METH_NOARGS, NULL},
+    {NULL,        NULL}    /* Sentinel */
+};
+
 
 /* Initialize this module. */
 
@@ -616,7 +643,10 @@
     if (PyType_Ready(&InitErrType) < 0)
         return;
     if (PyType_Ready(&SimplePropertyType) < 0)
-	return;
+        return;
+    CustomType.ob_type = &MetaType;
+    if (PyType_Ready(&CustomType) < 0)
+        return;
     m = Py_InitModule("foo", foo_functions);
     if (m == NULL)
         return;
@@ -635,4 +665,6 @@
         return;
     if (PyDict_SetItemString(d, "Property", (PyObject *) &SimplePropertyType) < 0)
         return;
+    if (PyDict_SetItemString(d, "Custom", (PyObject *) &CustomType) < 0)
+        return;
 }

diff --git a/pypy/translator/backendopt/test/test_mallocv.py b/pypy/translator/backendopt/test/test_mallocv.py
--- a/pypy/translator/backendopt/test/test_mallocv.py
+++ b/pypy/translator/backendopt/test/test_mallocv.py
@@ -5,7 +5,7 @@
 from pypy.translator.backendopt.all import backend_optimizations
 from pypy.translator.translator import TranslationContext, graphof
 from pypy.translator import simplify
-from pypy.objspace.flow.model import checkgraph, flatten, Block, mkentrymap
+from pypy.objspace.flow.model import checkgraph, Block, mkentrymap
 from pypy.objspace.flow.model import summary
 from pypy.rpython.llinterp import LLInterpreter, LLException
 from pypy.rpython.lltypesystem import lltype, llmemory, lloperation
@@ -33,8 +33,7 @@
     def check_malloc_removed(cls, graph, expected_mallocs, expected_calls):
         count_mallocs = 0
         count_calls = 0
-        for node in flatten(graph):
-            if isinstance(node, Block):
+        for node in graph.iterblocks():
                 for op in node.operations:
                     if op.opname == 'malloc':
                         count_mallocs += 1
@@ -54,7 +53,7 @@
         if option.view:
             t.view()
         self.original_graph_count = len(t.graphs)
-        # to detect missing keepalives and broken intermediate graphs,
+        # to detect broken intermediate graphs,
         # we do the loop ourselves instead of calling remove_simple_mallocs()
         maxiter = 100
         mallocv = MallocVirtualizer(t.graphs, t.rtyper, verbose=True)
@@ -557,36 +556,6 @@
     type_system = 'lltype'
     #MallocRemover = LLTypeMallocRemover
 
-    def test_with_keepalive(self):
-        from pypy.rlib.objectmodel import keepalive_until_here
-        def fn1(x, y):
-            if x > 0:
-                t = x+y, x-y
-            else:
-                t = x-y, x+y
-            s, d = t
-            keepalive_until_here(t)
-            return s*d
-        self.check(fn1, [int, int], [15, 10], 125)
-
-    def test_add_keepalives(self):
-        class A:
-            pass
-        SMALL = lltype.Struct('SMALL', ('x', lltype.Signed))
-        BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL))
-        def fn7(i):
-            big = lltype.malloc(BIG)
-            a = A()
-            a.big = big
-            a.small = big.s
-            a.small.x = 0
-            while i > 0:
-                a.small.x += i
-                i -= 1
-            return a.small.x
-        self.check(fn7, [int], [10], 55,
-                   expected_mallocs=1)   # no support for interior structs
-
     def test_getsubstruct(self):
         SMALL = lltype.Struct('SMALL', ('x', lltype.Signed))
         BIG = lltype.GcStruct('BIG', ('z', lltype.Signed), ('s', SMALL))
@@ -770,39 +739,6 @@
             return x.u1.b * x.u2.a
         self.check(fn, [], [], DONT_CHECK_RESULT)
 
-    def test_keep_all_keepalives(self):
-        SIZE = llmemory.sizeof(lltype.Signed)
-        PARRAY = lltype.Ptr(lltype.FixedSizeArray(lltype.Signed, 1))
-        class A:
-            def __init__(self):
-                self.addr = llmemory.raw_malloc(SIZE)
-            def __del__(self):
-                llmemory.raw_free(self.addr)
-        class B:
-            pass
-        def myfunc():
-            b = B()
-            b.keep = A()
-            b.data = llmemory.cast_adr_to_ptr(b.keep.addr, PARRAY)
-            b.data[0] = 42
-            ptr = b.data
-            # normally 'b' could go away as early as here, which would free
-            # the memory held by the instance of A in b.keep...
-            res = ptr[0]
-            # ...so we explicitly keep 'b' alive until here
-            objectmodel.keepalive_until_here(b)
-            return res
-        graph = self.check(myfunc, [], [], 42,
-                           expected_mallocs=1,    # 'A' instance left
-                           expected_calls=1)      # to A.__init__()
-
-        # there is a getarrayitem near the end of the graph of myfunc.
-        # However, the memory it accesses must still be protected by the
-        # following keepalive, even after malloc removal
-        entrymap = mkentrymap(graph)
-        [link] = entrymap[graph.returnblock]
-        assert link.prevblock.operations[-1].opname == 'keepalive'
-
     def test_nested_struct(self):
         S = lltype.GcStruct("S", ('x', lltype.Signed))
         T = lltype.GcStruct("T", ('s', S))


diff --git a/pypy/rpython/test/test_rstr.py b/pypy/rpython/test/test_rstr.py
--- a/pypy/rpython/test/test_rstr.py
+++ b/pypy/rpython/test/test_rstr.py
@@ -576,20 +576,56 @@
                 res = self.interpret(f, [i, newlines])
                 assert res == f(i, newlines)
 
-    def test_split(self):
+    def _make_split_test(self, split_fn):
         const = self.const
         def fn(i):
             s = [const(''), const('0.1.2.4.8'), const('.1.2'), const('1.2.'), const('.1.2.4.')][i]
-            l = s.split(const('.'))
+            l = getattr(s, split_fn)(const('.'))
             sum = 0
             for num in l:
-                 if len(num):
-                     sum += ord(num[0]) - ord(const('0')[0])
+                if len(num):
+                    sum += ord(num[0]) - ord(const('0')[0])
             return sum + len(l) * 100
+        return fn
+
+    def test_split(self):
+        fn = self._make_split_test('split')
         for i in range(5):
             res = self.interpret(fn, [i])
             assert res == fn(i)
 
+    def test_rsplit(self):
+        fn = self._make_split_test('rsplit')
+        for i in range(5):
+            res = self.interpret(fn, [i])
+            assert res == fn(i)
+
+    def _make_split_limit_test(self, split_fn):
+        const = self.const
+        def fn(i, j):
+            s = [const(''), const('0.1.2.4.8'), const('.1.2'), const('1.2.'), const('.1.2.4.')][i]
+            l = getattr(s, split_fn)(const('.'), j)
+            sum = 0
+            for num in l:
+                if len(num):
+                    sum += ord(num[0]) - ord(const('0')[0])
+            return sum + len(l) * 100
+        return fn
+
+    def test_split_limit(self):
+        fn = self._make_split_limit_test('split')
+        for i in range(5):
+            for j in range(4):
+                res = self.interpret(fn, [i, j])
+                assert res == fn(i, j)
+
+    def test_rsplit_limit(self):
+        fn = self._make_split_limit_test('rsplit')
+        for i in range(5):
+            for j in range(4):
+                res = self.interpret(fn, [i, j])
+                assert res == fn(i, j)
+
     def test_contains(self):
         const = self.const
         constchar = self.constchar

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
@@ -1,7 +1,7 @@
 import py
 from pypy.rlib.jit import JitDriver
 from pypy.jit.metainterp.test import test_loop
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.jit.metainterp.optimizeopt import ALL_OPTS_NAMES
 
 class LoopUnrollTest(test_loop.LoopTest):

diff --git a/pypy/rlib/test/test__jit_vref.py b/pypy/rlib/test/test__jit_vref.py
--- a/pypy/rlib/test/test__jit_vref.py
+++ b/pypy/rlib/test/test__jit_vref.py
@@ -6,8 +6,12 @@
 from pypy.annotation.annrpython import RPythonAnnotator
 from pypy.rpython.test.test_llinterp import interpret
 from pypy.rpython.lltypesystem.rclass import OBJECTPTR
+from pypy.rpython.ootypesystem.rclass import OBJECT
 from pypy.rpython.lltypesystem import lltype
 
+from pypy.rpython.test.tool import BaseRtypingTest, LLRtypeMixin, OORtypeMixin
+
+from pypy.rpython.ootypesystem import ootype
 
 class X(object):
     pass
@@ -79,37 +83,48 @@
     assert s.s_instance.can_be_None
     assert s.s_instance.classdef == a.bookkeeper.getuniqueclassdef(X)
 
-def test_rtype_1():
-    def f():
-        return virtual_ref(X())
-    x = interpret(f, [])
-    assert lltype.typeOf(x) == OBJECTPTR
+class BaseTestVRef(BaseRtypingTest):
+    def test_rtype_1(self):
+        def f():
+            return virtual_ref(X())
+        x = self.interpret(f, [])
+        assert lltype.typeOf(x) == self.OBJECTTYPE
 
-def test_rtype_2():
-    def f():
-        x1 = X()
-        vref = virtual_ref(x1)
-        x2 = vref()
-        virtual_ref_finish(x2)
-        return x2
-    x = interpret(f, [])
-    assert lltype.castable(OBJECTPTR, lltype.typeOf(x)) > 0
+    def test_rtype_2(self):
+        def f():
+            x1 = X()
+            vref = virtual_ref(x1)
+            x2 = vref()
+            virtual_ref_finish(x2)
+            return x2
+        x = self.interpret(f, [])
+        assert self.castable(self.OBJECTTYPE, x)
 
-def test_rtype_3():
-    def f(n):
-        if n > 0:
-            return virtual_ref(Y())
-        else:
-            return non_virtual_ref(Z())
-    x = interpret(f, [-5])
-    assert lltype.typeOf(x) == OBJECTPTR
+    def test_rtype_3(self):
+        def f(n):
+            if n > 0:
+                return virtual_ref(Y())
+            else:
+                return non_virtual_ref(Z())
+        x = self.interpret(f, [-5])
+        assert lltype.typeOf(x) == self.OBJECTTYPE
 
-def test_rtype_4():
-    def f(n):
-        if n > 0:
-            return virtual_ref(X())
-        else:
-            return vref_None
-    x = interpret(f, [-5])
-    assert lltype.typeOf(x) == OBJECTPTR
-    assert not x
+    def test_rtype_4(self):
+        def f(n):
+            if n > 0:
+                return virtual_ref(X())
+            else:
+                return vref_None
+        x = self.interpret(f, [-5])
+        assert lltype.typeOf(x) == self.OBJECTTYPE
+        assert not x
+
+class TestLLtype(BaseTestVRef, LLRtypeMixin):
+    OBJECTTYPE = OBJECTPTR
+    def castable(self, TO, var):
+        return lltype.castable(TO, lltype.typeOf(var)) > 0
+
+class TestOOtype(BaseTestVRef, OORtypeMixin):
+    OBJECTTYPE = OBJECT 
+    def castable(self, TO, var):
+        return ootype.isSubclass(lltype.typeOf(var), TO)

diff --git a/pypy/module/cpyext/object.py b/pypy/module/cpyext/object.py
--- a/pypy/module/cpyext/object.py
+++ b/pypy/module/cpyext/object.py
@@ -5,10 +5,9 @@
     Py_GE, CONST_STRING, FILEP, fwrite)
 from pypy.module.cpyext.pyobject import (
     PyObject, PyObjectP, create_ref, from_ref, Py_IncRef, Py_DecRef,
-    track_reference, get_typedescr, RefcountState)
+    track_reference, get_typedescr, _Py_NewReference, RefcountState)
 from pypy.module.cpyext.typeobject import PyTypeObjectPtr
 from pypy.module.cpyext.pyerrors import PyErr_NoMemory, PyErr_BadInternalCall
-from pypy.objspace.std.objectobject import W_ObjectObject
 from pypy.objspace.std.typeobject import W_TypeObject
 from pypy.interpreter.error import OperationError
 import pypy.module.__builtin__.operation as operation
@@ -184,26 +183,17 @@
     return 0
 
 @cpython_api([PyObject, PyTypeObjectPtr], PyObject)
-def PyObject_Init(space, py_obj, type):
+def PyObject_Init(space, obj, type):
     """Initialize a newly-allocated object op with its type and initial
     reference.  Returns the initialized object.  If type indicates that the
     object participates in the cyclic garbage detector, it is added to the
     detector's set of observed objects. Other fields of the object are not
     affected."""
-    if not py_obj:
+    if not obj:
         PyErr_NoMemory(space)
-    py_obj.c_ob_type = type
-    py_obj.c_ob_refcnt = 1
-    w_type = from_ref(space, rffi.cast(PyObject, type))
-    assert isinstance(w_type, W_TypeObject)
-    if w_type.is_cpytype():
-        w_obj = space.allocate_instance(W_ObjectObject, w_type)
-        track_reference(space, py_obj, w_obj)
-        state = space.fromcache(RefcountState)
-        state.set_lifeline(w_obj, py_obj)
-    else:
-        assert False, "Please add more cases in PyObject_Init"
-    return py_obj
+    obj.c_ob_type = type
+    _Py_NewReference(space, obj)
+    return obj
 
 @cpython_api([PyVarObject, PyTypeObjectPtr, Py_ssize_t], PyObject)
 def PyObject_InitVar(space, py_obj, type, size):
@@ -255,6 +245,16 @@
     expression cmp(o1, o2)."""
     return space.int_w(space.cmp(w_o1, w_o2))
 
+ at cpython_api([PyObject, PyObject, rffi.INTP], rffi.INT_real, error=-1)
+def PyObject_Cmp(space, w_o1, w_o2, result):
+    """Compare the values of o1 and o2 using a routine provided by o1, if one
+    exists, otherwise with a routine provided by o2.  The result of the
+    comparison is returned in result.  Returns -1 on failure.  This is the
+    equivalent of the Python statement result = cmp(o1, o2)."""
+    res = space.int_w(space.cmp(w_o1, w_o2))
+    result[0] = rffi.cast(rffi.INT, res)
+    return 0
+
 @cpython_api([PyObject, PyObject, rffi.INT_real], PyObject)
 def PyObject_RichCompare(space, w_o1, w_o2, opid_int):
     """Compare the values of o1 and o2 using the operation specified by opid,
@@ -395,7 +395,7 @@
         raise OperationError(space.w_TypeError, space.wrap(
             "expected a character buffer object"))
     if generic_cpy_call(space, pb.c_bf_getsegcount,
-                        obj, lltype.nullptr(rffi.INTP.TO)) != 1:
+                        obj, lltype.nullptr(Py_ssize_tP.TO)) != 1:
         raise OperationError(space.w_TypeError, space.wrap(
             "expected a single-segment buffer object"))
     size = generic_cpy_call(space, pb.c_bf_getcharbuffer,

diff --git a/dotviewer/conftest.py b/dotviewer/conftest.py
--- a/dotviewer/conftest.py
+++ b/dotviewer/conftest.py
@@ -6,4 +6,6 @@
         dest="pygame", default=False, 
         help="allow interactive tests using Pygame")
 
-option = py.test.config.option
+def pytest_configure(config):
+    global option
+    option = config.option

diff --git a/pypy/translator/gensupp.py b/pypy/translator/gensupp.py
--- a/pypy/translator/gensupp.py
+++ b/pypy/translator/gensupp.py
@@ -6,15 +6,13 @@
 import sys
 
 from pypy.objspace.flow.model import Block
-from pypy.objspace.flow.model import traverse
 
 # ordering the blocks of a graph by source position
 
 def ordered_blocks(graph):
     # collect all blocks
     allblocks = []
-    def visit(block):
-        if isinstance(block, Block):
+    for block in graph.iterblocks():
             # first we order by offset in the code string
             if block.operations:
                 ofs = block.operations[0].offset
@@ -26,7 +24,6 @@
             else:
                 txt = "dummy"
             allblocks.append((ofs, txt, block))
-    traverse(visit, graph)
     allblocks.sort()
     #for ofs, txt, block in allblocks:
     #    print ofs, txt, block


diff --git a/pypy/translator/jvm/test/test_extreme.py b/pypy/translator/jvm/test/test_extreme.py
--- a/pypy/translator/jvm/test/test_extreme.py
+++ b/pypy/translator/jvm/test/test_extreme.py
@@ -1,5 +1,8 @@
+import py
 from pypy.translator.jvm.test.runtest import JvmTest
 from pypy.translator.oosupport.test_template.extreme import BaseTestExtreme
 
 class TestExtreme(BaseTestExtreme, JvmTest):
-    pass
+
+    def test_runtimeerror_due_to_stack_overflow(self):
+        py.test.skip('hotspot bug')

diff --git a/pypy/translator/c/gcc/trackgcroot.py b/pypy/translator/c/gcc/trackgcroot.py
--- a/pypy/translator/c/gcc/trackgcroot.py
+++ b/pypy/translator/c/gcc/trackgcroot.py
@@ -1645,8 +1645,9 @@
                      darwin64='')
             print >> output, "%s:" % _globalname('pypy_asm_stackwalk')
 
-            print >> output, """\
+            s = """\
             /* See description in asmgcroot.py */
+            .cfi_startproc
             movq\t%rdi, %rdx\t/* 1st argument, which is the callback */
             movq\t%rsi, %rcx\t/* 2nd argument, which is gcrootanchor */
             movq\t%rsp, %rax\t/* my frame top address */
@@ -1666,6 +1667,7 @@
             pushq\t%rcx\t\t\t/* self->prev = gcrootanchor */
             movq\t%rsp, 8(%rcx)\t/* gcrootanchor->next = self */
             movq\t%rsp, 0(%rax)\t\t\t/* next->prev = self */
+            .cfi_def_cfa_offset 80\t/* 9 pushes + the retaddr = 80 bytes */
 
             /* note: the Mac OS X 16 bytes aligment must be respected. */
             call\t*%rdx\t\t/* invoke the callback */
@@ -1687,7 +1689,14 @@
             /* the return value is the one of the 'call' above, */
             /* because %rax (and possibly %rdx) are unmodified  */
             ret
+            .cfi_endproc
             """
+            if self.format == 'darwin64':
+                # obscure.  gcc there seems not to support .cfi_...
+                # hack it out...
+                s = re.sub(r'([.]cfi_[^/\n]+)([/\n])',
+                           r'/* \1 disabled on darwin */\2', s)
+            print >> output, s
             _variant(elf64='.size pypy_asm_stackwalk, .-pypy_asm_stackwalk',
                      darwin64='')
         else:

diff --git a/pypy/rpython/memory/gc/env.py b/pypy/rpython/memory/gc/env.py
--- a/pypy/rpython/memory/gc/env.py
+++ b/pypy/rpython/memory/gc/env.py
@@ -259,7 +259,7 @@
 get_L2cache = globals().get('get_L2cache_' + sys.platform,
                             lambda: -1)     # implement me for other platforms
 
-NURSERY_SIZE_UNKNOWN_CACHE = 1024*1024*1024
+NURSERY_SIZE_UNKNOWN_CACHE = 1024*1024
 # arbitrary 1M. better than default of 131k for most cases
 # in case it didn't work
 

diff --git a/pypy/rpython/lltypesystem/rlist.py b/pypy/rpython/lltypesystem/rlist.py
--- a/pypy/rpython/lltypesystem/rlist.py
+++ b/pypy/rpython/lltypesystem/rlist.py
@@ -16,7 +16,6 @@
 from pypy.rlib.debug import ll_assert
 from pypy.rlib.rarithmetic import ovfcheck
 from pypy.rpython.lltypesystem import rffi
-from pypy.rlib.objectmodel import keepalive_until_here
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rlib import rgc
 

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
@@ -1,6 +1,6 @@
 
 import py
-from pypy.jit.metainterp.test.test_basic import JitMixin
+from pypy.jit.metainterp.test.support import JitMixin
 from pypy.jit.tl.spli import interpreter, objects, serializer
 from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper
 from pypy.jit.backend.llgraph import runner

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
@@ -2,7 +2,7 @@
 from pypy.rlib.jit import JitDriver, hint
 from pypy.rlib.objectmodel import compute_unique_id
 from pypy.jit.codewriter.policy import StopAtXPolicy
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.rpython.lltypesystem import lltype, rclass
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.ootypesystem import ootype

diff --git a/pypy/module/thread/test/test_thread.py b/pypy/module/thread/test/test_thread.py
--- a/pypy/module/thread/test/test_thread.py
+++ b/pypy/module/thread/test/test_thread.py
@@ -214,3 +214,21 @@
         assert res == 1024*1024
         res = thread.stack_size(0)
         assert res == 2*1024*1024
+
+    def test_interrupt_main(self):
+        import thread, time
+        import signal
+
+        def f():
+            time.sleep(0.5)
+            thread.interrupt_main()
+
+        def busy_wait():
+            for x in range(1000):
+                time.sleep(0.01)
+
+        # This is normally called by app_main.py
+        signal.signal(signal.SIGINT, signal.default_int_handler)
+
+        thread.start_new_thread(f, ())
+        raises(KeyboardInterrupt, busy_wait)

diff --git a/pypy/interpreter/function.py b/pypy/interpreter/function.py
--- a/pypy/interpreter/function.py
+++ b/pypy/interpreter/function.py
@@ -22,13 +22,21 @@
     return func.code
 
 class Defaults(object):
-    _immutable_fields_ = ["items[*]"]
+    _immutable_fields_ = ["items[*]", "promote"]
 
-    def __init__(self, items):
+    def __init__(self, items, promote=False):
         self.items = items
+        self.promote = promote
 
     def getitems(self):
-        return jit.hint(self, promote=True).items
+        # an idea - we want to promote only items that we know won't change
+        # too often. this is the case for builtin functions and functions
+        # with known constant defaults. Otherwise we don't want to promote
+        # this so lambda a=a won't create a new trace each time it's
+        # encountered
+        if self.promote:
+            return jit.hint(self, promote=True).items
+        return self.items
 
     def getitem(self, idx):
         return self.getitems()[idx]
@@ -44,14 +52,15 @@
     can_change_code = True
 
     def __init__(self, space, code, w_globals=None, defs_w=[], closure=None,
-                 forcename=None):
+                 forcename=None, promote_defs=False):
         self.space = space
         self.name = forcename or code.co_name
         self.w_doc = None   # lazily read from code.getdocstring()
         self.code = code       # Code instance
         self.w_func_globals = w_globals  # the globals dictionary
         self.closure   = closure    # normally, list of Cell instances or None
-        self.defs = Defaults(defs_w)     # wrapper around list of w_default's
+        self.defs = Defaults(defs_w, promote=promote_defs)
+        # wrapper around list of w_default's
         self.w_func_dict = None # filled out below if needed
         self.w_module = None
 
@@ -620,7 +629,8 @@
     def __init__(self, func):
         assert isinstance(func, Function)
         Function.__init__(self, func.space, func.code, func.w_func_globals,
-                          func.defs.getitems(), func.closure, func.name)
+                          func.defs.getitems(), func.closure, func.name,
+                          promote_defs=True)
         self.w_doc = func.w_doc
         self.w_func_dict = func.w_func_dict
         self.w_module = func.w_module

diff --git a/pypy/module/cpyext/unicodeobject.py b/pypy/module/cpyext/unicodeobject.py
--- a/pypy/module/cpyext/unicodeobject.py
+++ b/pypy/module/cpyext/unicodeobject.py
@@ -7,15 +7,16 @@
     bootstrap_function, PyObjectFields, cpython_struct, CONST_STRING,
     CONST_WSTRING)
 from pypy.module.cpyext.pyerrors import PyErr_BadArgument
-from pypy.module.cpyext.pyobject import PyObject, from_ref, make_typedescr
+from pypy.module.cpyext.pyobject import (
+    PyObject, PyObjectP, Py_DecRef, make_ref, from_ref, track_reference,
+    make_typedescr, get_typedescr)
 from pypy.module.cpyext.stringobject import PyString_Check
 from pypy.module.sys.interp_encoding import setdefaultencoding
 from pypy.objspace.std import unicodeobject, unicodetype
 from pypy.rlib import runicode
 import sys
 
-## See comment in stringobject.py.  PyUnicode_FromUnicode(NULL, size) is not
-## yet supported.
+## See comment in stringobject.py.
 
 PyUnicodeObjectStruct = lltype.ForwardReference()
 PyUnicodeObject = lltype.Ptr(PyUnicodeObjectStruct)
@@ -28,7 +29,8 @@
     make_typedescr(space.w_unicode.instancetypedef,
                    basestruct=PyUnicodeObject.TO,
                    attach=unicode_attach,
-                   dealloc=unicode_dealloc)
+                   dealloc=unicode_dealloc,
+                   realize=unicode_realize)
 
 # Buffer for the default encoding (used by PyUnicde_GetDefaultEncoding)
 DEFAULT_ENCODING_SIZE = 100
@@ -39,12 +41,39 @@
 
 Py_UNICODE = lltype.UniChar
 
+def new_empty_unicode(space, length):
+    """
+    Allocatse a PyUnicodeObject and its buffer, but without a corresponding
+    interpreter object.  The buffer may be mutated, until unicode_realize() is
+    called.
+    """
+    typedescr = get_typedescr(space.w_unicode.instancetypedef)
+    py_obj = typedescr.allocate(space, space.w_unicode)
+    py_uni = rffi.cast(PyUnicodeObject, py_obj)
+
+    buflen = length + 1
+    py_uni.c_size = length
+    py_uni.c_buffer = lltype.malloc(rffi.CWCHARP.TO, buflen,
+                                    flavor='raw', zero=True)
+    return py_uni
+
 def unicode_attach(space, py_obj, w_obj):
     "Fills a newly allocated PyUnicodeObject with a unicode string"
     py_unicode = rffi.cast(PyUnicodeObject, py_obj)
     py_unicode.c_size = len(space.unicode_w(w_obj))
     py_unicode.c_buffer = lltype.nullptr(rffi.CWCHARP.TO)
 
+def unicode_realize(space, py_obj):
+    """
+    Creates the unicode in the interpreter. The PyUnicodeObject buffer must not
+    be modified after this call.
+    """
+    py_uni = rffi.cast(PyUnicodeObject, py_obj)
+    s = rffi.wcharpsize2unicode(py_uni.c_buffer, py_uni.c_size)
+    w_obj = space.wrap(s)
+    track_reference(space, py_obj, w_obj)
+    return w_obj
+
 @cpython_api([PyObject], lltype.Void, external=False)
 def unicode_dealloc(space, py_obj):
     py_unicode = rffi.cast(PyUnicodeObject, py_obj)
@@ -128,7 +157,9 @@
 def PyUnicode_AsUnicode(space, ref):
     """Return a read-only pointer to the Unicode object's internal Py_UNICODE
     buffer, NULL if unicode is not a Unicode object."""
-    if not PyUnicode_Check(space, ref):
+    # Don't use PyUnicode_Check, it will realize the object :-(
+    w_type = from_ref(space, rffi.cast(PyObject, ref.c_ob_type))
+    if not space.is_true(space.issubtype(w_type, space.w_unicode)):
         raise OperationError(space.w_TypeError,
                              space.wrap("expected unicode object"))
     return PyUnicode_AS_UNICODE(space, ref)
@@ -237,10 +268,11 @@
     object. If the buffer is not NULL, the return value might be a shared object.
     Therefore, modification of the resulting Unicode object is only allowed when u
     is NULL."""
-    if not wchar_p:
-        raise NotImplementedError
-    s = rffi.wcharpsize2unicode(wchar_p, length)
-    return space.wrap(s)
+    if wchar_p:
+        s = rffi.wcharpsize2unicode(wchar_p, length)
+        return make_ref(space, space.wrap(s))
+    else:
+        return rffi.cast(PyObject, new_empty_unicode(space, length))
 
 @cpython_api([CONST_WSTRING, Py_ssize_t], PyObject)
 def PyUnicode_FromWideChar(space, wchar_p, length):
@@ -330,6 +362,29 @@
     w_str = space.wrap(rffi.charpsize2str(s, size))
     return space.call_method(w_str, 'decode', space.wrap("utf-8"))
 
+ at cpython_api([PyObjectP, Py_ssize_t], rffi.INT_real, error=-1)
+def PyUnicode_Resize(space, ref, newsize):
+    # XXX always create a new string so far
+    py_uni = rffi.cast(PyUnicodeObject, ref[0])
+    if not py_uni.c_buffer:
+        raise OperationError(space.w_SystemError, space.wrap(
+            "PyUnicode_Resize called on already created string"))
+    try:
+        py_newuni = new_empty_unicode(space, newsize)
+    except MemoryError:
+        Py_DecRef(space, ref[0])
+        ref[0] = lltype.nullptr(PyObject.TO)
+        raise
+    to_cp = newsize
+    oldsize = py_uni.c_size
+    if oldsize < newsize:
+        to_cp = oldsize
+    for i in range(to_cp):
+        py_newuni.c_buffer[i] = py_uni.c_buffer[i]
+    Py_DecRef(space, ref[0])
+    ref[0] = rffi.cast(PyObject, py_newuni)
+    return 0
+
 @cpython_api([PyObject], PyObject)
 def PyUnicode_AsUTF8String(space, w_unicode):
     """Encode a Unicode object using UTF-8 and return the result as Python string

diff --git a/pypy/objspace/std/typeobject.py b/pypy/objspace/std/typeobject.py
--- a/pypy/objspace/std/typeobject.py
+++ b/pypy/objspace/std/typeobject.py
@@ -10,7 +10,7 @@
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.objectmodel import current_object_addr_as_int, compute_hash
 from pypy.rlib.jit import hint, purefunction_promote, we_are_jitted
-from pypy.rlib.jit import purefunction, dont_look_inside
+from pypy.rlib.jit import purefunction, dont_look_inside, unroll_safe
 from pypy.rlib.rarithmetic import intmask, r_uint
 
 # from compiler/misc.py
@@ -163,7 +163,7 @@
         if (not we_are_jitted() or w_self.is_heaptype() or
             w_self.space.config.objspace.std.mutable_builtintypes):
             return w_self._version_tag
-        # heap objects cannot get their version_tag changed
+        # prebuilt objects cannot get their version_tag changed
         return w_self._pure_version_tag()
 
     @purefunction_promote()
@@ -253,7 +253,7 @@
                     return w_value
         return None
                 
-
+    @unroll_safe
     def _lookup(w_self, key):
         space = w_self.space
         for w_class in w_self.mro_w:
@@ -262,6 +262,7 @@
                 return w_value
         return None
 
+    @unroll_safe
     def _lookup_where(w_self, key):
         # like lookup() but also returns the parent class in which the
         # attribute was found

diff --git a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
--- a/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_pypy_c_new.py
@@ -487,6 +487,7 @@
         """)
 
     def test_range_iter(self):
+        py.test.skip("until we fix defaults")
         def main(n):
             def g(n):
                 return range(n)
@@ -539,7 +540,7 @@
         i12 = int_sub_ovf(i3, 1)
         guard_no_overflow(descr=<Guard5>)
         --TICK--
-        jump(p0, p1, p2, i12, p4, descr=<Loop0>)
+        jump(p0, p1, p2, i12, descr=<Loop0>)
         """)
 
     def test_exception_inside_loop_2(self):
@@ -585,7 +586,7 @@
             --EXC-TICK--
             i14 = int_add(i4, 1)
             --TICK--
-            jump(p0, p1, p2, p3, i14, i5, p6, descr=<Loop0>)
+            jump(p0, p1, p2, p3, i14, i5, descr=<Loop0>)
         """)
 
     def test_chain_of_guards(self):
@@ -685,13 +686,13 @@
         assert log.result == 500
         loop, = log.loops_by_id('import')
         assert loop.match_by_id('import', """
-            p14 = call(ConstClass(ll_split_chr__GcStruct_listLlT_rpy_stringPtr_Char), p8, 46, descr=<GcPtrCallDescr>)
+            p14 = call(ConstClass(ll_split_chr), p8, 46, -1, descr=<GcPtrCallDescr>)
             guard_no_exception(descr=<Guard4>)
             guard_nonnull(p14, descr=<Guard5>)
             i15 = getfield_gc(p14, descr=<SignedFieldDescr list.length .*>)
             i16 = int_is_true(i15)
             guard_true(i16, descr=<Guard6>)
-            p18 = call(ConstClass(ll_pop_default__dum_nocheckConst_listPtr), p14, descr=<GcPtrCallDescr>)
+            p18 = call(ConstClass(ll_pop_default), p14, descr=<GcPtrCallDescr>)
             guard_no_exception(descr=<Guard7>)
             i19 = getfield_gc(p14, descr=<SignedFieldDescr list.length .*>)
             i20 = int_is_true(i19)
@@ -1009,10 +1010,11 @@
         """)
 
     def test_func_defaults(self):
+        py.test.skip("skipped until we fix defaults")
         def main(n):
             i = 1
             while i < n:
-                i += len(xrange(i)) / i
+                i += len(xrange(i+1)) - i
             return i
 
         log = self.run(main, [10000])
@@ -1023,17 +1025,49 @@
             guard_true(i10, descr=<Guard3>)
             # This can be improved if the JIT realized the lookup of i5 produces
             # a constant and thus can be removed entirely
-            i12 = int_sub(i5, 1)
-            i13 = uint_floordiv(i12, i7)
+            i120 = int_add(i5, 1)
+            i140 = int_lt(0, i120)
+            guard_true(i140, descr=<Guard4>)
+            i13 = uint_floordiv(i5, i7)
             i15 = int_add(i13, 1)
             i17 = int_lt(i15, 0)
-            guard_false(i17, descr=<Guard4>)
-            i18 = int_floordiv(i15, i5)
-            i19 = int_xor(i15, i5)
-            i20 = int_mod(i15, i5)
-            i21 = int_is_true(i20)
-            i22 = int_add_ovf(i5, i18)
-            guard_no_overflow(descr=<Guard5>)
+            guard_false(i17, descr=<Guard5>)
+            i20 = int_sub(i15, i5)
+            i21 = int_add_ovf(i5, i20)
+            guard_no_overflow(descr=<Guard6>)
             --TICK--
-            jump(p0, p1, p2, p3, p4, i22, i6, i7, p8, p9, descr=<Loop0>)
+            jump(p0, p1, p2, p3, p4, i21, i6, i7, p8, p9, descr=<Loop0>)
         """)
+
+    def test_unpack_iterable_non_list_tuple(self):
+        def main(n):
+            import array
+
+            items = [array.array("i", [1])] * n
+            total = 0
+            for a, in items:
+                total += a
+            return total
+
+        log = self.run(main, [1000000])
+        assert log.result == 1000000
+        loop, = log.loops_by_filename(self.filepath)
+        assert loop.match("""
+            i16 = int_ge(i12, i13)
+            guard_false(i16, descr=<Guard3>)
+            p17 = getarrayitem_gc(p15, i12, descr=<GcPtrArrayDescr>)
+            i19 = int_add(i12, 1)
+            setfield_gc(p4, i19, descr=<SignedFieldDescr .*W_AbstractSeqIterObject.inst_index .*>)
+            guard_nonnull_class(p17, 146982464, descr=<Guard4>)
+            i21 = getfield_gc(p17, descr=<SignedFieldDescr .*W_ArrayTypei.inst_len .*>)
+            i23 = int_lt(0, i21)
+            guard_true(i23, descr=<Guard5>)
+            i24 = getfield_gc(p17, descr=<NonGcPtrFieldDescr .*W_ArrayTypei.inst_buffer .*>)
+            i25 = getarrayitem_raw(i24, 0, descr=<SignedArrayNoLengthDescr>)
+            i27 = int_lt(1, i21)
+            guard_false(i27, descr=<Guard6>)
+            i28 = int_add_ovf(i10, i25)
+            guard_no_overflow(descr=<Guard7>)
+            --TICK--
+            jump(p0, p1, p2, p3, p4, p5, p6, p7, p8, p9, i28, i25, i19, i13, p14, p15, descr=<Loop0>)
+        """)

diff --git a/pypy/objspace/flow/test/test_model.py b/pypy/objspace/flow/test/test_model.py
--- a/pypy/objspace/flow/test/test_model.py
+++ b/pypy/objspace/flow/test/test_model.py
@@ -71,19 +71,6 @@
                                        pieces.headerblock.exits[1],
                                        pieces.whileblock.exits[0]]
 
-def test_traverse():
-    lst = []
-    traverse(lst.append, graph)
-    assert lst == [pieces.startblock,
-                   pieces.startblock.exits[0],
-                   pieces.headerblock,
-                   pieces.headerblock.exits[0],
-                   graph.returnblock,
-                   pieces.headerblock.exits[1],
-                   pieces.whileblock,
-                   pieces.whileblock.exits[0]]
-    assert flatten(graph) == lst
-
 def test_mkentrymap():
     entrymap = mkentrymap(graph)
     startlink = entrymap[graph.startblock][0]

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
@@ -3,7 +3,7 @@
 from pypy.rlib.jit import JitDriver, dont_look_inside, vref_None
 from pypy.rlib.jit import virtual_ref, virtual_ref_finish
 from pypy.rlib.objectmodel import compute_unique_id
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.jit.metainterp.resoperation import rop
 from pypy.jit.metainterp.virtualref import VirtualRefInfo
 

diff --git a/pypy/jit/metainterp/test/test_blackhole.py b/pypy/jit/metainterp/test/test_blackhole.py
--- a/pypy/jit/metainterp/test/test_blackhole.py
+++ b/pypy/jit/metainterp/test/test_blackhole.py
@@ -1,6 +1,6 @@
 import py
 from pypy.rlib.jit import JitDriver
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder
 from pypy.jit.metainterp.blackhole import BlackholeInterpreter
 from pypy.jit.metainterp.blackhole import convert_and_run_from_pyjitpl

diff --git a/pypy/jit/metainterp/test/test_tlc.py b/pypy/jit/metainterp/test/test_tlc.py
--- a/pypy/jit/metainterp/test/test_tlc.py
+++ b/pypy/jit/metainterp/test/test_tlc.py
@@ -3,7 +3,7 @@
 
 from pypy.jit.tl import tlc
 
-from pypy.jit.metainterp.test.test_basic import OOJitMixin, LLJitMixin
+from pypy.jit.metainterp.test.support import OOJitMixin, LLJitMixin
 
 
 class TLCTests:

diff --git a/pypy/module/signal/interp_signal.py b/pypy/module/signal/interp_signal.py
--- a/pypy/module/signal/interp_signal.py
+++ b/pypy/module/signal/interp_signal.py
@@ -146,6 +146,15 @@
                     self.pending_signals[n] = None
                     self.reissue_signal_action.fire_after_thread_switch()
 
+    def set_interrupt(self):
+        "Simulates the effect of a SIGINT signal arriving"
+        n = cpy_signal.SIGINT
+        if self.reissue_signal_action is None:
+            self.report_signal(n)
+        else:
+            self.pending_signals[n] = None
+            self.reissue_signal_action.fire_after_thread_switch()
+
     def report_signal(self, n):
         try:
             w_handler = self.handlers_w[n]

diff --git a/pypy/module/cpyext/test/test_cpyext.py b/pypy/module/cpyext/test/test_cpyext.py
--- a/pypy/module/cpyext/test/test_cpyext.py
+++ b/pypy/module/cpyext/test/test_cpyext.py
@@ -106,6 +106,11 @@
             del obj
         import gc; gc.collect()
 
+        try:
+            del space.getexecutioncontext().cpyext_threadstate
+        except AttributeError:
+            pass
+
         for w_obj in state.non_heaptypes_w:
             Py_DecRef(space, w_obj)
         state.non_heaptypes_w[:] = []
@@ -385,6 +390,19 @@
         assert module.__doc__ == "docstring"
         assert module.return_cookie() == 3.14
 
+    def test_load_dynamic(self):
+        import sys
+        init = """
+        if (Py_IsInitialized())
+            Py_InitModule("foo", NULL);
+        """
+        foo = self.import_module(name='foo', init=init)
+        assert 'foo' in sys.modules
+        del sys.modules['foo']
+        import imp
+        foo2 = imp.load_dynamic('foo', foo.__file__)
+        assert 'foo' in sys.modules
+        assert foo.__dict__ == foo2.__dict__
 
     def test_InitModule4_dotted(self):
         """

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
@@ -1,5 +1,5 @@
 import py
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.rlib.jit import JitDriver
 
 class ListTests(object):

diff --git a/pypy/module/thread/os_lock.py b/pypy/module/thread/os_lock.py
--- a/pypy/module/thread/os_lock.py
+++ b/pypy/module/thread/os_lock.py
@@ -113,7 +113,4 @@
 def allocate_lock(space):
     """Create a new lock object.  (allocate() is an obsolete synonym.)
 See LockType.__doc__ for information about locks."""
-    return space.wrap(Lock(space))
-
-def getlocktype(space):
-    return space.gettypeobject(Lock.typedef)
+    return space.wrap(Lock(space))
\ No newline at end of file

diff --git a/pypy/module/cpyext/import_.py b/pypy/module/cpyext/import_.py
--- a/pypy/module/cpyext/import_.py
+++ b/pypy/module/cpyext/import_.py
@@ -1,8 +1,10 @@
 from pypy.interpreter import module
 from pypy.module.cpyext.api import (
     generic_cpy_call, cpython_api, PyObject, CONST_STRING)
+from pypy.module.cpyext.pyobject import borrow_from
 from pypy.rpython.lltypesystem import rffi
 from pypy.interpreter.error import OperationError
+from pypy.interpreter.module import Module
 
 @cpython_api([PyObject], PyObject)
 def PyImport_Import(space, w_name):
@@ -45,3 +47,29 @@
     space.warn('PyImport_ImportModuleNoBlock() is not non-blocking',
                space.w_RuntimeWarning)
     return PyImport_Import(space, space.wrap(rffi.charp2str(name)))
+
+ at cpython_api([PyObject], PyObject)
+def PyImport_ReloadModule(space, w_mod):
+    from pypy.module.imp.importing import reload
+    return reload(space, w_mod)
+
+ at cpython_api([CONST_STRING], PyObject)
+def PyImport_AddModule(space, name):
+    """Return the module object corresponding to a module name.  The name
+    argument may be of the form package.module. First check the modules
+    dictionary if there's one there, and if not, create a new one and insert
+    it in the modules dictionary. Return NULL with an exception set on
+    failure.
+
+    This function does not load or import the module; if the module wasn't
+    already loaded, you will get an empty module object. Use
+    PyImport_ImportModule() or one of its variants to import a module.
+    Package structures implied by a dotted name for name are not created if
+    not already present."""
+    from pypy.module.imp.importing import check_sys_modules_w
+    modulename = rffi.charp2str(name)
+    w_mod = check_sys_modules_w(space, modulename)
+    if not w_mod or space.is_w(w_mod, space.w_None):
+        w_mod = Module(space, space.wrap(modulename))
+    return borrow_from(None, w_mod)
+


diff --git a/pypy/translator/exceptiontransform.py b/pypy/translator/exceptiontransform.py
--- a/pypy/translator/exceptiontransform.py
+++ b/pypy/translator/exceptiontransform.py
@@ -229,7 +229,6 @@
             n_need_exc_matching_blocks += need_exc_matching
             n_gen_exc_checks           += gen_exc_checks
         cleanup_graph(graph)
-        removenoops.remove_superfluous_keep_alive(graph)
         return n_need_exc_matching_blocks, n_gen_exc_checks
 
     def replace_stack_unwind(self, block):

diff --git a/pypy/jit/metainterp/test/test_dlist.py b/pypy/jit/metainterp/test/test_dlist.py
deleted file mode 100644
--- a/pypy/jit/metainterp/test/test_dlist.py
+++ /dev/null
@@ -1,165 +0,0 @@
-
-import py
-from pypy.rlib.jit import JitDriver
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
-py.test.skip("Disabled")
-
-class ListTests:
-    def test_basic(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'l'])
-        def f(n):
-            l = [0]
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, l=l)
-                myjitdriver.jit_merge_point(n=n, l=l)
-                x = l[0]
-                l[0] = x + 1
-                n -= 1
-            return l[0]
-
-        res = self.meta_interp(f, [10], listops=True)
-        assert res == f(10)        
-        self.check_loops(getarrayitem_gc=0, setarrayitem_gc=1)
-#                         XXX fix codewriter
-#                         guard_exception=0,
-#                         guard_no_exception=1)
-
-    def test_list_escapes(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'l'])
-        def f(n):
-            l = [0] * (n + 1)
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, l=l)
-                myjitdriver.jit_merge_point(n=n, l=l)
-                x = l[0]
-                l[0] = x + 1
-                l[n] = n
-                n -= 1
-            return l[3]
-
-        res = self.meta_interp(f, [10], listops=True)
-        assert res == f(10)
-        self.check_loops(setarrayitem_gc=2, getarrayitem_gc=0)
-
-    def test_list_escapes_but_getitem_goes(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'l'])
-        def f(n):
-            l = [0] * (n + 1)
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, l=l)
-                myjitdriver.jit_merge_point(n=n, l=l)
-                x = l[0]
-                l[0] = x + 1
-                l[n] = n
-                x = l[2]
-                y = l[1] + l[2]
-                l[1] = x + y
-                n -= 1
-            return l[3]
-
-        res = self.meta_interp(f, [10], listops=True)
-        assert res == f(10)
-        self.check_loops(setarrayitem_gc=3, getarrayitem_gc=0)
-
-    def test_list_of_ptrs(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'l'])
-        class A(object):
-            def __init__(self, x):
-                self.x = x
-
-        def f(n):
-            l = [A(3)]
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, l=l)
-                myjitdriver.jit_merge_point(n=n, l=l)
-                x = l[0].x + 1
-                l[0] = A(x)
-                n -= 1
-            return l[0].x
-
-        res = self.meta_interp(f, [10], listops=True)
-        assert res == f(10)
-        self.check_loops(setarrayitem_gc=1, getarrayitem_gc=0,
-                         new_with_vtable=1) # A should escape
-
-    def test_list_checklength(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'l'])
-
-        def f(n, a):
-            l = [0] * a
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, l=l)
-                myjitdriver.jit_merge_point(n=n, l=l)
-                if len(l) < 3:
-                    return 42
-                l[0] = n
-                n -= 1
-            return l[0]
-
-        res = self.meta_interp(f, [10, 13], listops=True)
-        assert res == f(10, 13)
-        self.check_loops(setarrayitem_gc=1, arraylen_gc=1)
-
-    def test_list_checklength_run(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'l'])
-
-        def f(n, a):
-            l = [0] * a
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, l=l)
-                myjitdriver.jit_merge_point(n=n, l=l)
-                if len(l) > n:
-                    return 42
-                l[0] = n
-                n -= 1
-            return l[0]
-
-        res = self.meta_interp(f, [50, 13], listops=True)
-        assert res == 42
-        self.check_loops(setarrayitem_gc=1, arraylen_gc=1)
-
-    def test_checklength_cannot_go_away(self):
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'l'])
-
-        def f(n):
-            l = [0] * n
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, l=l)
-                myjitdriver.jit_merge_point(n=n, l=l)
-                if len(l) < 3:
-                    return len(l)
-                l = [0] * n
-                n -= 1
-            return 0
-
-        res = self.meta_interp(f, [10], listops=True)
-        assert res == 2
-        self.check_loops(arraylen_gc=1)
-
-    def test_list_indexerror(self):
-        # this is an example where IndexError is raised before
-        # even getting to the JIT
-        py.test.skip("I suspect bug somewhere outside of the JIT")
-        myjitdriver = JitDriver(greens = [], reds = ['n', 'l'])
-        def f(n):
-            l = [0]
-            while n > 0:
-                myjitdriver.can_enter_jit(n=n, l=l)
-                myjitdriver.jit_merge_point(n=n, l=l)
-                l[n] = n
-                n -= 1
-            return l[3]
-
-        def g(n):
-            try:
-                f(n)
-                return 0
-            except IndexError:
-                return 42
-
-        res = self.meta_interp(g, [10])
-        assert res == 42
-        self.check_loops(setitem=2)
-
-class TestLLtype(ListTests, LLJitMixin):
-    pass

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
@@ -4,6 +4,8 @@
 from pypy.jit.metainterp.optimizeutil import descrlist_dict
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.jit.metainterp.optimizeopt import optimizer
+from pypy.jit.metainterp.executor import execute
+from pypy.jit.codewriter.heaptracker import vtable2descr
 
 
 class AbstractVirtualValue(optimizer.OptValue):
@@ -72,28 +74,53 @@
         assert isinstance(fieldvalue, optimizer.OptValue)
         self._fields[ofs] = fieldvalue
 
+    def _get_descr(self):
+        raise NotImplementedError
+
+    def _is_immutable_and_filled_with_constants(self):
+        count = self._get_descr().count_fields_if_immutable()
+        if count != len(self._fields):    # always the case if count == -1
+            return False
+        for value in self._fields.itervalues():
+            subbox = value.force_box()
+            if not isinstance(subbox, Const):
+                return False
+        return True
+
     def _really_force(self):
-        assert self.source_op is not None
+        op = self.source_op
+        assert op is not None
         # ^^^ This case should not occur any more (see test_bug_3).
         #
         if not we_are_translated():
-            self.source_op.name = 'FORCE ' + self.source_op.name
-        newoperations = self.optimizer.newoperations
-        newoperations.append(self.source_op)
-        self.box = box = self.source_op.result
-        #
-        iteritems = self._fields.iteritems()
-        if not we_are_translated(): #random order is fine, except for tests
-            iteritems = list(iteritems)
-            iteritems.sort(key = lambda (x,y): x.sort_key())
-        for ofs, value in iteritems:
-            if value.is_null():
-                continue
-            subbox = value.force_box()
-            op = ResOperation(rop.SETFIELD_GC, [box, subbox], None,
-                              descr=ofs)
+            op.name = 'FORCE ' + self.source_op.name
+
+        if self._is_immutable_and_filled_with_constants():
+            box = self.optimizer.constant_fold(op)
+            self.make_constant(box)
+            for ofs, value in self._fields.iteritems():
+                subbox = value.force_box()
+                assert isinstance(subbox, Const)
+                execute(self.optimizer.cpu, None, rop.SETFIELD_GC,
+                        ofs, box, subbox)
+            # keep self._fields, because it's all immutable anyway
+        else:
+            newoperations = self.optimizer.newoperations
             newoperations.append(op)
-        self._fields = None
+            self.box = box = op.result
+            #
+            iteritems = self._fields.iteritems()
+            if not we_are_translated(): #random order is fine, except for tests
+                iteritems = list(iteritems)
+                iteritems.sort(key = lambda (x,y): x.sort_key())
+            for ofs, value in iteritems:
+                if value.is_null():
+                    continue
+                subbox = value.force_box()
+                op = ResOperation(rop.SETFIELD_GC, [box, subbox], None,
+                                  descr=ofs)
+                newoperations.append(op)
+            self._fields = None
 
     def _get_field_descr_list(self):
         _cached_sorted_fields = self._cached_sorted_fields
@@ -168,6 +195,9 @@
         fielddescrs = self._get_field_descr_list()
         return modifier.make_virtual(self.known_class, fielddescrs)
 
+    def _get_descr(self):
+        return vtable2descr(self.optimizer.cpu, self.known_class.getint())
+
     def __repr__(self):
         cls_name = self.known_class.value.adr.ptr._obj._TYPE._name
         if self._fields is None:
@@ -185,6 +215,9 @@
         fielddescrs = self._get_field_descr_list()
         return modifier.make_vstruct(self.structdescr, fielddescrs)
 
+    def _get_descr(self):
+        return self.structdescr
+
 class VArrayValue(AbstractVirtualValue):
 
     def __init__(self, optimizer, arraydescr, size, keybox, source_op=None):
@@ -286,7 +319,6 @@
         vrefinfo = self.optimizer.metainterp_sd.virtualref_info
         c_cls = vrefinfo.jit_virtual_ref_const_class
         descr_virtual_token = vrefinfo.descr_virtual_token
-        descr_virtualref_index = vrefinfo.descr_virtualref_index
         #
         # Replace the VIRTUAL_REF operation with a virtual structure of type
         # 'jit_virtual_ref'.  The jit_virtual_ref structure may be forced soon,
@@ -296,7 +328,6 @@
         tokenbox = BoxInt()
         self.emit_operation(ResOperation(rop.FORCE_TOKEN, [], tokenbox))
         vrefvalue.setfield(descr_virtual_token, self.getvalue(tokenbox))
-        vrefvalue.setfield(descr_virtualref_index, self.getvalue(indexbox))
 
     def optimize_VIRTUAL_REF_FINISH(self, op):
         # Set the 'forced' field of the virtual_ref.

diff --git a/pypy/jit/backend/x86/test/test_rx86.py b/pypy/jit/backend/x86/test/test_rx86.py
--- a/pypy/jit/backend/x86/test/test_rx86.py
+++ b/pypy/jit/backend/x86/test/test_rx86.py
@@ -206,3 +206,8 @@
     s = CodeBuilder64()
     s.MOV_rm(edx, (edi, -1))
     assert s.getvalue() == '\x48\x8B\x57\xFF'
+
+def test_movsd_xj_64():
+    s = CodeBuilder64()
+    s.MOVSD_xj(xmm2, 0x01234567)
+    assert s.getvalue() == '\xF2\x0F\x10\x14\x25\x67\x45\x23\x01'

diff --git a/pypy/module/cpyext/stubs.py b/pypy/module/cpyext/stubs.py
--- a/pypy/module/cpyext/stubs.py
+++ b/pypy/module/cpyext/stubs.py
@@ -351,14 +351,6 @@
     """Return the number of free variables in co."""
     raise NotImplementedError
 
- at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real, PyObject, PyObject, PyObject, PyObject, PyObject, PyObject, PyObject, PyObject, rffi.INT_real, PyObject], PyCodeObject)
-def PyCode_New(space, argcount, nlocals, stacksize, flags, code, consts, names, varnames, freevars, cellvars, filename, name, firstlineno, lnotab):
-    """Return a new code object.  If you need a dummy code object to
-    create a frame, use PyCode_NewEmpty() instead.  Calling
-    PyCode_New() directly can bind you to a precise Python
-    version since the definition of the bytecode changes often."""
-    raise NotImplementedError
-
 @cpython_api([PyObject], rffi.INT_real, error=-1)
 def PyCodec_Register(space, search_function):
     """Register a new codec search function.
@@ -745,13 +737,6 @@
     described there."""
     raise NotImplementedError
 
- at cpython_api([], lltype.Void)
-def PyErr_SetInterrupt(space):
-    """This function simulates the effect of a SIGINT signal arriving --- the
-    next time PyErr_CheckSignals() is called, KeyboardInterrupt will be raised.
-    It may be called without holding the interpreter lock."""
-    raise NotImplementedError
-
 @cpython_api([rffi.INT_real], rffi.INT_real, error=CANNOT_FAIL)
 def PySignal_SetWakeupFd(space, fd):
     """This utility function specifies a file descriptor to which a '\0' byte will
@@ -1123,20 +1108,6 @@
     with an exception set on failure (the module still exists in this case)."""
     raise NotImplementedError
 
- at cpython_api([rffi.CCHARP], PyObject)
-def PyImport_AddModule(space, name):
-    """Return the module object corresponding to a module name.  The name argument
-    may be of the form package.module. First check the modules dictionary if
-    there's one there, and if not, create a new one and insert it in the modules
-    dictionary. Return NULL with an exception set on failure.
-    
-    This function does not load or import the module; if the module wasn't already
-    loaded, you will get an empty module object. Use PyImport_ImportModule()
-    or one of its variants to import a module.  Package structures implied by a
-    dotted name for name are not created if not already present."""
-    borrow_from()
-    raise NotImplementedError
-
 @cpython_api([rffi.CCHARP, PyObject], PyObject)
 def PyImport_ExecCodeModule(space, name, co):
     """Given a module name (possibly of the form package.module) and a code
@@ -1972,14 +1943,6 @@
     """
     raise NotImplementedError
 
- at cpython_api([PyObject, PyObject, rffi.INTP], rffi.INT_real, error=-1)
-def PyObject_Cmp(space, o1, o2, result):
-    """Compare the values of o1 and o2 using a routine provided by o1, if one
-    exists, otherwise with a routine provided by o2.  The result of the
-    comparison is returned in result.  Returns -1 on failure.  This is the
-    equivalent of the Python statement result = cmp(o1, o2)."""
-    raise NotImplementedError
-
 @cpython_api([PyObject], PyObject)
 def PyObject_Bytes(space, o):
     """Compute a bytes representation of object o.  In 2.x, this is just a alias

diff --git a/pypy/rlib/_rweakkeydict.py b/pypy/rlib/_rweakkeydict.py
--- a/pypy/rlib/_rweakkeydict.py
+++ b/pypy/rlib/_rweakkeydict.py
@@ -123,7 +123,7 @@
 @jit.dont_look_inside
 def ll_get(d, llkey):
     hash = compute_identity_hash(llkey)
-    i = rdict.ll_dict_lookup(d, llkey, hash)
+    i = rdict.ll_dict_lookup(d, llkey, hash) & rdict.MASK
     #llop.debug_print(lltype.Void, i, 'get', hex(hash),
     #                 ll_debugrepr(d.entries[i].key),
     #                 ll_debugrepr(d.entries[i].value))
@@ -143,7 +143,7 @@
 def ll_set_nonnull(d, llkey, llvalue):
     hash = compute_identity_hash(llkey)
     keyref = weakref_create(llkey)    # GC effects here, before the rest
-    i = rdict.ll_dict_lookup(d, llkey, hash)
+    i = rdict.ll_dict_lookup(d, llkey, hash) & rdict.MASK
     everused = d.entries.everused(i)
     d.entries[i].key = keyref
     d.entries[i].value = llvalue
@@ -160,7 +160,7 @@
 @jit.dont_look_inside
 def ll_set_null(d, llkey):
     hash = compute_identity_hash(llkey)
-    i = rdict.ll_dict_lookup(d, llkey, hash)
+    i = rdict.ll_dict_lookup(d, llkey, hash) & rdict.MASK
     if d.entries.everused(i):
         # If the entry was ever used, clean up its key and value.
         # We don't store a NULL value, but a dead weakref, because

diff --git a/pypy/module/_io/test/test_bufferedio.py b/pypy/module/_io/test/test_bufferedio.py
--- a/pypy/module/_io/test/test_bufferedio.py
+++ b/pypy/module/_io/test/test_bufferedio.py
@@ -191,6 +191,10 @@
         f = _io.BufferedReader(raw)
         assert repr(f) == '<_io.BufferedReader name=%r>' % (self.tmpfile,)
 
+class AppTestBufferedReaderWithThreads(AppTestBufferedReader):
+    spaceconfig = dict(usemodules=['_io', 'thread'])
+
+
 class AppTestBufferedWriter:
     def setup_class(cls):
         cls.space = gettestobjspace(usemodules=['_io'])

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
@@ -400,21 +400,9 @@
 # So we need a forward and backward mapping in our State instance
 PyObjectStruct = lltype.ForwardReference()
 PyObject = lltype.Ptr(PyObjectStruct)
-PyBufferProcs = lltype.ForwardReference()
 PyObjectFields = (("ob_refcnt", lltype.Signed), ("ob_type", PyTypeObjectPtr))
-def F(ARGS, RESULT=lltype.Signed):
-    return lltype.Ptr(lltype.FuncType(ARGS, RESULT))
-PyBufferProcsFields = (
-    ("bf_getreadbuffer", F([PyObject, lltype.Signed, rffi.VOIDPP])),
-    ("bf_getwritebuffer", F([PyObject, lltype.Signed, rffi.VOIDPP])),
-    ("bf_getsegcount", F([PyObject, rffi.INTP])),
-    ("bf_getcharbuffer", F([PyObject, lltype.Signed, rffi.CCHARPP])),
-# we don't support new buffer interface for now
-    ("bf_getbuffer", rffi.VOIDP),
-    ("bf_releasebuffer", rffi.VOIDP))
 PyVarObjectFields = PyObjectFields + (("ob_size", Py_ssize_t), )
 cpython_struct('PyObject', PyObjectFields, PyObjectStruct)
-cpython_struct('PyBufferProcs', PyBufferProcsFields, PyBufferProcs)
 PyVarObjectStruct = cpython_struct("PyVarObject", PyVarObjectFields)
 PyVarObject = lltype.Ptr(PyVarObjectStruct)
 
@@ -539,7 +527,8 @@
 
             elif is_PyObject(callable.api_func.restype):
                 if result is None:
-                    retval = make_ref(space, None)
+                    retval = rffi.cast(callable.api_func.restype,
+                                       make_ref(space, None))
                 elif isinstance(result, Reference):
                     retval = result.get_ref(space)
                 elif not rffi._isllptr(result):

diff --git a/pypy/translator/jvm/test/test_list.py b/pypy/translator/jvm/test/test_list.py
--- a/pypy/translator/jvm/test/test_list.py
+++ b/pypy/translator/jvm/test/test_list.py
@@ -6,7 +6,10 @@
     def test_recursive(self):
         py.test.skip("JVM doesn't support recursive lists")
     
-    def test_getitem_exc(self):
+    def test_getitem_exc_1(self):
+        py.test.skip('fixme!')
+
+    def test_getitem_exc_2(self):
         py.test.skip('fixme!')
 
     def test_r_short_list(self):

diff --git a/pypy/module/cpyext/typeobject.py b/pypy/module/cpyext/typeobject.py
--- a/pypy/module/cpyext/typeobject.py
+++ b/pypy/module/cpyext/typeobject.py
@@ -3,14 +3,14 @@
 
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.rpython.annlowlevel import llhelper
-from pypy.interpreter.baseobjspace import DescrMismatch
+from pypy.interpreter.baseobjspace import W_Root, DescrMismatch
 from pypy.objspace.std.typeobject import W_TypeObject
 from pypy.interpreter.typedef import GetSetProperty
 from pypy.module.cpyext.api import (
-    cpython_api, cpython_struct, bootstrap_function, Py_ssize_t,
+    cpython_api, cpython_struct, bootstrap_function, Py_ssize_t, Py_ssize_tP,
     generic_cpy_call, Py_TPFLAGS_READY, Py_TPFLAGS_READYING,
     Py_TPFLAGS_HEAPTYPE, METH_VARARGS, METH_KEYWORDS, CANNOT_FAIL,
-    PyBufferProcs, build_type_checkers)
+    build_type_checkers)
 from pypy.module.cpyext.pyobject import (
     PyObject, make_ref, create_ref, from_ref, get_typedescr, make_typedescr,
     track_reference, RefcountState, borrow_from)
@@ -24,7 +24,7 @@
 from pypy.module.cpyext.structmember import PyMember_GetOne, PyMember_SetOne
 from pypy.module.cpyext.typeobjectdefs import (
     PyTypeObjectPtr, PyTypeObject, PyGetSetDef, PyMemberDef, newfunc,
-    PyNumberMethods, PySequenceMethods)
+    PyNumberMethods, PySequenceMethods, PyBufferProcs)
 from pypy.module.cpyext.slotdefs import (
     slotdefs_for_tp_slots, slotdefs_for_wrappers, get_slot_tp_function)
 from pypy.interpreter.error import OperationError
@@ -287,11 +287,17 @@
 
         W_TypeObject.__init__(self, space, extension_name,
             bases_w or [space.w_object], dict_w)
-        self.flag_cpytype = True
+        if not space.is_true(space.issubtype(self, space.w_type)):
+            self.flag_cpytype = True
         self.flag_heaptype = False
 
 @bootstrap_function
 def init_typeobject(space):
+    # Probably a hack
+    space.model.typeorder[W_PyCTypeObject] = [(W_PyCTypeObject, None),
+                                              (W_TypeObject, None),
+                                              (W_Root, None)]
+
     make_typedescr(space.w_type.instancetypedef,
                    basestruct=PyTypeObject,
                    attach=type_attach,
@@ -355,14 +361,14 @@
     # hopefully this does not clash with the memory model assumed in
     # extension modules
 
- at cpython_api([PyObject, rffi.INTP], lltype.Signed, external=False,
+ at cpython_api([PyObject, Py_ssize_tP], lltype.Signed, external=False,
              error=CANNOT_FAIL)
 def str_segcount(space, w_obj, ref):
     if ref:
-        ref[0] = rffi.cast(rffi.INT, space.len_w(w_obj))
+        ref[0] = space.len_w(w_obj)
     return 1
 
- at cpython_api([PyObject, lltype.Signed, rffi.VOIDPP], lltype.Signed,
+ at cpython_api([PyObject, Py_ssize_t, rffi.VOIDPP], lltype.Signed,
              external=False, error=-1)
 def str_getreadbuffer(space, w_str, segment, ref):
     from pypy.module.cpyext.stringobject import PyString_AsString
@@ -375,7 +381,7 @@
     Py_DecRef(space, pyref)
     return space.len_w(w_str)
 
- at cpython_api([PyObject, lltype.Signed, rffi.CCHARPP], lltype.Signed,
+ at cpython_api([PyObject, Py_ssize_t, rffi.CCHARPP], lltype.Signed,
              external=False, error=-1)
 def str_getcharbuffer(space, w_str, segment, ref):
     from pypy.module.cpyext.stringobject import PyString_AsString
@@ -472,14 +478,19 @@
 def PyType_Ready(space, pto):
     if pto.c_tp_flags & Py_TPFLAGS_READY:
         return 0
+    type_realize(space, rffi.cast(PyObject, pto))
+    return 0
+
+def type_realize(space, py_obj):
+    pto = rffi.cast(PyTypeObjectPtr, py_obj)
     assert pto.c_tp_flags & Py_TPFLAGS_READYING == 0
     pto.c_tp_flags |= Py_TPFLAGS_READYING
     try:
-        type_realize(space, rffi.cast(PyObject, pto))
-        pto.c_tp_flags |= Py_TPFLAGS_READY
+        w_obj = _type_realize(space, py_obj)
     finally:
         pto.c_tp_flags &= ~Py_TPFLAGS_READYING
-    return 0
+    pto.c_tp_flags |= Py_TPFLAGS_READY
+    return w_obj
 
 def solid_base(space, w_type):
     typedef = w_type.instancetypedef
@@ -535,7 +546,7 @@
     finally:
         Py_DecRef(space, base_pyo)
 
-def type_realize(space, py_obj):
+def _type_realize(space, py_obj):
     """
     Creates an interpreter type from a PyTypeObject structure.
     """
@@ -554,7 +565,9 @@
 
     finish_type_1(space, py_type)
 
-    w_obj = space.allocate_instance(W_PyCTypeObject, space.w_type)
+    w_metatype = from_ref(space, rffi.cast(PyObject, py_type.c_ob_type))
+
+    w_obj = space.allocate_instance(W_PyCTypeObject, w_metatype)
     track_reference(space, py_obj, w_obj)
     w_obj.__init__(space, py_type)
     w_obj.ready()

diff --git a/pypy/objspace/std/test/test_listobject.py b/pypy/objspace/std/test/test_listobject.py
--- a/pypy/objspace/std/test/test_listobject.py
+++ b/pypy/objspace/std/test/test_listobject.py
@@ -347,8 +347,9 @@
         assert list('') == []
         assert list('abc') == ['a', 'b', 'c']
         assert list((1, 2)) == [1, 2]
-        l = []
+        l = [1]
         assert list(l) is not l
+        assert list(l) == l
         assert list(range(10)) == range(10)
 
     def test_explicit_new_init(self):

diff --git a/pypy/jit/tl/pypyjit_demo.py b/pypy/jit/tl/pypyjit_demo.py
--- a/pypy/jit/tl/pypyjit_demo.py
+++ b/pypy/jit/tl/pypyjit_demo.py
@@ -1,19 +1,16 @@
 
 try:
-    import pypyjit
-    pypyjit.set_param(threshold=3, inlining=True)
+    def main(n):
+        def g(n):
+            return range(n)
+        s = 0
+        for i in range(n):  # ID: for
+            tmp = g(n)
+            s += tmp[i]     # ID: getitem
+            a = 0
+        return s
+    main(10)
 
-    def sqrt(y, n=10000):
-        x = y / 2
-        while n > 0:
-            #assert y > 0 and x > 0
-            if y > 0 and x > 0: pass
-            n -= 1
-            x = (x + y/x) / 2
-        return x
-
-    print sqrt(1234, 4)
-    
 except Exception, e:
     print "Exception: ", type(e)
     print e

diff --git a/pypy/objspace/std/dictmultiobject.py b/pypy/objspace/std/dictmultiobject.py
--- a/pypy/objspace/std/dictmultiobject.py
+++ b/pypy/objspace/std/dictmultiobject.py
@@ -108,6 +108,11 @@
         #return w_value or None
         return None
 
+    def impl_setdefault(self, w_key, w_default):
+        # here the dict is always empty
+        self._as_rdict().impl_fallback_setitem(w_key, w_default)
+        return w_default
+
     def impl_setitem(self, w_key, w_value):
         self._as_rdict().impl_fallback_setitem(w_key, w_value)
 
@@ -181,6 +186,9 @@
     # _________________________________________________________________
     # fallback implementation methods
 
+    def impl_fallback_setdefault(self, w_key, w_default):
+        return self.r_dict_content.setdefault(w_key, w_default)
+
     def impl_fallback_setitem(self, w_key, w_value):
         self.r_dict_content[w_key] = w_value
 
@@ -227,6 +235,7 @@
     ("length", 0),
     ("setitem_str", 2),
     ("setitem", 2),
+    ("setdefault", 2),
     ("delitem", 1),
     ("iter", 0),
     ("items", 0),
@@ -317,6 +326,14 @@
     def impl_setitem_str(self, key, w_value):
         self.content[key] = w_value
 
+    def impl_setdefault(self, w_key, w_default):
+        space = self.space
+        if space.is_w(space.type(w_key), space.w_str):
+            return self.content.setdefault(space.str_w(w_key), w_default)
+        else:
+            return self._as_rdict().impl_fallback_setdefault(w_key, w_default)
+
+
     def impl_delitem(self, w_key):
         space = self.space
         w_key_type = space.type(w_key)
@@ -787,13 +804,7 @@
         return w_default
 
 def dict_setdefault__DictMulti_ANY_ANY(space, w_dict, w_key, w_default):
-    # XXX should be more efficient, with only one dict lookup
-    w_value = w_dict.getitem(w_key)
-    if w_value is not None:
-        return w_value
-    else:
-        w_dict.setitem(w_key, w_default)
-        return w_default
+    return w_dict.setdefault(w_key, w_default)
 
 def dict_pop__DictMulti_ANY(space, w_dict, w_key, defaults_w):
     len_defaults = len(defaults_w)

diff --git a/pypy/translator/backendopt/test/test_inline.py b/pypy/translator/backendopt/test/test_inline.py
--- a/pypy/translator/backendopt/test/test_inline.py
+++ b/pypy/translator/backendopt/test/test_inline.py
@@ -1,7 +1,7 @@
 # XXX clean up these tests to use more uniform helpers
 import py
 import os
-from pypy.objspace.flow.model import traverse, Block, Link, Variable, Constant
+from pypy.objspace.flow.model import Block, Link, Variable, Constant
 from pypy.objspace.flow.model import last_exception, checkgraph
 from pypy.translator.backendopt import canraise
 from pypy.translator.backendopt.inline import simple_inline_function, CannotInline
@@ -20,29 +20,27 @@
 from pypy.translator.backendopt import removenoops
 from pypy.objspace.flow.model import summary
 
-def no_missing_concretetype(node):
-    if isinstance(node, Block):
-        for v in node.inputargs:
-            assert hasattr(v, 'concretetype')
-        for op in node.operations:
-            for v in op.args:
-                assert hasattr(v, 'concretetype')
-            assert hasattr(op.result, 'concretetype')
-    if isinstance(node, Link):
-        if node.exitcase is not None:
-            assert hasattr(node, 'llexitcase')
-        for v in node.args:
-            assert hasattr(v, 'concretetype')
-        if isinstance(node.last_exception, (Variable, Constant)):
-            assert hasattr(node.last_exception, 'concretetype')
-        if isinstance(node.last_exc_value, (Variable, Constant)):
-            assert hasattr(node.last_exc_value, 'concretetype')
-
 def sanity_check(t):
     # look for missing '.concretetype'
     for graph in t.graphs:
         checkgraph(graph)
-        traverse(no_missing_concretetype, graph)
+        for node in graph.iterblocks():
+            for v in node.inputargs:
+                assert hasattr(v, 'concretetype')
+            for op in node.operations:
+                for v in op.args:
+                    assert hasattr(v, 'concretetype')
+                assert hasattr(op.result, 'concretetype')
+        for node in graph.iterlinks():
+            if node.exitcase is not None:
+                assert hasattr(node, 'llexitcase')
+            for v in node.args:
+                assert hasattr(v, 'concretetype')
+            if isinstance(node.last_exception, (Variable, Constant)):
+                assert hasattr(node.last_exception, 'concretetype')
+            if isinstance(node.last_exc_value, (Variable, Constant)):
+                assert hasattr(node.last_exc_value, 'concretetype')
+
 
 class CustomError1(Exception):
     def __init__(self):

diff --git a/pypy/jit/metainterp/test/test_optimizebasic.py b/pypy/jit/metainterp/test/test_optimizebasic.py
--- a/pypy/jit/metainterp/test/test_optimizebasic.py
+++ b/pypy/jit/metainterp/test/test_optimizebasic.py
@@ -253,7 +253,7 @@
         loop.call_pure_results = args_dict()
         if call_pure_results is not None:
             for k, v in call_pure_results.items():
-                loop.call_pure_results[list(k)] = v        
+                loop.call_pure_results[list(k)] = v
         metainterp_sd = FakeMetaInterpStaticData(self.cpu)
         if hasattr(self, 'vrefinfo'):
             metainterp_sd.virtualref_info = self.vrefinfo
@@ -2886,7 +2886,7 @@
         # the result of the call, recorded as the first arg), or turned into
         # a regular CALL.
         arg_consts = [ConstInt(i) for i in (123456, 4, 5, 6)]
-        call_pure_results = {tuple(arg_consts): ConstInt(42)}        
+        call_pure_results = {tuple(arg_consts): ConstInt(42)}
         ops = '''
         [i0, i1, i2]
         escape(i1)
@@ -2931,7 +2931,6 @@
         i0 = force_token()
         p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
         setfield_gc(p2, i0, descr=virtualtokendescr)
-        setfield_gc(p2, 5, descr=virtualrefindexdescr)
         escape(p2)
         setfield_gc(p2, p1, descr=virtualforceddescr)
         setfield_gc(p2, -3, descr=virtualtokendescr)
@@ -2964,7 +2963,6 @@
         #
         p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
         setfield_gc(p2, i3, descr=virtualtokendescr)
-        setfield_gc(p2, 3, descr=virtualrefindexdescr)
         setfield_gc(p0, p2, descr=nextdescr)
         #
         call_may_force(i1, descr=mayforcevirtdescr)
@@ -3005,7 +3003,6 @@
         #
         p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
         setfield_gc(p2, i3, descr=virtualtokendescr)
-        setfield_gc(p2, 2, descr=virtualrefindexdescr)
         setfield_gc(p0, p2, descr=nextdescr)
         #
         call_may_force(i1, descr=mayforcevirtdescr)
@@ -3062,7 +3059,7 @@
         self.loop.inputargs[0].value = self.nodeobjvalue
         self.check_expanded_fail_descr('''p2, p1
             p0.refdescr = p2
-            where p2 is a jit_virtual_ref_vtable, virtualtokendescr=i3, virtualrefindexdescr=2
+            where p2 is a jit_virtual_ref_vtable, virtualtokendescr=i3
             where p1 is a node_vtable, nextdescr=p1b
             where p1b is a node_vtable, valuedescr=i1
             ''', rop.GUARD_NO_EXCEPTION)
@@ -3084,7 +3081,6 @@
         i3 = force_token()
         p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
         setfield_gc(p2, i3, descr=virtualtokendescr)
-        setfield_gc(p2, 7, descr=virtualrefindexdescr)
         escape(p2)
         p1 = new_with_vtable(ConstClass(node_vtable))
         setfield_gc(p2, p1, descr=virtualforceddescr)
@@ -3111,7 +3107,6 @@
         i3 = force_token()
         p2 = new_with_vtable(ConstClass(jit_virtual_ref_vtable))
         setfield_gc(p2, i3, descr=virtualtokendescr)
-        setfield_gc(p2, 23, descr=virtualrefindexdescr)
         escape(p2)
         setfield_gc(p2, p1, descr=virtualforceddescr)
         setfield_gc(p2, -3, descr=virtualtokendescr)
@@ -3360,7 +3355,7 @@
         i1 = int_lt(i0, 4)
         guard_true(i1) []
         i1p = int_gt(i0, -4)
-        guard_true(i1p) []        
+        guard_true(i1p) []
         i2 = int_sub(i0, 10)
         i3 = int_lt(i2, -5)
         guard_true(i3) []
@@ -3371,7 +3366,7 @@
         i1 = int_lt(i0, 4)
         guard_true(i1) []
         i1p = int_gt(i0, -4)
-        guard_true(i1p) []        
+        guard_true(i1p) []
         i2 = int_sub(i0, 10)
         jump(i0)
         """

diff --git a/pypy/rpython/rint.py b/pypy/rpython/rint.py
--- a/pypy/rpython/rint.py
+++ b/pypy/rpython/rint.py
@@ -212,52 +212,48 @@
         # cpython, and rpython, assumed that integer division truncates
         # towards -infinity.  however, in C99 and most (all?) other
         # backends, integer division truncates towards 0.  so assuming
-        # that, we can generate scary code that applies the necessary
+        # that, we call a helper function that applies the necessary
         # correction in the right cases.
-        # paper and pencil are encouraged for this :)
-
-        from pypy.rpython.rbool import bool_repr
-        assert isinstance(repr.lowleveltype, Number)
-        c_zero = inputconst(repr.lowleveltype, repr.lowleveltype._default)
 
         op = func.split('_', 1)[0]
 
         if op == 'floordiv':
-            # return (x/y) - (((x^y)<0)&((x%y)!=0));
-            v_xor = hop.genop(prefix + 'xor', vlist,
-                            resulttype=repr)
-            v_xor_le = hop.genop(prefix + 'lt', [v_xor, c_zero],
-                                 resulttype=Bool)
-            v_xor_le = hop.llops.convertvar(v_xor_le, bool_repr, repr)
-            v_mod = hop.genop(prefix + 'mod', vlist,
-                            resulttype=repr)
-            v_mod_ne = hop.genop(prefix + 'ne', [v_mod, c_zero],
-                               resulttype=Bool)
-            v_mod_ne = hop.llops.convertvar(v_mod_ne, bool_repr, repr)
-            v_corr = hop.genop(prefix + 'and', [v_xor_le, v_mod_ne],
-                             resulttype=repr)
-            v_res = hop.genop(prefix + 'sub', [v_res, v_corr],
-                              resulttype=repr)
+            llfunc = globals()['ll_correct_' + prefix + 'floordiv']
+            v_res = hop.gendirectcall(llfunc, vlist[0], vlist[1], v_res)
         elif op == 'mod':
-            # return r + y*(((x^y)<0)&(r!=0));
-            v_xor = hop.genop(prefix + 'xor', vlist,
-                            resulttype=repr)
-            v_xor_le = hop.genop(prefix + 'lt', [v_xor, c_zero],
-                               resulttype=Bool)
-            v_xor_le = hop.llops.convertvar(v_xor_le, bool_repr, repr)
-            v_mod_ne = hop.genop(prefix + 'ne', [v_res, c_zero],
-                               resulttype=Bool)
-            v_mod_ne = hop.llops.convertvar(v_mod_ne, bool_repr, repr)
-            v_corr1 = hop.genop(prefix + 'and', [v_xor_le, v_mod_ne],
-                             resulttype=repr)
-            v_corr = hop.genop(prefix + 'mul', [v_corr1, vlist[1]],
-                             resulttype=repr)
-            v_res = hop.genop(prefix + 'add', [v_res, v_corr],
-                              resulttype=repr)
+            llfunc = globals()['ll_correct_' + prefix + 'mod']
+            v_res = hop.gendirectcall(llfunc, vlist[1], v_res)
+
     v_res = hop.llops.convertvar(v_res, repr, r_result)
     return v_res
 
 
+INT_BITS_1 = r_int.BITS - 1
+LLONG_BITS_1 = r_longlong.BITS - 1
+
+def ll_correct_int_floordiv(x, y, r):
+    p = r * y
+    if y < 0: u = p - x
+    else:     u = x - p
+    return r + (u >> INT_BITS_1)
+
+def ll_correct_llong_floordiv(x, y, r):
+    p = r * y
+    if y < 0: u = p - x
+    else:     u = x - p
+    return r + (u >> LLONG_BITS_1)
+
+def ll_correct_int_mod(y, r):
+    if y < 0: u = -r
+    else:     u = r
+    return r + (y & (u >> INT_BITS_1))
+
+def ll_correct_llong_mod(y, r):
+    if y < 0: u = -r
+    else:     u = r
+    return r + (y & (u >> LLONG_BITS_1))
+
+
 #Helper functions for comparisons
 
 def _rtype_compare_template(hop, func):

diff --git a/pypy/tool/jitlogparser/module_finder.py b/pypy/tool/jitlogparser/module_finder.py
--- a/pypy/tool/jitlogparser/module_finder.py
+++ b/pypy/tool/jitlogparser/module_finder.py
@@ -6,7 +6,7 @@
     more = [code]
     while more:
         next = more.pop()
-        res[next.co_firstlineno] = next
+        res[(next.co_firstlineno, next.co_name)] = next
         more += [co for co in next.co_consts
                  if isinstance(co, types.CodeType)]
     return res

diff --git a/pypy/module/imp/__init__.py b/pypy/module/imp/__init__.py
--- a/pypy/module/imp/__init__.py
+++ b/pypy/module/imp/__init__.py
@@ -19,6 +19,7 @@
         'load_module':     'interp_imp.load_module',
         'load_source':     'interp_imp.load_source',
         'load_compiled':   'interp_imp.load_compiled',
+        'load_dynamic':    'interp_imp.load_dynamic',
         '_run_compiled_module': 'interp_imp._run_compiled_module',   # pypy
         '_getimporter':    'importing._getimporter',                 # pypy
         #'run_module':      'interp_imp.run_module',
@@ -36,7 +37,6 @@
         }
 
     appleveldefs = {
-        'load_dynamic':    'app_imp.load_dynamic',
         }
 
     def __init__(self, space, *args):

diff --git a/pypy/translator/oosupport/test_template/builtin.py b/pypy/translator/oosupport/test_template/builtin.py
--- a/pypy/translator/oosupport/test_template/builtin.py
+++ b/pypy/translator/oosupport/test_template/builtin.py
@@ -227,6 +227,17 @@
         assert res == ord('a')
 
 
+    def test_rlocale(self):
+        from pypy.rlib.rlocale import isupper, islower, isalpha, isalnum, tolower
+        def fn():
+            assert isupper(ord("A"))
+            assert islower(ord("a"))
+            assert not isalpha(ord(" "))
+            assert isalnum(ord("1"))
+            assert tolower(ord("A")) == ord("a")
+        self.interpret(fn, [])
+
+
 class BaseTestTime(llBaseTestTime):
 
     def test_time_clock(self):

diff --git a/pypy/jit/metainterp/test/support.py b/pypy/jit/metainterp/test/support.py
new file mode 100644
--- /dev/null
+++ b/pypy/jit/metainterp/test/support.py
@@ -0,0 +1,261 @@
+
+import py, sys
+from pypy.rpython.lltypesystem import lltype, llmemory
+from pypy.rpython.ootypesystem import ootype
+from pypy.jit.backend.llgraph import runner
+from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats
+from pypy.jit.metainterp.optimizeopt import ALL_OPTS_DICT
+from pypy.jit.metainterp import pyjitpl, history
+from pypy.jit.metainterp.warmstate import set_future_value
+from pypy.jit.codewriter.policy import JitPolicy
+from pypy.jit.codewriter import longlong
+
+def _get_jitcodes(testself, CPUClass, func, values, type_system,
+                  supports_longlong=False, **kwds):
+    from pypy.jit.codewriter import support, codewriter
+
+    class FakeJitCell:
+        __compiled_merge_points = []
+        def get_compiled_merge_points(self):
+            return self.__compiled_merge_points[:]
+        def set_compiled_merge_points(self, lst):
+            self.__compiled_merge_points = lst
+
+    class FakeWarmRunnerState:
+        def attach_unoptimized_bridge_from_interp(self, greenkey, newloop):
+            pass
+
+        def jit_cell_at_key(self, greenkey):
+            assert greenkey == []
+            return self._cell
+        _cell = FakeJitCell()
+
+        trace_limit = sys.maxint
+        enable_opts = ALL_OPTS_DICT
+
+    func._jit_unroll_safe_ = True
+    rtyper = support.annotate(func, values, type_system=type_system)
+    graphs = rtyper.annotator.translator.graphs
+    result_kind = history.getkind(graphs[0].getreturnvar().concretetype)[0]
+
+    class FakeJitDriverSD:
+        num_green_args = 0
+        portal_graph = graphs[0]
+        virtualizable_info = None
+        greenfield_info = None
+        result_type = result_kind
+        portal_runner_ptr = "???"
+
+    stats = history.Stats()
+    cpu = CPUClass(rtyper, stats, None, False)
+    cw = codewriter.CodeWriter(cpu, [FakeJitDriverSD()])
+    testself.cw = cw
+    policy = JitPolicy()
+    policy.set_supports_longlong(supports_longlong)
+    cw.find_all_graphs(policy)
+    #
+    testself.warmrunnerstate = FakeWarmRunnerState()
+    testself.warmrunnerstate.cpu = cpu
+    FakeJitDriverSD.warmstate = testself.warmrunnerstate
+    if hasattr(testself, 'finish_setup_for_interp_operations'):
+        testself.finish_setup_for_interp_operations()
+    #
+    cw.make_jitcodes(verbose=True)
+
+def _run_with_blackhole(testself, args):
+    from pypy.jit.metainterp.blackhole import BlackholeInterpBuilder
+    cw = testself.cw
+    blackholeinterpbuilder = BlackholeInterpBuilder(cw)
+    blackholeinterp = blackholeinterpbuilder.acquire_interp()
+    count_i = count_r = count_f = 0
+    for value in args:
+        T = lltype.typeOf(value)
+        if T == lltype.Signed:
+            blackholeinterp.setarg_i(count_i, value)
+            count_i += 1
+        elif T == llmemory.GCREF:
+            blackholeinterp.setarg_r(count_r, value)
+            count_r += 1
+        elif T == lltype.Float:
+            value = longlong.getfloatstorage(value)
+            blackholeinterp.setarg_f(count_f, value)
+            count_f += 1
+        else:
+            raise TypeError(T)
+    [jitdriver_sd] = cw.callcontrol.jitdrivers_sd
+    blackholeinterp.setposition(jitdriver_sd.mainjitcode, 0)
+    blackholeinterp.run()
+    return blackholeinterp._final_result_anytype()
+
+def _run_with_pyjitpl(testself, args):
+
+    class DoneWithThisFrame(Exception):
+        pass
+
+    class DoneWithThisFrameRef(DoneWithThisFrame):
+        def __init__(self, cpu, *args):
+            DoneWithThisFrame.__init__(self, *args)
+
+    cw = testself.cw
+    opt = history.Options(listops=True)
+    metainterp_sd = pyjitpl.MetaInterpStaticData(cw.cpu, opt)
+    metainterp_sd.finish_setup(cw)
+    [jitdriver_sd] = metainterp_sd.jitdrivers_sd
+    metainterp = pyjitpl.MetaInterp(metainterp_sd, jitdriver_sd)
+    metainterp_sd.DoneWithThisFrameInt = DoneWithThisFrame
+    metainterp_sd.DoneWithThisFrameRef = DoneWithThisFrameRef
+    metainterp_sd.DoneWithThisFrameFloat = DoneWithThisFrame
+    testself.metainterp = metainterp
+    try:
+        metainterp.compile_and_run_once(jitdriver_sd, *args)
+    except DoneWithThisFrame, e:
+        #if conftest.option.view:
+        #    metainterp.stats.view()
+        return e.args[0]
+    else:
+        raise Exception("FAILED")
+
+def _run_with_machine_code(testself, args):
+    metainterp = testself.metainterp
+    num_green_args = metainterp.jitdriver_sd.num_green_args
+    loop_tokens = metainterp.get_compiled_merge_points(args[:num_green_args])
+    if len(loop_tokens) != 1:
+        return NotImplemented
+    # a loop was successfully created by _run_with_pyjitpl(); call it
+    cpu = metainterp.cpu
+    for i in range(len(args) - num_green_args):
+        x = args[num_green_args + i]
+        typecode = history.getkind(lltype.typeOf(x))
+        set_future_value(cpu, i, x, typecode)
+    faildescr = cpu.execute_token(loop_tokens[0])
+    assert faildescr.__class__.__name__.startswith('DoneWithThisFrameDescr')
+    if metainterp.jitdriver_sd.result_type == history.INT:
+        return cpu.get_latest_value_int(0)
+    elif metainterp.jitdriver_sd.result_type == history.REF:
+        return cpu.get_latest_value_ref(0)
+    elif metainterp.jitdriver_sd.result_type == history.FLOAT:
+        return cpu.get_latest_value_float(0)
+    else:
+        return None
+
+
+class JitMixin:
+    basic = True
+    def check_loops(self, expected=None, everywhere=False, **check):
+        get_stats().check_loops(expected=expected, everywhere=everywhere,
+                                **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.
+        This counts as 1 every bridge in addition to every loop; and it does
+        not count at all the entry bridges from interpreter, although they
+        are TreeLoops as well."""
+        assert get_stats().compiled_count == count
+    def check_tree_loop_count(self, count):
+        assert len(get_stats().loops) == count
+    def check_loop_count_at_most(self, count):
+        assert get_stats().compiled_count <= count
+    def check_enter_count(self, count):
+        assert get_stats().enter_count == count
+    def check_enter_count_at_most(self, count):
+        assert get_stats().enter_count <= count
+    def check_jumps(self, maxcount):
+        assert get_stats().exec_jumps <= maxcount
+    def check_aborted_count(self, count):
+        assert get_stats().aborted_count == count
+    def check_aborted_count_at_least(self, count):
+        assert get_stats().aborted_count >= count
+
+    def meta_interp(self, *args, **kwds):
+        kwds['CPUClass'] = self.CPUClass
+        kwds['type_system'] = self.type_system
+        if "backendopt" not in kwds:
+            kwds["backendopt"] = False
+        return ll_meta_interp(*args, **kwds)
+
+    def interp_operations(self, f, args, **kwds):
+        # get the JitCodes for the function f
+        _get_jitcodes(self, self.CPUClass, f, args, self.type_system, **kwds)
+        # try to run it with blackhole.py
+        result1 = _run_with_blackhole(self, args)
+        # try to run it with pyjitpl.py
+        result2 = _run_with_pyjitpl(self, args)
+        assert result1 == result2
+        # try to run it by running the code compiled just before
+        result3 = _run_with_machine_code(self, args)
+        assert result1 == result3 or result3 == NotImplemented
+        #
+        if (longlong.supports_longlong and
+            isinstance(result1, longlong.r_float_storage)):
+            result1 = longlong.getrealfloat(result1)
+        return result1
+
+    def check_history(self, expected=None, **isns):
+        # this can be used after calling meta_interp
+        get_stats().check_history(expected, **isns)
+
+    def check_operations_history(self, expected=None, **isns):
+        # this can be used after interp_operations
+        if expected is not None:
+            expected = dict(expected)
+            expected['jump'] = 1
+        self.metainterp.staticdata.stats.check_history(expected, **isns)
+
+
+class LLJitMixin(JitMixin):
+    type_system = 'lltype'
+    CPUClass = runner.LLtypeCPU
+
+    @staticmethod
+    def Ptr(T):
+        return lltype.Ptr(T)
+
+    @staticmethod
+    def GcStruct(name, *fields, **kwds):
+        S = lltype.GcStruct(name, *fields, **kwds)
+        return S
+
+    malloc = staticmethod(lltype.malloc)
+    nullptr = staticmethod(lltype.nullptr)
+
+    @staticmethod
+    def malloc_immortal(T):
+        return lltype.malloc(T, immortal=True)
+
+    def _get_NODE(self):
+        NODE = lltype.GcForwardReference()
+        NODE.become(lltype.GcStruct('NODE', ('value', lltype.Signed),
+                                            ('next', lltype.Ptr(NODE))))
+        return NODE
+    
+class OOJitMixin(JitMixin):
+    type_system = 'ootype'
+    #CPUClass = runner.OOtypeCPU
+
+    def setup_class(cls):
+        py.test.skip("ootype tests skipped for now")
+
+    @staticmethod
+    def Ptr(T):
+        return T
+
+    @staticmethod
+    def GcStruct(name, *fields, **kwds):
+        if 'hints' in kwds:
+            kwds['_hints'] = kwds['hints']
+            del kwds['hints']
+        I = ootype.Instance(name, ootype.ROOT, dict(fields), **kwds)
+        return I
+
+    malloc = staticmethod(ootype.new)
+    nullptr = staticmethod(ootype.null)
+
+    @staticmethod
+    def malloc_immortal(T):
+        return ootype.new(T)
+
+    def _get_NODE(self):
+        NODE = ootype.Instance('NODE', ootype.ROOT, {})
+        NODE._add_fields({'value': ootype.Signed,
+                          'next': NODE})
+        return NODE

diff --git a/pypy/module/_winreg/interp_winreg.py b/pypy/module/_winreg/interp_winreg.py
--- a/pypy/module/_winreg/interp_winreg.py
+++ b/pypy/module/_winreg/interp_winreg.py
@@ -261,7 +261,8 @@
 
                 if ret != 0:
                     raiseWindowsError(space, ret, 'RegQueryValue')
-                return space.wrap(rffi.charp2strn(buf, bufsize_p[0] - 1))
+                length = intmask(bufsize_p[0] - 1)
+                return space.wrap(rffi.charp2strn(buf, length))
 
 def convert_to_regdata(space, w_value, typ):
     buf = None
@@ -445,9 +446,10 @@
                         continue
                     if ret != 0:
                         raiseWindowsError(space, ret, 'RegQueryValueEx')
+                    length = intmask(retDataSize[0])
                     return space.newtuple([
                         convert_from_regdata(space, databuf,
-                                             retDataSize[0], retType[0]),
+                                             length, retType[0]),
                         space.wrap(retType[0]),
                         ])
 
@@ -595,11 +597,11 @@
                             if ret != 0:
                                 raiseWindowsError(space, ret, 'RegEnumValue')
 
+                            length = intmask(retDataSize[0])
                             return space.newtuple([
                                 space.wrap(rffi.charp2str(valuebuf)),
                                 convert_from_regdata(space, databuf,
-                                                     retDataSize[0],
-                                                     retType[0]),
+                                                     length, retType[0]),
                                 space.wrap(retType[0]),
                                 ])
 

diff --git a/pypy/jit/backend/cli/test/test_basic.py b/pypy/jit/backend/cli/test/test_basic.py
--- a/pypy/jit/backend/cli/test/test_basic.py
+++ b/pypy/jit/backend/cli/test/test_basic.py
@@ -1,14 +1,14 @@
 import py
 from pypy.jit.backend.cli.runner import CliCPU
-from pypy.jit.metainterp.test import test_basic
+from pypy.jit.metainterp.test import support, test_ajit
 
-class CliJitMixin(test_basic.OOJitMixin):
+class CliJitMixin(suport.OOJitMixin):
     CPUClass = CliCPU
     def setup_class(cls):
         from pypy.translator.cli.support import PythonNet
         PythonNet.System     # possibly raises Skip
 
-class TestBasic(CliJitMixin, test_basic.TestOOtype):
+class TestBasic(CliJitMixin, test_ajit.TestOOtype):
     # for the individual tests see
     # ====> ../../../metainterp/test/test_basic.py
 

diff --git a/pypy/translator/jvm/opcodes.py b/pypy/translator/jvm/opcodes.py
--- a/pypy/translator/jvm/opcodes.py
+++ b/pypy/translator/jvm/opcodes.py
@@ -106,6 +106,10 @@
     'debug_catch_exception':    Ignore,
     'debug_reraise_traceback':  Ignore,
     'debug_print_traceback':    Ignore,
+    'debug_start':              Ignore,
+    'debug_stop':               Ignore,
+    'debug_print':              Ignore,
+    'keepalive':                Ignore,
 
     # __________ numeric operations __________
 
@@ -144,6 +148,7 @@
     'int_xor_ovf':              jvm.IXOR,
     'int_floordiv_ovf_zer':     jvm.IFLOORDIVZEROVF,
     'int_mod_ovf_zer':          _check_zer(jvm.IREMOVF),
+    'int_between':              jvm.PYPYINTBETWEEN,
 
     'uint_invert':              'bitwise_negate',
 
@@ -185,8 +190,8 @@
     'llong_mod_zer':            _check_zer(jvm.LREM),
     'llong_and':                jvm.LAND,
     'llong_or':                 jvm.LOR,
-    'llong_lshift':             [PushAllArgs, jvm.L2I, jvm.LSHL, StoreResult],
-    'llong_rshift':             [PushAllArgs, jvm.L2I, jvm.LSHR, StoreResult],
+    'llong_lshift':             [PushAllArgs, jvm.LSHL, StoreResult],
+    'llong_rshift':             [PushAllArgs, jvm.LSHR, StoreResult],
     'llong_xor':                jvm.LXOR,
     'llong_floordiv_ovf':       jvm.LFLOORDIVOVF,
     'llong_floordiv_ovf_zer':   jvm.LFLOORDIVZEROVF,    
@@ -202,9 +207,11 @@
     'ullong_truediv':           None, # TODO
     'ullong_floordiv':          jvm.LDIV, # valid?
     'ullong_mod':               jvm.PYPYULONGMOD,
-    'ullong_lshift':            [PushAllArgs, jvm.L2I, jvm.LSHL, StoreResult],
-    'ullong_rshift':            [PushAllArgs, jvm.L2I, jvm.LUSHR, StoreResult],
+    'ullong_lshift':            [PushAllArgs, jvm.LSHL, StoreResult],
+    'ullong_rshift':            [PushAllArgs, jvm.LUSHR, StoreResult],
     'ullong_mod_zer':           jvm.PYPYULONGMOD,
+    'ullong_or':                jvm.LOR,
+    'ullong_and':               jvm.LAND,
 
     # when casting from bool we want that every truth value is casted
     # to 1: we can't simply DoNothing, because the CLI stack could
@@ -227,5 +234,8 @@
     'cast_float_to_uint':       jvm.PYPYDOUBLETOUINT,
     'truncate_longlong_to_int': jvm.L2I,
     'cast_longlong_to_float':   jvm.L2D,
+    'cast_float_to_ulonglong':  jvm.PYPYDOUBLETOULONG,
+    'cast_ulonglong_to_float':  jvm.PYPYULONGTODOUBLE,
     'cast_primitive':           [PushAllArgs, CastPrimitive, StoreResult],
+    'force_cast':               [PushAllArgs, CastPrimitive, StoreResult],
 })

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
@@ -1,6 +1,6 @@
 import py
 from pypy.jit.codewriter.policy import StopAtXPolicy
-from pypy.jit.metainterp.test.test_basic import OOJitMixin, LLJitMixin
+from pypy.jit.metainterp.test.support import OOJitMixin, LLJitMixin
 
 
 class ToyLanguageTests:

diff --git a/pypy/interpreter/pyframe.py b/pypy/interpreter/pyframe.py
--- a/pypy/interpreter/pyframe.py
+++ b/pypy/interpreter/pyframe.py
@@ -46,15 +46,15 @@
     w_f_trace                = None
     # For tracing
     instr_lb                 = 0
-    instr_ub                 = -1
-    instr_prev               = -1
+    instr_ub                 = 0
+    instr_prev_plus_one      = 0
     is_being_profiled        = False
 
     def __init__(self, space, code, w_globals, closure):
         self = hint(self, access_directly=True, fresh_virtualizable=True)
         assert isinstance(code, pycode.PyCode)
         self.pycode = code
-        eval.Frame.__init__(self, space, w_globals, code.co_nlocals)
+        eval.Frame.__init__(self, space, w_globals)
         self.valuestack_w = [None] * code.co_stacksize
         self.valuestackdepth = 0
         self.lastblock = None
@@ -63,7 +63,7 @@
         # regular functions always have CO_OPTIMIZED and CO_NEWLOCALS.
         # class bodies only have CO_NEWLOCALS.
         self.initialize_frame_scopes(closure, code)
-        self.fastlocals_w = [None]*self.numlocals
+        self.fastlocals_w = [None] * code.co_nlocals
         make_sure_not_resized(self.fastlocals_w)
         self.f_lineno = code.co_firstlineno
 
@@ -335,7 +335,7 @@
 
             w(self.instr_lb), #do we need these three (that are for tracing)
             w(self.instr_ub),
-            w(self.instr_prev),
+            w(self.instr_prev_plus_one),
             w_cells,
             ]
 
@@ -349,7 +349,7 @@
         args_w = space.unpackiterable(w_args)
         w_f_back, w_builtin, w_pycode, w_valuestack, w_blockstack, w_exc_value, w_tb,\
             w_globals, w_last_instr, w_finished, w_f_lineno, w_fastlocals, w_f_locals, \
-            w_f_trace, w_instr_lb, w_instr_ub, w_instr_prev, w_cells = args_w
+            w_f_trace, w_instr_lb, w_instr_ub, w_instr_prev_plus_one, w_cells = args_w
 
         new_frame = self
         pycode = space.interp_w(PyCode, w_pycode)
@@ -397,7 +397,7 @@
 
         new_frame.instr_lb = space.int_w(w_instr_lb)   #the three for tracing
         new_frame.instr_ub = space.int_w(w_instr_ub)
-        new_frame.instr_prev = space.int_w(w_instr_prev)
+        new_frame.instr_prev_plus_one = space.int_w(w_instr_prev_plus_one)
 
         self._setcellvars(cellvars)
         # XXX what if the frame is in another thread??
@@ -430,7 +430,10 @@
         """Initialize cellvars from self.fastlocals_w
         This is overridden in nestedscope.py"""
         pass
-    
+
+    def getfastscopelength(self):
+        return self.pycode.co_nlocals
+
     def getclosure(self):
         return None
 

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
@@ -25,12 +25,13 @@
 class Descr(history.AbstractDescr):
 
     def __init__(self, ofs, typeinfo, extrainfo=None, name=None,
-                 arg_types=None):
+                 arg_types=None, count_fields_if_immut=-1):
         self.ofs = ofs
         self.typeinfo = typeinfo
         self.extrainfo = extrainfo
         self.name = name
         self.arg_types = arg_types
+        self.count_fields_if_immut = count_fields_if_immut
 
     def get_arg_types(self):
         return self.arg_types
@@ -63,6 +64,9 @@
     def as_vtable_size_descr(self):
         return self
 
+    def count_fields_if_immutable(self):
+        return self.count_fields_if_immut
+
     def __lt__(self, other):
         raise TypeError("cannot use comparison on Descrs")
     def __le__(self, other):
@@ -109,12 +113,14 @@
         return False
 
     def getdescr(self, ofs, typeinfo='?', extrainfo=None, name=None,
-                 arg_types=None):
-        key = (ofs, typeinfo, extrainfo, name, arg_types)
+                 arg_types=None, count_fields_if_immut=-1):
+        key = (ofs, typeinfo, extrainfo, name, arg_types,
+               count_fields_if_immut)
         try:
             return self._descrs[key]
         except KeyError:
-            descr = Descr(ofs, typeinfo, extrainfo, name, arg_types)
+            descr = Descr(ofs, typeinfo, extrainfo, name, arg_types,
+                          count_fields_if_immut)
             self._descrs[key] = descr
             return descr
 
@@ -284,7 +290,8 @@
 
     def sizeof(self, S):
         assert not isinstance(S, lltype.Ptr)
-        return self.getdescr(symbolic.get_size(S))
+        count = heaptracker.count_fields_if_immutable(S)
+        return self.getdescr(symbolic.get_size(S), count_fields_if_immut=count)
 
 
 class LLtypeCPU(BaseCPU):

diff --git a/pypy/module/cpyext/typeobjectdefs.py b/pypy/module/cpyext/typeobjectdefs.py
--- a/pypy/module/cpyext/typeobjectdefs.py
+++ b/pypy/module/cpyext/typeobjectdefs.py
@@ -1,9 +1,8 @@
 from pypy.rpython.lltypesystem import rffi, lltype
 from pypy.rpython.lltypesystem.lltype import Ptr, FuncType, Void
-from pypy.module.cpyext.api import cpython_struct, \
-    PyVarObjectFields, Py_ssize_t, Py_TPFLAGS_READYING, \
-    Py_TPFLAGS_READY, Py_TPFLAGS_HEAPTYPE, \
-    PyTypeObject, PyTypeObjectPtr, PyBufferProcs, FILEP
+from pypy.module.cpyext.api import (cpython_struct, Py_ssize_t, Py_ssize_tP,
+    PyVarObjectFields, PyTypeObject, PyTypeObjectPtr, FILEP,
+    Py_TPFLAGS_READYING, Py_TPFLAGS_READY, Py_TPFLAGS_HEAPTYPE)
 from pypy.module.cpyext.pyobject import PyObject, make_ref, from_ref
 from pypy.module.cpyext.modsupport import PyMethodDef
 
@@ -55,6 +54,14 @@
 wrapperfunc = P(FT([PyO, PyO, rffi.VOIDP], PyO))
 wrapperfunc_kwds = P(FT([PyO, PyO, rffi.VOIDP, PyO], PyO))
 
+readbufferproc = P(FT([PyO, Py_ssize_t, rffi.VOIDPP], Py_ssize_t))
+writebufferproc = P(FT([PyO, Py_ssize_t, rffi.VOIDPP], Py_ssize_t))
+segcountproc = P(FT([PyO, Py_ssize_tP], Py_ssize_t))
+charbufferproc = P(FT([PyO, Py_ssize_t, rffi.CCHARPP], Py_ssize_t))
+## We don't support new buffer interface for now
+getbufferproc = rffi.VOIDP
+releasebufferproc = rffi.VOIDP
+
 
 PyGetSetDef = cpython_struct("PyGetSetDef", (
     ("name", rffi.CCHARP),
@@ -127,7 +134,6 @@
     ("mp_ass_subscript", objobjargproc),
 ))
 
-"""
 PyBufferProcs = cpython_struct("PyBufferProcs", (
     ("bf_getreadbuffer", readbufferproc),
     ("bf_getwritebuffer", writebufferproc),
@@ -136,7 +142,6 @@
     ("bf_getbuffer", getbufferproc),
     ("bf_releasebuffer", releasebufferproc),
 ))
-"""
 
 PyMemberDef = cpython_struct("PyMemberDef", (
     ("name", rffi.CCHARP),

diff --git a/pypy/module/posix/app_posix.py b/pypy/module/posix/app_posix.py
--- a/pypy/module/posix/app_posix.py
+++ b/pypy/module/posix/app_posix.py
@@ -190,14 +190,30 @@
 
     def wait():
         """ wait() -> (pid, status)
-    
+
         Wait for completion of a child process.
         """
         return posix.waitpid(-1, 0)
 
+    def wait3(options):
+        """ wait3(options) -> (pid, status, rusage)
+
+        Wait for completion of a child process and provides resource usage informations
+        """
+        from _pypy_wait import wait3
+        return wait3(options)
+
+    def wait4(pid, options):
+        """ wait4(pid, options) -> (pid, status, rusage)
+
+        Wait for completion of the child process "pid" and provides resource usage informations
+        """
+        from _pypy_wait import wait4
+        return wait4(pid, options)
+
 else:
     # Windows implementations
-    
+
     # Supply os.popen() based on subprocess
     def popen(cmd, mode="r", bufsize=-1):
         """popen(command [, mode='r' [, bufsize]]) -> pipe
@@ -285,7 +301,7 @@
             raise TypeError("invalid cmd type (%s, expected string)" %
                             (type(cmd),))
         return cmd
-        
+
     # A proxy for a file whose close waits for the process
     class _wrap_close(object):
         def __init__(self, stream, proc):

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
@@ -3,8 +3,102 @@
 from pypy.jit.metainterp.resoperation import rop, ResOperation
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.jit.metainterp.jitexc import JitException
+from pypy.jit.metainterp.optimizeopt.optimizer import Optimization
 
-from pypy.jit.metainterp.optimizeopt.optimizer import Optimization
+
+class CachedField(object):
+    def __init__(self):
+        # Cache information for a field descr.  It can be in one
+        # of two states:
+        #
+        #   1. 'cached_fields' is a dict mapping OptValues of structs
+        #      to OptValues of fields.  All fields on-heap are
+        #      synchronized with the values stored in the cache.
+        #
+        #   2. we just did one setfield, which is delayed (and thus
+        #      not synchronized).  'lazy_setfield' is the delayed
+        #      ResOperation.  In this state, 'cached_fields' contains
+        #      out-of-date information.  More precisely, the field
+        #      value pending in the ResOperation is *not* visible in
+        #      'cached_fields'.
+        #
+        self._cached_fields = {}
+        self._lazy_setfield = None
+        self._lazy_setfield_registered = False
+
+    def do_setfield(self, optheap, op):
+        # Update the state with the SETFIELD_GC operation 'op'.
+        structvalue = optheap.getvalue(op.getarg(0))
+        fieldvalue  = optheap.getvalue(op.getarg(1))
+        if self.possible_aliasing(optheap, structvalue):
+            self.force_lazy_setfield(optheap)
+            assert not self.possible_aliasing(optheap, structvalue)
+        cached_fieldvalue = self._cached_fields.get(structvalue, None)
+        if cached_fieldvalue is not fieldvalue:
+            # common case: store the 'op' as lazy_setfield, and register
+            # myself in the optheap's _lazy_setfields list
+            self._lazy_setfield = op
+            if not self._lazy_setfield_registered:
+                optheap._lazy_setfields.append(self)
+                self._lazy_setfield_registered = True
+        else:
+            # this is the case where the pending setfield ends up
+            # storing precisely the value that is already there,
+            # as proved by 'cached_fields'.  In this case, we don't
+            # need any _lazy_setfield: the heap value is already right.
+            # Note that this may reset to None a non-None lazy_setfield,
+            # cancelling its previous effects with no side effect.
+            self._lazy_setfield = None
+
+    def possible_aliasing(self, optheap, structvalue):
+        # If lazy_setfield is set and contains a setfield on a different
+        # structvalue, then we are annoyed, because it may point to either
+        # the same or a different structure at runtime.
+        return (self._lazy_setfield is not None
+                and (optheap.getvalue(self._lazy_setfield.getarg(0))
+                     is not structvalue))
+
+    def getfield_from_cache(self, optheap, structvalue):
+        # Returns the up-to-date field's value, or None if not cached.
+        if self.possible_aliasing(optheap, structvalue):
+            self.force_lazy_setfield(optheap)
+        if self._lazy_setfield is not None:
+            op = self._lazy_setfield
+            assert optheap.getvalue(op.getarg(0)) is structvalue
+            return optheap.getvalue(op.getarg(1))
+        else:
+            return self._cached_fields.get(structvalue, None)
+
+    def remember_field_value(self, structvalue, fieldvalue):
+        assert self._lazy_setfield is None
+        self._cached_fields[structvalue] = fieldvalue
+
+    def force_lazy_setfield(self, optheap):
+        op = self._lazy_setfield
+        if op is not None:
+            # This is the way _lazy_setfield is usually reset to None.
+            # Now we clear _cached_fields, because actually doing the
+            # setfield might impact any of the stored result (because of
+            # possible aliasing).
+            self._cached_fields.clear()
+            self._lazy_setfield = None
+            optheap.next_optimization.propagate_forward(op)
+            # Once it is done, we can put at least one piece of information
+            # back in the cache: the value of this particular structure's
+            # field.
+            structvalue = optheap.getvalue(op.getarg(0))
+            fieldvalue  = optheap.getvalue(op.getarg(1))
+            self.remember_field_value(structvalue, fieldvalue)
+
+    def get_reconstructed(self, optimizer, valuemap):
+        assert self._lazy_setfield is None
+        cf = CachedField()
+        for structvalue, fieldvalue in self._cached_fields.iteritems():
+            structvalue2 = structvalue.get_reconstructed(optimizer, valuemap)
+            fieldvalue2  = fieldvalue .get_reconstructed(optimizer, valuemap)
+            cf._cached_fields[structvalue2] = fieldvalue2
+        return cf
+
 
 class CachedArrayItems(object):
     def __init__(self):
@@ -20,40 +114,23 @@
     """Cache repeated heap accesses"""
     
     def __init__(self):
-        # cached fields:  {descr: {OptValue_instance: OptValue_fieldvalue}}
+        # cached fields:  {descr: CachedField}
         self.cached_fields = {}
-        self.known_heap_fields = {}
+        self._lazy_setfields = []
         # cached array items:  {descr: CachedArrayItems}
         self.cached_arrayitems = {}
-        # lazily written setfields (at most one per descr):  {descr: op}
-        self.lazy_setfields = {}
-        self.lazy_setfields_descrs = []     # keys (at least) of previous dict
 
     def reconstruct_for_next_iteration(self, optimizer, valuemap):
         new = OptHeap()
 
         if True:
             self.force_all_lazy_setfields()
-            assert not self.lazy_setfields_descrs
-            assert not self.lazy_setfields
         else:
-            new.lazy_setfields_descrs = self.lazy_setfields_descrs
-            new.lazy_setfields = self.lazy_setfields
+            assert 0   # was: new.lazy_setfields = self.lazy_setfields
         
         for descr, d in self.cached_fields.items():
-            newd = {}
-            new.cached_fields[descr] = newd
-            for value, fieldvalue in d.items():
-                newd[value.get_reconstructed(optimizer, valuemap)] = \
-                                       fieldvalue.get_reconstructed(optimizer, valuemap)
-            
-        for descr, d in self.known_heap_fields.items():
-            newd = {}
-            new.known_heap_fields[descr] = newd
-            for value, fieldvalue in d.items():
-                newd[value.get_reconstructed(optimizer, valuemap)] = \
-                                       fieldvalue.get_reconstructed(optimizer, valuemap)
-            
+            new.cached_fields[descr] = d.get_reconstructed(optimizer, valuemap)
+
         new.cached_arrayitems = {}
         for descr, d in self.cached_arrayitems.items():
             newd = {}
@@ -74,30 +151,16 @@
         return new
 
     def clean_caches(self):
+        del self._lazy_setfields[:]
         self.cached_fields.clear()
-        self.known_heap_fields.clear()
         self.cached_arrayitems.clear()
 
-    def cache_field_value(self, descr, value, fieldvalue, write=False):
-        if write:
-            # when seeing a setfield, we have to clear the cache for the same
-            # field on any other structure, just in case they are aliasing
-            # each other
-            d = self.cached_fields[descr] = {}
-        else:
-            d = self.cached_fields.setdefault(descr, {})
-        d[value] = fieldvalue
-
-    def read_cached_field(self, descr, value):
-        # XXX self.cached_fields and self.lazy_setfields should probably
-        # be merged somehow
-        d = self.cached_fields.get(descr, None)
-        if d is None:
-            op = self.lazy_setfields.get(descr, None)
-            if op is None:
-                return None
-            return self.getvalue(op.getarg(1))
-        return d.get(value, None)
+    def field_cache(self, descr):
+        try:
+            cf = self.cached_fields[descr]
+        except KeyError:
+            cf = self.cached_fields[descr] = CachedField()
+        return cf
 
     def cache_arrayitem_value(self, descr, value, indexvalue, fieldvalue, write=False):
         d = self.cached_arrayitems.get(descr, None)
@@ -157,11 +220,15 @@
             self.optimizer.pendingfields = self.force_lazy_setfields_for_guard()
             return
         opnum = op.getopnum()
-        if (opnum == rop.SETFIELD_GC or
-            opnum == rop.SETFIELD_RAW or
-            opnum == rop.SETARRAYITEM_GC or
-            opnum == rop.SETARRAYITEM_RAW or
-            opnum == rop.DEBUG_MERGE_POINT):
+        if (opnum == rop.SETFIELD_GC or        # handled specially
+            opnum == rop.SETFIELD_RAW or       # no effect on GC struct/array
+            opnum == rop.SETARRAYITEM_GC or    # handled specially
+            opnum == rop.SETARRAYITEM_RAW or   # no effect on GC struct
+            opnum == rop.STRSETITEM or         # no effect on GC struct/array
+            opnum == rop.UNICODESETITEM or     # no effect on GC struct/array
+            opnum == rop.DEBUG_MERGE_POINT or  # no effect whatsoever
+            opnum == rop.COPYSTRCONTENT or     # no effect on GC struct/array
+            opnum == rop.COPYUNICODECONTENT):  # no effect on GC struct/array
             return
         assert opnum != rop.CALL_PURE
         if (opnum == rop.CALL or
@@ -179,8 +246,8 @@
                 for fielddescr in effectinfo.write_descrs_fields:
                     self.force_lazy_setfield(fielddescr)
                     try:
-                        del self.cached_fields[fielddescr]
-                        del self.known_heap_fields[fielddescr]
+                        cf = self.cached_fields[fielddescr]
+                        cf._cached_fields.clear()
                     except KeyError:
                         pass
                 for arraydescr in effectinfo.write_descrs_arrays:
@@ -194,10 +261,7 @@
                     # ^^^ we only need to force this field; the other fields
                     # of virtualref_info and virtualizable_info are not gcptrs.
                 return
-            self.force_all_lazy_setfields()
-        elif op.is_final() or (not we_are_translated() and
-                               op.getopnum() < 0):   # escape() operations
-            self.force_all_lazy_setfields()
+        self.force_all_lazy_setfields()
         self.clean_caches()
 
 
@@ -205,58 +269,54 @@
         assert value.is_constant()
         newvalue = self.getvalue(value.box)
         if value is not newvalue:
-            for d in self.cached_fields.values():
-                if value in d:
-                    d[newvalue] = d[value]
-        # FIXME: Update the other caches too?
-        
-        
-    def force_lazy_setfield(self, descr, before_guard=False):
+            for cf in self.cached_fields.itervalues():
+                if value in cf._cached_fields:
+                    cf._cached_fields[newvalue] = cf._cached_fields[value]
+
+    def force_lazy_setfield(self, descr):
         try:
-            op = self.lazy_setfields[descr]
+            cf = self.cached_fields[descr]
         except KeyError:
             return
-        del self.lazy_setfields[descr]
-        value = self.getvalue(op.getarg(0))
-        fieldvalue = self.getvalue(op.getarg(1))
-        try:
-            heapvalue = self.known_heap_fields[op.getdescr()][value]
-            if fieldvalue is heapvalue:
-                return
-        except KeyError:
-            pass
-        self.next_optimization.propagate_forward(op)
+        cf.force_lazy_setfield(self)
 
+    def fixup_guard_situation(self):
         # hackish: reverse the order of the last two operations if it makes
         # sense to avoid a situation like "int_eq/setfield_gc/guard_true",
         # which the backend (at least the x86 backend) does not handle well.
         newoperations = self.optimizer.newoperations
-        if before_guard and len(newoperations) >= 2:
-            lastop = newoperations[-1]
-            prevop = newoperations[-2]
-            # - is_comparison() for cases like "int_eq/setfield_gc/guard_true"
-            # - CALL_MAY_FORCE: "call_may_force/setfield_gc/guard_not_forced"
-            # - is_ovf(): "int_add_ovf/setfield_gc/guard_no_overflow"
-            opnum = prevop.getopnum()
-            lastop_args = lastop.getarglist()
-            if ((prevop.is_comparison() or opnum == rop.CALL_MAY_FORCE
-                 or prevop.is_ovf())
-                and prevop.result not in lastop_args):
-                newoperations[-2] = lastop
-                newoperations[-1] = prevop
+        if len(newoperations) < 2:
+            return
+        lastop = newoperations[-1]
+        if (lastop.getopnum() != rop.SETFIELD_GC and
+            lastop.getopnum() != rop.SETARRAYITEM_GC):
+            return
+        # - is_comparison() for cases like "int_eq/setfield_gc/guard_true"
+        # - CALL_MAY_FORCE: "call_may_force/setfield_gc/guard_not_forced"
+        # - is_ovf(): "int_add_ovf/setfield_gc/guard_no_overflow"
+        prevop = newoperations[-2]
+        opnum = prevop.getopnum()
+        if not (prevop.is_comparison() or opnum == rop.CALL_MAY_FORCE
+                or prevop.is_ovf()):
+            return
+        if prevop.result in lastop.getarglist():
+            return
+        newoperations[-2] = lastop
+        newoperations[-1] = prevop
 
     def force_all_lazy_setfields(self):
-        if len(self.lazy_setfields_descrs) > 0:
-            for descr in self.lazy_setfields_descrs:
-                self.force_lazy_setfield(descr)
-            del self.lazy_setfields_descrs[:]
+        for cf in self._lazy_setfields:
+            if not we_are_translated():
+                assert cf in self.cached_fields.values()
+            cf.force_lazy_setfield(self)
 
     def force_lazy_setfields_for_guard(self):
         pendingfields = []
-        for descr in self.lazy_setfields_descrs:
-            try:
-                op = self.lazy_setfields[descr]
-            except KeyError:
+        for cf in self._lazy_setfields:
+            if not we_are_translated():
+                assert cf in self.cached_fields.values()
+            op = cf._lazy_setfield
+            if op is None:
                 continue
             # the only really interesting case that we need to handle in the
             # guards' resume data is that of a virtual object that is stored
@@ -266,41 +326,27 @@
             fieldvalue = self.getvalue(op.getarg(1))
             if fieldvalue.is_virtual():
                 # this is the case that we leave to resume.py
-                pendingfields.append((descr, value.box,
+                pendingfields.append((op.getdescr(), value.box,
                                       fieldvalue.get_key_box()))
             else:
-                self.force_lazy_setfield(descr, before_guard=True)
+                cf.force_lazy_setfield(self)
+                self.fixup_guard_situation()
         return pendingfields
 
-    def force_lazy_setfield_if_necessary(self, op, value, write=False):
-        try:
-            op1 = self.lazy_setfields[op.getdescr()]
-        except KeyError:
-            if write:
-                self.lazy_setfields_descrs.append(op.getdescr())
-        else:
-            if self.getvalue(op1.getarg(0)) is not value:
-                self.force_lazy_setfield(op.getdescr())
-
     def optimize_GETFIELD_GC(self, op):
-        value = self.getvalue(op.getarg(0))
-        self.force_lazy_setfield_if_necessary(op, value)
-        # check if the field was read from another getfield_gc just before
-        # or has been written to recently
-        fieldvalue = self.read_cached_field(op.getdescr(), value)
+        structvalue = self.getvalue(op.getarg(0))
+        cf = self.field_cache(op.getdescr())
+        fieldvalue = cf.getfield_from_cache(self, structvalue)
         if fieldvalue is not None:
             self.make_equal_to(op.result, fieldvalue)
             return
         # default case: produce the operation
-        value.ensure_nonnull()
+        structvalue.ensure_nonnull()
         ###self.optimizer.optimize_default(op)
         self.emit_operation(op)
         # then remember the result of reading the field
         fieldvalue = self.getvalue(op.result)
-        self.cache_field_value(op.getdescr(), value, fieldvalue)
-        # keep track of what's on the heap
-        d = self.known_heap_fields.setdefault(op.getdescr(), {})
-        d[value] = fieldvalue
+        cf.remember_field_value(structvalue, fieldvalue)
 
     def optimize_SETFIELD_GC(self, op):
         if self.has_pure_result(rop.GETFIELD_GC_PURE, [op.getarg(0)],
@@ -309,14 +355,8 @@
                      (op.getdescr().repr_of_descr()))
             raise BogusPureField
         #
-        value = self.getvalue(op.getarg(0))
-        fieldvalue = self.getvalue(op.getarg(1))
-        cached_fieldvalue = self.read_cached_field(op.getdescr(), value)
-        if fieldvalue is not cached_fieldvalue:
-            self.force_lazy_setfield_if_necessary(op, value, write=True)
-            self.lazy_setfields[op.getdescr()] = op
-            # remember the result of future reads of the field
-            self.cache_field_value(op.getdescr(), value, fieldvalue, write=True)
+        cf = self.field_cache(op.getdescr())
+        cf.do_setfield(self, op)
 
     def optimize_GETARRAYITEM_GC(self, op):
         value = self.getvalue(op.getarg(0))

diff --git a/pypy/module/cpyext/funcobject.py b/pypy/module/cpyext/funcobject.py
--- a/pypy/module/cpyext/funcobject.py
+++ b/pypy/module/cpyext/funcobject.py
@@ -14,6 +14,10 @@
     (("func_name", PyObject),)
 cpython_struct("PyFunctionObject", PyFunctionObjectFields, PyFunctionObjectStruct)
 
+PyCodeObjectStruct = lltype.ForwardReference()
+PyCodeObject = lltype.Ptr(PyCodeObjectStruct)
+cpython_struct("PyCodeObject", PyObjectFields, PyCodeObjectStruct)
+
 @bootstrap_function
 def init_functionobject(space):
     make_typedescr(Function.typedef,
@@ -65,7 +69,36 @@
     assert isinstance(w_method, Method)
     return borrow_from(w_method, w_method.w_class)
 
- at cpython_api([CONST_STRING, CONST_STRING, rffi.INT_real], PyObject)
+def unwrap_list_of_strings(space, w_list):
+    return [space.str_w(w_item) for w_item in space.fixedview(w_list)]
+
+ at cpython_api([rffi.INT_real, rffi.INT_real, rffi.INT_real, rffi.INT_real,
+              PyObject, PyObject, PyObject, PyObject, PyObject, PyObject,
+              PyObject, PyObject, rffi.INT_real, PyObject], PyCodeObject)
+def PyCode_New(space, argcount, nlocals, stacksize, flags,
+               w_code, w_consts, w_names, w_varnames, w_freevars, w_cellvars,
+               w_filename, w_funcname, firstlineno, w_lnotab):
+    """Return a new code object.  If you need a dummy code object to
+    create a frame, use PyCode_NewEmpty() instead.  Calling
+    PyCode_New() directly can bind you to a precise Python
+    version since the definition of the bytecode changes often."""
+    return space.wrap(PyCode(space,
+                             argcount=rffi.cast(lltype.Signed, argcount),
+                             nlocals=rffi.cast(lltype.Signed, nlocals),
+                             stacksize=rffi.cast(lltype.Signed, stacksize),
+                             flags=rffi.cast(lltype.Signed, flags),
+                             code=space.str_w(w_code),
+                             consts=space.fixedview(w_consts),
+                             names=unwrap_list_of_strings(space, w_names),
+                             varnames=unwrap_list_of_strings(space, w_varnames),
+                             filename=space.str_w(w_filename),
+                             name=space.str_w(w_funcname),
+                             firstlineno=rffi.cast(lltype.Signed, firstlineno),
+                             lnotab=space.str_w(w_lnotab),
+                             freevars=unwrap_list_of_strings(space, w_freevars),
+                             cellvars=unwrap_list_of_strings(space, w_cellvars)))
+
+ at cpython_api([CONST_STRING, CONST_STRING, rffi.INT_real], PyCodeObject)
 def PyCode_NewEmpty(space, filename, funcname, firstlineno):
     """Creates a new empty code object with the specified source location."""
     return space.wrap(PyCode(space,

diff --git a/pypy/translator/c/src/dtoa.c b/pypy/translator/c/src/dtoa.c
--- a/pypy/translator/c/src/dtoa.c
+++ b/pypy/translator/c/src/dtoa.c
@@ -116,7 +116,6 @@
 
 /* Begin PYPY hacks */
 /* #include "Python.h" */
-#define DOUBLE_IS_LITTLE_ENDIAN_IEEE754
 #define HAVE_UINT32_T
 #define HAVE_INT32_T
 #define HAVE_UINT64_T

diff --git a/pypy/module/imp/interp_imp.py b/pypy/module/imp/interp_imp.py
--- a/pypy/module/imp/interp_imp.py
+++ b/pypy/module/imp/interp_imp.py
@@ -126,8 +126,16 @@
     _run_compiled_module(space, w_modulename, filename, w_file, w_mod)
     return w_mod
 
+ at unwrap_spec(filename=str)
+def load_dynamic(space, w_modulename, filename, w_file=None):
+    if not space.config.objspace.usemodules.cpyext:
+        raise OperationError(space.w_ImportError, space.wrap(
+            "Not implemented"))
+    importing.load_c_extension(space, filename, space.str_w(w_modulename))
+    return importing.check_sys_modules(space, w_modulename)
+
 def new_module(space, w_name):
-    return space.wrap(Module(space, w_name))
+    return space.wrap(Module(space, w_name, add_package=False))
 
 def init_builtin(space, w_name):
     name = space.str_w(w_name)

diff --git a/pypy/module/pyexpat/interp_pyexpat.py b/pypy/module/pyexpat/interp_pyexpat.py
--- a/pypy/module/pyexpat/interp_pyexpat.py
+++ b/pypy/module/pyexpat/interp_pyexpat.py
@@ -253,8 +253,10 @@
     except OperationError, e:
         parser._exc_info = e
         XML_StopParser(parser.itself, XML_FALSE)
-        return 0
-    return 1
+        result = 0
+    else:
+        result = 1
+    return rffi.cast(rffi.INT, result)
 callback_type = lltype.Ptr(lltype.FuncType(
     [rffi.VOIDP, rffi.CCHARP, XML_Encoding_Ptr], rffi.INT))
 XML_SetUnknownEncodingHandler = expat_external(

diff --git a/pypy/rpython/lltypesystem/module/ll_math.py b/pypy/rpython/lltypesystem/module/ll_math.py
--- a/pypy/rpython/lltypesystem/module/ll_math.py
+++ b/pypy/rpython/lltypesystem/module/ll_math.py
@@ -6,7 +6,7 @@
 from pypy.rpython.lltypesystem import lltype, rffi
 from pypy.tool.sourcetools import func_with_new_name
 from pypy.tool.autopath import pypydir
-from pypy.rlib import rposix
+from pypy.rlib import jit, rposix
 from pypy.translator.tool.cbuild import ExternalCompilationInfo
 from pypy.rlib.rfloat import isinf, isnan, INFINITY, NAN
 
@@ -20,8 +20,7 @@
         separate_module_files=[cdir.join('src', 'll_math.c')],
         export_symbols=['_pypy_math_acosh', '_pypy_math_asinh',
                         '_pypy_math_atanh',
-                        '_pypy_math_expm1', '_pypy_math_log1p',
-                        '_pypy_math_isinf', '_pypy_math_isnan'],
+                        '_pypy_math_expm1', '_pypy_math_log1p'],
         )
     math_prefix = '_pypy_math_'
 else:
@@ -57,8 +56,6 @@
 math_fmod  = llexternal('fmod',  [rffi.DOUBLE, rffi.DOUBLE], rffi.DOUBLE)
 math_hypot = llexternal(underscore + 'hypot',
                         [rffi.DOUBLE, rffi.DOUBLE], rffi.DOUBLE)
-math_isinf = math_llexternal('isinf', [rffi.DOUBLE], rffi.INT)
-math_isnan = math_llexternal('isnan', [rffi.DOUBLE], rffi.INT)
 
 # ____________________________________________________________
 #
@@ -91,13 +88,13 @@
 #
 # Custom implementations
 
-
 def ll_math_isnan(y):
-    return bool(math_isnan(y))
-
+    # By not calling into the extenal function the JIT can inline this.  Floats
+    # are awesome.
+    return y != y
 
 def ll_math_isinf(y):
-    return bool(math_isinf(y))
+    return y != 0 and y * .5 == y
 
 
 ll_math_copysign = math_copysign

diff --git a/pypy/module/thread/os_thread.py b/pypy/module/thread/os_thread.py
--- a/pypy/module/thread/os_thread.py
+++ b/pypy/module/thread/os_thread.py
@@ -248,3 +248,8 @@
     """This is synonymous to ``raise SystemExit''.  It will cause the current
 thread to exit silently unless the exception is caught."""
     raise OperationError(space.w_SystemExit, space.w_None)
+
+def interrupt_main(space):
+    """Raise a KeyboardInterrupt in the main thread.
+A subthread can use this function to interrupt the main thread."""
+    space.check_signal_action.set_interrupt()

diff --git a/pypy/module/imp/app_imp.py b/pypy/module/imp/app_imp.py
deleted file mode 100644
--- a/pypy/module/imp/app_imp.py
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-def load_dynamic(name, pathname, file=None):
-    """Always raises ah ImportError on pypy"""
-    raise ImportError('Not implemented')

diff --git a/pypy/interpreter/gateway.py b/pypy/interpreter/gateway.py
--- a/pypy/interpreter/gateway.py
+++ b/pypy/interpreter/gateway.py
@@ -1126,7 +1126,7 @@
     """
     if not isinstance(source, str):
         source = py.std.inspect.getsource(source).lstrip()
-        while source.startswith('@py.test.mark.'):
+        while source.startswith(('@py.test.mark.', '@pytest.mark.')):
             # these decorators are known to return the same function
             # object, we may ignore them
             assert '\n' in source

diff --git a/pypy/module/cpyext/longobject.py b/pypy/module/cpyext/longobject.py
--- a/pypy/module/cpyext/longobject.py
+++ b/pypy/module/cpyext/longobject.py
@@ -5,6 +5,7 @@
 from pypy.interpreter.error import OperationError
 from pypy.module.cpyext.intobject import PyInt_AsUnsignedLongMask
 from pypy.rlib.rbigint import rbigint
+from pypy.rlib.rarithmetic import intmask
 
 
 PyLong_Check, PyLong_CheckExact = build_type_checkers("Long")
@@ -178,9 +179,9 @@
     assert isinstance(w_long, W_LongObject)
     return w_long.num.sign
 
- at cpython_api([CONST_STRING, rffi.SIZE_T, rffi.INT_real, rffi.INT_real], PyObject)
+UCHARP = rffi.CArrayPtr(rffi.UCHAR)
+ at cpython_api([UCHARP, rffi.SIZE_T, rffi.INT_real, rffi.INT_real], PyObject)
 def _PyLong_FromByteArray(space, bytes, n, little_endian, signed):
-    s = rffi.charpsize2str(bytes, n)
     little_endian = rffi.cast(lltype.Signed, little_endian)
     signed = rffi.cast(lltype.Signed, signed)
 
@@ -189,9 +190,9 @@
 
     for i in range(0, n):
         if little_endian:
-            c = ord(s[i])
+            c = intmask(bytes[i])
         else:
-            c = ord(s[n - i - 1])
+            c = intmask(bytes[n - i - 1])
         if i == 0 and signed and c & 0x80:
             negative = True
         if negative:


diff --git a/pypy/jit/tl/tla/test_tla.py b/pypy/jit/tl/tla/test_tla.py
--- a/pypy/jit/tl/tla/test_tla.py
+++ b/pypy/jit/tl/tla/test_tla.py
@@ -155,7 +155,7 @@
 
 # ____________________________________________________________
 
-from pypy.jit.metainterp.test.test_basic import LLJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin
 
 class TestLLtype(LLJitMixin):
     def test_loop(self):

diff --git a/pypy/interpreter/test/test_extmodules.py b/pypy/interpreter/test/test_extmodules.py
new file mode 100644
--- /dev/null
+++ b/pypy/interpreter/test/test_extmodules.py
@@ -0,0 +1,68 @@
+import sys
+import pytest
+
+from pypy.config.pypyoption import get_pypy_config
+from pypy.objspace.std import StdObjSpace
+from pypy.tool.udir import udir
+
+mod_init = """
+from pypy.interpreter.mixedmodule import MixedModule
+
+import time
+
+class Module(MixedModule):
+
+    appleveldefs = {}
+
+    interpleveldefs = {
+    'clock'    : 'interp_time.clock',
+    'time'     : 'interp_time.time_',
+    'sleep'    : 'interp_time.sleep',
+    }
+"""
+
+mod_interp = """
+import time
+
+from pypy.interpreter.gateway import unwrap_spec
+
+def clock(space):
+    return space.wrap(time.clock())
+
+def time_(space):
+    return space.wrap(time.time())
+
+ at unwrap_spec(seconds=float)
+def sleep(space, seconds):
+    time.sleep(seconds)
+"""
+
+old_sys_path = []
+
+def init_extmodule_code():
+    pkg = udir.join("testext")
+    pkg.ensure(dir=True)
+    pkg.join("__init__.py").write("# package")
+    mod = pkg.join("extmod")
+    mod.ensure(dir=True)
+    mod.join("__init__.py").write(mod_init)
+    mod.join("interp_time.py").write(mod_interp)
+
+class AppTestExtModules(object):
+    def setup_class(cls):
+        init_extmodule_code()
+        conf = get_pypy_config()
+        conf.objspace.extmodules = 'testext.extmod'
+        old_sys_path[:] = sys.path[:]
+        sys.path.insert(0, str(udir))
+        space = StdObjSpace(conf)
+        cls.space = space
+
+    def teardown_class(cls):
+        sys.path[:] = old_sys_path
+
+    @pytest.mark.skipif("config.option.runappdirect")
+    def test_import(self):
+        import extmod
+        assert extmod.__file__.endswith('extmod')
+        assert type(extmod.time()) is float

diff --git a/pypy/tool/jitlogparser/test/test_parser.py b/pypy/tool/jitlogparser/test/test_parser.py
--- a/pypy/tool/jitlogparser/test/test_parser.py
+++ b/pypy/tool/jitlogparser/test/test_parser.py
@@ -114,11 +114,11 @@
     fname = str(py.path.local(__file__).join('..', 'x.py'))
     ops = parse('''
     [i0, i1]
-    debug_merge_point("<code object f, file '%(fname)s', line 5> #9 LOAD_FAST", 0)
-    debug_merge_point("<code object f, file '%(fname)s', line 5> #12 LOAD_CONST", 0)
-    debug_merge_point("<code object f, file '%(fname)s', line 5> #22 LOAD_CONST", 0)
-    debug_merge_point("<code object f, file '%(fname)s', line 5> #28 LOAD_CONST", 0)
-    debug_merge_point("<code object f, file '%(fname)s', line 5> #6 SETUP_LOOP", 0)
+    debug_merge_point("<code object g, file '%(fname)s', line 5> #9 LOAD_FAST", 0)
+    debug_merge_point("<code object g, file '%(fname)s', line 5> #12 LOAD_CONST", 0)
+    debug_merge_point("<code object g, file '%(fname)s', line 5> #22 LOAD_CONST", 0)
+    debug_merge_point("<code object g, file '%(fname)s', line 5> #28 LOAD_CONST", 0)
+    debug_merge_point("<code object g, file '%(fname)s', line 5> #6 SETUP_LOOP", 0)
     ''' % locals())
     res = Function.from_operations(ops.operations, LoopStorage())
     assert res.linerange == (7, 9)

diff --git a/pypy/tool/pytest/appsupport.py b/pypy/tool/pytest/appsupport.py
--- a/pypy/tool/pytest/appsupport.py
+++ b/pypy/tool/pytest/appsupport.py
@@ -196,7 +196,7 @@
     class _ExceptionInfo(object):
         def __init__(self):
             import sys
-            self.type, self.value, _ = sys.exc_info()
+            self.type, self.value, self.traceback = sys.exc_info()
 
     return _ExceptionInfo
 """)    


diff --git a/pypy/module/cpyext/frameobject.py b/pypy/module/cpyext/frameobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/frameobject.py
@@ -0,0 +1,82 @@
+from pypy.rpython.lltypesystem import rffi, lltype
+from pypy.module.cpyext.api import (
+    cpython_api, bootstrap_function, PyObjectFields, cpython_struct)
+from pypy.module.cpyext.pyobject import (
+    PyObject, Py_DecRef, make_ref, from_ref, track_reference,
+    make_typedescr, get_typedescr)
+from pypy.module.cpyext.state import State
+from pypy.module.cpyext.pystate import PyThreadState
+from pypy.module.cpyext.funcobject import PyCodeObject
+from pypy.interpreter.pyframe import PyFrame
+from pypy.interpreter.pycode import PyCode
+
+PyFrameObjectStruct = lltype.ForwardReference()
+PyFrameObject = lltype.Ptr(PyFrameObjectStruct)
+PyFrameObjectFields = (PyObjectFields +
+    (("f_code", PyCodeObject),
+     ("f_globals", PyObject),
+     ("f_lineno", rffi.INT),
+     ))
+cpython_struct("PyFrameObject", PyFrameObjectFields, PyFrameObjectStruct)
+
+ at bootstrap_function
+def init_frameobject(space):
+    make_typedescr(PyFrame.typedef,
+                   basestruct=PyFrameObject.TO,
+                   attach=frame_attach,
+                   dealloc=frame_dealloc,
+                   realize=frame_realize)
+
+def frame_attach(space, py_obj, w_obj):
+    "Fills a newly allocated PyFrameObject with a frame object"
+    frame = space.interp_w(PyFrame, w_obj)
+    py_frame = rffi.cast(PyFrameObject, py_obj)
+    py_frame.c_f_code = rffi.cast(PyCodeObject, make_ref(space, frame.pycode))
+    py_frame.c_f_globals = make_ref(space, frame.w_globals)
+    rffi.setintfield(py_frame, 'c_f_lineno', frame.f_lineno)
+
+ at cpython_api([PyObject], lltype.Void, external=False)
+def frame_dealloc(space, py_obj):
+    py_frame = rffi.cast(PyFrameObject, py_obj)
+    py_code = rffi.cast(PyObject, py_frame.c_f_code)
+    Py_DecRef(space, py_code)
+    Py_DecRef(space, py_frame.c_f_globals)
+    from pypy.module.cpyext.object import PyObject_dealloc
+    PyObject_dealloc(space, py_obj)
+
+def frame_realize(space, py_obj):
+    """
+    Creates the frame in the interpreter. The PyFrameObject structure must not
+    be modified after this call.
+    """
+    py_frame = rffi.cast(PyFrameObject, py_obj)
+    py_code = rffi.cast(PyObject, py_frame.c_f_code)
+    w_code = from_ref(space, py_code)
+    code = space.interp_w(PyCode, w_code)
+    w_globals = from_ref(space, py_frame.c_f_globals)
+
+    frame = PyFrame(space, code, w_globals, closure=None)
+    frame.f_lineno = py_frame.c_f_lineno
+    w_obj = space.wrap(frame)
+    track_reference(space, py_obj, w_obj)
+    return w_obj
+
+ at cpython_api([PyThreadState, PyCodeObject, PyObject, PyObject], PyFrameObject)
+def PyFrame_New(space, tstate, w_code, w_globals, w_locals):
+    typedescr = get_typedescr(PyFrame.typedef)
+    py_obj = typedescr.allocate(space, space.gettypeobject(PyFrame.typedef))
+    py_frame = rffi.cast(PyFrameObject, py_obj)
+    space.interp_w(PyCode, w_code) # sanity check
+    py_frame.c_f_code = rffi.cast(PyCodeObject, make_ref(space, w_code))
+    py_frame.c_f_globals = make_ref(space, w_globals)
+    return py_frame
+
+ at cpython_api([PyFrameObject], rffi.INT_real, error=-1)
+def PyTraceBack_Here(space, w_frame):
+    from pypy.interpreter.pytraceback import record_application_traceback
+    state = space.fromcache(State)
+    if state.operror is None:
+        return -1
+    frame = space.interp_w(PyFrame, w_frame)
+    record_application_traceback(space, state.operror, frame, 0)
+    return 0

diff --git a/pypy/jit/backend/x86/runner.py b/pypy/jit/backend/x86/runner.py
--- a/pypy/jit/backend/x86/runner.py
+++ b/pypy/jit/backend/x86/runner.py
@@ -19,6 +19,8 @@
 
     def __init__(self, rtyper, stats, opts=None, translate_support_code=False,
                  gcdescr=None):
+        if gcdescr is not None:
+            gcdescr.force_index_ofs = FORCE_INDEX_OFS
         AbstractLLCPU.__init__(self, rtyper, stats, opts,
                                translate_support_code, gcdescr)
 
@@ -127,7 +129,7 @@
         fail_index = rffi.cast(TP, addr_of_force_index)[0]
         assert fail_index >= 0, "already forced!"
         faildescr = self.get_fail_descr_from_number(fail_index)
-        rffi.cast(TP, addr_of_force_index)[0] = -1
+        rffi.cast(TP, addr_of_force_index)[0] = ~fail_index
         frb = self.assembler._find_failure_recovery_bytecode(faildescr)
         bytecode = rffi.cast(rffi.UCHARP, frb)
         # start of "no gc operation!" block
@@ -147,7 +149,6 @@
     WORD = 4
     NUM_REGS = 8
     CALLEE_SAVE_REGISTERS = [regloc.ebx, regloc.esi, regloc.edi]
-    FRAME_FIXED_SIZE = len(CALLEE_SAVE_REGISTERS) + 2
 
     supports_longlong = True
 
@@ -163,7 +164,6 @@
     WORD = 8
     NUM_REGS = 16
     CALLEE_SAVE_REGISTERS = [regloc.ebx, regloc.r12, regloc.r13, regloc.r14, regloc.r15]
-    FRAME_FIXED_SIZE = len(CALLEE_SAVE_REGISTERS) + 2
 
     def __init__(self, *args, **kwargs):
         assert sys.maxint == (2**63 - 1)

diff --git a/pypy/jit/metainterp/test/test_compile.py b/pypy/jit/metainterp/test/test_compile.py
--- a/pypy/jit/metainterp/test/test_compile.py
+++ b/pypy/jit/metainterp/test/test_compile.py
@@ -86,6 +86,8 @@
     metainterp.history = History()
     metainterp.history.operations = loop.operations[:]
     metainterp.history.inputargs = loop.inputargs[:]
+    cpu._all_size_descrs_with_vtable = (
+        LLtypeMixin.cpu._all_size_descrs_with_vtable)
     #
     loop_tokens = []
     loop_token = compile_new_loop(metainterp, loop_tokens, [], 0, None)

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
@@ -3,7 +3,7 @@
 from pypy.rlib.jit import unroll_safe, dont_look_inside
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.debug import fatalerror
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.jit.codewriter.policy import StopAtXPolicy
 from pypy.rpython.annlowlevel import hlstr
 from pypy.jit.metainterp.warmspot import get_stats

diff --git a/pypy/rpython/lltypesystem/lloperation.py b/pypy/rpython/lltypesystem/lloperation.py
--- a/pypy/rpython/lltypesystem/lloperation.py
+++ b/pypy/rpython/lltypesystem/lloperation.py
@@ -490,7 +490,9 @@
     # ^^^ returns an address of nursery free pointer, for later modifications
     'gc_adr_of_nursery_top' : LLOp(),
     # ^^^ returns an address of pointer, since it can change at runtime
-    
+    'gc_adr_of_root_stack_top': LLOp(),
+    # ^^^ returns the address of gcdata.root_stack_top (for shadowstack only)
+
     # experimental operations in support of thread cloning, only
     # implemented by the Mark&Sweep GC
     'gc_x_swap_pool':       LLOp(canraise=(MemoryError,), canunwindgc=True),

diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -365,7 +365,11 @@
 
     def setbuiltinmodule(self, importname):
         """NOT_RPYTHON. load a lazy pypy/module and put it into sys.modules"""
-        fullname = "pypy.module.%s" % importname
+        if '.' in importname:
+            fullname = importname
+            importname = fullname.rsplit('.', 1)[1]
+        else:
+            fullname = "pypy.module.%s" % importname
 
         Module = __import__(fullname,
                             None, None, ["Module"]).Module
@@ -428,6 +432,11 @@
             if value and name not in modules:
                 modules.append(name)
 
+        if self.config.objspace.extmodules:
+            for name in self.config.objspace.extmodules.split(','):
+                if name not in modules:
+                    modules.append(name)
+
         # a bit of custom logic: time2 or rctime take precedence over time
         # XXX this could probably be done as a "requires" in the config
         if ('time2' in modules or 'rctime' in modules) and 'time' in modules:
@@ -745,7 +754,12 @@
         """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)
-        items = []
+        # If we know the expected length we can preallocate.
+        if expected_length == -1:
+            items = []
+        else:
+            items = [None] * expected_length
+        idx = 0
         while True:
             try:
                 w_item = self.next(w_iterator)
@@ -753,19 +767,22 @@
                 if not e.match(self, self.w_StopIteration):
                     raise
                 break  # done
-            if expected_length != -1 and len(items) == expected_length:
+            if expected_length != -1 and idx == expected_length:
                 raise OperationError(self.w_ValueError,
                                      self.wrap("too many values to unpack"))
-            items.append(w_item)
-        if expected_length != -1 and len(items) < expected_length:
-            i = len(items)
-            if i == 1:
+            if expected_length == -1:
+                items.append(w_item)
+            else:
+                items[idx] = w_item
+            idx += 1
+        if expected_length != -1 and 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" %
-                                (i, plural)))
+                                (idx, plural)))
         return items
 
     unpackiterable_unroll = jit.unroll_safe(func_with_new_name(unpackiterable,
@@ -1333,6 +1350,11 @@
         pass
     def _freeze_(self):
         return True
+    def __enter__(self):
+        pass
+    def __exit__(self, *args):
+        pass
+
 dummy_lock = DummyLock()
 
 ## Table describing the regular part of the interface of object spaces,

diff --git a/pypy/translator/cli/ilgenerator.py b/pypy/translator/cli/ilgenerator.py
--- a/pypy/translator/cli/ilgenerator.py
+++ b/pypy/translator/cli/ilgenerator.py
@@ -443,8 +443,8 @@
             self.ilasm.opcode('newarr', clitype.itemtype.typename())
     
     def _array_suffix(self, ARRAY, erase_unsigned=False):
-        from pypy.translator.cli.metavm import OOTYPE_TO_MNEMONIC
-        suffix = OOTYPE_TO_MNEMONIC.get(ARRAY.ITEM, 'ref')
+        from pypy.translator.cli.metavm import ootype_to_mnemonic
+        suffix = ootype_to_mnemonic(ARRAY.ITEM, ARRAY.ITEM, 'ref')
         if erase_unsigned:
             suffix = suffix.replace('u', 'i')
         return suffix

diff --git a/pypy/module/cpyext/include/code.h b/pypy/module/cpyext/include/code.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/include/code.h
@@ -0,0 +1,12 @@
+#ifndef Py_CODE_H
+#define Py_CODE_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef PyObject PyCodeObject;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_CODE_H */

diff --git a/pypy/translator/backendopt/ssa.py b/pypy/translator/backendopt/ssa.py
--- a/pypy/translator/backendopt/ssa.py
+++ b/pypy/translator/backendopt/ssa.py
@@ -1,4 +1,4 @@
-from pypy.objspace.flow.model import Variable, mkentrymap, flatten, Block
+from pypy.objspace.flow.model import Variable, mkentrymap, Block
 from pypy.tool.algo.unionfind import UnionFind
 
 class DataFlowFamilyBuilder:

diff --git a/pypy/rpython/ootypesystem/rstr.py b/pypy/rpython/ootypesystem/rstr.py
--- a/pypy/rpython/ootypesystem/rstr.py
+++ b/pypy/rpython/ootypesystem/rstr.py
@@ -211,8 +211,11 @@
     def ll_stringslice_minusone(s):
         return s.ll_substring(0, s.ll_strlen()-1)
 
-    def ll_split_chr(RESULT, s, c):
-        return RESULT.ll_convert_from_array(s.ll_split_chr(c))
+    def ll_split_chr(RESULT, s, c, max):
+        return RESULT.ll_convert_from_array(s.ll_split_chr(c, max))
+
+    def ll_rsplit_chr(RESULT, s, c, max):
+        return RESULT.ll_convert_from_array(s.ll_rsplit_chr(c, max))
 
     def ll_int(s, base):
         if not 2 <= base <= 36:

diff --git a/lib_pypy/pyrepl/reader.py b/lib_pypy/pyrepl/reader.py
--- a/lib_pypy/pyrepl/reader.py
+++ b/lib_pypy/pyrepl/reader.py
@@ -274,8 +274,12 @@
                         screeninfo.append((0, []))
                 self.lxy = p, ln
             prompt = self.get_prompt(ln, ll >= p >= 0)
+            while '\n' in prompt:
+                pre_prompt, _, prompt = prompt.partition('\n')
+                screen.append(pre_prompt)
+                screeninfo.append((0, []))
             p -= ll + 1
-            lp = len(prompt)
+            prompt, lp = self.process_prompt(prompt)
             l, l2 = disp_str(line)
             wrapcount = (len(l) + lp) / w
             if wrapcount == 0:
@@ -297,6 +301,31 @@
                 screeninfo.append((0, []))
         return screen
 
+    def process_prompt(self, prompt):
+        """ Process the prompt.
+        
+        This means calculate the length of the prompt. The character \x01
+        and \x02 are used to bracket ANSI control sequences and need to be
+        excluded from the length calculation.  So also a copy of the prompt
+        is returned with these control characters removed.  """
+
+        out_prompt = ''
+        l = len(prompt)
+        pos = 0
+        while True:
+            s = prompt.find('\x01', pos)
+            if s == -1:
+                break
+            e = prompt.find('\x02', s)
+            if e == -1:
+                break
+            # Found start and end brackets, subtract from string length
+            l = l - (e-s+1)
+            out_prompt += prompt[pos:s] + prompt[s+1:e]
+            pos = e+1
+        out_prompt += prompt[pos:]
+        return out_prompt, l
+
     def bow(self, p=None):
         """Return the 0-based index of the word break preceding p most
         immediately.

diff --git a/pypy/translator/unsimplify.py b/pypy/translator/unsimplify.py
--- a/pypy/translator/unsimplify.py
+++ b/pypy/translator/unsimplify.py
@@ -54,8 +54,7 @@
 def split_block(annotator, block, index, _forcelink=None):
     """return a link where prevblock is the block leading up but excluding the
     index'th operation and target is a new block with the neccessary variables 
-    passed on.  NOTE: if you call this after rtyping, you WILL need to worry
-    about keepalives, you may use backendopt.support.split_block_with_keepalive.
+    passed on.
     """
     assert 0 <= index <= len(block.operations)
     if block.exitswitch == c_last_exception:
@@ -115,46 +114,6 @@
     # in the second block!
     return split_block(annotator, block, 0, _forcelink=block.inputargs)
 
-def remove_direct_loops(annotator, graph):
-    """This is useful for code generators: it ensures that no link has
-    common input and output variables, which could occur if a block's exit
-    points back directly to the same block.  It allows code generators to be
-    simpler because they don't have to worry about overwriting input
-    variables when generating a sequence of assignments."""
-    def visit(link):
-        if isinstance(link, Link) and link.prevblock is link.target:
-            insert_empty_block(annotator, link)
-    traverse(visit, graph)
-
-def remove_double_links(annotator, graph):
-    """This can be useful for code generators: it ensures that no block has
-    more than one incoming links from one and the same other block. It allows
-    argument passing along links to be implemented with phi nodes since the
-    value of an argument can be determined by looking from which block the
-    control passed. """
-    def visit(block):
-        if isinstance(block, Block):
-            double_links = []
-            seen = {}
-            for link in block.exits:
-                if link.target in seen:
-                    double_links.append(link)
-                seen[link.target] = True
-            for link in double_links:
-                insert_empty_block(annotator, link)
-    traverse(visit, graph)
-
-def no_links_to_startblock(graph):
-    """Ensure no links to start block."""    
-    links_to_start_block = False
-    for block in graph.iterblocks():
-        for link in block.exits:
-            if link.target == graph.startblock:
-                links_to_start_block = True
-                break
-    if links_to_start_block:
-        insert_empty_startblock(None, graph)
-
 def call_initial_function(translator, initial_func, annhelper=None):
     """Before the program starts, call 'initial_func()'."""
     from pypy.annotation import model as annmodel

diff --git a/pypy/module/cpyext/test/test_unicodeobject.py b/pypy/module/cpyext/test/test_unicodeobject.py
--- a/pypy/module/cpyext/test/test_unicodeobject.py
+++ b/pypy/module/cpyext/test/test_unicodeobject.py
@@ -1,9 +1,81 @@
 # encoding: iso-8859-15
 from pypy.module.cpyext.test.test_api import BaseApiTest
-from pypy.module.cpyext.unicodeobject import Py_UNICODE
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from pypy.module.cpyext.unicodeobject import (
+    Py_UNICODE, PyUnicodeObject, new_empty_unicode)
+from pypy.module.cpyext.api import PyObjectP, PyObject
+from pypy.module.cpyext.pyobject import Py_DecRef
 from pypy.rpython.lltypesystem import rffi, lltype
 import sys, py
 
+class AppTestUnicodeObject(AppTestCpythonExtensionBase):
+    def test_unicodeobject(self):
+        module = self.import_extension('foo', [
+            ("get_hello1", "METH_NOARGS",
+             """
+                 return PyUnicode_FromStringAndSize(
+                     "Hello world<should not be included>", 11);
+             """),
+            ("test_GetSize", "METH_NOARGS",
+             """
+                 PyObject* s = PyUnicode_FromString("Hello world");
+                 int result = 0;
+
+                 if(PyUnicode_GetSize(s) == 11) {
+                     result = 1;
+                 }
+                 if(s->ob_type->tp_basicsize != sizeof(void*)*4)
+                     result = 0;
+                 Py_DECREF(s);
+                 return PyBool_FromLong(result);
+             """),
+            ("test_GetSize_exception", "METH_NOARGS",
+             """
+                 PyObject* f = PyFloat_FromDouble(1.0);
+                 Py_ssize_t size = PyUnicode_GetSize(f);
+
+                 Py_DECREF(f);
+                 return NULL;
+             """),
+             ("test_is_unicode", "METH_VARARGS",
+             """
+                return PyBool_FromLong(PyUnicode_Check(PyTuple_GetItem(args, 0)));
+             """)])
+        assert module.get_hello1() == u'Hello world'
+        assert module.test_GetSize()
+        raises(TypeError, module.test_GetSize_exception)
+
+        assert module.test_is_unicode(u"")
+        assert not module.test_is_unicode(())
+
+    def test_unicode_buffer_init(self):
+        module = self.import_extension('foo', [
+            ("getunicode", "METH_NOARGS",
+             """
+                 PyObject *s, *t;
+                 Py_UNICODE* c;
+                 Py_ssize_t len;
+
+                 s = PyUnicode_FromUnicode(NULL, 4);
+                 if (s == NULL)
+                    return NULL;
+                 t = PyUnicode_FromUnicode(NULL, 3);
+                 if (t == NULL)
+                    return NULL;
+                 Py_DECREF(t);
+                 c = PyUnicode_AsUnicode(s);
+                 c[0] = 'a';
+                 c[1] = 0xe9;
+                 c[3] = 'c';
+                 return s;
+             """),
+            ])
+        s = module.getunicode()
+        assert len(s) == 4
+        assert s == u'a&#65533;\x00c'
+
+
+
 class TestUnicode(BaseApiTest):
     def test_unicodeobject(self, space, api):
         assert api.PyUnicode_GET_SIZE(space.wrap(u'sp&#65533;m')) == 4
@@ -77,6 +149,28 @@
         assert space.unwrap(w_res) == u'sp&#65533;'
         rffi.free_charp(s)
 
+    def test_unicode_resize(self, space, api):
+        py_uni = new_empty_unicode(space, 10)
+        ar = lltype.malloc(PyObjectP.TO, 1, flavor='raw')
+        py_uni.c_buffer[0] = u'a'
+        py_uni.c_buffer[1] = u'b'
+        py_uni.c_buffer[2] = u'c'
+        ar[0] = rffi.cast(PyObject, py_uni)
+        api.PyUnicode_Resize(ar, 3)
+        py_uni = rffi.cast(PyUnicodeObject, ar[0])
+        assert py_uni.c_size == 3
+        assert py_uni.c_buffer[1] == u'b'
+        assert py_uni.c_buffer[3] == u'\x00'
+        # the same for growing
+        ar[0] = rffi.cast(PyObject, py_uni)
+        api.PyUnicode_Resize(ar, 10)
+        py_uni = rffi.cast(PyUnicodeObject, ar[0])
+        assert py_uni.c_size == 10
+        assert py_uni.c_buffer[1] == 'b'
+        assert py_uni.c_buffer[10] == '\x00'
+        Py_DecRef(space, ar[0])
+        lltype.free(ar, flavor='raw')
+
     def test_AsUTF8String(self, space, api):
         w_u = space.wrap(u'sp&#65533;m')
         w_res = api.PyUnicode_AsUTF8String(w_u)
@@ -235,13 +329,13 @@
 
         x_chunk = api.PyUnicode_AS_UNICODE(w_x)
         api.Py_UNICODE_COPY(target_chunk, x_chunk, 4)
-        w_y = api.PyUnicode_FromUnicode(target_chunk, 4)
+        w_y = space.wrap(rffi.wcharpsize2unicode(target_chunk, 4))
 
         assert space.eq_w(w_y, space.wrap(u"abcd"))
 
         size = api.PyUnicode_GET_SIZE(w_x)
         api.Py_UNICODE_COPY(target_chunk, x_chunk, size)
-        w_y = api.PyUnicode_FromUnicode(target_chunk, size)
+        w_y = space.wrap(rffi.wcharpsize2unicode(target_chunk, size))
 
         assert space.eq_w(w_y, w_x)
 

diff --git a/pypy/objspace/std/listobject.py b/pypy/objspace/std/listobject.py
--- a/pypy/objspace/std/listobject.py
+++ b/pypy/objspace/std/listobject.py
@@ -36,29 +36,35 @@
 init_defaults = Defaults([None])
 
 def init__List(space, w_list, __args__):
+    from pypy.objspace.std.tupleobject import W_TupleObject
     # this is on the silly side
     w_iterable, = __args__.parse_obj(
             None, 'list', init_signature, init_defaults)
-    #
-    # this is the old version of the loop at the end of this function:
-    #
-    #   w_list.wrappeditems = space.unpackiterable(w_iterable)
-    #
-    # This is commented out to avoid assigning a new RPython list to
-    # 'wrappeditems', which defeats the W_FastSeqIterObject optimization.
-    #
     items_w = w_list.wrappeditems
     del items_w[:]
     if w_iterable is not None:
-        w_iterator = space.iter(w_iterable)
-        while True:
-            try:
-                w_item = space.next(w_iterator)
-            except OperationError, e:
-                if not e.match(space, space.w_StopIteration):
-                    raise
-                break  # done
-            items_w.append(w_item)
+        # unfortunately this is duplicating space.unpackiterable to avoid
+        # assigning a new RPython list to 'wrappeditems', which defeats the
+        # W_FastSeqIterObject optimization.
+        if isinstance(w_iterable, W_ListObject):
+            items_w.extend(w_iterable.wrappeditems)
+        elif isinstance(w_iterable, W_TupleObject):
+            items_w.extend(w_iterable.wrappeditems)
+        else:
+            _init_from_iterable(space, items_w, w_iterable)
+
+def _init_from_iterable(space, items_w, w_iterable):
+    # in its own function to make the JIT look into init__List
+    # XXX this would need a JIT driver somehow?
+    w_iterator = space.iter(w_iterable)
+    while True:
+        try:
+            w_item = space.next(w_iterator)
+        except OperationError, e:
+            if not e.match(space, space.w_StopIteration):
+                raise
+            break  # done
+        items_w.append(w_item)
 
 def len__List(space, w_list):
     result = len(w_list.wrappeditems)

diff --git a/pypy/module/cpyext/include/compile.h b/pypy/module/cpyext/include/compile.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/include/compile.h
@@ -0,0 +1,13 @@
+#ifndef Py_COMPILE_H
+#define Py_COMPILE_H
+
+#include "code.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_COMPILE_H */

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
@@ -6,7 +6,7 @@
 from pypy.jit.backend.llgraph import runner
 from pypy.jit.metainterp.history import BoxInt
 
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.jit.metainterp.optimizeopt import ALL_OPTS_NAMES
 
 

diff --git a/pypy/doc/conf.py b/pypy/doc/conf.py
--- a/pypy/doc/conf.py
+++ b/pypy/doc/conf.py
@@ -45,9 +45,9 @@
 # built documents.
 #
 # The short X.Y version.
-version = '1.4.1'
+version = '1.5'
 # The full version, including alpha/beta/rc tags.
-release = '1.4.1'
+release = '1.5-alpha'
 
 # The language for content autogenerated by Sphinx. Refer to documentation
 # for a list of supported languages.

diff --git a/pypy/translator/backendopt/test/test_ssa.py b/pypy/translator/backendopt/test/test_ssa.py
--- a/pypy/translator/backendopt/test/test_ssa.py
+++ b/pypy/translator/backendopt/test/test_ssa.py
@@ -1,6 +1,6 @@
 from pypy.translator.backendopt.ssa import *
 from pypy.translator.translator import TranslationContext
-from pypy.objspace.flow.model import flatten, Block, Link, Variable, Constant
+from pypy.objspace.flow.model import Block, Link, Variable, Constant
 from pypy.objspace.flow.model import SpaceOperation
 
 

diff --git a/pypy/module/cpyext/test/test_api.py b/pypy/module/cpyext/test/test_api.py
--- a/pypy/module/cpyext/test/test_api.py
+++ b/pypy/module/cpyext/test/test_api.py
@@ -61,6 +61,12 @@
         except OperationError, e:
             print e.errorstr(self.space)
             raise
+
+        try:
+            del self.space.getexecutioncontext().cpyext_threadstate
+        except AttributeError:
+            pass
+
         if self.check_and_print_leaks():
             assert False, "Test leaks or loses object(s)."
 

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
@@ -23,18 +23,22 @@
         self.fail_descr_list = []
         self.fail_descr_free_list = []
 
+    def reserve_some_free_fail_descr_number(self):
+        lst = self.fail_descr_list
+        if len(self.fail_descr_free_list) > 0:
+            n = self.fail_descr_free_list.pop()
+            assert lst[n] is None
+        else:
+            n = len(lst)
+            lst.append(None)
+        return n
+
     def get_fail_descr_number(self, descr):
         assert isinstance(descr, history.AbstractFailDescr)
         n = descr.index
         if n < 0:
-            lst = self.fail_descr_list
-            if len(self.fail_descr_free_list) > 0:
-                n = self.fail_descr_free_list.pop()
-                assert lst[n] is None
-                lst[n] = descr
-            else:
-                n = len(lst)
-                lst.append(descr)
+            n = self.reserve_some_free_fail_descr_number()
+            self.fail_descr_list[n] = descr
             descr.index = n
         return n
 
@@ -294,6 +298,13 @@
     def record_faildescr_index(self, n):
         self.faildescr_indices.append(n)
 
+    def reserve_and_record_some_faildescr_index(self):
+        # like record_faildescr_index(), but invent and return a new,
+        # unused faildescr index
+        n = self.cpu.reserve_some_free_fail_descr_number()
+        self.record_faildescr_index(n)
+        return n
+
     def compiling_a_bridge(self):
         self.cpu.total_compiled_bridges += 1
         self.bridges_count += 1

diff --git a/pypy/translator/backendopt/inline.py b/pypy/translator/backendopt/inline.py
--- a/pypy/translator/backendopt/inline.py
+++ b/pypy/translator/backendopt/inline.py
@@ -5,7 +5,7 @@
 from pypy.objspace.flow.model import Variable, Constant, Block, Link
 from pypy.objspace.flow.model import SpaceOperation, c_last_exception
 from pypy.objspace.flow.model import FunctionGraph
-from pypy.objspace.flow.model import traverse, mkentrymap, checkgraph
+from pypy.objspace.flow.model import mkentrymap, checkgraph
 from pypy.annotation import model as annmodel
 from pypy.rpython.lltypesystem.lltype import Bool, Signed, typeOf, Void, Ptr
 from pypy.rpython.lltypesystem.lltype import normalizeptr
@@ -13,7 +13,7 @@
 from pypy.rpython import rmodel
 from pypy.tool.algo import sparsemat
 from pypy.translator.backendopt import removenoops
-from pypy.translator.backendopt.support import log, split_block_with_keepalive
+from pypy.translator.backendopt.support import log
 from pypy.translator.unsimplify import split_block
 from pypy.translator.backendopt.support import find_backedges, find_loop_blocks
 from pypy.translator.backendopt.canraise import RaiseAnalyzer
@@ -280,13 +280,6 @@
             self.varmap[var] = copyvar(None, var)
         return self.varmap[var]
 
-    def generate_keepalive(self, *args):
-        from pypy.translator.backendopt.support import generate_keepalive
-        if self.translator.rtyper.type_system.name == 'lltypesystem':
-            return generate_keepalive(*args)
-        else:
-            return []
-
     def passon_vars(self, cache_key):
         if cache_key in self._passon_vars:
             return self._passon_vars[cache_key]
@@ -397,7 +390,6 @@
             for exceptionlink in afterblock.exits[1:]:
                 if exc_match(vtable, exceptionlink.llexitcase):
                     passon_vars = self.passon_vars(link.prevblock)
-                    copiedblock.operations += self.generate_keepalive(passon_vars)
                     copiedlink.target = exceptionlink.target
                     linkargs = self.find_args_in_exceptional_case(
                         exceptionlink, link.prevblock, var_etype, var_evalue, afterblock, passon_vars)
@@ -445,7 +437,6 @@
         del blocks[-1].exits[0].llexitcase
         linkargs = copiedexceptblock.inputargs
         copiedexceptblock.recloseblock(Link(linkargs, blocks[0]))
-        copiedexceptblock.operations += self.generate_keepalive(linkargs)
 
     def do_inline(self, block, index_operation):
         splitlink = split_block(None, block, index_operation)
@@ -457,11 +448,8 @@
         # this copy is created with the method passon_vars
         self.original_passon_vars = [arg for arg in block.exits[0].args
                                          if isinstance(arg, Variable)]
-        n = 0
-        while afterblock.operations[n].opname == 'keepalive':
-            n += 1
-        assert afterblock.operations[n].opname == self.op.opname
-        self.op = afterblock.operations.pop(n)
+        assert afterblock.operations[0].opname == self.op.opname
+        self.op = afterblock.operations.pop(0)
         #vars that need to be passed through the blocks of the inlined function
         linktoinlined = splitlink
         copiedstartblock = self.copy_block(self.graph_to_inline.startblock)
@@ -551,7 +539,6 @@
 
 OP_WEIGHTS = {'same_as': 0,
               'cast_pointer': 0,
-              'keepalive': 0,
               'malloc': 2,
               'yield_current_frame_to_caller': sys.maxint, # XXX bit extreme
               'resume_point': sys.maxint, # XXX bit extreme
@@ -784,5 +771,4 @@
                               call_count_pred=call_count_pred)
         log.inlining('inlined %d callsites.'% (count,))
         for graph in graphs:
-            removenoops.remove_superfluous_keep_alive(graph)
             removenoops.remove_duplicate_casts(graph, translator)

diff --git a/pypy/module/cpyext/test/test_import.py b/pypy/module/cpyext/test/test_import.py
--- a/pypy/module/cpyext/test/test_import.py
+++ b/pypy/module/cpyext/test/test_import.py
@@ -1,5 +1,6 @@
 from pypy.module.cpyext.test.test_api import BaseApiTest
 from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+from pypy.rpython.lltypesystem import rffi, lltype
 
 class TestImport(BaseApiTest):
     def test_import(self, space, api):
@@ -7,6 +8,22 @@
         assert pdb
         assert space.getattr(pdb, space.wrap("pm"))
 
+    def test_addmodule(self, space, api):
+        with rffi.scoped_str2charp("sys") as modname:
+            w_sys = api.PyImport_AddModule(modname)
+        assert w_sys is space.sys
+
+        with rffi.scoped_str2charp("foobar") as modname:
+            w_foobar = api.PyImport_AddModule(modname)
+        assert space.str_w(space.getattr(w_foobar,
+                                         space.wrap('__name__'))) == 'foobar'
+
+    def test_reload(self, space, api):
+        pdb = api.PyImport_Import(space.wrap("pdb"))
+        space.delattr(pdb, space.wrap("set_trace"))
+        pdb = api.PyImport_ReloadModule(pdb)
+        assert space.getattr(pdb, space.wrap("set_trace"))
+
 class AppTestImportLogic(AppTestCpythonExtensionBase):
     def test_import_logic(self):
         skip("leak?")

diff --git a/pypy/module/cpyext/test/test_frameobject.py b/pypy/module/cpyext/test/test_frameobject.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/test/test_frameobject.py
@@ -0,0 +1,66 @@
+from pypy.module.cpyext.test.test_cpyext import AppTestCpythonExtensionBase
+
+class AppTestFrameObject(AppTestCpythonExtensionBase):
+
+    def test_forge_frame(self):
+        module = self.import_extension('foo', [
+            ("raise_exception", "METH_NOARGS",
+             """
+                 PyObject *py_srcfile = PyString_FromString("filename");
+                 PyObject *py_funcname = PyString_FromString("funcname");
+                 PyObject *py_globals = PyDict_New();
+                 PyObject *empty_string = PyString_FromString("");
+                 PyObject *empty_tuple = PyTuple_New(0);
+                 PyCodeObject *py_code;
+                 PyFrameObject *py_frame;
+
+                 py_code = PyCode_New(
+                     0,            /*int argcount,*/
+                     #if PY_MAJOR_VERSION >= 3
+                     0,            /*int kwonlyargcount,*/
+                     #endif
+                     0,            /*int nlocals,*/
+                     0,            /*int stacksize,*/
+                     0,            /*int flags,*/
+                     empty_string, /*PyObject *code,*/
+                     empty_tuple,  /*PyObject *consts,*/
+                     empty_tuple,  /*PyObject *names,*/
+                     empty_tuple,  /*PyObject *varnames,*/
+                     empty_tuple,  /*PyObject *freevars,*/
+                     empty_tuple,  /*PyObject *cellvars,*/
+                     py_srcfile,   /*PyObject *filename,*/
+                     py_funcname,  /*PyObject *name,*/
+                     42,           /*int firstlineno,*/
+                     empty_string  /*PyObject *lnotab*/
+                 );
+
+                 if (!py_code) goto bad;
+                 py_frame = PyFrame_New(
+                     PyThreadState_Get(), /*PyThreadState *tstate,*/
+                     py_code,             /*PyCodeObject *code,*/
+                     py_globals,          /*PyObject *globals,*/
+                     0                    /*PyObject *locals*/
+                 );
+                 if (!py_frame) goto bad;
+                 py_frame->f_lineno = 48; /* Does not work with CPython */
+                 PyErr_SetString(PyExc_ValueError, "error message");
+                 PyTraceBack_Here(py_frame);
+             bad:
+                 Py_XDECREF(py_srcfile);
+                 Py_XDECREF(py_funcname);
+                 Py_XDECREF(empty_string);
+                 Py_XDECREF(empty_tuple);
+                 Py_XDECREF(py_globals);
+                 Py_XDECREF(py_code);
+                 Py_XDECREF(py_frame);
+                 return NULL;
+             """),
+            ])
+        exc = raises(ValueError, module.raise_exception)
+        frame = exc.traceback.tb_frame
+        assert frame.f_code.co_filename == "filename"
+        assert frame.f_code.co_name == "funcname"
+
+        # Cython does not work on CPython as well...
+        assert exc.traceback.tb_lineno == 42 # should be 48
+        assert frame.f_lineno == 42

diff --git a/pypy/module/cpyext/slotdefs.py b/pypy/module/cpyext/slotdefs.py
--- a/pypy/module/cpyext/slotdefs.py
+++ b/pypy/module/cpyext/slotdefs.py
@@ -1,16 +1,20 @@
+from __future__ import with_statement
+
 import re
 
 from pypy.rpython.lltypesystem import rffi, lltype
-from pypy.module.cpyext.api import generic_cpy_call, cpython_api, PyObject
+from pypy.module.cpyext.api import (
+    cpython_api, generic_cpy_call, PyObject, Py_ssize_t)
 from pypy.module.cpyext.typeobjectdefs import (
     unaryfunc, wrapperfunc, ternaryfunc, PyTypeObjectPtr, binaryfunc,
-    getattrfunc, setattrofunc, lenfunc, ssizeargfunc, ssizessizeargfunc,
-    ssizeobjargproc, iternextfunc, initproc, richcmpfunc, hashfunc,
-    descrgetfunc, descrsetfunc, objobjproc)
+    getattrfunc, getattrofunc, setattrofunc, lenfunc, ssizeargfunc,
+    ssizessizeargfunc, ssizeobjargproc, iternextfunc, initproc, richcmpfunc,
+    cmpfunc, hashfunc, descrgetfunc, descrsetfunc, objobjproc, readbufferproc)
 from pypy.module.cpyext.pyobject import from_ref
 from pypy.module.cpyext.pyerrors import PyErr_Occurred
 from pypy.module.cpyext.state import State
 from pypy.interpreter.error import OperationError, operationerrfmt
+from pypy.interpreter.buffer import Buffer as W_Buffer
 from pypy.interpreter.argument import Arguments
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.rlib.objectmodel import specialize
@@ -65,6 +69,12 @@
     finally:
         rffi.free_charp(name_ptr)
 
+def wrap_getattro(space, w_self, w_args, func):
+    func_target = rffi.cast(getattrofunc, func)
+    check_num_args(space, w_args, 1)
+    args_w = space.fixedview(w_args)
+    return generic_cpy_call(space, func_target, w_self, args_w[0])
+
 def wrap_setattr(space, w_self, w_args, func):
     func_target = rffi.cast(setattrofunc, func)
     check_num_args(space, w_args, 2)
@@ -187,18 +197,59 @@
     check_num_args(space, w_args, 0)
     return space.wrap(generic_cpy_call(space, func_target, w_self))
 
+class CPyBuffer(W_Buffer):
+    # Similar to Py_buffer
+
+    def __init__(self, ptr, size, w_obj):
+        self.ptr = ptr
+        self.size = size
+        self.w_obj = w_obj # kept alive
+
+    def getlength(self):
+        return self.size
+
+    def getitem(self, index):
+        return self.ptr[index]
+
+def wrap_getreadbuffer(space, w_self, w_args, func):
+    func_target = rffi.cast(readbufferproc, func)
+    with lltype.scoped_alloc(rffi.VOIDPP.TO, 1) as ptr:
+        index = rffi.cast(Py_ssize_t, 0)
+        size = generic_cpy_call(space, func_target, w_self, index, ptr)
+        if size < 0:
+            space.fromcache(State).check_and_raise_exception(always=True)
+        return space.wrap(CPyBuffer(ptr[0], size, w_self))
+
 def get_richcmp_func(OP_CONST):
     def inner(space, w_self, w_args, func):
         func_target = rffi.cast(richcmpfunc, func)
         check_num_args(space, w_args, 1)
-        args_w = space.fixedview(w_args)
-        other_w = args_w[0]
+        w_other, = space.fixedview(w_args)
         return generic_cpy_call(space, func_target,
-            w_self, other_w, rffi.cast(rffi.INT_real, OP_CONST))
+            w_self, w_other, rffi.cast(rffi.INT_real, OP_CONST))
     return inner
 
 richcmp_eq = get_richcmp_func(Py_EQ)
 richcmp_ne = get_richcmp_func(Py_NE)
+richcmp_lt = get_richcmp_func(Py_LT)
+richcmp_le = get_richcmp_func(Py_LE)
+richcmp_gt = get_richcmp_func(Py_GT)
+richcmp_ge = get_richcmp_func(Py_GE)
+
+def wrap_cmpfunc(space, w_self, w_args, func):
+    func_target = rffi.cast(cmpfunc, func)
+    check_num_args(space, w_args, 1)
+    w_other, = space.fixedview(w_args)
+
+    if not space.is_true(space.issubtype(space.type(w_self),
+                                         space.type(w_other))):
+        raise OperationError(space.w_TypeError, space.wrap(
+            "%s.__cmp__(x,y) requires y to be a '%s', not a '%s'" %
+            (space.type(w_self).getname(space),
+             space.type(w_self).getname(space),
+             space.type(w_other).getname(space))))
+
+    return space.wrap(generic_cpy_call(space, func_target, w_self, w_other))
 
 @cpython_api([PyTypeObjectPtr, PyObject, PyObject], PyObject, external=False)
 def slot_tp_new(space, type, w_args, w_kwds):
@@ -289,7 +340,12 @@
 
     # irregular interface, because of tp_getattr/tp_getattro confusion
     if NAME == "__getattr__":
-        wrapper = wrap_getattr
+        if SLOT == "tp_getattro":
+            wrapper = wrap_getattro
+        elif SLOT == "tp_getattr":
+            wrapper = wrap_getattr
+        else:
+            assert False
 
     function = globals().get(FUNCTION, None)
     assert FLAGS == 0 or FLAGS == PyWrapperFlag_KEYWORDS
@@ -455,7 +511,7 @@
                "oct(x)"),
         UNSLOT("__hex__", nb_hex, slot_nb_hex, wrap_unaryfunc,
                "hex(x)"),
-        NBSLOT("__index__", nb_index, slot_nb_index, wrap_unaryfunc, 
+        NBSLOT("__index__", nb_index, slot_nb_index, wrap_unaryfunc,
                "x[y:z] <==> x[y.__index__():z.__index__()]"),
         IBSLOT("__iadd__", nb_inplace_add, slot_nb_inplace_add,
                wrap_binaryfunc, "+"),
@@ -560,12 +616,19 @@
 for regex, repl in slotdef_replacements:
     slotdefs_str = re.sub(regex, repl, slotdefs_str)
 
+slotdefs = eval(slotdefs_str)
+# PyPy addition
+slotdefs += (
+    TPSLOT("__buffer__", "tp_as_buffer.c_bf_getreadbuffer", None, "wrap_getreadbuffer", ""),
+)
+
 slotdefs_for_tp_slots = unrolling_iterable(
     [(x.method_name, x.slot_name, x.slot_names, x.slot_func)
-     for x in eval(slotdefs_str)])
+     for x in slotdefs])
+
 slotdefs_for_wrappers = unrolling_iterable(
     [(x.method_name, x.slot_names, x.wrapper_func, x.wrapper_func_kwds, x.doc)
-     for x in eval(slotdefs_str)])
+     for x in slotdefs])
 
 if __name__ == "__main__":
     print slotdefs_str

diff --git a/pypy/rpython/ootypesystem/ootype.py b/pypy/rpython/ootypesystem/ootype.py
--- a/pypy/rpython/ootypesystem/ootype.py
+++ b/pypy/rpython/ootypesystem/ootype.py
@@ -443,7 +443,8 @@
             "ll_upper": Meth([], self.SELFTYPE_T),
             "ll_lower": Meth([], self.SELFTYPE_T),
             "ll_substring": Meth([Signed, Signed], self.SELFTYPE_T), # ll_substring(start, count)
-            "ll_split_chr": Meth([self.CHAR], Array(self.SELFTYPE_T)), # XXX this is not pure!
+            "ll_split_chr": Meth([self.CHAR, Signed], Array(self.SELFTYPE_T)), # XXX this is not pure!
+            "ll_rsplit_chr": Meth([self.CHAR, Signed], Array(self.SELFTYPE_T)), # XXX this is not pure!
             "ll_contains": Meth([self.CHAR], Bool),
             "ll_replace_chr_chr": Meth([self.CHAR, self.CHAR], self.SELFTYPE_T),
             })
@@ -1480,9 +1481,16 @@
         # NOT_RPYTHON
         return self.make_string(self._str[start:start+count])
 
-    def ll_split_chr(self, ch):
+    def ll_split_chr(self, ch, max):
         # NOT_RPYTHON
-        l = [self.make_string(s) for s in self._str.split(ch)]
+        l = [self.make_string(s) for s in self._str.split(ch, max)]
+        res = _array(Array(self._TYPE), len(l))
+        res._array[:] = l
+        return res
+
+    def ll_rsplit_chr(self, ch, max):
+        # NOT_RPYTHON
+        l = [self.make_string(s) for s in self._str.rsplit(ch, max)]
         res = _array(Array(self._TYPE), len(l))
         res._array[:] = l
         return res

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
@@ -154,6 +154,24 @@
 
             self.emit_operation(op)
 
+    def optimize_INT_LSHIFT(self, op):
+        v1 = self.getvalue(op.getarg(0))
+        v2 = self.getvalue(op.getarg(1))
+
+        if v2.is_constant() and v2.box.getint() == 0:
+            self.make_equal_to(op.result, v1)
+        else:
+            self.emit_operation(op)
+
+    def optimize_INT_RSHIFT(self, op):
+        v1 = self.getvalue(op.getarg(0))
+        v2 = self.getvalue(op.getarg(1))
+
+        if v2.is_constant() and v2.box.getint() == 0:
+            self.make_equal_to(op.result, v1)
+        else:
+            self.emit_operation(op)
+
     def optimize_CALL_PURE(self, op):
         arg_consts = []
         for i in range(op.numargs()):

diff --git a/pypy/objspace/std/fake.py b/pypy/objspace/std/fake.py
--- a/pypy/objspace/std/fake.py
+++ b/pypy/objspace/std/fake.py
@@ -151,9 +151,9 @@
 
 class CPythonFakeFrame(eval.Frame):
 
-    def __init__(self, space, code, w_globals=None, numlocals=-1):
+    def __init__(self, space, code, w_globals=None):
         self.fakecode = code
-        eval.Frame.__init__(self, space, w_globals, numlocals)
+        eval.Frame.__init__(self, space, w_globals)
 
     def getcode(self):
         return self.fakecode

diff --git a/pypy/jit/tl/pypyjit.py b/pypy/jit/tl/pypyjit.py
--- a/pypy/jit/tl/pypyjit.py
+++ b/pypy/jit/tl/pypyjit.py
@@ -101,7 +101,7 @@
 
     # first annotate, rtype, and backendoptimize PyPy
     try:
-        interp, graph = get_interpreter(entry_point, [], backendopt=True,
+        interp, graph = get_interpreter(entry_point, [], backendopt=False,
                                         config=config,
                                         type_system=config.translation.type_system,
                                         policy=PyPyAnnotatorPolicy(space))

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,9 +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, X86RegisterManager,
-                                           X86XMMRegisterManager, get_ebp_ofs,
-                                           _get_scale)
+from pypy.jit.backend.x86.regalloc import (RegAlloc, get_ebp_ofs,
+                                           _get_scale, gpr_reg_mgr_cls)
 
 from pypy.jit.backend.x86.arch import (FRAME_FIXED_SIZE, FORCE_INDEX_OFS, WORD,
                                        IS_X86_32, IS_X86_64)
@@ -78,8 +77,8 @@
         self.loop_run_counters = []
         self.float_const_neg_addr = 0
         self.float_const_abs_addr = 0
-        self.malloc_fixedsize_slowpath1 = 0
-        self.malloc_fixedsize_slowpath2 = 0
+        self.malloc_slowpath1 = 0
+        self.malloc_slowpath2 = 0
         self.memcpy_addr = 0
         self.setup_failure_recovery()
         self._debug = False
@@ -124,8 +123,8 @@
             self._build_failure_recovery(True, withfloats=True)
             support.ensure_sse2_floats()
             self._build_float_constants()
-        if hasattr(gc_ll_descr, 'get_malloc_fixedsize_slowpath_addr'):
-            self._build_malloc_fixedsize_slowpath()
+        if gc_ll_descr.get_malloc_slowpath_addr is not None:
+            self._build_malloc_slowpath()
         self._build_stack_check_slowpath()
         debug_start('jit-backend-counts')
         self.set_debug(have_debug_prints())
@@ -133,6 +132,7 @@
 
     def setup(self, looptoken):
         assert self.memcpy_addr != 0, "setup_once() not called?"
+        self.current_clt = looptoken.compiled_loop_token
         self.pending_guard_tokens = []
         self.mc = codebuf.MachineCodeBlockWrapper()
         if self.datablockwrapper is None:
@@ -145,6 +145,7 @@
         self.mc = None
         self.looppos = -1
         self.currently_compiling_loop = None
+        self.current_clt = None
 
     def finish_once(self):
         if self._debug:
@@ -170,26 +171,47 @@
         self.float_const_neg_addr = float_constants
         self.float_const_abs_addr = float_constants + 16
 
-    def _build_malloc_fixedsize_slowpath(self):
+    def _build_malloc_slowpath(self):
+        # With asmgcc, we need two helpers, so that we can write two CALL
+        # instructions in assembler, with a mark_gc_roots in between.
+        # With shadowstack, this is not needed, so we produce a single helper.
+        gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+        #
         # ---------- first helper for the slow path of malloc ----------
         mc = codebuf.MachineCodeBlockWrapper()
         if self.cpu.supports_floats:          # save the XMM registers in
             for i in range(self.cpu.NUM_REGS):# the *caller* frame, from esp+8
                 mc.MOVSD_sx((WORD*2)+8*i, i)
         mc.SUB_rr(edx.value, eax.value)       # compute the size we want
-        if IS_X86_32:
-            mc.MOV_sr(WORD, edx.value)        # save it as the new argument
-        elif IS_X86_64:
-            # rdi can be clobbered: its content was forced to the stack
-            # by _fastpath_malloc(), like all other save_around_call_regs.
-            mc.MOV_rr(edi.value, edx.value)
-
-        addr = self.cpu.gc_ll_descr.get_malloc_fixedsize_slowpath_addr()
-        mc.JMP(imm(addr))                    # tail call to the real malloc
-        rawstart = mc.materialize(self.cpu.asmmemmgr, [])
-        self.malloc_fixedsize_slowpath1 = rawstart
-        # ---------- second helper for the slow path of malloc ----------
-        mc = codebuf.MachineCodeBlockWrapper()
+        addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr()
+        #
+        if gcrootmap is not None and gcrootmap.is_shadow_stack:
+            # ---- shadowstack ----
+            for reg, ofs in gpr_reg_mgr_cls.REGLOC_TO_COPY_AREA_OFS.items():
+                mc.MOV_br(ofs, reg.value)
+            mc.SUB_ri(esp.value, 16 - WORD)      # stack alignment of 16 bytes
+            if IS_X86_32:
+                mc.MOV_sr(0, edx.value)          # push argument
+            elif IS_X86_64:
+                mc.MOV_rr(edi.value, edx.value)
+            mc.CALL(imm(addr))
+            mc.ADD_ri(esp.value, 16 - WORD)
+            for reg, ofs in gpr_reg_mgr_cls.REGLOC_TO_COPY_AREA_OFS.items():
+                mc.MOV_rb(reg.value, ofs)
+        else:
+            # ---- asmgcc ----
+            if IS_X86_32:
+                mc.MOV_sr(WORD, edx.value)       # save it as the new argument
+            elif IS_X86_64:
+                # rdi can be clobbered: its content was forced to the stack
+                # by _fastpath_malloc(), like all other save_around_call_regs.
+                mc.MOV_rr(edi.value, edx.value)
+            mc.JMP(imm(addr))                    # tail call to the real malloc
+            rawstart = mc.materialize(self.cpu.asmmemmgr, [])
+            self.malloc_slowpath1 = rawstart
+            # ---------- second helper for the slow path of malloc ----------
+            mc = codebuf.MachineCodeBlockWrapper()
+        #
         if self.cpu.supports_floats:          # restore the XMM registers
             for i in range(self.cpu.NUM_REGS):# from where they were saved
                 mc.MOVSD_xs(i, (WORD*2)+8*i)
@@ -197,21 +219,28 @@
         mc.MOV(edx, heap(nursery_free_adr))   # load this in EDX
         mc.RET()
         rawstart = mc.materialize(self.cpu.asmmemmgr, [])
-        self.malloc_fixedsize_slowpath2 = rawstart
+        self.malloc_slowpath2 = rawstart
 
     def _build_stack_check_slowpath(self):
-        from pypy.rlib import rstack
         _, _, slowpathaddr = self.cpu.insert_stack_check()
         if slowpathaddr == 0 or self.cpu.exit_frame_with_exception_v < 0:
             return      # no stack check (for tests, or non-translated)
         #
+        # make a "function" that is called immediately at the start of
+        # an assembler function.  In particular, the stack looks like:
+        #
+        #    |  ...                |    <-- aligned to a multiple of 16
+        #    |  retaddr of caller  |
+        #    |  my own retaddr     |    <-- esp
+        #    +---------------------+
+        #
         mc = codebuf.MachineCodeBlockWrapper()
-        mc.PUSH_r(ebp.value)
-        mc.MOV_rr(ebp.value, esp.value)
         #
+        stack_size = WORD
         if IS_X86_64:
             # on the x86_64, we have to save all the registers that may
             # have been used to pass arguments
+            stack_size += 6*WORD + 8*8
             for reg in [edi, esi, edx, ecx, r8, r9]:
                 mc.PUSH_r(reg.value)
             mc.SUB_ri(esp.value, 8*8)
@@ -220,11 +249,13 @@
         #
         if IS_X86_32:
             mc.LEA_rb(eax.value, +8)
+            stack_size += 2*WORD
+            mc.PUSH_r(eax.value)        # alignment
             mc.PUSH_r(eax.value)
         elif IS_X86_64:
             mc.LEA_rb(edi.value, +16)
-            mc.AND_ri(esp.value, -16)
         #
+        # esp is now aligned to a multiple of 16 again
         mc.CALL(imm(slowpathaddr))
         #
         mc.MOV(eax, heap(self.cpu.pos_exception()))
@@ -232,16 +263,16 @@
         mc.J_il8(rx86.Conditions['NZ'], 0)
         jnz_location = mc.get_relative_pos()
         #
-        if IS_X86_64:
+        if IS_X86_32:
+            mc.ADD_ri(esp.value, 2*WORD)
+        elif IS_X86_64:
             # restore the registers
             for i in range(7, -1, -1):
                 mc.MOVSD_xs(i, 8*i)
-            for i, reg in [(6, r9), (5, r8), (4, ecx),
-                           (3, edx), (2, esi), (1, edi)]:
-                mc.MOV_rb(reg.value, -8*i)
+            mc.ADD_ri(esp.value, 8*8)
+            for reg in [r9, r8, ecx, edx, esi, edi]:
+                mc.POP_r(reg.value)
         #
-        mc.MOV_rr(esp.value, ebp.value)
-        mc.POP_r(ebp.value)
         mc.RET()
         #
         # patch the JNZ above
@@ -266,9 +297,7 @@
         # function, and will instead return to the caller's caller.  Note
         # also that we completely ignore the saved arguments, because we
         # are interrupting the function.
-        mc.MOV_rr(esp.value, ebp.value)
-        mc.POP_r(ebp.value)
-        mc.ADD_ri(esp.value, WORD)
+        mc.ADD_ri(esp.value, stack_size)
         mc.RET()
         #
         rawstart = mc.materialize(self.cpu.asmmemmgr, [])
@@ -537,7 +566,7 @@
     def _get_offset_of_ebp_from_esp(self, allocated_depth):
         # Given that [EBP] is where we saved EBP, i.e. in the last word
         # of our fixed frame, then the 'words' value is:
-        words = (self.cpu.FRAME_FIXED_SIZE - 1) + allocated_depth
+        words = (FRAME_FIXED_SIZE - 1) + allocated_depth
         # align, e.g. for Mac OS X
         aligned_words = align_stack_words(words+2)-2 # 2 = EIP+EBP
         return -WORD * aligned_words
@@ -550,6 +579,10 @@
         for regloc in self.cpu.CALLEE_SAVE_REGISTERS:
             self.mc.PUSH_r(regloc.value)
 
+        gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+        if gcrootmap and gcrootmap.is_shadow_stack:
+            self._call_header_shadowstack(gcrootmap)
+
     def _call_header_with_stack_check(self):
         if self.stack_check_slowpath == 0:
             pass                # no stack check (e.g. not translated)
@@ -571,12 +604,32 @@
     def _call_footer(self):
         self.mc.LEA_rb(esp.value, -len(self.cpu.CALLEE_SAVE_REGISTERS) * WORD)
 
+        gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+        if gcrootmap and gcrootmap.is_shadow_stack:
+            self._call_footer_shadowstack(gcrootmap)
+
         for i in range(len(self.cpu.CALLEE_SAVE_REGISTERS)-1, -1, -1):
             self.mc.POP_r(self.cpu.CALLEE_SAVE_REGISTERS[i].value)
 
         self.mc.POP_r(ebp.value)
         self.mc.RET()
 
+    def _call_header_shadowstack(self, gcrootmap):
+        # we need to put two words into the shadowstack: the MARKER
+        # and the address of the frame (ebp, actually)
+        rst = gcrootmap.get_root_stack_top_addr()
+        assert rx86.fits_in_32bits(rst)
+        self.mc.MOV_rj(eax.value, rst)                # MOV eax, [rootstacktop]
+        self.mc.LEA_rm(edx.value, (eax.value, 2*WORD))  # LEA edx, [eax+2*WORD]
+        self.mc.MOV_mi((eax.value, 0), gcrootmap.MARKER)    # MOV [eax], MARKER
+        self.mc.MOV_mr((eax.value, WORD), ebp.value)      # MOV [eax+WORD], ebp
+        self.mc.MOV_jr(rst, edx.value)                # MOV [rootstacktop], edx
+
+    def _call_footer_shadowstack(self, gcrootmap):
+        rst = gcrootmap.get_root_stack_top_addr()
+        assert rx86.fits_in_32bits(rst)
+        self.mc.SUB_ji8(rst, 2*WORD)       # SUB [rootstacktop], 2*WORD
+
     def _assemble_bootstrap_direct_call(self, arglocs, jmppos, stackdepth):
         if IS_X86_64:
             return self._assemble_bootstrap_direct_call_64(arglocs, jmppos, stackdepth)
@@ -686,8 +739,8 @@
         nonfloatlocs, floatlocs = arglocs
         self._call_header()
         stackadjustpos = self._patchable_stackadjust()
-        tmp = X86RegisterManager.all_regs[0]
-        xmmtmp = X86XMMRegisterManager.all_regs[0]
+        tmp = eax
+        xmmtmp = xmm0
         self.mc.begin_reuse_scratch_register()
         for i in range(len(nonfloatlocs)):
             loc = nonfloatlocs[i]
@@ -896,9 +949,9 @@
                     self.implement_guard(guard_token, checkfalsecond)
         return genop_cmp_guard_float
 
-    def _emit_call(self, x, arglocs, start=0, tmp=eax):
+    def _emit_call(self, force_index, x, arglocs, start=0, tmp=eax):
         if IS_X86_64:
-            return self._emit_call_64(x, arglocs, start)
+            return self._emit_call_64(force_index, x, arglocs, start)
 
         p = 0
         n = len(arglocs)
@@ -924,9 +977,9 @@
         self._regalloc.reserve_param(p//WORD)
         # x is a location
         self.mc.CALL(x)
-        self.mark_gc_roots()
+        self.mark_gc_roots(force_index)
 
-    def _emit_call_64(self, x, arglocs, start=0):
+    def _emit_call_64(self, force_index, x, arglocs, start):
         src_locs = []
         dst_locs = []
         xmm_src_locs = []
@@ -984,12 +1037,27 @@
 
         self._regalloc.reserve_param(len(pass_on_stack))
         self.mc.CALL(x)
-        self.mark_gc_roots()
+        self.mark_gc_roots(force_index)
 
     def call(self, addr, args, res):
-        self._emit_call(imm(addr), args)
+        force_index = self.write_new_force_index()
+        self._emit_call(force_index, imm(addr), args)
         assert res is eax
 
+    def write_new_force_index(self):
+        # for shadowstack only: get a new, unused force_index number and
+        # write it to FORCE_INDEX_OFS.  Used to record the call shape
+        # (i.e. where the GC pointers are in the stack) around a CALL
+        # instruction that doesn't already have a force_index.
+        gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+        if gcrootmap and gcrootmap.is_shadow_stack:
+            clt = self.current_clt
+            force_index = clt.reserve_and_record_some_faildescr_index()
+            self.mc.MOV_bi(FORCE_INDEX_OFS, force_index)
+            return force_index
+        else:
+            return 0
+
     genop_int_neg = _unaryop("NEG")
     genop_int_invert = _unaryop("NOT")
     genop_int_add = _binaryop("ADD", True)
@@ -1205,6 +1273,11 @@
             assert isinstance(loc_vtable, ImmedLoc)
             self.mc.MOV(mem(loc, self.cpu.vtable_offset), loc_vtable)
 
+    def set_new_array_length(self, loc, ofs_length, loc_num_elem):
+        assert isinstance(loc, RegLoc)
+        assert isinstance(loc_num_elem, ImmedLoc)
+        self.mc.MOV(mem(loc, ofs_length), loc_num_elem)
+
     # XXX genop_new is abused for all varsized mallocs with Boehm, for now
     # (instead of genop_new_array, genop_newstr, genop_newunicode)
     def genop_new(self, op, arglocs, result_loc):
@@ -1783,6 +1856,10 @@
         self.pending_guard_tokens.append(guard_token)
 
     def genop_call(self, op, arglocs, resloc):
+        force_index = self.write_new_force_index()
+        self._genop_call(op, arglocs, resloc, force_index)
+
+    def _genop_call(self, op, arglocs, resloc, force_index):
         sizeloc = arglocs[0]
         assert isinstance(sizeloc, ImmedLoc)
         size = sizeloc.value
@@ -1796,8 +1873,8 @@
             tmp = ecx
         else:
             tmp = eax
-        
-        self._emit_call(x, arglocs, 3, tmp=tmp)
+
+        self._emit_call(force_index, x, arglocs, 3, tmp=tmp)
 
         if IS_X86_32 and isinstance(resloc, StackLoc) and resloc.width == 8:
             # a float or a long long return
@@ -1828,7 +1905,7 @@
         faildescr = guard_op.getdescr()
         fail_index = self.cpu.get_fail_descr_number(faildescr)
         self.mc.MOV_bi(FORCE_INDEX_OFS, fail_index)
-        self.genop_call(op, arglocs, result_loc)
+        self._genop_call(op, arglocs, result_loc, fail_index)
         self.mc.CMP_bi(FORCE_INDEX_OFS, 0)
         self.implement_guard(guard_token, 'L')
 
@@ -1842,8 +1919,8 @@
         assert len(arglocs) - 2 == len(descr._x86_arglocs[0])
         #
         # Write a call to the direct_bootstrap_code of the target assembler
-        self._emit_call(imm(descr._x86_direct_bootstrap_code), arglocs, 2,
-                        tmp=eax)
+        self._emit_call(fail_index, imm(descr._x86_direct_bootstrap_code),
+                        arglocs, 2, tmp=eax)
         if op.result is None:
             assert result_loc is None
             value = self.cpu.done_with_this_frame_void_v
@@ -1868,7 +1945,7 @@
         jd = descr.outermost_jitdriver_sd
         assert jd is not None
         asm_helper_adr = self.cpu.cast_adr_to_int(jd.assembler_helper_adr)
-        self._emit_call(imm(asm_helper_adr), [eax, arglocs[1]], 0,
+        self._emit_call(fail_index, imm(asm_helper_adr), [eax, arglocs[1]], 0,
                         tmp=ecx)
         if IS_X86_32 and isinstance(result_loc, StackLoc) and result_loc.type == FLOAT:
             self.mc.FSTP_b(result_loc.value)
@@ -1895,7 +1972,7 @@
             # load the return value from fail_boxes_xxx[0]
             kind = op.result.type
             if kind == FLOAT:
-                xmmtmp = X86XMMRegisterManager.all_regs[0]
+                xmmtmp = xmm0
                 adr = self.fail_boxes_float.get_addr_for_num(0)
                 self.mc.MOVSD(xmmtmp, heap(adr))
                 self.mc.MOVSD(result_loc, xmmtmp)
@@ -1990,11 +2067,16 @@
         not_implemented("not implemented operation (guard): %s" %
                         op.getopname())
 
-    def mark_gc_roots(self):
+    def mark_gc_roots(self, force_index, use_copy_area=False):
+        if force_index < 0:
+            return     # not needed
         gcrootmap = self.cpu.gc_ll_descr.gcrootmap
         if gcrootmap:
-            mark = self._regalloc.get_mark_gc_roots(gcrootmap)
-            self.mc.insert_gcroot_marker(mark)
+            mark = self._regalloc.get_mark_gc_roots(gcrootmap, use_copy_area)
+            if gcrootmap.is_shadow_stack:
+                gcrootmap.write_callshape(mark, force_index)
+            else:
+                self.mc.insert_gcroot_marker(mark)
 
     def target_arglocs(self, loop_token):
         return loop_token._x86_arglocs
@@ -2006,8 +2088,7 @@
         else:
             self.mc.JMP(imm(loop_token._x86_loop_code))
 
-    def malloc_cond_fixedsize(self, nursery_free_adr, nursery_top_adr,
-                              size, tid):
+    def malloc_cond(self, nursery_free_adr, nursery_top_adr, size, tid):
         size = max(size, self.cpu.gc_ll_descr.minimal_size_in_nursery)
         self.mc.MOV(eax, heap(nursery_free_adr))
         self.mc.LEA_rm(edx.value, (eax.value, size))
@@ -2015,7 +2096,7 @@
         self.mc.J_il8(rx86.Conditions['NA'], 0) # patched later
         jmp_adr = self.mc.get_relative_pos()
 
-        # See comments in _build_malloc_fixedsize_slowpath for the
+        # See comments in _build_malloc_slowpath for the
         # details of the two helper functions that we are calling below.
         # First, we need to call two of them and not just one because we
         # need to have a mark_gc_roots() in between.  Then the calling
@@ -2025,19 +2106,27 @@
         # result in EAX; slowpath_addr2 additionally returns in EDX a
         # copy of heap(nursery_free_adr), so that the final MOV below is
         # a no-op.
-        slowpath_addr1 = self.malloc_fixedsize_slowpath1
+
         # reserve room for the argument to the real malloc and the
         # 8 saved XMM regs
         self._regalloc.reserve_param(1+16)
-        self.mc.CALL(imm(slowpath_addr1))
-        self.mark_gc_roots()
-        slowpath_addr2 = self.malloc_fixedsize_slowpath2
+
+        gcrootmap = self.cpu.gc_ll_descr.gcrootmap
+        shadow_stack = (gcrootmap is not None and gcrootmap.is_shadow_stack)
+        if not shadow_stack:
+            # there are two helpers to call only with asmgcc
+            slowpath_addr1 = self.malloc_slowpath1
+            self.mc.CALL(imm(slowpath_addr1))
+        self.mark_gc_roots(self.write_new_force_index(),
+                           use_copy_area=shadow_stack)
+        slowpath_addr2 = self.malloc_slowpath2
         self.mc.CALL(imm(slowpath_addr2))
 
         offset = self.mc.get_relative_pos() - jmp_adr
         assert 0 < offset <= 127
         self.mc.overwrite(jmp_adr-1, chr(offset))
         # on 64-bits, 'tid' is a value that fits in 31 bits
+        assert rx86.fits_in_32bits(tid)
         self.mc.MOV_mi((eax.value, 0), tid)
         self.mc.MOV(heap(nursery_free_adr), edx)
         

diff --git a/pypy/module/cpyext/include/traceback.h b/pypy/module/cpyext/include/traceback.h
new file mode 100644
--- /dev/null
+++ b/pypy/module/cpyext/include/traceback.h
@@ -0,0 +1,12 @@
+#ifndef Py_TRACEBACK_H
+#define Py_TRACEBACK_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef PyObject PyTracebackObject;
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* !Py_TRACEBACK_H */

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
@@ -2,7 +2,7 @@
 from pypy.rlib.jit import JitDriver
 from pypy.rlib.objectmodel import compute_hash
 from pypy.jit.metainterp.warmspot import ll_meta_interp, get_stats
-from pypy.jit.metainterp.test.test_basic import LLJitMixin, OOJitMixin
+from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin
 from pypy.jit.codewriter.policy import StopAtXPolicy
 from pypy.jit.metainterp.resoperation import rop
 from pypy.jit.metainterp import history


More information about the Pypy-commit mailing list