summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiguel Sofer <miguel.sofer@gmail.com>2009-12-08 01:34:04 (GMT)
committerMiguel Sofer <miguel.sofer@gmail.com>2009-12-08 01:34:04 (GMT)
commit903848120ff87aaa29fd7b7cc21b37b097edefc1 (patch)
tree897d5ed5a850e95bf6652b304c23e04977ac8119
parentddd3069fa1c4fd4dbcfd28c0486d8de3254fdae2 (diff)
downloadtcl-903848120ff87aaa29fd7b7cc21b37b097edefc1.zip
tcl-903848120ff87aaa29fd7b7cc21b37b097edefc1.tar.gz
tcl-903848120ff87aaa29fd7b7cc21b37b097edefc1.tar.bz2
* generic/tclExecute.c: Start cleaning the TEBC stables
* generic/tclInt.h:
-rw-r--r--ChangeLog3
-rw-r--r--generic/tclExecute.c377
-rw-r--r--generic/tclInt.h4
3 files changed, 165 insertions, 219 deletions
diff --git a/ChangeLog b/ChangeLog
index 4414ab0..da51581 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
2009-12-07 Miguel Sofer <msofer@users.sf.net>
+ * generic/tclExecute.c: Start cleaning the TEBC stables
+ * generic/tclInt.h:
+
* generic/tclCmdIL.c: Fix of [Bug #2910094] by aku
* tests/coroutine.test:
diff --git a/generic/tclExecute.c b/generic/tclExecute.c
index 9758676..05e40aa 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.450 2009/12/06 20:35:39 msofer Exp $
+ * RCS: @(#) $Id: tclExecute.c,v 1.451 2009/12/08 01:34:05 msofer Exp $
*/
#include "tclInt.h"
@@ -1867,9 +1867,6 @@ TclExecuteByteCode(
/*
* Bottom of allocated stack holds the NR data
*/
-
- int initLevel = 0;
-
/* NR_TEBC */
BottomData *bottomPtr = NULL;
@@ -1884,7 +1881,6 @@ TclExecuteByteCode(
Tcl_Obj **initTosPtr = NULL; /* Stack top at start of execution. */
ptrdiff_t *initCatchTop = NULL; /* Catch stack top at start of execution */
Var *compiledLocals = NULL;
- Namespace *namespacePtr = NULL;
CmdFrame *bcFramePtr = NULL; /* TIP #280 Structure for tracking lines */
Tcl_Obj **constants = &iPtr->execEnvPtr->constants[0];
@@ -1942,8 +1938,6 @@ TclExecuteByteCode(
* execution stack is large enough to execute this ByteCode.
*/
- int nested = 0;
-
if (!codePtr) {
resumeCoroutine:
/*
@@ -1956,11 +1950,8 @@ TclExecuteByteCode(
NRE_ASSERT(iPtr->execEnvPtr->corPtr->eePtr == iPtr->execEnvPtr);
NRE_ASSERT(COR_IS_SUSPENDED(iPtr->execEnvPtr->corPtr));
- initLevel = 0;
- nested = 1;
-
oldBottomPtr = iPtr->execEnvPtr->bottomPtr;
- iPtr->execEnvPtr->corPtr->stackLevel = &initLevel;
+ iPtr->execEnvPtr->corPtr->stackLevel = &bottomPtr;
if (iPtr->execEnvPtr->rewind) {
result = TCL_ERROR;
}
@@ -1968,213 +1959,51 @@ TclExecuteByteCode(
}
nonRecursiveCallStart:
- if (nested) {
- TEOV_callback *callbackPtr = TOP_CB(interp);
- int type = PTR2INT(callbackPtr->data[0]);
- ClientData param = callbackPtr->data[1];
-
- NRE_ASSERT(result==TCL_OK);
- NRE_ASSERT(callbackPtr != bottomPtr->rootPtr);
- NRE_ASSERT(callbackPtr->procPtr == NRCallTEBC);
-
- TOP_CB(interp) = callbackPtr->nextPtr;
- TCLNR_FREE(interp, callbackPtr);
-
- NR_DATA_BURY();
-
- switch (type) {
- case TCL_NR_BC_TYPE:
- /*
- * A request to run a bytecode: record this level's state
- * variables, swap codePtr and start running the new one.
- */
-
- codePtr = param;
- if (!codePtr) {
- /* NOT CALLED, does not (yet?) work */
- goto resumeCoroutine;
- }
- break;
- case TCL_NR_TAILCALL_TYPE: {
- /*
- * A request to perform a tailcall: just drop this bytecode.
- */
-
-#ifdef TCL_COMPILE_DEBUG
- if (traceInstructions) {
- fprintf(stdout, " Tailcall request received\n");
- }
-#endif
- if (catchTop != initCatchTop) {
- TEOV_callback *tailcallPtr = iPtr->varFramePtr->tailcallPtr;
-
- TclClearTailcall(interp, tailcallPtr);
- iPtr->varFramePtr->tailcallPtr = NULL;
- result = TCL_ERROR;
- Tcl_SetResult(interp,"Tailcall called from within a catch environment",
- TCL_STATIC);
- pc--;
- goto checkForCatch;
- }
- goto abnormalReturn;
- }
- case TCL_NR_YIELD_TYPE: { /*[yield] */
- CoroutineData *corPtr = iPtr->execEnvPtr->corPtr;
-
- if (!corPtr) {
- Tcl_SetResult(interp,
- "yield can only be called in a coroutine",
- TCL_STATIC);
- Tcl_SetErrorCode(interp, "COROUTINE_ILLEGAL_YIELD", NULL);
- result = TCL_ERROR;
- pc--;
- goto checkForCatch;
- }
- NRE_ASSERT(iPtr->execEnvPtr == corPtr->eePtr);
- NRE_ASSERT(corPtr->stackLevel != NULL);
- NRE_ASSERT(bottomPtr == corPtr->eePtr->bottomPtr);
- if (corPtr->stackLevel != &initLevel) {
- Tcl_SetResult(interp, "cannot yield: C stack busy",
- TCL_STATIC);
- Tcl_SetErrorCode(interp, "COROUTINE_CANT_YIELD", NULL);
- result = TCL_ERROR;
- pc--;
- goto checkForCatch;
- }
-
- /*
- * Save our state and return
- */
-
- NR_DATA_BURY();
- esPtr->tosPtr = tosPtr;
- iPtr->execEnvPtr->bottomPtr = bottomPtr;
- return TCL_OK;
- }
- default:
- Tcl_Panic("TEBC: TRCB sent us a callback we cannot handle!");
- }
- }
- nested = 1;
-
codePtr->refCount++;
bottomPtr = (BottomData *) GrowEvaluationStack(iPtr->execEnvPtr,
sizeof(BottomData) + codePtr->maxExceptDepth + sizeof(CmdFrame)
+ codePtr->maxStackDepth, 0);
curInstName = NULL;
auxObjList = NULL;
- initLevel = 1;
NR_DATA_INIT(); /* record this level's data */
if (iPtr->execEnvPtr->corPtr && !iPtr->execEnvPtr->corPtr->stackLevel) {
- iPtr->execEnvPtr->corPtr->stackLevel = &initLevel;
+ iPtr->execEnvPtr->corPtr->stackLevel = &bottomPtr;
}
- nonRecursiveCallReturn:
iPtr->execEnvPtr->bottomPtr = bottomPtr;
bcFramePtr = (CmdFrame *) (bottomPtr + 1);
initCatchTop = ((ptrdiff_t *) (bcFramePtr + 1)) - 1;
initTosPtr = (Tcl_Obj **) (initCatchTop + codePtr->maxExceptDepth);
esPtr = iPtr->execEnvPtr->execStackPtr;
- namespacePtr = iPtr->varFramePtr->nsPtr;
compiledLocals = iPtr->varFramePtr->compiledLocals;
- if (initLevel) {
- initLevel = 0;
- pc = codePtr->codeStart;
- catchTop = initCatchTop;
- tosPtr = initTosPtr;
-
- /*
- * TIP #280: Initialize the frame. Do not push it yet.
- */
-
- 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;
-
- if (iPtr->execEnvPtr->rewind) {
- result = TCL_ERROR;
- goto abnormalReturn;
- }
-
- } else {
- /*
- * Returning from a non-recursive call. State is already completely
- * reset, now process the return.
- */
-
- NRE_ASSERT(iPtr->cmdFramePtr == bcFramePtr);
- iPtr->cmdFramePtr = bcFramePtr->nextPtr;
-
- TclArgumentBCRelease((Tcl_Interp*) iPtr, bcFramePtr);
-
- /*
- * If the CallFrame is marked as tailcalling, keep tailcalling
- */
-
- if (iPtr->varFramePtr->tailcallPtr) {
- if (catchTop != initCatchTop) {
- TclClearTailcall(interp, iPtr->varFramePtr->tailcallPtr);
- iPtr->varFramePtr->tailcallPtr = NULL;
- result = TCL_ERROR;
- Tcl_SetResult(interp,"Tailcall called from within a catch environment",
- TCL_STATIC);
- pc--;
- goto checkForCatch;
- }
- goto abnormalReturn;
- }
-
- if (iPtr->execEnvPtr->rewind) {
- result = TCL_ERROR;
- goto abnormalReturn;
- }
-
- if (result == TCL_OK) {
- /*
- * Reset the interp's result to avoid possible duplications of
- * large objects [Bug 781585]. We do not call Tcl_ResetResult
- * to avoid any side effects caused by the resetting of
- * errorInfo and errorCode [Bug 804681], which are not needed
- * here. We chose instead to manipulate the interp's object
- * result directly.
- *
- * Note that the result object is now in objResultPtr, it
- * keeps the refCount it had in its role of
- * iPtr->objResultPtr.
- */
-
-#ifndef TCL_COMPILE_DEBUG
- if (*pc == INST_POP) {
- pc++;
- } else {
-#endif
- objResultPtr = Tcl_GetObjResult(interp);
- *(++tosPtr) = objResultPtr;
-
- TclNewObj(objResultPtr);
- Tcl_IncrRefCount(objResultPtr);
- iPtr->objResultPtr = objResultPtr;
-#ifndef TCL_COMPILE_DEBUG
- }
-#endif
- } else {
- cleanup = 0; /* already cleaned up */
- pc--; /* was pointing to next instruction */
- goto processExceptionReturn;
- }
+ pc = codePtr->codeStart;
+ catchTop = initCatchTop;
+ tosPtr = initTosPtr;
+
+ /*
+ * TIP #280: Initialize the frame. Do not push it yet.
+ */
+
+ 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;
+
+ if (iPtr->execEnvPtr->rewind) {
+ result = TCL_ERROR;
+ goto abnormalReturn;
}
#ifdef TCL_COMPILE_DEBUG
@@ -2461,7 +2290,7 @@ TclExecuteByteCode(
instStartCmdOK:
NEXT_INST_F(9, 0, 0);
} else if (((codePtr->compileEpoch == iPtr->compileEpoch)
- && (codePtr->nsEpoch == namespacePtr->resolverEpoch))
+ && (codePtr->nsEpoch == iPtr->varFramePtr->nsPtr->resolverEpoch))
|| (codePtr->flags & TCL_BYTECODE_PRECOMPILED)) {
checkInterp = 0;
goto instStartCmdOK;
@@ -2780,8 +2609,8 @@ TclExecuteByteCode(
CACHE_STACK_INFO();
cleanup = 1;
pc++;
- Tcl_NRAddCallback(interp, NRCallTEBC, INT2PTR(TCL_NR_BC_TYPE), newCodePtr,
- NULL, NULL);
+ NR_DATA_BURY();
+ codePtr = newCodePtr;
goto nonRecursiveCallStart;
}
@@ -2846,8 +2675,8 @@ TclExecuteByteCode(
bcFramePtr->data.tebc.pc = (char *) pc;
iPtr->cmdFramePtr = bcFramePtr;
pc++;
- Tcl_NRAddCallback(interp, NRCallTEBC, INT2PTR(TCL_NR_BC_TYPE), newCodePtr,
- NULL, NULL);
+ NR_DATA_BURY();
+ codePtr = newCodePtr;
goto nonRecursiveCallStart;
}
@@ -2936,21 +2765,131 @@ TclExecuteByteCode(
if (TOP_CB(interp) != bottomPtr->rootPtr) {
NRE_ASSERT(result == TCL_OK);
pc += pcAdjustment;
- goto nonRecursiveCallStart;
+
+ nonRecursiveCallSetup: {
+ TEOV_callback *callbackPtr = TOP_CB(interp);
+ int type = PTR2INT(callbackPtr->data[0]);
+ ClientData param = callbackPtr->data[1];
+
+ NRE_ASSERT(callbackPtr != bottomPtr->rootPtr);
+ NRE_ASSERT(callbackPtr->procPtr == NRCallTEBC);
+
+ TOP_CB(interp) = callbackPtr->nextPtr;
+ TCLNR_FREE(interp, callbackPtr);
+
+ NR_DATA_BURY();
+ switch (type) {
+ case TCL_NR_BC_TYPE:
+ /*
+ * A request to run a bytecode: record this
+ * level's state variables, swap codePtr and start
+ * running the new one.
+ */
+
+ if (param) {
+ codePtr = param;
+ goto nonRecursiveCallStart;
+ }
+ /* NOT CALLED, does not (yet?) work */
+ goto resumeCoroutine;
+ break;
+ case TCL_NR_TAILCALL_TYPE: {
+ /*
+ * A request to perform a tailcall: just drop this
+ * bytecode. */
+
+#ifdef TCL_COMPILE_DEBUG
+ if (traceInstructions) {
+ fprintf(stdout, " Tailcall request received\n");
+ }
+#endif
+ if (catchTop != initCatchTop) {
+ TEOV_callback *tailcallPtr = iPtr->varFramePtr->tailcallPtr;
+
+ TclClearTailcall(interp, tailcallPtr);
+ iPtr->varFramePtr->tailcallPtr = NULL;
+ result = TCL_ERROR;
+ Tcl_SetResult(interp,"Tailcall called from within a catch environment",
+ TCL_STATIC);
+ pc--;
+ goto checkForCatch;
+ }
+ goto abnormalReturn;
+ }
+ case TCL_NR_YIELD_TYPE: { /*[yield] */
+ CoroutineData *corPtr = iPtr->execEnvPtr->corPtr;
+
+ if (!corPtr) {
+ Tcl_SetResult(interp,
+ "yield can only be called in a coroutine",
+ TCL_STATIC);
+ Tcl_SetErrorCode(interp, "COROUTINE_ILLEGAL_YIELD", NULL);
+ result = TCL_ERROR;
+ pc--;
+ goto checkForCatch;
+ }
+ NRE_ASSERT(iPtr->execEnvPtr == corPtr->eePtr);
+ NRE_ASSERT(corPtr->stackLevel != NULL);
+ NRE_ASSERT(bottomPtr == corPtr->eePtr->bottomPtr);
+ if (corPtr->stackLevel != &bottomPtr) {
+ Tcl_SetResult(interp, "cannot yield: C stack busy",
+ TCL_STATIC);
+ Tcl_SetErrorCode(interp, "COROUTINE_CANT_YIELD", NULL);
+ result = TCL_ERROR;
+ pc--;
+ goto checkForCatch;
+ }
+
+ /*
+ * Save our state and return
+ */
+
+ NR_DATA_BURY();
+ esPtr->tosPtr = tosPtr;
+ iPtr->execEnvPtr->bottomPtr = bottomPtr;
+ return TCL_OK;
+ }
+ default:
+ Tcl_Panic("TEBC: TRCB sent us a callback we cannot handle!");
+ }
+ }
}
- TclArgumentBCRelease((Tcl_Interp*) iPtr, bcFramePtr);
+ pc += pcAdjustment;
- iPtr->cmdFramePtr = iPtr->cmdFramePtr->nextPtr;
- NRE_ASSERT(iPtr->cmdFramePtr == bcFramePtr->nextPtr);
+ nonRecursiveCallReturn:
- iPtr->execEnvPtr->bottomPtr = bottomPtr;
+ NRE_ASSERT(iPtr->cmdFramePtr == bcFramePtr);
+ iPtr->cmdFramePtr = bcFramePtr->nextPtr;
+ TclArgumentBCRelease((Tcl_Interp*) iPtr, bcFramePtr);
+ /*
+ * If the CallFrame is marked as tailcalling, keep tailcalling
+ */
+
+ if (iPtr->varFramePtr->tailcallPtr) {
+ if (catchTop != initCatchTop) {
+ TclClearTailcall(interp, iPtr->varFramePtr->tailcallPtr);
+ iPtr->varFramePtr->tailcallPtr = NULL;
+ result = TCL_ERROR;
+ Tcl_SetResult(interp,"Tailcall called from within a catch environment",
+ TCL_STATIC);
+ pc--;
+ goto checkForCatch;
+ }
+ goto abnormalReturn;
+ }
+
+ if (iPtr->execEnvPtr->rewind) {
+ result = TCL_ERROR;
+ goto abnormalReturn;
+ }
+
if (result == TCL_OK) {
Tcl_Obj *objPtr;
#ifndef TCL_COMPILE_DEBUG
- if (*(pc+pcAdjustment) == INST_POP) {
- NEXT_INST_V((pcAdjustment+1), cleanup, 0);
+ if (*pc == INST_POP) {
+ NEXT_INST_V(1, cleanup, 0);
}
#endif
/*
@@ -2979,8 +2918,9 @@ TclExecuteByteCode(
TclNewObj(objPtr);
Tcl_IncrRefCount(objPtr);
iPtr->objResultPtr = objPtr;
- NEXT_INST_V(pcAdjustment, cleanup, -1);
+ NEXT_INST_V(0, cleanup, -1);
} else {
+ pc--;
goto processExceptionReturn;
}
}
@@ -8003,10 +7943,13 @@ TclExecuteByteCode(
* caller's arguments and keep processing the caller.
*/
- while (cleanup--) {
- Tcl_Obj *objPtr = POP_OBJECT();
- Tcl_DecrRefCount(objPtr);
- }
+ bcFramePtr = (CmdFrame *) (bottomPtr + 1);
+ initCatchTop = ((ptrdiff_t *) (bcFramePtr + 1)) - 1;
+ initTosPtr = (Tcl_Obj **) (initCatchTop + codePtr->maxExceptDepth);
+ esPtr = iPtr->execEnvPtr->execStackPtr;
+
+ compiledLocals = iPtr->varFramePtr->compiledLocals;
+
goto nonRecursiveCallReturn;
} else {
TEOV_callback *callbackPtr = TOP_CB(iPtr);
@@ -8022,7 +7965,7 @@ TclExecuteByteCode(
* tailcall! Start the new bytecode.
*/
- goto nonRecursiveCallStart;
+ goto nonRecursiveCallSetup;
case TCL_NR_TAILCALL_TYPE:
TOP_CB(iPtr) = callbackPtr->nextPtr;
TCLNR_FREE(interp, callbackPtr);
diff --git a/generic/tclInt.h b/generic/tclInt.h
index c1315be..6eb542e 100644
--- a/generic/tclInt.h
+++ b/generic/tclInt.h
@@ -15,7 +15,7 @@
* See the file "license.terms" for information on usage and redistribution of
* this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclInt.h,v 1.450 2009/12/07 16:33:01 msofer Exp $
+ * RCS: @(#) $Id: tclInt.h,v 1.451 2009/12/08 01:34:05 msofer Exp $
*/
#ifndef _TCLINT
@@ -1400,7 +1400,7 @@ typedef struct CoroutineData {
CorContext caller;
CorContext running;
CorContext base;
- int *stackLevel;
+ void *stackLevel;
int auxNumLevels; /* While the coroutine is running the
* numLevels of the create/resume command is
* stored here; for suspended coroutines it