[pypy-commit] pypy numpypy-real-as-view: merge default into branch

mattip noreply at buildbot.pypy.org
Wed Jan 9 22:36:25 CET 2013


Author: mattip <matti.picus at gmail.com>
Branch: numpypy-real-as-view
Changeset: r59903:c95c67c88a2b
Date: 2013-01-09 23:36 +0200
http://bitbucket.org/pypy/pypy/changeset/c95c67c88a2b/

Log:	merge default into branch

diff too long, truncating to 2000 out of 11246 lines

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/pypy/doc/Makefile b/pypy/doc/Makefile
--- a/pypy/doc/Makefile
+++ b/pypy/doc/Makefile
@@ -32,38 +32,38 @@
 	-rm -rf $(BUILDDIR)/*
 
 html:
-	python config/generate.py
+	# python config/generate.py #readthedocs will not run this Makefile
 	$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
 	@echo
 	@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
 
 dirhtml:
-	python config/generate.py
+	# python config/generate.py #readthedocs will not run this Makefile
 	$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
 	@echo
 	@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
 
 pickle:
-	python config/generate.py
+	# python config/generate.py #readthedocs will not run this Makefile
 	$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
 	@echo
 	@echo "Build finished; now you can process the pickle files."
 
 json:
-	python config/generate.py
+	# python config/generate.py #readthedocs will not run this Makefile
 	$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
 	@echo
 	@echo "Build finished; now you can process the JSON files."
 
 htmlhelp:
-	python config/generate.py
+	# python config/generate.py #readthedocs will not run this Makefile
 	$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
 	@echo
 	@echo "Build finished; now you can run HTML Help Workshop with the" \
 	      ".hhp project file in $(BUILDDIR)/htmlhelp."
 
 qthelp:
-	python config/generate.py
+	# python config/generate.py #readthedocs will not run this Makefile
 	$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
 	@echo
 	@echo "Build finished; now you can run "qcollectiongenerator" with the" \
@@ -73,7 +73,7 @@
 	@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/PyPy.qhc"
 
 latex:
-	python config/generate.py
+	# python config/generate.py #readthedocs will not run this Makefile
 	$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
 	@echo
 	@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
@@ -81,26 +81,26 @@
 	      "run these through (pdf)latex."
 
 man:
-	python config/generate.py
+	# python config/generate.py #readthedocs will not run this Makefile
 	$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
 	@echo
 	@echo "Build finished. The manual pages are in $(BUILDDIR)/man"
 
 changes:
-	python config/generate.py
+	# python config/generate.py #readthedocs will not run this Makefile
 	$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
 	@echo
 	@echo "The overview file is in $(BUILDDIR)/changes."
 
 linkcheck:
-	python config/generate.py
+	# python config/generate.py #readthedocs will not run this Makefile
 	$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
 	@echo
 	@echo "Link check complete; look for any errors in the above output " \
 	      "or in $(BUILDDIR)/linkcheck/output.txt."
 
 doctest:
-	python config/generate.py
+	# python config/generate.py #readthedocs will not run this Makefile
 	$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
 	@echo "Testing of doctests in the sources finished, look at the " \
 	      "results in $(BUILDDIR)/doctest/output.txt."
diff --git a/pypy/doc/conf.py b/pypy/doc/conf.py
--- a/pypy/doc/conf.py
+++ b/pypy/doc/conf.py
@@ -38,7 +38,7 @@
 
 # General information about the project.
 project = u'PyPy'
-copyright = u'2011, The PyPy Project'
+copyright = u'2013, The PyPy Project'
 
 # The version info for the project you're documenting, acts as replacement for
 # |version| and |release|, also used in various other places throughout the
diff --git a/pypy/doc/config/translation.no__thread.txt b/pypy/doc/config/translation.no__thread.txt
--- a/pypy/doc/config/translation.no__thread.txt
+++ b/pypy/doc/config/translation.no__thread.txt
@@ -1,3 +1,3 @@
 Don't use gcc __thread attribute for fast thread local storage
-implementation . Increases the chance that moving the resulting
+implementation. Increases the chance that moving the resulting
 executable to another same processor Linux machine will work.
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/pypyconfig.py b/pypy/doc/pypyconfig.py
--- a/pypy/doc/pypyconfig.py
+++ b/pypy/doc/pypyconfig.py
@@ -3,6 +3,10 @@
 def setup(app):
     import sys, os
     sys.path.insert(0, os.path.abspath("../../"))
+
+    #Autmatically calls make_cmdlline_overview
+    from pypy.doc.config import generate 
+
     from pypy.config import makerestdoc
     import py
     role = makerestdoc.register_config_role(py.path.local())
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
@@ -5,6 +5,11 @@
 .. this is a revision shortly after release-2.0-beta1
 .. startrev: 0e6161a009c6
 
+.. branch: callback-jit
+Callbacks from C are now better JITted
+
+.. branch: remove-globals-in-jit
+
 .. branch: length-hint
 Implement __lenght_hint__ according to PEP 424
 
@@ -28,5 +33,7 @@
 
 .. 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/doc/windows.rst b/pypy/doc/windows.rst
--- a/pypy/doc/windows.rst
+++ b/pypy/doc/windows.rst
@@ -56,11 +56,24 @@
 ----------------------------
 
 On Windows, there is no standard place where to download, build and
-install third-party libraries.  We chose to install them in the parent
+install third-party libraries.  We recommend installing them in the parent
 directory of the pypy checkout.  For example, if you installed pypy in
 ``d:\pypy\trunk\`` (This directory contains a README file), the base
-directory is ``d:\pypy``. You may choose different values by setting the
-INCLUDE, LIB and PATH (for DLLs)
+directory is ``d:\pypy``. You must then set the
+INCLUDE, LIB and PATH (for DLLs) environment variables appropriately.
+
+Abridged method (for -Ojit builds using Visual Studio 2008)
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+Download the versions of all the external packages
+from 
+https://bitbucket.org/pypy/pypy/downloads/local.zip
+Then expand it into the base directory (base_dir) and modify your environment to reflect this::
+
+    set PATH=<base_dir>\bin;%PATH%
+    set INCLUDE=<base_dir>\include;%INCLUDE%
+    set LIB=<base_dir>\lib;%LIB%
+
+Now you should be good to go. Read on for more information.
 
 The Boehm garbage collector
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~
diff --git a/pypy/interpreter/typedef.py b/pypy/interpreter/typedef.py
--- a/pypy/interpreter/typedef.py
+++ b/pypy/interpreter/typedef.py
@@ -105,6 +105,13 @@
 # typical usage (case 1 is the most common kind of app-level subclasses;
 # case 2 is the memory-saving kind defined with __slots__).
 #
+#  +----------------------------------------------------------------+
+#  | NOTE: if withmapdict is enabled, the following doesn't apply!  |
+#  | Map dicts can flexibly allow any slots/__dict__/__weakref__ to |
+#  | show up only when needed.  In particular there is no way with  |
+#  | mapdict to prevent some objects from being weakrefable.        |
+#  +----------------------------------------------------------------+
+#
 #     dict   slots   del   weakrefable
 #
 # 1.    Y      N      N         Y          UserDictWeakref
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
@@ -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]
@@ -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/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
 
@@ -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
@@ -644,15 +644,9 @@
         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.make_sure_var_in_reg(op.getarg(0))
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
@@ -2,25 +2,13 @@
 """ Tests for register allocation for common constructs
 """
 
-import py
-from pypy.jit.metainterp.history import BoxInt, \
-     BoxPtr, TreeLoop, TargetToken
-from pypy.jit.metainterp.resoperation import rop, ResOperation
-from pypy.jit.codewriter import heaptracker
-from pypy.jit.backend.llsupport.descr import GcCache
-from pypy.jit.backend.llsupport.gc import GcLLDescription
+from pypy.jit.metainterp.history import TargetToken
+from pypy.jit.backend.llsupport.gc import GcLLDescription, GcLLDescr_boehm
 from pypy.jit.backend.detect_cpu import getcpuclass
 from pypy.jit.backend.arm.arch import WORD
 from pypy.rpython.lltypesystem import lltype, llmemory, rffi
-from pypy.rpython.annlowlevel import llhelper
-from pypy.rpython.lltypesystem import rclass
-from pypy.jit.backend.llsupport.gc import GcLLDescr_framework
 
-from pypy.jit.backend.arm.test.test_regalloc import MockAssembler
 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
 
 CPU = getcpuclass()
 
@@ -44,23 +32,14 @@
         return ['compressed'] + shape[1:]
 
 
-class MockGcDescr(GcCache):
-    get_malloc_slowpath_addr = None
-    write_barrier_descr = None
-    moving_gc = True
+class MockGcDescr(GcLLDescr_boehm):
     gcrootmap = MockGcRootMap()
 
-    def initialize(self):
-        pass
-
-    _record_constptrs = GcLLDescr_framework._record_constptrs.im_func
-    rewrite_assembler = GcLLDescr_framework.rewrite_assembler.im_func
-
 
 class TestRegallocGcIntegration(BaseTestRegalloc):
     
     cpu = CPU(None, None)
-    cpu.gc_ll_descr = MockGcDescr(False)
+    cpu.gc_ll_descr = MockGcDescr(None, None, None)
     cpu.setup_once()
     
     S = lltype.GcForwardReference()
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
     pass
diff --git a/pypy/jit/backend/arm/test/test_runner.py b/pypy/jit/backend/arm/test/test_runner.py
--- a/pypy/jit/backend/arm/test/test_runner.py
+++ b/pypy/jit/backend/arm/test/test_runner.py
@@ -60,16 +60,18 @@
             ]
         cpu.compile_loop(inp, operations, looptoken)
         args = [i for i in range(1, 15)]
-        self.cpu.execute_token(looptoken, *args)
-        output = [self.cpu.get_latest_value_int(i - 1) for i in range(1, 15)]
+        deadframe = self.cpu.execute_token(looptoken, *args)
+        output = [self.cpu.get_latest_value_int(deadframe, i - 1) for i in range(1, 15)]
         expected = [3, 7, 11, 15, 19, 23, 27, 3, 7, 11, 15, 19, 23, 27]
         assert output == expected
 
-    def test_redirect_call_assember2(self):
-        def assembler_helper(failindex, virtualizable):
-            return self.cpu.get_latest_value_int(0)
+    def test_redirect_call_assembler2(self):
+        def assembler_helper(deadframe, virtualizable):
+            x = self.cpu.get_latest_value_int(deadframe, 0)
+            assert x == 11
+            return 7
 
-        FUNCPTR = lltype.Ptr(lltype.FuncType([lltype.Signed, llmemory.GCREF],
+        FUNCPTR = lltype.Ptr(lltype.FuncType([llmemory.GCREF, llmemory.GCREF],
                                              lltype.Signed))
 
         class FakeJitDriverSD:
@@ -101,12 +103,12 @@
         self.cpu.compile_loop(loop2.inputargs, loop2.operations, lt2)
         self.cpu.compile_loop(loop3.inputargs, loop3.operations, lt3)
         self.cpu.compile_loop(loop1.inputargs, loop1.operations, lt1)
-        self.cpu.execute_token(lt1, 11)
-        assert self.cpu.get_latest_value_int(0) == 12
+        df = self.cpu.execute_token(lt1, 10)
+        assert self.cpu.get_latest_value_int(df, 0) == 7
 
         self.cpu.redirect_call_assembler(lt2, lt3)
-        self.cpu.execute_token(lt1, 11)
-        assert self.cpu.get_latest_value_int(0) == 10
+        df = self.cpu.execute_token(lt1, 12)
+        assert self.cpu.get_latest_value_int(df, 0) == 7
 
     SFloat = lltype.GcForwardReference()
     SFloat.become(lltype.GcStruct('SFloat', ('parent', rclass.OBJECT),
@@ -202,8 +204,8 @@
             ARGS = [lltype.Signed] * numargs
             RES = lltype.Signed
             args = [i+1 for i in range(numargs)]
-            res = self.cpu.execute_token(looptoken, *args)
-            assert self.cpu.get_latest_value_int(0) == sum(args)
+            deadframe = self.cpu.execute_token(looptoken, *args)
+            assert self.cpu.get_latest_value_int(deadframe, 0) == sum(args)
 
     def test_debugger_on(self):
         from pypy.rlib import debug
diff --git a/pypy/jit/backend/llgraph/llimpl.py b/pypy/jit/backend/llgraph/llimpl.py
deleted file mode 100644
--- a/pypy/jit/backend/llgraph/llimpl.py
+++ /dev/null
@@ -1,1968 +0,0 @@
-"""
-The non-RPythonic part of the llgraph backend.
-This contains all the code that is directly run
-when executing on top of the llinterpreter.
-"""
-
-import weakref
-from pypy.objspace.flow.model import Variable, Constant
-from pypy.annotation import model as annmodel
-from pypy.jit.metainterp.history import REF, INT, FLOAT
-from pypy.jit.metainterp import history
-from pypy.jit.codewriter import heaptracker
-from pypy.rpython.lltypesystem import lltype, llmemory, rclass, rstr, rffi
-from pypy.rpython.ootypesystem import ootype
-from pypy.rpython.module.support import LLSupport, OOSupport
-from pypy.rpython.llinterp import LLException
-from pypy.rpython.extregistry import ExtRegistryEntry
-
-from pypy.jit.metainterp import resoperation
-from pypy.jit.metainterp.resoperation import rop
-from pypy.jit.backend.llgraph import symbolic
-from pypy.jit.codewriter import longlong
-from pypy.jit.codewriter.effectinfo import EffectInfo
-
-from pypy.rlib.objectmodel import ComputedIntSymbolic, we_are_translated
-from pypy.rlib.rarithmetic import ovfcheck
-from pypy.rlib.rarithmetic import r_longlong, r_ulonglong, r_uint
-from pypy.rlib.rtimer import read_timestamp
-
-import py
-from pypy.tool.ansi_print import ansi_log
-log = py.log.Producer('runner')
-py.log.setconsumer('runner', ansi_log)
-
-IS_32_BIT = r_ulonglong is not r_uint
-
-
-def _from_opaque(opq):
-    return opq._obj.externalobj
-
-_TO_OPAQUE = {}
-
-def _to_opaque(value):
-    try:
-        return value._the_opaque_pointer
-    except AttributeError:
-        op = lltype.opaqueptr(_TO_OPAQUE[value.__class__], 'opaque',
-                              externalobj=value)
-        value._the_opaque_pointer = op
-        return op
-
-def _normalize(value):
-    if isinstance(value, lltype._ptr):
-        value = lltype.top_container(value._obj)
-    return value
-
-def from_opaque_string(s):
-    if isinstance(s, str):
-        return s
-    elif isinstance(s, ootype._string):
-        return OOSupport.from_rstr(s)
-    else:
-        return LLSupport.from_rstr(s)
-
-FLOAT_ARRAY_TP = lltype.Ptr(lltype.Array(lltype.Float, hints={"nolength": True}))
-def maybe_uncast(TP, array):
-    if array._TYPE.TO.OF != lltype.Float:
-        # array._TYPE.TO._hints.get("uncast_on_llgraph"):
-        array = rffi.cast(TP, array)
-    return array
-
-# a list of argtypes of all operations - couldn't find any and it's
-# very useful.  Note however that the table is half-broken here and
-# there, in ways that are sometimes a bit hard to fix; that's why
-# it is not "official".
-TYPES = {
-    'int_add'         : (('int', 'int'), 'int'),
-    'int_sub'         : (('int', 'int'), 'int'),
-    'int_mul'         : (('int', 'int'), 'int'),
-    'int_floordiv'    : (('int', 'int'), 'int'),
-    'int_mod'         : (('int', 'int'), 'int'),
-    'int_and'         : (('int', 'int'), 'int'),
-    'int_or'          : (('int', 'int'), 'int'),
-    'int_xor'         : (('int', 'int'), 'int'),
-    'int_lshift'      : (('int', 'int'), 'int'),
-    'int_rshift'      : (('int', 'int'), 'int'),
-    'int_lt'          : (('int', 'int'), 'bool'),
-    'int_gt'          : (('int', 'int'), 'bool'),
-    'int_ge'          : (('int', 'int'), 'bool'),
-    'int_le'          : (('int', 'int'), 'bool'),
-    'int_eq'          : (('int', 'int'), 'bool'),
-    'int_ne'          : (('int', 'int'), 'bool'),
-    'int_is_true'     : (('int',), 'bool'),
-    'int_is_zero'     : (('int',), 'bool'),
-    'int_neg'         : (('int',), 'int'),
-    'int_invert'      : (('int',), 'int'),
-    'int_add_ovf'     : (('int', 'int'), 'int'),
-    'int_sub_ovf'     : (('int', 'int'), 'int'),
-    'int_mul_ovf'     : (('int', 'int'), 'int'),
-    'int_force_ge_zero':(('int',), 'int'),
-    'uint_add'        : (('int', 'int'), 'int'),
-    'uint_sub'        : (('int', 'int'), 'int'),
-    'uint_mul'        : (('int', 'int'), 'int'),
-    'uint_lt'         : (('int', 'int'), 'bool'),
-    'uint_le'         : (('int', 'int'), 'bool'),
-    'uint_eq'         : (('int', 'int'), 'bool'),
-    'uint_ne'         : (('int', 'int'), 'bool'),
-    'uint_gt'         : (('int', 'int'), 'bool'),
-    'uint_ge'         : (('int', 'int'), 'bool'),
-    'uint_xor'        : (('int', 'int'), 'int'),
-    'uint_rshift'     : (('int', 'int'), 'int'),
-    'uint_floordiv'   : (('int', 'int'), 'int'),
-    'float_add'       : (('float', 'float'), 'float'),
-    'float_sub'       : (('float', 'float'), 'float'),
-    'float_mul'       : (('float', 'float'), 'float'),
-    'float_truediv'   : (('float', 'float'), 'float'),
-    'float_lt'        : (('float', 'float'), 'bool'),
-    'float_le'        : (('float', 'float'), 'bool'),
-    'float_eq'        : (('float', 'float'), 'bool'),
-    'float_ne'        : (('float', 'float'), 'bool'),
-    'float_gt'        : (('float', 'float'), 'bool'),
-    'float_ge'        : (('float', 'float'), 'bool'),
-    'float_neg'       : (('float',), 'float'),
-    'float_abs'       : (('float',), 'float'),
-    'cast_float_to_int':(('float',), 'int'),
-    'cast_int_to_float':(('int',), 'float'),
-    'same_as'         : (('int',), 'int'),      # could also be ptr=>ptr
-    'new_with_vtable' : (('ref',), 'ref'),
-    'new'             : ((), 'ref'),
-    'new_array'       : (('int',), 'ref'),
-    'oois'            : (('ref', 'ref'), 'bool'),
-    'ooisnot'         : (('ref', 'ref'), 'bool'),
-    'instanceof'      : (('ref',), 'bool'),
-    'subclassof'      : (('ref', 'ref'), 'bool'),
-    'runtimenew'      : (('ref',), 'ref'),
-    'setfield_gc'     : (('ref', 'intorptr'), None),
-    'getfield_gc'     : (('ref',), 'intorptr'),
-    'getfield_gc_pure': (('ref',), 'intorptr'),
-    'setfield_raw'    : (('ref', 'intorptr'), None),
-    'getfield_raw'    : (('ref',), 'intorptr'),
-    'getfield_raw_pure': (('ref',), 'intorptr'),
-    'setarrayitem_gc' : (('ref', 'int', 'intorptr'), None),
-    'getarrayitem_gc' : (('ref', 'int'), 'intorptr'),
-    'getarrayitem_gc_pure' : (('ref', 'int'), 'intorptr'),
-    'setarrayitem_raw' : (('ref', 'int', 'intorptr'), None),
-    'getarrayitem_raw' : (('ref', 'int'), 'intorptr'),
-    'getarrayitem_raw_pure' : (('ref', 'int'), 'intorptr'),
-    'arraylen_gc'     : (('ref',), 'int'),
-    'call'            : (('ref', 'varargs'), 'intorptr'),
-    'call_assembler'  : (('varargs',), 'intorptr'),
-    'cond_call_gc_wb' : (('ptr', 'ptr'), None),
-    'cond_call_gc_wb_array': (('ptr', 'int', 'ptr'), None),
-    'oosend'          : (('varargs',), 'intorptr'),
-    'oosend_pure'     : (('varargs',), 'intorptr'),
-    'guard_true'      : (('bool',), None),
-    'guard_false'     : (('bool',), None),
-    'guard_value'     : (('int', 'int'), None),
-    'guard_class'     : (('ref', 'ref'), None),
-    'guard_no_exception'   : ((), None),
-    'guard_exception'      : (('ref',), 'ref'),
-    'guard_no_overflow'    : ((), None),
-    'guard_overflow'       : ((), None),
-    'guard_nonnull'        : (('ref',), None),
-    'guard_isnull'        : (('ref',), None),
-    'guard_nonnull_class' : (('ref', 'ref'), None),
-    'newstr'          : (('int',), 'ref'),
-    'strlen'          : (('ref',), 'int'),
-    'strgetitem'      : (('ref', 'int'), 'int'),
-    'strsetitem'      : (('ref', 'int', 'int'), None),
-    'newunicode'      : (('int',), 'ref'),
-    'unicodelen'      : (('ref',), 'int'),
-    'unicodegetitem'  : (('ref', 'int'), 'int'),
-    'unicodesetitem'  : (('ref', 'int', 'int'), 'int'),
-    'cast_ptr_to_int' : (('ref',), 'int'),
-    'cast_int_to_ptr' : (('int',), 'ref'),
-    'debug_merge_point': (('ref', 'int', 'int'), None),
-    'force_token'     : ((), 'int'),
-    'call_may_force'  : (('int', 'varargs'), 'intorptr'),
-    'guard_not_forced': ((), None),
-}
-
-# ____________________________________________________________
-
-class CompiledLoop(object):
-    has_been_freed = False
-    invalid = False
-
-    def __init__(self):
-        self.inputargs = []
-        self.operations = []
-
-    def getargtypes(self):
-        return [v.concretetype for v in self.inputargs]
-
-    def __repr__(self):
-        lines = []
-        self.as_text(lines, 1)
-        return 'CompiledLoop %s:\n%s' % (self.inputargs, '\n'.join(lines))
-
-    def as_text(self, lines, indent):
-        for op in self.operations:
-            lines.append('\t'*indent + repr(op))
-
-class Operation(object):
-    result = None
-    descr = None
-    jump_target = None
-    fail_args = None
-
-    def __init__(self, opnum):
-        self.opnum = opnum
-        self.args = []
-
-    def __repr__(self):
-        if self.result is not None:
-            sres = repr0(self.result) + ' = '
-        else:
-            sres = ''
-        return '{%s%s(%s)}' % (sres, self.getopname(),
-                               ', '.join(map(repr0, self.args)))
-
-    def getopname(self):
-        try:
-            return resoperation.opname[self.opnum]
-        except KeyError:
-            return '<%d>' % self.opnum
-
-    def is_guard(self):
-        return rop._GUARD_FIRST <= self.opnum <= rop._GUARD_LAST
-
-    def is_final(self):
-        return rop._FINAL_FIRST <= self.opnum <= rop._FINAL_LAST
-
-def repr0(x):
-    if isinstance(x, list):
-        return '[' + ', '.join(repr0(y) for y in x) + ']'
-    elif isinstance(x, Constant):
-        return '(' + repr0(x.value) + ')'
-    elif isinstance(x, lltype._ptr):
-        x = llmemory.cast_ptr_to_adr(x)
-        if x.ptr:
-            try:
-                container = x.ptr._obj._normalizedcontainer()
-                return '* %s' % (container._TYPE._short_name(),)
-            except AttributeError:
-                return repr(x)
-        else:
-            return 'NULL'
-    else:
-        return repr(x)
-
-def repr_list(lst, types):
-    res_l = []
-    if types and types[-1] == 'varargs':
-        types = types[:-1] + ('int',) * (len(lst) - len(types) + 1)
-    assert len(types) == len(lst)
-    for elem, tp in zip(lst, types):
-        if isinstance(elem, Constant):
-            res_l.append('(%s)' % repr1(elem, tp))
-        else:
-            res_l.append(repr1(elem, tp))
-    return '[%s]' % (', '.join(res_l))
-
-def repr1(x, tp):
-    if tp == "intorptr":
-        TYPE = lltype.typeOf(x)
-        if isinstance(TYPE, lltype.Ptr) and TYPE.TO._gckind == 'gc':
-            tp = "ref"
-        else:
-            tp = "int"
-    if tp == 'int':
-        return str(x)
-    elif tp == 'void':
-        return '---'
-    elif tp == 'ref':
-        if not x:
-            return '(* None)'
-        if isinstance(x, int):
-            # XXX normalize?
-            ptr = str(llmemory.cast_int_to_adr(x))
-        elif isinstance(ootype.typeOf(x), ootype.OOType):
-            return repr(x)
-        else:
-            if getattr(x, '_fake', None):
-                return repr(x)
-            if lltype.typeOf(x) == llmemory.GCREF:
-                TP = lltype.Ptr(lltype.typeOf(x._obj.container))
-                ptr = lltype.cast_opaque_ptr(TP, x)
-            else:
-                ptr = x
-        try:
-            container = ptr._obj._normalizedcontainer()
-            return '(* %s)' % (container._TYPE._short_name(),)
-        except AttributeError:
-            return '(%r)' % (ptr,)
-    elif tp == 'bool':
-        assert x == 0 or x == 1
-        return str(bool(x))
-    #elif tp == 'fieldname':
-    #    return str(symbolic.TokenToField[x...][1])
-    elif tp == 'float':
-        return str(x)
-    else:
-        raise NotImplementedError("tp = %s" % tp)
-
-_variables = []
-
-def compile_start():
-    del _variables[:]
-    return _to_opaque(CompiledLoop())
-
-def mark_as_free(loop):
-    loop = _from_opaque(loop)
-    assert not loop.has_been_freed
-    loop.has_been_freed = True
-
-def compile_start_int_var(loop):
-    return compile_start_ref_var(loop, lltype.Signed)
-
-def compile_start_float_var(loop):
-    return compile_start_ref_var(loop, longlong.FLOATSTORAGE)
-
-def compile_start_ref_var(loop, TYPE):
-    loop = _from_opaque(loop)
-    assert not loop.operations
-    v = Variable()
-    v.concretetype = TYPE
-    loop.inputargs.append(v)
-    r = len(_variables)
-    _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))
-
-def compile_add_descr(loop, ofs, type, arg_types, extrainfo, width):
-    from pypy.jit.backend.llgraph.runner import Descr
-    loop = _from_opaque(loop)
-    op = loop.operations[-1]
-    assert isinstance(type, str) and len(type) == 1
-    op.descr = Descr(ofs, type, arg_types=arg_types, extrainfo=extrainfo, width=width)
-
-def compile_add_descr_arg(loop, ofs, type, arg_types):
-    from pypy.jit.backend.llgraph.runner import Descr
-    loop = _from_opaque(loop)
-    op = loop.operations[-1]
-    assert isinstance(type, str) and len(type) == 1
-    op.args.append(Descr(ofs, type, arg_types=arg_types))
-
-def compile_add_loop_token(loop, descr):
-    if we_are_translated():
-        raise ValueError("CALL_ASSEMBLER not supported")
-    loop = _from_opaque(loop)
-    op = loop.operations[-1]
-    op.descr = weakref.ref(descr)
-
-TARGET_TOKENS = weakref.WeakKeyDictionary()
-
-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, clt
-
-def compile_add_var(loop, intvar):
-    loop = _from_opaque(loop)
-    op = loop.operations[-1]
-    op.args.append(_variables[intvar])
-
-def compile_add_int_const(loop, value):
-    compile_add_ref_const(loop, value, lltype.Signed)
-
-def compile_add_float_const(loop, value):
-    compile_add_ref_const(loop, value, longlong.FLOATSTORAGE)
-
-def compile_add_ref_const(loop, value, TYPE):
-    loop = _from_opaque(loop)
-    const = Constant(value)
-    const.concretetype = TYPE
-    op = loop.operations[-1]
-    op.args.append(const)
-
-def compile_add_int_result(loop):
-    return compile_add_ref_result(loop, lltype.Signed)
-
-def compile_add_float_result(loop):
-    return compile_add_ref_result(loop, longlong.FLOATSTORAGE)
-
-def compile_add_ref_result(loop, TYPE):
-    loop = _from_opaque(loop)
-    v = Variable()
-    v.concretetype = TYPE
-    op = loop.operations[-1]
-    op.result = v
-    r = len(_variables)
-    _variables.append(v)
-    return r
-
-def compile_add_jump_target(loop, targettoken, source_clt):
-    loop = _from_opaque(loop)
-    descrobj = _normalize(targettoken)
-    (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 [v.concretetype for v in op.args] == (
-           [v.concretetype for v in target_inputargs])
-    #
-    if loop_target == loop:
-        log.info("compiling new loop")
-    else:
-        log.info("compiling new bridge")
-
-def compile_add_guard_jump_target(loop, loop_target):
-    loop = _from_opaque(loop)
-    loop_target = _from_opaque(loop_target)
-    op = loop.operations[-1]
-    assert op.is_guard()
-    op.jump_target = loop_target
-
-def compile_add_fail(loop, fail_index):
-    loop = _from_opaque(loop)
-    index = len(loop.operations)-1
-    op = loop.operations[index]
-    op.fail_index = fail_index
-    return index
-
-def compile_add_fail_arg(loop, intvar):
-    loop = _from_opaque(loop)
-    op = loop.operations[-1]
-    if op.fail_args is None:
-        op.fail_args = []
-    if intvar == -1:
-        op.fail_args.append(None)
-    else:
-        op.fail_args.append(_variables[intvar])
-
-def compile_redirect_fail(old_loop, old_index, new_loop):
-    old_loop = _from_opaque(old_loop)
-    new_loop = _from_opaque(new_loop)
-    guard_op = old_loop.operations[old_index]
-    assert guard_op.is_guard()
-    guard_op.jump_target = new_loop
-    # check that the bridge's inputargs are of the correct number and
-    # kind for the guard
-    if guard_op.fail_args is not None:
-        argkinds = [v.concretetype for v in guard_op.fail_args if v]
-    else:
-        argkinds = []
-    assert argkinds == [v.concretetype for v in new_loop.inputargs]
-
-# ------------------------------
-
-class Frame(object):
-    OPHANDLERS = [None] * (rop._LAST+1)
-
-    def __init__(self, cpu):
-        self.verbose = False
-        self.cpu = cpu
-        self.opindex = 1
-        self._forced = False
-        self._may_force = -1
-
-    def getenv(self, v):
-        from pypy.jit.backend.llgraph.runner import Descr
-        if isinstance(v, Constant):
-            return v.value
-        elif isinstance(v, Descr):
-            return v
-        else:
-            return self.env[v]
-
-    def _populate_fail_args(self, op, skip=None):
-        fail_args = []
-        if op.fail_args:
-            for fail_arg in op.fail_args:
-                if fail_arg is None:
-                    fail_args.append(None)
-                elif fail_arg is skip:
-                    fail_args.append(fail_arg.concretetype._defl())
-                else:
-                    fail_args.append(self.getenv(fail_arg))
-        self.fail_args = fail_args
-        self.fail_index = op.fail_index
-
-    def execute(self):
-        """Execute all operations in a loop,
-        possibly following to other loops as well.
-        """
-        global _last_exception
-        assert _last_exception is None, "exception left behind"
-        verbose = True
-        self.opindex = 0
-        while True:
-            assert not self.loop.has_been_freed
-            op = self.loop.operations[self.opindex]
-            args = [self.getenv(v) for v in op.args]
-            if not op.is_final():
-                try:
-                    result = self.execute_operation(op.opnum, args, op.descr,
-                                                    verbose)
-                except GuardFailed:
-                    assert op.is_guard()
-                    _stats.exec_conditional_jumps += 1
-                    if op.jump_target is not None:
-                        # a patched guard, pointing to further code
-                        if op.fail_args:
-                            args = [self.getenv(v) for v in op.fail_args if v]
-                        else:
-                            args = []
-                        assert len(op.jump_target.inputargs) == len(args)
-                        self.env = dict(zip(op.jump_target.inputargs, args))
-                        self.loop = op.jump_target
-                        self.opindex = 0
-                        continue
-                    else:
-                        self._populate_fail_args(op)
-                        # a non-patched guard
-                        if self.verbose:
-                            log.trace('failed: %s' % (
-                                ', '.join(map(str, fail_args)),))
-                        return op.fail_index
-                #verbose = self.verbose
-                assert (result is None) == (op.result is None)
-                if op.result is not None:
-                    RESTYPE = op.result.concretetype
-                    if RESTYPE is lltype.Signed:
-                        x = self.as_int(result)
-                    elif RESTYPE is llmemory.GCREF:
-                        x = self.as_ptr(result)
-                    elif RESTYPE is ootype.Object:
-                        x = self.as_object(result)
-                    elif RESTYPE is longlong.FLOATSTORAGE:
-                        x = self.as_floatstorage(result)
-                    else:
-                        raise Exception("op.result.concretetype is %r"
-                                        % (RESTYPE,))
-                    self.env[op.result] = x
-                self.opindex += 1
-                continue
-            if op.opnum == rop.JUMP:
-                inputargs = op.jump_target_inputargs
-                assert len(inputargs) == len(args)
-                self.env = dict(zip(inputargs, args))
-                self.loop = op.jump_target
-                self.opindex = op.jump_target_opindex
-                _stats.exec_jumps += 1
-            elif op.opnum == rop.FINISH:
-                if self.verbose:
-                    log.trace('finished: %s' % (
-                        ', '.join(map(str, args)),))
-                self.fail_args = args
-                return op.fail_index
-
-            else:
-                assert 0, "unknown final operation %d" % (op.opnum,)
-
-    def execute_operation(self, opnum, values, descr, verbose):
-        """Execute a single operation.
-        """
-        ophandler = self.OPHANDLERS[opnum]
-        if ophandler is None:
-            self._define_impl(opnum)
-            ophandler = self.OPHANDLERS[opnum]
-            assert ophandler is not None, "missing impl for op %d" % opnum
-        opname = resoperation.opname[opnum].lower()
-        exec_counters = _stats.exec_counters
-        exec_counters[opname] = exec_counters.get(opname, 0) + 1
-        for i in range(len(values)):
-            if isinstance(values[i], ComputedIntSymbolic):
-                values[i] = values[i].compute_fn()
-        res = NotImplemented
-        try:
-            res = ophandler(self, descr, *values)
-        finally:
-            if 0:     # if verbose:
-                argtypes, restype = TYPES[opname]
-                if res is None:
-                    resdata = ''
-                elif res is NotImplemented:
-                    resdata = '*fail*'
-                else:
-                    resdata = '-> ' + repr1(res, restype)
-                # fish the types
-                log.cpu('\t%s %s %s' % (opname, repr_list(values, argtypes),
-                                        resdata))
-        return res
-
-    def as_int(self, x):
-        return cast_to_int(x)
-
-    def as_ptr(self, x):
-        return cast_to_ptr(x)
-
-    def as_object(self, x):
-        return ootype.cast_to_object(x)
-
-    def as_floatstorage(self, x):
-        return cast_to_floatstorage(x)
-
-    def log_progress(self):
-        count = sum(_stats.exec_counters.values())
-        count_jumps = _stats.exec_jumps
-        log.trace('ran %d operations, %d jumps' % (count, count_jumps))
-
-    # ----------
-
-    @classmethod
-    def _define_impl(cls, opnum):
-        opname = resoperation.opname[opnum]
-        try:
-            op = getattr(cls, 'op_' + opname.lower())   # op_guard_true etc.
-        except AttributeError:
-            try:
-                impl = globals()['do_' + opname.lower()]  # do_arraylen_gc etc.
-                def op(self, descr, *args):
-                    if descr is None:
-                        return impl(*args)
-                    else:
-                        return impl(descr, *args)
-            except KeyError:
-                op = cls._make_impl_from_blackhole_interp(opname)
-        cls.OPHANDLERS[opnum] = op
-
-    @classmethod
-    def _make_impl_from_blackhole_interp(cls, opname):
-        from pypy.jit.metainterp.blackhole import BlackholeInterpreter
-        name = 'bhimpl_' + opname.lower()
-        func = BlackholeInterpreter.__dict__[name]
-        for argtype in func.argtypes:
-            assert argtype in ('i', 'r', 'f')
-        #
-        def _op_default_implementation(self, descr, *args):
-            # for all operations implemented in the blackhole interpreter
-            return func(*args)
-        #
-        return _op_default_implementation
-
-    def op_label(self, _, *args):
-        op = self.loop.operations[self.opindex]
-        assert op.opnum == rop.LABEL
-        assert len(op.args) == len(args)
-        newenv = {}
-        for v, value in zip(op.args, args):
-            newenv[v] = value
-        self.env = newenv
-
-    def op_debug_merge_point(self, _, *args):
-        from pypy.jit.metainterp.warmspot import get_stats
-        try:
-            stats = get_stats()
-        except AttributeError:
-            pass
-        else:
-            stats.add_merge_point_location(args[1:])
-        pass
-
-    def op_guard_true(self, _, value):
-        if not value:
-            raise GuardFailed
-
-    def op_guard_false(self, _, value):
-        if value:
-            raise GuardFailed
-
-    op_guard_nonnull = op_guard_true
-    op_guard_isnull  = op_guard_false
-
-    def op_guard_class(self, _, value, expected_class):
-        value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, value)
-        expected_class = llmemory.cast_adr_to_ptr(
-            llmemory.cast_int_to_adr(expected_class),
-            rclass.CLASSTYPE)
-        if value.typeptr != expected_class:
-            raise GuardFailed
-
-    def op_guard_nonnull_class(self, _, value, expected_class):
-        if not value:
-            raise GuardFailed
-        self.op_guard_class(_, value, expected_class)
-
-    def op_guard_value(self, _, value, expected_value):
-        if value != expected_value:
-            raise GuardFailed
-
-    def op_guard_no_exception(self, _):
-        if _last_exception:
-            raise GuardFailed
-
-    def _check_exception(self, expected_exception):
-        global _last_exception
-        expected_exception = self._cast_exception(expected_exception)
-        assert expected_exception
-        exc = _last_exception
-        if exc:
-            got = exc.args[0]
-            # exact match!
-            if got != expected_exception:
-                return False
-            return True
-        else:
-            return False
-
-    def _cast_exception(self, exception):
-        return llmemory.cast_adr_to_ptr(
-            llmemory.cast_int_to_adr(exception),
-            rclass.CLASSTYPE)
-
-    def _issubclass(self, cls1, cls2):
-        return rclass.ll_issubclass(cls1, cls2)
-
-    def op_guard_exception(self, _, expected_exception):
-        global _last_exception
-        if not self._check_exception(expected_exception):
-            raise GuardFailed
-        res = _last_exception[1]
-        _last_exception = None
-        return res
-
-    def op_guard_no_overflow(self, _):
-        flag = self.overflow_flag
-        del self.overflow_flag
-        if flag:
-            raise GuardFailed
-
-    def op_guard_overflow(self, _):
-        flag = self.overflow_flag
-        del self.overflow_flag
-        if not flag:
-            raise GuardFailed
-
-    def op_int_add_ovf(self, _, x, y):
-        try:
-            z = ovfcheck(x + y)
-        except OverflowError:
-            ovf = True
-            z = 0
-        else:
-            ovf = False
-        self.overflow_flag = ovf
-        return z
-
-    def op_int_sub_ovf(self, _, x, y):
-        try:
-            z = ovfcheck(x - y)
-        except OverflowError:
-            ovf = True
-            z = 0
-        else:
-            ovf = False
-        self.overflow_flag = ovf
-        return z
-
-    def op_int_mul_ovf(self, _, x, y):
-        try:
-            z = ovfcheck(x * y)
-        except OverflowError:
-            ovf = True
-            z = 0
-        else:
-            ovf = False
-        self.overflow_flag = ovf
-        return z
-
-    def op_keepalive(self, _, x):
-        pass
-
-    # ----------
-    # delegating to the builtins do_xxx() (done automatically for simple cases)
-
-    def op_getarrayitem_gc(self, arraydescr, array, index):
-        if arraydescr.typeinfo == REF:
-            return do_getarrayitem_gc_ptr(array, index)
-        elif arraydescr.typeinfo == INT:
-            return do_getarrayitem_gc_int(array, index)
-        elif arraydescr.typeinfo == FLOAT:
-            return do_getarrayitem_gc_float(array, index)
-        else:
-            raise NotImplementedError
-
-    op_getarrayitem_gc_pure = op_getarrayitem_gc
-
-    def op_getarrayitem_raw(self, arraydescr, array, index):
-        if arraydescr.typeinfo == REF:
-            raise NotImplementedError("getarrayitem_raw -> gcref")
-        elif arraydescr.typeinfo == INT:
-            return do_getarrayitem_raw_int(array, index, arraydescr.ofs)
-        elif arraydescr.typeinfo == FLOAT:
-            return do_getarrayitem_raw_float(array, index)
-        else:
-            raise NotImplementedError
-
-    op_getarrayitem_raw_pure = op_getarrayitem_raw
-
-    def op_getfield_gc(self, fielddescr, struct):
-        if fielddescr.typeinfo == REF:
-            return do_getfield_gc_ptr(struct, fielddescr.ofs)
-        elif fielddescr.typeinfo == INT:


More information about the pypy-commit mailing list