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;
}