summaryrefslogtreecommitdiffstats
path: root/Python/ceval.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c172
1 files changed, 96 insertions, 76 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 6c8afba..80adc30 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -6,6 +6,9 @@
XXX document it!
*/
+/* enable more aggressive intra-module optimizations, where available */
+#define PY_LOCAL_AGGRESSIVE
+
#include "Python.h"
#include "code.h"
@@ -16,7 +19,7 @@
#include <ctype.h>
-#ifndef WITH_TSC
+#ifndef WITH_TSC
#define READ_TIMESTAMP(var)
@@ -41,7 +44,7 @@ ppc_getcounter(uint64 *v)
asm volatile ("mftbu %0" : "=r" (tbu2));
if (__builtin_expect(tbu != tbu2, 0)) goto loop;
- /* The slightly peculiar way of writing the next lines is
+ /* The slightly peculiar way of writing the next lines is
compiled better by GCC than any other way I tried. */
((long*)(v))[0] = tbu;
((long*)(v))[1] = tb;
@@ -54,7 +57,7 @@ ppc_getcounter(uint64 *v)
#endif
-void dump_tsc(int opcode, int ticked, uint64 inst0, uint64 inst1,
+void dump_tsc(int opcode, int ticked, uint64 inst0, uint64 inst1,
uint64 loop0, uint64 loop1, uint64 intr0, uint64 intr1)
{
uint64 intr, inst, loop;
@@ -83,16 +86,16 @@ typedef PyObject *(*callproc)(PyObject *, PyObject *, PyObject *);
/* Forward declarations */
#ifdef WITH_TSC
-static PyObject *call_function(PyObject ***, int, uint64*, uint64*);
+static PyObject * call_function(PyObject ***, int, uint64*, uint64*);
#else
-static PyObject *call_function(PyObject ***, int);
+static PyObject * call_function(PyObject ***, int);
#endif
-static PyObject *fast_function(PyObject *, PyObject ***, int, int, int);
-static PyObject *do_call(PyObject *, PyObject ***, int, int);
-static PyObject *ext_do_call(PyObject *, PyObject ***, int, int, int);
-static PyObject *update_keyword_args(PyObject *, int, PyObject ***,PyObject *);
-static PyObject *update_star_args(int, int, PyObject *, PyObject ***);
-static PyObject *load_args(PyObject ***, int);
+static PyObject * fast_function(PyObject *, PyObject ***, int, int, int);
+static PyObject * do_call(PyObject *, PyObject ***, int, int);
+static PyObject * ext_do_call(PyObject *, PyObject ***, int, int, int);
+static PyObject * update_keyword_args(PyObject *, int, PyObject ***,PyObject *);
+static PyObject * update_star_args(int, int, PyObject *, PyObject ***);
+static PyObject * load_args(PyObject ***, int);
#define CALL_FLAG_VAR 1
#define CALL_FLAG_KW 2
@@ -108,19 +111,19 @@ static void call_exc_trace(Py_tracefunc, PyObject *, PyFrameObject *);
static int maybe_call_line_trace(Py_tracefunc, PyObject *,
PyFrameObject *, int *, int *, int *);
-static PyObject *apply_slice(PyObject *, PyObject *, PyObject *);
+static PyObject * apply_slice(PyObject *, PyObject *, PyObject *);
static int assign_slice(PyObject *, PyObject *,
PyObject *, PyObject *);
-static PyObject *cmp_outcome(int, PyObject *, PyObject *);
-static PyObject *import_from(PyObject *, PyObject *);
+static PyObject * cmp_outcome(int, PyObject *, PyObject *);
+static PyObject * import_from(PyObject *, PyObject *);
static int import_all_from(PyObject *, PyObject *);
-static PyObject *build_class(PyObject *, PyObject *, PyObject *);
+static PyObject * build_class(PyObject *, PyObject *, PyObject *);
static int exec_statement(PyFrameObject *,
PyObject *, PyObject *, PyObject *);
static void set_exc_info(PyThreadState *, PyObject *, PyObject *, PyObject *);
static void reset_exc_info(PyThreadState *);
static void format_exc_check_arg(PyObject *, char *, PyObject *);
-static PyObject *string_concatenate(PyObject *, PyObject *,
+static PyObject * string_concatenate(PyObject *, PyObject *,
PyFrameObject *, unsigned char *);
#define NAME_ERROR_MSG \
@@ -559,7 +562,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
inst0 -- beginning of switch statement for opcode dispatch
inst1 -- end of switch statement (may be skipped)
loop0 -- the top of the mainloop
- loop1 -- place where control returns again to top of mainloop
+ loop1 -- place where control returns again to top of mainloop
(may be skipped)
intr1 -- beginning of long interruption
intr2 -- end of long interruption
@@ -654,11 +657,11 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
#ifdef LLTRACE
#define PUSH(v) { (void)(BASIC_PUSH(v), \
lltrace && prtrace(TOP(), "push")); \
- assert(STACK_LEVEL() <= f->f_stacksize); }
+ assert(STACK_LEVEL() <= co->co_stacksize); }
#define POP() ((void)(lltrace && prtrace(TOP(), "pop")), BASIC_POP())
#define STACKADJ(n) { (void)(BASIC_STACKADJ(n), \
lltrace && prtrace(TOP(), "stackadj")); \
- assert(STACK_LEVEL() <= f->f_stacksize); }
+ assert(STACK_LEVEL() <= co->co_stacksize); }
#define EXT_POP(STACK_POINTER) (lltrace && prtrace(*(STACK_POINTER), "ext_pop"), *--(STACK_POINTER))
#else
#define PUSH(v) BASIC_PUSH(v)
@@ -729,7 +732,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
names = co->co_names;
consts = co->co_consts;
fastlocals = f->f_localsplus;
- freevars = f->f_localsplus + f->f_nlocals;
+ freevars = f->f_localsplus + co->co_nlocals;
first_instr = (unsigned char*) PyString_AS_STRING(co->co_code);
/* An explanation is in order for the next line.
@@ -760,7 +763,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
why = WHY_EXCEPTION;
goto on_error;
}
-
+
for (;;) {
#ifdef WITH_TSC
if (inst1 == 0) {
@@ -780,7 +783,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
READ_TIMESTAMP(loop0);
#endif
assert(stack_pointer >= f->f_valuestack); /* else underflow */
- assert(STACK_LEVEL() <= f->f_stacksize); /* else overflow */
+ assert(STACK_LEVEL() <= co->co_stacksize); /* else overflow */
/* Do periodic things. Doing this every time through
the loop would add too much overhead, so we do it
@@ -1534,7 +1537,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
/* XXX move into writeobject() ? */
if (PyString_Check(v)) {
char *s = PyString_AS_STRING(v);
- int len = PyString_GET_SIZE(v);
+ Py_ssize_t len = PyString_GET_SIZE(v);
if (len == 0 ||
!isspace(Py_CHARMASK(s[len-1])) ||
s[len-1] == ' ')
@@ -1543,7 +1546,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
#ifdef Py_USING_UNICODE
else if (PyUnicode_Check(v)) {
Py_UNICODE *s = PyUnicode_AS_UNICODE(v);
- int len = PyUnicode_GET_SIZE(v);
+ Py_ssize_t len = PyUnicode_GET_SIZE(v);
if (len == 0 ||
!Py_UNICODE_ISSPACE(s[len-1]) ||
s[len-1] == ' ')
@@ -1890,17 +1893,17 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
/* Don't stomp existing exception */
if (PyErr_Occurred())
break;
- if (oparg < f->f_ncells) {
- v = PyTuple_GetItem(co->co_cellvars,
+ if (oparg < PyTuple_GET_SIZE(co->co_cellvars)) {
+ v = PyTuple_GET_ITEM(co->co_cellvars,
oparg);
format_exc_check_arg(
PyExc_UnboundLocalError,
UNBOUNDLOCAL_ERROR_MSG,
v);
} else {
- v = PyTuple_GetItem(
+ v = PyTuple_GET_ITEM(
co->co_freevars,
- oparg - f->f_ncells);
+ oparg - PyTuple_GET_SIZE(co->co_cellvars));
format_exc_check_arg(
PyExc_NameError,
UNBOUNDFREE_ERROR_MSG,
@@ -2147,6 +2150,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
case CONTINUE_LOOP:
retval = PyInt_FromLong(oparg);
+ if (!retval) {
+ x = NULL;
+ break;
+ }
why = WHY_CONTINUE;
goto fast_block_end;
@@ -2180,7 +2187,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
re-raising the exception. (But non-local gotos
should still be resumed.)
*/
-
+
x = TOP();
u = SECOND();
if (PyInt_Check(u) || u == Py_None) {
@@ -2543,7 +2550,12 @@ fast_yield:
}
}
- reset_exc_info(tstate);
+ if (tstate->frame->f_exc_type != NULL)
+ reset_exc_info(tstate);
+ else {
+ assert(tstate->frame->f_exc_value == NULL);
+ assert(tstate->frame->f_exc_traceback == NULL);
+ }
/* pop frame */
exit_eval_frame:
@@ -2580,7 +2592,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
return NULL;
fastlocals = f->f_localsplus;
- freevars = f->f_localsplus + f->f_nlocals;
+ freevars = f->f_localsplus + co->co_nlocals;
if (co->co_argcount > 0 ||
co->co_flags & (CO_VARARGS | CO_VARKEYWORDS)) {
@@ -2716,7 +2728,7 @@ PyEval_EvalCodeEx(PyCodeObject *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 (f->f_ncells) {
+ if (PyTuple_GET_SIZE(co->co_cellvars)) {
int i = 0, j = 0, nargs, found;
char *cellname, *argname;
PyObject *c;
@@ -2734,7 +2746,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
that are arguments at the beginning of the cellvars
list so that we can march over it more efficiently?
*/
- for (i = 0; i < f->f_ncells; ++i) {
+ for (i = 0; i < PyTuple_GET_SIZE(co->co_cellvars); ++i) {
cellname = PyString_AS_STRING(
PyTuple_GET_ITEM(co->co_cellvars, i));
found = 0;
@@ -2745,7 +2757,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
c = PyCell_New(GETLOCAL(j));
if (c == NULL)
goto fail;
- GETLOCAL(f->f_nlocals + i) = c;
+ GETLOCAL(co->co_nlocals + i) = c;
found = 1;
break;
}
@@ -2754,16 +2766,16 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
c = PyCell_New(NULL);
if (c == NULL)
goto fail;
- SETLOCAL(f->f_nlocals + i, c);
+ SETLOCAL(co->co_nlocals + i, c);
}
}
}
- if (f->f_nfreevars) {
+ if (PyTuple_GET_SIZE(co->co_freevars)) {
int i;
- for (i = 0; i < f->f_nfreevars; ++i) {
+ for (i = 0; i < PyTuple_GET_SIZE(co->co_freevars); ++i) {
PyObject *o = PyTuple_GET_ITEM(closure, i);
Py_INCREF(o);
- freevars[f->f_ncells + i] = o;
+ freevars[PyTuple_GET_SIZE(co->co_cellvars) + i] = o;
}
}
@@ -2808,6 +2820,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
- Once an exception is caught by an except clause, it is transferred
from tstate->curexc_ZZZ to tstate->exc_ZZZ, from which sys.exc_info()
can pick it up. This is the primary task of set_exc_info().
+ XXX That can't be right: set_exc_info() doesn't look at tstate->curexc_ZZZ.
- Now let me explain the complicated dance with frame->f_exc_ZZZ.
@@ -2862,35 +2875,33 @@ static void
set_exc_info(PyThreadState *tstate,
PyObject *type, PyObject *value, PyObject *tb)
{
- PyFrameObject *frame;
+ PyFrameObject *frame = tstate->frame;
PyObject *tmp_type, *tmp_value, *tmp_tb;
- frame = tstate->frame;
+ assert(type != NULL);
+ assert(frame != NULL);
if (frame->f_exc_type == NULL) {
- /* This frame didn't catch an exception before */
- /* Save previous exception of this thread in this frame */
+ assert(frame->f_exc_value == NULL);
+ assert(frame->f_exc_traceback == NULL);
+ /* This frame didn't catch an exception before. */
+ /* Save previous exception of this thread in this frame. */
if (tstate->exc_type == NULL) {
+ /* XXX Why is this set to Py_None? */
Py_INCREF(Py_None);
tstate->exc_type = Py_None;
}
- tmp_type = frame->f_exc_type;
- tmp_value = frame->f_exc_value;
- tmp_tb = frame->f_exc_traceback;
- Py_XINCREF(tstate->exc_type);
+ Py_INCREF(tstate->exc_type);
Py_XINCREF(tstate->exc_value);
Py_XINCREF(tstate->exc_traceback);
frame->f_exc_type = tstate->exc_type;
frame->f_exc_value = tstate->exc_value;
frame->f_exc_traceback = tstate->exc_traceback;
- Py_XDECREF(tmp_type);
- Py_XDECREF(tmp_value);
- Py_XDECREF(tmp_tb);
}
- /* Set new exception for this thread */
+ /* Set new exception for this thread. */
tmp_type = tstate->exc_type;
tmp_value = tstate->exc_value;
tmp_tb = tstate->exc_traceback;
- Py_XINCREF(type);
+ Py_INCREF(type);
Py_XINCREF(value);
Py_XINCREF(tb);
tstate->exc_type = type;
@@ -2910,33 +2921,42 @@ reset_exc_info(PyThreadState *tstate)
{
PyFrameObject *frame;
PyObject *tmp_type, *tmp_value, *tmp_tb;
+
+ /* It's a precondition that the thread state's frame caught an
+ * exception -- verify in a debug build.
+ */
+ assert(tstate != NULL);
frame = tstate->frame;
- if (frame->f_exc_type != NULL) {
- /* This frame caught an exception */
- tmp_type = tstate->exc_type;
- tmp_value = tstate->exc_value;
- tmp_tb = tstate->exc_traceback;
- Py_XINCREF(frame->f_exc_type);
- Py_XINCREF(frame->f_exc_value);
- Py_XINCREF(frame->f_exc_traceback);
- tstate->exc_type = frame->f_exc_type;
- tstate->exc_value = frame->f_exc_value;
- tstate->exc_traceback = frame->f_exc_traceback;
- Py_XDECREF(tmp_type);
- Py_XDECREF(tmp_value);
- Py_XDECREF(tmp_tb);
- /* For b/w compatibility */
- PySys_SetObject("exc_type", frame->f_exc_type);
- PySys_SetObject("exc_value", frame->f_exc_value);
- PySys_SetObject("exc_traceback", frame->f_exc_traceback);
- }
+ assert(frame != NULL);
+ assert(frame->f_exc_type != NULL);
+
+ /* Copy the frame's exception info back to the thread state. */
+ tmp_type = tstate->exc_type;
+ tmp_value = tstate->exc_value;
+ tmp_tb = tstate->exc_traceback;
+ Py_INCREF(frame->f_exc_type);
+ Py_XINCREF(frame->f_exc_value);
+ Py_XINCREF(frame->f_exc_traceback);
+ tstate->exc_type = frame->f_exc_type;
+ tstate->exc_value = frame->f_exc_value;
+ tstate->exc_traceback = frame->f_exc_traceback;
+ Py_XDECREF(tmp_type);
+ Py_XDECREF(tmp_value);
+ Py_XDECREF(tmp_tb);
+
+ /* For b/w compatibility */
+ PySys_SetObject("exc_type", frame->f_exc_type);
+ PySys_SetObject("exc_value", frame->f_exc_value);
+ PySys_SetObject("exc_traceback", frame->f_exc_traceback);
+
+ /* Clear the frame's exception info. */
tmp_type = frame->f_exc_type;
tmp_value = frame->f_exc_value;
tmp_tb = frame->f_exc_traceback;
frame->f_exc_type = NULL;
frame->f_exc_value = NULL;
frame->f_exc_traceback = NULL;
- Py_XDECREF(tmp_type);
+ Py_DECREF(tmp_type);
Py_XDECREF(tmp_value);
Py_XDECREF(tmp_tb);
}
@@ -3800,7 +3820,7 @@ _PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi)
Py_ssize_t x;
if (PyInt_Check(v)) {
x = PyInt_AsSsize_t(v);
- }
+ }
else if (v->ob_type->tp_as_number &&
PyType_HasFeature(v->ob_type, Py_TPFLAGS_HAVE_INDEX)
&& v->ob_type->tp_as_number->nb_index) {
@@ -4015,10 +4035,10 @@ build_class(PyObject *methods, PyObject *bases, PyObject *name)
metaclass = (PyObject *) &PyType_Type;
Py_INCREF(metaclass);
}
- result = PyObject_CallFunction(metaclass, "OOO", name, bases, methods);
+ result = PyObject_CallFunctionObjArgs(metaclass, name, bases, methods, NULL);
Py_DECREF(metaclass);
if (result == NULL && PyErr_ExceptionMatches(PyExc_TypeError)) {
- /* A type error here likely means that the user passed
+ /* A type error here likely means that the user passed
in a base that was not a class (such the random module
instead of the random.random type). Help them out with
by augmenting the error message with more information.*/
@@ -4158,7 +4178,7 @@ string_concatenate(PyObject *v, PyObject *w,
{
/* This function implements 'variable += expr' when both arguments
are strings. */
-
+
if (v->ob_refcnt == 2) {
/* In the common case, there are 2 references to the value
* stored in 'variable' when the += is performed: one on the
@@ -4176,7 +4196,7 @@ string_concatenate(PyObject *v, PyObject *w,
}
case STORE_DEREF:
{
- PyObject **freevars = f->f_localsplus + f->f_nlocals;
+ PyObject **freevars = f->f_localsplus + f->f_code->co_nlocals;
PyObject *c = freevars[PEEKARG()];
if (PyCell_GET(c) == v)
PyCell_Set(c, NULL);