diff options
Diffstat (limited to 'generic/tclExecute.c')
-rw-r--r-- | generic/tclExecute.c | 100 |
1 files changed, 94 insertions, 6 deletions
diff --git a/generic/tclExecute.c b/generic/tclExecute.c index aac36da..5139dad 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.440 2009/07/12 18:04:33 dkf Exp $ + * RCS: @(#) $Id: tclExecute.c,v 1.441 2009/07/14 16:34:08 andreas_kupries Exp $ */ #include "tclInt.h" @@ -1517,6 +1517,91 @@ TclCompileObj( } /* + * #280. + * Literal sharing fix. This part of the fix is not required by 8.4 + * nor 8.5, because they eval-direct any literals, so just saving the + * argument locations per command in bytecode is enough, embedded + * 'eval' commands, etc. get the correct information. + * + * But in 8.6 all the embedded script are compiled, and the resulting + * bytecode stored in the literal. Now the shared literal has bytecode + * with location data for _one_ particular location this literal is + * found at. If we get executed from a different location the bytecode + * has to be recompiled to get the correct locations. Not doing this + * will execute the saved bytecode with data for a different location, + * causing 'info frame' to point to the wrong place in the sources. + * + * Future optimizations ... + * (1) Save the location data (ExtCmdLoc) keyed by start line. In that + * case we recompile once per location of the literal, but not + * continously, because the moment we have all locations we do not + * need to recompile any longer. + * + * (2) Alternative: Do not recompile, tell the execution engine the + * offset between saved starting line and actual one. Then modify + * the users to adjust the locations they have by this offset. + * + * (3) Alternative 2: Do not fully recompile, adjust just the location + * information. + */ + + { + Tcl_HashEntry *hePtr = Tcl_FindHashEntry(iPtr->lineBCPtr, + (char *) codePtr); + if (hePtr) { + ExtCmdLoc *eclPtr = Tcl_GetHashValue(hePtr); + int redo = 0; + + if (invoker) { + CmdFrame *ctxPtr = (CmdFrame *) + TclStackAlloc(interp, sizeof(CmdFrame)); + *ctxPtr = *invoker; + + if (invoker->type == TCL_LOCATION_BC) { + /* + * Note: Type BC => ctx.data.eval.path is not used. + * ctx.data.tebc.codePtr is used instead. + */ + + TclGetSrcInfoForPc(ctxPtr); + if (ctxPtr->type == TCL_LOCATION_SOURCE) { + /* + * The reference made by 'TclGetSrcInfoForPc' is dead. + */ + Tcl_DecrRefCount(ctxPtr->data.eval.path); + ctxPtr->data.eval.path = NULL; + } + } + + if (word < ctxPtr->nline) { + /* + * Note: We do not care if the line[word] is -1. This + * is a difference and requires a recompile (location + * changed from absolute to relative, literal is used + * fixed and through variable) + * + * Example: + * test info-32.0 using literal of info-24.8 + * (dict with ... vs set body ...). + */ + redo = + ((eclPtr->type == TCL_LOCATION_SOURCE) && + (eclPtr->start != ctxPtr->line[word])) || + ((eclPtr->type == TCL_LOCATION_BC) && + (ctxPtr->type == TCL_LOCATION_SOURCE)) + ; + } + + TclStackFree(interp, ctxPtr); + } + + if (redo) { + goto recompileObj; + } + } + } + + /* * Increment the code's ref count while it is being executed. If * afterwards no references to it remain, free the code. */ @@ -1940,14 +2025,12 @@ TclExecuteByteCode( bcFramePtr->nextPtr = iPtr->cmdFramePtr; bcFramePtr->nline = 0; bcFramePtr->line = NULL; - + bcFramePtr->litarg = NULL; bcFramePtr->data.tebc.codePtr = codePtr; bcFramePtr->data.tebc.pc = NULL; bcFramePtr->cmd.str.cmd = NULL; bcFramePtr->cmd.str.len = 0; - TclArgumentBCEnter((Tcl_Interp*) iPtr,codePtr,bcFramePtr); - if (iPtr->execEnvPtr->rewind) { result = TCL_ERROR; goto abnormalReturn; @@ -1962,6 +2045,8 @@ TclExecuteByteCode( NRE_ASSERT(iPtr->cmdFramePtr == bcFramePtr); iPtr->cmdFramePtr = bcFramePtr->nextPtr; + TclArgumentBCRelease((Tcl_Interp*) iPtr, bcFramePtr); + /* * If the CallFrame is marked as tailcalling, keep tailcalling */ @@ -2760,6 +2845,9 @@ TclExecuteByteCode( instructionCount = 1; + TclArgumentBCEnter((Tcl_Interp*) iPtr, objv, objc, + codePtr, bcFramePtr, pc - codePtr->codeStart); + DECACHE_STACK_INFO(); result = TclNREvalObjv(interp, objc, objv, @@ -2773,6 +2861,8 @@ TclExecuteByteCode( goto nonRecursiveCallStart; } + TclArgumentBCRelease((Tcl_Interp*) iPtr, bcFramePtr); + iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr; NRE_ASSERT(iPtr->cmdFramePtr == bcFramePtr->nextPtr); @@ -7794,8 +7884,6 @@ TclExecuteByteCode( } } - TclArgumentBCRelease((Tcl_Interp*) iPtr,codePtr); - oldBottomPtr = bottomPtr->prevBottomPtr; iPtr->cmdFramePtr = bcFramePtr->nextPtr; TclStackFree(interp, bottomPtr); /* free my stack */ |