[pypy-commit] pypy stm-thread-2: hg merge default

arigo noreply at buildbot.pypy.org
Sat Jan 5 19:58:02 CET 2013


Author: Armin Rigo <arigo at tunes.org>
Branch: stm-thread-2
Changeset: r59766:759e48aef604
Date: 2013-01-05 19:47 +0100
http://bitbucket.org/pypy/pypy/changeset/759e48aef604/

Log:	hg merge default

diff too long, truncating to 2000 out of 6159 lines

diff --git a/LICENSE b/LICENSE
--- a/LICENSE
+++ b/LICENSE
@@ -28,7 +28,7 @@
     DEALINGS IN THE SOFTWARE.
 
 
-PyPy Copyright holders 2003-2012
+PyPy Copyright holders 2003-2013
 ----------------------------------- 
 
 Except when otherwise stated (look for LICENSE files or information at
diff --git a/lib-python/2.7/ctypes/test/test_internals.py b/lib-python/2.7/ctypes/test/test_internals.py
--- a/lib-python/2.7/ctypes/test/test_internals.py
+++ b/lib-python/2.7/ctypes/test/test_internals.py
@@ -1,7 +1,10 @@
 # This tests the internal _objects attribute
 import unittest
 from ctypes import *
-from sys import getrefcount as grc
+try:
+    from sys import getrefcount as grc
+except ImportError:
+    grc = None      # e.g. PyPy
 
 # XXX This test must be reviewed for correctness!!!
 
@@ -22,6 +25,8 @@
         self.assertEqual(id(a), id(b))
 
     def test_ints(self):
+        if grc is None:
+            return unittest.skip("no sys.getrefcount()")
         i = 42000123
         refcnt = grc(i)
         ci = c_int(i)
@@ -29,6 +34,8 @@
         self.assertEqual(ci._objects, None)
 
     def test_c_char_p(self):
+        if grc is None:
+            return unittest.skip("no sys.getrefcount()")
         s = "Hello, World"
         refcnt = grc(s)
         cs = c_char_p(s)
diff --git a/lib-python/2.7/ctypes/test/test_memfunctions.py b/lib-python/2.7/ctypes/test/test_memfunctions.py
--- a/lib-python/2.7/ctypes/test/test_memfunctions.py
+++ b/lib-python/2.7/ctypes/test/test_memfunctions.py
@@ -53,7 +53,8 @@
         s = string_at("foo bar")
         # XXX The following may be wrong, depending on how Python
         # manages string instances
-        self.assertEqual(2, sys.getrefcount(s))
+        if hasattr(sys, 'getrefcount'):
+            self.assertEqual(2, sys.getrefcount(s))
         self.assertTrue(s, "foo bar")
 
         self.assertEqual(string_at("foo bar", 8), "foo bar\0")
diff --git a/lib-python/2.7/ctypes/test/test_python_api.py b/lib-python/2.7/ctypes/test/test_python_api.py
--- a/lib-python/2.7/ctypes/test/test_python_api.py
+++ b/lib-python/2.7/ctypes/test/test_python_api.py
@@ -9,7 +9,10 @@
 
 ################################################################
 
-from sys import getrefcount as grc
+try:
+    from sys import getrefcount as grc
+except ImportError:
+    grc = None      # e.g. PyPy
 if sys.version_info > (2, 4):
     c_py_ssize_t = c_size_t
 else:
diff --git a/lib-python/2.7/ctypes/test/test_refcounts.py b/lib-python/2.7/ctypes/test/test_refcounts.py
--- a/lib-python/2.7/ctypes/test/test_refcounts.py
+++ b/lib-python/2.7/ctypes/test/test_refcounts.py
@@ -11,7 +11,10 @@
 class RefcountTestCase(unittest.TestCase):
 
     def test_1(self):
-        from sys import getrefcount as grc
+        try:
+            from sys import getrefcount as grc
+        except ImportError:
+            return unittest.skip("no sys.getrefcount()")
 
         f = dll._testfunc_callback_i_if
         f.restype = ctypes.c_int
@@ -35,7 +38,10 @@
 
 
     def test_refcount(self):
-        from sys import getrefcount as grc
+        try:
+            from sys import getrefcount as grc
+        except ImportError:
+            return unittest.skip("no sys.getrefcount()")
         def func(*args):
             pass
         # this is the standard refcount for func
@@ -84,6 +90,10 @@
 class AnotherLeak(unittest.TestCase):
     def test_callback(self):
         import sys
+        try:
+            from sys import getrefcount
+        except ImportError:
+            return unittest.skip("no sys.getrefcount()")
 
         proto = ctypes.CFUNCTYPE(ctypes.c_int, ctypes.c_int, ctypes.c_int)
         def func(a, b):
diff --git a/lib-python/2.7/sre_parse.py b/lib-python/2.7/sre_parse.py
--- a/lib-python/2.7/sre_parse.py
+++ b/lib-python/2.7/sre_parse.py
@@ -16,6 +16,12 @@
 
 from sre_constants import *
 
+try:
+    from __pypy__ import newdict
+except ImportError:
+    def newdict(tp):
+        return {}
+
 SPECIAL_CHARS = ".\\[{()*+?^$|"
 REPEAT_CHARS = "*+?{"
 
@@ -68,7 +74,7 @@
         self.flags = 0
         self.open = []
         self.groups = 1
-        self.groupdict = {}
+        self.groupdict = newdict("module")
     def opengroup(self, name=None):
         gid = self.groups
         self.groups = gid + 1
diff --git a/lib-python/2.7/timeit.py b/lib-python/2.7/timeit.py
--- a/lib-python/2.7/timeit.py
+++ b/lib-python/2.7/timeit.py
@@ -190,7 +190,8 @@
         else:
             it = [None] * number
         gcold = gc.isenabled()
-        gc.disable()
+        if '__pypy__' not in sys.builtin_module_names:
+            gc.disable()    # only do that on CPython
         try:
             timing = self.inner(it, self.timer)
         finally:
diff --git a/lib_pypy/_ctypes_test.py b/lib_pypy/_ctypes_test.py
--- a/lib_pypy/_ctypes_test.py
+++ b/lib_pypy/_ctypes_test.py
@@ -2,10 +2,6 @@
 import tempfile
 import gc
 
-# Monkeypatch & hacks to let ctypes.tests import.
-# This should be removed at some point.
-sys.getrefcount = lambda x: len(gc.get_referrers(x)) - 1
-
 def compile_shared():
     """Compile '_ctypes_test.c' into an extension module, and import it
     """
diff --git a/lib_pypy/numpypy/core/arrayprint.py b/lib_pypy/numpypy/core/arrayprint.py
--- a/lib_pypy/numpypy/core/arrayprint.py
+++ b/lib_pypy/numpypy/core/arrayprint.py
@@ -248,9 +248,9 @@
                   'int' : IntegerFormat(data),
                   'float' : FloatFormat(data, precision, suppress_small),
                   'longfloat' : LongFloatFormat(precision),
-                  #'complexfloat' : ComplexFormat(data, precision,
-                  #                               suppress_small),
-                  #'longcomplexfloat' : LongComplexFormat(precision),
+                  'complexfloat' : ComplexFormat(data, precision,
+                                                 suppress_small),
+                  'longcomplexfloat' : LongComplexFormat(precision),
                   'datetime' : DatetimeFormat(data),
                   'timedelta' : TimedeltaFormat(data),
                   'numpystr' : repr_format,
@@ -294,19 +294,19 @@
             #else:
             format_function = formatdict['int']
         elif issubclass(dtypeobj, _nt.floating):
-            #if issubclass(dtypeobj, _nt.longfloat):
-            #    format_function = formatdict['longfloat']
-            #else:
-            format_function = formatdict['float']
-        #elif issubclass(dtypeobj, _nt.complexfloating):
-        #    if issubclass(dtypeobj, _nt.clongfloat):
-        #        format_function = formatdict['longcomplexfloat']
-        #    else:
-        #        format_function = formatdict['complexfloat']
+            if issubclass(dtypeobj, _nt.longfloat):
+                format_function = formatdict['longfloat']
+            else:
+                format_function = formatdict['float']
+        elif issubclass(dtypeobj, _nt.complexfloating):
+            if issubclass(dtypeobj, _nt.clongfloat):
+                format_function = formatdict['longcomplexfloat']
+            else:
+                format_function = formatdict['complexfloat']
         elif issubclass(dtypeobj, (_nt.unicode_, _nt.string_)):
             format_function = formatdict['numpystr']
-        elif issubclass(dtypeobj, _nt.datetime64):
-            format_function = formatdict['datetime']
+        #elif issubclass(dtypeobj, _nt.datetime64):
+        #    format_function = formatdict['datetime']
         else:
             format_function = formatdict['str']
 
diff --git a/pypy/annotation/annrpython.py b/pypy/annotation/annrpython.py
--- a/pypy/annotation/annrpython.py
+++ b/pypy/annotation/annrpython.py
@@ -8,7 +8,7 @@
 from pypy.objspace.flow.model import (Variable, Constant, FunctionGraph,
                                       c_last_exception, checkgraph)
 from pypy.translator import simplify, transform
-from pypy.annotation import model as annmodel, signature
+from pypy.annotation import model as annmodel, signature, unaryop, binaryop
 from pypy.annotation.bookkeeper import Bookkeeper
 import py
 log = py.log.Producer("annrpython")
@@ -453,12 +453,12 @@
         # occour for this specific, typed operation.
         if block.exitswitch == c_last_exception:
             op = block.operations[-1]
-            if op.opname in annmodel.BINARY_OPERATIONS:
+            if op.opname in binaryop.BINARY_OPERATIONS:
                 arg1 = self.binding(op.args[0])
                 arg2 = self.binding(op.args[1])
                 binop = getattr(pair(arg1, arg2), op.opname, None)
                 can_only_throw = annmodel.read_can_only_throw(binop, arg1, arg2)
-            elif op.opname in annmodel.UNARY_OPERATIONS:
+            elif op.opname in unaryop.UNARY_OPERATIONS:
                 arg1 = self.binding(op.args[0])
                 opname = op.opname
                 if opname == 'contains': opname = 'op_contains'
@@ -629,10 +629,10 @@
         return self.bookkeeper.newdict()
 
 
-    def _registeroperations(cls, model):
+    def _registeroperations(cls, unary_ops, binary_ops):
         # All unary operations
         d = {}
-        for opname in model.UNARY_OPERATIONS:
+        for opname in unary_ops:
             fnname = 'consider_op_' + opname
             exec py.code.Source("""
 def consider_op_%s(self, arg, *args):
@@ -640,7 +640,7 @@
 """ % (opname, opname)).compile() in globals(), d
             setattr(cls, fnname, d[fnname])
         # All binary operations
-        for opname in model.BINARY_OPERATIONS:
+        for opname in binary_ops:
             fnname = 'consider_op_' + opname
             exec py.code.Source("""
 def consider_op_%s(self, arg1, arg2, *args):
@@ -650,7 +650,7 @@
     _registeroperations = classmethod(_registeroperations)
 
 # register simple operations handling
-RPythonAnnotator._registeroperations(annmodel)
+RPythonAnnotator._registeroperations(unaryop.UNARY_OPERATIONS, binaryop.BINARY_OPERATIONS)
 
 
 class BlockedInference(Exception):
diff --git a/pypy/annotation/binaryop.py b/pypy/annotation/binaryop.py
--- a/pypy/annotation/binaryop.py
+++ b/pypy/annotation/binaryop.py
@@ -7,10 +7,10 @@
 from pypy.tool.pairtype import pair, pairtype
 from pypy.annotation.model import SomeObject, SomeInteger, SomeBool, s_Bool
 from pypy.annotation.model import SomeString, SomeChar, SomeList, SomeDict
-from pypy.annotation.model import SomeUnicodeCodePoint, SomeStringOrUnicode
+from pypy.annotation.model import SomeUnicodeCodePoint, SomeUnicodeString
 from pypy.annotation.model import SomeTuple, SomeImpossibleValue, s_ImpossibleValue
 from pypy.annotation.model import SomeInstance, SomeBuiltin, SomeIterator
-from pypy.annotation.model import SomePBC, SomeFloat, s_None
+from pypy.annotation.model import SomePBC, SomeFloat, s_None, SomeByteArray
 from pypy.annotation.model import SomeExternalObject, SomeWeakRef
 from pypy.annotation.model import SomeAddress, SomeTypedAddressAccess
 from pypy.annotation.model import SomeSingleFloat, SomeLongFloat, SomeType
@@ -19,7 +19,6 @@
 from pypy.annotation.model import read_can_only_throw
 from pypy.annotation.model import add_knowntypedata, merge_knowntypedata
 from pypy.annotation.model import SomeGenericCallable
-from pypy.annotation.model import SomeUnicodeString
 from pypy.annotation.bookkeeper import getbookkeeper
 from pypy.objspace.flow.model import Variable, Constant
 from pypy.rlib import rarithmetic
@@ -416,6 +415,34 @@
             result.const = str1.const + str2.const
         return result
 
+class __extend__(pairtype(SomeByteArray, SomeByteArray)):
+    def union((b1, b2)):
+        can_be_None = b1.can_be_None or b2.can_be_None
+        return SomeByteArray(can_be_None=can_be_None)
+
+    def add((b1, b2)):
+        result = SomeByteArray()
+        if b1.is_immutable_constant() and b2.is_immutable_constant():
+            result.const = b1.const + b2.const
+        return result
+
+class __extend__(pairtype(SomeByteArray, SomeInteger)):
+    def getitem((s_b, s_i)):
+        return SomeInteger()
+
+    def setitem((s_b, s_i), s_i2):
+        assert isinstance(s_i2, SomeInteger)
+
+class __extend__(pairtype(SomeString, SomeByteArray),
+                 pairtype(SomeByteArray, SomeString),
+                 pairtype(SomeChar, SomeByteArray),
+                 pairtype(SomeByteArray, SomeChar)):
+    def add((b1, b2)):
+        result = SomeByteArray()
+        if b1.is_immutable_constant() and b2.is_immutable_constant():
+            result.const = b1.const + b2.const
+        return result
+
 class __extend__(pairtype(SomeChar, SomeChar)):
 
     def union((chr1, chr2)):
@@ -458,7 +485,8 @@
         for s_item in s_tuple.items:
             if isinstance(s_item, SomeFloat):
                 pass   # or s_item is a subclass, like SomeInteger
-            elif isinstance(s_item, SomeStringOrUnicode) and s_item.no_nul:
+            elif (isinstance(s_item, SomeString) or
+                  isinstance(s_item, SomeUnicodeString)) and s_item.no_nul:
                 pass
             else:
                 no_nul = False
diff --git a/pypy/annotation/bookkeeper.py b/pypy/annotation/bookkeeper.py
--- a/pypy/annotation/bookkeeper.py
+++ b/pypy/annotation/bookkeeper.py
@@ -13,7 +13,7 @@
      SomeUnicodeCodePoint, SomeOOStaticMeth, s_None, s_ImpossibleValue, \
      SomeLLADTMeth, SomeBool, SomeTuple, SomeOOClass, SomeImpossibleValue, \
      SomeUnicodeString, SomeList, SomeObject, HarmlesslyBlocked, \
-     SomeWeakRef, lltype_to_annotation, SomeType
+     SomeWeakRef, lltype_to_annotation, SomeType, SomeByteArray
 from pypy.annotation.classdef import InstanceSource, ClassDef
 from pypy.annotation.listdef import ListDef, ListItem
 from pypy.annotation.dictdef import DictDef
@@ -349,6 +349,8 @@
                 result = SomeUnicodeCodePoint()
             else:
                 result = SomeUnicodeString()
+        elif tp is bytearray:
+            result = SomeByteArray()
         elif tp is tuple:
             result = SomeTuple(items = [self.immutablevalue(e, need_const) for e in x])
         elif tp is float:
diff --git a/pypy/annotation/builtin.py b/pypy/annotation/builtin.py
--- a/pypy/annotation/builtin.py
+++ b/pypy/annotation/builtin.py
@@ -9,7 +9,7 @@
 from pypy.annotation.model import SomeFloat, unionof, SomeUnicodeString
 from pypy.annotation.model import SomePBC, SomeInstance, SomeDict, SomeList
 from pypy.annotation.model import SomeWeakRef, SomeIterator
-from pypy.annotation.model import SomeOOObject
+from pypy.annotation.model import SomeOOObject, SomeByteArray
 from pypy.annotation.model import annotation_to_lltype, lltype_to_annotation, ll_to_annotation
 from pypy.annotation.model import add_knowntypedata
 from pypy.annotation.model import s_ImpossibleValue
@@ -119,6 +119,9 @@
 def builtin_unicode(s_unicode):
     return constpropagate(unicode, [s_unicode], SomeUnicodeString())
 
+def builtin_bytearray(s_str):
+    return constpropagate(bytearray, [s_str], SomeByteArray())
+
 def our_issubclass(cls1, cls2):
     """ we're going to try to be less silly in the face of old-style classes"""
     from pypy.annotation.classdef import ClassDef
@@ -253,24 +256,6 @@
                 s = SomeInteger(nonneg=True, knowntype=s.knowntype)
         return s
 
-def builtin_apply(*stuff):
-    getbookkeeper().warning("ignoring apply%r" % (stuff,))
-    return SomeObject()
-
-##def builtin_slice(*args):
-##    bk = getbookkeeper()
-##    if len(args) == 1:
-##        return SomeSlice(
-##            bk.immutablevalue(None), args[0], bk.immutablevalue(None))
-##    elif len(args) == 2:
-##        return SomeSlice(
-##            args[0], args[1], bk.immutablevalue(None))
-##    elif len(args) == 3:
-##        return SomeSlice(
-##            args[0], args[1], args[2])
-##    else:
-##        raise Exception, "bogus call to slice()"
-
 
 def OSError_init(s_self, *args):
     pass
diff --git a/pypy/annotation/model.py b/pypy/annotation/model.py
--- a/pypy/annotation/model.py
+++ b/pypy/annotation/model.py
@@ -201,11 +201,16 @@
             self.knowntypedata = knowntypedata
 
 class SomeStringOrUnicode(SomeObject):
+    """Base class for shared implementation of SomeString and SomeUnicodeString.
+
+    Cannot be an annotation."""
+
     immutable = True
     can_be_None=False
     no_nul = False  # No NUL character in the string.
 
     def __init__(self, can_be_None=False, no_nul=False):
+        assert type(self) is not SomeStringOrUnicode
         if can_be_None:
             self.can_be_None = True
         if no_nul:
@@ -224,19 +229,19 @@
             d2 = d2.copy(); d2['no_nul'] = 0   # ignored
         return d1 == d2
 
+    def nonnoneify(self):
+        return self.__class__(can_be_None=False, no_nul=self.no_nul)
+
 class SomeString(SomeStringOrUnicode):
     "Stands for an object which is known to be a string."
     knowntype = str
 
-    def nonnoneify(self):
-        return SomeString(can_be_None=False, no_nul=self.no_nul)
-
 class SomeUnicodeString(SomeStringOrUnicode):
     "Stands for an object which is known to be an unicode string"
     knowntype = unicode
 
-    def nonnoneify(self):
-        return SomeUnicodeString(can_be_None=False, no_nul=self.no_nul)
+class SomeByteArray(SomeStringOrUnicode):
+    knowntype = bytearray
 
 class SomeChar(SomeString):
     "Stands for an object known to be a string of length 1."
@@ -772,7 +777,3 @@
     else:
         raise RuntimeError("The annotator relies on 'assert' statements from the\n"
                      "\tannotated program: you cannot run it with 'python -O'.")
-
-# this has the side-effect of registering the unary and binary operations
-from pypy.annotation.unaryop  import UNARY_OPERATIONS
-from pypy.annotation.binaryop import BINARY_OPERATIONS
diff --git a/pypy/annotation/signature.py b/pypy/annotation/signature.py
--- a/pypy/annotation/signature.py
+++ b/pypy/annotation/signature.py
@@ -151,4 +151,9 @@
     actualtypes[:] = params_s
 
 def enforce_signature_return(funcdesc, sigtype, inferredtype):
-    return finish_type(sigtype, funcdesc.bookkeeper, funcdesc.pyobj)
+    s_sigret = finish_type(sigtype, funcdesc.bookkeeper, funcdesc.pyobj)
+    if not s_sigret.contains(inferredtype):
+        raise Exception("%r return value:\n"
+                        "expected %s,\n"
+                        "     got %s" % (funcdesc, s_sigret, inferredtype))
+    return s_sigret
diff --git a/pypy/annotation/test/test_annrpython.py b/pypy/annotation/test/test_annrpython.py
--- a/pypy/annotation/test/test_annrpython.py
+++ b/pypy/annotation/test/test_annrpython.py
@@ -3819,6 +3819,37 @@
         a = self.RPythonAnnotator()
         a.build_types(f, []) # assert did not explode
 
+    def test_bytearray(self):
+        def f():
+            return bytearray("xyz")
+
+        a = self.RPythonAnnotator()
+        assert isinstance(a.build_types(f, []), annmodel.SomeByteArray)
+
+    def test_bytearray_add(self):
+        def f(a):
+            return a + bytearray("xyz")
+
+        a = self.RPythonAnnotator()
+        assert isinstance(a.build_types(f, [annmodel.SomeByteArray()]),
+                          annmodel.SomeByteArray)
+        a = self.RPythonAnnotator()
+        assert isinstance(a.build_types(f, [str]),
+                          annmodel.SomeByteArray)
+        a = self.RPythonAnnotator()
+        assert isinstance(a.build_types(f, [annmodel.SomeChar()]),
+                          annmodel.SomeByteArray)
+
+    def test_bytearray_setitem_getitem(self):
+        def f(b, i, c):
+            b[i] = c
+            return b[i + 1]
+
+        a = self.RPythonAnnotator()
+        assert isinstance(a.build_types(f, [annmodel.SomeByteArray(),
+                                            int, int]),
+                          annmodel.SomeInteger)
+
 def g(n):
     return [0,1,2,n]
 
diff --git a/pypy/doc/config/objspace.usemodules.time.txt b/pypy/doc/config/objspace.usemodules.time.txt
--- a/pypy/doc/config/objspace.usemodules.time.txt
+++ b/pypy/doc/config/objspace.usemodules.time.txt
@@ -1,4 +1,5 @@
 Use the 'time' module. 
 
 Obsolete; use :config:`objspace.usemodules.rctime` for our up-to-date version
-of the application-level 'time' module.
+of the application-level 'time' module, at least for C-like targets (the C
+and LLVM backends).
diff --git a/pypy/doc/index.rst b/pypy/doc/index.rst
--- a/pypy/doc/index.rst
+++ b/pypy/doc/index.rst
@@ -67,7 +67,7 @@
 .. _Python: http://docs.python.org/index.html
 .. _`more...`: architecture.html#mission-statement 
 .. _`PyPy blog`: http://morepypy.blogspot.com/
-.. _`development bug/feature tracker`: https://codespeak.net/issue/pypy-dev/ 
+.. _`development bug/feature tracker`: https://bugs.pypy.org
 .. _here: http://tismerysoft.de/pypy/irc-logs/pypy
 .. _`Mercurial commit mailing list`: http://python.org/mailman/listinfo/pypy-commit
 .. _`development mailing list`: http://python.org/mailman/listinfo/pypy-dev
diff --git a/pypy/doc/whatsnew-head.rst b/pypy/doc/whatsnew-head.rst
--- a/pypy/doc/whatsnew-head.rst
+++ b/pypy/doc/whatsnew-head.rst
@@ -8,12 +8,27 @@
 .. branch: length-hint
 Implement __lenght_hint__ according to PEP 424
 
+.. branch: numpypy-longdouble
+Long double support for numpypy
+
+.. branch: signatures
+Improved RPython typing
+
+.. branch: rpython-bytearray
+Rudimentary support for bytearray in RPython
+
 .. branches we don't care about
 .. branch: autoreds
+.. branch: reflex-support
+.. branch: kill-faking
+.. branch: improved_ebnfparse_error
+.. branch: task-decorator
 
 .. branch: release-2.0-beta1
 
 .. branch: remove-PYPY_NOT_MAIN_FILE
 
+.. branch: missing-jit-operations
+
 .. branch: fix-lookinside-iff-oopspec
 Fixed the interaction between two internal tools for controlling the JIT.
diff --git a/pypy/jit/backend/arm/assembler.py b/pypy/jit/backend/arm/assembler.py
--- a/pypy/jit/backend/arm/assembler.py
+++ b/pypy/jit/backend/arm/assembler.py
@@ -1,5 +1,6 @@
 from __future__ import with_statement
 import os
+from pypy.jit.backend.llsupport import jitframe
 from pypy.jit.backend.arm.helper.assembler import saved_registers
 from pypy.jit.backend.arm import conditions as c
 from pypy.jit.backend.arm import registers as r
@@ -8,7 +9,7 @@
 from pypy.jit.backend.arm.codebuilder import ARMv7Builder, OverwritingBuilder
 from pypy.jit.backend.arm.locations import get_fp_offset
 from pypy.jit.backend.arm.regalloc import (Regalloc, ARMFrameManager,
-                    ARMv7RegisterManager, check_imm_arg,
+                    CoreRegisterManager, check_imm_arg,
                     operations as regalloc_operations,
                     operations_with_guard as regalloc_operations_with_guard)
 from pypy.jit.backend.llsupport.asmmemmgr import MachineDataBlockWrapper
@@ -25,12 +26,12 @@
 from pypy.rpython.lltypesystem.lloperation import llop
 from pypy.jit.backend.arm.opassembler import ResOpAssembler
 from pypy.rlib.debug import (debug_print, debug_start, debug_stop,
-                             have_debug_prints)
+                             have_debug_prints, fatalerror)
 from pypy.rlib.jit import AsmInfo
 from pypy.rlib.objectmodel import compute_unique_id
 
 # XXX Move to llsupport
-from pypy.jit.backend.x86.support import values_array, memcpy_fn
+from pypy.jit.backend.x86.support import memcpy_fn
 
 DEBUG_COUNTER = lltype.Struct('DEBUG_COUNTER', ('i', lltype.Signed),
                               ('type', lltype.Char),  # 'b'ridge, 'l'abel or
@@ -44,14 +45,8 @@
 
     debug = True
 
-    def __init__(self, cpu, failargs_limit=1000):
+    def __init__(self, cpu, translate_support_code=False):
         self.cpu = cpu
-        self.fail_boxes_int = values_array(lltype.Signed, failargs_limit)
-        self.fail_boxes_float = values_array(longlong.FLOATSTORAGE,
-                                                            failargs_limit)
-        self.fail_boxes_ptr = values_array(llmemory.GCREF, failargs_limit)
-        self.fail_boxes_count = 0
-        self.fail_force_index = 0
         self.setup_failure_recovery()
         self.mc = None
         self.memcpy_addr = 0
@@ -68,6 +63,7 @@
         self._debug = False
         self.loop_run_counters = []
         self.debug_counter_descr = cpu.fielddescrof(DEBUG_COUNTER, 'i')
+        self.force_token_to_dead_frame = {}    # XXX temporary hack
 
     def set_debug(self, v):
         r = self._debug
@@ -112,9 +108,13 @@
         gc_ll_descr.initialize()
         self._build_wb_slowpath(False)
         self._build_wb_slowpath(True)
+        self._build_failure_recovery(exc=True, withfloats=False)
+        self._build_failure_recovery(exc=False, withfloats=False)
         if self.cpu.supports_floats:
             self._build_wb_slowpath(False, withfloats=True)
             self._build_wb_slowpath(True, withfloats=True)
+            self._build_failure_recovery(exc=True, withfloats=True)
+            self._build_failure_recovery(exc=False, withfloats=True)
         self._build_propagate_exception_path()
         if gc_ll_descr.get_malloc_slowpath_addr is not None:
             self._build_malloc_slowpath()
@@ -122,10 +122,7 @@
         if gc_ll_descr.gcrootmap and gc_ll_descr.gcrootmap.is_shadow_stack:
             self._build_release_gil(gc_ll_descr.gcrootmap)
         self.memcpy_addr = self.cpu.cast_ptr_to_int(memcpy_fn)
-        self._exit_code_addr = self._gen_exit_path()
-        self._leave_jitted_hook_save_exc = \
-                                    self._gen_leave_jitted_hook_code(True)
-        self._leave_jitted_hook = self._gen_leave_jitted_hook_code(False)
+
         if not self._debug:
             # if self._debug is already set it means that someone called
             # set_debug by hand before initializing the assembler. Leave it
@@ -220,36 +217,17 @@
         self.releasegil_addr = rffi.cast(lltype.Signed, releasegil_func)
         self.reacqgil_addr = rffi.cast(lltype.Signed, reacqgil_func)
 
-    def _gen_leave_jitted_hook_code(self, save_exc):
-        mc = ARMv7Builder()
-        if self.cpu.supports_floats:
-            floats = r.caller_vfp_resp
-        else:
-            floats = []
-        with saved_registers(mc, r.caller_resp + [r.lr], floats):
-            addr = self.cpu.get_on_leave_jitted_int(save_exception=save_exc)
-            mc.BL(addr)
-        assert self._exit_code_addr != 0
-        mc.B(self._exit_code_addr)
-        return mc.materialize(self.cpu.asmmemmgr, [],
-                               self.cpu.gc_ll_descr.gcrootmap)
-
     def _build_propagate_exception_path(self):
         if self.cpu.propagate_exception_v < 0:
             return      # not supported (for tests, or non-translated)
         #
         mc = ARMv7Builder()
-        # call on_leave_jitted_save_exc()
-        if self.cpu.supports_floats:
-            floats = r.caller_vfp_resp
-        else:
-            floats = []
-        with saved_registers(mc, r.caller_resp + [r.lr], floats):
-            addr = self.cpu.get_on_leave_jitted_int(save_exception=True,
-                                                default_to_memoryerror=True)
-            mc.BL(addr)
-        mc.gen_load_int(r.ip.value, self.cpu.propagate_exception_v)
-        mc.MOV_rr(r.r0.value, r.ip.value)
+        #
+        # Call the helper, which will return a dead frame object with
+        # the correct exception set, or MemoryError by default
+        # XXX make sure we return the correct value here
+        addr = rffi.cast(lltype.Signed, self.cpu.get_propagate_exception())
+        mc.BL(addr)
         self.gen_func_epilog(mc=mc)
         self.propagate_exception_path = mc.materialize(self.cpu.asmmemmgr, [])
 
@@ -282,12 +260,12 @@
         # restore registers and return 
         # We check for c.EQ here, meaning all bits zero in this case
         mc.POP([reg.value for reg in r.argument_regs] + [r.pc.value], cond=c.EQ)
-        # call on_leave_jitted_save_exc()
-        addr = self.cpu.get_on_leave_jitted_int(save_exception=True)
+        #
+        # Call the helper, which will return a dead frame object with
+        # the correct exception set, or MemoryError by default
+        addr = rffi.cast(lltype.Signed, self.cpu.get_propagate_exception())
         mc.BL(addr)
         #
-        mc.gen_load_int(r.r0.value, self.cpu.propagate_exception_v)
-        #
         # footer -- note the ADD, which skips the return address of this
         # function, and will instead return to the caller's caller.  Note
         # also that we completely ignore the saved arguments, because we
@@ -339,39 +317,82 @@
 
     def setup_failure_recovery(self):
 
-        @rgc.no_collect
+        #@rgc.no_collect -- XXX still true, but hacked gc_set_extra_threshold
         def failure_recovery_func(mem_loc, frame_pointer, stack_pointer):
             """mem_loc is a structure in memory describing where the values for
             the failargs are stored.  frame loc is the address of the frame
             pointer for the frame to be decoded frame """
-            vfp_registers = rffi.cast(rffi.LONGLONGP, stack_pointer)
-            registers = rffi.ptradd(vfp_registers, len(r.all_vfp_regs))
+            vfp_registers = rffi.cast(rffi.LONGP, stack_pointer)
+            registers = rffi.ptradd(vfp_registers, 2*len(r.all_vfp_regs))
             registers = rffi.cast(rffi.LONGP, registers)
-            return self.decode_registers_and_descr(mem_loc, frame_pointer,
+            bytecode = rffi.cast(rffi.UCHARP, mem_loc)
+            return self.grab_frame_values(self.cpu, bytecode, frame_pointer,
                                                     registers, vfp_registers)
+        self.failure_recovery_code = [0, 0, 0, 0]
 
         self.failure_recovery_func = failure_recovery_func
 
-    recovery_func_sign = lltype.Ptr(lltype.FuncType([lltype.Signed] * 3,
-                                                        lltype.Signed))
+    _FAILURE_RECOVERY_FUNC = lltype.Ptr(lltype.FuncType([rffi.LONGP] * 3,
+                                                        llmemory.GCREF))
 
-    @rgc.no_collect
-    def decode_registers_and_descr(self, mem_loc, frame_pointer,
+    @staticmethod
+    #@rgc.no_collect -- XXX still true, but hacked gc_set_extra_threshold
+    def grab_frame_values(cpu, bytecode, frame_pointer,
                                                 registers, vfp_registers):
-        """Decode locations encoded in memory at mem_loc and write the values
-        to the failboxes.  Values for spilled vars and registers are stored on
-        stack at frame_loc """
-        assert frame_pointer & 1 == 0
-        self.fail_force_index = frame_pointer
-        bytecode = rffi.cast(rffi.UCHARP, mem_loc)
+        # no malloc allowed here!!  xxx apart from one, hacking a lot
+        force_index = rffi.cast(lltype.Signed, frame_pointer)
         num = 0
-        value = 0
-        fvalue = 0
+        deadframe = lltype.nullptr(jitframe.DEADFRAME)
+        # step 1: lots of mess just to count the final value of 'num'
+        bytecode1 = bytecode
+        while 1:
+            code = rffi.cast(lltype.Signed, bytecode1[0])
+            bytecode1 = rffi.ptradd(bytecode1, 1)
+            if code >= AssemblerARM.CODE_FROMSTACK:
+                while code > 0x7F:
+                    code = rffi.cast(lltype.Signed, bytecode1[0])
+                    bytecode1 = rffi.ptradd(bytecode1, 1)
+            else:
+                kind = code & 3
+                if kind == AssemblerARM.DESCR_SPECIAL:
+                    if code == AssemblerARM.CODE_HOLE:
+                        num += 1
+                        continue
+                    if code == AssemblerARM.CODE_INPUTARG:
+                        continue
+                    if code == AssemblerARM.CODE_FORCED:
+                        # resuming from a GUARD_NOT_FORCED
+                        token = force_index
+                        deadframe = (
+                            cpu.assembler.force_token_to_dead_frame.pop(token))
+                        deadframe = lltype.cast_opaque_ptr(
+                            jitframe.DEADFRAMEPTR, deadframe)
+                        continue
+                    assert code == AssemblerARM.CODE_STOP
+                    break
+            num += 1
+
+        # allocate the deadframe
+        if not deadframe:
+            # Remove the "reserve" at the end of the nursery.  This means
+            # that it is guaranteed that the following malloc() works
+            # without requiring a collect(), but it needs to be re-added
+            # as soon as possible.
+            cpu.gc_clear_extra_threshold()
+            assert num <= cpu.get_failargs_limit()
+            try:
+                deadframe = lltype.malloc(jitframe.DEADFRAME, num)
+            except MemoryError:
+                fatalerror("memory usage error in grab_frame_values")
+        # fill it
         code_inputarg = False
-        while True:
+        num = 0
+        value_hi = 0
+        while 1:
+            # decode the next instruction from the bytecode
             code = rffi.cast(lltype.Signed, bytecode[0])
             bytecode = rffi.ptradd(bytecode, 1)
-            if code >= self.CODE_FROMSTACK:
+            if code >= AssemblerARM.CODE_FROMSTACK:
                 if code > 0x7F:
                     shift = 7
                     code &= 0x7F
@@ -384,54 +405,63 @@
                             break
                 # load the value from the stack
                 kind = code & 3
-                code = int((code - self.CODE_FROMSTACK) >> 2)
+                code = (code - AssemblerARM.CODE_FROMSTACK) >> 2
                 if code_inputarg:
                     code = ~code
                     code_inputarg = False
-                if kind == self.DESCR_FLOAT:
-                    # we use code + 1 to get the hi word of the double worded float
-                    stackloc = frame_pointer - get_fp_offset(int(code) + 1)
-                    assert stackloc & 3 == 0
-                    fvalue = rffi.cast(rffi.LONGLONGP, stackloc)[0]
-                else:
-                    stackloc = frame_pointer - get_fp_offset(int(code))
-                    assert stackloc & 1 == 0
-                    value = rffi.cast(rffi.LONGP, stackloc)[0]
+                stackloc = force_index - get_fp_offset(int(code))
+                value = rffi.cast(rffi.LONGP, stackloc)[0]
+                if kind == AssemblerARM.DESCR_FLOAT:
+                    assert WORD == 4
+                    value_hi = value
+                    value = rffi.cast(rffi.LONGP, stackloc - WORD)[0]
             else:
-                # 'code' identifies a register: load its value
                 kind = code & 3
-                if kind == self.DESCR_SPECIAL:
-                    if code == self.CODE_HOLE:
+                if kind == AssemblerARM.DESCR_SPECIAL:
+                    if code == AssemblerARM.CODE_HOLE:
                         num += 1
                         continue
-                    if code == self.CODE_INPUTARG:
+                    if code == AssemblerARM.CODE_INPUTARG:
                         code_inputarg = True
                         continue
-                    assert code == self.CODE_STOP
+                    if code == AssemblerARM.CODE_FORCED:
+                        continue
+                    assert code == AssemblerARM.CODE_STOP
                     break
+                # 'code' identifies a register: load its value
                 code >>= 2
-                if kind == self.DESCR_FLOAT:
-                    fvalue = vfp_registers[code]
+                if kind == AssemblerARM.DESCR_FLOAT:
+                    if WORD == 4:
+                        value = vfp_registers[2*code]
+                        value_hi = vfp_registers[2*code + 1]
+                    else:
+                        value = registers[code]
                 else:
                     value = registers[code]
             # store the loaded value into fail_boxes_<type>
-            if kind == self.DESCR_FLOAT:
-                tgt = self.fail_boxes_float.get_addr_for_num(num)
-                rffi.cast(rffi.LONGLONGP, tgt)[0] = fvalue
+            if kind == AssemblerARM.DESCR_INT:
+                deadframe.jf_values[num].int = value
+            elif kind == AssemblerARM.DESCR_REF:
+                deadframe.jf_values[num].ref = rffi.cast(llmemory.GCREF, value)
+            elif kind == AssemblerARM.DESCR_FLOAT:
+                assert WORD == 4
+                assert not longlong.is_64_bit
+                floatvalue = rffi.cast(lltype.SignedLongLong, value_hi)
+                floatvalue <<= 32
+                floatvalue |= rffi.cast(lltype.SignedLongLong,
+                                        rffi.cast(lltype.Unsigned, value))
+                deadframe.jf_values[num].float = floatvalue
             else:
-                if kind == self.DESCR_INT:
-                    tgt = self.fail_boxes_int.get_addr_for_num(num)
-                elif kind == self.DESCR_REF:
-                    assert (value & 3) == 0, "misaligned pointer"
-                    tgt = self.fail_boxes_ptr.get_addr_for_num(num)
-                else:
-                    assert 0, "bogus kind"
-                rffi.cast(rffi.LONGP, tgt)[0] = value
+                assert 0, "bogus kind"
             num += 1
-        self.fail_boxes_count = num
+        #
+        assert num == len(deadframe.jf_values)
+        if not we_are_translated():
+            assert bytecode[4] == 0xCC
         fail_index = rffi.cast(rffi.INTP, bytecode)[0]
-        fail_index = rffi.cast(lltype.Signed, fail_index)
-        return fail_index
+        fail_descr = cpu.get_fail_descr_from_number(fail_index)
+        deadframe.jf_descr = fail_descr.hide(cpu)
+        return lltype.cast_opaque_ptr(llmemory.GCREF, deadframe)
 
     def decode_inputargs(self, code):
         descr_to_box_type = [REF, INT, FLOAT]
@@ -492,10 +522,10 @@
             # are stored in r0 and r1.
             mc.SUB_rr(r.r0.value, r.r1.value, r.r0.value)
             addr = self.cpu.gc_ll_descr.get_malloc_slowpath_addr()
-            for reg, ofs in ARMv7RegisterManager.REGLOC_TO_COPY_AREA_OFS.items():
+            for reg, ofs in CoreRegisterManager.REGLOC_TO_COPY_AREA_OFS.items():
                 mc.STR_ri(reg.value, r.fp.value, imm=ofs)
             mc.BL(addr)
-            for reg, ofs in ARMv7RegisterManager.REGLOC_TO_COPY_AREA_OFS.items():
+            for reg, ofs in CoreRegisterManager.REGLOC_TO_COPY_AREA_OFS.items():
                 mc.LDR_ri(reg.value, r.fp.value, imm=ofs)
 
         mc.CMP_ri(r.r0.value, 0)
@@ -514,12 +544,26 @@
         self.mc.CMP_ri(r.r0.value, 0)
         self.mc.B(self.propagate_exception_path, c=c.EQ)
 
-    def _gen_exit_path(self):
+    def _build_failure_recovery(self, exc, withfloats=False):
         mc = ARMv7Builder()
-        decode_registers_addr = llhelper(self.recovery_func_sign,
+        failure_recovery = llhelper(self._FAILURE_RECOVERY_FUNC,
                                             self.failure_recovery_func)
         self._insert_checks(mc)
-        with saved_registers(mc, r.all_regs, r.all_vfp_regs):
+        if withfloats:
+            f = r.all_vfp_regs
+        else:
+            f = []
+        with saved_registers(mc, r.all_regs, f):
+            if exc:
+                # We might have an exception pending.  Load it into r4
+                # (this is a register saved across calls)
+                mc.gen_load_int(r.r5.value, self.cpu.pos_exc_value())
+                mc.LDR_ri(r.r4.value, self.cpu.pos_exc_value())
+                # clear the exc flags
+                mc.gen_load_int(r.r6.value, 0)
+                mc.STR_ri(r.r6.value, r.r5.value)
+                mc.gen_load_int(r.r5.value, self.cpu.pos_exception())
+                mc.STR_ri(r.r6.value, r.r5.value)
             # move mem block address, to r0 to pass as
             mc.MOV_rr(r.r0.value, r.lr.value)
             # pass the current frame pointer as second param
@@ -527,23 +571,32 @@
             # pass the current stack pointer as third param
             mc.MOV_rr(r.r2.value, r.sp.value)
             self._insert_checks(mc)
-            mc.BL(rffi.cast(lltype.Signed, decode_registers_addr))
+            mc.BL(rffi.cast(lltype.Signed, failure_recovery))
+            if exc:
+                # save ebx into 'jf_guard_exc'
+                from pypy.jit.backend.llsupport.descr import unpack_fielddescr
+                descrs = self.cpu.gc_ll_descr.getframedescrs(self.cpu)
+                offset, size, _ = unpack_fielddescr(descrs.jf_guard_exc)
+                mc.STR_rr(r.r4.value, r.r0.value, offset, cond=c.AL)
             mc.MOV_rr(r.ip.value, r.r0.value)
         mc.MOV_rr(r.r0.value, r.ip.value)
         self.gen_func_epilog(mc=mc)
-        return mc.materialize(self.cpu.asmmemmgr, [],
+        rawstart = mc.materialize(self.cpu.asmmemmgr, [],
                                    self.cpu.gc_ll_descr.gcrootmap)
+        self.failure_recovery_code[exc + 2 * withfloats] = rawstart
+        self.mc = None
 
     DESCR_REF       = 0x00
     DESCR_INT       = 0x01
     DESCR_FLOAT     = 0x02
     DESCR_SPECIAL   = 0x03
     CODE_FROMSTACK  = 64
-    CODE_STOP       = 0 | DESCR_SPECIAL
-    CODE_HOLE       = 4 | DESCR_SPECIAL
-    CODE_INPUTARG   = 8 | DESCR_SPECIAL
+    CODE_STOP       = 0  | DESCR_SPECIAL
+    CODE_HOLE       = 4  | DESCR_SPECIAL
+    CODE_INPUTARG   = 8  | DESCR_SPECIAL
+    CODE_FORCED     = 12 | DESCR_SPECIAL #XXX where should this be written?
 
-    def gen_descr_encoding(self, descr, failargs, locs):
+    def write_failure_recovery_description(self, descr, failargs, locs):
         assert self.mc is not None
         for i in range(len(failargs)):
             arg = failargs[i]
@@ -575,26 +628,33 @@
             self.mc.writechar(chr(n))
         self.mc.writechar(chr(self.CODE_STOP))
 
-        fdescr = self.cpu.get_fail_descr_number(descr)
-        self.mc.write32(fdescr)
+
+    def generate_quick_failure(self, guardtok, fcond=c.AL):
+        assert isinstance(guardtok.save_exc, bool)
+        fail_index = self.cpu.get_fail_descr_number(guardtok.descr)
+        startpos = self.mc.currpos()
+        withfloats = False
+        for box in guardtok.failargs:
+            if box is not None and box.type == FLOAT:
+                withfloats = True
+                break
+        exc = guardtok.save_exc
+        target = self.failure_recovery_code[exc + 2 * withfloats]
+        assert target != 0
+        self.mc.BL(target)
+        # write tight data that describes the failure recovery
+        if guardtok.is_guard_not_forced:
+            self.mc.writechar(chr(self.CODE_FORCED))
+        self.write_failure_recovery_description(guardtok.descr,
+                                guardtok.failargs, guardtok.faillocs[1:])
+        self.mc.write32(fail_index)
+        # for testing the decoding, write a final byte 0xCC
+        if not we_are_translated():
+            self.mc.writechar('\xCC')
+            faillocs = [loc for loc in guardtok.faillocs if loc is not None]
+            guardtok.descr._arm_debug_faillocs = faillocs
         self.align()
-
-        # assert that the fail_boxes lists are big enough
-        assert len(failargs) <= self.fail_boxes_int.SIZE
-
-    def _gen_path_to_exit_path(self, descr, args, arglocs,
-                                            save_exc, fcond=c.AL):
-        assert isinstance(save_exc, bool)
-        self.gen_exit_code(self.mc, save_exc, fcond)
-        self.gen_descr_encoding(descr, args, arglocs[1:])
-
-    def gen_exit_code(self, mc, save_exc, fcond=c.AL):
-        assert isinstance(save_exc, bool)
-        if save_exc:
-            path = self._leave_jitted_hook_save_exc
-        else:
-            path = self._leave_jitted_hook
-        mc.BL(path)
+        return startpos
 
     def align(self):
         while(self.mc.currpos() % FUNC_ALIGN != 0):
@@ -841,15 +901,10 @@
 
     def write_pending_failure_recoveries(self):
         for tok in self.pending_guards:
-            descr = tok.descr
             #generate the exit stub and the encoded representation
-            pos = self.mc.currpos()
-            tok.pos_recovery_stub = pos
-
-            self._gen_path_to_exit_path(descr, tok.failargs,
-                                        tok.faillocs, save_exc=tok.save_exc)
+            tok.pos_recovery_stub = self.generate_quick_failure(tok)
             # store info on the descr
-            descr._arm_current_frame_depth = tok.faillocs[0].getint()
+            tok.descr._arm_current_frame_depth = tok.faillocs[0].getint()
 
     def process_pending_guards(self, block_start):
         clt = self.current_clt
@@ -860,7 +915,7 @@
             descr._arm_failure_recovery_block = failure_recovery_pos
             relative_offset = tok.pos_recovery_stub - tok.offset
             guard_pos = block_start + tok.offset
-            if not tok.is_invalidate:
+            if not tok.is_guard_not_invalidated:
                 # patch the guard jumpt to the stub
                 # overwrite the generate NOP with a B_offs to the pos of the
                 # stub
@@ -1255,11 +1310,6 @@
         else:
             raise AssertionError('Trying to pop to an invalid location')
 
-    def leave_jitted_hook(self):
-        ptrs = self.fail_boxes_ptr.ar
-        llop.gc_assume_young_pointers(lltype.Void,
-                                      llmemory.cast_ptr_to_adr(ptrs))
-
     def malloc_cond(self, nursery_free_adr, nursery_top_adr, size):
         assert size & (WORD-1) == 0     # must be correctly aligned
 
diff --git a/pypy/jit/backend/arm/helper/regalloc.py b/pypy/jit/backend/arm/helper/regalloc.py
--- a/pypy/jit/backend/arm/helper/regalloc.py
+++ b/pypy/jit/backend/arm/helper/regalloc.py
@@ -32,14 +32,14 @@
         imm_a0 = check_imm_box(a0, imm_size, allow_zero=allow_zero)
         imm_a1 = check_imm_box(a1, imm_size, allow_zero=allow_zero)
         if not imm_a0 and imm_a1:
-            l0 = self._ensure_value_is_boxed(a0)
+            l0 = self.make_sure_var_in_reg(a0)
             l1 = self.convert_to_imm(a1)
         elif commutative and imm_a0 and not imm_a1:
             l1 = self.convert_to_imm(a0)
-            l0 = self._ensure_value_is_boxed(a1, boxes)
+            l0 = self.make_sure_var_in_reg(a1, boxes)
         else:
-            l0 = self._ensure_value_is_boxed(a0, boxes)
-            l1 = self._ensure_value_is_boxed(a1, boxes)
+            l0 = self.make_sure_var_in_reg(a0, boxes)
+            l1 = self.make_sure_var_in_reg(a1, boxes)
         self.possibly_free_vars_for_op(op)
         self.free_temp_vars()
         res = self.force_allocate_reg(op.result, boxes)
@@ -52,10 +52,10 @@
     if guard:
         def f(self, op, guard_op, fcond):
             locs = []
-            loc1 = self._ensure_value_is_boxed(op.getarg(0))
+            loc1 = self.make_sure_var_in_reg(op.getarg(0))
             locs.append(loc1)
             if base:
-                loc2 = self._ensure_value_is_boxed(op.getarg(1))
+                loc2 = self.make_sure_var_in_reg(op.getarg(1))
                 locs.append(loc2)
             self.possibly_free_vars_for_op(op)
             self.free_temp_vars()
@@ -70,10 +70,10 @@
     else:
         def f(self, op, fcond):
             locs = []
-            loc1 = self._ensure_value_is_boxed(op.getarg(0))
+            loc1 = self.make_sure_var_in_reg(op.getarg(0))
             locs.append(loc1)
             if base:
-                loc2 = self._ensure_value_is_boxed(op.getarg(1))
+                loc2 = self.make_sure_var_in_reg(op.getarg(1))
                 locs.append(loc2)
             self.possibly_free_vars_for_op(op)
             self.free_temp_vars()
@@ -111,11 +111,11 @@
         arg0, arg1 = boxes
         imm_a1 = check_imm_box(arg1)
 
-        l0 = self._ensure_value_is_boxed(arg0, forbidden_vars=boxes)
+        l0 = self.make_sure_var_in_reg(arg0, forbidden_vars=boxes)
         if imm_a1:
             l1 = self.convert_to_imm(arg1)
         else:
-            l1 = self._ensure_value_is_boxed(arg1, forbidden_vars=boxes)
+            l1 = self.make_sure_var_in_reg(arg1, forbidden_vars=boxes)
 
         self.possibly_free_vars_for_op(op)
         self.free_temp_vars()
@@ -134,7 +134,7 @@
         assert fcond is not None
         a0 = op.getarg(0)
         assert isinstance(a0, Box)
-        reg = self._ensure_value_is_boxed(a0)
+        reg = self.make_sure_var_in_reg(a0)
         self.possibly_free_vars_for_op(op)
         if guard_op is None:
             res = self.force_allocate_reg(op.result, [a0])
diff --git a/pypy/jit/backend/arm/opassembler.py b/pypy/jit/backend/arm/opassembler.py
--- a/pypy/jit/backend/arm/opassembler.py
+++ b/pypy/jit/backend/arm/opassembler.py
@@ -16,6 +16,7 @@
                                                 gen_emit_unary_float_op,
                                                 saved_registers,
                                                 count_reg_args)
+from pypy.jit.backend.arm.helper.regalloc import check_imm_arg
 from pypy.jit.backend.arm.codebuilder import ARMv7Builder, OverwritingBuilder
 from pypy.jit.backend.arm.jump import remap_frame_layout
 from pypy.jit.backend.arm.regalloc import TempInt, TempPtr
@@ -27,18 +28,20 @@
 from pypy.jit.metainterp.history import JitCellToken, TargetToken
 from pypy.jit.metainterp.resoperation import rop
 from pypy.rlib.objectmodel import we_are_translated
-from pypy.rpython.lltypesystem import rstr
+from pypy.rlib import rgc
+from pypy.rpython.lltypesystem import rstr, rffi, lltype, llmemory
 
 NO_FORCE_INDEX = -1
 
 
 class GuardToken(object):
-    def __init__(self, descr, failargs, faillocs, offset,
-                            save_exc, fcond=c.AL, is_invalidate=False):
+    def __init__(self, descr, failargs, faillocs, offset, save_exc, fcond=c.AL,
+                 is_guard_not_invalidated=False, is_guard_not_forced=False):
         assert isinstance(save_exc, bool)
         self.descr = descr
         self.offset = offset
-        self.is_invalidate = is_invalidate
+        self.is_guard_not_invalidated = is_guard_not_invalidated
+        self.is_guard_not_forced = is_guard_not_forced
         self.failargs = failargs
         self.faillocs = faillocs
         self.save_exc = save_exc
@@ -190,7 +193,8 @@
         return fcond
 
     def _emit_guard(self, op, arglocs, fcond, save_exc,
-                                    is_guard_not_invalidated=False):
+                                    is_guard_not_invalidated=False, 
+                                    is_guard_not_forced=False):
         assert isinstance(save_exc, bool)
         assert isinstance(fcond, int)
         descr = op.getdescr()
@@ -210,7 +214,8 @@
                                     faillocs=arglocs,
                                     offset=pos,
                                     save_exc=save_exc,
-                                    is_invalidate=is_guard_not_invalidated,
+                                    is_guard_not_invalidated=is_guard_not_invalidated,
+                                    is_guard_not_forced=is_guard_not_forced,
                                     fcond=fcond))
         return c.AL
 
@@ -312,49 +317,10 @@
         return fcond
 
     def emit_op_finish(self, op, arglocs, regalloc, fcond):
-        for i in range(len(arglocs) - 1):
-            loc = arglocs[i]
-            box = op.getarg(i)
-            if loc is None:
-                continue
-            if loc.is_reg():
-                if box.type == REF:
-                    adr = self.fail_boxes_ptr.get_addr_for_num(i)
-                elif box.type == INT:
-                    adr = self.fail_boxes_int.get_addr_for_num(i)
-                else:
-                    assert 0
-                self.mc.gen_load_int(r.ip.value, adr)
-                self.mc.STR_ri(loc.value, r.ip.value)
-            elif loc.is_vfp_reg():
-                assert box.type == FLOAT
-                adr = self.fail_boxes_float.get_addr_for_num(i)
-                self.mc.gen_load_int(r.ip.value, adr)
-                self.mc.VSTR(loc.value, r.ip.value)
-            elif loc.is_stack() or loc.is_imm() or loc.is_imm_float():
-                if box.type == FLOAT:
-                    adr = self.fail_boxes_float.get_addr_for_num(i)
-                    self.mov_loc_loc(loc, r.vfp_ip)
-                    self.mc.gen_load_int(r.ip.value, adr)
-                    self.mc.VSTR(r.vfp_ip.value, r.ip.value)
-                elif box.type == REF or box.type == INT:
-                    if box.type == REF:
-                        adr = self.fail_boxes_ptr.get_addr_for_num(i)
-                    elif box.type == INT:
-                        adr = self.fail_boxes_int.get_addr_for_num(i)
-                    else:
-                        assert 0
-                    self.mov_loc_loc(loc, r.ip)
-                    self.mc.gen_load_int(r.lr.value, adr)
-                    self.mc.STR_ri(r.ip.value, r.lr.value)
-            else:
-                assert 0
-        # note: no exception should currently be set in llop.get_exception_addr
-        # even if this finish may be an exit_frame_with_exception (in this case
-        # the exception instance is in arglocs[0]).
-        addr = self.cpu.get_on_leave_jitted_int(save_exception=False)
-        self.mc.BL(addr)
-        self.mc.gen_load_int(r.r0.value, arglocs[-1].value)
+        [argloc] = arglocs
+        if argloc is not r.r0: #XXX verify this
+            self.mov_loc_loc(argloc, r.r0, fcond)
+        # exit function
         self.gen_func_epilog()
         return fcond
 
@@ -988,8 +954,8 @@
     def _emit_copystrcontent(self, op, regalloc, fcond, is_unicode):
         # compute the source address
         args = op.getarglist()
-        base_loc = regalloc._ensure_value_is_boxed(args[0], args)
-        ofs_loc = regalloc._ensure_value_is_boxed(args[2], args)
+        base_loc = regalloc.make_sure_var_in_reg(args[0], args)
+        ofs_loc = regalloc.make_sure_var_in_reg(args[2], args)
         assert args[0] is not args[1]    # forbidden case of aliasing
         regalloc.possibly_free_var(args[0])
         regalloc.free_temp_vars()
@@ -1009,8 +975,8 @@
         dstaddr_loc = regalloc.force_allocate_reg(dstaddr_box,
                                                         selected_reg=r.r0)
         forbidden_vars.append(dstaddr_box)
-        base_loc = regalloc._ensure_value_is_boxed(args[1], forbidden_vars)
-        ofs_loc = regalloc._ensure_value_is_boxed(args[3], forbidden_vars)
+        base_loc = regalloc.make_sure_var_in_reg(args[1], forbidden_vars)
+        ofs_loc = regalloc.make_sure_var_in_reg(args[3], forbidden_vars)
         assert base_loc.is_reg()
         assert ofs_loc.is_reg()
         regalloc.possibly_free_var(args[1])
@@ -1026,7 +992,7 @@
         # need the box here
         if isinstance(args[4], Box):
             length_box = args[4]
-            length_loc = regalloc._ensure_value_is_boxed(args[4],
+            length_loc = regalloc.make_sure_var_in_reg(args[4],
                                                         forbidden_vars)
         else:
             length_box = TempInt()
@@ -1152,8 +1118,26 @@
                 value = self.cpu.done_with_this_frame_float_v
             else:
                 raise AssertionError(kind)
-        self.mc.gen_load_int(r.ip.value, value)
-        self.mc.CMP_rr(tmploc.value, r.ip.value)
+        from pypy.jit.backend.llsupport.descr import unpack_fielddescr
+        from pypy.jit.backend.llsupport.descr import unpack_interiorfielddescr
+        descrs = self.cpu.gc_ll_descr.getframedescrs(self.cpu)
+        _offset, _size, _ = unpack_fielddescr(descrs.jf_descr)
+        fail_descr = self.cpu.get_fail_descr_from_number(value)
+        value = fail_descr.hide(self.cpu)
+        rgc._make_sure_does_not_move(value)
+        value = rffi.cast(lltype.Signed, value)
+
+        if check_imm_arg(_offset):
+            self.mc.LDR_ri(r.ip.value, tmploc.value, imm=_offset)
+        else:
+            self.mc.gen_load_int(r.ip.value, _offset)
+            self.mc.LDR_rr(r.ip.value, tmploc.value, r.ip.value)
+        if check_imm_arg(value):
+            self.mc.CMP_ri(r.ip.value, imm=value)
+        else:
+            self.mc.gen_load_int(r.lr.value, value)
+            self.mc.CMP_rr(r.lr.value, r.ip.value)
+
 
         #if values are equal we take the fast path
         # Slow path, calling helper
@@ -1180,19 +1164,31 @@
         if op.result is not None:
             # load the return value from fail_boxes_xxx[0]
             kind = op.result.type
-            if kind == INT:
-                adr = self.fail_boxes_int.get_addr_for_num(0)
-            elif kind == REF:
-                adr = self.fail_boxes_ptr.get_addr_for_num(0)
-            elif kind == FLOAT:
-                adr = self.fail_boxes_float.get_addr_for_num(0)
+            if kind == FLOAT:
+                t = unpack_interiorfielddescr(descrs.as_float)[0]
+                if not check_imm_arg(t):
+                    self.mc.gen_load_int(r.ip.value, t, cond=fast_path_cond)
+                    self.mc.ADD_rr(r.ip.value, r.r0.value, r.ip.value,
+                                          cond=fast_path_cond)
+                    t = 0
+                    base = r.ip
+                else:
+                    base = r.r0
+                self.mc.VLDR(resloc.value, base.value, imm=t,
+                                          cond=fast_path_cond)
             else:
-                raise AssertionError(kind)
-            self.mc.gen_load_int(r.ip.value, adr, cond=fast_path_cond)
-            if op.result.type == FLOAT:
-                self.mc.VLDR(resloc.value, r.ip.value, cond=fast_path_cond)
-            else:
-                self.mc.LDR_ri(resloc.value, r.ip.value, cond=fast_path_cond)
+                assert resloc is r.r0
+                if kind == INT:
+                    t = unpack_interiorfielddescr(descrs.as_int)[0]
+                else:
+                    t = unpack_interiorfielddescr(descrs.as_ref)[0]
+                if not check_imm_arg(t):
+                    self.mc.gen_load_int(r.ip.value, t, cond=fast_path_cond)
+                    self.mc.LDR_rr(resloc.value, resloc.value, r.ip.value,
+                                          cond=fast_path_cond)
+                else:
+                    self.mc.LDR_ri(resloc.value, resloc.value, imm=t,
+                                          cond=fast_path_cond)
         # jump to merge point
         jmp_pos = self.mc.currpos()
         self.mc.BKPT()
@@ -1266,7 +1262,8 @@
 
         self.mc.LDR_ri(r.ip.value, r.fp.value)
         self.mc.CMP_ri(r.ip.value, 0)
-        self._emit_guard(guard_op, arglocs[1 + numargs:], c.GE, save_exc=True)
+        self._emit_guard(guard_op, arglocs[1 + numargs:], c.GE,
+                                   save_exc=True, is_guard_not_forced=True)
         return fcond
 
     def emit_guard_call_release_gil(self, op, guard_op, arglocs, regalloc,
diff --git a/pypy/jit/backend/arm/regalloc.py b/pypy/jit/backend/arm/regalloc.py
--- a/pypy/jit/backend/arm/regalloc.py
+++ b/pypy/jit/backend/arm/regalloc.py
@@ -84,8 +84,28 @@
 def void(self, op, fcond):
     return []
 
+class ARMRegisterManager(RegisterManager):
+    def return_constant(self, v, forbidden_vars=[], selected_reg=None):
+        self._check_type(v)
+        if isinstance(v, Const):
+            if isinstance(v, ConstPtr):
+                tp = REF
+            elif isinstance(v, ConstFloat):
+                tp = FLOAT
+            else:
+                tp = INT
+            loc = self.get_scratch_reg(tp,
+                    self.temp_boxes + forbidden_vars,
+                    selected_reg=selected_reg)
+            immvalue = self.convert_to_imm(v)
+            self.assembler.load(loc, immvalue)
+            return loc
+        else:
+            return RegisterManager.return_constant(self, v,
+                                    forbidden_vars, selected_reg)
 
-class VFPRegisterManager(RegisterManager):
+
+class VFPRegisterManager(ARMRegisterManager):
     all_regs = r.all_vfp_regs
     box_types = [FLOAT]
     save_around_call_regs = r.all_vfp_regs
@@ -107,20 +127,7 @@
         reg = self.force_allocate_reg(v, selected_reg=r.d0)
         return reg
 
-    def ensure_value_is_boxed(self, thing, forbidden_vars=[]):
-        loc = None
-        if isinstance(thing, Const):
-            assert isinstance(thing, ConstFloat)
-            loc = self.get_scratch_reg(FLOAT, self.temp_boxes + forbidden_vars)
-            immvalue = self.convert_to_imm(thing)
-            self.assembler.load(loc, immvalue)
-        else:
-            loc = self.make_sure_var_in_reg(thing,
-                            forbidden_vars=self.temp_boxes + forbidden_vars)
-        return loc
-
-    def get_scratch_reg(self, type=FLOAT, forbidden_vars=[],
-                                                        selected_reg=None):
+    def get_scratch_reg(self, type=FLOAT, forbidden_vars=[], selected_reg=None):
         assert type == FLOAT  # for now
         box = TempFloat()
         self.temp_boxes.append(box)
@@ -129,7 +136,7 @@
         return reg
 
 
-class ARMv7RegisterManager(RegisterManager):
+class CoreRegisterManager(ARMRegisterManager):
     all_regs = r.all_regs
     box_types = None       # or a list of acceptable types
     no_lower_byte_regs = all_regs
@@ -162,22 +169,6 @@
             return locations.ImmLocation(rffi.cast(lltype.Signed, c.value))
         assert 0
 
-    def ensure_value_is_boxed(self, thing, forbidden_vars=None):
-        loc = None
-        if isinstance(thing, Const):
-            if isinstance(thing, ConstPtr):
-                tp = REF
-            else:
-                tp = INT
-            loc = self.get_scratch_reg(tp, forbidden_vars=self.temp_boxes
-                                                            + forbidden_vars)
-            immvalue = self.convert_to_imm(thing)
-            self.assembler.load(loc, immvalue)
-        else:
-            loc = self.make_sure_var_in_reg(thing,
-                            forbidden_vars=self.temp_boxes + forbidden_vars)
-        return loc
-
     def get_scratch_reg(self, type=INT, forbidden_vars=[], selected_reg=None):
         assert type == INT or type == REF
         box = TempBox()
@@ -277,7 +268,12 @@
 
     def make_sure_var_in_reg(self, var, forbidden_vars=[],
                          selected_reg=None, need_lower_byte=False):
-        assert 0, 'should not be called directly'
+        if var.type == FLOAT:
+            return self.vfprm.make_sure_var_in_reg(var, forbidden_vars,
+                                        selected_reg, need_lower_byte)
+        else:
+            return self.rm.make_sure_var_in_reg(var, forbidden_vars,
+                                        selected_reg, need_lower_byte)
 
     def convert_to_imm(self, value):
         if isinstance(value, ConstInt):
@@ -294,7 +290,7 @@
         fm = self.frame_manager
         asm = self.assembler
         self.vfprm = VFPRegisterManager(longevity, fm, asm)
-        self.rm = ARMv7RegisterManager(longevity, fm, asm)
+        self.rm = CoreRegisterManager(longevity, fm, asm)
 
     def prepare_loop(self, inputargs, operations):
         self._prepare(inputargs, operations)
@@ -426,12 +422,6 @@
         self.rm.before_call(force_store, save_all_regs)
         self.vfprm.before_call(force_store, save_all_regs)
 
-    def _ensure_value_is_boxed(self, thing, forbidden_vars=[]):
-        if thing.type == FLOAT:
-            return self.vfprm.ensure_value_is_boxed(thing, forbidden_vars)
-        else:
-            return self.rm.ensure_value_is_boxed(thing, forbidden_vars)
-
     def _sync_var(self, v):
         if v.type == FLOAT:
             self.vfprm._sync_var(v)
@@ -444,14 +434,14 @@
         imm_a0 = check_imm_box(a0)
         imm_a1 = check_imm_box(a1)
         if not imm_a0 and imm_a1:
-            l0 = self._ensure_value_is_boxed(a0, boxes)
+            l0 = self.make_sure_var_in_reg(a0, boxes)
             l1 = self.convert_to_imm(a1)
         elif imm_a0 and not imm_a1:
             l0 = self.convert_to_imm(a0)
-            l1 = self._ensure_value_is_boxed(a1, boxes)
+            l1 = self.make_sure_var_in_reg(a1, boxes)
         else:
-            l0 = self._ensure_value_is_boxed(a0, boxes)
-            l1 = self._ensure_value_is_boxed(a1, boxes)
+            l0 = self.make_sure_var_in_reg(a0, boxes)
+            l1 = self.make_sure_var_in_reg(a1, boxes)
         return [l0, l1]
 
     def prepare_op_int_add(self, op, fcond):
@@ -466,14 +456,14 @@
         imm_a0 = check_imm_box(a0)
         imm_a1 = check_imm_box(a1)
         if not imm_a0 and imm_a1:
-            l0 = self._ensure_value_is_boxed(a0, boxes)
+            l0 = self.make_sure_var_in_reg(a0, boxes)
             l1 = self.convert_to_imm(a1)
         elif imm_a0 and not imm_a1:
             l0 = self.convert_to_imm(a0)
-            l1 = self._ensure_value_is_boxed(a1, boxes)
+            l1 = self.make_sure_var_in_reg(a1, boxes)
         else:
-            l0 = self._ensure_value_is_boxed(a0, boxes)
-            l1 = self._ensure_value_is_boxed(a1, boxes)
+            l0 = self.make_sure_var_in_reg(a0, boxes)
+            l1 = self.make_sure_var_in_reg(a1, boxes)
         return [l0, l1]
 
     def prepare_op_int_sub(self, op, fcond):
@@ -487,8 +477,8 @@
         boxes = op.getarglist()
         a0, a1 = boxes
 
-        reg1 = self._ensure_value_is_boxed(a0, forbidden_vars=boxes)
-        reg2 = self._ensure_value_is_boxed(a1, forbidden_vars=boxes)
+        reg1 = self.make_sure_var_in_reg(a0, forbidden_vars=boxes)
+        reg2 = self.make_sure_var_in_reg(a1, forbidden_vars=boxes)
 
         self.possibly_free_vars(boxes)
         self.possibly_free_vars_for_op(op)
@@ -497,14 +487,14 @@
         return [reg1, reg2, res]
     
     def prepare_op_int_force_ge_zero(self, op, fcond):
-        argloc = self._ensure_value_is_boxed(op.getarg(0))
+        argloc = self.make_sure_var_in_reg(op.getarg(0))
         resloc = self.force_allocate_reg(op.result, [op.getarg(0)])
         return [argloc, resloc]
 
     def prepare_guard_int_mul_ovf(self, op, guard, fcond):
         boxes = op.getarglist()
-        reg1 = self._ensure_value_is_boxed(boxes[0], forbidden_vars=boxes)
-        reg2 = self._ensure_value_is_boxed(boxes[1], forbidden_vars=boxes)
+        reg1 = self.make_sure_var_in_reg(boxes[0], forbidden_vars=boxes)
+        reg2 = self.make_sure_var_in_reg(boxes[1], forbidden_vars=boxes)
         res = self.force_allocate_reg(op.result)
         return self._prepare_guard(guard, [reg1, reg2, res])
 
@@ -576,7 +566,7 @@
     prepare_guard_int_is_zero = prepare_op_unary_cmp('int_is_zero')
 
     def prepare_op_int_neg(self, op, fcond):
-        l0 = self._ensure_value_is_boxed(op.getarg(0))
+        l0 = self.make_sure_var_in_reg(op.getarg(0))
         self.possibly_free_vars_for_op(op)
         self.free_temp_vars()
         resloc = self.force_allocate_reg(op.result)
@@ -629,15 +619,15 @@
 
     def _prepare_llong_binop_xx(self, op, fcond):
         # arg 0 is the address of the function
-        loc0 = self._ensure_value_is_boxed(op.getarg(1))
-        loc1 = self._ensure_value_is_boxed(op.getarg(2))
+        loc0 = self.make_sure_var_in_reg(op.getarg(1))
+        loc1 = self.make_sure_var_in_reg(op.getarg(2))
         self.possibly_free_vars_for_op(op)
         self.free_temp_vars()
         res = self.vfprm.force_allocate_reg(op.result)
         return [loc0, loc1, res]
 
     def _prepare_llong_to_int(self, op, fcond):
-        loc0 = self._ensure_value_is_boxed(op.getarg(1))
+        loc0 = self.make_sure_var_in_reg(op.getarg(1))
         res = self.force_allocate_reg(op.result)
         return [loc0, res]
 
@@ -654,18 +644,12 @@
         return args
 
     def prepare_op_finish(self, op, fcond):
-        args = [None] * (op.numargs() + 1)
-        for i in range(op.numargs()):
-            arg = op.getarg(i)
-            if arg:
-                args[i] = self.loc(arg)
-                self.possibly_free_var(arg)
-        n = self.cpu.get_fail_descr_number(op.getdescr())
-        args[-1] = imm(n)
-        return args
+        loc = self.loc(op.getarg(0))
+        self.possibly_free_var(op.getarg(0))
+        return [loc]
 
     def prepare_op_guard_true(self, op, fcond):
-        l0 = self._ensure_value_is_boxed(op.getarg(0))
+        l0 = self.make_sure_var_in_reg(op.getarg(0))
         args = self._prepare_guard(op, [l0])
         return args
 
@@ -677,9 +661,9 @@
         boxes = op.getarglist()
         a0, a1 = boxes
         imm_a1 = check_imm_box(a1)
-        l0 = self._ensure_value_is_boxed(a0, boxes)
+        l0 = self.make_sure_var_in_reg(a0, boxes)
         if not imm_a1:
-            l1 = self._ensure_value_is_boxed(a1, boxes)
+            l1 = self.make_sure_var_in_reg(a1, boxes)
         else:
             l1 = self.convert_to_imm(a1)
         assert op.result is None
@@ -699,7 +683,7 @@
     def prepare_op_guard_exception(self, op, fcond):
         boxes = op.getarglist()
         arg0 = ConstInt(rffi.cast(lltype.Signed, op.getarg(0).getint()))
-        loc = self._ensure_value_is_boxed(arg0)
+        loc = self.make_sure_var_in_reg(arg0)
         loc1 = self.get_scratch_reg(INT, boxes)
         if op.result in self.longevity:
             resloc = self.force_allocate_reg(op.result, boxes)
@@ -713,7 +697,7 @@
         return arglocs
 
     def prepare_op_guard_no_exception(self, op, fcond):
-        loc = self._ensure_value_is_boxed(
+        loc = self.make_sure_var_in_reg(
                     ConstInt(self.cpu.pos_exception()))
         arglocs = self._prepare_guard(op, [loc])
         return arglocs
@@ -727,7 +711,7 @@
         assert isinstance(op.getarg(0), Box)
         boxes = op.getarglist()
 
-        x = self._ensure_value_is_boxed(boxes[0], boxes)
+        x = self.make_sure_var_in_reg(boxes[0], boxes)
         y_val = rffi.cast(lltype.Signed, op.getarg(1).getint())
 
         arglocs = [x, None, None]
@@ -837,8 +821,8 @@
         boxes = op.getarglist()
         a0, a1 = boxes
         ofs, size, sign = unpack_fielddescr(op.getdescr())
-        base_loc = self._ensure_value_is_boxed(a0, boxes)
-        value_loc = self._ensure_value_is_boxed(a1, boxes)
+        base_loc = self.make_sure_var_in_reg(a0, boxes)
+        value_loc = self.make_sure_var_in_reg(a1, boxes)
         if check_imm_arg(ofs):
             ofs_loc = imm(ofs)
         else:
@@ -851,7 +835,7 @@
     def prepare_op_getfield_gc(self, op, fcond):
         a0 = op.getarg(0)
         ofs, size, sign = unpack_fielddescr(op.getdescr())
-        base_loc = self._ensure_value_is_boxed(a0)
+        base_loc = self.make_sure_var_in_reg(a0)
         immofs = imm(ofs)
         if check_imm_arg(ofs):
             ofs_loc = immofs
@@ -871,8 +855,8 @@
         t = unpack_interiorfielddescr(op.getdescr())
         ofs, itemsize, fieldsize, sign = t
         args = op.getarglist()
-        base_loc = self._ensure_value_is_boxed(op.getarg(0), args)
-        index_loc = self._ensure_value_is_boxed(op.getarg(1), args)
+        base_loc = self.make_sure_var_in_reg(op.getarg(0), args)
+        index_loc = self.make_sure_var_in_reg(op.getarg(1), args)
         immofs = imm(ofs)
         if check_imm_arg(ofs):
             ofs_loc = immofs
@@ -889,9 +873,9 @@
         t = unpack_interiorfielddescr(op.getdescr())
         ofs, itemsize, fieldsize, sign = t
         args = op.getarglist()
-        base_loc = self._ensure_value_is_boxed(op.getarg(0), args)
-        index_loc = self._ensure_value_is_boxed(op.getarg(1), args)
-        value_loc = self._ensure_value_is_boxed(op.getarg(2), args)
+        base_loc = self.make_sure_var_in_reg(op.getarg(0), args)
+        index_loc = self.make_sure_var_in_reg(op.getarg(1), args)
+        value_loc = self.make_sure_var_in_reg(op.getarg(2), args)
         immofs = imm(ofs)
         if check_imm_arg(ofs):
             ofs_loc = immofs
@@ -907,7 +891,7 @@
         assert isinstance(arraydescr, ArrayDescr)
         ofs = arraydescr.lendescr.offset
         arg = op.getarg(0)
-        base_loc = self._ensure_value_is_boxed(arg)
+        base_loc = self.make_sure_var_in_reg(arg)
         self.possibly_free_vars_for_op(op)
         self.free_temp_vars()
         res = self.force_allocate_reg(op.result)
@@ -917,9 +901,9 @@
         size, ofs, _ = unpack_arraydescr(op.getdescr())
         scale = get_scale(size)
         args = op.getarglist()
-        base_loc = self._ensure_value_is_boxed(args[0], args)
-        ofs_loc = self._ensure_value_is_boxed(args[1], args)
-        value_loc = self._ensure_value_is_boxed(args[2], args)
+        base_loc = self.make_sure_var_in_reg(args[0], args)
+        ofs_loc = self.make_sure_var_in_reg(args[1], args)
+        value_loc = self.make_sure_var_in_reg(args[2], args)
         assert check_imm_arg(ofs)
         return [value_loc, base_loc, ofs_loc, imm(scale), imm(ofs)]
     prepare_op_setarrayitem_raw = prepare_op_setarrayitem_gc
@@ -929,8 +913,8 @@
         boxes = op.getarglist()
         size, ofs, _ = unpack_arraydescr(op.getdescr())
         scale = get_scale(size)
-        base_loc = self._ensure_value_is_boxed(boxes[0], boxes)
-        ofs_loc = self._ensure_value_is_boxed(boxes[1], boxes)
+        base_loc = self.make_sure_var_in_reg(boxes[0], boxes)
+        ofs_loc = self.make_sure_var_in_reg(boxes[1], boxes)
         self.possibly_free_vars_for_op(op)
         self.free_temp_vars()
         res = self.force_allocate_reg(op.result)
@@ -944,7 +928,7 @@
 
     def prepare_op_strlen(self, op, fcond):
         args = op.getarglist()
-        l0 = self._ensure_value_is_boxed(op.getarg(0))
+        l0 = self.make_sure_var_in_reg(op.getarg(0))
         basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR,
                                          self.cpu.translate_support_code)
         immofs = imm(ofs_length)
@@ -963,14 +947,14 @@
 
     def prepare_op_strgetitem(self, op, fcond):
         boxes = op.getarglist()
-        base_loc = self._ensure_value_is_boxed(boxes[0])
+        base_loc = self.make_sure_var_in_reg(boxes[0])
 
         a1 = boxes[1]
         imm_a1 = check_imm_box(a1)
         if imm_a1:
             ofs_loc = self.convert_to_imm(a1)
         else:
-            ofs_loc = self._ensure_value_is_boxed(a1, boxes)
+            ofs_loc = self.make_sure_var_in_reg(a1, boxes)
 
         self.possibly_free_vars_for_op(op)
         self.free_temp_vars()
@@ -983,9 +967,9 @@
 
     def prepare_op_strsetitem(self, op, fcond):
         boxes = op.getarglist()
-        base_loc = self._ensure_value_is_boxed(boxes[0], boxes)
-        ofs_loc = self._ensure_value_is_boxed(boxes[1], boxes)
-        value_loc = self._ensure_value_is_boxed(boxes[2], boxes)
+        base_loc = self.make_sure_var_in_reg(boxes[0], boxes)
+        ofs_loc = self.make_sure_var_in_reg(boxes[1], boxes)
+        value_loc = self.make_sure_var_in_reg(boxes[2], boxes)
         basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.STR,
                                          self.cpu.translate_support_code)
         assert itemsize == 1
@@ -995,7 +979,7 @@
     prepare_op_copyunicodecontent = void
 
     def prepare_op_unicodelen(self, op, fcond):
-        l0 = self._ensure_value_is_boxed(op.getarg(0))
+        l0 = self.make_sure_var_in_reg(op.getarg(0))
         basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE,
                                          self.cpu.translate_support_code)
         immofs = imm(ofs_length)
@@ -1012,8 +996,8 @@
 
     def prepare_op_unicodegetitem(self, op, fcond):
         boxes = op.getarglist()
-        base_loc = self._ensure_value_is_boxed(boxes[0], boxes)
-        ofs_loc = self._ensure_value_is_boxed(boxes[1], boxes)
+        base_loc = self.make_sure_var_in_reg(boxes[0], boxes)
+        ofs_loc = self.make_sure_var_in_reg(boxes[1], boxes)
 
         self.possibly_free_vars_for_op(op)
         self.free_temp_vars()
@@ -1027,9 +1011,9 @@
 
     def prepare_op_unicodesetitem(self, op, fcond):
         boxes = op.getarglist()
-        base_loc = self._ensure_value_is_boxed(boxes[0], boxes)
-        ofs_loc = self._ensure_value_is_boxed(boxes[1], boxes)
-        value_loc = self._ensure_value_is_boxed(boxes[2], boxes)
+        base_loc = self.make_sure_var_in_reg(boxes[0], boxes)
+        ofs_loc = self.make_sure_var_in_reg(boxes[1], boxes)
+        value_loc = self.make_sure_var_in_reg(boxes[2], boxes)
         basesize, itemsize, ofs_length = symbolic.get_array_token(rstr.UNICODE,
                                          self.cpu.translate_support_code)
         scale = itemsize / 2
@@ -1042,7 +1026,7 @@
         if imm_arg:
             argloc = self.convert_to_imm(arg)
         else:
-            argloc = self._ensure_value_is_boxed(arg)
+            argloc = self.make_sure_var_in_reg(arg)
         self.possibly_free_vars_for_op(op)
         self.free_temp_vars()
         resloc = self.force_allocate_reg(op.result)
@@ -1093,7 +1077,7 @@
         # twice from the memory.
         N = op.numargs()
         args = op.getarglist()
-        arglocs = [self._ensure_value_is_boxed(op.getarg(i), args)
+        arglocs = [self.make_sure_var_in_reg(op.getarg(i), args)
                                                               for i in range(N)]
         tmp = self.get_scratch_reg(INT, args)
         assert tmp not in arglocs
@@ -1215,7 +1199,7 @@
                             float_result=False, name='prepare_guard_float_ge')
 
     def prepare_op_math_sqrt(self, op, fcond):
-        loc = self._ensure_value_is_boxed(op.getarg(1))
+        loc = self.make_sure_var_in_reg(op.getarg(1))
         self.possibly_free_vars_for_op(op)
         self.free_temp_vars()
         res = self.vfprm.force_allocate_reg(op.result)
@@ -1223,12 +1207,12 @@
         return [loc, res]
 
     def prepare_op_cast_float_to_int(self, op, fcond):
-        loc1 = self._ensure_value_is_boxed(op.getarg(0))
+        loc1 = self.make_sure_var_in_reg(op.getarg(0))
         res = self.rm.force_allocate_reg(op.result)
         return [loc1, res]
 
     def prepare_op_cast_int_to_float(self, op, fcond):
-        loc1 = self._ensure_value_is_boxed(op.getarg(0))
+        loc1 = self.make_sure_var_in_reg(op.getarg(0))
         res = self.vfprm.force_allocate_reg(op.result)
         return [loc1, res]
 
@@ -1247,12 +1231,12 @@
         return [loc, res]
 
     def prepare_op_cast_float_to_singlefloat(self, op, fcond):
-        loc1 = self._ensure_value_is_boxed(op.getarg(0))
+        loc1 = self.make_sure_var_in_reg(op.getarg(0))
         res = self.force_allocate_reg(op.result)
         return [loc1, res]
-    
+
     def prepare_op_cast_singlefloat_to_float(self, op, fcond):
-        loc1 = self._ensure_value_is_boxed(op.getarg(0))
+        loc1 = self.make_sure_var_in_reg(op.getarg(0))
         res = self.force_allocate_reg(op.result)
         return [loc1, res]
 
diff --git a/pypy/jit/backend/arm/runner.py b/pypy/jit/backend/arm/runner.py
--- a/pypy/jit/backend/arm/runner.py
+++ b/pypy/jit/backend/arm/runner.py
@@ -23,15 +23,21 @@
         AbstractLLCPU.__init__(self, rtyper, stats, opts,
                                translate_support_code, gcdescr)
 
+        from pypy.jit.backend.llsupport import jitframe
+        self.deadframe_size_max = llmemory.sizeof(jitframe.DEADFRAME,
+                                                  self.get_failargs_limit())
+
     def set_debug(self, flag):
         return self.assembler.set_debug(flag)
 
+    def get_failargs_limit(self):
+        if self.opts is not None:
+            return self.opts.failargs_limit
+        else:
+            return 1000
+
     def setup(self):
-        if self.opts is not None:
-            failargs_limit = self.opts.failargs_limit
-        else:
-            failargs_limit = 1000
-        self.assembler = AssemblerARM(self, failargs_limit=failargs_limit)
+        self.assembler = AssemblerARM(self, self.translate_support_code)
 
     def setup_once(self):
         self.assembler.setup_once()
@@ -51,24 +57,6 @@
         return self.assembler.assemble_bridge(faildescr, inputargs, operations,
                                                 original_loop_token, log=log)
 
-    def get_latest_value_float(self, index):
-        return self.assembler.fail_boxes_float.getitem(index)
-
-    def get_latest_value_int(self, index):
-        return self.assembler.fail_boxes_int.getitem(index)
-
-    def get_latest_value_ref(self, index):
-        return self.assembler.fail_boxes_ptr.getitem(index)
-
-    def get_latest_value_count(self):
-        return self.assembler.fail_boxes_count
-
-    def get_latest_force_token(self):
-        return self.assembler.fail_force_index
-
-    def get_on_leave_jitted_hook(self):
-        return self.assembler.leave_jitted_hook
-
     def clear_latest_values(self, count):
         setitem = self.assembler.fail_boxes_ptr.setitem
         null = lltype.nullptr(llmemory.GCREF.TO)
@@ -76,7 +64,7 @@
             setitem(index, null)
 
     def make_execute_token(self, *ARGS):
-        FUNCPTR = lltype.Ptr(lltype.FuncType(ARGS, lltype.Signed))
+        FUNCPTR = lltype.Ptr(lltype.FuncType(ARGS, llmemory.GCREF))
 
         def execute_token(executable_token, *args):
             clt = executable_token.compiled_loop_token
@@ -91,12 +79,13 @@
                 prev_interpreter = LLInterpreter.current_interpreter
                 LLInterpreter.current_interpreter = self.debug_ll_interpreter
             try:
-                fail_index = func(*args)
+                deadframe = 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)
+            self.gc_set_extra_threshold()
+            return deadframe
         return execute_token
 
     def cast_ptr_to_int(x):
@@ -115,17 +104,22 @@
         assert fail_index >= 0, "already forced!"
         faildescr = self.get_fail_descr_from_number(fail_index)
         rffi.cast(TP, addr_of_force_index)[0] = ~fail_index
-        bytecode = self.assembler._find_failure_recovery_bytecode(faildescr)
+        frb = self.assembler._find_failure_recovery_bytecode(faildescr)
+        bytecode = rffi.cast(rffi.UCHARP, frb)
         addr_all_null_regsiters = rffi.cast(rffi.LONG, self.all_null_registers)
-        # start of "no gc operation!" block
-        fail_index_2 = self.assembler.failure_recovery_func(
-            bytecode,
-            addr_of_force_index,
-            addr_all_null_regsiters)
-        self.assembler.leave_jitted_hook()
-        # end of "no gc operation!" block
-        assert fail_index == fail_index_2
-        return faildescr
+        #
+        assert (rffi.cast(lltype.Signed, bytecode[0]) ==
+                self.assembler.CODE_FORCED)
+        bytecode = rffi.ptradd(bytecode, 1)
+        deadframe = self.assembler.grab_frame_values(self,
+                        bytecode, addr_of_force_index,
+                        self.all_null_registers,
+                        self.all_null_registers)
+        #
+        assert self.get_latest_descr(deadframe) is faildescr
+        self.assembler.force_token_to_dead_frame[addr_of_force_index] = (
+            deadframe)
+        return deadframe
 
     def redirect_call_assembler(self, oldlooptoken, newlooptoken):
         self.assembler.redirect_call_assembler(oldlooptoken, newlooptoken)
diff --git a/pypy/jit/backend/arm/test/test_gc_integration.py b/pypy/jit/backend/arm/test/test_gc_integration.py
--- a/pypy/jit/backend/arm/test/test_gc_integration.py
+++ b/pypy/jit/backend/arm/test/test_gc_integration.py
@@ -20,7 +20,7 @@
 from pypy.jit.backend.arm.test.test_regalloc import BaseTestRegalloc
 from pypy.jit.backend.arm.regalloc import ARMFrameManager, VFPRegisterManager
 from pypy.jit.codewriter.effectinfo import EffectInfo
-from pypy.jit.backend.arm.regalloc import Regalloc, ARMv7RegisterManager
+from pypy.jit.backend.arm.regalloc import Regalloc
 
 CPU = getcpuclass()
 
diff --git a/pypy/jit/backend/arm/test/test_loop_unroll.py b/pypy/jit/backend/arm/test/test_loop_unroll.py
--- a/pypy/jit/backend/arm/test/test_loop_unroll.py
+++ b/pypy/jit/backend/arm/test/test_loop_unroll.py
@@ -1,8 +1,8 @@
 import py
-from pypy.jit.backend.x86.test.test_basic import Jit386Mixin
+from pypy.jit.backend.arm.test.support import JitARMMixin
 from pypy.jit.metainterp.test import test_loop_unroll
 
-class TestLoopSpec(Jit386Mixin, test_loop_unroll.LoopUnrollTest):
+class TestLoopSpec(JitARMMixin, test_loop_unroll.LoopUnrollTest):
     # for the individual tests see
     # ====> ../../../metainterp/test/test_loop.py


More information about the pypy-commit mailing list