Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Changes In Branch bug-3614342 Excluding Merge-Ins
This is equivalent to a diff from 47e3976f09 to f938eff7f5
|
2013-06-05
| ||
| 20:23 | merge fixes check-in: 9fb220c28a user: dkf tags: dkf-bytecode-optimizer | |
| 15:22 | [Bugs 2835313, 3614226, 3614342]: Complete the construction of break/continue compilers that get the... check-in: 0cf4701170 user: dgp tags: trunk | |
| 15:07 | Repair TCL_COMPILE_DEBUG guards Closed-Leaf check-in: f938eff7f5 user: dgp tags: bug-3614342 | |
| 14:50 | Stack Depth fixups. check-in: 37677f8c2e user: dgp tags: bug-3614342 | |
| 08:11 | [Bugs 2835313, 3614226]: Complete the construction of break/continue compilers that get the stack cl... check-in: ac84c44dcf user: dkf tags: bug-3614342 | |
| 07:57 | merge trunk Closed-Leaf check-in: 831ea0cbac user: dkf tags: dkf-compile-improvements | |
|
2013-06-04
| ||
| 08:34 | TIP #414 implementation check-in: f76bf90f39 user: jan.nijtmans tags: initsubsystems | |
| 08:33 | Eliminate NO_VIZ macro as current zlib uses HAVE_HIDDEN in stead. One more last-moment fix for FreeB... check-in: 47e3976f09 user: jan.nijtmans tags: trunk | |
|
2013-06-03
| ||
| 20:31 | merge 8.5 check-in: d0c70147da user: dgp tags: trunk | |
Changes to ChangeLog.
1 2 | 2013-06-04 Jan Nijtmans <nijtmans@users.sf.net> | > > > > > > > > > > | < | | | | | | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 | 2013-06-05 Donal K. Fellows <dkf@users.sf.net> * generic/tclExecute.c (INST_EXPAND_DROP): [Bugs 2835313, 3614226]: New opcode to allow resetting the stack to get rid of an expansion, restoring the stack to a known state in the process. * generic/tclCompile.c, generic/tclCompCmds.c: Adjusted the compilers for [break] and [continue] to get stack cleanup right in the majority of cases. * tests/for.test (for-7.*): Set of tests for these evil cases. 2013-06-04 Jan Nijtmans <nijtmans@users.sf.net> * unix/tcl.m4: Eliminate NO_VIZ macro as current zlib uses HAVE_HIDDEN instead. One more last-moment fix for FreeBSD by Pietro Cerutti 2013-06-03 Miguel Sofer <msofer@users.sf.net> * generic/tclExecute.c: fix for perf bug detected by Kieran (https://groups.google.com/forum/?fromgroups#!topic/comp.lang.tcl/vfpI3bc-DkQ), diagnosed by dgp to be a close relative of [Bug 781585], which was fixed by commit [f46fb50cb3]. This bug was introduced by myself in commit [cbfe055d8c]. 2013-06-03 Donal K. Fellows <dkf@users.sf.net> * generic/tclCompCmds.c (TclCompileBreakCmd, TclCompileContinueCmd): Added code to allow [break] and [continue] to be issued as a jump (in the most common cases) rather than using the more expensive exception processing path in the bytecode engine. [Bug 3614226]: Partial fix for the issues relating to cleaning up the stack when dealing with [break] and [continue]. 2013-05-27 Harald Oehlmann <oehhar@users.sf.net> * library/msgcat/msgcat.tcl: [Bug 3036566]: Also get locale from registry key HCU\Control Panel\Desktop : PreferredUILanguages to honor installed language packs on Vista+. Bumped msgcat version to 1.5.2 2013-05-22 Andreas Kupries <andreask@activestate.com> * tclCompile.c: Removed duplicate const qualifier causing the HP native cc to error out. 2013-05-22 Donal K. Fellows <dkf@users.sf.net> * generic/tclUtf.c (TclUtfCasecmp): [Bug 3613609]: Replace problematic uses of strcasecmp with a proper UTF-8-aware version. Affects both [lsearch -nocase] and [lsort -nocase]. |
| ︙ | ︙ | |||
89 90 91 92 93 94 95 | need for various wrapper functions/macros. For Tcl 9 a better solution is needed, but that cannot be done without introducing binary incompatibility. 2013-04-30 Andreas Kupries <andreask@activestate.com> * library/platform/platform.tcl (::platform::LibcVersion): | | | | < | | | | | | | | | 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 | need for various wrapper functions/macros. For Tcl 9 a better solution is needed, but that cannot be done without introducing binary incompatibility. 2013-04-30 Andreas Kupries <andreask@activestate.com> * library/platform/platform.tcl (::platform::LibcVersion): * library/platform/pkgIndex.tcl: Followup to the 2013-01-30 change. The RE become too restrictive again. SuSe added a timestamp after the version. Loosened up a bit. Bumped package to version 1.0.12. 2013-04-29 Donal K. Fellows <dkf@users.sf.net> * generic/tclCompCmds.c (TclCompileArraySetCmd): Generate better code when the list of things to set is a literal. 2013-04-25 Jan Nijtmans <nijtmans@users.sf.net> * generic/tclDecls.h: Implement Tcl_NewBooleanObj, Tcl_DbNewBooleanObj and Tcl_SetBooleanObj as macros using Tcl_NewIntObj, Tcl_DbNewLongObj and Tcl_SetIntObj. Starting with Tcl 8.5, this is exactly the same, it only eliminates code duplication. * generic/tclInt.h: Eliminate use of NO_WIDE_TYPE everywhere: It's exactly the same as TCL_WIDE_INT_IS_LONG 2013-04-19 Jan Nijtmans <nijtmans@users.sf.net> * generic/tclDecls.h: Implement many Tcl_*Var* functions and Tcl_GetIndexFromObj as (faster/stack-saving) macros around resp their Tcl_*Var*2 equivalent and Tcl_GetIndexFromObjStruct. 2013-04-12 Jan Nijtmans <nijtmans@users.sf.net> * generic/tclDecls.h: Implement Tcl_Pkg* functions as (faster/stack-saving) macros around Tcl_Pkg*Ex functions. 2013-04-08 Don Porter <dgp@users.sourceforge.net> * generic/regc_color.c: [Bug 3610026]: Stop crash when the number of * generic/regerrs.h: "colors" in a regular expression overflows a * generic/regex.h: short int. Thanks to Heikki Linnakangas for * generic/regguts.h: the report and the patch. * tests/regexp.test: 2013-04-04 Reinhard Max <max@suse.de> * library/http/http.tcl (http::geturl): Allow URLs that don't have a path, but a query query, e.g. http://example.com?foo=bar * Bump the http package to 2.8.7. 2013-03-22 Venkat Iyer <venkat@comit.com> * library/tzdata/Africa/Cairo: Update to tzdata2013b. * library/tzdata/Africa/Casablanca: * library/tzdata/Africa/Gaborone: * library/tzdata/Africa/Tripoli: |
| ︙ | ︙ | |||
162 163 164 165 166 167 168 | * library/tzdata/Pacific/Fiji: * library/tzdata/Asia/Khandyga: (new) * library/tzdata/Asia/Ust-Nera: (new) * library/tzdata/Europe/Busingen: (new) 2013-03-21 Don Porter <dgp@users.sourceforge.net> | | | | | | | | | | | | 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 | * library/tzdata/Pacific/Fiji: * library/tzdata/Asia/Khandyga: (new) * library/tzdata/Asia/Ust-Nera: (new) * library/tzdata/Europe/Busingen: (new) 2013-03-21 Don Porter <dgp@users.sourceforge.net> * library/auto.tcl: [Bug 2102614]: Add ensemble indexing support to * tests/autoMkindex.test: [auto_mkindex]. Thanks Brian Griffin. 2013-03-19 Don Porter <dgp@users.sourceforge.net> * generic/tclFCmd.c: [Bug 3597000]: Consistent [file copy] result. * tests/fileSystem.test: 2013-03-19 Jan Nijtmans <nijtmans@users.sf.net> * win/tclWinFile.c: [Bug 3608360]: Incompatible behaviour of "file exists". 2013-03-18 Donal K. Fellows <dkf@users.sf.net> * tests/cmdAH.test (cmdAH-19.12): [Bug 3608360]: Added test to ensure that we never ever allow [file exists] to do globbing. 2013-03-12 Jan Nijtmans <nijtmans@users.sf.net> * unix/tcl.m4: Patch by Andrew Shadura, providing better support for three architectures they have in Debian. 2013-03-11 Don Porter <dgp@users.sourceforge.net> * generic/tclCompile.c: [Bugs 3607246,3607372]: Unbalanced refcounts * generic/tclLiteral.c: of literals in the global literal table. 2013-03-06 Don Porter <dgp@users.sourceforge.net> * generic/regc_nfa.c: [Bugs 3604074,3606683]: Rewrite of the * generic/regcomp.c: fixempties() routine (and supporting routines) to completely eliminate the infinite loop hazard. Thanks to Tom Lane for the much improved solution. 2013-02-28 Don Porter <dgp@users.sourceforge.net> * generic/tclLiteral.c: Revise TclReleaseLiteral() to tolerate a NULL interp argument. * generic/tclCompile.c: Update callers and revise mistaken comments. * generic/tclProc.c: 2013-02-27 Jan Nijtmans <nijtmans@users.sf.net> * generic/regcomp.c: [Bug 3606139]: missing error check allows |
| ︙ | ︙ | |||
4895 4896 4897 4898 4899 4900 4901 | normalized paths, otherwise it might result in a crash on CYGWIN. Restyle according to the Tcl style guide. * generic/tclStrToD.c: [Bug 3005233]: Fix for build on OpenBSD vax 2010-05-19 Alexandre Ferrieux <ferrieux@users.sourceforge.net> * tests/dict.test: Add missing tests for [Bug 3004007], fixed under | | < | 4903 4904 4905 4906 4907 4908 4909 4910 4911 4912 4913 4914 4915 4916 4917 | normalized paths, otherwise it might result in a crash on CYGWIN. Restyle according to the Tcl style guide. * generic/tclStrToD.c: [Bug 3005233]: Fix for build on OpenBSD vax 2010-05-19 Alexandre Ferrieux <ferrieux@users.sourceforge.net> * tests/dict.test: Add missing tests for [Bug 3004007], fixed under the radar on 2010-02-24 (dkf): EIAS violation in list-dict conversions 2010-05-19 Jan Nijtmans <nijtmans@users.sf.net> * generic/regcomp.c: Don't use arrays of length 1, just use a * generic/tclFileName.c: single element then, it makes code more * generic/tclLoad.c: readable. (Here it even prevents a type cast) |
| ︙ | ︙ | |||
6750 6751 6752 6753 6754 6755 6756 | * tests/http.test * library/http/pkgIndex.tcl: Bump to http 2.8.2 * unix/Makefile.in: * win/Makefile.in: 2009-11-11 Alexandre Ferrieux <ferrieux@users.sourceforge.net> | | | < | | 6757 6758 6759 6760 6761 6762 6763 6764 6765 6766 6767 6768 6769 6770 6771 6772 6773 | * tests/http.test * library/http/pkgIndex.tcl: Bump to http 2.8.2 * unix/Makefile.in: * win/Makefile.in: 2009-11-11 Alexandre Ferrieux <ferrieux@users.sourceforge.net> * generic/tclIO.c: Fix [Bug 2888099] (close discards ENOSPC error) by saving the errno from the first of two FlushChannel()s. Uneasy to test; might need specific channel drivers. Four-hands with aku. 2009-11-10 Pat Thoyts <patthoyts@users.sourceforge.net> * tests/winFCmd.test: Cleanup directories that have been set chmod 000. On Windows7 and Vista we really have no access and these were getting left behind. A few tests were changed to reflect the intent of the test where |
| ︙ | ︙ |
Changes to generic/tclAssembly.c.
| ︙ | ︙ | |||
16 17 18 19 20 21 22 | /*- *- THINGS TO DO: *- More instructions: *- done - alternate exit point (affects stack and exception range checking) *- break and continue - if exception ranges can be sorted out. *- foreach_start4, foreach_step4 *- returnImm, returnStk | | | 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | /*- *- THINGS TO DO: *- More instructions: *- done - alternate exit point (affects stack and exception range checking) *- break and continue - if exception ranges can be sorted out. *- foreach_start4, foreach_step4 *- returnImm, returnStk *- expandStart, expandStkTop, invokeExpanded, expandDrop *- dictFirst, dictNext, dictDone *- dictUpdateStart, dictUpdateEnd *- jumpTable testing *- syntax (?) *- returnCodeBranch */ |
| ︙ | ︙ |
Changes to generic/tclCompCmds.c.
| ︙ | ︙ | |||
489 490 491 492 493 494 495 |
/*
* Find the innermost exception range that contains this command.
*/
rangePtr = TclGetInnermostExceptionRange(envPtr, TCL_BREAK, &auxPtr);
if (rangePtr && rangePtr->type == LOOP_EXCEPTION_RANGE) {
| < < < < < < < < < < < < < < | | > | < < < | > | | | > | > > | < < < < < < | 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 |
/*
* Find the innermost exception range that contains this command.
*/
rangePtr = TclGetInnermostExceptionRange(envPtr, TCL_BREAK, &auxPtr);
if (rangePtr && rangePtr->type == LOOP_EXCEPTION_RANGE) {
/*
* Found the target! No need for a nasty INST_BREAK here.
*/
TclCleanupStackForBreakContinue(envPtr, auxPtr);
TclAddLoopBreakFixup(envPtr, auxPtr);
TclAdjustStackDepth(1, envPtr);
} else {
/*
* Emit a real break.
*/
PushStringLiteral(envPtr, "");
TclEmitOpcode(INST_DUP, envPtr);
TclEmitInstInt4(INST_RETURN_IMM, TCL_BREAK, envPtr);
TclEmitInt4(0, envPtr);
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TclCompileCatchCmd --
|
| ︙ | ︙ | |||
836 837 838 839 840 841 842 |
/*
* See if we can find a valid continueOffset (i.e., not -1) in the
* innermost containing exception range.
*/
rangePtr = TclGetInnermostExceptionRange(envPtr, TCL_CONTINUE, &auxPtr);
if (rangePtr && rangePtr->type == LOOP_EXCEPTION_RANGE) {
| < < < < < < < < < < < < < < | | > | < < < | > | | | > | > > | < < < < < < | 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 |
/*
* See if we can find a valid continueOffset (i.e., not -1) in the
* innermost containing exception range.
*/
rangePtr = TclGetInnermostExceptionRange(envPtr, TCL_CONTINUE, &auxPtr);
if (rangePtr && rangePtr->type == LOOP_EXCEPTION_RANGE) {
/*
* Found the target! No need for a nasty INST_CONTINUE here.
*/
TclCleanupStackForBreakContinue(envPtr, auxPtr);
TclAddLoopContinueFixup(envPtr, auxPtr);
TclAdjustStackDepth(1, envPtr);
} else {
/*
* Emit a real continue.
*/
PushStringLiteral(envPtr, "");
TclEmitOpcode(INST_DUP, envPtr);
TclEmitInstInt4(INST_RETURN_IMM, TCL_CONTINUE, envPtr);
TclEmitInt4(0, envPtr);
}
return TCL_OK;
}
/*
*----------------------------------------------------------------------
*
* TclCompileDict*Cmd --
|
| ︙ | ︙ |
Changes to generic/tclCompile.c.
| ︙ | ︙ | |||
536 537 538 539 540 541 542 543 544 545 546 547 548 549 |
* <objc,objv> = <op4,top op4 after popping 1> */
{"listConcat", 1, -1, 0, {OPERAND_NONE}},
/* Concatenates the two lists at the top of the stack into a single
* list and pushes that resulting list onto the stack.
* Stack: ... list1 list2 => ... [lconcat list1 list2] */
{NULL, 0, 0, 0, {OPERAND_NONE}}
};
/*
* Prototypes for procedures defined later in this file:
*/
| > > > > | 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 |
* <objc,objv> = <op4,top op4 after popping 1> */
{"listConcat", 1, -1, 0, {OPERAND_NONE}},
/* Concatenates the two lists at the top of the stack into a single
* list and pushes that resulting list onto the stack.
* Stack: ... list1 list2 => ... [lconcat list1 list2] */
{"expandDrop", 1, 0, 0, {OPERAND_NONE}},
/* Drops an element from the auxiliary stack, popping stack elements
* until the matching stack depth is reached. */
{NULL, 0, 0, 0, {OPERAND_NONE}}
};
/*
* Prototypes for procedures defined later in this file:
*/
|
| ︙ | ︙ | |||
567 568 569 570 571 572 573 574 575 576 577 578 579 580 | static void PeepholeOptimize(CompileEnv *envPtr); #ifdef TCL_COMPILE_STATS static void RecordByteCodeStats(ByteCode *codePtr); #endif /* TCL_COMPILE_STATS */ static void RegisterAuxDataType(const AuxDataType *typePtr); static int SetByteCodeFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static int FormatInstruction(ByteCode *codePtr, const unsigned char *pc, Tcl_Obj *bufferObj); static void PrintSourceToObj(Tcl_Obj *appendObj, const char *stringPtr, int maxChars); static void UpdateStringOfInstName(Tcl_Obj *objPtr); /* | > | 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 | static void PeepholeOptimize(CompileEnv *envPtr); #ifdef TCL_COMPILE_STATS static void RecordByteCodeStats(ByteCode *codePtr); #endif /* TCL_COMPILE_STATS */ static void RegisterAuxDataType(const AuxDataType *typePtr); static int SetByteCodeFromAny(Tcl_Interp *interp, Tcl_Obj *objPtr); static void StartExpanding(CompileEnv *envPtr); static int FormatInstruction(ByteCode *codePtr, const unsigned char *pc, Tcl_Obj *bufferObj); static void PrintSourceToObj(Tcl_Obj *appendObj, const char *stringPtr, int maxChars); static void UpdateStringOfInstName(Tcl_Obj *objPtr); /* |
| ︙ | ︙ | |||
2056 2057 2058 2059 2060 2061 2062 |
/*
* Should only start issuing instructions after the "command has
* started" so that the command range is correct in the bytecode.
*/
if (expand) {
| < | | 2061 2062 2063 2064 2065 2066 2067 2068 2069 2070 2071 2072 2073 2074 2075 |
/*
* Should only start issuing instructions after the "command has
* started" so that the command range is correct in the bytecode.
*/
if (expand) {
StartExpanding(envPtr);
}
/*
* TIP #280. Scan the words and compute the extended location
* information. The map first contain full per-word line
* information for use by the compiler. This is later replaced by
* a reduced form which signals non-literal words, stored in
|
| ︙ | ︙ | |||
3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 |
rangePtr->breakOffset = -1;
rangePtr->continueOffset = -1;
rangePtr->catchOffset = -1;
auxPtr = &envPtr->exceptAuxArrayPtr[index];
auxPtr->supportsContinue = 1;
auxPtr->stackDepth = envPtr->currStackDepth;
auxPtr->expandTarget = envPtr->expandCount;
auxPtr->numBreakTargets = 0;
auxPtr->breakTargets = NULL;
auxPtr->allocBreakTargets = 0;
auxPtr->numContinueTargets = 0;
auxPtr->continueTargets = NULL;
auxPtr->allocContinueTargets = 0;
return index;
| > | 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 |
rangePtr->breakOffset = -1;
rangePtr->continueOffset = -1;
rangePtr->catchOffset = -1;
auxPtr = &envPtr->exceptAuxArrayPtr[index];
auxPtr->supportsContinue = 1;
auxPtr->stackDepth = envPtr->currStackDepth;
auxPtr->expandTarget = envPtr->expandCount;
auxPtr->expandTargetDepth = -1;
auxPtr->numBreakTargets = 0;
auxPtr->breakTargets = NULL;
auxPtr->allocBreakTargets = 0;
auxPtr->numContinueTargets = 0;
auxPtr->continueTargets = NULL;
auxPtr->allocContinueTargets = 0;
return index;
|
| ︙ | ︙ | |||
3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 |
CurrentOffset(envPtr);
TclEmitInstInt4(INST_JUMP4, 0, envPtr);
}
/*
* ---------------------------------------------------------------------
*
* TclFinalizeLoopExceptionRange --
*
* Finalizes a loop exception range, binding the registered [break] and
* [continue] implementations so that they jump to the correct place.
* Note that this must only be called after *all* the exception range
* target offsets have been set.
*
| > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604 3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658 3659 3660 3661 3662 3663 3664 3665 3666 3667 3668 3669 3670 3671 3672 3673 3674 3675 3676 3677 3678 3679 3680 3681 3682 3683 3684 3685 3686 3687 3688 3689 3690 3691 3692 3693 3694 3695 3696 3697 |
CurrentOffset(envPtr);
TclEmitInstInt4(INST_JUMP4, 0, envPtr);
}
/*
* ---------------------------------------------------------------------
*
* TclCleanupStackForBreakContinue --
*
* Ditch the extra elements from the auxiliary stack and the main
* stack. How to do this exactly depends on whether there are any
* elements on the auxiliary stack to pop.
*
* ---------------------------------------------------------------------
*/
void
TclCleanupStackForBreakContinue(
CompileEnv *envPtr,
ExceptionAux *auxPtr)
{
int toPop = envPtr->expandCount - auxPtr->expandTarget;
if (toPop > 0) {
while (toPop > 0) {
TclEmitOpcode(INST_EXPAND_DROP, envPtr);
toPop--;
}
toPop = auxPtr->expandTargetDepth - auxPtr->stackDepth;
while (toPop > 0) {
TclEmitOpcode(INST_POP, envPtr);
TclAdjustStackDepth(1, envPtr);
toPop--;
}
} else {
toPop = envPtr->currStackDepth - auxPtr->stackDepth;
while (toPop > 0) {
TclEmitOpcode(INST_POP, envPtr);
TclAdjustStackDepth(1, envPtr);
toPop--;
}
}
}
/*
* ---------------------------------------------------------------------
*
* StartExpanding --
*
* Pushes an INST_EXPAND_START and does some additional housekeeping so
* that the [break] and [continue] compilers can use an exception-free
* issue to discard it.
*
* ---------------------------------------------------------------------
*/
static void
StartExpanding(
CompileEnv *envPtr)
{
int i;
TclEmitOpcode(INST_EXPAND_START, envPtr);
/*
* Update inner exception ranges with information about the environment
* where this expansion started.
*/
for (i=0 ; i<envPtr->exceptArrayNext ; i++) {
ExceptionRange *rangePtr = &envPtr->exceptArrayPtr[i];
ExceptionAux *auxPtr = &envPtr->exceptAuxArrayPtr[i];
/*
* Ignore loops unless they're still being built.
*/
if (rangePtr->codeOffset > CurrentOffset(envPtr)) {
continue;
}
if (rangePtr->numCodeBytes != -1) {
continue;
}
/*
* Adequate condition: further out loops and further in exceptions
* don't actually need this information.
*/
if (auxPtr->expandTarget == envPtr->expandCount) {
auxPtr->expandTargetDepth = envPtr->currStackDepth;
}
}
/*
* There's now one more expansion being processed on the auxiliary stack.
*/
envPtr->expandCount++;
}
/*
* ---------------------------------------------------------------------
*
* TclFinalizeLoopExceptionRange --
*
* Finalizes a loop exception range, binding the registered [break] and
* [continue] implementations so that they jump to the correct place.
* Note that this must only be called after *all* the exception range
* target offsets have been set.
*
|
| ︙ | ︙ | |||
3622 3623 3624 3625 3626 3627 3628 |
}
for (i=0 ; i<auxPtr->numContinueTargets ; i++) {
site = envPtr->codeStart + auxPtr->continueTargets[i];
if (rangePtr->continueOffset == -1) {
int j;
/*
| | > | 3724 3725 3726 3727 3728 3729 3730 3731 3732 3733 3734 3735 3736 3737 3738 3739 |
}
for (i=0 ; i<auxPtr->numContinueTargets ; i++) {
site = envPtr->codeStart + auxPtr->continueTargets[i];
if (rangePtr->continueOffset == -1) {
int j;
/*
* WTF? Can't bind, so revert to an INST_CONTINUE. Not enough
* space to do anything else.
*/
*site = INST_CONTINUE;
for (j=0 ; j<4 ; j++) {
*++site = INST_NOP;
}
} else {
|
| ︙ | ︙ |
Changes to generic/tclCompile.h.
| ︙ | ︙ | |||
116 117 118 119 120 121 122 123 124 125 126 127 128 129 |
* to calculate the number of POPs required to
* restore the stack to its prior state. */
int expandTarget; /* The number of expansions expected on the
* auxData stack at the time the loop starts;
* we can't currently discard them except by
* doing INST_INVOKE_EXPANDED; this is a known
* problem. */
int numBreakTargets; /* The number of [break]s that want to be
* targeted to the place where this loop
* exception will be bound to. */
int *breakTargets; /* The offsets of the INST_JUMP4 instructions
* issued by the [break]s that we must
* update. Note that resizing a jump (via
* TclFixupForwardJump) can cause the contents
| > > > > > | 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 |
* to calculate the number of POPs required to
* restore the stack to its prior state. */
int expandTarget; /* The number of expansions expected on the
* auxData stack at the time the loop starts;
* we can't currently discard them except by
* doing INST_INVOKE_EXPANDED; this is a known
* problem. */
int expandTargetDepth; /* The stack depth expected at the outermost
* expansion within the loop. Not meaningful
* if there have are no open expansions
* between the looping level and the point of
* jump issue. */
int numBreakTargets; /* The number of [break]s that want to be
* targeted to the place where this loop
* exception will be bound to. */
int *breakTargets; /* The offsets of the INST_JUMP4 instructions
* issued by the [break]s that we must
* update. Note that resizing a jump (via
* TclFixupForwardJump) can cause the contents
|
| ︙ | ︙ | |||
768 769 770 771 772 773 774 775 | #define INST_ARRAY_MAKE_STK 161 #define INST_ARRAY_MAKE_IMM 162 #define INST_INVOKE_REPLACE 163 #define INST_LIST_CONCAT 164 /* The last opcode */ | > > | | 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 | #define INST_ARRAY_MAKE_STK 161 #define INST_ARRAY_MAKE_IMM 162 #define INST_INVOKE_REPLACE 163 #define INST_LIST_CONCAT 164 #define INST_EXPAND_DROP 165 /* The last opcode */ #define LAST_INST_OPCODE 165 /* * Table describing the Tcl bytecode instructions: their name (for displaying * code), total number of code bytes required (including operand bytes), and a * description of the type of each operand. These operand types include signed * and unsigned integers of length one and four bytes. The unsigned integers * are used for indexes or for, e.g., the count of objects to push in a "push" |
| ︙ | ︙ | |||
981 982 983 984 985 986 987 988 989 990 991 992 993 994 | *---------------------------------------------------------------- * Procedures shared among Tcl bytecode compilation and execution modules but * not used outside: *---------------------------------------------------------------- */ MODULE_SCOPE void TclCleanupByteCode(ByteCode *codePtr); MODULE_SCOPE void TclCompileCmdWord(Tcl_Interp *interp, Tcl_Token *tokenPtr, int count, CompileEnv *envPtr); MODULE_SCOPE void TclCompileExpr(Tcl_Interp *interp, const char *script, int numBytes, CompileEnv *envPtr, int optimize); MODULE_SCOPE void TclCompileExprWords(Tcl_Interp *interp, Tcl_Token *tokenPtr, int numWords, | > > | 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 | *---------------------------------------------------------------- * Procedures shared among Tcl bytecode compilation and execution modules but * not used outside: *---------------------------------------------------------------- */ MODULE_SCOPE void TclCleanupByteCode(ByteCode *codePtr); MODULE_SCOPE void TclCleanupStackForBreakContinue(CompileEnv *envPtr, ExceptionAux *auxPtr); MODULE_SCOPE void TclCompileCmdWord(Tcl_Interp *interp, Tcl_Token *tokenPtr, int count, CompileEnv *envPtr); MODULE_SCOPE void TclCompileExpr(Tcl_Interp *interp, const char *script, int numBytes, CompileEnv *envPtr, int optimize); MODULE_SCOPE void TclCompileExprWords(Tcl_Interp *interp, Tcl_Token *tokenPtr, int numWords, |
| ︙ | ︙ |
Changes to generic/tclExecute.c.
| ︙ | ︙ | |||
253 254 255 256 257 258 259 | * * We use the new compile-time assertions to check that nCleanup is constant * and within range. */ /* Verify the stack depth, only when no expansion is in progress */ | | | 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 |
*
* We use the new compile-time assertions to check that nCleanup is constant
* and within range.
*/
/* Verify the stack depth, only when no expansion is in progress */
#ifdef TCL_COMPILE_DEBUG
#define CHECK_STACK() \
do { \
ValidatePcAndStackTop(codePtr, pc, CURR_DEPTH, \
/*checkStack*/ !(starting || auxObjList)); \
starting = 0; \
} while (0)
#else
|
| ︙ | ︙ | |||
2626 2627 2628 2629 2630 2631 2632 |
if (!onlyb) {
bytes = TclGetStringFromObj(objResultPtr, &length);
if (length + appendLen < 0) {
/* TODO: convert panic to error ? */
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded",
INT_MAX);
}
| | | 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 |
if (!onlyb) {
bytes = TclGetStringFromObj(objResultPtr, &length);
if (length + appendLen < 0) {
/* TODO: convert panic to error ? */
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded",
INT_MAX);
}
#ifndef TCL_COMPILE_DEBUG
if (bytes != tclEmptyStringRep && !Tcl_IsShared(objResultPtr)) {
TclFreeIntRep(objResultPtr);
objResultPtr->bytes = ckrealloc(bytes, length+appendLen+1);
objResultPtr->length = length + appendLen;
p = TclGetString(objResultPtr) + length;
currPtr = &OBJ_AT_DEPTH(opnd - 2);
} else
|
| ︙ | ︙ | |||
2662 2663 2664 2665 2666 2667 2668 |
} else {
bytes = (char *) Tcl_GetByteArrayFromObj(objResultPtr, &length);
if (length + appendLen < 0) {
/* TODO: convert panic to error ? */
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded",
INT_MAX);
}
| | | 2662 2663 2664 2665 2666 2667 2668 2669 2670 2671 2672 2673 2674 2675 2676 |
} else {
bytes = (char *) Tcl_GetByteArrayFromObj(objResultPtr, &length);
if (length + appendLen < 0) {
/* TODO: convert panic to error ? */
Tcl_Panic("max size for a Tcl value (%d bytes) exceeded",
INT_MAX);
}
#ifndef TCL_COMPILE_DEBUG
if (!Tcl_IsShared(objResultPtr)) {
bytes = (char *) Tcl_SetByteArrayLength(objResultPtr,
length + appendLen);
p = bytes + length;
currPtr = &OBJ_AT_DEPTH(opnd - 2);
} else
#endif
|
| ︙ | ︙ | |||
2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 |
* error, also in INST_EXPAND_STKTOP).
*/
TclNewObj(objPtr);
objPtr->internalRep.ptrAndLongRep.value = CURR_DEPTH;
PUSH_TAUX_OBJ(objPtr);
NEXT_INST_F(1, 0, 0);
case INST_EXPAND_STKTOP: {
int i;
ptrdiff_t moved;
/*
* Make sure that the element at stackTop is a list; if not, just
| > > > > > > > > > > > > > > > > | 2713 2714 2715 2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736 2737 2738 2739 2740 2741 2742 |
* error, also in INST_EXPAND_STKTOP).
*/
TclNewObj(objPtr);
objPtr->internalRep.ptrAndLongRep.value = CURR_DEPTH;
PUSH_TAUX_OBJ(objPtr);
NEXT_INST_F(1, 0, 0);
case INST_EXPAND_DROP:
/*
* Drops an element of the auxObjList, popping stack elements to
* restore the stack to the state before the point where the aux
* element was created.
*/
CLANG_ASSERT(auxObjList);
objc = CURR_DEPTH - auxObjList->internalRep.ptrAndLongRep.value;
POP_TAUX_OBJ();
#ifdef TCL_COMPILE_DEBUG
/* Ugly abuse! */
starting = 1;
#endif
NEXT_INST_V(1, objc, 0);
case INST_EXPAND_STKTOP: {
int i;
ptrdiff_t moved;
/*
* Make sure that the element at stackTop is a list; if not, just
|
| ︙ | ︙ | |||
6820 6821 6822 6823 6824 6825 6826 |
/*
* An external evaluation (INST_INVOKE or INST_EVAL) returned
* something different from TCL_OK, or else INST_BREAK or
* INST_CONTINUE were called.
*/
processExceptionReturn:
| | | 6836 6837 6838 6839 6840 6841 6842 6843 6844 6845 6846 6847 6848 6849 6850 |
/*
* An external evaluation (INST_INVOKE or INST_EVAL) returned
* something different from TCL_OK, or else INST_BREAK or
* INST_CONTINUE were called.
*/
processExceptionReturn:
#ifdef TCL_COMPILE_DEBUG
switch (*pc) {
case INST_INVOKE_STK1:
opnd = TclGetUInt1AtPtr(pc+1);
TRACE(("%u => ... after \"%.20s\": ", opnd, cmdNameBuf));
break;
case INST_INVOKE_STK4:
opnd = TclGetUInt4AtPtr(pc+1);
|
| ︙ | ︙ | |||
6877 6878 6879 6880 6881 6882 6883 |
result = TCL_OK;
pc = (codePtr->codeStart + rangePtr->continueOffset);
TRACE_APPEND(("%s, range at %d, new pc %d\n",
StringForResultCode(result),
rangePtr->codeOffset, rangePtr->continueOffset));
NEXT_INST_F(0, 0, 0);
}
| | | 6893 6894 6895 6896 6897 6898 6899 6900 6901 6902 6903 6904 6905 6906 6907 |
result = TCL_OK;
pc = (codePtr->codeStart + rangePtr->continueOffset);
TRACE_APPEND(("%s, range at %d, new pc %d\n",
StringForResultCode(result),
rangePtr->codeOffset, rangePtr->continueOffset));
NEXT_INST_F(0, 0, 0);
}
#ifdef TCL_COMPILE_DEBUG
if (traceInstructions) {
objPtr = Tcl_GetObjResult(interp);
if ((result != TCL_ERROR) && (result != TCL_RETURN)) {
TRACE_APPEND(("OTHER RETURN CODE %d, result= \"%s\"\n ",
result, O2S(objPtr)));
} else {
TRACE_APPEND(("%s, result= \"%s\"\n",
|
| ︙ | ︙ |
Changes to tests/for.test.
| ︙ | ︙ | |||
850 851 852 853 854 855 856 |
}
set tmp $end
set end [meminfo]
}
expr {$end - $tmp}
}}
} 0
| | | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876 877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 |
}
set tmp $end
set end [meminfo]
}
expr {$end - $tmp}
}}
} 0
test for-7.3 {Bug 3614226: ensure that break cleans up the expansion stack} memory {
apply {{} {
# Can't use [memtest]; must be careful when we change stack frames
set end [meminfo]
for {set i 0} {$i < 5} {incr i} {
for {set x 0} {[incr x]<50} {} {
puts {*}[puts a b c {*}[break] d e f]
}
set tmp $end
set end [meminfo]
}
expr {$end - $tmp}
}}
} 0
test for-7.4 {Bug 3614226: ensure that continue cleans up the expansion stack} memory {
apply {{} {
# Can't use [memtest]; must be careful when we change stack frames
set end [meminfo]
for {set i 0} {$i < 5} {incr i} {
for {set x 0} {[incr x]<50} {} {
puts {*}[puts a b c {*}[continue] d e f]
}
set tmp $end
set end [meminfo]
}
expr {$end - $tmp}
}}
} 0
test for-7.5 {Bug 3614226: ensure that break cleans up the combination of main and expansion stack} memory {
apply {{} {
set l [lrepeat 50 p q r]
# Can't use [memtest]; must be careful when we change stack frames
set end [meminfo]
for {set i 0} {$i < 5} {incr i} {
for {set x 0} {[incr x]<50} {} {
puts [puts {*}$l {*}[puts a b c {*}$l {*}[break] d e f]]
}
set tmp $end
set end [meminfo]
}
expr {$end - $tmp}
}}
} 0
test for-7.6 {Bug 3614226: ensure that continue cleans up the combination of main and expansion stack} memory {
apply {{} {
set l [lrepeat 50 p q r]
# Can't use [memtest]; must be careful when we change stack frames
set end [meminfo]
for {set i 0} {$i < 5} {incr i} {
for {set x 0} {[incr x]<50} {} {
puts [puts {*}$l {*}[puts a b c {*}$l {*}[continue] d e f]]
}
set tmp $end
set end [meminfo]
}
expr {$end - $tmp}
}}
} 0
test for-7.7 {Bug 3614226: ensure that break only cleans up the right amount} memory {
apply {{} {
set l [lrepeat 50 p q r]
# Can't use [memtest]; must be careful when we change stack frames
set end [meminfo]
for {set i 0} {$i < 5} {incr i} {
unset -nocomplain {*}[for {set x 0} {[incr x]<50} {} {
puts [puts {*}$l {*}[puts a b c {*}$l {*}[break] d e f]]
}]
set tmp $end
set end [meminfo]
}
expr {$end - $tmp}
}}
} 0
test for-7.8 {Bug 3614226: ensure that continue only cleans up the right amount} memory {
apply {{} {
set l [lrepeat 50 p q r]
# Can't use [memtest]; must be careful when we change stack frames
set end [meminfo]
for {set i 0} {$i < 5} {incr i} {
unset -nocomplain {*}[for {set x 0} {[incr x]<50} {} {
puts [puts {*}$l {*}[puts a b c {*}$l {*}[continue] d e f]]
}]
set tmp $end
set end [meminfo]
}
expr {$end - $tmp}
}}
} 0
|
| ︙ | ︙ |