Index: generic/tclExecute.c
===================================================================
RCS file: /cvsroot/tcl/tcl/generic/tclExecute.c,v
retrieving revision 1.341
diff -u -r1.341 tclExecute.c
--- generic/tclExecute.c	8 Nov 2007 07:10:43 -0000	1.341
+++ generic/tclExecute.c	8 Nov 2007 10:24:35 -0000
@@ -9,6 +9,7 @@
  * Copyright (c) 2002-2005 by Miguel Sofer.
  * Copyright (c) 2005-2007 by Donal K. Fellows.
  * Copyright (c) 2007 Daniel A. Steffen <das@users.sourceforge.net>
+ * Copyright (c) 2007 George Peter Staplin.
  *
  * See the file "license.terms" for information on usage and redistribution of
  * this file, and for a DISCLAIMER OF ALL WARRANTIES.
@@ -23,6 +24,25 @@
 #include <math.h>
 #include <float.h>
 
+#define TCL_VM_TIME_TABLE 1
+
+#ifdef TCL_VM_TIME_TABLE
+
+#ifdef TCL_WIDE_CLICKS
+#define GetClicks(foo) (foo = TclpGetWideClicks())
+#elif 1
+/* Taken from linux's asm-x86_64/msr.h rdtscll */
+#define GetClicks(foo) do {				  \
+            uint32_t __a,__d; \
+	    asm volatile("rdtsc" : "=a" (__a), "=d" (__d)); \
+	    (foo) = ((uint64_t)__a) | (((uint64_t)__d)<<32); \
+	} while(0)
+#else
+#define GetClicks(foo) (foo = TclpGetClicks())
+#endif
+#endif
+
+
 /*
  * Hack to determine whether we may expect IEEE floating point. The hack is
  * formally incorrect in that non-IEEE platforms might have the same precision
@@ -1498,6 +1518,38 @@
     Tcl_SetBignumObj(valuePtr, &value);
     return TCL_OK;
 }
+
+#ifdef TCL_VM_TIME_TABLE
+
+static int timeTableReady = 0;
+static Tcl_WideInt childClicks = 0;
+static Tcl_WideInt biasClicks = 0;
+static struct {
+    Tcl_WideInt instCount;
+    Tcl_WideInt instTotalTime;
+} timeTable[LAST_INST_OPCODE + 1];
+
+static void
+DumpTimeTable(void) {
+    int i;
+    FILE *fp;
+    
+    fp = fopen("time.log", "a");
+    if (NULL == fp) {
+	perror("fopen");
+	return;
+    }
+    
+    for (i = 0; i <= LAST_INST_OPCODE; ++i) {
+	if (timeTable[i].instTotalTime) {
+	    fprintf(fp, "%d %lld %lld\n", i, timeTable[i].instTotalTime,
+		    timeTable[i].instCount);
+	}
+    }
+    fprintf(fp, "- -\n");
+}
+#endif
+
 
 /*
  *----------------------------------------------------------------------
@@ -1529,6 +1581,10 @@
      */
 #define iPtr ((Interp *) interp)
 
+#ifdef TCL_VM_TIME_TABLE
+    int lastInstruction = -1;
+    Tcl_WideInt before = 0, clicks, startClicks = 0;
+#endif
     /*
      * Constants: variables that do not change during the execution, used
      * sporadically.
@@ -1634,6 +1690,26 @@
     namespacePtr = iPtr->varFramePtr->nsPtr;
     compiledLocals = iPtr->varFramePtr->compiledLocals;
 
+
+#if TCL_VM_TIME_TABLE
+    if (!timeTableReady) {
+	int i;
+
+	GetClicks(clicks);
+	for (i = 0; i <= LAST_INST_OPCODE; ++i) {
+	    timeTable[i].instCount = timeTable[i].instTotalTime = 0;
+	    GetClicks(biasClicks);
+	}
+	biasClicks = (biasClicks - clicks)/i;
+	fprintf(stderr, "biasClicks %lld\n", biasClicks);
+	
+	timeTableReady = 1;
+	if (atexit(DumpTimeTable))
+	    perror("atexit");
+    }
+#endif
+
+
     /*
      * Loop executing instructions until a "done" instruction, a TCL_RETURN,
      * or some error.
@@ -1758,6 +1834,20 @@
 	}
     }
 
+
+#ifdef TCL_VM_TIME_TABLE
+    GetClicks(clicks);
+    if (before && (-1 != lastInstruction)) {
+	timeTable[lastInstruction].instTotalTime += clicks - before - childClicks;
+	timeTable[lastInstruction].instCount++;
+    } else {
+	startClicks = clicks;
+    }
+    childClicks = 0;
+    before = clicks + biasClicks;
+    lastInstruction = *pc;
+#endif    
+
     /*
      * These two instructions account for 26% of all instructions (according
      * to measurements on tclbench by Ben Vitale
@@ -7078,6 +7168,16 @@
 	}
     }
 
+#ifdef TCL_VM_TIME_TABLE
+    GetClicks(clicks);
+    if (before && (-1 != lastInstruction)) {
+	timeTable[lastInstruction].instTotalTime += clicks - before - childClicks;
+	timeTable[lastInstruction].instCount++;
+    }
+    GetClicks(childClicks);
+    childClicks -= startClicks;
+#endif
+
     /*
      * Restore the stack to the state it had previous to this bytecode.
      */
