diff options
author | Lars Knoll <lars.knoll@qt.io> | 2018-09-05 10:27:30 +0200 |
---|---|---|
committer | Lars Knoll <lars.knoll@qt.io> | 2018-09-07 10:31:50 +0000 |
commit | 06e3ff28bb52500ae45f0c174ff8cd746593855c (patch) | |
tree | 81aaedd377354ba9e9e5d90633180af50532251b /src | |
parent | ee3d935a8b45576a237c74fd453fb0810f30f574 (diff) |
Some fixes when unwinding inside for-of loops
This is not perfect yet, as the two regressions in TestExpectations
show, but it's an improvement over the current situation.
Change-Id: I82c0ef0f69619562037c573bea1026abc53c1ab3
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
Diffstat (limited to 'src')
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 40 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilercontrolflow_p.h | 13 |
2 files changed, 28 insertions, 25 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index cbe935c5cd..274917dd0a 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -1134,7 +1134,14 @@ bool Codegen::visit(ArrayPattern *ast) BytecodeGenerator::Label done = bytecodeGenerator->newLabel(); { - ControlFlowLoop flow(this, &end, &in, /*requiresUnwind*/ true); + auto unwind = [this, iterator]() { + Reference iteratorDone = Reference::fromConst(this, Encode(false)).storeOnStack(); + iterator.loadInAccumulator(); + Instruction::IteratorClose close; + close.done = iteratorDone.stackSlot(); + bytecodeGenerator->addInstruction(close); + }; + ControlFlowLoop flow(this, &end, &in, unwind); bytecodeGenerator->jump().link(in); BytecodeGenerator::Label body = bytecodeGenerator->label(); @@ -1149,15 +1156,9 @@ bool Codegen::visit(ArrayPattern *ast) bytecodeGenerator->addInstruction(next); bytecodeGenerator->addJumpInstruction(Instruction::JumpFalse()).link(body); bytecodeGenerator->jump().link(done); - } - - end.link(); - Reference iteratorDone = Reference::fromConst(this, Encode(false)).storeOnStack(); - iterator.loadInAccumulator(); - Instruction::IteratorClose close; - close.done = iteratorDone.stackSlot(); - bytecodeGenerator->addInstruction(close); + end.link(); + } done.link(); } else { @@ -3177,7 +3178,16 @@ bool Codegen::visit(ForEachStatement *ast) BytecodeGenerator::Label done = bytecodeGenerator->newLabel(); { - ControlFlowLoop flow(this, &end, &in, /*requiresUnwind*/ true); + auto unwind = [ast, this, iterator]() { + if (ast->type == ForEachType::Of) { + Reference iteratorDone = Reference::fromConst(this, Encode(false)).storeOnStack(); + iterator.loadInAccumulator(); + Instruction::IteratorClose close; + close.done = iteratorDone.stackSlot(); + bytecodeGenerator->addInstruction(close); + } + }; + ControlFlowLoop flow(this, &end, &in, unwind); bytecodeGenerator->jump().link(in); BytecodeGenerator::Label body = bytecodeGenerator->label(); @@ -3220,16 +3230,8 @@ bool Codegen::visit(ForEachStatement *ast) bytecodeGenerator->addInstruction(next); bytecodeGenerator->addJumpInstruction(Instruction::JumpFalse()).link(body); bytecodeGenerator->jump().link(done); - } - - end.link(); - if (ast->type == ForEachType::Of) { - Reference iteratorDone = Reference::fromConst(this, Encode(false)).storeOnStack(); - iterator.loadInAccumulator(); - Instruction::IteratorClose close; - close.done = iteratorDone.stackSlot(); - bytecodeGenerator->addInstruction(close); + end.link(); } done.link(); diff --git a/src/qml/compiler/qv4compilercontrolflow_p.h b/src/qml/compiler/qv4compilercontrolflow_p.h index 1ef290ea56..1884b33588 100644 --- a/src/qml/compiler/qv4compilercontrolflow_p.h +++ b/src/qml/compiler/qv4compilercontrolflow_p.h @@ -193,27 +193,28 @@ struct ControlFlowLoop : public ControlFlowUnwind QString loopLabel; BytecodeGenerator::Label *breakLabel = nullptr; BytecodeGenerator::Label *continueLabel = nullptr; - bool _requiresUnwind; + std::function<void()> unwind = nullptr; - ControlFlowLoop(Codegen *cg, BytecodeGenerator::Label *breakLabel, BytecodeGenerator::Label *continueLabel = nullptr, bool requiresUnwind = false) - : ControlFlowUnwind(cg, Loop), loopLabel(ControlFlow::loopLabel()), breakLabel(breakLabel), continueLabel(continueLabel), _requiresUnwind(requiresUnwind) + ControlFlowLoop(Codegen *cg, BytecodeGenerator::Label *breakLabel, BytecodeGenerator::Label *continueLabel = nullptr, std::function<void()> unwind = nullptr) + : ControlFlowUnwind(cg, Loop), loopLabel(ControlFlow::loopLabel()), breakLabel(breakLabel), continueLabel(continueLabel), unwind(unwind) { - if (_requiresUnwind) { + if (unwind != nullptr) { setupUnwindHandler(); generator()->setUnwindHandler(&unwindLabel); } } ~ControlFlowLoop() { - if (_requiresUnwind) { + if (unwind != nullptr) { unwindLabel.link(); generator()->setUnwindHandler(parentUnwindHandler()); + unwind(); emitUnwindHandler(); } } bool requiresUnwind() override { - return _requiresUnwind; + return unwind != nullptr; } BytecodeGenerator::Label getUnwindTarget(UnwindType type, const QString &label) override { |