summaryrefslogtreecommitdiffstats
path: root/generic/tclCompile.c
diff options
context:
space:
mode:
authorandreask <andreask>2011-05-17 21:26:26 (GMT)
committerandreask <andreask>2011-05-17 21:26:26 (GMT)
commitb1afef184bd6e770f5f2f45c2492011a9da336d2 (patch)
treea4bbac44980f75997bbb2923ce29f7d17cb3a70d /generic/tclCompile.c
parent4ac324aa8ce1d6355bcf7086f6e4fe2faf4143bc (diff)
downloadtcl-b1afef184bd6e770f5f2f45c2492011a9da336d2.zip
tcl-b1afef184bd6e770f5f2f45c2492011a9da336d2.tar.gz
tcl-b1afef184bd6e770f5f2f45c2492011a9da336d2.tar.bz2
* generic/tclCompile.c (TclFixupForwardJump): Tracked down and fixed
* generic/tclBasic.c (TclArgumentBCEnter): the cause of a violation of my assertion that 'ePtr->nline == objc' in TclArgumentBCEnter. When a bytecode was grown during jump fixup the pc -> command line mapping was not updated. When things aligned just wrong the mapping would direct command A to the data for command B, with a different number of arguments.
Diffstat (limited to 'generic/tclCompile.c')
-rw-r--r--generic/tclCompile.c64
1 files changed, 64 insertions, 0 deletions
diff --git a/generic/tclCompile.c b/generic/tclCompile.c
index 2d8d58c..8a7cbf8 100644
--- a/generic/tclCompile.c
+++ b/generic/tclCompile.c
@@ -3020,6 +3020,70 @@ TclFixupForwardJump(
rangePtr->type);
}
}
+
+ /*
+ * TIP #280: Adjust the mapping from PC values to the per-command
+ * information about arguments and their line numbers.
+ *
+ * Note: We cannot simply remove an out-of-date entry and then reinsert
+ * with the proper PC, because then we might overwrite another entry which
+ * was at that location. Therefore we pull (copy + delete) all effected
+ * entries (beyond the fixed PC) into an array, update them there, and at
+ * last reinsert them all.
+ */
+
+ {
+ ExtCmdLoc* eclPtr = envPtr->extCmdMapPtr;
+
+ /* A helper structure */
+
+ typedef struct {
+ int pc;
+ int cmd;
+ } MAP;
+
+ /*
+ * And the helper array. At most the whole hashtable is placed into
+ * this.
+ */
+
+ MAP *map = (MAP*) ckalloc (sizeof(MAP) * eclPtr->litInfo.numEntries);
+
+ Tcl_HashSearch hSearch;
+ Tcl_HashEntry* hPtr;
+ int n, k, isnew;
+
+ /*
+ * Phase I: Locate the affected entries, and save them in adjusted
+ * form to the array. This removes them from the hash.
+ */
+
+ for (n = 0, hPtr = Tcl_FirstHashEntry(&eclPtr->litInfo, &hSearch);
+ hPtr != NULL;
+ hPtr = Tcl_NextHashEntry(&hSearch)) {
+
+ map [n].cmd = PTR2INT(Tcl_GetHashValue(hPtr));
+ map [n].pc = PTR2INT(Tcl_GetHashKey (&eclPtr->litInfo,hPtr));
+
+ if (map[n].pc >= (jumpFixupPtr->codeOffset + 2)) {
+ Tcl_DeleteHashEntry(hPtr);
+ map [n].pc += 3;
+ n++;
+ }
+ }
+
+ /*
+ * Phase II: Re-insert the modified entries into the hash.
+ */
+
+ for (k=0;k<n;k++) {
+ hPtr = Tcl_CreateHashEntry(&eclPtr->litInfo, INT2PTR(map[k].pc), &isnew);
+ Tcl_SetHashValue(hPtr, INT2PTR(map[k].cmd));
+ }
+
+ ckfree (map);
+ }
+
return 1; /* the jump was grown */
}