diff options
author | andreask <andreask> | 2011-05-17 21:38:46 (GMT) |
---|---|---|
committer | andreask <andreask> | 2011-05-17 21:38:46 (GMT) |
commit | 23c320cea6647facf962db57c34c5cd85b9432b6 (patch) | |
tree | b5e7c39efe55151da282aae8a06fc6d25a81b1e5 | |
parent | 3b2326b2cb12d8d9376f464d61e70ef88433d2c5 (diff) | |
parent | ae8c7e936a3c00a11a29a50f2b80df021acbea51 (diff) | |
download | tcl-23c320cea6647facf962db57c34c5cd85b9432b6.zip tcl-23c320cea6647facf962db57c34c5cd85b9432b6.tar.gz tcl-23c320cea6647facf962db57c34c5cd85b9432b6.tar.bz2 |
Merged core-8-5-branch, fixup of TIP 280 location mapping.
-rw-r--r-- | ChangeLog | 10 | ||||
-rw-r--r-- | generic/tclBasic.c | 4 | ||||
-rw-r--r-- | generic/tclCompile.c | 64 |
3 files changed, 78 insertions, 0 deletions
@@ -1,3 +1,13 @@ +2011-05-17 Andreas Kupries <andreask@activestate.com> + + * 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. + 2011-05-11 Reinhard Max <max@suse.de> * unix/tclUnixSock.c (TcpWatchProc): No need to check for server diff --git a/generic/tclBasic.c b/generic/tclBasic.c index 2da455b..d80731e 100644 --- a/generic/tclBasic.c +++ b/generic/tclBasic.c @@ -5590,6 +5590,10 @@ TclArgumentBCEnter( * have to save them at compile time. */ + if (ePtr->nline != objc) { + Tcl_Panic ("TIP 280 data structure inconsistency"); + } + for (word = 1; word < objc; word++) { if (ePtr->line[word] >= 0) { int isnew; diff --git a/generic/tclCompile.c b/generic/tclCompile.c index 2194ae1..0eaf834 100644 --- a/generic/tclCompile.c +++ b/generic/tclCompile.c @@ -3320,6 +3320,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 */ } |