diff options
author | Miguel Sofer <miguel.sofer@gmail.com> | 2005-04-02 02:08:22 (GMT) |
---|---|---|
committer | Miguel Sofer <miguel.sofer@gmail.com> | 2005-04-02 02:08:22 (GMT) |
commit | 95b50e96cfeca13080aa95e5a4cd378cbea25955 (patch) | |
tree | 60e127a56dc4b46c2944f5cd3e2270be9489cdca /generic/tclBasic.c | |
parent | fbb5749d9fa84503a3480ab6e24a9f0436772110 (diff) | |
download | tcl-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.c | 37 |
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); |