Commits

Armin Rigo committed de5da9b Merge

hg merge remove-globals-in-jit

Comments (0)

Files changed (132)

pypy/doc/release-2.0.0-beta1.rst

+===============
+PyPy 2.0 beta 1
+===============
+
+We're pleased to announce the 2.0 beta 1 release of PyPy. This release is
+not a typical beta, in a sense the stability is the same or better than 1.9
+and can be used in production. It does however include a few performance
+regressions documented below that don't allow us to label is as 2.0 final.
+(It also contains many performance improvements.)
+
+The main features of this release are support for ARM processor and
+compatibility with CFFI. It also includes
+numerous improvements to the numpy in pypy effort, cpyext and performance.
+
+You can download the PyPy 2.0 beta 1 release here:
+
+    http://pypy.org/download.html 
+
+What is PyPy?
+=============
+
+PyPy is a very compliant Python interpreter, almost a drop-in replacement for
+CPython 2.7.3. It's fast (`pypy 2.0 beta 1 and cpython 2.7.3`_
+performance comparison) due to its integrated tracing JIT compiler.
+
+This release supports x86 machines running Linux 32/64, Mac OS X 64 or
+Windows 32. It also supports ARM machines running Linux.
+Windows 64 work is still stalling, we would welcome a volunteer
+to handle that.
+
+.. XXX link
+
+XXX donors info?
+
+Regressions
+===========
+
+Reasons why this is not PyPy 2.0:
+
+* the ``ctypes`` fast path is now slower than it used to be. In PyPy
+  1.9 ``ctypes`` was either incredibly faster or slower than CPython depending whether
+  you hit the fast path or not. Right now it's usually simply slower. We're
+  probably going to rewrite ``ctypes`` using ``cffi``, which will make it
+  universally faster.
+
+* ``cffi`` (an alternative to interfacing with C code) is very fast, but
+  it is missing one optimization that will make it as fast as a native
+  call from C.
+
+* ``numpypy`` lazy computation was disabled for the sake of simplicity.
+  We should reenable this for the final 2.0 release.
+
+Highlights
+==========
+
+* ``cffi`` is officially supported by PyPy. You can install it normally by
+  using ``pip install cffi`` once you have PyPy installed. The corresponding
+  ``0.4`` version of ``cffi`` has been released.
+
+* ARM is now an officially supported processor architecture.
+  PyPy now work on soft-float ARM/Linux builds.  Currently ARM processors
+  supporting the ARMv7 and later ISA that include a floating-point unit are
+  supported.
+
+* This release contains the latest Python standard library 2.7.3 and is fully
+  compatible with Python 2.7.3.
+
+* It does not however contain hash randomization, since the solution present
+  in CPython is not solving the problem anyway. The reason can be
+  found on the `CPython issue tracker`_.
+
+* ``gc.get_referrers()`` is now faster.
+
+* Various numpy improvements. The list includes:
+
+  * axis argument support in many places
+
+  * full support for fancy indexing
+
+  * ``complex128`` and ``complex64`` dtypes
+
+* `JIT hooks`_ are now a powerful tool to introspect the JITting process that
+  PyPy performs.
+
+* ``**kwds`` usage is much faster in the typical scenario
+
+* operations on ``long`` objects are now as fast as in CPython (from
+  roughly 2x slower)
+
+* We now have special strategies for ``dict``/``set``/``list`` which contain
+  unicode strings, which means that now such collections will be both faster
+  and more compact.
+

pypy/doc/whatsnew-2.0.0-beta1.rst

+======================
+What's new in PyPy xxx
+======================
+
+.. this is the revision of the last merge from default to release-1.9.x
+.. startrev: 8d567513d04d
+
+Fixed the performance of gc.get_referrers()
+
+.. branch: default
+.. branch: app_main-refactor
+.. branch: win-ordinal
+.. branch: reflex-support
+Provides cppyy module (disabled by default) for access to C++ through Reflex.
+See doc/cppyy.rst for full details and functionality.
+.. branch: nupypy-axis-arg-check
+Check that axis arg is valid in _numpypy
+.. branch:less-gettestobjspace
+.. branch: move-apptest-support
+
+.. branch: iterator-in-rpython
+.. branch: numpypy_count_nonzero
+.. branch: numpy-refactor
+Remove numpy lazy evaluation and simplify everything
+.. branch: numpy-reintroduce-jit-drivers
+.. branch: numpy-fancy-indexing
+Support for array[array-of-ints] in numpy
+.. branch: even-more-jit-hooks
+Implement better JIT hooks
+.. branch: virtual-arguments
+Improve handling of **kwds greatly, making them virtual sometimes.
+.. branch: improve-rbigint
+Introduce __int128 on systems where it's supported and improve the speed of
+rlib/rbigint.py greatly.
+.. branch: translation-cleanup
+Start to clean up a bit the flow object space.
+.. branch: ffi-backend
+Support CFFI.  http://morepypy.blogspot.ch/2012/08/cffi-release-03.html
+.. branch: speedup-unpackiterable
+.. branch: stdlib-2.7.3
+The stdlib was updated to version 2.7.3
+
+.. branch: numpypy-complex2
+Complex dtype support for numpy
+.. branch: numpypy-problems
+Improve dtypes intp, uintp, void, string and record
+.. branch: numpypy.float16
+Add float16 numpy dtype
+.. branch: kill-someobject
+major cleanups including killing some object support
+.. branch: cpyext-PyThreadState_New
+implement threadstate-related functions in cpyext
+
+.. branch: unicode-strategies
+add dict/list/set strategies optimized for unicode items
+
+.. "uninteresting" branches that we should just ignore for the whatsnew:
+.. branch: slightly-shorter-c
+.. branch: better-enforceargs
+.. branch: rpython-unicode-formatting
+.. branch: jit-opaque-licm
+.. branch: rpython-utf8
+Support for utf-8 encoding in RPython
+.. branch: arm-backend-2
+Support ARM in the JIT.

pypy/doc/whatsnew-head.rst

 See doc/cppyy.rst for full details and functionality.
 .. branch: nupypy-axis-arg-check
 Check that axis arg is valid in _numpypy
+.. branch:less-gettestobjspace
+.. branch: move-apptest-support
 
 .. branch: iterator-in-rpython
 .. branch: numpypy_count_nonzero
 Complex dtype support for numpy
 .. branch: numpypy-problems
 Improve dtypes intp, uintp, void, string and record
+.. branch: numpypy.float16
+Add float16 numpy dtype
 .. branch: kill-someobject
 major cleanups including killing some object support
 .. branch: cpyext-PyThreadState_New

pypy/interpreter/argument.py

File contents unchanged.

pypy/interpreter/baseobjspace.py

         """
         # If we can guess the expected length we can preallocate.
         try:
-            lgt_estimate = self.len_w(w_iterable)
-        except OperationError, o:
-            if (not o.match(self, self.w_AttributeError) and
-                not o.match(self, self.w_TypeError)):
-                raise
-            items = []
-        else:
-            try:
-                items = newlist_hint(lgt_estimate)
-            except MemoryError:
-                items = [] # it might have lied
-        #
+            items = newlist_hint(self.length_hint(w_iterable, 0))
+        except MemoryError:
+            items = [] # it might have lied
+
         tp = self.type(w_iterator)
         while True:
             unpackiterable_driver.jit_merge_point(tp=tp,
         return self._unpackiterable_known_length_jitlook(w_iterator,
                                                          expected_length)
 
+    def length_hint(self, w_obj, default):
+        """Return the length of an object, consulting its __length_hint__
+        method if necessary.
+        """
+        try:
+            return self.len_w(w_obj)
+        except OperationError, e:
+            if not (e.match(self, self.w_TypeError) or
+                    e.match(self, self.w_AttributeError)):
+                raise
+
+        w_descr = self.lookup(w_obj, '__length_hint__')
+        if w_descr is None:
+            return default
+        try:
+            w_hint = self.get_and_call_function(w_descr, w_obj)
+        except OperationError, e:
+            if not (e.match(self, self.w_TypeError) or
+                    e.match(self, self.w_AttributeError)):
+                raise
+            return default
+        if self.is_w(w_hint, self.w_NotImplemented):
+            return default
+
+        hint = self.int_w(w_hint)
+        if hint < 0:
+            raise OperationError(self.w_ValueError, self.wrap(
+                    "__length_hint__() should return >= 0"))
+        return hint
+
     def fixedview(self, w_iterable, expected_length=-1):
         """ A fixed list view of w_iterable. Don't modify the result
         """
     def newlist_str(self, list_s):
         return self.newlist([self.wrap(s) for s in list_s])
 
+    def newlist_hint(self, sizehint):
+        from pypy.objspace.std.listobject import make_empty_list_with_size
+        return make_empty_list_with_size(self, sizehint)
+
     @jit.unroll_safe
     def exception_match(self, w_exc_type, w_check_class):
         """Checks if the given exception type matches 'w_check_class'."""

pypy/interpreter/test/test_argument.py

File contents unchanged.

pypy/jit/backend/arm/arch.py

 static int pypy__arm_int_div(int a, int b) {
     return a/b;
 }
-static uint pypy__arm_uint_div(uint a, uint b) {
+static unsigned int pypy__arm_uint_div(unsigned int a, unsigned int b) {
     return a/b;
 }
-static int pypy__arm_int_mod(uint a, uint b) {
+static int pypy__arm_int_mod(int a, int b) {
     return a % b;
 }
 """])

pypy/jit/backend/arm/test/test_regalloc.py

         return -1
 
 
+def get_zero_division_error(self):
+    # for tests, a random emulated ll_inst will do
+    ll_inst = lltype.malloc(rclass.OBJECT)
+    ll_inst.typeptr = lltype.malloc(rclass.OBJECT_VTABLE,
+                                    immortal=True)
+    _zer_error_vtable = llmemory.cast_ptr_to_adr(ll_inst.typeptr)
+    zer_vtable = self.cast_adr_to_int(_zer_error_vtable)
+    zer_inst = lltype.cast_opaque_ptr(llmemory.GCREF, ll_inst)
+    return zer_vtable, zer_inst
+
+
 class BaseTestRegalloc(object):
     cpu = CPU(None, None)
     cpu.setup_once()
     f_calldescr = cpu.calldescrof(FPTR.TO, FPTR.TO.ARGS, FPTR.TO.RESULT,
                                                     EffectInfo.MOST_GENERAL)
 
-    zero_division_tp, zero_division_value = cpu.get_zero_division_error()
+    zero_division_tp, zero_division_value = get_zero_division_error(cpu)
     zd_addr = cpu.cast_int_to_adr(zero_division_tp)
     zero_division_error = llmemory.cast_adr_to_ptr(zd_addr,
                                             lltype.Ptr(rclass.OBJECT_VTABLE))

pypy/jit/backend/llgraph/llimpl.py

-"""
-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:
-            return do_getfield_gc_int(struct, fielddescr.ofs)
-        elif fielddescr.typeinfo == FLOAT:
-            return do_getfield_gc_float(struct, fielddescr.ofs)
-        else:
-            raise NotImplementedError
-
-    op_getfield_gc_pure = op_getfield_gc
-
-    def op_getfield_raw(self, fielddescr, struct):
-        if fielddescr.typeinfo == REF:
-            return do_getfield_raw_ptr(struct, fielddescr.ofs)
-        elif fielddescr.typeinfo == INT:
-            return do_getfield_raw_int(struct, fielddescr.ofs)
-        elif fielddescr.typeinfo == FLOAT:
-            return do_getfield_raw_float(struct, fielddescr.ofs)
-        else:
-            raise NotImplementedError
-
-    op_getfield_raw_pure = op_getfield_raw
-
-    def op_raw_store(self, arraydescr, addr, offset, value):
-        if arraydescr.typeinfo == REF:
-            raise AssertionError("cannot store GC pointer in raw storage")
-        elif arraydescr.typeinfo == INT:
-            do_raw_store_int(addr, offset, arraydescr.ofs, value)
-        elif arraydescr.typeinfo == FLOAT:
-            do_raw_store_float(addr, offset, value)
-        else:
-            raise NotImplementedError
-
-    def op_raw_load(self, arraydescr, addr, offset):
-        if arraydescr.typeinfo == REF: 
-            raise AssertionError("cannot store GC pointer in raw storage")
-        elif arraydescr.typeinfo == INT:
-            return do_raw_load_int(addr, offset, arraydescr.ofs)
-        elif arraydescr.typeinfo == FLOAT:
-            return do_raw_load_float(addr, offset)
-        else:
-            raise NotImplementedError
-
-    def op_new(self, size):
-        return do_new(size.ofs)
-
-    def op_new_with_vtable(self, descr, vtable):
-        assert descr is None
-        descr = heaptracker.vtable2descr(self.cpu, vtable)
-        result = do_new(descr.ofs)
-        value = lltype.cast_opaque_ptr(rclass.OBJECTPTR, result)
-        value.typeptr = cast_from_int(rclass.CLASSTYPE, vtable)
-        return result
-
-    def op_setarrayitem_gc(self, arraydescr, array, index, newvalue):
-        if arraydescr.typeinfo == REF:
-            do_setarrayitem_gc_ptr(array, index, newvalue)
-        elif arraydescr.typeinfo == INT:
-            do_setarrayitem_gc_int(array, index, newvalue)
-        elif arraydescr.typeinfo == FLOAT:
-            do_setarrayitem_gc_float(array, index, newvalue)
-        else:
-            raise NotImplementedError
-
-    def op_setarrayitem_raw(self, arraydescr, array, index, newvalue):
-        if arraydescr.typeinfo == REF:
-            raise NotImplementedError("setarrayitem_raw <- gcref")
-        elif arraydescr.typeinfo == INT:
-            do_setarrayitem_raw_int(array, index, newvalue, arraydescr.ofs)
-        elif arraydescr.typeinfo == FLOAT:
-            do_setarrayitem_raw_float(array, index, newvalue)
-        else:
-            raise NotImplementedError
-
-    def op_getinteriorfield_gc(self, descr, array, index):
-        if descr.typeinfo == REF:
-            return do_getinteriorfield_gc_ptr(array, index, descr.ofs)
-        elif descr.typeinfo == INT:
-            return do_getinteriorfield_gc_int(array, index, descr.ofs)
-        elif descr.typeinfo == FLOAT:
-            return do_getinteriorfield_gc_float(array, index, descr.ofs)
-        else:
-            raise NotImplementedError
-
-    def op_getinteriorfield_raw(self, descr, array, index):
-        if descr.typeinfo == REF:
-            return do_getinteriorfield_raw_ptr(array, index, descr.width, descr.ofs)
-        elif descr.typeinfo == INT:
-            return do_getinteriorfield_raw_int(array, index, descr.width, descr.ofs)
-        elif descr.typeinfo == FLOAT:
-            return do_getinteriorfield_raw_float(array, index, descr.width, descr.ofs)
-        else:
-            raise NotImplementedError
-
-    def op_setinteriorfield_gc(self, descr, array, index, newvalue):
-        if descr.typeinfo == REF:
-            return do_setinteriorfield_gc_ptr(array, index, descr.ofs,
-                                              newvalue)
-        elif descr.typeinfo == INT:
-            return do_setinteriorfield_gc_int(array, index, descr.ofs,
-                                              newvalue)
-        elif descr.typeinfo == FLOAT:
-            return do_setinteriorfield_gc_float(array, index, descr.ofs,
-                                                newvalue)
-        else:
-            raise NotImplementedError
-
-    def op_setinteriorfield_raw(self, descr, array, index, newvalue):
-        if descr.typeinfo == REF:
-            return do_setinteriorfield_raw_ptr(array, index, newvalue, descr.width, descr.ofs)
-        elif descr.typeinfo == INT:
-            return do_setinteriorfield_raw_int(array, index, newvalue, descr.width, descr.ofs)
-        elif descr.typeinfo == FLOAT:
-            return do_setinteriorfield_raw_float(array, index, newvalue, descr.width, descr.ofs)
-        else:
-            raise NotImplementedError
-
-    def op_setfield_gc(self, fielddescr, struct, newvalue):
-        if fielddescr.typeinfo == REF:
-            do_setfield_gc_ptr(struct, fielddescr.ofs, newvalue)
-        elif fielddescr.typeinfo == INT:
-            do_setfield_gc_int(struct, fielddescr.ofs, newvalue)
-        elif fielddescr.typeinfo == FLOAT:
-            do_setfield_gc_float(struct, fielddescr.ofs, newvalue)
-        else:
-            raise NotImplementedError
-
-    def op_setfield_raw(self, fielddescr, struct, newvalue):
-        if fielddescr.typeinfo == REF:
-            do_setfield_raw_ptr(struct, fielddescr.ofs, newvalue)
-        elif fielddescr.typeinfo == INT:
-            do_setfield_raw_int(struct, fielddescr.ofs, newvalue)
-        elif fielddescr.typeinfo == FLOAT:
-            do_setfield_raw_float(struct, fielddescr.ofs, newvalue)
-        else:
-            raise NotImplementedError
-
-    def op_call(self, calldescr, func, *args):
-        effectinfo = calldescr.get_extra_info()
-        if effectinfo is not None and hasattr(effectinfo, 'oopspecindex'):
-            oopspecindex = effectinfo.oopspecindex
-            if oopspecindex == EffectInfo.OS_MATH_SQRT:
-                return do_math_sqrt(args[0])
-        return self._do_call(calldescr, func, args, call_with_llptr=False)
-
-    def op_call_release_gil(self, calldescr, func, *args):
-        return self._do_call(calldescr, func, args, call_with_llptr=True)
-
-    def _do_call(self, calldescr, func, args, call_with_llptr):
-        global _last_exception
-        assert _last_exception is None, "exception left behind"
-        assert _call_args_i == _call_args_r == _call_args_f == []
-        args_in_order = []
-        for x in args:
-            T = lltype.typeOf(x)
-            if T is lltype.Signed:
-                args_in_order.append('i')
-                _call_args_i.append(x)
-            elif T == llmemory.GCREF:
-                args_in_order.append('r')
-                _call_args_r.append(x)
-            elif T is longlong.FLOATSTORAGE:
-                args_in_order.append('f')
-                _call_args_f.append(x)
-            else:
-                raise TypeError(x)
-        try:
-            return _do_call_common(func, args_in_order, calldescr,
-                                   call_with_llptr)
-        except LLException, lle:
-            _last_exception = lle
-            d = {'v': None,
-                 REF: lltype.nullptr(llmemory.GCREF.TO),
-                 INT: 0,
-                 FLOAT: 0.0}
-            return d[calldescr.typeinfo]
-
-    def op_cond_call_gc_wb(self, descr, a, b):
-        py.test.skip("cond_call_gc_wb not supported")
-
-    def op_cond_call_gc_wb_array(self, descr, a, b, c):
-        py.test.skip("cond_call_gc_wb_array not supported")
-
-    def op_oosend(self, descr, obj, *args):
-        raise NotImplementedError("oosend for lltype backend??")
-
-    op_oosend_pure = op_oosend
-
-    def op_new_array(self, arraydescr, count):
-        return do_new_array(arraydescr.ofs, count)
-
-    def op_force_token(self, descr):
-        opaque_frame = _to_opaque(self)
-        return llmemory.cast_ptr_to_adr(opaque_frame)
-
-    def op_read_timestamp(self, descr):
-        return read_timestamp()
-
-    def op_call_may_force(self, calldescr, func, *args):
-        assert not self._forced
-        self._may_force = self.opindex
-        try:
-            return self.op_call(calldescr, func, *args)
-        finally:
-            self._may_force = -1
-
-    def op_call_assembler(self, wref_loop_token, *args):
-        if we_are_translated():
-            raise ValueError("CALL_ASSEMBLER not supported")
-        return self._do_call_assembler(wref_loop_token, *args)
-
-    def _do_call_assembler(self, wref_loop_token, *args):
-        global _last_exception
-        loop_token = wref_loop_token()
-        assert loop_token, "CALL_ASSEMBLER to a target that already died"
-        ctl = loop_token.compiled_loop_token
-        if hasattr(ctl, 'redirected'):
-            return self._do_call_assembler(ctl.redirected, *args)
-        assert not self._forced
-        self._may_force = self.opindex
-        try:
-            inpargs = _from_opaque(ctl.compiled_version).inputargs
-            assert len(inpargs) == len(args)
-            for i, inparg in enumerate(inpargs):
-                TYPE = inparg.concretetype
-                if TYPE is lltype.Signed:
-                    set_future_value_int(i, args[i])
-                elif isinstance(TYPE, lltype.Ptr):
-                    set_future_value_ref(i, args[i])
-                elif TYPE is longlong.FLOATSTORAGE:
-                    set_future_value_float(i, args[i])
-                else:
-                    raise Exception("Nonsense type %s" % TYPE)
-
-            failindex = self.cpu._execute_token(loop_token)
-            jd = loop_token.outermost_jitdriver_sd
-            assert jd is not None, ("call_assembler(): the loop_token needs "
-                                    "to have 'outermost_jitdriver_sd'")
-            if jd.index_of_virtualizable != -1:
-                vable = args[jd.index_of_virtualizable]
-            else:
-                vable = lltype.nullptr(llmemory.GCREF.TO)
-            #
-            # Emulate the fast path
-            if failindex == self.cpu.done_with_this_frame_int_v:
-                reset_vable(jd, vable)
-                return self.cpu.get_latest_value_int(0)
-            if failindex == self.cpu.done_with_this_frame_ref_v:
-                reset_vable(jd, vable)
-                return self.cpu.get_latest_value_ref(0)
-            if failindex == self.cpu.done_with_this_frame_float_v:
-                reset_vable(jd, vable)
-                return self.cpu.get_latest_value_float(0)
-            if failindex == self.cpu.done_with_this_frame_void_v:
-                reset_vable(jd, vable)
-                return None
-            #
-            assembler_helper_ptr = jd.assembler_helper_adr.ptr  # fish
-            try:
-                return assembler_helper_ptr(failindex, vable)
-            except LLException, lle:
-                assert _last_exception is None, "exception left behind"
-                _last_exception = lle
-                # fish op
-                op = self.loop.operations[self.opindex]
-                if op.result is not None:
-                    return 0
-        finally:
-            self._may_force = -1
-
-    def op_guard_not_forced(self, descr):
-        forced = self._forced
-        self._forced = False
-        if forced:
-            raise GuardFailed
-
-    def op_guard_not_invalidated(self, descr):
-        if self.loop.invalid:
-            raise GuardFailed
-
-class OOFrame(Frame):
-
-    OPHANDLERS = [None] * (rop._LAST+1)
-
-    def op_new_with_vtable(self, descr, vtable):
-        assert descr is None
-        typedescr = get_class_size(self.memocast, vtable)
-        return ootype.cast_to_object(ootype.new(typedescr.TYPE))
-
-    def op_new_array(self, typedescr, count):
-        res = ootype.oonewarray(typedescr.ARRAY, count)
-        return ootype.cast_to_object(res)
-
-    def op_getfield_gc(self, fielddescr, obj):
-        TYPE = fielddescr.TYPE
-        fieldname = fielddescr.fieldname
-        _, T = TYPE._lookup_field(fieldname)
-        obj = ootype.cast_from_object(TYPE, obj)
-        res = getattr(obj, fieldname)
-        if isinstance(T, ootype.OOType):
-            return ootype.cast_to_object(res)
-        return res
-
-    op_getfield_gc_pure = op_getfield_gc
-
-    def op_setfield_gc(self, fielddescr, obj, newvalue):
-        TYPE = fielddescr.TYPE
-        fieldname = fielddescr.fieldname
-        _, T = TYPE._lookup_field(fieldname)
-        obj = ootype.cast_from_object(TYPE, obj)
-        if isinstance(ootype.typeOf(newvalue), ootype.OOType):
-            newvalue = ootype.cast_from_object(T, newvalue)
-        elif isinstance(T, lltype.Primitive):
-            newvalue = lltype.cast_primitive(T, newvalue)
-        setattr(obj, fieldname, newvalue)
-
-    def op_getarrayitem_gc(self, typedescr, obj, index):
-        array = ootype.cast_from_object(typedescr.ARRAY, obj)
-        res = array.ll_getitem_fast(index)
-        if isinstance(typedescr.TYPE, ootype.OOType):
-            return ootype.cast_to_object(res)
-        return res
-
-    op_getarrayitem_gc_pure = op_getarrayitem_gc
-
-    def op_setarrayitem_gc(self, typedescr, obj, index, objnewvalue):
-        array = ootype.cast_from_object(typedescr.ARRAY, obj)
-        if ootype.typeOf(objnewvalue) == ootype.Object:
-            newvalue = ootype.cast_from_object(typedescr.TYPE, objnewvalue)
-        else:
-            newvalue = objnewvalue
-        array.ll_setitem_fast(index, newvalue)
-
-    def op_arraylen_gc(self, typedescr, obj):
-        array = ootype.cast_from_object(typedescr.ARRAY, obj)
-        return array.ll_length()
-
-    def op_call(self, calldescr, func, *args):
-        sm = ootype.cast_from_object(calldescr.FUNC, func)
-        newargs = cast_call_args(calldescr.FUNC.ARGS, args)
-        res = call_maybe_on_top_of_llinterp(sm, newargs)
-        if isinstance(calldescr.FUNC.RESULT, ootype.OOType):
-            return ootype.cast_to_object(res)
-        return res
-
-    def op_oosend(self, descr, obj, *args):
-        METH = descr.METH
-        obj = ootype.cast_from_object(descr.SELFTYPE, obj)
-        meth = getattr(obj, descr.methname)
-        newargs = cast_call_args(METH.ARGS, args)
-        res = call_maybe_on_top_of_llinterp(meth, newargs)
-        if isinstance(METH.RESULT, ootype.OOType):
-            return ootype.cast_to_object(res)
-        return res
-
-    op_oosend_pure = op_oosend
-
-    def op_guard_class(self, _, value, expected_class):
-        value = ootype.cast_from_object(ootype.ROOT, value)
-        expected_class = ootype.cast_from_object(ootype.Class, expected_class)
-        if ootype.classof(value) is not expected_class:
-            raise GuardFailed
-
-    def op_runtimenew(self, _, cls):
-        cls = ootype.cast_from_object(ootype.Class, cls)
-        res = ootype.runtimenew(cls)
-        return ootype.cast_to_object(res)
-
-    def op_instanceof(self, typedescr, obj):
-        inst = ootype.cast_from_object(ootype.ROOT, obj)
-        return ootype.instanceof(inst, typedescr.TYPE)
-
-    def op_subclassof(self, _, obj1, obj2):
-        cls1 = ootype.cast_from_object(ootype.Class, obj1)
-        cls2 = ootype.cast_from_object(ootype.Class, obj2)
-        return ootype.subclassof(cls1, cls2)
-
-    def _cast_exception(self, exception):
-        return ootype.cast_from_object(ootype.Class, exception)
-
-    def _issubclass(self, cls1, cls2):
-        return ootype.subclassof(cls1, cls2)
-
-# ____________________________________________________________
-
-def cast_to_int(x):
-    TP = lltype.typeOf(x)
-    if isinstance(TP, lltype.Ptr):
-        return heaptracker.adr2int(llmemory.cast_ptr_to_adr(x))
-    if TP == llmemory.Address:
-        return heaptracker.adr2int(x)
-    if TP is lltype.SingleFloat:
-        return longlong.singlefloat2int(x)
-    return lltype.cast_primitive(lltype.Signed, x)
-
-def cast_from_int(TYPE, x):
-    if isinstance(TYPE, lltype.Ptr):
-        if isinstance(x, (int, long, llmemory.AddressAsInt)):
-            x = llmemory.cast_int_to_adr(x)
-        if TYPE is rffi.VOIDP or (
-                hasattr(TYPE.TO, '_hints') and
-                TYPE.TO._hints.get("uncast_on_llgraph")):
-            # assume that we want a "C-style" cast, without typechecking the value
-            return rffi.cast(TYPE, x)
-        return llmemory.cast_adr_to_ptr(x, TYPE)
-    elif TYPE == llmemory.Address:
-        if isinstance(x, (int, long, llmemory.AddressAsInt)):
-            x = llmemory.cast_int_to_adr(x)
-        assert lltype.typeOf(x) == llmemory.Address
-        return x
-    elif TYPE is lltype.SingleFloat:
-        assert lltype.typeOf(x) is lltype.Signed
-        return longlong.int2singlefloat(x)
-    else:
-        if lltype.typeOf(x) == llmemory.Address:
-            x = heaptracker.adr2int(x)
-        return lltype.cast_primitive(TYPE, x)
-
-def cast_to_ptr(x):
-    assert isinstance(lltype.typeOf(x), lltype.Ptr)
-    return lltype.cast_opaque_ptr(llmemory.GCREF, x)
-
-def cast_from_ptr(TYPE, x):
-    return lltype.cast_opaque_ptr(TYPE, x)
-
-def cast_to_floatstorage(x):
-    if isinstance(x, float):
-        return longlong.getfloatstorage(x)      # common case
-    if IS_32_BIT:
-        assert longlong.supports_longlong
-        if isinstance(x, r_longlong):
-            return x
-        if isinstance(x, r_ulonglong):
-            return rffi.cast(lltype.SignedLongLong, x)
-    raise TypeError(type(x))
-
-def cast_from_floatstorage(TYPE, x):
-    assert isinstance(x, longlong.r_float_storage)
-    if TYPE is lltype.Float:
-        return longlong.getrealfloat(x)
-    if longlong.is_longlong(TYPE):
-        return rffi.cast(TYPE, x)
-    raise TypeError(TYPE)
-
-
-def new_frame(is_oo, cpu):
-    if is_oo:
-        frame = OOFrame(cpu)
-    else:
-        frame = Frame(cpu)
-    return _to_opaque(frame)
-
-_future_values = []
-
-def frame_clear(frame, loop):
-    frame = _from_opaque(frame)
-    loop = _from_opaque(loop)
-    assert len(_future_values) == len(loop.inputargs)
-    frame.loop = loop
-    frame.env = {}
-    for i in range(len(loop.inputargs)):
-        expected_type = loop.inputargs[i].concretetype
-        assert lltype.typeOf(_future_values[i]) == expected_type
-        frame.env[loop.inputargs[i]] = _future_values[i]
-    del _future_values[:]
-
-def set_future_value_int(index, value):
-    assert lltype.typeOf(value) is lltype.Signed
-    set_future_value_ref(index, value)
-
-def set_future_value_float(index, value):
-    assert isinstance(value, longlong.r_float_storage)
-    set_future_value_ref(index, value)
-
-def set_future_value_ref(index, value):
-    del _future_values[index:]
-    assert len(_future_values) == index
-    _future_values.append(value)
-
-def frame_execute(frame):
-    frame = _from_opaque(frame)
-    if frame.verbose:
-        values = [frame.env[v] for v in frame.loop.inputargs]
-        log.trace('Entering CPU frame <- %r' % (values,))
-    try:
-        result = frame.execute()
-        if frame.verbose:
-            log.trace('Leaving CPU frame -> #%d' % (result,))
-            frame.log_progress()
-    except Exception, e:
-        log.ERROR('%s in CPU frame: %s' % (e.__class__.__name__, e))
-        # Only invoke pdb when io capturing is not on otherwise py.io complains.
-        if py.test.config.option.capture == 'no':
-            import sys, pdb
-            pdb.post_mortem(sys.exc_info()[2])
-        raise
-    del frame.env
-    return result
-
-def frame_int_getvalue(frame, num):
-    frame = _from_opaque(frame)
-    assert num >= 0
-    x = frame.fail_args[num]
-    assert lltype.typeOf(x) is lltype.Signed
-    return x
-
-def frame_float_getvalue(frame, num):
-    frame = _from_opaque(frame)
-    assert num >= 0
-    x = frame.fail_args[num]
-    assert lltype.typeOf(x) is longlong.FLOATSTORAGE
-    return x
-
-def frame_ptr_getvalue(frame, num):
-    frame = _from_opaque(frame)
-    assert num >= 0
-    x = frame.fail_args[num]
-    assert lltype.typeOf(x) == llmemory.GCREF
-    return x
-
-def frame_get_value_count(frame):
-    frame = _from_opaque(frame)
-    return len(frame.fail_args)
-
-def frame_clear_latest_values(frame, count):
-    frame = _from_opaque(frame)
-    assert count == len(frame.fail_args)
-    del frame.fail_args
-
-_last_exception = None
-
-def grab_exc_value():
-    global _last_exception
-    if _last_exception is not None:
-        result = _last_exception.args[1]
-        _last_exception = None
-        return lltype.cast_opaque_ptr(llmemory.GCREF, result)
-    else:
-        return lltype.nullptr(llmemory.GCREF.TO)
-
-##_pseudo_exceptions = {}
-
-##def _get_error(Class):
-##    if _llinterp.typer is not None:
-##        llframe = _llinterp.frame_class(None, None, _llinterp)
-##        try:
-##            llframe.make_llexception(Class())
-##        except LLException, e:
-##            return e
-##        else:
-##            assert 0, "should have raised"
-##    else:
-##        # for tests, a random emulated ll_inst will do
-##        if Class not in _pseudo_exceptions:
-##            ll_inst = lltype.malloc(rclass.OBJECT, zero=True)
-##            ll_inst.typeptr = lltype.malloc(rclass.OBJECT_VTABLE,
-##                                            immortal=True)
-##            _pseudo_exceptions[Class] = LLException(ll_inst.typeptr, ll_inst)
-##        return _pseudo_exceptions[Class]
-
-##def get_overflow_error_value():
-##    return lltype.cast_opaque_ptr(llmemory.GCREF,
-##                                  _get_error(OverflowError).args[1])
-
-def force(opaque_frame):
-    frame = _from_opaque(opaque_frame)
-    assert not frame._forced
-    frame._forced = True
-    assert frame._may_force >= 0
-    call_op = frame.loop.operations[frame._may_force]
-    guard_op = frame.loop.operations[frame._may_force+1]
-    opnum = call_op.opnum
-    assert opnum == rop.CALL_MAY_FORCE or opnum == rop.CALL_ASSEMBLER
-    frame._populate_fail_args(guard_op, skip=call_op.result)
-    return frame.fail_index
-
-def get_forced_token_frame(force_token):
-    opaque_frame = llmemory.cast_adr_to_ptr(force_token,
-                                            lltype.Ptr(_TO_OPAQUE[Frame]))
-    return opaque_frame
-
-def get_frame_forced_token(opaque_frame):
-    return llmemory.cast_ptr_to_adr(opaque_frame)
-
-##def cast_adr_to_int(memocast, adr):
-##    # xxx slow
-##    assert lltype.typeOf(adr) == llmemory.Address
-##    memocast = _from_opaque(memocast)
-##    addresses = memocast.addresses
-##    for i in xrange(len(addresses)-1, -1, -1):
-##        if addresses[i] == adr:
-##            return i
-##    i = len(addresses)
-##    addresses.append(adr)
-##    return i
-
-##def cast_int_to_adr(memocast, int):
-##    memocast = _from_opaque(memocast)
-##    assert 0 <= int < len(memocast.addresses)
-##    return memocast.addresses[int]
-
-##def get_class_size(memocast, vtable):
-##    memocast = _from_opaque(memocast)
-##    return memocast.vtable_to_size[vtable]
-
-##def set_class_size(memocast, vtable, size):
-##    memocast = _from_opaque(memocast)
-##    memocast.vtable_to_size[vtable] = size
-
-class GuardFailed(Exception):
-    pass
-
-# ____________________________________________________________
-
-
-def do_same_as(x):
-    return x
-
-def do_arraylen_gc(arraydescr, array):
-    array = array._obj.container
-    return array.getlength()
-
-def do_strlen(string):
-    str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string)
-    return len(str.chars)
-
-def do_strgetitem(string, index):
-    str = lltype.cast_opaque_ptr(lltype.Ptr(rstr.STR), string)
-    return ord(str.chars[index])
-
-def do_unicodelen(string):
-    uni = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string)
-    return len(uni.chars)
-
-def do_unicodegetitem(string, index):
-    uni = lltype.cast_opaque_ptr(lltype.Ptr(rstr.UNICODE), string)
-    return ord(uni.chars[index])
-
-def do_getarrayitem_gc_int(array, index):
-    array = array._obj.container
-    return cast_to_int(array.getitem(index))
-
-def do_getarrayitem_raw_int(array, index, itemsize):
-    array = array.adr.ptr
-    ITEMTYPE = lltype.typeOf(array).TO.OF
-    TYPE = symbolic.Size2Type[itemsize]
-    if TYPE.OF != ITEMTYPE:
-        array = rffi.cast(lltype.Ptr(TYPE), array)
-    return cast_to_int(array._obj.getitem(index))
-
-def do_getarrayitem_gc_float(array, index):
-    array = array._obj.container
-    return cast_to_floatstorage(array.getitem(index))
-
-def do_getarrayitem_raw_float(array, index):
-    array = maybe_uncast(FLOAT_ARRAY_TP, array.adr.ptr)
-    return cast_to_floatstorage(array._obj.getitem(index))
-
-def do_getarrayitem_gc_ptr(array, index):
-    array = array._obj.container
-    return cast_to_ptr(array.getitem(index))
-
-def _getfield_gc(struct, fieldnum):
-    STRUCT, fieldname = symbolic.TokenToField[fieldnum]
-    ptr = lltype.cast_opaque_ptr(lltype.Ptr(STRUCT), struct)
-    return getattr(ptr, fieldname)
-
-def do_getfield_gc_int(struct, fieldnum):
-    return cast_to_int(_getfield_gc(struct, fieldnum))
-
-def do_getfield_gc_float(struct, fieldnum):
-    return cast_to_floatstorage(_getfield_gc(struct, fieldnum))
-
-def do_getfield_gc_ptr(struct, fieldnum):
-    return cast_to_ptr(_getfield_gc(struct, fieldnum))
-
-def _getinteriorfield_gc(struct, fieldnum):
-    STRUCT, fieldname = symbolic.TokenToField[fieldnum]
-    return getattr(struct, fieldname)
-
-def do_getinteriorfield_gc_int(array, index, fieldnum):
-    struct = array._obj.container.getitem(index)
-    return cast_to_int(_getinteriorfield_gc(struct, fieldnum))
-
-def do_getinteriorfield_gc_float(array, index, fieldnum):
-    struct = array._obj.container.getitem(index)
-    return cast_to_floatstorage(_getinteriorfield_gc(struct, fieldnum))
-
-def do_getinteriorfield_gc_ptr(array, index, fieldnum):
-    struct = array._obj.container.getitem(index)
-    return cast_to_ptr(_getinteriorfield_gc(struct, fieldnum))
-
-def _getfield_raw(struct, fieldnum):
-    STRUCT, fieldname = symbolic.TokenToField[fieldnum]
-    ptr = cast_from_int(lltype.Ptr(STRUCT), struct)
-    return getattr(ptr, fieldname)
-
-def do_getfield_raw_int(struct, fieldnum):
-    return cast_to_int(_getfield_raw(struct, fieldnum))
-
-def do_getfield_raw_float(struct, fieldnum):
-    return cast_to_floatstorage(_getfield_raw(struct, fieldnum))
-
-def do_getfield_raw_ptr(struct, fieldnum):
-    return cast_to_ptr(_getfield_raw(struct, fieldnum))
-
-def do_raw_load_int(struct, offset, descrofs):
-    TYPE = symbolic.Size2Type[descrofs]
-    ll_p = rffi.cast(rffi.CCHARP, struct)
-    ll_p = rffi.cast(lltype.Ptr(TYPE), rffi.ptradd(ll_p, offset))
-    value = ll_p[0]
-    return rffi.cast(lltype.Signed, value)
-
-def do_raw_load_float(struct, offset):
-    ll_p = rffi.cast(rffi.CCHARP, struct)
-    ll_p = rffi.cast(rffi.CArrayPtr(longlong.FLOATSTORAGE),
-                     rffi.ptradd(ll_p, offset))
-    value = ll_p[0]
-    return value
-
-def do_raw_store_int(struct, offset, descrofs, value):
-    TYPE = symbolic.Size2Type[descrofs]
-    ll_p = rffi.cast(rffi.CCHARP, struct)
-    ll_p = rffi.cast(lltype.Ptr(TYPE), rffi.ptradd(ll_p, offset))
-    ll_p[0] = rffi.cast(TYPE.OF, value)
-
-def do_raw_store_float(struct, offset, value):
-    ll_p = rffi.cast(rffi.CCHARP, struct)
-    ll_p = rffi.cast(rffi.CArrayPtr(longlong.FLOATSTORAGE),
-                     rffi.ptradd(ll_p, offset))
-    ll_p[0] = value
-
-def do_new(size):
-    TYPE = symbolic.Size2Type[size]
-    x = lltype.malloc(TYPE, zero=True)
-    return cast_to_ptr(x)
-
-def do_new_array(arraynum, count):
-    TYPE = symbolic.Size2Type[arraynum]
-    assert count >= 0 # explode if it's not
-    x = lltype.malloc(TYPE, count, zero=True)
-    return cast_to_ptr(x)
-
-def do_setarrayitem_gc_int(array, index, newvalue):
-    array = array._obj.container