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 /generic/tclCompile.c | |
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.
Diffstat (limited to 'generic/tclCompile.c')
-rw-r--r-- | generic/tclCompile.c | 64 |
1 files changed, 64 insertions, 0 deletions
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 */ } |