Index: src/compiler/bytecode-graph-builder.cc |
diff --git a/src/compiler/bytecode-graph-builder.cc b/src/compiler/bytecode-graph-builder.cc |
index 12a5d29d21770df1c39b691df66c3654c3f27946..d522419c2155103281491453dad8fd769ef7ccde 100644 |
--- a/src/compiler/bytecode-graph-builder.cc |
+++ b/src/compiler/bytecode-graph-builder.cc |
@@ -68,17 +68,16 @@ class BytecodeGraphBuilder::Environment : public ZoneObject { |
Node* Context() const { return context_; } |
void SetContext(Node* new_context) { context_ = new_context; } |
- Environment* CopyForConditional(); |
- Environment* CopyForLoop(); |
- Environment* CopyForOsrEntry(); |
+ Environment* Copy(); |
void Merge(Environment* other); |
- void PrepareForOsrEntry(); |
- void PrepareForLoopExit(Node* loop); |
+ void PrepareForOsrEntry(); |
+ void PrepareForLoop(const BytecodeLoopAssignments& assignments); |
+ void PrepareForLoopExit(Node* loop, |
+ const BytecodeLoopAssignments& assignments); |
private: |
explicit Environment(const Environment* copy); |
- void PrepareForLoop(); |
bool StateValuesRequireUpdate(Node** state_values, Node** values, int count); |
void UpdateStateValues(Node** state_values, Node** values, int count); |
@@ -250,20 +249,7 @@ void BytecodeGraphBuilder::Environment::RecordAfterState( |
} |
} |
- |
-BytecodeGraphBuilder::Environment* |
-BytecodeGraphBuilder::Environment::CopyForLoop() { |
- PrepareForLoop(); |
- return new (zone()) Environment(this); |
-} |
- |
-BytecodeGraphBuilder::Environment* |
-BytecodeGraphBuilder::Environment::CopyForOsrEntry() { |
- return new (zone()) Environment(this); |
-} |
- |
-BytecodeGraphBuilder::Environment* |
-BytecodeGraphBuilder::Environment::CopyForConditional() { |
+BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::Environment::Copy() { |
return new (zone()) Environment(this); |
} |
@@ -290,8 +276,8 @@ void BytecodeGraphBuilder::Environment::Merge( |
} |
} |
- |
-void BytecodeGraphBuilder::Environment::PrepareForLoop() { |
+void BytecodeGraphBuilder::Environment::PrepareForLoop( |
+ const BytecodeLoopAssignments& assignments) { |
// Create a control node for the loop header. |
Node* control = builder()->NewLoop(); |
@@ -299,11 +285,23 @@ void BytecodeGraphBuilder::Environment::PrepareForLoop() { |
Node* effect = builder()->NewEffectPhi(1, GetEffectDependency(), control); |
UpdateEffectDependency(effect); |
- // Assume everything in the loop is updated. |
+ // Create Phis for any values that may be updated by the end of the loop. |
context_ = builder()->NewPhi(1, context_, control); |
- int size = static_cast<int>(values()->size()); |
- for (int i = 0; i < size; i++) { |
- values()->at(i) = builder()->NewPhi(1, values()->at(i), control); |
+ for (int i = 0; i < parameter_count(); i++) { |
+ if (assignments.ContainsParameter(i)) { |
+ values_[i] = builder()->NewPhi(1, values_[i], control); |
+ } |
+ } |
+ for (int i = 0; i < register_count(); i++) { |
+ if (assignments.ContainsLocal(i)) { |
+ int index = register_base() + i; |
+ values_[index] = builder()->NewPhi(1, values_[index], control); |
+ } |
+ } |
+ |
+ if (assignments.ContainsAccumulator()) { |
+ values_[accumulator_base()] = |
+ builder()->NewPhi(1, values_[accumulator_base()], control); |
} |
// Connect to the loop end. |
@@ -368,7 +366,8 @@ bool BytecodeGraphBuilder::Environment::StateValuesRequireUpdate( |
return false; |
} |
-void BytecodeGraphBuilder::Environment::PrepareForLoopExit(Node* loop) { |
+void BytecodeGraphBuilder::Environment::PrepareForLoopExit( |
+ Node* loop, const BytecodeLoopAssignments& assignments) { |
DCHECK_EQ(loop->opcode(), IrOpcode::kLoop); |
Node* control = GetControlDependency(); |
@@ -382,15 +381,30 @@ void BytecodeGraphBuilder::Environment::PrepareForLoopExit(Node* loop) { |
GetEffectDependency(), loop_exit); |
UpdateEffectDependency(effect_rename); |
- // TODO(jarin) We should also rename context here. However, uncoditional |
+ // TODO(jarin) We should also rename context here. However, unconditional |
// renaming confuses global object and native context specialization. |
// We should only rename if the context is assigned in the loop. |
- // Rename the environmnent values. |
- for (size_t i = 0; i < values_.size(); i++) { |
- Node* rename = |
- graph()->NewNode(common()->LoopExitValue(), values_[i], loop_exit); |
- values_[i] = rename; |
+ // Rename the environment values if they were assigned in the loop. |
+ for (int i = 0; i < parameter_count(); i++) { |
+ if (assignments.ContainsParameter(i)) { |
+ Node* rename = |
+ graph()->NewNode(common()->LoopExitValue(), values_[i], loop_exit); |
+ values_[i] = rename; |
+ } |
+ } |
+ for (int i = 0; i < register_count(); i++) { |
+ if (assignments.ContainsLocal(i)) { |
+ Node* rename = graph()->NewNode(common()->LoopExitValue(), |
+ values_[register_base() + i], loop_exit); |
+ values_[register_base() + i] = rename; |
+ } |
+ } |
+ |
+ if (assignments.ContainsAccumulator()) { |
+ Node* rename = graph()->NewNode(common()->LoopExitValue(), |
+ values_[accumulator_base()], loop_exit); |
+ values_[accumulator_base()] = rename; |
} |
} |
@@ -605,7 +619,7 @@ void BytecodeGraphBuilder::PrepareFrameState(Node* node, |
void BytecodeGraphBuilder::VisitBytecodes(bool stack_check) { |
BytecodeAnalysis bytecode_analysis(bytecode_array(), local_zone(), |
FLAG_analyze_environment_liveness); |
- bytecode_analysis.Analyze(); |
+ bytecode_analysis.Analyze(osr_ast_id_); |
set_bytecode_analysis(&bytecode_analysis); |
interpreter::BytecodeArrayIterator iterator(bytecode_array()); |
@@ -628,7 +642,6 @@ void BytecodeGraphBuilder::VisitBytecodes(bool stack_check) { |
SwitchToMergeEnvironment(current_offset); |
if (environment() != nullptr) { |
BuildLoopHeaderEnvironment(current_offset); |
- BuildOSRLoopEntryPoint(current_offset); |
// Skip the first stack check if stack_check is false |
if (!stack_check && |
@@ -855,7 +868,7 @@ BytecodeGraphBuilder::Environment* BytecodeGraphBuilder::CheckContextExtensions( |
extension_slot, jsgraph()->TheHoleConstant()); |
NewBranch(check_no_extension); |
- Environment* true_environment = environment()->CopyForConditional(); |
+ Environment* true_environment = environment()->Copy(); |
{ |
NewIfFalse(); |
@@ -1901,9 +1914,17 @@ void BytecodeGraphBuilder::SwitchToMergeEnvironment(int current_offset) { |
void BytecodeGraphBuilder::BuildLoopHeaderEnvironment(int current_offset) { |
if (bytecode_analysis()->IsLoopHeader(current_offset)) { |
- // Add loop header and store a copy so we can connect merged back |
- // edge inputs to the loop header. |
- merge_environments_[current_offset] = environment()->CopyForLoop(); |
+ const LoopInfo& loop_info = |
+ bytecode_analysis()->GetLoopInfoFor(current_offset); |
+ |
+ // Add loop header. |
+ environment()->PrepareForLoop(loop_info.assignments()); |
+ |
+ BuildOSRLoopEntryPoint(current_offset); |
+ |
+ // Store a copy of the environment so we can connect merged back edge inputs |
+ // to the loop header. |
+ merge_environments_[current_offset] = environment()->Copy(); |
} |
} |
@@ -1929,13 +1950,14 @@ void BytecodeGraphBuilder::MergeControlToLeaveFunction(Node* exit) { |
} |
void BytecodeGraphBuilder::BuildOSRLoopEntryPoint(int current_offset) { |
+ DCHECK(bytecode_analysis()->IsLoopHeader(current_offset)); |
+ |
if (!osr_ast_id_.IsNone() && osr_loop_offset_ == current_offset) { |
// For OSR add a special {OsrLoopEntry} node into the current loop header. |
// It will be turned into a usable entry by the OSR deconstruction. |
- Environment* loop_env = merge_environments_[current_offset]; |
- Environment* osr_env = loop_env->CopyForOsrEntry(); |
+ Environment* osr_env = environment()->Copy(); |
osr_env->PrepareForOsrEntry(); |
- loop_env->Merge(osr_env); |
+ environment()->Merge(osr_env); |
} |
} |
@@ -1966,8 +1988,10 @@ void BytecodeGraphBuilder::BuildLoopExitsUntilLoop(int loop_offset) { |
int current_loop = bytecode_analysis()->GetLoopOffsetFor(origin_offset); |
while (loop_offset < current_loop) { |
Node* loop_node = merge_environments_[current_loop]->GetControlDependency(); |
- environment()->PrepareForLoopExit(loop_node); |
- current_loop = bytecode_analysis()->GetParentLoopFor(current_loop); |
+ const LoopInfo& loop_info = |
+ bytecode_analysis()->GetLoopInfoFor(current_loop); |
+ environment()->PrepareForLoopExit(loop_node, loop_info.assignments()); |
+ current_loop = loop_info.parent_offset(); |
} |
} |
@@ -1981,7 +2005,7 @@ void BytecodeGraphBuilder::BuildJump() { |
void BytecodeGraphBuilder::BuildJumpIf(Node* condition) { |
NewBranch(condition); |
- Environment* if_false_environment = environment()->CopyForConditional(); |
+ Environment* if_false_environment = environment()->Copy(); |
NewIfTrue(); |
MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); |
set_environment(if_false_environment); |
@@ -1990,7 +2014,7 @@ void BytecodeGraphBuilder::BuildJumpIf(Node* condition) { |
void BytecodeGraphBuilder::BuildJumpIfNot(Node* condition) { |
NewBranch(condition); |
- Environment* if_true_environment = environment()->CopyForConditional(); |
+ Environment* if_true_environment = environment()->Copy(); |
NewIfFalse(); |
MergeIntoSuccessorEnvironment(bytecode_iterator().GetJumpTargetOffset()); |
set_environment(if_true_environment); |
@@ -2128,7 +2152,7 @@ Node* BytecodeGraphBuilder::MakeNode(const Operator* op, int value_input_count, |
int handler_offset = exception_handlers_.top().handler_offset_; |
int context_index = exception_handlers_.top().context_register_; |
interpreter::Register context_register(context_index); |
- Environment* success_env = environment()->CopyForConditional(); |
+ Environment* success_env = environment()->Copy(); |
const Operator* op = common()->IfException(); |
Node* effect = environment()->GetEffectDependency(); |
Node* on_exception = graph()->NewNode(op, effect, result); |