Tcl Source Code

Artifact [7fd3fe6a07]
Login

Artifact 7fd3fe6a07c9e67db82c48b960144613e6f09cf9:

Attachment "patchLit" to ticket [1090905fff] added by msofer 2004-12-25 01:05:41.
Index: generic/tclCompile.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclCompile.c,v
retrieving revision 1.80
diff -u -r1.80 tclCompile.c
--- generic/tclCompile.c	20 Dec 2004 18:27:18 -0000	1.80
+++ generic/tclCompile.c	24 Dec 2004 18:02:51 -0000
@@ -1146,10 +1146,11 @@
 			/*
 			 * No compile procedure so push the word. If the
 			 * command was found, push a CmdName object to
-			 * reduce runtime lookups.
+			 * reduce runtime lookups. Avoid sharing this literal
+			 * among different namespaces to reduce shimmering.
 			 */
 
-			objIndex = TclRegisterNewLiteral(envPtr,
+			objIndex = TclRegisterNewNSLiteral(envPtr,
 				tokenPtr[1].start, tokenPtr[1].size);
 			if (cmdPtr != NULL) {
 			    TclSetCmdNameObj(interp,
@@ -1318,9 +1319,9 @@
 		if (Tcl_DStringLength(&textBuffer) > 0) {
 		    int literal;
 		    
-		    literal = TclRegisterLiteral(envPtr,
+		    literal = TclRegisterNewLiteral(envPtr,
 			    Tcl_DStringValue(&textBuffer),
-			    Tcl_DStringLength(&textBuffer), /*onHeap*/ 0);
+			    Tcl_DStringLength(&textBuffer));
 		    TclEmitPush(literal, envPtr);
 		    numObjsToConcat++;
 		    Tcl_DStringFree(&textBuffer);
@@ -1339,9 +1340,9 @@
 		if (Tcl_DStringLength(&textBuffer) > 0) {
 		    int literal;
 		    
-		    literal = TclRegisterLiteral(envPtr,
+		    literal = TclRegisterNewLiteral(envPtr,
 			    Tcl_DStringValue(&textBuffer),
-			    Tcl_DStringLength(&textBuffer), /*onHeap*/ 0);
+			    Tcl_DStringLength(&textBuffer));
 		    TclEmitPush(literal, envPtr);
 		    numObjsToConcat++;
 		    Tcl_DStringFree(&textBuffer);
@@ -1433,8 +1434,8 @@
     if (Tcl_DStringLength(&textBuffer) > 0) {
 	int literal;
 
-	literal = TclRegisterLiteral(envPtr, Tcl_DStringValue(&textBuffer),
-	        Tcl_DStringLength(&textBuffer), /*onHeap*/ 0);
+	literal = TclRegisterNewLiteral(envPtr, Tcl_DStringValue(&textBuffer),
+	        Tcl_DStringLength(&textBuffer));
 	TclEmitPush(literal, envPtr);
 	numObjsToConcat++;
     }
@@ -1456,7 +1457,7 @@
      */
     
     if (envPtr->codeNext == entryCodeNext) {
-	TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0),
+	TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0),
 	        envPtr);
     }
     Tcl_DStringFree(&textBuffer);
@@ -1573,7 +1574,7 @@
     for (i = 0;  i < numWords;  i++) {
 	TclCompileTokens(interp, wordPtr+1, wordPtr->numComponents, envPtr);
 	if (i < (numWords - 1)) {
-	    TclEmitPush(TclRegisterLiteral(envPtr, " ", 1, /*onHeap*/ 0),
+	    TclEmitPush(TclRegisterNewLiteral(envPtr, " ", 1),
 	            envPtr);
 	}
 	wordPtr += (wordPtr->numComponents + 1);
Index: generic/tclCompile.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclCompile.h,v
retrieving revision 1.52
diff -u -r1.52 tclCompile.h
--- generic/tclCompile.h	10 Dec 2004 13:09:14 -0000	1.52
+++ generic/tclCompile.h	24 Dec 2004 18:02:52 -0000
@@ -842,7 +842,7 @@
 			    CONST char *string, int maxChars));
 MODULE_SCOPE void	TclRegisterAuxDataType _ANSI_ARGS_((AuxDataType *typePtr));
 MODULE_SCOPE int	TclRegisterLiteral _ANSI_ARGS_((CompileEnv *envPtr,
-			    char *bytes, int length, int onHeap));
+			    char *bytes, int length, int flags));
 MODULE_SCOPE void	TclReleaseLiteral _ANSI_ARGS_((Tcl_Interp *interp,
 			    Tcl_Obj *objPtr));
 MODULE_SCOPE void	TclSetCmdNameObj _ANSI_ARGS_((Tcl_Interp *interp,
@@ -860,11 +860,13 @@
 
 /*
  *----------------------------------------------------------------
- * Macros used by Tcl bytecode compilation and execution modules
- * inside the Tcl core but not used outside.
+ * Macros and flag values used by Tcl bytecode compilation and execution
+ * modules inside the Tcl core but not used outside.
  *----------------------------------------------------------------
  */
 
+#define LITERAL_ON_HEAP    0x01
+#define LITERAL_NS_SCOPE   0x02
 /*
  * Form of TclRegisterLiteral with onHeap == 0.
  * In that case, it is safe to cast away CONSTness, and it
@@ -872,7 +874,19 @@
  */
 
 #define TclRegisterNewLiteral(envPtr, bytes, length) \
-	TclRegisterLiteral(envPtr, (char *)(bytes), length, /*onHeap*/ 0)
+	TclRegisterLiteral(envPtr, (char *)(bytes), length, \
+                /*flags*/ 0)
+
+/*
+ * Form of TclRegisterNSLiteral with onHeap == 0.
+ * In that case, it is safe to cast away CONSTness, and it
+ * is cleanest to do that here, all in one place.
+ */
+
+#define TclRegisterNewNSLiteral(envPtr, bytes, length) \
+	TclRegisterLiteral(envPtr, (char *)(bytes), length, \
+                /*flags*/ LITERAL_NS_SCOPE)
+
 
 /*
  * Macro used to manually adjust the stack requirements; used
Index: generic/tclExecute.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclExecute.c,v
retrieving revision 1.168
diff -u -r1.168 tclExecute.c
--- generic/tclExecute.c	15 Dec 2004 20:44:36 -0000	1.168
+++ generic/tclExecute.c	24 Dec 2004 18:02:58 -0000
@@ -885,7 +885,7 @@
 	 */
 	    
 	if (compEnv.codeNext == compEnv.codeStart) {
-	    TclEmitPush(TclRegisterLiteral(&compEnv, "0", 1, /*onHeap*/ 0),
+	    TclEmitPush(TclRegisterNewLiteral(&compEnv, "0", 1),
 		    &compEnv);
 	}
 
Index: generic/tclInt.h
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclInt.h,v
retrieving revision 1.208
diff -u -r1.208 tclInt.h
--- generic/tclInt.h	16 Dec 2004 19:36:34 -0000	1.208
+++ generic/tclInt.h	24 Dec 2004 18:02:58 -0000
@@ -973,6 +973,11 @@
 					 * entry can be freed when refCount
 					 * drops to 0. If in a local literal
 					 * table, -1. */
+    Namespace *nsPtr;                    /* Namespace in which this literal is
+					 * used. We try to avoid sharing
+					 * literal non-FQ command names among
+					 * different namespaces to reduce
+					 * shimmering.*/ 
 } LiteralEntry;
 
 typedef struct LiteralTable {
Index: generic/tclLiteral.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclLiteral.c,v
retrieving revision 1.20
diff -u -r1.20 tclLiteral.c
--- generic/tclLiteral.c	2 Aug 2004 15:33:36 -0000	1.20
+++ generic/tclLiteral.c	24 Dec 2004 18:02:58 -0000
@@ -238,17 +238,17 @@
  *	in the global table. We then add a reference to the shared
  *	literal in the CompileEnv's literal array. 
  *
- *	If onHeap is 1, this procedure is given ownership of the string: if
- *	an object is created then its string representation is set directly
- *	from string, otherwise the string is freed. Typically, a caller sets
- *	onHeap 1 if "string" is an already heap-allocated buffer holding the
- *	result of backslash substitutions.
+ *	If LITERAL_ON_HEAP is set in flags, this procedure is given ownership
+ *	of the string: if an object is created then its string representation
+ *	is set directly from string, otherwise the string is freed. Typically,
+ *	a caller sets LITERAL_ON_HEAP if "string" is an already heap-allocated
+ *	buffer holding the result of backslash substitutions.
  *
  *----------------------------------------------------------------------
  */
 
 int
-TclRegisterLiteral(envPtr, bytes, length, onHeap)
+TclRegisterLiteral(envPtr, bytes, length, flags)
     CompileEnv *envPtr;		/* Points to the CompileEnv in whose object
 				 * array an object is found or created. */
     register char *bytes;	/* Points to string for which to find or
@@ -257,9 +257,11 @@
     int length;			/* Number of bytes in the string. If < 0,
 				 * the string consists of all bytes up to
 				 * the first null character. */
-    int onHeap;			/* If 1 then the caller already malloc'd
-				 * bytes and ownership is passed to this
-				 * procedure. */
+    int flags;			/* If LITERAL_ON_HEAP then the caller already
+				 * malloc'd bytes and ownership is passed to
+				 * this procedure. If LITERAL_NS_SCOPE then
+				 * the literal shouldnot be shared accross
+				 * namespaces. */
 {
     Interp *iPtr = envPtr->iPtr;
     LiteralTable *globalTablePtr = &(iPtr->literalTable);
@@ -270,6 +272,7 @@
     int localHash, globalHash, objIndex;
     long n;
     char buf[TCL_INTEGER_SPACE];
+    Namespace *nsPtr;
 
     if (length < 0) {
 	length = (bytes? strlen(bytes) : 0);
@@ -289,7 +292,7 @@
 		|| ((objPtr->bytes[0] == bytes[0])
 			&& (memcmp(objPtr->bytes, bytes, (unsigned) length)
 				== 0)))) {
-	    if (onHeap) {
+	    if (flags & LITERAL_ON_HEAP) {
 		ckfree(bytes);
 	    }
 	    objIndex = (localPtr - envPtr->literalArrayPtr);
@@ -302,15 +305,28 @@
     }
 
     /*
-     * The literal is new to this CompileEnv. Is it in the interpreter's
-     * global literal table?
+     * The literal is new to this CompileEnv. Should it be shared accross
+     * namespaces? If it is a fully qualified name, the namespace
+     * specification is not needed to avoid sharing.
+     */
+
+    if ((flags & LITERAL_NS_SCOPE) && iPtr->varFramePtr
+	    && ((length <2) || (bytes[0] != ':') || (bytes[1] != ':'))) {
+	nsPtr = iPtr->varFramePtr->nsPtr;
+    } else {
+	nsPtr = NULL;
+    }
+
+    /*
+     * Is it in the interpreter's global literal table?
      */
 
     globalHash = (hash & globalTablePtr->mask);
     for (globalPtr = globalTablePtr->buckets[globalHash];
 	 globalPtr != NULL;  globalPtr = globalPtr->nextPtr) {
 	objPtr = globalPtr->objPtr;
-	if ((objPtr->length == length) && ((length == 0)
+	if ((globalPtr->nsPtr == nsPtr)
+		&& (objPtr->length == length) && ((length == 0)
 		|| ((objPtr->bytes[0] == bytes[0])
 			&& (memcmp(objPtr->bytes, bytes, (unsigned) length)
 				== 0)))) {
@@ -319,7 +335,7 @@
 	     * local literal array.
 	     */
 	    
-	    if (onHeap) {
+	    if (flags & LITERAL_ON_HEAP) {
 		ckfree(bytes);
 	    }
 	    objIndex = AddLocalLiteralEntry(envPtr, globalPtr, localHash);
@@ -343,7 +359,7 @@
 
     TclNewObj(objPtr);
     Tcl_IncrRefCount(objPtr);
-    if (onHeap) {
+    if (flags & LITERAL_ON_HEAP) {
 	objPtr->bytes = bytes;
 	objPtr->length = length;
     } else {
@@ -373,6 +389,7 @@
     globalPtr = (LiteralEntry *) ckalloc((unsigned) sizeof(LiteralEntry));
     globalPtr->objPtr = objPtr;
     globalPtr->refCount = 0;
+    globalPtr->nsPtr = nsPtr;
     globalPtr->nextPtr = globalTablePtr->buckets[globalHash];
     globalTablePtr->buckets[globalHash] = globalPtr;
     globalTablePtr->numEntries++;
Index: generic/tclProc.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclProc.c,v
retrieving revision 1.71
diff -u -r1.71 tclProc.c
--- generic/tclProc.c	20 Dec 2004 21:20:06 -0000	1.71
+++ generic/tclProc.c	24 Dec 2004 18:02:59 -0000
@@ -1837,6 +1837,6 @@
 	} 
     }
     envPtr->currStackDepth = savedStackDepth;
-    TclEmitPush(TclRegisterLiteral(envPtr, "", 0, /*onHeap*/ 0), envPtr);
+    TclEmitPush(TclRegisterNewLiteral(envPtr, "", 0), envPtr);
     return TCL_OK;
 }