summaryrefslogtreecommitdiffstats
path: root/Python/ceval.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c2489
1 files changed, 1074 insertions, 1415 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 06ada97..f0ea7c9 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -13,7 +13,6 @@
#include "code.h"
#include "frameobject.h"
-#include "eval.h"
#include "opcode.h"
#include "structmember.h"
@@ -132,21 +131,13 @@ static void call_exc_trace(Py_tracefunc, PyObject *, PyFrameObject *);
static int maybe_call_line_trace(Py_tracefunc, PyObject *,
PyFrameObject *, int *, int *, int *);
-static PyObject * apply_slice(PyObject *, PyObject *, PyObject *);
-static int assign_slice(PyObject *, PyObject *,
- PyObject *, PyObject *);
static PyObject * cmp_outcome(int, PyObject *, PyObject *);
static PyObject * import_from(PyObject *, PyObject *);
static int import_all_from(PyObject *, PyObject *);
-static PyObject * build_class(PyObject *, PyObject *, PyObject *);
-static int exec_statement(PyFrameObject *,
- PyObject *, PyObject *, PyObject *);
-static void set_exc_info(PyThreadState *, PyObject *, PyObject *, PyObject *);
-static void reset_exc_info(PyThreadState *);
-static void format_exc_check_arg(PyObject *, char *, PyObject *);
-static PyObject * string_concatenate(PyObject *, PyObject *,
- PyFrameObject *, unsigned char *);
-static PyObject * kwd_as_string(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 \
@@ -227,42 +218,127 @@ PyEval_GetCallStats(PyObject *self)
#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
#ifdef HAVE_ERRNO_H
#include <errno.h>
#endif
#include "pythread.h"
-static PyThread_type_lock interpreter_lock = 0; /* This is the GIL */
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 interpreter_lock != 0;
+ return gil_created();
}
void
PyEval_InitThreads(void)
{
- if (interpreter_lock)
+ if (gil_created())
return;
- interpreter_lock = PyThread_allocate_lock();
- PyThread_acquire_lock(interpreter_lock, 1);
+ 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)
{
- PyThread_acquire_lock(interpreter_lock, 1);
+ PyThreadState *tstate = PyThreadState_GET();
+ if (tstate == NULL)
+ Py_FatalError("PyEval_AcquireLock: current thread state is NULL");
+ take_gil(tstate);
}
void
PyEval_ReleaseLock(void)
{
- PyThread_release_lock(interpreter_lock);
+ /* 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
@@ -271,8 +347,8 @@ 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(interpreter_lock);
- PyThread_acquire_lock(interpreter_lock, 1);
+ assert(gil_created());
+ take_gil(tstate);
if (PyThreadState_Swap(tstate) != NULL)
Py_FatalError(
"PyEval_AcquireThread: non-NULL old thread state");
@@ -285,7 +361,7 @@ PyEval_ReleaseThread(PyThreadState *tstate)
Py_FatalError("PyEval_ReleaseThread: NULL thread state");
if (PyThreadState_Swap(NULL) != tstate)
Py_FatalError("PyEval_ReleaseThread: wrong thread state");
- PyThread_release_lock(interpreter_lock);
+ drop_gil(tstate);
}
/* This function is called from PyOS_AfterFork to ensure that newly
@@ -297,17 +373,13 @@ void
PyEval_ReInitThreads(void)
{
PyObject *threading, *result;
- PyThreadState *tstate;
+ PyThreadState *tstate = PyThreadState_GET();
- if (!interpreter_lock)
+ if (!gil_created())
return;
- /*XXX Can't use PyThread_free_lock here because it does too
- much error-checking. Doing this cleanly would require
- adding a new function to each thread_*.h. Instead, just
- create a new lock and waste a little bit of memory */
- interpreter_lock = PyThread_allocate_lock();
+ recreate_gil();
pending_lock = PyThread_allocate_lock();
- PyThread_acquire_lock(interpreter_lock, 1);
+ take_gil(tstate);
main_thread = PyThread_get_thread_ident();
/* Update the threading module with the new state.
@@ -327,7 +399,20 @@ PyEval_ReInitThreads(void)
Py_DECREF(result);
Py_DECREF(threading);
}
-#endif
+
+#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
@@ -340,8 +425,8 @@ PyEval_SaveThread(void)
if (tstate == NULL)
Py_FatalError("PyEval_SaveThread: NULL tstate");
#ifdef WITH_THREAD
- if (interpreter_lock)
- PyThread_release_lock(interpreter_lock);
+ if (gil_created())
+ drop_gil(tstate);
#endif
return tstate;
}
@@ -352,9 +437,15 @@ PyEval_RestoreThread(PyThreadState *tstate)
if (tstate == NULL)
Py_FatalError("PyEval_RestoreThread: NULL tstate");
#ifdef WITH_THREAD
- if (interpreter_lock) {
+ if (gil_created()) {
int err = errno;
- PyThread_acquire_lock(interpreter_lock, 1);
+ 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
@@ -400,7 +491,6 @@ static struct {
} pendingcalls[NPENDINGCALLS];
static int pendingfirst = 0;
static int pendinglast = 0;
-static volatile int pendingcalls_to_do = 1; /* trigger initialization of lock */
static char pendingbusy = 0;
int
@@ -439,8 +529,7 @@ Py_AddPendingCall(int (*func)(void *), void *arg)
pendinglast = j;
}
/* signal main loop */
- _Py_Ticker = 0;
- pendingcalls_to_do = 1;
+ SIGNAL_PENDING_CALLS();
if (lock != NULL)
PyThread_release_lock(lock);
return result;
@@ -482,7 +571,10 @@ Py_MakePendingCalls(void)
arg = pendingcalls[j].arg;
pendingfirst = (j + 1) % NPENDINGCALLS;
}
- pendingcalls_to_do = pendingfirst != pendinglast;
+ 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)
@@ -527,7 +619,7 @@ static struct {
} pendingcalls[NPENDINGCALLS];
static volatile int pendingfirst = 0;
static volatile int pendinglast = 0;
-static volatile int pendingcalls_to_do = 0;
+static _Py_atomic_int pendingcalls_to_do = {0};
int
Py_AddPendingCall(int (*func)(void *), void *arg)
@@ -548,8 +640,7 @@ Py_AddPendingCall(int (*func)(void *), void *arg)
pendingcalls[i].arg = arg;
pendinglast = j;
- _Py_Ticker = 0;
- pendingcalls_to_do = 1; /* Signal main loop */
+ SIGNAL_PENDING_CALLS();
busy = 0;
/* XXX End critical section */
return 0;
@@ -562,7 +653,7 @@ Py_MakePendingCalls(void)
if (busy)
return 0;
busy = 1;
- pendingcalls_to_do = 0;
+ UNSIGNAL_PENDING_CALLS();
for (;;) {
int i;
int (*func)(void *);
@@ -575,7 +666,7 @@ Py_MakePendingCalls(void)
pendingfirst = (i + 1) % NPENDINGCALLS;
if (func(arg) < 0) {
busy = 0;
- pendingcalls_to_do = 1; /* We're not done yet */
+ SIGNAL_PENDING_CALLS(); /* We're not done yet */
return -1;
}
}
@@ -624,14 +715,25 @@ _Py_CheckRecursiveCall(char *where)
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;
}
- _Py_CheckRecursionLimit = recursion_limit;
return 0;
}
@@ -643,11 +745,12 @@ enum why_code {
WHY_RETURN = 0x0008, /* 'return' statement */
WHY_BREAK = 0x0010, /* 'break' statement */
WHY_CONTINUE = 0x0020, /* 'continue' statement */
- WHY_YIELD = 0x0040 /* 'yield' operator */
+ WHY_YIELD = 0x0040, /* 'yield' operator */
+ WHY_SILENCED = 0x0080 /* Exception silenced by 'with' */
};
-static enum why_code do_raise(PyObject *, PyObject *, PyObject *);
-static int unpack_iterable(PyObject *, int, PyObject **);
+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
@@ -656,20 +759,17 @@ static int unpack_iterable(PyObject *, int, PyObject **);
fast_next_opcode*/
static int _Py_TracingPossible = 0;
-/* for manipulating the thread switch and periodic "stuff" - used to be
- per thread, now just a pair o' globals */
-int _Py_CheckInterval = 100;
-volatile int _Py_Ticker = 0; /* so that we hit a "tick" first thing */
+
PyObject *
-PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals)
+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, NULL);
}
@@ -700,7 +800,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
register PyObject *w;
register PyObject *u;
register PyObject *t;
- register PyObject *stream = NULL; /* for PRINT opcodes */
register PyObject **fastlocals, **freevars;
PyObject *retval = NULL; /* Return value */
PyThreadState *tstate = PyThreadState_GET();
@@ -723,6 +822,124 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
char *filename;
#endif
+/* 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
@@ -754,7 +971,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
It's a case-by-case judgement. I'll use intr1 for the following
cases:
- EXEC_STMT
IMPORT_STAR
IMPORT_FROM
CALL_FUNCTION (and friends)
@@ -784,8 +1000,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
/* 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,
- GET_ITER is often followed by FOR_ITER. And FOR_ITER is often
- followed by STORE_FAST or UNPACK_SEQUENCE.
+ 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
@@ -801,16 +1017,23 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
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.
+
*/
-#ifdef DYNAMIC_EXECUTION_PROFILE
+#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
-#endif
-
#define PREDICTED(op) PRED_##op: next_instr++
#define PREDICTED_WITH_ARG(op) PRED_##op: oparg = PEEKARG(); next_instr += 3
+#endif
+
/* Stack manipulation macros */
@@ -865,6 +1088,80 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
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); \
+ }
+
+#define SAVE_EXC_STATE() \
+ { \
+ 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); \
+ }
+
+#define SWAP_EXC_STATE() \
+ { \
+ 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; \
+ }
+
+#define RESTORE_AND_CLEAR_EXC_STATE() \
+ { \
+ 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); \
+ }
+
/* Start of code */
if (f == NULL)
@@ -915,7 +1212,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
consts = co->co_consts;
fastlocals = f->f_localsplus;
freevars = f->f_localsplus + co->co_nlocals;
- first_instr = (unsigned char*) PyString_AS_STRING(co->co_code);
+ 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
@@ -938,11 +1235,32 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
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();
+ }
+ else {
+ SAVE_EXC_STATE();
+ }
+ }
+
#ifdef LLTRACE
lltrace = PyDict_GetItemString(f->f_globals, "__lltrace__") != NULL;
#endif
#if defined(Py_DEBUG) || defined(LLTRACE)
- filename = PyString_AsString(co->co_filename);
+ {
+ PyObject *error_type, *error_value, *error_traceback;
+ PyErr_Fetch(&error_type, &error_value, &error_traceback);
+ filename = _PyUnicode_AsString(co->co_filename);
+ if (filename == NULL && tstate->overflowed) {
+ /* maximum recursion depth exceeded */
+ goto exit_eval_frame;
+ }
+ PyErr_Restore(error_type, error_value, error_traceback);
+ }
#endif
why = WHY_NOT;
@@ -984,55 +1302,46 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
async I/O handler); see Py_AddPendingCall() and
Py_MakePendingCalls() above. */
- if (--_Py_Ticker < 0) {
+ 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;
}
- _Py_Ticker = _Py_CheckInterval;
tstate->tick_counter++;
#ifdef WITH_TSC
ticked = 1;
#endif
- if (pendingcalls_to_do) {
+ if (_Py_atomic_load_relaxed(&pendingcalls_to_do)) {
if (Py_MakePendingCalls() < 0) {
why = WHY_EXCEPTION;
goto on_error;
}
- if (pendingcalls_to_do)
- /* MakePendingCalls() didn't succeed.
- Force early re-execution of this
- "periodic" code, possibly after
- a thread switch */
- _Py_Ticker = 0;
}
#ifdef WITH_THREAD
- if (interpreter_lock) {
+ if (_Py_atomic_load_relaxed(&gil_drop_request)) {
/* Give another thread a chance */
-
if (PyThreadState_Swap(NULL) != tstate)
Py_FatalError("ceval: tstate mix-up");
- PyThread_release_lock(interpreter_lock);
+ drop_gil(tstate);
/* Other threads may run now */
- PyThread_acquire_lock(interpreter_lock, 1);
+ take_gil(tstate);
if (PyThreadState_Swap(tstate) != NULL)
Py_FatalError("ceval: orphan tstate");
-
- /* Check for thread interrupts */
-
- if (tstate->async_exc != NULL) {
- x = tstate->async_exc;
- tstate->async_exc = NULL;
- PyErr_SetNone(x);
- Py_DECREF(x);
- why = WHY_EXCEPTION;
- goto on_error;
- }
}
#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:
@@ -1105,599 +1414,406 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
/* case STOP_CODE: this is an error! */
- case NOP:
- goto fast_next_opcode;
+ TARGET(NOP)
+ FAST_DISPATCH();
- case LOAD_FAST:
+ TARGET(LOAD_FAST)
x = GETLOCAL(oparg);
if (x != NULL) {
Py_INCREF(x);
PUSH(x);
- goto fast_next_opcode;
+ FAST_DISPATCH();
}
format_exc_check_arg(PyExc_UnboundLocalError,
UNBOUNDLOCAL_ERROR_MSG,
PyTuple_GetItem(co->co_varnames, oparg));
break;
- case LOAD_CONST:
+ TARGET(LOAD_CONST)
x = GETITEM(consts, oparg);
Py_INCREF(x);
PUSH(x);
- goto fast_next_opcode;
+ FAST_DISPATCH();
PREDICTED_WITH_ARG(STORE_FAST);
- case STORE_FAST:
+ TARGET(STORE_FAST)
v = POP();
SETLOCAL(oparg, v);
- goto fast_next_opcode;
+ FAST_DISPATCH();
- case POP_TOP:
+ TARGET(POP_TOP)
v = POP();
Py_DECREF(v);
- goto fast_next_opcode;
+ FAST_DISPATCH();
- case ROT_TWO:
+ TARGET(ROT_TWO)
v = TOP();
w = SECOND();
SET_TOP(w);
SET_SECOND(v);
- goto fast_next_opcode;
+ FAST_DISPATCH();
- case ROT_THREE:
+ TARGET(ROT_THREE)
v = TOP();
w = SECOND();
x = THIRD();
SET_TOP(w);
SET_SECOND(x);
SET_THIRD(v);
- goto fast_next_opcode;
+ FAST_DISPATCH();
- case ROT_FOUR:
- u = TOP();
- v = SECOND();
- w = THIRD();
- x = FOURTH();
- SET_TOP(v);
- SET_SECOND(w);
- SET_THIRD(x);
- SET_FOURTH(u);
- goto fast_next_opcode;
-
- case DUP_TOP:
+ TARGET(DUP_TOP)
v = TOP();
Py_INCREF(v);
PUSH(v);
- goto fast_next_opcode;
+ FAST_DISPATCH();
- case DUP_TOPX:
- if (oparg == 2) {
- x = TOP();
- Py_INCREF(x);
- w = SECOND();
- Py_INCREF(w);
- STACKADJ(2);
- SET_TOP(x);
- SET_SECOND(w);
- goto fast_next_opcode;
- } else if (oparg == 3) {
- x = TOP();
- Py_INCREF(x);
- w = SECOND();
- Py_INCREF(w);
- v = THIRD();
- Py_INCREF(v);
- STACKADJ(3);
- SET_TOP(x);
- SET_SECOND(w);
- SET_THIRD(v);
- goto fast_next_opcode;
- }
- Py_FatalError("invalid argument to DUP_TOPX"
- " (bytecode corruption?)");
- /* Never returns, so don't bother to set why. */
- break;
+ TARGET(DUP_TOP_TWO)
+ x = TOP();
+ Py_INCREF(x);
+ w = SECOND();
+ Py_INCREF(w);
+ STACKADJ(2);
+ SET_TOP(x);
+ SET_SECOND(w);
+ FAST_DISPATCH();
- case UNARY_POSITIVE:
+ TARGET(UNARY_POSITIVE)
v = TOP();
x = PyNumber_Positive(v);
Py_DECREF(v);
SET_TOP(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case UNARY_NEGATIVE:
+ TARGET(UNARY_NEGATIVE)
v = TOP();
x = PyNumber_Negative(v);
Py_DECREF(v);
SET_TOP(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case UNARY_NOT:
+ TARGET(UNARY_NOT)
v = TOP();
err = PyObject_IsTrue(v);
Py_DECREF(v);
if (err == 0) {
Py_INCREF(Py_True);
SET_TOP(Py_True);
- continue;
+ DISPATCH();
}
else if (err > 0) {
Py_INCREF(Py_False);
SET_TOP(Py_False);
err = 0;
- continue;
+ DISPATCH();
}
STACKADJ(-1);
break;
- case UNARY_CONVERT:
- v = TOP();
- x = PyObject_Repr(v);
- Py_DECREF(v);
- SET_TOP(x);
- if (x != NULL) continue;
- break;
-
- case UNARY_INVERT:
+ TARGET(UNARY_INVERT)
v = TOP();
x = PyNumber_Invert(v);
Py_DECREF(v);
SET_TOP(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case BINARY_POWER:
+ 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) continue;
+ if (x != NULL) DISPATCH();
break;
- case BINARY_MULTIPLY:
+ TARGET(BINARY_MULTIPLY)
w = POP();
v = TOP();
x = PyNumber_Multiply(v, w);
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case BINARY_DIVIDE:
- if (!_Py_QnewFlag) {
- w = POP();
- v = TOP();
- x = PyNumber_Divide(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) continue;
- break;
- }
- /* -Qnew is in effect: fall through to
- BINARY_TRUE_DIVIDE */
- case BINARY_TRUE_DIVIDE:
+ 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) continue;
+ if (x != NULL) DISPATCH();
break;
- case BINARY_FLOOR_DIVIDE:
+ 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) continue;
+ if (x != NULL) DISPATCH();
break;
- case BINARY_MODULO:
+ TARGET(BINARY_MODULO)
w = POP();
v = TOP();
- if (PyString_CheckExact(v))
- x = PyString_Format(v, w);
+ 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) continue;
+ if (x != NULL) DISPATCH();
break;
- case BINARY_ADD:
+ TARGET(BINARY_ADD)
w = POP();
v = TOP();
- if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) {
- /* INLINE: int + int */
- register long a, b, i;
- a = PyInt_AS_LONG(v);
- b = PyInt_AS_LONG(w);
- /* cast to avoid undefined behaviour
- on overflow */
- i = (long)((unsigned long)a + b);
- if ((i^a) < 0 && (i^b) < 0)
- goto slow_add;
- x = PyInt_FromLong(i);
- }
- else if (PyString_CheckExact(v) &&
- PyString_CheckExact(w)) {
- x = string_concatenate(v, w, f, next_instr);
- /* string_concatenate consumed the ref to v */
+ 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 {
- slow_add:
x = PyNumber_Add(v, w);
}
Py_DECREF(v);
skip_decref_vx:
Py_DECREF(w);
SET_TOP(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case BINARY_SUBTRACT:
+ TARGET(BINARY_SUBTRACT)
w = POP();
v = TOP();
- if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) {
- /* INLINE: int - int */
- register long a, b, i;
- a = PyInt_AS_LONG(v);
- b = PyInt_AS_LONG(w);
- /* cast to avoid undefined behaviour
- on overflow */
- i = (long)((unsigned long)a - b);
- if ((i^a) < 0 && (i^~b) < 0)
- goto slow_sub;
- x = PyInt_FromLong(i);
- }
- else {
- slow_sub:
- x = PyNumber_Subtract(v, w);
- }
+ x = PyNumber_Subtract(v, w);
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case BINARY_SUBSCR:
+ TARGET(BINARY_SUBSCR)
w = POP();
v = TOP();
- if (PyList_CheckExact(v) && PyInt_CheckExact(w)) {
- /* INLINE: list[int] */
- Py_ssize_t i = PyInt_AsSsize_t(w);
- if (i < 0)
- i += PyList_GET_SIZE(v);
- if (i >= 0 && i < PyList_GET_SIZE(v)) {
- x = PyList_GET_ITEM(v, i);
- Py_INCREF(x);
- }
- else
- goto slow_get;
- }
- else
- slow_get:
- x = PyObject_GetItem(v, w);
+ x = PyObject_GetItem(v, w);
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case BINARY_LSHIFT:
+ TARGET(BINARY_LSHIFT)
w = POP();
v = TOP();
x = PyNumber_Lshift(v, w);
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case BINARY_RSHIFT:
+ TARGET(BINARY_RSHIFT)
w = POP();
v = TOP();
x = PyNumber_Rshift(v, w);
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case BINARY_AND:
+ TARGET(BINARY_AND)
w = POP();
v = TOP();
x = PyNumber_And(v, w);
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case BINARY_XOR:
+ TARGET(BINARY_XOR)
w = POP();
v = TOP();
x = PyNumber_Xor(v, w);
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case BINARY_OR:
+ TARGET(BINARY_OR)
w = POP();
v = TOP();
x = PyNumber_Or(v, w);
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case LIST_APPEND:
+ TARGET(LIST_APPEND)
w = POP();
v = PEEK(oparg);
err = PyList_Append(v, w);
Py_DECREF(w);
if (err == 0) {
PREDICT(JUMP_ABSOLUTE);
- continue;
+ DISPATCH();
}
break;
- case SET_ADD:
+ TARGET(SET_ADD)
w = POP();
v = stack_pointer[-oparg];
err = PySet_Add(v, w);
Py_DECREF(w);
if (err == 0) {
PREDICT(JUMP_ABSOLUTE);
- continue;
+ DISPATCH();
}
break;
- case INPLACE_POWER:
+ 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) continue;
+ if (x != NULL) DISPATCH();
break;
- case INPLACE_MULTIPLY:
+ TARGET(INPLACE_MULTIPLY)
w = POP();
v = TOP();
x = PyNumber_InPlaceMultiply(v, w);
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case INPLACE_DIVIDE:
- if (!_Py_QnewFlag) {
- w = POP();
- v = TOP();
- x = PyNumber_InPlaceDivide(v, w);
- Py_DECREF(v);
- Py_DECREF(w);
- SET_TOP(x);
- if (x != NULL) continue;
- break;
- }
- /* -Qnew is in effect: fall through to
- INPLACE_TRUE_DIVIDE */
- case INPLACE_TRUE_DIVIDE:
+ 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) continue;
+ if (x != NULL) DISPATCH();
break;
- case INPLACE_FLOOR_DIVIDE:
+ 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) continue;
+ if (x != NULL) DISPATCH();
break;
- case INPLACE_MODULO:
+ TARGET(INPLACE_MODULO)
w = POP();
v = TOP();
x = PyNumber_InPlaceRemainder(v, w);
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case INPLACE_ADD:
+ TARGET(INPLACE_ADD)
w = POP();
v = TOP();
- if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) {
- /* INLINE: int + int */
- register long a, b, i;
- a = PyInt_AS_LONG(v);
- b = PyInt_AS_LONG(w);
- i = a + b;
- if ((i^a) < 0 && (i^b) < 0)
- goto slow_iadd;
- x = PyInt_FromLong(i);
- }
- else if (PyString_CheckExact(v) &&
- PyString_CheckExact(w)) {
- x = string_concatenate(v, w, f, next_instr);
- /* string_concatenate consumed the ref to v */
+ 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 {
- slow_iadd:
x = PyNumber_InPlaceAdd(v, w);
}
Py_DECREF(v);
skip_decref_v:
Py_DECREF(w);
SET_TOP(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case INPLACE_SUBTRACT:
+ TARGET(INPLACE_SUBTRACT)
w = POP();
v = TOP();
- if (PyInt_CheckExact(v) && PyInt_CheckExact(w)) {
- /* INLINE: int - int */
- register long a, b, i;
- a = PyInt_AS_LONG(v);
- b = PyInt_AS_LONG(w);
- i = a - b;
- if ((i^a) < 0 && (i^~b) < 0)
- goto slow_isub;
- x = PyInt_FromLong(i);
- }
- else {
- slow_isub:
- x = PyNumber_InPlaceSubtract(v, w);
- }
+ x = PyNumber_InPlaceSubtract(v, w);
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case INPLACE_LSHIFT:
+ TARGET(INPLACE_LSHIFT)
w = POP();
v = TOP();
x = PyNumber_InPlaceLshift(v, w);
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case INPLACE_RSHIFT:
+ TARGET(INPLACE_RSHIFT)
w = POP();
v = TOP();
x = PyNumber_InPlaceRshift(v, w);
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case INPLACE_AND:
+ TARGET(INPLACE_AND)
w = POP();
v = TOP();
x = PyNumber_InPlaceAnd(v, w);
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case INPLACE_XOR:
+ TARGET(INPLACE_XOR)
w = POP();
v = TOP();
x = PyNumber_InPlaceXor(v, w);
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case INPLACE_OR:
+ TARGET(INPLACE_OR)
w = POP();
v = TOP();
x = PyNumber_InPlaceOr(v, w);
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
- if (x != NULL) continue;
- break;
-
- case SLICE+0:
- case SLICE+1:
- case SLICE+2:
- case SLICE+3:
- if ((opcode-SLICE) & 2)
- w = POP();
- else
- w = NULL;
- if ((opcode-SLICE) & 1)
- v = POP();
- else
- v = NULL;
- u = TOP();
- x = apply_slice(u, v, w);
- Py_DECREF(u);
- Py_XDECREF(v);
- Py_XDECREF(w);
- SET_TOP(x);
- if (x != NULL) continue;
- break;
-
- case STORE_SLICE+0:
- case STORE_SLICE+1:
- case STORE_SLICE+2:
- case STORE_SLICE+3:
- if ((opcode-STORE_SLICE) & 2)
- w = POP();
- else
- w = NULL;
- if ((opcode-STORE_SLICE) & 1)
- v = POP();
- else
- v = NULL;
- u = POP();
- t = POP();
- err = assign_slice(u, v, w, t); /* u[v:w] = t */
- Py_DECREF(t);
- Py_DECREF(u);
- Py_XDECREF(v);
- Py_XDECREF(w);
- if (err == 0) continue;
- break;
-
- case DELETE_SLICE+0:
- case DELETE_SLICE+1:
- case DELETE_SLICE+2:
- case DELETE_SLICE+3:
- if ((opcode-DELETE_SLICE) & 2)
- w = POP();
- else
- w = NULL;
- if ((opcode-DELETE_SLICE) & 1)
- v = POP();
- else
- v = NULL;
- u = POP();
- err = assign_slice(u, v, w, (PyObject *)NULL);
- /* del u[v:w] */
- Py_DECREF(u);
- Py_XDECREF(v);
- Py_XDECREF(w);
- if (err == 0) continue;
+ if (x != NULL) DISPATCH();
break;
- case STORE_SUBSCR:
+ TARGET(STORE_SUBSCR)
w = TOP();
v = SECOND();
u = THIRD();
@@ -1707,10 +1823,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
Py_DECREF(u);
Py_DECREF(v);
Py_DECREF(w);
- if (err == 0) continue;
+ if (err == 0) DISPATCH();
break;
- case DELETE_SUBSCR:
+ TARGET(DELETE_SUBSCR)
w = TOP();
v = SECOND();
STACKADJ(-2);
@@ -1718,10 +1834,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
err = PyObject_DelItem(v, w);
Py_DECREF(v);
Py_DECREF(w);
- if (err == 0) continue;
+ if (err == 0) DISPATCH();
break;
- case PRINT_EXPR:
+ TARGET(PRINT_EXPR)
v = POP();
w = PySys_GetObject("displayhook");
if (w == NULL) {
@@ -1745,103 +1861,18 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
Py_XDECREF(x);
break;
- case PRINT_ITEM_TO:
- w = stream = POP();
- /* fall through to PRINT_ITEM */
-
- case PRINT_ITEM:
- v = POP();
- if (stream == NULL || stream == Py_None) {
- w = PySys_GetObject("stdout");
- if (w == NULL) {
- PyErr_SetString(PyExc_RuntimeError,
- "lost sys.stdout");
- err = -1;
- }
- }
- /* PyFile_SoftSpace() can exececute arbitrary code
- if sys.stdout is an instance with a __getattr__.
- If __getattr__ raises an exception, w will
- be freed, so we need to prevent that temporarily. */
- Py_XINCREF(w);
- if (w != NULL && PyFile_SoftSpace(w, 0))
- err = PyFile_WriteString(" ", w);
- if (err == 0)
- err = PyFile_WriteObject(v, w, Py_PRINT_RAW);
- if (err == 0) {
- /* XXX move into writeobject() ? */
- if (PyString_Check(v)) {
- char *s = PyString_AS_STRING(v);
- Py_ssize_t len = PyString_GET_SIZE(v);
- if (len == 0 ||
- !isspace(Py_CHARMASK(s[len-1])) ||
- s[len-1] == ' ')
- PyFile_SoftSpace(w, 1);
- }
-#ifdef Py_USING_UNICODE
- else if (PyUnicode_Check(v)) {
- Py_UNICODE *s = PyUnicode_AS_UNICODE(v);
- Py_ssize_t len = PyUnicode_GET_SIZE(v);
- if (len == 0 ||
- !Py_UNICODE_ISSPACE(s[len-1]) ||
- s[len-1] == ' ')
- PyFile_SoftSpace(w, 1);
- }
-#endif
- else
- PyFile_SoftSpace(w, 1);
- }
- Py_XDECREF(w);
- Py_DECREF(v);
- Py_XDECREF(stream);
- stream = NULL;
- if (err == 0)
- continue;
- break;
-
- case PRINT_NEWLINE_TO:
- w = stream = POP();
- /* fall through to PRINT_NEWLINE */
-
- case PRINT_NEWLINE:
- if (stream == NULL || stream == Py_None) {
- w = PySys_GetObject("stdout");
- if (w == NULL) {
- PyErr_SetString(PyExc_RuntimeError,
- "lost sys.stdout");
- why = WHY_EXCEPTION;
- }
- }
- if (w != NULL) {
- /* w.write() may replace sys.stdout, so we
- * have to keep our reference to it */
- Py_INCREF(w);
- err = PyFile_WriteString("\n", w);
- if (err == 0)
- PyFile_SoftSpace(w, 0);
- Py_DECREF(w);
- }
- Py_XDECREF(stream);
- stream = NULL;
- break;
-
-
#ifdef CASE_TOO_BIG
default: switch (opcode) {
#endif
- case RAISE_VARARGS:
- u = v = w = NULL;
+ TARGET(RAISE_VARARGS)
+ v = w = NULL;
switch (oparg) {
- case 3:
- u = POP(); /* traceback */
- /* Fallthrough */
case 2:
- v = POP(); /* value */
- /* Fallthrough */
+ v = POP(); /* cause */
case 1:
w = POP(); /* exc */
case 0: /* Fallthrough */
- why = do_raise(w, v, u);
+ why = do_raise(w, v);
break;
default:
PyErr_SetString(PyExc_SystemError,
@@ -1851,61 +1882,65 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
}
break;
- case LOAD_LOCALS:
- if ((x = f->f_locals) != NULL) {
- Py_INCREF(x);
- PUSH(x);
- continue;
- }
- PyErr_SetString(PyExc_SystemError, "no locals");
- break;
+ TARGET(STORE_LOCALS)
+ x = POP();
+ v = f->f_locals;
+ Py_XDECREF(v);
+ f->f_locals = x;
+ DISPATCH();
- case RETURN_VALUE:
+ TARGET(RETURN_VALUE)
retval = POP();
why = WHY_RETURN;
goto fast_block_end;
- case YIELD_VALUE:
+ TARGET(YIELD_VALUE)
retval = POP();
f->f_stacktop = stack_pointer;
why = WHY_YIELD;
goto fast_yield;
- case EXEC_STMT:
- w = TOP();
- v = SECOND();
- u = THIRD();
- STACKADJ(-3);
- READ_TIMESTAMP(intr0);
- err = exec_statement(f, u, v, w);
- READ_TIMESTAMP(intr1);
- Py_DECREF(u);
- Py_DECREF(v);
- Py_DECREF(w);
- break;
-
- case POP_BLOCK:
+ TARGET(POP_EXCEPT)
{
PyTryBlock *b = PyFrame_BlockPop(f);
- while (STACK_LEVEL() > b->b_level) {
- v = POP();
- Py_DECREF(v);
+ 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);
}
- continue;
+ DISPATCH();
+
+ TARGET(POP_BLOCK)
+ {
+ PyTryBlock *b = PyFrame_BlockPop(f);
+ UNWIND_BLOCK(b);
+ }
+ DISPATCH();
PREDICTED(END_FINALLY);
- case END_FINALLY:
+ TARGET(END_FINALLY)
v = POP();
- if (PyInt_Check(v)) {
- why = (enum why_code) PyInt_AS_LONG(v);
+ 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) ||
- PyString_Check(v)) {
+ else if (PyExceptionClass_Check(v)) {
w = POP();
u = POP();
PyErr_Restore(v, w, u);
@@ -1920,19 +1955,19 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
Py_DECREF(v);
break;
- case BUILD_CLASS:
- u = TOP();
- v = SECOND();
- w = THIRD();
- STACKADJ(-2);
- x = build_class(u, v, w);
- SET_TOP(x);
- Py_DECREF(u);
- Py_DECREF(v);
- Py_DECREF(w);
+ 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;
- case STORE_NAME:
+ TARGET(STORE_NAME)
w = GETITEM(names, oparg);
v = POP();
if ((x = f->f_locals) != NULL) {
@@ -1941,15 +1976,14 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
else
err = PyObject_SetItem(x, w, v);
Py_DECREF(v);
- if (err == 0) continue;
+ if (err == 0) DISPATCH();
break;
}
PyErr_Format(PyExc_SystemError,
- "no locals found when storing %s",
- PyObject_REPR(w));
+ "no locals found when storing %R", w);
break;
- case DELETE_NAME:
+ TARGET(DELETE_NAME)
w = GETITEM(names, oparg);
if ((x = f->f_locals) != NULL) {
if ((err = PyObject_DelItem(x, w)) != 0)
@@ -1959,12 +1993,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
break;
}
PyErr_Format(PyExc_SystemError,
- "no locals when deleting %s",
- PyObject_REPR(w));
+ "no locals when deleting %R", w);
break;
PREDICTED_WITH_ARG(UNPACK_SEQUENCE);
- case UNPACK_SEQUENCE:
+ TARGET(UNPACK_SEQUENCE)
v = POP();
if (PyTuple_CheckExact(v) &&
PyTuple_GET_SIZE(v) == oparg) {
@@ -1976,7 +2009,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
PUSH(w);
}
Py_DECREF(v);
- continue;
+ DISPATCH();
} else if (PyList_CheckExact(v) &&
PyList_GET_SIZE(v) == oparg) {
PyObject **items = \
@@ -1986,7 +2019,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
Py_INCREF(w);
PUSH(w);
}
- } else if (unpack_iterable(v, oparg,
+ } else if (unpack_iterable(v, oparg, -1,
stack_pointer + oparg)) {
STACKADJ(oparg);
} else {
@@ -1996,7 +2029,22 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
Py_DECREF(v);
break;
- case STORE_ATTR:
+ 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();
@@ -2004,10 +2052,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
err = PyObject_SetAttr(v, w, u); /* v.w = u */
Py_DECREF(v);
Py_DECREF(u);
- if (err == 0) continue;
+ if (err == 0) DISPATCH();
break;
- case DELETE_ATTR:
+ TARGET(DELETE_ATTR)
w = GETITEM(names, oparg);
v = POP();
err = PyObject_SetAttr(v, w, (PyObject *)NULL);
@@ -2015,27 +2063,26 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
Py_DECREF(v);
break;
- case STORE_GLOBAL:
+ TARGET(STORE_GLOBAL)
w = GETITEM(names, oparg);
v = POP();
err = PyDict_SetItem(f->f_globals, w, v);
Py_DECREF(v);
- if (err == 0) continue;
+ if (err == 0) DISPATCH();
break;
- case DELETE_GLOBAL:
+ 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;
- case LOAD_NAME:
+ TARGET(LOAD_NAME)
w = GETITEM(names, oparg);
if ((v = f->f_locals) == NULL) {
PyErr_Format(PyExc_SystemError,
- "no locals when loading %s",
- PyObject_REPR(w));
+ "no locals when loading %R", w);
why = WHY_EXCEPTION;
break;
}
@@ -2066,15 +2113,15 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
Py_INCREF(x);
}
PUSH(x);
- continue;
+ DISPATCH();
- case LOAD_GLOBAL:
+ TARGET(LOAD_GLOBAL)
w = GETITEM(names, oparg);
- if (PyString_CheckExact(w)) {
+ if (PyUnicode_CheckExact(w)) {
/* Inline the PyDict_GetItem() calls.
WARNING: this is an extreme speed hack.
Do not try this at home. */
- long hash = ((PyStringObject *)w)->ob_shash;
+ Py_hash_t hash = ((PyUnicodeObject *)w)->hash;
if (hash != -1) {
PyDictObject *d;
PyDictEntry *e;
@@ -2088,7 +2135,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
if (x != NULL) {
Py_INCREF(x);
PUSH(x);
- continue;
+ DISPATCH();
}
d = (PyDictObject *)(f->f_builtins);
e = d->ma_lookup(d, w, hash);
@@ -2100,7 +2147,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
if (x != NULL) {
Py_INCREF(x);
PUSH(x);
- continue;
+ DISPATCH();
}
goto load_global_error;
}
@@ -2119,13 +2166,13 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
}
Py_INCREF(x);
PUSH(x);
- continue;
+ DISPATCH();
- case DELETE_FAST:
+ TARGET(DELETE_FAST)
x = GETLOCAL(oparg);
if (x != NULL) {
SETLOCAL(oparg, NULL);
- continue;
+ DISPATCH();
}
format_exc_check_arg(
PyExc_UnboundLocalError,
@@ -2134,47 +2181,42 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
);
break;
- case LOAD_CLOSURE:
+ 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) continue;
+ if (x != NULL) DISPATCH();
break;
- case LOAD_DEREF:
+ TARGET(LOAD_DEREF)
x = freevars[oparg];
w = PyCell_Get(x);
if (w != NULL) {
PUSH(w);
- continue;
+ DISPATCH();
}
err = -1;
- /* Don't stomp existing exception */
- if (PyErr_Occurred())
- break;
- if (oparg < PyTuple_GET_SIZE(co->co_cellvars)) {
- v = PyTuple_GET_ITEM(co->co_cellvars,
- oparg);
- format_exc_check_arg(
- PyExc_UnboundLocalError,
- UNBOUNDLOCAL_ERROR_MSG,
- v);
- } else {
- v = PyTuple_GET_ITEM(co->co_freevars, oparg -
- PyTuple_GET_SIZE(co->co_cellvars));
- format_exc_check_arg(PyExc_NameError,
- UNBOUNDFREE_ERROR_MSG, v);
- }
+ format_exc_unbound(co, oparg);
break;
- case STORE_DEREF:
+ TARGET(STORE_DEREF)
w = POP();
x = freevars[oparg];
PyCell_Set(x, w);
Py_DECREF(w);
- continue;
+ DISPATCH();
- case BUILD_TUPLE:
+ TARGET(BUILD_TUPLE)
x = PyTuple_New(oparg);
if (x != NULL) {
for (; --oparg >= 0;) {
@@ -2182,11 +2224,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
PyTuple_SET_ITEM(x, oparg, w);
}
PUSH(x);
- continue;
+ DISPATCH();
}
break;
- case BUILD_LIST:
+ TARGET(BUILD_LIST)
x = PyList_New(oparg);
if (x != NULL) {
for (; --oparg >= 0;) {
@@ -2194,11 +2236,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
PyList_SET_ITEM(x, oparg, w);
}
PUSH(x);
- continue;
+ DISPATCH();
}
break;
- case BUILD_SET:
+ TARGET(BUILD_SET)
x = PySet_New(NULL);
if (x != NULL) {
for (; --oparg >= 0;) {
@@ -2212,18 +2254,17 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
break;
}
PUSH(x);
- continue;
+ DISPATCH();
}
break;
-
- case BUILD_MAP:
+ TARGET(BUILD_MAP)
x = _PyDict_NewPresized((Py_ssize_t)oparg);
PUSH(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case STORE_MAP:
+ TARGET(STORE_MAP)
w = TOP(); /* key */
u = SECOND(); /* value */
v = THIRD(); /* dict */
@@ -2232,10 +2273,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
err = PyDict_SetItem(v, w, u); /* v[w] = u */
Py_DECREF(u);
Py_DECREF(w);
- if (err == 0) continue;
+ if (err == 0) DISPATCH();
break;
- case MAP_ADD:
+ TARGET(MAP_ADD)
w = TOP(); /* key */
u = SECOND(); /* value */
STACKADJ(-2);
@@ -2246,55 +2287,32 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
Py_DECREF(w);
if (err == 0) {
PREDICT(JUMP_ABSOLUTE);
- continue;
+ DISPATCH();
}
break;
- case LOAD_ATTR:
+ TARGET(LOAD_ATTR)
w = GETITEM(names, oparg);
v = TOP();
x = PyObject_GetAttr(v, w);
Py_DECREF(v);
SET_TOP(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case COMPARE_OP:
+ TARGET(COMPARE_OP)
w = POP();
v = TOP();
- if (PyInt_CheckExact(w) && PyInt_CheckExact(v)) {
- /* INLINE: cmp(int, int) */
- register long a, b;
- register int res;
- a = PyInt_AS_LONG(v);
- b = PyInt_AS_LONG(w);
- switch (oparg) {
- case PyCmp_LT: res = a < b; break;
- case PyCmp_LE: res = a <= b; break;
- case PyCmp_EQ: res = a == b; break;
- case PyCmp_NE: res = a != b; break;
- case PyCmp_GT: res = a > b; break;
- case PyCmp_GE: res = a >= b; break;
- case PyCmp_IS: res = v == w; break;
- case PyCmp_IS_NOT: res = v != w; break;
- default: goto slow_compare;
- }
- x = res ? Py_True : Py_False;
- Py_INCREF(x);
- }
- else {
- slow_compare:
- x = cmp_outcome(oparg, v, w);
- }
+ 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);
- continue;
+ DISPATCH();
- case IMPORT_NAME:
+ TARGET(IMPORT_NAME)
w = GETITEM(names, oparg);
x = PyDict_GetItemString(f->f_builtins, "__import__");
if (x == NULL) {
@@ -2305,7 +2323,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
Py_INCREF(x);
v = POP();
u = TOP();
- if (PyInt_AsLong(u) != -1 || PyErr_Occurred())
+ if (PyLong_AsLong(u) != -1 || PyErr_Occurred())
w = PyTuple_Pack(5,
w,
f->f_globals,
@@ -2335,10 +2353,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
READ_TIMESTAMP(intr1);
Py_DECREF(w);
SET_TOP(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case IMPORT_STAR:
+ TARGET(IMPORT_STAR)
v = POP();
PyFrame_FastToLocals(f);
if ((x = f->f_locals) == NULL) {
@@ -2351,34 +2369,34 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
READ_TIMESTAMP(intr1);
PyFrame_LocalsToFast(f, 0);
Py_DECREF(v);
- if (err == 0) continue;
+ if (err == 0) DISPATCH();
break;
- case IMPORT_FROM:
+ 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) continue;
+ if (x != NULL) DISPATCH();
break;
- case JUMP_FORWARD:
+ TARGET(JUMP_FORWARD)
JUMPBY(oparg);
- goto fast_next_opcode;
+ FAST_DISPATCH();
PREDICTED_WITH_ARG(POP_JUMP_IF_FALSE);
- case POP_JUMP_IF_FALSE:
+ TARGET(POP_JUMP_IF_FALSE)
w = POP();
if (w == Py_True) {
Py_DECREF(w);
- goto fast_next_opcode;
+ FAST_DISPATCH();
}
if (w == Py_False) {
Py_DECREF(w);
JUMPTO(oparg);
- goto fast_next_opcode;
+ FAST_DISPATCH();
}
err = PyObject_IsTrue(w);
Py_DECREF(w);
@@ -2388,19 +2406,19 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
JUMPTO(oparg);
else
break;
- continue;
+ DISPATCH();
PREDICTED_WITH_ARG(POP_JUMP_IF_TRUE);
- case POP_JUMP_IF_TRUE:
+ TARGET(POP_JUMP_IF_TRUE)
w = POP();
if (w == Py_False) {
Py_DECREF(w);
- goto fast_next_opcode;
+ FAST_DISPATCH();
}
if (w == Py_True) {
Py_DECREF(w);
JUMPTO(oparg);
- goto fast_next_opcode;
+ FAST_DISPATCH();
}
err = PyObject_IsTrue(w);
Py_DECREF(w);
@@ -2412,18 +2430,18 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
;
else
break;
- continue;
+ DISPATCH();
- case JUMP_IF_FALSE_OR_POP:
+ TARGET(JUMP_IF_FALSE_OR_POP)
w = TOP();
if (w == Py_True) {
STACKADJ(-1);
Py_DECREF(w);
- goto fast_next_opcode;
+ FAST_DISPATCH();
}
if (w == Py_False) {
JUMPTO(oparg);
- goto fast_next_opcode;
+ FAST_DISPATCH();
}
err = PyObject_IsTrue(w);
if (err > 0) {
@@ -2435,18 +2453,18 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
JUMPTO(oparg);
else
break;
- continue;
+ DISPATCH();
- case JUMP_IF_TRUE_OR_POP:
+ TARGET(JUMP_IF_TRUE_OR_POP)
w = TOP();
if (w == Py_False) {
STACKADJ(-1);
Py_DECREF(w);
- goto fast_next_opcode;
+ FAST_DISPATCH();
}
if (w == Py_True) {
JUMPTO(oparg);
- goto fast_next_opcode;
+ FAST_DISPATCH();
}
err = PyObject_IsTrue(w);
if (err > 0) {
@@ -2459,10 +2477,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
}
else
break;
- continue;
+ DISPATCH();
PREDICTED_WITH_ARG(JUMP_ABSOLUTE);
- case JUMP_ABSOLUTE:
+ TARGET(JUMP_ABSOLUTE)
JUMPTO(oparg);
#if FAST_LOOPS
/* Enabling this path speeds-up all while and for-loops by bypassing
@@ -2470,14 +2488,14 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
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 goto fast_next_opcode).
+ that contain only instructions ending with FAST_DISPATCH).
*/
- goto fast_next_opcode;
+ FAST_DISPATCH();
#else
- continue;
+ DISPATCH();
#endif
- case GET_ITER:
+ TARGET(GET_ITER)
/* before: [obj]; after [getiter(obj)] */
v = TOP();
x = PyObject_GetIter(v);
@@ -2485,13 +2503,13 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
if (x != NULL) {
SET_TOP(x);
PREDICT(FOR_ITER);
- continue;
+ DISPATCH();
}
STACKADJ(-1);
break;
PREDICTED_WITH_ARG(FOR_ITER);
- case FOR_ITER:
+ TARGET(FOR_ITER)
/* before: [iter]; after: [iter, iter()] *or* [] */
v = TOP();
x = (*v->ob_type->tp_iternext)(v);
@@ -2499,7 +2517,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
PUSH(x);
PREDICT(STORE_FAST);
PREDICT(UNPACK_SEQUENCE);
- continue;
+ DISPATCH();
}
if (PyErr_Occurred()) {
if (!PyErr_ExceptionMatches(
@@ -2511,14 +2529,14 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
x = v = POP();
Py_DECREF(v);
JUMPBY(oparg);
- continue;
+ DISPATCH();
- case BREAK_LOOP:
+ TARGET(BREAK_LOOP)
why = WHY_BREAK;
goto fast_block_end;
- case CONTINUE_LOOP:
- retval = PyInt_FromLong(oparg);
+ TARGET(CONTINUE_LOOP)
+ retval = PyLong_FromLong(oparg);
if (!retval) {
x = NULL;
break;
@@ -2526,9 +2544,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
why = WHY_CONTINUE;
goto fast_block_end;
- case SETUP_LOOP:
- case SETUP_EXCEPT:
- case SETUP_FINALLY:
+ 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.
@@ -2536,9 +2555,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
PyFrame_BlockSetup(f, opcode, INSTR_OFFSET() + oparg,
STACK_LEVEL());
- continue;
+ DISPATCH();
- case SETUP_WITH:
+ TARGET(SETUP_WITH)
{
static PyObject *exit, *enter;
w = TOP();
@@ -2556,18 +2575,16 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
Py_DECREF(u);
if (!x)
break;
- /* Setup a finally block (SETUP_WITH as a block is
- equivalent to SETUP_FINALLY except it normalizes
- the exception) before pushing the result of
- __enter__ on the stack. */
- PyFrame_BlockSetup(f, SETUP_WITH, INSTR_OFFSET() + oparg,
+ /* 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);
- continue;
+ DISPATCH();
}
- case WITH_CLEANUP:
+ TARGET(WITH_CLEANUP)
{
/* At the top of the stack are 1-3 values indicating
how/why we entered the finally clause:
@@ -2575,32 +2592,36 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
- (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 all cases, we remove EXIT from the stack, leaving
- the rest in the same order.
+ 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
- "zap" this information, to prevent END_FINALLY from
- re-raising the exception. (But non-local gotos
- should still be resumed.)
+ 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 = POP();
+ u = TOP();
if (u == Py_None) {
+ (void)POP();
exit_func = TOP();
SET_TOP(u);
v = w = Py_None;
}
- else if (PyInt_Check(u)) {
- switch(PyInt_AS_LONG(u)) {
+ else if (PyLong_Check(u)) {
+ (void)POP();
+ switch(PyLong_AsLong(u)) {
case WHY_RETURN:
case WHY_CONTINUE:
/* Retval in TOP. */
@@ -2616,12 +2637,25 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
u = v = w = Py_None;
}
else {
- v = TOP();
- w = SECOND();
- exit_func = THIRD();
- SET_TOP(u);
- SET_SECOND(v);
- SET_THIRD(w);
+ 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,
@@ -2640,22 +2674,14 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
break; /* Go to error exit */
else if (err > 0) {
err = 0;
- /* There was an exception and a true return */
- STACKADJ(-2);
- Py_INCREF(Py_None);
- SET_TOP(Py_None);
- Py_DECREF(u);
- Py_DECREF(v);
- Py_DECREF(w);
- } else {
- /* The stack was rearranged to remove EXIT
- above. Let END_FINALLY do its thing */
+ /* There was an exception and a True return */
+ PUSH(PyLong_FromLong((long) WHY_SILENCED));
}
PREDICT(END_FINALLY);
break;
}
- case CALL_FUNCTION:
+ TARGET(CALL_FUNCTION)
{
PyObject **sp;
PCALL(PCALL_ALL);
@@ -2668,13 +2694,14 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
stack_pointer = sp;
PUSH(x);
if (x != NULL)
- continue;
+ DISPATCH();
break;
}
- case CALL_FUNCTION_VAR:
- case CALL_FUNCTION_KW:
- case CALL_FUNCTION_VAR_KW:
+ 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;
@@ -2698,6 +2725,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
Py_DECREF(*pfunc);
*pfunc = self;
na++;
+ n++;
} else
Py_INCREF(func);
sp = stack_pointer;
@@ -2713,55 +2741,71 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
}
PUSH(x);
if (x != NULL)
- continue;
+ DISPATCH();
break;
}
- case MAKE_FUNCTION:
+ 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;
+
v = POP(); /* code object */
x = PyFunction_New(v, f->f_globals);
Py_DECREF(v);
- /* XXX Maybe this should be a separate opcode? */
- if (x != NULL && oparg > 0) {
- v = PyTuple_New(oparg);
+
+ 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;
}
- while (--oparg >= 0) {
+ 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();
- PyTuple_SET_ITEM(v, oparg, w);
+ /* XXX(nnorwitz): check for errors */
+ PyDict_SetItem(v, t, w);
+ Py_DECREF(w);
}
- err = PyFunction_SetDefaults(x, v);
- Py_DECREF(v);
- }
- PUSH(x);
- break;
- case MAKE_CLOSURE:
- {
- v = POP(); /* code object */
- x = PyFunction_New(v, f->f_globals);
- Py_DECREF(v);
- if (x != NULL) {
- v = POP();
- if (PyFunction_SetClosure(x, v) != 0) {
- /* Can't happen unless bytecode is corrupt. */
+ if (PyFunction_SetAnnotations(x, v) != 0) {
+ /* Can't happen unless
+ PyFunction_SetAnnotations changes. */
why = WHY_EXCEPTION;
}
Py_DECREF(v);
+ Py_DECREF(u);
}
- if (x != NULL && oparg > 0) {
- v = PyTuple_New(oparg);
+
+ /* 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 (--oparg >= 0) {
+ while (--posdefaults >= 0) {
w = POP();
- PyTuple_SET_ITEM(v, oparg, w);
+ PyTuple_SET_ITEM(v, posdefaults, w);
}
if (PyFunction_SetDefaults(x, v) != 0) {
/* Can't happen unless
@@ -2770,11 +2814,33 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
}
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;
}
- case BUILD_SLICE:
+ TARGET(BUILD_SLICE)
if (oparg == 3)
w = POP();
else
@@ -2786,14 +2852,17 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
Py_DECREF(v);
Py_XDECREF(w);
SET_TOP(x);
- if (x != NULL) continue;
+ if (x != NULL) DISPATCH();
break;
- case EXTENDED_ARG:
+ 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",
@@ -2881,60 +2950,65 @@ fast_block_end:
assert(why != WHY_YIELD);
if (b->b_type == SETUP_LOOP && why == WHY_CONTINUE) {
why = WHY_NOT;
- JUMPTO(PyInt_AS_LONG(retval));
+ JUMPTO(PyLong_AS_LONG(retval));
Py_DECREF(retval);
break;
}
-
/* Now we have to pop the block. */
f->f_iblock--;
- while (STACK_LEVEL() > b->b_level) {
- v = POP();
- Py_XDECREF(v);
+ 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 (b->b_type == SETUP_FINALLY ||
- (b->b_type == SETUP_EXCEPT &&
- why == WHY_EXCEPTION) ||
- b->b_type == SETUP_WITH) {
- if (why == WHY_EXCEPTION) {
- PyObject *exc, *val, *tb;
- PyErr_Fetch(&exc, &val, &tb);
- if (val == NULL) {
- val = Py_None;
- Py_INCREF(val);
- }
- /* Make the raw exception data
- available to the handler,
- so a program can emulate the
- Python main loop. Don't do
- this for 'finally'. */
- if (b->b_type == SETUP_EXCEPT ||
- b->b_type == SETUP_WITH) {
- PyErr_NormalizeException(
- &exc, &val, &tb);
- set_exc_info(tstate,
- exc, val, tb);
- }
- if (tb == NULL) {
- Py_INCREF(Py_None);
- PUSH(Py_None);
- } else
- PUSH(tb);
- PUSH(val);
- PUSH(exc);
+ 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 {
- if (why & (WHY_RETURN | WHY_CONTINUE))
- PUSH(retval);
- v = PyInt_FromLong((long)why);
- PUSH(v);
+ 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;
@@ -2960,6 +3034,26 @@ fast_block_end:
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()
+ else
+ SWAP_EXC_STATE()
+ }
+
if (tstate->use_tracing) {
if (tstate->c_tracefunc) {
if (why == WHY_RETURN || why == WHY_YIELD) {
@@ -2992,13 +3086,6 @@ fast_yield:
}
}
- if (tstate->frame->f_exc_type != NULL)
- reset_exc_info(tstate);
- else {
- assert(tstate->frame->f_exc_value == NULL);
- assert(tstate->frame->f_exc_traceback == NULL);
- }
-
/* pop frame */
exit_eval_frame:
Py_LeaveRecursiveCall();
@@ -3012,15 +3099,17 @@ exit_eval_frame:
the test in the if statements in Misc/gdbinit (pystack and pystackv). */
PyObject *
-PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
+PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals,
PyObject **args, int argcount, PyObject **kws, int kwcount,
- PyObject **defs, int defcount, PyObject *closure)
+ 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;
if (globals == NULL) {
PyErr_SetString(PyExc_SystemError,
@@ -3037,8 +3126,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
fastlocals = f->f_localsplus;
freevars = f->f_localsplus + co->co_nlocals;
- if (co->co_argcount > 0 ||
- co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) {
+ if (total_args || co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) {
int i;
int n = argcount;
PyObject *kwdict = NULL;
@@ -3046,7 +3134,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
kwdict = PyDict_New();
if (kwdict == NULL)
goto fail;
- i = co->co_argcount;
+ i = total_args;
if (co->co_flags & CO_VARARGS)
i++;
SETLOCAL(i, kwdict);
@@ -3054,9 +3142,9 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
if (argcount > co->co_argcount) {
if (!(co->co_flags & CO_VARARGS)) {
PyErr_Format(PyExc_TypeError,
- "%.200s() takes %s %d "
- "argument%s (%d given)",
- PyString_AsString(co->co_name),
+ "%U() takes %s %d "
+ "positional argument%s (%d given)",
+ co->co_name,
defcount ? "at most" : "exactly",
co->co_argcount,
co->co_argcount == 1 ? "" : "s",
@@ -3074,7 +3162,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
u = PyTuple_New(argcount - n);
if (u == NULL)
goto fail;
- SETLOCAL(co->co_argcount, u);
+ SETLOCAL(total_args, u);
for (i = n; i < argcount; i++) {
x = args[i];
Py_INCREF(x);
@@ -3086,26 +3174,22 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
PyObject *keyword = kws[2*i];
PyObject *value = kws[2*i + 1];
int j;
- if (keyword == NULL || !(PyString_Check(keyword)
-#ifdef Py_USING_UNICODE
- || PyUnicode_Check(keyword)
-#endif
- )) {
+ if (keyword == NULL || !PyUnicode_Check(keyword)) {
PyErr_Format(PyExc_TypeError,
- "%.200s() keywords must be strings",
- PyString_AsString(co->co_name));
+ "%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 < co->co_argcount; j++) {
+ 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 < co->co_argcount; j++) {
+ for (j = 0; j < total_args; j++) {
PyObject *nm = co_varnames[j];
int cmp = PyObject_RichCompareBool(
keyword, nm, Py_EQ);
@@ -3114,37 +3198,49 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
else if (cmp < 0)
goto fail;
}
- if (kwdict == NULL) {
- PyObject *kwd_str = kwd_as_string(keyword);
- if (kwd_str) {
- PyErr_Format(PyExc_TypeError,
- "%.200s() got an unexpected "
- "keyword argument '%.400s'",
- PyString_AsString(co->co_name),
- PyString_AsString(kwd_str));
- Py_DECREF(kwd_str);
- }
+ 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) {
- PyObject *kwd_str = kwd_as_string(keyword);
- if (kwd_str) {
- PyErr_Format(PyExc_TypeError,
- "%.200s() got multiple "
- "values for keyword "
- "argument '%.400s'",
- PyString_AsString(co->co_name),
- PyString_AsString(kwd_str));
- Py_DECREF(kwd_str);
- }
+ PyErr_Format(PyExc_TypeError,
+ "%U() got multiple "
+ "values for keyword "
+ "argument '%S'",
+ co->co_name,
+ keyword);
goto fail;
}
Py_INCREF(value);
SETLOCAL(j, value);
}
+ if (co->co_kwonlyargcount > 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;
+ }
+ }
+ PyErr_Format(PyExc_TypeError,
+ "%U() needs keyword-only argument %S",
+ co->co_name, name);
+ goto fail;
+ }
+ }
if (argcount < co->co_argcount) {
int m = co->co_argcount - defcount;
for (i = argcount; i < m; i++) {
@@ -3154,13 +3250,14 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
if (GETLOCAL(j))
given++;
PyErr_Format(PyExc_TypeError,
- "%.200s() takes %s %d "
- "argument%s (%d given)",
- PyString_AsString(co->co_name),
+ "%U() takes %s %d "
+ "argument%s "
+ "(%d given)",
+ co->co_name,
((co->co_flags & CO_VARARGS) ||
defcount) ? "at least"
: "exactly",
- m, m == 1 ? "" : "s", given);
+ m, m == 1 ? "" : "s", given);
goto fail;
}
}
@@ -3179,8 +3276,8 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
}
else if (argcount > 0 || kwcount > 0) {
PyErr_Format(PyExc_TypeError,
- "%.200s() takes no arguments (%d given)",
- PyString_AsString(co->co_name),
+ "%U() takes no arguments (%d given)",
+ co->co_name,
argcount + kwcount);
goto fail;
}
@@ -3188,10 +3285,10 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
vars into frame. This isn't too efficient right now. */
if (PyTuple_GET_SIZE(co->co_cellvars)) {
int i, j, nargs, found;
- char *cellname, *argname;
+ Py_UNICODE *cellname, *argname;
PyObject *c;
- nargs = co->co_argcount;
+ nargs = total_args;
if (co->co_flags & CO_VARARGS)
nargs++;
if (co->co_flags & CO_VARKEYWORDS)
@@ -3205,13 +3302,13 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
list so that we can march over it more efficiently?
*/
for (i = 0; i < PyTuple_GET_SIZE(co->co_cellvars); ++i) {
- cellname = PyString_AS_STRING(
+ cellname = PyUnicode_AS_UNICODE(
PyTuple_GET_ITEM(co->co_cellvars, i));
found = 0;
for (j = 0; j < nargs; j++) {
- argname = PyString_AS_STRING(
+ argname = PyUnicode_AS_UNICODE(
PyTuple_GET_ITEM(co->co_varnames, j));
- if (strcmp(cellname, argname) == 0) {
+ if (Py_UNICODE_strcmp(cellname, argname) == 0) {
c = PyCell_New(GETLOCAL(j));
if (c == NULL)
goto fail;
@@ -3271,12 +3368,6 @@ static PyObject *
special_lookup(PyObject *o, char *meth, PyObject **cache)
{
PyObject *res;
- if (PyInstance_Check(o)) {
- if (!*cache)
- return PyObject_GetAttrString(o, meth);
- else
- return PyObject_GetAttr(o, *cache);
- }
res = _PyObject_LookupSpecial(o, meth, cache);
if (res == NULL && !PyErr_Occurred()) {
PyErr_SetObject(PyExc_AttributeError, *cache);
@@ -3286,300 +3377,112 @@ special_lookup(PyObject *o, char *meth, PyObject **cache)
}
-static PyObject *
-kwd_as_string(PyObject *kwd) {
-#ifdef Py_USING_UNICODE
- if (PyString_Check(kwd)) {
-#else
- assert(PyString_Check(kwd));
-#endif
- Py_INCREF(kwd);
- return kwd;
-#ifdef Py_USING_UNICODE
- }
- return _PyUnicode_AsDefaultEncodedString(kwd, "replace");
-#endif
-}
-
-
-/* Implementation notes for set_exc_info() and reset_exc_info():
-
-- Below, 'exc_ZZZ' stands for 'exc_type', 'exc_value' and
- 'exc_traceback'. These always travel together.
-
-- tstate->curexc_ZZZ is the "hot" exception that is set by
- PyErr_SetString(), cleared by PyErr_Clear(), and so on.
-
-- Once an exception is caught by an except clause, it is transferred
- from tstate->curexc_ZZZ to tstate->exc_ZZZ, from which sys.exc_info()
- can pick it up. This is the primary task of set_exc_info().
- XXX That can't be right: set_exc_info() doesn't look at tstate->curexc_ZZZ.
-
-- Now let me explain the complicated dance with frame->f_exc_ZZZ.
-
- Long ago, when none of this existed, there were just a few globals:
- one set corresponding to the "hot" exception, and one set
- corresponding to sys.exc_ZZZ. (Actually, the latter weren't C
- globals; they were simply stored as sys.exc_ZZZ. For backwards
- compatibility, they still are!) The problem was that in code like
- this:
-
- try:
- "something that may fail"
- except "some exception":
- "do something else first"
- "print the exception from sys.exc_ZZZ."
-
- if "do something else first" invoked something that raised and caught
- an exception, sys.exc_ZZZ were overwritten. That was a frequent
- cause of subtle bugs. I fixed this by changing the semantics as
- follows:
-
- - Within one frame, sys.exc_ZZZ will hold the last exception caught
- *in that frame*.
-
- - But initially, and as long as no exception is caught in a given
- frame, sys.exc_ZZZ will hold the last exception caught in the
- previous frame (or the frame before that, etc.).
-
- The first bullet fixed the bug in the above example. The second
- bullet was for backwards compatibility: it was (and is) common to
- have a function that is called when an exception is caught, and to
- have that function access the caught exception via sys.exc_ZZZ.
- (Example: traceback.print_exc()).
-
- At the same time I fixed the problem that sys.exc_ZZZ weren't
- thread-safe, by introducing sys.exc_info() which gets it from tstate;
- but that's really a separate improvement.
-
- The reset_exc_info() function in ceval.c restores the tstate->exc_ZZZ
- variables to what they were before the current frame was called. The
- set_exc_info() function saves them on the frame so that
- reset_exc_info() can restore them. The invariant is that
- frame->f_exc_ZZZ is NULL iff the current frame never caught an
- exception (where "catching" an exception applies only to successful
- except clauses); and if the current frame ever caught an exception,
- frame->f_exc_ZZZ is the exception that was stored in tstate->exc_ZZZ
- at the start of the current frame.
-
-*/
-
-static void
-set_exc_info(PyThreadState *tstate,
- PyObject *type, PyObject *value, PyObject *tb)
-{
- PyFrameObject *frame = tstate->frame;
- PyObject *tmp_type, *tmp_value, *tmp_tb;
-
- assert(type != NULL);
- assert(frame != NULL);
- if (frame->f_exc_type == NULL) {
- assert(frame->f_exc_value == NULL);
- assert(frame->f_exc_traceback == NULL);
- /* This frame didn't catch an exception before. */
- /* Save previous exception of this thread in this frame. */
- if (tstate->exc_type == NULL) {
- /* XXX Why is this set to Py_None? */
- Py_INCREF(Py_None);
- tstate->exc_type = Py_None;
- }
- Py_INCREF(tstate->exc_type);
- Py_XINCREF(tstate->exc_value);
- Py_XINCREF(tstate->exc_traceback);
- frame->f_exc_type = tstate->exc_type;
- frame->f_exc_value = tstate->exc_value;
- frame->f_exc_traceback = tstate->exc_traceback;
- }
- /* Set new exception for this thread. */
- tmp_type = tstate->exc_type;
- tmp_value = tstate->exc_value;
- tmp_tb = tstate->exc_traceback;
- Py_INCREF(type);
- Py_XINCREF(value);
- Py_XINCREF(tb);
- tstate->exc_type = type;
- tstate->exc_value = value;
- tstate->exc_traceback = tb;
- Py_XDECREF(tmp_type);
- Py_XDECREF(tmp_value);
- Py_XDECREF(tmp_tb);
- /* For b/w compatibility */
- PySys_SetObject("exc_type", type);
- PySys_SetObject("exc_value", value);
- PySys_SetObject("exc_traceback", tb);
-}
-
-static void
-reset_exc_info(PyThreadState *tstate)
-{
- PyFrameObject *frame;
- PyObject *tmp_type, *tmp_value, *tmp_tb;
-
- /* It's a precondition that the thread state's frame caught an
- * exception -- verify in a debug build.
- */
- assert(tstate != NULL);
- frame = tstate->frame;
- assert(frame != NULL);
- assert(frame->f_exc_type != NULL);
-
- /* Copy the frame's exception info back to the thread state. */
- tmp_type = tstate->exc_type;
- tmp_value = tstate->exc_value;
- tmp_tb = tstate->exc_traceback;
- Py_INCREF(frame->f_exc_type);
- Py_XINCREF(frame->f_exc_value);
- Py_XINCREF(frame->f_exc_traceback);
- tstate->exc_type = frame->f_exc_type;
- tstate->exc_value = frame->f_exc_value;
- tstate->exc_traceback = frame->f_exc_traceback;
- Py_XDECREF(tmp_type);
- Py_XDECREF(tmp_value);
- Py_XDECREF(tmp_tb);
-
- /* For b/w compatibility */
- PySys_SetObject("exc_type", frame->f_exc_type);
- PySys_SetObject("exc_value", frame->f_exc_value);
- PySys_SetObject("exc_traceback", frame->f_exc_traceback);
-
- /* Clear the frame's exception info. */
- tmp_type = frame->f_exc_type;
- tmp_value = frame->f_exc_value;
- tmp_tb = frame->f_exc_traceback;
- frame->f_exc_type = NULL;
- frame->f_exc_value = NULL;
- frame->f_exc_traceback = NULL;
- Py_DECREF(tmp_type);
- Py_XDECREF(tmp_value);
- Py_XDECREF(tmp_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 *type, PyObject *value, PyObject *tb)
+do_raise(PyObject *exc, PyObject *cause)
{
- if (type == NULL) {
+ PyObject *type = NULL, *value = NULL;
+
+ if (exc == NULL) {
/* Reraise */
PyThreadState *tstate = PyThreadState_GET();
- type = tstate->exc_type == NULL ? Py_None : tstate->exc_type;
+ 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 <class>, <classinstance>
- raise <class>, <argument tuple>
- raise <class>, None
- raise <class>, <argument>
- raise <classinstance>, None
- raise <string>, <object>
- raise <string>, None
-
- An omitted second argument is the same as None.
-
- In addition, raise <tuple>, <anything> is the same as
- raising the tuple's first item (and it better have one!);
- this rule is applied recursively.
-
- Finally, an optional third argument can be supplied, which
- gives the traceback to be substituted (useful when
- re-raising an exception after examining it). */
-
- /* First, check the traceback argument, replacing None with
- NULL. */
- if (tb == Py_None) {
- Py_DECREF(tb);
- tb = NULL;
- }
- else if (tb != NULL && !PyTraceBack_Check(tb)) {
- PyErr_SetString(PyExc_TypeError,
- "raise: arg 3 must be a traceback or None");
- goto raise_error;
- }
-
- /* Next, replace a missing value with None */
- if (value == NULL) {
- value = Py_None;
- Py_INCREF(value);
- }
+ raise
+ raise <instance>
+ raise <type> */
- /* Next, repeatedly, replace a tuple exception with its first item */
- while (PyTuple_Check(type) && PyTuple_Size(type) > 0) {
- PyObject *tmp = type;
- type = PyTuple_GET_ITEM(type, 0);
- Py_INCREF(type);
- Py_DECREF(tmp);
- }
-
- if (PyExceptionClass_Check(type)) {
- PyErr_NormalizeException(&type, &value, &tb);
+ 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 %s() should have returned an instance of "
- "BaseException, not '%s'",
- ((PyTypeObject *)type)->tp_name,
- Py_TYPE(value)->tp_name);
+ "calling %R should have returned an instance of "
+ "BaseException, not %R",
+ type, Py_TYPE(value));
goto raise_error;
}
}
- else if (PyExceptionInstance_Check(type)) {
- /* Raising an instance. The value should be a dummy. */
- if (value != Py_None) {
- PyErr_SetString(PyExc_TypeError,
- "instance exception may not have a separate value");
- goto raise_error;
- }
- else {
- /* Normalize to raise <class>, <instance> */
- Py_DECREF(value);
- value = type;
- type = PyExceptionInstance_Class(type);
- Py_INCREF(type);
- }
+ 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 :-) */
- PyErr_Format(PyExc_TypeError,
- "exceptions must be old-style classes or "
- "derived from BaseException, not %s",
- type->ob_type->tp_name);
+ Py_DECREF(exc);
+ PyErr_SetString(PyExc_TypeError,
+ "exceptions must derive from BaseException");
goto raise_error;
}
- assert(PyExceptionClass_Check(type));
- if (Py_Py3kWarningFlag && PyClass_Check(type)) {
- if (PyErr_WarnEx(PyExc_DeprecationWarning,
- "exceptions must derive from BaseException "
- "in 3.x", 1) < 0)
+ 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_Restore(type, value, tb);
- if (tb == NULL)
- return WHY_EXCEPTION;
- else
- return WHY_RERAISE;
- raise_error:
+ 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(tb);
+ 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. */
+ 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, PyObject **sp)
+unpack_iterable(PyObject *v, int argcnt, int argcntafter, PyObject **sp)
{
- int i = 0;
+ int i = 0, j = 0;
+ Py_ssize_t ll = 0;
PyObject *it; /* iter(v) */
PyObject *w;
+ PyObject *l = NULL; /* variable list */
assert(v != NULL);
@@ -3601,17 +3504,43 @@ unpack_iterable(PyObject *v, int argcnt, PyObject **sp)
*--sp = w;
}
- /* We better have exhausted the iterator now. */
- w = PyIter_Next(it);
- if (w == NULL) {
- if (PyErr_Occurred())
- goto Error;
- Py_DECREF(it);
- return 1;
+ 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;
}
- Py_DECREF(w);
- PyErr_SetString(PyExc_ValueError, "too many values to unpack");
- /* fall through */
+
+ 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);
@@ -3818,13 +3747,6 @@ PyEval_GetFrame(void)
}
int
-PyEval_GetRestricted(void)
-{
- PyFrameObject *current_frame = PyEval_GetFrame();
- return current_frame == NULL ? 0 : PyFrame_IsRestricted(current_frame);
-}
-
-int
PyEval_MergeCompilerFlags(PyCompilerFlags *cf)
{
PyFrameObject *current_frame = PyEval_GetFrame();
@@ -3847,17 +3769,6 @@ PyEval_MergeCompilerFlags(PyCompilerFlags *cf)
return result;
}
-int
-Py_FlushLine(void)
-{
- PyObject *f = PySys_GetObject("stdout");
- if (f == NULL)
- return 0;
- if (!PyFile_SoftSpace(f, 0))
- return 0;
- return PyFile_WriteString("\n", f);
-}
-
/* External interface to call any callable object.
The arg must be a tuple or NULL. The kw must be a dict or NULL. */
@@ -3898,17 +3809,11 @@ PyEval_GetFuncName(PyObject *func)
if (PyMethod_Check(func))
return PyEval_GetFuncName(PyMethod_GET_FUNCTION(func));
else if (PyFunction_Check(func))
- return PyString_AsString(((PyFunctionObject*)func)->func_name);
+ return _PyUnicode_AsString(((PyFunctionObject*)func)->func_name);
else if (PyCFunction_Check(func))
return ((PyCFunctionObject*)func)->m_ml->ml_name;
- else if (PyClass_Check(func))
- return PyString_AsString(((PyClassObject*)func)->cl_name);
- else if (PyInstance_Check(func)) {
- return PyString_AsString(
- ((PyInstanceObject*)func)->in_class->cl_name);
- } else {
+ else
return func->ob_type->tp_name;
- }
}
const char *
@@ -3920,13 +3825,8 @@ PyEval_GetFuncDesc(PyObject *func)
return "()";
else if (PyCFunction_Check(func))
return "()";
- else if (PyClass_Check(func))
- return " constructor";
- else if (PyInstance_Check(func)) {
- return " instance";
- } else {
+ else
return " object";
- }
}
static void
@@ -4073,12 +3973,14 @@ 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 && nk==0 &&
+ 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;
@@ -4114,9 +4016,9 @@ fast_function(PyObject *func, PyObject ***pp_stack, int n, int na, int nk)
d = &PyTuple_GET_ITEM(argdefs, 0);
nd = Py_SIZE(argdefs);
}
- return PyEval_EvalCodeEx(co, globals,
+ return PyEval_EvalCodeEx((PyObject*)co, globals,
(PyObject *)NULL, (*pp_stack)-n, na,
- (*pp_stack)-2*nk, nk, d, nd,
+ (*pp_stack)-2*nk, nk, d, nd, kwdefs,
PyFunction_GET_CLOSURE(func));
}
@@ -4140,10 +4042,10 @@ update_keyword_args(PyObject *orig_kwdict, int nk, PyObject ***pp_stack,
if (PyDict_GetItem(kwdict, key) != NULL) {
PyErr_Format(PyExc_TypeError,
"%.200s%s got multiple values "
- "for keyword argument '%.200s'",
+ "for keyword argument '%U'",
PyEval_GetFuncName(func),
PyEval_GetFuncDesc(func),
- PyString_AsString(key));
+ key);
Py_DECREF(key);
Py_DECREF(value);
Py_DECREF(kwdict);
@@ -4237,7 +4139,7 @@ do_call(PyObject *func, PyObject ***pp_stack, int na, int nk)
}
else
result = PyObject_Call(func, callargs, kwdict);
- call_fail:
+call_fail:
Py_XDECREF(callargs);
Py_XDECREF(kwdict);
return result;
@@ -4354,14 +4256,7 @@ _PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi)
{
if (v != NULL) {
Py_ssize_t x;
- if (PyInt_Check(v)) {
- /* XXX(nnorwitz): I think PyInt_AS_LONG is correct,
- however, it looks like it should be AsSsize_t.
- There should be a comment here explaining why.
- */
- x = PyInt_AS_LONG(v);
- }
- else if (PyIndex_Check(v)) {
+ if (PyIndex_Check(v)) {
x = PyNumber_AsSsize_t(v, NULL);
if (x == -1 && PyErr_Occurred())
return 0;
@@ -4377,76 +4272,8 @@ _PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi)
return 1;
}
-#undef ISINDEX
-#define ISINDEX(x) ((x) == NULL || \
- PyInt_Check(x) || PyLong_Check(x) || PyIndex_Check(x))
-
-static PyObject *
-apply_slice(PyObject *u, PyObject *v, PyObject *w) /* return u[v:w] */
-{
- PyTypeObject *tp = u->ob_type;
- PySequenceMethods *sq = tp->tp_as_sequence;
-
- if (sq && sq->sq_slice && ISINDEX(v) && ISINDEX(w)) {
- Py_ssize_t ilow = 0, ihigh = PY_SSIZE_T_MAX;
- if (!_PyEval_SliceIndex(v, &ilow))
- return NULL;
- if (!_PyEval_SliceIndex(w, &ihigh))
- return NULL;
- return PySequence_GetSlice(u, ilow, ihigh);
- }
- else {
- PyObject *slice = PySlice_New(v, w, NULL);
- if (slice != NULL) {
- PyObject *res = PyObject_GetItem(u, slice);
- Py_DECREF(slice);
- return res;
- }
- else
- return NULL;
- }
-}
-
-static int
-assign_slice(PyObject *u, PyObject *v, PyObject *w, PyObject *x)
- /* u[v:w] = x */
-{
- PyTypeObject *tp = u->ob_type;
- PySequenceMethods *sq = tp->tp_as_sequence;
-
- if (sq && sq->sq_ass_slice && ISINDEX(v) && ISINDEX(w)) {
- Py_ssize_t ilow = 0, ihigh = PY_SSIZE_T_MAX;
- if (!_PyEval_SliceIndex(v, &ilow))
- return -1;
- if (!_PyEval_SliceIndex(w, &ihigh))
- return -1;
- if (x == NULL)
- return PySequence_DelSlice(u, ilow, ihigh);
- else
- return PySequence_SetSlice(u, ilow, ihigh, x);
- }
- else {
- PyObject *slice = PySlice_New(v, w, NULL);
- if (slice != NULL) {
- int res;
- if (x != NULL)
- res = PyObject_SetItem(u, slice, x);
- else
- res = PyObject_DelItem(u, slice);
- Py_DECREF(slice);
- return res;
- }
- else
- return -1;
- }
-}
-
-#define Py3kExceptionClass_Check(x) \
- (PyType_Check((x)) && \
- PyType_FastSubclass((PyTypeObject*)(x), Py_TPFLAGS_BASE_EXC_SUBCLASS))
-
-#define CANNOT_CATCH_MSG "catching classes that don't inherit from " \
- "BaseException is not allowed in 3.x"
+#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)
@@ -4476,48 +4303,18 @@ cmp_outcome(int op, register PyObject *v, register PyObject *w)
length = PyTuple_Size(w);
for (i = 0; i < length; i += 1) {
PyObject *exc = PyTuple_GET_ITEM(w, i);
- if (PyString_Check(exc)) {
- int ret_val;
- ret_val = PyErr_WarnEx(
- PyExc_DeprecationWarning,
- "catching of string "
- "exceptions is deprecated", 1);
- if (ret_val < 0)
- return NULL;
- }
- else if (Py_Py3kWarningFlag &&
- !PyTuple_Check(exc) &&
- !Py3kExceptionClass_Check(exc))
- {
- int ret_val;
- ret_val = PyErr_WarnEx(
- PyExc_DeprecationWarning,
- CANNOT_CATCH_MSG, 1);
- if (ret_val < 0)
- return NULL;
+ if (!PyExceptionClass_Check(exc)) {
+ PyErr_SetString(PyExc_TypeError,
+ CANNOT_CATCH_MSG);
+ return NULL;
}
}
}
else {
- if (PyString_Check(w)) {
- int ret_val;
- ret_val = PyErr_WarnEx(
- PyExc_DeprecationWarning,
- "catching of string "
- "exceptions is deprecated", 1);
- if (ret_val < 0)
- return NULL;
- }
- else if (Py_Py3kWarningFlag &&
- !PyTuple_Check(w) &&
- !Py3kExceptionClass_Check(w))
- {
- int ret_val;
- ret_val = PyErr_WarnEx(
- PyExc_DeprecationWarning,
- CANNOT_CATCH_MSG, 1);
- if (ret_val < 0)
- return NULL;
+ if (!PyExceptionClass_Check(w)) {
+ PyErr_SetString(PyExc_TypeError,
+ CANNOT_CATCH_MSG);
+ return NULL;
}
}
res = PyErr_GivenExceptionMatches(v, w);
@@ -4537,9 +4334,7 @@ import_from(PyObject *v, PyObject *name)
x = PyObject_GetAttr(v, name);
if (x == NULL && PyErr_ExceptionMatches(PyExc_AttributeError)) {
- PyErr_Format(PyExc_ImportError,
- "cannot import name %.230s",
- PyString_AsString(name));
+ PyErr_Format(PyExc_ImportError, "cannot import name %S", name);
}
return x;
}
@@ -4581,8 +4376,8 @@ import_all_from(PyObject *locals, PyObject *v)
break;
}
if (skip_leading_underscores &&
- PyString_Check(name) &&
- PyString_AS_STRING(name)[0] == '_')
+ PyUnicode_Check(name) &&
+ PyUnicode_AS_UNICODE(name)[0] == '_')
{
Py_DECREF(name);
continue;
@@ -4603,188 +4398,51 @@ import_all_from(PyObject *locals, PyObject *v)
return err;
}
-static PyObject *
-build_class(PyObject *methods, PyObject *bases, PyObject *name)
-{
- PyObject *metaclass = NULL, *result, *base;
-
- if (PyDict_Check(methods))
- metaclass = PyDict_GetItemString(methods, "__metaclass__");
- if (metaclass != NULL)
- Py_INCREF(metaclass);
- else if (PyTuple_Check(bases) && PyTuple_GET_SIZE(bases) > 0) {
- base = PyTuple_GET_ITEM(bases, 0);
- metaclass = PyObject_GetAttrString(base, "__class__");
- if (metaclass == NULL) {
- PyErr_Clear();
- metaclass = (PyObject *)base->ob_type;
- Py_INCREF(metaclass);
- }
- }
- else {
- PyObject *g = PyEval_GetGlobals();
- if (g != NULL && PyDict_Check(g))
- metaclass = PyDict_GetItemString(g, "__metaclass__");
- if (metaclass == NULL)
- metaclass = (PyObject *) &PyClass_Type;
- Py_INCREF(metaclass);
- }
- result = PyObject_CallFunctionObjArgs(metaclass, name, bases, methods,
- NULL);
- Py_DECREF(metaclass);
- if (result == NULL && PyErr_ExceptionMatches(PyExc_TypeError)) {
- /* A type error here likely means that the user passed
- in a base that was not a class (such the random module
- instead of the random.random type). Help them out with
- by augmenting the error message with more information.*/
-
- PyObject *ptype, *pvalue, *ptraceback;
-
- PyErr_Fetch(&ptype, &pvalue, &ptraceback);
- if (PyString_Check(pvalue)) {
- PyObject *newmsg;
- newmsg = PyString_FromFormat(
- "Error when calling the metaclass bases\n"
- " %s",
- PyString_AS_STRING(pvalue));
- if (newmsg != NULL) {
- Py_DECREF(pvalue);
- pvalue = newmsg;
- }
- }
- PyErr_Restore(ptype, pvalue, ptraceback);
- }
- return result;
-}
-
-static int
-exec_statement(PyFrameObject *f, PyObject *prog, PyObject *globals,
- PyObject *locals)
-{
- int n;
- PyObject *v;
- int plain = 0;
-
- if (PyTuple_Check(prog) && globals == Py_None && locals == Py_None &&
- ((n = PyTuple_Size(prog)) == 2 || n == 3)) {
- /* Backward compatibility hack */
- globals = PyTuple_GetItem(prog, 1);
- if (n == 3)
- locals = PyTuple_GetItem(prog, 2);
- prog = PyTuple_GetItem(prog, 0);
- }
- if (globals == Py_None) {
- globals = PyEval_GetGlobals();
- if (locals == Py_None) {
- locals = PyEval_GetLocals();
- plain = 1;
- }
- if (!globals || !locals) {
- PyErr_SetString(PyExc_SystemError,
- "globals and locals cannot be NULL");
- return -1;
- }
- }
- else if (locals == Py_None)
- locals = globals;
- if (!PyString_Check(prog) &&
-#ifdef Py_USING_UNICODE
- !PyUnicode_Check(prog) &&
-#endif
- !PyCode_Check(prog) &&
- !PyFile_Check(prog)) {
- PyErr_SetString(PyExc_TypeError,
- "exec: arg 1 must be a string, file, or code object");
- return -1;
- }
- if (!PyDict_Check(globals)) {
- PyErr_SetString(PyExc_TypeError,
- "exec: arg 2 must be a dictionary or None");
- return -1;
- }
- if (!PyMapping_Check(locals)) {
- PyErr_SetString(PyExc_TypeError,
- "exec: arg 3 must be a mapping or None");
- return -1;
- }
- if (PyDict_GetItemString(globals, "__builtins__") == NULL)
- PyDict_SetItemString(globals, "__builtins__", f->f_builtins);
- if (PyCode_Check(prog)) {
- if (PyCode_GetNumFree((PyCodeObject *)prog) > 0) {
- PyErr_SetString(PyExc_TypeError,
- "code object passed to exec may not contain free variables");
- return -1;
- }
- v = PyEval_EvalCode((PyCodeObject *) prog, globals, locals);
- }
- else if (PyFile_Check(prog)) {
- FILE *fp = PyFile_AsFile(prog);
- char *name = PyString_AsString(PyFile_Name(prog));
- PyCompilerFlags cf;
- if (name == NULL)
- return -1;
- cf.cf_flags = 0;
- if (PyEval_MergeCompilerFlags(&cf))
- v = PyRun_FileFlags(fp, name, Py_file_input, globals,
- locals, &cf);
- else
- v = PyRun_File(fp, name, Py_file_input, globals,
- locals);
- }
- else {
- PyObject *tmp = NULL;
- char *str;
- PyCompilerFlags cf;
- cf.cf_flags = 0;
-#ifdef Py_USING_UNICODE
- if (PyUnicode_Check(prog)) {
- tmp = PyUnicode_AsUTF8String(prog);
- if (tmp == NULL)
- return -1;
- prog = tmp;
- cf.cf_flags |= PyCF_SOURCE_IS_UTF8;
- }
-#endif
- if (PyString_AsStringAndSize(prog, &str, NULL))
- return -1;
- if (PyEval_MergeCompilerFlags(&cf))
- v = PyRun_StringFlags(str, Py_file_input, globals,
- locals, &cf);
- else
- v = PyRun_String(str, Py_file_input, globals, locals);
- Py_XDECREF(tmp);
- }
- if (plain)
- PyFrame_LocalsToFast(f, 0);
- if (v == NULL)
- return -1;
- Py_DECREF(v);
- return 0;
-}
-
static void
-format_exc_check_arg(PyObject *exc, char *format_str, PyObject *obj)
+format_exc_check_arg(PyObject *exc, const char *format_str, PyObject *obj)
{
- char *obj_str;
+ const char *obj_str;
if (!obj)
return;
- obj_str = PyString_AsString(obj);
+ 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 *
-string_concatenate(PyObject *v, PyObject *w,
+unicode_concatenate(PyObject *v, PyObject *w,
PyFrameObject *f, unsigned char *next_instr)
{
/* This function implements 'variable += expr' when both arguments
- are strings. */
- Py_ssize_t v_len = PyString_GET_SIZE(v);
- Py_ssize_t w_len = PyString_GET_SIZE(w);
+ are (Unicode) strings. */
+ Py_ssize_t v_len = PyUnicode_GET_SIZE(v);
+ Py_ssize_t w_len = PyUnicode_GET_SIZE(w);
Py_ssize_t new_len = v_len + w_len;
if (new_len < 0) {
PyErr_SetString(PyExc_OverflowError,
@@ -4792,7 +4450,7 @@ string_concatenate(PyObject *v, PyObject *w,
return NULL;
}
- if (v->ob_refcnt == 2) {
+ 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
@@ -4833,12 +4491,12 @@ string_concatenate(PyObject *v, PyObject *w,
}
}
- if (v->ob_refcnt == 1 && !PyString_CHECK_INTERNED(v)) {
+ if (Py_REFCNT(v) == 1 && !PyUnicode_CHECK_INTERNED(v)) {
/* Now we own the last reference to 'v', so we can resize it
* in-place.
*/
- if (_PyString_Resize(&v, new_len) != 0) {
- /* XXX if _PyString_Resize() fails, 'v' has been
+ if (PyUnicode_Resize(&v, new_len) != 0) {
+ /* XXX if PyUnicode_Resize() fails, 'v' has been
* deallocated so it cannot be put back into
* 'variable'. The MemoryError is raised when there
* is no value in 'variable', which might (very
@@ -4847,14 +4505,15 @@ string_concatenate(PyObject *v, PyObject *w,
return NULL;
}
/* copy 'w' into the newly allocated area of 'v' */
- memcpy(PyString_AS_STRING(v) + v_len,
- PyString_AS_STRING(w), w_len);
+ memcpy(PyUnicode_AS_UNICODE(v) + v_len,
+ PyUnicode_AS_UNICODE(w), w_len*sizeof(Py_UNICODE));
return v;
}
else {
/* When in-place resizing is not an option. */
- PyString_Concat(&v, w);
- return v;
+ w = PyUnicode_Concat(v, w);
+ Py_DECREF(v);
+ return w;
}
}
@@ -4867,7 +4526,7 @@ getarray(long a[256])
PyObject *l = PyList_New(256);
if (l == NULL) return NULL;
for (i = 0; i < 256; i++) {
- PyObject *x = PyInt_FromLong(a[i]);
+ PyObject *x = PyLong_FromLong(a[i]);
if (x == NULL) {
Py_DECREF(l);
return NULL;