summaryrefslogtreecommitdiffstats
path: root/generic/tclBasic.c
diff options
context:
space:
mode:
authorMiguel Sofer <miguel.sofer@gmail.com>2005-04-02 02:08:22 (GMT)
committerMiguel Sofer <miguel.sofer@gmail.com>2005-04-02 02:08:22 (GMT)
commit95b50e96cfeca13080aa95e5a4cd378cbea25955 (patch)
tree60e127a56dc4b46c2944f5cd3e2270be9489cdca /generic/tclBasic.c
parentfbb5749d9fa84503a3480ab6e24a9f0436772110 (diff)
downloadtcl-95b50e96cfeca13080aa95e5a4cd378cbea25955.zip
tcl-95b50e96cfeca13080aa95e5a4cd378cbea25955.tar.gz
tcl-95b50e96cfeca13080aa95e5a4cd378cbea25955.tar.bz2
Changed the internal representation of lists to (a) reduce the malloc/free
calls at list creation (from 2 to 1), (b) reduce the cost of handling empty lists (we now never create a list internal rep for them), (c) allow refcounting of the list internal rep. The latter permits insuring that the pointers returned by Tcl_ListObjGetElements remain valid even if the object shimmers away from its original list type. This is [Patch 1158008]
Diffstat (limited to 'generic/tclBasic.c')
-rw-r--r--generic/tclBasic.c37
1 files changed, 21 insertions, 16 deletions
diff --git a/generic/tclBasic.c b/generic/tclBasic.c
index 1c497dc..bcb8967 100644
--- a/generic/tclBasic.c
+++ b/generic/tclBasic.c
@@ -13,7 +13,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclBasic.c,v 1.142 2005/03/18 15:50:59 dgp Exp $
+ * RCS: @(#) $Id: tclBasic.c,v 1.143 2005/04/02 02:08:29 msofer Exp $
*/
#include "tclInt.h"
@@ -3754,26 +3754,31 @@ Tcl_EvalObjEx(interp, objPtr, flags)
*/
if ((objPtr->typePtr == &tclListType) && /* is a list... */
(objPtr->bytes == NULL) /* ...without a string rep */) {
- List *listRepPtr =
- (List *) objPtr->internalRep.twoPtrValue.ptr1;
- int i, objc = listRepPtr->elemCount;
- Tcl_Obj **objv;
+ List *listRepPtr;
/*
- * Copy the list elements here, to avoid a segfault if objPtr
- * loses its List internal rep [Bug 1119369]
+ * Increase the reference count of the List structure, to avoid a
+ * segfault if objPtr loses its List internal rep [Bug 1119369]
*/
- objv = (Tcl_Obj **) TclStackAlloc(interp, objc*sizeof(Tcl_Obj *));
- for (i=0; i < objc; i++) {
- objv[i] = listRepPtr->elements[i];
- Tcl_IncrRefCount(objv[i]);
- }
- result = Tcl_EvalObjv(interp, objc, objv, flags);
- for (i=0; i < objc; i++) {
- TclDecrRefCount(objv[i]);
+ listRepPtr = (List *) objPtr->internalRep.twoPtrValue.ptr1;
+ listRepPtr->refCount++;
+
+ result = Tcl_EvalObjv(interp, listRepPtr->elemCount,
+ &listRepPtr->elements, flags);
+
+ /*
+ * If we are the last users of listRepPtr, free it.
+ */
+
+ if (--listRepPtr->refCount <= 0) {
+ int i, elemCount = listRepPtr->elemCount;
+ Tcl_Obj **elements = &listRepPtr->elements;
+ for (i=0; i<elemCount; i++) {
+ Tcl_DecrRefCount(elements[i]);
+ }
+ ckfree((char *) listRepPtr);
}
- TclStackFree(interp);
} else {
script = Tcl_GetStringFromObj(objPtr, &numSrcBytes);
result = Tcl_EvalEx(interp, script, numSrcBytes, flags);