[crankshaft] Make infinite loops preserve control flow.

We have to preserve control flow so that the liveness analysis is less
confused. This CL fixes loops to preserve teh original control flow.

BUG=chromium:599710
LOG=n

Review URL: https://codereview.chromium.org/1863123002

Cr-Commit-Position: refs/heads/master@{#35318}
This commit is contained in:
jarin 2016-04-06 22:36:25 -07:00 committed by Commit bot
parent ea61d86f0d
commit 3df0a8c1f2
2 changed files with 71 additions and 17 deletions

View File

@ -5116,7 +5116,7 @@ void HOptimizedGraphBuilder::VisitDoWhileStatement(DoWhileStatement* stmt) {
HBasicBlock* body_exit =
JoinContinue(stmt, current_block(), break_info.continue_block());
HBasicBlock* loop_successor = NULL;
if (body_exit != NULL && !stmt->cond()->ToBooleanIsTrue()) {
if (body_exit != NULL) {
set_current_block(body_exit);
loop_successor = graph()->CreateBasicBlock();
if (stmt->cond()->ToBooleanIsFalse()) {
@ -5158,19 +5158,17 @@ void HOptimizedGraphBuilder::VisitWhileStatement(WhileStatement* stmt) {
// If the condition is constant true, do not generate a branch.
HBasicBlock* loop_successor = NULL;
if (!stmt->cond()->ToBooleanIsTrue()) {
HBasicBlock* body_entry = graph()->CreateBasicBlock();
loop_successor = graph()->CreateBasicBlock();
CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
if (body_entry->HasPredecessor()) {
body_entry->SetJoinId(stmt->BodyId());
set_current_block(body_entry);
}
if (loop_successor->HasPredecessor()) {
loop_successor->SetJoinId(stmt->ExitId());
} else {
loop_successor = NULL;
}
HBasicBlock* body_entry = graph()->CreateBasicBlock();
loop_successor = graph()->CreateBasicBlock();
CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
if (body_entry->HasPredecessor()) {
body_entry->SetJoinId(stmt->BodyId());
set_current_block(body_entry);
}
if (loop_successor->HasPredecessor()) {
loop_successor->SetJoinId(stmt->ExitId());
} else {
loop_successor = NULL;
}
BreakAndContinueInfo break_info(stmt, scope());
@ -5199,10 +5197,9 @@ void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) {
DCHECK(current_block() != NULL);
HBasicBlock* loop_entry = BuildLoopEntry(stmt);
HBasicBlock* loop_successor = NULL;
HBasicBlock* loop_successor = graph()->CreateBasicBlock();
HBasicBlock* body_entry = graph()->CreateBasicBlock();
if (stmt->cond() != NULL) {
HBasicBlock* body_entry = graph()->CreateBasicBlock();
loop_successor = graph()->CreateBasicBlock();
CHECK_BAILOUT(VisitForControl(stmt->cond(), body_entry, loop_successor));
if (body_entry->HasPredecessor()) {
body_entry->SetJoinId(stmt->BodyId());
@ -5213,6 +5210,14 @@ void HOptimizedGraphBuilder::VisitForStatement(ForStatement* stmt) {
} else {
loop_successor = NULL;
}
} else {
// Create dummy control flow so that variable liveness analysis
// produces teh correct result.
HControlInstruction* branch = New<HBranch>(graph()->GetConstantTrue());
branch->SetSuccessorAt(0, body_entry);
branch->SetSuccessorAt(1, loop_successor);
FinishCurrentBlock(branch);
set_current_block(body_entry);
}
BreakAndContinueInfo break_info(stmt, scope());

View File

@ -0,0 +1,49 @@
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Flags: --allow-natives-syntax
var f1 = function() { while (1) { } }
function g1() {
var s = "hey";
f1 = function() { return true; }
if (f1()) { return s; }
}
%OptimizeFunctionOnNextCall(g1);
assertEquals("hey", g1());
var f2 = function() { do { } while (1); }
function g2() {
var s = "hey";
f2 = function() { return true; }
if (f2()) { return s; }
}
%OptimizeFunctionOnNextCall(g2);
assertEquals("hey", g2());
var f3 = function() { for (;;); }
function g3() {
var s = "hey";
f3 = function() { return true; }
if (f3()) { return s; }
}
%OptimizeFunctionOnNextCall(g3);
assertEquals("hey", g3());
var f4 = function() { for (;;); }
function g4() {
var s = "hey";
f4 = function() { return true; }
while (f4()) { return s; }
}
%OptimizeFunctionOnNextCall(g4);
assertEquals("hey", g4());