summaryrefslogtreecommitdiffstats
path: root/generic
diff options
context:
space:
mode:
authordgp <dgp@users.sourceforge.net>2008-01-17 17:45:48 (GMT)
committerdgp <dgp@users.sourceforge.net>2008-01-17 17:45:48 (GMT)
commitd65d106e08beec7af30268e183a2e2e267515f0e (patch)
treebe85d3374b911c3a482ec5fd2ee41bab84e51f5d /generic
parentd2345775974324ce25f617209a264d6e64b57cd6 (diff)
downloadtcl-d65d106e08beec7af30268e183a2e2e267515f0e.zip
tcl-d65d106e08beec7af30268e183a2e2e267515f0e.tar.gz
tcl-d65d106e08beec7af30268e183a2e2e267515f0e.tar.bz2
* generic/tclCompExpr.c: Revision to preserve parsed intreps
of numeric and boolean literals when compiling expressions with (optimize == 1).
Diffstat (limited to 'generic')
-rw-r--r--generic/tclCompExpr.c47
1 files changed, 42 insertions, 5 deletions
diff --git a/generic/tclCompExpr.c b/generic/tclCompExpr.c
index c3d7532..5039218 100644
--- a/generic/tclCompExpr.c
+++ b/generic/tclCompExpr.c
@@ -10,7 +10,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclCompExpr.c,v 1.93 2008/01/16 21:05:47 msofer Exp $
+ * RCS: @(#) $Id: tclCompExpr.c,v 1.94 2008/01/17 17:45:51 dgp Exp $
*/
#include "tclInt.h"
@@ -834,6 +834,22 @@ ParseExpr(
switch (lexeme) {
case NUMBER:
case BOOLEAN:
+ /*
+ * TODO: Consider using a dict or hash to collapse all
+ * duplicate literals into a single representative value.
+ * (Like what is done with [split $s {}]).
+ * Pro: ~75% memory saving on expressions like
+ * {1+1+1+1+1+.....+1} (Convert "pointer + Tcl_Obj" cost
+ * to "pointer" cost only)
+ * Con: Cost of the dict store/retrieve on every literal
+ * in every expression when expressions like the above
+ * tend to be uncommon.
+ * The memory savings is temporary; Compiling to bytecode
+ * will collapse things as literals are registered
+ * anyway, so the savings applies only to the time
+ * between parsing and compiling. Possibly important
+ * due to high-water mark nature of memory allocation.
+ */
Tcl_ListObjAppendElement(NULL, litList, literal);
complete = lastParsed = OT_LITERAL;
start += scanned;
@@ -2314,12 +2330,33 @@ CompileExprTree(
Tcl_Obj *literal = *litObjv;
if (optimize) {
- int length;
+ int length, index;
const char *bytes = TclGetStringFromObj(literal, &length);
+ LiteralEntry *lePtr;
+ Tcl_Obj *objPtr;
- /* TODO: Consider ways to preserve intrep */
- TclEmitPush(TclRegisterNewLiteral(envPtr, bytes, length),
- envPtr);
+ index = TclRegisterNewLiteral(envPtr, bytes, length);
+ lePtr = envPtr->literalArrayPtr + index;
+ objPtr = lePtr->objPtr;
+ if ((objPtr->typePtr == NULL) && (literal->typePtr != NULL)) {
+ /*
+ * Would like to do this:
+ *
+ * lePtr->objPtr = literal;
+ * Tcl_IncrRefCount(literal);
+ * Tcl_DecrRefCount(objPtr);
+ *
+ * However, the design of the "global" and "local"
+ * LiteralTable does not permit the value of lePtr->objPtr
+ * to change. So rather than replace lePtr->objPtr, we
+ * do surgery to transfer our desired intrep into it.
+ *
+ */
+ objPtr->typePtr = literal->typePtr;
+ objPtr->internalRep = literal->internalRep;
+ literal->typePtr = NULL;
+ }
+ TclEmitPush(index, envPtr);
} else {
/*
* When optimize==0, we know the expression is a one-off