[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:
parent
ea61d86f0d
commit
3df0a8c1f2
@ -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());
|
||||
|
49
test/mjsunit/regress/regress-599710.js
Normal file
49
test/mjsunit/regress/regress-599710.js
Normal 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());
|
Loading…
Reference in New Issue
Block a user