summaryrefslogtreecommitdiff
path: root/Python/ceval.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c886
1 files changed, 501 insertions, 385 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index f0ea7c90dc..2b1619163b 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;
}
@@ -749,6 +750,9 @@ enum why_code {
WHY_SILENCED = 0x0080 /* Exception silenced by 'with' */
};
+static void save_exc_state(PyThreadState *, PyFrameObject *);
+static void swap_exc_state(PyThreadState *, PyFrameObject *);
+static void restore_and_clear_exc_state(PyThreadState *, PyFrameObject *);
static enum why_code do_raise(PyObject *, PyObject *);
static int unpack_iterable(PyObject *, int, int, PyObject **);
@@ -817,9 +821,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 +1118,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 +1174,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,27 +1195,14 @@ 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;
@@ -1412,8 +1354,6 @@ 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();
@@ -1894,6 +1834,40 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
why = WHY_RETURN;
goto fast_block_end;
+ TARGET(YIELD_FROM)
+ u = POP();
+ x = TOP();
+ /* send u to x */
+ if (PyGen_CheckExact(x)) {
+ retval = _PyGen_Send((PyGenObject *)x, u);
+ } else {
+ _Py_IDENTIFIER(send);
+ if (u == Py_None)
+ retval = Py_TYPE(x)->tp_iternext(x);
+ else
+ retval = _PyObject_CallMethodId(x, &PyId_send, "O", u);
+ }
+ Py_DECREF(u);
+ if (!retval) {
+ PyObject *val;
+ x = POP(); /* Remove iter from stack */
+ Py_DECREF(x);
+ err = _PyGen_FetchStopIterationValue(&val);
+ if (err < 0) {
+ x = NULL;
+ break;
+ }
+ x = val;
+ PUSH(x);
+ continue;
+ }
+ /* 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)
retval = POP();
f->f_stacktop = stack_pointer;
@@ -1956,16 +1930,33 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
break;
TARGET(LOAD_BUILD_CLASS)
- x = PyDict_GetItemString(f->f_builtins,
- "__build_class__");
- if (x == NULL) {
- PyErr_SetString(PyExc_ImportError,
- "__build_class__ not found");
- break;
+ {
+ _Py_IDENTIFIER(__build_class__);
+
+ if (PyDict_CheckExact(f->f_builtins)) {
+ x = _PyDict_GetItemId(f->f_builtins, &PyId___build_class__);
+ if (x == NULL) {
+ PyErr_SetString(PyExc_NameError,
+ "__build_class__ not found");
+ break;
+ }
+ Py_INCREF(x);
+ }
+ else {
+ PyObject *build_class_str = _PyUnicode_FromId(&PyId___build_class__);
+ if (build_class_str == NULL)
+ break;
+ x = PyObject_GetItem(f->f_builtins, build_class_str);
+ if (x == NULL) {
+ if (PyErr_ExceptionMatches(PyExc_KeyError))
+ PyErr_SetString(PyExc_NameError,
+ "__build_class__ not found");
+ break;
+ }
}
- Py_INCREF(x);
PUSH(x);
break;
+ }
TARGET(STORE_NAME)
w = GETITEM(names, oparg);
@@ -2092,7 +2083,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
}
else {
x = PyObject_GetItem(v, w);
- if (x == NULL && PyErr_Occurred()) {
+ if (x == NULL && _PyErr_OCCURRED()) {
if (!PyErr_ExceptionMatches(
PyExc_KeyError))
break;
@@ -2101,70 +2092,62 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
}
if (x == NULL) {
x = PyDict_GetItem(f->f_globals, w);
+ Py_XINCREF(x);
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 (PyDict_CheckExact(f->f_builtins)) {
+ x = PyDict_GetItem(f->f_builtins, w);
+ if (x == NULL) {
+ format_exc_check_arg(
+ PyExc_NameError,
+ NAME_ERROR_MSG, w);
+ break;
+ }
+ Py_INCREF(x);
+ }
+ else {
+ x = PyObject_GetItem(f->f_builtins, w);
+ if (x == NULL) {
+ if (PyErr_ExceptionMatches(PyExc_KeyError))
+ format_exc_check_arg(
+ PyExc_NameError,
+ NAME_ERROR_MSG, w);
+ break;
+ }
}
}
- Py_INCREF(x);
}
PUSH(x);
DISPATCH();
TARGET(LOAD_GLOBAL)
w = GETITEM(names, oparg);
- if (PyUnicode_CheckExact(w)) {
- /* Inline the PyDict_GetItem() calls.
- WARNING: this is an extreme speed hack.
- Do not try this at home. */
- Py_hash_t hash = ((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;
+ if (PyDict_CheckExact(f->f_globals)
+ && PyDict_CheckExact(f->f_builtins)) {
+ x = _PyDict_LoadGlobal((PyDictObject *)f->f_globals,
+ (PyDictObject *)f->f_builtins,
+ w);
+ if (x == NULL) {
+ if (!_PyErr_OCCURRED())
+ format_exc_check_arg(PyExc_NameError,
+ GLOBAL_NAME_ERROR_MSG, w);
+ break;
}
+ Py_INCREF(x);
}
- /* 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);
+ else {
+ /* Slow-path if globals or builtins is not a dict */
+ x = PyObject_GetItem(f->f_globals, w);
if (x == NULL) {
- load_global_error:
- format_exc_check_arg(
- PyExc_NameError,
- GLOBAL_NAME_ERROR_MSG, w);
- break;
+ x = PyObject_GetItem(f->f_builtins, w);
+ if (x == NULL) {
+ if (PyErr_ExceptionMatches(PyExc_KeyError))
+ format_exc_check_arg(
+ PyExc_NameError,
+ GLOBAL_NAME_ERROR_MSG, w);
+ break;
+ }
}
}
- Py_INCREF(x);
PUSH(x);
DISPATCH();
@@ -2313,8 +2296,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
DISPATCH();
TARGET(IMPORT_NAME)
+ {
+ _Py_IDENTIFIER(__import__);
w = GETITEM(names, oparg);
- x = PyDict_GetItemString(f->f_builtins, "__import__");
+ x = _PyDict_GetItemId(f->f_builtins, &PyId___import__);
if (x == NULL) {
PyErr_SetString(PyExc_ImportError,
"__import__ not found");
@@ -2355,6 +2340,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
SET_TOP(x);
if (x != NULL) DISPATCH();
break;
+ }
TARGET(IMPORT_STAR)
v = POP();
@@ -2559,13 +2545,14 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
TARGET(SETUP_WITH)
{
- static PyObject *exit, *enter;
+ _Py_IDENTIFIER(__exit__);
+ _Py_IDENTIFIER(__enter__);
w = TOP();
- x = special_lookup(w, "__exit__", &exit);
+ x = special_lookup(w, &PyId___exit__);
if (!x)
break;
SET_TOP(x);
- u = special_lookup(w, "__enter__", &enter);
+ u = special_lookup(w, &PyId___enter__);
Py_DECREF(w);
if (!u) {
x = NULL;
@@ -2586,7 +2573,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
TARGET(WITH_CLEANUP)
{
- /* At the top of the stack are 1-3 values indicating
+ /* At the top of the stack are 1-6 values indicating
how/why we entered the finally clause:
- TOP = None
- (TOP, SECOND) = (WHY_{RETURN,CONTINUE}), retval
@@ -2599,9 +2586,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
otherwise we must call
EXIT(None, None, None)
- In the first two cases, we remove EXIT from the
+ In the first three 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
+ fourth 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,
@@ -2725,7 +2712,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
Py_DECREF(*pfunc);
*pfunc = self;
na++;
- n++;
+ /* n++; */
} else
Py_INCREF(func);
sp = stack_pointer;
@@ -2753,9 +2740,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
int kwdefaults = (oparg>>8) & 0xff;
int num_annotations = (oparg >> 16) & 0x7fff;
+ w = POP(); /* qualname */
v = POP(); /* code object */
- x = PyFunction_New(v, f->f_globals);
+ x = PyFunction_NewWithQualName(v, f->f_globals, w);
Py_DECREF(v);
+ Py_DECREF(w);
if (x != NULL && opcode == MAKE_CLOSURE) {
v = POP();
@@ -3049,9 +3038,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) {
@@ -3060,8 +3049,7 @@ fast_yield:
if (call_trace(tstate->c_tracefunc,
tstate->c_traceobj, f,
PyTrace_RETURN, retval)) {
- Py_XDECREF(retval);
- retval = NULL;
+ Py_CLEAR(retval);
why = WHY_EXCEPTION;
}
}
@@ -3079,9 +3067,8 @@ fast_yield:
else if (call_trace(tstate->c_profilefunc,
tstate->c_profileobj, f,
PyTrace_RETURN, retval)) {
- Py_XDECREF(retval);
- retval = NULL;
- why = WHY_EXCEPTION;
+ Py_CLEAR(retval);
+ /* why = WHY_EXCEPTION; */
}
}
}
@@ -3094,6 +3081,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 +3247,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,219 +3266,165 @@ 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;
+ }
+ if (PyDict_SetItem(kwdict, keyword, value) == -1) {
+ goto fail;
+ }
+ 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));
+ /* Clear the local copy. */
+ SETLOCAL(arg, NULL);
}
- }
- 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;
+ else {
+ c = PyCell_New(NULL);
}
+ if (c == NULL)
+ goto fail;
+ SETLOCAL(co->co_nlocals + i, c);
+ }
+ for (i = 0; i < PyTuple_GET_SIZE(co->co_freevars); ++i) {
+ PyObject *o = PyTuple_GET_ITEM(closure, i);
+ Py_INCREF(o);
+ freevars[PyTuple_GET_SIZE(co->co_cellvars) + i] = o;
}
if (co->co_flags & CO_GENERATOR) {
/* Don't need to keep the reference to f_back, it will be set
* when the generator is resumed. */
- Py_XDECREF(f->f_back);
- f->f_back = NULL;
+ Py_CLEAR(f->f_back);
PCALL(PCALL_GENERATOR);
@@ -3365,18 +3451,72 @@ 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
@@ -3446,6 +3586,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 "
@@ -3571,6 +3715,7 @@ call_exc_trace(Py_tracefunc func, PyObject *self, PyFrameObject *f)
value = Py_None;
Py_INCREF(value);
}
+ PyErr_NormalizeException(&type, &value, &traceback);
arg = PyTuple_Pack(3, type, value, traceback);
if (arg == NULL) {
PyErr_Restore(type, value, traceback);
@@ -4192,7 +4337,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 +4487,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 +4498,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 +4524,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 +4585,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 +4628,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