From 61df5f46580699c45d9263e3e98a0cf3f2006672 Mon Sep 17 00:00:00 2001 From: dgp Date: Thu, 13 Oct 2016 15:37:45 +0000 Subject: Streamline the substring copying case of [string replace] bytecode execution. --- generic/tclExecute.c | 66 ++++++++++++++++++---------------------------------- 1 file changed, 23 insertions(+), 43 deletions(-) diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 34d92d3..cd27f6b 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -5804,57 +5804,37 @@ TEBCresume( * Remove substring using copying. */ - if (length3 == 0) { - if (fromIdx > 0) { - objResultPtr = Tcl_NewUnicodeObj(ustring1, fromIdx); - if (toIdx < length) { - Tcl_AppendUnicodeToObj(objResultPtr, ustring1 + toIdx + 1, - length - toIdx); - } - } else { - objResultPtr = Tcl_NewUnicodeObj(ustring1 + toIdx + 1, - length - toIdx); - } - TclDecrRefCount(value3Ptr); - TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); - NEXT_INST_F(1, 1, 1); - } - - /* - * Splice string pieces by full copying. - */ - + objResultPtr = NULL; if (fromIdx > 0) { objResultPtr = Tcl_NewUnicodeObj(ustring1, fromIdx); - Tcl_AppendObjToObj(objResultPtr, value3Ptr); - if (toIdx < length) { - Tcl_AppendUnicodeToObj(objResultPtr, ustring1 + toIdx + 1, - length - toIdx); + } + if (length3 > 0) { + if (objResultPtr) { + Tcl_AppendObjToObj(objResultPtr, value3Ptr); + } else if (Tcl_IsShared(value3Ptr)) { + objResultPtr = Tcl_DuplicateObj(value3Ptr); + } else { + objResultPtr = value3Ptr; } - } else if (Tcl_IsShared(value3Ptr)) { - objResultPtr = Tcl_DuplicateObj(value3Ptr); - if (toIdx < length) { + } + if (toIdx < length) { + if (objResultPtr) { Tcl_AppendUnicodeToObj(objResultPtr, ustring1 + toIdx + 1, length - toIdx); - } - } else { - /* - * Be careful with splicing the stack in this case; we have a - * refCount:1 object in value3Ptr and we want to append to it and - * make it be the refCount:1 object at the top of the stack - * afterwards. [Bug 82e7f67325] - */ - - if (toIdx < length) { - Tcl_AppendUnicodeToObj(value3Ptr, ustring1 + toIdx + 1, + } else { + objResultPtr = Tcl_NewUnicodeObj(ustring1 + toIdx + 1, length - toIdx); } - TRACE_APPEND(("\"%.30s\"\n", O2S(value3Ptr))); - TclDecrRefCount(valuePtr); - OBJ_AT_TOS = value3Ptr; /* Tricky! */ - NEXT_INST_F(1, 0, 0); } - TclDecrRefCount(value3Ptr); + if (objResultPtr == NULL) { + /* This has to be the case [string replace $s 0 end {}] */ + /* which has result {} which is same as value3Ptr. */ + objResultPtr = value3Ptr; + } + if (objResultPtr != value3Ptr) { + /* See [Bug 82e7f67325] */ + TclDecrRefCount(value3Ptr); + } TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); NEXT_INST_F(1, 1, 1); -- cgit v0.12 From dca9bb39489c9c228b3c1ccc6019e3cee3699c7a Mon Sep 17 00:00:00 2001 From: dgp Date: Thu, 13 Oct 2016 16:43:05 +0000 Subject: Stop invading the String internals to work around a bug. Fix it instead. --- generic/tclExecute.c | 13 ------------- generic/tclStringObj.c | 10 ++++++++++ 2 files changed, 10 insertions(+), 13 deletions(-) diff --git a/generic/tclExecute.c b/generic/tclExecute.c index cd27f6b..56e3f72 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -19,7 +19,6 @@ #include "tclCompile.h" #include "tclOOInt.h" #include "tommath.h" -#include "tclStringRep.h" #include #include @@ -5744,16 +5743,6 @@ TEBCresume( if (length3 - 1 == toIdx - fromIdx) { unsigned char *bytes1, *bytes2; - /* - * Flush the info in the string internal rep that refers to the - * about-to-be-invalidated UTF-8 rep. This indicates that a new - * buffer needs to be allocated, and assumes that the value is - * already of tclStringTypePtr type, which should be true provided - * we call it after Tcl_GetUnicodeFromObj. - */ -#define MarkStringInternalRepForFlush(objPtr) \ - (GET_STRING(objPtr)->allocated = 0) - if (Tcl_IsShared(valuePtr)) { objResultPtr = Tcl_DuplicateObj(valuePtr); if (TclIsPureByteArray(objResultPtr) @@ -5766,7 +5755,6 @@ TEBCresume( ustring2 = Tcl_GetUnicodeFromObj(value3Ptr, NULL); memcpy(ustring1 + fromIdx, ustring2, length3 * sizeof(Tcl_UniChar)); - MarkStringInternalRepForFlush(objResultPtr); } Tcl_InvalidateStringRep(objResultPtr); TclDecrRefCount(value3Ptr); @@ -5783,7 +5771,6 @@ TEBCresume( ustring2 = Tcl_GetUnicodeFromObj(value3Ptr, NULL); memcpy(ustring1 + fromIdx, ustring2, length3 * sizeof(Tcl_UniChar)); - MarkStringInternalRepForFlush(valuePtr); } Tcl_InvalidateStringRep(valuePtr); TclDecrRefCount(value3Ptr); diff --git a/generic/tclStringObj.c b/generic/tclStringObj.c index 11a57e9..60b08ae 100644 --- a/generic/tclStringObj.c +++ b/generic/tclStringObj.c @@ -3025,6 +3025,16 @@ UpdateStringOfString( { String *stringPtr = GET_STRING(objPtr); + /* + * This routine is only called when we need to generate the + * string rep objPtr->bytes because it does not exist -- it is NULL. + * In that circumstance, any lingering claim about the size of + * memory pointed to by that NULL pointer is clearly bogus, and + * needs a reset. + */ + + stringPtr->allocated = 0; + if (stringPtr->numChars == 0) { TclInitStringRep(objPtr, tclEmptyStringRep, 0); } else { -- cgit v0.12 From 23b011c32d44c8182e0a04316704b590bd2920dd Mon Sep 17 00:00:00 2001 From: dgp Date: Thu, 13 Oct 2016 16:50:06 +0000 Subject: Another streamline. --- generic/tclExecute.c | 48 +++++++++++++++++++----------------------------- 1 file changed, 19 insertions(+), 29 deletions(-) diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 56e3f72..e7ff8dc 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -5745,37 +5745,27 @@ TEBCresume( if (Tcl_IsShared(valuePtr)) { objResultPtr = Tcl_DuplicateObj(valuePtr); - if (TclIsPureByteArray(objResultPtr) - && TclIsPureByteArray(value3Ptr)) { - bytes1 = Tcl_GetByteArrayFromObj(objResultPtr, NULL); - bytes2 = Tcl_GetByteArrayFromObj(value3Ptr, NULL); - memcpy(bytes1 + fromIdx, bytes2, length3); - } else { - ustring1 = Tcl_GetUnicodeFromObj(objResultPtr, NULL); - ustring2 = Tcl_GetUnicodeFromObj(value3Ptr, NULL); - memcpy(ustring1 + fromIdx, ustring2, - length3 * sizeof(Tcl_UniChar)); - } - Tcl_InvalidateStringRep(objResultPtr); - TclDecrRefCount(value3Ptr); - TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); - NEXT_INST_F(1, 1, 1); } else { - if (TclIsPureByteArray(valuePtr) - && TclIsPureByteArray(value3Ptr)) { - bytes1 = Tcl_GetByteArrayFromObj(valuePtr, NULL); - bytes2 = Tcl_GetByteArrayFromObj(value3Ptr, NULL); - memcpy(bytes1 + fromIdx, bytes2, length3); - } else { - ustring1 = Tcl_GetUnicodeFromObj(valuePtr, NULL); - ustring2 = Tcl_GetUnicodeFromObj(value3Ptr, NULL); - memcpy(ustring1 + fromIdx, ustring2, - length3 * sizeof(Tcl_UniChar)); - } - Tcl_InvalidateStringRep(valuePtr); - TclDecrRefCount(value3Ptr); - TRACE_APPEND(("\"%.30s\"\n", O2S(valuePtr))); + objResultPtr = valuePtr; + } + if (TclIsPureByteArray(objResultPtr) + && TclIsPureByteArray(value3Ptr)) { + bytes1 = Tcl_GetByteArrayFromObj(objResultPtr, NULL); + bytes2 = Tcl_GetByteArrayFromObj(value3Ptr, NULL); + memcpy(bytes1 + fromIdx, bytes2, length3); + } else { + ustring1 = Tcl_GetUnicodeFromObj(objResultPtr, NULL); + ustring2 = Tcl_GetUnicodeFromObj(value3Ptr, NULL); + memcpy(ustring1 + fromIdx, ustring2, + length3 * sizeof(Tcl_UniChar)); + } + Tcl_InvalidateStringRep(objResultPtr); + TclDecrRefCount(value3Ptr); + TRACE_APPEND(("\"%.30s\"\n", O2S(objResultPtr))); + if (objResultPtr == valuePtr) { NEXT_INST_F(1, 0, 0); + } else { + NEXT_INST_F(1, 1, 1); } } -- cgit v0.12