[Python-checkins] python/dist/src/Python ceval.c,2.323,2.324 compile.c,2.257,2.258 frozen.c,1.12,1.13 import.c,2.208,2.209 traceback.c,2.38,2.39

mwh@users.sourceforge.net mwh@users.sourceforge.net
2002年8月15日 07:59:04 -0700


Update of /cvsroot/python/python/dist/src/Python
In directory usw-pr-cvs1:/tmp/cvs-serv10908/Python
Modified Files:
	ceval.c compile.c frozen.c import.c traceback.c 
Log Message:
This is my patch
[ 587993 ] SET_LINENO killer
Remove SET_LINENO. Tracing is now supported by inspecting co_lnotab.
Many sundry changes to document and adapt to this change.
Index: ceval.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v
retrieving revision 2.323
retrieving revision 2.324
diff -C2 -d -r2.323 -r2.324
*** ceval.c	9 Aug 2002 18:35:52 -0000	2.323
--- ceval.c	15 Aug 2002 14:59:02 -0000	2.324
***************
*** 52,55 ****
--- 52,58 ----
 				 PyFrameObject *, int);
 static void call_exc_trace(Py_tracefunc, PyObject *, PyFrameObject *);
+ static void maybe_call_line_trace(int, Py_tracefunc, PyObject *, 
+ 				 PyFrameObject *, int *, int *);
+ 
 static PyObject *apply_slice(PyObject *, PyObject *, PyObject *);
 static int assign_slice(PyObject *, PyObject *,
***************
*** 500,503 ****
--- 503,516 ----
 	PyThreadState *tstate = PyThreadState_GET();
 	PyCodeObject *co;
+ 
+ 	/* when tracing we set things up so that 
+ 
+ not (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. */
+ 	int instr_ub = -1, instr_lb = 0;
+ 
 	unsigned char *first_instr;
 	PyObject *names;
***************
*** 587,591 ****
 	freevars = f->f_localsplus + f->f_nlocals;
 	_PyCode_GETCODEPTR(co, &first_instr);
! 	next_instr = first_instr + f->f_lasti;
 	stack_pointer = f->f_stacktop;
 	assert(stack_pointer != NULL);
--- 600,609 ----
 	freevars = f->f_localsplus + f->f_nlocals;
 	_PyCode_GETCODEPTR(co, &first_instr);
! 	if (f->f_lasti < 0) {
! 		next_instr = first_instr;
! 	}
! 	else {
! 		next_instr = first_instr + f->f_lasti;
! 	}
 	stack_pointer = f->f_stacktop;
 	assert(stack_pointer != NULL);
***************
*** 638,643 ****
 
 	for (;;) {
! 		assert(stack_pointer >= f->f_valuestack);	/* else underflow */
! 		assert(STACK_LEVEL() <= f->f_stacksize);	/* else overflow */
 		/* Do periodic things. Doing this every time through
 		 the loop would add too much overhead, so we do it
--- 656,662 ----
 
 	for (;;) {
! 		assert(stack_pointer >= f->f_valuestack); /* else underflow */
! 		assert(STACK_LEVEL() <= f->f_stacksize); /* else overflow */
! 
 		/* Do periodic things. Doing this every time through
 		 the loop would add too much overhead, so we do it
***************
*** 659,664 ****
 			/* If we have true signals, the signal handler
 			 will call Py_AddPendingCall() so we don't
! 			 have to call sigcheck(). On the Mac and
! 			 DOS, alas, we have to call it. */
 			if (PyErr_CheckSignals()) {
 				why = WHY_EXCEPTION;
--- 678,683 ----
 			/* If we have true signals, the signal handler
 			 will call Py_AddPendingCall() so we don't
! 			 have to call PyErr_CheckSignals(). On the 
! 			 Mac and DOS, alas, we have to call it. */
 			if (PyErr_CheckSignals()) {
 				why = WHY_EXCEPTION;
***************
*** 687,693 ****
 		/* Extract opcode and argument */
 
- #if defined(Py_DEBUG) || defined(LLTRACE)
 		f->f_lasti = INSTR_OFFSET();
- #endif
 
 		opcode = NEXTOP();
--- 706,710 ----
***************
*** 709,721 ****
 			if (HAS_ARG(opcode)) {
 				printf("%d: %d, %d\n",
! 					(int) (INSTR_OFFSET() - 3),
! 					opcode, oparg);
 			}
 			else {
 				printf("%d: %d\n",
! 					(int) (INSTR_OFFSET() - 1), opcode);
 			}
 		}
 #endif
 		/* Main switch on opcode */
 
--- 726,749 ----
 			if (HAS_ARG(opcode)) {
 				printf("%d: %d, %d\n",
! 				 f->f_lasti, opcode, oparg);
 			}
 			else {
 				printf("%d: %d\n",
! 				 f->f_lasti, opcode);
 			}
 		}
 #endif
+ 
+ 		/* line-by-line tracing support */
+ 
+ 		if (tstate->c_tracefunc != NULL && !tstate->tracing) {
+ 			/* see maybe_call_line_trace
+ 			 for expository comments */
+ 			maybe_call_line_trace(opcode, 
+ 					 tstate->c_tracefunc,
+ 					 tstate->c_traceobj,
+ 					 f, &instr_lb, &instr_ub);
+ 		}
+ 
 		/* Main switch on opcode */
 
***************
*** 729,752 ****
 		/* case STOP_CODE: this is an error! */
 
- 		case SET_LINENO:
- #ifdef LLTRACE
- 			if (lltrace)
- 				printf("--- %s:%d \n", filename, oparg);
- #endif
- 			f->f_lineno = oparg;
- 			if (tstate->c_tracefunc == NULL || tstate->tracing)
- 				goto fast_next_opcode;
- 			/* Trace each line of code reached */
- 			f->f_lasti = INSTR_OFFSET();
- 			/* Inline call_trace() for performance: */
- 			tstate->tracing++;
- 			tstate->use_tracing = 0;
- 			err = (tstate->c_tracefunc)(tstate->c_traceobj, f,
- 						 PyTrace_LINE, Py_None);
- 			tstate->use_tracing = (tstate->c_tracefunc
- 					 || tstate->c_profilefunc);
- 			tstate->tracing--;
- 			break;
- 
 		case LOAD_FAST:
 			x = GETLOCAL(oparg);
--- 757,760 ----
***************
*** 1505,1511 ****
--- 1513,1527 ----
 			break;
 
+ 		case RETURN_NONE:
+ 			retval = Py_None;
+ 			Py_INCREF(retval);
+ 			why = WHY_RETURN;
+ 			break;
+ 
 		case YIELD_VALUE:
 			retval = POP();
 			f->f_stacktop = stack_pointer;
+ 			/* abuse the lasti field: here it points to 
+ 			 the *next* instruction */
 			f->f_lasti = INSTR_OFFSET();
 			why = WHY_YIELD;
***************
*** 1955,1959 ****
 		 PyObject **pfunc = stack_pointer - n - 1;
 		 PyObject *func = *pfunc;
- 		 f->f_lasti = INSTR_OFFSET() - 3; /* For tracing */
 
 		 /* Always dispatch PyCFunction first, because
--- 1971,1974 ----
***************
*** 2023,2027 ****
 		 pfunc = stack_pointer - n - 1;
 		 func = *pfunc;
- 		 f->f_lasti = INSTR_OFFSET() - 3; /* For tracing */
 
 		 if (PyMethod_Check(func)
--- 2038,2041 ----
***************
*** 2135,2139 ****
 			fprintf(stderr,
 				"XXX lineno: %d, opcode: %d\n",
! 				f->f_lineno, opcode);
 			PyErr_SetString(PyExc_SystemError, "unknown opcode");
 			why = WHY_EXCEPTION;
--- 2149,2154 ----
 			fprintf(stderr,
 				"XXX lineno: %d, opcode: %d\n",
! 				PyCode_Addr2Line(f->f_code, f->f_lasti),
! 				opcode);
 			PyErr_SetString(PyExc_SystemError, "unknown opcode");
 			why = WHY_EXCEPTION;
***************
*** 2190,2196 ****
 
 		if (why == WHY_EXCEPTION) {
- 			f->f_lasti = INSTR_OFFSET() - 1;
- 			if (HAS_ARG(opcode))
- 				f->f_lasti -= 2;
 			PyTraceBack_Here(f);
 
--- 2205,2208 ----
***************
*** 2874,2877 ****
--- 2886,3008 ----
 	tstate->tracing--;
 	return result;
+ }
+ 
+ static void
+ maybe_call_line_trace(int opcode, Py_tracefunc func, PyObject *obj, 
+ 		 PyFrameObject *frame, int *instr_lb, int *instr_ub)
+ {
+ 	/* 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 call the line
+ 	 trace function when executing a POP_TOP or RETURN_NONE
+ 	 opcodes. An example probably serves best.
+ 
+ 	 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 RETURN_NONE 
+ 
+ 	 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).
+ 
+ 	 On the other hand, if 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.
+ 
+ 	 This is why it is important that RETURN_NONE is *only* used
+ 	 for the "falling off the end of the function" form of
+ 	 returning None -- using it for code like
+ 
+ 	 1: def f():
+ 	 2: return
+ 
+ 	 would, once again, lead to misleading tracing behaviour.
+ 
+ 	 It is also worth mentioning that getting tracing behaviour
+ 	 right is the *entire* motivation for adding the RETURN_NONE
+ 	 opcode.
+ 	*/
+ 
+ 	if (opcode != POP_TOP && opcode != RETURN_NONE &&
+ 	 (frame->f_lasti < *instr_lb || frame->f_lasti > *instr_ub)) {
+ 		PyCodeObject* co = frame->f_code;
+ 		int size, addr;
+ 		unsigned char* p;
+ 
+ 		call_trace(func, obj, frame, PyTrace_LINE, Py_None);
+ 
+ 		size = PyString_Size(co->co_lnotab) / 2;
+ 		p = (unsigned char*)PyString_AsString(co->co_lnotab);
+ 
+ 		/* 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. */
+ 
+ 		addr = 0;
+ 
+ 		/* 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++;
+ 			p++;
+ 			--size;
+ 		}
+ 		*instr_lb = addr;
+ 		if (size > 0) {
+ 			while (--size >= 0) {
+ 				addr += *p++;
+ 				if (*p++)
+ 					break;
+ 			}
+ 			*instr_ub = addr;
+ 		}
+ 		else {
+ 			*instr_ub = INT_MAX;
+ 		}
+ 	}
 }
 
Index: compile.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v
retrieving revision 2.257
retrieving revision 2.258
diff -C2 -d -r2.257 -r2.258
*** compile.c	14 Aug 2002 15:51:28 -0000	2.257
--- compile.c	15 Aug 2002 14:59:02 -0000	2.258
***************
*** 408,414 ****
 /* All about c_lnotab.
 
! c_lnotab is an array of unsigned bytes disguised as a Python string. In -O
! mode, SET_LINENO opcodes aren't generated, and bytecode offsets are mapped
! to source code line #s (when needed for tracebacks) via c_lnotab instead.
 The array is conceptually a list of
 (bytecode offset increment, line number increment)
--- 408,415 ----
 /* All about c_lnotab.
 
! c_lnotab is an array of unsigned bytes disguised as a Python string. Since
! version 2.3, SET_LINENO opcodes are never generated and bytecode offsets are
! mapped to source code line #s via c_lnotab instead.
! 
 The array is conceptually a list of
 (bytecode offset increment, line number increment)
***************
*** 831,839 ****
 {
 	int extended_arg = arg >> 16;
- 	if (op == SET_LINENO) {
- 		com_set_lineno(c, arg);
- 		if (Py_OptimizeFlag)
- 			return;
- 	}
 	if (extended_arg){
 		com_addbyte(c, EXTENDED_ARG);
--- 832,835 ----
***************
*** 1739,1743 ****
 			if (ch->n_lineno != lineno) {
 				lineno = ch->n_lineno;
! 				com_addoparg(c, SET_LINENO, lineno);
 			}
 			com_argument(c, ch, &keywords);
--- 1735,1739 ----
 			if (ch->n_lineno != lineno) {
 				lineno = ch->n_lineno;
! 				com_set_lineno(c, lineno);
 			}
 			com_argument(c, ch, &keywords);
***************
*** 3169,3173 ****
 		}
 		if (i > 0)
! 			com_addoparg(c, SET_LINENO, ch->n_lineno);
 		com_node(c, ch);
 		com_addfwref(c, JUMP_IF_FALSE, &a);
--- 3165,3169 ----
 		}
 		if (i > 0)
! 			com_set_lineno(c, ch->n_lineno);
 		com_node(c, ch);
 		com_addfwref(c, JUMP_IF_FALSE, &a);
***************
*** 3196,3200 ****
 	block_push(c, SETUP_LOOP);
 	c->c_begin = c->c_nexti;
! 	com_addoparg(c, SET_LINENO, n->n_lineno);
 	com_node(c, CHILD(n, 1));
 	com_addfwref(c, JUMP_IF_FALSE, &anchor);
--- 3192,3196 ----
 	block_push(c, SETUP_LOOP);
 	c->c_begin = c->c_nexti;
! 	com_set_lineno(c, n->n_lineno);
 	com_node(c, CHILD(n, 1));
 	com_addfwref(c, JUMP_IF_FALSE, &anchor);
***************
*** 3229,3233 ****
 	com_addbyte(c, GET_ITER);
 	c->c_begin = c->c_nexti;
! 	com_addoparg(c, SET_LINENO, n->n_lineno);
 	com_addfwref(c, FOR_ITER, &anchor);
 	com_push(c, 1);
--- 3225,3229 ----
 	com_addbyte(c, GET_ITER);
 	c->c_begin = c->c_nexti;
! 	com_set_lineno(c, n->n_lineno);
 	com_addfwref(c, FOR_ITER, &anchor);
 	com_push(c, 1);
***************
*** 3340,3344 ****
 		except_anchor = 0;
 		com_push(c, 3); /* tb, val, exc pushed by exception */
! 		com_addoparg(c, SET_LINENO, ch->n_lineno);
 		if (NCH(ch) > 1) {
 			com_addbyte(c, DUP_TOP);
--- 3336,3340 ----
 		except_anchor = 0;
 		com_push(c, 3); /* tb, val, exc pushed by exception */
! 		com_set_lineno(c, ch->n_lineno);
 		if (NCH(ch) > 1) {
 			com_addbyte(c, DUP_TOP);
***************
*** 3402,3406 ****
 	com_backpatch(c, finally_anchor);
 	ch = CHILD(n, NCH(n)-1);
! 	com_addoparg(c, SET_LINENO, ch->n_lineno);
 	com_node(c, ch);
 	com_addbyte(c, END_FINALLY);
--- 3398,3402 ----
 	com_backpatch(c, finally_anchor);
 	ch = CHILD(n, NCH(n)-1);
! 	com_set_lineno(c, ch->n_lineno);
 	com_node(c, ch);
 	com_addbyte(c, END_FINALLY);
***************
*** 3728,3732 ****
 	case simple_stmt:
 		/* small_stmt (';' small_stmt)* [';'] NEWLINE */
! 		com_addoparg(c, SET_LINENO, n->n_lineno);
 		{
 			int i;
--- 3724,3728 ----
 	case simple_stmt:
 		/* small_stmt (';' small_stmt)* [';'] NEWLINE */
! 		com_set_lineno(c, n->n_lineno);
 		{
 			int i;
***************
*** 3737,3741 ****
 	
 	case compound_stmt:
! 		com_addoparg(c, SET_LINENO, n->n_lineno);
 		n = CHILD(n, 0);
 		goto loop;
--- 3733,3737 ----
 	
 	case compound_stmt:
! 		com_set_lineno(c, n->n_lineno);
 		n = CHILD(n, 0);
 		goto loop;
***************
*** 3991,3998 ****
 	com_node(c, CHILD(n, 4));
 	c->c_infunction = 0;
! 	com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
! 	com_push(c, 1);
! 	com_addbyte(c, RETURN_VALUE);
! 	com_pop(c, 1);
 }
 
--- 3987,3991 ----
 	com_node(c, CHILD(n, 4));
 	c->c_infunction = 0;
! 	com_addbyte(c, RETURN_NONE);
 }
 
***************
*** 4051,4055 ****
 compile_node(struct compiling *c, node *n)
 {
! 	com_addoparg(c, SET_LINENO, n->n_lineno);
 	
 	switch (TYPE(n)) {
--- 4044,4048 ----
 compile_node(struct compiling *c, node *n)
 {
! 	com_set_lineno(c, n->n_lineno);
 	
 	switch (TYPE(n)) {
***************
*** 4061,4068 ****
 		if (TYPE(n) != NEWLINE)
 			com_node(c, n);
! 		com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
! 		com_push(c, 1);
! 		com_addbyte(c, RETURN_VALUE);
! 		com_pop(c, 1);
 		c->c_interactive--;
 		break;
--- 4054,4058 ----
 		if (TYPE(n) != NEWLINE)
 			com_node(c, n);
! 		com_addbyte(c, RETURN_NONE);
 		c->c_interactive--;
 		break;
***************
*** 4070,4077 ****
 	case file_input: /* A whole file, or built-in function exec() */
 		com_file_input(c, n);
! 		com_addoparg(c, LOAD_CONST, com_addconst(c, Py_None));
! 		com_push(c, 1);
! 		com_addbyte(c, RETURN_VALUE);
! 		com_pop(c, 1);
 		break;
 	
--- 4060,4064 ----
 	case file_input: /* A whole file, or built-in function exec() */
 		com_file_input(c, n);
! 		com_addbyte(c, RETURN_NONE);
 		break;
 	
Index: frozen.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/frozen.c,v
retrieving revision 1.12
retrieving revision 1.13
diff -C2 -d -r1.12 -r1.13
*** frozen.c	14 Jun 2002 01:11:57 -0000	1.12
--- frozen.c	15 Aug 2002 14:59:02 -0000	1.13
***************
*** 14,23 ****
 static unsigned char M___hello__[] = {
 	99,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
! 	0,115,15,0,0,0,127,0,0,127,1,0,100,0,0,71,
! 	72,100,1,0,83,40,2,0,0,0,115,14,0,0,0,72,
! 	101,108,108,111,32,119,111,114,108,100,46,46,46,78,40,0,
! 	0,0,0,40,0,0,0,0,40,0,0,0,0,40,0,0,
! 	0,0,115,8,0,0,0,104,101,108,108,111,46,112,121,115,
! 	1,0,0,0,63,1,0,0,0,115,0,0,0,0,
 };
 
--- 14,23 ----
 static unsigned char M___hello__[] = {
 	99,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,
! 	0,115,9,0,0,0,100,0,0,71,72,100,1,0,83,40,
! 	2,0,0,0,115,14,0,0,0,72,101,108,108,111,32,119,
! 	111,114,108,100,46,46,46,78,40,0,0,0,0,40,0,0,
! 	0,0,40,0,0,0,0,40,0,0,0,0,115,8,0,0,
! 	0,104,101,108,108,111,46,112,121,115,1,0,0,0,63,1,
! 	0,0,0,115,0,0,0,0,
 };
 
Index: import.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/import.c,v
retrieving revision 2.208
retrieving revision 2.209
diff -C2 -d -r2.208 -r2.209
*** import.c	30 Jun 2002 15:26:10 -0000	2.208
--- import.c	15 Aug 2002 14:59:02 -0000	2.209
***************
*** 50,53 ****
--- 50,56 ----
 start counting in increments of 10 from now on ?!
 
+ MWH, 2002年08月03日: Removed SET_LINENO. Couldn't be bothered figuring
+ out the MAGIC schemes, so just incremented it by 10.
+ 
 Known values:
 Python 1.5: 20121
***************
*** 61,66 ****
 Python 2.2: 60717
 Python 2.3a0: 62011
 */
! #define MAGIC (62011 | ((long)'\r'<<16) | ((long)'\n'<<24))
 
 /* Magic word as global; note that _PyImport_Init() can change the
--- 64,70 ----
 Python 2.2: 60717
 Python 2.3a0: 62011
+ Python 2.3a0: 62021
 */
! #define MAGIC (62021 | ((long)'\r'<<16) | ((long)'\n'<<24))
 
 /* Magic word as global; note that _PyImport_Init() can change the
Index: traceback.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/traceback.c,v
retrieving revision 2.38
retrieving revision 2.39
diff -C2 -d -r2.38 -r2.39
*** traceback.c	14 Apr 2002 20:12:41 -0000	2.38
--- traceback.c	15 Aug 2002 14:59:02 -0000	2.39
***************
*** 104,109 ****
 
 static tracebackobject *
! newtracebackobject(tracebackobject *next, PyFrameObject *frame, int lasti,
! 		 int lineno)
 {
 	tracebackobject *tb;
--- 104,108 ----
 
 static tracebackobject *
! newtracebackobject(tracebackobject *next, PyFrameObject *frame)
 {
 	tracebackobject *tb;
***************
*** 119,124 ****
 		Py_XINCREF(frame);
 		tb->tb_frame = frame;
! 		tb->tb_lasti = lasti;
! 		tb->tb_lineno = lineno;
 		PyObject_GC_Track(tb);
 	}
--- 118,124 ----
 		Py_XINCREF(frame);
 		tb->tb_frame = frame;
! 		tb->tb_lasti = frame->f_lasti;
! 		tb->tb_lineno = PyCode_Addr2Line(frame->f_code, 
! 						 frame->f_lasti);
 		PyObject_GC_Track(tb);
 	}
***************
*** 131,136 ****
 	PyThreadState *tstate = frame->f_tstate;
 	tracebackobject *oldtb = (tracebackobject *) tstate->curexc_traceback;
! 	tracebackobject *tb = newtracebackobject(oldtb,
! 				frame, frame->f_lasti, frame->f_lineno);
 	if (tb == NULL)
 		return -1;
--- 131,135 ----
 	PyThreadState *tstate = frame->f_tstate;
 	tracebackobject *oldtb = (tracebackobject *) tstate->curexc_traceback;
! 	tracebackobject *tb = newtracebackobject(oldtb, frame);
 	if (tb == NULL)
 		return -1;

AltStyle によって変換されたページ (->オリジナル) /