summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authordkf <donal.k.fellows@manchester.ac.uk>2012-02-16 13:51:02 (GMT)
committerdkf <donal.k.fellows@manchester.ac.uk>2012-02-16 13:51:02 (GMT)
commitb4ca6b5a992c406bbf4f3ef73ecb5ae2a8d878a6 (patch)
treeb94afa1b480c83e5095e24e1d8596e4c76b8708a
parent182448a5403990b1f583b5f9cf6cf6d8e2b7c8de (diff)
downloadtcl-b4ca6b5a992c406bbf4f3ef73ecb5ae2a8d878a6.zip
tcl-b4ca6b5a992c406bbf4f3ef73ecb5ae2a8d878a6.tar.gz
tcl-b4ca6b5a992c406bbf4f3ef73ecb5ae2a8d878a6.tar.bz2
* generic/tclExecute.c (INST_LIST_RANGE_IMM): Enhance implementation
so that shortening a (not multiply-referenced) list by lopping the end off with [lrange] or [lreplace] is efficient.
-rw-r--r--ChangeLog6
-rw-r--r--generic/tclExecute.c25
2 files changed, 29 insertions, 2 deletions
diff --git a/ChangeLog b/ChangeLog
index e5d23bf..7f8c443 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2012-02-16 Donal K. Fellows <dkf@users.sf.net>
+
+ * generic/tclExecute.c (INST_LIST_RANGE_IMM): Enhance implementation
+ so that shortening a (not multiply-referenced) list by lopping the end
+ off with [lrange] or [lreplace] is efficient.
+
2012-02-15 Donal K. Fellows <dkf@users.sf.net>
* generic/tclCompCmds.c (TclCompileLreplaceCmd): Added a compilation
diff --git a/generic/tclExecute.c b/generic/tclExecute.c
index 92b6612..e402634 100644
--- a/generic/tclExecute.c
+++ b/generic/tclExecute.c
@@ -4310,12 +4310,33 @@ TEBCresume(
*/
if (fromIdx<=toIdx && fromIdx<objc && toIdx>=0) {
- if (fromIdx<0) {
+ if (fromIdx < 0) {
fromIdx = 0;
}
if (toIdx >= objc) {
toIdx = objc-1;
}
+ if (fromIdx == 0 && toIdx != objc-1 && !Tcl_IsShared(valuePtr)) {
+ /*
+ * BEWARE! This is looking inside the implementation of the
+ * list type.
+ */
+
+ List *listPtr = valuePtr->internalRep.twoPtrValue.ptr1;
+
+ if (listPtr->refCount == 1) {
+ TRACE(("\"%.30s\" %d %d => ", O2S(valuePtr),
+ TclGetInt4AtPtr(pc+1), TclGetInt4AtPtr(pc+5)));
+ for (index=toIdx+1 ; index<objc-1 ; index++) {
+ TclDecrRefCount(objv[index]);
+ }
+ listPtr->elemCount = toIdx+1;
+ listPtr->canonicalFlag = 1;
+ TclInvalidateStringRep(valuePtr);
+ TRACE_APPEND(("%.30s\n", O2S(valuePtr)));
+ NEXT_INST_F(9, 0, 0);
+ }
+ }
objResultPtr = Tcl_NewListObj(toIdx-fromIdx+1, objv+fromIdx);
} else {
TclNewObj(objResultPtr);
@@ -5716,7 +5737,7 @@ TEBCresume(
}
result = TclIncrObj(interp, valuePtr, value2Ptr);
if (result == TCL_OK) {
- Tcl_InvalidateStringRep(dictPtr);
+ TclInvalidateStringRep(dictPtr);
}
TclDecrRefCount(value2Ptr);
}