summaryrefslogtreecommitdiffstats
path: root/generic/tclCmdIL.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/tclCmdIL.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/tclCmdIL.c')
-rw-r--r--generic/tclCmdIL.c46
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;
}