From 313459bc23e59254ad32059385f99cb0d80feecb Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 21 Feb 2011 21:05:50 +0000 Subject: Remove filename variable from ceval.c Issue #11168: Remove filename debug variable from PyEval_EvalFrameEx(). It encoded the Unicode filename to UTF-8, but the encoding fails on undecodable filename (on surrogate characters) which raises an unexpected UnicodeEncodeError on recursion limit. --- Python/ceval.c | 16 ---------------- 1 file changed, 16 deletions(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index f6d4b0b84b..c10a2ff594 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -811,10 +811,6 @@ 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; -#endif /* Computed GOTOs, or the-optimization-commonly-but-improperly-known-as-"threaded code" @@ -1227,18 +1223,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) #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); - } -#endif why = WHY_NOT; err = 0; -- cgit v1.2.1 From ffbf24bf0cc297d080d6d68bc809a9c156c49123 Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Tue, 22 Feb 2011 20:15:44 +0000 Subject: Issue #8914: fix various warnings from the Clang static analyzer v254. --- Python/ceval.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index c10a2ff594..9572918dc3 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2690,7 +2690,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) Py_DECREF(*pfunc); *pfunc = self; na++; - n++; + /* n++; */ } else Py_INCREF(func); sp = stack_pointer; @@ -3026,7 +3026,7 @@ fast_yield: PyTrace_RETURN, retval)) { Py_XDECREF(retval); retval = NULL; - why = WHY_EXCEPTION; + /* why = WHY_EXCEPTION; */ } } } -- cgit v1.2.1 From e4d2501d8d2d2050dd6950aa4a794003fb2c7889 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 22 Mar 2011 01:09:21 +0100 Subject: Issue #7330, #10833: Replace %100s by %.100s and %200s by %.200s I suppose that the author would like to truncate the type name, not get a string of 100/200 characters. --- Python/ceval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index d2444aa9f0..50d5aacd9e 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4130,7 +4130,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); -- cgit v1.2.1 From 76e229fd30ea1520a581971429237c57131af241 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 5 Jun 2011 22:04:07 -0500 Subject: greatly improve argument parsing error messages (closes #12265) --- Python/ceval.c | 303 +++++++++++++++++++++++++++++++-------------------------- 1 file changed, 166 insertions(+), 137 deletions(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index 5627e83999..f1f4c70da1 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3045,6 +3045,63 @@ exit_eval_frame: return retval; } +static void +positional_argument_error(PyCodeObject *co, int given, int defcount, PyObject **fastlocals) +{ + int plural; + int kwonly_given = 0; + int atleast = co->co_argcount - defcount; + int i; + PyObject *sig, *kwonly_sig; + + if (given == -1) { + given = 0; + for (i = 0; i < co->co_argcount; i++) + if (GETLOCAL(i)) + given++; + } + for (i = co->co_argcount; i < co->co_argcount + co->co_kwonlyargcount; i++) + if (GETLOCAL(i)) + kwonly_given++; + if (co->co_flags & CO_VARARGS) { + plural = atleast != 1; + sig = PyUnicode_FromFormat("at least %d", atleast); + } + else if (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(""); + } + 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). */ @@ -3061,6 +3118,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, @@ -3077,161 +3137,130 @@ 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); + Py_INCREF(value); + SETLOCAL(j, value); + } + if (argcount > co->co_argcount && !(co->co_flags & CO_VARARGS)) { + positional_argument_error(co, argcount, 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) { + positional_argument_error(co, -1, 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) { + 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; } } + PyErr_Format(PyExc_TypeError, + "%U() requires keyword-only argument '%S'", + co->co_name, name); + 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)) { -- cgit v1.2.1 From cc1b48469f203e2e125a16c560f0eb7050fba626 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 24 Jun 2011 09:37:26 -0500 Subject: give the names of missing positional or keyword-only arguments (closes #12356) --- Python/ceval.c | 141 +++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 118 insertions(+), 23 deletions(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index f1f4c70da1..ac0707046a 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3046,28 +3046,118 @@ exit_eval_frame: } static void -positional_argument_error(PyCodeObject *co, int given, int defcount, PyObject **fastlocals) +format_missing(const char *kind, PyCodeObject *co, PyObject *names) +{ + int err; + Py_ssize_t len = PyList_GET_SIZE(names); + PyObject *name_str, *comma, *tail, *tmp; + + assert(PyList_CheckExact(names)); + assert(len >= 1); + /* Deal with the joys of natural language. */ + switch (len) { + case 1: + name_str = PyList_GET_ITEM(names, 0); + Py_INCREF(name_str); + break; + case 2: + name_str = PyUnicode_FromFormat("%U and %U", + PyList_GET_ITEM(names, len - 2), + PyList_GET_ITEM(names, len - 1)); + break; + default: + tail = PyUnicode_FromFormat(", %U, and %U", + PyList_GET_ITEM(names, len - 2), + PyList_GET_ITEM(names, len - 1)); + /* Chop off the last two objects in the list. This shouldn't actually + fail, but we can't be too careful. */ + err = PyList_SetSlice(names, len - 2, len, NULL); + if (err == -1) { + Py_DECREF(tail); + return; + } + /* Stitch everything up into a nice comma-separated list. */ + comma = PyUnicode_FromString(", "); + if (comma == NULL) { + Py_DECREF(tail); + return; + } + tmp = PyUnicode_Join(comma, names); + Py_DECREF(comma); + if (tmp == NULL) { + Py_DECREF(tail); + return; + } + name_str = PyUnicode_Concat(tmp, tail); + Py_DECREF(tmp); + Py_DECREF(tail); + break; + } + if (name_str == NULL) + return; + PyErr_Format(PyExc_TypeError, + "%U() missing %i required %s argument%s: %U", + co->co_name, + len, + kind, + len == 1 ? "" : "s", + name_str); + Py_DECREF(name_str); +} + +static void +missing_arguments(PyCodeObject *co, int missing, int defcount, + PyObject **fastlocals) +{ + int i, j = 0; + int start, end; + int positional = defcount != -1; + const char *kind = positional ? "positional" : "keyword-only"; + PyObject *missing_names; + + /* Compute the names of the arguments that are missing. */ + missing_names = PyList_New(missing); + if (missing_names == NULL) + return; + if (positional) { + start = 0; + end = co->co_argcount - defcount; + } + else { + start = co->co_argcount; + end = start + co->co_kwonlyargcount; + } + for (i = start; i < end; i++) { + if (GETLOCAL(i) == NULL) { + PyObject *raw = PyTuple_GET_ITEM(co->co_varnames, i); + PyObject *name = PyObject_Repr(raw); + if (name == NULL) { + Py_DECREF(missing_names); + return; + } + PyList_SET_ITEM(missing_names, j++, name); + } + } + assert(j == missing); + format_missing(kind, co, missing_names); + Py_DECREF(missing_names); +} + +static void +too_many_positional(PyCodeObject *co, int given, int defcount, PyObject **fastlocals) { int plural; int kwonly_given = 0; - int atleast = co->co_argcount - defcount; int i; PyObject *sig, *kwonly_sig; - if (given == -1) { - given = 0; - for (i = 0; i < co->co_argcount; i++) - if (GETLOCAL(i)) - given++; - } + 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)) + if (GETLOCAL(i) != NULL) kwonly_given++; - if (co->co_flags & CO_VARARGS) { - plural = atleast != 1; - sig = PyUnicode_FromFormat("at least %d", atleast); - } - else if (defcount) { + if (defcount) { + int atleast = co->co_argcount - defcount; plural = 1; sig = PyUnicode_FromFormat("from %d to %d", atleast, co->co_argcount); } @@ -3089,6 +3179,7 @@ positional_argument_error(PyCodeObject *co, int given, int defcount, PyObject ** 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", @@ -3217,16 +3308,18 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals, SETLOCAL(j, value); } if (argcount > co->co_argcount && !(co->co_flags & CO_VARARGS)) { - positional_argument_error(co, argcount, defcount, fastlocals); + too_many_positional(co, argcount, 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) { - positional_argument_error(co, -1, defcount, fastlocals); - goto fail; - } + int missing = 0; + for (i = argcount; i < m; i++) + if (GETLOCAL(i) == NULL) + missing++; + if (missing) { + missing_arguments(co, missing, defcount, fastlocals); + goto fail; } if (n > m) i = n - m; @@ -3241,6 +3334,7 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals, } } if (co->co_kwonlyargcount > 0) { + int missing = 0; for (i = co->co_argcount; i < total_args; i++) { PyObject *name; if (GETLOCAL(i) != NULL) @@ -3254,9 +3348,10 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals, continue; } } - PyErr_Format(PyExc_TypeError, - "%U() requires keyword-only argument '%S'", - co->co_name, name); + missing++; + } + if (missing) { + missing_arguments(co, missing, -1, fastlocals); goto fail; } } -- cgit v1.2.1 From 78e7d230757093d24166ed820271a07ddf77d3e3 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sat, 25 Jun 2011 22:54:45 -0500 Subject: map cells to arg slots at code creation time (closes #12399) This removes nested loops in PyEval_EvalCodeEx. --- Python/ceval.c | 64 +++++++++++++++------------------------------------------- 1 file changed, 16 insertions(+), 48 deletions(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index ac0707046a..33213fa72d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3357,56 +3357,24 @@ PyEval_EvalCodeEx(PyObject *_co, PyObject *globals, PyObject *locals, } /* 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) { -- cgit v1.2.1 From 2b7be477eff47f56618447c940977645a14c3017 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 3 Jul 2011 16:48:31 -0500 Subject: convert generator exc state functions into static functions --- Python/ceval.c | 116 ++++++++++++++++++++++++++++++--------------------------- 1 file changed, 62 insertions(+), 54 deletions(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index 1dd0d49118..5a5e23c552 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -749,6 +749,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 **); @@ -1110,54 +1113,6 @@ 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) @@ -1236,11 +1191,10 @@ 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 @@ -3033,9 +2987,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) { @@ -3453,6 +3407,60 @@ special_lookup(PyObject *o, char *meth, PyObject **cache) } +/* 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 -- cgit v1.2.1 From f409710160ebcab1fb89f5cb6cf0d8f733d07089 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 3 Jul 2011 17:06:32 -0500 Subject: no one passes NULL here (or should anyway) --- Python/ceval.c | 3 --- 1 file changed, 3 deletions(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index 5a5e23c552..5c936376db 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1115,9 +1115,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) /* Start of code */ - if (f == NULL) - return NULL; - /* push frame */ if (Py_EnterRecursiveCall("")) return NULL; -- cgit v1.2.1 From 9ab49a8a88fec533bed7891464129e7603f530a4 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 17 Jul 2011 22:49:50 -0500 Subject: excise the remains of STOP_CODE, which hasn't done anything useful for years --- Python/ceval.c | 2 -- 1 file changed, 2 deletions(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index 6d493633a9..068da6f5f1 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1347,8 +1347,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(); -- cgit v1.2.1 From b4f0c255b55fb428481d238fede5cd449a2dbf66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Charles-Fran=C3=A7ois=20Natali?= Date: Sat, 23 Jul 2011 18:15:43 +0200 Subject: Issue 12620: Make pendingbusy flag static to Py_MakePendingCalls(). --- Python/ceval.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index 068da6f5f1..1c9153e276 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -491,7 +491,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 +537,7 @@ Py_AddPendingCall(int (*func)(void *), void *arg) int Py_MakePendingCalls(void) { + static int busy = 0; int i; int r = 0; @@ -552,9 +552,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 Date: Wed, 28 Sep 2011 07:41:54 +0200 Subject: Implement PEP 393. --- Python/ceval.c | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index 1c9153e276..0a346f4179 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2054,7 +2054,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) /* 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; + Py_hash_t hash = ((PyASCIIObject *)w)->hash; if (hash != -1) { PyDictObject *d; PyDictEntry *e; @@ -4456,7 +4456,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; @@ -4520,6 +4521,14 @@ unicode_concatenate(PyObject *v, PyObject *w, { /* This function implements 'variable += expr' when both arguments are (Unicode) strings. */ + + w = PyUnicode_Concat(v, w); + Py_DECREF(v); + return w; + + /* XXX: This optimization is currently disabled as unicode objects in the + new flexible representation are not in-place resizable anymore. */ +#if 0 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; @@ -4570,7 +4579,8 @@ unicode_concatenate(PyObject *v, PyObject *w, } } - if (Py_REFCNT(v) == 1 && !PyUnicode_CHECK_INTERNED(v)) { + if (Py_REFCNT(v) == 1 && !PyUnicode_CHECK_INTERNED(v) && + !PyUnicode_IS_COMPACT((PyUnicodeObject *)v)) { /* Now we own the last reference to 'v', so we can resize it * in-place. */ @@ -4594,6 +4604,7 @@ unicode_concatenate(PyObject *v, PyObject *w, Py_DECREF(v); return w; } +#endif } #ifdef DYNAMIC_EXECUTION_PROFILE -- cgit v1.2.1 From 3238a6809400acc13c558cff1c184e58fcf92d9c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sat, 1 Oct 2011 01:26:08 +0200 Subject: Remove commented code: str+=str is no more super-optimized --- Python/ceval.c | 118 +++------------------------------------------------------ 1 file changed, 6 insertions(+), 112 deletions(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index 0a346f4179..f6f422ee32 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -136,8 +136,6 @@ static PyObject * import_from(PyObject *, PyObject *); static int import_all_from(PyObject *, PyObject *); static void format_exc_check_arg(PyObject *, const char *, PyObject *); static void format_exc_unbound(PyCodeObject *co, int oparg); -static PyObject * unicode_concatenate(PyObject *, PyObject *, - PyFrameObject *, unsigned char *); static PyObject * special_lookup(PyObject *, char *, PyObject **); #define NAME_ERROR_MSG \ @@ -1509,17 +1507,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) TARGET(BINARY_ADD) w = POP(); v = TOP(); - if (PyUnicode_CheckExact(v) && - PyUnicode_CheckExact(w)) { - x = unicode_concatenate(v, w, f, next_instr); - /* unicode_concatenate consumed the ref to v */ - goto skip_decref_vx; - } - else { + if (PyUnicode_Check(v) && PyUnicode_Check(w)) + x = PyUnicode_Concat(v, w); + else x = PyNumber_Add(v, w); - } Py_DECREF(v); - skip_decref_vx: Py_DECREF(w); SET_TOP(x); if (x != NULL) DISPATCH(); @@ -1670,17 +1662,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) TARGET(INPLACE_ADD) w = POP(); v = TOP(); - if (PyUnicode_CheckExact(v) && - PyUnicode_CheckExact(w)) { - x = unicode_concatenate(v, w, f, next_instr); - /* unicode_concatenate consumed the ref to v */ - goto skip_decref_v; - } - else { + if (PyUnicode_Check(v) && PyUnicode_Check(w)) + x = PyUnicode_Concat(v, w); + else x = PyNumber_InPlaceAdd(v, w); - } Py_DECREF(v); - skip_decref_v: Py_DECREF(w); SET_TOP(x); if (x != NULL) DISPATCH(); @@ -4515,98 +4501,6 @@ format_exc_unbound(PyCodeObject *co, int oparg) } } -static PyObject * -unicode_concatenate(PyObject *v, PyObject *w, - PyFrameObject *f, unsigned char *next_instr) -{ - /* This function implements 'variable += expr' when both arguments - are (Unicode) strings. */ - - w = PyUnicode_Concat(v, w); - Py_DECREF(v); - return w; - - /* XXX: This optimization is currently disabled as unicode objects in the - new flexible representation are not in-place resizable anymore. */ -#if 0 - 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; - } - - if (Py_REFCNT(v) == 2) { - /* In the common case, there are 2 references to the value - * stored in 'variable' when the += is performed: one on the - * value stack (in 'v') and one still stored in the - * 'variable'. We try to delete the variable now to reduce - * the refcnt to 1. - */ - switch (*next_instr) { - case STORE_FAST: - { - int oparg = PEEKARG(); - PyObject **fastlocals = f->f_localsplus; - if (GETLOCAL(oparg) == v) - SETLOCAL(oparg, NULL); - break; - } - case STORE_DEREF: - { - PyObject **freevars = (f->f_localsplus + - f->f_code->co_nlocals); - PyObject *c = freevars[PEEKARG()]; - if (PyCell_GET(c) == v) - PyCell_Set(c, NULL); - break; - } - case STORE_NAME: - { - PyObject *names = f->f_code->co_names; - PyObject *name = GETITEM(names, PEEKARG()); - PyObject *locals = f->f_locals; - if (PyDict_CheckExact(locals) && - PyDict_GetItem(locals, name) == v) { - if (PyDict_DelItem(locals, name) != 0) { - PyErr_Clear(); - } - } - break; - } - } - } - - if (Py_REFCNT(v) == 1 && !PyUnicode_CHECK_INTERNED(v) && - !PyUnicode_IS_COMPACT((PyUnicodeObject *)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; - } -#endif -} - #ifdef DYNAMIC_EXECUTION_PROFILE static PyObject * -- cgit v1.2.1 From cd6c51adb67b308df10d175f2e1afc94d8742e1b Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 30 Sep 2011 21:31:21 -0400 Subject: remove "fast-path" for (i)adding strings These were just an artifact of the old unicode concatenation hack and likely just penalized other kinds of adding. Also, this fixes __(i)add__ on string subclasses. --- Python/ceval.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index f6f422ee32..870d19d55c 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1507,10 +1507,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) TARGET(BINARY_ADD) w = POP(); v = TOP(); - if (PyUnicode_Check(v) && PyUnicode_Check(w)) - x = PyUnicode_Concat(v, w); - else - x = PyNumber_Add(v, w); + x = PyNumber_Add(v, w); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); @@ -1662,10 +1659,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) TARGET(INPLACE_ADD) w = POP(); v = TOP(); - if (PyUnicode_Check(v) && PyUnicode_Check(w)) - x = PyUnicode_Concat(v, w); - else - x = PyNumber_InPlaceAdd(v, w); + x = PyNumber_InPlaceAdd(v, w); Py_DECREF(v); Py_DECREF(w); SET_TOP(x); -- cgit v1.2.1 From a8b8005d1149e2f94427ba5684f1684f9ff7971e Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Sun, 2 Oct 2011 20:34:20 +0200 Subject: ceval.c: restore str+=str optimization --- Python/ceval.c | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 3 deletions(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index 870d19d55c..686a54dafe 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -136,6 +136,8 @@ static PyObject * import_from(PyObject *, PyObject *); static int import_all_from(PyObject *, PyObject *); static void format_exc_check_arg(PyObject *, const char *, PyObject *); static void format_exc_unbound(PyCodeObject *co, int oparg); +static PyObject * unicode_concatenate(PyObject *, PyObject *, + PyFrameObject *, unsigned char *); static PyObject * special_lookup(PyObject *, char *, PyObject **); #define NAME_ERROR_MSG \ @@ -1507,8 +1509,17 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) TARGET(BINARY_ADD) w = POP(); v = TOP(); - x = PyNumber_Add(v, w); + if (PyUnicode_CheckExact(v) && + PyUnicode_CheckExact(w)) { + x = unicode_concatenate(v, w, f, next_instr); + /* unicode_concatenate consumed the ref to v */ + goto skip_decref_vx; + } + else { + x = PyNumber_Add(v, w); + } Py_DECREF(v); + skip_decref_vx: Py_DECREF(w); SET_TOP(x); if (x != NULL) DISPATCH(); @@ -1659,8 +1670,17 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) TARGET(INPLACE_ADD) w = POP(); v = TOP(); - x = PyNumber_InPlaceAdd(v, w); + if (PyUnicode_CheckExact(v) && + PyUnicode_CheckExact(w)) { + x = unicode_concatenate(v, w, f, next_instr); + /* unicode_concatenate consumed the ref to v */ + goto skip_decref_v; + } + else { + x = PyNumber_InPlaceAdd(v, w); + } Py_DECREF(v); + skip_decref_v: Py_DECREF(w); SET_TOP(x); if (x != NULL) DISPATCH(); @@ -3399,7 +3419,7 @@ save_exc_state(PyThreadState *tstate, PyFrameObject *f) f->f_exc_traceback = tstate->exc_traceback; Py_XDECREF(type); Py_XDECREF(value); - Py_XDECREF(traceback); + Py_XDECREF(traceback); } static void @@ -4495,6 +4515,56 @@ format_exc_unbound(PyCodeObject *co, int oparg) } } +static PyObject * +unicode_concatenate(PyObject *v, PyObject *w, + PyFrameObject *f, unsigned char *next_instr) +{ + PyObject *res; + if (Py_REFCNT(v) == 2) { + /* In the common case, there are 2 references to the value + * stored in 'variable' when the += is performed: one on the + * value stack (in 'v') and one still stored in the + * 'variable'. We try to delete the variable now to reduce + * the refcnt to 1. + */ + switch (*next_instr) { + case STORE_FAST: + { + int oparg = PEEKARG(); + PyObject **fastlocals = f->f_localsplus; + if (GETLOCAL(oparg) == v) + SETLOCAL(oparg, NULL); + break; + } + case STORE_DEREF: + { + PyObject **freevars = (f->f_localsplus + + f->f_code->co_nlocals); + PyObject *c = freevars[PEEKARG()]; + if (PyCell_GET(c) == v) + PyCell_Set(c, NULL); + break; + } + case STORE_NAME: + { + PyObject *names = f->f_code->co_names; + PyObject *name = GETITEM(names, PEEKARG()); + PyObject *locals = f->f_locals; + if (PyDict_CheckExact(locals) && + PyDict_GetItem(locals, name) == v) { + if (PyDict_DelItem(locals, name) != 0) { + PyErr_Clear(); + } + } + break; + } + } + } + res = v; + PyUnicode_Append(&res, w); + return res; +} + #ifdef DYNAMIC_EXECUTION_PROFILE static PyObject * -- cgit v1.2.1 From dcacb24f386ae1b107462181af42b6826ec15fb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Sun, 9 Oct 2011 10:38:36 +0200 Subject: =?UTF-8?q?Add=20API=20for=20static=20strings,=20primarily=20good?= =?UTF-8?q?=20for=20identifiers.=20Thanks=20to=20Konrad=20Sch=C3=B6bel=20a?= =?UTF-8?q?nd=20Jasper=20Schulz=20for=20helping=20with=20the=20mass-editin?= =?UTF-8?q?g.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Python/ceval.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index 686a54dafe..04d3df1500 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -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 -- cgit v1.2.1 From f5ad3b280b43227eb0e3fa63d89490a58ba9c28b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Fri, 14 Oct 2011 10:20:37 +0200 Subject: Rename _Py_identifier to _Py_IDENTIFIER. --- Python/ceval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index 04d3df1500..543c6f2179 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -372,7 +372,7 @@ PyEval_ReleaseThread(PyThreadState *tstate) void PyEval_ReInitThreads(void) { - _Py_identifier(_after_fork); + _Py_IDENTIFIER(_after_fork); PyObject *threading, *result; PyThreadState *tstate = PyThreadState_GET(); -- cgit v1.2.1 From 406e4d8f1d3d003e8754d9e65607a697e7f5c865 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Fri, 14 Oct 2011 15:16:45 +0200 Subject: Port SetAttrString/HasAttrString to SetAttrId/GetAttrId. --- Python/ceval.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index 543c6f2179..8d980fdc93 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -4422,7 +4422,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; @@ -4431,7 +4433,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; -- cgit v1.2.1 From 949c3f094c436fea35325980527d63d0d9eabd21 Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Fri, 25 Nov 2011 18:56:07 +0100 Subject: PEP 3155 / issue #13448: Qualified name for classes and functions. --- Python/ceval.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index 8d980fdc93..ed82b9411a 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2687,9 +2687,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(); -- cgit v1.2.1 From e4f5fc423651e760f014159dce83273f9d54831c Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Fri, 13 Jan 2012 21:43:40 +1000 Subject: Implement PEP 380 - 'yield from' (closes #11682) --- Python/ceval.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index ed82b9411a..134d1eec4b 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1828,6 +1828,52 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) why = WHY_RETURN; goto fast_block_end; + TARGET(YIELD_FROM) + u = POP(); + x = PyObject_GetIter(u); + Py_DECREF(u); + if (x == NULL) + break; + /* x is now the iterator, make the first next() call */ + retval = (*Py_TYPE(x)->tp_iternext)(x); + if (!retval) { + /* iter may be exhausted */ + Py_CLEAR(x); + if (!PyErr_ExceptionMatches(PyExc_StopIteration)) { + /* some other exception */ + break; + } + /* try to get return value from exception */ + PyObject *et, *ev, *tb; + PyErr_Fetch(&et, &ev, &tb); + Py_XDECREF(et); + Py_XDECREF(tb); + /* u is return value */ + u = NULL; + if (ev) { + u = PyObject_GetAttrString(ev, "value"); + Py_DECREF(ev); + if (u == NULL) { + if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { + /* some other exception */ + break; + } + PyErr_Clear(); + } + } + if (u == NULL) { + u = Py_None; + Py_INCREF(u); + } + PUSH(u); + continue; + } + /* x is iterator, retval is value to be yielded */ + f->f_yieldfrom = x; + f->f_stacktop = stack_pointer; + why = WHY_YIELD; + goto fast_yield; + TARGET(YIELD_VALUE) retval = POP(); f->f_stacktop = stack_pointer; -- cgit v1.2.1 From 8a26917ad2c8bc07ba5389c9ad599f1eb0a2936e Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 13 Jan 2012 14:54:31 -0500 Subject: NULL and no exception set from tp_iternext means StopIteration --- Python/ceval.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index 134d1eec4b..98219b0c9d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1839,7 +1839,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) if (!retval) { /* iter may be exhausted */ Py_CLEAR(x); - if (!PyErr_ExceptionMatches(PyExc_StopIteration)) { + if (PyErr_Occurred() && + !PyErr_ExceptionMatches(PyExc_StopIteration)) { /* some other exception */ break; } -- cgit v1.2.1 From 3705fefce326453806de7400c01106a85f81908b Mon Sep 17 00:00:00 2001 From: Amaury Forgeot d'Arc Date: Fri, 13 Jan 2012 21:08:49 +0100 Subject: Fix compilation with C89 compilers (Windows...) --- Python/ceval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index 98219b0c9d..e2d96c5c44 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1837,6 +1837,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) /* x is now the iterator, make the first next() call */ retval = (*Py_TYPE(x)->tp_iternext)(x); if (!retval) { + PyObject *et, *ev, *tb; /* iter may be exhausted */ Py_CLEAR(x); if (PyErr_Occurred() && @@ -1845,7 +1846,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) break; } /* try to get return value from exception */ - PyObject *et, *ev, *tb; PyErr_Fetch(&et, &ev, &tb); Py_XDECREF(et); Py_XDECREF(tb); -- cgit v1.2.1 From a89a01f7a48f0e422ff34ee40f1f0c16985dd5a8 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Sun, 22 Jan 2012 11:24:29 -0500 Subject: use the static identifier api for looking up special methods I had to move the static identifier code from unicodeobject.h to object.h in order for this to work. --- Python/ceval.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index e2d96c5c44..06bff4c169 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" @@ -2540,13 +2540,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; @@ -3440,12 +3441,12 @@ 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; -- cgit v1.2.1 From fc7f17dd7a77350fd6906e2082f2375647b57c6a Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Sun, 26 Feb 2012 17:49:52 +1000 Subject: Close issue #6210: Implement PEP 409 --- Python/ceval.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index 06bff4c169..017dc4aab9 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3567,22 +3567,23 @@ do_raise(PyObject *exc, PyObject *cause) if (cause) { PyObject *fixed_cause; + int result; if (PyExceptionClass_Check(cause)) { fixed_cause = PyObject_CallObject(cause, NULL); if (fixed_cause == NULL) goto raise_error; - Py_DECREF(cause); - } - else if (PyExceptionInstance_Check(cause)) { + Py_CLEAR(cause); + } else { + /* Let "exc.__cause__ = cause" handle all further checks */ fixed_cause = cause; + cause = NULL; /* Steal the reference */ } - else { - PyErr_SetString(PyExc_TypeError, - "exception causes must derive from " - "BaseException"); + /* We retain ownership of the reference to fixed_cause */ + result = _PyException_SetCauseChecked(value, fixed_cause); + Py_DECREF(fixed_cause); + if (result < 0) { goto raise_error; } - PyException_SetCause(value, fixed_cause); } PyErr_SetObject(type, value); -- cgit v1.2.1 From 0ea564cff248528b899a26f75b173f35b55d505a Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Thu, 15 Mar 2012 15:37:39 -0500 Subject: perform yield from delegation by repeating YIELD_FROM opcode (closes #14230) This allows generators that are using yield from to be seen by debuggers. It also kills the f_yieldfrom field on frame objects. Patch mostly from Mark Shannon with a few tweaks by me. --- Python/ceval.c | 58 +++++++++++++++++++++++----------------------------------- 1 file changed, 23 insertions(+), 35 deletions(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index 017dc4aab9..54980565bf 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1170,6 +1170,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 @@ -1830,49 +1832,35 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) TARGET(YIELD_FROM) u = POP(); - x = PyObject_GetIter(u); + x = TOP(); + /* send u to x */ + if (PyGen_CheckExact(x)) { + retval = _PyGen_Send((PyGenObject *)x, u); + } else { + if (u == Py_None) + retval = PyIter_Next(x); + else + retval = PyObject_CallMethod(x, "send", "O", u); + } Py_DECREF(u); - if (x == NULL) - break; - /* x is now the iterator, make the first next() call */ - retval = (*Py_TYPE(x)->tp_iternext)(x); if (!retval) { - PyObject *et, *ev, *tb; - /* iter may be exhausted */ - Py_CLEAR(x); - if (PyErr_Occurred() && - !PyErr_ExceptionMatches(PyExc_StopIteration)) { - /* some other exception */ + PyObject *val; + x = POP(); /* Remove iter from stack */ + Py_DECREF(x); + err = PyGen_FetchStopIterationValue(&val); + if (err < 0) { + x = NULL; break; } - /* try to get return value from exception */ - PyErr_Fetch(&et, &ev, &tb); - Py_XDECREF(et); - Py_XDECREF(tb); - /* u is return value */ - u = NULL; - if (ev) { - u = PyObject_GetAttrString(ev, "value"); - Py_DECREF(ev); - if (u == NULL) { - if (!PyErr_ExceptionMatches(PyExc_AttributeError)) { - /* some other exception */ - break; - } - PyErr_Clear(); - } - } - if (u == NULL) { - u = Py_None; - Py_INCREF(u); - } - PUSH(u); + x = val; + PUSH(x); continue; } - /* x is iterator, retval is value to be yielded */ - f->f_yieldfrom = x; + /* 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) -- cgit v1.2.1 From c177108b1d0ce7611272b5e1527738f7d9794b4e Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Tue, 20 Mar 2012 23:17:04 -0400 Subject: use identifier api --- Python/ceval.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index 54980565bf..418237807a 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1837,10 +1837,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) if (PyGen_CheckExact(x)) { retval = _PyGen_Send((PyGenObject *)x, u); } else { + _Py_IDENTIFIER(send); if (u == Py_None) retval = PyIter_Next(x); else - retval = PyObject_CallMethod(x, "send", "O", u); + retval = _PyObject_CallMethodId(x, &PyId_send, "O", u); } Py_DECREF(u); if (!retval) { -- cgit v1.2.1 From 6c62fbe9459a3d680a651c6216d60f87d04e1f40 Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Mon, 26 Mar 2012 22:10:51 +0200 Subject: Issue #14383: Add _PyDict_GetItemId() and _PyDict_SetItemId() functions These functions simplify the usage of static constant Unicode strings. Generalize the usage of _Py_Identifier in ceval.c and typeobject.c. --- Python/ceval.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index 418237807a..ae0bd242a0 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -822,6 +822,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) PyObject *names; PyObject *consts; + _Py_IDENTIFIER(__ltrace__); + /* Computed GOTOs, or the-optimization-commonly-but-improperly-known-as-"threaded code" using gcc's labels-as-values extension @@ -1198,7 +1200,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) } #ifdef LLTRACE - lltrace = PyDict_GetItemString(f->f_globals, "__lltrace__") != NULL; + lltrace = _PyDict_GetItemId(f->f_globals, &PyId___ltrace__) != NULL; #endif why = WHY_NOT; @@ -1926,8 +1928,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) break; TARGET(LOAD_BUILD_CLASS) - x = PyDict_GetItemString(f->f_builtins, - "__build_class__"); + { + _Py_IDENTIFIER(__build_class__); + x = _PyDict_GetItemId(f->f_builtins, &PyId___build_class__); if (x == NULL) { PyErr_SetString(PyExc_ImportError, "__build_class__ not found"); @@ -1936,6 +1939,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) Py_INCREF(x); PUSH(x); break; + } TARGET(STORE_NAME) w = GETITEM(names, oparg); @@ -2283,8 +2287,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"); @@ -2325,6 +2331,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) SET_TOP(x); if (x != NULL) DISPATCH(); break; + } TARGET(IMPORT_STAR) v = POP(); -- cgit v1.2.1 From e511dcc4e34ada4889ccc1d20fb3416b0add9fcb Mon Sep 17 00:00:00 2001 From: Brett Cannon Date: Mon, 2 Apr 2012 12:17:59 -0400 Subject: Guard an LLTRACE variable to silence an unused variable warning. --- Python/ceval.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index ae0bd242a0..7908d444e1 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -822,7 +822,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) PyObject *names; PyObject *consts; +#ifdef LLTRACE _Py_IDENTIFIER(__ltrace__); +#endif /* Computed GOTOs, or the-optimization-commonly-but-improperly-known-as-"threaded code" -- cgit v1.2.1 From e4df8a8777b02802690f3b697689ee831be6ec9e Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Thu, 19 Apr 2012 00:57:45 +0200 Subject: Issue #14385: Support other types than dict for __builtins__ It is now possible to use a custom type for the __builtins__ namespace, instead of a dict. It can be used for sandboxing for example. Raise also a NameError instead of ImportError if __build_class__ name if not found in __builtins__. --- Python/ceval.c | 142 ++++++++++++++++++++++++++++++++++++++------------------- 1 file changed, 94 insertions(+), 48 deletions(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index 7908d444e1..a32d685f08 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1932,11 +1932,26 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) TARGET(LOAD_BUILD_CLASS) { _Py_IDENTIFIER(__build_class__); - x = _PyDict_GetItemId(f->f_builtins, &PyId___build_class__); - if (x == NULL) { - PyErr_SetString(PyExc_ImportError, - "__build_class__ not found"); - break; + + 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; + } + } + 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); @@ -2078,12 +2093,24 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) 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 (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; + } + } + 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); @@ -2093,50 +2120,69 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) TARGET(LOAD_GLOBAL) w = GETITEM(names, oparg); - if (PyUnicode_CheckExact(w)) { - /* Inline the PyDict_GetItem() calls. - WARNING: this is an extreme speed hack. - Do not try this at home. */ - Py_hash_t hash = ((PyASCIIObject *)w)->hash; - if (hash != -1) { - PyDictObject *d; - PyDictEntry *e; - d = (PyDictObject *)(f->f_globals); - e = d->ma_lookup(d, w, hash); - if (e == NULL) { - x = NULL; - break; - } - x = e->me_value; - if (x != NULL) { - Py_INCREF(x); - PUSH(x); - DISPATCH(); + if (PyDict_CheckExact(f->f_globals) + && PyDict_CheckExact(f->f_builtins)) { + if (PyUnicode_CheckExact(w)) { + /* Inline the PyDict_GetItem() calls. + WARNING: this is an extreme speed hack. + Do not try this at home. */ + Py_hash_t hash = ((PyASCIIObject *)w)->hash; + if (hash != -1) { + PyDictObject *d; + PyDictEntry *e; + d = (PyDictObject *)(f->f_globals); + e = d->ma_lookup(d, w, hash); + if (e == NULL) { + x = NULL; + break; + } + x = e->me_value; + if (x != NULL) { + Py_INCREF(x); + PUSH(x); + DISPATCH(); + } + d = (PyDictObject *)(f->f_builtins); + e = d->ma_lookup(d, w, hash); + if (e == NULL) { + x = NULL; + break; + } + x = e->me_value; + if (x != NULL) { + Py_INCREF(x); + PUSH(x); + DISPATCH(); + } + goto load_global_error; } - d = (PyDictObject *)(f->f_builtins); - e = d->ma_lookup(d, w, hash); - if (e == NULL) { - x = NULL; + } + /* 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; } - x = e->me_value; - if (x != NULL) { - Py_INCREF(x); - PUSH(x); - DISPATCH(); - } - goto load_global_error; } + Py_INCREF(x); + PUSH(x); + DISPATCH(); } - /* This is the un-inlined version of the code above */ - x = PyDict_GetItem(f->f_globals, w); + + /* Slow-path if globals or builtins is not a dict */ + x = PyObject_GetItem(f->f_globals, w); if (x == NULL) { - x = PyDict_GetItem(f->f_builtins, w); + x = PyObject_GetItem(f->f_builtins, w); if (x == NULL) { - load_global_error: - format_exc_check_arg( - PyExc_NameError, - GLOBAL_NAME_ERROR_MSG, w); + if (PyErr_ExceptionMatches(PyExc_KeyError)) + format_exc_check_arg( + PyExc_NameError, + GLOBAL_NAME_ERROR_MSG, w); break; } } -- cgit v1.2.1 From 46b682030355f0f4ac9ac5d743e1840143b8695c Mon Sep 17 00:00:00 2001 From: Antoine Pitrou Date: Thu, 19 Apr 2012 18:21:04 +0200 Subject: Fix refleak: PyObject_GetItem returns a new reference, not a borrowed one like PyDict_GetItem. --- Python/ceval.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index a32d685f08..fde7841e2d 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1940,6 +1940,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) "__build_class__ not found"); break; } + Py_INCREF(x); } else { PyObject *build_class_str = _PyUnicode_FromId(&PyId___build_class__); @@ -1953,7 +1954,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) break; } } - Py_INCREF(x); PUSH(x); break; } @@ -2092,6 +2092,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) } if (x == NULL) { x = PyDict_GetItem(f->f_globals, w); + Py_XINCREF(x); if (x == NULL) { if (PyDict_CheckExact(f->f_builtins)) { x = PyDict_GetItem(f->f_builtins, w); @@ -2101,6 +2102,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) NAME_ERROR_MSG, w); break; } + Py_INCREF(x); } else { x = PyObject_GetItem(f->f_builtins, w); @@ -2113,7 +2115,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) } } } - Py_INCREF(x); } PUSH(x); DISPATCH(); @@ -2186,7 +2187,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) break; } } - Py_INCREF(x); PUSH(x); DISPATCH(); -- cgit v1.2.1 From ae34dd246694454660cfeaeab1e71e1f123f56d4 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 23 Apr 2012 11:24:50 -0400 Subject: Implement PEP 412: Key-sharing dictionaries (closes #13903) Patch from Mark Shannon. --- Python/ceval.c | 75 ++++++++++++++-------------------------------------------- 1 file changed, 18 insertions(+), 57 deletions(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index fde7841e2d..a4e5a327df 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2123,70 +2123,31 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) w = GETITEM(names, oparg); if (PyDict_CheckExact(f->f_globals) && PyDict_CheckExact(f->f_builtins)) { - if (PyUnicode_CheckExact(w)) { - /* Inline the PyDict_GetItem() calls. - WARNING: this is an extreme speed hack. - Do not try this at home. */ - Py_hash_t hash = ((PyASCIIObject *)w)->hash; - if (hash != -1) { - PyDictObject *d; - PyDictEntry *e; - d = (PyDictObject *)(f->f_globals); - e = d->ma_lookup(d, w, hash); - if (e == NULL) { - x = NULL; - break; - } - x = e->me_value; - if (x != NULL) { - Py_INCREF(x); - PUSH(x); - DISPATCH(); - } - d = (PyDictObject *)(f->f_builtins); - e = d->ma_lookup(d, w, hash); - if (e == NULL) { - x = NULL; - break; - } - x = e->me_value; - if (x != NULL) { - Py_INCREF(x); - PUSH(x); - DISPATCH(); - } - goto load_global_error; - } + 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; } - /* This is the un-inlined version of the code above */ - x = PyDict_GetItem(f->f_globals, w); + } + else { + /* Slow-path if globals or builtins is not a dict */ + x = PyObject_GetItem(f->f_globals, w); if (x == NULL) { - x = PyDict_GetItem(f->f_builtins, w); + x = PyObject_GetItem(f->f_builtins, w); if (x == NULL) { - load_global_error: - format_exc_check_arg( - PyExc_NameError, - GLOBAL_NAME_ERROR_MSG, w); + if (PyErr_ExceptionMatches(PyExc_KeyError)) + format_exc_check_arg( + PyExc_NameError, + GLOBAL_NAME_ERROR_MSG, w); break; } } - Py_INCREF(x); - PUSH(x); - DISPATCH(); - } - - /* Slow-path if globals or builtins is not a dict */ - x = PyObject_GetItem(f->f_globals, w); - if (x == NULL) { - 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(); -- cgit v1.2.1 From 9acba005f60545d2de253976fbdaa80ca0819497 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Thu, 26 Apr 2012 00:26:37 -0400 Subject: only incref when using borrowing functions --- Python/ceval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index a4e5a327df..b9a006b675 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -2132,6 +2132,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) GLOBAL_NAME_ERROR_MSG, w); break; } + Py_INCREF(x); } else { /* Slow-path if globals or builtins is not a dict */ @@ -2147,7 +2148,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) } } } - Py_INCREF(x); PUSH(x); DISPATCH(); -- cgit v1.2.1 From 9031c8f35aa4af460cb1507b2fc1ec8f78601327 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 14 May 2012 22:09:31 -0700 Subject: PEP 415: Implement suppression of __context__ display with an exception attribute This replaces the original PEP 409 implementation. See #14133. --- Python/ceval.c | 21 ++++++++++++--------- 1 file changed, 12 insertions(+), 9 deletions(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index b9a006b675..718bb32b56 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3572,23 +3572,26 @@ do_raise(PyObject *exc, PyObject *cause) if (cause) { PyObject *fixed_cause; - int result; if (PyExceptionClass_Check(cause)) { fixed_cause = PyObject_CallObject(cause, NULL); if (fixed_cause == NULL) goto raise_error; - Py_CLEAR(cause); - } else { - /* Let "exc.__cause__ = cause" handle all further checks */ + Py_DECREF(cause); + } + else if (PyExceptionInstance_Check(cause)) { fixed_cause = cause; - cause = NULL; /* Steal the reference */ } - /* We retain ownership of the reference to fixed_cause */ - result = _PyException_SetCauseChecked(value, fixed_cause); - Py_DECREF(fixed_cause); - if (result < 0) { + else if (cause == Py_None) { + Py_DECREF(cause); + fixed_cause = NULL; + } + else { + PyErr_SetString(PyExc_TypeError, + "exception causes must derive from " + "BaseException"); goto raise_error; } + PyException_SetCause(value, fixed_cause); } PyErr_SetObject(type, value); -- cgit v1.2.1 From 62658b334269ecd11edcebcdcfd7f6ebb5c55988 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Fri, 1 Jun 2012 11:18:22 -0700 Subject: check return for error --- Python/ceval.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index 718bb32b56..b3ec013e17 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -3107,6 +3107,8 @@ format_missing(const char *kind, PyCodeObject *co, PyObject *names) 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); -- cgit v1.2.1 From 6f05005995c33fa2ce64b4132fe97cd3684f6caf Mon Sep 17 00:00:00 2001 From: Nick Coghlan Date: Sun, 17 Jun 2012 15:15:49 +1000 Subject: Issue #13783: the PEP 380 implementation no longer expands the public C API --- Python/ceval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index b3ec013e17..7e9318bc0b 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1852,7 +1852,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) PyObject *val; x = POP(); /* Remove iter from stack */ Py_DECREF(x); - err = PyGen_FetchStopIterationValue(&val); + err = _PyGen_FetchStopIterationValue(&val); if (err < 0) { x = NULL; break; -- cgit v1.2.1 From f7855defe4c631c0821e773adc9c6c12e1062425 Mon Sep 17 00:00:00 2001 From: Benjamin Peterson Date: Mon, 6 Aug 2012 17:53:09 -0700 Subject: fix yield from return value on custom iterators (closes #15568) --- Python/ceval.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'Python/ceval.c') diff --git a/Python/ceval.c b/Python/ceval.c index 7e9318bc0b..82bfcc6128 100644 --- a/Python/ceval.c +++ b/Python/ceval.c @@ -1843,7 +1843,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag) } else { _Py_IDENTIFIER(send); if (u == Py_None) - retval = PyIter_Next(x); + retval = Py_TYPE(x)->tp_iternext(x); else retval = _PyObject_CallMethodId(x, &PyId_send, "O", u); } -- cgit v1.2.1