diff options
author | andreas_kupries <akupries@shaw.ca> | 2008-07-25 20:30:24 (GMT) |
---|---|---|
committer | andreas_kupries <akupries@shaw.ca> | 2008-07-25 20:30:24 (GMT) |
commit | ab493437ef6fb750de339bb51d29743250bcde32 (patch) | |
tree | 87d311ea52aa54f2769f6a3585c367411bdd337e /generic | |
parent | 0165e5e6989f8b3baad4c63d67077cdb388dd9bf (diff) | |
download | tcl-ab493437ef6fb750de339bb51d29743250bcde32.zip tcl-ab493437ef6fb750de339bb51d29743250bcde32.tar.gz tcl-ab493437ef6fb750de339bb51d29743250bcde32.tar.bz2 |
* tests/info.test: Tests 38.* added, exactly testing the tracking
of location for uplevel scripts.
* generic/tclCompile.c (TclInitCompileEnv): Reorganized the
initialization of the #280 location information to match the flow
in TclEvalObjEx to get more absolute contexts.
* generic/tclBasic.c (TclEvalObjEx): Moved the pure-list
optimization out of the eval-direct code path to be done always,
i.e. even when a compile is requested. This way we do not loose
the association between #280 location information and the list
elements, if any.
Diffstat (limited to 'generic')
-rw-r--r-- | generic/tclBasic.c | 131 | ||||
-rw-r--r-- | generic/tclCompile.c | 45 | ||||
-rw-r--r-- | generic/tclProc.c | 4 |
3 files changed, 96 insertions, 84 deletions
diff --git a/generic/tclBasic.c b/generic/tclBasic.c index 9cb5707..917a8a5 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.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: tclBasic.c,v 1.295.2.4 2008/07/23 20:47:30 andreas_kupries Exp $ + * RCS: @(#) $Id: tclBasic.c,v 1.295.2.5 2008/07/25 20:30:34 andreas_kupries Exp $ */ #include "tclInt.h" @@ -1409,6 +1409,10 @@ DeleteInterpProc( ckfree((char *) eclPtr->loc); } + if (eclPtr->eiloc != NULL) { + ckfree((char *) eclPtr->eiloc); + } + ckfree((char *) eclPtr); Tcl_DeleteHashEntry(hPtr); } @@ -4755,7 +4759,7 @@ TclArgumentGet(interp,obj,cfPtrPtr,wordPtr) ((List *)obj->internalRep.twoPtrValue.ptr1)->canonicalFlag)) { return; } - + /* * First look for location information recorded in the argument * stack. That is nearest. @@ -4920,79 +4924,80 @@ TclEvalObjEx( Tcl_IncrRefCount(objPtr); - if (flags & TCL_EVAL_DIRECT) { - /* - * We're not supposed to use the compiler or byte-code interpreter. - * Let Tcl_EvalEx evaluate the command directly (and probably more - * slowly). - * - * Pure List Optimization (no string representation). In this case, we - * can safely use Tcl_EvalObjv instead and get an appreciable - * improvement in execution speed. This is because it allows us to - * avoid a setFromAny step that would just pack everything into a - * string and back out again. - * - * This restriction has been relaxed a bit by storing in lists whether - * they are "canonical" or not (a canonical list being one that is - * either pure or that has its string rep derived by - * UpdateStringOfList from the internal rep). - */ + /* Pure List Optimization (no string representation). In this case, we can + * safely use Tcl_EvalObjv instead and get an appreciable improvement in + * execution speed. This is because it allows us to avoid a setFromAny + * step that would just pack everything into a string and back out again. + * + * This also preserves any associations between list elements and location + * information for such elements. + * + * This restriction has been relaxed a bit by storing in lists whether + * they are "canonical" or not (a canonical list being one that is either + * pure or that has its string rep derived by UpdateStringOfList from the + * internal rep). + */ - if (objPtr->typePtr == &tclListType) { /* is a list... */ - List *listRepPtr = objPtr->internalRep.twoPtrValue.ptr1; + if (objPtr->typePtr == &tclListType) { /* is a list... */ + List *listRepPtr = objPtr->internalRep.twoPtrValue.ptr1; - if (objPtr->bytes == NULL || /* ...without a string rep */ - listRepPtr->canonicalFlag) {/* ...or that is canonical */ - /* - * TIP #280 Structures for tracking lines. As we know that - * this is dynamic execution we ignore the invoker, even if - * known. - */ + if (objPtr->bytes == NULL || /* ...without a string rep */ + listRepPtr->canonicalFlag) {/* ...or that is canonical */ + /* + * TIP #280 Structures for tracking lines. As we know that this is + * dynamic execution we ignore the invoker, even if known. + */ - int nelements; - Tcl_Obj **elements, *copyPtr = TclListObjCopy(NULL, objPtr); - CmdFrame *eoFramePtr = (CmdFrame *) - TclStackAlloc(interp, sizeof(CmdFrame)); + int nelements; + Tcl_Obj **elements, *copyPtr = TclListObjCopy(NULL, objPtr); + CmdFrame *eoFramePtr = (CmdFrame *) + TclStackAlloc(interp, sizeof(CmdFrame)); - eoFramePtr->type = TCL_LOCATION_EVAL_LIST; - eoFramePtr->level = (iPtr->cmdFramePtr == NULL? - 1 : iPtr->cmdFramePtr->level + 1); - eoFramePtr->framePtr = iPtr->framePtr; - eoFramePtr->nextPtr = iPtr->cmdFramePtr; + eoFramePtr->type = TCL_LOCATION_EVAL_LIST; + eoFramePtr->level = (iPtr->cmdFramePtr == NULL? + 1 : iPtr->cmdFramePtr->level + 1); + eoFramePtr->framePtr = iPtr->framePtr; + eoFramePtr->nextPtr = iPtr->cmdFramePtr; - eoFramePtr->nline = 0; - eoFramePtr->line = NULL; + eoFramePtr->nline = 0; + eoFramePtr->line = NULL; - eoFramePtr->cmd.listPtr = objPtr; - Tcl_IncrRefCount(eoFramePtr->cmd.listPtr); - eoFramePtr->data.eval.path = NULL; + eoFramePtr->cmd.listPtr = objPtr; + Tcl_IncrRefCount(eoFramePtr->cmd.listPtr); + eoFramePtr->data.eval.path = NULL; - /* - * TIP #280 We do _not_ compute all the line numbers for the - * words in the command. For the eval of a pure list the most - * sensible choice is to put all words on line 1. Given that - * we neither need memory for them nor compute anything. - * 'line' is left NULL. The two places using this information - * (TclInfoFrame, and TclInitCompileEnv), are special-cased to - * use the proper line number directly instead of accessing - * the 'line' array. - */ + /* + * TIP #280 We do _not_ compute all the line numbers for the words + * in the command. For the eval of a pure list the most sensible + * choice is to put all words on line 1. Given that we neither + * need memory for them nor compute anything. 'line' is left + * NULL. The two places using this information (TclInfoFrame, and + * TclInitCompileEnv), are special-cased to use the proper line + * number directly instead of accessing the 'line' array. + */ - Tcl_ListObjGetElements(NULL, copyPtr, - &nelements, &elements); + Tcl_ListObjGetElements(NULL, copyPtr, + &nelements, &elements); - iPtr->cmdFramePtr = eoFramePtr; - result = Tcl_EvalObjv(interp, nelements, elements, - flags); + iPtr->cmdFramePtr = eoFramePtr; + result = Tcl_EvalObjv(interp, nelements, elements, + flags); - Tcl_DecrRefCount(copyPtr); - iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr; - Tcl_DecrRefCount(eoFramePtr->cmd.listPtr); - TclStackFree(interp, eoFramePtr); + Tcl_DecrRefCount(copyPtr); + iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr; + Tcl_DecrRefCount(eoFramePtr->cmd.listPtr); + TclStackFree(interp, eoFramePtr); - goto done; - } + goto done; } + } + + if (flags & TCL_EVAL_DIRECT) { + /* + * We're not supposed to use the compiler or byte-code interpreter. + * Let Tcl_EvalEx evaluate the command directly (and probably more + * slowly). + */ /* * TIP #280. Propagate context as much as we can. Especially if the diff --git a/generic/tclCompile.c b/generic/tclCompile.c index e557860..3c7ca6e 100644 --- a/generic/tclCompile.c +++ b/generic/tclCompile.c @@ -11,7 +11,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclCompile.c,v 1.146.2.5 2008/07/23 20:47:32 andreas_kupries Exp $ + * RCS: @(#) $Id: tclCompile.c,v 1.146.2.6 2008/07/25 20:30:44 andreas_kupries Exp $ */ #include "tclInt.h" @@ -933,7 +933,22 @@ TclInitCompileEnv( * ...) which may make change the type as well. */ - if ((invoker->nline <= word) || (invoker->line[word] < 0)) { + CmdFrame* ctxPtr = (CmdFrame *) TclStackAlloc(interp, sizeof(CmdFrame)); + int pc = 0; + + *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); + pc = 1; + } + + if ((ctxPtr->nline <= word) || (ctxPtr->line[word] < 0)) { /* * Word is not a literal, relative counting. */ @@ -941,45 +956,37 @@ TclInitCompileEnv( envPtr->line = 1; envPtr->extCmdMapPtr->type = (envPtr->procPtr ? TCL_LOCATION_PROC : TCL_LOCATION_BC); - } else { - CmdFrame *ctxPtr; - int pc = 0; - - ctxPtr = (CmdFrame *) TclStackAlloc(interp, sizeof(CmdFrame)); - *ctxPtr = *invoker; - if (invoker->type == TCL_LOCATION_BC) { + if (pc && (ctxPtr->type == TCL_LOCATION_SOURCE)) { /* - * Note: Type BC => ctx.data.eval.path is not used. - * ctx.data.tebc.codePtr is used instead. + * The reference made by 'TclGetSrcInfoForPc' is dead. */ - - TclGetSrcInfoForPc(ctxPtr); - pc = 1; + Tcl_DecrRefCount(ctxPtr->data.eval.path); } - + } else { envPtr->line = ctxPtr->line[word]; envPtr->extCmdMapPtr->type = ctxPtr->type; if (ctxPtr->type == TCL_LOCATION_SOURCE) { + envPtr->extCmdMapPtr->path = ctxPtr->data.eval.path; + if (pc) { /* * The reference 'TclGetSrcInfoForPc' made is transfered. */ - envPtr->extCmdMapPtr->path = ctxPtr->data.eval.path; ctxPtr->data.eval.path = NULL; } else { /* * We have a new reference here. */ - envPtr->extCmdMapPtr->path = ctxPtr->data.eval.path; - Tcl_IncrRefCount(envPtr->extCmdMapPtr->path); + Tcl_IncrRefCount(ctxPtr->data.eval.path); } } - TclStackFree(interp, ctxPtr); } + + TclStackFree(interp, ctxPtr); } envPtr->auxDataArrayPtr = envPtr->staticAuxDataArraySpace; diff --git a/generic/tclProc.c b/generic/tclProc.c index f9e6822..2b7c5f7 100644 --- a/generic/tclProc.c +++ b/generic/tclProc.c @@ -12,7 +12,7 @@ * See the file "license.terms" for information on usage and redistribution of * this file, and for a DISCLAIMER OF ALL WARRANTIES. * - * RCS: @(#) $Id: tclProc.c,v 1.139.2.1 2008/07/21 19:38:19 andreas_kupries Exp $ + * RCS: @(#) $Id: tclProc.c,v 1.139.2.2 2008/07/25 20:30:47 andreas_kupries Exp $ */ #include "tclInt.h" @@ -2162,7 +2162,7 @@ TclProcCleanupProc( /* * TIP #280: Release the location data associated with this Proc * structure, if any. The interpreter may not exist (For example for - * procbody structurues created by tbcload. + * procbody structures created by tbcload. */ if (!iPtr) { |