aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorErik Verbruggen <erik.verbruggen@qt.io>2019-01-25 14:18:30 +0100
committerErik Verbruggen <erik.verbruggen@qt.io>2019-01-31 14:32:29 +0000
commit205f836e5d976a983638dd2969077a9e24c1c4fd (patch)
tree623a7f053cc5bd45884ef181a799e85da91054e3 /src
parenta8729cf143a79b274c002166476c54dc152c6679 (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')
-rw-r--r--src/qml/compiler/qv4codegen.cpp7
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;
}