From a9c634a7974da04b7fefa4fa3062e41e8ccfec6e Mon Sep 17 00:00:00 2001
From: Miguel Sofer <miguel.sofer@gmail.com>
Date: Sat, 9 Jun 2007 21:07:31 +0000
Subject: 	* generic/tclObj.c (Tcl_GetCommandFromObj): rewritten to make
 the 	logic clearer; slightly faster too.

---
 ChangeLog        |  3 +++
 generic/tclObj.c | 73 +++++++++++++++++++++++++-------------------------------
 2 files changed, 35 insertions(+), 41 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 9d75fe7..302f890 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,8 @@
 2007-06-09  Miguel Sofer  <msofer@users.sf.net>
 
+	* generic/tclObj.c (Tcl_GetCommandFromObj): rewritten to make the
+	logic clearer; slightly faster too.
+	
 	* generic/tclBasic.c:   Split TEOv in two, by separating a
 	processor for non-TCL_OK returns. Also spli TEOvI in a full
 	version that handles non-existing and traced commands, and a
diff --git a/generic/tclObj.c b/generic/tclObj.c
index 36596c5..1c6384a 100644
--- a/generic/tclObj.c
+++ b/generic/tclObj.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: tclObj.c,v 1.123 2007/06/09 20:12:55 msofer Exp $
+ * RCS: @(#) $Id: tclObj.c,v 1.124 2007/06/09 21:07:31 msofer Exp $
  */
 
 #include "tclInt.h"
@@ -3465,7 +3465,7 @@ Tcl_GetCommandFromObj(
     register Command *cmdPtr;
     Namespace *currNsPtr;
     int result;
-    CallFrame *savedFramePtr;
+    CallFrame *savedFramePtr = NULL;
     char *name;
 
     /*
@@ -3476,66 +3476,57 @@ Tcl_GetCommandFromObj(
      * 456668]
      */
 
-    savedFramePtr = iPtr->varFramePtr;
     name = Tcl_GetString(objPtr);
     if ((*name++ == ':') && (*name == ':')) {
+	savedFramePtr = iPtr->varFramePtr;
 	iPtr->varFramePtr = iPtr->rootFramePtr;
     }
 
     /*
-     * Get the internal representation, converting to a command type if
-     * needed. The internal representation is a ResolvedCmdName that points to
-     * the actual command.
-     */
-
-    if (objPtr->typePtr != &tclCmdNameType) {
-	result = tclCmdNameType.setFromAnyProc(interp, objPtr);
-	if (result != TCL_OK) {
-	    iPtr->varFramePtr = savedFramePtr;
-	    return (Tcl_Command) NULL;
-	}
-    }
-    resPtr = (ResolvedCmdName *) objPtr->internalRep.twoPtrValue.ptr1;
-
-    /*
      * Get the current namespace.
      */
 
     currNsPtr = iPtr->varFramePtr->nsPtr;
 
     /*
+     * Get the internal representation, converting to a command type if
+     * needed. The internal representation is a ResolvedCmdName that points to
+     * the actual command.
+     *
      * Check the context namespace and the namespace epoch of the resolved
-     * symbol to make sure that it is fresh. If not, then force another
-     * conversion to the command type, to discard the old rep and create a new
-     * one. Note that we verify that the namespace id of the context namespace
-     * is the same as the one we cached; this insures that the namespace
-     * wasn't deleted and a new one created at the same address with the same
-     * command epoch.
+     * symbol to make sure that it is fresh. Note that we verify that the
+     * namespace id of the context namespace is the same as the one we cached;
+     * this insures that the namespace wasn't deleted and a new one created at
+     * the same address with the same command epoch.
+     *
+     * Check also that the command's epoch is up to date, and that the command
+     * is not deleted.
+     *
+     * If any check fails, then force another conversion to the command type,
+     * to discard the old rep and create a new one.      
      */
 
-    cmdPtr = NULL;
-    if ((resPtr != NULL)
-	    && (resPtr->refNsPtr == currNsPtr)
-	    && (resPtr->refNsId == currNsPtr->nsId)
-	    && (resPtr->refNsCmdEpoch == currNsPtr->cmdRefEpoch)) {
-	cmdPtr = resPtr->cmdPtr;
-	if ((cmdPtr->cmdEpoch != resPtr->cmdEpoch) || (cmdPtr->flags & CMD_IS_DELETED)) {
-	    cmdPtr = NULL;
-	}
-    }
+    resPtr = (ResolvedCmdName *) objPtr->internalRep.twoPtrValue.ptr1;
+    if ((objPtr->typePtr != &tclCmdNameType)
+	    || (resPtr == NULL)
+	    || (resPtr->refNsPtr != currNsPtr)
+	    || (resPtr->refNsId != currNsPtr->nsId)
+	    || (resPtr->refNsCmdEpoch != currNsPtr->cmdRefEpoch)
+	    || (cmdPtr = resPtr->cmdPtr, cmdPtr->cmdEpoch != resPtr->cmdEpoch)
+	    || (cmdPtr->flags & CMD_IS_DELETED)) {
 
-    if (cmdPtr == NULL) {
 	result = tclCmdNameType.setFromAnyProc(interp, objPtr);
-	if (result != TCL_OK) {
-	    iPtr->varFramePtr = savedFramePtr;
-	    return (Tcl_Command) NULL;
-	}
 	resPtr = (ResolvedCmdName *) objPtr->internalRep.twoPtrValue.ptr1;
-	if (resPtr != NULL) {
+	if ((result == TCL_OK) && resPtr) {
 	    cmdPtr = resPtr->cmdPtr;
+	} else {
+	    cmdPtr = NULL;
 	}
     }
-    iPtr->varFramePtr = savedFramePtr;
+
+    if (savedFramePtr) {
+	iPtr->varFramePtr = savedFramePtr;
+    }
     return (Tcl_Command) cmdPtr;
 }
 
-- 
cgit v0.12