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/tclCmdIL.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/tclCmdIL.c')
-rw-r--r-- | generic/tclCmdIL.c | 46 |
1 files changed, 13 insertions, 33 deletions
diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c index 746d033..1813fe0 100644 --- a/generic/tclCmdIL.c +++ b/generic/tclCmdIL.c @@ -15,7 +15,7 @@ * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclCmdIL.c,v 1.71 2004/12/14 21:11:45 msofer Exp $ + * RCS: @(#) $Id: tclCmdIL.c,v 1.72 2005/04/02 02:08:31 msofer Exp $ */ #include "tclInt.h" @@ -2866,8 +2866,9 @@ Tcl_LrepeatObjCmd(dummy, interp, objc, objv) register Tcl_Obj *CONST objv[]; /* The argument objects. */ { int elementCount, i, result; - Tcl_Obj **dataArray; - + Tcl_Obj *listPtr, **dataArray; + List *listRepPtr; + /* * Check arguments for legality: * lrepeat posInt value ?value ...? @@ -2896,33 +2897,14 @@ Tcl_LrepeatObjCmd(dummy, interp, objc, objv) objv += 2; /* - * Create workspace array large enough to hold each init value - * elementCount times. Note that we don't bother with stack - * allocation for this, as we expect this function to be used - * mainly when stack allocation would be inappropriate anyway. - * First check to see if we'd overflow and try to allocate an - * object larger than our memory allocator allows. Note that this - * is actually a fairly small value when you're on a serious - * 64-bit machine, but that requires API changes to fix. - * - * We allocate using attemptckalloc() because if we ask for - * something big but can't get it, we've still got a high chance - * of having a proper failover strategy. If *that* fails to get - * memory, Tcl_Panic() will happen just a few lines lower... + * Get an empty list object that is allocated large enough to hold each + * init value elementCount times. */ - if ((unsigned)elementCount > INT_MAX/sizeof(Tcl_Obj *)/objc) { - Tcl_AppendResult(interp, "overflow of maximum list length", NULL); - return TCL_ERROR; - } - - dataArray = (Tcl_Obj **) - attemptckalloc(elementCount * objc * sizeof(Tcl_Obj *)); - - if (dataArray == NULL) { - Tcl_AppendResult(interp, "insufficient memory to create list", NULL); - return TCL_ERROR; - } + listPtr = Tcl_NewListObj(elementCount*objc, NULL); + listRepPtr = (List *) listPtr->internalRep.twoPtrValue.ptr1; + listRepPtr->elemCount = elementCount*objc; + dataArray = &listRepPtr->elements; /* * Set the elements. Note that we handle the common degenerate @@ -2934,6 +2916,7 @@ Tcl_LrepeatObjCmd(dummy, interp, objc, objv) if (objc == 1) { register Tcl_Obj *tmpPtr = objv[0]; + tmpPtr->refCount += elementCount; for (i=0 ; i<elementCount ; i++) { dataArray[i] = tmpPtr; } @@ -2942,16 +2925,13 @@ Tcl_LrepeatObjCmd(dummy, interp, objc, objv) for (i=0 ; i<elementCount ; i++) { for (j=0 ; j<objc ; j++) { + Tcl_IncrRefCount(objv[j]); dataArray[k++] = objv[j]; } } } - /* - * Build the result list, clean up and return. - */ - - Tcl_SetObjResult(interp, TclNewListObjDirect(elementCount*objc,dataArray)); + Tcl_SetObjResult(interp, listPtr); return TCL_OK; } |