summaryrefslogtreecommitdiffstats
path: root/generic/tclExecute.c
diff options
context:
space:
mode:
Diffstat (limited to 'generic/tclExecute.c')
-rw-r--r--generic/tclExecute.c294
1 files changed, 50 insertions, 244 deletions
diff --git a/generic/tclExecute.c b/generic/tclExecute.c
index 029f402..32cbf6a 100644
--- a/generic/tclExecute.c
+++ b/generic/tclExecute.c
@@ -173,13 +173,13 @@ static BuiltinFunc const tclBuiltinFuncTable[] = {
typedef struct TEBCdata {
ByteCode *codePtr; /* Constant until the BC returns */
+ Tcl_Obj *srcPtr;
/* -----------------------------------------*/
const unsigned char *pc; /* These fields are used on return TO this */
ptrdiff_t *catchTop; /* this level: they record the state when a */
int cleanup; /* new codePtr was received for NR */
Tcl_Obj *auxObjList; /* execution. */
int checkInterp;
- CmdFrame cmdFrame;
void *stack[1]; /* Start of the actual combined catch and obj
* stacks; the struct will be expanded as
* necessary */
@@ -797,6 +797,35 @@ ReleaseDictIterator(
objPtr->typePtr = NULL;
}
+static void UpdateStringOfBcSource(Tcl_Obj *objPtr);
+
+static const Tcl_ObjType bcSourceType = {
+ "bcSource", /* name */
+ NULL, /* freeIntRepProc */
+ NULL, /* dupIntRepProc */
+ UpdateStringOfBcSource, /* updateStringProc */
+ NULL /* setFromAnyProc */
+};
+
+static void
+UpdateStringOfBcSource(
+ Tcl_Obj *objPtr)
+{
+ int len;
+ const char *bytes;
+ unsigned char *pc = objPtr->internalRep.twoPtrValue.ptr1;
+ ByteCode *codePtr = objPtr->internalRep.twoPtrValue.ptr2;
+
+ bytes = GetSrcInfoForPc(pc, codePtr, &len, NULL);
+ objPtr->bytes = (char *) ckalloc((unsigned) len + 1);
+ memcpy(objPtr->bytes, bytes, len);
+ objPtr->bytes[len] = '\0';
+ objPtr->length = len;
+}
+
+
+
+
/*
*----------------------------------------------------------------------
*
@@ -1504,14 +1533,10 @@ CompileExprObj(
}
}
if (objPtr->typePtr != &exprCodeType) {
- /*
- * TIP #280: No invoker (yet) - Expression compilation.
- */
-
int length;
const char *string = TclGetStringFromObj(objPtr, &length);
- TclInitCompileEnv(interp, &compEnv, string, length, NULL, 0);
+ TclInitCompileEnv(interp, &compEnv, string, length);
TclCompileExpr(interp, string, length, &compEnv, 0);
/*
@@ -1634,9 +1659,7 @@ FreeExprCodeInternalRep(
ByteCode *
TclCompileObj(
Tcl_Interp *interp,
- Tcl_Obj *objPtr,
- const CmdFrame *invoker,
- int word)
+ Tcl_Obj *objPtr)
{
register Interp *iPtr = (Interp *) interp;
register ByteCode *codePtr; /* Tcl Internal type of bytecode. */
@@ -1691,109 +1714,13 @@ TclCompileObj(
goto recompileObj;
}
- /*
- * #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.
- */
-
- if (invoker == NULL) {
- return codePtr;
- } else {
- Tcl_HashEntry *hePtr =
- Tcl_FindHashEntry(iPtr->lineBCPtr, codePtr);
- ExtCmdLoc *eclPtr;
- CmdFrame *ctxCopyPtr;
- int redo;
-
- if (!hePtr) {
- return codePtr;
- }
-
- eclPtr = Tcl_GetHashValue(hePtr);
- redo = 0;
- ctxCopyPtr = TclStackAlloc(interp, sizeof(CmdFrame));
- *ctxCopyPtr = *invoker;
-
- if (invoker->type == TCL_LOCATION_BC) {
- /*
- * Note: Type BC => ctx.data.eval.path is not used.
- * ctx.data.tebc.codePtr used instead
- */
-
- TclGetSrcInfoForPc(ctxCopyPtr);
- if (ctxCopyPtr->type == TCL_LOCATION_SOURCE) {
- /*
- * The reference made by 'TclGetSrcInfoForPc' is dead.
- */
-
- Tcl_DecrRefCount(ctxCopyPtr->data.eval.path);
- ctxCopyPtr->data.eval.path = NULL;
- }
- }
-
- if (word < ctxCopyPtr->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 != ctxCopyPtr->line[word]))
- || ((eclPtr->type == TCL_LOCATION_BC)
- && (ctxCopyPtr->type == TCL_LOCATION_SOURCE));
- }
-
- TclStackFree(interp, ctxCopyPtr);
- if (!redo) {
- return codePtr;
- }
- }
+ return codePtr;
}
recompileObj:
iPtr->errorLine = 1;
- /*
- * TIP #280. Remember the invoker for a moment in the interpreter
- * structures so that the byte code compiler can pick it up when
- * initializing the compilation environment, i.e. the extended location
- * information.
- */
-
- iPtr->invokeCmdFramePtr = invoker;
- iPtr->invokeWord = word;
TclSetByteCodeFromAny(interp, objPtr, NULL, NULL);
- iPtr->invokeCmdFramePtr = NULL;
codePtr = objPtr->internalRep.twoPtrValue.ptr1;
if (iPtr->varFramePtr->localCachePtr) {
codePtr->localCachePtr = iPtr->varFramePtr->localCachePtr;
@@ -1946,7 +1873,6 @@ TclIncrObj(
*
*----------------------------------------------------------------------
*/
-#define bcFramePtr (&TD->cmdFrame)
#define initCatchTop ((ptrdiff_t *) (&TD->stack[-1]))
#define initTosPtr ((Tcl_Obj **) (initCatchTop+codePtr->maxExceptDepth))
#define esPtr (iPtr->execEnvPtr->execStackPtr)
@@ -1973,7 +1899,7 @@ TclNRExecuteByteCode(
* Reserve the stack, setup the TEBCdataPtr (TD) and CallFrame
*
* The execution uses a unified stack: first a TEBCdata, immediately
- * above it a CmdFrame, then the catch stack, then the execution stack.
+ * above it the catch stack, then the execution stack.
*
* Make sure the catch stack is large enough to hold the maximum number of
* catch commands that could ever be executing at the same time (this will
@@ -1985,31 +1911,16 @@ TclNRExecuteByteCode(
esPtr->tosPtr = initTosPtr;
TD->codePtr = codePtr;
+ TD->srcPtr = Tcl_NewObj();
+ TD->srcPtr->typePtr = &bcSourceType;
+ TclInvalidateStringRep(TD->srcPtr);
+
TD->pc = codePtr->codeStart;
TD->catchTop = initCatchTop;
TD->cleanup = 0;
TD->auxObjList = NULL;
TD->checkInterp = 0;
- /*
- * TIP #280: Initialize the frame. Do not push it yet: it will be pushed
- * every time that we call out from this TD, popped when we return to it.
- */
-
- bcFramePtr->type = ((codePtr->flags & TCL_BYTECODE_PRECOMPILED)
- ? TCL_LOCATION_PREBC : TCL_LOCATION_BC);
- bcFramePtr->level = (iPtr->cmdFramePtr ? iPtr->cmdFramePtr->level+1 : 1);
- bcFramePtr->numLevels = iPtr->numLevels;
- bcFramePtr->framePtr = iPtr->framePtr;
- 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;
-
#ifdef TCL_COMPILE_STATS
iPtr->stats.numExecutions++;
#endif
@@ -2075,6 +1986,7 @@ TEBCresume(
#define auxObjList (TD->auxObjList)
#define catchTop (TD->catchTop)
#define codePtr (TD->codePtr)
+#define srcPtr (TD->srcPtr)
#define checkInterp (TD->checkInterp)
/* Indicates when a check of interp readyness is
* necessary. Set by CACHE_STACK_INFO() */
@@ -2115,7 +2027,6 @@ TEBCresume(
int starting = 1;
traceInstructions = (tclTraceExec == 3);
#endif
-
TEBC_DATA_DIG();
#ifdef TCL_COMPILE_DEBUG
@@ -2130,11 +2041,6 @@ TEBCresume(
if (iPtr->execEnvPtr->rewind) {
result = TCL_ERROR;
}
- NRE_ASSERT(iPtr->cmdFramePtr == bcFramePtr);
- iPtr->cmdFramePtr = bcFramePtr->nextPtr;
- if (iPtr->flags & INTERP_DEBUG_FRAME) {
- TclArgumentBCRelease((Tcl_Interp *) iPtr, bcFramePtr);
- }
if (codePtr->flags & TCL_BYTECODE_RECOMPILE) {
iPtr->flags |= ERR_ALREADY_LOGGED;
codePtr->flags &= ~TCL_BYTECODE_RECOMPILE;
@@ -2392,6 +2298,7 @@ TEBCresume(
NULL);
goto gotError;
}
+ NRE_ASSERT(!COR_IS_SUSPENDED(corPtr));
#ifdef TCL_COMPILE_DEBUG
TRACE_WITH_OBJ(("yield, result="), iPtr->objResultPtr);
@@ -2399,17 +2306,6 @@ TEBCresume(
fprintf(stdout, "\n");
}
#endif
- /* TIP #280: Record the last piece of info needed by
- * 'TclGetSrcInfoForPc', and push the frame.
- */
-
- bcFramePtr->data.tebc.pc = (char *) pc;
- iPtr->cmdFramePtr = bcFramePtr;
-
- if (iPtr->flags & INTERP_DEBUG_FRAME) {
- TclArgumentBCEnter((Tcl_Interp *) iPtr, objv, objc,
- codePtr, bcFramePtr, pc - codePtr->codeStart);
- }
pc++;
cleanup = 1;
@@ -2757,8 +2653,6 @@ TEBCresume(
case INST_EXPR_STK: {
ByteCode *newCodePtr;
- bcFramePtr->data.tebc.pc = (char *) pc;
- iPtr->cmdFramePtr = bcFramePtr;
DECACHE_STACK_INFO();
newCodePtr = CompileExprObj(interp, OBJ_AT_TOS);
CACHE_STACK_INFO();
@@ -2774,13 +2668,10 @@ TEBCresume(
instEvalStk:
case INST_EVAL_STK:
- bcFramePtr->data.tebc.pc = (char *) pc;
- iPtr->cmdFramePtr = bcFramePtr;
-
cleanup = 1;
pc += 1;
TEBC_YIELD();
- return TclNREvalObjEx(interp, OBJ_AT_TOS, 0, NULL, 0);
+ return TclNREvalObjEx(interp, OBJ_AT_TOS, 0);
case INST_INVOKE_EXPANDED:
CLANG_ASSERT(auxObjList);
@@ -2833,21 +2724,14 @@ TEBCresume(
/*
* Finally, let TclEvalObjv handle the command.
- *
- * TIP #280: Record the last piece of info needed by
- * 'TclGetSrcInfoForPc', and push the frame.
*/
- bcFramePtr->data.tebc.pc = (char *) pc;
- iPtr->cmdFramePtr = bcFramePtr;
-
- if (iPtr->flags & INTERP_DEBUG_FRAME) {
- TclArgumentBCEnter((Tcl_Interp *) iPtr, objv, objc,
- codePtr, bcFramePtr, pc - codePtr->codeStart);
+ if (!(codePtr->flags & TCL_BYTECODE_PRECOMPILED)) {
+ srcPtr->internalRep.twoPtrValue.ptr1 = (unsigned char *) pc;
+ srcPtr->internalRep.twoPtrValue.ptr2 = codePtr;
+ iPtr->cmdSourcePtr = srcPtr;
}
- DECACHE_STACK_INFO();
-
pc += pcAdjustment;
TEBC_YIELD();
return TclNREvalObjv(interp, objc, objv,
@@ -2985,12 +2869,6 @@ TEBCresume(
}
objPtr = copyPtr;
}
- bcFramePtr->data.tebc.pc = (char *) pc;
- iPtr->cmdFramePtr = bcFramePtr;
- if (iPtr->flags & INTERP_DEBUG_FRAME) {
- TclArgumentBCEnter((Tcl_Interp *) iPtr, objv, objc,
- codePtr, bcFramePtr, pc - codePtr->codeStart);
- }
iPtr->ensembleRewrite.sourceObjs = objv;
iPtr->ensembleRewrite.numRemovedObjs = opnd;
iPtr->ensembleRewrite.numInsertedObjs = 1;
@@ -3000,7 +2878,7 @@ TEBCresume(
TclNRAddCallback(interp, TclClearRootEnsemble, NULL,NULL,NULL,NULL);
TclSkipTailcall(interp);
- return TclNREvalObjEx(interp, objPtr, TCL_EVAL_INVOKE, NULL, INT_MIN);
+ return TclNREvalObjEx(interp, objPtr, TCL_EVAL_INVOKE);
/*
* -----------------------------------------------------------------
@@ -6902,8 +6780,8 @@ TEBCresume(
bytes = GetSrcInfoForPc(pc, codePtr, &length, &pcBeg);
DECACHE_STACK_INFO();
- TclLogCommandInfo(interp, codePtr->source, bytes,
- bytes ? length : 0, pcBeg, tosPtr);
+ Tcl_LogCommandInfo(interp, codePtr->source, bytes,
+ bytes ? length : 0);
CACHE_STACK_INFO();
}
iPtr->flags &= ~ERR_ALREADY_LOGGED;
@@ -7042,10 +6920,9 @@ TEBCresume(
(unsigned) CURR_DEPTH, (unsigned) 0);
Tcl_Panic("TclNRExecuteByteCode execution failure: end stack top < start stack top");
}
- CLANG_ASSERT(bcFramePtr);
}
- iPtr->cmdFramePtr = bcFramePtr->nextPtr;
+ TclDecrRefCount(srcPtr);
if (--codePtr->refCount <= 0) {
TclCleanupByteCode(codePtr);
}
@@ -7091,9 +6968,8 @@ TEBCresume(
}
#undef codePtr
+#undef srcPtr
#undef iPtr
-#undef bcFramePtr
-#undef initCatchTop
#undef initTosPtr
#undef auxObjList
#undef catchTop
@@ -8680,76 +8556,6 @@ IllegalExprOperandType(
*----------------------------------------------------------------------
*/
-const char *
-TclGetSrcInfoForCmd(
- Interp *iPtr,
- int *lenPtr)
-{
- CmdFrame *cfPtr = iPtr->cmdFramePtr;
- ByteCode *codePtr = (ByteCode *) cfPtr->data.tebc.codePtr;
-
- return GetSrcInfoForPc((unsigned char *) cfPtr->data.tebc.pc,
- codePtr, lenPtr, NULL);
-}
-
-void
-TclGetSrcInfoForPc(
- CmdFrame *cfPtr)
-{
- ByteCode *codePtr = (ByteCode *) cfPtr->data.tebc.codePtr;
-
- if (cfPtr->cmd.str.cmd == NULL) {
- cfPtr->cmd.str.cmd = GetSrcInfoForPc(
- (unsigned char *) cfPtr->data.tebc.pc, codePtr,
- &cfPtr->cmd.str.len, NULL);
- }
-
- if (cfPtr->cmd.str.cmd != NULL) {
- /*
- * We now have the command. We can get the srcOffset back and from
- * there find the list of word locations for this command.
- */
-
- ExtCmdLoc *eclPtr;
- ECL *locPtr = NULL;
- int srcOffset, i;
- Interp *iPtr = (Interp *) *codePtr->interpHandle;
- Tcl_HashEntry *hePtr =
- Tcl_FindHashEntry(iPtr->lineBCPtr, codePtr);
-
- if (!hePtr) {
- return;
- }
-
- srcOffset = cfPtr->cmd.str.cmd - codePtr->source;
- eclPtr = Tcl_GetHashValue(hePtr);
-
- for (i=0; i < eclPtr->nuloc; i++) {
- if (eclPtr->loc[i].srcOffset == srcOffset) {
- locPtr = eclPtr->loc+i;
- break;
- }
- }
- if (locPtr == NULL) {
- Tcl_Panic("LocSearch failure");
- }
-
- cfPtr->line = locPtr->line;
- cfPtr->nline = locPtr->nline;
- cfPtr->type = eclPtr->type;
-
- if (eclPtr->type == TCL_LOCATION_SOURCE) {
- cfPtr->data.eval.path = eclPtr->path;
- Tcl_IncrRefCount(cfPtr->data.eval.path);
- }
-
- /*
- * Do not set cfPtr->data.eval.path NULL for non-SOURCE. Needed for
- * cfPtr->data.tebc.codePtr.
- */
- }
-}
-
static const char *
GetSrcInfoForPc(
const unsigned char *pc, /* The program counter value for which to