aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-09-05 10:27:30 +0200
committerLars Knoll <lars.knoll@qt.io>2018-09-07 10:31:50 +0000
commit06e3ff28bb52500ae45f0c174ff8cd746593855c (patch)
tree81aaedd377354ba9e9e5d90633180af50532251b /src
parentee3d935a8b45576a237c74fd453fb0810f30f574 (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.cpp40
-rw-r--r--src/qml/compiler/qv4compilercontrolflow_p.h13
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 {