diff options
author | Erik Verbruggen <erik.verbruggen@qt.io> | 2019-02-25 12:09:07 +0100 |
---|---|---|
committer | Erik Verbruggen <erik.verbruggen@qt.io> | 2019-03-01 14:33:36 +0000 |
commit | 0b9bef199114232f493131a123a1d4559988bc65 (patch) | |
tree | 45b3aaa1f5a71625229bea61965a8010f9602704 /src/qml/compiler | |
parent | 1ede9c24d08efcb8c2f711db100f3a5cb779452c (diff) |
V4: Undo rotation of the do-while loop
Previously the generated code looked like this:
Jump loop-body
loop-condition:
acc = condition
JumpFalse loop-end
loop-body:
...
Jump loop-condition
loop end:
...
This is a problem for anything that analyzes the bytecode in 1 pass from
top to bottom: at the point of the loop-condition the state of the
interpreter isn't known yet: that state will only be known after
analyzing the loop body. The new generated code does not have that
problem:
loop-body:
...
acc = condition
JumpTrue loop-body
loop-end:
...
Change-Id: I16977e9ce1f9377e7bf4d09afc16136ba0111463
Reviewed-by: Ulf Hermann <ulf.hermann@qt.io>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 24 |
1 files changed, 14 insertions, 10 deletions
diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 56ff15a78c..fcd93bb600 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -3246,22 +3246,26 @@ bool Codegen::visit(DoWhileStatement *ast) BytecodeGenerator::Label end = bytecodeGenerator->newLabel(); ControlFlowLoop flow(this, &end, &cond); - bytecodeGenerator->jump().link(body); - cond.link(); - bytecodeGenerator->addLoopStart(cond); - - if (!AST::cast<TrueLiteral *>(ast->expression)) { - TailCallBlocker blockTailCalls(this); - condition(ast->expression, &body, &end, true); - } + // special case that is not a loop: + // do {...} while (false) + if (!AST::cast<FalseLiteral *>(ast->expression)) + bytecodeGenerator->addLoopStart(body); body.link(); statement(ast->statement); setJumpOutLocation(bytecodeGenerator, ast->statement, ast->semicolonToken); - if (!AST::cast<FalseLiteral *>(ast->expression)) - bytecodeGenerator->jump().link(cond); + cond.link(); + if (AST::cast<TrueLiteral *>(ast->expression)) { + // do {} while (true) -> just jump back to the loop body, no need to generate a condition + bytecodeGenerator->jump().link(body); + } else if (AST::cast<FalseLiteral *>(ast->expression)) { + // do {} while (false) -> fall through, no need to generate a condition + } else { + TailCallBlocker blockTailCalls(this); + condition(ast->expression, &body, &end, false); + } end.link(); |