diff options
author | dgp <dgp@noemail.net> | 2015-11-30 18:24:03 (GMT) |
---|---|---|
committer | dgp <dgp@noemail.net> | 2015-11-30 18:24:03 (GMT) |
commit | 3ef0ca053eb1bfbb53a49dce0e392f4d7bb708e3 (patch) | |
tree | cd8826d0ca3017c6608aacf783028b34c9c391f7 | |
parent | aee25d1338dede7e8dee1272dee4d1b14a41cd83 (diff) | |
download | tcl-3ef0ca053eb1bfbb53a49dce0e392f4d7bb708e3.zip tcl-3ef0ca053eb1bfbb53a49dce0e392f4d7bb708e3.tar.gz tcl-3ef0ca053eb1bfbb53a49dce0e392f4d7bb708e3.tar.bz2 |
[32c5740a4d] Have Tcl_ListObjReplace() try to use realloc() for growing when
it can do so.
FossilOrigin-Name: a467b03d94c80bdee5623352dc1f221e5a98201f
-rw-r--r-- | generic/tclListObj.c | 33 |
1 files changed, 30 insertions, 3 deletions
diff --git a/generic/tclListObj.c b/generic/tclListObj.c index 0dfa845..14b8a14 100644 --- a/generic/tclListObj.c +++ b/generic/tclListObj.c @@ -857,7 +857,7 @@ Tcl_ListObjReplace( { List *listRepPtr; register Tcl_Obj **elemPtrs; - int numElems, numRequired, numAfterLast, start, i, j, isShared; + int needGrow, numElems, numRequired, numAfterLast, start, i, j, isShared; if (Tcl_IsShared(listPtr)) { Tcl_Panic("%s called with shared object", "Tcl_ListObjReplace"); @@ -913,12 +913,39 @@ Tcl_ListObjReplace( } isShared = (listRepPtr->refCount > 1); numRequired = numElems - count + objc; /* Known <= LIST_MAX */ + needGrow = numRequired > listRepPtr->maxElemCount; for (i = 0; i < objc; i++) { Tcl_IncrRefCount(objv[i]); } - if ((numRequired <= listRepPtr->maxElemCount) && !isShared) { + if (needGrow && !isShared) { + /* Try to use realloc */ + List *newPtr = NULL; + int attempt = 2 * numRequired; + if (attempt <= LIST_MAX) { + newPtr = attemptckrealloc(listRepPtr, LIST_SIZE(attempt)); + } + if (newPtr == NULL) { + attempt = numRequired + 1 + TCL_MIN_ELEMENT_GROWTH; + if (attempt > LIST_MAX) { + attempt = LIST_MAX; + } + newPtr = attemptckrealloc(listRepPtr, LIST_SIZE(attempt)); + } + if (newPtr == NULL) { + attempt = numRequired; + newPtr = attemptckrealloc(listRepPtr, LIST_SIZE(attempt)); + } + if (newPtr) { + listRepPtr = newPtr; + listPtr->internalRep.twoPtrValue.ptr1 = listRepPtr; + elemPtrs = &listRepPtr->elements; + listRepPtr->maxElemCount = attempt; + needGrow = numRequired > listRepPtr->maxElemCount; + } + } + if (!needGrow && !isShared) { int shift; /* @@ -955,7 +982,7 @@ Tcl_ListObjReplace( Tcl_Obj **oldPtrs = elemPtrs; int newMax; - if (numRequired > listRepPtr->maxElemCount){ + if (needGrow){ newMax = 2 * numRequired; } else { newMax = listRepPtr->maxElemCount; |