diff cos/python/Python/ceval.c @ 27:7f74363f4c82

Added some files for the python port
author windel
date Tue, 27 Dec 2011 18:59:02 +0100
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/cos/python/Python/ceval.c	Tue Dec 27 18:59:02 2011 +0100
@@ -0,0 +1,4327 @@
+
+/* Execute compiled code */
+
+/* XXX TO DO:
+   XXX speed up searching for keywords by using a dictionary
+   XXX document it!
+   */
+
+/* enable more aggressive intra-module optimizations, where available */
+#define PY_LOCAL_AGGRESSIVE
+
+#include "Python.h"
+
+#include "code.h"
+#include "frameobject.h"
+#include "opcode.h"
+#include "structmember.h"
+
+#include <ctype.h>
+
+typedef PyObject *(*callproc)(PyObject *, PyObject *, PyObject *);
+
+/* Forward declarations */
+static PyObject * call_function(PyObject ***, int);
+static PyObject * fast_function(PyObject *, PyObject ***, int, int, int);
+static PyObject * do_call(PyObject *, PyObject ***, int, int);
+static PyObject * ext_do_call(PyObject *, PyObject ***, int, int, int);
+static PyObject * update_keyword_args(PyObject *, int, PyObject ***,
+                                      PyObject *);
+static PyObject * update_star_args(int, int, PyObject *, PyObject ***);
+static PyObject * load_args(PyObject ***, int);
+#define CALL_FLAG_VAR 1
+#define CALL_FLAG_KW 2
+
+static int call_trace(Py_tracefunc, PyObject *, PyFrameObject *,
+                      int, PyObject *);
+static int call_trace_protected(Py_tracefunc, PyObject *,
+                                PyFrameObject *, int, PyObject *);
+static void call_exc_trace(Py_tracefunc, PyObject *, PyFrameObject *);
+static int maybe_call_line_trace(Py_tracefunc, PyObject *,
+                                 PyFrameObject *, int *, int *, int *);
+
+static PyObject * cmp_outcome(int, PyObject *, PyObject *);
+static PyObject * import_from(PyObject *, PyObject *);
+static int import_all_from(PyObject *, PyObject *);
+static void format_exc_check_arg(PyObject *, const char *, PyObject *);
+static void format_exc_unbound(PyCodeObject *co, int oparg);
+static PyObject * unicode_concatenate(PyObject *, PyObject *,
+                                      PyFrameObject *, unsigned char *);
+static PyObject * special_lookup(PyObject *, char *, PyObject **);
+
+#define NAME_ERROR_MSG \
+    "name '%.200s' is not defined"
+#define GLOBAL_NAME_ERROR_MSG \
+    "global name '%.200s' is not defined"
+#define UNBOUNDLOCAL_ERROR_MSG \
+    "local variable '%.200s' referenced before assignment"
+#define UNBOUNDFREE_ERROR_MSG \
+    "free variable '%.200s' referenced before assignment" \
+    " in enclosing scope"
+
+#define PCALL(O)
+
+PyObject *
+PyEval_GetCallStats(PyObject *self)
+{
+    Py_INCREF(Py_None);
+    return Py_None;
+}
+
+
+#ifdef WITH_THREAD
+#define GIL_REQUEST _Py_atomic_load_relaxed(&gil_drop_request)
+#else
+#define GIL_REQUEST 0
+#endif
+
+/* This can set eval_breaker to 0 even though gil_drop_request became
+   1.  We believe this is all right because the eval loop will release
+   the GIL eventually anyway. */
+#define COMPUTE_EVAL_BREAKER() \
+    _Py_atomic_store_relaxed( \
+        &eval_breaker, \
+        GIL_REQUEST | \
+        _Py_atomic_load_relaxed(&pendingcalls_to_do) | \
+        pending_async_exc)
+
+#ifdef WITH_THREAD
+
+#define SET_GIL_DROP_REQUEST() \
+    do { \
+        _Py_atomic_store_relaxed(&gil_drop_request, 1); \
+        _Py_atomic_store_relaxed(&eval_breaker, 1); \
+    } while (0)
+
+#define RESET_GIL_DROP_REQUEST() \
+    do { \
+        _Py_atomic_store_relaxed(&gil_drop_request, 0); \
+        COMPUTE_EVAL_BREAKER(); \
+    } while (0)
+
+#endif
+
+/* Pending calls are only modified under pending_lock */
+#define SIGNAL_PENDING_CALLS() \
+    do { \
+        _Py_atomic_store_relaxed(&pendingcalls_to_do, 1); \
+        _Py_atomic_store_relaxed(&eval_breaker, 1); \
+    } while (0)
+
+#define UNSIGNAL_PENDING_CALLS() \
+    do { \
+        _Py_atomic_store_relaxed(&pendingcalls_to_do, 0); \
+        COMPUTE_EVAL_BREAKER(); \
+    } while (0)
+
+#define SIGNAL_ASYNC_EXC() \
+    do { \
+        pending_async_exc = 1; \
+        _Py_atomic_store_relaxed(&eval_breaker, 1); \
+    } while (0)
+
+#define UNSIGNAL_ASYNC_EXC() \
+    do { pending_async_exc = 0; COMPUTE_EVAL_BREAKER(); } while (0)
+
+
+#ifdef WITH_THREAD
+
+#include "pythread.h"
+
+static PyThread_type_lock pending_lock = 0; /* for pending calls */
+static long main_thread = 0;
+/* This single variable consolidates all requests to break out of the fast path
+   in the eval loop. */
+static _Py_atomic_int eval_breaker = {0};
+/* Request for dropping the GIL */
+static _Py_atomic_int gil_drop_request = {0};
+/* Request for running pending calls. */
+static _Py_atomic_int pendingcalls_to_do = {0};
+/* Request for looking at the `async_exc` field of the current thread state.
+   Guarded by the GIL. */
+static int pending_async_exc = 0;
+
+#include "ceval_gil.h"
+
+int
+PyEval_ThreadsInitialized(void)
+{
+    return gil_created();
+}
+
+void
+PyEval_InitThreads(void)
+{
+    if (gil_created())
+        return;
+    create_gil();
+    take_gil(PyThreadState_GET());
+    main_thread = PyThread_get_thread_ident();
+    if (!pending_lock)
+        pending_lock = PyThread_allocate_lock();
+}
+
+void
+_PyEval_FiniThreads(void)
+{
+    if (!gil_created())
+        return;
+    destroy_gil();
+    assert(!gil_created());
+}
+
+void
+PyEval_AcquireLock(void)
+{
+    PyThreadState *tstate = PyThreadState_GET();
+    if (tstate == NULL)
+        Py_FatalError("PyEval_AcquireLock: current thread state is NULL");
+    take_gil(tstate);
+}
+
+void
+PyEval_ReleaseLock(void)
+{
+    /* This function must succeed when the current thread state is NULL.
+       We therefore avoid PyThreadState_GET() which dumps a fatal error
+       in debug mode.
+    */
+    drop_gil((PyThreadState*)_Py_atomic_load_relaxed(
+        &_PyThreadState_Current));
+}
+
+void
+PyEval_AcquireThread(PyThreadState *tstate)
+{
+    if (tstate == NULL)
+        Py_FatalError("PyEval_AcquireThread: NULL new thread state");
+    /* Check someone has called PyEval_InitThreads() to create the lock */
+    assert(gil_created());
+    take_gil(tstate);
+    if (PyThreadState_Swap(tstate) != NULL)
+        Py_FatalError(
+            "PyEval_AcquireThread: non-NULL old thread state");
+}
+
+void
+PyEval_ReleaseThread(PyThreadState *tstate)
+{
+    if (tstate == NULL)
+        Py_FatalError("PyEval_ReleaseThread: NULL thread state");
+    if (PyThreadState_Swap(NULL) != tstate)
+        Py_FatalError("PyEval_ReleaseThread: wrong thread state");
+    drop_gil(tstate);
+}
+
+/* This function is called from PyOS_AfterFork to ensure that newly
+   created child processes don't hold locks referring to threads which
+   are not running in the child process.  (This could also be done using
+   pthread_atfork mechanism, at least for the pthreads implementation.) */
+
+void
+PyEval_ReInitThreads(void)
+{
+    _Py_IDENTIFIER(_after_fork);
+    PyObject *threading, *result;
+    PyThreadState *tstate = PyThreadState_GET();
+
+    if (!gil_created())
+        return;
+    recreate_gil();
+    pending_lock = PyThread_allocate_lock();
+    take_gil(tstate);
+    main_thread = PyThread_get_thread_ident();
+
+    /* Update the threading module with the new state.
+     */
+    tstate = PyThreadState_GET();
+    threading = PyMapping_GetItemString(tstate->interp->modules,
+                                        "threading");
+    if (threading == NULL) {
+        /* threading not imported */
+        PyErr_Clear();
+        return;
+    }
+    result = _PyObject_CallMethodId(threading, &PyId__after_fork, NULL);
+    if (result == NULL)
+        PyErr_WriteUnraisable(threading);
+    else
+        Py_DECREF(result);
+    Py_DECREF(threading);
+}
+
+#else
+static _Py_atomic_int eval_breaker = {0};
+static int pending_async_exc = 0;
+#endif /* WITH_THREAD */
+
+/* This function is used to signal that async exceptions are waiting to be
+   raised, therefore it is also useful in non-threaded builds. */
+
+void
+_PyEval_SignalAsyncExc(void)
+{
+    SIGNAL_ASYNC_EXC();
+}
+
+/* Functions save_thread and restore_thread are always defined so
+   dynamically loaded modules needn't be compiled separately for use
+   with and without threads: */
+
+PyThreadState *
+PyEval_SaveThread(void)
+{
+    PyThreadState *tstate = PyThreadState_Swap(NULL);
+    if (tstate == NULL)
+        Py_FatalError("PyEval_SaveThread: NULL tstate");
+#ifdef WITH_THREAD
+    if (gil_created())
+        drop_gil(tstate);
+#endif
+    return tstate;
+}
+
+void
+PyEval_RestoreThread(PyThreadState *tstate)
+{
+    if (tstate == NULL)
+        Py_FatalError("PyEval_RestoreThread: NULL tstate");
+#ifdef WITH_THREAD
+    if (gil_created()) {
+        int err = errno;
+        take_gil(tstate);
+        /* _Py_Finalizing is protected by the GIL */
+        if (_Py_Finalizing && tstate != _Py_Finalizing) {
+            drop_gil(tstate);
+            PyThread_exit_thread();
+            assert(0);  /* unreachable */
+        }
+        errno = err;
+    }
+#endif
+    PyThreadState_Swap(tstate);
+}
+
+
+/* Mechanism whereby asynchronously executing callbacks (e.g. UNIX
+   signal handlers or Mac I/O completion routines) can schedule calls
+   to a function to be called synchronously.
+   The synchronous function is called with one void* argument.
+   It should return 0 for success or -1 for failure -- failure should
+   be accompanied by an exception.
+
+   If registry succeeds, the registry function returns 0; if it fails
+   (e.g. due to too many pending calls) it returns -1 (without setting
+   an exception condition).
+
+   Note that because registry may occur from within signal handlers,
+   or other asynchronous events, calling malloc() is unsafe!
+
+#ifdef WITH_THREAD
+   Any thread can schedule pending calls, but only the main thread
+   will execute them.
+   There is no facility to schedule calls to a particular thread, but
+   that should be easy to change, should that ever be required.  In
+   that case, the static variables here should go into the python
+   threadstate.
+#endif
+*/
+
+#ifdef WITH_THREAD
+
+/* The WITH_THREAD implementation is thread-safe.  It allows
+   scheduling to be made from any thread, and even from an executing
+   callback.
+ */
+
+#define NPENDINGCALLS 32
+static struct {
+    int (*func)(void *);
+    void *arg;
+} pendingcalls[NPENDINGCALLS];
+static int pendingfirst = 0;
+static int pendinglast = 0;
+
+int
+Py_AddPendingCall(int (*func)(void *), void *arg)
+{
+    int i, j, result=0;
+    PyThread_type_lock lock = pending_lock;
+
+    /* try a few times for the lock.  Since this mechanism is used
+     * for signal handling (on the main thread), there is a (slim)
+     * chance that a signal is delivered on the same thread while we
+     * hold the lock during the Py_MakePendingCalls() function.
+     * This avoids a deadlock in that case.
+     * Note that signals can be delivered on any thread.  In particular,
+     * on Windows, a SIGINT is delivered on a system-created worker
+     * thread.
+     * We also check for lock being NULL, in the unlikely case that
+     * this function is called before any bytecode evaluation takes place.
+     */
+    if (lock != NULL) {
+        for (i = 0; i<100; i++) {
+            if (PyThread_acquire_lock(lock, NOWAIT_LOCK))
+                break;
+        }
+        if (i == 100)
+            return -1;
+    }
+
+    i = pendinglast;
+    j = (i + 1) % NPENDINGCALLS;
+    if (j == pendingfirst) {
+        result = -1; /* Queue full */
+    } else {
+        pendingcalls[i].func = func;
+        pendingcalls[i].arg = arg;
+        pendinglast = j;
+    }
+    /* signal main loop */
+    SIGNAL_PENDING_CALLS();
+    if (lock != NULL)
+        PyThread_release_lock(lock);
+    return result;
+}
+
+int
+Py_MakePendingCalls(void)
+{
+    static int busy = 0;
+    int i;
+    int r = 0;
+
+    if (!pending_lock) {
+        /* initial allocation of the lock */
+        pending_lock = PyThread_allocate_lock();
+        if (pending_lock == NULL)
+            return -1;
+    }
+
+    /* only service pending calls on main thread */
+    if (main_thread && PyThread_get_thread_ident() != main_thread)
+        return 0;
+    /* don't perform recursive pending calls */
+    if (busy)
+        return 0;
+    busy = 1;
+    /* perform a bounded number of calls, in case of recursion */
+    for (i=0; i<NPENDINGCALLS; i++) {
+        int j;
+        int (*func)(void *);
+        void *arg = NULL;
+
+        /* pop one item off the queue while holding the lock */
+        PyThread_acquire_lock(pending_lock, WAIT_LOCK);
+        j = pendingfirst;
+        if (j == pendinglast) {
+            func = NULL; /* Queue empty */
+        } else {
+            func = pendingcalls[j].func;
+            arg = pendingcalls[j].arg;
+            pendingfirst = (j + 1) % NPENDINGCALLS;
+        }
+        if (pendingfirst != pendinglast)
+            SIGNAL_PENDING_CALLS();
+        else
+            UNSIGNAL_PENDING_CALLS();
+        PyThread_release_lock(pending_lock);
+        /* having released the lock, perform the callback */
+        if (func == NULL)
+            break;
+        r = func(arg);
+        if (r)
+            break;
+    }
+    busy = 0;
+    return r;
+}
+
+#else /* if ! defined WITH_THREAD */
+
+/*
+   WARNING!  ASYNCHRONOUSLY EXECUTING CODE!
+   This code is used for signal handling in python that isn't built
+   with WITH_THREAD.
+   Don't use this implementation when Py_AddPendingCalls() can happen
+   on a different thread!
+
+   There are two possible race conditions:
+   (1) nested asynchronous calls to Py_AddPendingCall()
+   (2) AddPendingCall() calls made while pending calls are being processed.
+
+   (1) is very unlikely because typically signal delivery
+   is blocked during signal handling.  So it should be impossible.
+   (2) is a real possibility.
+   The current code is safe against (2), but not against (1).
+   The safety against (2) is derived from the fact that only one
+   thread is present, interrupted by signals, and that the critical
+   section is protected with the "busy" variable.  On Windows, which
+   delivers SIGINT on a system thread, this does not hold and therefore
+   Windows really shouldn't use this version.
+   The two threads could theoretically wiggle around the "busy" variable.
+*/
+
+#define NPENDINGCALLS 32
+static struct {
+    int (*func)(void *);
+    void *arg;
+} pendingcalls[NPENDINGCALLS];
+static volatile int pendingfirst = 0;
+static volatile int pendinglast = 0;
+static _Py_atomic_int pendingcalls_to_do = {0};
+
+int
+Py_AddPendingCall(int (*func)(void *), void *arg)
+{
+    static volatile int busy = 0;
+    int i, j;
+    /* XXX Begin critical section */
+    if (busy)
+        return -1;
+    busy = 1;
+    i = pendinglast;
+    j = (i + 1) % NPENDINGCALLS;
+    if (j == pendingfirst) {
+        busy = 0;
+        return -1; /* Queue full */
+    }
+    pendingcalls[i].func = func;
+    pendingcalls[i].arg = arg;
+    pendinglast = j;
+
+    SIGNAL_PENDING_CALLS();
+    busy = 0;
+    /* XXX End critical section */
+    return 0;
+}
+
+int
+Py_MakePendingCalls(void)
+{
+    static int busy = 0;
+    if (busy)
+        return 0;
+    busy = 1;
+    UNSIGNAL_PENDING_CALLS();
+    for (;;) {
+        int i;
+        int (*func)(void *);
+        void *arg;
+        i = pendingfirst;
+        if (i == pendinglast)
+            break; /* Queue empty */
+        func = pendingcalls[i].func;
+        arg = pendingcalls[i].arg;
+        pendingfirst = (i + 1) % NPENDINGCALLS;
+        if (func(arg) < 0) {
+            busy = 0;
+            SIGNAL_PENDING_CALLS(); /* We're not done yet */
+            return -1;
+        }
+    }
+    busy = 0;
+    return 0;
+}
+
+#endif /* WITH_THREAD */
+
+
+/* The interpreter's recursion limit */
+
+#ifndef Py_DEFAULT_RECURSION_LIMIT
+#define Py_DEFAULT_RECURSION_LIMIT 1000
+#endif
+static int recursion_limit = Py_DEFAULT_RECURSION_LIMIT;
+int _Py_CheckRecursionLimit = Py_DEFAULT_RECURSION_LIMIT;
+
+/* the macro Py_EnterRecursiveCall() only calls _Py_CheckRecursiveCall()
+   if the recursion_depth reaches _Py_CheckRecursionLimit.
+   If USE_STACKCHECK, the macro decrements _Py_CheckRecursionLimit
+   to guarantee that _Py_CheckRecursiveCall() is regularly called.
+   Without USE_STACKCHECK, there is no need for this. */
+int
+_Py_CheckRecursiveCall(char *where)
+{
+    PyThreadState *tstate = PyThreadState_GET();
+
+#ifdef USE_STACKCHECK
+    if (PyOS_CheckStack()) {
+        --tstate->recursion_depth;
+        PyErr_SetString(PyExc_MemoryError, "Stack overflow");
+        return -1;
+    }
+#endif
+    _Py_CheckRecursionLimit = recursion_limit;
+    if (tstate->recursion_critical)
+        /* Somebody asked that we don't check for recursion. */
+        return 0;
+    if (tstate->overflowed) {
+        if (tstate->recursion_depth > recursion_limit + 50) {
+            /* Overflowing while handling an overflow. Give up. */
+            Py_FatalError("Cannot recover from stack overflow.");
+        }
+        return 0;
+    }
+    if (tstate->recursion_depth > recursion_limit) {
+        --tstate->recursion_depth;
+        tstate->overflowed = 1;
+        PyErr_Format(PyExc_RuntimeError,
+                     "maximum recursion depth exceeded%s",
+                     where);
+        return -1;
+    }
+    return 0;
+}
+
+/* Status code for main loop (reason for stack unwind) */
+enum why_code {
+        WHY_NOT =       0x0001, /* No error */
+        WHY_EXCEPTION = 0x0002, /* Exception occurred */
+        WHY_RERAISE =   0x0004, /* Exception re-raised by 'finally' */
+        WHY_RETURN =    0x0008, /* 'return' statement */
+        WHY_BREAK =     0x0010, /* 'break' statement */
+        WHY_CONTINUE =  0x0020, /* 'continue' statement */
+        WHY_YIELD =     0x0040, /* 'yield' operator */
+        WHY_SILENCED =  0x0080  /* Exception silenced by 'with' */
+};
+
+static void save_exc_state(PyThreadState *, PyFrameObject *);
+static void swap_exc_state(PyThreadState *, PyFrameObject *);
+static void restore_and_clear_exc_state(PyThreadState *, PyFrameObject *);
+static enum why_code do_raise(PyObject *, PyObject *);
+static int unpack_iterable(PyObject *, int, int, PyObject **);
+
+/* Records whether tracing is on for any thread.  Counts the number of
+   threads for which tstate->c_tracefunc is non-NULL, so if the value
+   is 0, we know we don't have to check this thread's c_tracefunc.
+   This speeds up the if statement in PyEval_EvalFrameEx() after
+   fast_next_opcode*/
+static int _Py_TracingPossible = 0;
+
+
+
+PyObject *
+PyEval_EvalCode(PyObject *co, PyObject *globals, PyObject *locals)
+{
+    return PyEval_EvalCodeEx(co,
+                      globals, locals,
+                      (PyObject **)NULL, 0,
+                      (PyObject **)NULL, 0,
+                      (PyObject **)NULL, 0,
+                      NULL, NULL);
+}
+
+
+/* Interpreter main loop */
+
+PyObject *
+PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
+{
+    register PyObject **stack_pointer;  /* Next free slot in value stack */
+    register unsigned char *next_instr;
+    register int opcode;        /* Current opcode */
+    register int oparg;         /* Current opcode argument, if any */
+    register enum why_code why; /* Reason for block stack unwind */
+    register int err;           /* Error status -- nonzero if error */
+    register PyObject *x;       /* Result object -- NULL if error */
+    register PyObject *v;       /* Temporary objects popped off stack */
+    register PyObject *w;
+    register PyObject *u;
+    register PyObject *t;
+    register PyObject **fastlocals, **freevars;
+    PyObject *retval = NULL;            /* Return value */
+    PyThreadState *tstate = PyThreadState_GET();
+    PyCodeObject *co;
+
+    /* when tracing we set things up so that
+
+           not (instr_lb <= current_bytecode_offset < instr_ub)
+
+       is true when the line being executed has changed.  The
+       initial values are such as to make this false the first
+       time it is tested. */
+    int instr_ub = -1, instr_lb = 0, instr_prev = -1;
+
+    unsigned char *first_instr;
+    PyObject *names;
+    PyObject *consts;
+
+/* Computed GOTOs, or
+       the-optimization-commonly-but-improperly-known-as-"threaded code"
+   using gcc's labels-as-values extension
+   (http://gcc.gnu.org/onlinedocs/gcc/Labels-as-Values.html).
+
+   The traditional bytecode evaluation loop uses a "switch" statement, which
+   decent compilers will optimize as a single indirect branch instruction
+   combined with a lookup table of jump addresses. However, since the
+   indirect jump instruction is shared by all opcodes, the CPU will have a
+   hard time making the right prediction for where to jump next (actually,
+   it will be always wrong except in the uncommon case of a sequence of
+   several identical opcodes).
+
+   "Threaded code" in contrast, uses an explicit jump table and an explicit
+   indirect jump instruction at the end of each opcode. Since the jump
+   instruction is at a different address for each opcode, the CPU will make a
+   separate prediction for each of these instructions, which is equivalent to
+   predicting the second opcode of each opcode pair. These predictions have
+   a much better chance to turn out valid, especially in small bytecode loops.
+
+   A mispredicted branch on a modern CPU flushes the whole pipeline and
+   can cost several CPU cycles (depending on the pipeline depth),
+   and potentially many more instructions (depending on the pipeline width).
+   A correctly predicted branch, however, is nearly free.
+
+   At the time of this writing, the "threaded code" version is up to 15-20%
+   faster than the normal "switch" version, depending on the compiler and the
+   CPU architecture.
+
+   We disable the optimization if DYNAMIC_EXECUTION_PROFILE is defined,
+   because it would render the measurements invalid.
+
+
+   NOTE: care must be taken that the compiler doesn't try to "optimize" the
+   indirect jumps by sharing them between all opcodes. Such optimizations
+   can be disabled on gcc by using the -fno-gcse flag (or possibly
+   -fno-crossjumping).
+*/
+
+#ifdef DYNAMIC_EXECUTION_PROFILE
+#undef USE_COMPUTED_GOTOS
+#define USE_COMPUTED_GOTOS 0
+#endif
+
+#ifdef HAVE_COMPUTED_GOTOS
+    #ifndef USE_COMPUTED_GOTOS
+    #define USE_COMPUTED_GOTOS 1
+    #endif
+#else
+    #if defined(USE_COMPUTED_GOTOS) && USE_COMPUTED_GOTOS
+    #error "Computed gotos are not supported on this compiler."
+    #endif
+    #undef USE_COMPUTED_GOTOS
+    #define USE_COMPUTED_GOTOS 0
+#endif
+
+#if USE_COMPUTED_GOTOS
+/* Import the static jump table */
+#include "opcode_targets.h"
+
+/* This macro is used when several opcodes defer to the same implementation
+   (e.g. SETUP_LOOP, SETUP_FINALLY) */
+#define TARGET_WITH_IMPL(op, impl) \
+    TARGET_##op: \
+        opcode = op; \
+        if (HAS_ARG(op)) \
+            oparg = NEXTARG(); \
+    case op: \
+        goto impl; \
+
+#define TARGET(op) \
+    TARGET_##op: \
+        opcode = op; \
+        if (HAS_ARG(op)) \
+            oparg = NEXTARG(); \
+    case op:
+
+
+#define DISPATCH() \
+    { \
+        if (!_Py_atomic_load_relaxed(&eval_breaker)) {      \
+                    FAST_DISPATCH(); \
+        } \
+        continue; \
+    }
+
+#ifdef LLTRACE
+#define FAST_DISPATCH() \
+    { \
+        if (!lltrace && !_Py_TracingPossible) { \
+            f->f_lasti = INSTR_OFFSET(); \
+            goto *opcode_targets[*next_instr++]; \
+        } \
+        goto fast_next_opcode; \
+    }
+#else
+#define FAST_DISPATCH() \
+    { \
+        if (!_Py_TracingPossible) { \
+            f->f_lasti = INSTR_OFFSET(); \
+            goto *opcode_targets[*next_instr++]; \
+        } \
+        goto fast_next_opcode; \
+    }
+#endif
+
+#else
+#define TARGET(op) \
+    case op:
+#define TARGET_WITH_IMPL(op, impl) \
+    /* silence compiler warnings about `impl` unused */ \
+    if (0) goto impl; \
+    case op:
+#define DISPATCH() continue
+#define FAST_DISPATCH() goto fast_next_opcode
+#endif
+
+
+/* Tuple access macros */
+
+#ifndef Py_DEBUG
+#define GETITEM(v, i) PyTuple_GET_ITEM((PyTupleObject *)(v), (i))
+#else
+#define GETITEM(v, i) PyTuple_GetItem((v), (i))
+#endif
+
+#ifdef WITH_TSC
+/* Use Pentium timestamp counter to mark certain events:
+   inst0 -- beginning of switch statement for opcode dispatch
+   inst1 -- end of switch statement (may be skipped)
+   loop0 -- the top of the mainloop
+   loop1 -- place where control returns again to top of mainloop
+            (may be skipped)
+   intr1 -- beginning of long interruption
+   intr2 -- end of long interruption
+
+   Many opcodes call out to helper C functions.  In some cases, the
+   time in those functions should be counted towards the time for the
+   opcode, but not in all cases.  For example, a CALL_FUNCTION opcode
+   calls another Python function; there's no point in charge all the
+   bytecode executed by the called function to the caller.
+
+   It's hard to make a useful judgement statically.  In the presence
+   of operator overloading, it's impossible to tell if a call will
+   execute new Python code or not.
+
+   It's a case-by-case judgement.  I'll use intr1 for the following
+   cases:
+
+   IMPORT_STAR
+   IMPORT_FROM
+   CALL_FUNCTION (and friends)
+
+ */
+    uint64 inst0, inst1, loop0, loop1, intr0 = 0, intr1 = 0;
+    int ticked = 0;
+
+    READ_TIMESTAMP(inst0);
+    READ_TIMESTAMP(inst1);
+    READ_TIMESTAMP(loop0);
+    READ_TIMESTAMP(loop1);
+
+    /* shut up the compiler */
+    opcode = 0;
+#endif
+
+/* Code access macros */
+
+#define INSTR_OFFSET()  ((int)(next_instr - first_instr))
+#define NEXTOP()        (*next_instr++)
+#define NEXTARG()       (next_instr += 2, (next_instr[-1]<<8) + next_instr[-2])
+#define PEEKARG()       ((next_instr[2]<<8) + next_instr[1])
+#define JUMPTO(x)       (next_instr = first_instr + (x))
+#define JUMPBY(x)       (next_instr += (x))
+
+/* OpCode prediction macros
+    Some opcodes tend to come in pairs thus making it possible to
+    predict the second code when the first is run.  For example,
+    COMPARE_OP is often followed by JUMP_IF_FALSE or JUMP_IF_TRUE.  And,
+    those opcodes are often followed by a POP_TOP.
+
+    Verifying the prediction costs a single high-speed test of a register
+    variable against a constant.  If the pairing was good, then the
+    processor's own internal branch predication has a high likelihood of
+    success, resulting in a nearly zero-overhead transition to the
+    next opcode.  A successful prediction saves a trip through the eval-loop
+    including its two unpredictable branches, the HAS_ARG test and the
+    switch-case.  Combined with the processor's internal branch prediction,
+    a successful PREDICT has the effect of making the two opcodes run as if
+    they were a single new opcode with the bodies combined.
+
+    If collecting opcode statistics, your choices are to either keep the
+    predictions turned-on and interpret the results as if some opcodes
+    had been combined or turn-off predictions so that the opcode frequency
+    counter updates for both opcodes.
+
+    Opcode prediction is disabled with threaded code, since the latter allows
+    the CPU to record separate branch prediction information for each
+    opcode.
+
+*/
+
+#if defined(DYNAMIC_EXECUTION_PROFILE) || USE_COMPUTED_GOTOS
+#define PREDICT(op)             if (0) goto PRED_##op
+#define PREDICTED(op)           PRED_##op:
+#define PREDICTED_WITH_ARG(op)  PRED_##op:
+#else
+#define PREDICT(op)             if (*next_instr == op) goto PRED_##op
+#define PREDICTED(op)           PRED_##op: next_instr++
+#define PREDICTED_WITH_ARG(op)  PRED_##op: oparg = PEEKARG(); next_instr += 3
+#endif
+
+
+/* Stack manipulation macros */
+
+/* The stack can grow at most MAXINT deep, as co_nlocals and
+   co_stacksize are ints. */
+#define STACK_LEVEL()     ((int)(stack_pointer - f->f_valuestack))
+#define EMPTY()           (STACK_LEVEL() == 0)
+#define TOP()             (stack_pointer[-1])
+#define SECOND()          (stack_pointer[-2])
+#define THIRD()           (stack_pointer[-3])
+#define FOURTH()          (stack_pointer[-4])
+#define PEEK(n)           (stack_pointer[-(n)])
+#define SET_TOP(v)        (stack_pointer[-1] = (v))
+#define SET_SECOND(v)     (stack_pointer[-2] = (v))
+#define SET_THIRD(v)      (stack_pointer[-3] = (v))
+#define SET_FOURTH(v)     (stack_pointer[-4] = (v))
+#define SET_VALUE(n, v)   (stack_pointer[-(n)] = (v))
+#define BASIC_STACKADJ(n) (stack_pointer += n)
+#define BASIC_PUSH(v)     (*stack_pointer++ = (v))
+#define BASIC_POP()       (*--stack_pointer)
+
+#define PUSH(v)                BASIC_PUSH(v)
+#define POP()                  BASIC_POP()
+#define STACKADJ(n)            BASIC_STACKADJ(n)
+#define EXT_POP(STACK_POINTER) (*--(STACK_POINTER))
+
+/* Local variable macros */
+
+#define GETLOCAL(i)     (fastlocals[i])
+
+/* The SETLOCAL() macro must not DECREF the local variable in-place and
+   then store the new value; it must copy the old value to a temporary
+   value, then store the new value, and then DECREF the temporary value.
+   This is because it is possible that during the DECREF the frame is
+   accessed by other code (e.g. a __del__ method or gc.collect()) and the
+   variable would be pointing to already-freed memory. */
+#define SETLOCAL(i, value)      do { PyObject *tmp = GETLOCAL(i); \
+                                     GETLOCAL(i) = value; \
+                                     Py_XDECREF(tmp); } while (0)
+
+
+#define UNWIND_BLOCK(b) \
+    while (STACK_LEVEL() > (b)->b_level) { \
+        PyObject *v = POP(); \
+        Py_XDECREF(v); \
+    }
+
+#define UNWIND_EXCEPT_HANDLER(b) \
+    { \
+        PyObject *type, *value, *traceback; \
+        assert(STACK_LEVEL() >= (b)->b_level + 3); \
+        while (STACK_LEVEL() > (b)->b_level + 3) { \
+            value = POP(); \
+            Py_XDECREF(value); \
+        } \
+        type = tstate->exc_type; \
+        value = tstate->exc_value; \
+        traceback = tstate->exc_traceback; \
+        tstate->exc_type = POP(); \
+        tstate->exc_value = POP(); \
+        tstate->exc_traceback = POP(); \
+        Py_XDECREF(type); \
+        Py_XDECREF(value); \
+        Py_XDECREF(traceback); \
+    }
+
+/* Start of code */
+
+    /* push frame */
+    if (Py_EnterRecursiveCall(""))
+        return NULL;
+
+    tstate->frame = f;
+
+    if (tstate->use_tracing) {
+        if (tstate->c_tracefunc != NULL) {
+            /* tstate->c_tracefunc, if defined, is a
+               function that will be called on *every* entry
+               to a code block.  Its return value, if not
+               None, is a function that will be called at
+               the start of each executed line of code.
+               (Actually, the function must return itself
+               in order to continue tracing.)  The trace
+               functions are called with three arguments:
+               a pointer to the current frame, a string
+               indicating why the function is called, and
+               an argument which depends on the situation.
+               The global trace function is also called
+               whenever an exception is detected. */
+            if (call_trace_protected(tstate->c_tracefunc,
+                                     tstate->c_traceobj,
+                                     f, PyTrace_CALL, Py_None)) {
+                /* Trace function raised an error */
+                goto exit_eval_frame;
+            }
+        }
+        if (tstate->c_profilefunc != NULL) {
+            /* Similar for c_profilefunc, except it needn't
+               return itself and isn't called for "line" events */
+            if (call_trace_protected(tstate->c_profilefunc,
+                                     tstate->c_profileobj,
+                                     f, PyTrace_CALL, Py_None)) {
+                /* Profile function raised an error */
+                goto exit_eval_frame;
+            }
+        }
+    }
+
+    co = f->f_code;
+    names = co->co_names;
+    consts = co->co_consts;
+    fastlocals = f->f_localsplus;
+    freevars = f->f_localsplus + co->co_nlocals;
+    first_instr = (unsigned char*) PyBytes_AS_STRING(co->co_code);
+    /* An explanation is in order for the next line.
+
+       f->f_lasti now refers to the index of the last instruction
+       executed.  You might think this was obvious from the name, but
+       this wasn't always true before 2.3!  PyFrame_New now sets
+       f->f_lasti to -1 (i.e. the index *before* the first instruction)
+       and YIELD_VALUE doesn't fiddle with f_lasti any more.  So this
+       does work.  Promise.
+
+       When the PREDICT() macros are enabled, some opcode pairs follow in
+       direct succession without updating f->f_lasti.  A successful
+       prediction effectively links the two codes together as if they
+       were a single new opcode; accordingly,f->f_lasti will point to
+       the first code in the pair (for instance, GET_ITER followed by
+       FOR_ITER is effectively a single opcode and f->f_lasti will point
+       at to the beginning of the combined pair.)
+    */
+    next_instr = first_instr + f->f_lasti + 1;
+    stack_pointer = f->f_stacktop;
+    assert(stack_pointer != NULL);
+    f->f_stacktop = NULL;       /* remains NULL unless yield suspends frame */
+
+    if (co->co_flags & CO_GENERATOR && !throwflag) {
+        if (f->f_exc_type != NULL && f->f_exc_type != Py_None) {
+            /* We were in an except handler when we left,
+               restore the exception state which was put aside
+               (see YIELD_VALUE). */
+            swap_exc_state(tstate, f);
+        }
+        else
+            save_exc_state(tstate, f);
+    }
+
+    why = WHY_NOT;
+    err = 0;
+    x = Py_None;        /* Not a reference, just anything non-NULL */
+    w = NULL;
+
+    if (throwflag) { /* support for generator.throw() */
+        why = WHY_EXCEPTION;
+        goto on_error;
+    }
+
+    for (;;) {
+        assert(stack_pointer >= f->f_valuestack); /* else underflow */
+        assert(STACK_LEVEL() <= co->co_stacksize);  /* else overflow */
+
+        /* Do periodic things.  Doing this every time through
+           the loop would add too much overhead, so we do it
+           only every Nth instruction.  We also do it if
+           ``pendingcalls_to_do'' is set, i.e. when an asynchronous
+           event needs attention (e.g. a signal handler or
+           async I/O handler); see Py_AddPendingCall() and
+           Py_MakePendingCalls() above. */
+
+        if (_Py_atomic_load_relaxed(&eval_breaker)) {
+            if (*next_instr == SETUP_FINALLY) {
+                /* Make the last opcode before
+                   a try: finally: block uninterruptible. */
+                goto fast_next_opcode;
+            }
+            tstate->tick_counter++;
+            if (_Py_atomic_load_relaxed(&pendingcalls_to_do)) {
+                if (Py_MakePendingCalls() < 0) {
+                    why = WHY_EXCEPTION;
+                    goto on_error;
+                }
+            }
+#ifdef WITH_THREAD
+            if (_Py_atomic_load_relaxed(&gil_drop_request)) {
+                /* Give another thread a chance */
+                if (PyThreadState_Swap(NULL) != tstate)
+                    Py_FatalError("ceval: tstate mix-up");
+                drop_gil(tstate);
+
+                /* Other threads may run now */
+
+                take_gil(tstate);
+                if (PyThreadState_Swap(tstate) != NULL)
+                    Py_FatalError("ceval: orphan tstate");
+            }
+#endif
+            /* Check for asynchronous exceptions. */
+            if (tstate->async_exc != NULL) {
+                x = tstate->async_exc;
+                tstate->async_exc = NULL;
+                UNSIGNAL_ASYNC_EXC();
+                PyErr_SetNone(x);
+                Py_DECREF(x);
+                why = WHY_EXCEPTION;
+                goto on_error;
+            }
+        }
+
+    fast_next_opcode:
+        f->f_lasti = INSTR_OFFSET();
+
+        /* line-by-line tracing support */
+
+        if (_Py_TracingPossible &&
+            tstate->c_tracefunc != NULL && !tstate->tracing) {
+            /* see maybe_call_line_trace
+               for expository comments */
+            f->f_stacktop = stack_pointer;
+
+            err = maybe_call_line_trace(tstate->c_tracefunc,
+                                        tstate->c_traceobj,
+                                        f, &instr_lb, &instr_ub,
+                                        &instr_prev);
+            /* Reload possibly changed frame fields */
+            JUMPTO(f->f_lasti);
+            if (f->f_stacktop != NULL) {
+                stack_pointer = f->f_stacktop;
+                f->f_stacktop = NULL;
+            }
+            if (err) {
+                /* trace function raised an exception */
+                goto on_error;
+            }
+        }
+
+        /* Extract opcode and argument */
+
+        opcode = NEXTOP();
+        oparg = 0;   /* allows oparg to be stored in a register because
+            it doesn't have to be remembered across a full loop */
+        if (HAS_ARG(opcode))
+            oparg = NEXTARG();
+    dispatch_opcode:
+
+        /* Main switch on opcode */
+
+        switch (opcode) {
+
+        /* BEWARE!
+           It is essential that any operation that fails sets either
+           x to NULL, err to nonzero, or why to anything but WHY_NOT,
+           and that no operation that succeeds does this! */
+
+        TARGET(NOP)
+            FAST_DISPATCH();
+
+        TARGET(LOAD_FAST)
+            x = GETLOCAL(oparg);
+            if (x != NULL) {
+                Py_INCREF(x);
+                PUSH(x);
+                FAST_DISPATCH();
+            }
+            format_exc_check_arg(PyExc_UnboundLocalError,
+                UNBOUNDLOCAL_ERROR_MSG,
+                PyTuple_GetItem(co->co_varnames, oparg));
+            break;
+
+        TARGET(LOAD_CONST)
+            x = GETITEM(consts, oparg);
+            Py_INCREF(x);
+            PUSH(x);
+            FAST_DISPATCH();
+
+        PREDICTED_WITH_ARG(STORE_FAST);
+        TARGET(STORE_FAST)
+            v = POP();
+            SETLOCAL(oparg, v);
+            FAST_DISPATCH();
+
+        TARGET(POP_TOP)
+            v = POP();
+            Py_DECREF(v);
+            FAST_DISPATCH();
+
+        TARGET(ROT_TWO)
+            v = TOP();
+            w = SECOND();
+            SET_TOP(w);
+            SET_SECOND(v);
+            FAST_DISPATCH();
+
+        TARGET(ROT_THREE)
+            v = TOP();
+            w = SECOND();
+            x = THIRD();
+            SET_TOP(w);
+            SET_SECOND(x);
+            SET_THIRD(v);
+            FAST_DISPATCH();
+
+        TARGET(DUP_TOP)
+            v = TOP();
+            Py_INCREF(v);
+            PUSH(v);
+            FAST_DISPATCH();
+
+        TARGET(DUP_TOP_TWO)
+            x = TOP();
+            Py_INCREF(x);
+            w = SECOND();
+            Py_INCREF(w);
+            STACKADJ(2);
+            SET_TOP(x);
+            SET_SECOND(w);
+            FAST_DISPATCH();
+
+        TARGET(UNARY_POSITIVE)
+            v = TOP();
+            x = PyNumber_Positive(v);
+            Py_DECREF(v);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(UNARY_NEGATIVE)
+            v = TOP();
+            x = PyNumber_Negative(v);
+            Py_DECREF(v);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(UNARY_NOT)
+            v = TOP();
+            err = PyObject_IsTrue(v);
+            Py_DECREF(v);
+            if (err == 0) {
+                Py_INCREF(Py_True);
+                SET_TOP(Py_True);
+                DISPATCH();
+            }
+            else if (err > 0) {
+                Py_INCREF(Py_False);
+                SET_TOP(Py_False);
+                err = 0;
+                DISPATCH();
+            }
+            STACKADJ(-1);
+            break;
+
+        TARGET(UNARY_INVERT)
+            v = TOP();
+            x = PyNumber_Invert(v);
+            Py_DECREF(v);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(BINARY_POWER)
+            w = POP();
+            v = TOP();
+            x = PyNumber_Power(v, w, Py_None);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(BINARY_MULTIPLY)
+            w = POP();
+            v = TOP();
+            x = PyNumber_Multiply(v, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(BINARY_TRUE_DIVIDE)
+            w = POP();
+            v = TOP();
+            x = PyNumber_TrueDivide(v, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(BINARY_FLOOR_DIVIDE)
+            w = POP();
+            v = TOP();
+            x = PyNumber_FloorDivide(v, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(BINARY_MODULO)
+            w = POP();
+            v = TOP();
+            if (PyUnicode_CheckExact(v))
+                x = PyUnicode_Format(v, w);
+            else
+                x = PyNumber_Remainder(v, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(BINARY_ADD)
+            w = POP();
+            v = TOP();
+            if (PyUnicode_CheckExact(v) &&
+                     PyUnicode_CheckExact(w)) {
+                x = unicode_concatenate(v, w, f, next_instr);
+                /* unicode_concatenate consumed the ref to v */
+                goto skip_decref_vx;
+            }
+            else {
+                x = PyNumber_Add(v, w);
+            }
+            Py_DECREF(v);
+          skip_decref_vx:
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(BINARY_SUBTRACT)
+            w = POP();
+            v = TOP();
+            x = PyNumber_Subtract(v, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(BINARY_SUBSCR)
+            w = POP();
+            v = TOP();
+            x = PyObject_GetItem(v, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(BINARY_LSHIFT)
+            w = POP();
+            v = TOP();
+            x = PyNumber_Lshift(v, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(BINARY_RSHIFT)
+            w = POP();
+            v = TOP();
+            x = PyNumber_Rshift(v, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(BINARY_AND)
+            w = POP();
+            v = TOP();
+            x = PyNumber_And(v, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(BINARY_XOR)
+            w = POP();
+            v = TOP();
+            x = PyNumber_Xor(v, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(BINARY_OR)
+            w = POP();
+            v = TOP();
+            x = PyNumber_Or(v, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(LIST_APPEND)
+            w = POP();
+            v = PEEK(oparg);
+            err = PyList_Append(v, w);
+            Py_DECREF(w);
+            if (err == 0) {
+                PREDICT(JUMP_ABSOLUTE);
+                DISPATCH();
+            }
+            break;
+
+        TARGET(SET_ADD)
+            w = POP();
+            v = stack_pointer[-oparg];
+            err = PySet_Add(v, w);
+            Py_DECREF(w);
+            if (err == 0) {
+                PREDICT(JUMP_ABSOLUTE);
+                DISPATCH();
+            }
+            break;
+
+        TARGET(INPLACE_POWER)
+            w = POP();
+            v = TOP();
+            x = PyNumber_InPlacePower(v, w, Py_None);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(INPLACE_MULTIPLY)
+            w = POP();
+            v = TOP();
+            x = PyNumber_InPlaceMultiply(v, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(INPLACE_TRUE_DIVIDE)
+            w = POP();
+            v = TOP();
+            x = PyNumber_InPlaceTrueDivide(v, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(INPLACE_FLOOR_DIVIDE)
+            w = POP();
+            v = TOP();
+            x = PyNumber_InPlaceFloorDivide(v, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(INPLACE_MODULO)
+            w = POP();
+            v = TOP();
+            x = PyNumber_InPlaceRemainder(v, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(INPLACE_ADD)
+            w = POP();
+            v = TOP();
+            if (PyUnicode_CheckExact(v) &&
+                     PyUnicode_CheckExact(w)) {
+                x = unicode_concatenate(v, w, f, next_instr);
+                /* unicode_concatenate consumed the ref to v */
+                goto skip_decref_v;
+            }
+            else {
+                x = PyNumber_InPlaceAdd(v, w);
+            }
+            Py_DECREF(v);
+          skip_decref_v:
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(INPLACE_SUBTRACT)
+            w = POP();
+            v = TOP();
+            x = PyNumber_InPlaceSubtract(v, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(INPLACE_LSHIFT)
+            w = POP();
+            v = TOP();
+            x = PyNumber_InPlaceLshift(v, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(INPLACE_RSHIFT)
+            w = POP();
+            v = TOP();
+            x = PyNumber_InPlaceRshift(v, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(INPLACE_AND)
+            w = POP();
+            v = TOP();
+            x = PyNumber_InPlaceAnd(v, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(INPLACE_XOR)
+            w = POP();
+            v = TOP();
+            x = PyNumber_InPlaceXor(v, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(INPLACE_OR)
+            w = POP();
+            v = TOP();
+            x = PyNumber_InPlaceOr(v, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(STORE_SUBSCR)
+            w = TOP();
+            v = SECOND();
+            u = THIRD();
+            STACKADJ(-3);
+            /* v[w] = u */
+            err = PyObject_SetItem(v, w, u);
+            Py_DECREF(u);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            if (err == 0) DISPATCH();
+            break;
+
+        TARGET(DELETE_SUBSCR)
+            w = TOP();
+            v = SECOND();
+            STACKADJ(-2);
+            /* del v[w] */
+            err = PyObject_DelItem(v, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            if (err == 0) DISPATCH();
+            break;
+
+        TARGET(PRINT_EXPR)
+            v = POP();
+            w = PySys_GetObject("displayhook");
+            if (w == NULL) {
+                PyErr_SetString(PyExc_RuntimeError,
+                                "lost sys.displayhook");
+                err = -1;
+                x = NULL;
+            }
+            if (err == 0) {
+                x = PyTuple_Pack(1, v);
+                if (x == NULL)
+                    err = -1;
+            }
+            if (err == 0) {
+                w = PyEval_CallObject(w, x);
+                Py_XDECREF(w);
+                if (w == NULL)
+                    err = -1;
+            }
+            Py_DECREF(v);
+            Py_XDECREF(x);
+            break;
+
+        TARGET(RAISE_VARARGS)
+            v = w = NULL;
+            switch (oparg) {
+            case 2:
+                v = POP(); /* cause */
+            case 1:
+                w = POP(); /* exc */
+            case 0: /* Fallthrough */
+                why = do_raise(w, v);
+                break;
+            default:
+                PyErr_SetString(PyExc_SystemError,
+                           "bad RAISE_VARARGS oparg");
+                why = WHY_EXCEPTION;
+                break;
+            }
+            break;
+
+        TARGET(STORE_LOCALS)
+            x = POP();
+            v = f->f_locals;
+            Py_XDECREF(v);
+            f->f_locals = x;
+            DISPATCH();
+
+        TARGET(RETURN_VALUE)
+            retval = POP();
+            why = WHY_RETURN;
+            goto fast_block_end;
+
+        TARGET(YIELD_VALUE)
+            retval = POP();
+            f->f_stacktop = stack_pointer;
+            why = WHY_YIELD;
+            goto fast_yield;
+
+        TARGET(POP_EXCEPT)
+            {
+                PyTryBlock *b = PyFrame_BlockPop(f);
+                if (b->b_type != EXCEPT_HANDLER) {
+                    PyErr_SetString(PyExc_SystemError,
+                        "popped block is not an except handler");
+                    why = WHY_EXCEPTION;
+                    break;
+                }
+                UNWIND_EXCEPT_HANDLER(b);
+            }
+            DISPATCH();
+
+        TARGET(POP_BLOCK)
+            {
+                PyTryBlock *b = PyFrame_BlockPop(f);
+                UNWIND_BLOCK(b);
+            }
+            DISPATCH();
+
+        PREDICTED(END_FINALLY);
+        TARGET(END_FINALLY)
+            v = POP();
+            if (PyLong_Check(v)) {
+                why = (enum why_code) PyLong_AS_LONG(v);
+                assert(why != WHY_YIELD);
+                if (why == WHY_RETURN ||
+                    why == WHY_CONTINUE)
+                    retval = POP();
+                if (why == WHY_SILENCED) {
+                    /* An exception was silenced by 'with', we must
+                    manually unwind the EXCEPT_HANDLER block which was
+                    created when the exception was caught, otherwise
+                    the stack will be in an inconsistent state. */
+                    PyTryBlock *b = PyFrame_BlockPop(f);
+                    assert(b->b_type == EXCEPT_HANDLER);
+                    UNWIND_EXCEPT_HANDLER(b);
+                    why = WHY_NOT;
+                }
+            }
+            else if (PyExceptionClass_Check(v)) {
+                w = POP();
+                u = POP();
+                PyErr_Restore(v, w, u);
+                why = WHY_RERAISE;
+                break;
+            }
+            else if (v != Py_None) {
+                PyErr_SetString(PyExc_SystemError,
+                    "'finally' pops bad exception");
+                why = WHY_EXCEPTION;
+            }
+            Py_DECREF(v);
+            break;
+
+        TARGET(LOAD_BUILD_CLASS)
+            x = PyDict_GetItemString(f->f_builtins,
+                                     "__build_class__");
+            if (x == NULL) {
+                PyErr_SetString(PyExc_ImportError,
+                                "__build_class__ not found");
+                break;
+            }
+            Py_INCREF(x);
+            PUSH(x);
+            break;
+
+        TARGET(STORE_NAME)
+            w = GETITEM(names, oparg);
+            v = POP();
+            if ((x = f->f_locals) != NULL) {
+                if (PyDict_CheckExact(x))
+                    err = PyDict_SetItem(x, w, v);
+                else
+                    err = PyObject_SetItem(x, w, v);
+                Py_DECREF(v);
+                if (err == 0) DISPATCH();
+                break;
+            }
+            PyErr_Format(PyExc_SystemError,
+                         "no locals found when storing %R", w);
+            break;
+
+        TARGET(DELETE_NAME)
+            w = GETITEM(names, oparg);
+            if ((x = f->f_locals) != NULL) {
+                if ((err = PyObject_DelItem(x, w)) != 0)
+                    format_exc_check_arg(PyExc_NameError,
+                                         NAME_ERROR_MSG,
+                                         w);
+                break;
+            }
+            PyErr_Format(PyExc_SystemError,
+                         "no locals when deleting %R", w);
+            break;
+
+        PREDICTED_WITH_ARG(UNPACK_SEQUENCE);
+        TARGET(UNPACK_SEQUENCE)
+            v = POP();
+            if (PyTuple_CheckExact(v) &&
+                PyTuple_GET_SIZE(v) == oparg) {
+                PyObject **items = \
+                    ((PyTupleObject *)v)->ob_item;
+                while (oparg--) {
+                    w = items[oparg];
+                    Py_INCREF(w);
+                    PUSH(w);
+                }
+                Py_DECREF(v);
+                DISPATCH();
+            } else if (PyList_CheckExact(v) &&
+                       PyList_GET_SIZE(v) == oparg) {
+                PyObject **items = \
+                    ((PyListObject *)v)->ob_item;
+                while (oparg--) {
+                    w = items[oparg];
+                    Py_INCREF(w);
+                    PUSH(w);
+                }
+            } else if (unpack_iterable(v, oparg, -1,
+                                       stack_pointer + oparg)) {
+                STACKADJ(oparg);
+            } else {
+                /* unpack_iterable() raised an exception */
+                why = WHY_EXCEPTION;
+            }
+            Py_DECREF(v);
+            break;
+
+        TARGET(UNPACK_EX)
+        {
+            int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8);
+            v = POP();
+
+            if (unpack_iterable(v, oparg & 0xFF, oparg >> 8,
+                                stack_pointer + totalargs)) {
+                stack_pointer += totalargs;
+            } else {
+                why = WHY_EXCEPTION;
+            }
+            Py_DECREF(v);
+            break;
+        }
+
+        TARGET(STORE_ATTR)
+            w = GETITEM(names, oparg);
+            v = TOP();
+            u = SECOND();
+            STACKADJ(-2);
+            err = PyObject_SetAttr(v, w, u); /* v.w = u */
+            Py_DECREF(v);
+            Py_DECREF(u);
+            if (err == 0) DISPATCH();
+            break;
+
+        TARGET(DELETE_ATTR)
+            w = GETITEM(names, oparg);
+            v = POP();
+            err = PyObject_SetAttr(v, w, (PyObject *)NULL);
+                                            /* del v.w */
+            Py_DECREF(v);
+            break;
+
+        TARGET(STORE_GLOBAL)
+            w = GETITEM(names, oparg);
+            v = POP();
+            err = PyDict_SetItem(f->f_globals, w, v);
+            Py_DECREF(v);
+            if (err == 0) DISPATCH();
+            break;
+
+        TARGET(DELETE_GLOBAL)
+            w = GETITEM(names, oparg);
+            if ((err = PyDict_DelItem(f->f_globals, w)) != 0)
+                format_exc_check_arg(
+                    PyExc_NameError, GLOBAL_NAME_ERROR_MSG, w);
+            break;
+
+        TARGET(LOAD_NAME)
+            w = GETITEM(names, oparg);
+            if ((v = f->f_locals) == NULL) {
+                PyErr_Format(PyExc_SystemError,
+                             "no locals when loading %R", w);
+                why = WHY_EXCEPTION;
+                break;
+            }
+            if (PyDict_CheckExact(v)) {
+                x = PyDict_GetItem(v, w);
+                Py_XINCREF(x);
+            }
+            else {
+                x = PyObject_GetItem(v, w);
+                if (x == NULL && PyErr_Occurred()) {
+                    if (!PyErr_ExceptionMatches(
+                                    PyExc_KeyError))
+                        break;
+                    PyErr_Clear();
+                }
+            }
+            if (x == NULL) {
+                x = PyDict_GetItem(f->f_globals, w);
+                if (x == NULL) {
+                    x = PyDict_GetItem(f->f_builtins, w);
+                    if (x == NULL) {
+                        format_exc_check_arg(
+                                    PyExc_NameError,
+                                    NAME_ERROR_MSG, w);
+                        break;
+                    }
+                }
+                Py_INCREF(x);
+            }
+            PUSH(x);
+            DISPATCH();
+
+        TARGET(LOAD_GLOBAL)
+            w = GETITEM(names, oparg);
+            if (PyUnicode_CheckExact(w)) {
+                /* Inline the PyDict_GetItem() calls.
+                   WARNING: this is an extreme speed hack.
+                   Do not try this at home. */
+                Py_hash_t hash = ((PyASCIIObject *)w)->hash;
+                if (hash != -1) {
+                    PyDictObject *d;
+                    PyDictEntry *e;
+                    d = (PyDictObject *)(f->f_globals);
+                    e = d->ma_lookup(d, w, hash);
+                    if (e == NULL) {
+                        x = NULL;
+                        break;
+                    }
+                    x = e->me_value;
+                    if (x != NULL) {
+                        Py_INCREF(x);
+                        PUSH(x);
+                        DISPATCH();
+                    }
+                    d = (PyDictObject *)(f->f_builtins);
+                    e = d->ma_lookup(d, w, hash);
+                    if (e == NULL) {
+                        x = NULL;
+                        break;
+                    }
+                    x = e->me_value;
+                    if (x != NULL) {
+                        Py_INCREF(x);
+                        PUSH(x);
+                        DISPATCH();
+                    }
+                    goto load_global_error;
+                }
+            }
+            /* This is the un-inlined version of the code above */
+            x = PyDict_GetItem(f->f_globals, w);
+            if (x == NULL) {
+                x = PyDict_GetItem(f->f_builtins, w);
+                if (x == NULL) {
+                  load_global_error:
+                    format_exc_check_arg(
+                                PyExc_NameError,
+                                GLOBAL_NAME_ERROR_MSG, w);
+                    break;
+                }
+            }
+            Py_INCREF(x);
+            PUSH(x);
+            DISPATCH();
+
+        TARGET(DELETE_FAST)
+            x = GETLOCAL(oparg);
+            if (x != NULL) {
+                SETLOCAL(oparg, NULL);
+                DISPATCH();
+            }
+            format_exc_check_arg(
+                PyExc_UnboundLocalError,
+                UNBOUNDLOCAL_ERROR_MSG,
+                PyTuple_GetItem(co->co_varnames, oparg)
+                );
+            break;
+
+        TARGET(DELETE_DEREF)
+            x = freevars[oparg];
+            if (PyCell_GET(x) != NULL) {
+                PyCell_Set(x, NULL);
+                DISPATCH();
+            }
+            err = -1;
+            format_exc_unbound(co, oparg);
+            break;
+
+        TARGET(LOAD_CLOSURE)
+            x = freevars[oparg];
+            Py_INCREF(x);
+            PUSH(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(LOAD_DEREF)
+            x = freevars[oparg];
+            w = PyCell_Get(x);
+            if (w != NULL) {
+                PUSH(w);
+                DISPATCH();
+            }
+            err = -1;
+            format_exc_unbound(co, oparg);
+            break;
+
+        TARGET(STORE_DEREF)
+            w = POP();
+            x = freevars[oparg];
+            PyCell_Set(x, w);
+            Py_DECREF(w);
+            DISPATCH();
+
+        TARGET(BUILD_TUPLE)
+            x = PyTuple_New(oparg);
+            if (x != NULL) {
+                for (; --oparg >= 0;) {
+                    w = POP();
+                    PyTuple_SET_ITEM(x, oparg, w);
+                }
+                PUSH(x);
+                DISPATCH();
+            }
+            break;
+
+        TARGET(BUILD_LIST)
+            x =  PyList_New(oparg);
+            if (x != NULL) {
+                for (; --oparg >= 0;) {
+                    w = POP();
+                    PyList_SET_ITEM(x, oparg, w);
+                }
+                PUSH(x);
+                DISPATCH();
+            }
+            break;
+
+        TARGET(BUILD_SET)
+            x = PySet_New(NULL);
+            if (x != NULL) {
+                for (; --oparg >= 0;) {
+                    w = POP();
+                    if (err == 0)
+                        err = PySet_Add(x, w);
+                    Py_DECREF(w);
+                }
+                if (err != 0) {
+                    Py_DECREF(x);
+                    break;
+                }
+                PUSH(x);
+                DISPATCH();
+            }
+            break;
+
+        TARGET(BUILD_MAP)
+            x = _PyDict_NewPresized((Py_ssize_t)oparg);
+            PUSH(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(STORE_MAP)
+            w = TOP();     /* key */
+            u = SECOND();  /* value */
+            v = THIRD();   /* dict */
+            STACKADJ(-2);
+            assert (PyDict_CheckExact(v));
+            err = PyDict_SetItem(v, w, u);  /* v[w] = u */
+            Py_DECREF(u);
+            Py_DECREF(w);
+            if (err == 0) DISPATCH();
+            break;
+
+        TARGET(MAP_ADD)
+            w = TOP();     /* key */
+            u = SECOND();  /* value */
+            STACKADJ(-2);
+            v = stack_pointer[-oparg];  /* dict */
+            assert (PyDict_CheckExact(v));
+            err = PyDict_SetItem(v, w, u);  /* v[w] = u */
+            Py_DECREF(u);
+            Py_DECREF(w);
+            if (err == 0) {
+                PREDICT(JUMP_ABSOLUTE);
+                DISPATCH();
+            }
+            break;
+
+        TARGET(LOAD_ATTR)
+            w = GETITEM(names, oparg);
+            v = TOP();
+            x = PyObject_GetAttr(v, w);
+            Py_DECREF(v);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(COMPARE_OP)
+            w = POP();
+            v = TOP();
+            x = cmp_outcome(oparg, v, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x == NULL) break;
+            PREDICT(POP_JUMP_IF_FALSE);
+            PREDICT(POP_JUMP_IF_TRUE);
+            DISPATCH();
+
+        TARGET(IMPORT_NAME)
+            w = GETITEM(names, oparg);
+            x = PyDict_GetItemString(f->f_builtins, "__import__");
+            if (x == NULL) {
+                PyErr_SetString(PyExc_ImportError,
+                                "__import__ not found");
+                break;
+            }
+            Py_INCREF(x);
+            v = POP();
+            u = TOP();
+            if (PyLong_AsLong(u) != -1 || PyErr_Occurred())
+                w = PyTuple_Pack(5,
+                            w,
+                            f->f_globals,
+                            f->f_locals == NULL ?
+                                  Py_None : f->f_locals,
+                            v,
+                            u);
+            else
+                w = PyTuple_Pack(4,
+                            w,
+                            f->f_globals,
+                            f->f_locals == NULL ?
+                                  Py_None : f->f_locals,
+                            v);
+            Py_DECREF(v);
+            Py_DECREF(u);
+            if (w == NULL) {
+                u = POP();
+                Py_DECREF(x);
+                x = NULL;
+                break;
+            }
+            READ_TIMESTAMP(intr0);
+            v = x;
+            x = PyEval_CallObject(v, w);
+            Py_DECREF(v);
+            READ_TIMESTAMP(intr1);
+            Py_DECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(IMPORT_STAR)
+            v = POP();
+            PyFrame_FastToLocals(f);
+            if ((x = f->f_locals) == NULL) {
+                PyErr_SetString(PyExc_SystemError,
+                    "no locals found during 'import *'");
+                break;
+            }
+            READ_TIMESTAMP(intr0);
+            err = import_all_from(x, v);
+            READ_TIMESTAMP(intr1);
+            PyFrame_LocalsToFast(f, 0);
+            Py_DECREF(v);
+            if (err == 0) DISPATCH();
+            break;
+
+        TARGET(IMPORT_FROM)
+            w = GETITEM(names, oparg);
+            v = TOP();
+            READ_TIMESTAMP(intr0);
+            x = import_from(v, w);
+            READ_TIMESTAMP(intr1);
+            PUSH(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(JUMP_FORWARD)
+            JUMPBY(oparg);
+            FAST_DISPATCH();
+
+        PREDICTED_WITH_ARG(POP_JUMP_IF_FALSE);
+        TARGET(POP_JUMP_IF_FALSE)
+            w = POP();
+            if (w == Py_True) {
+                Py_DECREF(w);
+                FAST_DISPATCH();
+            }
+            if (w == Py_False) {
+                Py_DECREF(w);
+                JUMPTO(oparg);
+                FAST_DISPATCH();
+            }
+            err = PyObject_IsTrue(w);
+            Py_DECREF(w);
+            if (err > 0)
+                err = 0;
+            else if (err == 0)
+                JUMPTO(oparg);
+            else
+                break;
+            DISPATCH();
+
+        PREDICTED_WITH_ARG(POP_JUMP_IF_TRUE);
+        TARGET(POP_JUMP_IF_TRUE)
+            w = POP();
+            if (w == Py_False) {
+                Py_DECREF(w);
+                FAST_DISPATCH();
+            }
+            if (w == Py_True) {
+                Py_DECREF(w);
+                JUMPTO(oparg);
+                FAST_DISPATCH();
+            }
+            err = PyObject_IsTrue(w);
+            Py_DECREF(w);
+            if (err > 0) {
+                err = 0;
+                JUMPTO(oparg);
+            }
+            else if (err == 0)
+                ;
+            else
+                break;
+            DISPATCH();
+
+        TARGET(JUMP_IF_FALSE_OR_POP)
+            w = TOP();
+            if (w == Py_True) {
+                STACKADJ(-1);
+                Py_DECREF(w);
+                FAST_DISPATCH();
+            }
+            if (w == Py_False) {
+                JUMPTO(oparg);
+                FAST_DISPATCH();
+            }
+            err = PyObject_IsTrue(w);
+            if (err > 0) {
+                STACKADJ(-1);
+                Py_DECREF(w);
+                err = 0;
+            }
+            else if (err == 0)
+                JUMPTO(oparg);
+            else
+                break;
+            DISPATCH();
+
+        TARGET(JUMP_IF_TRUE_OR_POP)
+            w = TOP();
+            if (w == Py_False) {
+                STACKADJ(-1);
+                Py_DECREF(w);
+                FAST_DISPATCH();
+            }
+            if (w == Py_True) {
+                JUMPTO(oparg);
+                FAST_DISPATCH();
+            }
+            err = PyObject_IsTrue(w);
+            if (err > 0) {
+                err = 0;
+                JUMPTO(oparg);
+            }
+            else if (err == 0) {
+                STACKADJ(-1);
+                Py_DECREF(w);
+            }
+            else
+                break;
+            DISPATCH();
+
+        PREDICTED_WITH_ARG(JUMP_ABSOLUTE);
+        TARGET(JUMP_ABSOLUTE)
+            JUMPTO(oparg);
+#if FAST_LOOPS
+            /* Enabling this path speeds-up all while and for-loops by bypassing
+               the per-loop checks for signals.  By default, this should be turned-off
+               because it prevents detection of a control-break in tight loops like
+               "while 1: pass".  Compile with this option turned-on when you need
+               the speed-up and do not need break checking inside tight loops (ones
+               that contain only instructions ending with FAST_DISPATCH).
+            */
+            FAST_DISPATCH();
+#else
+            DISPATCH();
+#endif
+
+        TARGET(GET_ITER)
+            /* before: [obj]; after [getiter(obj)] */
+            v = TOP();
+            x = PyObject_GetIter(v);
+            Py_DECREF(v);
+            if (x != NULL) {
+                SET_TOP(x);
+                PREDICT(FOR_ITER);
+                DISPATCH();
+            }
+            STACKADJ(-1);
+            break;
+
+        PREDICTED_WITH_ARG(FOR_ITER);
+        TARGET(FOR_ITER)
+            /* before: [iter]; after: [iter, iter()] *or* [] */
+            v = TOP();
+            x = (*v->ob_type->tp_iternext)(v);
+            if (x != NULL) {
+                PUSH(x);
+                PREDICT(STORE_FAST);
+                PREDICT(UNPACK_SEQUENCE);
+                DISPATCH();
+            }
+            if (PyErr_Occurred()) {
+                if (!PyErr_ExceptionMatches(
+                                PyExc_StopIteration))
+                    break;
+                PyErr_Clear();
+            }
+            /* iterator ended normally */
+            x = v = POP();
+            Py_DECREF(v);
+            JUMPBY(oparg);
+            DISPATCH();
+
+        TARGET(BREAK_LOOP)
+            why = WHY_BREAK;
+            goto fast_block_end;
+
+        TARGET(CONTINUE_LOOP)
+            retval = PyLong_FromLong(oparg);
+            if (!retval) {
+                x = NULL;
+                break;
+            }
+            why = WHY_CONTINUE;
+            goto fast_block_end;
+
+        TARGET_WITH_IMPL(SETUP_LOOP, _setup_finally)
+        TARGET_WITH_IMPL(SETUP_EXCEPT, _setup_finally)
+        TARGET(SETUP_FINALLY)
+        _setup_finally:
+            /* NOTE: If you add any new block-setup opcodes that
+               are not try/except/finally handlers, you may need
+               to update the PyGen_NeedsFinalizing() function.
+               */
+
+            PyFrame_BlockSetup(f, opcode, INSTR_OFFSET() + oparg,
+                               STACK_LEVEL());
+            DISPATCH();
+
+        TARGET(SETUP_WITH)
+        {
+            static PyObject *exit, *enter;
+            w = TOP();
+            x = special_lookup(w, "__exit__", &exit);
+            if (!x)
+                break;
+            SET_TOP(x);
+            u = special_lookup(w, "__enter__", &enter);
+            Py_DECREF(w);
+            if (!u) {
+                x = NULL;
+                break;
+            }
+            x = PyObject_CallFunctionObjArgs(u, NULL);
+            Py_DECREF(u);
+            if (!x)
+                break;
+            /* Setup the finally block before pushing the result
+               of __enter__ on the stack. */
+            PyFrame_BlockSetup(f, SETUP_FINALLY, INSTR_OFFSET() + oparg,
+                               STACK_LEVEL());
+
+            PUSH(x);
+            DISPATCH();
+        }
+
+        TARGET(WITH_CLEANUP)
+        {
+            /* At the top of the stack are 1-3 values indicating
+               how/why we entered the finally clause:
+               - TOP = None
+               - (TOP, SECOND) = (WHY_{RETURN,CONTINUE}), retval
+               - TOP = WHY_*; no retval below it
+               - (TOP, SECOND, THIRD) = exc_info()
+                 (FOURTH, FITH, SIXTH) = previous exception for EXCEPT_HANDLER
+               Below them is EXIT, the context.__exit__ bound method.
+               In the last case, we must call
+                 EXIT(TOP, SECOND, THIRD)
+               otherwise we must call
+                 EXIT(None, None, None)
+
+               In the first two cases, we remove EXIT from the
+               stack, leaving the rest in the same order.  In the
+               third case, we shift the bottom 3 values of the
+               stack down, and replace the empty spot with NULL.
+
+               In addition, if the stack represents an exception,
+               *and* the function call returns a 'true' value, we
+               push WHY_SILENCED onto the stack.  END_FINALLY will
+               then not re-raise the exception.  (But non-local
+               gotos should still be resumed.)
+            */
+
+            PyObject *exit_func;
+            u = TOP();
+            if (u == Py_None) {
+                (void)POP();
+                exit_func = TOP();
+                SET_TOP(u);
+                v = w = Py_None;
+            }
+            else if (PyLong_Check(u)) {
+                (void)POP();
+                switch(PyLong_AsLong(u)) {
+                case WHY_RETURN:
+                case WHY_CONTINUE:
+                    /* Retval in TOP. */
+                    exit_func = SECOND();
+                    SET_SECOND(TOP());
+                    SET_TOP(u);
+                    break;
+                default:
+                    exit_func = TOP();
+                    SET_TOP(u);
+                    break;
+                }
+                u = v = w = Py_None;
+            }
+            else {
+                PyObject *tp, *exc, *tb;
+                PyTryBlock *block;
+                v = SECOND();
+                w = THIRD();
+                tp = FOURTH();
+                exc = PEEK(5);
+                tb = PEEK(6);
+                exit_func = PEEK(7);
+                SET_VALUE(7, tb);
+                SET_VALUE(6, exc);
+                SET_VALUE(5, tp);
+                /* UNWIND_EXCEPT_HANDLER will pop this off. */
+                SET_FOURTH(NULL);
+                /* We just shifted the stack down, so we have
+                   to tell the except handler block that the
+                   values are lower than it expects. */
+                block = &f->f_blockstack[f->f_iblock - 1];
+                assert(block->b_type == EXCEPT_HANDLER);
+                block->b_level--;
+            }
+            /* XXX Not the fastest way to call it... */
+            x = PyObject_CallFunctionObjArgs(exit_func, u, v, w,
+                                             NULL);
+            Py_DECREF(exit_func);
+            if (x == NULL)
+                break; /* Go to error exit */
+
+            if (u != Py_None)
+                err = PyObject_IsTrue(x);
+            else
+                err = 0;
+            Py_DECREF(x);
+
+            if (err < 0)
+                break; /* Go to error exit */
+            else if (err > 0) {
+                err = 0;
+                /* There was an exception and a True return */
+                PUSH(PyLong_FromLong((long) WHY_SILENCED));
+            }
+            PREDICT(END_FINALLY);
+            break;
+        }
+
+        TARGET(CALL_FUNCTION)
+        {
+            PyObject **sp;
+            PCALL(PCALL_ALL);
+            sp = stack_pointer;
+            x = call_function(&sp, oparg);
+            stack_pointer = sp;
+            PUSH(x);
+            if (x != NULL)
+                DISPATCH();
+            break;
+        }
+
+        TARGET_WITH_IMPL(CALL_FUNCTION_VAR, _call_function_var_kw)
+        TARGET_WITH_IMPL(CALL_FUNCTION_KW, _call_function_var_kw)
+        TARGET(CALL_FUNCTION_VAR_KW)
+        _call_function_var_kw:
+        {
+            int na = oparg & 0xff;
+            int nk = (oparg>>8) & 0xff;
+            int flags = (opcode - CALL_FUNCTION) & 3;
+            int n = na + 2 * nk;
+            PyObject **pfunc, *func, **sp;
+            PCALL(PCALL_ALL);
+            if (flags & CALL_FLAG_VAR)
+                n++;
+            if (flags & CALL_FLAG_KW)
+                n++;
+            pfunc = stack_pointer - n - 1;
+            func = *pfunc;
+
+            if (PyMethod_Check(func)
+                && PyMethod_GET_SELF(func) != NULL) {
+                PyObject *self = PyMethod_GET_SELF(func);
+                Py_INCREF(self);
+                func = PyMethod_GET_FUNCTION(func);
+                Py_INCREF(func);
+                Py_DECREF(*pfunc);
+                *pfunc = self;
+                na++;
+                /* n++; */
+            } else
+                Py_INCREF(func);
+            sp = stack_pointer;
+            READ_TIMESTAMP(intr0);
+            x = ext_do_call(func, &sp, flags, na, nk);
+            READ_TIMESTAMP(intr1);
+            stack_pointer = sp;
+            Py_DECREF(func);
+
+            while (stack_pointer > pfunc) {
+                w = POP();
+                Py_DECREF(w);
+            }
+            PUSH(x);
+            if (x != NULL)
+                DISPATCH();
+            break;
+        }
+
+        TARGET_WITH_IMPL(MAKE_CLOSURE, _make_function)
+        TARGET(MAKE_FUNCTION)
+        _make_function:
+        {
+            int posdefaults = oparg & 0xff;
+            int kwdefaults = (oparg>>8) & 0xff;
+            int num_annotations = (oparg >> 16) & 0x7fff;
+
+            w = POP(); /* qualname */
+            v = POP(); /* code object */
+            x = PyFunction_NewWithQualName(v, f->f_globals, w);
+            Py_DECREF(v);
+            Py_DECREF(w);
+
+            if (x != NULL && opcode == MAKE_CLOSURE) {
+                v = POP();
+                if (PyFunction_SetClosure(x, v) != 0) {
+                    /* Can't happen unless bytecode is corrupt. */
+                    why = WHY_EXCEPTION;
+                }
+                Py_DECREF(v);
+            }
+
+            if (x != NULL && num_annotations > 0) {
+                Py_ssize_t name_ix;
+                u = POP(); /* names of args with annotations */
+                v = PyDict_New();
+                if (v == NULL) {
+                    Py_DECREF(x);
+                    x = NULL;
+                    break;
+                }
+                name_ix = PyTuple_Size(u);
+                assert(num_annotations == name_ix+1);
+                while (name_ix > 0) {
+                    --name_ix;
+                    t = PyTuple_GET_ITEM(u, name_ix);
+                    w = POP();
+                    /* XXX(nnorwitz): check for errors */
+                    PyDict_SetItem(v, t, w);
+                    Py_DECREF(w);
+                }
+
+                if (PyFunction_SetAnnotations(x, v) != 0) {
+                    /* Can't happen unless
+                       PyFunction_SetAnnotations changes. */
+                    why = WHY_EXCEPTION;
+                }
+                Py_DECREF(v);
+                Py_DECREF(u);
+            }
+
+            /* XXX Maybe this should be a separate opcode? */
+            if (x != NULL && posdefaults > 0) {
+                v = PyTuple_New(posdefaults);
+                if (v == NULL) {
+                    Py_DECREF(x);
+                    x = NULL;
+                    break;
+                }
+                while (--posdefaults >= 0) {
+                    w = POP();
+                    PyTuple_SET_ITEM(v, posdefaults, w);
+                }
+                if (PyFunction_SetDefaults(x, v) != 0) {
+                    /* Can't happen unless
+                       PyFunction_SetDefaults changes. */
+                    why = WHY_EXCEPTION;
+                }
+                Py_DECREF(v);
+            }
+            if (x != NULL && kwdefaults > 0) {
+                v = PyDict_New();
+                if (v == NULL) {
+                    Py_DECREF(x);
+                    x = NULL;
+                    break;
+                }
+                while (--kwdefaults >= 0) {
+                    w = POP(); /* default value */
+                    u = POP(); /* kw only arg name */
+                    /* XXX(nnorwitz): check for errors */
+                    PyDict_SetItem(v, u, w);
+                    Py_DECREF(w);
+                    Py_DECREF(u);
+                }
+                if (PyFunction_SetKwDefaults(x, v) != 0) {
+                    /* Can't happen unless
+                       PyFunction_SetKwDefaults changes. */
+                    why = WHY_EXCEPTION;
+                }
+                Py_DECREF(v);
+            }
+            PUSH(x);
+            break;
+        }
+
+        TARGET(BUILD_SLICE)
+            if (oparg == 3)
+                w = POP();
+            else
+                w = NULL;
+            v = POP();
+            u = TOP();
+            x = PySlice_New(u, v, w);
+            Py_DECREF(u);
+            Py_DECREF(v);
+            Py_XDECREF(w);
+            SET_TOP(x);
+            if (x != NULL) DISPATCH();
+            break;
+
+        TARGET(EXTENDED_ARG)
+            opcode = NEXTOP();
+            oparg = oparg<<16 | NEXTARG();
+            goto dispatch_opcode;
+
+#if USE_COMPUTED_GOTOS
+        _unknown_opcode:
+#endif
+        default:
+            fprintf(stderr,
+                "XXX lineno: %d, opcode: %d\n",
+                PyFrame_GetLineNumber(f),
+                opcode);
+            PyErr_SetString(PyExc_SystemError, "unknown opcode");
+            why = WHY_EXCEPTION;
+            break;
+
+
+        } /* switch */
+
+        on_error:
+
+        READ_TIMESTAMP(inst1);
+
+        /* Quickly continue if no error occurred */
+
+        if (why == WHY_NOT) {
+            if (err == 0 && x != NULL) {
+#ifdef CHECKEXC
+                /* This check is expensive! */
+                if (PyErr_Occurred())
+                    fprintf(stderr,
+                        "XXX undetected error\n");
+                else {
+#endif
+                    READ_TIMESTAMP(loop1);
+                    continue; /* Normal, fast path */
+#ifdef CHECKEXC
+                }
+#endif
+            }
+            why = WHY_EXCEPTION;
+            x = Py_None;
+            err = 0;
+        }
+
+        /* Double-check exception status */
+
+        if (why == WHY_EXCEPTION || why == WHY_RERAISE) {
+            if (!PyErr_Occurred()) {
+                PyErr_SetString(PyExc_SystemError,
+                    "error return without exception set");
+                why = WHY_EXCEPTION;
+            }
+        }
+#ifdef CHECKEXC
+        else {
+            /* This check is expensive! */
+            if (PyErr_Occurred()) {
+                char buf[128];
+                sprintf(buf, "Stack unwind with exception "
+                    "set and why=%d", why);
+                Py_FatalError(buf);
+            }
+        }
+#endif
+
+        /* Log traceback info if this is a real exception */
+
+        if (why == WHY_EXCEPTION) {
+            PyTraceBack_Here(f);
+
+            if (tstate->c_tracefunc != NULL)
+                call_exc_trace(tstate->c_tracefunc,
+                               tstate->c_traceobj, f);
+        }
+
+        /* For the rest, treat WHY_RERAISE as WHY_EXCEPTION */
+
+        if (why == WHY_RERAISE)
+            why = WHY_EXCEPTION;
+
+        /* Unwind stacks if a (pseudo) exception occurred */
+
+fast_block_end:
+        while (why != WHY_NOT && f->f_iblock > 0) {
+            /* Peek at the current block. */
+            PyTryBlock *b = &f->f_blockstack[f->f_iblock - 1];
+
+            assert(why != WHY_YIELD);
+            if (b->b_type == SETUP_LOOP && why == WHY_CONTINUE) {
+                why = WHY_NOT;
+                JUMPTO(PyLong_AS_LONG(retval));
+                Py_DECREF(retval);
+                break;
+            }
+            /* Now we have to pop the block. */
+            f->f_iblock--;
+
+            if (b->b_type == EXCEPT_HANDLER) {
+                UNWIND_EXCEPT_HANDLER(b);
+                continue;
+            }
+            UNWIND_BLOCK(b);
+            if (b->b_type == SETUP_LOOP && why == WHY_BREAK) {
+                why = WHY_NOT;
+                JUMPTO(b->b_handler);
+                break;
+            }
+            if (why == WHY_EXCEPTION && (b->b_type == SETUP_EXCEPT
+                || b->b_type == SETUP_FINALLY)) {
+                PyObject *exc, *val, *tb;
+                int handler = b->b_handler;
+                /* Beware, this invalidates all b->b_* fields */
+                PyFrame_BlockSetup(f, EXCEPT_HANDLER, -1, STACK_LEVEL());
+                PUSH(tstate->exc_traceback);
+                PUSH(tstate->exc_value);
+                if (tstate->exc_type != NULL) {
+                    PUSH(tstate->exc_type);
+                }
+                else {
+                    Py_INCREF(Py_None);
+                    PUSH(Py_None);
+                }
+                PyErr_Fetch(&exc, &val, &tb);
+                /* Make the raw exception data
+                   available to the handler,
+                   so a program can emulate the
+                   Python main loop. */
+                PyErr_NormalizeException(
+                    &exc, &val, &tb);
+                PyException_SetTraceback(val, tb);
+                Py_INCREF(exc);
+                tstate->exc_type = exc;
+                Py_INCREF(val);
+                tstate->exc_value = val;
+                tstate->exc_traceback = tb;
+                if (tb == NULL)
+                    tb = Py_None;
+                Py_INCREF(tb);
+                PUSH(tb);
+                PUSH(val);
+                PUSH(exc);
+                why = WHY_NOT;
+                JUMPTO(handler);
+                break;
+            }
+            if (b->b_type == SETUP_FINALLY) {
+                if (why & (WHY_RETURN | WHY_CONTINUE))
+                    PUSH(retval);
+                PUSH(PyLong_FromLong((long)why));
+                why = WHY_NOT;
+                JUMPTO(b->b_handler);
+                break;
+            }
+        } /* unwind stack */
+
+        /* End the loop if we still have an error (or return) */
+
+        if (why != WHY_NOT)
+            break;
+        READ_TIMESTAMP(loop1);
+
+    } /* main loop */
+
+    assert(why != WHY_YIELD);
+    /* Pop remaining stack entries. */
+    while (!EMPTY()) {
+        v = POP();
+        Py_XDECREF(v);
+    }
+
+    if (why != WHY_RETURN)
+        retval = NULL;
+
+fast_yield:
+    if (co->co_flags & CO_GENERATOR && (why == WHY_YIELD || why == WHY_RETURN)) {
+        /* The purpose of this block is to put aside the generator's exception
+           state and restore that of the calling frame. If the current
+           exception state is from the caller, we clear the exception values
+           on the generator frame, so they are not swapped back in latter. The
+           origin of the current exception state is determined by checking for
+           except handler blocks, which we must be in iff a new exception
+           state came into existence in this frame. (An uncaught exception
+           would have why == WHY_EXCEPTION, and we wouldn't be here). */
+        int i;
+        for (i = 0; i < f->f_iblock; i++)
+            if (f->f_blockstack[i].b_type == EXCEPT_HANDLER)
+                break;
+        if (i == f->f_iblock)
+            /* We did not create this exception. */
+            restore_and_clear_exc_state(tstate, f);
+        else
+            swap_exc_state(tstate, f);
+    }
+
+    if (tstate->use_tracing) {
+        if (tstate->c_tracefunc) {
+            if (why == WHY_RETURN || why == WHY_YIELD) {
+                if (call_trace(tstate->c_tracefunc,
+                               tstate->c_traceobj, f,
+                               PyTrace_RETURN, retval)) {
+                    Py_XDECREF(retval);
+                    retval = NULL;
+                    why = WHY_EXCEPTION;
+                }
+            }
+            else if (why == WHY_EXCEPTION) {
+                call_trace_protected(tstate->c_tracefunc,
+                                     tstate->c_traceobj, f,
+                                     PyTrace_RETURN, NULL);
+            }
+        }
+        if (tstate->c_profilefunc) {
+            if (why == WHY_EXCEPTION)
+                call_trace_protected(tstate->c_profilefunc,
+                                     tstate->c_profileobj, f,
+                                     PyTrace_RETURN, NULL);
+            else if (call_trace(tstate->c_profilefunc,
+                                tstate->c_profileobj, f,
+                                PyTrace_RETURN, retval)) {
+                Py_XDECREF(retval);
+                retval = NULL;
+                /* why = WHY_EXCEPTION; */
+            }
+        }
+    }
+
+    /* pop frame */
+exit_eval_frame:
+    Py_LeaveRecursiveCall();
+    tstate->frame = f->f_back;
+
+    return retval;
+}
+
+static void
+format_missing(const char *kind, PyCodeObject *co, PyObject *names)
+{
+    int err;
+    Py_ssize_t len = PyList_GET_SIZE(names);
+    PyObject *name_str, *comma, *tail, *tmp;
+
+    assert(PyList_CheckExact(names));
+    assert(len >= 1);
+    /* Deal with the joys of natural language. */
+    switch (len) {
+    case 1:
+        name_str = PyList_GET_ITEM(names, 0);
+        Py_INCREF(name_str);
+        break;
+    case 2:
+        name_str = PyUnicode_FromFormat("%U and %U",
+                                        PyList_GET_ITEM(names, len - 2),
+                                        PyList_GET_ITEM(names, len - 1));
+        break;
+    default:
+        tail = PyUnicode_FromFormat(", %U, and %U",
+                                    PyList_GET_ITEM(names, len - 2),
+                                    PyList_GET_ITEM(names, len - 1));
+        /* Chop off the last two objects in the list. This shouldn't actually
+           fail, but we can't be too careful. */
+        err = PyList_SetSlice(names, len - 2, len, NULL);
+        if (err == -1) {
+            Py_DECREF(tail);
+            return;
+        }
+        /* Stitch everything up into a nice comma-separated list. */
+        comma = PyUnicode_FromString(", ");
+        if (comma == NULL) {
+            Py_DECREF(tail);
+            return;
+        }
+        tmp = PyUnicode_Join(comma, names);
+        Py_DECREF(comma);
+        if (tmp == NULL) {
+            Py_DECREF(tail);
+            return;
+        }
+        name_str = PyUnicode_Concat(tmp, tail);
+        Py_DECREF(tmp);
+        Py_DECREF(tail);
+        break;
+    }
+    if (name_str == NULL)
+        return;
+    PyErr_Format(PyExc_TypeError,
+                 "%U() missing %i required %s argument%s: %U",
+                 co->co_name,
+                 len,
+                 kind,
+                 len == 1 ? "" : "s",
+                 name_str);
+    Py_DECREF(name_str);
+}
+
+static void
+missing_arguments(PyCodeObject *co, int missing, int defcount,
+                  PyObject **fastlocals)
+{
+    int i, j = 0;
+    int start, end;
+    int positional = defcount != -1;
+    const char *kind = positional ? "positional" : "keyword-only";
+    PyObject *missing_names;
+
+    /* Compute the names of the arguments that are missing. */
+    missing_names = PyList_New(missing);
+    if (missing_names == NULL)
+        return;
+    if (positional) {
+        start = 0;
+        end = co->co_argcount - defcount;
+    }
+    else {
+        start = co->co_argcount;
+        end = start + co->co_kwonlyargcount;
+    }
+    for (i = start; i < end; i++) {
+        if (GETLOCAL(i) == NULL) {
+            PyObject *raw = PyTuple_GET_ITEM(co->co_varnames, i);
+            PyObject *name = PyObject_Repr(raw);
+            if (name == NULL) {
+                Py_DECREF(missing_names);
+                return;
+            }
+            PyList_SET_ITEM(missing_names, j++, name);
+        }
+    }
+    assert(j == missing);
+    format_missing(kind, co, missing_names);
+    Py_DECREF(missing_names);
+}
+
+static void
+too_many_positional(PyCodeObject *co, int given, int defcount, PyObject **fastlocals)
+{
+    int plural;
+    int kwonly_given = 0;
+    int i;
+    PyObject *sig, *kwonly_sig;
+
+    assert((co->co_flags & CO_VARARGS) == 0);
+    /* Count missing keyword-only args. */
+    for (i = co->co_argcount; i < co->co_argcount + co->co_kwonlyargcount; i++)
+        if (GETLOCAL(i) != NULL)
+            kwonly_given++;
+    if (defcount) {
+        int atleast = co->co_argcount - defcount;
+        plural = 1;
+        sig = PyUnicode_FromFormat("from %d to %d", atleast, co->co_argcount);
+    }
+    else {
+        plural = co->co_argcount != 1;
+        sig = PyUnicode_FromFormat("%d", co->co_argcount);
+    }
+    if (sig == NULL)
+        return;
+    if (kwonly_given) {
+        const char *format = " positional argument%s (and %d keyword-only argument%s)";
+        kwonly_sig = PyUnicode_FromFormat(format, given != 1 ? "s" : "", kwonly_given,
+                                              kwonly_given != 1 ? "s" : "");
+        if (kwonly_sig == NULL) {
+            Py_DECREF(sig);
+            return;
+        }
+    }
+    else {
+        /* This will not fail. */
+        kwonly_sig = PyUnicode_FromString("");
+        assert(kwonly_sig != NULL);
+    }
+    PyErr_Format(PyExc_TypeError,
+                 "%U() takes %U positional argument%s but %d%U %s given",
+                 co->co_name,
+                 sig,
+                 plural ? "s" : "",
+                 given,
+                 kwonly_sig,
+                 given == 1 && !kwonly_given ? "was" : "were");
+    Py_DECREF(sig);
+    Py_DECREF(kwonly_sig);
+}
+
+/* This is gonna seem *real weird*, but if you put some other code between
+   PyEval_EvalFrame() and PyEval_EvalCodeEx() you will need to adjust
+   the test in the if statements in Misc/gdbinit (pystack and pystackv). */
+
+PyObject *
+PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,
+           PyObject **args, int argcount, PyObject **kws, int kwcount,
+           PyObject **defs, int defcount, PyObject *kwdefs, PyObject *closure)
+{
+    PyCodeObject* co = (PyCodeObject*)_co;
+    register PyFrameObject *f;
+    register PyObject *retval = NULL;
+    register PyObject **fastlocals, **freevars;
+    PyThreadState *tstate = PyThreadState_GET();
+    PyObject *x, *u;
+    int total_args = co->co_argcount + co->co_kwonlyargcount;
+    int i;
+    int n = argcount;
+    PyObject *kwdict = NULL;
+
+    if (globals == NULL) {
+        PyErr_SetString(PyExc_SystemError,
+                        "PyEval_EvalCodeEx: NULL globals");
+        return NULL;
+    }
+
+    assert(tstate != NULL);
+    assert(globals != NULL);
+    f = PyFrame_New(tstate, co, globals, locals);
+    if (f == NULL)
+        return NULL;
+
+    fastlocals = f->f_localsplus;
+    freevars = f->f_localsplus + co->co_nlocals;
+
+    /* Parse arguments. */
+    if (co->co_flags & CO_VARKEYWORDS) {
+        kwdict = PyDict_New();
+        if (kwdict == NULL)
+            goto fail;
+        i = total_args;
+        if (co->co_flags & CO_VARARGS)
+            i++;
+        SETLOCAL(i, kwdict);
+    }
+    if (argcount > co->co_argcount)
+        n = co->co_argcount;
+    for (i = 0; i < n; i++) {
+        x = args[i];
+        Py_INCREF(x);
+        SETLOCAL(i, x);
+    }
+    if (co->co_flags & CO_VARARGS) {
+        u = PyTuple_New(argcount - n);
+        if (u == NULL)
+            goto fail;
+        SETLOCAL(total_args, u);
+        for (i = n; i < argcount; i++) {
+            x = args[i];
+            Py_INCREF(x);
+            PyTuple_SET_ITEM(u, i-n, x);
+        }
+    }
+    for (i = 0; i < kwcount; i++) {
+        PyObject **co_varnames;
+        PyObject *keyword = kws[2*i];
+        PyObject *value = kws[2*i + 1];
+        int j;
+        if (keyword == NULL || !PyUnicode_Check(keyword)) {
+            PyErr_Format(PyExc_TypeError,
+                         "%U() keywords must be strings",
+                         co->co_name);
+            goto fail;
+        }
+        /* Speed hack: do raw pointer compares. As names are
+           normally interned this should almost always hit. */
+        co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item;
+        for (j = 0; j < total_args; j++) {
+            PyObject *nm = co_varnames[j];
+            if (nm == keyword)
+                goto kw_found;
+        }
+        /* Slow fallback, just in case */
+        for (j = 0; j < total_args; j++) {
+            PyObject *nm = co_varnames[j];
+            int cmp = PyObject_RichCompareBool(
+                keyword, nm, Py_EQ);
+            if (cmp > 0)
+                goto kw_found;
+            else if (cmp < 0)
+                goto fail;
+        }
+        if (j >= total_args && kwdict == NULL) {
+            PyErr_Format(PyExc_TypeError,
+                         "%U() got an unexpected "
+                         "keyword argument '%S'",
+                         co->co_name,
+                         keyword);
+            goto fail;
+        }
+        PyDict_SetItem(kwdict, keyword, value);
+        continue;
+      kw_found:
+        if (GETLOCAL(j) != NULL) {
+            PyErr_Format(PyExc_TypeError,
+                         "%U() got multiple "
+                         "values for argument '%S'",
+                         co->co_name,
+                         keyword);
+            goto fail;
+        }
+        Py_INCREF(value);
+        SETLOCAL(j, value);
+    }
+    if (argcount > co->co_argcount && !(co->co_flags & CO_VARARGS)) {
+        too_many_positional(co, argcount, defcount, fastlocals);
+        goto fail;
+    }
+    if (argcount < co->co_argcount) {
+        int m = co->co_argcount - defcount;
+        int missing = 0;
+        for (i = argcount; i < m; i++)
+            if (GETLOCAL(i) == NULL)
+                missing++;
+        if (missing) {
+            missing_arguments(co, missing, defcount, fastlocals);
+            goto fail;
+        }
+        if (n > m)
+            i = n - m;
+        else
+            i = 0;
+        for (; i < defcount; i++) {
+            if (GETLOCAL(m+i) == NULL) {
+                PyObject *def = defs[i];
+                Py_INCREF(def);
+                SETLOCAL(m+i, def);
+            }
+        }
+    }
+    if (co->co_kwonlyargcount > 0) {
+        int missing = 0;
+        for (i = co->co_argcount; i < total_args; i++) {
+            PyObject *name;
+            if (GETLOCAL(i) != NULL)
+                continue;
+            name = PyTuple_GET_ITEM(co->co_varnames, i);
+            if (kwdefs != NULL) {
+                PyObject *def = PyDict_GetItem(kwdefs, name);
+                if (def) {
+                    Py_INCREF(def);
+                    SETLOCAL(i, def);
+                    continue;
+                }
+            }
+            missing++;
+        }
+        if (missing) {
+            missing_arguments(co, missing, -1, fastlocals);
+            goto fail;
+        }
+    }
+
+    /* Allocate and initialize storage for cell vars, and copy free
+       vars into frame. */
+    for (i = 0; i < PyTuple_GET_SIZE(co->co_cellvars); ++i) {
+        PyObject *c;
+        int arg;
+        /* Possibly account for the cell variable being an argument. */
+        if (co->co_cell2arg != NULL &&
+            (arg = co->co_cell2arg[i]) != CO_CELL_NOT_AN_ARG)
+            c = PyCell_New(GETLOCAL(arg));
+        else
+            c = PyCell_New(NULL);
+        if (c == NULL)
+            goto fail;
+        SETLOCAL(co->co_nlocals + i, c);
+    }
+    for (i = 0; i < PyTuple_GET_SIZE(co->co_freevars); ++i) {
+        PyObject *o = PyTuple_GET_ITEM(closure, i);
+        Py_INCREF(o);
+        freevars[PyTuple_GET_SIZE(co->co_cellvars) + i] = o;
+    }
+
+    if (co->co_flags & CO_GENERATOR) {
+        /* Don't need to keep the reference to f_back, it will be set
+         * when the generator is resumed. */
+        Py_XDECREF(f->f_back);
+        f->f_back = NULL;
+
+        PCALL(PCALL_GENERATOR);
+
+        /* Create a new generator that owns the ready to run frame
+         * and return that as the value. */
+        return PyGen_New(f);
+    }
+
+    retval = PyEval_EvalFrameEx(f,0);
+
+fail: /* Jump here from prelude on failure */
+
+    /* decref'ing the frame can cause __del__ methods to get invoked,
+       which can call back into Python.  While we're done with the
+       current Python frame (f), the associated C stack is still in use,
+       so recursion_depth must be boosted for the duration.
+    */
+    assert(tstate != NULL);
+    ++tstate->recursion_depth;
+    Py_DECREF(f);
+    --tstate->recursion_depth;
+    return retval;
+}
+
+
+static PyObject *
+special_lookup(PyObject *o, char *meth, PyObject **cache)
+{
+    PyObject *res;
+    res = _PyObject_LookupSpecial(o, meth, cache);
+    if (res == NULL && !PyErr_Occurred()) {
+        PyErr_SetObject(PyExc_AttributeError, *cache);
+        return NULL;
+    }
+    return res;
+}
+
+
+/* These 3 functions deal with the exception state of generators. */
+
+static void
+save_exc_state(PyThreadState *tstate, PyFrameObject *f)
+{
+    PyObject *type, *value, *traceback;
+    Py_XINCREF(tstate->exc_type);
+    Py_XINCREF(tstate->exc_value);
+    Py_XINCREF(tstate->exc_traceback);
+    type = f->f_exc_type;
+    value = f->f_exc_value;
+    traceback = f->f_exc_traceback;
+    f->f_exc_type = tstate->exc_type;
+    f->f_exc_value = tstate->exc_value;
+    f->f_exc_traceback = tstate->exc_traceback;
+    Py_XDECREF(type);
+    Py_XDECREF(value);
+    Py_XDECREF(traceback);
+}
+
+static void
+swap_exc_state(PyThreadState *tstate, PyFrameObject *f)
+{
+    PyObject *tmp;
+    tmp = tstate->exc_type;
+    tstate->exc_type = f->f_exc_type;
+    f->f_exc_type = tmp;
+    tmp = tstate->exc_value;
+    tstate->exc_value = f->f_exc_value;
+    f->f_exc_value = tmp;
+    tmp = tstate->exc_traceback;
+    tstate->exc_traceback = f->f_exc_traceback;
+    f->f_exc_traceback = tmp;
+}
+
+static void
+restore_and_clear_exc_state(PyThreadState *tstate, PyFrameObject *f)
+{
+    PyObject *type, *value, *tb;
+    type = tstate->exc_type;
+    value = tstate->exc_value;
+    tb = tstate->exc_traceback;
+    tstate->exc_type = f->f_exc_type;
+    tstate->exc_value = f->f_exc_value;
+    tstate->exc_traceback = f->f_exc_traceback;
+    f->f_exc_type = NULL;
+    f->f_exc_value = NULL;
+    f->f_exc_traceback = NULL;
+    Py_XDECREF(type);
+    Py_XDECREF(value);
+    Py_XDECREF(tb);
+}
+
+
+/* Logic for the raise statement (too complicated for inlining).
+   This *consumes* a reference count to each of its arguments. */
+static enum why_code
+do_raise(PyObject *exc, PyObject *cause)
+{
+    PyObject *type = NULL, *value = NULL;
+
+    if (exc == NULL) {
+        /* Reraise */
+        PyThreadState *tstate = PyThreadState_GET();
+        PyObject *tb;
+        type = tstate->exc_type;
+        value = tstate->exc_value;
+        tb = tstate->exc_traceback;
+        if (type == Py_None) {
+            PyErr_SetString(PyExc_RuntimeError,
+                            "No active exception to reraise");
+            return WHY_EXCEPTION;
+            }
+        Py_XINCREF(type);
+        Py_XINCREF(value);
+        Py_XINCREF(tb);
+        PyErr_Restore(type, value, tb);
+        return WHY_RERAISE;
+    }
+
+    /* We support the following forms of raise:
+       raise
+       raise <instance>
+       raise <type> */
+
+    if (PyExceptionClass_Check(exc)) {
+        type = exc;
+        value = PyObject_CallObject(exc, NULL);
+        if (value == NULL)
+            goto raise_error;
+        if (!PyExceptionInstance_Check(value)) {
+            PyErr_Format(PyExc_TypeError,
+                         "calling %R should have returned an instance of "
+                         "BaseException, not %R",
+                         type, Py_TYPE(value));
+            goto raise_error;
+        }
+    }
+    else if (PyExceptionInstance_Check(exc)) {
+        value = exc;
+        type = PyExceptionInstance_Class(exc);
+        Py_INCREF(type);
+    }
+    else {
+        /* Not something you can raise.  You get an exception
+           anyway, just not what you specified :-) */
+        Py_DECREF(exc);
+        PyErr_SetString(PyExc_TypeError,
+                        "exceptions must derive from BaseException");
+        goto raise_error;
+    }
+
+    if (cause) {
+        PyObject *fixed_cause;
+        if (PyExceptionClass_Check(cause)) {
+            fixed_cause = PyObject_CallObject(cause, NULL);
+            if (fixed_cause == NULL)
+                goto raise_error;
+            Py_DECREF(cause);
+        }
+        else if (PyExceptionInstance_Check(cause)) {
+            fixed_cause = cause;
+        }
+        else {
+            PyErr_SetString(PyExc_TypeError,
+                            "exception causes must derive from "
+                            "BaseException");
+            goto raise_error;
+        }
+        PyException_SetCause(value, fixed_cause);
+    }
+
+    PyErr_SetObject(type, value);
+    /* PyErr_SetObject incref's its arguments */
+    Py_XDECREF(value);
+    Py_XDECREF(type);
+    return WHY_EXCEPTION;
+
+raise_error:
+    Py_XDECREF(value);
+    Py_XDECREF(type);
+    Py_XDECREF(cause);
+    return WHY_EXCEPTION;
+}
+
+/* Iterate v argcnt times and store the results on the stack (via decreasing
+   sp).  Return 1 for success, 0 if error.
+
+   If argcntafter == -1, do a simple unpack. If it is >= 0, do an unpack
+   with a variable target.
+*/
+
+static int
+unpack_iterable(PyObject *v, int argcnt, int argcntafter, PyObject **sp)
+{
+    int i = 0, j = 0;
+    Py_ssize_t ll = 0;
+    PyObject *it;  /* iter(v) */
+    PyObject *w;
+    PyObject *l = NULL; /* variable list */
+
+    assert(v != NULL);
+
+    it = PyObject_GetIter(v);
+    if (it == NULL)
+        goto Error;
+
+    for (; i < argcnt; i++) {
+        w = PyIter_Next(it);
+        if (w == NULL) {
+            /* Iterator done, via error or exhaustion. */
+            if (!PyErr_Occurred()) {
+                PyErr_Format(PyExc_ValueError,
+                    "need more than %d value%s to unpack",
+                    i, i == 1 ? "" : "s");
+            }
+            goto Error;
+        }
+        *--sp = w;
+    }
+
+    if (argcntafter == -1) {
+        /* We better have exhausted the iterator now. */
+        w = PyIter_Next(it);
+        if (w == NULL) {
+            if (PyErr_Occurred())
+                goto Error;
+            Py_DECREF(it);
+            return 1;
+        }
+        Py_DECREF(w);
+        PyErr_Format(PyExc_ValueError, "too many values to unpack "
+                     "(expected %d)", argcnt);
+        goto Error;
+    }
+
+    l = PySequence_List(it);
+    if (l == NULL)
+        goto Error;
+    *--sp = l;
+    i++;
+
+    ll = PyList_GET_SIZE(l);
+    if (ll < argcntafter) {
+        PyErr_Format(PyExc_ValueError, "need more than %zd values to unpack",
+                     argcnt + ll);
+        goto Error;
+    }
+
+    /* Pop the "after-variable" args off the list. */
+    for (j = argcntafter; j > 0; j--, i++) {
+        *--sp = PyList_GET_ITEM(l, ll - j);
+    }
+    /* Resize the list. */
+    Py_SIZE(l) = ll - argcntafter;
+    Py_DECREF(it);
+    return 1;
+
+Error:
+    for (; i > 0; i--, sp++)
+        Py_DECREF(*sp);
+    Py_XDECREF(it);
+    return 0;
+}
+
+
+#ifdef LLTRACE
+static int
+prtrace(PyObject *v, char *str)
+{
+    printf("%s ", str);
+    if (PyObject_Print(v, stdout, 0) != 0)
+        PyErr_Clear(); /* Don't know what else to do */
+    printf("\n");
+    return 1;
+}
+#endif
+
+static void
+call_exc_trace(Py_tracefunc func, PyObject *self, PyFrameObject *f)
+{
+    PyObject *type, *value, *traceback, *arg;
+    int err;
+    PyErr_Fetch(&type, &value, &traceback);
+    if (value == NULL) {
+        value = Py_None;
+        Py_INCREF(value);
+    }
+    arg = PyTuple_Pack(3, type, value, traceback);
+    if (arg == NULL) {
+        PyErr_Restore(type, value, traceback);
+        return;
+    }
+    err = call_trace(func, self, f, PyTrace_EXCEPTION, arg);
+    Py_DECREF(arg);
+    if (err == 0)
+        PyErr_Restore(type, value, traceback);
+    else {
+        Py_XDECREF(type);
+        Py_XDECREF(value);
+        Py_XDECREF(traceback);
+    }
+}
+
+static int
+call_trace_protected(Py_tracefunc func, PyObject *obj, PyFrameObject *frame,
+                     int what, PyObject *arg)
+{
+    PyObject *type, *value, *traceback;
+    int err;
+    PyErr_Fetch(&type, &value, &traceback);
+    err = call_trace(func, obj, frame, what, arg);
+    if (err == 0)
+    {
+        PyErr_Restore(type, value, traceback);
+        return 0;
+    }
+    else {
+        Py_XDECREF(type);
+        Py_XDECREF(value);
+        Py_XDECREF(traceback);
+        return -1;
+    }
+}
+
+static int
+call_trace(Py_tracefunc func, PyObject *obj, PyFrameObject *frame,
+           int what, PyObject *arg)
+{
+    register PyThreadState *tstate = frame->f_tstate;
+    int result;
+    if (tstate->tracing)
+        return 0;
+    tstate->tracing++;
+    tstate->use_tracing = 0;
+    result = func(obj, frame, what, arg);
+    tstate->use_tracing = ((tstate->c_tracefunc != NULL)
+                           || (tstate->c_profilefunc != NULL));
+    tstate->tracing--;
+    return result;
+}
+
+PyObject *
+_PyEval_CallTracing(PyObject *func, PyObject *args)
+{
+    PyFrameObject *frame = PyEval_GetFrame();
+    PyThreadState *tstate = frame->f_tstate;
+    int save_tracing = tstate->tracing;
+    int save_use_tracing = tstate->use_tracing;
+    PyObject *result;
+
+    tstate->tracing = 0;
+    tstate->use_tracing = ((tstate->c_tracefunc != NULL)
+                           || (tstate->c_profilefunc != NULL));
+    result = PyObject_Call(func, args, NULL);
+    tstate->tracing = save_tracing;
+    tstate->use_tracing = save_use_tracing;
+    return result;
+}
+
+/* See Objects/lnotab_notes.txt for a description of how tracing works. */
+static int
+maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
+                      PyFrameObject *frame, int *instr_lb, int *instr_ub,
+                      int *instr_prev)
+{
+    int result = 0;
+    int line = frame->f_lineno;
+
+    /* If the last instruction executed isn't in the current
+       instruction window, reset the window.
+    */
+    if (frame->f_lasti < *instr_lb || frame->f_lasti >= *instr_ub) {
+        PyAddrPair bounds;
+        line = _PyCode_CheckLineNumber(frame->f_code, frame->f_lasti,
+                                       &bounds);
+        *instr_lb = bounds.ap_lower;
+        *instr_ub = bounds.ap_upper;
+    }
+    /* If the last instruction falls at the start of a line or if
+       it represents a jump backwards, update the frame's line
+       number and call the trace function. */
+    if (frame->f_lasti == *instr_lb || frame->f_lasti < *instr_prev) {
+        frame->f_lineno = line;
+        result = call_trace(func, obj, frame, PyTrace_LINE, Py_None);
+    }
+    *instr_prev = frame->f_lasti;
+    return result;
+}
+
+void
+PyEval_SetProfile(Py_tracefunc func, PyObject *arg)
+{
+    PyThreadState *tstate = PyThreadState_GET();
+    PyObject *temp = tstate->c_profileobj;
+    Py_XINCREF(arg);
+    tstate->c_profilefunc = NULL;
+    tstate->c_profileobj = NULL;
+    /* Must make sure that tracing is not ignored if 'temp' is freed */
+    tstate->use_tracing = tstate->c_tracefunc != NULL;
+    Py_XDECREF(temp);
+    tstate->c_profilefunc = func;
+    tstate->c_profileobj = arg;
+    /* Flag that tracing or profiling is turned on */
+    tstate->use_tracing = (func != NULL) || (tstate->c_tracefunc != NULL);
+}
+
+void
+PyEval_SetTrace(Py_tracefunc func, PyObject *arg)
+{
+    PyThreadState *tstate = PyThreadState_GET();
+    PyObject *temp = tstate->c_traceobj;
+    _Py_TracingPossible += (func != NULL) - (tstate->c_tracefunc != NULL);
+    Py_XINCREF(arg);
+    tstate->c_tracefunc = NULL;
+    tstate->c_traceobj = NULL;
+    /* Must make sure that profiling is not ignored if 'temp' is freed */
+    tstate->use_tracing = tstate->c_profilefunc != NULL;
+    Py_XDECREF(temp);
+    tstate->c_tracefunc = func;
+    tstate->c_traceobj = arg;
+    /* Flag that tracing or profiling is turned on */
+    tstate->use_tracing = ((func != NULL)
+                           || (tstate->c_profilefunc != NULL));
+}
+
+PyObject *
+PyEval_GetBuiltins(void)
+{
+    PyFrameObject *current_frame = PyEval_GetFrame();
+    if (current_frame == NULL)
+        return PyThreadState_GET()->interp->builtins;
+    else
+        return current_frame->f_builtins;
+}
+
+PyObject *
+PyEval_GetLocals(void)
+{
+    PyFrameObject *current_frame = PyEval_GetFrame();
+    if (current_frame == NULL)
+        return NULL;
+    PyFrame_FastToLocals(current_frame);
+    return current_frame->f_locals;
+}
+
+PyObject *
+PyEval_GetGlobals(void)
+{
+    PyFrameObject *current_frame = PyEval_GetFrame();
+    if (current_frame == NULL)
+        return NULL;
+    else
+        return current_frame->f_globals;
+}
+
+PyFrameObject *
+PyEval_GetFrame(void)
+{
+    PyThreadState *tstate = PyThreadState_GET();
+    return _PyThreadState_GetFrame(tstate);
+}
+
+int
+PyEval_MergeCompilerFlags(PyCompilerFlags *cf)
+{
+    PyFrameObject *current_frame = PyEval_GetFrame();
+    int result = cf->cf_flags != 0;
+
+    if (current_frame != NULL) {
+        const int codeflags = current_frame->f_code->co_flags;
+        const int compilerflags = codeflags & PyCF_MASK;
+        if (compilerflags) {
+            result = 1;
+            cf->cf_flags |= compilerflags;
+        }
+#if 0 /* future keyword */
+        if (codeflags & CO_GENERATOR_ALLOWED) {
+            result = 1;
+            cf->cf_flags |= CO_GENERATOR_ALLOWED;
+        }
+#endif
+    }
+    return result;
+}
+
+
+/* External interface to call any callable object.
+   The arg must be a tuple or NULL.  The kw must be a dict or NULL. */
+
+PyObject *
+PyEval_CallObjectWithKeywords(PyObject *func, PyObject *arg, PyObject *kw)
+{
+    PyObject *result;
+
+    if (arg == NULL) {
+        arg = PyTuple_New(0);
+        if (arg == NULL)
+            return NULL;
+    }
+    else if (!PyTuple_Check(arg)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "argument list must be a tuple");
+        return NULL;
+    }
+    else
+        Py_INCREF(arg);
+
+    if (kw != NULL && !PyDict_Check(kw)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "keyword list must be a dictionary");
+        Py_DECREF(arg);
+        return NULL;
+    }
+
+    result = PyObject_Call(func, arg, kw);
+    Py_DECREF(arg);
+    return result;
+}
+
+const char *
+PyEval_GetFuncName(PyObject *func)
+{
+    if (PyMethod_Check(func))
+        return PyEval_GetFuncName(PyMethod_GET_FUNCTION(func));
+    else if (PyFunction_Check(func))
+        return _PyUnicode_AsString(((PyFunctionObject*)func)->func_name);
+    else if (PyCFunction_Check(func))
+        return ((PyCFunctionObject*)func)->m_ml->ml_name;
+    else
+        return func->ob_type->tp_name;
+}
+
+const char *
+PyEval_GetFuncDesc(PyObject *func)
+{
+    if (PyMethod_Check(func))
+        return "()";
+    else if (PyFunction_Check(func))
+        return "()";
+    else if (PyCFunction_Check(func))
+        return "()";
+    else
+        return " object";
+}
+
+static void
+err_args(PyObject *func, int flags, int nargs)
+{
+    if (flags & METH_NOARGS)
+        PyErr_Format(PyExc_TypeError,
+                     "%.200s() takes no arguments (%d given)",
+                     ((PyCFunctionObject *)func)->m_ml->ml_name,
+                     nargs);
+    else
+        PyErr_Format(PyExc_TypeError,
+                     "%.200s() takes exactly one argument (%d given)",
+                     ((PyCFunctionObject *)func)->m_ml->ml_name,
+                     nargs);
+}
+
+#define C_TRACE(x, call) \
+if (tstate->use_tracing && tstate->c_profilefunc) { \
+    if (call_trace(tstate->c_profilefunc, \
+        tstate->c_profileobj, \
+        tstate->frame, PyTrace_C_CALL, \
+        func)) { \
+        x = NULL; \
+    } \
+    else { \
+        x = call; \
+        if (tstate->c_profilefunc != NULL) { \
+            if (x == NULL) { \
+                call_trace_protected(tstate->c_profilefunc, \
+                    tstate->c_profileobj, \
+                    tstate->frame, PyTrace_C_EXCEPTION, \
+                    func); \
+                /* XXX should pass (type, value, tb) */ \
+            } else { \
+                if (call_trace(tstate->c_profilefunc, \
+                    tstate->c_profileobj, \
+                    tstate->frame, PyTrace_C_RETURN, \
+                    func)) { \
+                    Py_DECREF(x); \
+                    x = NULL; \
+                } \
+            } \
+        } \
+    } \
+} else { \
+    x = call; \
+    }
+
+static PyObject *
+call_function(PyObject ***pp_stack, int oparg
+#ifdef WITH_TSC
+                , uint64* pintr0, uint64* pintr1
+#endif
+                )
+{
+    int na = oparg & 0xff;
+    int nk = (oparg>>8) & 0xff;
+    int n = na + 2 * nk;
+    PyObject **pfunc = (*pp_stack) - n - 1;
+    PyObject *func = *pfunc;
+    PyObject *x, *w;
+
+    /* Always dispatch PyCFunction first, because these are
+       presumed to be the most frequent callable object.
+    */
+    if (PyCFunction_Check(func) && nk == 0) {
+        int flags = PyCFunction_GET_FLAGS(func);
+        PyThreadState *tstate = PyThreadState_GET();
+
+        PCALL(PCALL_CFUNCTION);
+        if (flags & (METH_NOARGS | METH_O)) {
+            PyCFunction meth = PyCFunction_GET_FUNCTION(func);
+            PyObject *self = PyCFunction_GET_SELF(func);
+            if (flags & METH_NOARGS && na == 0) {
+                C_TRACE(x, (*meth)(self,NULL));
+            }
+            else if (flags & METH_O && na == 1) {
+                PyObject *arg = EXT_POP(*pp_stack);
+                C_TRACE(x, (*meth)(self,arg));
+                Py_DECREF(arg);
+            }
+            else {
+                err_args(func, flags, na);
+                x = NULL;
+            }
+        }
+        else {
+            PyObject *callargs;
+            callargs = load_args(pp_stack, na);
+            READ_TIMESTAMP(*pintr0);
+            C_TRACE(x, PyCFunction_Call(func,callargs,NULL));
+            READ_TIMESTAMP(*pintr1);
+            Py_XDECREF(callargs);
+        }
+    } else {
+        if (PyMethod_Check(func) && PyMethod_GET_SELF(func) != NULL) {
+            /* optimize access to bound methods */
+            PyObject *self = PyMethod_GET_SELF(func);
+            PCALL(PCALL_METHOD);
+            PCALL(PCALL_BOUND_METHOD);
+            Py_INCREF(self);
+            func = PyMethod_GET_FUNCTION(func);
+            Py_INCREF(func);
+            Py_DECREF(*pfunc);
+            *pfunc = self;
+            na++;
+            n++;
+        } else
+            Py_INCREF(func);
+        READ_TIMESTAMP(*pintr0);
+        if (PyFunction_Check(func))
+            x = fast_function(func, pp_stack, n, na, nk);
+        else
+            x = do_call(func, pp_stack, na, nk);
+        READ_TIMESTAMP(*pintr1);
+        Py_DECREF(func);
+    }
+
+    /* Clear the stack of the function object.  Also removes
+       the arguments in case they weren't consumed already
+       (fast_function() and err_args() leave them on the stack).
+     */
+    while ((*pp_stack) > pfunc) {
+        w = EXT_POP(*pp_stack);
+        Py_DECREF(w);
+        PCALL(PCALL_POP);
+    }
+    return x;
+}
+
+/* The fast_function() function optimize calls for which no argument
+   tuple is necessary; the objects are passed directly from the stack.
+   For the simplest case -- a function that takes only positional
+   arguments and is called with only positional arguments -- it
+   inlines the most primitive frame setup code from
+   PyEval_EvalCodeEx(), which vastly reduces the checks that must be
+   done before evaluating the frame.
+*/
+
+static PyObject *
+fast_function(PyObject *func, PyObject ***pp_stack, int n, int na, int nk)
+{
+    PyCodeObject *co = (PyCodeObject *)PyFunction_GET_CODE(func);
+    PyObject *globals = PyFunction_GET_GLOBALS(func);
+    PyObject *argdefs = PyFunction_GET_DEFAULTS(func);
+    PyObject *kwdefs = PyFunction_GET_KW_DEFAULTS(func);
+    PyObject **d = NULL;
+    int nd = 0;
+
+    PCALL(PCALL_FUNCTION);
+    PCALL(PCALL_FAST_FUNCTION);
+    if (argdefs == NULL && co->co_argcount == n &&
+        co->co_kwonlyargcount == 0 && nk==0 &&
+        co->co_flags == (CO_OPTIMIZED | CO_NEWLOCALS | CO_NOFREE)) {
+        PyFrameObject *f;
+        PyObject *retval = NULL;
+        PyThreadState *tstate = PyThreadState_GET();
+        PyObject **fastlocals, **stack;
+        int i;
+
+        PCALL(PCALL_FASTER_FUNCTION);
+        assert(globals != NULL);
+        /* XXX Perhaps we should create a specialized
+           PyFrame_New() that doesn't take locals, but does
+           take builtins without sanity checking them.
+        */
+        assert(tstate != NULL);
+        f = PyFrame_New(tstate, co, globals, NULL);
+        if (f == NULL)
+            return NULL;
+
+        fastlocals = f->f_localsplus;
+        stack = (*pp_stack) - n;
+
+        for (i = 0; i < n; i++) {
+            Py_INCREF(*stack);
+            fastlocals[i] = *stack++;
+        }
+        retval = PyEval_EvalFrameEx(f,0);
+        ++tstate->recursion_depth;
+        Py_DECREF(f);
+        --tstate->recursion_depth;
+        return retval;
+    }
+    if (argdefs != NULL) {
+        d = &PyTuple_GET_ITEM(argdefs, 0);
+        nd = Py_SIZE(argdefs);
+    }
+    return PyEval_EvalCodeEx((PyObject*)co, globals,
+                             (PyObject *)NULL, (*pp_stack)-n, na,
+                             (*pp_stack)-2*nk, nk, d, nd, kwdefs,
+                             PyFunction_GET_CLOSURE(func));
+}
+
+static PyObject *
+update_keyword_args(PyObject *orig_kwdict, int nk, PyObject ***pp_stack,
+                    PyObject *func)
+{
+    PyObject *kwdict = NULL;
+    if (orig_kwdict == NULL)
+        kwdict = PyDict_New();
+    else {
+        kwdict = PyDict_Copy(orig_kwdict);
+        Py_DECREF(orig_kwdict);
+    }
+    if (kwdict == NULL)
+        return NULL;
+    while (--nk >= 0) {
+        int err;
+        PyObject *value = EXT_POP(*pp_stack);
+        PyObject *key = EXT_POP(*pp_stack);
+        if (PyDict_GetItem(kwdict, key) != NULL) {
+            PyErr_Format(PyExc_TypeError,
+                         "%.200s%s got multiple values "
+                         "for keyword argument '%U'",
+                         PyEval_GetFuncName(func),
+                         PyEval_GetFuncDesc(func),
+                         key);
+            Py_DECREF(key);
+            Py_DECREF(value);
+            Py_DECREF(kwdict);
+            return NULL;
+        }
+        err = PyDict_SetItem(kwdict, key, value);
+        Py_DECREF(key);
+        Py_DECREF(value);
+        if (err) {
+            Py_DECREF(kwdict);
+            return NULL;
+        }
+    }
+    return kwdict;
+}
+
+static PyObject *
+update_star_args(int nstack, int nstar, PyObject *stararg,
+                 PyObject ***pp_stack)
+{
+    PyObject *callargs, *w;
+
+    callargs = PyTuple_New(nstack + nstar);
+    if (callargs == NULL) {
+        return NULL;
+    }
+    if (nstar) {
+        int i;
+        for (i = 0; i < nstar; i++) {
+            PyObject *a = PyTuple_GET_ITEM(stararg, i);
+            Py_INCREF(a);
+            PyTuple_SET_ITEM(callargs, nstack + i, a);
+        }
+    }
+    while (--nstack >= 0) {
+        w = EXT_POP(*pp_stack);
+        PyTuple_SET_ITEM(callargs, nstack, w);
+    }
+    return callargs;
+}
+
+static PyObject *
+load_args(PyObject ***pp_stack, int na)
+{
+    PyObject *args = PyTuple_New(na);
+    PyObject *w;
+
+    if (args == NULL)
+        return NULL;
+    while (--na >= 0) {
+        w = EXT_POP(*pp_stack);
+        PyTuple_SET_ITEM(args, na, w);
+    }
+    return args;
+}
+
+static PyObject *
+do_call(PyObject *func, PyObject ***pp_stack, int na, int nk)
+{
+    PyObject *callargs = NULL;
+    PyObject *kwdict = NULL;
+    PyObject *result = NULL;
+
+    if (nk > 0) {
+        kwdict = update_keyword_args(NULL, nk, pp_stack, func);
+        if (kwdict == NULL)
+            goto call_fail;
+    }
+    callargs = load_args(pp_stack, na);
+    if (callargs == NULL)
+        goto call_fail;
+#ifdef CALL_PROFILE
+    /* At this point, we have to look at the type of func to
+       update the call stats properly.  Do it here so as to avoid
+       exposing the call stats machinery outside ceval.c
+    */
+    if (PyFunction_Check(func))
+        PCALL(PCALL_FUNCTION);
+    else if (PyMethod_Check(func))
+        PCALL(PCALL_METHOD);
+    else if (PyType_Check(func))
+        PCALL(PCALL_TYPE);
+    else if (PyCFunction_Check(func))
+        PCALL(PCALL_CFUNCTION);
+    else
+        PCALL(PCALL_OTHER);
+#endif
+    if (PyCFunction_Check(func)) {
+        PyThreadState *tstate = PyThreadState_GET();
+        C_TRACE(result, PyCFunction_Call(func, callargs, kwdict));
+    }
+    else
+        result = PyObject_Call(func, callargs, kwdict);
+call_fail:
+    Py_XDECREF(callargs);
+    Py_XDECREF(kwdict);
+    return result;
+}
+
+static PyObject *
+ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk)
+{
+    int nstar = 0;
+    PyObject *callargs = NULL;
+    PyObject *stararg = NULL;
+    PyObject *kwdict = NULL;
+    PyObject *result = NULL;
+
+    if (flags & CALL_FLAG_KW) {
+        kwdict = EXT_POP(*pp_stack);
+        if (!PyDict_Check(kwdict)) {
+            PyObject *d;
+            d = PyDict_New();
+            if (d == NULL)
+                goto ext_call_fail;
+            if (PyDict_Update(d, kwdict) != 0) {
+                Py_DECREF(d);
+                /* PyDict_Update raises attribute
+                 * error (percolated from an attempt
+                 * to get 'keys' attribute) instead of
+                 * a type error if its second argument
+                 * is not a mapping.
+                 */
+                if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
+                    PyErr_Format(PyExc_TypeError,
+                                 "%.200s%.200s argument after ** "
+                                 "must be a mapping, not %.200s",
+                                 PyEval_GetFuncName(func),
+                                 PyEval_GetFuncDesc(func),
+                                 kwdict->ob_type->tp_name);
+                }
+                goto ext_call_fail;
+            }
+            Py_DECREF(kwdict);
+            kwdict = d;
+        }
+    }
+    if (flags & CALL_FLAG_VAR) {
+        stararg = EXT_POP(*pp_stack);
+        if (!PyTuple_Check(stararg)) {
+            PyObject *t = NULL;
+            t = PySequence_Tuple(stararg);
+            if (t == NULL) {
+                if (PyErr_ExceptionMatches(PyExc_TypeError)) {
+                    PyErr_Format(PyExc_TypeError,
+                                 "%.200s%.200s argument after * "
+                                 "must be a sequence, not %.200s",
+                                 PyEval_GetFuncName(func),
+                                 PyEval_GetFuncDesc(func),
+                                 stararg->ob_type->tp_name);
+                }
+                goto ext_call_fail;
+            }
+            Py_DECREF(stararg);
+            stararg = t;
+        }
+        nstar = PyTuple_GET_SIZE(stararg);
+    }
+    if (nk > 0) {
+        kwdict = update_keyword_args(kwdict, nk, pp_stack, func);
+        if (kwdict == NULL)
+            goto ext_call_fail;
+    }
+    callargs = update_star_args(na, nstar, stararg, pp_stack);
+    if (callargs == NULL)
+        goto ext_call_fail;
+#ifdef CALL_PROFILE
+    /* At this point, we have to look at the type of func to
+       update the call stats properly.  Do it here so as to avoid
+       exposing the call stats machinery outside ceval.c
+    */
+    if (PyFunction_Check(func))
+        PCALL(PCALL_FUNCTION);
+    else if (PyMethod_Check(func))
+        PCALL(PCALL_METHOD);
+    else if (PyType_Check(func))
+        PCALL(PCALL_TYPE);
+    else if (PyCFunction_Check(func))
+        PCALL(PCALL_CFUNCTION);
+    else
+        PCALL(PCALL_OTHER);
+#endif
+    if (PyCFunction_Check(func)) {
+        PyThreadState *tstate = PyThreadState_GET();
+        C_TRACE(result, PyCFunction_Call(func, callargs, kwdict));
+    }
+    else
+        result = PyObject_Call(func, callargs, kwdict);
+ext_call_fail:
+    Py_XDECREF(callargs);
+    Py_XDECREF(kwdict);
+    Py_XDECREF(stararg);
+    return result;
+}
+
+/* Extract a slice index from a PyInt or PyLong or an object with the
+   nb_index slot defined, and store in *pi.
+   Silently reduce values larger than PY_SSIZE_T_MAX to PY_SSIZE_T_MAX,
+   and silently boost values less than -PY_SSIZE_T_MAX-1 to -PY_SSIZE_T_MAX-1.
+   Return 0 on error, 1 on success.
+*/
+/* Note:  If v is NULL, return success without storing into *pi.  This
+   is because_PyEval_SliceIndex() is called by apply_slice(), which can be
+   called by the SLICE opcode with v and/or w equal to NULL.
+*/
+int
+_PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi)
+{
+    if (v != NULL) {
+        Py_ssize_t x;
+        if (PyIndex_Check(v)) {
+            x = PyNumber_AsSsize_t(v, NULL);
+            if (x == -1 && PyErr_Occurred())
+                return 0;
+        }
+        else {
+            PyErr_SetString(PyExc_TypeError,
+                            "slice indices must be integers or "
+                            "None or have an __index__ method");
+            return 0;
+        }
+        *pi = x;
+    }
+    return 1;
+}
+
+#define CANNOT_CATCH_MSG "catching classes that do not inherit from "\
+                         "BaseException is not allowed"
+
+static PyObject *
+cmp_outcome(int op, register PyObject *v, register PyObject *w)
+{
+    int res = 0;
+    switch (op) {
+    case PyCmp_IS:
+        res = (v == w);
+        break;
+    case PyCmp_IS_NOT:
+        res = (v != w);
+        break;
+    case PyCmp_IN:
+        res = PySequence_Contains(w, v);
+        if (res < 0)
+            return NULL;
+        break;
+    case PyCmp_NOT_IN:
+        res = PySequence_Contains(w, v);
+        if (res < 0)
+            return NULL;
+        res = !res;
+        break;
+    case PyCmp_EXC_MATCH:
+        if (PyTuple_Check(w)) {
+            Py_ssize_t i, length;
+            length = PyTuple_Size(w);
+            for (i = 0; i < length; i += 1) {
+                PyObject *exc = PyTuple_GET_ITEM(w, i);
+                if (!PyExceptionClass_Check(exc)) {
+                    PyErr_SetString(PyExc_TypeError,
+                                    CANNOT_CATCH_MSG);
+                    return NULL;
+                }
+            }
+        }
+        else {
+            if (!PyExceptionClass_Check(w)) {
+                PyErr_SetString(PyExc_TypeError,
+                                CANNOT_CATCH_MSG);
+                return NULL;
+            }
+        }
+        res = PyErr_GivenExceptionMatches(v, w);
+        break;
+    default:
+        return PyObject_RichCompare(v, w, op);
+    }
+    v = res ? Py_True : Py_False;
+    Py_INCREF(v);
+    return v;
+}
+
+static PyObject *
+import_from(PyObject *v, PyObject *name)
+{
+    PyObject *x;
+
+    x = PyObject_GetAttr(v, name);
+    if (x == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
+        PyErr_Format(PyExc_ImportError, "cannot import name %S", name);
+    }
+    return x;
+}
+
+static int
+import_all_from(PyObject *locals, PyObject *v)
+{
+    _Py_IDENTIFIER(__all__);
+    _Py_IDENTIFIER(__dict__);
+    PyObject *all = _PyObject_GetAttrId(v, &PyId___all__);
+    PyObject *dict, *name, *value;
+    int skip_leading_underscores = 0;
+    int pos, err;
+
+    if (all == NULL) {
+        if (!PyErr_ExceptionMatches(PyExc_AttributeError))
+            return -1; /* Unexpected error */
+        PyErr_Clear();
+        dict = _PyObject_GetAttrId(v, &PyId___dict__);
+        if (dict == NULL) {
+            if (!PyErr_ExceptionMatches(PyExc_AttributeError))
+                return -1;
+            PyErr_SetString(PyExc_ImportError,
+            "from-import-* object has no __dict__ and no __all__");
+            return -1;
+        }
+        all = PyMapping_Keys(dict);
+        Py_DECREF(dict);
+        if (all == NULL)
+            return -1;
+        skip_leading_underscores = 1;
+    }
+
+    for (pos = 0, err = 0; ; pos++) {
+        name = PySequence_GetItem(all, pos);
+        if (name == NULL) {
+            if (!PyErr_ExceptionMatches(PyExc_IndexError))
+                err = -1;
+            else
+                PyErr_Clear();
+            break;
+        }
+        if (skip_leading_underscores &&
+            PyUnicode_Check(name) &&
+            PyUnicode_READY(name) != -1 &&
+            PyUnicode_READ_CHAR(name, 0) == '_')
+        {
+            Py_DECREF(name);
+            continue;
+        }
+        value = PyObject_GetAttr(v, name);
+        if (value == NULL)
+            err = -1;
+        else if (PyDict_CheckExact(locals))
+            err = PyDict_SetItem(locals, name, value);
+        else
+            err = PyObject_SetItem(locals, name, value);
+        Py_DECREF(name);
+        Py_XDECREF(value);
+        if (err != 0)
+            break;
+    }
+    Py_DECREF(all);
+    return err;
+}
+
+static void
+format_exc_check_arg(PyObject *exc, const char *format_str, PyObject *obj)
+{
+    const char *obj_str;
+
+    if (!obj)
+        return;
+
+    obj_str = _PyUnicode_AsString(obj);
+    if (!obj_str)
+        return;
+
+    PyErr_Format(exc, format_str, obj_str);
+}
+
+static void
+format_exc_unbound(PyCodeObject *co, int oparg)
+{
+    PyObject *name;
+    /* Don't stomp existing exception */
+    if (PyErr_Occurred())
+        return;
+    if (oparg < PyTuple_GET_SIZE(co->co_cellvars)) {
+        name = PyTuple_GET_ITEM(co->co_cellvars,
+                                oparg);
+        format_exc_check_arg(
+            PyExc_UnboundLocalError,
+            UNBOUNDLOCAL_ERROR_MSG,
+            name);
+    } else {
+        name = PyTuple_GET_ITEM(co->co_freevars, oparg -
+                                PyTuple_GET_SIZE(co->co_cellvars));
+        format_exc_check_arg(PyExc_NameError,
+                             UNBOUNDFREE_ERROR_MSG, name);
+    }
+}
+
+static PyObject *
+unicode_concatenate(PyObject *v, PyObject *w,
+                    PyFrameObject *f, unsigned char *next_instr)
+{
+    PyObject *res;
+    if (Py_REFCNT(v) == 2) {
+        /* In the common case, there are 2 references to the value
+         * stored in 'variable' when the += is performed: one on the
+         * value stack (in 'v') and one still stored in the
+         * 'variable'.  We try to delete the variable now to reduce
+         * the refcnt to 1.
+         */
+        switch (*next_instr) {
+        case STORE_FAST:
+        {
+            int oparg = PEEKARG();
+            PyObject **fastlocals = f->f_localsplus;
+            if (GETLOCAL(oparg) == v)
+                SETLOCAL(oparg, NULL);
+            break;
+        }
+        case STORE_DEREF:
+        {
+            PyObject **freevars = (f->f_localsplus +
+                                   f->f_code->co_nlocals);
+            PyObject *c = freevars[PEEKARG()];
+            if (PyCell_GET(c) == v)
+                PyCell_Set(c, NULL);
+            break;
+        }
+        case STORE_NAME:
+        {
+            PyObject *names = f->f_code->co_names;
+            PyObject *name = GETITEM(names, PEEKARG());
+            PyObject *locals = f->f_locals;
+            if (PyDict_CheckExact(locals) &&
+                PyDict_GetItem(locals, name) == v) {
+                if (PyDict_DelItem(locals, name) != 0) {
+                    PyErr_Clear();
+                }
+            }
+            break;
+        }
+        }
+    }
+    res = v;
+    PyUnicode_Append(&res, w);
+    return res;
+}
+
+