| Index: Python/ceval.c |
| =================================================================== |
| --- Python/ceval.c (revision 70087) |
| +++ Python/ceval.c (working copy) |
| @@ -111,7 +111,7 @@ |
| PyFrameObject *, int, PyObject *); |
| static void call_exc_trace(Py_tracefunc, PyObject *, PyFrameObject *); |
| static int maybe_call_line_trace(Py_tracefunc, PyObject *, |
| - PyFrameObject *, int *, int *, int *); |
| + PyFrameObject *, int *, int *, int *, int *); |
| static PyObject * apply_slice(PyObject *, PyObject *, PyObject *); |
| static int assign_slice(PyObject *, PyObject *, |
| @@ -688,12 +688,15 @@ |
| /* when tracing we set things up so that |
| - not (instr_lb <= current_bytecode_offset < instr_ub) |
| + instr_lb <= current_bytecode_offset < instr_ub |
| - is true when the line being executed has changed. The |
| - initial values are such as to make this false the first |
| - time it is tested. */ |
| + is false when the line being executed may have changed. |
| + The initial values are such as to make this false the first |
| + time it is tested. Then maybe_call_line_trace calls |
| + PyCode_CheckLineNumber() to check if the line has actually |
| + changed. */ |
| int instr_ub = -1, instr_lb = 0, instr_prev = -1; |
| + int cur_line = 0; |
| unsigned char *first_instr; |
| PyObject *names; |
| @@ -785,8 +788,11 @@ |
| #ifdef DYNAMIC_EXECUTION_PROFILE |
| #define PREDICT(op) if (0) goto PRED_##op |
| +#define PREDICT_WITH_SIGNALS(op) if (0) goto PRED_##op |
| #else |
| #define PREDICT(op) if (*next_instr == op) goto PRED_##op |
| +#define PREDICT_WITH_SIGNALS(op) \ |
| + if (*next_instr == op && --_Py_Ticker > 0) goto PRED_##op |
| #endif |
| #define PREDICTED(op) PRED_##op: next_instr++ |
| @@ -908,8 +914,8 @@ |
| prediction effectively links the two codes together as if they |
| were a single new opcode; accordingly,f->f_lasti will point to |
| the first code in the pair (for instance, GET_ITER followed by |
| - FOR_ITER is effectively a single opcode and f->f_lasti will point |
| - at to the beginning of the combined pair.) |
| + JUMP_FORWARD is effectively a single opcode and f->f_lasti will |
| + point at to the beginning of the combined pair.) |
| */ |
| next_instr = first_instr + f->f_lasti + 1; |
| stack_pointer = f->f_stacktop; |
| @@ -1027,7 +1033,7 @@ |
| err = maybe_call_line_trace(tstate->c_tracefunc, |
| tstate->c_traceobj, |
| f, &instr_lb, &instr_ub, |
| - &instr_prev); |
| + &instr_prev, &cur_line); |
| /* Reload possibly changed frame fields */ |
| JUMPTO(f->f_lasti); |
| if (f->f_stacktop != NULL) { |
| @@ -1425,7 +1431,7 @@ |
| err = PyList_Append(v, w); |
| Py_DECREF(w); |
| if (err == 0) { |
| - PREDICT(JUMP_ABSOLUTE); |
| + PREDICT(FOR_ITER); |
| continue; |
| } |
| break; |
| @@ -2293,6 +2299,7 @@ |
| if (x != NULL) continue; |
| break; |
| + PREDICTED_WITH_ARG(JUMP_FORWARD); |
| case JUMP_FORWARD: |
| JUMPBY(oparg); |
| goto fast_next_opcode; |
| @@ -2307,14 +2314,22 @@ |
| if (w == Py_False) { |
| Py_DECREF(w); |
| JUMPTO(oparg); |
| +#if FAST_LOOPS /* See JUMP_ABSOLUTE for a description of this define */ |
| goto fast_next_opcode; |
| +#else |
| + continue; |
| +#endif |
| } |
| err = PyObject_IsTrue(w); |
| Py_DECREF(w); |
| if (err > 0) |
| err = 0; |
| - else if (err == 0) |
| + else if (err == 0) { |
| JUMPTO(oparg); |
| +#if FAST_LOOPS /* See JUMP_ABSOLUTE for a description of this define */ |
| + goto fast_next_opcode; |
| +#endif |
| + } |
| else |
| break; |
| continue; |
| @@ -2329,13 +2344,20 @@ |
| if (w == Py_True) { |
| Py_DECREF(w); |
| JUMPTO(oparg); |
| +#if FAST_LOOPS /* See JUMP_ABSOLUTE for a description of this define */ |
| goto fast_next_opcode; |
| +#else |
| + continue; |
| +#endif |
| } |
| err = PyObject_IsTrue(w); |
| Py_DECREF(w); |
| if (err > 0) { |
| err = 0; |
| JUMPTO(oparg); |
| +#if FAST_LOOPS /* See JUMP_ABSOLUTE for a description of this define */ |
| + goto fast_next_opcode; |
| +#endif |
| } |
| else if (err == 0) |
| ; |
| @@ -2390,7 +2412,6 @@ |
| break; |
| continue; |
| - PREDICTED_WITH_ARG(JUMP_ABSOLUTE); |
| case JUMP_ABSOLUTE: |
| JUMPTO(oparg); |
| #if FAST_LOOPS |
| @@ -2413,7 +2434,7 @@ |
| Py_DECREF(v); |
| if (x != NULL) { |
| SET_TOP(x); |
| - PREDICT(FOR_ITER); |
| + PREDICT(JUMP_FORWARD); |
| continue; |
| } |
| STACKADJ(-1); |
| @@ -2426,7 +2447,10 @@ |
| x = (*v->ob_type->tp_iternext)(v); |
| if (x != NULL) { |
| PUSH(x); |
| - PREDICT(STORE_FAST); |
| + JUMPTO(oparg); |
| + /* STORE_FAST is a fast_next_opcode so we must be careful |
| + about not blocking signals in an empty loop. */ |
| + PREDICT_WITH_SIGNALS(STORE_FAST); |
| PREDICT(UNPACK_SEQUENCE); |
| continue; |
| } |
| @@ -2437,9 +2461,8 @@ |
| PyErr_Clear(); |
| } |
| /* iterator ended normally */ |
| - x = v = POP(); |
| + x = v = POP(); |
| Py_DECREF(v); |
| - JUMPBY(oparg); |
| continue; |
| case BREAK_LOOP: |
| @@ -3594,7 +3617,7 @@ |
| static int |
| maybe_call_line_trace(Py_tracefunc func, PyObject *obj, |
| PyFrameObject *frame, int *instr_lb, int *instr_ub, |
| - int *instr_prev) |
| + int *instr_prev, int *cur_line) |
| { |
| int result = 0; |
| @@ -3609,13 +3632,14 @@ |
| line = PyCode_CheckLineNumber(frame->f_code, frame->f_lasti, |
| &bounds); |
| - if (line >= 0) { |
| + if (line >= 0 && line != *cur_line) { |
| frame->f_lineno = line; |
| result = call_trace(func, obj, frame, |
| PyTrace_LINE, Py_None); |
| } |
| *instr_lb = bounds.ap_lower; |
| *instr_ub = bounds.ap_upper; |
| + *cur_line = line; |
| } |
| else if (frame->f_lasti <= *instr_prev) { |
| result = call_trace(func, obj, frame, PyTrace_LINE, Py_None); |