diff options
author | dkf <donal.k.fellows@manchester.ac.uk> | 2013-10-20 18:15:08 (GMT) |
---|---|---|
committer | dkf <donal.k.fellows@manchester.ac.uk> | 2013-10-20 18:15:08 (GMT) |
commit | ff83c9993b14e1a40c0003bbda71dbbf2fe79a98 (patch) | |
tree | 0733388d31d6723b8dbe3d4f2976ef2178516cae /generic/tclOptimize.c | |
parent | 6df7d9226ad0c3c3721e54bcb2d7a4b9fe914b93 (diff) | |
parent | 39e314ad912cdbd29ba3e01673b1097b40118f8b (diff) | |
download | tcl-ff83c9993b14e1a40c0003bbda71dbbf2fe79a98.zip tcl-ff83c9993b14e1a40c0003bbda71dbbf2fe79a98.tar.gz tcl-ff83c9993b14e1a40c0003bbda71dbbf2fe79a98.tar.bz2 |
[2835313] Ensure correct stack balance when break and continue exceptions are about: the hard cases with potential concealed exception generation.
Diffstat (limited to 'generic/tclOptimize.c')
-rw-r--r-- | generic/tclOptimize.c | 18 |
1 files changed, 17 insertions, 1 deletions
diff --git a/generic/tclOptimize.c b/generic/tclOptimize.c index b7f4173..3b16e6e 100644 --- a/generic/tclOptimize.c +++ b/generic/tclOptimize.c @@ -344,21 +344,28 @@ AdvanceJumps( CompileEnv *envPtr) { unsigned char *currentInstPtr; + Tcl_HashTable jumps; for (currentInstPtr = envPtr->codeStart ; currentInstPtr < envPtr->codeNext-1 ; currentInstPtr += AddrLength(currentInstPtr)) { - int offset, delta; + int offset, delta, isNew; switch (*currentInstPtr) { case INST_JUMP1: case INST_JUMP_TRUE1: case INST_JUMP_FALSE1: offset = TclGetInt1AtPtr(currentInstPtr + 1); + Tcl_InitHashTable(&jumps, TCL_ONE_WORD_KEYS); for (delta=0 ; offset+delta != 0 ;) { if (offset + delta < -128 || offset + delta > 127) { break; } + Tcl_CreateHashEntry(&jumps, INT2PTR(offset), &isNew); + if (!isNew) { + offset = TclGetInt1AtPtr(currentInstPtr + 1); + break; + } offset += delta; switch (*(currentInstPtr + offset)) { case INST_NOP: @@ -373,13 +380,21 @@ AdvanceJumps( } break; } + Tcl_DeleteHashTable(&jumps); TclStoreInt1AtPtr(offset, currentInstPtr + 1); continue; case INST_JUMP4: case INST_JUMP_TRUE4: case INST_JUMP_FALSE4: + Tcl_InitHashTable(&jumps, TCL_ONE_WORD_KEYS); + Tcl_CreateHashEntry(&jumps, INT2PTR(0), &isNew); for (offset = TclGetInt4AtPtr(currentInstPtr + 1); offset!=0 ;) { + Tcl_CreateHashEntry(&jumps, INT2PTR(offset), &isNew); + if (!isNew) { + offset = TclGetInt4AtPtr(currentInstPtr + 1); + break; + } switch (*(currentInstPtr + offset)) { case INST_NOP: offset += InstLength(INST_NOP); @@ -393,6 +408,7 @@ AdvanceJumps( } break; } + Tcl_DeleteHashTable(&jumps); TclStoreInt4AtPtr(offset, currentInstPtr + 1); continue; } |