diff options
author | ferrieux <ferrieux@users.sourceforge.net> | 2008-06-29 23:05:56 (GMT) |
---|---|---|
committer | ferrieux <ferrieux@users.sourceforge.net> | 2008-06-29 23:05:56 (GMT) |
commit | 6806d5f10cc77778fd3bac70f636b1e1210d6ced (patch) | |
tree | 12a97631f8850a1945efc601dbe8d9358fc30ad7 /generic/tclExecute.c | |
parent | 131a59f68c8b1673c1fcd9b035bb7791eea72bc9 (diff) | |
download | tcl-6806d5f10cc77778fd3bac70f636b1e1210d6ced.zip tcl-6806d5f10cc77778fd3bac70f636b1e1210d6ced.tar.gz tcl-6806d5f10cc77778fd3bac70f636b1e1210d6ced.tar.bz2 |
Avoid useless String conversion for CONCAT1 of pure byte arrays [Patch 1953758].
Diffstat (limited to 'generic/tclExecute.c')
-rw-r--r-- | generic/tclExecute.c | 58 |
1 files changed, 57 insertions, 1 deletions
diff --git a/generic/tclExecute.c b/generic/tclExecute.c index 6e0d0d3..f00b01a 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -14,7 +14,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclExecute.c,v 1.373 2008/06/13 05:45:10 mistachkin Exp $ + * RCS: @(#) $Id: tclExecute.c,v 1.374 2008/06/29 23:05:56 ferrieux Exp $ */ #include "tclInt.h" @@ -2122,19 +2122,42 @@ TclExecuteByteCode( int opnd, length, appendLen = 0; char *bytes, *p; Tcl_Obj **currPtr; + int onlyb ; opnd = TclGetUInt1AtPtr(pc+1); /* + * Detect only-bytearray-or-null case + */ + onlyb = 1; + for (currPtr=&OBJ_AT_DEPTH(opnd-1); currPtr<=&OBJ_AT_TOS; currPtr++) { + if (((*currPtr)->typePtr != &tclByteArrayType) + &&((*currPtr)->bytes != tclEmptyStringRep)) + {onlyb=0;break;} + } + + /* * Compute the length to be appended. */ + if (onlyb) + { + for (currPtr=&OBJ_AT_DEPTH(opnd-2); currPtr<=&OBJ_AT_TOS; currPtr++) { + if ((*currPtr)->bytes == tclEmptyStringRep) + continue; /* don't shimmer nulls */ + Tcl_GetByteArrayFromObj(*currPtr, &length); + appendLen += length; + } + } + else + { for (currPtr=&OBJ_AT_DEPTH(opnd-2); currPtr<=&OBJ_AT_TOS; currPtr++) { bytes = TclGetStringFromObj(*currPtr, &length); if (bytes != NULL) { appendLen += length; } } + } /* * If nothing is to be appended, just return the first object by @@ -2158,6 +2181,8 @@ TclExecuteByteCode( */ objResultPtr = OBJ_AT_DEPTH(opnd-1); + if (!onlyb) + { bytes = TclGetStringFromObj(objResultPtr, &length); #if !TCL_COMPILE_DEBUG if (bytes != tclEmptyStringRep && !Tcl_IsShared(objResultPtr)) { @@ -2191,6 +2216,37 @@ TclExecuteByteCode( } *p = '\0'; + } else { + + bytes = (char *) Tcl_GetByteArrayFromObj(objResultPtr, &length); +#if !TCL_COMPILE_DEBUG + if (!Tcl_IsShared(objResultPtr)) { + bytes = (char *) Tcl_SetByteArrayLength(objResultPtr,length+appendLen); + p = bytes + length; + currPtr = &OBJ_AT_DEPTH(opnd - 2); + } else { +#endif + TclNewObj(objResultPtr); + bytes = (char *) Tcl_SetByteArrayLength(objResultPtr,length+appendLen); + p = bytes; + currPtr = &OBJ_AT_DEPTH(opnd - 1); +#if !TCL_COMPILE_DEBUG + } +#endif + + /* + * Append the remaining characters. + */ + + for (; currPtr <= &OBJ_AT_TOS; currPtr++) { + if ((*currPtr)->bytes == tclEmptyStringRep) + continue; /* don't shimmer nulls */ + bytes = (char *) Tcl_GetByteArrayFromObj(*currPtr, &length); + memcpy(p, bytes, (size_t) length); + p += length; + } + } + TRACE_WITH_OBJ(("%u => ", opnd), objResultPtr); NEXT_INST_V(2, opnd, 1); } |