[Python-checkins] python/dist/src/Python ceval.c,2.332,2.333 compile.c,2.262,2.263

mwh@users.sourceforge.net mwh@users.sourceforge.net
Fri, 30 Aug 2002 06:09:54 -0700


Update of /cvsroot/python/python/dist/src/Python
In directory usw-pr-cvs1:/tmp/cvs-serv24418/Python

Modified Files:
	ceval.c compile.c 
Log Message:
Further SET_LINENO reomval fixes.  See comments in patch #587933.

Use a slightly different strategy to determine when not to call the line 
trace function.  This removes the need for the RETURN_NONE opcode, so
that's gone again.  Update docs and comments to match.

Thanks to Neal and Armin!

Also add a test suite.  This should have come with the original patch...


Index: ceval.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/ceval.c,v
retrieving revision 2.332
retrieving revision 2.333
diff -C2 -d -r2.332 -r2.333
*** ceval.c	23 Aug 2002 14:11:35 -0000	2.332
--- ceval.c	30 Aug 2002 13:09:50 -0000	2.333
***************
*** 1516,1525 ****
  			break;
  
- 		case RETURN_NONE:
- 			retval = Py_None;
- 			Py_INCREF(retval);
- 			why = WHY_RETURN;
- 			break;
- 
  		case YIELD_VALUE:
  			retval = POP();
--- 1516,1519 ----
***************
*** 2881,2887 ****
  	   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:
--- 2875,2880 ----
  	   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:
***************
*** 2908,2912 ****
  		      19 PRINT_ITEM          
  		      20 PRINT_NEWLINE       
! 		 >>   21 RETURN_NONE         
  
  	   If a is false, execution will jump to instruction at offset
--- 2901,2906 ----
  		      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
***************
*** 2916,2948 ****
  	   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
--- 2910,2933 ----
  	   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.
  	*/
  
! 	if ((frame->f_lasti < *instr_lb || frame->f_lasti >= *instr_ub)) {
  		PyCodeObject* co = frame->f_code;
  		int size, addr;
  		unsigned char* p;
  
! 		size = PyString_GET_SIZE(co->co_lnotab) / 2;
! 		p = (unsigned char*)PyString_AS_STRING(co->co_lnotab);
  
! 		addr = 0;
  
  		/* possible optimization: if f->f_lasti == instr_ub
***************
*** 2951,2956 ****
  		   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
--- 2936,2939 ----
***************
*** 2959,2963 ****
  		   increments gets confusing, to say the least. */
  
! 		while (size >= 0) {
  			if (addr + *p > frame->f_lasti)
  				break;
--- 2942,2946 ----
  		   increments gets confusing, to say the least. */
  
! 		while (size > 0) {
  			if (addr + *p > frame->f_lasti)
  				break;
***************
*** 2966,2969 ****
--- 2949,2955 ----
  			--size;
  		}
+ 		if (addr == frame->f_lasti)
+ 			call_trace(func, obj, frame, 
+ 				   PyTrace_LINE, Py_None);
  		*instr_lb = addr;
  		if (size > 0) {

Index: compile.c
===================================================================
RCS file: /cvsroot/python/python/dist/src/Python/compile.c,v
retrieving revision 2.262
retrieving revision 2.263
diff -C2 -d -r2.262 -r2.263
*** compile.c	16 Aug 2002 02:48:11 -0000	2.262
--- compile.c	30 Aug 2002 13:09:51 -0000	2.263
***************
*** 4015,4019 ****
  	com_node(c, CHILD(n, 4));
  	c->c_infunction = 0;
! 	com_addbyte(c, RETURN_NONE);
  }
  
--- 4015,4022 ----
  	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);
  }
  
***************
*** 4082,4086 ****
  		if (TYPE(n) != NEWLINE)
  			com_node(c, n);
! 		com_addbyte(c, RETURN_NONE);
  		c->c_interactive--;
  		break;
--- 4085,4092 ----
  		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;
***************
*** 4088,4092 ****
  	case file_input: /* A whole file, or built-in function exec() */
  		com_file_input(c, n);
! 		com_addbyte(c, RETURN_NONE);
  		break;
  	
--- 4094,4101 ----
  	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;