summaryrefslogtreecommitdiff
path: root/Python/ceval.c
diff options
context:
space:
mode:
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c505
1 files changed, 385 insertions, 120 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 1e44b1cc9c..10dd3a1f29 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -27,10 +27,11 @@
typedef unsigned long long uint64;
-#if defined(__ppc__) /* <- Don't know if this is the correct symbol; this
- section should work for GCC on any PowerPC
- platform, irrespective of OS.
- POWER? Who knows :-) */
+/* PowerPC support.
+ "__ppc__" appears to be the preprocessor definition to detect on OS X, whereas
+ "__powerpc__" appears to be the correct one for Linux with GCC
+*/
+#if defined(__ppc__) || defined (__powerpc__)
#define READ_TIMESTAMP(var) ppc_getcounter(&var)
@@ -146,6 +147,7 @@ static void format_exc_check_arg(PyObject *, char *, PyObject *);
static PyObject * string_concatenate(PyObject *, PyObject *,
PyFrameObject *, unsigned char *);
static PyObject * kwd_as_string(PyObject *);
+static PyObject * special_lookup(PyObject *, char *, PyObject **);
#define NAME_ERROR_MSG \
"name '%.200s' is not defined"
@@ -232,6 +234,7 @@ PyEval_GetCallStats(PyObject *self)
#include "pythread.h"
static PyThread_type_lock interpreter_lock = 0; /* This is the GIL */
+static PyThread_type_lock pending_lock = 0; /* for pending calls */
static long main_thread = 0;
int
@@ -303,6 +306,7 @@ PyEval_ReInitThreads(void)
adding a new function to each thread_*.h. Instead, just
create a new lock and waste a little bit of memory */
interpreter_lock = PyThread_allocate_lock();
+ pending_lock = PyThread_allocate_lock();
PyThread_acquire_lock(interpreter_lock, 1);
main_thread = PyThread_get_thread_ident();
@@ -375,19 +379,145 @@ PyEval_RestoreThread(PyThreadState *tstate)
#ifdef WITH_THREAD
Any thread can schedule pending calls, but only the main thread
will execute them.
+ There is no facility to schedule calls to a particular thread, but
+ that should be easy to change, should that ever be required. In
+ that case, the static variables here should go into the python
+ threadstate.
#endif
+*/
+
+#ifdef WITH_THREAD
+
+/* The WITH_THREAD implementation is thread-safe. It allows
+ scheduling to be made from any thread, and even from an executing
+ callback.
+ */
+
+#define NPENDINGCALLS 32
+static struct {
+ int (*func)(void *);
+ void *arg;
+} pendingcalls[NPENDINGCALLS];
+static int pendingfirst = 0;
+static int pendinglast = 0;
+static volatile int pendingcalls_to_do = 1; /* trigger initialization of lock */
+static char pendingbusy = 0;
+
+int
+Py_AddPendingCall(int (*func)(void *), void *arg)
+{
+ int i, j, result=0;
+ PyThread_type_lock lock = pending_lock;
+
+ /* try a few times for the lock. Since this mechanism is used
+ * for signal handling (on the main thread), there is a (slim)
+ * chance that a signal is delivered on the same thread while we
+ * hold the lock during the Py_MakePendingCalls() function.
+ * This avoids a deadlock in that case.
+ * Note that signals can be delivered on any thread. In particular,
+ * on Windows, a SIGINT is delivered on a system-created worker
+ * thread.
+ * We also check for lock being NULL, in the unlikely case that
+ * this function is called before any bytecode evaluation takes place.
+ */
+ if (lock != NULL) {
+ for (i = 0; i<100; i++) {
+ if (PyThread_acquire_lock(lock, NOWAIT_LOCK))
+ break;
+ }
+ if (i == 100)
+ return -1;
+ }
+
+ i = pendinglast;
+ j = (i + 1) % NPENDINGCALLS;
+ if (j == pendingfirst) {
+ result = -1; /* Queue full */
+ } else {
+ pendingcalls[i].func = func;
+ pendingcalls[i].arg = arg;
+ pendinglast = j;
+ }
+ /* signal main loop */
+ _Py_Ticker = 0;
+ pendingcalls_to_do = 1;
+ if (lock != NULL)
+ PyThread_release_lock(lock);
+ return result;
+}
+
+int
+Py_MakePendingCalls(void)
+{
+ int i;
+ int r = 0;
+
+ if (!pending_lock) {
+ /* initial allocation of the lock */
+ pending_lock = PyThread_allocate_lock();
+ if (pending_lock == NULL)
+ return -1;
+ }
+
+ /* only service pending calls on main thread */
+ if (main_thread && PyThread_get_thread_ident() != main_thread)
+ return 0;
+ /* don't perform recursive pending calls */
+ if (pendingbusy)
+ return 0;
+ pendingbusy = 1;
+ /* perform a bounded number of calls, in case of recursion */
+ for (i=0; i<NPENDINGCALLS; i++) {
+ int j;
+ int (*func)(void *);
+ void *arg = NULL;
+
+ /* pop one item off the queue while holding the lock */
+ PyThread_acquire_lock(pending_lock, WAIT_LOCK);
+ j = pendingfirst;
+ if (j == pendinglast) {
+ func = NULL; /* Queue empty */
+ } else {
+ func = pendingcalls[j].func;
+ arg = pendingcalls[j].arg;
+ pendingfirst = (j + 1) % NPENDINGCALLS;
+ }
+ pendingcalls_to_do = pendingfirst != pendinglast;
+ PyThread_release_lock(pending_lock);
+ /* having released the lock, perform the callback */
+ if (func == NULL)
+ break;
+ r = func(arg);
+ if (r)
+ break;
+ }
+ pendingbusy = 0;
+ return r;
+}
+
+#else /* if ! defined WITH_THREAD */
+
+/*
+ WARNING! ASYNCHRONOUSLY EXECUTING CODE!
+ This code is used for signal handling in python that isn't built
+ with WITH_THREAD.
+ Don't use this implementation when Py_AddPendingCalls() can happen
+ on a different thread!
- XXX WARNING! ASYNCHRONOUSLY EXECUTING CODE!
There are two possible race conditions:
- (1) nested asynchronous registry calls;
- (2) registry calls made while pending calls are being processed.
- While (1) is very unlikely, (2) is a real possibility.
+ (1) nested asynchronous calls to Py_AddPendingCall()
+ (2) AddPendingCall() calls made while pending calls are being processed.
+
+ (1) is very unlikely because typically signal delivery
+ is blocked during signal handling. So it should be impossible.
+ (2) is a real possibility.
The current code is safe against (2), but not against (1).
The safety against (2) is derived from the fact that only one
- thread (the main thread) ever takes things out of the queue.
-
- XXX Darn! With the advent of thread state, we should have an array
- of pending calls per thread in the thread state! Later...
+ thread is present, interrupted by signals, and that the critical
+ section is protected with the "busy" variable. On Windows, which
+ delivers SIGINT on a system thread, this does not hold and therefore
+ Windows really shouldn't use this version.
+ The two threads could theoretically wiggle around the "busy" variable.
*/
#define NPENDINGCALLS 32
@@ -397,7 +527,7 @@ static struct {
} pendingcalls[NPENDINGCALLS];
static volatile int pendingfirst = 0;
static volatile int pendinglast = 0;
-static volatile int things_to_do = 0;
+static volatile int pendingcalls_to_do = 0;
int
Py_AddPendingCall(int (*func)(void *), void *arg)
@@ -405,8 +535,6 @@ Py_AddPendingCall(int (*func)(void *), void *arg)
static volatile int busy = 0;
int i, j;
/* XXX Begin critical section */
- /* XXX If you want this to be safe against nested
- XXX asynchronous calls, you'll have to work harder! */
if (busy)
return -1;
busy = 1;
@@ -421,7 +549,7 @@ Py_AddPendingCall(int (*func)(void *), void *arg)
pendinglast = j;
_Py_Ticker = 0;
- things_to_do = 1; /* Signal main loop */
+ pendingcalls_to_do = 1; /* Signal main loop */
busy = 0;
/* XXX End critical section */
return 0;
@@ -431,14 +559,10 @@ int
Py_MakePendingCalls(void)
{
static int busy = 0;
-#ifdef WITH_THREAD
- if (main_thread && PyThread_get_thread_ident() != main_thread)
- return 0;
-#endif
if (busy)
return 0;
busy = 1;
- things_to_do = 0;
+ pendingcalls_to_do = 0;
for (;;) {
int i;
int (*func)(void *);
@@ -451,7 +575,7 @@ Py_MakePendingCalls(void)
pendingfirst = (i + 1) % NPENDINGCALLS;
if (func(arg) < 0) {
busy = 0;
- things_to_do = 1; /* We're not done yet */
+ pendingcalls_to_do = 1; /* We're not done yet */
return -1;
}
}
@@ -459,6 +583,8 @@ Py_MakePendingCalls(void)
return 0;
}
+#endif /* WITH_THREAD */
+
/* The interpreter's recursion limit */
@@ -533,7 +659,7 @@ static int _Py_TracingPossible = 0;
/* for manipulating the thread switch and periodic "stuff" - used to be
per thread, now just a pair o' globals */
int _Py_CheckInterval = 100;
-volatile int _Py_Ticker = 100;
+volatile int _Py_Ticker = 0; /* so that we hit a "tick" first thing */
PyObject *
PyEval_EvalCode(PyCodeObject *co, PyObject *globals, PyObject *locals)
@@ -658,8 +784,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
/* OpCode prediction macros
Some opcodes tend to come in pairs thus making it possible to
predict the second code when the first is run. For example,
- COMPARE_OP is often followed by JUMP_IF_FALSE or JUMP_IF_TRUE. And,
- those opcodes are often followed by a POP_TOP.
+ GET_ITER is often followed by FOR_ITER. And FOR_ITER is often
+ followed by STORE_FAST or UNPACK_SEQUENCE.
Verifying the prediction costs a single high-speed test of a register
variable against a constant. If the pairing was good, then the
@@ -696,10 +822,12 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
#define SECOND() (stack_pointer[-2])
#define THIRD() (stack_pointer[-3])
#define FOURTH() (stack_pointer[-4])
+#define PEEK(n) (stack_pointer[-(n)])
#define SET_TOP(v) (stack_pointer[-1] = (v))
#define SET_SECOND(v) (stack_pointer[-2] = (v))
#define SET_THIRD(v) (stack_pointer[-3] = (v))
#define SET_FOURTH(v) (stack_pointer[-4] = (v))
+#define SET_VALUE(n, v) (stack_pointer[-(n)] = (v))
#define BASIC_STACKADJ(n) (stack_pointer += n)
#define BASIC_PUSH(v) (*stack_pointer++ = (v))
#define BASIC_POP() (*--stack_pointer)
@@ -851,7 +979,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
/* Do periodic things. Doing this every time through
the loop would add too much overhead, so we do it
only every Nth instruction. We also do it if
- ``things_to_do'' is set, i.e. when an asynchronous
+ ``pendingcalls_to_do'' is set, i.e. when an asynchronous
event needs attention (e.g. a signal handler or
async I/O handler); see Py_AddPendingCall() and
Py_MakePendingCalls() above. */
@@ -859,7 +987,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
if (--_Py_Ticker < 0) {
if (*next_instr == SETUP_FINALLY) {
/* Make the last opcode before
- a try: finally: block uninterruptable. */
+ a try: finally: block uninterruptible. */
goto fast_next_opcode;
}
_Py_Ticker = _Py_CheckInterval;
@@ -867,12 +995,12 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
#ifdef WITH_TSC
ticked = 1;
#endif
- if (things_to_do) {
+ if (pendingcalls_to_do) {
if (Py_MakePendingCalls() < 0) {
why = WHY_EXCEPTION;
goto on_error;
}
- if (things_to_do)
+ if (pendingcalls_to_do)
/* MakePendingCalls() didn't succeed.
Force early re-execution of this
"periodic" code, possibly after
@@ -1004,7 +1132,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
SETLOCAL(oparg, v);
goto fast_next_opcode;
- PREDICTED(POP_TOP);
case POP_TOP:
v = POP();
Py_DECREF(v);
@@ -1177,7 +1304,10 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
case BINARY_MODULO:
w = POP();
v = TOP();
- x = PyNumber_Remainder(v, w);
+ if (PyString_CheckExact(v))
+ x = PyString_Format(v, w);
+ else
+ x = PyNumber_Remainder(v, w);
Py_DECREF(v);
Py_DECREF(w);
SET_TOP(x);
@@ -1317,9 +1447,19 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
case LIST_APPEND:
w = POP();
- v = POP();
+ v = PEEK(oparg);
err = PyList_Append(v, w);
- Py_DECREF(v);
+ Py_DECREF(w);
+ if (err == 0) {
+ PREDICT(JUMP_ABSOLUTE);
+ continue;
+ }
+ break;
+
+ case SET_ADD:
+ w = POP();
+ v = stack_pointer[-oparg];
+ err = PySet_Add(v, w);
Py_DECREF(w);
if (err == 0) {
PREDICT(JUMP_ABSOLUTE);
@@ -1848,7 +1988,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
}
} else if (unpack_iterable(v, oparg,
stack_pointer + oparg)) {
- stack_pointer += oparg;
+ STACKADJ(oparg);
} else {
/* unpack_iterable() raised an exception */
why = WHY_EXCEPTION;
@@ -2058,6 +2198,25 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
}
break;
+ case BUILD_SET:
+ x = PySet_New(NULL);
+ if (x != NULL) {
+ for (; --oparg >= 0;) {
+ w = POP();
+ if (err == 0)
+ err = PySet_Add(x, w);
+ Py_DECREF(w);
+ }
+ if (err != 0) {
+ Py_DECREF(x);
+ break;
+ }
+ PUSH(x);
+ continue;
+ }
+ break;
+
+
case BUILD_MAP:
x = _PyDict_NewPresized((Py_ssize_t)oparg);
PUSH(x);
@@ -2076,6 +2235,21 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
if (err == 0) continue;
break;
+ case MAP_ADD:
+ w = TOP(); /* key */
+ u = SECOND(); /* value */
+ STACKADJ(-2);
+ v = stack_pointer[-oparg]; /* dict */
+ assert (PyDict_CheckExact(v));
+ err = PyDict_SetItem(v, w, u); /* v[w] = u */
+ Py_DECREF(u);
+ Py_DECREF(w);
+ if (err == 0) {
+ PREDICT(JUMP_ABSOLUTE);
+ continue;
+ }
+ break;
+
case LOAD_ATTR:
w = GETITEM(names, oparg);
v = TOP();
@@ -2116,8 +2290,8 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
Py_DECREF(w);
SET_TOP(x);
if (x == NULL) break;
- PREDICT(JUMP_IF_FALSE);
- PREDICT(JUMP_IF_TRUE);
+ PREDICT(POP_JUMP_IF_FALSE);
+ PREDICT(POP_JUMP_IF_TRUE);
continue;
case IMPORT_NAME:
@@ -2194,41 +2368,45 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
JUMPBY(oparg);
goto fast_next_opcode;
- PREDICTED_WITH_ARG(JUMP_IF_FALSE);
- case JUMP_IF_FALSE:
- w = TOP();
+ PREDICTED_WITH_ARG(POP_JUMP_IF_FALSE);
+ case POP_JUMP_IF_FALSE:
+ w = POP();
if (w == Py_True) {
- PREDICT(POP_TOP);
+ Py_DECREF(w);
goto fast_next_opcode;
}
if (w == Py_False) {
- JUMPBY(oparg);
+ Py_DECREF(w);
+ JUMPTO(oparg);
goto fast_next_opcode;
}
err = PyObject_IsTrue(w);
+ Py_DECREF(w);
if (err > 0)
err = 0;
else if (err == 0)
- JUMPBY(oparg);
+ JUMPTO(oparg);
else
break;
continue;
- PREDICTED_WITH_ARG(JUMP_IF_TRUE);
- case JUMP_IF_TRUE:
- w = TOP();
+ PREDICTED_WITH_ARG(POP_JUMP_IF_TRUE);
+ case POP_JUMP_IF_TRUE:
+ w = POP();
if (w == Py_False) {
- PREDICT(POP_TOP);
+ Py_DECREF(w);
goto fast_next_opcode;
}
if (w == Py_True) {
- JUMPBY(oparg);
+ Py_DECREF(w);
+ JUMPTO(oparg);
goto fast_next_opcode;
}
err = PyObject_IsTrue(w);
+ Py_DECREF(w);
if (err > 0) {
err = 0;
- JUMPBY(oparg);
+ JUMPTO(oparg);
}
else if (err == 0)
;
@@ -2236,6 +2414,53 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
break;
continue;
+ case JUMP_IF_FALSE_OR_POP:
+ w = TOP();
+ if (w == Py_True) {
+ STACKADJ(-1);
+ Py_DECREF(w);
+ goto fast_next_opcode;
+ }
+ if (w == Py_False) {
+ JUMPTO(oparg);
+ goto fast_next_opcode;
+ }
+ err = PyObject_IsTrue(w);
+ if (err > 0) {
+ STACKADJ(-1);
+ Py_DECREF(w);
+ err = 0;
+ }
+ else if (err == 0)
+ JUMPTO(oparg);
+ else
+ break;
+ continue;
+
+ case JUMP_IF_TRUE_OR_POP:
+ w = TOP();
+ if (w == Py_False) {
+ STACKADJ(-1);
+ Py_DECREF(w);
+ goto fast_next_opcode;
+ }
+ if (w == Py_True) {
+ JUMPTO(oparg);
+ goto fast_next_opcode;
+ }
+ err = PyObject_IsTrue(w);
+ if (err > 0) {
+ err = 0;
+ JUMPTO(oparg);
+ }
+ else if (err == 0) {
+ STACKADJ(-1);
+ Py_DECREF(w);
+ }
+ else
+ break;
+ continue;
+
PREDICTED_WITH_ARG(JUMP_ABSOLUTE);
case JUMP_ABSOLUTE:
JUMPTO(oparg);
@@ -2313,6 +2538,35 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
STACK_LEVEL());
continue;
+ case SETUP_WITH:
+ {
+ static PyObject *exit, *enter;
+ w = TOP();
+ x = special_lookup(w, "__exit__", &exit);
+ if (!x)
+ break;
+ SET_TOP(x);
+ u = special_lookup(w, "__enter__", &enter);
+ Py_DECREF(w);
+ if (!u) {
+ x = NULL;
+ break;
+ }
+ x = PyObject_CallFunctionObjArgs(u, NULL);
+ Py_DECREF(u);
+ if (!x)
+ break;
+ /* Setup a finally block (SETUP_WITH as a block is
+ equivalent to SETUP_FINALLY except it normalizes
+ the exception) before pushing the result of
+ __enter__ on the stack. */
+ PyFrame_BlockSetup(f, SETUP_WITH, INSTR_OFFSET() + oparg,
+ STACK_LEVEL());
+
+ PUSH(x);
+ continue;
+ }
+
case WITH_CLEANUP:
{
/* At the top of the stack are 1-3 values indicating
@@ -2444,7 +2698,6 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
Py_DECREF(*pfunc);
*pfunc = self;
na++;
- n++;
} else
Py_INCREF(func);
sp = stack_pointer;
@@ -2544,7 +2797,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
default:
fprintf(stderr,
"XXX lineno: %d, opcode: %d\n",
- PyCode_Addr2Line(f->f_code, f->f_lasti),
+ PyFrame_GetLineNumber(f),
opcode);
PyErr_SetString(PyExc_SystemError, "unknown opcode");
why = WHY_EXCEPTION;
@@ -2622,20 +2875,20 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
fast_block_end:
while (why != WHY_NOT && f->f_iblock > 0) {
- PyTryBlock *b = PyFrame_BlockPop(f);
+ /* Peek at the current block. */
+ PyTryBlock *b = &f->f_blockstack[f->f_iblock - 1];
assert(why != WHY_YIELD);
if (b->b_type == SETUP_LOOP && why == WHY_CONTINUE) {
- /* For a continue inside a try block,
- don't pop the block for the loop. */
- PyFrame_BlockSetup(f, b->b_type, b->b_handler,
- b->b_level);
why = WHY_NOT;
JUMPTO(PyInt_AS_LONG(retval));
Py_DECREF(retval);
break;
}
+ /* Now we have to pop the block. */
+ f->f_iblock--;
+
while (STACK_LEVEL() > b->b_level) {
v = POP();
Py_XDECREF(v);
@@ -2647,7 +2900,8 @@ fast_block_end:
}
if (b->b_type == SETUP_FINALLY ||
(b->b_type == SETUP_EXCEPT &&
- why == WHY_EXCEPTION)) {
+ why == WHY_EXCEPTION) ||
+ b->b_type == SETUP_WITH) {
if (why == WHY_EXCEPTION) {
PyObject *exc, *val, *tb;
PyErr_Fetch(&exc, &val, &tb);
@@ -2660,7 +2914,8 @@ fast_block_end:
so a program can emulate the
Python main loop. Don't do
this for 'finally'. */
- if (b->b_type == SETUP_EXCEPT) {
+ if (b->b_type == SETUP_EXCEPT ||
+ b->b_type == SETUP_WITH) {
PyErr_NormalizeException(
&exc, &val, &tb);
set_exc_info(tstate,
@@ -2800,13 +3055,12 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
if (!(co->co_flags & CO_VARARGS)) {
PyErr_Format(PyExc_TypeError,
"%.200s() takes %s %d "
- "%sargument%s (%d given)",
+ "argument%s (%d given)",
PyString_AsString(co->co_name),
defcount ? "at most" : "exactly",
co->co_argcount,
- kwcount ? "non-keyword " : "",
co->co_argcount == 1 ? "" : "s",
- argcount);
+ argcount + kwcount);
goto fail;
}
n = co->co_argcount;
@@ -2832,8 +3086,11 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
PyObject *keyword = kws[2*i];
PyObject *value = kws[2*i + 1];
int j;
- if (keyword == NULL || !(PyString_Check(keyword) ||
- PyUnicode_Check(keyword))) {
+ if (keyword == NULL || !(PyString_Check(keyword)
+#ifdef Py_USING_UNICODE
+ || PyUnicode_Check(keyword)
+#endif
+ )) {
PyErr_Format(PyExc_TypeError,
"%.200s() keywords must be strings",
PyString_AsString(co->co_name));
@@ -2841,7 +3098,7 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
}
/* Speed hack: do raw pointer compares. As names are
normally interned this should almost always hit. */
- co_varnames = PySequence_Fast_ITEMS(co->co_varnames);
+ co_varnames = ((PyTupleObject *)(co->co_varnames))->ob_item;
for (j = 0; j < co->co_argcount; j++) {
PyObject *nm = co_varnames[j];
if (nm == keyword)
@@ -2857,26 +3114,21 @@ PyEval_EvalCodeEx(PyCodeObject *co, PyObject *globals, PyObject *locals,
else if (cmp < 0)
goto fail;
}
- /* Check errors from Compare */
- if (PyErr_Occurred())
- goto fail;
- if (j >= co->co_argcount) {
- if (kwdict == NULL) {
- PyObject *kwd_str = kwd_as_string(keyword);
- if (kwd_str) {
- PyErr_Format(PyExc_TypeError,
- "%.200s() got an unexpected "
- "keyword argument '%.400s'",
- PyString_AsString(co->co_name),
- PyString_AsString(kwd_str));
- Py_DECREF(kwd_str);
- }
- goto fail;
+ if (kwdict == NULL) {
+ PyObject *kwd_str = kwd_as_string(keyword);
+ if (kwd_str) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s() got an unexpected "
+ "keyword argument '%.400s'",
+ PyString_AsString(co->co_name),
+ PyString_AsString(kwd_str));
+ Py_DECREF(kwd_str);
}
- PyDict_SetItem(kwdict, keyword, value);
- continue;
+ goto fail;
}
-kw_found:
+ PyDict_SetItem(kwdict, keyword, value);
+ continue;
+ kw_found:
if (GETLOCAL(j) != NULL) {
PyObject *kwd_str = kwd_as_string(keyword);
if (kwd_str) {
@@ -2897,15 +3149,18 @@ kw_found:
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,
"%.200s() takes %s %d "
- "%sargument%s (%d given)",
+ "argument%s (%d given)",
PyString_AsString(co->co_name),
((co->co_flags & CO_VARARGS) ||
defcount) ? "at least"
: "exactly",
- m, kwcount ? "non-keyword " : "",
- m == 1 ? "" : "s", i);
+ m, m == 1 ? "" : "s", given);
goto fail;
}
}
@@ -2922,14 +3177,12 @@ kw_found:
}
}
}
- else {
- if (argcount > 0 || kwcount > 0) {
- PyErr_Format(PyExc_TypeError,
- "%.200s() takes no arguments (%d given)",
- PyString_AsString(co->co_name),
- argcount + kwcount);
- goto fail;
- }
+ else if (argcount > 0 || kwcount > 0) {
+ PyErr_Format(PyExc_TypeError,
+ "%.200s() takes no arguments (%d given)",
+ PyString_AsString(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. */
@@ -3015,13 +3268,37 @@ fail: /* Jump here from prelude on failure */
static PyObject *
+special_lookup(PyObject *o, char *meth, PyObject **cache)
+{
+ PyObject *res;
+ if (PyInstance_Check(o)) {
+ if (!*cache)
+ return PyObject_GetAttrString(o, meth);
+ else
+ return PyObject_GetAttr(o, *cache);
+ }
+ res = _PyObject_LookupSpecial(o, meth, cache);
+ if (res == NULL && !PyErr_Occurred()) {
+ PyErr_SetObject(PyExc_AttributeError, *cache);
+ return NULL;
+ }
+ return res;
+}
+
+
+static PyObject *
kwd_as_string(PyObject *kwd) {
+#ifdef Py_USING_UNICODE
if (PyString_Check(kwd)) {
+#else
+ assert(PyString_Check(kwd));
+#endif
Py_INCREF(kwd);
return kwd;
+#ifdef Py_USING_UNICODE
}
- else
- return _PyUnicode_AsDefaultEncodedString(kwd, "replace");
+ return _PyUnicode_AsDefaultEncodedString(kwd, "replace");
+#endif
}
@@ -3429,33 +3706,30 @@ _PyEval_CallTracing(PyObject *func, PyObject *args)
return result;
}
+/* See Objects/lnotab_notes.txt for a description of how tracing works. */
static int
maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
PyFrameObject *frame, int *instr_lb, int *instr_ub,
int *instr_prev)
{
int result = 0;
+ int line = frame->f_lineno;
/* If the last instruction executed isn't in the current
- instruction window, reset the window. If the last
- instruction happens to fall at the start of a line or if it
- represents a jump backwards, call the trace function.
+ instruction window, reset the window.
*/
- if ((frame->f_lasti < *instr_lb || frame->f_lasti >= *instr_ub)) {
- int line;
+ if (frame->f_lasti < *instr_lb || frame->f_lasti >= *instr_ub) {
PyAddrPair bounds;
-
- line = PyCode_CheckLineNumber(frame->f_code, frame->f_lasti,
- &bounds);
- if (line >= 0) {
- frame->f_lineno = line;
- result = call_trace(func, obj, frame,
- PyTrace_LINE, Py_None);
- }
+ line = _PyCode_CheckLineNumber(frame->f_code, frame->f_lasti,
+ &bounds);
*instr_lb = bounds.ap_lower;
*instr_ub = bounds.ap_upper;
}
- else if (frame->f_lasti <= *instr_prev) {
+ /* If the last instruction falls at the start of a line or if
+ it represents a jump backwards, update the frame's line
+ number and call the trace function. */
+ if (frame->f_lasti == *instr_lb || frame->f_lasti < *instr_prev) {
+ frame->f_lineno = line;
result = call_trace(func, obj, frame, PyTrace_LINE, Py_None);
}
*instr_prev = frame->f_lasti;
@@ -3578,18 +3852,7 @@ Py_FlushLine(void)
/* External interface to call any callable object.
- The arg must be a tuple or NULL. */
-
-#undef PyEval_CallObject
-/* for backward compatibility: export this interface */
-
-PyObject *
-PyEval_CallObject(PyObject *func, PyObject *arg)
-{
- return PyEval_CallObjectWithKeywords(func, arg, (PyObject *)NULL);
-}
-#define PyEval_CallObject(func,arg) \
- PyEval_CallObjectWithKeywords(func, arg, (PyObject *)NULL)
+ The arg must be a tuple or NULL. The kw must be a dict or NULL. */
PyObject *
PyEval_CallObjectWithKeywords(PyObject *func, PyObject *arg, PyObject *kw)
@@ -4417,7 +4680,9 @@ exec_statement(PyFrameObject *f, PyObject *prog, PyObject *globals,
else if (locals == Py_None)
locals = globals;
if (!PyString_Check(prog) &&
+#ifdef Py_USING_UNICODE
!PyUnicode_Check(prog) &&
+#endif
!PyCode_Check(prog) &&
!PyFile_Check(prog)) {
PyErr_SetString(PyExc_TypeError,