summaryrefslogtreecommitdiffstats
path: root/generic/tclBasic.c
diff options
context:
space:
mode:
authorMiguel Sofer <miguel.sofer@gmail.com>2007-06-10 23:15:05 (GMT)
committerMiguel Sofer <miguel.sofer@gmail.com>2007-06-10 23:15:05 (GMT)
commit57ba79b9aa406ba55b5987ac6bf3556cce00d9df (patch)
tree9e526ad2806f8efeac869fbd387fcf300f74d7ea /generic/tclBasic.c
parent78cbf63f6981c799426895c68d288d6ab57f0d01 (diff)
downloadtcl-57ba79b9aa406ba55b5987ac6bf3556cce00d9df.zip
tcl-57ba79b9aa406ba55b5987ac6bf3556cce00d9df.tar.gz
tcl-57ba79b9aa406ba55b5987ac6bf3556cce00d9df.tar.bz2
* generic/tclBasic.c: Further TEOvI split, creating a new
* generic/tclCompile.h: TclEvalObjvKnownCommand() function to * generic/tclExecute.c: handle commands that are already known and are not traced. INST_INVOKE now calls into this function instead of inlining parts of TEOvI. Same perf, better isolation.
Diffstat (limited to 'generic/tclBasic.c')
-rw-r--r--generic/tclBasic.c136
1 files changed, 76 insertions, 60 deletions
diff --git a/generic/tclBasic.c b/generic/tclBasic.c
index a06b203..8be21cc 100644
--- a/generic/tclBasic.c
+++ b/generic/tclBasic.c
@@ -13,7 +13,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.248 2007/06/10 21:14:41 hobbs Exp $
+ * RCS: @(#) $Id: tclBasic.c,v 1.249 2007/06/10 23:15:05 msofer Exp $
*/
#include "tclInt.h"
@@ -3383,12 +3383,21 @@ TclInterpReady(
/*
*----------------------------------------------------------------------
*
- * TclEvalObjvInternal --
+ * TclEvalObjvInternal, FullEvalObjvInternal, TclEvalObjvKnownCommand --
*
- * This function evaluates a Tcl command that has already been parsed
+ * These functions evaluate a Tcl command that has already been parsed
* into words, with one Tcl_Obj holding each word. The caller is
* responsible for managing the iPtr->numLevels.
*
+ * TclEvalObjvInternal is the backend for Tcl_EvalObjv, the other two are
+ * separate backends for TclEvalObjvInternal:
+ * - FullEvalObjvInternal is the full implementation, with [unknown] and
+ * trace handling.
+ * - TclEvalObjvKnownCommand is a fast implementation for known untraced
+ * commands.
+ * The bytecode engine calls directly into both TclEvalObjvInternal and
+ * TclEvalObjvKnownCommand.
+ *
* Results:
* The return value is a standard Tcl completion code such as TCL_OK or
* TCL_ERROR. A result or error message is left in interp's result. If an
@@ -3681,6 +3690,56 @@ FullEvalObjvInternal(
}
int
+TclEvalObjvKnownCommand(
+ Tcl_Interp *interp, /* Interpreter in which to evaluate the
+ * command. Also used for error reporting. */
+ int objc, /* Number of words in command. */
+ Tcl_Obj *const objv[], /* An array of pointers to objects that are
+ * the words that make up the command. */
+ Command *cmdPtr) /* The already determined valid command */
+{
+ Interp *iPtr = (Interp *) interp;
+ int code = TCL_OK;
+
+ /*
+ * Finally, invoke the command's Tcl_ObjCmdProc.
+ */
+
+ cmdPtr->refCount++;
+ iPtr->cmdCount++;
+
+ if (!TclLimitExceeded(iPtr->limit)) {
+ code = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, objc, objv);
+ }
+ if (Tcl_AsyncReady()) {
+ code = Tcl_AsyncInvoke(interp, code);
+ }
+ if (code == TCL_OK && TclLimitReady(iPtr->limit)) {
+ code = Tcl_LimitCheck(interp);
+ }
+
+ /*
+ * Decrement the reference count of cmdPtr and deallocate it if it has
+ * dropped to zero.
+ */
+
+ TclCleanupCommandMacro(cmdPtr);
+
+ /*
+ * If the interpreter has a non-empty string result, the result object is
+ * either empty or stale because some function set interp->result
+ * directly. If so, move the string result to the result object, then
+ * reset the string result.
+ */
+
+ if (*(iPtr->result) != 0) {
+ (void) Tcl_GetObjResult(interp);
+ }
+
+ return code;
+}
+
+int
TclEvalObjvInternal(
Tcl_Interp *interp, /* Interpreter in which to evaluate the
* command. Also used for error reporting. */
@@ -3702,9 +3761,7 @@ TclEvalObjvInternal(
{
Command *cmdPtr;
Interp *iPtr = (Interp *) interp;
- CallFrame *savedVarFramePtr = NULL;
CallFrame *varFramePtr = iPtr->varFramePtr;
- int code = TCL_OK;
Namespace *savedNsPtr = NULL;
Namespace *lookupNsPtr = iPtr->lookupNsPtr;
@@ -3729,11 +3786,12 @@ TclEvalObjvInternal(
} else {
varFramePtr->nsPtr = iPtr->globalNsPtr;
}
- } else if ((flags & TCL_EVAL_GLOBAL) && (varFramePtr != iPtr->rootFramePtr)
- && !savedVarFramePtr) {
- varFramePtr = iPtr->rootFramePtr;
- savedVarFramePtr = iPtr->varFramePtr;
- iPtr->varFramePtr = varFramePtr;
+ } else if ((flags & TCL_EVAL_GLOBAL) && (varFramePtr != iPtr->rootFramePtr)) {
+ /*
+ * Use the full version, so that this one can do optimised tail calls.
+ */
+
+ return FullEvalObjvInternal(interp, objc, objv, command, length, flags);
}
}
@@ -3746,65 +3804,23 @@ TclEvalObjvInternal(
if (savedNsPtr) {
varFramePtr->nsPtr = savedNsPtr;
}
-
- if ((cmdPtr == NULL) || (iPtr->tracePtr != NULL) ||
- (cmdPtr->flags & CMD_HAS_EXEC_TRACES)) {
+
+ if ((cmdPtr && !iPtr->tracePtr && !(cmdPtr->flags & CMD_HAS_EXEC_TRACES))) {
+ if (!(flags & TCL_EVAL_INVOKE) &&
+ (iPtr->ensembleRewrite.sourceObjs != NULL)) {
+ iPtr->ensembleRewrite.sourceObjs = NULL;
+ }
+ return TclEvalObjvKnownCommand(interp, objc, objv, cmdPtr);
+ } else {
/*
* Need the full version: command is either unknown or traced
*/
- if (savedVarFramePtr) {
- iPtr->varFramePtr = savedVarFramePtr;
- }
if (lookupNsPtr) {
iPtr->lookupNsPtr = lookupNsPtr;
}
return FullEvalObjvInternal(interp, objc, objv, command, length, flags);
}
-
- /*
- * Finally, invoke the command's Tcl_ObjCmdProc.
- */
-
- cmdPtr->refCount++;
- iPtr->cmdCount++;
-
- if (!TclLimitExceeded(iPtr->limit)) {
- if (!(flags & TCL_EVAL_INVOKE) &&
- (iPtr->ensembleRewrite.sourceObjs != NULL)) {
- iPtr->ensembleRewrite.sourceObjs = NULL;
- }
- code = (*cmdPtr->objProc)(cmdPtr->objClientData, interp, objc, objv);
- }
- if (Tcl_AsyncReady()) {
- code = Tcl_AsyncInvoke(interp, code);
- }
- if (code == TCL_OK && TclLimitReady(iPtr->limit)) {
- code = Tcl_LimitCheck(interp);
- }
-
- /*
- * Decrement the reference count of cmdPtr and deallocate it if it has
- * dropped to zero.
- */
-
- TclCleanupCommandMacro(cmdPtr);
-
- /*
- * If the interpreter has a non-empty string result, the result object is
- * either empty or stale because some function set interp->result
- * directly. If so, move the string result to the result object, then
- * reset the string result.
- */
-
- if (*(iPtr->result) != 0) {
- (void) Tcl_GetObjResult(interp);
- }
-
- if (savedVarFramePtr) {
- iPtr->varFramePtr = savedVarFramePtr;
- }
- return code;
}
/*