diff options
author | Erik Verbruggen <erik.verbruggen@qt.io> | 2019-01-25 14:18:30 +0100 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@qt.io> | 2019-01-31 14:32:29 +0000 |
commit | 205f836e5d976a983638dd2969077a9e24c1c4fd (patch) | |
tree | 623a7f053cc5bd45884ef181a799e85da91054e3 /src/qml/compiler | |
parent | a8729cf143a79b274c002166476c54dc152c6679 (diff) |
V4: Fix unwind handler reset after for-in loop
Consider this JavaScript snippet:
function f() {
for (var i in []) {}
}
This generates the following bytecode sequence:
2 0: 14 00 09 MoveConst r3, C0
3: ec 00 00 DefineArray (function), 0
6: da 00 GetIterator 0
8: 18 08 StoreReg r2
10: c0 0f SetUnwindHandler 27
12: 50 04 Jump 18
14: 16 0a LoadReg r4
16: 18 07 StoreReg r1
3 18: 16 08 LoadReg r2
20: dc 0a 09 IteratorNext r4, r3
23: 54 f5 JumpFalse 14
25: 50 03 Jump 30
27: c0 00 SetUnwindHandler <null>
29: c2 UnwindDispatch
4 30: 0e LoadUndefined
31: 02 Ret
The problem is a normal loop exit: instruction 23 will not jump back,
but fall through, and then instruction 25 will jump over the
instructions resetting the unwind handler (27 + 29). Removing this jump
fixes the issue.
Change-Id: Ic9f03555ebebc27144490bce04e9a4166ed7c97c
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 7 |
1 files changed, 2 insertions, 5 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 0696cb4a3a..fb3c66b123 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -3339,7 +3339,6 @@ bool Codegen::visit(ForEachStatement *ast) BytecodeGenerator::Label in = bytecodeGenerator->newLabel(); BytecodeGenerator::Label end = bytecodeGenerator->newLabel(); - BytecodeGenerator::Label done = bytecodeGenerator->newLabel(); { auto cleanup = [ast, iterator, iteratorDone, this]() { @@ -3397,13 +3396,11 @@ bool Codegen::visit(ForEachStatement *ast) next.done = iteratorDone.stackSlot(); bytecodeGenerator->addInstruction(next); bytecodeGenerator->addJumpInstruction(Instruction::JumpFalse()).link(body); - bytecodeGenerator->jump().link(done); - end.link(); + // all execution paths need to end up here (normal loop exit, break, and exceptions) in + // order to reset the unwind handler, and to close the iterator in calse of an for-of loop. } - done.link(); - return false; } |