diff options
author | dgp <dgp@users.sourceforge.net> | 2015-11-30 18:24:03 (GMT) |
---|---|---|
committer | dgp <dgp@users.sourceforge.net> | 2015-11-30 18:24:03 (GMT) |
commit | efe36a3e290e2f47f8bed9ca19569cf46d0079ce (patch) | |
tree | e974efb50137031d77c3aaade660be8b3c54ac2d /generic | |
parent | 0994fde7781b45449af20570e7ac1295e647cab9 (diff) | |
download | tcl-efe36a3e290e2f47f8bed9ca19569cf46d0079ce.zip tcl-efe36a3e290e2f47f8bed9ca19569cf46d0079ce.tar.gz tcl-efe36a3e290e2f47f8bed9ca19569cf46d0079ce.tar.bz2 |
[32c5740a4d] Have Tcl_ListObjReplace() try to use realloc() for growing when
it can do so.
Diffstat (limited to 'generic')
-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; |