summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorferrieux <ferrieux@users.sourceforge.net>2014-08-05 18:20:48 (GMT)
committerferrieux <ferrieux@users.sourceforge.net>2014-08-05 18:20:48 (GMT)
commit504a1200f71158b91d5d939b25c21c5110985963 (patch)
treeb5b62a2a7d17f0c9726d18fe2af9f636c53ded71
parent201e2d1d6adb55742fd72f75a35c18bba901a0eb (diff)
downloadtcl-504a1200f71158b91d5d939b25c21c5110985963.zip
tcl-504a1200f71158b91d5d939b25c21c5110985963.tar.gz
tcl-504a1200f71158b91d5d939b25c21c5110985963.tar.bz2
More aggressive constant folding in [string cat]. Thanks AndreasK for kicking.
-rw-r--r--generic/tclCompCmdsSZ.c47
1 files changed, 27 insertions, 20 deletions
diff --git a/generic/tclCompCmdsSZ.c b/generic/tclCompCmdsSZ.c
index 87b1ebb..fb26430 100644
--- a/generic/tclCompCmdsSZ.c
+++ b/generic/tclCompCmdsSZ.c
@@ -289,19 +289,38 @@ TclCompileStringCatCmd(
return TCL_OK;
}
- /* Detection of foldable constants. Often used for mixed quoting. */
+ /* General case: issue CONCAT1's (by chunks of 255 if needed), folding
+ contiguous constants along the way */
- folded = Tcl_NewObj();
+ numArgs = 0;
+ folded = NULL;
wordTokenPtr = TokenAfter(parsePtr->tokenPtr);
for (i = 1; i < numWords; i++) {
obj = Tcl_NewObj();
if (TclWordKnownAtCompileTime(wordTokenPtr, obj)) {
- Tcl_AppendObjToObj(folded, obj);
+ if (folded) {
+ Tcl_AppendObjToObj(folded, obj);
+ Tcl_DecrRefCount(obj);
+ } else {
+ folded = obj;
+ }
} else {
Tcl_DecrRefCount(obj);
- Tcl_DecrRefCount(folded);
- folded = NULL;
- break;
+ if (folded) {
+ int len;
+ const char *bytes = Tcl_GetStringFromObj(folded, &len);
+
+ PushLiteral(envPtr, bytes, len);
+ Tcl_DecrRefCount(folded);
+ folded = NULL;
+ numArgs ++;
+ }
+ CompileWord(envPtr, wordTokenPtr, interp, i);
+ numArgs ++;
+ if (numArgs >= 254) { /* 254 to take care of the possible +1 of "folded" above */
+ TclEmitInstInt1(INST_STR_CONCAT1, 254, envPtr);
+ numArgs -= 253; /* concat pushes 1 obj, the result */
+ }
}
wordTokenPtr = TokenAfter(wordTokenPtr);
}
@@ -310,21 +329,9 @@ TclCompileStringCatCmd(
const char *bytes = Tcl_GetStringFromObj(folded, &len);
PushLiteral(envPtr, bytes, len);
- return TCL_OK;
- }
-
- /* General case: just issue CONCAT1's (by chunks of 255 if needed) */
-
- numArgs = 0;
- wordTokenPtr = TokenAfter(parsePtr->tokenPtr);
- for (i = 1; i < numWords; i++) {
- CompileWord(envPtr, wordTokenPtr, interp, i);
+ Tcl_DecrRefCount(folded);
+ folded = NULL;
numArgs ++;
- if (numArgs == 255) {
- TclEmitInstInt1(INST_STR_CONCAT1, 255, envPtr);
- numArgs = 1; /* concat pushes 1 obj, the result */
- }
- wordTokenPtr = TokenAfter(wordTokenPtr);
}
if (numArgs > 1) {
TclEmitInstInt1(INST_STR_CONCAT1, numArgs, envPtr);