Fork me on GitHub

Ignore:
File:
1 edited

Legend:

Unmodified
Added
Removed
  • external/tcl/tclExecute.c

    radeddd8 rd7d2da3  
    5151
    5252/*
     53 * Variable that controls whether execution tracing is enabled and, if so,
     54 * what level of tracing is desired:
     55 *    0: no execution tracing
     56 *    1: trace invocations of Tcl procs only
     57 *    2: trace invocations of all (not compiled away) commands
     58 *    3: display each instruction executed
     59 * This variable is linked to the Tcl variable "tcl_traceExec".
     60 */
     61
     62int tclTraceExec = 0;
     63
     64/*
    5365 * The following global variable is use to signal matherr that Tcl
    5466 * is responsible for the arithmetic, so errors can be handled in a
     
    90102};
    91103   
     104/*
     105 * Mapping from Tcl result codes to strings; used for error and debugging
     106 * messages.
     107 */
     108
     109#ifdef TCL_COMPILE_DEBUG
     110static char *resultStrings[] = {
     111    "TCL_OK", "TCL_ERROR", "TCL_RETURN", "TCL_BREAK", "TCL_CONTINUE"
     112};
     113#endif /* TCL_COMPILE_DEBUG */
     114
     115/*
     116 * The following are statistics-related variables that record information
     117 * about the bytecode compiler and interpreter's operation. This includes
     118 * an array that records for each instruction how often it is executed.
     119 */
     120
     121#ifdef TCL_COMPILE_STATS
     122static long numExecutions = 0;
     123static int instructionCount[256];
     124#endif /* TCL_COMPILE_STATS */
     125
    92126/*
    93127 * Macros for testing floating-point values for certain special cases. Test
     
    153187#define POP_OBJECT() \
    154188    (stackPtr[stackTop--].o)
     189
     190/*
     191 * Macros used to trace instruction execution. The macros TRACE,
     192 * TRACE_WITH_OBJ, and O2S are only used inside TclExecuteByteCode.
     193 * O2S is only used in TRACE* calls to get a string from an object.
     194 *
     195 * NOTE THAT CLIENTS OF O2S ARE LIKELY TO FAIL IF THE OBJECT'S
     196 * STRING REP CONTAINS NULLS.
     197 */
     198
     199#ifdef TCL_COMPILE_DEBUG
     200       
     201#define O2S(objPtr) \
     202    Tcl_GetStringFromObj((objPtr), &length)
     203       
     204#ifdef TCL_COMPILE_STATS
     205#define TRACE(a) \
     206    if (traceInstructions) { \
     207        fprintf(stdout, "%d: %d,%ld (%u) ", iPtr->numLevels, \
     208               stackTop, (tclObjsAlloced - tclObjsFreed), \
     209               (unsigned int)(pc - codePtr->codeStart)); \
     210        printf a; \
     211        fflush(stdout); \
     212    }
     213#define TRACE_WITH_OBJ(a, objPtr) \
     214    if (traceInstructions) { \
     215        fprintf(stdout, "%d: %d,%ld (%u) ", iPtr->numLevels, \
     216               stackTop, (tclObjsAlloced - tclObjsFreed), \
     217               (unsigned int)(pc - codePtr->codeStart)); \
     218        printf a; \
     219        bytes = Tcl_GetStringFromObj((objPtr), &length); \
     220        TclPrintSource(stdout, bytes, TclMin(length, 30)); \
     221        fprintf(stdout, "\n"); \
     222        fflush(stdout); \
     223    }
     224#else  /* not TCL_COMPILE_STATS */
     225#define TRACE(a) \
     226    if (traceInstructions) { \
     227        fprintf(stdout, "%d: %d (%u) ", iPtr->numLevels, stackTop, \
     228               (unsigned int)(pc - codePtr->codeStart)); \
     229        printf a; \
     230        fflush(stdout); \
     231    }
     232#define TRACE_WITH_OBJ(a, objPtr) \
     233    if (traceInstructions) { \
     234        fprintf(stdout, "%d: %d (%u) ", iPtr->numLevels, stackTop, \
     235               (unsigned int)(pc - codePtr->codeStart)); \
     236        printf a; \
     237        bytes = Tcl_GetStringFromObj((objPtr), &length); \
     238        TclPrintSource(stdout, bytes, TclMin(length, 30)); \
     239        fprintf(stdout, "\n"); \
     240        fflush(stdout); \
     241    }
     242#endif /* TCL_COMPILE_STATS */
     243
     244#else  /* not TCL_COMPILE_DEBUG */
     245       
     246#define TRACE(a)
     247#define TRACE_WITH_OBJ(a, objPtr)
     248#define O2S(objPtr)
     249       
     250#endif /* TCL_COMPILE_DEBUG */
    155251
    156252/*
     
    178274static int              ExprUnaryFunc _ANSI_ARGS_((Tcl_Interp *interp,
    179275                            ExecEnv *eePtr, ClientData clientData));
     276#ifdef TCL_COMPILE_STATS
     277static int              EvalStatsCmd _ANSI_ARGS_((ClientData clientData,
     278                            Tcl_Interp *interp, int argc, char **argv));
     279#endif /* TCL_COMPILE_STATS */
    180280static void             FreeCmdNameInternalRep _ANSI_ARGS_((
    181281                            Tcl_Obj *objPtr));
     
    193293static int              SetCmdNameFromAny _ANSI_ARGS_((Tcl_Interp *interp,
    194294                            Tcl_Obj *objPtr));
     295#ifdef TCL_COMPILE_DEBUG
     296static char *           StringForResultCode _ANSI_ARGS_((int result));
     297#endif /* TCL_COMPILE_DEBUG */
    195298static void             UpdateStringOfCmdName _ANSI_ARGS_((Tcl_Obj *objPtr));
     299#ifdef TCL_COMPILE_DEBUG
     300static void             ValidatePcAndStackTop _ANSI_ARGS_((
     301                            ByteCode *codePtr, unsigned char *pc,
     302                            int stackTop, int stackLowerBound,
     303                            int stackUpperBound));
     304#endif /* TCL_COMPILE_DEBUG */
    196305
    197306/*
     
    259368 *
    260369 * Side effects:
    261  *      This procedure initializes the array of instruction names.
     370 *      This procedure initializes the array of instruction names. If
     371 *      compiling with the TCL_COMPILE_STATS flag, it initializes the
     372 *      array that counts the executions of each instruction and it
     373 *      creates the "evalstats" command. It also registers the command name
     374 *      Tcl_ObjType. It also establishes the link between the Tcl
     375 *      "tcl_traceExec" and C "tclTraceExec" variables.
    262376 *
    263377 *----------------------------------------------------------------------
     
    277391    for (i = 0;  instructionTable[i].name != NULL;  i++) {
    278392        opName[i] = instructionTable[i].name;
     393    }
     394
     395#ifdef TCL_COMPILE_STATS   
     396    (VOID *) memset(instructionCount, 0, sizeof(instructionCount));
     397    (VOID *) memset(tclByteCodeCount, 0, sizeof(tclByteCodeCount));
     398    (VOID *) memset(tclSourceCount, 0, sizeof(tclSourceCount));
     399
     400    Tcl_CreateCommand(interp, "evalstats", EvalStatsCmd,
     401                      (ClientData) NULL, (Tcl_CmdDeleteProc *) NULL);
     402#endif /* TCL_COMPILE_STATS */
     403   
     404    if (Tcl_LinkVar(interp, "tcl_traceExec", (char *) &tclTraceExec,
     405                    TCL_LINK_INT) != TCL_OK) {
     406        panic("InitByteCodeExecution: can't create link for tcl_traceExec variable");
    279407    }
    280408}
     
    470598                                 * process break, continue, and errors. */
    471599    int result = TCL_OK;        /* Return code returned after execution. */
     600    int traceInstructions = (tclTraceExec == 3);
    472601    Tcl_Obj *valuePtr, *value2Ptr, *namePtr, *objPtr;
    473602    char *bytes;
    474603    int length;
    475604    long i;
     605    Tcl_DString command;        /* Used for debugging. If tclTraceExec >= 2
     606                                 * holds a string representing the last
     607                                 * command invoked. */
    476608
    477609    /*
     
    488620
    489621    /*
     622     * THIS PROC FAILS IF AN OBJECT'S STRING REP HAS A NULL BYTE.
     623     */
     624
     625    if (tclTraceExec >= 2) {
     626        PrintByteCodeInfo(codePtr);
     627#ifdef TCL_COMPILE_STATS
     628        fprintf(stdout, "  Starting stack top=%d, system objects=%ld\n",
     629                eePtr->stackTop, (tclObjsAlloced - tclObjsFreed));
     630#else
     631        fprintf(stdout, "  Starting stack top=%d\n", eePtr->stackTop);
     632#endif /* TCL_COMPILE_STATS */
     633        fflush(stdout);
     634    }
     635
     636#ifdef TCL_COMPILE_STATS
     637    numExecutions++;
     638#endif /* TCL_COMPILE_STATS */
     639
     640    /*
    490641     * Make sure the catch stack is large enough to hold the maximum number
    491642     * of catch commands that could ever be executing at the same time. This
     
    508659
    509660    /*
     661     * Initialize the buffer that holds a string containing the name and
     662     * arguments for the last invoked command.
     663     */
     664
     665    Tcl_DStringInit(&command);
     666
     667    /*
    510668     * Loop executing instructions until a "done" instruction, a TCL_RETURN,
    511669     * or some error.
     
    513671
    514672    for (;;) {
     673#ifdef TCL_COMPILE_DEBUG
     674        ValidatePcAndStackTop(codePtr, pc, stackTop, initStackTop,
     675                eePtr->stackEnd);
     676#else /* not TCL_COMPILE_DEBUG */
     677        if (traceInstructions) {
     678#ifdef TCL_COMPILE_STATS
     679            fprintf(stdout, "%d: %d,%ld ", iPtr->numLevels, stackTop,
     680                    (tclObjsAlloced - tclObjsFreed));
     681#else /* TCL_COMPILE_STATS */
     682            fprintf(stdout, "%d: %d ", iPtr->numLevels, stackTop);
     683#endif /* TCL_COMPILE_STATS */
     684            TclPrintInstruction(codePtr, pc);
     685            fflush(stdout);
     686        }
     687#endif /* TCL_COMPILE_DEBUG */
     688       
    515689        opCode = *pc;
     690#ifdef TCL_COMPILE_STATS   
     691        instructionCount[opCode]++;
     692#endif /* TCL_COMPILE_STATS */
    516693
    517694        switch (opCode) {
     
    533710                panic("TclExecuteByteCode execution failure: end stack top != start stack top");
    534711            }
     712            TRACE_WITH_OBJ(("done => return code=%d, result is ", result),
     713                    iPtr->objResultPtr);
    535714            goto done;
    536715           
     
    538717            valuePtr = objArrayPtr[TclGetUInt1AtPtr(pc+1)];
    539718            PUSH_OBJECT(valuePtr);
     719            TRACE_WITH_OBJ(("push1 %u => ", TclGetUInt1AtPtr(pc+1)),
     720                    valuePtr);
    540721            ADJUST_PC(2);
    541722           
     
    543724            valuePtr = objArrayPtr[TclGetUInt4AtPtr(pc+1)];
    544725            PUSH_OBJECT(valuePtr);
     726            TRACE_WITH_OBJ(("push4 %u => ", TclGetUInt4AtPtr(pc+1)),
     727                    valuePtr);
    545728            ADJUST_PC(5);
    546729           
    547730        case INST_POP:
    548731            valuePtr = POP_OBJECT();
     732            TRACE_WITH_OBJ(("pop => discarding "), valuePtr);
    549733            TclDecrRefCount(valuePtr); /* finished with pop'ed object. */
    550734            ADJUST_PC(1);
     
    553737            valuePtr = stackPtr[stackTop].o;
    554738            PUSH_OBJECT(Tcl_DuplicateObj(valuePtr));
     739            TRACE_WITH_OBJ(("dup => "), valuePtr);
    555740            ADJUST_PC(1);
    556741
     
    605790               
    606791                PUSH_OBJECT(concatObjPtr);
     792                TRACE_WITH_OBJ(("concat %u => ", opnd), concatObjPtr);
    607793                ADJUST_PC(2);
    608794            }
     
    629815                                    * Init. to avoid compiler warning. */
    630816                Tcl_Command cmd;
     817#ifdef TCL_COMPILE_DEBUG
     818                int isUnknownCmd = 0;
     819                char cmdNameBuf[30];
     820#endif /* TCL_COMPILE_DEBUG */
    631821               
    632822                /*
     
    677867                                "invalid command name \"", cmdName, "\"",
    678868                                (char *) NULL);
     869                        TRACE(("%s %u => unknown proc not found: ",
     870                               opName[opCode], objc));
    679871                        result = TCL_ERROR;
    680872                        goto checkForCatch;
    681873                    }
    682874                    cmdPtr = (Command *) cmd;
     875#ifdef TCL_COMPILE_DEBUG
     876                    isUnknownCmd = 1;
     877#endif /*TCL_COMPILE_DEBUG*/                   
    683878                    stackTop++; /* need room for new inserted objv[0] */
    684879                    for (i = objc;  i >= 0;  i--) {
     
    723918                Tcl_ResetResult(interp);
    724919
     920                if (tclTraceExec >= 2) {
     921                    char buffer[50];
     922
     923                    sprintf(buffer, "%d: (%u) invoking ", iPtr->numLevels,
     924                            (unsigned int)(pc - codePtr->codeStart));
     925                    Tcl_DStringAppend(&command, buffer, -1);
     926                   
     927#ifdef TCL_COMPILE_DEBUG
     928                    if (traceInstructions) { /* tclTraceExec == 3 */
     929                        strncpy(cmdNameBuf, cmdName, 20);
     930                        TRACE(("%s %u => call ", opName[opCode],
     931                               (isUnknownCmd? objc-1 : objc)));
     932                    } else {
     933                        fprintf(stdout, "%s", buffer);
     934                    }
     935#else /* TCL_COMPILE_DEBUG */
     936                    fprintf(stdout, "%s", buffer);
     937#endif /*TCL_COMPILE_DEBUG*/
     938
     939                    for (i = 0;  i < objc;  i++) {
     940                        bytes = TclGetStringFromObj(objv[i], &length);
     941                        TclPrintSource(stdout, bytes, TclMin(length, 15));
     942                        fprintf(stdout, " ");
     943
     944                        sprintf(buffer, "\"%.*s\" ", TclMin(length, 15), bytes);
     945                        Tcl_DStringAppend(&command, buffer, -1);
     946                    }
     947                    fprintf(stdout, "\n");
     948                    fflush(stdout);
     949
     950                    Tcl_DStringFree(&command);
     951                }
     952
    725953                iPtr->cmdCount++;
    726954                DECACHE_STACK_INFO();
     
    768996                     */
    769997                    PUSH_OBJECT(Tcl_GetObjResult(interp));
     998                    TRACE_WITH_OBJ(("%s %u => ...after \"%.20s\", result=",
     999                            opName[opCode], objc, cmdNameBuf),
     1000                            Tcl_GetObjResult(interp));
    7701001                    ADJUST_PC(pcAdjustment);
    7711002                   
     
    7841015                            /*catchOnly*/ 0, codePtr);
    7851016                    if (rangePtr == NULL) {
     1017                        TRACE(("%s %u => ... after \"%.20s\", no encl. loop or catch, returning %s\n",
     1018                                opName[opCode], objc, cmdNameBuf,
     1019                                StringForResultCode(result)));
    7861020                        goto abnormalReturn; /* no catch exists to check */
    7871021                    }
     
    7911025                            newPcOffset = rangePtr->breakOffset;
    7921026                        } else if (rangePtr->continueOffset == -1) {
     1027                            TRACE(("%s %u => ... after \"%.20s\", %s, loop w/o continue, checking for catch\n",
     1028                                   opName[opCode], objc, cmdNameBuf,
     1029                                   StringForResultCode(result)));
    7931030                            goto checkForCatch;
    7941031                        } else {
    7951032                            newPcOffset = rangePtr->continueOffset;
    7961033                        }
     1034                        TRACE(("%s %u => ... after \"%.20s\", %s, range at %d, new pc %d\n",
     1035                               opName[opCode], objc, cmdNameBuf,
     1036                               StringForResultCode(result),
     1037                               rangePtr->codeOffset, newPcOffset));
    7971038                        break;
    7981039                    case CATCH_EXCEPTION_RANGE:
     1040                        TRACE(("%s %u => ... after \"%.20s\", %s...\n",
     1041                               opName[opCode], objc, cmdNameBuf,
     1042                               StringForResultCode(result)));
    7991043                        goto processCatch; /* it will use rangePtr */
    8001044                    default:
     
    8101054                     * enclosing catch exception range, if any.
    8111055                     */
     1056                    TRACE_WITH_OBJ(("%s %u => ... after \"%.20s\", TCL_ERROR ",
     1057                            opName[opCode], objc, cmdNameBuf),
     1058                            Tcl_GetObjResult(interp));
    8121059                    goto checkForCatch;
    8131060
     
    8181065                     * for an enclosing catch exception range, if any.
    8191066                     */
     1067                    TRACE(("%s %u => ... after \"%.20s\", TCL_RETURN\n",
     1068                            opName[opCode], objc, cmdNameBuf));
    8201069                    goto checkForCatch;
    8211070
    8221071                default:
     1072                    TRACE_WITH_OBJ(("%s %u => ... after \"%.20s\", OTHER RETURN CODE %d ",
     1073                            opName[opCode], objc, cmdNameBuf, result),
     1074                            Tcl_GetObjResult(interp));
    8231075                    goto checkForCatch;
    8241076                } /* end of switch on result from invoke instruction */
     
    8361088               
    8371089                PUSH_OBJECT(Tcl_GetObjResult(interp));
     1090                TRACE_WITH_OBJ(("evalStk \"%.30s\" => ", O2S(objPtr)),
     1091                        Tcl_GetObjResult(interp));
    8381092                TclDecrRefCount(objPtr);
    8391093                ADJUST_PC(1);
     
    8551109                        codePtr);
    8561110                if (rangePtr == NULL) {
     1111                    TRACE(("evalStk \"%.30s\" => no encl. loop or catch, returning %s\n",
     1112                            O2S(objPtr), StringForResultCode(result)));
    8571113                    Tcl_DecrRefCount(objPtr);
    8581114                    goto abnormalReturn;    /* no catch exists to check */
     
    8631119                        newPcOffset = rangePtr->breakOffset;
    8641120                    } else if (rangePtr->continueOffset == -1) {
     1121                        TRACE(("evalStk \"%.30s\" => %s, loop w/o continue, checking for catch\n",
     1122                               O2S(objPtr), StringForResultCode(result)));
    8651123                        Tcl_DecrRefCount(objPtr);
    8661124                        goto checkForCatch;
     
    8691127                    }
    8701128                    result = TCL_OK;
     1129                    TRACE_WITH_OBJ(("evalStk \"%.30s\" => %s, range at %d, new pc %d ",
     1130                            O2S(objPtr), StringForResultCode(result),
     1131                            rangePtr->codeOffset, newPcOffset), valuePtr);
    8711132                    break;
    8721133                case CATCH_EXCEPTION_RANGE:
     1134                    TRACE_WITH_OBJ(("evalStk \"%.30s\" => %s ",
     1135                            O2S(objPtr), StringForResultCode(result)),
     1136                            valuePtr);
    8731137                    Tcl_DecrRefCount(objPtr);
    8741138                    goto processCatch;  /* it will use rangePtr */
     
    8801144                continue;       /* restart outer instruction loop at pc */
    8811145            } else { /* eval returned TCL_ERROR, TCL_RETURN, unknown code */
     1146                TRACE_WITH_OBJ(("evalStk \"%.30s\" => ERROR: ", O2S(objPtr)),
     1147                        Tcl_GetObjResult(interp));
    8821148                Tcl_DecrRefCount(objPtr);
    8831149                goto checkForCatch;
     
    8911157            CACHE_STACK_INFO();
    8921158            if (result != TCL_OK) {
     1159                TRACE_WITH_OBJ(("exprStk \"%.30s\" => ERROR: ",
     1160                        O2S(objPtr)), Tcl_GetObjResult(interp));
    8931161                Tcl_DecrRefCount(objPtr);
    8941162                goto checkForCatch;
    8951163            }
    8961164            stackPtr[++stackTop].o = valuePtr; /* already has right refct */
     1165            TRACE_WITH_OBJ(("exprStk \"%.30s\" => ", O2S(objPtr)), valuePtr);
    8971166            TclDecrRefCount(objPtr);
    8981167            ADJUST_PC(1);
     
    9131182            CACHE_STACK_INFO();
    9141183            if (valuePtr == NULL) {
     1184                TRACE_WITH_OBJ(("%s %u => ERROR: ", opName[opCode], opnd),
     1185                        Tcl_GetObjResult(interp));
    9151186                result = TCL_ERROR;
    9161187                goto checkForCatch;
    9171188            }
    9181189            PUSH_OBJECT(valuePtr);
     1190            TRACE_WITH_OBJ(("%s %u => ", opName[opCode], opnd), valuePtr);
    9191191            ADJUST_PC(pcAdjustment);
    9201192
     
    9261198            CACHE_STACK_INFO();
    9271199            if (valuePtr == NULL) {
     1200                TRACE_WITH_OBJ(("loadScalarStk \"%.30s\" => ERROR: ",
     1201                        O2S(namePtr)), Tcl_GetObjResult(interp));
    9281202                Tcl_DecrRefCount(namePtr);
    9291203                result = TCL_ERROR;
     
    9311205            }
    9321206            PUSH_OBJECT(valuePtr);
     1207            TRACE_WITH_OBJ(("loadScalarStk \"%.30s\" => ",
     1208                    O2S(namePtr)), valuePtr);
    9331209            TclDecrRefCount(namePtr);
    9341210            ADJUST_PC(1);
     
    9521228                CACHE_STACK_INFO();
    9531229                if (valuePtr == NULL) {
     1230                    TRACE_WITH_OBJ(("%s %u \"%.30s\" => ERROR: ",
     1231                            opName[opCode], opnd, O2S(elemPtr)),
     1232                            Tcl_GetObjResult(interp));
    9541233                    Tcl_DecrRefCount(elemPtr);
    9551234                    result = TCL_ERROR;
     
    9571236                }
    9581237                PUSH_OBJECT(valuePtr);
     1238                TRACE_WITH_OBJ(("%s %u \"%.30s\" => ",
     1239                        opName[opCode], opnd, O2S(elemPtr)), valuePtr);
    9591240                TclDecrRefCount(elemPtr);
    9601241            }
     
    9711252                CACHE_STACK_INFO();
    9721253                if (valuePtr == NULL) {
     1254                    TRACE_WITH_OBJ(("loadArrayStk \"%.30s(%.30s)\" => ERROR: ",
     1255                            O2S(namePtr), O2S(elemPtr)),
     1256                            Tcl_GetObjResult(interp));
    9731257                    Tcl_DecrRefCount(namePtr);
    9741258                    Tcl_DecrRefCount(elemPtr);
     
    9771261                }
    9781262                PUSH_OBJECT(valuePtr);
     1263                TRACE_WITH_OBJ(("loadArrayStk \"%.30s(%.30s)\" => ",
     1264                        O2S(namePtr), O2S(elemPtr)), valuePtr);
    9791265                TclDecrRefCount(namePtr);
    9801266                TclDecrRefCount(elemPtr);
     
    9891275            CACHE_STACK_INFO();
    9901276            if (valuePtr == NULL) {
     1277                TRACE_WITH_OBJ(("loadStk \"%.30s\" => ERROR: ",
     1278                        O2S(namePtr)), Tcl_GetObjResult(interp));
    9911279                Tcl_DecrRefCount(namePtr);
    9921280                result = TCL_ERROR;
     
    9941282            }
    9951283            PUSH_OBJECT(valuePtr);
     1284            TRACE_WITH_OBJ(("loadStk \"%.30s\" => ", O2S(namePtr)),
     1285                    valuePtr);
    9961286            TclDecrRefCount(namePtr);
    9971287            ADJUST_PC(1);
     
    10131303            CACHE_STACK_INFO();
    10141304            if (value2Ptr == NULL) {
     1305                TRACE_WITH_OBJ(("%s %u <- \"%.30s\" => ERROR: ",
     1306                        opName[opCode], opnd, O2S(valuePtr)),
     1307                        Tcl_GetObjResult(interp));
    10151308                Tcl_DecrRefCount(valuePtr);
    10161309                result = TCL_ERROR;
     
    10181311            }
    10191312            PUSH_OBJECT(value2Ptr);
     1313            TRACE_WITH_OBJ(("%s %u <- \"%.30s\" => ",
     1314                    opName[opCode], opnd, O2S(valuePtr)), value2Ptr);
    10201315            TclDecrRefCount(valuePtr);
    10211316            ADJUST_PC(pcAdjustment);
     
    10291324            CACHE_STACK_INFO();
    10301325            if (value2Ptr == NULL) {
     1326                TRACE_WITH_OBJ(
     1327                        ("storeScalarStk \"%.30s\" <- \"%.30s\" => ERROR: ",
     1328                        O2S(namePtr), O2S(valuePtr)),
     1329                        Tcl_GetObjResult(interp));
    10311330                Tcl_DecrRefCount(namePtr);
    10321331                Tcl_DecrRefCount(valuePtr);
     
    10351334            }
    10361335            PUSH_OBJECT(value2Ptr);
     1336            TRACE_WITH_OBJ(
     1337                    ("storeScalarStk \"%.30s\" <- \"%.30s\" => ",
     1338                    O2S(namePtr),
     1339                    O2S(valuePtr)),
     1340                    value2Ptr);
    10371341            TclDecrRefCount(namePtr);
    10381342            TclDecrRefCount(valuePtr);
     
    10591363                CACHE_STACK_INFO();
    10601364                if (value2Ptr == NULL) {
     1365                    TRACE_WITH_OBJ(
     1366                            ("%s %u \"%.30s\" <- \"%.30s\" => ERROR: ",
     1367                            opName[opCode], opnd, O2S(elemPtr),
     1368                            O2S(valuePtr)), Tcl_GetObjResult(interp));
    10611369                    Tcl_DecrRefCount(elemPtr);
    10621370                    Tcl_DecrRefCount(valuePtr);
     
    10651373                }
    10661374                PUSH_OBJECT(value2Ptr);
     1375                TRACE_WITH_OBJ(("%s %u \"%.30s\" <- \"%.30s\" => ",
     1376                        opName[opCode], opnd, O2S(elemPtr), O2S(valuePtr)),
     1377                        value2Ptr);
    10671378                TclDecrRefCount(elemPtr);
    10681379                TclDecrRefCount(valuePtr);
     
    10821393                CACHE_STACK_INFO();
    10831394                if (value2Ptr == NULL) {
     1395                    TRACE_WITH_OBJ(("storeArrayStk \"%.30s(%.30s)\" <- \"%.30s\" => ERROR: ",
     1396                            O2S(namePtr), O2S(elemPtr), O2S(valuePtr)),
     1397                            Tcl_GetObjResult(interp));
    10841398                    Tcl_DecrRefCount(namePtr);
    10851399                    Tcl_DecrRefCount(elemPtr);
     
    10891403                }
    10901404                PUSH_OBJECT(value2Ptr);
     1405                TRACE_WITH_OBJ(("storeArrayStk \"%.30s(%.30s)\" <- \"%.30s\" => ",
     1406                        O2S(namePtr), O2S(elemPtr), O2S(valuePtr)),
     1407                        value2Ptr);
    10911408                TclDecrRefCount(namePtr);
    10921409                TclDecrRefCount(elemPtr);
     
    11031420            CACHE_STACK_INFO();
    11041421            if (value2Ptr == NULL) {
     1422                TRACE_WITH_OBJ(("storeStk \"%.30s\" <- \"%.30s\" => ERROR: ",
     1423                        O2S(namePtr), O2S(valuePtr)),
     1424                        Tcl_GetObjResult(interp));
    11051425                Tcl_DecrRefCount(namePtr);
    11061426                Tcl_DecrRefCount(valuePtr);
     
    11091429            }
    11101430            PUSH_OBJECT(value2Ptr);
     1431            TRACE_WITH_OBJ(("storeStk \"%.30s\" <- \"%.30s\" => ",
     1432                    O2S(namePtr), O2S(valuePtr)), value2Ptr);
    11111433            TclDecrRefCount(namePtr);
    11121434            TclDecrRefCount(valuePtr);
     
    11191441                result = tclIntType.setFromAnyProc(interp, valuePtr);
    11201442                if (result != TCL_OK) {
     1443                    TRACE_WITH_OBJ(("incrScalar1 %u (by %s) => ERROR converting increment amount to int: ",
     1444                            opnd, O2S(valuePtr)), Tcl_GetObjResult(interp));
    11211445                    Tcl_DecrRefCount(valuePtr);
    11221446                    goto checkForCatch;
     
    11281452            CACHE_STACK_INFO();
    11291453            if (value2Ptr == NULL) {
     1454                TRACE_WITH_OBJ(("incrScalar1 %u (by %ld) => ERROR: ",
     1455                        opnd, i), Tcl_GetObjResult(interp));
    11301456                Tcl_DecrRefCount(valuePtr);
    11311457                result = TCL_ERROR;
     
    11331459            }
    11341460            PUSH_OBJECT(value2Ptr);
     1461            TRACE_WITH_OBJ(("incrScalar1 %u (by %ld) => ", opnd, i),
     1462                    value2Ptr);
    11351463            TclDecrRefCount(valuePtr);
    11361464            ADJUST_PC(2);
     
    11431471                result = tclIntType.setFromAnyProc(interp, valuePtr);
    11441472                if (result != TCL_OK) {
     1473                    TRACE_WITH_OBJ(("%s \"%.30s\" (by %s) => ERROR converting increment amount to int: ",
     1474                            opName[opCode], O2S(namePtr), O2S(valuePtr)),
     1475                            Tcl_GetObjResult(interp));
    11451476                    Tcl_DecrRefCount(namePtr);
    11461477                    Tcl_DecrRefCount(valuePtr);
     
    11541485            CACHE_STACK_INFO();
    11551486            if (value2Ptr == NULL) {
     1487                TRACE_WITH_OBJ(("%s \"%.30s\" (by %ld) => ERROR: ",
     1488                        opName[opCode], O2S(namePtr), i),
     1489                        Tcl_GetObjResult(interp));
    11561490                Tcl_DecrRefCount(namePtr);
    11571491                Tcl_DecrRefCount(valuePtr);
     
    11601494            }
    11611495            PUSH_OBJECT(value2Ptr);
     1496            TRACE_WITH_OBJ(("%s \"%.30s\" (by %ld) => ",
     1497                    opName[opCode], O2S(namePtr), i), value2Ptr);
    11621498            Tcl_DecrRefCount(namePtr);
    11631499            Tcl_DecrRefCount(valuePtr);
     
    11741510                    result = tclIntType.setFromAnyProc(interp, valuePtr);
    11751511                    if (result != TCL_OK) {
     1512                        TRACE_WITH_OBJ(("incrArray1 %u \"%.30s\" (by %s) => ERROR converting increment amount to int: ",
     1513                                opnd, O2S(elemPtr), O2S(valuePtr)),
     1514                                Tcl_GetObjResult(interp));
    11761515                        Tcl_DecrRefCount(elemPtr);
    11771516                        Tcl_DecrRefCount(valuePtr);
     
    11851524                CACHE_STACK_INFO();
    11861525                if (value2Ptr == NULL) {
     1526                    TRACE_WITH_OBJ(("incrArray1 %u \"%.30s\" (by %ld) => ERROR: ",
     1527                            opnd, O2S(elemPtr), i),
     1528                            Tcl_GetObjResult(interp));
    11871529                    Tcl_DecrRefCount(elemPtr);
    11881530                    Tcl_DecrRefCount(valuePtr);
     
    11911533                }
    11921534                PUSH_OBJECT(value2Ptr);
     1535                TRACE_WITH_OBJ(("incrArray1 %u \"%.30s\" (by %ld) => ",
     1536                        opnd, O2S(elemPtr), i), value2Ptr);
    11931537                Tcl_DecrRefCount(elemPtr);
    11941538                Tcl_DecrRefCount(valuePtr);
     
    12061550                    result = tclIntType.setFromAnyProc(interp, valuePtr);
    12071551                    if (result != TCL_OK) {
     1552                        TRACE_WITH_OBJ(("incrArrayStk \"%.30s(%.30s)\" (by %s) => ERROR converting increment amount to int: ",
     1553                                O2S(namePtr), O2S(elemPtr), O2S(valuePtr)),
     1554                                Tcl_GetObjResult(interp));
    12081555                        Tcl_DecrRefCount(namePtr);
    12091556                        Tcl_DecrRefCount(elemPtr);
     
    12181565                CACHE_STACK_INFO();
    12191566                if (value2Ptr == NULL) {
     1567                    TRACE_WITH_OBJ(("incrArrayStk \"%.30s(%.30s)\" (by %ld) => ERROR: ",
     1568                            O2S(namePtr), O2S(elemPtr), i),
     1569                            Tcl_GetObjResult(interp));
    12201570                    Tcl_DecrRefCount(namePtr);
    12211571                    Tcl_DecrRefCount(elemPtr);
     
    12251575                }
    12261576                PUSH_OBJECT(value2Ptr);
     1577                TRACE_WITH_OBJ(("incrArrayStk \"%.30s(%.30s)\" (by %ld) => ",
     1578                        O2S(namePtr), O2S(elemPtr), i), value2Ptr);
    12271579                Tcl_DecrRefCount(namePtr);
    12281580                Tcl_DecrRefCount(elemPtr);
     
    12381590            CACHE_STACK_INFO();
    12391591            if (value2Ptr == NULL) {
     1592                TRACE_WITH_OBJ(("incrScalar1Imm %u %ld => ERROR: ",
     1593                        opnd, i), Tcl_GetObjResult(interp));
    12401594                result = TCL_ERROR;
    12411595                goto checkForCatch;
    12421596            }
    12431597            PUSH_OBJECT(value2Ptr);
     1598            TRACE_WITH_OBJ(("incrScalar1Imm %u %ld => ", opnd, i),
     1599                    value2Ptr);
    12441600            ADJUST_PC(3);
    12451601
     
    12531609            CACHE_STACK_INFO();
    12541610            if (value2Ptr == NULL) {
     1611                TRACE_WITH_OBJ(("%s \"%.30s\" %ld => ERROR: ",
     1612                        opName[opCode], O2S(namePtr), i),
     1613                        Tcl_GetObjResult(interp));
    12551614                result = TCL_ERROR;
    12561615                Tcl_DecrRefCount(namePtr);
     
    12581617            }
    12591618            PUSH_OBJECT(value2Ptr);
     1619            TRACE_WITH_OBJ(("%s \"%.30s\" %ld => ",
     1620                    opName[opCode], O2S(namePtr), i), value2Ptr);
    12601621            TclDecrRefCount(namePtr);
    12611622            ADJUST_PC(2);
     
    12731634                CACHE_STACK_INFO();
    12741635                if (value2Ptr == NULL) {
     1636                    TRACE_WITH_OBJ(("incrArray1Imm %u \"%.30s\" (by %ld) => ERROR: ",
     1637                            opnd, O2S(elemPtr), i),
     1638                            Tcl_GetObjResult(interp));
    12751639                    Tcl_DecrRefCount(elemPtr);
    12761640                    result = TCL_ERROR;
     
    12781642                }
    12791643                PUSH_OBJECT(value2Ptr);
     1644                TRACE_WITH_OBJ(("incrArray1Imm %u \"%.30s\" (by %ld) => ",
     1645                        opnd, O2S(elemPtr), i), value2Ptr);
    12801646                Tcl_DecrRefCount(elemPtr);
    12811647            }
     
    12941660                CACHE_STACK_INFO();
    12951661                if (value2Ptr == NULL) {
     1662                    TRACE_WITH_OBJ(("incrArrayStkImm \"%.30s(%.30s)\" (by %ld) => ERROR: ",
     1663                            O2S(namePtr), O2S(elemPtr), i),
     1664                            Tcl_GetObjResult(interp));
    12961665                    Tcl_DecrRefCount(namePtr);
    12971666                    Tcl_DecrRefCount(elemPtr);
     
    13001669                }
    13011670                PUSH_OBJECT(value2Ptr);
     1671                TRACE_WITH_OBJ(("incrArrayStkImm \"%.30s(%.30s)\" (by %ld) => ",
     1672                        O2S(namePtr), O2S(elemPtr), i), value2Ptr);
    13021673                Tcl_DecrRefCount(namePtr);
    13031674                Tcl_DecrRefCount(elemPtr);
     
    13071678        case INST_JUMP1:
    13081679            opnd = TclGetInt1AtPtr(pc+1);
     1680            TRACE(("jump1 %d => new pc %u\n", opnd,
     1681                   (unsigned int)(pc + opnd - codePtr->codeStart)));
    13091682            ADJUST_PC(opnd);
    13101683
    13111684        case INST_JUMP4:
    13121685            opnd = TclGetInt4AtPtr(pc+1);
     1686            TRACE(("jump4 %d => new pc %u\n", opnd,
     1687                   (unsigned int)(pc + opnd - codePtr->codeStart)));
    13131688            ADJUST_PC(opnd);
    13141689
     
    13341709                    result = Tcl_GetBooleanFromObj(interp, valuePtr, &b);
    13351710                    if (result != TCL_OK) {
     1711                        TRACE_WITH_OBJ(("%s %d => ERROR: ", opName[opCode],
     1712                                opnd), Tcl_GetObjResult(interp));
    13361713                        Tcl_DecrRefCount(valuePtr);
    13371714                        goto checkForCatch;
     
    13391716                }
    13401717                if (b) {
     1718                    TRACE(("%s %d => %.20s true, new pc %u\n",
     1719                            opName[opCode], opnd, O2S(valuePtr),
     1720                            (unsigned int)(pc+opnd - codePtr->codeStart)));
    13411721                    TclDecrRefCount(valuePtr);
    13421722                    ADJUST_PC(opnd);
    13431723                } else {
     1724                    TRACE(("%s %d => %.20s false\n", opName[opCode], opnd,
     1725                            O2S(valuePtr)));
    13441726                    TclDecrRefCount(valuePtr);
    13451727                    ADJUST_PC(pcAdjustment);
     
    13681750                    result = Tcl_GetBooleanFromObj(interp, valuePtr, &b);
    13691751                    if (result != TCL_OK) {
     1752                        TRACE_WITH_OBJ(("%s %d => ERROR: ", opName[opCode],
     1753                                opnd), Tcl_GetObjResult(interp));
    13701754                        Tcl_DecrRefCount(valuePtr);
    13711755                        goto checkForCatch;
     
    13731757                }
    13741758                if (b) {
     1759                    TRACE(("%s %d => %.20s true\n", opName[opCode], opnd,
     1760                            O2S(valuePtr)));
    13751761                    TclDecrRefCount(valuePtr);
    13761762                    ADJUST_PC(pcAdjustment);
    13771763                } else {
     1764                    TRACE(("%s %d => %.20s false, new pc %u\n",
     1765                            opName[opCode], opnd, O2S(valuePtr),
     1766                           (unsigned int)(pc + opnd - codePtr->codeStart)));
    13781767                    TclDecrRefCount(valuePtr);
    13791768                    ADJUST_PC(opnd);
     
    14151804                    }
    14161805                    if (result != TCL_OK) {
     1806                        TRACE(("%s \"%.20s\" => ILLEGAL TYPE %s \n",
     1807                                opName[opCode], O2S(valuePtr),
     1808                                (t1Ptr? t1Ptr->name : "null")));
    14171809                        IllegalExprOperandType(interp, opCode, valuePtr);
    14181810                        Tcl_DecrRefCount(valuePtr);
     
    14381830                    }
    14391831                    if (result != TCL_OK) {
     1832                        TRACE(("%s \"%.20s\" => ILLEGAL TYPE %s \n",
     1833                                opName[opCode], O2S(value2Ptr),
     1834                                (t2Ptr? t2Ptr->name : "null")));
    14401835                        IllegalExprOperandType(interp, opCode, value2Ptr);
    14411836                        Tcl_DecrRefCount(valuePtr);
     
    14561851                if (Tcl_IsShared(valuePtr)) {
    14571852                    PUSH_OBJECT(Tcl_NewLongObj(iResult));
     1853                    TRACE(("%s %.20s %.20s => %d\n", opName[opCode],
     1854                           O2S(valuePtr), O2S(value2Ptr), iResult));
    14581855                    TclDecrRefCount(valuePtr);
    14591856                } else {        /* reuse the valuePtr object */
     1857                    TRACE(("%s %.20s %.20s => %d\n",
     1858                           opName[opCode], /* NB: stack top is off by 1 */
     1859                           O2S(valuePtr), O2S(value2Ptr), iResult));
    14601860                    Tcl_SetLongObj(valuePtr, iResult);
    14611861                    ++stackTop; /* valuePtr now on stk top has right r.c. */
     
    16132013                if (Tcl_IsShared(valuePtr)) {
    16142014                    PUSH_OBJECT(Tcl_NewLongObj(iResult));
     2015                    TRACE(("%s %.20s %.20s => %ld\n", opName[opCode],
     2016                        O2S(valuePtr), O2S(value2Ptr), iResult));
    16152017                    TclDecrRefCount(valuePtr);
    16162018                } else {        /* reuse the valuePtr object */
     2019                    TRACE(("%s %.20s %.20s => %ld\n",
     2020                        opName[opCode], /* NB: stack top is off by 1 */
     2021                        O2S(valuePtr), O2S(value2Ptr), iResult));
    16172022                    Tcl_SetLongObj(valuePtr, iResult);
    16182023                    ++stackTop; /* valuePtr now on stk top has right r.c. */
     
    16442049                            valuePtr, &i);
    16452050                    if (result != TCL_OK) {
     2051                        TRACE(("%s %.20s %.20s => ILLEGAL 1st TYPE %s\n",
     2052                              opName[opCode], O2S(valuePtr), O2S(value2Ptr),
     2053                              (valuePtr->typePtr?
     2054                                   valuePtr->typePtr->name : "null")));
    16462055                        IllegalExprOperandType(interp, opCode, valuePtr);
    16472056                        Tcl_DecrRefCount(valuePtr);
     
    16562065                            value2Ptr, &i2);
    16572066                    if (result != TCL_OK) {
     2067                        TRACE(("%s %.20s %.20s => ILLEGAL 2nd TYPE %s\n",
     2068                              opName[opCode], O2S(valuePtr), O2S(value2Ptr),
     2069                              (value2Ptr->typePtr?
     2070                                   value2Ptr->typePtr->name : "null")));
    16582071                        IllegalExprOperandType(interp, opCode, value2Ptr);
    16592072                        Tcl_DecrRefCount(valuePtr);
     
    16722085                     */
    16732086                    if (i2 == 0) {
     2087                        TRACE(("mod %ld %ld => DIVIDE BY ZERO\n", i, i2));
    16742088                        Tcl_DecrRefCount(valuePtr);
    16752089                        Tcl_DecrRefCount(value2Ptr);
     
    17232137                if (Tcl_IsShared(valuePtr)) {
    17242138                    PUSH_OBJECT(Tcl_NewLongObj(iResult));
     2139                    TRACE(("%s %ld %ld => %ld\n", opName[opCode], i, i2,
     2140                           iResult));
    17252141                    TclDecrRefCount(valuePtr);
    17262142                } else {        /* reuse the valuePtr object */
     2143                    TRACE(("%s %ld %ld => %ld\n", opName[opCode], i, i2,
     2144                        iResult)); /* NB: stack top is off by 1 */
    17272145                    Tcl_SetLongObj(valuePtr, iResult);
    17282146                    ++stackTop; /* valuePtr now on stk top has right r.c. */
     
    17682186                    }
    17692187                    if (result != TCL_OK) {
     2188                        TRACE(("%s %.20s %.20s => ILLEGAL 1st TYPE %s\n",
     2189                               opName[opCode], s, O2S(value2Ptr),
     2190                               (valuePtr->typePtr?
     2191                                    valuePtr->typePtr->name : "null")));
    17702192                        IllegalExprOperandType(interp, opCode, valuePtr);
    17712193                        Tcl_DecrRefCount(valuePtr);
     
    17902212                    }
    17912213                    if (result != TCL_OK) {
     2214                        TRACE(("%s %.20s %.20s => ILLEGAL 2nd TYPE %s\n",
     2215                               opName[opCode], O2S(valuePtr), s,
     2216                               (value2Ptr->typePtr?
     2217                                    value2Ptr->typePtr->name : "null")));
    17922218                        IllegalExprOperandType(interp, opCode, value2Ptr);
    17932219                        Tcl_DecrRefCount(valuePtr);
     
    18202246                    case INST_DIV:
    18212247                        if (d2 == 0.0) {
     2248                            TRACE(("div %.6g %.6g => DIVIDE BY ZERO\n",
     2249                                   d1, d2));
    18222250                            Tcl_DecrRefCount(valuePtr);
    18232251                            Tcl_DecrRefCount(value2Ptr);
     
    18332261                   
    18342262                    if (IS_NAN(dResult) || IS_INF(dResult)) {
     2263                        TRACE(("%s %.20s %.20s => IEEE FLOATING PT ERROR\n",
     2264                               opName[opCode], O2S(valuePtr), O2S(value2Ptr)));
    18352265                        TclExprFloatError(interp, dResult);
    18362266                        result = TCL_ERROR;
     
    18612291                         */
    18622292                        if (i2 == 0) {
     2293                            TRACE(("div %ld %ld => DIVIDE BY ZERO\n",
     2294                                    i, i2));
    18632295                            Tcl_DecrRefCount(valuePtr);
    18642296                            Tcl_DecrRefCount(value2Ptr);
     
    18862318                    if (doDouble) {
    18872319                        PUSH_OBJECT(Tcl_NewDoubleObj(dResult));
     2320                        TRACE(("%s %.6g %.6g => %.6g\n", opName[opCode],
     2321                               d1, d2, dResult));
    18882322                    } else {
    18892323                        PUSH_OBJECT(Tcl_NewLongObj(iResult));
     2324                        TRACE(("%s %ld %ld => %ld\n", opName[opCode],
     2325                               i, i2, iResult));
    18902326                    }
    18912327                    TclDecrRefCount(valuePtr);
    18922328                } else {            /* reuse the valuePtr object */
    18932329                    if (doDouble) { /* NB: stack top is off by 1 */
     2330                        TRACE(("%s %.6g %.6g => %.6g\n", opName[opCode],
     2331                               d1, d2, dResult));
    18942332                        Tcl_SetDoubleObj(valuePtr, dResult);
    18952333                    } else {
     2334                        TRACE(("%s %ld %ld => %ld\n", opName[opCode],
     2335                               i, i2, iResult));
    18962336                        Tcl_SetLongObj(valuePtr, iResult);
    18972337                    }
     
    19232363                    }
    19242364                    if (result != TCL_OK) {
     2365                        TRACE(("%s \"%.20s\" => ILLEGAL TYPE %s \n",
     2366                                opName[opCode], s,
     2367                                (tPtr? tPtr->name : "null")));
    19252368                        IllegalExprOperandType(interp, opCode, valuePtr);
    19262369                        goto checkForCatch;
    19272370                    }
    19282371                }
     2372                TRACE_WITH_OBJ(("uplus %s => ", O2S(valuePtr)), valuePtr);
    19292373            }
    19302374            ADJUST_PC(1);
     
    19552399                    }
    19562400                    if (result != TCL_OK) {
     2401                        TRACE(("%s \"%.20s\" => ILLEGAL TYPE %s\n",
     2402                                opName[opCode], s,
     2403                               (tPtr? tPtr->name : "null")));
    19572404                        IllegalExprOperandType(interp, opCode, valuePtr);
    19582405                        Tcl_DecrRefCount(valuePtr);
     
    19702417                        objPtr = Tcl_NewLongObj(
    19712418                                (opCode == INST_UMINUS)? -i : !i);
     2419                        TRACE_WITH_OBJ(("%s %ld => ", opName[opCode], i),
     2420                                objPtr); /* NB: stack top is off by 1 */
    19722421                    } else {
    19732422                        d = valuePtr->internalRep.doubleValue;
     
    19812430                            objPtr = Tcl_NewLongObj((d==0.0)? 1 : 0);
    19822431                        }
     2432                        TRACE_WITH_OBJ(("%s %.6g => ", opName[opCode], d),
     2433                                objPtr); /* NB: stack top is off by 1 */
    19832434                    }
    19842435                    PUSH_OBJECT(objPtr);
     
    19922443                        Tcl_SetLongObj(valuePtr,
    19932444                                (opCode == INST_UMINUS)? -i : !i);
     2445                        TRACE_WITH_OBJ(("%s %ld => ", opName[opCode], i),
     2446                                valuePtr); /* NB: stack top is off by 1 */
    19942447                    } else {
    19952448                        d = valuePtr->internalRep.doubleValue;
     
    20032456                            Tcl_SetLongObj(valuePtr, (d==0.0)? 1 : 0);
    20042457                        }
     2458                        TRACE_WITH_OBJ(("%s %.6g => ", opName[opCode], d),
     2459                                valuePtr); /* NB: stack top is off by 1 */
    20052460                    }
    20062461                    ++stackTop; /* valuePtr now on stk top has right r.c. */
     
    20262481                            valuePtr, &i);
    20272482                    if (result != TCL_OK) {   /* try to convert to double */
     2483                        TRACE(("bitnot \"%.20s\" => ILLEGAL TYPE %s\n",
     2484                               O2S(valuePtr), (tPtr? tPtr->name : "null")));
    20282485                        IllegalExprOperandType(interp, opCode, valuePtr);
    20292486                        Tcl_DecrRefCount(valuePtr);
     
    20352492                if (Tcl_IsShared(valuePtr)) {
    20362493                    PUSH_OBJECT(Tcl_NewLongObj(~i));
     2494                    TRACE(("bitnot 0x%lx => (%lu)\n", i, ~i));
    20372495                    TclDecrRefCount(valuePtr);
    20382496                } else {
     
    20422500                    Tcl_SetLongObj(valuePtr, ~i);
    20432501                    ++stackTop; /* valuePtr now on stk top has right r.c. */
     2502                    TRACE(("bitnot 0x%lx => (%lu)\n", i, ~i));
    20442503                }
    20452504            }
     
    20562515
    20572516                if ((opnd < 0) || (opnd > LAST_BUILTIN_FUNC)) {
     2517                    TRACE(("UNRECOGNIZED BUILTIN FUNC CODE %d\n", opnd));
    20582518                    panic("TclExecuteByteCode: unrecognized builtin function code %d", opnd);
    20592519                }
     
    20682528                    goto checkForCatch;
    20692529                }
     2530                TRACE_WITH_OBJ(("callBuiltinFunc1 %d => ", opnd),
     2531                        stackPtr[stackTop].o);
    20702532            }
    20712533            ADJUST_PC(2);
     
    20932555                    goto checkForCatch;
    20942556                }
     2557                TRACE_WITH_OBJ(("callFunc1 %d => ", objc),
     2558                        stackPtr[stackTop].o);
    20952559                ADJUST_PC(2);
    20962560            }
     
    21632627                        d = valuePtr->internalRep.doubleValue;
    21642628                        if (IS_NAN(d) || IS_INF(d)) {
     2629                            TRACE(("tryCvtToNumeric \"%.20s\" => IEEE FLOATING PT ERROR\n",
     2630                                   O2S(valuePtr)));
    21652631                            TclExprFloatError(interp, d);
    21662632                            result = TCL_ERROR;
     
    21702636                    shared = shared;            /* lint, shared not used. */
    21712637                    converted = converted;      /* lint, converted not used. */
     2638                    TRACE(("tryCvtToNumeric \"%.20s\" => numeric, %s, %s\n",
     2639                           O2S(valuePtr),
     2640                           (converted? "converted" : "not converted"),
     2641                           (shared? "shared" : "not shared")));
     2642                } else {
     2643                    TRACE(("tryCvtToNumeric \"%.20s\" => not numeric\n",
     2644                           O2S(valuePtr)));
    21722645                }
    21732646            }
     
    21872660                    codePtr);
    21882661            if (rangePtr == NULL) {
     2662                TRACE(("break => no encl. loop or catch, returning TCL_BREAK\n"));
    21892663                result = TCL_BREAK;
    21902664                goto abnormalReturn; /* no catch exists to check */
     
    21932667            case LOOP_EXCEPTION_RANGE:
    21942668                result = TCL_OK;
     2669                TRACE(("break => range at %d, new pc %d\n",
     2670                       rangePtr->codeOffset, rangePtr->breakOffset));
    21952671                break;
    21962672            case CATCH_EXCEPTION_RANGE:
    21972673                result = TCL_BREAK;
     2674                TRACE(("break => ...\n"));
    21982675                goto processCatch; /* it will use rangePtr */
    21992676            default:
     
    22162693                    codePtr);
    22172694            if (rangePtr == NULL) {
     2695                TRACE(("continue => no encl. loop or catch, returning TCL_CONTINUE\n"));
    22182696                result = TCL_CONTINUE;
    22192697                goto abnormalReturn;
     
    22222700            case LOOP_EXCEPTION_RANGE:
    22232701                if (rangePtr->continueOffset == -1) {
     2702                    TRACE(("continue => loop w/o continue, checking for catch\n"));
    22242703                    goto checkForCatch;
    22252704                } else {
    22262705                    result = TCL_OK;
     2706                    TRACE(("continue => range at %d, new pc %d\n",
     2707                           rangePtr->codeOffset, rangePtr->continueOffset));
    22272708                }
    22282709                break;
    22292710            case CATCH_EXCEPTION_RANGE:
    22302711                result = TCL_CONTINUE;
     2712                TRACE(("continue => ...\n"));
    22312713                goto processCatch; /* it will use rangePtr */
    22322714            default:
     
    22622744                TclSetVarScalar(iterVarPtr);
    22632745                TclClearVarUndefined(iterVarPtr);
     2746                TRACE(("foreach_start4 %u => loop iter count temp %d\n",
     2747                        opnd, iterTmpIndex));
    22642748            }
    22652749            ADJUST_PC(5);
     
    23102794                    result = Tcl_ListObjLength(interp, listPtr, &listLen);
    23112795                    if (result != TCL_OK) {
     2796                        TRACE_WITH_OBJ(("foreach_step4 %u => ERROR converting list %ld, \"%s\": ",
     2797                                opnd, i, O2S(listPtr)),
     2798                                Tcl_GetObjResult(interp));
    23122799                        goto checkForCatch;
    23132800                    }
     
    23532840                            CACHE_STACK_INFO();
    23542841                            if (value2Ptr == NULL) {
     2842                                TRACE_WITH_OBJ(("foreach_step4 %u => ERROR init. index temp %d: ",
     2843                                       opnd, varIndex),
     2844                                       Tcl_GetObjResult(interp));
    23552845                                if (setEmptyStr) {
    23562846                                    Tcl_DecrRefCount(elemPtr); /* unneeded */
     
    23722862
    23732863                PUSH_OBJECT(Tcl_NewLongObj(continueLoop));
     2864                TRACE(("foreach_step4 %u => %d lists, iter %d, %s loop\n",
     2865                        opnd, numLists, iterNum,
     2866                        (continueLoop? "continue" : "exit")));
    23742867            }
    23752868            ADJUST_PC(5);
     
    23822875             */
    23832876            catchStackPtr[++catchTop] = stackTop;
     2877            TRACE(("beginCatch4 %u => catchTop=%d, stackTop=%d\n",
     2878                    TclGetUInt4AtPtr(pc+1), catchTop, stackTop));
    23842879            ADJUST_PC(5);
    23852880
     
    23872882            catchTop--;
    23882883            result = TCL_OK;
     2884            TRACE(("endCatch => catchTop=%d\n", catchTop));
    23892885            ADJUST_PC(1);
    23902886
    23912887        case INST_PUSH_RESULT:
    23922888            PUSH_OBJECT(Tcl_GetObjResult(interp));
     2889            TRACE_WITH_OBJ(("pushResult => "), Tcl_GetObjResult(interp));
    23932890            ADJUST_PC(1);
    23942891
    23952892        case INST_PUSH_RETURN_CODE:
    23962893            PUSH_OBJECT(Tcl_NewLongObj(result));
     2894            TRACE(("pushReturnCode => %u\n", result));
    23972895            ADJUST_PC(1);
    23982896
    23992897        default:
     2898            TRACE(("UNRECOGNIZED INSTRUCTION %u\n", opCode));
    24002899            panic("TclExecuteByteCode: unrecognized opCode %u", opCode);
    24012900        } /* end of switch on opCode */
     
    24272926        rangePtr = TclGetExceptionRangeForPc(pc, /*catchOnly*/ 1, codePtr);
    24282927        if (rangePtr == NULL) {
     2928            TRACE(("   ... no enclosing catch, returning %s\n",
     2929                    StringForResultCode(result)));
    24292930            goto abnormalReturn;
    24302931        }
     
    24442945            TclDecrRefCount(valuePtr);
    24452946        }
     2947        TRACE(("  ... found catch at %d, catchTop=%d, unwound to %d, new pc %u\n",
     2948                rangePtr->codeOffset, catchTop, catchStackPtr[catchTop],
     2949                (unsigned int)(rangePtr->catchOffset)));
    24462950        pc = (codePtr->codeStart + rangePtr->catchOffset);
    24472951        continue;               /* restart the execution loop at pc */
     
    24712975#undef STATIC_CATCH_STACK_SIZE
    24722976}
     2977
     2978
     2979/*
     2980 *----------------------------------------------------------------------
     2981 *
     2982 * PrintByteCodeInfo --
     2983 *
     2984 *      This procedure prints a summary about a bytecode object to stdout.
     2985 *      It is called by TclExecuteByteCode when starting to execute the
     2986 *      bytecode object if tclTraceExec has the value 2 or more.
     2987 *
     2988 * Results:
     2989 *      None.
     2990 *
     2991 * Side effects:
     2992 *      None.
     2993 *
     2994 *----------------------------------------------------------------------
     2995 */
     2996
     2997static void
     2998PrintByteCodeInfo(codePtr)
     2999    register ByteCode *codePtr; /* The bytecode whose summary is printed
     3000                                 * to stdout. */
     3001{
     3002    Proc *procPtr = codePtr->procPtr;
     3003    int numCmds = codePtr->numCommands;
     3004    int numObjs = codePtr->numObjects;
     3005    int objBytes, i;
     3006
     3007    objBytes = (numObjs * sizeof(Tcl_Obj));
     3008    for (i = 0;  i < numObjs;  i++) {
     3009        Tcl_Obj *litObjPtr = codePtr->objArrayPtr[i];
     3010        if (litObjPtr->bytes != NULL) {
     3011            objBytes += litObjPtr->length;
     3012        }
     3013    }
     3014   
     3015    fprintf(stdout, "\nExecuting ByteCode 0x%x, ref ct %u, epoch %u, interp 0x%x(epoch %u)\n",
     3016            (unsigned int) codePtr, codePtr->refCount,
     3017            codePtr->compileEpoch, (unsigned int) codePtr->iPtr,
     3018            codePtr->iPtr->compileEpoch);
     3019   
     3020    fprintf(stdout, "  Source: ");
     3021    TclPrintSource(stdout, codePtr->source, 70);
     3022
     3023    fprintf(stdout, "\n  Cmds %d, chars %d, inst %u, objs %u, aux %d, stk depth %u, code/src %.2fn",
     3024            numCmds, codePtr->numSrcChars, codePtr->numCodeBytes, numObjs,
     3025            codePtr->numAuxDataItems, codePtr->maxStackDepth,
     3026            (codePtr->numSrcChars?
     3027                    ((float)codePtr->totalSize)/((float)codePtr->numSrcChars) : 0.0));
     3028
     3029    fprintf(stdout, "  Code %zu = %u(header)+%d(inst)+%d(objs)+%u(exc)+%u(aux)+%d(cmd map)\n",
     3030            codePtr->totalSize, sizeof(ByteCode), codePtr->numCodeBytes,
     3031            objBytes, (codePtr->numExcRanges * sizeof(ExceptionRange)),
     3032            (codePtr->numAuxDataItems * sizeof(AuxData)),
     3033            codePtr->numCmdLocBytes);
     3034
     3035    if (procPtr != NULL) {
     3036        fprintf(stdout,
     3037                "  Proc 0x%x, ref ct %d, args %d, compiled locals %d\n",
     3038                (unsigned int) procPtr, procPtr->refCount,
     3039                procPtr->numArgs, procPtr->numCompiledLocals);
     3040    }
     3041}
     3042
     3043
     3044/*
     3045 *----------------------------------------------------------------------
     3046 *
     3047 * ValidatePcAndStackTop --
     3048 *
     3049 *      This procedure is called by TclExecuteByteCode when debugging to
     3050 *      verify that the program counter and stack top are valid during
     3051 *      execution.
     3052 *
     3053 * Results:
     3054 *      None.
     3055 *
     3056 * Side effects:
     3057 *      Prints a message to stderr and panics if either the pc or stack
     3058 *      top are invalid.
     3059 *
     3060 *----------------------------------------------------------------------
     3061 */
     3062
     3063#ifdef TCL_COMPILE_DEBUG
     3064static void
     3065ValidatePcAndStackTop(codePtr, pc, stackTop, stackLowerBound, stackUpperBound)
     3066    register ByteCode *codePtr; /* The bytecode whose summary is printed
     3067                                 * to stdout. */
     3068    unsigned char *pc;          /* Points to first byte of a bytecode
     3069                                 * instruction. The program counter. */
     3070    int stackTop;               /* Current stack top. Must be between
     3071                                 * stackLowerBound and stackUpperBound
     3072                                 * (inclusive). */
     3073    int stackLowerBound;        /* Smallest legal value for stackTop. */
     3074    int stackUpperBound;        /* Greatest legal value for stackTop. */
     3075{
     3076    unsigned int relativePc = (unsigned int) (pc - codePtr->codeStart);
     3077    unsigned int codeStart = (unsigned int) codePtr->codeStart;
     3078    unsigned int codeEnd = (unsigned int)
     3079            (codePtr->codeStart + codePtr->numCodeBytes);
     3080    unsigned char opCode = *pc;
     3081
     3082    if (((unsigned int) pc < codeStart) || ((unsigned int) pc > codeEnd)) {
     3083        fprintf(stderr, "\nBad instruction pc 0x%x in TclExecuteByteCode\n",
     3084                (unsigned int) pc);
     3085        panic("TclExecuteByteCode execution failure: bad pc");
     3086    }
     3087    if ((unsigned int) opCode > LAST_INST_OPCODE) {
     3088        fprintf(stderr, "\nBad opcode %d at pc %u in TclExecuteByteCode\n",
     3089                (unsigned int) opCode, relativePc);
     3090        panic("TclExecuteByteCode execution failure: bad opcode");
     3091    }
     3092    if ((stackTop < stackLowerBound) || (stackTop > stackUpperBound)) {
     3093        int numChars;
     3094        char *cmd = GetSrcInfoForPc(pc, codePtr, &numChars);
     3095        char *ellipsis = "";
     3096       
     3097        fprintf(stderr, "\nBad stack top %d at pc %u in TclExecuteByteCode",
     3098                stackTop, relativePc);
     3099        if (cmd != NULL) {
     3100            if (numChars > 100) {
     3101                numChars = 100;
     3102                ellipsis = "...";
     3103            }
     3104            fprintf(stderr, "\n executing %.*s%s\n", numChars, cmd,
     3105                    ellipsis);
     3106        } else {
     3107            fprintf(stderr, "\n");
     3108        }
     3109        panic("TclExecuteByteCode execution failure: bad stack top");
     3110    }
     3111}
     3112#endif /* TCL_COMPILE_DEBUG */
    24733113
    24743114
     
    36314271
    36324272
     4273#ifdef TCL_COMPILE_STATS
     4274/*
     4275 *----------------------------------------------------------------------
     4276 *
     4277 * TclLog2 --
     4278 *
     4279 *      Procedure used while collecting compilation statistics to determine
     4280 *      the log base 2 of an integer.
     4281 *
     4282 * Results:
     4283 *      Returns the log base 2 of the operand. If the argument is less
     4284 *      than or equal to zero, a zero is returned.
     4285 *
     4286 * Side effects:
     4287 *      None.
     4288 *
     4289 *----------------------------------------------------------------------
     4290 */
     4291
     4292int
     4293TclLog2(value)
     4294    register int value;         /* The integer for which to compute the
     4295                                 * log base 2. */
     4296{
     4297    register int n = value;
     4298    register int result = 0;
     4299
     4300    while (n > 1) {
     4301        n = n >> 1;
     4302        result++;
     4303    }
     4304    return result;
     4305}
     4306
     4307
     4308/*
     4309 *----------------------------------------------------------------------
     4310 *
     4311 * EvalStatsCmd --
     4312 *
     4313 *      Implements the "evalstats" command that prints instruction execution
     4314 *      counts to stdout.
     4315 *
     4316 * Results:
     4317 *      Standard Tcl results.
     4318 *
     4319 * Side effects:
     4320 *      None.
     4321 *
     4322 *----------------------------------------------------------------------
     4323 */
     4324
     4325static int
     4326EvalStatsCmd(unused, interp, argc, argv)
     4327    ClientData unused;          /* Unused. */
     4328    Tcl_Interp *interp;         /* The current interpreter. */
     4329    int argc;                   /* The number of arguments. */
     4330    char **argv;                /* The argument strings. */
     4331{
     4332    register double total = 0.0;
     4333    register int i;
     4334    int maxSizeDecade = 0;
     4335    double totalHeaderBytes = (tclNumCompilations * sizeof(ByteCode));
     4336
     4337    for (i = 0;  i < 256;  i++) {
     4338        if (instructionCount[i] != 0) {
     4339            total += instructionCount[i];
     4340        }
     4341    }
     4342
     4343    for (i = 31;  i >= 0;  i--) {
     4344        if ((tclSourceCount[i] > 0) && (tclByteCodeCount[i] > 0)) {
     4345            maxSizeDecade = i;
     4346            break;
     4347        }
     4348    }
     4349
     4350    fprintf(stdout, "\nNumber of compilations           %ld\n",
     4351            tclNumCompilations);
     4352    fprintf(stdout, "Number of executions               %ld\n",
     4353            numExecutions);
     4354    fprintf(stdout, "Average executions/compilation     %.0f\n",
     4355            ((float) numExecutions/tclNumCompilations));
     4356   
     4357    fprintf(stdout, "\nInstructions executed            %.0f\n",
     4358            total);
     4359    fprintf(stdout, "Average instructions/compile       %.0f\n",
     4360            total/tclNumCompilations);
     4361    fprintf(stdout, "Average instructions/execution     %.0f\n",
     4362            total/numExecutions);
     4363   
     4364    fprintf(stdout, "\nTotal source bytes               %.6g\n",
     4365            tclTotalSourceBytes);
     4366    fprintf(stdout, "Total code bytes           %.6g\n",
     4367            tclTotalCodeBytes);
     4368    fprintf(stdout, "Average code/compilation   %.0f\n",
     4369            tclTotalCodeBytes/tclNumCompilations);
     4370    fprintf(stdout, "Average code/source                %.2f\n",
     4371            tclTotalCodeBytes/tclTotalSourceBytes);
     4372    fprintf(stdout, "Current source bytes               %.6g\n",
     4373            tclCurrentSourceBytes);
     4374    fprintf(stdout, "Current code bytes         %.6g\n",
     4375            tclCurrentCodeBytes);
     4376    fprintf(stdout, "Current code/source                %.2f\n",
     4377            tclCurrentCodeBytes/tclCurrentSourceBytes);
     4378   
     4379    fprintf(stdout, "\nTotal objects allocated          %ld\n",
     4380            tclObjsAlloced);
     4381    fprintf(stdout, "Total objects freed                %ld\n",
     4382            tclObjsFreed);
     4383    fprintf(stdout, "Current objects:           %ld\n",
     4384            (tclObjsAlloced - tclObjsFreed));
     4385
     4386    fprintf(stdout, "\nBreakdown of code byte requirements:\n");
     4387    fprintf(stdout, "                   Total bytes      Pct of    Avg per\n");
     4388    fprintf(stdout, "                                  all code    compile\n");
     4389    fprintf(stdout, "Total code        %12.6g        100%%   %8.2f\n",
     4390            tclTotalCodeBytes, tclTotalCodeBytes/tclNumCompilations);
     4391    fprintf(stdout, "Header            %12.6g   %8.2f%%   %8.2f\n",
     4392            totalHeaderBytes,
     4393            ((totalHeaderBytes * 100.0) / tclTotalCodeBytes),
     4394            totalHeaderBytes/tclNumCompilations);
     4395    fprintf(stdout, "Instructions      %12.6g   %8.2f%%   %8.2f\n",
     4396            tclTotalInstBytes,
     4397            ((tclTotalInstBytes * 100.0) / tclTotalCodeBytes),
     4398            tclTotalInstBytes/tclNumCompilations);
     4399    fprintf(stdout, "Objects           %12.6g   %8.2f%%   %8.2f\n",
     4400            tclTotalObjBytes,
     4401            ((tclTotalObjBytes * 100.0) / tclTotalCodeBytes),
     4402            tclTotalObjBytes/tclNumCompilations);
     4403    fprintf(stdout, "Exception table   %12.6g   %8.2f%%   %8.2f\n",
     4404            tclTotalExceptBytes,
     4405            ((tclTotalExceptBytes * 100.0) / tclTotalCodeBytes),
     4406            tclTotalExceptBytes/tclNumCompilations);
     4407    fprintf(stdout, "Auxiliary data    %12.6g   %8.2f%%   %8.2f\n",
     4408            tclTotalAuxBytes,
     4409            ((tclTotalAuxBytes * 100.0) / tclTotalCodeBytes),
     4410            tclTotalAuxBytes/tclNumCompilations);
     4411    fprintf(stdout, "Command map       %12.6g   %8.2f%%   %8.2f\n",
     4412            tclTotalCmdMapBytes,
     4413            ((tclTotalCmdMapBytes * 100.0) / tclTotalCodeBytes),
     4414            tclTotalCmdMapBytes/tclNumCompilations);
     4415   
     4416    fprintf(stdout, "\nSource and ByteCode size distributions:\n");
     4417    fprintf(stdout, "    binary decade          source    code\n");
     4418    for (i = 0;  i <= maxSizeDecade;  i++) {
     4419        int decadeLow, decadeHigh;
     4420
     4421        if (i == 0) {
     4422            decadeLow = 0;
     4423        } else {
     4424            decadeLow = 1 << i;
     4425        }
     4426        decadeHigh = (1 << (i+1)) - 1;
     4427        fprintf(stdout, "       %6d -%6d                %6d     %6d\n",
     4428                decadeLow, decadeHigh,
     4429                tclSourceCount[i], tclByteCodeCount[i]);
     4430    }
     4431
     4432    fprintf(stdout, "\nInstruction counts:\n");
     4433    for (i = 0;  i < 256;  i++) {
     4434        if (instructionCount[i]) {
     4435            fprintf(stdout, "%20s %8d %6.2f%%\n",
     4436                    opName[i], instructionCount[i],
     4437                    (instructionCount[i] * 100.0)/total);
     4438        }
     4439    }
     4440
     4441#ifdef TCL_MEM_DEBUG
     4442    fprintf(stdout, "\nHeap Statistics:\n");
     4443    TclDumpMemoryInfo(stdout);
     4444#endif /* TCL_MEM_DEBUG */
     4445
     4446    return TCL_OK;
     4447}
     4448#endif /* TCL_COMPILE_STATS */
     4449
     4450
    36334451/*
    36344452 *----------------------------------------------------------------------
     
    39404758    panic("UpdateStringOfCmdName should never be invoked");
    39414759}
     4760
     4761
     4762#ifdef TCL_COMPILE_DEBUG
     4763/*
     4764 *----------------------------------------------------------------------
     4765 *
     4766 * StringForResultCode --
     4767 *
     4768 *      Procedure that returns a human-readable string representing a
     4769 *      Tcl result code such as TCL_ERROR.
     4770 *
     4771 * Results:
     4772 *      If the result code is one of the standard Tcl return codes, the
     4773 *      result is a string representing that code such as "TCL_ERROR".
     4774 *      Otherwise, the result string is that code formatted as a
     4775 *      sequence of decimal digit characters. Note that the resulting
     4776 *      string must not be modified by the caller.
     4777 *
     4778 * Side effects:
     4779 *      None.
     4780 *
     4781 *----------------------------------------------------------------------
     4782 */
     4783
     4784static char *
     4785StringForResultCode(result)
     4786    int result;                 /* The Tcl result code for which to
     4787                                 * generate a string. */
     4788{
     4789    static char buf[20];
     4790   
     4791    if ((result >= TCL_OK) && (result <= TCL_CONTINUE)) {
     4792        return resultStrings[result];
     4793    }
     4794    TclFormatInt(buf, result);
     4795    return buf;
     4796}
     4797#endif /* TCL_COMPILE_DEBUG */
Note: See TracChangeset for help on using the changeset viewer.