From 71b0ad990caaf6a297049da2c63821a4e29c57ac Mon Sep 17 00:00:00 2001 From: "jan.nijtmans" Date: Mon, 28 Nov 2022 23:16:31 +0000 Subject: Reduce shimmering: If a conclusion can be drawn about the number of list elements, don't get the elements before the list length is checked --- generic/tclArithSeries.h | 4 ++-- generic/tclAssembly.c | 5 ++++- generic/tclBinary.c | 10 +++++++--- generic/tclCmdAH.c | 6 ++++-- generic/tclCmdIL.c | 10 ++++++++-- generic/tclCmdMZ.c | 5 ++++- generic/tclDecls.h | 1 + generic/tclEnsemble.c | 12 ++++++++++-- generic/tclListObj.c | 4 ++-- generic/tclProc.c | 8 ++++++++ generic/tclTrace.c | 19 +++++++++++++++---- generic/tclVar.c | 8 ++++++-- generic/tclZipfs.c | 6 +++++- 13 files changed, 76 insertions(+), 22 deletions(-) diff --git a/generic/tclArithSeries.h b/generic/tclArithSeries.h index 1daacdd..28fd993 100644 --- a/generic/tclArithSeries.h +++ b/generic/tclArithSeries.h @@ -15,7 +15,7 @@ * Note that the len can in theory be always computed by start,end,step * but it's faster to cache it inside the internal representation. */ -typedef struct ArithSeries { +typedef struct { Tcl_Size len; Tcl_Obj **elements; int isDouble; @@ -23,7 +23,7 @@ typedef struct ArithSeries { Tcl_WideInt end; Tcl_WideInt step; } ArithSeries; -typedef struct ArithSeriesDbl { +typedef struct { Tcl_Size len; Tcl_Obj **elements; int isDouble; diff --git a/generic/tclAssembly.c b/generic/tclAssembly.c index dbf37bb8..ab5cd7a 100644 --- a/generic/tclAssembly.c +++ b/generic/tclAssembly.c @@ -1985,7 +1985,7 @@ CreateMirrorJumpTable( * table. */ int i; - if (TclListObjGetElementsM(interp, jumps, &objc, &objv) != TCL_OK) { + if (TclListObjLengthM(interp, jumps, &objc) != TCL_OK) { return TCL_ERROR; } if (objc % 2 != 0) { @@ -1997,6 +1997,9 @@ CreateMirrorJumpTable( } return TCL_ERROR; } + if (TclListObjGetElementsM(interp, jumps, &objc, &objv) != TCL_OK) { + return TCL_ERROR; + } /* * Allocate the jumptable. diff --git a/generic/tclBinary.c b/generic/tclBinary.c index e4c8766..b744203 100644 --- a/generic/tclBinary.c +++ b/generic/tclBinary.c @@ -1125,11 +1125,10 @@ BinaryFormatCmd( * The macro evals its args more than once: avoid arg++ */ - if (TclListObjGetElementsM(interp, objv[arg], &listc, - &listv) != TCL_OK) { + if (TclListObjLengthM(interp, objv[arg], &listc + ) != TCL_OK) { return TCL_ERROR; } - arg++; if (count == BINARY_ALL) { count = listc; @@ -1139,6 +1138,11 @@ BinaryFormatCmd( -1)); return TCL_ERROR; } + if (TclListObjGetElementsM(interp, objv[arg], &listc, + &listv) != TCL_OK) { + return TCL_ERROR; + } + arg++; } offset += count*size; break; diff --git a/generic/tclCmdAH.c b/generic/tclCmdAH.c index 9905633..2281b5a 100644 --- a/generic/tclCmdAH.c +++ b/generic/tclCmdAH.c @@ -2860,8 +2860,8 @@ EachloopCmd( result = TCL_ERROR; goto done; } - TclListObjGetElementsM(NULL, statePtr->vCopyList[i], - &statePtr->varcList[i], &statePtr->varvList[i]); + TclListObjLengthM(NULL, statePtr->vCopyList[i], + &statePtr->varcList[i]); if (statePtr->varcList[i] < 1) { Tcl_SetObjResult(interp, Tcl_ObjPrintf( "%s varlist is empty", @@ -2872,6 +2872,8 @@ EachloopCmd( result = TCL_ERROR; goto done; } + TclListObjGetElementsM(NULL, statePtr->vCopyList[i], + &statePtr->varcList[i], &statePtr->varvList[i]); /* Values */ if (TclHasInternalRep(objv[2+i*2],&tclArithSeriesType)) { diff --git a/generic/tclCmdIL.c b/generic/tclCmdIL.c index e2493c4..8e52d65 100644 --- a/generic/tclCmdIL.c +++ b/generic/tclCmdIL.c @@ -20,6 +20,7 @@ #include "tclInt.h" #include "tclRegexp.h" #include "tclArithSeries.h" +#include "tclTomMath.h" #include #include @@ -2573,6 +2574,7 @@ Tcl_LlengthObjCmd( /* Argument objects. */ { int listLen, result; + Tcl_Obj *objPtr; if (objc != 2) { Tcl_WrongNumArgs(interp, 1, objv, "list"); @@ -2589,7 +2591,8 @@ Tcl_LlengthObjCmd( * length. */ - Tcl_SetObjResult(interp, Tcl_NewWideIntObj(listLen)); + TclNewUIntObj(objPtr, listLen); + Tcl_SetObjResult(interp, objPtr); return TCL_OK; } @@ -3152,7 +3155,7 @@ Tcl_LreverseObjCmd( } /* end ArithSeries */ /* True List */ - if (TclListObjGetElementsM(interp, objv[1], &elemc, &elemv) != TCL_OK) { + if (TclListObjLengthM(interp, objv[1], &elemc) != TCL_OK) { return TCL_ERROR; } @@ -3164,6 +3167,9 @@ Tcl_LreverseObjCmd( Tcl_SetObjResult(interp, objv[1]); return TCL_OK; } + if (TclListObjGetElementsM(interp, objv[1], &elemc, &elemv) != TCL_OK) { + return TCL_ERROR; + } if (Tcl_IsShared(objv[1]) || ListObjRepIsShared(objv[1])) { /* Bug 1675044 */ diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c index 57541f9..147c2dc 100644 --- a/generic/tclCmdMZ.c +++ b/generic/tclCmdMZ.c @@ -3610,7 +3610,7 @@ TclNRSwitchObjCmd( Tcl_Obj **listv; blist = objv[0]; - if (TclListObjGetElementsM(interp, objv[0], &objc, &listv) != TCL_OK) { + if (TclListObjLengthM(interp, objv[0], &objc) != TCL_OK) { return TCL_ERROR; } @@ -3623,6 +3623,9 @@ TclNRSwitchObjCmd( "?-option ...? string {?pattern body ...? ?default body?}"); return TCL_ERROR; } + if (TclListObjGetElementsM(interp, objv[0], &objc, &listv) != TCL_OK) { + return TCL_ERROR; + } objv = listv; splitObjs = 1; } diff --git a/generic/tclDecls.h b/generic/tclDecls.h index 75fc17e..d8b4b5d 100644 --- a/generic/tclDecls.h +++ b/generic/tclDecls.h @@ -4182,6 +4182,7 @@ extern const TclStubs *tclStubsPtr; /* !END!: Do not edit above this line. */ #undef TclUnusedStubEntry + #if defined(USE_TCL_STUBS) # undef Tcl_CreateInterp # undef Tcl_FindExecutable diff --git a/generic/tclEnsemble.c b/generic/tclEnsemble.c index 88b611f..963f1d8 100644 --- a/generic/tclEnsemble.c +++ b/generic/tclEnsemble.c @@ -562,8 +562,8 @@ TclNamespaceEnsembleCmd( continue; } do { - if (TclListObjGetElementsM(interp, listObj, &len, - &listv) != TCL_OK) { + if (TclListObjLengthM(interp, listObj, &len + ) != TCL_OK) { Tcl_DictObjDone(&search); if (patchedDict) { Tcl_DecrRefCount(patchedDict); @@ -582,6 +582,14 @@ TclNamespaceEnsembleCmd( } goto freeMapAndError; } + if (TclListObjGetElementsM(interp, listObj, &len, + &listv) != TCL_OK) { + Tcl_DictObjDone(&search); + if (patchedDict) { + Tcl_DecrRefCount(patchedDict); + } + goto freeMapAndError; + } cmd = TclGetString(listv[0]); if (!(cmd[0] == ':' && cmd[1] == ':')) { Tcl_Obj *newList = Tcl_DuplicateObj(listObj); diff --git a/generic/tclListObj.c b/generic/tclListObj.c index 776ff0e..80477f7 100644 --- a/generic/tclListObj.c +++ b/generic/tclListObj.c @@ -1994,7 +1994,7 @@ int Tcl_ListObjLength( Tcl_Interp *interp, /* Used to report errors if not NULL. */ Tcl_Obj *listObj, /* List object whose #elements to return. */ - Tcl_Size *lenPtr) /* The resulting int is stored here. */ + Tcl_Size *lenPtr) /* The resulting length is stored here. */ { ListRep listRep; @@ -2632,7 +2632,7 @@ TclLindexFlat( /* Handle ArithSeries as special case */ if (TclHasInternalRep(listObj,&tclArithSeriesType)) { - Tcl_WideInt listLen = TclArithSeriesObjLength(listObj); + Tcl_Size listLen = TclArithSeriesObjLength(listObj); Tcl_Size index; Tcl_Obj *elemObj = NULL; for (i=0 ; i