[pypy-commit] pypy jit-multilabel: hg merge default

hakanardo noreply at buildbot.pypy.org
Sat Dec 17 13:13:11 CET 2011


Author: Hakan Ardo <hakan at debian.org>
Branch: jit-multilabel
Changeset: r50607:2d900cd7e4e3
Date: 2011-12-17 12:49 +0100
http://bitbucket.org/pypy/pypy/changeset/2d900cd7e4e3/

Log:	hg merge default

diff --git a/lib-python/modified-2.7/ctypes/test/test_callbacks.py b/lib-python/modified-2.7/ctypes/test/test_callbacks.py
--- a/lib-python/modified-2.7/ctypes/test/test_callbacks.py
+++ b/lib-python/modified-2.7/ctypes/test/test_callbacks.py
@@ -1,5 +1,6 @@
 import unittest
 from ctypes import *
+from ctypes.test import xfail
 import _ctypes_test
 
 class Callbacks(unittest.TestCase):
@@ -98,6 +99,7 @@
 ##        self.check_type(c_char_p, "abc")
 ##        self.check_type(c_char_p, "def")
 
+    @xfail
     def test_pyobject(self):
         o = ()
         from sys import getrefcount as grc
diff --git a/lib-python/modified-2.7/ctypes/test/test_libc.py b/lib-python/modified-2.7/ctypes/test/test_libc.py
--- a/lib-python/modified-2.7/ctypes/test/test_libc.py
+++ b/lib-python/modified-2.7/ctypes/test/test_libc.py
@@ -25,7 +25,10 @@
         lib.my_qsort(chars, len(chars)-1, sizeof(c_char), comparefunc(sort))
         self.assertEqual(chars.raw, "   ,,aaaadmmmnpppsss\x00")
 
-    def test_no_more_xfail(self):
+    def SKIPPED_test_no_more_xfail(self):
+        # We decided to not explicitly support the whole ctypes-2.7
+        # and instead go for a case-by-case, demand-driven approach.
+        # So this test is skipped instead of failing.
         import socket
         import ctypes.test
         self.assertTrue(not hasattr(ctypes.test, 'xfail'),
diff --git a/pypy/doc/config/objspace.std.withspecialisedtuple.txt b/pypy/doc/config/objspace.std.withspecialisedtuple.txt
new file mode 100644
--- /dev/null
+++ b/pypy/doc/config/objspace.std.withspecialisedtuple.txt
@@ -0,0 +1,3 @@
+Use "specialized tuples", a custom implementation for some common kinds
+of tuples.  Currently limited to tuples of length 2, in three variants:
+(int, int), (float, float), and a generic (object, object).
diff --git a/pypy/interpreter/baseobjspace.py b/pypy/interpreter/baseobjspace.py
--- a/pypy/interpreter/baseobjspace.py
+++ b/pypy/interpreter/baseobjspace.py
@@ -190,8 +190,8 @@
     def is_w(self, space, w_other):
         return self is w_other
 
-    def unique_id(self, space):
-        return space.wrap(compute_unique_id(self))
+    def immutable_unique_id(self, space):
+        return None
 
     def str_w(self, space):
         w_msg = typed_unwrap_error_msg(space, "string", self)
@@ -706,7 +706,10 @@
         return w_two.is_w(self, w_one)
 
     def id(self, w_obj):
-        return w_obj.unique_id(self)
+        w_result = w_obj.immutable_unique_id(self)
+        if w_result is None:
+            w_result = self.wrap(compute_unique_id(w_obj))
+        return w_result
 
     def hash_w(self, w_obj):
         """shortcut for space.int_w(space.hash(w_obj))"""
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -54,7 +54,11 @@
 #  Hash support
 
 def default_identity_hash(space, w_obj):
-    return space.wrap(compute_identity_hash(w_obj))
+    w_unique_id = w_obj.immutable_unique_id(space)
+    if w_unique_id is None:     # common case
+        return space.wrap(compute_identity_hash(w_obj))
+    else:
+        return space.hash(w_unique_id)
 
 # ____________________________________________________________
 #
diff --git a/pypy/jit/backend/llgraph/llimpl.py b/pypy/jit/backend/llgraph/llimpl.py
--- a/pypy/jit/backend/llgraph/llimpl.py
+++ b/pypy/jit/backend/llgraph/llimpl.py
@@ -328,6 +328,14 @@
     _variables.append(v)
     return r
 
+def compile_started_vars(clt):
+    if not hasattr(clt, '_debug_argtypes'):    # only when compiling the loop
+        argtypes = [v.concretetype for v in _variables]
+        try:
+            clt._debug_argtypes = argtypes
+        except AttributeError:    # when 'clt' is actually a translated
+            pass                  # GcStruct
+
 def compile_add(loop, opnum):
     loop = _from_opaque(loop)
     loop.operations.append(Operation(opnum))
@@ -355,11 +363,13 @@
 
 TARGET_TOKENS = weakref.WeakKeyDictionary()
 
-def compile_add_target_token(loop, descr):
+def compile_add_target_token(loop, descr, clt):
+    # here, 'clt' is the compiled_loop_token of the original loop that
+    # we are compiling
     loop = _from_opaque(loop)
     op = loop.operations[-1]
     descrobj = _normalize(descr)
-    TARGET_TOKENS[descrobj] = loop, len(loop.operations), op.args
+    TARGET_TOKENS[descrobj] = loop, len(loop.operations), op.args, clt
 
 def compile_add_var(loop, intvar):
     loop = _from_opaque(loop)
@@ -395,17 +405,25 @@
     _variables.append(v)
     return r
 
-def compile_add_jump_target(loop, targettoken):
+def compile_add_jump_target(loop, targettoken, source_clt):
     loop = _from_opaque(loop)
     descrobj = _normalize(targettoken)
-    loop_target, target_opindex, target_inputargs = TARGET_TOKENS[descrobj]
+    (loop_target, target_opindex, target_inputargs, target_clt
+        ) = TARGET_TOKENS[descrobj]
+    #
+    try:
+        assert source_clt._debug_argtypes == target_clt._debug_argtypes
+    except AttributeError:   # when translated
+        pass
     #
     op = loop.operations[-1]
     op.jump_target = loop_target
     op.jump_target_opindex = target_opindex
     op.jump_target_inputargs = target_inputargs
     assert op.opnum == rop.JUMP
-    assert len(op.args) == len(target_inputargs)
+    assert [v.concretetype for v in op.args] == (
+           [v.concretetype for v in target_inputargs])
+    #
     if loop_target == loop:
         log.info("compiling new loop")
     else:
@@ -987,6 +1005,7 @@
         self._may_force = self.opindex
         try:
             inpargs = _from_opaque(ctl.compiled_version).inputargs
+            assert len(inpargs) == len(args)
             for i, inparg in enumerate(inpargs):
                 TYPE = inparg.concretetype
                 if TYPE is lltype.Signed:
@@ -1816,6 +1835,7 @@
 setannotation(compile_start_int_var, annmodel.SomeInteger())
 setannotation(compile_start_ref_var, annmodel.SomeInteger())
 setannotation(compile_start_float_var, annmodel.SomeInteger())
+setannotation(compile_started_vars, annmodel.s_None)
 setannotation(compile_add, annmodel.s_None)
 setannotation(compile_add_descr, annmodel.s_None)
 setannotation(compile_add_descr_arg, annmodel.s_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
@@ -138,11 +138,12 @@
         clt = original_loop_token.compiled_loop_token
         clt.loop_and_bridges.append(c)
         clt.compiling_a_bridge()
-        self._compile_loop_or_bridge(c, inputargs, operations)
+        self._compile_loop_or_bridge(c, inputargs, operations, clt)
         old, oldindex = faildescr._compiled_fail
         llimpl.compile_redirect_fail(old, oldindex, c)
 
-    def compile_loop(self, inputargs, operations, jitcell_token, log=True, name=''):
+    def compile_loop(self, inputargs, operations, jitcell_token,
+                     log=True, name=''):
         """In a real assembler backend, this should assemble the given
         list of operations.  Here we just generate a similar CompiledLoop
         instance.  The code here is RPython, whereas the code in llimpl
@@ -153,14 +154,14 @@
         clt.loop_and_bridges = [c]
         clt.compiled_version = c
         jitcell_token.compiled_loop_token = clt
-        self._compile_loop_or_bridge(c, inputargs, operations)
+        self._compile_loop_or_bridge(c, inputargs, operations, clt)
 
     def free_loop_and_bridges(self, compiled_loop_token):
         for c in compiled_loop_token.loop_and_bridges:
             llimpl.mark_as_free(c)
         model.AbstractCPU.free_loop_and_bridges(self, compiled_loop_token)
 
-    def _compile_loop_or_bridge(self, c, inputargs, operations):
+    def _compile_loop_or_bridge(self, c, inputargs, operations, clt):
         var2index = {}
         for box in inputargs:
             if isinstance(box, history.BoxInt):
@@ -172,10 +173,11 @@
                 var2index[box] = llimpl.compile_start_float_var(c)
             else:
                 raise Exception("box is: %r" % (box,))
-        self._compile_operations(c, operations, var2index)
+        llimpl.compile_started_vars(clt)
+        self._compile_operations(c, operations, var2index, clt)
         return c
 
-    def _compile_operations(self, c, operations, var2index):
+    def _compile_operations(self, c, operations, var2index, clt):
         for op in operations:
             llimpl.compile_add(c, op.getopnum())
             descr = op.getdescr()
@@ -187,7 +189,7 @@
                 assert op.getopnum() != rop.JUMP
                 llimpl.compile_add_loop_token(c, descr)
             if isinstance(descr, history.TargetToken) and op.getopnum() == rop.LABEL:
-                llimpl.compile_add_target_token(c, descr)
+                llimpl.compile_add_target_token(c, descr, clt)
             if self.is_oo and isinstance(descr, (OODescr, MethDescr)):
                 # hack hack, not rpython
                 c._obj.externalobj.operations[-1].setdescr(descr)
@@ -241,7 +243,7 @@
         assert op.is_final()
         if op.getopnum() == rop.JUMP:
             targettoken = op.getdescr()
-            llimpl.compile_add_jump_target(c, targettoken)
+            llimpl.compile_add_jump_target(c, targettoken, clt)
         elif op.getopnum() == rop.FINISH:
             faildescr = op.getdescr()
             index = self.get_fail_descr_number(faildescr)
@@ -260,23 +262,28 @@
         self.latest_frame = frame
         return fail_index
 
-    def execute_token(self, loop_token):
-        """Calls the fake 'assembler' generated for the given loop.
-        Returns the descr of the last executed operation: either the one
-        attached to the failing guard, or the one attached to the FINISH.
-        Use set_future_value_xxx() before, and get_latest_value_xxx() after.
-        """
-        fail_index = self._execute_token(loop_token)
-        return self.get_fail_descr_from_number(fail_index)
-
-    def set_future_value_int(self, index, intvalue):
-        llimpl.set_future_value_int(index, intvalue)
-
-    def set_future_value_ref(self, index, objvalue):
-        llimpl.set_future_value_ref(index, objvalue)
-
-    def set_future_value_float(self, index, floatvalue):
-        llimpl.set_future_value_float(index, floatvalue)
+    def make_execute_token(self, *argtypes):
+        nb_args = len(argtypes)
+        unroll_argtypes = unrolling_iterable(list(enumerate(argtypes)))
+        #
+        def execute_token(loop_token, *args):
+            assert len(args) == nb_args
+            for index, TYPE in unroll_argtypes:
+                x = args[index]
+                assert TYPE == lltype.typeOf(x)
+                if TYPE == lltype.Signed:
+                    llimpl.set_future_value_int(index, x)
+                elif TYPE == llmemory.GCREF:
+                    llimpl.set_future_value_ref(index, x)
+                elif TYPE == longlong.FLOATSTORAGE:
+                    llimpl.set_future_value_float(index, x)
+                else:
+                    assert 0
+            #
+            fail_index = self._execute_token(loop_token)
+            return self.get_fail_descr_from_number(fail_index)
+        #
+        return execute_token
 
     def get_latest_value_int(self, index):
         return llimpl.frame_int_getvalue(self.latest_frame, index)
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
@@ -69,6 +69,8 @@
         self.bindings[box] = loc
         #
         index = self.get_loc_index(loc)
+        if index < 0:
+            return
         endindex = index + self.frame_size(box.type)
         while len(self.used) < endindex:
             self.used.append(False)
@@ -91,6 +93,8 @@
         #
         size = self.frame_size(box.type)
         baseindex = self.get_loc_index(loc)
+        if baseindex < 0:
+            return
         for i in range(size):
             index = baseindex + i
             assert 0 <= index < len(self.used)
@@ -98,7 +102,8 @@
 
     def try_to_reuse_location(self, box, loc):
         index = self.get_loc_index(loc)
-        assert index >= 0
+        if index < 0:
+            return False
         size = self.frame_size(box.type)
         for i in range(size):
             while (index + i) >= len(self.used):
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
@@ -1,5 +1,6 @@
 from pypy.rlib.debug import debug_start, debug_print, debug_stop
 from pypy.jit.metainterp import history
+from pypy.rpython.lltypesystem import lltype
 
 
 class AbstractCPU(object):
@@ -84,24 +85,21 @@
         """Print a disassembled version of looptoken to stdout"""
         raise NotImplementedError
 
-    def execute_token(self, looptoken):
-        """Execute the generated code referenced by the looptoken.
+    def execute_token(self, looptoken, *args):
+        """NOT_RPYTHON (for tests only)
+        Execute the generated code referenced by the looptoken.
         Returns the descr of the last executed operation: either the one
         attached to the failing guard, or the one attached to the FINISH.
-        Use set_future_value_xxx() before, and get_latest_value_xxx() after.
+        Use get_latest_value_xxx() afterwards to read the result(s).
         """
-        raise NotImplementedError
+        argtypes = [lltype.typeOf(x) for x in args]
+        execute = self.make_execute_token(*argtypes)
+        return execute(looptoken, *args)
 
-    def set_future_value_int(self, index, intvalue):
-        """Set the value for the index'th argument for the loop to run."""
-        raise NotImplementedError
-
-    def set_future_value_float(self, index, floatvalue):
-        """Set the value for the index'th argument for the loop to run."""
-        raise NotImplementedError
-
-    def set_future_value_ref(self, index, objvalue):
-        """Set the value for the index'th argument for the loop to run."""
+    def make_execute_token(self, *argtypes):
+        """Must make and return an execute_token() function that will be
+        called with the given argtypes.
+        """
         raise NotImplementedError
 
     def get_latest_value_int(self, index):
diff --git a/pypy/jit/backend/test/calling_convention_test.py b/pypy/jit/backend/test/calling_convention_test.py
--- a/pypy/jit/backend/test/calling_convention_test.py
+++ b/pypy/jit/backend/test/calling_convention_test.py
@@ -40,17 +40,18 @@
         local_floats = list(floats)
         local_ints = list(ints)
         expected_result = 0.0
+        arguments = []
         for i in range(len(args)):
             x = args[i]
             if x[0] == 'f':
                 x = local_floats.pop()
                 t = longlong.getfloatstorage(x)
-                self.cpu.set_future_value_float(i, t)
+                arguments.append(t)
             else:
                 x = local_ints.pop()
-                self.cpu.set_future_value_int(i, x)
+                arguments.append(x)
             expected_result += x
-        return expected_result
+        return arguments, expected_result
 
     @classmethod
     def get_funcbox(cls, cpu, func_ptr):
@@ -110,9 +111,9 @@
             looptoken = JitCellToken()
             done_number = self.cpu.get_fail_descr_number(loop.operations[-1].getdescr())
             self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
-            expected_result = self._prepare_args(args, floats, ints)
+            argvals, expected_result = self._prepare_args(args, floats, ints)
 
-            res = self.cpu.execute_token(looptoken)
+            res = self.cpu.execute_token(looptoken, *argvals)
             x = longlong.getrealfloat(cpu.get_latest_value_float(0))
             assert abs(x - expected_result) < 0.0001
 
@@ -258,8 +259,8 @@
             done_number = self.cpu.get_fail_descr_number(called_loop.operations[-1].getdescr())
             self.cpu.compile_loop(called_loop.inputargs, called_loop.operations, called_looptoken)
 
-            expected_result = self._prepare_args(args, floats, ints)
-            res = cpu.execute_token(called_looptoken)
+            argvals, expected_result = self._prepare_args(args, floats, ints)
+            res = cpu.execute_token(called_looptoken, *argvals)
             assert res.identifier == 3
             t = longlong.getrealfloat(cpu.get_latest_value_float(0))
             assert abs(t - expected_result) < 0.0001
@@ -288,8 +289,8 @@
                 self.cpu.compile_loop(loop.inputargs, loop.operations, othertoken)
 
                 # prepare call to called_loop
-                self._prepare_args(args, floats, ints)
-                res = cpu.execute_token(othertoken)
+                argvals, _ = self._prepare_args(args, floats, ints)
+                res = cpu.execute_token(othertoken, *argvals)
                 x = longlong.getrealfloat(cpu.get_latest_value_float(0))
                 assert res.identifier == 4
                 assert abs(x - expected_result) < 0.0001
diff --git a/pypy/jit/backend/test/runner_test.py b/pypy/jit/backend/test/runner_test.py
--- a/pypy/jit/backend/test/runner_test.py
+++ b/pypy/jit/backend/test/runner_test.py
@@ -34,20 +34,17 @@
                                                                 descr)
         looptoken = JitCellToken()
         self.cpu.compile_loop(inputargs, operations, looptoken)
-        j = 0
+        args = []
         for box in inputargs:
             if isinstance(box, BoxInt):
-                self.cpu.set_future_value_int(j, box.getint())
-                j += 1
+                args.append(box.getint())
             elif isinstance(box, (BoxPtr, BoxObj)):
-                self.cpu.set_future_value_ref(j, box.getref_base())
-                j += 1
+                args.append(box.getref_base())
             elif isinstance(box, BoxFloat):
-                self.cpu.set_future_value_float(j, box.getfloatstorage())
-                j += 1
+                args.append(box.getfloatstorage())
             else:
                 raise NotImplementedError(box)
-        res = self.cpu.execute_token(looptoken)
+        res = self.cpu.execute_token(looptoken, *args)
         if res is operations[-1].getdescr():
             self.guard_failed = False
         else:
@@ -108,8 +105,7 @@
         inputargs = [i0]
         looptoken = JitCellToken()
         self.cpu.compile_loop(inputargs, operations, looptoken)
-        self.cpu.set_future_value_int(0, 2)
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, 2)
         res = self.cpu.get_latest_value_int(0)
         assert res == 3
         assert fail.identifier == 1
@@ -131,8 +127,7 @@
         operations[3].setfailargs([i1])
 
         self.cpu.compile_loop(inputargs, operations, looptoken)
-        self.cpu.set_future_value_int(0, 2)
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, 2)
         assert fail.identifier == 2
         res = self.cpu.get_latest_value_int(0)
         assert res == 10
@@ -156,8 +151,7 @@
         operations[4].setfailargs([None, None, i1, None])
 
         self.cpu.compile_loop(inputargs, operations, looptoken)
-        self.cpu.set_future_value_int(0, 44)
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, 44)
         assert fail.identifier == 2
         res = self.cpu.get_latest_value_int(2)
         assert res == 10
@@ -222,8 +216,7 @@
 
         self.cpu.compile_bridge(faildescr1, [i1b], bridge, looptoken)
 
-        self.cpu.set_future_value_int(0, 2)
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, 2)
         assert fail.identifier == 2
         res = self.cpu.get_latest_value_int(0)
         assert res == 20
@@ -264,8 +257,7 @@
 
         self.cpu.compile_bridge(faildescr1, [i1b], bridge, looptoken)
 
-        self.cpu.set_future_value_int(0, 2)
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, 2)
         assert fail.identifier == 2
         res = self.cpu.get_latest_value_int(0)
         assert res == 20
@@ -288,8 +280,7 @@
         operations[3].setfailargs([None, i1, None])
         self.cpu.compile_loop(inputargs, operations, looptoken)
 
-        self.cpu.set_future_value_int(0, 2)
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, 2)
         assert fail is faildescr1
 
         count = self.cpu.get_latest_value_count()
@@ -311,8 +302,7 @@
             ResOperation(rop.FINISH, [i0], None, descr=faildescr)
             ]
         self.cpu.compile_loop([i0], operations, looptoken)
-        self.cpu.set_future_value_int(0, 99)
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, 99)
         assert fail is faildescr
         res = self.cpu.get_latest_value_int(0)
         assert res == 99
@@ -343,8 +333,7 @@
                 ]
             self.cpu.compile_loop([f0], operations, looptoken)
             value = longlong.getfloatstorage(-61.25)
-            self.cpu.set_future_value_float(0, value)
-            fail = self.cpu.execute_token(looptoken)
+            fail = self.cpu.execute_token(looptoken, value)
             assert fail is faildescr
             res = self.cpu.get_latest_value_float(0)
             assert longlong.getrealfloat(res) == -61.25
@@ -379,9 +368,7 @@
             ]
         operations[-2].setfailargs([t, z])
         cpu.compile_loop([x, y], operations, looptoken)
-        self.cpu.set_future_value_int(0, 0)
-        self.cpu.set_future_value_int(1, 10)
-        res = self.cpu.execute_token(looptoken)
+        res = self.cpu.execute_token(looptoken, 0, 10)
         assert self.cpu.get_latest_value_int(0) == 0
         assert self.cpu.get_latest_value_int(1) == 55
 
@@ -442,9 +429,7 @@
             for x, y, z in testcases:
                 excvalue = self.cpu.grab_exc_value()
                 assert not excvalue
-                self.cpu.set_future_value_int(0, x)
-                self.cpu.set_future_value_int(1, y)
-                fail = self.cpu.execute_token(looptoken)
+                fail = self.cpu.execute_token(looptoken, x, y)
                 if (z == boom) ^ reversed:
                     assert fail.identifier == 1
                 else:
@@ -1129,17 +1114,7 @@
                     assert 0
             values[index_counter] = 11
             #
-            for i, (box, val) in enumerate(zip(inputargs, values)):
-                if isinstance(box, BoxInt):
-                    self.cpu.set_future_value_int(i, val)
-                elif isinstance(box, BoxPtr):
-                    self.cpu.set_future_value_ref(i, val)
-                elif isinstance(box, BoxFloat):
-                    self.cpu.set_future_value_float(i, val)
-                else:
-                    assert 0
-            #
-            fail = self.cpu.execute_token(looptoken)
+            fail = self.cpu.execute_token(looptoken, *values)
             assert fail.identifier == 15
             #
             dstvalues = values[:]
@@ -1191,10 +1166,11 @@
 
         self.cpu.compile_bridge(faildescr1, fboxes2, bridge, looptoken)
 
+        args = []
         for i in range(len(fboxes)):
             x = 13.5 + 6.73 * i
-            self.cpu.set_future_value_float(i, longlong.getfloatstorage(x))
-        fail = self.cpu.execute_token(looptoken)
+            args.append(longlong.getfloatstorage(x))
+        fail = self.cpu.execute_token(looptoken, *args)
         assert fail.identifier == 2
         res = self.cpu.get_latest_value_float(0)
         assert longlong.getrealfloat(res) == 8.5
@@ -1244,14 +1220,12 @@
                         if test1 == -42 or combinaison[0] == 'b':
                             for test2 in [-65, -42, -11]:
                                 if test2 == -42 or combinaison[1] == 'b':
-                                    n = 0
+                                    args = []
                                     if combinaison[0] == 'b':
-                                        cpu.set_future_value_int(n, test1)
-                                        n += 1
+                                        args.append(test1)
                                     if combinaison[1] == 'b':
-                                        cpu.set_future_value_int(n, test2)
-                                        n += 1
-                                    fail = cpu.execute_token(looptoken)
+                                        args.append(test2)
+                                    fail = cpu.execute_token(looptoken, *args)
                                     #
                                     expected = compare(test1, test2)
                                     expected ^= guard_case
@@ -1303,16 +1277,14 @@
                         if test1 == -4.5 or combinaison[0] == 'b':
                             for test2 in [-6.5, -4.5, -2.5, nan]:
                                 if test2 == -4.5 or combinaison[1] == 'b':
-                                    n = 0
+                                    args = []
                                     if combinaison[0] == 'b':
-                                        cpu.set_future_value_float(
-                                            n, longlong.getfloatstorage(test1))
-                                        n += 1
+                                        args.append(
+                                            longlong.getfloatstorage(test1))
                                     if combinaison[1] == 'b':
-                                        cpu.set_future_value_float(
-                                            n, longlong.getfloatstorage(test2))
-                                        n += 1
-                                    fail = cpu.execute_token(looptoken)
+                                        args.append(
+                                            longlong.getfloatstorage(test2))
+                                    fail = cpu.execute_token(looptoken, *args)
                                     #
                                     expected = compare(test1, test2)
                                     expected ^= guard_case
@@ -1356,15 +1328,16 @@
         #
         self.cpu.compile_loop(inputargs, operations, looptoken)
         #
-        for i, box in enumerate(inputargs):
+        args = []
+        for box in inputargs:
             if isinstance(box, BoxInt):
-                self.cpu.set_future_value_int(i, box.getint())
+                args.append(box.getint())
             elif isinstance(box, BoxFloat):
-                self.cpu.set_future_value_float(i, box.getfloatstorage())
+                args.append(box.getfloatstorage())
             else:
                 assert 0
         #
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, *args)
         assert fail.identifier == 1
 
     def test_nan_and_infinity(self):
@@ -1427,10 +1400,9 @@
                         unique_testcase_list = list(set(testcase))
                         self.cpu.compile_loop(unique_testcase_list, operations,
                                               looptoken)
-                        for i, box in enumerate(unique_testcase_list):
-                            self.cpu.set_future_value_float(
-                                i, box.getfloatstorage())
-                        fail = self.cpu.execute_token(looptoken)
+                        args = [box.getfloatstorage()
+                                for box in unique_testcase_list]
+                        fail = self.cpu.execute_token(looptoken, *args)
                         if fail.identifier != 5 - (expected_id^expected):
                             if fail.identifier == 4:
                                 msg = "was taken"
@@ -1699,14 +1671,12 @@
         loop = parse(ops, self.cpu, namespace=locals())
         looptoken = JitCellToken()
         self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
-        self.cpu.set_future_value_int(0, 1)
-        self.cpu.execute_token(looptoken)
+        self.cpu.execute_token(looptoken, 1)
         assert self.cpu.get_latest_value_int(0) == 0
         assert self.cpu.get_latest_value_ref(1) == xptr
         excvalue = self.cpu.grab_exc_value()
         assert not excvalue
-        self.cpu.set_future_value_int(0, 0)
-        self.cpu.execute_token(looptoken)
+        self.cpu.execute_token(looptoken, 0)
         assert self.cpu.get_latest_value_int(0) == 1
         excvalue = self.cpu.grab_exc_value()
         assert not excvalue
@@ -1725,8 +1695,7 @@
         loop = parse(ops, self.cpu, namespace=locals())
         looptoken = JitCellToken()
         self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
-        self.cpu.set_future_value_int(0, 1)
-        self.cpu.execute_token(looptoken)
+        self.cpu.execute_token(looptoken, 1)
         assert self.cpu.get_latest_value_int(0) == 1
         excvalue = self.cpu.grab_exc_value()
         assert excvalue == yptr
@@ -1744,13 +1713,11 @@
         loop = parse(ops, self.cpu, namespace=locals())
         looptoken = JitCellToken()
         self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
-        self.cpu.set_future_value_int(0, 1)
-        self.cpu.execute_token(looptoken)
+        self.cpu.execute_token(looptoken, 1)
         assert self.cpu.get_latest_value_int(0) == 1
         excvalue = self.cpu.grab_exc_value()
         assert excvalue == xptr
-        self.cpu.set_future_value_int(0, 0)
-        self.cpu.execute_token(looptoken)
+        self.cpu.execute_token(looptoken, 0)
         assert self.cpu.get_latest_value_int(0) == 0
         excvalue = self.cpu.grab_exc_value()
         assert not excvalue
@@ -1922,16 +1889,12 @@
         ops[2].setfailargs([i1, i0])
         looptoken = JitCellToken()
         self.cpu.compile_loop([i0, i1], ops, looptoken)
-        self.cpu.set_future_value_int(0, 20)
-        self.cpu.set_future_value_int(1, 0)
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, 20, 0)
         assert fail.identifier == 0
         assert self.cpu.get_latest_value_int(0) == 20
         assert values == []
 
-        self.cpu.set_future_value_int(0, 10)
-        self.cpu.set_future_value_int(1, 1)
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, 10, 1)
         assert fail.identifier == 1
         assert self.cpu.get_latest_value_int(0) == 1
         assert self.cpu.get_latest_value_int(1) == 10
@@ -1967,16 +1930,12 @@
         ops[2].setfailargs([i1, i2, i0])
         looptoken = JitCellToken()
         self.cpu.compile_loop([i0, i1], ops, looptoken)
-        self.cpu.set_future_value_int(0, 20)
-        self.cpu.set_future_value_int(1, 0)
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, 20, 0)
         assert fail.identifier == 0
         assert self.cpu.get_latest_value_int(0) == 42
         assert values == []
 
-        self.cpu.set_future_value_int(0, 10)
-        self.cpu.set_future_value_int(1, 1)
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, 10, 1)
         assert fail.identifier == 1
         assert self.cpu.get_latest_value_int(0) == 1
         assert self.cpu.get_latest_value_int(1) == 42
@@ -2013,17 +1972,13 @@
         ops[2].setfailargs([i1, f2, i0])
         looptoken = JitCellToken()
         self.cpu.compile_loop([i0, i1], ops, looptoken)
-        self.cpu.set_future_value_int(0, 20)
-        self.cpu.set_future_value_int(1, 0)
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, 20, 0)
         assert fail.identifier == 0
         x = self.cpu.get_latest_value_float(0)
         assert longlong.getrealfloat(x) == 42.5
         assert values == []
 
-        self.cpu.set_future_value_int(0, 10)
-        self.cpu.set_future_value_int(1, 1)
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, 10, 1)
         assert fail.identifier == 1
         assert self.cpu.get_latest_value_int(0) == 1
         x = self.cpu.get_latest_value_float(1)
@@ -2058,8 +2013,7 @@
         ops[1].setfailargs([i1, i2])
         looptoken = JitCellToken()
         self.cpu.compile_loop([i1], ops, looptoken)
-        self.cpu.set_future_value_int(0, ord('G'))
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, ord('G'))
         assert fail.identifier == 0
         assert self.cpu.get_latest_value_int(0) == ord('g')
 
@@ -2118,12 +2072,12 @@
         ops[1].setfailargs([])
         looptoken = JitCellToken()
         self.cpu.compile_loop([i0, i1, i2, i3], ops, looptoken)
-        self.cpu.set_future_value_int(0, rffi.cast(lltype.Signed, raw))
-        self.cpu.set_future_value_int(1, 2)
-        self.cpu.set_future_value_int(2, 4)
-        self.cpu.set_future_value_int(3, rffi.cast(lltype.Signed, fn))
+        args = [rffi.cast(lltype.Signed, raw),
+                2,
+                4,
+                rffi.cast(lltype.Signed, fn)]
         assert glob.lst == []
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, *args)
         assert fail.identifier == 0
         assert len(glob.lst) > 0
         lltype.free(raw, flavor='raw')
@@ -2176,9 +2130,8 @@
         self.cpu.compile_loop([i1, i2], ops, looptoken)
 
         buffer = lltype.malloc(rffi.CCHARP.TO, buflen, flavor='raw')
-        self.cpu.set_future_value_int(0, buflen)
-        self.cpu.set_future_value_int(1, rffi.cast(lltype.Signed, buffer))
-        fail = self.cpu.execute_token(looptoken)
+        args = [buflen, rffi.cast(lltype.Signed, buffer)]
+        fail = self.cpu.execute_token(looptoken, *args)
         assert fail.identifier == 0
         assert self.cpu.get_latest_value_int(0) == len(cwd)
         assert rffi.charp2strn(buffer, buflen) == cwd
@@ -2197,9 +2150,7 @@
         looptoken = JitCellToken()
         self.cpu.compile_loop([i0, i1], ops, looptoken)
 
-        self.cpu.set_future_value_int(0, -42)
-        self.cpu.set_future_value_int(1, 9)
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, -42, 9)
         assert fail.identifier == 0
         assert self.cpu.get_latest_value_int(0) == -42
         print 'step 1 ok'
@@ -2208,9 +2159,7 @@
         # mark as failing
         self.cpu.invalidate_loop(looptoken)
 
-        self.cpu.set_future_value_int(0, -42)
-        self.cpu.set_future_value_int(1, 9)
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, -42, 9)
         assert fail is faildescr
         assert self.cpu.get_latest_value_int(0) == 9
         print 'step 2 ok'
@@ -2226,9 +2175,7 @@
         ops[0].setfailargs([])
         self.cpu.compile_bridge(faildescr, [i2], ops, looptoken)
 
-        self.cpu.set_future_value_int(0, -42)
-        self.cpu.set_future_value_int(1, 9)
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, -42, 9)
         assert fail.identifier == 3
         assert self.cpu.get_latest_value_int(0) == 9
         print 'step 3 ok'
@@ -2237,9 +2184,7 @@
         # mark as failing again
         self.cpu.invalidate_loop(looptoken)
 
-        self.cpu.set_future_value_int(0, -42)
-        self.cpu.set_future_value_int(1, 9)
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, -42, 9)
         assert fail is faildescr2
         print 'step 4 ok'
         print '-'*79
@@ -2448,9 +2393,8 @@
         FakeJitDriverSD.portal_calldescr = self.cpu.calldescrof(
             lltype.Ptr(lltype.FuncType(ARGS, RES)), ARGS, RES,
             EffectInfo.MOST_GENERAL)
-        for i in range(10):
-            self.cpu.set_future_value_int(i, i+1)
-        res = self.cpu.execute_token(looptoken)
+        args = [i+1 for i in range(10)]
+        res = self.cpu.execute_token(looptoken, *args)
         assert self.cpu.get_latest_value_int(0) == 55
         ops = '''
         [i0, i1, i2, i3, i4, i5, i6, i7, i8, i9]
@@ -2462,9 +2406,8 @@
         loop = parse(ops, namespace=locals())
         othertoken = JitCellToken()
         self.cpu.compile_loop(loop.inputargs, loop.operations, othertoken)
-        for i in range(10):
-            self.cpu.set_future_value_int(i, i+1)
-        res = self.cpu.execute_token(othertoken)
+        args = [i+1 for i in range(10)]
+        res = self.cpu.execute_token(othertoken, *args)
         assert self.cpu.get_latest_value_int(0) == 13
         assert called
 
@@ -2499,9 +2442,9 @@
         looptoken = JitCellToken()
         looptoken.outermost_jitdriver_sd = FakeJitDriverSD()
         self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
-        self.cpu.set_future_value_float(0, longlong.getfloatstorage(1.2))
-        self.cpu.set_future_value_float(1, longlong.getfloatstorage(2.3))
-        res = self.cpu.execute_token(looptoken)
+        args = [longlong.getfloatstorage(1.2),
+                longlong.getfloatstorage(2.3)]
+        res = self.cpu.execute_token(looptoken, *args)
         x = self.cpu.get_latest_value_float(0)
         assert longlong.getrealfloat(x) == 1.2 + 2.3
         ops = '''
@@ -2513,9 +2456,9 @@
         loop = parse(ops, namespace=locals())
         othertoken = JitCellToken()
         self.cpu.compile_loop(loop.inputargs, loop.operations, othertoken)
-        self.cpu.set_future_value_float(0, longlong.getfloatstorage(1.2))
-        self.cpu.set_future_value_float(1, longlong.getfloatstorage(3.2))
-        res = self.cpu.execute_token(othertoken)
+        args = [longlong.getfloatstorage(1.2),
+                longlong.getfloatstorage(3.2)]
+        res = self.cpu.execute_token(othertoken, *args)
         x = self.cpu.get_latest_value_float(0)
         assert longlong.getrealfloat(x) == 13.5
         assert called
@@ -2526,9 +2469,9 @@
         try:
             othertoken = JitCellToken()
             self.cpu.compile_loop(loop.inputargs, loop.operations, othertoken)
-            self.cpu.set_future_value_float(0, longlong.getfloatstorage(1.2))
-            self.cpu.set_future_value_float(1, longlong.getfloatstorage(3.2))
-            res = self.cpu.execute_token(othertoken)
+            args = [longlong.getfloatstorage(1.2),
+                    longlong.getfloatstorage(3.2)]
+            res = self.cpu.execute_token(othertoken, *args)
             x = self.cpu.get_latest_value_float(0)
             assert longlong.getrealfloat(x) == 1.2 + 3.2
             assert not called
@@ -2589,9 +2532,9 @@
         looptoken = JitCellToken()
         looptoken.outermost_jitdriver_sd = FakeJitDriverSD()
         self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
-        self.cpu.set_future_value_float(0, longlong.getfloatstorage(1.25))
-        self.cpu.set_future_value_float(1, longlong.getfloatstorage(2.35))
-        res = self.cpu.execute_token(looptoken)
+        args = [longlong.getfloatstorage(1.25),
+                longlong.getfloatstorage(2.35)]
+        res = self.cpu.execute_token(looptoken, *args)
         x = self.cpu.get_latest_value_float(0)
         assert longlong.getrealfloat(x) == 1.25 + 2.35
         assert not called
@@ -2607,9 +2550,9 @@
         self.cpu.compile_loop(loop.inputargs, loop.operations, othertoken)
 
         # normal call_assembler: goes to looptoken
-        self.cpu.set_future_value_float(0, longlong.getfloatstorage(1.25))
-        self.cpu.set_future_value_float(1, longlong.getfloatstorage(3.25))
-        res = self.cpu.execute_token(othertoken)
+        args = [longlong.getfloatstorage(1.25),
+                longlong.getfloatstorage(3.25)]
+        res = self.cpu.execute_token(othertoken, *args)
         x = self.cpu.get_latest_value_float(0)
         assert longlong.getrealfloat(x) == 13.5
         assert called
@@ -2629,10 +2572,9 @@
         self.cpu.redirect_call_assembler(looptoken, looptoken2)
 
         # now, our call_assembler should go to looptoken2
-        self.cpu.set_future_value_float(0, longlong.getfloatstorage(6.0))
-        self.cpu.set_future_value_float(1, longlong.getfloatstorage(1.5))
-                                                       # 6.0-1.5 == 1.25+3.25
-        res = self.cpu.execute_token(othertoken)
+        args = [longlong.getfloatstorage(6.0),
+                longlong.getfloatstorage(1.5)]         # 6.0-1.5 == 1.25+3.25
+        res = self.cpu.execute_token(othertoken, *args)
         x = self.cpu.get_latest_value_float(0)
         assert longlong.getrealfloat(x) == 13.5
         assert called
@@ -2986,8 +2928,7 @@
         looptoken = JitCellToken()
         self.cpu.compile_loop(inputargs, operations, looptoken)
         # overflowing value:
-        self.cpu.set_future_value_int(0, sys.maxint // 4 + 1)
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, sys.maxint // 4 + 1)
         assert fail.identifier == excdescr.identifier
 
     def test_compile_loop_with_target(self):
@@ -3014,8 +2955,7 @@
         operations[6].setfailargs([i1])
 
         self.cpu.compile_loop(inputargs, operations, looptoken)
-        self.cpu.set_future_value_int(0, 2)
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, 2)
         assert fail.identifier == 2
         res = self.cpu.get_latest_value_int(0)
         assert res == 10
@@ -3027,8 +2967,7 @@
             ]
         self.cpu.compile_bridge(faildescr, inputargs, operations, looptoken)
         
-        self.cpu.set_future_value_int(0, 2)
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, 2)
         assert fail.identifier == 3
         res = self.cpu.get_latest_value_int(0)
         assert res == -10
@@ -3108,13 +3047,13 @@
         self.cpu.compile_bridge(faildescr1, inputargs, operations, looptoken1)
 
         looptoken2 = JitCellToken()
-        inputargs = []
+        inputargs = [BoxInt()]
         operations = [
             ResOperation(rop.JUMP, [ConstInt(0)], None, descr=targettoken1),
             ]
         self.cpu.compile_loop(inputargs, operations, looptoken2)
 
-        fail = self.cpu.execute_token(looptoken2)
+        fail = self.cpu.execute_token(looptoken2, -9)
         assert fail.identifier == 42
 
 
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
@@ -6,6 +6,7 @@
 from pypy.jit.metainterp.history import BoxInt, ConstInt, JitCellToken
 from pypy.jit.metainterp.history import BoxPtr, ConstPtr, TargetToken
 from pypy.jit.metainterp.history import BoxFloat, ConstFloat, Const
+from pypy.jit.metainterp.history import INT, FLOAT
 from pypy.jit.metainterp.resoperation import ResOperation, rop
 from pypy.jit.metainterp.executor import execute_nonspec
 from pypy.jit.metainterp.resoperation import opname
@@ -616,8 +617,13 @@
             return self.loop._jitcelltoken
         if not hasattr(self, '_initialjumploop_celltoken'):
             self._initialjumploop_celltoken = JitCellToken()
-            self.cpu.compile_loop(self.startvars[:],
-                                  [ResOperation(rop.JUMP, self.startvars[:], None,
+            args = []
+            for box in self.startvars:
+                if box not in self.loop.inputargs:
+                    box = box.constbox()
+                args.append(box)
+            self.cpu.compile_loop(self.loop.inputargs,
+                                  [ResOperation(rop.JUMP, args, None,
                                                 descr=self.loop._targettoken)],
                                   self._initialjumploop_celltoken)
         return self._initialjumploop_celltoken
@@ -649,14 +655,8 @@
         exc = cpu.grab_exc_value()
         assert not exc
 
-        for i, box in enumerate(self.startvars):
-            if isinstance(box, BoxInt):
-                cpu.set_future_value_int(i, box.value)
-            elif isinstance(box, BoxFloat):
-                cpu.set_future_value_float(i, box.value)
-            else:
-                raise NotImplementedError(box)
-        fail = cpu.execute_token(self.runjitcelltoken())
+        arguments = [box.value for box in self.loop.inputargs]
+        fail = cpu.execute_token(self.runjitcelltoken(), *arguments)
         assert fail is self.should_fail_by.getdescr()
         for i, v in enumerate(self.get_fail_args()):
             if isinstance(v, (BoxFloat, ConstFloat)):
@@ -717,10 +717,21 @@
             # to build_bridge().)
 
             # First make up the other loop...
-            subset = bridge_builder.subset_of_intvars(r)
-            subset = [i for i in subset if i in fail_args]
-            if len(subset) == 0:
-                return False
+            #
+            # New restriction: must have the same argument count and types
+            # as the original loop
+            subset = []
+            for box in self.loop.inputargs:
+                srcbox = r.choice(fail_args)
+                if srcbox.type != box.type:
+                    if box.type == INT:
+                        srcbox = ConstInt(r.random_integer())
+                    elif box.type == FLOAT:
+                        srcbox = ConstFloat(r.random_float_storage())
+                    else:
+                        raise AssertionError(box.type)
+                subset.append(srcbox)
+            #
             args = [x.clonebox() for x in subset]
             rl = RandomLoop(self.builder.cpu, self.builder.fork,
                                      r, args)
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
@@ -38,6 +38,7 @@
 from pypy.jit.backend.x86.jump import remap_frame_layout
 from pypy.jit.codewriter.effectinfo import EffectInfo
 from pypy.jit.codewriter import longlong
+from pypy.rlib.rarithmetic import intmask
 
 # darwin requires the stack to be 16 bytes aligned on calls. Same for gcc 4.5.0,
 # better safe than sorry
@@ -309,12 +310,11 @@
                 mc.MOVSD_sx(8*i, i)     # xmm0 to xmm7
         #
         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)
+            mc.PUSH_r(esp.value)
         elif IS_X86_64:
-            mc.LEA_rb(edi.value, +16)
+            mc.MOV_rr(edi.value, esp.value)
         #
         # esp is now aligned to a multiple of 16 again
         mc.CALL(imm(slowpathaddr))
@@ -325,7 +325,7 @@
         jnz_location = mc.get_relative_pos()
         #
         if IS_X86_32:
-            mc.ADD_ri(esp.value, 2*WORD)
+            mc.ADD_ri(esp.value, 2*WORD)    # cancel the two PUSHes above
         elif IS_X86_64:
             # restore the registers
             for i in range(7, -1, -1):
@@ -421,10 +421,8 @@
 
     def assemble_loop(self, loopname, inputargs, operations, looptoken, log):
         '''adds the following attributes to looptoken:
-               _x86_loop_code       (an integer giving an address)
-               _x86_bootstrap_code  (an integer giving an address)
-               _x86_direct_bootstrap_code  ( "    "     "    "   )
-               _x86_arglocs
+               _x86_function_addr   (address of the generated func, as an int)
+               _x86_loop_code       (debug: addr of the start of the ResOps)
                _x86_debug_checksum
         '''
         # XXX this function is too longish and contains some code
@@ -445,12 +443,12 @@
             operations = self._inject_debugging_code(looptoken, operations)
 
         regalloc = RegAlloc(self, self.cpu.translate_support_code)
-        arglocs, operations = regalloc.prepare_loop(inputargs, operations,
-                                                    looptoken, clt.allgcrefs)
-        looptoken._x86_arglocs = arglocs
-
-        bootstrappos = self.mc.get_relative_pos()
-        stackadjustpos = self._assemble_bootstrap_code(inputargs, arglocs)
+        #
+        self._call_header_with_stack_check()
+        stackadjustpos = self._patchable_stackadjust()
+        clt._debug_nbargs = len(inputargs)
+        operations = regalloc.prepare_loop(inputargs, operations,
+                                           looptoken, clt.allgcrefs)
         looppos = self.mc.get_relative_pos()
         looptoken._x86_loop_code = looppos
         clt.frame_depth = -1     # temporarily
@@ -458,19 +456,17 @@
         frame_depth, param_depth = self._assemble(regalloc, operations)
         clt.frame_depth = frame_depth
         clt.param_depth = param_depth
-
-        directbootstrappos = self.mc.get_relative_pos()
-        self._assemble_bootstrap_direct_call(arglocs, looppos,
-                                             frame_depth+param_depth)
+        #
+        size_excluding_failure_stuff = self.mc.get_relative_pos()
         self.write_pending_failure_recoveries()
-        fullsize = self.mc.get_relative_pos()
+        full_size = self.mc.get_relative_pos()
         #
         rawstart = self.materialize_loop(looptoken)
         debug_start("jit-backend-addr")
         debug_print("Loop %d (%s) has address %x to %x (bootstrap %x)" % (
             looptoken.number, loopname,
             rawstart + looppos,
-            rawstart + directbootstrappos,
+            rawstart + size_excluding_failure_stuff,
             rawstart))
         debug_stop("jit-backend-addr")
         self._patch_stackadjust(rawstart + stackadjustpos,
@@ -481,18 +477,17 @@
         if not we_are_translated():
             # used only by looptoken.dump() -- useful in tests
             looptoken._x86_rawstart = rawstart
-            looptoken._x86_fullsize = fullsize
+            looptoken._x86_fullsize = full_size
             looptoken._x86_ops_offset = ops_offset
+        looptoken._x86_function_addr = rawstart
 
-        looptoken._x86_bootstrap_code = rawstart + bootstrappos
-        looptoken._x86_direct_bootstrap_code = rawstart + directbootstrappos
         self.fixup_target_tokens(rawstart)
         self.teardown()
         # oprofile support
         if self.cpu.profile_agent is not None:
             name = "Loop # %s: %s" % (looptoken.number, loopname)
             self.cpu.profile_agent.native_code_written(name,
-                                                       rawstart, fullsize)
+                                                       rawstart, full_size)
         return ops_offset
 
     def assemble_bridge(self, faildescr, inputargs, operations,
@@ -802,152 +797,21 @@
             self.mc.MOV_ri(ebx.value, rst)           # MOV ebx, rootstacktop
             self.mc.SUB_mi8((ebx.value, 0), 2*WORD)  # SUB [ebx], 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)
-        # XXX pushing ebx esi and edi is a bit pointless, since we store
-        #     all regsiters anyway, for the case of guard_not_forced
-        # XXX this can be improved greatly. Right now it'll behave like
-        #     a normal call
-        nonfloatlocs, floatlocs = arglocs
-        self._call_header_with_stack_check()
-        self.mc.LEA_rb(esp.value, self._get_offset_of_ebp_from_esp(stackdepth))
-        offset = 2 * WORD
-        tmp = eax
-        xmmtmp = xmm0
-        for i in range(len(nonfloatlocs)):
-            loc = nonfloatlocs[i]
-            if loc is not None:
-                if isinstance(loc, RegLoc):
-                    assert not loc.is_xmm
-                    self.mc.MOV_rb(loc.value, offset)
-                else:
-                    self.mc.MOV_rb(tmp.value, offset)
-                    self.mc.MOV(loc, tmp)
-                offset += WORD
-            loc = floatlocs[i]
-            if loc is not None:
-                if isinstance(loc, RegLoc):
-                    assert loc.is_xmm
-                    self.mc.MOVSD_xb(loc.value, offset)
-                else:
-                    self.mc.MOVSD_xb(xmmtmp.value, offset)
-                    assert isinstance(loc, StackLoc)
-                    self.mc.MOVSD_bx(loc.value, xmmtmp.value)
-                offset += 2 * WORD
-        endpos = self.mc.get_relative_pos() + 5
-        self.mc.JMP_l(jmppos - endpos)
-        assert endpos == self.mc.get_relative_pos()
-
-    def _assemble_bootstrap_direct_call_64(self, arglocs, jmppos, stackdepth):
-        # XXX: Very similar to _emit_call_64
-
-        src_locs = []
-        dst_locs = []
-        xmm_src_locs = []
-        xmm_dst_locs = []
-        get_from_stack = []
-
-        # In reverse order for use with pop()
-        unused_gpr = [r9, r8, ecx, edx, esi, edi]
-        unused_xmm = [xmm7, xmm6, xmm5, xmm4, xmm3, xmm2, xmm1, xmm0]
-
-        nonfloatlocs, floatlocs = arglocs
-        self._call_header_with_stack_check()
-        self.mc.LEA_rb(esp.value, self._get_offset_of_ebp_from_esp(stackdepth))
-
-        # The lists are padded with Nones
-        assert len(nonfloatlocs) == len(floatlocs)
-
-        for i in range(len(nonfloatlocs)):
-            loc = nonfloatlocs[i]
-            if loc is not None:
-                if len(unused_gpr) > 0:
-                    src_locs.append(unused_gpr.pop())
-                    dst_locs.append(loc)
-                else:
-                    get_from_stack.append((loc, False))
-
-            floc = floatlocs[i]
-            if floc is not None:
-                if len(unused_xmm) > 0:
-                    xmm_src_locs.append(unused_xmm.pop())
-                    xmm_dst_locs.append(floc)
-                else:
-                    get_from_stack.append((floc, True))
-
-        remap_frame_layout(self, src_locs, dst_locs, X86_64_SCRATCH_REG)
-        remap_frame_layout(self, xmm_src_locs, xmm_dst_locs, X86_64_XMM_SCRATCH_REG)
-
-        for i in range(len(get_from_stack)):
-            loc, is_xmm = get_from_stack[i]
-            if is_xmm:
-                self.mc.MOVSD_xb(X86_64_XMM_SCRATCH_REG.value, (2 + i) * WORD)
-                self.mc.MOVSD(loc, X86_64_XMM_SCRATCH_REG)
-            else:
-                self.mc.MOV_rb(X86_64_SCRATCH_REG.value, (2 + i) * WORD)
-                # XXX: We're assuming that "loc" won't require regloc to
-                # clobber the scratch register
-                self.mc.MOV(loc, X86_64_SCRATCH_REG)
-
-        endpos = self.mc.get_relative_pos() + 5
-        self.mc.JMP_l(jmppos - endpos)
-        assert endpos == self.mc.get_relative_pos()
-
     def redirect_call_assembler(self, oldlooptoken, newlooptoken):
         # some minimal sanity checking
-        oldnonfloatlocs, oldfloatlocs = oldlooptoken._x86_arglocs
-        newnonfloatlocs, newfloatlocs = newlooptoken._x86_arglocs
-        assert len(oldnonfloatlocs) == len(newnonfloatlocs)
-        assert len(oldfloatlocs) == len(newfloatlocs)
+        old_nbargs = oldlooptoken.compiled_loop_token._debug_nbargs
+        new_nbargs = newlooptoken.compiled_loop_token._debug_nbargs
+        assert old_nbargs == new_nbargs
         # we overwrite the instructions at the old _x86_direct_bootstrap_code
         # to start with a JMP to the new _x86_direct_bootstrap_code.
         # Ideally we should rather patch all existing CALLs, but well.
-        oldadr = oldlooptoken._x86_direct_bootstrap_code
-        target = newlooptoken._x86_direct_bootstrap_code
+        oldadr = oldlooptoken._x86_function_addr
+        target = newlooptoken._x86_function_addr
         mc = codebuf.MachineCodeBlockWrapper()
         mc.JMP(imm(target))
+        assert mc.get_relative_pos() <= 13  # keep in sync with prepare_loop()
         mc.copy_to_raw_memory(oldadr)
 
-    def _assemble_bootstrap_code(self, inputargs, arglocs):
-        nonfloatlocs, floatlocs = arglocs
-        self._call_header()
-        stackadjustpos = self._patchable_stackadjust()
-        tmp = eax
-        xmmtmp = xmm0
-        self.mc.begin_reuse_scratch_register()
-        for i in range(len(nonfloatlocs)):
-            loc = nonfloatlocs[i]
-            if loc is None:
-                continue
-            if isinstance(loc, RegLoc):
-                target = loc
-            else:
-                target = tmp
-            if inputargs[i].type == REF:
-                adr = self.fail_boxes_ptr.get_addr_for_num(i)
-                self.mc.MOV(target, heap(adr))
-                self.mc.MOV(heap(adr), imm0)
-            else:
-                adr = self.fail_boxes_int.get_addr_for_num(i)
-                self.mc.MOV(target, heap(adr))
-            if target is not loc:
-                assert isinstance(loc, StackLoc)
-                self.mc.MOV_br(loc.value, target.value)
-        for i in range(len(floatlocs)):
-            loc = floatlocs[i]
-            if loc is None:
-                continue
-            adr = self.fail_boxes_float.get_addr_for_num(i)
-            if isinstance(loc, RegLoc):
-                self.mc.MOVSD(loc, heap(adr))
-            else:
-                self.mc.MOVSD(xmmtmp, heap(adr))
-                assert isinstance(loc, StackLoc)
-                self.mc.MOVSD_bx(loc.value, xmmtmp.value)
-        self.mc.end_reuse_scratch_register()
-        return stackadjustpos
-
     def dump(self, text):
         if not self.verbose:
             return
@@ -974,7 +838,7 @@
         if isinstance(loc, RegLoc) and loc.is_xmm:
             self.mc.SUB_ri(esp.value, 8)   # = size of doubles
             self.mc.MOVSD_sx(0, loc.value)
-        elif WORD == 4 and isinstance(loc, StackLoc) and loc.width == 8:
+        elif WORD == 4 and isinstance(loc, StackLoc) and loc.get_width() == 8:
             # XXX evil trick
             self.mc.PUSH_b(get_ebp_ofs(loc.position))
             self.mc.PUSH_b(get_ebp_ofs(loc.position + 1))
@@ -985,13 +849,25 @@
         if isinstance(loc, RegLoc) and loc.is_xmm:
             self.mc.MOVSD_xs(loc.value, 0)
             self.mc.ADD_ri(esp.value, 8)   # = size of doubles
-        elif WORD == 4 and isinstance(loc, StackLoc) and loc.width == 8:
+        elif WORD == 4 and isinstance(loc, StackLoc) and loc.get_width() == 8:
             # XXX evil trick
             self.mc.POP_b(get_ebp_ofs(loc.position + 1))
             self.mc.POP_b(get_ebp_ofs(loc.position))
         else:
             self.mc.POP(loc)
 
+    def regalloc_immedmem2mem(self, from_loc, to_loc):
+        # move a ConstFloatLoc directly to a StackLoc, as two MOVs
+        # (even on x86-64, because the immediates are encoded as 32 bits)
+        assert isinstance(from_loc, ConstFloatLoc)
+        assert isinstance(to_loc,   StackLoc)
+        low_part  = rffi.cast(rffi.CArrayPtr(rffi.INT), from_loc.value)[0]
+        high_part = rffi.cast(rffi.CArrayPtr(rffi.INT), from_loc.value)[1]
+        low_part  = intmask(low_part)
+        high_part = intmask(high_part)
+        self.mc.MOV_bi(to_loc.value,     low_part)
+        self.mc.MOV_bi(to_loc.value + 4, high_part)
+
     def regalloc_perform(self, op, arglocs, resloc):
         genop_list[op.getopnum()](self, op, arglocs, resloc)
 
@@ -1143,18 +1019,18 @@
                     self.mc.MOVSD_sx(p, loc.value)
                 else:
                     self.mc.MOV_sr(p, loc.value)
-            p += round_up_to_4(loc.width)
+            p += loc.get_width()
         p = 0
         for i in range(start, n):
             loc = arglocs[i]
             if not isinstance(loc, RegLoc):
-                if loc.width == 8:
+                if loc.get_width() == 8:
                     self.mc.MOVSD(xmm0, loc)
                     self.mc.MOVSD_sx(p, xmm0.value)
                 else:
                     self.mc.MOV(tmp, loc)
                     self.mc.MOV_sr(p, tmp.value)
-            p += round_up_to_4(loc.width)
+            p += loc.get_width()
         self._regalloc.reserve_param(p//WORD)
         # x is a location
         self.mc.CALL(x)
@@ -1891,10 +1767,10 @@
     DESCR_INT       = 0x01
     DESCR_FLOAT     = 0x02
     DESCR_SPECIAL   = 0x03
-    # XXX: 4*8 works on i386, should we optimize for that case?
-    CODE_FROMSTACK  = 4*16
+    CODE_FROMSTACK  = 4 * (8 + 8*IS_X86_64)
     CODE_STOP       = 0 | DESCR_SPECIAL
     CODE_HOLE       = 4 | DESCR_SPECIAL
+    CODE_INPUTARG   = 8 | DESCR_SPECIAL
 
     def write_failure_recovery_description(self, mc, failargs, locs):
         for i in range(len(failargs)):
@@ -1910,7 +1786,11 @@
                     raise AssertionError("bogus kind")
                 loc = locs[i]
                 if isinstance(loc, StackLoc):
-                    n = self.CODE_FROMSTACK//4 + loc.position
+                    pos = loc.position
+                    if pos < 0:
+                        mc.writechar(chr(self.CODE_INPUTARG))
+                        pos = ~pos
+                    n = self.CODE_FROMSTACK//4 + pos
                 else:
                     assert isinstance(loc, RegLoc)
                     n = loc.value
@@ -1930,6 +1810,7 @@
         descr_to_box_type = [REF, INT, FLOAT]
         bytecode = rffi.cast(rffi.UCHARP, bytecode)
         arglocs = []
+        code_inputarg = False
         while 1:
             # decode the next instruction from the bytecode
             code = rffi.cast(lltype.Signed, bytecode[0])
@@ -1948,11 +1829,17 @@
                             break
                 kind = code & 3
                 code = (code - self.CODE_FROMSTACK) >> 2
+                if code_inputarg:
+                    code = ~code
+                    code_inputarg = False
                 loc = X86FrameManager.frame_pos(code, descr_to_box_type[kind])
             elif code == self.CODE_STOP:
                 break
             elif code == self.CODE_HOLE:
                 continue
+            elif code == self.CODE_INPUTARG:
+                code_inputarg = True
+                continue
             else:
                 # 'code' identifies a register
                 kind = code & 3
@@ -1968,6 +1855,7 @@
     def grab_frame_values(self, bytecode, frame_addr, allregisters):
         # no malloc allowed here!!
         self.fail_ebp = allregisters[16 + ebp.value]
+        code_inputarg = False
         num = 0
         value_hi = 0
         while 1:
@@ -1988,6 +1876,9 @@
                 # load the value from the stack
                 kind = code & 3
                 code = (code - self.CODE_FROMSTACK) >> 2
+                if code_inputarg:
+                    code = ~code
+                    code_inputarg = False
                 stackloc = frame_addr + get_ebp_ofs(code)
                 value = rffi.cast(rffi.LONGP, stackloc)[0]
                 if kind == self.DESCR_FLOAT and WORD == 4:
@@ -2000,6 +1891,9 @@
                     if code == self.CODE_HOLE:
                         num += 1
                         continue
+                    if code == self.CODE_INPUTARG:
+                        code_inputarg = True
+                        continue
                     assert code == self.CODE_STOP
                     break
                 code >>= 2
@@ -2104,9 +1998,9 @@
         # returns in eax the fail_index
 
         # now we return from the complete frame, which starts from
-        # _assemble_bootstrap_code().  The LEA in _call_footer below throws
-        # away most of the frame, including all the PUSHes that we did just
-        # above.
+        # _call_header_with_stack_check().  The LEA in _call_footer below
+        # throws away most of the frame, including all the PUSHes that we
+        # did just above.
 
         self._call_footer()
         rawstart = mc.materialize(self.cpu.asmmemmgr, [])
@@ -2189,7 +2083,7 @@
                         argtypes=op.getdescr().get_arg_types(),
                         callconv=op.getdescr().get_call_conv())
 
-        if IS_X86_32 and isinstance(resloc, StackLoc) and resloc.width == 8:
+        if IS_X86_32 and isinstance(resloc, StackLoc) and resloc.type == FLOAT:
             # a float or a long long return
             if op.getdescr().get_return_type() == 'L':
                 self.mc.MOV_br(resloc.value, eax.value)      # long long
@@ -2354,10 +2248,10 @@
         self.mc.MOV_bi(FORCE_INDEX_OFS, fail_index)
         descr = op.getdescr()
         assert isinstance(descr, JitCellToken)
-        assert len(arglocs) - 2 == len(descr._x86_arglocs[0])
+        assert len(arglocs) - 2 == descr.compiled_loop_token._debug_nbargs
         #
-        # Write a call to the direct_bootstrap_code of the target assembler
-        self._emit_call(fail_index, imm(descr._x86_direct_bootstrap_code),
+        # Write a call to the target assembler
+        self._emit_call(fail_index, imm(descr._x86_function_addr),
                         arglocs, 2, tmp=eax)
         if op.result is None:
             assert result_loc is None
@@ -2588,6 +2482,14 @@
                     self.gcrootmap_retaddr_forced = -1
 
     def closing_jump(self, target_token):
+        # The backend's logic assumes that the target code is in a piece of
+        # assembler that was also called with the same number of arguments,
+        # so that the locations [ebp+8..] of the input arguments are valid
+        # stack locations both before and after the jump.
+        my_nbargs = self.current_clt._debug_nbargs
+        target_nbargs = target_token._x86_clt._debug_nbargs
+        assert my_nbargs == target_nbargs
+        #
         target = target_token._x86_loop_code
         if target_token in self.target_tokens_currently_compiling:
             curpos = self.mc.get_relative_pos() + 5
@@ -2666,11 +2568,6 @@
         num = getattr(rop, opname.upper())
         genop_list[num] = value
 
-def round_up_to_4(size):
-    if size < 4:
-        return 4
-    return size
-
 # XXX: ri386 migration shims:
 def addr_add(reg_or_imm1, reg_or_imm2, offset=0, scale=0):
     return AddressLoc(reg_or_imm1, reg_or_imm2, scale, offset)
diff --git a/pypy/jit/backend/x86/jump.py b/pypy/jit/backend/x86/jump.py
--- a/pypy/jit/backend/x86/jump.py
+++ b/pypy/jit/backend/x86/jump.py
@@ -1,6 +1,6 @@
 import sys
 from pypy.tool.pairtype import extendabletype
-from pypy.jit.backend.x86.regloc import ImmedLoc, StackLoc
+from pypy.jit.backend.x86.regloc import ImmediateAssemblerLocation, StackLoc
 
 def remap_frame_layout(assembler, src_locations, dst_locations, tmpreg):
     pending_dests = len(dst_locations)
@@ -12,7 +12,7 @@
         srccount[key] = 0
     for i in range(len(dst_locations)):
         src = src_locations[i]
-        if isinstance(src, ImmedLoc):
+        if isinstance(src, ImmediateAssemblerLocation):
             continue
         key = src._getregkey()
         if key in srccount:
@@ -31,7 +31,7 @@
                 srccount[key] = -1       # means "it's done"
                 pending_dests -= 1
                 src = src_locations[i]
-                if not isinstance(src, ImmedLoc):
+                if not isinstance(src, ImmediateAssemblerLocation):
                     key = src._getregkey()
                     if key in srccount:
                         srccount[key] -= 1
@@ -66,6 +66,13 @@
 
 def _move(assembler, src, dst, tmpreg):
     if dst.is_memory_reference() and src.is_memory_reference():
+        if isinstance(src, ImmediateAssemblerLocation):
+            assembler.regalloc_immedmem2mem(src, dst)
+            return
+        if tmpreg is None:
+            assembler.regalloc_push(src)
+            assembler.regalloc_pop(dst)
+            return
         assembler.regalloc_mov(src, tmpreg)
         src = tmpreg
     assembler.regalloc_mov(src, dst)
@@ -87,7 +94,7 @@
         dstloc = dst_locations2[i]
         if isinstance(loc, StackLoc):
             key = loc._getregkey()
-            if (key in dst_keys or (loc.width > WORD and
+            if (key in dst_keys or (loc.get_width() > WORD and
                                     (key + WORD) in dst_keys)):
                 assembler.regalloc_push(loc)
                 extrapushes.append(dstloc)
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
@@ -28,7 +28,7 @@
 class X86RegisterManager(RegisterManager):
 
     box_types = [INT, REF]
-    all_regs = [eax, ecx, edx, ebx, esi, edi]
+    all_regs = [ecx, eax, edx, ebx, esi, edi]
     no_lower_byte_regs = [esi, edi]
     save_around_call_regs = [eax, edx, ecx]
     frame_reg = ebp
@@ -60,7 +60,7 @@
 
 class X86_64_RegisterManager(X86RegisterManager):
     # r11 omitted because it's used as scratch
-    all_regs = [eax, ecx, edx, ebx, esi, edi, r8, r9, r10, r12, r13, r14, r15]
+    all_regs = [ecx, eax, edx, ebx, esi, edi, r8, r9, r10, r12, r13, r14, r15]
     no_lower_byte_regs = []
     save_around_call_regs = [eax, ecx, edx, esi, edi, r8, r9, r10]
 
@@ -130,9 +130,9 @@
     @staticmethod
     def frame_pos(i, box_type):
         if IS_X86_32 and box_type == FLOAT:
-            return StackLoc(i, get_ebp_ofs(i+1), 2, box_type)
+            return StackLoc(i, get_ebp_ofs(i+1), box_type)
         else:
-            return StackLoc(i, get_ebp_ofs(i), 1, box_type)
+            return StackLoc(i, get_ebp_ofs(i), box_type)
     @staticmethod
     def frame_size(box_type):
         if IS_X86_32 and box_type == FLOAT:
@@ -165,6 +165,7 @@
         self.jump_target_descr = None
         self.close_stack_struct = 0
         self.final_jump_op = None
+        self.min_bytes_before_label = 0
 
     def _prepare(self, inputargs, operations, allgcrefs):
         self.fm = X86FrameManager()
@@ -173,22 +174,26 @@
         operations = cpu.gc_ll_descr.rewrite_assembler(cpu, operations,
                                                        allgcrefs)
         # compute longevity of variables
-        longevity, useful = self._compute_vars_longevity(inputargs, operations)
-        self.longevity = longevity
-        self.rm = gpr_reg_mgr_cls(longevity,
+        self._compute_vars_longevity(inputargs, operations)
+        self.rm = gpr_reg_mgr_cls(self.longevity,
                                   frame_manager = self.fm,
                                   assembler = self.assembler)
-        self.xrm = xmm_reg_mgr_cls(longevity, frame_manager = self.fm,
+        self.xrm = xmm_reg_mgr_cls(self.longevity, frame_manager = self.fm,
                                    assembler = self.assembler)
-        return operations, useful
+        return operations
 
     def prepare_loop(self, inputargs, operations, looptoken, allgcrefs):
-        operations, useful = self._prepare(inputargs, operations, allgcrefs)
-        return self._process_inputargs(inputargs, useful), operations
+        operations = self._prepare(inputargs, operations, allgcrefs)
+        self._set_initial_bindings(inputargs)
+        # note: we need to make a copy of inputargs because possibly_free_vars
+        # is also used on op args, which is a non-resizable list
+        self.possibly_free_vars(list(inputargs))
+        self.min_bytes_before_label = 13
+        return operations
 
     def prepare_bridge(self, prev_depths, inputargs, arglocs, operations,
                        allgcrefs):
-        operations, _ = self._prepare(inputargs, operations, allgcrefs)
+        operations = self._prepare(inputargs, operations, allgcrefs)
         self._update_bindings(arglocs, inputargs)
         self.param_depth = prev_depths[1]
         return operations
@@ -196,46 +201,56 @@
     def reserve_param(self, n):
         self.param_depth = max(self.param_depth, n)
 
-    def _process_inputargs(self, inputargs, useful):
-        # XXX we can sort out here by longevity if we need something
-        # more optimal
-        floatlocs = [None] * len(inputargs)
-        nonfloatlocs = [None] * len(inputargs)
-        # Don't use all_regs[0] for passing arguments around a loop.
-        # Must be kept in sync with consider_jump().
-        # XXX this should probably go to llsupport/regalloc.py
-        xmmtmp = self.xrm.free_regs.pop(0)
-        tmpreg = self.rm.free_regs.pop(0)
-        assert tmpreg == X86RegisterManager.all_regs[0]
-        assert xmmtmp == X86XMMRegisterManager.all_regs[0]
-        for i in range(len(inputargs)):
-            arg = inputargs[i]
-            assert not isinstance(arg, Const)
-            reg = None
-            if self.longevity[arg][1] > -1 and arg in useful:
-                if arg.type == FLOAT:
-                    # xxx is it really a good idea?  at the first CALL they
-                    # will all be flushed anyway
-                    reg = self.xrm.try_allocate_reg(arg)
+    def _set_initial_bindings(self, inputargs):
+        if IS_X86_64:
+            inputargs = self._set_initial_bindings_regs_64(inputargs)
+        #                   ...
+        # stack layout:     arg2
+        #                   arg1
+        #                   arg0
+        #                   return address
+        #                   saved ebp        <-- ebp points here
+        #                   ...
+        cur_frame_pos = - 1 - FRAME_FIXED_SIZE
+        assert get_ebp_ofs(cur_frame_pos-1) == 2*WORD
+        assert get_ebp_ofs(cur_frame_pos-2) == 3*WORD
+        #
+        for box in inputargs:
+            assert isinstance(box, Box)
+            #
+            if IS_X86_32 and box.type == FLOAT:
+                cur_frame_pos -= 2
+            else:
+                cur_frame_pos -= 1
+            loc = self.fm.frame_pos(cur_frame_pos, box.type)
+            self.fm.set_binding(box, loc)
+
+    def _set_initial_bindings_regs_64(self, inputargs):
+        # In reverse order for use with pop()
+        unused_gpr = [r9, r8, ecx, edx, esi, edi]
+        unused_xmm = [xmm7, xmm6, xmm5, xmm4, xmm3, xmm2, xmm1, xmm0]
+        #
+        pass_on_stack = []
+        #
+        for box in inputargs:
+            assert isinstance(box, Box)
+            #
+            if box.type == FLOAT:
+                if len(unused_xmm) > 0:
+                    ask = unused_xmm.pop()
+                    got = self.xrm.try_allocate_reg(box, selected_reg=ask)
+                    assert ask == got
                 else:
-                    reg = self.rm.try_allocate_reg(arg)
-            if reg:
-                loc = reg
+                    pass_on_stack.append(box)
             else:
-                loc = self.fm.loc(arg)
-            if arg.type == FLOAT:
-                floatlocs[i] = loc
-            else:
-                nonfloatlocs[i] = loc
-            # otherwise we have it saved on stack, so no worry
-        self.rm.free_regs.insert(0, tmpreg)
-        self.xrm.free_regs.insert(0, xmmtmp)
-        assert tmpreg not in nonfloatlocs
-        assert xmmtmp not in floatlocs
-        # note: we need to make a copy of inputargs because possibly_free_vars
-        # is also used on op args, which is a non-resizable list
-        self.possibly_free_vars(list(inputargs))
-        return nonfloatlocs, floatlocs
+                if len(unused_gpr) > 0:
+                    ask = unused_gpr.pop()
+                    got = self.rm.try_allocate_reg(box, selected_reg=ask)
+                    assert ask == got
+                else:
+                    pass_on_stack.append(box)
+        #
+        return pass_on_stack
 
     def possibly_free_var(self, var):
         if var.type == FLOAT:
@@ -446,8 +461,15 @@
             i += 1
         assert not self.rm.reg_bindings
         assert not self.xrm.reg_bindings
+        self.flush_loop()
         self.assembler.mc.mark_op(None) # end of the loop
 
+    def flush_loop(self):
+        # rare case: if the loop is too short, pad with NOPs
+        mc = self.assembler.mc
+        while mc.get_relative_pos() < self.min_bytes_before_label:
+            mc.NOP()
+
     def _compute_vars_longevity(self, inputargs, operations):
         # compute a dictionary that maps variables to index in
         # operations that is a "last-time-seen"
@@ -458,7 +480,7 @@
         # only to guard operations or to jump or to finish
         produced = {}
         last_used = {}
-        useful = {}
+        last_real_usage = {}
         for i in range(len(operations)-1, -1, -1):
             op = operations[i]
             if op.result:
@@ -469,10 +491,13 @@
             opnum = op.getopnum()
             for j in range(op.numargs()):
                 arg = op.getarg(j)
-                if opnum != rop.JUMP and opnum != rop.FINISH:
-                    useful[arg] = None
-                if isinstance(arg, Box) and arg not in last_used:
+                if not isinstance(arg, Box):
+                    continue
+                if arg not in last_used:
                     last_used[arg] = i
+                if opnum != rop.JUMP and opnum != rop.LABEL:
+                    if arg not in last_real_usage:
+                        last_real_usage[arg] = i
             if op.is_guard():
                 for arg in op.getfailargs():
                     if arg is None: # hole
@@ -480,7 +505,8 @@
                     assert isinstance(arg, Box)
                     if arg not in last_used:
                         last_used[arg] = i
-
+        self.last_real_usage = last_real_usage
+        #
         longevity = {}
         for arg in produced:
             if arg in last_used:
@@ -496,7 +522,7 @@
                 longevity[arg] = (0, last_used[arg])
                 del last_used[arg]
         assert len(last_used) == 0
-        return longevity, useful
+        self.longevity = longevity
 
     def loc(self, v):
         if v is None: # xxx kludgy
@@ -1344,51 +1370,51 @@
         #   we would like the boxes to be after the jump.
 
     def _compute_hint_frame_locations_from_descr(self, descr):
-        nonfloatlocs, floatlocs = descr._x86_arglocs
+        arglocs = descr._x86_arglocs
         jump_op = self.final_jump_op
-        assert len(nonfloatlocs) == jump_op.numargs()
+        assert len(arglocs) == jump_op.numargs()
         for i in range(jump_op.numargs()):
             box = jump_op.getarg(i)
             if isinstance(box, Box):
-                loc = nonfloatlocs[i]
+                loc = arglocs[i]
                 if isinstance(loc, StackLoc):
-                    assert box.type != FLOAT
                     self.fm.hint_frame_locations[box] = loc
-                else:
-                    loc = floatlocs[i]
-                    if isinstance(loc, StackLoc):
-                        assert box.type == FLOAT
-                        self.fm.hint_frame_locations[box] = loc
 
     def consider_jump(self, op):
         assembler = self.assembler
         assert self.jump_target_descr is None
         descr = op.getdescr()
         assert isinstance(descr, TargetToken)
-        nonfloatlocs, floatlocs = descr._x86_arglocs
+        arglocs = descr._x86_arglocs
         self.jump_target_descr = descr
-        # compute 'tmploc' to be all_regs[0] by spilling what is there
-        box = TempBox()
-        box1 = TempBox()
-        tmpreg = X86RegisterManager.all_regs[0]
-        tmploc = self.rm.force_allocate_reg(box, selected_reg=tmpreg)
-        xmmtmp = X86XMMRegisterManager.all_regs[0]
-        self.xrm.force_allocate_reg(box1, selected_reg=xmmtmp)
         # Part about non-floats
-        # XXX we don't need a copy, we only just the original list
-        src_locations1 = [self.loc(op.getarg(i)) for i in range(op.numargs())
-                         if op.getarg(i).type != FLOAT]
-        assert tmploc not in nonfloatlocs
-        dst_locations1 = [loc for loc in nonfloatlocs if loc is not None]
+        src_locations1 = []
+        dst_locations1 = []
         # Part about floats
-        src_locations2 = [self.loc(op.getarg(i)) for i in range(op.numargs())
-                         if op.getarg(i).type == FLOAT]
-        dst_locations2 = [loc for loc in floatlocs if loc is not None]
+        src_locations2 = []
+        dst_locations2 = []
+        # Build the four lists
+        for i in range(op.numargs()):
+            box = op.getarg(i)
+            src_loc = self.loc(box)
+            dst_loc = arglocs[i]
+            if box.type != FLOAT:
+                src_locations1.append(src_loc)
+                dst_locations1.append(dst_loc)
+            else:
+                src_locations2.append(src_loc)
+                dst_locations2.append(dst_loc)
+        # Do we have a temp var?
+        if IS_X86_64:
+            tmpreg = X86_64_SCRATCH_REG
+            xmmtmp = X86_64_XMM_SCRATCH_REG
+        else:
+            tmpreg = None
+            xmmtmp = None
+        # Do the remapping
         remap_frame_layout_mixed(assembler,
-                                 src_locations1, dst_locations1, tmploc,
+                                 src_locations1, dst_locations1, tmpreg,
                                  src_locations2, dst_locations2, xmmtmp)
-        self.rm.possibly_free_var(box)
-        self.xrm.possibly_free_var(box1)
         self.possibly_free_vars_for_op(op)
         assembler.closing_jump(self.jump_target_descr)
 
@@ -1440,23 +1466,20 @@
         self.rm.force_allocate_frame_reg(op.result)
 
     def consider_label(self, op):
-        # XXX big refactoring needed?
         descr = op.getdescr()
         assert isinstance(descr, TargetToken)
         inputargs = op.getarglist()
-        floatlocs = [None] * len(inputargs)
-        nonfloatlocs = [None] * len(inputargs)
+        arglocs = [None] * len(inputargs)
         #
-        # we need to make sure that the tmpreg and xmmtmp are free
-        tmpreg = X86RegisterManager.all_regs[0]
-        tmpvar = TempBox()
-        self.rm.force_allocate_reg(tmpvar, selected_reg=tmpreg)
-        self.rm.possibly_free_var(tmpvar)
-        #
-        xmmtmp = X86XMMRegisterManager.all_regs[0]
-        tmpvar = TempBox()
-        self.xrm.force_allocate_reg(tmpvar, selected_reg=xmmtmp)
-        self.xrm.possibly_free_var(tmpvar)
+        # we use force_spill() on the boxes that are not going to be really
+        # used any more in the loop, but that are kept alive anyway
+        # by being in a next LABEL's or a JUMP's argument or fail_args
+        # of some guard
+        position = self.rm.position
+        for arg in inputargs:
+            assert isinstance(arg, Box)
+            if self.last_real_usage.get(arg, -1) <= position:
+                self.force_spill_var(arg)
         #
         # we need to make sure that no variable is stored in ebp
         for arg in inputargs:
@@ -1467,16 +1490,18 @@
         #
         for i in range(len(inputargs)):
             arg = inputargs[i]
-            assert not isinstance(arg, Const)
+            assert isinstance(arg, Box)
             loc = self.loc(arg)
-            assert not (loc is tmpreg or loc is xmmtmp or loc is ebp)
-            if arg.type == FLOAT:
-                floatlocs[i] = loc
-            else:
-                nonfloatlocs[i] = loc
+            assert loc is not ebp
+            arglocs[i] = loc
             if isinstance(loc, RegLoc):
                 self.fm.mark_as_free(arg)
-        descr._x86_arglocs = nonfloatlocs, floatlocs
+        #
+        # if we are too close to the start of the loop, the label's target may
+        # get overridden by redirect_call_assembler().  (rare case)
+        self.flush_loop()
+        #
+        descr._x86_arglocs = arglocs
         descr._x86_loop_code = self.assembler.mc.get_relative_pos()
         descr._x86_clt = self.assembler.current_clt
         self.assembler.target_tokens_currently_compiling[descr] = None
@@ -1490,23 +1515,6 @@
         if jump_op is not None and jump_op.getdescr() is descr:
             self._compute_hint_frame_locations_from_descr(descr)
 
-##        from pypy.rpython.annlowlevel import llhelper
-##        def fn(addr):
-##            print '...label:', hex(addr), nonfloatlocs
-##        FUNC = lltype.Ptr(lltype.FuncType([lltype.Signed], lltype.Void))
-##        ll_disp = llhelper(FUNC, fn)
-##        faddr = rffi.cast(lltype.Signed, ll_disp)
-##        for i in range(16):
-##            self.assembler.mc.PUSH_r(i)
-##        self.assembler.mc.CALL_l(0)
-##        self.assembler.mc.POP(edi)
-##        self.assembler.mc.MOV(r11, imm(faddr))
-##        self.assembler.mc.CALL(r11)
-##        for i in range(15, -1, -1):
-##            if i == esp.value:
-##                i -= 1
-##            self.assembler.mc.POP_r(i)
-
     def not_implemented_op(self, op):
         not_implemented("not implemented operation: %s" % op.getopname())
 
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
@@ -16,8 +16,7 @@
 #
 
 class AssemblerLocation(object):
-    # XXX: Is adding "width" here correct?
-    _attrs_ = ('value', 'width', '_location_code')
+    _attrs_ = ('value', '_location_code')
     _immutable_ = True
     def _getregkey(self):
         return self.value
@@ -28,6 +27,9 @@
     def location_code(self):
         return self._location_code
 
+    def get_width(self):
+        raise NotImplementedError
+
     def value_r(self): return self.value
     def value_b(self): return self.value
     def value_s(self): return self.value
@@ -43,14 +45,21 @@
     _immutable_ = True
     _location_code = 'b'
 
-    def __init__(self, position, ebp_offset, num_words, type):
-        assert ebp_offset < 0   # so no confusion with RegLoc.value
+    def __init__(self, position, ebp_offset, type):
+        # _getregkey() returns self.value; the value returned must not
+        # conflict with RegLoc._getregkey().  It doesn't a bit by chance,
+        # so let it fail the following assert if it no longer does.
+        assert not (0 <= ebp_offset < 8 + 8 * IS_X86_64)
         self.position = position
         self.value = ebp_offset
-        self.width = num_words * WORD
         # One of INT, REF, FLOAT
         self.type = type
 
+    def get_width(self):
+        if self.type == FLOAT:
+            return 8
+        return WORD
+
     def __repr__(self):
         return '%d(%%ebp)' % (self.value,)
 
@@ -64,10 +73,8 @@
         self.value = regnum
         self.is_xmm = is_xmm
         if self.is_xmm:
-            self.width = 8
             self._location_code = 'x'
         else:
-            self.width = WORD
             self._location_code = 'r'
     def __repr__(self):
         if self.is_xmm:
@@ -75,6 +82,11 @@
         else:
             return rx86.R.names[self.value]
 
+    def get_width(self):
+        if self.is_xmm:
+            return 8
+        return WORD
+
     def lowest8bits(self):
         assert not self.is_xmm
         return RegLoc(rx86.low_byte(self.value), False)
@@ -92,9 +104,11 @@
         else:
             return eax
 
-class ImmedLoc(AssemblerLocation):
+class ImmediateAssemblerLocation(AssemblerLocation):
     _immutable_ = True
-    width = WORD
+
+class ImmedLoc(ImmediateAssemblerLocation):
+    _immutable_ = True
     _location_code = 'i'
 
     def __init__(self, value):
@@ -105,6 +119,9 @@
     def getint(self):
         return self.value
 
+    def get_width(self):
+        return WORD
+
     def __repr__(self):
         return "ImmedLoc(%d)" % (self.value)
 
@@ -117,7 +134,6 @@
 class AddressLoc(AssemblerLocation):
     _immutable_ = True
 
-    width = WORD
     # The address is base_loc + (scaled_loc << scale) + static_offset
     def __init__(self, base_loc, scaled_loc, scale=0, static_offset=0):
         assert 0 <= scale < 4
@@ -146,6 +162,9 @@
         info = getattr(self, attr, '?')
         return '<AddressLoc %r: %s>' % (self._location_code, info)
 
+    def get_width(self):
+        return WORD
+
     def value_a(self):
         return self.loc_a
 
@@ -180,32 +199,34 @@
             raise AssertionError(self._location_code)
         return result
 
-class ConstFloatLoc(AssemblerLocation):
-    # XXX: We have to use this class instead of just AddressLoc because
-    # we want a width of 8  (... I think.  Check this!)
+class ConstFloatLoc(ImmediateAssemblerLocation):
     _immutable_ = True
-    width = 8
     _location_code = 'j'
 
     def __init__(self, address):
         self.value = address
 
+    def get_width(self):
+        return 8
+
     def __repr__(self):
         return '<ConstFloatLoc @%s>' % (self.value,)
 
 if IS_X86_32:
-    class FloatImmedLoc(AssemblerLocation):
+    class FloatImmedLoc(ImmediateAssemblerLocation):
         # This stands for an immediate float.  It cannot be directly used in
         # any assembler instruction.  Instead, it is meant to be decomposed
         # in two 32-bit halves.  On 64-bit, FloatImmedLoc() is a function
         # instead; see below.
         _immutable_ = True
-        width = 8
         _location_code = '#'     # don't use me
 
         def __init__(self, floatstorage):
             self.aslonglong = floatstorage
 
+        def get_width(self):
+            return 8
+
         def low_part(self):
             return intmask(self.aslonglong)
 
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
@@ -3,6 +3,7 @@
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.rpython.llinterp import LLInterpreter
 from pypy.rlib.objectmodel import we_are_translated
+from pypy.jit.codewriter import longlong
 from pypy.jit.metainterp import history, compile
 from pypy.jit.backend.x86.assembler import Assembler386
 from pypy.jit.backend.x86.arch import FORCE_INDEX_OFS
@@ -21,7 +22,6 @@
     supports_floats = True
     supports_singlefloats = True
 
-    BOOTSTRAP_TP = lltype.FuncType([], lltype.Signed)
     dont_keepalive_stuff = False # for tests
     with_threads = False
 
@@ -91,15 +91,6 @@
         return self.assembler.assemble_bridge(faildescr, inputargs, operations,
                                               original_loop_token, log=log)
 
-    def set_future_value_int(self, index, intvalue):
-        self.assembler.fail_boxes_int.setitem(index, intvalue)
-
-    def set_future_value_float(self, index, floatvalue):
-        self.assembler.fail_boxes_float.setitem(index, floatvalue)
-
-    def set_future_value_ref(self, index, ptrvalue):
-        self.assembler.fail_boxes_ptr.setitem(index, ptrvalue)
-
     def get_latest_value_int(self, index):
         return self.assembler.fail_boxes_int.getitem(index)
 
@@ -122,27 +113,28 @@
         # the FORCE_TOKEN operation and this helper both return 'ebp'.
         return self.assembler.fail_ebp
 
-    def execute_token(self, executable_token):
-        addr = executable_token._x86_bootstrap_code
-        #llop.debug_print(lltype.Void, ">>>> Entering", addr)
-        func = rffi.cast(lltype.Ptr(self.BOOTSTRAP_TP), addr)
-        fail_index = self._execute_call(func)
-        #llop.debug_print(lltype.Void, "<<<< Back")
-        return self.get_fail_descr_from_number(fail_index)
-
-    def _execute_call(self, func):
-        # help flow objspace
-        prev_interpreter = None
-        if not self.translate_support_code:
-            prev_interpreter = LLInterpreter.current_interpreter
-            LLInterpreter.current_interpreter = self.debug_ll_interpreter
-        res = 0
-        try:
-            res = func()
-        finally:
+    def make_execute_token(self, *ARGS):
+        FUNCPTR = lltype.Ptr(lltype.FuncType(ARGS, lltype.Signed))
+        #
+        def execute_token(executable_token, *args):
+            clt = executable_token.compiled_loop_token
+            assert len(args) == clt._debug_nbargs
+            #
+            addr = executable_token._x86_function_addr
+            func = rffi.cast(FUNCPTR, addr)
+            #llop.debug_print(lltype.Void, ">>>> Entering", addr)
+            prev_interpreter = None   # help flow space
             if not self.translate_support_code:
-                LLInterpreter.current_interpreter = prev_interpreter
-        return res
+                prev_interpreter = LLInterpreter.current_interpreter
+                LLInterpreter.current_interpreter = self.debug_ll_interpreter
+            try:
+                fail_index = func(*args)
+            finally:
+                if not self.translate_support_code:
+                    LLInterpreter.current_interpreter = prev_interpreter
+            #llop.debug_print(lltype.Void, "<<<< Back")
+            return self.get_fail_descr_from_number(fail_index)
+        return execute_token
 
     def cast_ptr_to_int(x):
         adr = llmemory.cast_ptr_to_adr(x)
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
@@ -46,12 +46,13 @@
             xmm2]
     assert len(failargs) == len(locs)
     assembler.write_failure_recovery_description(mc, failargs, locs)
-    nums = [Assembler386.DESCR_INT   + 4*(16+0),
-            Assembler386.DESCR_REF   + 4*(16+1),
-            Assembler386.DESCR_FLOAT + 4*(16+10),
-            Assembler386.DESCR_INT   + 4*(16+100),
-            Assembler386.DESCR_REF   + 4*(16+101),
-            Assembler386.DESCR_FLOAT + 4*(16+110),
+    base = 8 + 8*IS_X86_64
+    nums = [Assembler386.DESCR_INT   + 4*(base+0),
+            Assembler386.DESCR_REF   + 4*(base+1),
+            Assembler386.DESCR_FLOAT + 4*(base+10),
+            Assembler386.DESCR_INT   + 4*(base+100),
+            Assembler386.DESCR_REF   + 4*(base+101),
+            Assembler386.DESCR_FLOAT + 4*(base+110),
             Assembler386.CODE_HOLE,
             Assembler386.CODE_HOLE,
             Assembler386.DESCR_INT   + 4*ebx.value,
diff --git a/pypy/jit/backend/x86/test/test_jump.py b/pypy/jit/backend/x86/test/test_jump.py
--- a/pypy/jit/backend/x86/test/test_jump.py
+++ b/pypy/jit/backend/x86/test/test_jump.py
@@ -71,6 +71,18 @@
                              ('mov', eax, s24),
                              ('mov', s12, edi)]
 
+def test_no_tmp_reg():
+    assembler = MockAssembler()
+    s8 = frame_pos(0, INT)
+    s12 = frame_pos(13, INT)
+    s20 = frame_pos(20, INT)
+    s24 = frame_pos(221, INT)
+    remap_frame_layout(assembler, [s8, eax, s12], [s20, s24, edi], None)
+    assert assembler.ops == [('push', s8),
+                             ('pop', s20),
+                             ('mov', eax, s24),
+                             ('mov', s12, edi)]
+
 def test_reordering():
     assembler = MockAssembler()
     s8 = frame_pos(8, INT)
@@ -237,7 +249,7 @@
         while len(result) < count:
             x = fn()
             keys = [x._getregkey()]
-            if isinstance(x, StackLoc) and x.width > WORD:
+            if isinstance(x, StackLoc) and x.get_width() > WORD:
                 keys.append(keys[0] + WORD)
             for key in keys:
                 if key in seen:
@@ -255,7 +267,7 @@
         for i, loc in enumerate(locations):
             if isinstance(loc, RegLoc):
                 if loc.is_xmm:
-                    if loc.width > WORD:
+                    if loc.get_width() > WORD:
                         newvalue = ('value-xmm-%d' % i,
                                     'value-xmm-hiword-%d' % i)
                     else:
@@ -264,8 +276,8 @@
                 else:
                     regs1[loc.value] = 'value-int-%d' % i
             elif isinstance(loc, StackLoc):
-                stack[loc.value] = 'value-width%d-%d' % (loc.width, i)
-                if loc.width > WORD:
+                stack[loc.value] = 'value-width%d-%d' % (loc.get_width(), i)
+                if loc.get_width() > WORD:
                     stack[loc.value+WORD] = 'value-hiword-%d' % i
             else:
                 assert isinstance(loc, ImmedLoc)
@@ -287,7 +299,7 @@
         #
         def read(loc, expected_width=None):
             if expected_width is not None:
-                assert loc.width == expected_width
+                assert loc.get_width() == expected_width
             if isinstance(loc, RegLoc):
                 if loc.is_xmm:
                     return regs2[loc.value]
@@ -295,7 +307,7 @@
                     return regs1[loc.value]
             if isinstance(loc, StackLoc):
                 got = stack[loc.value]
-                if loc.width > WORD:
+                if loc.get_width() > WORD:
                     got = (got, stack[loc.value+WORD])
                 return got
             if isinstance(loc, ImmedLoc):
@@ -309,7 +321,7 @@
                 else:
                     regs1[loc.value] = newvalue
             elif isinstance(loc, StackLoc):
-                if loc.width > WORD:
+                if loc.get_width() > WORD:
                     newval1, newval2 = newvalue
                     stack[loc.value] = newval1
                     stack[loc.value+WORD] = newval2
diff --git a/pypy/jit/backend/x86/test/test_recompilation.py b/pypy/jit/backend/x86/test/test_recompilation.py
--- a/pypy/jit/backend/x86/test/test_recompilation.py
+++ b/pypy/jit/backend/x86/test/test_recompilation.py
@@ -19,8 +19,7 @@
         finish(i3, descr=fdescr2)
         '''
         bridge = self.attach_bridge(ops, loop, -2)
-        self.cpu.set_future_value_int(0, 0)
-        fail = self.run(loop)
+        fail = self.run(loop, 0)
         assert fail.identifier == 2
         assert self.getint(0) == 21
     
@@ -55,8 +54,7 @@
         assert descr._x86_bridge_param_depth == 0
         # the force_spill() forces the stack to grow
         assert new > previous
-        self.cpu.set_future_value_int(0, 0)
-        fail = self.run(loop)
+        fail = self.run(loop, 0)
         assert fail.identifier == 2
         assert self.getint(0) == 21
         assert self.getint(1) == 22
@@ -71,20 +69,19 @@
         i2 = int_lt(i1, 20)
         guard_true(i2, descr=fdescr1) [i1]
         jump(i1, i10, i11, i12, i13, i14, i15, i16, descr=targettoken)
-        ''', [0])
+        ''', [0, 0, 0, 0, 0, 0, 0, 0])
         other_loop = self.interpret('''
-        [i3]
+        [i3, i10, i11, i12, i13, i14, i15, i16]
         label(i3, descr=targettoken2)
         guard_false(i3, descr=fdescr2) [i3]
         jump(i3, descr=targettoken2)
-        ''', [1])
+        ''', [1, 0, 0, 0, 0, 0, 0, 0])
         ops = '''
         [i3]
         jump(i3, 1, 2, 3, 4, 5, 6, 7, descr=targettoken)
         '''
         bridge = self.attach_bridge(ops, other_loop, 1)
-        self.cpu.set_future_value_int(0, 1)
-        fail = self.run(other_loop)
+        fail = self.run(other_loop, 1, 0, 0, 0, 0, 0, 0, 0)
         assert fail.identifier == 1
 
     def test_bridge_jumps_to_self_deeper(self):
@@ -100,7 +97,7 @@
         i5 = int_lt(i3, 20)
         guard_true(i5) [i99, i3]
         jump(i3, i30, 1, i30, i30, i30, descr=targettoken)
-        ''', [0])
+        ''', [0, 0, 0, 0, 0, 0])
         assert self.getint(0) == 0
         assert self.getint(1) == 1
         ops = '''
@@ -123,10 +120,7 @@
         # the force_spill() forces the stack to grow
         assert guard_op.getdescr()._x86_bridge_frame_depth > loop_frame_depth
         assert guard_op.getdescr()._x86_bridge_param_depth == 0
-        self.cpu.set_future_value_int(0, 0)
-        self.cpu.set_future_value_int(1, 0)
-        self.cpu.set_future_value_int(2, 0)
-        self.run(loop)
+        self.run(loop, 0, 0, 0, 0, 0, 0)
         assert self.getint(0) == 1
         assert self.getint(1) == 20
 
@@ -142,7 +136,7 @@
         i5 = int_lt(i3, 20)
         guard_true(i5) [i99, i3]
         jump(i3, i1, i2, descr=targettoken)
-        ''', [0])
+        ''', [0, 0, 0])
         assert self.getint(0) == 0
         assert self.getint(1) == 1
         ops = '''
@@ -150,10 +144,7 @@
         jump(i3, 0, 1, descr=targettoken)
         '''
         bridge = self.attach_bridge(ops, loop, 5)
-        self.cpu.set_future_value_int(0, 0)
-        self.cpu.set_future_value_int(1, 0)
-        self.cpu.set_future_value_int(2, 0)
-        self.run(loop)
+        self.run(loop, 0, 0, 0)
         assert self.getint(0) == 1
         assert self.getint(1) == 20
         
diff --git a/pypy/jit/backend/x86/test/test_regalloc.py b/pypy/jit/backend/x86/test/test_regalloc.py
--- a/pypy/jit/backend/x86/test/test_regalloc.py
+++ b/pypy/jit/backend/x86/test/test_regalloc.py
@@ -142,19 +142,20 @@
         loop = self.parse(ops)
         looptoken = JitCellToken()
         self.cpu.compile_loop(loop.inputargs, loop.operations, looptoken)
-        for i, arg in enumerate(args):
+        arguments = []
+        for arg in args:
             if isinstance(arg, int):
-                self.cpu.set_future_value_int(i, arg)
+                arguments.append(arg)
             elif isinstance(arg, float):
                 arg = longlong.getfloatstorage(arg)
-                self.cpu.set_future_value_float(i, arg)
+                arguments.append(arg)
             else:
                 assert isinstance(lltype.typeOf(arg), lltype.Ptr)
                 llgcref = lltype.cast_opaque_ptr(llmemory.GCREF, arg)
-                self.cpu.set_future_value_ref(i, llgcref)
+                arguments.append(llgcref)
         loop._jitcelltoken = looptoken
         if run:
-            self.cpu.execute_token(looptoken)
+            self.cpu.execute_token(looptoken, *arguments)
         return loop
 
     def prepare_loop(self, ops):
@@ -193,8 +194,8 @@
                                 loop._jitcelltoken)
         return bridge
 
-    def run(self, loop):
-        return self.cpu.execute_token(loop._jitcelltoken)
+    def run(self, loop, *arguments):
+        return self.cpu.execute_token(loop._jitcelltoken, *arguments)
 
 class TestRegallocSimple(BaseTestRegalloc):
     def test_simple_loop(self):
@@ -220,7 +221,7 @@
         '''
         loop = self.interpret(ops, [0, 0, 0, 0])
         ops2 = '''
-        [i5]
+        [i5, i6, i7, i8]
         label(i5, descr=targettoken2)
         i1 = int_add(i5, 1)
         i3 = int_add(i1, 1)
@@ -229,14 +230,13 @@
         guard_true(i2) [i4]
         jump(i4, descr=targettoken2)
         '''
-        loop2 = self.interpret(ops2, [0])
+        loop2 = self.interpret(ops2, [0, 0, 0, 0])
         bridge_ops = '''
         [i4]
         jump(i4, i4, i4, i4, descr=targettoken)
         '''
         bridge = self.attach_bridge(bridge_ops, loop2, 5)
-        self.cpu.set_future_value_int(0, 0)
-        self.run(loop2)
+        self.run(loop2, 0, 0, 0, 0)
         assert self.getint(0) == 31
         assert self.getint(1) == 30
         assert self.getint(2) == 30
@@ -274,8 +274,7 @@
         loop = self.interpret(ops, [0])
         assert self.getint(0) == 1
         bridge = self.attach_bridge(bridge_ops, loop, 2)
-        self.cpu.set_future_value_int(0, 0)
-        self.run(loop)
+        self.run(loop, 0)
         assert self.getint(0) == 1
 
     def test_inputarg_unused(self):
@@ -301,9 +300,7 @@
         assert self.getint(0) == 0
         assert self.getint(1) == 10
         bridge = self.attach_bridge(bridge_ops, loop, 0)
-        self.cpu.set_future_value_int(0, 0)
-        self.cpu.set_future_value_int(1, 10)
-        self.run(loop)
+        self.run(loop, 0, 10)
         assert self.getint(0) == 0
         assert self.getint(1) == 10
 
@@ -320,9 +317,7 @@
         finish(1, 2)
         '''
         self.attach_bridge(bridge_ops, loop, 0)
-        self.cpu.set_future_value_int(0, 0)
-        self.cpu.set_future_value_int(1, 1)
-        self.run(loop)
+        self.run(loop, 0, 1)
 
     def test_spill_for_constant(self):
         ops = '''
@@ -406,7 +401,7 @@
         guard_true(i5) [i2, i1]
         jump(i0, i18, i15, i16, i2, i1, i4, descr=targettoken)
         '''
-        self.interpret(ops, [0, 1, 2, 3])
+        self.interpret(ops, [0, 1, 2, 3, 0, 0, 0])
 
     def test_op_result_unused(self):
         ops = '''
@@ -440,9 +435,7 @@
         finish(i0, i1, i2, i3, i4, i5, i6, i7, i8)
         '''
         self.attach_bridge(bridge_ops, loop, 1)
-        for i in range(9):
-            self.cpu.set_future_value_int(i, i)
-        self.run(loop)
+        self.run(loop, 0, 1, 2, 3, 4, 5, 6, 7, 8)
         assert self.getints(9) == range(9)
 
     def test_loopargs(self):
@@ -452,27 +445,13 @@
         jump(i4, i1, i2, i3)
         """
         regalloc = self.prepare_loop(ops)
-        assert len(regalloc.rm.reg_bindings) == 2
+        if IS_X86_64:
+            assert len(regalloc.rm.reg_bindings) == 4
+            assert len(regalloc.fm.bindings) == 0
+        else:
+            assert len(regalloc.rm.reg_bindings) == 0
+            assert len(regalloc.fm.bindings) == 4
 
-    def test_loopargs_2(self):
-        ops = """
-        [i0, i1, i2, i3]
-        i4 = int_add(i0, i1)
-        finish(i4, i1, i2, i3)
-        """
-        regalloc = self.prepare_loop(ops)
-        assert len(regalloc.rm.reg_bindings) == 2
-
-    def test_loopargs_3(self):
-        ops = """
-        [i0, i1, i2, i3]
-        i4 = int_add(i0, i1)
-        guard_true(i4) [i0, i1, i2, i3, i4]
-        jump(i4, i1, i2, i3)
-        """
-        regalloc = self.prepare_loop(ops)
-        assert len(regalloc.rm.reg_bindings) == 2
-    
 
 class TestRegallocCompOps(BaseTestRegalloc):
     
@@ -640,8 +619,8 @@
         i10 = call(ConstClass(f1ptr), i0, descr=f1_calldescr)
         finish(i10, i1, i2, i3, i4, i5, i6, i7, i8, i9)
         '''
-        loop = self.interpret(ops, [4, 7, 9, 9 ,9, 9, 9, 9, 9, 9, 9])
-        assert self.getints(11) == [5, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9]
+        loop = self.interpret(ops, [4, 7, 9, 9 ,9, 9, 9, 9, 9, 9])
+        assert self.getints(10) == [5, 7, 9, 9, 9, 9, 9, 9, 9, 9]
         clt = loop._jitcelltoken.compiled_loop_token
         assert clt.param_depth == self.expected_param_depth(1)
 
@@ -652,8 +631,8 @@
         i11 = call(ConstClass(f2ptr), i10, i1, descr=f2_calldescr)        
         finish(i11, i1,  i2, i3, i4, i5, i6, i7, i8, i9)
         '''
-        loop = self.interpret(ops, [4, 7, 9, 9 ,9, 9, 9, 9, 9, 9, 9])
-        assert self.getints(11) == [5*7, 7, 9, 9, 9, 9, 9, 9, 9, 9, 9]
+        loop = self.interpret(ops, [4, 7, 9, 9 ,9, 9, 9, 9, 9, 9])
+        assert self.getints(10) == [5*7, 7, 9, 9, 9, 9, 9, 9, 9, 9]
         clt = loop._jitcelltoken.compiled_loop_token
         assert clt.param_depth == self.expected_param_depth(2)
 
@@ -689,9 +668,7 @@
 
         assert loop.operations[-2].getdescr()._x86_bridge_param_depth == self.expected_param_depth(2)
 
-        self.cpu.set_future_value_int(0, 4)
-        self.cpu.set_future_value_int(1, 7)        
-        self.run(loop)
+        self.run(loop, 4, 7)
         assert self.getint(0) == 5*7
 
     def test_bridge_calls_2(self):
@@ -712,8 +689,6 @@
 
         assert loop.operations[-2].getdescr()._x86_bridge_param_depth == self.expected_param_depth(2)
 
-        self.cpu.set_future_value_int(0, 4)
-        self.cpu.set_future_value_int(1, 7)        
-        self.run(loop)
+        self.run(loop, 4, 7)
         assert self.getint(0) == 29
 
diff --git a/pypy/jit/backend/x86/test/test_regalloc2.py b/pypy/jit/backend/x86/test/test_regalloc2.py
--- a/pypy/jit/backend/x86/test/test_regalloc2.py
+++ b/pypy/jit/backend/x86/test/test_regalloc2.py
@@ -22,8 +22,7 @@
     cpu.setup_once()
     looptoken = JitCellToken()
     cpu.compile_loop(inputargs, operations, looptoken)
-    cpu.set_future_value_int(0, 9)
-    cpu.execute_token(looptoken)
+    cpu.execute_token(looptoken, 9)
     assert cpu.get_latest_value_int(0) == (9 >> 3)
     assert cpu.get_latest_value_int(1) == (~18)
 
@@ -45,8 +44,7 @@
     cpu.setup_once()
     looptoken = JitCellToken()
     cpu.compile_loop(inputargs, operations, looptoken)
-    cpu.set_future_value_int(0, -10)
-    cpu.execute_token(looptoken)
+    cpu.execute_token(looptoken, -10)
     assert cpu.get_latest_value_int(0) == 0
     assert cpu.get_latest_value_int(1) == -1000
     assert cpu.get_latest_value_int(2) == 1
@@ -142,17 +140,7 @@
     cpu.setup_once()
     looptoken = JitCellToken()
     cpu.compile_loop(inputargs, operations, looptoken)
-    cpu.set_future_value_int(0, -13)
-    cpu.set_future_value_int(1, 10)
-    cpu.set_future_value_int(2, 10)
-    cpu.set_future_value_int(3, 8)
-    cpu.set_future_value_int(4, -8)
-    cpu.set_future_value_int(5, -16)
-    cpu.set_future_value_int(6, -18)
-    cpu.set_future_value_int(7, 46)
-    cpu.set_future_value_int(8, -12)
-    cpu.set_future_value_int(9, 26)
-    cpu.execute_token(looptoken)
+    cpu.execute_token(looptoken, -13, 10, 10, 8, -8, -16, -18, 46, -12, 26)
     assert cpu.get_latest_value_int(0) == 0
     assert cpu.get_latest_value_int(1) == 0
     assert cpu.get_latest_value_int(2) == 0
@@ -257,17 +245,7 @@
     cpu.setup_once()
     looptoken = JitCellToken()
     cpu.compile_loop(inputargs, operations, looptoken)
-    cpu.set_future_value_int(0, 17)
-    cpu.set_future_value_int(1, -20)
-    cpu.set_future_value_int(2, -6)
-    cpu.set_future_value_int(3, 6)
-    cpu.set_future_value_int(4, 1)
-    cpu.set_future_value_int(5, 13)
-    cpu.set_future_value_int(6, 13)
-    cpu.set_future_value_int(7, 9)
-    cpu.set_future_value_int(8, 49)
-    cpu.set_future_value_int(9, 8)
-    cpu.execute_token(looptoken)
+    cpu.execute_token(looptoken, 17, -20, -6, 6, 1, 13, 13, 9, 49, 8)
     assert cpu.get_latest_value_int(0) == 0
     assert cpu.get_latest_value_int(1) == 8
     assert cpu.get_latest_value_int(2) == 1
diff --git a/pypy/jit/backend/x86/test/test_runner.py b/pypy/jit/backend/x86/test/test_runner.py
--- a/pypy/jit/backend/x86/test/test_runner.py
+++ b/pypy/jit/backend/x86/test/test_runner.py
@@ -282,11 +282,7 @@
                     ops[-2].setfailargs([i1])
                     looptoken = JitCellToken()
                     self.cpu.compile_loop([b], ops, looptoken)
-                    if op == rop.INT_IS_TRUE:
-                        self.cpu.set_future_value_int(0, b.value)
-                    else:
-                        self.cpu.set_future_value_ref(0, b.value)
-                    self.cpu.execute_token(looptoken)
+                    self.cpu.execute_token(looptoken, b.value)
                     result = self.cpu.get_latest_value_int(0)
                     if guard == rop.GUARD_FALSE:
                         assert result == execute(self.cpu, None,
@@ -332,9 +328,8 @@
                     inputargs = [i for i in (a, b) if isinstance(i, Box)]
                     looptoken = JitCellToken()
                     self.cpu.compile_loop(inputargs, ops, looptoken)
-                    for i, box in enumerate(inputargs):
-                        self.cpu.set_future_value_int(i, box.value)
-                    self.cpu.execute_token(looptoken)
+                    inputvalues = [box.value for box in inputargs]
+                    self.cpu.execute_token(looptoken, *inputvalues)
                     result = self.cpu.get_latest_value_int(0)
                     expected = execute(self.cpu, None, op, None, a, b).value
                     if guard == rop.GUARD_FALSE:
@@ -400,8 +395,7 @@
         assert address >= loopaddress + loopsize
         assert size >= 10 # randomish number
 
-        self.cpu.set_future_value_int(0, 2)
-        fail = self.cpu.execute_token(looptoken)
+        fail = self.cpu.execute_token(looptoken, 2)
         assert fail.identifier == 2
         res = self.cpu.get_latest_value_int(0)
         assert res == 20
@@ -507,9 +501,7 @@
             looptoken = JitCellToken()
             self.cpu.compile_loop([i1, i2], ops, looptoken)
 
-            self.cpu.set_future_value_int(0, 123450)
-            self.cpu.set_future_value_int(1, 123408)
-            fail = self.cpu.execute_token(looptoken)
+            fail = self.cpu.execute_token(looptoken, 123450, 123408)
             assert fail.identifier == 0
             assert self.cpu.get_latest_value_int(0) == 42
             assert self.cpu.get_latest_value_int(1) == 42
@@ -541,8 +533,7 @@
             self.cpu.assembler.set_debug(True)
             looptoken = JitCellToken()
             self.cpu.compile_loop(ops.inputargs, ops.operations, looptoken)
-            self.cpu.set_future_value_int(0, 0)
-            self.cpu.execute_token(looptoken)
+            self.cpu.execute_token(looptoken, 0)
             # check debugging info
             struct = self.cpu.assembler.loop_run_counters[0]
             assert struct.i == 10
@@ -565,7 +556,6 @@
         self.cpu.assembler.set_debug(True)
         looptoken = JitCellToken()
         self.cpu.compile_loop(ops.inputargs, ops.operations, looptoken)
-        self.cpu.set_future_value_int(0, 0)
-        self.cpu.execute_token(looptoken)
+        self.cpu.execute_token(looptoken, 0)
         assert looptoken._x86_debug_checksum == sum([op.getopnum()
                                                      for op in ops.operations])
diff --git a/pypy/jit/codewriter/jtransform.py b/pypy/jit/codewriter/jtransform.py
--- a/pypy/jit/codewriter/jtransform.py
+++ b/pypy/jit/codewriter/jtransform.py
@@ -498,27 +498,29 @@
         else:
             log.WARNING('ignoring hint %r at %r' % (hints, self.graph))
 
+    def _rewrite_raw_malloc(self, op, name, args):
+        d = op.args[1].value.copy()
+        d.pop('flavor')
+        add_memory_pressure = d.pop('add_memory_pressure', False)
+        zero = d.pop('zero', False)
+        track_allocation = d.pop('track_allocation', True)
+        if d:
+            raise UnsupportedMallocFlags(d)
+        TYPE = op.args[0].value
+        if zero:
+            name += '_zero'
+        if add_memory_pressure:
+            name += '_add_memory_pressure'
+        if not track_allocation:
+            name += '_no_track_allocation'
+        return self._do_builtin_call(op, name, args,
+                                     extra = (TYPE,),
+                                     extrakey = TYPE)
+
     def rewrite_op_malloc_varsize(self, op):
         if op.args[1].value['flavor'] == 'raw':
-            d = op.args[1].value.copy()
-            d.pop('flavor')
-            add_memory_pressure = d.pop('add_memory_pressure', False)
-            zero = d.pop('zero', False)
-            track_allocation = d.pop('track_allocation', True)
-            if d:
-                raise UnsupportedMallocFlags(d)
-            ARRAY = op.args[0].value
-            name = 'raw_malloc'
-            if zero:
-                name += '_zero'
-            if add_memory_pressure:
-                name += '_add_memory_pressure'
-            if not track_allocation:
-                name += '_no_track_allocation'
-            return self._do_builtin_call(op, name,
-                                         [op.args[2]],
-                                         extra = (ARRAY,),
-                                         extrakey = ARRAY)
+            return self._rewrite_raw_malloc(op, 'raw_malloc_varsize',
+                                            [op.args[2]])
         if op.args[0].value == rstr.STR:
             return SpaceOperation('newstr', [op.args[2]], op.result)
         elif op.args[0].value == rstr.UNICODE:
@@ -531,11 +533,18 @@
                                   op.result)
 
     def rewrite_op_free(self, op):
-        flags = op.args[1].value
-        assert flags['flavor'] == 'raw'
-        ARRAY = op.args[0].concretetype.TO
-        return self._do_builtin_call(op, 'raw_free', [op.args[0]],
-                                     extra = (ARRAY,), extrakey = ARRAY)
+        d = op.args[1].value.copy()
+        assert d['flavor'] == 'raw'
+        d.pop('flavor')
+        track_allocation = d.pop('track_allocation', True)
+        if d:
+            raise UnsupportedMallocFlags(d)
+        STRUCT = op.args[0].concretetype.TO
+        name = 'raw_free'
+        if not track_allocation:
+            name += '_no_track_allocation'
+        return self._do_builtin_call(op, name, [op.args[0]],
+                                     extra = (STRUCT,), extrakey = STRUCT)
 
     def rewrite_op_getarrayitem(self, op):
         ARRAY = op.args[0].concretetype.TO
@@ -736,6 +745,9 @@
         return [op0, op1]
 
     def rewrite_op_malloc(self, op):
+        if op.args[1].value['flavor'] == 'raw':
+            return self._rewrite_raw_malloc(op, 'raw_malloc_fixedsize', [])
+        #
         assert op.args[1].value == {'flavor': 'gc'}
         STRUCT = op.args[0].value
         vtable = heaptracker.get_vtable_for_gcstruct(self.cpu, STRUCT)
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
@@ -599,26 +599,75 @@
             return p
         return _ll_0_alloc_with_del
 
-    def build_raw_malloc_builder(zero=False, add_memory_pressure=False, track_allocation=True):
-        def build_ll_1_raw_malloc(ARRAY):
-            def _ll_1_raw_malloc(n):
-                return lltype.malloc(ARRAY, n, flavor='raw', zero=zero, add_memory_pressure=add_memory_pressure)
-            return _ll_1_raw_malloc
-        return build_ll_1_raw_malloc
+    def build_raw_malloc_varsize_builder(zero=False,
+                                         add_memory_pressure=False,
+                                         track_allocation=True):
+        def build_ll_1_raw_malloc_varsize(ARRAY):
+            def _ll_1_raw_malloc_varsize(n):
+                return lltype.malloc(ARRAY, n, flavor='raw', zero=zero,
+                                     add_memory_pressure=add_memory_pressure,
+                                     track_allocation=track_allocation)
+            return _ll_1_raw_malloc_varsize
+        return build_ll_1_raw_malloc_varsize
 
-    build_ll_1_raw_malloc = build_raw_malloc_builder()
-    build_ll_1_raw_malloc_zero = build_raw_malloc_builder(zero=True)
-    build_ll_1_raw_malloc_zero_add_memory_pressure = build_raw_malloc_builder(zero=True, add_memory_pressure=True)
-    build_ll_1_raw_malloc_add_memory_pressure = build_raw_malloc_builder(add_memory_pressure=True)
-    build_ll_1_raw_malloc_no_track_allocation = build_raw_malloc_builder(track_allocation=False)
-    build_ll_1_raw_malloc_zero_no_track_allocation = build_raw_malloc_builder(zero=True, track_allocation=False)
-    build_ll_1_raw_malloc_zero_add_memory_pressure_no_track_allocation = build_raw_malloc_builder(zero=True, add_memory_pressure=True, track_allocation=False)
-    build_ll_1_raw_malloc_add_memory_pressure_no_track_allocation = build_raw_malloc_builder(add_memory_pressure=True, track_allocation=False)
+    build_ll_1_raw_malloc_varsize = (
+        build_raw_malloc_varsize_builder())
+    build_ll_1_raw_malloc_varsize_zero = (
+        build_raw_malloc_varsize_builder(zero=True))
+    build_ll_1_raw_malloc_varsize_zero_add_memory_pressure = (
+        build_raw_malloc_varsize_builder(zero=True, add_memory_pressure=True))
+    build_ll_1_raw_malloc_varsize_add_memory_pressure = (
+        build_raw_malloc_varsize_builder(add_memory_pressure=True))
+    build_ll_1_raw_malloc_varsize_no_track_allocation = (
+        build_raw_malloc_varsize_builder(track_allocation=False))
+    build_ll_1_raw_malloc_varsize_zero_no_track_allocation = (
+        build_raw_malloc_varsize_builder(zero=True, track_allocation=False))
+    build_ll_1_raw_malloc_varsize_zero_add_memory_pressure_no_track_allocation = (
+        build_raw_malloc_varsize_builder(zero=True, add_memory_pressure=True, track_allocation=False))
+    build_ll_1_raw_malloc_varsize_add_memory_pressure_no_track_allocation = (
+        build_raw_malloc_varsize_builder(add_memory_pressure=True, track_allocation=False))
 
-    def build_ll_1_raw_free(ARRAY):
-        def _ll_1_raw_free(p):
-            lltype.free(p, flavor='raw')
-        return _ll_1_raw_free
+    def build_raw_malloc_fixedsize_builder(zero=False,
+                                           add_memory_pressure=False,
+                                           track_allocation=True):
+        def build_ll_0_raw_malloc_fixedsize(STRUCT):
+            def _ll_0_raw_malloc_fixedsize():
+                return lltype.malloc(STRUCT, flavor='raw', zero=zero,
+                                     add_memory_pressure=add_memory_pressure,
+                                     track_allocation=track_allocation)
+            return _ll_0_raw_malloc_fixedsize
+        return build_ll_0_raw_malloc_fixedsize
+
+    build_ll_0_raw_malloc_fixedsize = (
+        build_raw_malloc_fixedsize_builder())
+    build_ll_0_raw_malloc_fixedsize_zero = (
+        build_raw_malloc_fixedsize_builder(zero=True))
+    build_ll_0_raw_malloc_fixedsize_zero_add_memory_pressure = (
+        build_raw_malloc_fixedsize_builder(zero=True, add_memory_pressure=True))
+    build_ll_0_raw_malloc_fixedsize_add_memory_pressure = (
+        build_raw_malloc_fixedsize_builder(add_memory_pressure=True))
+    build_ll_0_raw_malloc_fixedsize_no_track_allocation = (
+        build_raw_malloc_fixedsize_builder(track_allocation=False))
+    build_ll_0_raw_malloc_fixedsize_zero_no_track_allocation = (
+        build_raw_malloc_fixedsize_builder(zero=True, track_allocation=False))
+    build_ll_0_raw_malloc_fixedsize_zero_add_memory_pressure_no_track_allocation = (
+        build_raw_malloc_fixedsize_builder(zero=True, add_memory_pressure=True, track_allocation=False))
+    build_ll_0_raw_malloc_fixedsize_add_memory_pressure_no_track_allocation = (
+        build_raw_malloc_fixedsize_builder(add_memory_pressure=True, track_allocation=False))
+
+    def build_raw_free_builder(track_allocation=True):
+        def build_ll_1_raw_free(ARRAY):
+            def _ll_1_raw_free(p):
+                lltype.free(p, flavor='raw',
+                            track_allocation=track_allocation)
+            return _ll_1_raw_free
+        return build_ll_1_raw_free
+
+    build_ll_1_raw_free = (
+        build_raw_free_builder())
+    build_ll_1_raw_free_no_track_allocation = (
+        build_raw_free_builder(track_allocation=False))
+
 
 class OOtypeHelpers:
 
diff --git a/pypy/jit/codewriter/test/test_codewriter.py b/pypy/jit/codewriter/test/test_codewriter.py
--- a/pypy/jit/codewriter/test/test_codewriter.py
+++ b/pypy/jit/codewriter/test/test_codewriter.py
@@ -217,7 +217,7 @@
     cw.make_jitcodes(verbose=True)
     #
     s = jitdriver_sd.mainjitcode.dump()
-    assert 'residual_call_ir_i $<* fn _ll_1_raw_malloc__Signed>' in s
+    assert 'residual_call_ir_i $<* fn _ll_1_raw_malloc_varsize__Signed>' in s
     assert 'setarrayitem_raw_i' in s
     assert 'getarrayitem_raw_i' in s
     assert 'residual_call_ir_v $<* fn _ll_1_raw_free__arrayPtr>' in s
diff --git a/pypy/jit/codewriter/test/test_jtransform.py b/pypy/jit/codewriter/test/test_jtransform.py
--- a/pypy/jit/codewriter/test/test_jtransform.py
+++ b/pypy/jit/codewriter/test/test_jtransform.py
@@ -550,7 +550,7 @@
     tr = Transformer(FakeCPU(), FakeResidualCallControl())
     op0, op1 = tr.rewrite_operation(op)
     assert op0.opname == 'residual_call_ir_i'
-    assert op0.args[0].value == 'raw_malloc'    # pseudo-function as a str
+    assert op0.args[0].value == 'raw_malloc_varsize' # pseudo-function as a str
     assert op1.opname == '-live-'
     assert op1.args == []
 
@@ -564,7 +564,7 @@
     tr = Transformer(FakeCPU(), FakeResidualCallControl())
     op0, op1 = tr.rewrite_operation(op)
     assert op0.opname == 'residual_call_ir_i'
-    assert op0.args[0].value == 'raw_malloc_zero'    # pseudo-function as a str
+    assert op0.args[0].value == 'raw_malloc_varsize_zero'  # pseudo-fn as a str
     assert op1.opname == '-live-'
     assert op1.args == []
 
@@ -578,6 +578,35 @@
     tr = Transformer(FakeCPU(), FakeResidualCallControl())
     py.test.raises(UnsupportedMallocFlags, tr.rewrite_operation, op)
 
+def test_raw_malloc_fixedsize():
+    S = lltype.Struct('dummy', ('x', lltype.Signed))
+    v = varoftype(lltype.Ptr(S))
+    flags = Constant({'flavor': 'raw', 'zero': True}, lltype.Void)
+    op = SpaceOperation('malloc', [Constant(S, lltype.Void), flags], v)
+    tr = Transformer(FakeCPU(), FakeResidualCallControl())
+    op0, op1 = tr.rewrite_operation(op)
+    assert op0.opname == 'residual_call_r_i'
+    assert op0.args[0].value == 'raw_malloc_fixedsize_zero' #pseudo-fn as a str
+    assert op1.opname == '-live-'
+    assert op1.args == []
+
+def test_raw_free():
+    S = lltype.Struct('dummy', ('x', lltype.Signed))
+    for flag in [True, False]:
+        flags = Constant({'flavor': 'raw', 'track_allocation': flag},
+                         lltype.Void)
+        op = SpaceOperation('free', [varoftype(lltype.Ptr(S)), flags],
+                            varoftype(lltype.Void))
+        tr = Transformer(FakeCPU(), FakeResidualCallControl())
+        op0, op1 = tr.rewrite_operation(op)
+        assert op0.opname == 'residual_call_ir_v'
+        if flag:
+            pseudo_op_name = 'raw_free'
+        else:
+            pseudo_op_name = 'raw_free_no_track_allocation'
+        assert op0.args[0].value == pseudo_op_name   # pseudo-function as a str
+        assert op1.opname == '-live-'
+
 def test_rename_on_links():
     v1 = Variable()
     v2 = Variable(); v2.concretetype = llmemory.Address
diff --git a/pypy/jit/metainterp/blackhole.py b/pypy/jit/metainterp/blackhole.py
--- a/pypy/jit/metainterp/blackhole.py
+++ b/pypy/jit/metainterp/blackhole.py
@@ -1504,7 +1504,6 @@
                         all_virtuals=None):
     from pypy.jit.metainterp.resume import blackhole_from_resumedata
     #debug_start('jit-blackhole')
-    metainterp_sd.profiler.start_blackhole()
     blackholeinterp = blackhole_from_resumedata(
         metainterp_sd.blackholeinterpbuilder,
         jitdriver_sd,
@@ -1518,10 +1517,9 @@
     current_exc = blackholeinterp._prepare_resume_from_failure(
         resumedescr.guard_opnum, dont_change_position)
 
-    try:
-        _run_forever(blackholeinterp, current_exc)
-    finally:
-        metainterp_sd.profiler.end_blackhole()
+    #try:
+    _run_forever(blackholeinterp, current_exc)
+    #finally:
         #debug_stop('jit-blackhole')
 
 def convert_and_run_from_pyjitpl(metainterp, raising_exception=False):
@@ -1529,7 +1527,6 @@
     # 'metainterp.framestack'.
     #debug_start('jit-blackhole')
     metainterp_sd = metainterp.staticdata
-    metainterp_sd.profiler.start_blackhole()
     nextbh = None
     for frame in metainterp.framestack:
         curbh = metainterp_sd.blackholeinterpbuilder.acquire_interp()
@@ -1546,8 +1543,7 @@
         firstbh.exception_last_value = current_exc
         current_exc = lltype.nullptr(rclass.OBJECTPTR.TO)
     #
-    try:
-        _run_forever(firstbh, current_exc)
-    finally:
-        metainterp_sd.profiler.end_blackhole()
+    #try:
+    _run_forever(firstbh, current_exc)
+    #finally:
         #debug_stop('jit-blackhole')
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
@@ -11,7 +11,7 @@
 from pypy.jit.metainterp.resoperation import ResOperation, rop, get_deep_immutable_oplist
 from pypy.jit.metainterp.history import TreeLoop, Box, History, JitCellToken, TargetToken
 from pypy.jit.metainterp.history import AbstractFailDescr, BoxInt
-from pypy.jit.metainterp.history import BoxPtr, BoxObj, BoxFloat, Const
+from pypy.jit.metainterp.history import BoxPtr, BoxObj, BoxFloat, Const, ConstInt
 from pypy.jit.metainterp import history
 from pypy.jit.metainterp.typesystem import llhelper, oohelper
 from pypy.jit.metainterp.optimize import InvalidLoop
@@ -254,7 +254,44 @@
     record_loop_or_bridge(metainterp_sd, loop)
     return target_token
 
+def patch_new_loop_to_load_virtualizable_fields(loop, jitdriver_sd):
+    vinfo = jitdriver_sd.virtualizable_info
+    extra_ops = []
+    inputargs = loop.inputargs
+    vable_box = inputargs[jitdriver_sd.index_of_virtualizable]
+    i = jitdriver_sd.num_red_args
+    loop.inputargs = inputargs[:i]
+    for descr in vinfo.static_field_descrs:
+        assert i < len(inputargs)
+        box = inputargs[i]
+        extra_ops.append(
+            ResOperation(rop.GETFIELD_GC, [vable_box], box, descr))
+        i += 1
+    arrayindex = 0
+    for descr in vinfo.array_field_descrs:
+        vable = vable_box.getref_base()
+        arraylen = vinfo.get_array_length(vable, arrayindex)
+        arraybox = BoxPtr()
+        extra_ops.append(
+            ResOperation(rop.GETFIELD_GC, [vable_box], arraybox, descr))
+        arraydescr = vinfo.array_descrs[arrayindex]
+        assert i + arraylen <= len(inputargs)
+        for index in range(arraylen):
+            box = inputargs[i]
+            extra_ops.append(
+                ResOperation(rop.GETARRAYITEM_GC,
+                             [arraybox, ConstInt(index)],
+                             box, descr=arraydescr))
+            i += 1
+        arrayindex += 1
+    assert i == len(inputargs)
+    loop.operations = extra_ops + loop.operations
+
 def send_loop_to_backend(greenkey, jitdriver_sd, metainterp_sd, loop, type):
+    vinfo = jitdriver_sd.virtualizable_info
+    if vinfo is not None:
+        patch_new_loop_to_load_virtualizable_fields(loop, jitdriver_sd)
+
     original_jitcell_token = loop.original_jitcell_token
     jitdriver_sd.on_compile(metainterp_sd.logger_ops, original_jitcell_token,
                             loop.operations, type, greenkey)
@@ -435,14 +472,14 @@
         if self.must_compile(metainterp_sd, jitdriver_sd):
             self.start_compiling()
             try:
-                return self._trace_and_compile_from_bridge(metainterp_sd,
-                                                           jitdriver_sd)
+                self._trace_and_compile_from_bridge(metainterp_sd,
+                                                    jitdriver_sd)
             finally:
                 self.done_compiling()
         else:
             from pypy.jit.metainterp.blackhole import resume_in_blackhole
             resume_in_blackhole(metainterp_sd, jitdriver_sd, self)
-            assert 0, "unreachable"
+        assert 0, "unreachable"
 
     def _trace_and_compile_from_bridge(self, metainterp_sd, jitdriver_sd):
         # 'jitdriver_sd' corresponds to the outermost one, i.e. the one
@@ -451,7 +488,7 @@
         # jitdrivers.
         from pypy.jit.metainterp.pyjitpl import MetaInterp
         metainterp = MetaInterp(metainterp_sd, jitdriver_sd)
-        return metainterp.handle_guard_failure(self)
+        metainterp.handle_guard_failure(self)
     _trace_and_compile_from_bridge._dont_inline_ = True
 
     def must_compile(self, metainterp_sd, jitdriver_sd):
@@ -767,21 +804,25 @@
         assert exception, "PropagateExceptionDescr: no exception??"
         raise metainterp_sd.ExitFrameWithExceptionRef(cpu, exception)
 
-def compile_tmp_callback(cpu, jitdriver_sd, greenboxes, redboxes,
+def compile_tmp_callback(cpu, jitdriver_sd, greenboxes, redargtypes,
                          memory_manager=None):
     """Make a LoopToken that corresponds to assembler code that just
     calls back the interpreter.  Used temporarily: a fully compiled
     version of the code may end up replacing it.
     """
-    # 'redboxes' is only used to know the types of red arguments.
-    inputargs = [box.clonebox() for box in redboxes]
     jitcell_token = make_jitcell_token(jitdriver_sd)
-    # 'nb_red_args' might be smaller than len(redboxes),
-    # because it doesn't include the virtualizable boxes.
     nb_red_args = jitdriver_sd.num_red_args
+    assert len(redargtypes) == nb_red_args
+    inputargs = []
+    for kind in redargtypes:
+        if   kind == history.INT:   box = BoxInt()
+        elif kind == history.REF:   box = BoxPtr()
+        elif kind == history.FLOAT: box = BoxFloat()
+        else: raise AssertionError
+        inputargs.append(box)
     k = jitdriver_sd.portal_runner_adr
     funcbox = history.ConstInt(heaptracker.adr2int(k))
-    callargs = [funcbox] + greenboxes + inputargs[:nb_red_args]
+    callargs = [funcbox] + greenboxes + inputargs
     #
     result_type = jitdriver_sd.result_type
     if result_type == history.INT:
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
@@ -124,9 +124,6 @@
     def sort_key(self):
         raise NotImplementedError
 
-    def set_future_value(self, cpu, j):
-        raise NotImplementedError
-
     def nonnull(self):
         raise NotImplementedError
 
@@ -289,9 +286,6 @@
     def _get_hash_(self):
         return make_hashable_int(self.value)
 
-    def set_future_value(self, cpu, j):
-        cpu.set_future_value_int(j, self.value)
-
     def same_constant(self, other):
         if isinstance(other, ConstInt):
             return self.value == other.value
@@ -329,9 +323,6 @@
     def _get_hash_(self):
         return longlong.gethash(self.value)
 
-    def set_future_value(self, cpu, j):
-        cpu.set_future_value_float(j, self.value)
-
     def same_constant(self, other):
         if isinstance(other, ConstFloat):
             return self.value == other.value
@@ -378,9 +369,6 @@
     def getaddr(self):
         return llmemory.cast_ptr_to_adr(self.value)
 
-    def set_future_value(self, cpu, j):
-        cpu.set_future_value_ref(j, self.value)
-
     def same_constant(self, other):
         if isinstance(other, ConstPtr):
             return self.value == other.value
@@ -432,9 +420,6 @@
         else:
             return 0
 
-    def set_future_value(self, cpu, j):
-        cpu.set_future_value_ref(j, self.value)
-
 ##    def getaddr(self):
 ##        # so far this is used only when calling
 ##        # CodeWriter.IndirectCallset.bytecode_for_address.  We don't need a
@@ -540,9 +525,6 @@
     def _get_hash_(self):
         return make_hashable_int(self.value)
 
-    def set_future_value(self, cpu, j):
-        cpu.set_future_value_int(j, self.value)
-
     def nonnull(self):
         return self.value != 0
 
@@ -575,9 +557,6 @@
     def _get_hash_(self):
         return longlong.gethash(self.value)
 
-    def set_future_value(self, cpu, j):
-        cpu.set_future_value_float(j, self.value)
-
     def nonnull(self):
         return self.value != longlong.ZEROF
 
@@ -620,9 +599,6 @@
         else:
             return 0
 
-    def set_future_value(self, cpu, j):
-        cpu.set_future_value_ref(j, self.value)
-
     def nonnull(self):
         return bool(self.value)
 
@@ -667,19 +643,12 @@
     def nonnull(self):
         return bool(self.value)
 
-    def set_future_value(self, cpu, j):
-        cpu.set_future_value_ref(j, self.value)
-
     def repr_rpython(self):
         return repr_rpython(self, 'bo')
 
     _getrepr_ = repr_object
 
 
-def set_future_values(cpu, boxes):
-    for j in range(len(boxes)):
-        boxes[j].set_future_value(cpu, j)
-
 # ____________________________________________________________
 
 
@@ -768,10 +737,23 @@
 
 class TargetToken(AbstractDescr):
     def __init__(self, targeting_jitcell_token=None):
-        # The jitcell to which jumps might result in a jump to this label
+        # Warning, two different jitcell_tokens here!
+        #
+        # * 'targeting_jitcell_token' is only useful for the front-end,
+        #   and it means: consider the LABEL that uses this TargetToken.
+        #   At this position, the state is logically the one given
+        #   by targeting_jitcell_token.  So e.g. if we want to enter the
+        #   JIT with some given green args, if the jitcell matches, then
+        #   we can jump to this LABEL.
+        #
+        # * 'original_jitcell_token' is information from the backend's
+        #   point of view: it means that this TargetToken is used in
+        #   a LABEL that belongs to either:
+        #   - a loop; then 'original_jitcell_token' is this loop
+        #   - or a bridge; then 'original_jitcell_token' is the loop
+        #     out of which we made this bridge
+        #
         self.targeting_jitcell_token = targeting_jitcell_token
-        
-        # The jitcell where the trace containing the label with this TargetToken begins
         self.original_jitcell_token = None
 
         self.virtual_state = None
@@ -981,15 +963,19 @@
         self.aborted_keys = []
         self.invalidated_token_numbers = set()    # <- not RPython
         self.jitcell_token_wrefs = []
+        self.jitcell_dicts = []                   # <- not RPython
 
     def clear(self):
         del self.loops[:]
         del self.locations[:]
         del self.aborted_keys[:]
+        del self.jitcell_token_wrefs[:]
         self.invalidated_token_numbers.clear()
         self.compiled_count = 0
         self.enter_count = 0
         self.aborted_count = 0
+        for dict in self.jitcell_dicts:
+            dict.clear()
 
     def add_jitcell_token(self, token):
         assert isinstance(token, JitCellToken)
diff --git a/pypy/jit/metainterp/jitdriver.py b/pypy/jit/metainterp/jitdriver.py
--- a/pypy/jit/metainterp/jitdriver.py
+++ b/pypy/jit/metainterp/jitdriver.py
@@ -11,6 +11,7 @@
     #    self.portal_calldescr  ... pypy.jit.metainterp.warmspot
     #    self.num_green_args    ... pypy.jit.metainterp.warmspot
     #    self.num_red_args      ... pypy.jit.metainterp.warmspot
+    #    self.red_args_types    ... pypy.jit.metainterp.warmspot
     #    self.result_type       ... pypy.jit.metainterp.warmspot
     #    self.virtualizable_info... pypy.jit.metainterp.warmspot
     #    self.greenfield_info   ... pypy.jit.metainterp.warmspot
diff --git a/pypy/jit/metainterp/jitprof.py b/pypy/jit/metainterp/jitprof.py
--- a/pypy/jit/metainterp/jitprof.py
+++ b/pypy/jit/metainterp/jitprof.py
@@ -10,8 +10,6 @@
 counters="""
 TRACING
 BACKEND
-RUNNING
-BLACKHOLE
 OPS
 RECORDED_OPS
 GUARDS
@@ -67,18 +65,6 @@
     def end_backend(self):
         pass
 
-    def start_running(self):
-        pass
-
-    def end_running(self):
-        pass
-
-    def start_blackhole(self):
-        pass
-
-    def end_blackhole(self):
-        pass
-
     def count(self, kind, inc=1):
         pass
 
@@ -134,16 +120,6 @@
     def start_backend(self):   self._start(BACKEND)
     def end_backend(self):     self._end  (BACKEND)
 
-    # Don't record times for 'running' and 'blackhole' because there are
-    # too many of them: calling time.time() is a major blocker.
-    # If you are interested in these numbers, use 'PYPYLOG=file' and
-    # look at the resulting file with pypy/tool/logparser.py.
-    def start_running(self): self.count(RUNNING)
-    def end_running(self):   pass
-
-    def start_blackhole(self): self.count(BLACKHOLE)
-    def end_blackhole(self):   pass
-
     def count(self, kind, inc=1):
         self.counters[kind] += inc        
     
@@ -165,8 +141,6 @@
         calls = self.calls
         self._print_line_time("Tracing", cnt[TRACING],   tim[TRACING])
         self._print_line_time("Backend", cnt[BACKEND],   tim[BACKEND])
-        self._print_intline("Running asm", cnt[RUNNING])
-        self._print_intline("Blackhole", cnt[BLACKHOLE])
         line = "TOTAL:      \t\t%f" % (self.tk - self.starttime, )
         debug_print(line)
         self._print_intline("ops", cnt[OPS])
diff --git a/pypy/jit/metainterp/memmgr.py b/pypy/jit/metainterp/memmgr.py
--- a/pypy/jit/metainterp/memmgr.py
+++ b/pypy/jit/metainterp/memmgr.py
@@ -1,5 +1,5 @@
 import math
-from pypy.rlib.rarithmetic import r_int64
+from pypy.rlib.rarithmetic import r_int64, r_uint
 from pypy.rlib.debug import debug_start, debug_print, debug_stop
 from pypy.rlib.objectmodel import we_are_translated
 
@@ -21,6 +21,7 @@
 #
 
 class MemoryManager(object):
+    NO_NEXT_CHECK = r_int64(2 ** 63 - 1)
 
     def __init__(self):
         self.check_frequency = -1
@@ -36,12 +37,13 @@
         # According to my estimates it's about 5e9 years given 1000 loops
         # per second
         self.current_generation = r_int64(1)
-        self.next_check = r_int64(-1)
+        self.next_check = self.NO_NEXT_CHECK
         self.alive_loops = {}
+        self._cleanup_jitcell_dicts = lambda: None
 
     def set_max_age(self, max_age, check_frequency=0):
         if max_age <= 0:
-            self.next_check = r_int64(-1)
+            self.next_check = self.NO_NEXT_CHECK
         else:
             self.max_age = max_age
             if check_frequency <= 0:
@@ -49,10 +51,11 @@
             self.check_frequency = check_frequency
             self.next_check = self.current_generation + 1
 
-    def next_generation(self):
+    def next_generation(self, do_cleanups_now=True):
         self.current_generation += 1
-        if self.current_generation == self.next_check:
+        if do_cleanups_now and self.current_generation >= self.next_check:
             self._kill_old_loops_now()
+            self._cleanup_jitcell_dicts()
             self.next_check = self.current_generation + self.check_frequency
 
     def keep_loop_alive(self, looptoken):
@@ -81,3 +84,22 @@
             # a single one is not enough for all tests :-(
             rgc.collect(); rgc.collect(); rgc.collect()
         debug_stop("jit-mem-collect")
+
+    def get_current_generation_uint(self):
+        """Return the current generation, possibly truncated to a uint.
+        To use only as an approximation for decaying counters."""
+        return r_uint(self.current_generation)
+
+    def record_jitcell_dict(self, callback):
+        """NOT_RPYTHON.  The given jitcell_dict is a dict that needs
+        occasional clean-ups of old cells.  A cell is old if it never
+        reached the threshold, and its counter decayed to a tiny value."""
+        # note that the various jitcell_dicts have different RPython types,
+        # so we have to make a different function for each one.  These
+        # functions are chained to each other: each calls the previous one.
+        def cleanup_dict():
+            callback()
+            cleanup_previous()
+        #
+        cleanup_previous = self._cleanup_jitcell_dicts
+        self._cleanup_jitcell_dicts = cleanup_dict
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
@@ -246,15 +246,16 @@
                 self.force_lazy_setfields_and_arrayitems_for_guard())
             return
         opnum = op.getopnum()
-        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
+        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.SETINTERIORFIELD_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
diff --git a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
--- a/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
+++ b/pypy/jit/metainterp/optimizeopt/test/test_optimizeopt.py
@@ -7744,6 +7744,22 @@
         """
         self.optimize_loop(ops, expected)
 
+    def test_setinteriorfield_should_not_clear_cache(self):
+        ops = """
+        [i0, p0]
+        i2 = getfield_gc(p0, descr=adescr)
+        i3 = call(i2, descr=nonwritedescr)
+        setinteriorfield_raw(i0, i2, i3)
+        jump(i0, p0)
+        """
+        expected = """
+        [i0, p0, i2]
+        i3 = call(i2, descr=nonwritedescr)
+        setinteriorfield_raw(i0, i2, i3)
+        jump(i0, p0, i2)
+        """
+        self.optimize_loop(ops, expected)
+
 class TestLLtype(OptimizeOptTest, LLtypeMixin):
     pass
 
diff --git a/pypy/jit/metainterp/pyjitpl.py b/pypy/jit/metainterp/pyjitpl.py
--- a/pypy/jit/metainterp/pyjitpl.py
+++ b/pypy/jit/metainterp/pyjitpl.py
@@ -1810,7 +1810,7 @@
 
     def _interpret(self):
         # Execute the frames forward until we raise a DoneWithThisFrame,
-        # a ExitFrameWithException, or a GenerateMergePoint exception.
+        # a ExitFrameWithException, or a ContinueRunningNormally exception.
         self.staticdata.stats.entered()
         while True:
             self.framestack[-1].run_one_step()
@@ -1858,8 +1858,6 @@
         self.seen_loop_header_for_jdindex = -1
         try:
             self.interpret()
-        except GenerateMergePoint, gmp:
-            return self.designate_target_loop(gmp)
         except SwitchToBlackhole, stb:
             self.run_blackhole_interp_to_cancel_tracing(stb)
         assert False, "should always raise"
@@ -1894,8 +1892,6 @@
             if self.resumekey_original_loop_token is None:   # very rare case
                 raise SwitchToBlackhole(ABORT_BRIDGE)
             self.interpret()
-        except GenerateMergePoint, gmp:
-            return self.designate_target_loop(gmp)
         except SwitchToBlackhole, stb:
             self.run_blackhole_interp_to_cancel_tracing(stb)
         assert False, "should always raise"
@@ -1980,12 +1976,48 @@
         start = len(self.history.operations)
         self.current_merge_points.append((live_arg_boxes, start))
 
-    def designate_target_loop(self, gmp):
-        loop_token = gmp.target_loop_token
+    def _unpack_boxes(self, boxes, start, stop):
+        ints = []; refs = []; floats = []
+        for i in range(start, stop):
+            box = boxes[i]
+            if   box.type == history.INT: ints.append(box.getint())
+            elif box.type == history.REF: refs.append(box.getref_base())
+            elif box.type == history.FLOAT:floats.append(box.getfloatstorage())
+            else: assert 0
+        return ints[:], refs[:], floats[:]
+
+    def raise_continue_running_normally(self, live_arg_boxes, loop_token):
+        self.history.inputargs = None
+        self.history.operations = None
+        # For simplicity, we just raise ContinueRunningNormally here and
+        # ignore the loop_token passed in.  It means that we go back to
+        # interpreted mode, but it should come back very quickly to the
+        # JIT, find probably the same 'loop_token', and execute it.
+        if we_are_translated():
+            num_green_args = self.jitdriver_sd.num_green_args
+            gi, gr, gf = self._unpack_boxes(live_arg_boxes, 0, num_green_args)
+            ri, rr, rf = self._unpack_boxes(live_arg_boxes, num_green_args,
+                                            len(live_arg_boxes))
+            CRN = self.staticdata.ContinueRunningNormally
+            raise CRN(gi, gr, gf, ri, rr, rf)
+        else:
+            # However, in order to keep the existing tests working
+            # (which are based on the assumption that 'loop_token' is
+            # directly used here), a bit of custom non-translatable code...
+            self._nontranslated_run_directly(live_arg_boxes, loop_token)
+            assert 0, "unreachable"
+
+    def _nontranslated_run_directly(self, live_arg_boxes, loop_token):
+        "NOT_RPYTHON"
+        args = []
         num_green_args = self.jitdriver_sd.num_green_args
-        residual_args = gmp.argboxes[num_green_args:]
-        history.set_future_values(self.cpu, residual_args)
-        return loop_token
+        num_red_args = self.jitdriver_sd.num_red_args
+        for box in live_arg_boxes[num_green_args:num_green_args+num_red_args]:
+            if   box.type == history.INT: args.append(box.getint())
+            elif box.type == history.REF: args.append(box.getref_base())
+            elif box.type == history.FLOAT: args.append(box.getfloatstorage())
+            else: assert 0
+        self.jitdriver_sd.warmstate.execute_assembler(loop_token, *args)
 
     def prepare_resume_from_failure(self, opnum, dont_change_position=False):
         frame = self.framestack[-1]
@@ -2054,10 +2086,9 @@
 
 
         if target_token is not None: # raise if it *worked* correctly
-            self.history.inputargs = None
-            self.history.operations = None
             assert isinstance(target_token, TargetToken)
-            raise GenerateMergePoint(live_arg_boxes, target_token.targeting_jitcell_token)
+            jitcell_token = target_token.targeting_jitcell_token
+            self.raise_continue_running_normally(live_arg_boxes, jitcell_token)
 
     def compile_trace(self, live_arg_boxes, start_resumedescr):
         num_green_args = self.jitdriver_sd.num_green_args
@@ -2075,10 +2106,9 @@
         finally:
             self.history.operations.pop()     # remove the JUMP
         if target_token is not None: # raise if it *worked* correctly
-            self.history.inputargs = None
-            self.history.operations = None
             assert isinstance(target_token, TargetToken)
-            raise GenerateMergePoint(live_arg_boxes, target_token.targeting_jitcell_token)
+            jitcell_token = target_token.targeting_jitcell_token
+            self.raise_continue_running_normally(live_arg_boxes, jitcell_token)
 
     def compile_bridge_and_loop(self, original_boxes, live_arg_boxes, start,
                                 bridge_arg_boxes, start_resumedescr):
@@ -2114,10 +2144,8 @@
         except RetraceLoop:
             assert False
         assert target_loop_token is not None
-
-        self.history.inputargs = None
-        self.history.operations = None
-        raise GenerateMergePoint(live_arg_boxes, old_loop_tokens[0])
+        self.raise_continue_running_normally(live_arg_boxes,
+                                             old_loop_tokens[0])
 
     def compile_done_with_this_frame(self, exitbox):
         self.gen_store_back_in_virtualizable()
@@ -2395,22 +2423,6 @@
                                             abox, ConstInt(j), itembox)
             assert i + 1 == len(self.virtualizable_boxes)
 
-    def gen_load_from_other_virtualizable(self, vinfo, vbox):
-        boxes = []
-        assert vinfo is not None
-        for i in range(vinfo.num_static_extra_boxes):
-            descr = vinfo.static_field_descrs[i]
-            boxes.append(self.execute_and_record(rop.GETFIELD_GC, descr, vbox))
-        virtualizable = vinfo.unwrap_virtualizable_box(vbox)
-        for k in range(vinfo.num_arrays):
-            descr = vinfo.array_field_descrs[k]
-            abox = self.execute_and_record(rop.GETFIELD_GC, descr, vbox)
-            descr = vinfo.array_descrs[k]
-            for j in range(vinfo.get_array_length(virtualizable, k)):
-                boxes.append(self.execute_and_record(rop.GETARRAYITEM_GC, descr,
-                                                     abox, ConstInt(j)))
-        return boxes
-
     def replace_box(self, oldbox, newbox):
         assert isinstance(oldbox, Box)
         for frame in self.framestack:
@@ -2482,25 +2494,13 @@
         greenargs = arglist[1:num_green_args+1]
         args = arglist[num_green_args+1:]
         assert len(args) == targetjitdriver_sd.num_red_args
-        vinfo = targetjitdriver_sd.virtualizable_info
-        if vinfo is not None:
-            index = targetjitdriver_sd.index_of_virtualizable
-            vbox = args[index]
-            args = args + self.gen_load_from_other_virtualizable(vinfo, vbox)
-            # ^^^ and not "+=", which makes 'args' a resizable list
         warmrunnerstate = targetjitdriver_sd.warmstate
-        token = warmrunnerstate.get_assembler_token(greenargs, args)
+        token = warmrunnerstate.get_assembler_token(greenargs)
         op = op.copy_and_change(rop.CALL_ASSEMBLER, args=args, descr=token)
         self.history.operations.append(op)
 
 # ____________________________________________________________
 
-class GenerateMergePoint(JitException):
-    def __init__(self, args, target_loop_token):
-        assert target_loop_token is not None
-        self.argboxes = args
-        self.target_loop_token = target_loop_token
-
 class ChangeFrame(JitException):
     """Raised after we mutated metainterp.framestack, in order to force
     it to reload the current top-of-stack frame that gets interpreted."""
diff --git a/pypy/jit/metainterp/resoperation.py b/pypy/jit/metainterp/resoperation.py
--- a/pypy/jit/metainterp/resoperation.py
+++ b/pypy/jit/metainterp/resoperation.py
@@ -381,11 +381,11 @@
     'GUARD_ISNULL/1d',
     'GUARD_NONNULL_CLASS/2d',
     '_GUARD_FOLDABLE_LAST',
-    'GUARD_NO_EXCEPTION/0d',
-    'GUARD_EXCEPTION/1d',
+    'GUARD_NO_EXCEPTION/0d',    # may be called with an exception currently set
+    'GUARD_EXCEPTION/1d',       # may be called with an exception currently set
     'GUARD_NO_OVERFLOW/0d',
     'GUARD_OVERFLOW/0d',
-    'GUARD_NOT_FORCED/0d',
+    'GUARD_NOT_FORCED/0d',      # may be called with an exception currently set
     'GUARD_NOT_INVALIDATED/0d',
     '_GUARD_LAST', # ----- end of guard operations -----
 
diff --git a/pypy/jit/metainterp/test/support.py b/pypy/jit/metainterp/test/support.py
--- a/pypy/jit/metainterp/test/support.py
+++ b/pypy/jit/metainterp/test/support.py
@@ -4,9 +4,9 @@
 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.warmstate import unspecialize_value
 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 codewriter, longlong
 from pypy.rlib.rfloat import isnan
@@ -136,11 +136,11 @@
     procedure_token = metainterp.get_procedure_token(args[:num_green_args])
     # a loop was successfully created by _run_with_pyjitpl(); call it
     cpu = metainterp.cpu
+    args1 = []
     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(procedure_token)
+        args1.append(unspecialize_value(x))
+    faildescr = cpu.execute_token(procedure_token, *args1)
     assert faildescr.__class__.__name__.startswith('DoneWithThisFrameDescr')
     if metainterp.jitdriver_sd.result_type == history.INT:
         return cpu.get_latest_value_int(0)
diff --git a/pypy/jit/metainterp/test/test_ajit.py b/pypy/jit/metainterp/test/test_ajit.py
--- a/pypy/jit/metainterp/test/test_ajit.py
+++ b/pypy/jit/metainterp/test/test_ajit.py
@@ -9,7 +9,6 @@
 from pypy.jit.metainterp.test.support import LLJitMixin, OOJitMixin, noConst
 from pypy.jit.metainterp.typesystem import LLTypeHelper, OOTypeHelper
 from pypy.jit.metainterp.warmspot import get_stats
-from pypy.jit.metainterp.warmstate import set_future_value
 from pypy.rlib import rerased
 from pypy.rlib.jit import (JitDriver, we_are_jitted, hint, dont_look_inside,
     loop_invariant, elidable, promote, jit_debug, assert_green,
@@ -2911,6 +2910,27 @@
         res = self.meta_interp(f, [32])
         assert res == f(32)
 
+    def test_decay_counters(self):
+        myjitdriver = JitDriver(greens = ['m'], reds = ['n'])
+        def f(m, n):
+            while n > 0:
+                myjitdriver.jit_merge_point(m=m, n=n)
+                n += m
+                n -= m
+                n -= 1
+        def main():
+            f(5, 7)      # run 7x with m=5           counter[m=5] = 7
+            f(15, 10)    # compiles one loop         counter[m=5] = 3  (automatic decay)
+            f(5, 5)      # run 5x times with m=5     counter[m=5] = 8
+        #
+        self.meta_interp(main, [], decay_halflife=1,
+                         function_threshold=0, threshold=9, trace_eagerness=99)
+        self.check_trace_count(1)
+        #
+        self.meta_interp(main, [], decay_halflife=1,
+                         function_threshold=0, threshold=8, trace_eagerness=99)
+        self.check_trace_count(2)
+
 
 class TestOOtype(BasicTests, OOJitMixin):
 
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
@@ -55,6 +55,7 @@
         warmstate = FakeState()
         on_compile = staticmethod(lambda *args: None)
         on_compile_bridge = staticmethod(lambda *args: None)
+        virtualizable_info = None
 
 def test_compile_loop():
     cpu = FakeCPU()
@@ -171,23 +172,17 @@
         result_type = INT
     #
     loop_token = compile_tmp_callback(cpu, FakeJitDriverSD(),
-                                      [ConstInt(12), ConstInt(34)],
-                                      [BoxInt(56), ConstInt(78), BoxInt(90)])
+                                      [ConstInt(12), ConstInt(34)], "ii")
     #
     raiseme = None
-    cpu.set_future_value_int(0, -156)
-    cpu.set_future_value_int(1, -178)
-    cpu.set_future_value_int(2, -190)     # passed in, but dropped
-    fail_descr = cpu.execute_token(loop_token)
+    # only two arguments must be passed in
+    fail_descr = cpu.execute_token(loop_token, -156, -178)
     assert fail_descr is FakeJitDriverSD().portal_finishtoken
     #
     EXC = lltype.GcStruct('EXC')
     llexc = lltype.malloc(EXC)
     raiseme = LLException("exception class", llexc)
-    cpu.set_future_value_int(0, -156)
-    cpu.set_future_value_int(1, -178)
-    cpu.set_future_value_int(2, -190)
-    fail_descr = cpu.execute_token(loop_token)
+    fail_descr = cpu.execute_token(loop_token, -156, -178)
     assert isinstance(fail_descr, compile.PropagateExceptionDescr)
     got = cpu.grab_exc_value()
     assert lltype.cast_opaque_ptr(lltype.Ptr(EXC), got) == llexc
@@ -196,10 +191,7 @@
         class ExitFrameWithExceptionRef(Exception):
             pass
     FakeMetaInterpSD.cpu = cpu
-    cpu.set_future_value_int(0, -156)
-    cpu.set_future_value_int(1, -178)
-    cpu.set_future_value_int(2, -190)
-    fail_descr = cpu.execute_token(loop_token)
+    fail_descr = cpu.execute_token(loop_token, -156, -178)
     try:
         fail_descr.handle_fail(FakeMetaInterpSD(), None)
     except FakeMetaInterpSD.ExitFrameWithExceptionRef, e:
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
@@ -10,7 +10,7 @@
         self.counter = 123456
         Profiler.start(self)
         self.events = []
-        self.times = [0, 0, 0, 0]
+        self.times = [0, 0]
     
     def timer(self):
         self.counter += 1
@@ -24,12 +24,6 @@
         Profiler._end(self, event)
         self.events.append(~event)
 
-    def start_running(self):   self._start(RUNNING)
-    def end_running(self):     self._end(RUNNING)
-
-    def start_blackhole(self): self._start(BLACKHOLE)
-    def end_blackhole(self):   self._end(BLACKHOLE)
-
 class ProfilerMixin(LLJitMixin):
     def meta_interp(self, *args, **kwds):
         kwds = kwds.copy()
@@ -56,14 +50,10 @@
             BACKEND,
             ~ BACKEND,
             ~ TRACING,
-            RUNNING,
-            ~ RUNNING,
-            BLACKHOLE,
-            ~ BLACKHOLE
             ]
         assert profiler.events == expected
-        assert profiler.times == [2, 1, 1, 1]
-        assert profiler.counters == [1, 1, 1, 1, 3, 3, 1, 15, 2, 0, 0, 0, 0,
+        assert profiler.times == [2, 1]
+        assert profiler.counters == [1, 1, 3, 3, 1, 15, 2, 0, 0, 0, 0,
                                      0, 0, 0, 0, 0]
 
     def test_simple_loop_with_call(self):
diff --git a/pypy/jit/metainterp/test/test_rawmem.py b/pypy/jit/metainterp/test/test_rawmem.py
--- a/pypy/jit/metainterp/test/test_rawmem.py
+++ b/pypy/jit/metainterp/test/test_rawmem.py
@@ -8,7 +8,7 @@
         VOID_TP = lltype.Array(lltype.Void, hints={"nolength": True, "uncast_on_llgraph": True})
         class A(object):
             def __init__(self, x):
-                self.storage = rffi.cast(lltype.Ptr(VOID_TP), x)\
+                self.storage = rffi.cast(lltype.Ptr(VOID_TP), x)
 
         def f(n):
             x = lltype.malloc(TP, n, flavor="raw", zero=True)
@@ -19,4 +19,14 @@
             lltype.free(x, flavor="raw")
             return s
         res = self.interp_operations(f, [10])
-        assert res == 1.0
\ No newline at end of file
+
+    def test_fixed_size_malloc(self):
+        TIMEVAL = lltype.Struct('dummy', ('tv_sec', rffi.LONG), ('tv_usec', rffi.LONG))
+        def f():
+            p = lltype.malloc(TIMEVAL, flavor='raw')
+            lltype.free(p, flavor='raw')
+            return 42
+        res = self.interp_operations(f, [])
+        assert res == 42
+        self.check_operations_history({'call': 2, 'guard_no_exception': 1,
+                                       'finish': 1})
diff --git a/pypy/jit/metainterp/test/test_tl.py b/pypy/jit/metainterp/test/test_tl.py
--- a/pypy/jit/metainterp/test/test_tl.py
+++ b/pypy/jit/metainterp/test/test_tl.py
@@ -72,16 +72,16 @@
         res = self.meta_interp(main, [0, 6], listops=True,
                                backendopt=True)
         assert res == 5040
-        self.check_resops({'jump': 1, 'int_le': 2, 'guard_value': 1,
-                           'int_mul': 2, 'guard_false': 2, 'int_sub': 2})
+        self.check_simple_loop({'jump': 1, 'int_le': 1,
+                                'int_mul': 1, 'guard_false': 1, 'int_sub': 1})
 
     def test_tl_2(self):
         main = self._get_main()
         res = self.meta_interp(main, [1, 10], listops=True,
                                backendopt=True)
         assert res == main(1, 10)
-        self.check_resops({'int_le': 2, 'int_sub': 2, 'jump': 1,
-                           'guard_false': 2, 'guard_value': 1})
+        self.check_simple_loop({'int_le': 1, 'int_sub': 1, 'jump': 1,
+                                'guard_false': 1})
 
     def test_tl_call(self, listops=True, policy=None):
         from pypy.jit.tl.tl import interp
diff --git a/pypy/jit/metainterp/test/test_virtualizable.py b/pypy/jit/metainterp/test/test_virtualizable.py
--- a/pypy/jit/metainterp/test/test_virtualizable.py
+++ b/pypy/jit/metainterp/test/test_virtualizable.py
@@ -77,7 +77,7 @@
             return xy.inst_x
         res = self.meta_interp(f, [20])
         assert res == 30
-        self.check_resops(setfield_gc=0, getfield_gc=0)
+        self.check_simple_loop(setfield_gc=0, getfield_gc=0)
 
     def test_preexisting_access_2(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'xy'],
@@ -102,7 +102,8 @@
         assert f(5) == 185
         res = self.meta_interp(f, [5])
         assert res == 185
-        self.check_resops(setfield_gc=0, getfield_gc=0)
+        self.check_resops(setfield_gc=0,
+                          getfield_gc=2)  # <= at the header of the loop
 
     def test_two_paths_access(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'xy'],
@@ -124,7 +125,7 @@
             return xy.inst_x
         res = self.meta_interp(f, [18])
         assert res == 10118
-        self.check_resops(setfield_gc=0, getfield_gc=0)
+        self.check_resops(setfield_gc=0, getfield_gc=2)
 
     def test_synchronize_in_return(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'xy'],
@@ -146,7 +147,7 @@
             return xy.inst_x
         res = self.meta_interp(f, [18])
         assert res == 10180
-        self.check_resops(setfield_gc=0, getfield_gc=0)
+        self.check_resops(setfield_gc=0, getfield_gc=2)
 
     def test_virtualizable_and_greens(self):
         myjitdriver = JitDriver(greens = ['m'], reds = ['n', 'xy'],
@@ -174,7 +175,7 @@
             return res
         res = self.meta_interp(f, [40])
         assert res == 50 * 4
-        self.check_resops(setfield_gc=0, getfield_gc=0)
+        self.check_resops(setfield_gc=0, getfield_gc=4)
 
     def test_double_frame(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'xy', 'other'],
@@ -197,7 +198,8 @@
             return xy.inst_x
         res = self.meta_interp(f, [20])
         assert res == 134
-        self.check_resops(setfield_gc=2, getfield_gc=1)
+        self.check_simple_loop(setfield_gc=1, getfield_gc=0)
+        self.check_resops(setfield_gc=2, getfield_gc=3)
 
     # ------------------------------
 
@@ -247,8 +249,8 @@
             return xy2.inst_l1[2]
         res = self.meta_interp(f, [16])
         assert res == 3001 + 16 * 80
-        self.check_resops(setarrayitem_gc=0, setfield_gc=0,
-                          getarrayitem_gc=0, getfield_gc=0)
+        self.check_simple_loop(setarrayitem_gc=0, setfield_gc=0,
+                               getarrayitem_gc=0, getfield_gc=0)
 
     def test_synchronize_arrays_in_return(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'xy2'],
@@ -278,7 +280,8 @@
         assert f(18) == 10360
         res = self.meta_interp(f, [18])
         assert res == 10360
-        self.check_resops(setfield_gc=0, getarrayitem_gc=0, getfield_gc=0)
+        self.check_simple_loop(setfield_gc=0, getarrayitem_gc=0,
+                               getfield_gc=0, setarrayitem_gc=0)
 
     def test_array_length(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'xy2'],
@@ -304,8 +307,8 @@
             return xy2.inst_l1[1]
         res = self.meta_interp(f, [18])
         assert res == 2941309 + 18
-        self.check_resops(setfield_gc=0, getarrayitem_gc=0,
-                          arraylen_gc=0, getfield_gc=0)
+        self.check_simple_loop(setfield_gc=0, getarrayitem_gc=0,
+                               arraylen_gc=0, getfield_gc=0)
 
     def test_residual_function(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'xy2'],
@@ -338,8 +341,8 @@
             return xy2.inst_l1[1]
         res = self.meta_interp(f, [18])
         assert res == 2941309 + 18
-        self.check_resops(call=2, setfield_gc=0, getarrayitem_gc=0,
-                          arraylen_gc=2, getfield_gc=0)
+        self.check_simple_loop(call=1, setfield_gc=0, getarrayitem_gc=0,
+                               arraylen_gc=1, getfield_gc=0)
 
     def test_double_frame_array(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'xy2', 'other'],
@@ -375,8 +378,8 @@
         expected = f(20)
         res = self.meta_interp(f, [20], enable_opts='')
         assert res == expected
-        self.check_resops(setarrayitem_gc=1, setfield_gc=0,
-                          getarrayitem_gc=1, arraylen_gc=1, getfield_gc=1)
+        self.check_simple_loop(setarrayitem_gc=1, setfield_gc=0,
+                               getarrayitem_gc=1, arraylen_gc=1, getfield_gc=1)
 
     # ------------------------------
 
@@ -423,7 +426,8 @@
         assert f(18) == 10360
         res = self.meta_interp(f, [18])
         assert res == 10360
-        self.check_resops(setfield_gc=0, getarrayitem_gc=0, getfield_gc=0)
+        self.check_simple_loop(getfield_gc=0, getarrayitem_gc=0,
+                               setfield_gc=0, setarrayitem_gc=0)
 
     # ------------------------------
 
@@ -457,7 +461,7 @@
 
         res = self.meta_interp(f, [10])
         assert res == 55
-        self.check_resops(setfield_gc=0, getfield_gc=0)
+        self.check_simple_loop(setfield_gc=0, getfield_gc=0)
 
     def test_virtualizable_with_array(self):
         myjitdriver = JitDriver(greens = [], reds = ['n', 'x', 'frame'],
@@ -491,7 +495,8 @@
 
         res = self.meta_interp(f, [10, 1], listops=True)
         assert res == f(10, 1)
-        self.check_resops(getarrayitem_gc=0)
+        self.check_simple_loop(getfield_gc=0, getarrayitem_gc=0)
+        self.check_resops(getfield_gc=2, getarrayitem_gc=4)
 
     def test_subclass_of_virtualizable(self):
         myjitdriver = JitDriver(greens = [], reds = ['frame'],
@@ -519,7 +524,7 @@
 
         res = self.meta_interp(f, [10])
         assert res == 55
-        self.check_resops(setfield_gc=0, getfield_gc=0)
+        self.check_simple_loop(setfield_gc=0, getfield_gc=0)
 
     def test_external_pass(self):
         jitdriver = JitDriver(greens = [], reds = ['n', 'z', 'frame'],
@@ -1037,7 +1042,7 @@
 
         res = self.meta_interp(f, [10])
         assert res == 55
-        self.check_resops(setfield_gc=0, getfield_gc=0)
+        self.check_simple_loop(setfield_gc=0, getfield_gc=0)
 
         from pypy.jit.backend.test.support import BaseCompiledMixin
         if isinstance(self, BaseCompiledMixin):
@@ -1197,7 +1202,8 @@
 
         res = self.meta_interp(f, [10])
         assert res == 155
-        self.check_resops(setfield_gc=0, getfield_gc=0)
+        self.check_simple_loop(setfield_gc=0, getfield_gc=0)
+        self.check_resops(setfield_gc=0, getfield_gc=2)
 
     def test_blackhole_should_synchronize(self):
         myjitdriver = JitDriver(greens = [], reds = ['frame'],
@@ -1233,7 +1239,8 @@
 
         res = self.meta_interp(f, [10])
         assert res == 155
-        self.check_resops(setfield_gc=0, getfield_gc=0)
+        self.check_simple_loop(setfield_gc=0, getfield_gc=0)
+        self.check_resops(setfield_gc=0, getfield_gc=2)
 
     def test_blackhole_should_not_reenter(self):
         if not self.basic:
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
@@ -303,18 +303,11 @@
         exc_vtable = lltype.malloc(OBJECT_VTABLE, immortal=True)
         cls.exc_vtable = exc_vtable
 
-        class FakeLoopToken:
+        class FakeFailDescr(object):
             def __init__(self, no):
                 self.no = no
-                self.generation = 0
-
-        class FakeFailDescr(object):
-            def __init__(self, looptoken):
-                assert isinstance(looptoken, FakeLoopToken)
-                self.looptoken = looptoken
-            
             def handle_fail(self, metainterp_sd, jitdrivers_sd):
-                no = self.looptoken.no
+                no = self.no
                 if no == 0:
                     raise metainterp_sd.warmrunnerdesc.DoneWithThisFrameInt(3)
                 if no == 1:
@@ -326,7 +319,7 @@
                     raise metainterp_sd.warmrunnerdesc.ExitFrameWithExceptionRef(
                         metainterp_sd.cpu,
                         lltype.cast_opaque_ptr(llmemory.GCREF, exc))
-                return self.looptoken
+                assert 0
 
         class FakeDescr:
             def as_vtable_size_descr(self):
@@ -353,11 +346,10 @@
             sizeof       = nodescr
 
             def get_fail_descr_from_number(self, no):
-                return FakeFailDescr(FakeLoopToken(no))
+                return FakeFailDescr(no)
 
-            def execute_token(self, token):
-                assert token.no == 2
-                return FakeFailDescr(FakeLoopToken(1))
+            def make_execute_token(self, *ARGS):
+                return "not callable"
 
         driver = JitDriver(reds = ['red'], greens = ['green'])
         
@@ -381,7 +373,6 @@
         [jd] = self.desc.jitdrivers_sd
         assert jd._assembler_call_helper(0, 0) == 3
         assert jd._assembler_call_helper(1, 0) == 10
-        assert jd._assembler_call_helper(2, 0) == 10
         try:
             jd._assembler_call_helper(3, 0)
         except LLException, lle:
diff --git a/pypy/jit/metainterp/test/test_warmstate.py b/pypy/jit/metainterp/test/test_warmstate.py
--- a/pypy/jit/metainterp/test/test_warmstate.py
+++ b/pypy/jit/metainterp/test/test_warmstate.py
@@ -1,3 +1,4 @@
+import math
 from pypy.rpython.test.test_llinterp import interpret
 from pypy.rpython.lltypesystem import lltype, llmemory, rstr, rffi
 from pypy.rpython.ootypesystem import ootype
@@ -8,7 +9,7 @@
 from pypy.jit.metainterp.history import BoxInt, BoxFloat, BoxPtr
 from pypy.jit.metainterp.history import ConstInt, ConstFloat, ConstPtr
 from pypy.jit.codewriter import longlong
-from pypy.rlib.rarithmetic import r_singlefloat
+from pypy.rlib.rarithmetic import r_singlefloat, r_uint
 
 def boxfloat(x):
     return BoxFloat(longlong.getfloatstorage(x))
@@ -151,29 +152,6 @@
     assert get_jitcell(False, 42, 0.25) is cell4
     assert cell1 is not cell3 is not cell4 is not cell1
 
-def test_make_set_future_values():
-    future_values = {}
-    class FakeCPU:
-        def set_future_value_int(self, j, value):
-            future_values[j] = "int", value
-        def set_future_value_float(self, j, value):
-            future_values[j] = "float", value
-    class FakeWarmRunnerDesc:
-        cpu = FakeCPU()
-        memory_manager = None
-    class FakeJitDriverSD:
-        _red_args_types = ["int", "float"]
-        virtualizable_info = None
-    #
-    state = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD())
-    set_future_values = state.make_set_future_values()
-    set_future_values(5, 42.5)
-    assert future_values == {
-        0: ("int", 5),
-        1: ("float", longlong.getfloatstorage(42.5)),
-    }
-    assert set_future_values is state.make_set_future_values()
-
 def test_make_unwrap_greenkey():
     class FakeJitDriverSD:
         _green_args_spec = [lltype.Signed, lltype.Float]
@@ -210,6 +188,7 @@
         _confirm_enter_jit_ptr = None
         _can_never_inline_ptr = None
         _should_unroll_one_iteration_ptr = None
+        red_args_types = []
     class FakeCell:
         dont_trace_here = False
     state = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD())
@@ -239,6 +218,7 @@
         _can_never_inline_ptr = None
         _get_jitcell_at_ptr = None
         _should_unroll_one_iteration_ptr = None
+        red_args_types = []
     state = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD())
     state.make_jitdriver_callbacks()
     res = state.get_location_str([ConstInt(5), constfloat(42.5)])
@@ -264,6 +244,7 @@
         _can_never_inline_ptr = None
         _get_jitcell_at_ptr = None
         _should_unroll_one_iteration_ptr = None
+        red_args_types = []
 
     state = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD())
     state.make_jitdriver_callbacks()
@@ -289,8 +270,83 @@
         _can_never_inline_ptr = llhelper(CAN_NEVER_INLINE, can_never_inline)
         _get_jitcell_at_ptr = None
         _should_unroll_one_iteration_ptr = None
+        red_args_types = []
 
     state = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD())
     state.make_jitdriver_callbacks()
     res = state.can_never_inline(5, 42.5)
     assert res is True
+
+def test_decay_counters():
+    cell = JitCell(r_uint(5))
+    cell.counter = 100
+    cell.adjust_counter(r_uint(5), math.log(0.9))
+    assert cell.counter == 100
+    cell.adjust_counter(r_uint(6), math.log(0.9))
+    assert cell.counter == 90
+    cell.adjust_counter(r_uint(9), math.log(0.9))
+    assert cell.counter == int(90 * (0.9**3))
+
+def test_cleanup_jitcell_dict():
+    from pypy.jit.metainterp.memmgr import MemoryManager
+    class FakeWarmRunnerDesc:
+        memory_manager = MemoryManager()
+        class cpu:
+            pass
+    class FakeJitDriverSD:
+        _green_args_spec = [lltype.Signed]
+    #
+    # Test creating tons of jitcells that remain at 0
+    warmstate = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD())
+    get_jitcell = warmstate._make_jitcell_getter_default()
+    cell1 = get_jitcell(True, -1)
+    assert len(warmstate._jitcell_dict) == 1
+    assert FakeWarmRunnerDesc.memory_manager.current_generation == 1
+    #
+    for i in range(1, 20005):
+        get_jitcell(True, i)     # should trigger a clean-up at 20001
+        assert len(warmstate._jitcell_dict) == (i % 20000) + 1
+    assert FakeWarmRunnerDesc.memory_manager.current_generation == 2
+    #
+    # Same test, with one jitcell that has a counter of BASE instead of 0
+    warmstate = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD())
+    warmstate.set_param_decay_halflife(2)
+    warmstate.set_param_threshold(5)
+    warmstate.set_param_function_threshold(0)
+    get_jitcell = warmstate._make_jitcell_getter_default()
+    cell2 = get_jitcell(True, -2)
+    cell2.counter = BASE = warmstate.increment_threshold * 3
+    #
+    for i in range(0, 20005):
+        get_jitcell(True, i)
+        assert len(warmstate._jitcell_dict) == (i % 19999) + 2
+    #
+    assert cell2 in warmstate._jitcell_dict.values()
+    assert cell2.counter == int(BASE * math.sqrt(0.5))   # decayed once
+    assert FakeWarmRunnerDesc.memory_manager.current_generation == 3
+    #
+    # Same test, with jitcells that are compiled and free by the memmgr
+    warmstate = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD())
+    get_jitcell = warmstate._make_jitcell_getter_default()
+    get_jitcell(True, -1)
+    assert FakeWarmRunnerDesc.memory_manager.current_generation == 3
+    #
+    for i in range(1, 20005):
+        cell = get_jitcell(True, i)
+        cell.counter = -1
+        cell.wref_procedure_token = None    # or a dead weakref, equivalently
+        assert len(warmstate._jitcell_dict) == (i % 20000) + 1
+    assert FakeWarmRunnerDesc.memory_manager.current_generation == 4
+    #
+    # Same test, with counter == -2 (rare case, kept alive)
+    warmstate = WarmEnterState(FakeWarmRunnerDesc(), FakeJitDriverSD())
+    get_jitcell = warmstate._make_jitcell_getter_default()
+    cell = get_jitcell(True, -1)
+    cell.counter = -2
+    assert FakeWarmRunnerDesc.memory_manager.current_generation == 4
+    #
+    for i in range(1, 20005):
+        cell = get_jitcell(True, i)
+        cell.counter = -2
+        assert len(warmstate._jitcell_dict) == i + 1
+    assert FakeWarmRunnerDesc.memory_manager.current_generation == 5
diff --git a/pypy/jit/metainterp/warmspot.py b/pypy/jit/metainterp/warmspot.py
--- a/pypy/jit/metainterp/warmspot.py
+++ b/pypy/jit/metainterp/warmspot.py
@@ -64,9 +64,11 @@
 
 def jittify_and_run(interp, graph, args, repeat=1, graph_and_interp_only=False,
                     backendopt=False, trace_limit=sys.maxint,
+                    threshold=3, trace_eagerness=2,
                     inline=False, loop_longevity=0, retrace_limit=5,
-                    function_threshold=4,
-                    enable_opts=ALL_OPTS_NAMES, max_retrace_guards=15, **kwds):
+                    function_threshold=4, decay_halflife=0,
+                    enable_opts=ALL_OPTS_NAMES, max_retrace_guards=15,
+                    **kwds):
     from pypy.config.config import ConfigError
     translator = interp.typer.annotator.translator
     try:
@@ -83,15 +85,16 @@
         pass
     warmrunnerdesc = WarmRunnerDesc(translator, backendopt=backendopt, **kwds)
     for jd in warmrunnerdesc.jitdrivers_sd:
-        jd.warmstate.set_param_threshold(3)          # for tests
+        jd.warmstate.set_param_threshold(threshold)
         jd.warmstate.set_param_function_threshold(function_threshold)
-        jd.warmstate.set_param_trace_eagerness(2)    # for tests
+        jd.warmstate.set_param_trace_eagerness(trace_eagerness)
         jd.warmstate.set_param_trace_limit(trace_limit)
         jd.warmstate.set_param_inlining(inline)
         jd.warmstate.set_param_loop_longevity(loop_longevity)
         jd.warmstate.set_param_retrace_limit(retrace_limit)
         jd.warmstate.set_param_max_retrace_guards(max_retrace_guards)
         jd.warmstate.set_param_enable_opts(enable_opts)
+        jd.warmstate.set_param_decay_halflife(decay_halflife)
     warmrunnerdesc.finish()
     if graph_and_interp_only:
         return interp, graph
@@ -522,9 +525,9 @@
         greens_v, reds_v = support.decode_hp_hint_args(op)
         ALLARGS = [v.concretetype for v in (greens_v + reds_v)]
         jd._green_args_spec = [v.concretetype for v in greens_v]
-        jd._red_args_types = [history.getkind(v.concretetype) for v in reds_v]
+        jd.red_args_types = [history.getkind(v.concretetype) for v in reds_v]
         jd.num_green_args = len(jd._green_args_spec)
-        jd.num_red_args = len(jd._red_args_types)
+        jd.num_red_args = len(jd.red_args_types)
         RESTYPE = graph.getreturnvar().concretetype
         (jd._JIT_ENTER_FUNCTYPE,
          jd._PTR_JIT_ENTER_FUNCTYPE) = self.cpu.ts.get_FuncType(ALLARGS, lltype.Void)
@@ -771,16 +774,16 @@
 
         def assembler_call_helper(failindex, virtualizableref):
             fail_descr = self.cpu.get_fail_descr_from_number(failindex)
-            while True:
-                if vinfo is not None:
-                    virtualizable = lltype.cast_opaque_ptr(
-                        vinfo.VTYPEPTR, virtualizableref)
-                    vinfo.reset_vable_token(virtualizable)
-                try:
-                    loop_token = fail_descr.handle_fail(self.metainterp_sd, jd)
-                except JitException, e:
-                    return handle_jitexception(e)
-                fail_descr = self.execute_token(loop_token)
+            if vinfo is not None:
+                virtualizable = lltype.cast_opaque_ptr(
+                    vinfo.VTYPEPTR, virtualizableref)
+                vinfo.reset_vable_token(virtualizable)
+            try:
+                fail_descr.handle_fail(self.metainterp_sd, jd)
+            except JitException, e:
+                return handle_jitexception(e)
+            else:
+                assert 0, "should have raised"
 
         jd._assembler_call_helper = assembler_call_helper # for debugging
         jd._assembler_helper_ptr = self.helper_func(
@@ -910,10 +913,3 @@
         graphs = self.translator.graphs
         for graph, block, i in find_force_quasi_immutable(graphs):
             self.replace_force_quasiimmut_with_direct_call(block.operations[i])
-
-    # ____________________________________________________________
-
-    def execute_token(self, loop_token):
-        fail_descr = self.cpu.execute_token(loop_token)
-        self.memory_manager.keep_loop_alive(loop_token)
-        return fail_descr
diff --git a/pypy/jit/metainterp/warmstate.py b/pypy/jit/metainterp/warmstate.py
--- a/pypy/jit/metainterp/warmstate.py
+++ b/pypy/jit/metainterp/warmstate.py
@@ -1,10 +1,10 @@
-import sys, weakref
+import sys, weakref, math
 from pypy.rpython.lltypesystem import lltype, llmemory, rstr, rffi
 from pypy.rpython.ootypesystem import ootype
 from pypy.rpython.annlowlevel import hlstr, cast_base_ptr_to_instance
 from pypy.rpython.annlowlevel import cast_object_to_ptr
 from pypy.rlib.objectmodel import specialize, we_are_translated, r_dict
-from pypy.rlib.rarithmetic import intmask
+from pypy.rlib.rarithmetic import intmask, r_uint
 from pypy.rlib.nonconst import NonConstant
 from pypy.rlib.unroll import unrolling_iterable
 from pypy.rlib.jit import PARAMETERS
@@ -12,6 +12,7 @@
 from pypy.rlib.debug import debug_start, debug_stop, debug_print
 from pypy.jit.metainterp import history
 from pypy.jit.codewriter import support, heaptracker, longlong
+from pypy.tool.sourcetools import func_with_new_name
 
 # ____________________________________________________________
 
@@ -142,26 +143,6 @@
     else:
         return rffi.cast(lltype.Signed, x)
 
- at specialize.ll_and_arg(3)
-def set_future_value(cpu, j, value, typecode):
-    if typecode == 'ref':
-        refvalue = cpu.ts.cast_to_ref(value)
-        cpu.set_future_value_ref(j, refvalue)
-    elif typecode == 'int':
-        if isinstance(lltype.typeOf(value), lltype.Ptr):
-            intvalue = llmemory.AddressAsInt(llmemory.cast_ptr_to_adr(value))
-        else:
-            intvalue = lltype.cast_primitive(lltype.Signed, value)
-        cpu.set_future_value_int(j, intvalue)
-    elif typecode == 'float':
-        if lltype.typeOf(value) is lltype.Float:
-            value = longlong.getfloatstorage(value)
-        else:
-            assert longlong.is_longlong(lltype.typeOf(value))
-            value = rffi.cast(lltype.SignedLongLong, value)
-        cpu.set_future_value_float(j, value)
-    else:
-        assert False
 
 class JitCell(BaseJitCell):
     # the counter can mean the following things:
@@ -172,6 +153,25 @@
     dont_trace_here = False
     wref_procedure_token = None
 
+    def __init__(self, generation):
+        # The stored 'counter' value follows an exponential decay model.
+        # Conceptually after every generation, it decays by getting
+        # multiplied by a constant <= 1.0.  In practice, decaying occurs
+        # lazily: the following field records the latest seen generation
+        # number, and adjustment is done by adjust_counter() when needed.
+        self.latest_generation_seen = generation
+
+    def adjust_counter(self, generation, log_decay_factor):
+        if generation != self.latest_generation_seen:
+            # The latest_generation_seen is older than the current generation.
+            # Adjust by multiplying self.counter N times by decay_factor, i.e.
+            # by decay_factor ** N, which is equal to exp(log(decay_factor)*N).
+            assert self.counter >= 0
+            N = generation - self.latest_generation_seen
+            factor = math.exp(log_decay_factor * N)
+            self.counter = int(self.counter * factor)
+            self.latest_generation_seen = generation
+
     def get_procedure_token(self):
         if self.wref_procedure_token is not None:
             token = self.wref_procedure_token()
@@ -191,7 +191,6 @@
 
 class WarmEnterState(object):
     THRESHOLD_LIMIT = sys.maxint // 2
-    default_jitcell_dict = None
 
     def __init__(self, warmrunnerdesc, jitdriver_sd):
         "NOT_RPYTHON"
@@ -232,6 +231,17 @@
     def set_param_inlining(self, value):
         self.inlining = value
 
+    def set_param_decay_halflife(self, value):
+        # Use 0 or -1 to mean "no decay".  Initialize the internal variable
+        # 'log_decay_factor'.  It is choosen such that by multiplying the
+        # counter on loops by 'exp(log_decay_factor)' (<= 1.0) every
+        # generation, then the counter will be divided by two after 'value'
+        # generations have passed.
+        if value <= 0:
+            self.log_decay_factor = 0.0    # log(1.0)
+        else:
+            self.log_decay_factor = math.log(0.5) / value
+
     def set_param_enable_opts(self, value):
         from pypy.jit.metainterp.optimizeopt import ALL_OPTS_DICT, ALL_OPTS_NAMES
 
@@ -297,26 +307,61 @@
         index_of_virtualizable = jitdriver_sd.index_of_virtualizable
         num_green_args = jitdriver_sd.num_green_args
         get_jitcell = self.make_jitcell_getter()
-        set_future_values = self.make_set_future_values()
         self.make_jitdriver_callbacks()
         confirm_enter_jit = self.confirm_enter_jit
+        range_red_args = unrolling_iterable(
+            range(num_green_args, num_green_args + jitdriver_sd.num_red_args))
+        memmgr = self.warmrunnerdesc.memory_manager
+        if memmgr is not None:
+            get_current_generation = memmgr.get_current_generation_uint
+        else:
+            get_current_generation = lambda: r_uint(0)
+        # get a new specialized copy of the method
+        ARGS = []
+        for kind in jitdriver_sd.red_args_types:
+            if kind == 'int':
+                ARGS.append(lltype.Signed)
+            elif kind == 'ref':
+                ARGS.append(llmemory.GCREF)
+            elif kind == 'float':
+                ARGS.append(longlong.FLOATSTORAGE)
+            else:
+                assert 0, kind
+        func_execute_token = self.cpu.make_execute_token(*ARGS)
+
+        def execute_assembler(loop_token, *args):
+            # Call the backend to run the 'looptoken' with the given
+            # input args.
+            fail_descr = func_execute_token(loop_token, *args)
+            #
+            # If we have a virtualizable, we have to reset its
+            # 'vable_token' field afterwards
+            if vinfo is not None:
+                virtualizable = args[index_of_virtualizable]
+                virtualizable = vinfo.cast_gcref_to_vtype(virtualizable)
+                vinfo.reset_vable_token(virtualizable)
+            #
+            # Record in the memmgr that we just ran this loop,
+            # so that it will keep it alive for a longer time
+            warmrunnerdesc.memory_manager.keep_loop_alive(loop_token)
+            #
+            # Handle the failure
+            fail_descr.handle_fail(metainterp_sd, jitdriver_sd)
+            #
+            assert 0, "should have raised"
 
         def maybe_compile_and_run(threshold, *args):
             """Entry point to the JIT.  Called at the point with the
             can_enter_jit() hint.
             """
-            if vinfo is not None:
-                virtualizable = args[num_green_args + index_of_virtualizable]
-                virtualizable = vinfo.cast_to_vtype(virtualizable)
-            else:
-                virtualizable = None
-
             # look for the cell corresponding to the current greenargs
             greenargs = args[:num_green_args]
             cell = get_jitcell(True, *greenargs)
 
             if cell.counter >= 0:
                 # update the profiling counter
+                cell.adjust_counter(get_current_generation(),
+                                    self.log_decay_factor)
                 n = cell.counter + threshold
                 if n <= self.THRESHOLD_LIMIT:       # bound not reached
                     cell.counter = n
@@ -330,42 +375,36 @@
                 # set counter to -2, to mean "tracing in effect"
                 cell.counter = -2
                 try:
-                    procedure_token = metainterp.compile_and_run_once(jitdriver_sd,
-                                                                 *args)
+                    metainterp.compile_and_run_once(jitdriver_sd, *args)
                 finally:
                     if cell.counter == -2:
                         cell.counter = 0
             else:
-                if cell.counter == -2:
+                if cell.counter != -1:
+                    assert cell.counter == -2
                     # tracing already happening in some outer invocation of
                     # this function. don't trace a second time.
                     return
-                assert cell.counter == -1
                 if not confirm_enter_jit(*args):
                     return
+                # machine code was already compiled for these greenargs
                 procedure_token = cell.get_procedure_token()
                 if procedure_token is None:   # it was a weakref that has been freed
                     cell.counter = 0
                     return
-                # machine code was already compiled for these greenargs
-                # get the assembler and fill in the boxes
-                set_future_values(*args[num_green_args:])
-
-            # ---------- execute assembler ----------
-            while True:     # until interrupted by an exception
-                metainterp_sd.profiler.start_running()
-                #debug_start("jit-running")
-                fail_descr = warmrunnerdesc.execute_token(procedure_token)
-                #debug_stop("jit-running")
-                metainterp_sd.profiler.end_running()
-                procedure_token = None     # for test_memmgr
-                if vinfo is not None:
-                    vinfo.reset_vable_token(virtualizable)
-                procedure_token = fail_descr.handle_fail(metainterp_sd,
-                                                         jitdriver_sd)
+                # extract and unspecialize the red arguments to pass to
+                # the assembler
+                execute_args = ()
+                for i in range_red_args:
+                    execute_args += (unspecialize_value(args[i]), )
+                # run it!  this executes until interrupted by an exception
+                execute_assembler(procedure_token, *execute_args)
+            #
+            assert 0, "should not reach this point"
 
         maybe_compile_and_run._dont_inline_ = True
         self.maybe_compile_and_run = maybe_compile_and_run
+        self.execute_assembler = execute_assembler
         return maybe_compile_and_run
 
     # ----------
@@ -415,6 +454,15 @@
         #
         return jit_getter
 
+    def _new_jitcell(self):
+        warmrunnerdesc = self.warmrunnerdesc
+        if (warmrunnerdesc is not None and
+                warmrunnerdesc.memory_manager is not None):
+            gen = warmrunnerdesc.memory_manager.get_current_generation_uint()
+        else:
+            gen = r_uint(0)
+        return JitCell(gen)
+
     def _make_jitcell_getter_default(self):
         "NOT_RPYTHON"
         jitdriver_sd = self.jitdriver_sd
@@ -439,6 +487,49 @@
             return x
         #
         jitcell_dict = r_dict(comparekey, hashkey)
+        try:
+            self.warmrunnerdesc.stats.jitcell_dicts.append(jitcell_dict)
+        except AttributeError:
+            pass
+        #
+        memmgr = self.warmrunnerdesc and self.warmrunnerdesc.memory_manager
+        if memmgr:
+            def _cleanup_dict():
+                minimum = sys.maxint
+                if self.increment_threshold > 0:
+                    minimum = min(minimum, self.increment_threshold)
+                if self.increment_function_threshold > 0:
+                    minimum = min(minimum, self.increment_function_threshold)
+                currentgen = memmgr.get_current_generation_uint()
+                killme = []
+                for key, cell in jitcell_dict.iteritems():
+                    if cell.counter >= 0:
+                        cell.adjust_counter(currentgen, self.log_decay_factor)
+                        if cell.counter < minimum:
+                            killme.append(key)
+                    elif (cell.counter == -1
+                          and cell.get_procedure_token() is None):
+                        killme.append(key)
+                for key in killme:
+                    del jitcell_dict[key]
+            #
+            def _maybe_cleanup_dict():
+                # If no tracing goes on at all because the jitcells are
+                # each time for new greenargs, the dictionary grows forever.
+                # So every one in a (rare) while, we decide to force an
+                # artificial next_generation() and _cleanup_dict().
+                self._trigger_automatic_cleanup += 1
+                if self._trigger_automatic_cleanup > 20000:
+                    self._trigger_automatic_cleanup = 0
+                    memmgr.next_generation(do_cleanups_now=False)
+                    _cleanup_dict()
+            #
+            self._trigger_automatic_cleanup = 0
+            self._jitcell_dict = jitcell_dict       # for tests
+            memmgr.record_jitcell_dict(_cleanup_dict)
+        else:
+            def _maybe_cleanup_dict():
+                pass
         #
         def get_jitcell(build, *greenargs):
             try:
@@ -446,7 +537,8 @@
             except KeyError:
                 if not build:
                     return None
-                cell = JitCell()
+                _maybe_cleanup_dict()
+                cell = self._new_jitcell()
                 jitcell_dict[greenargs] = cell
             return cell
         return get_jitcell
@@ -457,6 +549,10 @@
         get_jitcell_at_ptr = self.jitdriver_sd._get_jitcell_at_ptr
         set_jitcell_at_ptr = self.jitdriver_sd._set_jitcell_at_ptr
         lltohlhack = {}
+        # note that there is no equivalent of record_jitcell_dict()
+        # in the case of custom getters.  We assume that the interpreter
+        # stores the JitCells on some objects that can go away by GC,
+        # like the PyCode objects in PyPy.
         #
         def get_jitcell(build, *greenargs):
             fn = support.maybe_on_top_of_llinterp(rtyper, get_jitcell_at_ptr)
@@ -478,7 +574,7 @@
             if not build:
                 return cell
             if cell is None:
-                cell = JitCell()
+                cell = self._new_jitcell()
                 # <hacks>
                 if we_are_translated():
                     cellref = cast_object_to_ptr(BASEJITCELL, cell)
@@ -502,56 +598,6 @@
 
     # ----------
 
-    def make_set_future_values(self):
-        "NOT_RPYTHON"
-        if hasattr(self, 'set_future_values'):
-            return self.set_future_values
-
-        jitdriver_sd   = self.jitdriver_sd
-        cpu = self.cpu
-        vinfo = jitdriver_sd.virtualizable_info
-        red_args_types = unrolling_iterable(jitdriver_sd._red_args_types)
-        #
-        def set_future_values(*redargs):
-            i = 0
-            for typecode in red_args_types:
-                set_future_value(cpu, i, redargs[i], typecode)
-                i = i + 1
-            if vinfo is not None:
-                set_future_values_from_vinfo(*redargs)
-        #
-        if vinfo is not None:
-            i0 = len(jitdriver_sd._red_args_types)
-            index_of_virtualizable = jitdriver_sd.index_of_virtualizable
-            vable_static_fields = unrolling_iterable(
-                zip(vinfo.static_extra_types, vinfo.static_fields))
-            vable_array_fields = unrolling_iterable(
-                zip(vinfo.arrayitem_extra_types, vinfo.array_fields))
-            getlength = cpu.ts.getlength
-            getarrayitem = cpu.ts.getarrayitem
-            #
-            def set_future_values_from_vinfo(*redargs):
-                i = i0
-                virtualizable = redargs[index_of_virtualizable]
-                virtualizable = vinfo.cast_to_vtype(virtualizable)
-                for typecode, fieldname in vable_static_fields:
-                    x = getattr(virtualizable, fieldname)
-                    set_future_value(cpu, i, x, typecode)
-                    i = i + 1
-                for typecode, fieldname in vable_array_fields:
-                    lst = getattr(virtualizable, fieldname)
-                    for j in range(getlength(lst)):
-                        x = getarrayitem(lst, j)
-                        set_future_value(cpu, i, x, typecode)
-                        i = i + 1
-        else:
-            set_future_values_from_vinfo = None
-        #
-        self.set_future_values = set_future_values
-        return set_future_values
-
-    # ----------
-
     def make_jitdriver_callbacks(self):
         if hasattr(self, 'get_location_str'):
             return
@@ -601,8 +647,9 @@
             jd.on_compile = lambda *args: None
             jd.on_compile_bridge = lambda *args: None
 
-        def get_assembler_token(greenkey, redboxes):
-            # 'redboxes' is only used to know the types of red arguments
+        redargtypes = ''.join([kind[0] for kind in jd.red_args_types])
+
+        def get_assembler_token(greenkey):
             cell = self.jit_cell_at_key(greenkey)
             procedure_token = cell.get_procedure_token()
             if procedure_token is None:
@@ -611,7 +658,7 @@
                     cell.counter = 0      # but was freed in the meantime.
                 memmgr = warmrunnerdesc.memory_manager
                 procedure_token = compile_tmp_callback(cpu, jd, greenkey,
-                                                   redboxes, memmgr)
+                                                       redargtypes, memmgr)
                 cell.set_procedure_token(procedure_token)
             return procedure_token
         self.get_assembler_token = get_assembler_token
diff --git a/pypy/jit/tool/jitoutput.py b/pypy/jit/tool/jitoutput.py
--- a/pypy/jit/tool/jitoutput.py
+++ b/pypy/jit/tool/jitoutput.py
@@ -10,9 +10,6 @@
 REGEXES = [
     (('tracing_no', 'tracing_time'), '^Tracing:\s+([\d.]+)\s+([\d.]+)$'),
     (('backend_no', 'backend_time'), '^Backend:\s+([\d.]+)\s+([\d.]+)$'),
-    (('asm_no',), '^Running asm:\s+([\d.]+)$'),
-    (('blackhole_no',),
-         '^Blackhole:\s+([\d.]+)$'),
     (None, '^TOTAL.*$'),
     (('ops.total',), '^ops:\s+(\d+)$'),
     (('recorded_ops.total',), '^recorded ops:\s+(\d+)$'),
diff --git a/pypy/jit/tool/test/test_jitoutput.py b/pypy/jit/tool/test/test_jitoutput.py
--- a/pypy/jit/tool/test/test_jitoutput.py
+++ b/pypy/jit/tool/test/test_jitoutput.py
@@ -34,8 +34,6 @@
     # assert did not crash
     # asserts below are a bit delicate, possibly they might be deleted
     assert info.tracing_no == 1
-    assert info.asm_no == 1
-    assert info.blackhole_no == 1
     assert info.backend_no == 1
     assert info.ops.total == 2
     assert info.recorded_ops.total == 2
@@ -47,8 +45,6 @@
 
 DATA = '''Tracing:         1       0.006992
 Backend:        1       0.000525
-Running asm:            1
-Blackhole:              1
 TOTAL:                  0.025532
 ops:                    2
 recorded ops:           6
@@ -75,8 +71,6 @@
     info = parse_prof(DATA)
     assert info.tracing_no == 1
     assert info.tracing_time == 0.006992
-    assert info.asm_no == 1
-    assert info.blackhole_no == 1
     assert info.backend_no == 1
     assert info.backend_time == 0.000525
     assert info.ops.total == 2
diff --git a/pypy/module/_ssl/test/test_ssl.py b/pypy/module/_ssl/test/test_ssl.py
--- a/pypy/module/_ssl/test/test_ssl.py
+++ b/pypy/module/_ssl/test/test_ssl.py
@@ -161,11 +161,16 @@
 
     def test_shutdown(self):
         import socket, ssl, sys, gc
-        if sys.platform == 'darwin':
-            skip("get also on CPython: error: [Errno 0]")
         ss = socket.ssl(self.s)
         ss.write("hello\n")
-        assert ss.shutdown() is self.s._sock
+        try:
+            result = ss.shutdown()
+        except socket.error, e:
+            # xxx obscure case; throwing errno 0 is pretty odd...
+            if e.errno == 0:
+                skip("Shutdown raised errno 0. CPython does this too")
+            raise
+        assert result is self.s._sock
         raises(ssl.SSLError, ss.write, "hello\n")
         del ss; gc.collect()
 
diff --git a/pypy/module/micronumpy/__init__.py b/pypy/module/micronumpy/__init__.py
--- a/pypy/module/micronumpy/__init__.py
+++ b/pypy/module/micronumpy/__init__.py
@@ -1,9 +1,19 @@
 from pypy.interpreter.mixedmodule import MixedModule
 
 
+class PyPyModule(MixedModule):
+    interpleveldefs = {
+        'debug_repr': 'interp_extras.debug_repr',
+    }
+    appleveldefs = {}
+
 class Module(MixedModule):
     applevel_name = 'numpypy'
 
+    submodules = {
+        'pypy': PyPyModule
+    }
+
     interpleveldefs = {
         'ndarray': 'interp_numarray.W_NDimArray',
         'dtype': 'interp_dtype.W_Dtype',
@@ -81,6 +91,7 @@
         'mean': 'app_numpy.mean',
         'sum': 'app_numpy.sum',
         'min': 'app_numpy.min',
+        'identity': 'app_numpy.identity',
         'max': 'app_numpy.max',
         'inf': 'app_numpy.inf',
         'e': 'app_numpy.e',
diff --git a/pypy/module/micronumpy/app_numpy.py b/pypy/module/micronumpy/app_numpy.py
--- a/pypy/module/micronumpy/app_numpy.py
+++ b/pypy/module/micronumpy/app_numpy.py
@@ -13,6 +13,11 @@
     # weighting, just the average part!
     return mean(a)
 
+def identity(n, dtype=None):
+    a = numpypy.zeros((n,n), dtype=dtype)
+    for i in range(n):
+        a[i][i] = 1
+    return a
 
 def mean(a):
     if not hasattr(a, "mean"):
diff --git a/pypy/module/micronumpy/interp_boxes.py b/pypy/module/micronumpy/interp_boxes.py
--- a/pypy/module/micronumpy/interp_boxes.py
+++ b/pypy/module/micronumpy/interp_boxes.py
@@ -86,6 +86,7 @@
     descr_ge = _binop_impl("greater_equal")
 
     descr_radd = _binop_right_impl("add")
+    descr_rsub = _binop_right_impl("subtract")
     descr_rmul = _binop_right_impl("multiply")
 
     descr_neg = _unaryop_impl("negative")
@@ -132,7 +133,7 @@
     descr__new__, get_dtype = new_dtype_getter("long")
 
 class W_ULongBox(W_UnsignedIntegerBox, PrimitiveBox):
-    pass
+    descr__new__, get_dtype = new_dtype_getter("ulong")
 
 class W_Int64Box(W_SignedIntegerBox, PrimitiveBox):
     descr__new__, get_dtype = new_dtype_getter("int64")
@@ -170,7 +171,8 @@
     __mul__ = interp2app(W_GenericBox.descr_mul),
     __div__ = interp2app(W_GenericBox.descr_div),
 
-    __radd__ = interp2app(W_GenericBox.descr_add),
+    __radd__ = interp2app(W_GenericBox.descr_radd),
+    __rsub__ = interp2app(W_GenericBox.descr_rsub),
     __rmul__ = interp2app(W_GenericBox.descr_rmul),
 
     __eq__ = interp2app(W_GenericBox.descr_eq),
diff --git a/pypy/module/micronumpy/interp_extras.py b/pypy/module/micronumpy/interp_extras.py
new file mode 100644
--- /dev/null
+++ b/pypy/module/micronumpy/interp_extras.py
@@ -0,0 +1,7 @@
+from pypy.interpreter.gateway import unwrap_spec
+from pypy.module.micronumpy.interp_numarray import BaseArray
+
+
+ at unwrap_spec(array=BaseArray)
+def debug_repr(space, array):
+    return space.wrap(array.debug_repr())
diff --git a/pypy/module/micronumpy/interp_numarray.py b/pypy/module/micronumpy/interp_numarray.py
--- a/pypy/module/micronumpy/interp_numarray.py
+++ b/pypy/module/micronumpy/interp_numarray.py
@@ -581,6 +581,7 @@
     def descr_get_dtype(self, space):
         return space.wrap(self.find_dtype())
 
+    @jit.unroll_safe
     def descr_get_shape(self, space):
         return space.newtuple([space.wrap(i) for i in self.shape])
 
@@ -791,7 +792,8 @@
                 raise OperationError(space.w_IndexError, space.wrap(
                         "0-d arrays can't be indexed"))
             item = concrete._index_of_single_item(space, w_idx)
-            concrete.setitem_w(space, item, w_value)
+            dtype = concrete.find_dtype()
+            concrete.setitem(item, dtype.coerce(space, w_value))
             return
         if not isinstance(w_value, BaseArray):
             w_value = convert_to_array(space, w_value)
@@ -924,9 +926,6 @@
     def start_iter(self, res_shape=None):
         raise NotImplementedError
 
-    def descr_debug_repr(self, space):
-        return space.wrap(self.debug_repr())
-
     def descr_array_iface(self, space):
         concrete = self.get_concrete()
         storage = concrete.get_storage(space)
@@ -1178,10 +1177,6 @@
     def eval(self, iter):
         return self.parent.getitem(iter.get_offset())
 
-    @unwrap_spec(item=int)
-    def setitem_w(self, space, item, w_value):
-        return self.parent.setitem_w(space, item, w_value)
-
     def setitem(self, item, value):
         # This is currently not possible to be called from anywhere.
         raise NotImplementedError
@@ -1330,9 +1325,6 @@
         raise OperationError(space.w_TypeError, space.wrap(
             "len() of unsized object"))
 
-    def setitem_w(self, space, item, w_value):
-        return self.setitem(item, self.dtype.coerce(space, w_value))
-
     def setitem(self, item, value):
         self.invalidated()
         self.dtype.setitem(self.storage, item, value)
@@ -1472,7 +1464,6 @@
 
     __repr__ = interp2app(BaseArray.descr_repr),
     __str__ = interp2app(BaseArray.descr_str),
-    __debug_repr__ = interp2app(BaseArray.descr_debug_repr),
     __array_interface__ = GetSetProperty(BaseArray.descr_array_iface),
 
     dtype = GetSetProperty(BaseArray.descr_get_dtype),
diff --git a/pypy/module/micronumpy/interp_support.py b/pypy/module/micronumpy/interp_support.py
--- a/pypy/module/micronumpy/interp_support.py
+++ b/pypy/module/micronumpy/interp_support.py
@@ -1,34 +1,90 @@
-from pypy.interpreter.error import OperationError
+from pypy.interpreter.error import OperationError, operationerrfmt
 from pypy.interpreter.gateway import unwrap_spec
-from pypy.module.micronumpy.interp_dtype import get_dtype_cache
-from pypy.rlib.rstruct.runpack import runpack
 from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.module.micronumpy import interp_dtype
+from pypy.objspace.std.strutil import strip_spaces
 
 
 FLOAT_SIZE = rffi.sizeof(lltype.Float)
 
- at unwrap_spec(s=str)
-def fromstring(space, s):
+def _fromstring_text(space, s, count, sep, length, dtype):
     from pypy.module.micronumpy.interp_numarray import W_NDimArray
+
+    sep_stripped = strip_spaces(sep)
+    skip_bad_vals = len(sep_stripped) == 0
+
+    items = []
+    num_items = 0
+    idx = 0
+    
+    while (num_items < count or count == -1) and idx < len(s):
+        nextidx = s.find(sep, idx)
+        if nextidx < 0:
+            nextidx = length
+        piece = strip_spaces(s[idx:nextidx])
+        if len(piece) > 0 or not skip_bad_vals:
+            if len(piece) == 0 and not skip_bad_vals:
+                val = dtype.itemtype.default_fromstring(space)
+            else:
+                try:
+                    val = dtype.coerce(space, space.wrap(piece))
+                except OperationError, e:
+                    if not e.match(space, space.w_ValueError):
+                        raise
+                    gotit = False
+                    while not gotit and len(piece) > 0:
+                        piece = piece[:-1]
+                        try:
+                            val = dtype.coerce(space, space.wrap(piece))
+                            gotit = True
+                        except OperationError, e:
+                            if not e.match(space, space.w_ValueError):
+                                raise
+                    if not gotit:
+                        val = dtype.itemtype.default_fromstring(space)
+                    nextidx = length
+            items.append(val)
+            num_items += 1
+        idx = nextidx + 1
+    
+    if count > num_items:
+        raise OperationError(space.w_ValueError, space.wrap(
+            "string is smaller than requested size"))
+
+    a = W_NDimArray(num_items, [num_items], dtype=dtype)
+    for i, val in enumerate(items):
+        a.dtype.setitem(a.storage, i, val)
+    
+    return space.wrap(a)
+
+def _fromstring_bin(space, s, count, length, dtype):
+    from pypy.module.micronumpy.interp_numarray import W_NDimArray
+    
+    itemsize = dtype.itemtype.get_element_size()
+    if count == -1:
+        count = length / itemsize
+    if length % itemsize != 0:
+        raise operationerrfmt(space.w_ValueError,
+                              "string length %d not divisable by item size %d",
+                              length, itemsize)
+    if count * itemsize > length:
+        raise OperationError(space.w_ValueError, space.wrap(
+            "string is smaller than requested size"))
+        
+    a = W_NDimArray(count, [count], dtype=dtype)
+    for i in range(count):
+        val = dtype.itemtype.runpack_str(s[i*itemsize:i*itemsize + itemsize])
+        a.dtype.setitem(a.storage, i, val)
+        
+    return space.wrap(a)
+
+ at unwrap_spec(s=str, count=int, sep=str)
+def fromstring(space, s, w_dtype=None, count=-1, sep=''):
+    dtype = space.interp_w(interp_dtype.W_Dtype,
+        space.call_function(space.gettypefor(interp_dtype.W_Dtype), w_dtype)
+    )
     length = len(s)
-
-    if length % FLOAT_SIZE == 0:
-        number = length/FLOAT_SIZE
+    if sep == '':
+        return _fromstring_bin(space, s, count, length, dtype)
     else:
-        raise OperationError(space.w_ValueError, space.wrap(
-            "string length %d not divisable by %d" % (length, FLOAT_SIZE)))
-
-    dtype = get_dtype_cache(space).w_float64dtype
-    a = W_NDimArray(number, [number], dtype=dtype)
-
-    start = 0
-    end = FLOAT_SIZE
-    i = 0
-    while i < number:
-        part = s[start:end]
-        a.dtype.setitem(a.storage, i, dtype.box(runpack('d', part)))
-        i += 1
-        start += FLOAT_SIZE
-        end += FLOAT_SIZE
-
-    return space.wrap(a)
+        return _fromstring_text(space, s, count, sep, length, dtype)
diff --git a/pypy/module/micronumpy/test/test_dtypes.py b/pypy/module/micronumpy/test/test_dtypes.py
--- a/pypy/module/micronumpy/test/test_dtypes.py
+++ b/pypy/module/micronumpy/test/test_dtypes.py
@@ -193,6 +193,7 @@
 
         assert type(X(True)) is numpy.bool_
         assert X(True) is numpy.True_
+        assert numpy.bool_("False") is numpy.True_
 
     def test_int8(self):
         import numpypy as numpy
@@ -211,6 +212,10 @@
 
         assert type(int(x)) is int
         assert int(x) == -128
+        assert numpy.int8('50') == numpy.int8(50)
+        raises(ValueError, numpy.int8, '50.2')
+        assert numpy.int8('127') == 127
+        assert numpy.int8('128') == -128
 
     def test_uint8(self):
         import numpypy as numpy
@@ -232,6 +237,8 @@
 
         assert numpy.uint8(255) == 255
         assert numpy.uint8(256) == 0
+        assert numpy.uint8('255') == 255
+        assert numpy.uint8('256') == 0
 
     def test_int16(self):
         import numpypy as numpy
@@ -240,26 +247,43 @@
         assert x == 3
         assert numpy.int16(32767) == 32767
         assert numpy.int16(32768) == -32768
+        assert numpy.int16('32767') == 32767
+        assert numpy.int16('32768') == -32768
 
     def test_uint16(self):
         import numpypy as numpy
 
         assert numpy.uint16(65535) == 65535
         assert numpy.uint16(65536) == 0
+        assert numpy.uint16('65535') == 65535
+        assert numpy.uint16('65536') == 0
 
     def test_int32(self):
+        import sys
         import numpypy as numpy
 
         x = numpy.int32(23)
         assert x == 23
         assert numpy.int32(2147483647) == 2147483647
-        assert numpy.int32(2147483648) == -2147483648
+        assert numpy.int32('2147483647') == 2147483647
+        if sys.maxint > 2 ** 31 - 1:
+            assert numpy.int32(2147483648) == -2147483648
+            assert numpy.int32('2147483648') == -2147483648
+        else:
+            raises(OverflowError, numpy.int32, 2147483648)
+            raises(OverflowError, numpy.int32, '2147483648')
 
     def test_uint32(self):
+        import sys
         import numpypy as numpy
 
-        assert numpy.uint32(4294967295) == 4294967295
-        assert numpy.uint32(4294967296) == 0
+        assert numpy.uint32(10) == 10
+
+        if sys.maxint > 2 ** 31 - 1:
+            assert numpy.uint32(4294967295) == 4294967295
+            assert numpy.uint32(4294967296) == 0
+            assert numpy.uint32('4294967295') == 4294967295
+            assert numpy.uint32('4294967296') == 0
 
     def test_int_(self):
         import numpypy as numpy
@@ -279,8 +303,15 @@
         assert numpy.dtype(numpy.int64).type is numpy.int64
         assert numpy.int64(3) == 3
 
-        assert numpy.int64(9223372036854775807) == 9223372036854775807
+        if sys.maxint >= 2 ** 63 - 1:
+            assert numpy.int64(9223372036854775807) == 9223372036854775807
+            assert numpy.int64('9223372036854775807') == 9223372036854775807
+        else:
+            raises(OverflowError, numpy.int64, 9223372036854775807)
+            raises(OverflowError, numpy.int64, '9223372036854775807')
+        
         raises(OverflowError, numpy.int64, 9223372036854775808)
+        raises(OverflowError, numpy.int64, '9223372036854775808')
 
     def test_uint64(self):
         import sys
@@ -304,6 +335,8 @@
         assert numpy.float32.mro() == [numpy.float32, numpy.floating, numpy.inexact, numpy.number, numpy.generic, object]
 
         assert numpy.float32(12) == numpy.float64(12)
+        assert numpy.float32('23.4') == numpy.float32(23.4)
+        raises(ValueError, numpy.float32, '23.2df')
 
     def test_float64(self):
         import numpypy as numpy
@@ -315,6 +348,8 @@
         assert numpy.dtype(float).type is numpy.float64
 
         assert numpy.float64(2.0) == 2.0
+        assert numpy.float64('23.4') == numpy.float64(23.4)
+        raises(ValueError, numpy.float64, '23.2df')
 
     def test_subclass_type(self):
         import numpypy as numpy
diff --git a/pypy/module/micronumpy/test/test_numarray.py b/pypy/module/micronumpy/test/test_numarray.py
--- a/pypy/module/micronumpy/test/test_numarray.py
+++ b/pypy/module/micronumpy/test/test_numarray.py
@@ -491,6 +491,11 @@
         for i in range(5):
             assert b[i] == i - 5
 
+    def test_scalar_subtract(self):
+        from numpypy import int32
+        assert int32(2) - 1 == 1
+        assert 1 - int32(2) == -1
+
     def test_mul(self):
         import numpypy
 
@@ -722,6 +727,26 @@
         a = array([True] * 5, bool)
         assert a.sum() == 5
 
+    def test_identity(self):
+        from numpypy import identity, array
+        from numpypy import int32, float64, dtype
+        a = identity(0)
+        assert len(a) == 0
+        assert a.dtype == dtype('float64')
+        assert a.shape == (0,0)
+        b = identity(1, dtype=int32)
+        assert len(b) == 1
+        assert b[0][0] == 1
+        assert b.shape == (1,1)
+        assert b.dtype == dtype('int32')
+        c = identity(2)
+        assert c.shape == (2,2)
+        assert (c == [[1,0],[0,1]]).all()
+        d = identity(3, dtype='int32')
+        assert d.shape == (3,3)
+        assert d.dtype == dtype('int32')
+        assert (d == [[1,0,0],[0,1,0],[0,0,1]]).all()
+
     def test_prod(self):
         from numpypy import array
         a = array(range(1, 6))
@@ -868,16 +893,17 @@
 
     def test_debug_repr(self):
         from numpypy import zeros, sin
+        from numpypy.pypy import debug_repr
         a = zeros(1)
-        assert a.__debug_repr__() == 'Array'
-        assert (a + a).__debug_repr__() == 'Call2(add, Array, Array)'
-        assert (a[::2]).__debug_repr__() == 'Slice(Array)'
-        assert (a + 2).__debug_repr__() == 'Call2(add, Array, Scalar)'
-        assert (a + a.flat).__debug_repr__() == 'Call2(add, Array, FlatIter(Array))'
-        assert sin(a).__debug_repr__() == 'Call1(sin, Array)'
+        assert debug_repr(a) == 'Array'
+        assert debug_repr(a + a) == 'Call2(add, Array, Array)'
+        assert debug_repr(a[::2]) == 'Slice(Array)'
+        assert debug_repr(a + 2) == 'Call2(add, Array, Scalar)'
+        assert debug_repr(a + a.flat) == 'Call2(add, Array, FlatIter(Array))'
+        assert debug_repr(sin(a)) == 'Call1(sin, Array)'
         b = a + a
         b[0] = 3
-        assert b.__debug_repr__() == 'Call2(add, forced=Array)'
+        assert debug_repr(b) == 'Call2(add, forced=Array)'
 
     def test_tolist_scalar(self):
         from numpypy import int32, bool_
@@ -1168,13 +1194,110 @@
         import struct
         BaseNumpyAppTest.setup_class.im_func(cls)
         cls.w_data = cls.space.wrap(struct.pack('dddd', 1, 2, 3, 4))
+        cls.w_fdata = cls.space.wrap(struct.pack('f', 2.3))
+        cls.w_float32val = cls.space.wrap(struct.pack('f', 5.2))
+        cls.w_float64val = cls.space.wrap(struct.pack('d', 300.4))
+        cls.w_ulongval = cls.space.wrap(struct.pack('L', 12))
 
     def test_fromstring(self):
-        from numpypy import fromstring
+        import sys
+        from numpypy import fromstring, array, uint8, float32, int32
+
         a = fromstring(self.data)
         for i in range(4):
             assert a[i] == i + 1
-        raises(ValueError, fromstring, "abc")
+        b = fromstring('\x01\x02', dtype=uint8)
+        assert a[0] == 1
+        assert a[1] == 2
+        c = fromstring(self.fdata, dtype=float32)
+        assert c[0] == float32(2.3)
+        d = fromstring("1 2", sep=' ', count=2, dtype=uint8)
+        assert len(d) == 2
+        assert d[0] == 1
+        assert d[1] == 2
+        e = fromstring('3, 4,5', dtype=uint8, sep=',')
+        assert len(e) == 3
+        assert e[0] == 3
+        assert e[1] == 4
+        assert e[2] == 5
+        f = fromstring('\x01\x02\x03\x04\x05', dtype=uint8, count=3)
+        assert len(f) == 3
+        assert f[0] == 1
+        assert f[1] == 2
+        assert f[2] == 3
+        g = fromstring("1  2    3 ", dtype=uint8, sep=" ")
+        assert len(g) == 3
+        assert g[0] == 1
+        assert g[1] == 2
+        assert g[2] == 3
+        h = fromstring("1, , 2, 3", dtype=uint8, sep=",")
+        assert (h == [1,0,2,3]).all()
+        i = fromstring("1    2 3", dtype=uint8, sep=" ")
+        assert (i == [1,2,3]).all()
+        j = fromstring("1\t\t\t\t2\t3", dtype=uint8, sep="\t")
+        assert (j == [1,2,3]).all()
+        k = fromstring("1,x,2,3", dtype=uint8, sep=",")
+        assert (k == [1,0]).all()
+        l = fromstring("1,x,2,3", dtype='float32', sep=",")
+        assert (l == [1.0,-1.0]).all()
+        m = fromstring("1,,2,3", sep=",")
+        assert (m == [1.0,-1.0,2.0,3.0]).all()
+        n = fromstring("3.4 2.0 3.8 2.2", dtype=int32, sep=" ")
+        assert (n == [3]).all()
+        o = fromstring("1.0 2f.0f 3.8 2.2", dtype=float32, sep=" ")
+        assert len(o) == 2
+        assert o[0] == 1.0
+        assert o[1] == 2.0
+        p = fromstring("1.0,,2.0,3.0", sep=",")
+        assert (p == [1.0, -1.0, 2.0, 3.0]).all()
+        q = fromstring("1.0,,2.0,3.0", sep=" ")
+        assert (q == [1.0]).all()
+        r = fromstring("\x01\x00\x02", dtype='bool')
+        assert (r == [True, False, True]).all()
+        s = fromstring("1,2,3,,5", dtype=bool, sep=",")
+        assert (s == [True, True, True, False, True]).all()
+        t = fromstring("", bool)
+        assert (t == []).all()
+        u = fromstring("\x01\x00\x00\x00\x00\x00\x00\x00", dtype=int)
+        if sys.maxint > 2 ** 31 - 1:
+            assert (u == [1]).all()
+        else:
+            assert (u == [1, 0]).all()
+
+    def test_fromstring_types(self):
+        from numpypy import (fromstring, int8, int16, int32, int64, uint8,
+            uint16, uint32, float32, float64)
+
+        a = fromstring('\xFF', dtype=int8)
+        assert a[0] == -1
+        b = fromstring('\xFF', dtype=uint8)
+        assert b[0] == 255
+        c = fromstring('\xFF\xFF', dtype=int16)
+        assert c[0] == -1
+        d = fromstring('\xFF\xFF', dtype=uint16)
+        assert d[0] == 65535
+        e = fromstring('\xFF\xFF\xFF\xFF', dtype=int32)
+        assert e[0] == -1
+        f = fromstring('\xFF\xFF\xFF\xFF', dtype=uint32)
+        assert repr(f[0]) == '4294967295'
+        g = fromstring('\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF', dtype=int64)
+        assert g[0] == -1
+        h = fromstring(self.float32val, dtype=float32)
+        assert h[0] == float32(5.2)
+        i = fromstring(self.float64val, dtype=float64)
+        assert i[0] == float64(300.4)
+        j = fromstring(self.ulongval, dtype='L')
+        assert j[0] == 12
+
+
+    def test_fromstring_invalid(self):
+        from numpypy import fromstring, uint16, uint8, int32
+        #default dtype is 64-bit float, so 3 bytes should fail
+        raises(ValueError, fromstring, "\x01\x02\x03")
+        #3 bytes is not modulo 2 bytes (int16)
+        raises(ValueError, fromstring, "\x01\x03\x03", dtype=uint16)
+        #5 bytes is larger than 3 bytes
+        raises(ValueError, fromstring, "\x01\x02\x03", count=5, dtype=uint8)
 
 
 class AppTestRepr(BaseNumpyAppTest):
diff --git a/pypy/module/micronumpy/test/test_zjit.py b/pypy/module/micronumpy/test/test_zjit.py
--- a/pypy/module/micronumpy/test/test_zjit.py
+++ b/pypy/module/micronumpy/test/test_zjit.py
@@ -250,22 +250,6 @@
                                 'int_ge': 1, 'guard_false': 1,
                                 'jump': 1})
 
-    def define_slice2():
-        return """
-        a = |30|
-        s1 = a -> :20:2
-        s2 = a -> :30:3
-        b = s1 + s2
-        b -> 3
-        """
-
-    def test_slice2(self):
-        result = self.run("slice2")
-        assert result == 15
-        self.check_simple_loop({'getinteriorfield_raw': 2, 'float_add': 1,
-                                'setinteriorfield_raw': 1, 'int_add': 3,
-                                'int_ge': 1, 'guard_false': 1, 'jump': 1})
-
     def define_multidim():
         return """
         a = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]]
diff --git a/pypy/module/micronumpy/types.py b/pypy/module/micronumpy/types.py
--- a/pypy/module/micronumpy/types.py
+++ b/pypy/module/micronumpy/types.py
@@ -8,6 +8,7 @@
 from pypy.rlib.objectmodel import specialize
 from pypy.rlib.rarithmetic import LONG_BIT, widen
 from pypy.rpython.lltypesystem import lltype, rffi
+from pypy.rlib.rstruct.runpack import runpack
 
 
 def simple_unary_op(func):
@@ -55,6 +56,7 @@
 
 class Primitive(object):
     _mixin_ = True
+
     def get_element_size(self):
         return rffi.sizeof(self.T)
 
@@ -84,6 +86,9 @@
     def _coerce(self, space, w_item):
         raise NotImplementedError
 
+    def default_fromstring(self, space):
+        raise NotImplementedError
+
     def read(self, storage, width, i, offset):
         return self.box(libffi.array_getitem(clibffi.cast_type_to_ffitype(self.T),
             width, storage, i, offset
@@ -102,6 +107,9 @@
                 width, storage, i, offset, value
             )
 
+    def runpack_str(self, s):
+        return self.box(runpack(self.format_code, s))
+
     @simple_binary_op
     def add(self, v1, v2):
         return v1 + v2
@@ -164,6 +172,7 @@
 class Bool(BaseType, Primitive):
     T = lltype.Bool
     BoxType = interp_boxes.W_BoolBox
+    format_code = "?"
 
     True = BoxType(True)
     False = BoxType(False)
@@ -193,11 +202,14 @@
     def for_computation(self, v):
         return int(v)
 
+    def default_fromstring(self, space):
+        return self.box(False)
+
 class Integer(Primitive):
     _mixin_ = True
 
     def _coerce(self, space, w_item):
-        return self.box(space.int_w(space.int(w_item)))
+        return self.box(space.int_w(space.call_function(space.w_int, w_item)))
 
     def str_format(self, box):
         value = self.unbox(box)
@@ -206,6 +218,9 @@
     def for_computation(self, v):
         return widen(v)
 
+    def default_fromstring(self, space):
+        return self.box(0)
+
     @simple_binary_op
     def div(self, v1, v2):
         if v2 == 0:
@@ -241,42 +256,52 @@
 class Int8(BaseType, Integer):
     T = rffi.SIGNEDCHAR
     BoxType = interp_boxes.W_Int8Box
+    format_code = "b"
 
 class UInt8(BaseType, Integer):
     T = rffi.UCHAR
     BoxType = interp_boxes.W_UInt8Box
+    format_code = "B"
 
 class Int16(BaseType, Integer):
     T = rffi.SHORT
     BoxType = interp_boxes.W_Int16Box
+    format_code = "h"
 
 class UInt16(BaseType, Integer):
     T = rffi.USHORT
     BoxType = interp_boxes.W_UInt16Box
+    format_code = "H"
 
 class Int32(BaseType, Integer):
     T = rffi.INT
     BoxType = interp_boxes.W_Int32Box
+    format_code = "i"
 
 class UInt32(BaseType, Integer):
     T = rffi.UINT
     BoxType = interp_boxes.W_UInt32Box
+    format_code = "I"
 
 class Long(BaseType, Integer):
     T = rffi.LONG
     BoxType = interp_boxes.W_LongBox
+    format_code = "l"
 
 class ULong(BaseType, Integer):
     T = rffi.ULONG
     BoxType = interp_boxes.W_ULongBox
+    format_code = "L"
 
 class Int64(BaseType, Integer):
     T = rffi.LONGLONG
     BoxType = interp_boxes.W_Int64Box
+    format_code = "q"
 
 class UInt64(BaseType, Integer):
     T = rffi.ULONGLONG
     BoxType = interp_boxes.W_UInt64Box
+    format_code = "Q"
 
     def _coerce(self, space, w_item):
         try:
@@ -295,7 +320,7 @@
     _mixin_ = True
 
     def _coerce(self, space, w_item):
-        return self.box(space.float_w(space.float(w_item)))
+        return self.box(space.float_w(space.call_function(space.w_float, w_item)))
 
     def str_format(self, box):
         value = self.unbox(box)
@@ -304,6 +329,9 @@
     def for_computation(self, v):
         return float(v)
 
+    def default_fromstring(self, space):
+        return self.box(-1.0)
+
     @simple_binary_op
     def div(self, v1, v2):
         try:
@@ -403,7 +431,9 @@
 class Float32(BaseType, Float):
     T = rffi.FLOAT
     BoxType = interp_boxes.W_Float32Box
+    format_code = "f"
 
 class Float64(BaseType, Float):
     T = rffi.DOUBLE
-    BoxType = interp_boxes.W_Float64Box
\ No newline at end of file
+    BoxType = interp_boxes.W_Float64Box
+    format_code = "d"
\ No newline at end of file
diff --git a/pypy/module/posix/test/test_posix2.py b/pypy/module/posix/test/test_posix2.py
--- a/pypy/module/posix/test/test_posix2.py
+++ b/pypy/module/posix/test/test_posix2.py
@@ -656,7 +656,11 @@
                 os.fsync(f)     # <- should also work with a file, or anything
             finally:            #    with a fileno() method
                 f.close()
-            raises(OSError, os.fsync, fd)
+            try:
+                # May not raise anything with a buggy libc (or eatmydata)
+                os.fsync(fd)
+            except OSError:
+                pass
             raises(ValueError, os.fsync, -1)
 
     if hasattr(os, 'fdatasync'):
@@ -668,7 +672,11 @@
                 os.fdatasync(fd)
             finally:
                 f.close()
-            raises(OSError, os.fdatasync, fd)
+            try:
+                # May not raise anything with a buggy libc (or eatmydata)
+                os.fdatasync(fd)
+            except OSError:
+                pass
             raises(ValueError, os.fdatasync, -1)
 
     if hasattr(os, 'fchdir'):
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
@@ -210,9 +210,9 @@
     def entry_bridge_ops(self, *args, **kwds):
         ops = list(self._allops(*args, **kwds))
         labels = [op for op in ops if op.name == 'label']
-        assert ops.index(labels[0]) == 0
-        i = ops.index(labels[1])
-        return ops[1:i]
+        i0 = ops.index(labels[0])
+        i1 = ops.index(labels[1])
+        return ops[i0+1:i1]
 
     @property
     def chunks(self):
@@ -409,7 +409,7 @@
         """
         iter_exp_ops = iter(expected_ops)
         iter_ops = RevertableIterator(self.ops)
-        for opindex, exp_op in enumerate(iter_exp_ops):
+        for exp_op in iter_exp_ops:
             try:
                 if exp_op == '...':
                     # loop until we find an operation which matches
@@ -430,7 +430,7 @@
                 if exp_op[4] is False:    # optional operation
                     iter_ops.revert_one()
                     continue       # try to match with the next exp_op
-                e.opindex = opindex
+                e.opindex = iter_ops.index - 1
                 raise
         #
         # make sure we exhausted iter_ops
diff --git a/pypy/module/pypyjit/test_pypy_c/test_00_model.py b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
--- a/pypy/module/pypyjit/test_pypy_c/test_00_model.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_00_model.py
@@ -45,8 +45,10 @@
         cmdline = [sys.executable]
         if not import_site:
             cmdline.append('-S')
-        for key, value in jitopts.iteritems():
-            cmdline += ['--jit', '%s=%s' % (key, value)]
+        if jitopts:
+            jitcmdline = ['%s=%s' % (key, value)
+                          for key, value in jitopts.items()]
+            cmdline += ['--jit', ','.join(jitcmdline)]
         cmdline.append(str(self.filepath))
         #
         print cmdline, logfile
diff --git a/pypy/module/pypyjit/test_pypy_c/test_generators.py b/pypy/module/pypyjit/test_pypy_c/test_generators.py
--- a/pypy/module/pypyjit/test_pypy_c/test_generators.py
+++ b/pypy/module/pypyjit/test_pypy_c/test_generators.py
@@ -6,6 +6,8 @@
         def main(n):
             def f():
                 for i in range(10000):
+                    i -= 1
+                    i -= 42    # ID: subtract
                     yield i
 
             def g():
@@ -15,10 +17,15 @@
             g()
 
         log = self.run(main, [500])
-        loop, = log.loops_by_filename(self.filepath, is_entry_bridge='*')
+        # XXX XXX this test fails so far because of a detail that
+        # changed with jit-simplify-backendintf.  We should try to
+        # think of a way to be more resistent against such details.
+        # The issue is that we now get one Tracing, then go back
+        # to the interpreter hoping to immediately run the JITted
+        # code; but instead, we Trace again, just because another
+        # counter was also about to reach its limit...
+        loop, = log.loops_by_filename(self.filepath)
         assert loop.match_by_id("generator", """
-            ...
-            label(..., descr=...)
             i16 = force_token()
             p45 = new_with_vtable(ConstClass(W_IntObject))
             setfield_gc(p45, i29, descr=<SignedFieldDescr .*>)
@@ -26,3 +33,8 @@
             i47 = arraylen_gc(p8, descr=<GcPtrArrayDescr>) # Should be removed by backend
             jump(..., descr=...)
             """)
+        assert loop.match_by_id("subtract", """
+            setfield_gc(p7, 35, descr=<.*last_instr .*>)      # XXX bad, kill me
+            i2 = int_sub_ovf(i1, 42)
+            guard_no_overflow(descr=...)
+            """)
diff --git a/pypy/objspace/std/complexobject.py b/pypy/objspace/std/complexobject.py
--- a/pypy/objspace/std/complexobject.py
+++ b/pypy/objspace/std/complexobject.py
@@ -31,9 +31,9 @@
         imag2 = float2longlong(imag2)
         return real1 == real2 and imag1 == imag2
 
-    def unique_id(self, space):
+    def immutable_unique_id(self, space):
         if self.user_overridden_class:
-            return W_Object.unique_id(self, space)
+            return None
         from pypy.rlib.longlong2float import float2longlong
         from pypy.objspace.std.model import IDTAG_COMPLEX as tag
         real = space.float_w(space.getattr(self, space.wrap("real")))
diff --git a/pypy/objspace/std/floatobject.py b/pypy/objspace/std/floatobject.py
--- a/pypy/objspace/std/floatobject.py
+++ b/pypy/objspace/std/floatobject.py
@@ -34,9 +34,9 @@
         two = float2longlong(space.float_w(w_other))
         return one == two
 
-    def unique_id(self, space):
+    def immutable_unique_id(self, space):
         if self.user_overridden_class:
-            return W_Object.unique_id(self, space)
+            return None
         from pypy.rlib.longlong2float import float2longlong
         from pypy.objspace.std.model import IDTAG_FLOAT as tag
         val = float2longlong(space.float_w(self))
diff --git a/pypy/objspace/std/intobject.py b/pypy/objspace/std/intobject.py
--- a/pypy/objspace/std/intobject.py
+++ b/pypy/objspace/std/intobject.py
@@ -26,9 +26,9 @@
             return self is w_other
         return space.int_w(self) == space.int_w(w_other)
 
-    def unique_id(self, space):
+    def immutable_unique_id(self, space):
         if self.user_overridden_class:
-            return W_Object.unique_id(self, space)
+            return None
         from pypy.objspace.std.model import IDTAG_INT as tag
         b = space.bigint_w(self)
         b = b.lshift(3).or_(rbigint.fromint(tag))
diff --git a/pypy/objspace/std/longobject.py b/pypy/objspace/std/longobject.py
--- a/pypy/objspace/std/longobject.py
+++ b/pypy/objspace/std/longobject.py
@@ -18,9 +18,9 @@
             return self is w_other
         return space.bigint_w(self).eq(space.bigint_w(w_other))
 
-    def unique_id(self, space):
+    def immutable_unique_id(self, space):
         if self.user_overridden_class:
-            return W_Object.unique_id(self, space)
+            return None
         from pypy.objspace.std.model import IDTAG_LONG as tag
         b = space.bigint_w(self)
         b = b.lshift(3).or_(rbigint.fromint(tag))
diff --git a/pypy/objspace/std/specialisedtupleobject.py b/pypy/objspace/std/specialisedtupleobject.py
--- a/pypy/objspace/std/specialisedtupleobject.py
+++ b/pypy/objspace/std/specialisedtupleobject.py
@@ -177,52 +177,55 @@
 
 _specialisations = []
 Cls_ii = make_specialised_class((int, int))
-Cls_is = make_specialised_class((int, str))
-Cls_io = make_specialised_class((int, object))
-Cls_si = make_specialised_class((str, int))
-Cls_ss = make_specialised_class((str, str))
-Cls_so = make_specialised_class((str, object))
-Cls_oi = make_specialised_class((object, int))
-Cls_os = make_specialised_class((object, str))
+#Cls_is = make_specialised_class((int, str))
+#Cls_io = make_specialised_class((int, object))
+#Cls_si = make_specialised_class((str, int))
+#Cls_ss = make_specialised_class((str, str))
+#Cls_so = make_specialised_class((str, object))
+#Cls_oi = make_specialised_class((object, int))
+#Cls_os = make_specialised_class((object, str))
 Cls_oo = make_specialised_class((object, object))
 Cls_ff = make_specialised_class((float, float))
-Cls_ooo = make_specialised_class((object, object, object))
+#Cls_ooo = make_specialised_class((object, object, object))
 
 def makespecialisedtuple(space, list_w):
     if len(list_w) == 2:
         w_arg1, w_arg2 = list_w
         w_type1 = space.type(w_arg1)
-        w_type2 = space.type(w_arg2)
+        #w_type2 = space.type(w_arg2)
         #
         if w_type1 is space.w_int:
+            w_type2 = space.type(w_arg2)
             if w_type2 is space.w_int:
                 return Cls_ii(space, w_arg1, w_arg2)
-            elif w_type2 is space.w_str:
-                return Cls_is(space, w_arg1, w_arg2)
-            else:
-                return Cls_io(space, w_arg1, w_arg2)
+            #elif w_type2 is space.w_str:
+            #    return Cls_is(space, w_arg1, w_arg2)
+            #else:
+            #    return Cls_io(space, w_arg1, w_arg2)
         #
-        elif w_type1 is space.w_str:
-            if w_type2 is space.w_int:
-                return Cls_si(space, w_arg1, w_arg2)
-            elif w_type2 is space.w_str:
-                return Cls_ss(space, w_arg1, w_arg2)
-            else:
-                return Cls_so(space, w_arg1, w_arg2)
+        #elif w_type1 is space.w_str:
+        #    if w_type2 is space.w_int:
+        #        return Cls_si(space, w_arg1, w_arg2)
+        #    elif w_type2 is space.w_str:
+        #        return Cls_ss(space, w_arg1, w_arg2)
+        #    else:
+        #        return Cls_so(space, w_arg1, w_arg2)
         #
-        elif w_type1 is space.w_float and w_type2 is space.w_float:
-            return Cls_ff(space, w_arg1, w_arg2)
+        elif w_type1 is space.w_float:
+            w_type2 = space.type(w_arg2)
+            if w_type2 is space.w_float:
+                return Cls_ff(space, w_arg1, w_arg2)
         #
-        else:
-            if w_type2 is space.w_int:
-                return Cls_oi(space, w_arg1, w_arg2)
-            elif w_type2 is space.w_str:
-                return Cls_os(space, w_arg1, w_arg2)
-            else:
-                return Cls_oo(space, w_arg1, w_arg2)
+        #else:
+        #    if w_type2 is space.w_int:
+        #        return Cls_oi(space, w_arg1, w_arg2)
+        #    elif w_type2 is space.w_str:
+        #        return Cls_os(space, w_arg1, w_arg2)
+        #    else:
+        return Cls_oo(space, w_arg1, w_arg2)
         #
-    elif len(list_w) == 3:
-        return Cls_ooo(space, list_w[0], list_w[1], list_w[2])
+    #elif len(list_w) == 3:
+    #    return Cls_ooo(space, list_w[0], list_w[1], list_w[2])
     else:
         raise NotSpecialised
 
diff --git a/pypy/objspace/std/stringobject.py b/pypy/objspace/std/stringobject.py
--- a/pypy/objspace/std/stringobject.py
+++ b/pypy/objspace/std/stringobject.py
@@ -32,9 +32,9 @@
             return False
         return space.str_w(self) is space.str_w(w_other)
 
-    def unique_id(self, space):
+    def immutable_unique_id(self, space):
         if self.user_overridden_class:
-            return W_Object.unique_id(self, space)
+            return None
         return space.wrap(compute_unique_id(space.str_w(self)))
 
 
@@ -514,44 +514,41 @@
     if maxsplit == 0:
         return space.wrap(input)
 
-    #print "from replace, input: %s, sub: %s, by: %s" % (input, sub, by)
+    # An ok guess at the default size
+    builder = StringBuilder(len(input))
+    first = True
 
     if not sub:
         upper = len(input)
         if maxsplit > 0 and maxsplit < upper + 2:
             upper = maxsplit - 1
             assert upper >= 0
-        substrings_w = [""]
+        first = False
         for i in range(upper):
-            c = input[i]
-            substrings_w.append(c)
-        substrings_w.append(input[upper:])
+            builder.append(by)
+            builder.append(input[i])
+        builder.append(by)
+        builder.append_slice(input, upper, len(input))
     else:
         start = 0
         sublen = len(sub)
-        substrings_w = []
 
         while maxsplit != 0:
             next = input.find(sub, start)
             if next < 0:
                 break
-            substrings_w.append(input[start:next])
+            if not first:
+                builder.append(by)
+            first = False
+            builder.append_slice(input, start, next)
             start = next + sublen
             maxsplit -= 1   # NB. if it's already < 0, it stays < 0
 
-        substrings_w.append(input[start:])
+        if not first:
+            builder.append(by)
+        builder.append_slice(input, start, len(input))
 
-    try:
-        # XXX conservative estimate. If your strings are that close
-        # to overflowing, bad luck.
-        one = ovfcheck(len(substrings_w) * len(by))
-        ovfcheck(one + len(input))
-    except OverflowError:
-        raise OperationError(
-            space.w_OverflowError,
-            space.wrap("replace string is too long"))
-
-    return space.wrap(by.join(substrings_w))
+    return space.wrap(builder.build())
 
 
 def str_replace__String_ANY_ANY_ANY(space, w_self, w_sub, w_by, w_maxsplit):
diff --git a/pypy/objspace/std/test/test_obj.py b/pypy/objspace/std/test/test_obj.py
--- a/pypy/objspace/std/test/test_obj.py
+++ b/pypy/objspace/std/test/test_obj.py
@@ -253,6 +253,12 @@
         y = 2j
         assert id(x) != id(y)
 
+    def test_object_hash_immutable(self):
+        x = 42
+        y = 40
+        y += 2
+        assert object.__hash__(x) == object.__hash__(y)
+
 
 def test_isinstance_shortcut():
     from pypy.objspace.std import objspace
diff --git a/pypy/objspace/std/test/test_specialisedtupleobject.py b/pypy/objspace/std/test/test_specialisedtupleobject.py
--- a/pypy/objspace/std/test/test_specialisedtupleobject.py
+++ b/pypy/objspace/std/test/test_specialisedtupleobject.py
@@ -33,15 +33,15 @@
         N_space = gettestobjspace(**{"objspace.std.withspecialisedtuple": False})
         S_space = gettestobjspace(**{"objspace.std.withspecialisedtuple": True})
         
-        def hash_test(values):
+        def hash_test(values, must_be_specialized=True):
             N_values_w = [N_space.wrap(value) for value in values]
             S_values_w = [S_space.wrap(value) for value in values]
             N_w_tuple = N_space.newtuple(N_values_w)
             S_w_tuple = S_space.newtuple(S_values_w)
-    
-            assert isinstance(S_w_tuple, W_SpecialisedTupleObject)
+
+            if must_be_specialized:
+                assert isinstance(S_w_tuple, W_SpecialisedTupleObject)
             assert isinstance(N_w_tuple, W_TupleObject)
-            assert not N_space.is_true(N_space.eq(N_w_tuple, S_w_tuple))
             assert S_space.is_true(S_space.eq(N_w_tuple, S_w_tuple))
             assert S_space.is_true(S_space.eq(N_space.hash(N_w_tuple), S_space.hash(S_w_tuple)))
 
@@ -53,7 +53,7 @@
         hash_test([1,(1,2)])
         hash_test([1,('a',2)])
         hash_test([1,()])
-        hash_test([1,2,3])
+        hash_test([1,2,3], must_be_specialized=False)
 
 
 class AppTestW_SpecialisedTupleObject:
@@ -83,6 +83,8 @@
         return ("SpecialisedTupleObject" + expected) in r
 
     def test_createspecialisedtuple(self):
+        have = ['ii', 'ff', 'oo']
+        #
         spec = {int: 'i',
                 float: 'f',
                 str: 's',
@@ -92,14 +94,14 @@
             for y in [43, 4.3, "bar", []]:
                 expected1 = spec[type(x)]
                 expected2 = spec[type(y)]
-                if (expected1 == 'f') ^ (expected2 == 'f'):
-                    if expected1 == 'f': expected1 = 'o'
-                    if expected2 == 'f': expected2 = 'o'
+                if expected1 + expected2 not in have:
+                    expected1 = expected2 = 'o'
                 obj = (x, y)
                 assert self.isspecialised(obj, '_' + expected1 + expected2)
         #
-        obj = (1, 2, 3)
-        assert self.isspecialised(obj, '_ooo')
+        if 'ooo' in have:
+            obj = (1, 2, 3)
+            assert self.isspecialised(obj, '_ooo')
 
     def test_delegation(self):
         t = self.forbid_delegation((42, 43))
@@ -214,6 +216,8 @@
         raises(IndexError, "t[-3]")
 
     def test_three_tuples(self):
+        if not self.isspecialised((1, 2, 3)):
+            skip("don't have specialization for 3-tuples")
         b = self.forbid_delegation((1, 2, 3))
         c = (1,)
         d = c + (2, 3)
@@ -221,6 +225,16 @@
         assert b == d
 
     def test_mongrel(self):
+        a = self.forbid_delegation((2.2, '333'))
+        assert self.isspecialised(a)
+        assert len(a) == 2
+        assert a[0] == 2.2 and a[1] == '333'
+        b = ('333',)
+        assert a == (2.2,) + b
+        assert not a != (2.2,) + b
+        #
+        if not self.isspecialised((1, 2, 3)):
+            skip("don't have specialization for 3-tuples")
         a = self.forbid_delegation((1, 2.2, '333'))
         assert self.isspecialised(a)
         assert len(a) == 3
diff --git a/pypy/objspace/std/typetype.py b/pypy/objspace/std/typetype.py
--- a/pypy/objspace/std/typetype.py
+++ b/pypy/objspace/std/typetype.py
@@ -10,7 +10,6 @@
     w_dict=gateway.NoneNotWrapped):
 
     "This is used to create user-defined classes only."
-    from pypy.objspace.std.typeobject import W_TypeObject
     # XXX check types
 
     w_typetype = _precheck_for_new(space, w_typetype)
@@ -19,10 +18,18 @@
     if (space.is_w(space.type(w_typetype), space.w_type) and w_bases is None and
         w_dict is None):
         return space.type(w_name)
-    elif w_bases is None or w_dict is None:
+    else:
+        return _create_new_type(space, w_typetype, w_name, w_bases, w_dict)
+
+
+def _create_new_type(space, w_typetype, w_name, w_bases, w_dict):
+    # this is in its own function because we want the special case 'type(x)'
+    # above to be seen by the jit.
+    from pypy.objspace.std.typeobject import W_TypeObject
+
+    if w_bases is None or w_dict is None:
         raise OperationError(space.w_TypeError, space.wrap("type() takes 1 or 3 arguments"))
 
-
     bases_w = space.fixedview(w_bases)
 
     w_winner = w_typetype
diff --git a/pypy/objspace/std/unicodeobject.py b/pypy/objspace/std/unicodeobject.py
--- a/pypy/objspace/std/unicodeobject.py
+++ b/pypy/objspace/std/unicodeobject.py
@@ -32,9 +32,9 @@
             return False
         return space.unicode_w(self) is space.unicode_w(w_other)
 
-    def unique_id(self, space):
+    def immutable_unique_id(self, space):
         if self.user_overridden_class:
-            return W_Object.unique_id(self, space)
+            return None
         return space.wrap(compute_unique_id(space.unicode_w(self)))
 
 
diff --git a/pypy/rlib/jit.py b/pypy/rlib/jit.py
--- a/pypy/rlib/jit.py
+++ b/pypy/rlib/jit.py
@@ -395,6 +395,7 @@
               'retrace_limit': 5,
               'max_retrace_guards': 15,
               'enable_opts': 'all',
+              'decay_halflife': 40,
               }
 unroll_parameters = unrolling_iterable(PARAMETERS.items())
 DEFAULT = object()
diff --git a/pypy/rlib/longlong2float.py b/pypy/rlib/longlong2float.py
--- a/pypy/rlib/longlong2float.py
+++ b/pypy/rlib/longlong2float.py
@@ -79,19 +79,19 @@
 longlong2float = rffi.llexternal(
     "pypy__longlong2float", [rffi.LONGLONG], rffi.DOUBLE,
     _callable=longlong2float_emulator, compilation_info=eci,
-    _nowrapper=True, elidable_function=True)
+    _nowrapper=True, elidable_function=True, sandboxsafe=True)
 
 float2longlong = rffi.llexternal(
     "pypy__float2longlong", [rffi.DOUBLE], rffi.LONGLONG,
     _callable=float2longlong_emulator, compilation_info=eci,
-    _nowrapper=True, elidable_function=True)
+    _nowrapper=True, elidable_function=True, sandboxsafe=True)
 
 uint2singlefloat = rffi.llexternal(
     "pypy__uint2singlefloat", [rffi.UINT], rffi.FLOAT,
     _callable=uint2singlefloat_emulator, compilation_info=eci,
-    _nowrapper=True, elidable_function=True)
+    _nowrapper=True, elidable_function=True, sandboxsafe=True)
 
 singlefloat2uint = rffi.llexternal(
     "pypy__singlefloat2uint", [rffi.FLOAT], rffi.UINT,
     _callable=singlefloat2uint_emulator, compilation_info=eci,
-    _nowrapper=True, elidable_function=True)
+    _nowrapper=True, elidable_function=True, sandboxsafe=True)
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
@@ -16,6 +16,7 @@
 from pypy.rpython.annlowlevel import llhelper
 from pypy.rlib.objectmodel import we_are_translated
 from pypy.rlib.rstring import StringBuilder, UnicodeBuilder
+from pypy.rlib import jit
 from pypy.rpython.lltypesystem import llmemory
 import os, sys
 
@@ -249,8 +250,7 @@
     wrapper = func_with_new_name(wrapper, name)
 
     if calling_conv != "c":
-        from pypy.rlib.jit import dont_look_inside
-        wrapper = dont_look_inside(wrapper)
+        wrapper = jit.dont_look_inside(wrapper)
 
     return wrapper
 
@@ -697,6 +697,8 @@
         return b.build()
 
     # str -> char*
+    # Can't inline this because of the raw address manipulation.
+    @jit.dont_look_inside
     def get_nonmovingbuffer(data):
         """
         Either returns a non-moving copy or performs neccessary pointer
@@ -717,6 +719,8 @@
     get_nonmovingbuffer._annenforceargs_ = [strtype]
 
     # (str, char*) -> None
+    # Can't inline this because of the raw address manipulation.
+    @jit.dont_look_inside
     def free_nonmovingbuffer(data, buf):
         """
         Either free a non-moving buffer or keep the original storage alive.
diff --git a/pypy/rpython/rint.py b/pypy/rpython/rint.py
--- a/pypy/rpython/rint.py
+++ b/pypy/rpython/rint.py
@@ -126,10 +126,7 @@
     rtype_inplace_rshift = rtype_rshift
 
     def rtype_pow(_, hop):
-        raise MissingRTypeOperation("pow(int, int)"
-                                    " (use float**float instead; it is too"
-                                    " easy to overlook the overflow"
-                                    " issues of int**int)")
+        raise MissingRTypeOperation("'**' not supported in RPython")
 
     rtype_pow_ovf = rtype_pow
     rtype_inplace_pow = rtype_pow
diff --git a/pypy/tool/clean_old_branches.py b/pypy/tool/clean_old_branches.py
--- a/pypy/tool/clean_old_branches.py
+++ b/pypy/tool/clean_old_branches.py
@@ -11,14 +11,17 @@
     sys.exit(1)
 
 def heads(args):
-    g = os.popen(r"hg heads --topo %s --template '{branches} {node|short}\n'"
+    g = os.popen(r"hg heads --topo %s --template '{node|short}:{branches}\n'"
                  % args, 'r')
     result = g.read()
     g.close()
     result = result.splitlines(False)
-    result = [s for s in result
-                if not s.startswith(' ')
-                   and not s.startswith('closed-branches ')]
+    for line in result:
+        if len(line.split(':', 1)) != 2:
+            raise ValueError("'result' contains: %r" % line)
+    result = [s.split(':', 1) for s in result]
+    result = [(head, branch) for (head, branch) in result
+                if branch not in ['', 'closed-branches']]
     return result
 
 all_heads = heads("--closed")
@@ -34,8 +37,7 @@
 
 closed_heads.reverse()
 
-for branch_head in closed_heads:
-    branch, head = branch_head.split()
+for head, branch in closed_heads:
     print '\t', branch
 print
 print 'The branches listed above will be merged to "closed-branches".'
@@ -54,8 +56,7 @@
         print '*** error %r' % (err,)
         sys.exit(1)
 
-for branch_head in closed_heads:
-    branch, head = branch_head.split()
+for head, branch in closed_heads:
     print
     print '***** %s ***** %s *****' % (branch, head)
     do("hg up --clean closed-branches")
diff --git a/pypy/tool/gcc_cache.py b/pypy/tool/gcc_cache.py
--- a/pypy/tool/gcc_cache.py
+++ b/pypy/tool/gcc_cache.py
@@ -11,6 +11,9 @@
     # Import 'platform' every time, the compiler may have been changed
     from pypy.translator.platform import platform
     cache_dir = cache_dir_root.join(cachename).ensure(dir=1)
+    c_files.extend([py.path.local(f) for f in eci.separate_module_files])
+    eci = ExternalCompilationInfo(**eci._copy_attributes())
+    eci.separate_module_files = ()
     filecontents = [c_file.read() for c_file in c_files]
     key = repr((filecontents, eci, platform.key()))
     hash = md5(key).hexdigest()


More information about the pypy-commit mailing list