diff options
Diffstat (limited to 'Python/ceval.c')
-rw-r--r-- | Python/ceval.c | 2856 |
1 files changed, 1526 insertions, 1330 deletions
diff --git a/Python/ceval.c b/Python/ceval.c index f0ea7c9..807fa7d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -138,7 +138,7 @@ 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 **); +static PyObject * special_lookup(PyObject *, _Py_Identifier *); #define NAME_ERROR_MSG \ "name '%.200s' is not defined" @@ -372,6 +372,7 @@ PyEval_ReleaseThread(PyThreadState *tstate) void PyEval_ReInitThreads(void) { + _Py_IDENTIFIER(_after_fork); PyObject *threading, *result; PyThreadState *tstate = PyThreadState_GET(); @@ -392,7 +393,7 @@ PyEval_ReInitThreads(void) PyErr_Clear(); return; } - result = PyObject_CallMethod(threading, "_after_fork", NULL); + result = _PyObject_CallMethodId(threading, &PyId__after_fork, NULL); if (result == NULL) PyErr_WriteUnraisable(threading); else @@ -491,7 +492,6 @@ static struct { } pendingcalls[NPENDINGCALLS]; static int pendingfirst = 0; static int pendinglast = 0; -static char pendingbusy = 0; int Py_AddPendingCall(int (*func)(void *), void *arg) @@ -538,6 +538,7 @@ Py_AddPendingCall(int (*func)(void *), void *arg) int Py_MakePendingCalls(void) { + static int busy = 0; int i; int r = 0; @@ -552,9 +553,9 @@ Py_MakePendingCalls(void) if (main_thread && PyThread_get_thread_ident() != main_thread) return 0; /* don't perform recursive pending calls */ - if (pendingbusy) + if (busy) return 0; - pendingbusy = 1; + busy = 1; /* perform a bounded number of calls, in case of recursion */ for (i=0; i<NPENDINGCALLS; i++) { int j; @@ -583,7 +584,7 @@ Py_MakePendingCalls(void) if (r) break; } - pendingbusy = 0; + busy = 0; return r; } @@ -741,7 +742,6 @@ _Py_CheckRecursiveCall(char *where) enum why_code { WHY_NOT = 0x0001, /* No error */ WHY_EXCEPTION = 0x0002, /* Exception occurred */ - WHY_RERAISE = 0x0004, /* Exception re-raised by 'finally' */ WHY_RETURN = 0x0008, /* 'return' statement */ WHY_BREAK = 0x0010, /* 'break' statement */ WHY_CONTINUE = 0x0020, /* 'continue' statement */ @@ -749,7 +749,10 @@ enum why_code { WHY_SILENCED = 0x0080 /* Exception silenced by 'with' */ }; -static enum why_code do_raise(PyObject *, PyObject *); +static void save_exc_state(PyThreadState *, PyFrameObject *); +static void swap_exc_state(PyThreadState *, PyFrameObject *); +static void restore_and_clear_exc_state(PyThreadState *, PyFrameObject *); +static int do_raise(PyObject *, PyObject *); static int unpack_iterable(PyObject *, int, int, PyObject **); /* Records whether tracing is on for any thread. Counts the number of @@ -794,12 +797,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) register int opcode; /* Current opcode */ register int oparg; /* Current opcode argument, if any */ register enum why_code why; /* Reason for block stack unwind */ - register int err; /* Error status -- nonzero if error */ - register PyObject *x; /* Result object -- NULL if error */ - register PyObject *v; /* Temporary objects popped off stack */ - register PyObject *w; - register PyObject *u; - register PyObject *t; register PyObject **fastlocals, **freevars; PyObject *retval = NULL; /* Return value */ PyThreadState *tstate = PyThreadState_GET(); @@ -817,9 +814,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) unsigned char *first_instr; PyObject *names; PyObject *consts; -#if defined(Py_DEBUG) || defined(LLTRACE) - /* Make it easier to find out where we are with a debugger */ - char *filename; + +#ifdef LLTRACE + _Py_IDENTIFIER(__ltrace__); #endif /* Computed GOTOs, or @@ -1114,59 +1111,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) 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) - return NULL; - /* push frame */ if (Py_EnterRecursiveCall("")) return NULL; @@ -1221,6 +1167,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) f->f_lasti to -1 (i.e. the index *before* the first instruction) and YIELD_VALUE doesn't fiddle with f_lasti any more. So this does work. Promise. + YIELD_FROM sets f_lasti to itself, in order to repeated yield + multiple values. When the PREDICT() macros are enabled, some opcode pairs follow in direct succession without updating f->f_lasti. A successful @@ -1240,38 +1188,20 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) /* 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(); + swap_exc_state(tstate, f); } + else + save_exc_state(tstate, f); } #ifdef LLTRACE - lltrace = PyDict_GetItemString(f->f_globals, "__lltrace__") != NULL; -#endif -#if defined(Py_DEBUG) || defined(LLTRACE) - { - 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); - } + lltrace = _PyDict_GetItemId(f->f_globals, &PyId___ltrace__) != NULL; #endif why = WHY_NOT; - err = 0; - x = Py_None; /* Not a reference, just anything non-NULL */ - w = NULL; - if (throwflag) { /* support for generator.throw() */ - why = WHY_EXCEPTION; - goto on_error; - } + if (throwflag) /* support for generator.throw() */ + goto error; for (;;) { #ifdef WITH_TSC @@ -1313,10 +1243,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) ticked = 1; #endif if (_Py_atomic_load_relaxed(&pendingcalls_to_do)) { - if (Py_MakePendingCalls() < 0) { - why = WHY_EXCEPTION; - goto on_error; - } + if (Py_MakePendingCalls() < 0) + goto error; } #ifdef WITH_THREAD if (_Py_atomic_load_relaxed(&gil_drop_request)) { @@ -1334,13 +1262,12 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) #endif /* Check for asynchronous exceptions. */ if (tstate->async_exc != NULL) { - x = tstate->async_exc; + PyObject *exc = tstate->async_exc; tstate->async_exc = NULL; UNSIGNAL_ASYNC_EXC(); - PyErr_SetNone(x); - Py_DECREF(x); - why = WHY_EXCEPTION; - goto on_error; + PyErr_SetNone(exc); + Py_DECREF(exc); + goto error; } } @@ -1351,6 +1278,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) if (_Py_TracingPossible && tstate->c_tracefunc != NULL && !tstate->tracing) { + int err; /* see maybe_call_line_trace for expository comments */ f->f_stacktop = stack_pointer; @@ -1365,10 +1293,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) stack_pointer = f->f_stacktop; f->f_stacktop = NULL; } - if (err) { + if (err) /* trace function raised an exception */ - goto on_error; - } + goto error; } /* Extract opcode and argument */ @@ -1412,92 +1339,102 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) x to NULL, err to nonzero, or why to anything but WHY_NOT, and that no operation that succeeds does this! */ - /* case STOP_CODE: this is an error! */ - TARGET(NOP) FAST_DISPATCH(); - TARGET(LOAD_FAST) - x = GETLOCAL(oparg); - if (x != NULL) { - Py_INCREF(x); - PUSH(x); - FAST_DISPATCH(); + TARGET(LOAD_FAST) { + PyObject *value = GETLOCAL(oparg); + if (value == NULL) { + format_exc_check_arg(PyExc_UnboundLocalError, + UNBOUNDLOCAL_ERROR_MSG, + PyTuple_GetItem(co->co_varnames, oparg)); + goto error; } - format_exc_check_arg(PyExc_UnboundLocalError, - UNBOUNDLOCAL_ERROR_MSG, - PyTuple_GetItem(co->co_varnames, oparg)); - break; + Py_INCREF(value); + PUSH(value); + FAST_DISPATCH(); + } - TARGET(LOAD_CONST) - x = GETITEM(consts, oparg); - Py_INCREF(x); - PUSH(x); + TARGET(LOAD_CONST) { + PyObject *value = GETITEM(consts, oparg); + Py_INCREF(value); + PUSH(value); FAST_DISPATCH(); + } PREDICTED_WITH_ARG(STORE_FAST); - TARGET(STORE_FAST) - v = POP(); - SETLOCAL(oparg, v); + TARGET(STORE_FAST) { + PyObject *value = POP(); + SETLOCAL(oparg, value); FAST_DISPATCH(); + } - TARGET(POP_TOP) - v = POP(); - Py_DECREF(v); + TARGET(POP_TOP) { + PyObject *value = POP(); + Py_DECREF(value); FAST_DISPATCH(); + } - TARGET(ROT_TWO) - v = TOP(); - w = SECOND(); - SET_TOP(w); - SET_SECOND(v); + TARGET(ROT_TWO) { + PyObject *top = TOP(); + PyObject *second = SECOND(); + SET_TOP(second); + SET_SECOND(top); FAST_DISPATCH(); + } - TARGET(ROT_THREE) - v = TOP(); - w = SECOND(); - x = THIRD(); - SET_TOP(w); - SET_SECOND(x); - SET_THIRD(v); + TARGET(ROT_THREE) { + PyObject *top = TOP(); + PyObject *second = SECOND(); + PyObject *third = THIRD(); + SET_TOP(second); + SET_SECOND(third); + SET_THIRD(top); FAST_DISPATCH(); + } - TARGET(DUP_TOP) - v = TOP(); - Py_INCREF(v); - PUSH(v); + TARGET(DUP_TOP) { + PyObject *top = TOP(); + Py_INCREF(top); + PUSH(top); FAST_DISPATCH(); + } - TARGET(DUP_TOP_TWO) - x = TOP(); - Py_INCREF(x); - w = SECOND(); - Py_INCREF(w); + TARGET(DUP_TOP_TWO) { + PyObject *top = TOP(); + PyObject *second = SECOND(); + Py_INCREF(top); + Py_INCREF(second); STACKADJ(2); - SET_TOP(x); - SET_SECOND(w); + SET_TOP(top); + SET_SECOND(second); FAST_DISPATCH(); + } - TARGET(UNARY_POSITIVE) - v = TOP(); - x = PyNumber_Positive(v); - Py_DECREF(v); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + TARGET(UNARY_POSITIVE) { + PyObject *value = TOP(); + PyObject *res = PyNumber_Positive(value); + Py_DECREF(value); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); + } - TARGET(UNARY_NEGATIVE) - v = TOP(); - x = PyNumber_Negative(v); - Py_DECREF(v); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + TARGET(UNARY_NEGATIVE) { + PyObject *value = TOP(); + PyObject *res = PyNumber_Negative(value); + Py_DECREF(value); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); + } - TARGET(UNARY_NOT) - v = TOP(); - err = PyObject_IsTrue(v); - Py_DECREF(v); + TARGET(UNARY_NOT) { + PyObject *value = TOP(); + int err = PyObject_IsTrue(value); + Py_DECREF(value); if (err == 0) { Py_INCREF(Py_True); SET_TOP(Py_True); @@ -1510,422 +1447,507 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) DISPATCH(); } STACKADJ(-1); - break; + goto error; + } - TARGET(UNARY_INVERT) - v = TOP(); - x = PyNumber_Invert(v); - Py_DECREF(v); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + TARGET(UNARY_INVERT) { + PyObject *value = TOP(); + PyObject *res = PyNumber_Invert(value); + Py_DECREF(value); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); + } - TARGET(BINARY_POWER) - w = POP(); - v = TOP(); - x = PyNumber_Power(v, w, Py_None); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + TARGET(BINARY_POWER) { + PyObject *exp = POP(); + PyObject *base = TOP(); + PyObject *res = PyNumber_Power(base, exp, Py_None); + Py_DECREF(base); + Py_DECREF(exp); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); + } - TARGET(BINARY_MULTIPLY) - w = POP(); - v = TOP(); - x = PyNumber_Multiply(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + TARGET(BINARY_MULTIPLY) { + PyObject *right = POP(); + PyObject *left = TOP(); + PyObject *res = PyNumber_Multiply(left, right); + Py_DECREF(left); + Py_DECREF(right); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); + } - TARGET(BINARY_TRUE_DIVIDE) - w = POP(); - v = TOP(); - x = PyNumber_TrueDivide(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + TARGET(BINARY_TRUE_DIVIDE) { + PyObject *divisor = POP(); + PyObject *dividend = TOP(); + PyObject *quotient = PyNumber_TrueDivide(dividend, divisor); + Py_DECREF(dividend); + Py_DECREF(divisor); + SET_TOP(quotient); + if (quotient == NULL) + goto error; + DISPATCH(); + } - TARGET(BINARY_FLOOR_DIVIDE) - w = POP(); - v = TOP(); - x = PyNumber_FloorDivide(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + TARGET(BINARY_FLOOR_DIVIDE) { + PyObject *divisor = POP(); + PyObject *dividend = TOP(); + PyObject *quotient = PyNumber_FloorDivide(dividend, divisor); + Py_DECREF(dividend); + Py_DECREF(divisor); + SET_TOP(quotient); + if (quotient == NULL) + goto error; + DISPATCH(); + } - TARGET(BINARY_MODULO) - w = POP(); - v = TOP(); - if (PyUnicode_CheckExact(v)) - x = PyUnicode_Format(v, w); - else - x = PyNumber_Remainder(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + TARGET(BINARY_MODULO) { + PyObject *divisor = POP(); + PyObject *dividend = TOP(); + PyObject *res = PyUnicode_CheckExact(dividend) ? + PyUnicode_Format(dividend, divisor) : + PyNumber_Remainder(dividend, divisor); + Py_DECREF(divisor); + Py_DECREF(dividend); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); + } - TARGET(BINARY_ADD) - w = POP(); - v = TOP(); - if (PyUnicode_CheckExact(v) && - PyUnicode_CheckExact(w)) { - x = unicode_concatenate(v, w, f, next_instr); + TARGET(BINARY_ADD) { + PyObject *right = POP(); + PyObject *left = TOP(); + PyObject *sum; + if (PyUnicode_CheckExact(left) && + PyUnicode_CheckExact(right)) { + sum = unicode_concatenate(left, right, f, next_instr); /* unicode_concatenate consumed the ref to v */ - goto skip_decref_vx; } else { - x = PyNumber_Add(v, w); + sum = PyNumber_Add(left, right); + Py_DECREF(left); } - Py_DECREF(v); - skip_decref_vx: - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(BINARY_SUBTRACT) - w = POP(); - v = TOP(); - x = PyNumber_Subtract(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; - - TARGET(BINARY_SUBSCR) - w = POP(); - v = TOP(); - x = PyObject_GetItem(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + Py_DECREF(right); + SET_TOP(sum); + if (sum == NULL) + goto error; + DISPATCH(); + } - TARGET(BINARY_LSHIFT) - w = POP(); - v = TOP(); - x = PyNumber_Lshift(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + TARGET(BINARY_SUBTRACT) { + PyObject *right = POP(); + PyObject *left = TOP(); + PyObject *diff = PyNumber_Subtract(left, right); + Py_DECREF(right); + Py_DECREF(left); + SET_TOP(diff); + if (diff == NULL) + goto error; + DISPATCH(); + } - TARGET(BINARY_RSHIFT) - w = POP(); - v = TOP(); - x = PyNumber_Rshift(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + TARGET(BINARY_SUBSCR) { + PyObject *sub = POP(); + PyObject *container = TOP(); + PyObject *res = PyObject_GetItem(container, sub); + Py_DECREF(container); + Py_DECREF(sub); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); + } - TARGET(BINARY_AND) - w = POP(); - v = TOP(); - x = PyNumber_And(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + TARGET(BINARY_LSHIFT) { + PyObject *right = POP(); + PyObject *left = TOP(); + PyObject *res = PyNumber_Lshift(left, right); + Py_DECREF(left); + Py_DECREF(right); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); + } - TARGET(BINARY_XOR) - w = POP(); - v = TOP(); - x = PyNumber_Xor(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + TARGET(BINARY_RSHIFT) { + PyObject *right = POP(); + PyObject *left = TOP(); + PyObject *res = PyNumber_Rshift(left, right); + Py_DECREF(left); + Py_DECREF(right); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); + } - TARGET(BINARY_OR) - w = POP(); - v = TOP(); - x = PyNumber_Or(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + TARGET(BINARY_AND) { + PyObject *right = POP(); + PyObject *left = TOP(); + PyObject *res = PyNumber_And(left, right); + Py_DECREF(left); + Py_DECREF(right); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); + } - TARGET(LIST_APPEND) - w = POP(); - v = PEEK(oparg); - err = PyList_Append(v, w); - Py_DECREF(w); - if (err == 0) { - PREDICT(JUMP_ABSOLUTE); - DISPATCH(); - } - break; + TARGET(BINARY_XOR) { + PyObject *right = POP(); + PyObject *left = TOP(); + PyObject *res = PyNumber_Xor(left, right); + Py_DECREF(left); + Py_DECREF(right); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); + } - TARGET(SET_ADD) - w = POP(); - v = stack_pointer[-oparg]; - err = PySet_Add(v, w); - Py_DECREF(w); - if (err == 0) { - PREDICT(JUMP_ABSOLUTE); - DISPATCH(); - } - break; + TARGET(BINARY_OR) { + PyObject *right = POP(); + PyObject *left = TOP(); + PyObject *res = PyNumber_Or(left, right); + Py_DECREF(left); + Py_DECREF(right); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); + } - TARGET(INPLACE_POWER) - w = POP(); - v = TOP(); - x = PyNumber_InPlacePower(v, w, Py_None); + TARGET(LIST_APPEND) { + PyObject *v = POP(); + PyObject *list = PEEK(oparg); + int err; + err = PyList_Append(list, v); Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + if (err != 0) + goto error; + PREDICT(JUMP_ABSOLUTE); + DISPATCH(); + } - TARGET(INPLACE_MULTIPLY) - w = POP(); - v = TOP(); - x = PyNumber_InPlaceMultiply(v, w); + TARGET(SET_ADD) { + PyObject *v = POP(); + PyObject *set = stack_pointer[-oparg]; + int err; + err = PySet_Add(set, v); Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + if (err != 0) + goto error; + PREDICT(JUMP_ABSOLUTE); + DISPATCH(); + } - TARGET(INPLACE_TRUE_DIVIDE) - w = POP(); - v = TOP(); - x = PyNumber_InPlaceTrueDivide(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + TARGET(INPLACE_POWER) { + PyObject *exp = POP(); + PyObject *base = TOP(); + PyObject *res = PyNumber_InPlacePower(base, exp, Py_None); + Py_DECREF(base); + Py_DECREF(exp); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); + } - TARGET(INPLACE_FLOOR_DIVIDE) - w = POP(); - v = TOP(); - x = PyNumber_InPlaceFloorDivide(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + TARGET(INPLACE_MULTIPLY) { + PyObject *right = POP(); + PyObject *left = TOP(); + PyObject *res = PyNumber_InPlaceMultiply(left, right); + Py_DECREF(left); + Py_DECREF(right); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); + } - TARGET(INPLACE_MODULO) - w = POP(); - v = TOP(); - x = PyNumber_InPlaceRemainder(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + TARGET(INPLACE_TRUE_DIVIDE) { + PyObject *divisor = POP(); + PyObject *dividend = TOP(); + PyObject *quotient = PyNumber_InPlaceTrueDivide(dividend, divisor); + Py_DECREF(dividend); + Py_DECREF(divisor); + SET_TOP(quotient); + if (quotient == NULL) + goto error; + DISPATCH(); + } + + TARGET(INPLACE_FLOOR_DIVIDE) { + PyObject *divisor = POP(); + PyObject *dividend = TOP(); + PyObject *quotient = PyNumber_InPlaceFloorDivide(dividend, divisor); + Py_DECREF(dividend); + Py_DECREF(divisor); + SET_TOP(quotient); + if (quotient == NULL) + goto error; + DISPATCH(); + } - TARGET(INPLACE_ADD) - w = POP(); - v = TOP(); - if (PyUnicode_CheckExact(v) && - PyUnicode_CheckExact(w)) { - x = unicode_concatenate(v, w, f, next_instr); + TARGET(INPLACE_MODULO) { + PyObject *right = POP(); + PyObject *left = TOP(); + PyObject *mod = PyNumber_InPlaceRemainder(left, right); + Py_DECREF(left); + Py_DECREF(right); + SET_TOP(mod); + if (mod == NULL) + goto error; + DISPATCH(); + } + + TARGET(INPLACE_ADD) { + PyObject *right = POP(); + PyObject *left = TOP(); + PyObject *sum; + if (PyUnicode_CheckExact(left) && PyUnicode_CheckExact(right)) { + sum = unicode_concatenate(left, right, f, next_instr); /* unicode_concatenate consumed the ref to v */ - goto skip_decref_v; } else { - x = PyNumber_InPlaceAdd(v, w); + sum = PyNumber_InPlaceAdd(left, right); + Py_DECREF(left); } - Py_DECREF(v); - skip_decref_v: - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + Py_DECREF(right); + SET_TOP(sum); + if (sum == NULL) + goto error; + DISPATCH(); + } - TARGET(INPLACE_SUBTRACT) - w = POP(); - v = TOP(); - x = PyNumber_InPlaceSubtract(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + TARGET(INPLACE_SUBTRACT) { + PyObject *right = POP(); + PyObject *left = TOP(); + PyObject *diff = PyNumber_InPlaceSubtract(left, right); + Py_DECREF(left); + Py_DECREF(right); + SET_TOP(diff); + if (diff == NULL) + goto error; + DISPATCH(); + } - TARGET(INPLACE_LSHIFT) - w = POP(); - v = TOP(); - x = PyNumber_InPlaceLshift(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + TARGET(INPLACE_LSHIFT) { + PyObject *right = POP(); + PyObject *left = TOP(); + PyObject *res = PyNumber_InPlaceLshift(left, right); + Py_DECREF(left); + Py_DECREF(right); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); + } - TARGET(INPLACE_RSHIFT) - w = POP(); - v = TOP(); - x = PyNumber_InPlaceRshift(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + TARGET(INPLACE_RSHIFT) { + PyObject *right = POP(); + PyObject *left = TOP(); + PyObject *res = PyNumber_InPlaceRshift(left, right); + Py_DECREF(left); + Py_DECREF(right); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); + } - TARGET(INPLACE_AND) - w = POP(); - v = TOP(); - x = PyNumber_InPlaceAnd(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + TARGET(INPLACE_AND) { + PyObject *right = POP(); + PyObject *left = TOP(); + PyObject *res = PyNumber_InPlaceAnd(left, right); + Py_DECREF(left); + Py_DECREF(right); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); + } - TARGET(INPLACE_XOR) - w = POP(); - v = TOP(); - x = PyNumber_InPlaceXor(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + TARGET(INPLACE_XOR) { + PyObject *right = POP(); + PyObject *left = TOP(); + PyObject *res = PyNumber_InPlaceXor(left, right); + Py_DECREF(left); + Py_DECREF(right); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); + } - TARGET(INPLACE_OR) - w = POP(); - v = TOP(); - x = PyNumber_InPlaceOr(v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + TARGET(INPLACE_OR) { + PyObject *right = POP(); + PyObject *left = TOP(); + PyObject *res = PyNumber_InPlaceOr(left, right); + Py_DECREF(left); + Py_DECREF(right); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); + } - TARGET(STORE_SUBSCR) - w = TOP(); - v = SECOND(); - u = THIRD(); + TARGET(STORE_SUBSCR) { + PyObject *sub = TOP(); + PyObject *container = SECOND(); + PyObject *v = THIRD(); + int err; STACKADJ(-3); /* v[w] = u */ - err = PyObject_SetItem(v, w, u); - Py_DECREF(u); + err = PyObject_SetItem(container, sub, v); Py_DECREF(v); - Py_DECREF(w); - if (err == 0) DISPATCH(); - break; + Py_DECREF(container); + Py_DECREF(sub); + if (err != 0) + goto error; + DISPATCH(); + } - TARGET(DELETE_SUBSCR) - w = TOP(); - v = SECOND(); + TARGET(DELETE_SUBSCR) { + PyObject *sub = TOP(); + PyObject *container = SECOND(); + int err; STACKADJ(-2); /* del v[w] */ - err = PyObject_DelItem(v, w); - Py_DECREF(v); - Py_DECREF(w); - if (err == 0) DISPATCH(); - break; + err = PyObject_DelItem(container, sub); + Py_DECREF(container); + Py_DECREF(sub); + if (err != 0) + goto error; + DISPATCH(); + } - TARGET(PRINT_EXPR) - v = POP(); - w = PySys_GetObject("displayhook"); - if (w == NULL) { + TARGET(PRINT_EXPR) { + PyObject *value = POP(); + PyObject *hook = PySys_GetObject("displayhook"); + PyObject *res; + if (hook == NULL) { PyErr_SetString(PyExc_RuntimeError, "lost sys.displayhook"); - err = -1; - x = NULL; + Py_DECREF(value); + goto error; } - if (err == 0) { - x = PyTuple_Pack(1, v); - if (x == NULL) - err = -1; - } - if (err == 0) { - w = PyEval_CallObject(w, x); - Py_XDECREF(w); - if (w == NULL) - err = -1; - } - Py_DECREF(v); - Py_XDECREF(x); - break; + res = PyObject_CallFunctionObjArgs(hook, value, NULL); + Py_DECREF(value); + if (res == NULL) + goto error; + Py_DECREF(res); + DISPATCH(); + } #ifdef CASE_TOO_BIG default: switch (opcode) { #endif - TARGET(RAISE_VARARGS) - v = w = NULL; + TARGET(RAISE_VARARGS) { + PyObject *cause = NULL, *exc = NULL; switch (oparg) { case 2: - v = POP(); /* cause */ + cause = POP(); /* cause */ case 1: - w = POP(); /* exc */ + exc = POP(); /* exc */ case 0: /* Fallthrough */ - why = do_raise(w, v); + if (do_raise(exc, cause)) { + why = WHY_EXCEPTION; + goto fast_block_end; + } break; default: PyErr_SetString(PyExc_SystemError, "bad RAISE_VARARGS oparg"); - why = WHY_EXCEPTION; break; } - break; + goto error; + } - TARGET(STORE_LOCALS) - x = POP(); - v = f->f_locals; - Py_XDECREF(v); - f->f_locals = x; + TARGET(STORE_LOCALS) { + PyObject *locals = POP(); + PyObject *old = f->f_locals; + Py_XDECREF(old); + f->f_locals = locals; DISPATCH(); + } - TARGET(RETURN_VALUE) + TARGET(RETURN_VALUE) { retval = POP(); why = WHY_RETURN; goto fast_block_end; + } + + TARGET(YIELD_FROM) { + PyObject *v = POP(); + PyObject *reciever = TOP(); + int err; + if (PyGen_CheckExact(reciever)) { + retval = _PyGen_Send((PyGenObject *)reciever, v); + } else { + _Py_IDENTIFIER(send); + if (v == Py_None) + retval = Py_TYPE(reciever)->tp_iternext(reciever); + else + retval = _PyObject_CallMethodId(reciever, &PyId_send, "O", v); + } + Py_DECREF(v); + if (retval == NULL) { + PyObject *val; + err = _PyGen_FetchStopIterationValue(&val); + if (err < 0) + goto error; + Py_DECREF(reciever); + SET_TOP(val); + DISPATCH(); + } + /* x remains on stack, retval is value to be yielded */ + f->f_stacktop = stack_pointer; + why = WHY_YIELD; + /* and repeat... */ + f->f_lasti--; + goto fast_yield; + } - TARGET(YIELD_VALUE) + TARGET(YIELD_VALUE) { retval = POP(); f->f_stacktop = stack_pointer; why = WHY_YIELD; goto fast_yield; + } - TARGET(POP_EXCEPT) - { - PyTryBlock *b = PyFrame_BlockPop(f); - if (b->b_type != EXCEPT_HANDLER) { - PyErr_SetString(PyExc_SystemError, - "popped block is not an except handler"); - why = WHY_EXCEPTION; - break; - } - UNWIND_EXCEPT_HANDLER(b); + TARGET(POP_EXCEPT) { + PyTryBlock *b = PyFrame_BlockPop(f); + if (b->b_type != EXCEPT_HANDLER) { + PyErr_SetString(PyExc_SystemError, + "popped block is not an except handler"); + goto error; } + UNWIND_EXCEPT_HANDLER(b); DISPATCH(); + } - TARGET(POP_BLOCK) - { - PyTryBlock *b = PyFrame_BlockPop(f); - UNWIND_BLOCK(b); - } + TARGET(POP_BLOCK) { + PyTryBlock *b = PyFrame_BlockPop(f); + UNWIND_BLOCK(b); DISPATCH(); + } PREDICTED(END_FINALLY); - TARGET(END_FINALLY) - v = POP(); - if (PyLong_Check(v)) { - why = (enum why_code) PyLong_AS_LONG(v); - assert(why != WHY_YIELD); + TARGET(END_FINALLY) { + PyObject *status = POP(); + if (PyLong_Check(status)) { + why = (enum why_code) PyLong_AS_LONG(status); + assert(why != WHY_YIELD && why != WHY_EXCEPTION); if (why == WHY_RETURN || why == WHY_CONTINUE) retval = POP(); @@ -1938,239 +1960,281 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) assert(b->b_type == EXCEPT_HANDLER); UNWIND_EXCEPT_HANDLER(b); why = WHY_NOT; + Py_DECREF(status); + DISPATCH(); } + Py_DECREF(status); + goto fast_block_end; } - else if (PyExceptionClass_Check(v)) { - w = POP(); - u = POP(); - PyErr_Restore(v, w, u); - why = WHY_RERAISE; - break; + else if (PyExceptionClass_Check(status)) { + PyObject *exc = POP(); + PyObject *tb = POP(); + PyErr_Restore(status, exc, tb); + why = WHY_EXCEPTION; + goto fast_block_end; } - else if (v != Py_None) { + else if (status != Py_None) { PyErr_SetString(PyExc_SystemError, "'finally' pops bad exception"); - why = WHY_EXCEPTION; + Py_DECREF(status); + goto error; } - Py_DECREF(v); - break; + Py_DECREF(status); + DISPATCH(); + } - TARGET(LOAD_BUILD_CLASS) - x = PyDict_GetItemString(f->f_builtins, - "__build_class__"); - if (x == NULL) { - PyErr_SetString(PyExc_ImportError, - "__build_class__ not found"); - break; + TARGET(LOAD_BUILD_CLASS) { + _Py_IDENTIFIER(__build_class__); + + PyObject *bc; + if (PyDict_CheckExact(f->f_builtins)) { + bc = _PyDict_GetItemId(f->f_builtins, &PyId___build_class__); + if (bc == NULL) { + PyErr_SetString(PyExc_NameError, + "__build_class__ not found"); + goto error; + } + Py_INCREF(bc); } - Py_INCREF(x); - PUSH(x); - break; + else { + PyObject *build_class_str = _PyUnicode_FromId(&PyId___build_class__); + if (build_class_str == NULL) + break; + bc = PyObject_GetItem(f->f_builtins, build_class_str); + if (bc == NULL) { + if (PyErr_ExceptionMatches(PyExc_KeyError)) + PyErr_SetString(PyExc_NameError, + "__build_class__ not found"); + goto error; + } + } + PUSH(bc); + DISPATCH(); + } - TARGET(STORE_NAME) - w = GETITEM(names, oparg); - v = POP(); - if ((x = f->f_locals) != NULL) { - if (PyDict_CheckExact(x)) - err = PyDict_SetItem(x, w, v); - else - err = PyObject_SetItem(x, w, v); + TARGET(STORE_NAME) { + PyObject *name = GETITEM(names, oparg); + PyObject *v = POP(); + PyObject *ns = f->f_locals; + int err; + if (ns == NULL) { + PyErr_Format(PyExc_SystemError, + "no locals found when storing %R", name); Py_DECREF(v); - if (err == 0) DISPATCH(); - break; + goto error; } - PyErr_Format(PyExc_SystemError, - "no locals found when storing %R", w); - break; + if (PyDict_CheckExact(ns)) + err = PyDict_SetItem(ns, name, v); + else + err = PyObject_SetItem(ns, name, v); + Py_DECREF(v); + if (err != 0) + goto error; + DISPATCH(); + } - TARGET(DELETE_NAME) - w = GETITEM(names, oparg); - if ((x = f->f_locals) != NULL) { - if ((err = PyObject_DelItem(x, w)) != 0) - format_exc_check_arg(PyExc_NameError, - NAME_ERROR_MSG, - w); - break; + TARGET(DELETE_NAME) { + PyObject *name = GETITEM(names, oparg); + PyObject *ns = f->f_locals; + int err; + if (ns == NULL) { + PyErr_Format(PyExc_SystemError, + "no locals when deleting %R", name); + goto error; } - PyErr_Format(PyExc_SystemError, - "no locals when deleting %R", w); - break; + err = PyObject_DelItem(ns, name); + if (err != 0) { + format_exc_check_arg(PyExc_NameError, + NAME_ERROR_MSG, + name); + goto error; + } + DISPATCH(); + } PREDICTED_WITH_ARG(UNPACK_SEQUENCE); - TARGET(UNPACK_SEQUENCE) - v = POP(); - if (PyTuple_CheckExact(v) && - PyTuple_GET_SIZE(v) == oparg) { - PyObject **items = \ - ((PyTupleObject *)v)->ob_item; + TARGET(UNPACK_SEQUENCE) { + PyObject *seq = POP(), *item, **items; + if (PyTuple_CheckExact(seq) && + PyTuple_GET_SIZE(seq) == oparg) { + items = ((PyTupleObject *)seq)->ob_item; while (oparg--) { - w = items[oparg]; - Py_INCREF(w); - PUSH(w); + item = items[oparg]; + Py_INCREF(item); + PUSH(item); } - Py_DECREF(v); - DISPATCH(); - } else if (PyList_CheckExact(v) && - PyList_GET_SIZE(v) == oparg) { - PyObject **items = \ - ((PyListObject *)v)->ob_item; + } else if (PyList_CheckExact(seq) && + PyList_GET_SIZE(seq) == oparg) { + items = ((PyListObject *)seq)->ob_item; while (oparg--) { - w = items[oparg]; - Py_INCREF(w); - PUSH(w); + item = items[oparg]; + Py_INCREF(item); + PUSH(item); } - } else if (unpack_iterable(v, oparg, -1, + } else if (unpack_iterable(seq, oparg, -1, stack_pointer + oparg)) { STACKADJ(oparg); } else { /* unpack_iterable() raised an exception */ - why = WHY_EXCEPTION; + Py_DECREF(seq); + goto error; } - Py_DECREF(v); - break; + Py_DECREF(seq); + DISPATCH(); + } - TARGET(UNPACK_EX) - { + TARGET(UNPACK_EX) { int totalargs = 1 + (oparg & 0xFF) + (oparg >> 8); - v = POP(); + PyObject *seq = POP(); - if (unpack_iterable(v, oparg & 0xFF, oparg >> 8, + if (unpack_iterable(seq, oparg & 0xFF, oparg >> 8, stack_pointer + totalargs)) { stack_pointer += totalargs; } else { - why = WHY_EXCEPTION; + Py_DECREF(seq); + goto error; } - Py_DECREF(v); - break; + Py_DECREF(seq); + DISPATCH(); } - TARGET(STORE_ATTR) - w = GETITEM(names, oparg); - v = TOP(); - u = SECOND(); + TARGET(STORE_ATTR) { + PyObject *name = GETITEM(names, oparg); + PyObject *owner = TOP(); + PyObject *v = SECOND(); + int err; STACKADJ(-2); - err = PyObject_SetAttr(v, w, u); /* v.w = u */ + err = PyObject_SetAttr(owner, name, v); Py_DECREF(v); - Py_DECREF(u); - if (err == 0) DISPATCH(); - break; + Py_DECREF(owner); + if (err != 0) + goto error; + DISPATCH(); + } - TARGET(DELETE_ATTR) - w = GETITEM(names, oparg); - v = POP(); - err = PyObject_SetAttr(v, w, (PyObject *)NULL); - /* del v.w */ - Py_DECREF(v); - break; + TARGET(DELETE_ATTR) { + PyObject *name = GETITEM(names, oparg); + PyObject *owner = POP(); + int err; + err = PyObject_SetAttr(owner, name, (PyObject *)NULL); + Py_DECREF(owner); + if (err != 0) + goto error; + DISPATCH(); + } - TARGET(STORE_GLOBAL) - w = GETITEM(names, oparg); - v = POP(); - err = PyDict_SetItem(f->f_globals, w, v); + TARGET(STORE_GLOBAL) { + PyObject *name = GETITEM(names, oparg); + PyObject *v = POP(); + int err; + err = PyDict_SetItem(f->f_globals, name, v); Py_DECREF(v); - if (err == 0) DISPATCH(); - break; + if (err != 0) + goto error; + DISPATCH(); + } - TARGET(DELETE_GLOBAL) - w = GETITEM(names, oparg); - if ((err = PyDict_DelItem(f->f_globals, w)) != 0) + TARGET(DELETE_GLOBAL) { + PyObject *name = GETITEM(names, oparg); + int err; + err = PyDict_DelItem(f->f_globals, name); + if (err != 0) { format_exc_check_arg( - PyExc_NameError, GLOBAL_NAME_ERROR_MSG, w); - break; + PyExc_NameError, GLOBAL_NAME_ERROR_MSG, name); + goto error; + } + DISPATCH(); + } - TARGET(LOAD_NAME) - w = GETITEM(names, oparg); - if ((v = f->f_locals) == NULL) { + TARGET(LOAD_NAME) { + PyObject *name = GETITEM(names, oparg); + PyObject *locals = f->f_locals; + PyObject *v; + if (locals == NULL) { PyErr_Format(PyExc_SystemError, - "no locals when loading %R", w); - why = WHY_EXCEPTION; - break; + "no locals when loading %R", name); + goto error; } - if (PyDict_CheckExact(v)) { - x = PyDict_GetItem(v, w); - Py_XINCREF(x); + if (PyDict_CheckExact(locals)) { + v = PyDict_GetItem(locals, name); + Py_XINCREF(v); } else { - x = PyObject_GetItem(v, w); - if (x == NULL && PyErr_Occurred()) { + v = PyObject_GetItem(locals, name); + if (v == NULL && PyErr_Occurred()) { if (!PyErr_ExceptionMatches( PyExc_KeyError)) break; PyErr_Clear(); } } - if (x == NULL) { - x = PyDict_GetItem(f->f_globals, w); - if (x == NULL) { - x = PyDict_GetItem(f->f_builtins, w); - if (x == NULL) { - format_exc_check_arg( - PyExc_NameError, - NAME_ERROR_MSG, w); - break; + if (v == NULL) { + v = PyDict_GetItem(f->f_globals, name); + Py_XINCREF(v); + if (v == NULL) { + if (PyDict_CheckExact(f->f_builtins)) { + v = PyDict_GetItem(f->f_builtins, name); + if (v == NULL) { + format_exc_check_arg( + PyExc_NameError, + NAME_ERROR_MSG, name); + goto error; + } + Py_INCREF(v); + } + else { + v = PyObject_GetItem(f->f_builtins, name); + if (v == NULL) { + if (PyErr_ExceptionMatches(PyExc_KeyError)) + format_exc_check_arg( + PyExc_NameError, + NAME_ERROR_MSG, name); + goto error; + } } } - Py_INCREF(x); } - PUSH(x); + PUSH(v); DISPATCH(); + } - TARGET(LOAD_GLOBAL) - w = GETITEM(names, oparg); - if (PyUnicode_CheckExact(w)) { - /* Inline the PyDict_GetItem() calls. - WARNING: this is an extreme speed hack. - Do not try this at home. */ - Py_hash_t hash = ((PyUnicodeObject *)w)->hash; - if (hash != -1) { - PyDictObject *d; - PyDictEntry *e; - d = (PyDictObject *)(f->f_globals); - e = d->ma_lookup(d, w, hash); - if (e == NULL) { - x = NULL; - break; - } - x = e->me_value; - if (x != NULL) { - Py_INCREF(x); - PUSH(x); - DISPATCH(); - } - d = (PyDictObject *)(f->f_builtins); - e = d->ma_lookup(d, w, hash); - if (e == NULL) { - x = NULL; - break; - } - x = e->me_value; - if (x != NULL) { - Py_INCREF(x); - PUSH(x); - DISPATCH(); - } - goto load_global_error; + TARGET(LOAD_GLOBAL) { + PyObject *name = GETITEM(names, oparg); + PyObject *v; + if (PyDict_CheckExact(f->f_globals) + && PyDict_CheckExact(f->f_builtins)) { + v = _PyDict_LoadGlobal((PyDictObject *)f->f_globals, + (PyDictObject *)f->f_builtins, + name); + if (v == NULL) { + if (!PyErr_Occurred()) + format_exc_check_arg(PyExc_NameError, + GLOBAL_NAME_ERROR_MSG, name); + goto error; } + Py_INCREF(v); } - /* This is the un-inlined version of the code above */ - x = PyDict_GetItem(f->f_globals, w); - if (x == NULL) { - x = PyDict_GetItem(f->f_builtins, w); - if (x == NULL) { - load_global_error: - format_exc_check_arg( - PyExc_NameError, - GLOBAL_NAME_ERROR_MSG, w); - break; + else { + /* Slow-path if globals or builtins is not a dict */ + v = PyObject_GetItem(f->f_globals, name); + if (v == NULL) { + v = PyObject_GetItem(f->f_builtins, name); + if (v == NULL) { + if (PyErr_ExceptionMatches(PyExc_KeyError)) + format_exc_check_arg( + PyExc_NameError, + GLOBAL_NAME_ERROR_MSG, name); + goto error; + } } } - Py_INCREF(x); - PUSH(x); + PUSH(v); DISPATCH(); + } - TARGET(DELETE_FAST) - x = GETLOCAL(oparg); - if (x != NULL) { + TARGET(DELETE_FAST) { + PyObject *v = GETLOCAL(oparg); + if (v != NULL) { SETLOCAL(oparg, NULL); DISPATCH(); } @@ -2179,249 +2243,277 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) UNBOUNDLOCAL_ERROR_MSG, PyTuple_GetItem(co->co_varnames, oparg) ); - break; + goto error; + } - TARGET(DELETE_DEREF) - x = freevars[oparg]; - if (PyCell_GET(x) != NULL) { - PyCell_Set(x, NULL); + TARGET(DELETE_DEREF) { + PyObject *cell = freevars[oparg]; + if (PyCell_GET(cell) != NULL) { + PyCell_Set(cell, NULL); DISPATCH(); } - err = -1; format_exc_unbound(co, oparg); - break; + goto error; + } - TARGET(LOAD_CLOSURE) - x = freevars[oparg]; - Py_INCREF(x); - PUSH(x); - if (x != NULL) DISPATCH(); - break; + TARGET(LOAD_CLOSURE) { + PyObject *cell = freevars[oparg]; + Py_INCREF(cell); + PUSH(cell); + DISPATCH(); + } - TARGET(LOAD_DEREF) - x = freevars[oparg]; - w = PyCell_Get(x); - if (w != NULL) { - PUSH(w); - DISPATCH(); + TARGET(LOAD_DEREF) { + PyObject *cell = freevars[oparg]; + PyObject *value = PyCell_GET(cell); + if (value == NULL) { + format_exc_unbound(co, oparg); + goto error; } - err = -1; - format_exc_unbound(co, oparg); - break; + Py_INCREF(value); + PUSH(value); + DISPATCH(); + } - TARGET(STORE_DEREF) - w = POP(); - x = freevars[oparg]; - PyCell_Set(x, w); - Py_DECREF(w); + TARGET(STORE_DEREF) { + PyObject *v = POP(); + PyObject *cell = freevars[oparg]; + PyCell_Set(cell, v); + Py_DECREF(v); DISPATCH(); + } - TARGET(BUILD_TUPLE) - x = PyTuple_New(oparg); - if (x != NULL) { - for (; --oparg >= 0;) { - w = POP(); - PyTuple_SET_ITEM(x, oparg, w); - } - PUSH(x); - DISPATCH(); + TARGET(BUILD_TUPLE) { + PyObject *tup = PyTuple_New(oparg); + if (tup == NULL) + goto error; + while (--oparg >= 0) { + PyObject *item = POP(); + PyTuple_SET_ITEM(tup, oparg, item); } - break; + PUSH(tup); + DISPATCH(); + } - TARGET(BUILD_LIST) - x = PyList_New(oparg); - if (x != NULL) { - for (; --oparg >= 0;) { - w = POP(); - PyList_SET_ITEM(x, oparg, w); - } - PUSH(x); - DISPATCH(); + TARGET(BUILD_LIST) { + PyObject *list = PyList_New(oparg); + if (list == NULL) + goto error; + while (--oparg >= 0) { + PyObject *item = POP(); + PyList_SET_ITEM(list, oparg, item); } - break; + PUSH(list); + DISPATCH(); + } - TARGET(BUILD_SET) - x = PySet_New(NULL); - if (x != NULL) { - for (; --oparg >= 0;) { - w = POP(); - if (err == 0) - err = PySet_Add(x, w); - Py_DECREF(w); - } - if (err != 0) { - Py_DECREF(x); - break; - } - PUSH(x); - DISPATCH(); + TARGET(BUILD_SET) { + PyObject *set = PySet_New(NULL); + int err = 0; + if (set == NULL) + goto error; + while (--oparg >= 0) { + PyObject *item = POP(); + if (err == 0) + err = PySet_Add(set, item); + Py_DECREF(item); } - break; + if (err != 0) { + Py_DECREF(set); + goto error; + } + PUSH(set); + DISPATCH(); + } - TARGET(BUILD_MAP) - x = _PyDict_NewPresized((Py_ssize_t)oparg); - PUSH(x); - if (x != NULL) DISPATCH(); - break; + TARGET(BUILD_MAP) { + PyObject *map = _PyDict_NewPresized((Py_ssize_t)oparg); + if (map == NULL) + goto error; + PUSH(map); + DISPATCH(); + } - TARGET(STORE_MAP) - w = TOP(); /* key */ - u = SECOND(); /* value */ - v = THIRD(); /* dict */ + TARGET(STORE_MAP) { + PyObject *key = TOP(); + PyObject *value = SECOND(); + PyObject *map = THIRD(); + int err; STACKADJ(-2); - assert (PyDict_CheckExact(v)); - err = PyDict_SetItem(v, w, u); /* v[w] = u */ - Py_DECREF(u); - Py_DECREF(w); - if (err == 0) DISPATCH(); - break; + assert(PyDict_CheckExact(map)); + err = PyDict_SetItem(map, key, value); + Py_DECREF(value); + Py_DECREF(key); + if (err != 0) + goto error; + DISPATCH(); + } - TARGET(MAP_ADD) - w = TOP(); /* key */ - u = SECOND(); /* value */ + TARGET(MAP_ADD) { + PyObject *key = TOP(); + PyObject *value = SECOND(); + PyObject *map; + int err; STACKADJ(-2); - v = stack_pointer[-oparg]; /* dict */ - assert (PyDict_CheckExact(v)); - err = PyDict_SetItem(v, w, u); /* v[w] = u */ - Py_DECREF(u); - Py_DECREF(w); - if (err == 0) { - PREDICT(JUMP_ABSOLUTE); - DISPATCH(); - } - break; + map = stack_pointer[-oparg]; /* dict */ + assert(PyDict_CheckExact(map)); + err = PyDict_SetItem(map, key, value); /* v[w] = u */ + Py_DECREF(value); + Py_DECREF(key); + if (err != 0) + goto error; + PREDICT(JUMP_ABSOLUTE); + DISPATCH(); + } - TARGET(LOAD_ATTR) - w = GETITEM(names, oparg); - v = TOP(); - x = PyObject_GetAttr(v, w); - Py_DECREF(v); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + TARGET(LOAD_ATTR) { + PyObject *name = GETITEM(names, oparg); + PyObject *owner = TOP(); + PyObject *res = PyObject_GetAttr(owner, name); + Py_DECREF(owner); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); + } - TARGET(COMPARE_OP) - w = POP(); - v = TOP(); - x = cmp_outcome(oparg, v, w); - Py_DECREF(v); - Py_DECREF(w); - SET_TOP(x); - if (x == NULL) break; + TARGET(COMPARE_OP) { + PyObject *right = POP(); + PyObject *left = TOP(); + PyObject *res = cmp_outcome(oparg, left, right); + Py_DECREF(left); + Py_DECREF(right); + SET_TOP(res); + if (res == NULL) + goto error; PREDICT(POP_JUMP_IF_FALSE); PREDICT(POP_JUMP_IF_TRUE); DISPATCH(); + } - TARGET(IMPORT_NAME) - w = GETITEM(names, oparg); - x = PyDict_GetItemString(f->f_builtins, "__import__"); - if (x == NULL) { + TARGET(IMPORT_NAME) { + _Py_IDENTIFIER(__import__); + PyObject *name = GETITEM(names, oparg); + PyObject *func = _PyDict_GetItemId(f->f_builtins, &PyId___import__); + PyObject *from, *level, *args, *res; + if (func == NULL) { PyErr_SetString(PyExc_ImportError, "__import__ not found"); - break; + goto error; } - Py_INCREF(x); - v = POP(); - u = TOP(); - if (PyLong_AsLong(u) != -1 || PyErr_Occurred()) - w = PyTuple_Pack(5, - w, + Py_INCREF(func); + from = POP(); + level = TOP(); + if (PyLong_AsLong(level) != -1 || PyErr_Occurred()) + args = PyTuple_Pack(5, + name, f->f_globals, f->f_locals == NULL ? Py_None : f->f_locals, - v, - u); + from, + level); else - w = PyTuple_Pack(4, - w, + args = PyTuple_Pack(4, + name, f->f_globals, f->f_locals == NULL ? Py_None : f->f_locals, - v); - Py_DECREF(v); - Py_DECREF(u); - if (w == NULL) { - u = POP(); - Py_DECREF(x); - x = NULL; - break; + from); + Py_DECREF(level); + Py_DECREF(from); + if (args == NULL) { + Py_DECREF(func); + STACKADJ(-1); + goto error; } READ_TIMESTAMP(intr0); - v = x; - x = PyEval_CallObject(v, w); - Py_DECREF(v); + res = PyEval_CallObject(func, args); READ_TIMESTAMP(intr1); - Py_DECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + Py_DECREF(args); + Py_DECREF(func); + SET_TOP(res); + if (res == NULL) + goto error; + DISPATCH(); + } - TARGET(IMPORT_STAR) - v = POP(); + TARGET(IMPORT_STAR) { + PyObject *from = POP(), *locals; + int err; PyFrame_FastToLocals(f); - if ((x = f->f_locals) == NULL) { + locals = f->f_locals; + if (locals == NULL) { PyErr_SetString(PyExc_SystemError, "no locals found during 'import *'"); - break; + goto error; } READ_TIMESTAMP(intr0); - err = import_all_from(x, v); + err = import_all_from(locals, from); READ_TIMESTAMP(intr1); PyFrame_LocalsToFast(f, 0); - Py_DECREF(v); - if (err == 0) DISPATCH(); - break; + Py_DECREF(from); + if (err != 0) + goto error; + DISPATCH(); + } - TARGET(IMPORT_FROM) - w = GETITEM(names, oparg); - v = TOP(); + TARGET(IMPORT_FROM) { + PyObject *name = GETITEM(names, oparg); + PyObject *from = TOP(); + PyObject *res; READ_TIMESTAMP(intr0); - x = import_from(v, w); + res = import_from(from, name); READ_TIMESTAMP(intr1); - PUSH(x); - if (x != NULL) DISPATCH(); - break; + PUSH(res); + if (res == NULL) + goto error; + DISPATCH(); + } - TARGET(JUMP_FORWARD) + TARGET(JUMP_FORWARD) { JUMPBY(oparg); FAST_DISPATCH(); + } PREDICTED_WITH_ARG(POP_JUMP_IF_FALSE); - TARGET(POP_JUMP_IF_FALSE) - w = POP(); - if (w == Py_True) { - Py_DECREF(w); + TARGET(POP_JUMP_IF_FALSE) { + PyObject *cond = POP(); + int err; + if (cond == Py_True) { + Py_DECREF(cond); FAST_DISPATCH(); } - if (w == Py_False) { - Py_DECREF(w); + if (cond == Py_False) { + Py_DECREF(cond); JUMPTO(oparg); FAST_DISPATCH(); } - err = PyObject_IsTrue(w); - Py_DECREF(w); + err = PyObject_IsTrue(cond); + Py_DECREF(cond); if (err > 0) err = 0; else if (err == 0) JUMPTO(oparg); else - break; + goto error; DISPATCH(); + } PREDICTED_WITH_ARG(POP_JUMP_IF_TRUE); - TARGET(POP_JUMP_IF_TRUE) - w = POP(); - if (w == Py_False) { - Py_DECREF(w); + TARGET(POP_JUMP_IF_TRUE) { + PyObject *cond = POP(); + int err; + if (cond == Py_False) { + Py_DECREF(cond); FAST_DISPATCH(); } - if (w == Py_True) { - Py_DECREF(w); + if (cond == Py_True) { + Py_DECREF(cond); JUMPTO(oparg); FAST_DISPATCH(); } - err = PyObject_IsTrue(w); - Py_DECREF(w); + err = PyObject_IsTrue(cond); + Py_DECREF(cond); if (err > 0) { err = 0; JUMPTO(oparg); @@ -2429,58 +2521,63 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) else if (err == 0) ; else - break; + goto error; DISPATCH(); + } - TARGET(JUMP_IF_FALSE_OR_POP) - w = TOP(); - if (w == Py_True) { + TARGET(JUMP_IF_FALSE_OR_POP) { + PyObject *cond = TOP(); + int err; + if (cond == Py_True) { STACKADJ(-1); - Py_DECREF(w); + Py_DECREF(cond); FAST_DISPATCH(); } - if (w == Py_False) { + if (cond == Py_False) { JUMPTO(oparg); FAST_DISPATCH(); } - err = PyObject_IsTrue(w); + err = PyObject_IsTrue(cond); if (err > 0) { STACKADJ(-1); - Py_DECREF(w); + Py_DECREF(cond); err = 0; } else if (err == 0) JUMPTO(oparg); else - break; + goto error; DISPATCH(); + } - TARGET(JUMP_IF_TRUE_OR_POP) - w = TOP(); - if (w == Py_False) { + TARGET(JUMP_IF_TRUE_OR_POP) { + PyObject *cond = TOP(); + int err; + if (cond == Py_False) { STACKADJ(-1); - Py_DECREF(w); + Py_DECREF(cond); FAST_DISPATCH(); } - if (w == Py_True) { + if (cond == Py_True) { JUMPTO(oparg); FAST_DISPATCH(); } - err = PyObject_IsTrue(w); + err = PyObject_IsTrue(cond); if (err > 0) { err = 0; JUMPTO(oparg); } else if (err == 0) { STACKADJ(-1); - Py_DECREF(w); + Py_DECREF(cond); } else - break; + goto error; DISPATCH(); + } PREDICTED_WITH_ARG(JUMP_ABSOLUTE); - TARGET(JUMP_ABSOLUTE) + TARGET(JUMP_ABSOLUTE) { JUMPTO(oparg); #if FAST_LOOPS /* Enabling this path speeds-up all while and for-loops by bypassing @@ -2494,60 +2591,60 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) #else DISPATCH(); #endif + } - TARGET(GET_ITER) + TARGET(GET_ITER) { /* before: [obj]; after [getiter(obj)] */ - v = TOP(); - x = PyObject_GetIter(v); - Py_DECREF(v); - if (x != NULL) { - SET_TOP(x); - PREDICT(FOR_ITER); - DISPATCH(); - } - STACKADJ(-1); - break; + PyObject *iterable = TOP(); + PyObject *iter = PyObject_GetIter(iterable); + Py_DECREF(iterable); + SET_TOP(iter); + if (iter == NULL) + goto error; + PREDICT(FOR_ITER); + DISPATCH(); + } PREDICTED_WITH_ARG(FOR_ITER); - TARGET(FOR_ITER) + TARGET(FOR_ITER) { /* before: [iter]; after: [iter, iter()] *or* [] */ - v = TOP(); - x = (*v->ob_type->tp_iternext)(v); - if (x != NULL) { - PUSH(x); + PyObject *iter = TOP(); + PyObject *next = (*iter->ob_type->tp_iternext)(iter); + if (next != NULL) { + PUSH(next); PREDICT(STORE_FAST); PREDICT(UNPACK_SEQUENCE); DISPATCH(); } if (PyErr_Occurred()) { - if (!PyErr_ExceptionMatches( - PyExc_StopIteration)) - break; + if (!PyErr_ExceptionMatches(PyExc_StopIteration)) + goto error; PyErr_Clear(); } /* iterator ended normally */ - x = v = POP(); - Py_DECREF(v); + STACKADJ(-1); + Py_DECREF(iter); JUMPBY(oparg); DISPATCH(); + } - TARGET(BREAK_LOOP) + TARGET(BREAK_LOOP) { why = WHY_BREAK; goto fast_block_end; + } - TARGET(CONTINUE_LOOP) + TARGET(CONTINUE_LOOP) { retval = PyLong_FromLong(oparg); - if (!retval) { - x = NULL; - break; - } + if (retval == NULL) + goto error; why = WHY_CONTINUE; goto fast_block_end; + } TARGET_WITH_IMPL(SETUP_LOOP, _setup_finally) TARGET_WITH_IMPL(SETUP_EXCEPT, _setup_finally) TARGET(SETUP_FINALLY) - _setup_finally: + _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. @@ -2556,36 +2653,35 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) PyFrame_BlockSetup(f, opcode, INSTR_OFFSET() + oparg, STACK_LEVEL()); DISPATCH(); + } - TARGET(SETUP_WITH) - { - static PyObject *exit, *enter; - w = TOP(); - x = special_lookup(w, "__exit__", &exit); - if (!x) - break; - SET_TOP(x); - u = special_lookup(w, "__enter__", &enter); - Py_DECREF(w); - if (!u) { - x = NULL; - break; - } - x = PyObject_CallFunctionObjArgs(u, NULL); - Py_DECREF(u); - if (!x) - break; + TARGET(SETUP_WITH) { + _Py_IDENTIFIER(__exit__); + _Py_IDENTIFIER(__enter__); + PyObject *mgr = TOP(); + PyObject *exit = special_lookup(mgr, &PyId___exit__), *enter; + PyObject *res; + if (exit == NULL) + goto error; + SET_TOP(exit); + enter = special_lookup(mgr, &PyId___enter__); + Py_DECREF(mgr); + if (enter == NULL) + goto error; + res = PyObject_CallFunctionObjArgs(enter, NULL); + Py_DECREF(enter); + if (res == NULL) + goto error; /* 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); + PUSH(res); DISPATCH(); } - TARGET(WITH_CLEANUP) - { + TARGET(WITH_CLEANUP) { /* At the top of the stack are 1-3 values indicating how/why we entered the finally clause: - TOP = None @@ -2612,42 +2708,42 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) */ PyObject *exit_func; - u = TOP(); - if (u == Py_None) { + PyObject *exc = TOP(), *val = Py_None, *tb = Py_None, *res; + int err; + if (exc == Py_None) { (void)POP(); exit_func = TOP(); - SET_TOP(u); - v = w = Py_None; + SET_TOP(exc); } - else if (PyLong_Check(u)) { - (void)POP(); - switch(PyLong_AsLong(u)) { + else if (PyLong_Check(exc)) { + STACKADJ(-1); + switch (PyLong_AsLong(exc)) { case WHY_RETURN: case WHY_CONTINUE: /* Retval in TOP. */ exit_func = SECOND(); SET_SECOND(TOP()); - SET_TOP(u); + SET_TOP(exc); break; default: exit_func = TOP(); - SET_TOP(u); + SET_TOP(exc); break; } - u = v = w = Py_None; + exc = Py_None; } else { - PyObject *tp, *exc, *tb; + PyObject *tp2, *exc2, *tb2; PyTryBlock *block; - v = SECOND(); - w = THIRD(); - tp = FOURTH(); - exc = PEEK(5); - tb = PEEK(6); + val = SECOND(); + tb = THIRD(); + tp2 = FOURTH(); + exc2 = PEEK(5); + tb2 = PEEK(6); exit_func = PEEK(7); - SET_VALUE(7, tb); - SET_VALUE(6, exc); - SET_VALUE(5, tp); + SET_VALUE(7, tb2); + SET_VALUE(6, exc2); + SET_VALUE(5, tp2); /* UNWIND_EXCEPT_HANDLER will pop this off. */ SET_FOURTH(NULL); /* We just shifted the stack down, so we have @@ -2658,56 +2754,53 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) block->b_level--; } /* XXX Not the fastest way to call it... */ - x = PyObject_CallFunctionObjArgs(exit_func, u, v, w, - NULL); + res = PyObject_CallFunctionObjArgs(exit_func, exc, val, tb, NULL); Py_DECREF(exit_func); - if (x == NULL) - break; /* Go to error exit */ + if (res == NULL) + goto error; - if (u != Py_None) - err = PyObject_IsTrue(x); + if (exc != Py_None) + err = PyObject_IsTrue(res); else err = 0; - Py_DECREF(x); + Py_DECREF(res); if (err < 0) - break; /* Go to error exit */ + goto error; else if (err > 0) { err = 0; /* There was an exception and a True return */ PUSH(PyLong_FromLong((long) WHY_SILENCED)); } PREDICT(END_FINALLY); - break; + DISPATCH(); } - TARGET(CALL_FUNCTION) - { - PyObject **sp; + TARGET(CALL_FUNCTION) { + PyObject **sp, *res; PCALL(PCALL_ALL); sp = stack_pointer; #ifdef WITH_TSC - x = call_function(&sp, oparg, &intr0, &intr1); + res = call_function(&sp, oparg, &intr0, &intr1); #else - x = call_function(&sp, oparg); + res = call_function(&sp, oparg); #endif stack_pointer = sp; - PUSH(x); - if (x != NULL) - DISPATCH(); - break; + PUSH(res); + if (res == NULL) + goto error; + DISPATCH(); } 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: - { + _call_function_var_kw: { int na = oparg & 0xff; int nk = (oparg>>8) & 0xff; int flags = (opcode - CALL_FUNCTION) & 3; int n = na + 2 * nk; - PyObject **pfunc, *func, **sp; + PyObject **pfunc, *func, **sp, *res; PCALL(PCALL_ALL); if (flags & CALL_FLAG_VAR) n++; @@ -2725,140 +2818,161 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) Py_DECREF(*pfunc); *pfunc = self; na++; - n++; + /* n++; */ } else Py_INCREF(func); sp = stack_pointer; READ_TIMESTAMP(intr0); - x = ext_do_call(func, &sp, flags, na, nk); + res = ext_do_call(func, &sp, flags, na, nk); READ_TIMESTAMP(intr1); stack_pointer = sp; Py_DECREF(func); while (stack_pointer > pfunc) { - w = POP(); - Py_DECREF(w); + PyObject *o = POP(); + Py_DECREF(o); } - PUSH(x); - if (x != NULL) - DISPATCH(); - break; + PUSH(res); + if (res == NULL) + goto error; + DISPATCH(); } TARGET_WITH_IMPL(MAKE_CLOSURE, _make_function) TARGET(MAKE_FUNCTION) - _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); + PyObject *qualname = POP(); /* qualname */ + PyObject *code = POP(); /* code object */ + PyObject *func = PyFunction_NewWithQualName(code, f->f_globals, qualname); + Py_DECREF(code); + Py_DECREF(qualname); - if (x != NULL && opcode == MAKE_CLOSURE) { - v = POP(); - if (PyFunction_SetClosure(x, v) != 0) { + if (func == NULL) + goto error; + + if (opcode == MAKE_CLOSURE) { + PyObject *closure = POP(); + if (PyFunction_SetClosure(func, closure) != 0) { /* Can't happen unless bytecode is corrupt. */ - why = WHY_EXCEPTION; + Py_DECREF(func); + Py_DECREF(closure); + goto error; } - Py_DECREF(v); + Py_DECREF(closure); } - if (x != NULL && num_annotations > 0) { + if (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; + PyObject *names = POP(); /* names of args with annotations */ + PyObject *anns = PyDict_New(); + if (anns == NULL) { + Py_DECREF(func); + goto error; } - name_ix = PyTuple_Size(u); + name_ix = PyTuple_Size(names); assert(num_annotations == name_ix+1); while (name_ix > 0) { + PyObject *name, *value; + int err; --name_ix; - t = PyTuple_GET_ITEM(u, name_ix); - w = POP(); - /* XXX(nnorwitz): check for errors */ - PyDict_SetItem(v, t, w); - Py_DECREF(w); + name = PyTuple_GET_ITEM(names, name_ix); + value = POP(); + err = PyDict_SetItem(anns, name, value); + Py_DECREF(value); + if (err != 0) { + Py_DECREF(anns); + Py_DECREF(func); + goto error; + } } - if (PyFunction_SetAnnotations(x, v) != 0) { + if (PyFunction_SetAnnotations(func, anns) != 0) { /* Can't happen unless PyFunction_SetAnnotations changes. */ - why = WHY_EXCEPTION; + Py_DECREF(anns); + Py_DECREF(func); + goto error; } - Py_DECREF(v); - Py_DECREF(u); + Py_DECREF(anns); + Py_DECREF(names); } /* 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; + if (posdefaults > 0) { + PyObject *defs = PyTuple_New(posdefaults); + if (defs == NULL) { + Py_DECREF(func); + goto error; } - while (--posdefaults >= 0) { - w = POP(); - PyTuple_SET_ITEM(v, posdefaults, w); - } - if (PyFunction_SetDefaults(x, v) != 0) { + while (--posdefaults >= 0) + PyTuple_SET_ITEM(defs, posdefaults, POP()); + if (PyFunction_SetDefaults(func, defs) != 0) { /* Can't happen unless PyFunction_SetDefaults changes. */ - why = WHY_EXCEPTION; + Py_DECREF(defs); + Py_DECREF(func); + goto error; } - Py_DECREF(v); + Py_DECREF(defs); } - if (x != NULL && kwdefaults > 0) { - v = PyDict_New(); - if (v == NULL) { - Py_DECREF(x); - x = NULL; - break; + if (kwdefaults > 0) { + PyObject *defs = PyDict_New(); + if (defs == NULL) { + Py_DECREF(func); + goto error; } 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); + PyObject *v = POP(); /* default value */ + PyObject *key = POP(); /* kw only arg name */ + int err = PyDict_SetItem(defs, key, v); + Py_DECREF(v); + Py_DECREF(key); + if (err != 0) { + Py_DECREF(defs); + Py_DECREF(func); + goto error; + } } - if (PyFunction_SetKwDefaults(x, v) != 0) { + if (PyFunction_SetKwDefaults(func, defs) != 0) { /* Can't happen unless PyFunction_SetKwDefaults changes. */ - why = WHY_EXCEPTION; + Py_DECREF(func); + Py_DECREF(defs); + goto error; } - Py_DECREF(v); + Py_DECREF(defs); } - PUSH(x); - break; + PUSH(func); + DISPATCH(); } - TARGET(BUILD_SLICE) + TARGET(BUILD_SLICE) { + PyObject *start, *stop, *step, *slice; if (oparg == 3) - w = POP(); + step = POP(); else - w = NULL; - v = POP(); - u = TOP(); - x = PySlice_New(u, v, w); - Py_DECREF(u); - Py_DECREF(v); - Py_XDECREF(w); - SET_TOP(x); - if (x != NULL) DISPATCH(); - break; + step = NULL; + stop = POP(); + start = TOP(); + slice = PySlice_New(start, stop, step); + Py_DECREF(start); + Py_DECREF(stop); + Py_XDECREF(step); + SET_TOP(slice); + if (slice == NULL) + goto error; + DISPATCH(); + } - TARGET(EXTENDED_ARG) + TARGET(EXTENDED_ARG) { opcode = NEXTOP(); oparg = oparg<<16 | NEXTARG(); goto dispatch_opcode; + } #if USE_COMPUTED_GOTOS _unknown_opcode: @@ -2869,8 +2983,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) PyFrame_GetLineNumber(f), opcode); PyErr_SetString(PyExc_SystemError, "unknown opcode"); - why = WHY_EXCEPTION; - break; + goto error; #ifdef CASE_TOO_BIG } @@ -2878,71 +2991,31 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) } /* switch */ - on_error: + /* This should never be reached. Every opcode should end with DISPATCH() + or goto error. */ + assert(0); +error: READ_TIMESTAMP(inst1); - /* Quickly continue if no error occurred */ - - if (why == WHY_NOT) { - if (err == 0 && x != NULL) { -#ifdef CHECKEXC - /* This check is expensive! */ - if (PyErr_Occurred()) - fprintf(stderr, - "XXX undetected error\n"); - else { -#endif - READ_TIMESTAMP(loop1); - continue; /* Normal, fast path */ -#ifdef CHECKEXC - } -#endif - } - why = WHY_EXCEPTION; - x = Py_None; - err = 0; - } - - /* Double-check exception status */ - - if (why == WHY_EXCEPTION || why == WHY_RERAISE) { - if (!PyErr_Occurred()) { - PyErr_SetString(PyExc_SystemError, - "error return without exception set"); - why = WHY_EXCEPTION; - } - } -#ifdef CHECKEXC - else { - /* This check is expensive! */ - if (PyErr_Occurred()) { - char buf[128]; - sprintf(buf, "Stack unwind with exception " - "set and why=%d", why); - Py_FatalError(buf); - } - } -#endif - - /* Log traceback info if this is a real exception */ + assert(why == WHY_NOT); + why = WHY_EXCEPTION; - if (why == WHY_EXCEPTION) { - PyTraceBack_Here(f); + /* Double-check exception status. */ + if (!PyErr_Occurred()) + PyErr_SetString(PyExc_SystemError, + "error return without exception set"); - if (tstate->c_tracefunc != NULL) - call_exc_trace(tstate->c_tracefunc, - tstate->c_traceobj, f); - } + /* Log traceback info. */ + PyTraceBack_Here(f); - /* For the rest, treat WHY_RERAISE as WHY_EXCEPTION */ + if (tstate->c_tracefunc != NULL) + call_exc_trace(tstate->c_tracefunc, tstate->c_traceobj, f); - if (why == WHY_RERAISE) - why = WHY_EXCEPTION; +fast_block_end: + assert(why != WHY_NOT); /* Unwind stacks if a (pseudo) exception occurred */ - -fast_block_end: while (why != WHY_NOT && f->f_iblock > 0) { /* Peek at the current block. */ PyTryBlock *b = &f->f_blockstack[f->f_iblock - 1]; @@ -3026,8 +3099,8 @@ fast_block_end: assert(why != WHY_YIELD); /* Pop remaining stack entries. */ while (!EMPTY()) { - v = POP(); - Py_XDECREF(v); + PyObject *o = POP(); + Py_XDECREF(o); } if (why != WHY_RETURN) @@ -3049,9 +3122,9 @@ fast_yield: break; if (i == f->f_iblock) /* We did not create this exception. */ - RESTORE_AND_CLEAR_EXC_STATE() + restore_and_clear_exc_state(tstate, f); else - SWAP_EXC_STATE() + swap_exc_state(tstate, f); } if (tstate->use_tracing) { @@ -3081,7 +3154,7 @@ fast_yield: PyTrace_RETURN, retval)) { Py_XDECREF(retval); retval = NULL; - why = WHY_EXCEPTION; + /* why = WHY_EXCEPTION; */ } } } @@ -3094,6 +3167,156 @@ exit_eval_frame: return retval; } +static void +format_missing(const char *kind, PyCodeObject *co, PyObject *names) +{ + int err; + Py_ssize_t len = PyList_GET_SIZE(names); + PyObject *name_str, *comma, *tail, *tmp; + + assert(PyList_CheckExact(names)); + assert(len >= 1); + /* Deal with the joys of natural language. */ + switch (len) { + case 1: + name_str = PyList_GET_ITEM(names, 0); + Py_INCREF(name_str); + break; + case 2: + name_str = PyUnicode_FromFormat("%U and %U", + PyList_GET_ITEM(names, len - 2), + PyList_GET_ITEM(names, len - 1)); + break; + default: + tail = PyUnicode_FromFormat(", %U, and %U", + PyList_GET_ITEM(names, len - 2), + PyList_GET_ITEM(names, len - 1)); + if (tail == NULL) + return; + /* Chop off the last two objects in the list. This shouldn't actually + fail, but we can't be too careful. */ + err = PyList_SetSlice(names, len - 2, len, NULL); + if (err == -1) { + Py_DECREF(tail); + return; + } + /* Stitch everything up into a nice comma-separated list. */ + comma = PyUnicode_FromString(", "); + if (comma == NULL) { + Py_DECREF(tail); + return; + } + tmp = PyUnicode_Join(comma, names); + Py_DECREF(comma); + if (tmp == NULL) { + Py_DECREF(tail); + return; + } + name_str = PyUnicode_Concat(tmp, tail); + Py_DECREF(tmp); + Py_DECREF(tail); + break; + } + if (name_str == NULL) + return; + PyErr_Format(PyExc_TypeError, + "%U() missing %i required %s argument%s: %U", + co->co_name, + len, + kind, + len == 1 ? "" : "s", + name_str); + Py_DECREF(name_str); +} + +static void +missing_arguments(PyCodeObject *co, int missing, int defcount, + PyObject **fastlocals) +{ + int i, j = 0; + int start, end; + int positional = defcount != -1; + const char *kind = positional ? "positional" : "keyword-only"; + PyObject *missing_names; + + /* Compute the names of the arguments that are missing. */ + missing_names = PyList_New(missing); + if (missing_names == NULL) + return; + if (positional) { + start = 0; + end = co->co_argcount - defcount; + } + else { + start = co->co_argcount; + end = start + co->co_kwonlyargcount; + } + for (i = start; i < end; i++) { + if (GETLOCAL(i) == NULL) { + PyObject *raw = PyTuple_GET_ITEM(co->co_varnames, i); + PyObject *name = PyObject_Repr(raw); + if (name == NULL) { + Py_DECREF(missing_names); + return; + } + PyList_SET_ITEM(missing_names, j++, name); + } + } + assert(j == missing); + format_missing(kind, co, missing_names); + Py_DECREF(missing_names); +} + +static void +too_many_positional(PyCodeObject *co, int given, int defcount, PyObject **fastlocals) +{ + int plural; + int kwonly_given = 0; + int i; + PyObject *sig, *kwonly_sig; + + assert((co->co_flags & CO_VARARGS) == 0); + /* Count missing keyword-only args. */ + for (i = co->co_argcount; i < co->co_argcount + co->co_kwonlyargcount; i++) + if (GETLOCAL(i) != NULL) + kwonly_given++; + if (defcount) { + int atleast = co->co_argcount - defcount; + plural = 1; + sig = PyUnicode_FromFormat("from %d to %d", atleast, co->co_argcount); + } + else { + plural = co->co_argcount != 1; + sig = PyUnicode_FromFormat("%d", co->co_argcount); + } + if (sig == NULL) + return; + if (kwonly_given) { + const char *format = " positional argument%s (and %d keyword-only argument%s)"; + kwonly_sig = PyUnicode_FromFormat(format, given != 1 ? "s" : "", kwonly_given, + kwonly_given != 1 ? "s" : ""); + if (kwonly_sig == NULL) { + Py_DECREF(sig); + return; + } + } + else { + /* This will not fail. */ + kwonly_sig = PyUnicode_FromString(""); + assert(kwonly_sig != NULL); + } + PyErr_Format(PyExc_TypeError, + "%U() takes %U positional argument%s but %d%U %s given", + co->co_name, + sig, + plural ? "s" : "", + given, + kwonly_sig, + given == 1 && !kwonly_given ? "was" : "were"); + Py_DECREF(sig); + Py_DECREF(kwonly_sig); +} + /* This is gonna seem *real weird*, but if you put some other code between PyEval_EvalFrame() and PyEval_EvalCodeEx() you will need to adjust the test in the if statements in Misc/gdbinit (pystack and pystackv). */ @@ -3110,6 +3333,9 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals, PyThreadState *tstate = PyThreadState_GET(); PyObject *x, *u; int total_args = co->co_argcount + co->co_kwonlyargcount; + int i; + int n = argcount; + PyObject *kwdict = NULL; if (globals == NULL) { PyErr_SetString(PyExc_SystemError, @@ -3126,212 +3352,153 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals, fastlocals = f->f_localsplus; freevars = f->f_localsplus + co->co_nlocals; - if (total_args || co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) { - int i; - int n = argcount; - PyObject *kwdict = NULL; - if (co->co_flags & CO_VARKEYWORDS) { - kwdict = PyDict_New(); - if (kwdict == NULL) - goto fail; - i = total_args; - if (co->co_flags & CO_VARARGS) - i++; - SETLOCAL(i, kwdict); - } - if (argcount > co->co_argcount) { - if (!(co->co_flags & CO_VARARGS)) { - PyErr_Format(PyExc_TypeError, - "%U() takes %s %d " - "positional argument%s (%d given)", - co->co_name, - defcount ? "at most" : "exactly", - co->co_argcount, - co->co_argcount == 1 ? "" : "s", - argcount + kwcount); - goto fail; - } - n = co->co_argcount; - } - for (i = 0; i < n; i++) { + /* Parse arguments. */ + if (co->co_flags & CO_VARKEYWORDS) { + kwdict = PyDict_New(); + if (kwdict == NULL) + goto fail; + i = total_args; + if (co->co_flags & CO_VARARGS) + i++; + SETLOCAL(i, kwdict); + } + if (argcount > co->co_argcount) + n = co->co_argcount; + for (i = 0; i < n; i++) { + x = args[i]; + Py_INCREF(x); + SETLOCAL(i, x); + } + if (co->co_flags & CO_VARARGS) { + u = PyTuple_New(argcount - n); + if (u == NULL) + goto fail; + SETLOCAL(total_args, u); + for (i = n; i < argcount; i++) { x = args[i]; Py_INCREF(x); - SETLOCAL(i, x); + PyTuple_SET_ITEM(u, i-n, x); } - if (co->co_flags & CO_VARARGS) { - u = PyTuple_New(argcount - n); - if (u == NULL) - goto fail; - SETLOCAL(total_args, u); - for (i = n; i < argcount; i++) { - x = args[i]; - Py_INCREF(x); - PyTuple_SET_ITEM(u, i-n, x); - } + } + for (i = 0; i < kwcount; i++) { + PyObject **co_varnames; + PyObject *keyword = kws[2*i]; + PyObject *value = kws[2*i + 1]; + int j; + if (keyword == NULL || !PyUnicode_Check(keyword)) { + PyErr_Format(PyExc_TypeError, + "%U() keywords must be strings", + co->co_name); + goto fail; } - for (i = 0; i < kwcount; i++) { - PyObject **co_varnames; - PyObject *keyword = kws[2*i]; - PyObject *value = kws[2*i + 1]; - int j; - if (keyword == NULL || !PyUnicode_Check(keyword)) { - PyErr_Format(PyExc_TypeError, - "%U() keywords must be strings", - co->co_name); - goto fail; - } - /* Speed hack: do raw pointer compares. As names are - normally interned this should almost always hit. */ - co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item; - for (j = 0; j < total_args; j++) { - PyObject *nm = co_varnames[j]; - if (nm == keyword) - goto kw_found; - } - /* Slow fallback, just in case */ - for (j = 0; j < total_args; j++) { - PyObject *nm = co_varnames[j]; - int cmp = PyObject_RichCompareBool( - keyword, nm, Py_EQ); - if (cmp > 0) - goto kw_found; - else if (cmp < 0) - goto fail; - } - if (j >= total_args && kwdict == NULL) { - PyErr_Format(PyExc_TypeError, - "%U() got an unexpected " - "keyword argument '%S'", - co->co_name, - keyword); + /* Speed hack: do raw pointer compares. As names are + normally interned this should almost always hit. */ + co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item; + for (j = 0; j < total_args; j++) { + PyObject *nm = co_varnames[j]; + if (nm == keyword) + goto kw_found; + } + /* Slow fallback, just in case */ + for (j = 0; j < total_args; j++) { + PyObject *nm = co_varnames[j]; + int cmp = PyObject_RichCompareBool( + keyword, nm, Py_EQ); + if (cmp > 0) + goto kw_found; + else if (cmp < 0) goto fail; - } - PyDict_SetItem(kwdict, keyword, value); - continue; - kw_found: - if (GETLOCAL(j) != NULL) { - PyErr_Format(PyExc_TypeError, + } + if (j >= total_args && kwdict == NULL) { + PyErr_Format(PyExc_TypeError, + "%U() got an unexpected " + "keyword argument '%S'", + co->co_name, + keyword); + goto fail; + } + PyDict_SetItem(kwdict, keyword, value); + continue; + kw_found: + if (GETLOCAL(j) != NULL) { + PyErr_Format(PyExc_TypeError, "%U() got multiple " - "values for keyword " - "argument '%S'", + "values for argument '%S'", co->co_name, keyword); - goto fail; - } - Py_INCREF(value); - SETLOCAL(j, value); + goto fail; } - 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; - } + Py_INCREF(value); + SETLOCAL(j, value); + } + if (argcount > co->co_argcount && !(co->co_flags & CO_VARARGS)) { + too_many_positional(co, argcount, defcount, fastlocals); + goto fail; + } + if (argcount < co->co_argcount) { + int m = co->co_argcount - defcount; + int missing = 0; + for (i = argcount; i < m; i++) + if (GETLOCAL(i) == NULL) + missing++; + if (missing) { + missing_arguments(co, missing, defcount, fastlocals); + goto fail; } - if (argcount < co->co_argcount) { - int m = co->co_argcount - defcount; - for (i = argcount; i < m; i++) { - if (GETLOCAL(i) == NULL) { - int j, given = 0; - for (j = 0; j < co->co_argcount; j++) - if (GETLOCAL(j)) - given++; - PyErr_Format(PyExc_TypeError, - "%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); - goto fail; - } + if (n > m) + i = n - m; + else + i = 0; + for (; i < defcount; i++) { + if (GETLOCAL(m+i) == NULL) { + PyObject *def = defs[i]; + Py_INCREF(def); + SETLOCAL(m+i, def); } - if (n > m) - i = n - m; - else - i = 0; - for (; i < defcount; i++) { - if (GETLOCAL(m+i) == NULL) { - PyObject *def = defs[i]; + } + } + if (co->co_kwonlyargcount > 0) { + int missing = 0; + for (i = co->co_argcount; i < total_args; i++) { + PyObject *name; + if (GETLOCAL(i) != NULL) + continue; + name = PyTuple_GET_ITEM(co->co_varnames, i); + if (kwdefs != NULL) { + PyObject *def = PyDict_GetItem(kwdefs, name); + if (def) { Py_INCREF(def); - SETLOCAL(m+i, def); + SETLOCAL(i, def); + continue; } } + missing++; + } + if (missing) { + missing_arguments(co, missing, -1, fastlocals); + goto fail; } } - else if (argcount > 0 || kwcount > 0) { - PyErr_Format(PyExc_TypeError, - "%U() takes no arguments (%d given)", - co->co_name, - argcount + kwcount); - goto fail; - } + /* Allocate and initialize storage for cell vars, and copy free - vars into frame. This isn't too efficient right now. */ - if (PyTuple_GET_SIZE(co->co_cellvars)) { - int i, j, nargs, found; - Py_UNICODE *cellname, *argname; + vars into frame. */ + for (i = 0; i < PyTuple_GET_SIZE(co->co_cellvars); ++i) { PyObject *c; - - nargs = total_args; - if (co->co_flags & CO_VARARGS) - nargs++; - if (co->co_flags & CO_VARKEYWORDS) - nargs++; - - /* Initialize each cell var, taking into account - cell vars that are initialized from arguments. - - Should arrange for the compiler to put cellvars - that are arguments at the beginning of the cellvars - list so that we can march over it more efficiently? - */ - for (i = 0; i < PyTuple_GET_SIZE(co->co_cellvars); ++i) { - cellname = PyUnicode_AS_UNICODE( - PyTuple_GET_ITEM(co->co_cellvars, i)); - found = 0; - for (j = 0; j < nargs; j++) { - argname = PyUnicode_AS_UNICODE( - PyTuple_GET_ITEM(co->co_varnames, j)); - if (Py_UNICODE_strcmp(cellname, argname) == 0) { - c = PyCell_New(GETLOCAL(j)); - if (c == NULL) - goto fail; - GETLOCAL(co->co_nlocals + i) = c; - found = 1; - break; - } - } - if (found == 0) { - c = PyCell_New(NULL); - if (c == NULL) - goto fail; - SETLOCAL(co->co_nlocals + i, c); - } - } + int arg; + /* Possibly account for the cell variable being an argument. */ + if (co->co_cell2arg != NULL && + (arg = co->co_cell2arg[i]) != CO_CELL_NOT_AN_ARG) + c = PyCell_New(GETLOCAL(arg)); + else + c = PyCell_New(NULL); + if (c == NULL) + goto fail; + SETLOCAL(co->co_nlocals + i, c); } - if (PyTuple_GET_SIZE(co->co_freevars)) { - int i; - for (i = 0; i < PyTuple_GET_SIZE(co->co_freevars); ++i) { - PyObject *o = PyTuple_GET_ITEM(closure, i); - Py_INCREF(o); - freevars[PyTuple_GET_SIZE(co->co_cellvars) + i] = o; - } + for (i = 0; i < PyTuple_GET_SIZE(co->co_freevars); ++i) { + PyObject *o = PyTuple_GET_ITEM(closure, i); + Py_INCREF(o); + freevars[PyTuple_GET_SIZE(co->co_cellvars) + i] = o; } if (co->co_flags & CO_GENERATOR) { @@ -3365,21 +3532,75 @@ fail: /* Jump here from prelude on failure */ static PyObject * -special_lookup(PyObject *o, char *meth, PyObject **cache) +special_lookup(PyObject *o, _Py_Identifier *id) { PyObject *res; - res = _PyObject_LookupSpecial(o, meth, cache); + res = _PyObject_LookupSpecial(o, id); if (res == NULL && !PyErr_Occurred()) { - PyErr_SetObject(PyExc_AttributeError, *cache); + PyErr_SetObject(PyExc_AttributeError, id->object); return NULL; } return res; } +/* These 3 functions deal with the exception state of generators. */ + +static void +save_exc_state(PyThreadState *tstate, PyFrameObject *f) +{ + PyObject *type, *value, *traceback; + Py_XINCREF(tstate->exc_type); + Py_XINCREF(tstate->exc_value); + Py_XINCREF(tstate->exc_traceback); + type = f->f_exc_type; + value = f->f_exc_value; + traceback = f->f_exc_traceback; + f->f_exc_type = tstate->exc_type; + f->f_exc_value = tstate->exc_value; + f->f_exc_traceback = tstate->exc_traceback; + Py_XDECREF(type); + Py_XDECREF(value); + Py_XDECREF(traceback); +} + +static void +swap_exc_state(PyThreadState *tstate, PyFrameObject *f) +{ + PyObject *tmp; + tmp = tstate->exc_type; + tstate->exc_type = f->f_exc_type; + f->f_exc_type = tmp; + tmp = tstate->exc_value; + tstate->exc_value = f->f_exc_value; + f->f_exc_value = tmp; + tmp = tstate->exc_traceback; + tstate->exc_traceback = f->f_exc_traceback; + f->f_exc_traceback = tmp; +} + +static void +restore_and_clear_exc_state(PyThreadState *tstate, PyFrameObject *f) +{ + PyObject *type, *value, *tb; + type = tstate->exc_type; + value = tstate->exc_value; + tb = tstate->exc_traceback; + tstate->exc_type = f->f_exc_type; + tstate->exc_value = f->f_exc_value; + tstate->exc_traceback = f->f_exc_traceback; + f->f_exc_type = NULL; + f->f_exc_value = NULL; + f->f_exc_traceback = NULL; + Py_XDECREF(type); + Py_XDECREF(value); + Py_XDECREF(tb); +} + + /* Logic for the raise statement (too complicated for inlining). This *consumes* a reference count to each of its arguments. */ -static enum why_code +static int do_raise(PyObject *exc, PyObject *cause) { PyObject *type = NULL, *value = NULL; @@ -3394,13 +3615,13 @@ do_raise(PyObject *exc, PyObject *cause) if (type == Py_None) { PyErr_SetString(PyExc_RuntimeError, "No active exception to reraise"); - return WHY_EXCEPTION; - } + return 0; + } Py_XINCREF(type); Py_XINCREF(value); Py_XINCREF(tb); PyErr_Restore(type, value, tb); - return WHY_RERAISE; + return 1; } /* We support the following forms of raise: @@ -3446,6 +3667,10 @@ do_raise(PyObject *exc, PyObject *cause) else if (PyExceptionInstance_Check(cause)) { fixed_cause = cause; } + else if (cause == Py_None) { + Py_DECREF(cause); + fixed_cause = NULL; + } else { PyErr_SetString(PyExc_TypeError, "exception causes must derive from " @@ -3459,13 +3684,13 @@ do_raise(PyObject *exc, PyObject *cause) /* PyErr_SetObject incref's its arguments */ Py_XDECREF(value); Py_XDECREF(type); - return WHY_EXCEPTION; + return 0; raise_error: Py_XDECREF(value); Py_XDECREF(type); Py_XDECREF(cause); - return WHY_EXCEPTION; + return 0; } /* Iterate v argcnt times and store the results on the stack (via decreasing @@ -4192,7 +4417,7 @@ ext_do_call(PyObject *func, PyObject ***pp_stack, int flags, int na, int nk) if (PyErr_ExceptionMatches(PyExc_TypeError)) { PyErr_Format(PyExc_TypeError, "%.200s%.200s argument after * " - "must be a sequence, not %200s", + "must be a sequence, not %.200s", PyEval_GetFuncName(func), PyEval_GetFuncDesc(func), stararg->ob_type->tp_name); @@ -4342,7 +4567,9 @@ import_from(PyObject *v, PyObject *name) static int import_all_from(PyObject *locals, PyObject *v) { - PyObject *all = PyObject_GetAttrString(v, "__all__"); + _Py_IDENTIFIER(__all__); + _Py_IDENTIFIER(__dict__); + PyObject *all = _PyObject_GetAttrId(v, &PyId___all__); PyObject *dict, *name, *value; int skip_leading_underscores = 0; int pos, err; @@ -4351,7 +4578,7 @@ import_all_from(PyObject *locals, PyObject *v) if (!PyErr_ExceptionMatches(PyExc_AttributeError)) return -1; /* Unexpected error */ PyErr_Clear(); - dict = PyObject_GetAttrString(v, "__dict__"); + dict = _PyObject_GetAttrId(v, &PyId___dict__); if (dict == NULL) { if (!PyErr_ExceptionMatches(PyExc_AttributeError)) return -1; @@ -4377,7 +4604,8 @@ import_all_from(PyObject *locals, PyObject *v) } if (skip_leading_underscores && PyUnicode_Check(name) && - PyUnicode_AS_UNICODE(name)[0] == '_') + PyUnicode_READY(name) != -1 && + PyUnicode_READ_CHAR(name, 0) == '_') { Py_DECREF(name); continue; @@ -4437,19 +4665,9 @@ format_exc_unbound(PyCodeObject *co, int oparg) static PyObject * unicode_concatenate(PyObject *v, PyObject *w, - PyFrameObject *f, unsigned char *next_instr) + PyFrameObject *f, unsigned char *next_instr) { - /* This function implements 'variable += expr' when both arguments - 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, - "strings are too large to concat"); - return NULL; - } - + PyObject *res; if (Py_REFCNT(v) == 2) { /* In the common case, there are 2 references to the value * stored in 'variable' when the += is performed: one on the @@ -4490,31 +4708,9 @@ unicode_concatenate(PyObject *v, PyObject *w, } } } - - 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 (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 - * remotely) be a cause of incompatibilities. - */ - return NULL; - } - /* copy 'w' into the newly allocated area of 'v' */ - 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. */ - w = PyUnicode_Concat(v, w); - Py_DECREF(v); - return w; - } + res = v; + PyUnicode_Append(&res, w); + return res; } #ifdef DYNAMIC_EXECUTION_PROFILE |