diff options
-rw-r--r-- | generic/tclBasic.c | 8 | ||||
-rw-r--r-- | generic/tclCompile.c | 10 | ||||
-rw-r--r-- | generic/tclExecute.c | 9 | ||||
-rw-r--r-- | generic/tclProc.c | 33 |
4 files changed, 56 insertions, 4 deletions
diff --git a/generic/tclBasic.c b/generic/tclBasic.c index 5c5bc64..0fc8e31 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -5968,6 +5968,14 @@ TclNREvalObjEx( int result; /* + * Shortcut for empty scripts; avoid computing a string rep + */ + + if (objPtr->bytes && (*objPtr->bytes == '\0')) { + return TCL_OK; + } + + /* * This function consists of three independent blocks for: direct * evaluation of canonical lists, compilation and bytecode execution and * finally direct evaluation. Precisely one of these blocks will be run. diff --git a/generic/tclCompile.c b/generic/tclCompile.c index f62ec14..af86ba6 100644 --- a/generic/tclCompile.c +++ b/generic/tclCompile.c @@ -1255,8 +1255,14 @@ Tcl_NRSubstObj( { ByteCode *codePtr = CompileSubstObj(interp, objPtr, flags); - /* TODO: Confirm we do not need this. */ - /* Tcl_ResetResult(interp); */ + /* + * Shortcut for empty scripts; avoid computing a string rep + */ + + if (objPtr->bytes && (*objPtr->bytes == '\0')) { + return TCL_OK; + } + return TclNRExecuteByteCode(interp, codePtr); } diff --git a/generic/tclExecute.c b/generic/tclExecute.c index b10af65..ff1da8b 100644 --- a/generic/tclExecute.c +++ b/generic/tclExecute.c @@ -2034,6 +2034,15 @@ TclNRExecuteByteCode( * sizeof(void *); int numWords = (size + sizeof(Tcl_Obj *) - 1) / sizeof(Tcl_Obj *); + /* + * Shortcut for compiled empty scripts + */ + + if (codePtr->source && (*codePtr->source == '\0') + && !(codePtr->flags & TCL_BYTECODE_PRECOMPILED)) { + return TCL_OK; + } + codePtr->refCount++; /* diff --git a/generic/tclProc.c b/generic/tclProc.c index ac65bde..f6f6e3e 100644 --- a/generic/tclProc.c +++ b/generic/tclProc.c @@ -1441,7 +1441,7 @@ InitArgsAndLocals( if (localCt) { if (!codePtr->localCachePtr) { - InitLocalCache(procPtr) ; + InitLocalCache(procPtr); } framePtr->localCachePtr = codePtr->localCachePtr; framePtr->localCachePtr->refCount++; @@ -1697,12 +1697,41 @@ TclNRInterpProc( * procedure. */ Tcl_Obj *const objv[]) /* Argument value objects. */ { - int result = TclPushProcCallFrame(clientData, interp, objc, objv, + Proc *procPtr = clientData; + Interp *iPtr = (Interp *) interp; + int result; + Tcl_Obj *bodyPtr = procPtr->bodyPtr; + + /* + * Shortcut for empty bodies. Note that this also avoids compiling and + * shimmering the empty string, as well as pushing/popping a CallFrame and + * invoking TEBC. + */ + + if (bodyPtr->bytes && (*bodyPtr->bytes == '\0')) { + /* empty body ... */ + ByteCode *codePtr = (ByteCode *) bodyPtr->internalRep.twoPtrValue.ptr1; + if ((bodyPtr->typePtr != &tclByteCodeType) || + !(codePtr->flags & TCL_BYTECODE_PRECOMPILED)) { + /* ... and not precompiled ... */ + if (objc == procPtr->numArgs + 1) { + /* ... and correct number of arguments; we will still be + * compiling empty bodies that have default values or args + * for simplicity sake - to avoid having to go through the + * linked list of compiled locals to determine the nature of + * the last formal argument(s). */ + return TCL_OK; + } + } + } + + result = TclPushProcCallFrame(procPtr, interp, objc, objv, /*isLambda*/ 0); if (result != TCL_OK) { return TCL_ERROR; } + return TclNRInterpProcCore(interp, objv[0], 1, &MakeProcError); } |