aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler/qv4codegen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/compiler/qv4codegen.cpp')
-rw-r--r--src/qml/compiler/qv4codegen.cpp97
1 files changed, 49 insertions, 48 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp
index 274917dd0a..1d6e8819f5 100644
--- a/src/qml/compiler/qv4codegen.cpp
+++ b/src/qml/compiler/qv4codegen.cpp
@@ -638,6 +638,7 @@ void Codegen::destructureElementList(const Codegen::Reference &array, PatternEle
Reference iterator = Reference::fromStackSlot(this);
Reference iteratorValue = Reference::fromStackSlot(this);
Reference iteratorDone = Reference::fromStackSlot(this);
+ Reference::storeConstOnStack(this, Encode(false), iteratorDone.stackSlot());
array.loadInAccumulator();
Instruction::GetIterator iteratorObjInstr;
@@ -645,60 +646,58 @@ void Codegen::destructureElementList(const Codegen::Reference &array, PatternEle
bytecodeGenerator->addInstruction(iteratorObjInstr);
iterator.storeConsumeAccumulator();
- bool hadNext = false;
bool hasRest = false;
BytecodeGenerator::Label end = bytecodeGenerator->newLabel();
-
- for (PatternElementList *p = bindingList; p; p = p->next) {
- PatternElement *e = p->element;
- for (Elision *elision = p->elision; elision; elision = elision->next) {
+ {
+ auto cleanup = [this, iterator, iteratorDone]() {
iterator.loadInAccumulator();
- Instruction::IteratorNext next;
- next.value = iteratorValue.stackSlot();
- bytecodeGenerator->addInstruction(next);
- hadNext = true;
- bool last = !elision->next && !e && !p->next;
- if (last)
- iteratorDone.storeConsumeAccumulator();
- }
+ Instruction::IteratorClose close;
+ close.done = iteratorDone.stackSlot();
+ bytecodeGenerator->addInstruction(close);
+ };
- if (!e)
- continue;
+ ControlFlowUnwindCleanup flow(this, cleanup);
- hadNext = true;
- RegisterScope scope(this);
- iterator.loadInAccumulator();
+ for (PatternElementList *p = bindingList; p; p = p->next) {
+ PatternElement *e = p->element;
+ for (Elision *elision = p->elision; elision; elision = elision->next) {
+ iterator.loadInAccumulator();
+ Instruction::IteratorNext next;
+ next.value = iteratorValue.stackSlot();
+ next.done = iteratorDone.stackSlot();
+ bytecodeGenerator->addInstruction(next);
+ }
- if (e->type == PatternElement::RestElement) {
- bytecodeGenerator->addInstruction(Instruction::DestructureRestElement());
- initializeAndDestructureBindingElement(e, Reference::fromAccumulator(this), isDefinition);
- hasRest = true;
- } else {
- Instruction::IteratorNext next;
- next.value = iteratorValue.stackSlot();
- bytecodeGenerator->addInstruction(next);
- bool last = !p->next || (!p->next->elision && !p->next->element);
- if (last)
- iteratorDone.storeConsumeAccumulator();
- initializeAndDestructureBindingElement(e, iteratorValue, isDefinition);
- if (hasError) {
- end.link();
- return;
+ if (!e)
+ continue;
+
+ RegisterScope scope(this);
+ iterator.loadInAccumulator();
+
+ if (e->type == PatternElement::RestElement) {
+ Reference::fromConst(this, Encode(true)).storeOnStack(iteratorDone.stackSlot());
+ bytecodeGenerator->addInstruction(Instruction::DestructureRestElement());
+ initializeAndDestructureBindingElement(e, Reference::fromAccumulator(this), isDefinition);
+ hasRest = true;
+ } else {
+ Instruction::IteratorNext next;
+ next.value = iteratorValue.stackSlot();
+ next.done = iteratorDone.stackSlot();
+ bytecodeGenerator->addInstruction(next);
+ initializeAndDestructureBindingElement(e, iteratorValue, isDefinition);
+ if (hasError) {
+ end.link();
+ return;
+ }
}
}
- }
- if (!hadNext) {
- Reference::storeConstOnStack(this, Encode(false), iteratorDone.stackSlot());
+ if (hasRest)
+ // no need to close the iterator
+ bytecodeGenerator->jump().link(end);
}
- if (!hasRest) {
- iterator.loadInAccumulator();
- Instruction::IteratorClose close;
- close.done = iteratorDone.stackSlot();
- bytecodeGenerator->addInstruction(close);
- }
end.link();
}
@@ -1112,6 +1111,7 @@ bool Codegen::visit(ArrayPattern *ast)
RegisterScope scope(this);
Reference iterator = Reference::fromStackSlot(this);
+ Reference iteratorDone = Reference::fromConst(this, Encode(false)).storeOnStack();
Reference lhsValue = Reference::fromStackSlot(this);
// There should be a temporal block, so that variables declared in lhs shadow outside vars.
@@ -1134,14 +1134,13 @@ bool Codegen::visit(ArrayPattern *ast)
BytecodeGenerator::Label done = bytecodeGenerator->newLabel();
{
- auto unwind = [this, iterator]() {
- Reference iteratorDone = Reference::fromConst(this, Encode(false)).storeOnStack();
+ auto cleanup = [this, iterator, iteratorDone]() {
iterator.loadInAccumulator();
Instruction::IteratorClose close;
close.done = iteratorDone.stackSlot();
bytecodeGenerator->addInstruction(close);
};
- ControlFlowLoop flow(this, &end, &in, unwind);
+ ControlFlowLoop flow(this, &end, &in, cleanup);
bytecodeGenerator->jump().link(in);
BytecodeGenerator::Label body = bytecodeGenerator->label();
@@ -1153,6 +1152,7 @@ bool Codegen::visit(ArrayPattern *ast)
iterator.loadInAccumulator();
Instruction::IteratorNext next;
next.value = lhsValue.stackSlot();
+ next.done = iteratorDone.stackSlot();
bytecodeGenerator->addInstruction(next);
bytecodeGenerator->addJumpInstruction(Instruction::JumpFalse()).link(body);
bytecodeGenerator->jump().link(done);
@@ -3155,6 +3155,7 @@ bool Codegen::visit(ForEachStatement *ast)
RegisterScope scope(this);
Reference iterator = Reference::fromStackSlot(this);
+ Reference iteratorDone = Reference::fromConst(this, Encode(false)).storeOnStack();
Reference lhsValue = Reference::fromStackSlot(this);
// There should be a temporal block, so that variables declared in lhs shadow outside vars.
@@ -3178,16 +3179,15 @@ bool Codegen::visit(ForEachStatement *ast)
BytecodeGenerator::Label done = bytecodeGenerator->newLabel();
{
- auto unwind = [ast, this, iterator]() {
+ auto cleanup = [ast, iterator, iteratorDone, this]() {
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);
+ ControlFlowLoop flow(this, &end, &in, cleanup);
bytecodeGenerator->jump().link(in);
BytecodeGenerator::Label body = bytecodeGenerator->label();
@@ -3227,6 +3227,7 @@ bool Codegen::visit(ForEachStatement *ast)
iterator.loadInAccumulator();
Instruction::IteratorNext next;
next.value = lhsValue.stackSlot();
+ next.done = iteratorDone.stackSlot();
bytecodeGenerator->addInstruction(next);
bytecodeGenerator->addJumpInstruction(Instruction::JumpFalse()).link(body);
bytecodeGenerator->jump().link(done);