Commit ca5aa3c8 authored by neis's avatar neis Committed by Commit bot

[interpreter] Always 'continue' loops by jumping forward to end of body.

We sometimes used to continue by jumping _back_ to the condition check at the
top of the loop. After my recent generator-related changes, that check is no
longer at the loop header, so a continue could create an additional loop. In
order to avoid this, we now always set the continue target to be the first
instruction following the loop body.

BUG=

Review-Url: https://codereview.chromium.org/1943383003
Cr-Commit-Position: refs/heads/master@{#36029}
parent 88877e55
...@@ -1038,6 +1038,7 @@ void BytecodeGenerator::VisitIterationBody(IterationStatement* stmt, ...@@ -1038,6 +1038,7 @@ void BytecodeGenerator::VisitIterationBody(IterationStatement* stmt,
ControlScopeForIteration execution_control(this, stmt, loop_builder); ControlScopeForIteration execution_control(this, stmt, loop_builder);
builder()->StackCheck(stmt->position()); builder()->StackCheck(stmt->position());
Visit(stmt->body()); Visit(stmt->body());
loop_builder->SetContinueTarget();
} }
void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
...@@ -1045,14 +1046,11 @@ void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) { ...@@ -1045,14 +1046,11 @@ void BytecodeGenerator::VisitDoWhileStatement(DoWhileStatement* stmt) {
VisitIterationHeader(stmt, &loop_builder); VisitIterationHeader(stmt, &loop_builder);
if (stmt->cond()->ToBooleanIsFalse()) { if (stmt->cond()->ToBooleanIsFalse()) {
VisitIterationBody(stmt, &loop_builder); VisitIterationBody(stmt, &loop_builder);
loop_builder.Condition();
} else if (stmt->cond()->ToBooleanIsTrue()) { } else if (stmt->cond()->ToBooleanIsTrue()) {
loop_builder.Condition();
VisitIterationBody(stmt, &loop_builder); VisitIterationBody(stmt, &loop_builder);
loop_builder.JumpToHeader(); loop_builder.JumpToHeader();
} else { } else {
VisitIterationBody(stmt, &loop_builder); VisitIterationBody(stmt, &loop_builder);
loop_builder.Condition();
builder()->SetExpressionAsStatementPosition(stmt->cond()); builder()->SetExpressionAsStatementPosition(stmt->cond());
VisitForAccumulatorValue(stmt->cond()); VisitForAccumulatorValue(stmt->cond());
loop_builder.JumpToHeaderIfTrue(); loop_builder.JumpToHeaderIfTrue();
...@@ -1068,7 +1066,6 @@ void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) { ...@@ -1068,7 +1066,6 @@ void BytecodeGenerator::VisitWhileStatement(WhileStatement* stmt) {
LoopBuilder loop_builder(builder()); LoopBuilder loop_builder(builder());
VisitIterationHeader(stmt, &loop_builder); VisitIterationHeader(stmt, &loop_builder);
loop_builder.Condition();
if (!stmt->cond()->ToBooleanIsTrue()) { if (!stmt->cond()->ToBooleanIsTrue()) {
builder()->SetExpressionAsStatementPosition(stmt->cond()); builder()->SetExpressionAsStatementPosition(stmt->cond());
VisitForAccumulatorValue(stmt->cond()); VisitForAccumulatorValue(stmt->cond());
...@@ -1092,7 +1089,6 @@ void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { ...@@ -1092,7 +1089,6 @@ void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
LoopBuilder loop_builder(builder()); LoopBuilder loop_builder(builder());
VisitIterationHeader(stmt, &loop_builder); VisitIterationHeader(stmt, &loop_builder);
loop_builder.Condition();
if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) { if (stmt->cond() && !stmt->cond()->ToBooleanIsTrue()) {
builder()->SetExpressionAsStatementPosition(stmt->cond()); builder()->SetExpressionAsStatementPosition(stmt->cond());
VisitForAccumulatorValue(stmt->cond()); VisitForAccumulatorValue(stmt->cond());
...@@ -1100,7 +1096,6 @@ void BytecodeGenerator::VisitForStatement(ForStatement* stmt) { ...@@ -1100,7 +1096,6 @@ void BytecodeGenerator::VisitForStatement(ForStatement* stmt) {
} }
VisitIterationBody(stmt, &loop_builder); VisitIterationBody(stmt, &loop_builder);
if (stmt->next() != nullptr) { if (stmt->next() != nullptr) {
loop_builder.Next();
builder()->SetStatementPosition(stmt->next()); builder()->SetStatementPosition(stmt->next());
Visit(stmt->next()); Visit(stmt->next());
} }
...@@ -1218,7 +1213,6 @@ void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { ...@@ -1218,7 +1213,6 @@ void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
// The loop // The loop
VisitIterationHeader(stmt, &loop_builder); VisitIterationHeader(stmt, &loop_builder);
builder()->SetExpressionAsStatementPosition(stmt->each()); builder()->SetExpressionAsStatementPosition(stmt->each());
loop_builder.Condition();
builder()->ForInDone(index, cache_length); builder()->ForInDone(index, cache_length);
loop_builder.BreakIfTrue(); loop_builder.BreakIfTrue();
DCHECK(Register::AreContiguous(cache_type, cache_array)); DCHECK(Register::AreContiguous(cache_type, cache_array));
...@@ -1227,7 +1221,6 @@ void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) { ...@@ -1227,7 +1221,6 @@ void BytecodeGenerator::VisitForInStatement(ForInStatement* stmt) {
loop_builder.ContinueIfUndefined(); loop_builder.ContinueIfUndefined();
VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot()); VisitForInAssignment(stmt->each(), stmt->EachFeedbackSlot());
VisitIterationBody(stmt, &loop_builder); VisitIterationBody(stmt, &loop_builder);
loop_builder.Next();
builder()->ForInStep(index); builder()->ForInStep(index);
builder()->StoreAccumulatorInRegister(index); builder()->StoreAccumulatorInRegister(index);
loop_builder.JumpToHeader(); loop_builder.JumpToHeader();
...@@ -1245,7 +1238,6 @@ void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) { ...@@ -1245,7 +1238,6 @@ void BytecodeGenerator::VisitForOfStatement(ForOfStatement* stmt) {
VisitForEffect(stmt->assign_iterator()); VisitForEffect(stmt->assign_iterator());
VisitIterationHeader(stmt, &loop_builder); VisitIterationHeader(stmt, &loop_builder);
loop_builder.Next();
builder()->SetExpressionAsStatementPosition(stmt->next_result()); builder()->SetExpressionAsStatementPosition(stmt->next_result());
VisitForEffect(stmt->next_result()); VisitForEffect(stmt->next_result());
VisitForAccumulatorValue(stmt->result_done()); VisitForAccumulatorValue(stmt->result_done());
......
...@@ -109,19 +109,11 @@ void LoopBuilder::EndLoop() { ...@@ -109,19 +109,11 @@ void LoopBuilder::EndLoop() {
DCHECK(loop_header_.is_bound()); DCHECK(loop_header_.is_bound());
builder()->Bind(&loop_end_); builder()->Bind(&loop_end_);
SetBreakTarget(loop_end_); SetBreakTarget(loop_end_);
if (next_.is_bound()) {
DCHECK(!condition_.is_bound() || next_.offset() >= condition_.offset());
SetContinueTarget(next_);
} else {
DCHECK(condition_.is_bound());
DCHECK_GE(condition_.offset(), loop_header_.offset());
DCHECK_LE(condition_.offset(), loop_end_.offset());
SetContinueTarget(condition_);
}
} }
void LoopBuilder::SetContinueTarget() {
void LoopBuilder::SetContinueTarget(const BytecodeLabel& target) { BytecodeLabel target;
builder()->Bind(&target);
BindLabels(target, &continue_sites_); BindLabels(target, &continue_sites_);
} }
......
...@@ -88,26 +88,21 @@ class LoopBuilder final : public BreakableControlFlowBuilder { ...@@ -88,26 +88,21 @@ class LoopBuilder final : public BreakableControlFlowBuilder {
~LoopBuilder(); ~LoopBuilder();
void LoopHeader(ZoneVector<BytecodeLabel>* additional_labels); void LoopHeader(ZoneVector<BytecodeLabel>* additional_labels);
void Condition() { builder()->Bind(&condition_); }
void Next() { builder()->Bind(&next_); }
void JumpToHeader() { builder()->Jump(&loop_header_); } void JumpToHeader() { builder()->Jump(&loop_header_); }
void JumpToHeaderIfTrue() { builder()->JumpIfTrue(&loop_header_); } void JumpToHeaderIfTrue() { builder()->JumpIfTrue(&loop_header_); }
void SetContinueTarget();
void EndLoop(); void EndLoop();
// This method is called when visiting continue statements in the AST. // This method is called when visiting continue statements in the AST.
// Inserts a jump to a unbound label that is patched when the corresponding // Inserts a jump to an unbound label that is patched when SetContinueTarget
// SetContinueTarget is called. // is called.
void Continue() { EmitJump(&continue_sites_); } void Continue() { EmitJump(&continue_sites_); }
void ContinueIfTrue() { EmitJumpIfTrue(&continue_sites_); } void ContinueIfTrue() { EmitJumpIfTrue(&continue_sites_); }
void ContinueIfUndefined() { EmitJumpIfUndefined(&continue_sites_); } void ContinueIfUndefined() { EmitJumpIfUndefined(&continue_sites_); }
void ContinueIfNull() { EmitJumpIfNull(&continue_sites_); } void ContinueIfNull() { EmitJumpIfNull(&continue_sites_); }
private: private:
void SetContinueTarget(const BytecodeLabel& continue_target);
BytecodeLabel loop_header_; BytecodeLabel loop_header_;
BytecodeLabel condition_;
BytecodeLabel next_;
BytecodeLabel loop_end_; BytecodeLabel loop_end_;
// Unbound labels that identify jumps for continue statements in the code. // Unbound labels that identify jumps for continue statements in the code.
......
...@@ -90,7 +90,7 @@ bytecodes: [ ...@@ -90,7 +90,7 @@ bytecodes: [
B(LdaSmi), U8(3), B(LdaSmi), U8(3),
B(TestEqual), R(2), B(TestEqual), R(2),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(-39), B(Jump), U8(14),
B(Ldar), R(0), B(Ldar), R(0),
B(Star), R(2), B(Star), R(2),
B(LdaSmi), U8(4), B(LdaSmi), U8(4),
...@@ -132,7 +132,7 @@ bytecodes: [ ...@@ -132,7 +132,7 @@ bytecodes: [
B(LdaZero), B(LdaZero),
B(TestLessThan), R(1), B(TestLessThan), R(1),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(-10), B(Jump), U8(60),
B(Ldar), R(0), B(Ldar), R(0),
B(Star), R(1), B(Star), R(1),
B(LdaSmi), U8(3), B(LdaSmi), U8(3),
...@@ -150,7 +150,7 @@ bytecodes: [ ...@@ -150,7 +150,7 @@ bytecodes: [
B(LdaSmi), U8(10), B(LdaSmi), U8(10),
B(TestEqual), R(1), B(TestEqual), R(1),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(-46), B(Jump), U8(24),
B(Ldar), R(0), B(Ldar), R(0),
B(Star), R(1), B(Star), R(1),
B(LdaSmi), U8(5), B(LdaSmi), U8(5),
...@@ -453,7 +453,7 @@ bytecodes: [ ...@@ -453,7 +453,7 @@ bytecodes: [
B(LdaSmi), U8(6), B(LdaSmi), U8(6),
B(TestEqual), R(2), B(TestEqual), R(2),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(-41), B(Jump), U8(2),
B(Jump), U8(-43), B(Jump), U8(-43),
B(Ldar), R(1), B(Ldar), R(1),
B(Return), B(Return),
...@@ -491,7 +491,7 @@ bytecodes: [ ...@@ -491,7 +491,7 @@ bytecodes: [
B(LdaSmi), U8(2), B(LdaSmi), U8(2),
B(TestEqual), R(1), B(TestEqual), R(1),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(-23), B(Jump), U8(12),
B(Ldar), R(0), B(Ldar), R(0),
B(Star), R(1), B(Star), R(1),
B(LdaSmi), U8(1), B(LdaSmi), U8(1),
...@@ -533,7 +533,7 @@ bytecodes: [ ...@@ -533,7 +533,7 @@ bytecodes: [
B(LdaSmi), U8(2), B(LdaSmi), U8(2),
B(TestEqual), R(1), B(TestEqual), R(1),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(-23), B(Jump), U8(12),
B(Ldar), R(0), B(Ldar), R(0),
B(Star), R(1), B(Star), R(1),
B(LdaSmi), U8(1), B(LdaSmi), U8(1),
...@@ -825,7 +825,7 @@ bytecodes: [ ...@@ -825,7 +825,7 @@ bytecodes: [
B(JumpIfToBooleanFalse), U8(8), B(JumpIfToBooleanFalse), U8(8),
B(PopContext), R(3), B(PopContext), R(3),
B(PopContext), R(3), B(PopContext), R(3),
B(Jump), U8(-69), B(Jump), U8(43),
B(LdaContextSlot), R(context), U8(4), B(LdaContextSlot), R(context), U8(4),
B(JumpIfNotHole), U8(11), B(JumpIfNotHole), U8(11),
B(LdaConstant), U8(3), B(LdaConstant), U8(3),
......
...@@ -429,7 +429,7 @@ bytecodes: [ ...@@ -429,7 +429,7 @@ bytecodes: [
B(LdaSmi), U8(10), B(LdaSmi), U8(10),
B(TestEqual), R(13), B(TestEqual), R(13),
B(JumpIfFalse), U8(4), B(JumpIfFalse), U8(4),
B(Jump), U8(-75), B(Jump), U8(17),
B(Ldar), R(7), B(Ldar), R(7),
B(Star), R(13), B(Star), R(13),
B(LdaSmi), U8(20), B(LdaSmi), U8(20),
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment