mirror of
https://github.com/python/cpython.git
synced 2025-09-06 08:51:39 +00:00
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.
This commit is contained in:
parent
9ada3d6e29
commit
49fd7fa443
640 changed files with 52240 additions and 18408 deletions
150
Python/ceval.c
150
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;
|
||||
int line;
|
||||
PyAddrPair bounds;
|
||||
|
||||
size = PyString_GET_SIZE(co->co_lnotab) / 2;
|
||||
p = (unsigned char*)PyString_AS_STRING(co->co_lnotab);
|
||||
|
||||
addr = 0;
|
||||
line = co->co_firstlineno;
|
||||
|
||||
/* 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'.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue