Tcl Source Code

Artifact [0615feac4b]
Login

Artifact 0615feac4bf5e2f3688d84ba1b6dc7f69326815d:

Attachment "729692.patch" to ticket [729692ffff] added by msofer 2004-03-30 07:41:52.
? 729692.patch
? unix/ERR
? unix/httpd_2680
? unix/httpd_32632
? unix/httpd_879
? unix/st7CigPj
Index: generic/tclCompile.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclCompile.c,v
retrieving revision 1.59
diff -u -r1.59 tclCompile.c
--- generic/tclCompile.c	29 Mar 2004 02:09:46 -0000	1.59
+++ generic/tclCompile.c	30 Mar 2004 00:23:02 -0000
@@ -282,6 +282,9 @@
 	/* List Index:	push (lindex stktop op4) */
     {"listRangeImm",	  9,	0,	   2,	{OPERAND_IDX4, OPERAND_IDX4}},
 	/* List Range:	push (lrange stktop op4 op4) */
+
+    {"startCommand",      5,    0,         1,   {OPERAND_UINT4}},
+        /* Start of bytecoded command: op is the length of the cmd's code */ 
     {0}
 };
 
@@ -1056,9 +1059,26 @@
 			    unsigned int savedCodeNext =
 				    envPtr->codeNext - envPtr->codeStart;
 
+			    /*
+			     * Mark the start of the command; the proper
+			     * bytecode length will be updated later.
+			     */
+			    
+			    TclEmitInstInt4(INST_START_CMD, 0, envPtr);
+			    
 			    code = (*(cmdPtr->compileProc))(interp, &parse,
 			            envPtr);
+			    
 			    if (code == TCL_OK) {
+				/*
+				 * Fix the bytecode length.
+				 */
+				unsigned char *fixPtr = envPtr->codeStart + savedCodeNext + 1;
+				unsigned int fixLen = envPtr->codeNext - envPtr->codeStart
+				        - savedCodeNext;
+				
+				TclStoreInt4AtPtr(fixLen, fixPtr);
+				
 				goto finishCommand;
 			    } else if (code == TCL_OUT_LINE_COMPILE) {
 				/*
Index: generic/tclCompile.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclCompile.h,v
retrieving revision 1.42
diff -u -r1.42 tclCompile.h
--- generic/tclCompile.h	20 Jan 2004 15:49:54 -0000	1.42
+++ generic/tclCompile.h	30 Mar 2004 00:23:03 -0000
@@ -543,8 +543,10 @@
 #define INST_LIST_INDEX_IMM		102
 #define INST_LIST_RANGE_IMM		103
 
+#define INST_START_CMD                  104
+
 /* The last opcode */
-#define LAST_INST_OPCODE		103
+#define LAST_INST_OPCODE		104
 
 /*
  * Table describing the Tcl bytecode instructions: their name (for
Index: generic/tclExecute.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclExecute.c,v
retrieving revision 1.121
diff -u -r1.121 tclExecute.c
--- generic/tclExecute.c	18 Jan 2004 16:19:05 -0000	1.121
+++ generic/tclExecute.c	30 Mar 2004 00:23:07 -0000
@@ -61,15 +61,6 @@
 #   endif /* MAXDOUBLE */
 #endif /* !DBL_MAX */
 
-/*
- * A mask (should be 2**n-1) that is used to work out when the
- * bytecode engine should call Tcl_AsyncReady() to see whether there
- * is a signal that needs handling.
- */
-
-#ifndef ASYNC_CHECK_COUNT_MASK
-#   define ASYNC_CHECK_COUNT_MASK	15
-#endif /* !ASYNC_CHECK_COUNT_MASK */
 
 /*
  * Boolean flag indicating whether the Tcl bytecode interpreter has been
@@ -1098,9 +1089,11 @@
     int traceInstructions = (tclTraceExec == 3);
     char cmdNameBuf[21];
 #endif
-    int instructionCount = 0;	/* Counter that is used to work out
-				 * when to call Tcl_AsyncReady() */
-
+    Namespace *namespacePtr;
+    int codeCompileEpoch = codePtr->compileEpoch;
+    int codeNsEpoch = codePtr->nsEpoch;
+    int codePrecompiled = (codePtr->flags & TCL_BYTECODE_PRECOMPILED);
+    
     /*
      * The execution uses a unified stack: first the catch stack, immediately
      * above it the execution stack.
@@ -1134,6 +1127,11 @@
     iPtr->stats.numExecutions++;
 #endif
 
+    if (iPtr->varFramePtr != NULL) {
+        namespacePtr = iPtr->varFramePtr->nsPtr;
+    } else {
+        namespacePtr = iPtr->globalNsPtr;
+    }
 
     /*
      * Loop executing instructions until a "done" instruction, a 
@@ -1220,16 +1218,39 @@
      * do the check every 16th instruction.
      */
 
-    if (!(instructionCount++ & ASYNC_CHECK_COUNT_MASK) && Tcl_AsyncReady()) {
-	DECACHE_STACK_INFO();
-	result = Tcl_AsyncInvoke(interp, result);
-	CACHE_STACK_INFO();
-	if (result == TCL_ERROR) {
-	    goto checkForCatch;
-	}
-    }
 
     switch (*pc) {
+    case INST_START_CMD:
+	if (Tcl_AsyncReady()) {
+	    DECACHE_STACK_INFO();
+	    result = Tcl_AsyncInvoke(interp, result);
+	    CACHE_STACK_INFO();
+	    if (result == TCL_ERROR) {
+		goto checkForCatch;
+	    }
+	}
+	if ((!(iPtr->flags & DELETED)
+		    && (codeCompileEpoch == iPtr->compileEpoch)
+		    && (codeNsEpoch == namespacePtr->resolverEpoch))
+		|| codePrecompiled) {
+	    NEXT_INST_F(5, 0, 0);
+	} else {
+	    bytes = GetSrcInfoForPc(pc, codePtr, &length);
+	    result = Tcl_EvalEx(interp, bytes, length, 0);
+	    if (result != TCL_OK) {
+		goto checkForCatch;
+	    }
+	    opnd = TclGetUInt4AtPtr(pc+1);
+	    objResultPtr = Tcl_GetObjResult(interp);
+	    {
+		Tcl_Obj *newObjResultPtr;
+		TclNewObj(newObjResultPtr);
+		Tcl_IncrRefCount(newObjResultPtr);
+		iPtr->objResultPtr = newObjResultPtr;
+	    }
+	    NEXT_INST_V(opnd, 0, -1);
+	}
+	
     case INST_RETURN:
 	{
 	    int code = TclGetInt4AtPtr(pc+1);
@@ -1532,14 +1553,6 @@
 	    ++*preservedStackRefCountPtr;
 
 	    /*
-	     * Reset the instructionCount variable, since we're about
-	     * to check for async stuff anyway while processing
-	     * TclEvalObjvInternal.
-	     */
-
-	    instructionCount = 1;
-
-	    /*
 	     * Finally, let TclEvalObjvInternal handle the command. 
 	     */
 
Index: tests/interp.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/interp.test,v
retrieving revision 1.26
diff -u -r1.26 interp.test
--- tests/interp.test	17 Mar 2004 18:14:17 -0000	1.26
+++ tests/interp.test	30 Mar 2004 00:23:09 -0000
@@ -753,7 +753,7 @@
 	list [catch {a eval foo} msg] $msg
     } {1 {attempt to call eval in deleted interpreter}}
 }
-test interp-18.9 {eval in deleted interp, bug 495830} {knownBug} {
+test interp-18.9 {eval in deleted interp, bug 495830} {
     interp create tst
     interp alias tst suicide {} interp delete tst
     list [catch {tst eval {suicide; set a 5}} msg] $msg
Index: tests/proc.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/proc.test,v
retrieving revision 1.12
diff -u -r1.12 proc.test
--- tests/proc.test	14 Nov 2003 20:44:47 -0000	1.12
+++ tests/proc.test	30 Mar 2004 00:23:09 -0000
@@ -325,6 +325,15 @@
     set result
 } -5
 
+test proc-7.1 {Redefining a compiled cmd: Bug 729692} {
+    proc bar args {}
+    proc foo {} {
+	proc bar args {return bar}
+	bar
+    }
+    foo
+} bar
+
 # cleanup
 catch {rename p ""}
 catch {rename t ""}
Index: tests/rename.test
===================================================================
RCS file: /cvsroot/tcl/tcl/tests/rename.test,v
retrieving revision 1.10
diff -u -r1.10 rename.test
--- tests/rename.test	12 Sep 2001 20:28:50 -0000	1.10
+++ tests/rename.test	30 Mar 2004 00:23:09 -0000
@@ -160,7 +160,7 @@
 
 
 test rename-6.1 {old code invalidated (epoch incremented) when cmd with compile proc is renamed } {
-    proc x {} {
+     proc x {} {
         set a 123
         set b [incr a]
     }
@@ -168,6 +168,8 @@
     rename incr incr.old
     proc incr {} {puts "new incr called!"}
     catch {x} msg
+    rename incr {}
+    rename incr.old incr
     set msg
 } {wrong # args: should be "incr"}