summaryrefslogtreecommitdiffstats
path: root/Python/ceval.c
diff options
context:
space:
mode:
authorThomas Wouters <thomas@python.org>2006-04-21 10:40:58 (GMT)
committerThomas Wouters <thomas@python.org>2006-04-21 10:40:58 (GMT)
commit49fd7fa4431da299196d74087df4a04f99f9c46f (patch)
tree35ace5fe78d3d52c7a9ab356ab9f6dbf8d4b71f4 /Python/ceval.c
parent9ada3d6e29d5165dadacbe6be07bcd35cfbef59d (diff)
downloadcpython-49fd7fa4431da299196d74087df4a04f99f9c46f.zip
cpython-49fd7fa4431da299196d74087df4a04f99f9c46f.tar.gz
cpython-49fd7fa4431da299196d74087df4a04f99f9c46f.tar.bz2
Merge p3yk branch with the trunk up to revision 45595. This breaks a fair
number of tests, all because of the codecs/_multibytecodecs issue described here (it's not a Py3K issue, just something Py3K discovers): http://mail.python.org/pipermail/python-dev/2006-April/064051.html Hye-Shik Chang promised to look for a fix, so no need to fix it here. The tests that are expected to break are: test_codecencodings_cn test_codecencodings_hk test_codecencodings_jp test_codecencodings_kr test_codecencodings_tw test_codecs test_multibytecodec This merge fixes an actual test failure (test_weakref) in this branch, though, so I believe merging is the right thing to do anyway.
Diffstat (limited to 'Python/ceval.c')
-rw-r--r--Python/ceval.c150
1 files changed, 25 insertions, 125 deletions
diff --git a/Python/ceval.c b/Python/ceval.c
index 6f76781..6c8afba 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -507,7 +507,7 @@ PyEval_EvalFrame(PyFrameObject *f) {
}
PyObject *
-PyEval_EvalFrameEx(PyFrameObject *f, int throw)
+PyEval_EvalFrameEx(PyFrameObject *f, int throwflag)
{
#ifdef DXPAIRS
int lastopcode = 0;
@@ -756,7 +756,7 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throw)
x = Py_None; /* Not a reference, just anything non-NULL */
w = NULL;
- if (throw) { /* support for generator.throw() */
+ if (throwflag) { /* support for generator.throw() */
why = WHY_EXCEPTION;
goto on_error;
}
@@ -2153,6 +2153,9 @@ PyEval_EvalFrameEx(PyFrameObject *f, int throw)
case SETUP_LOOP:
case SETUP_EXCEPT:
case SETUP_FINALLY:
+ /* NOTE: If you add any new block-setup opcodes that are not try/except/finally
+ handlers, you may need to update the PyGen_NeedsFinalizing() function. */
+
PyFrame_BlockSetup(f, opcode, INSTR_OFFSET() + oparg,
STACK_LEVEL());
continue;
@@ -3180,132 +3183,29 @@ maybe_call_line_trace(Py_tracefunc func, PyObject *obj,
PyFrameObject *frame, int *instr_lb, int *instr_ub,
int *instr_prev)
{
- /* The theory of SET_LINENO-less tracing.
-
- In a nutshell, we use the co_lnotab field of the code object
- to tell when execution has moved onto a different line.
-
- As mentioned above, the basic idea is so set things up so
- that
-
- *instr_lb <= frame->f_lasti < *instr_ub
-
- is true so long as execution does not change lines.
-
- This is all fairly simple. Digging the information out of
- co_lnotab takes some work, but is conceptually clear.
-
- Somewhat harder to explain is why we don't *always* call the
- line trace function when the above test fails.
-
- Consider this code:
-
- 1: def f(a):
- 2: if a:
- 3: print 1
- 4: else:
- 5: print 2
-
- which compiles to this:
-
- 2 0 LOAD_FAST 0 (a)
- 3 JUMP_IF_FALSE 9 (to 15)
- 6 POP_TOP
-
- 3 7 LOAD_CONST 1 (1)
- 10 PRINT_ITEM
- 11 PRINT_NEWLINE
- 12 JUMP_FORWARD 6 (to 21)
- >> 15 POP_TOP
-
- 5 16 LOAD_CONST 2 (2)
- 19 PRINT_ITEM
- 20 PRINT_NEWLINE
- >> 21 LOAD_CONST 0 (None)
- 24 RETURN_VALUE
-
- If 'a' is false, execution will jump to instruction at offset
- 15 and the co_lnotab will claim that execution has moved to
- line 3. This is at best misleading. In this case we could
- associate the POP_TOP with line 4, but that doesn't make
- sense in all cases (I think).
-
- What we do is only call the line trace function if the co_lnotab
- indicates we have jumped to the *start* of a line, i.e. if the
- current instruction offset matches the offset given for the
- start of a line by the co_lnotab.
-
- This also takes care of the situation where 'a' is true.
- Execution will jump from instruction offset 12 to offset 21.
- Then the co_lnotab would imply that execution has moved to line
- 5, which is again misleading.
-
- Why do we set f_lineno when tracing? Well, consider the code
- above when 'a' is true. If stepping through this with 'n' in
- pdb, you would stop at line 1 with a "call" type event, then
- line events on lines 2 and 3, then a "return" type event -- but
- you would be shown line 5 during this event. This is a change
- from the behaviour in 2.2 and before, and I've found it
- confusing in practice. By setting and using f_lineno when
- tracing, one can report a line number different from that
- suggested by f_lasti on this one occasion where it's desirable.
- */
-
int result = 0;
+ /* 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.
+ */
if ((frame->f_lasti < *instr_lb || frame->f_lasti >= *instr_ub)) {
- PyCodeObject* co = frame->f_code;
- int size, addr, line;
- unsigned char* p;
-
- size = PyString_GET_SIZE(co->co_lnotab) / 2;
- p = (unsigned char*)PyString_AS_STRING(co->co_lnotab);
-
- addr = 0;
- line = co->co_firstlineno;
+ int line;
+ PyAddrPair bounds;
- /* possible optimization: if f->f_lasti == instr_ub
- (likely to be a common case) then we already know
- instr_lb -- if we stored the matching value of p
- somwhere we could skip the first while loop. */
-
- /* see comments in compile.c for the description of
- co_lnotab. A point to remember: increments to p
- should come in pairs -- although we don't care about
- the line increments here, treating them as byte
- increments gets confusing, to say the least. */
-
- while (size > 0) {
- if (addr + *p > frame->f_lasti)
- break;
- addr += *p++;
- if (*p) *instr_lb = addr;
- line += *p++;
- --size;
- }
-
- if (addr == frame->f_lasti) {
+ 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);
- }
-
- if (size > 0) {
- while (--size >= 0) {
- addr += *p++;
- if (*p++)
- break;
- }
- *instr_ub = addr;
- }
- else {
- *instr_ub = INT_MAX;
- }
+ }
+ *instr_lb = bounds.ap_lower;
+ *instr_ub = bounds.ap_upper;
}
else if (frame->f_lasti <= *instr_prev) {
- /* jumping back in the same line forces a trace event */
- result = call_trace(func, obj, frame,
- PyTrace_LINE, Py_None);
+ result = call_trace(func, obj, frame, PyTrace_LINE, Py_None);
}
*instr_prev = frame->f_lasti;
return result;
@@ -3623,9 +3523,9 @@ call_function(PyObject ***pp_stack, int oparg
Py_DECREF(func);
}
- /* Clear the stack of the function object and the arguments,
- in case they weren't consumed already.
- XXX(twouters) when are they not consumed already?
+ /* Clear the stack of the function object. Also removes
+ the arguments in case they weren't consumed already
+ (fast_function() and err_args() leave them on the stack).
*/
while ((*pp_stack) > pfunc) {
w = EXT_POP(*pp_stack);
@@ -3899,7 +3799,7 @@ _PyEval_SliceIndex(PyObject *v, Py_ssize_t *pi)
if (v != NULL) {
Py_ssize_t x;
if (PyInt_Check(v)) {
- x = PyInt_AsLong(v);
+ x = PyInt_AsSsize_t(v);
}
else if (v->ob_type->tp_as_number &&
PyType_HasFeature(v->ob_type, Py_TPFLAGS_HAVE_INDEX)
@@ -4302,8 +4202,8 @@ string_concatenate(PyObject *v, PyObject *w,
/* Now we own the last reference to 'v', so we can resize it
* in-place.
*/
- int v_len = PyString_GET_SIZE(v);
- int w_len = PyString_GET_SIZE(w);
+ Py_ssize_t v_len = PyString_GET_SIZE(v);
+ Py_ssize_t w_len = PyString_GET_SIZE(w);
if (_PyString_Resize(&v, v_len + w_len) != 0) {
/* XXX if _PyString_Resize() fails, 'v' has been
* deallocated so it cannot be put back into 'variable'.