Commit 35a393f8 authored by mvstanton's avatar mvstanton Committed by Commit bot

[Turbofan] Run escape analysis concurrently.

BUG=v8:5428

Review-Url: https://codereview.chromium.org/2606273002
Cr-Commit-Position: refs/heads/master@{#42027}
parent b0e9116d
...@@ -106,7 +106,8 @@ Reduction EscapeAnalysisReducer::Reduce(Node* node) { ...@@ -106,7 +106,8 @@ Reduction EscapeAnalysisReducer::Reduce(Node* node) {
namespace { namespace {
Node* MaybeGuard(JSGraph* jsgraph, Node* original, Node* replacement) { Node* MaybeGuard(JSGraph* jsgraph, Zone* zone, Node* original,
Node* replacement) {
// We might need to guard the replacement if the type of the {replacement} // We might need to guard the replacement if the type of the {replacement}
// node is not in a sub-type relation to the type of the the {original} node. // node is not in a sub-type relation to the type of the the {original} node.
Type* const replacement_type = NodeProperties::GetType(replacement); Type* const replacement_type = NodeProperties::GetType(replacement);
...@@ -115,6 +116,7 @@ Node* MaybeGuard(JSGraph* jsgraph, Node* original, Node* replacement) { ...@@ -115,6 +116,7 @@ Node* MaybeGuard(JSGraph* jsgraph, Node* original, Node* replacement) {
Node* const control = NodeProperties::GetControlInput(original); Node* const control = NodeProperties::GetControlInput(original);
replacement = jsgraph->graph()->NewNode( replacement = jsgraph->graph()->NewNode(
jsgraph->common()->TypeGuard(original_type), replacement, control); jsgraph->common()->TypeGuard(original_type), replacement, control);
NodeProperties::SetType(replacement, original_type);
} }
return replacement; return replacement;
} }
...@@ -132,7 +134,7 @@ Reduction EscapeAnalysisReducer::ReduceLoad(Node* node) { ...@@ -132,7 +134,7 @@ Reduction EscapeAnalysisReducer::ReduceLoad(Node* node) {
isolate()->counters()->turbo_escape_loads_replaced()->Increment(); isolate()->counters()->turbo_escape_loads_replaced()->Increment();
TRACE("Replaced #%d (%s) with #%d (%s)\n", node->id(), TRACE("Replaced #%d (%s) with #%d (%s)\n", node->id(),
node->op()->mnemonic(), rep->id(), rep->op()->mnemonic()); node->op()->mnemonic(), rep->id(), rep->op()->mnemonic());
rep = MaybeGuard(jsgraph(), node, rep); rep = MaybeGuard(jsgraph(), zone(), node, rep);
ReplaceWithValue(node, rep); ReplaceWithValue(node, rep);
return Replace(rep); return Replace(rep);
} }
......
...@@ -431,7 +431,6 @@ bool IsEquivalentPhi(Node* phi, ZoneVector<Node*>& inputs) { ...@@ -431,7 +431,6 @@ bool IsEquivalentPhi(Node* phi, ZoneVector<Node*>& inputs) {
} }
return true; return true;
} }
} // namespace } // namespace
bool VirtualObject::MergeFields(size_t i, Node* at, MergeCache* cache, bool VirtualObject::MergeFields(size_t i, Node* at, MergeCache* cache,
...@@ -440,12 +439,21 @@ bool VirtualObject::MergeFields(size_t i, Node* at, MergeCache* cache, ...@@ -440,12 +439,21 @@ bool VirtualObject::MergeFields(size_t i, Node* at, MergeCache* cache,
int value_input_count = static_cast<int>(cache->fields().size()); int value_input_count = static_cast<int>(cache->fields().size());
Node* rep = GetField(i); Node* rep = GetField(i);
if (!rep || !IsCreatedPhi(i)) { if (!rep || !IsCreatedPhi(i)) {
Type* phi_type = Type::None();
for (Node* input : cache->fields()) {
CHECK_NOT_NULL(input);
CHECK(!input->IsDead());
Type* input_type = NodeProperties::GetType(input);
phi_type = Type::Union(phi_type, input_type, graph->zone());
}
Node* control = NodeProperties::GetControlInput(at); Node* control = NodeProperties::GetControlInput(at);
cache->fields().push_back(control); cache->fields().push_back(control);
Node* phi = graph->NewNode( Node* phi = graph->NewNode(
common->Phi(MachineRepresentation::kTagged, value_input_count), common->Phi(MachineRepresentation::kTagged, value_input_count),
value_input_count + 1, &cache->fields().front()); value_input_count + 1, &cache->fields().front());
NodeProperties::SetType(phi, phi_type);
SetField(i, phi, true); SetField(i, phi, true);
#ifdef DEBUG #ifdef DEBUG
if (FLAG_trace_turbo_escape) { if (FLAG_trace_turbo_escape) {
PrintF(" Creating Phi #%d as merge of", phi->id()); PrintF(" Creating Phi #%d as merge of", phi->id());
...@@ -865,7 +873,11 @@ EscapeAnalysis::EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common, ...@@ -865,7 +873,11 @@ EscapeAnalysis::EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common,
virtual_states_(zone), virtual_states_(zone),
replacements_(zone), replacements_(zone),
cycle_detection_(zone), cycle_detection_(zone),
cache_(nullptr) {} cache_(nullptr) {
// Type slot_not_analyzed_ manually.
double v = OpParameter<double>(slot_not_analyzed_);
NodeProperties::SetType(slot_not_analyzed_, Type::Range(v, v, zone));
}
EscapeAnalysis::~EscapeAnalysis() {} EscapeAnalysis::~EscapeAnalysis() {}
...@@ -1398,10 +1410,16 @@ void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* load, ...@@ -1398,10 +1410,16 @@ void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* load,
Node* rep = replacement(load); Node* rep = replacement(load);
if (!rep || !IsEquivalentPhi(rep, cache_->fields())) { if (!rep || !IsEquivalentPhi(rep, cache_->fields())) {
int value_input_count = static_cast<int>(cache_->fields().size()); int value_input_count = static_cast<int>(cache_->fields().size());
Type* phi_type = Type::None();
for (Node* input : cache_->fields()) {
Type* input_type = NodeProperties::GetType(input);
phi_type = Type::Union(phi_type, input_type, graph()->zone());
}
cache_->fields().push_back(NodeProperties::GetControlInput(from)); cache_->fields().push_back(NodeProperties::GetControlInput(from));
Node* phi = graph()->NewNode( Node* phi = graph()->NewNode(
common()->Phi(MachineRepresentation::kTagged, value_input_count), common()->Phi(MachineRepresentation::kTagged, value_input_count),
value_input_count + 1, &cache_->fields().front()); value_input_count + 1, &cache_->fields().front());
NodeProperties::SetType(phi, phi_type);
status_analysis_->ResizeStatusVector(); status_analysis_->ResizeStatusVector();
SetReplacement(load, phi); SetReplacement(load, phi);
TRACE(" got phi created.\n"); TRACE(" got phi created.\n");
...@@ -1595,6 +1613,7 @@ Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) { ...@@ -1595,6 +1613,7 @@ Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) {
Node* new_object_state = Node* new_object_state =
graph()->NewNode(common()->ObjectState(input_count), input_count, graph()->NewNode(common()->ObjectState(input_count), input_count,
&cache_->fields().front()); &cache_->fields().front());
NodeProperties::SetType(new_object_state, Type::OtherInternal());
vobj->SetObjectState(new_object_state); vobj->SetObjectState(new_object_state);
TRACE( TRACE(
"Creating object state #%d for vobj %p (from node #%d) at effect " "Creating object state #%d for vobj %p (from node #%d) at effect "
......
...@@ -111,6 +111,7 @@ class PipelineData { ...@@ -111,6 +111,7 @@ class PipelineData {
javascript_ = new (graph_zone_) JSOperatorBuilder(graph_zone_); javascript_ = new (graph_zone_) JSOperatorBuilder(graph_zone_);
jsgraph_ = new (graph_zone_) jsgraph_ = new (graph_zone_)
JSGraph(isolate_, graph_, common_, javascript_, simplified_, machine_); JSGraph(isolate_, graph_, common_, javascript_, simplified_, machine_);
is_asm_ = info->shared_info()->asm_function();
} }
// For WASM compile entry point. // For WASM compile entry point.
...@@ -133,7 +134,10 @@ class PipelineData { ...@@ -133,7 +134,10 @@ class PipelineData {
instruction_zone_(instruction_zone_scope_.zone()), instruction_zone_(instruction_zone_scope_.zone()),
register_allocation_zone_scope_(zone_stats_, ZONE_NAME), register_allocation_zone_scope_(zone_stats_, ZONE_NAME),
register_allocation_zone_(register_allocation_zone_scope_.zone()), register_allocation_zone_(register_allocation_zone_scope_.zone()),
protected_instructions_(protected_instructions) {} protected_instructions_(protected_instructions) {
is_asm_ =
info->has_shared_info() ? info->shared_info()->asm_function() : false;
}
// For machine graph testing entry point. // For machine graph testing entry point.
PipelineData(ZoneStats* zone_stats, CompilationInfo* info, Graph* graph, PipelineData(ZoneStats* zone_stats, CompilationInfo* info, Graph* graph,
...@@ -149,8 +153,9 @@ class PipelineData { ...@@ -149,8 +153,9 @@ class PipelineData {
instruction_zone_scope_(zone_stats_, ZONE_NAME), instruction_zone_scope_(zone_stats_, ZONE_NAME),
instruction_zone_(instruction_zone_scope_.zone()), instruction_zone_(instruction_zone_scope_.zone()),
register_allocation_zone_scope_(zone_stats_, ZONE_NAME), register_allocation_zone_scope_(zone_stats_, ZONE_NAME),
register_allocation_zone_(register_allocation_zone_scope_.zone()) {} register_allocation_zone_(register_allocation_zone_scope_.zone()) {
is_asm_ = false;
}
// For register allocation testing entry point. // For register allocation testing entry point.
PipelineData(ZoneStats* zone_stats, CompilationInfo* info, PipelineData(ZoneStats* zone_stats, CompilationInfo* info,
InstructionSequence* sequence) InstructionSequence* sequence)
...@@ -163,7 +168,10 @@ class PipelineData { ...@@ -163,7 +168,10 @@ class PipelineData {
instruction_zone_(sequence->zone()), instruction_zone_(sequence->zone()),
sequence_(sequence), sequence_(sequence),
register_allocation_zone_scope_(zone_stats_, ZONE_NAME), register_allocation_zone_scope_(zone_stats_, ZONE_NAME),
register_allocation_zone_(register_allocation_zone_scope_.zone()) {} register_allocation_zone_(register_allocation_zone_scope_.zone()) {
is_asm_ =
info->has_shared_info() ? info->shared_info()->asm_function() : false;
}
~PipelineData() { ~PipelineData() {
DeleteRegisterAllocationZone(); DeleteRegisterAllocationZone();
...@@ -178,6 +186,7 @@ class PipelineData { ...@@ -178,6 +186,7 @@ class PipelineData {
bool compilation_failed() const { return compilation_failed_; } bool compilation_failed() const { return compilation_failed_; }
void set_compilation_failed() { compilation_failed_ = true; } void set_compilation_failed() { compilation_failed_ = true; }
bool is_asm() const { return is_asm_; }
bool verify_graph() const { return verify_graph_; } bool verify_graph() const { return verify_graph_; }
void set_verify_graph(bool value) { verify_graph_ = value; } void set_verify_graph(bool value) { verify_graph_ = value; }
...@@ -328,6 +337,7 @@ class PipelineData { ...@@ -328,6 +337,7 @@ class PipelineData {
PipelineStatistics* pipeline_statistics_ = nullptr; PipelineStatistics* pipeline_statistics_ = nullptr;
bool compilation_failed_ = false; bool compilation_failed_ = false;
bool verify_graph_ = false; bool verify_graph_ = false;
bool is_asm_ = false;
Handle<Code> code_ = Handle<Code>::null(); Handle<Code> code_ = Handle<Code>::null();
// All objects in the following group of fields are allocated in graph_zone_. // All objects in the following group of fields are allocated in graph_zone_.
...@@ -979,14 +989,20 @@ struct LoopExitEliminationPhase { ...@@ -979,14 +989,20 @@ struct LoopExitEliminationPhase {
} }
}; };
struct GenericLoweringPrepPhase { struct ConcurrentOptimizationPrepPhase {
static const char* phase_name() { return "generic lowering prep"; } static const char* phase_name() {
return "concurrent optimization preparation";
}
void Run(PipelineData* data, Zone* temp_zone) { void Run(PipelineData* data, Zone* temp_zone) {
// Make sure we cache these code stubs. // Make sure we cache these code stubs.
data->jsgraph()->CEntryStubConstant(1); data->jsgraph()->CEntryStubConstant(1);
data->jsgraph()->CEntryStubConstant(2); data->jsgraph()->CEntryStubConstant(2);
data->jsgraph()->CEntryStubConstant(3); data->jsgraph()->CEntryStubConstant(3);
// This is needed for escape analysis.
NodeProperties::SetType(data->jsgraph()->FalseConstant(), Type::Boolean());
NodeProperties::SetType(data->jsgraph()->TrueConstant(), Type::Boolean());
} }
}; };
...@@ -1540,21 +1556,12 @@ bool PipelineImpl::CreateGraph() { ...@@ -1540,21 +1556,12 @@ bool PipelineImpl::CreateGraph() {
Run<LoadEliminationPhase>(); Run<LoadEliminationPhase>();
RunPrintAndVerify("Load eliminated"); RunPrintAndVerify("Load eliminated");
} }
if (FLAG_turbo_escape) {
Run<EscapeAnalysisPhase>();
if (data->compilation_failed()) {
info()->AbortOptimization(kCyclicObjectStateDetectedInEscapeAnalysis);
data->EndPhaseKind();
return false;
}
RunPrintAndVerify("Escape Analysed");
}
} }
} }
// Do some hacky things to prepare generic lowering. // Do some hacky things to prepare for the optimization phase.
Run<GenericLoweringPrepPhase>(); // (caching handles, etc.).
Run<ConcurrentOptimizationPrepPhase>();
data->EndPhaseKind(); data->EndPhaseKind();
...@@ -1564,6 +1571,18 @@ bool PipelineImpl::CreateGraph() { ...@@ -1564,6 +1571,18 @@ bool PipelineImpl::CreateGraph() {
bool PipelineImpl::OptimizeGraph(Linkage* linkage) { bool PipelineImpl::OptimizeGraph(Linkage* linkage) {
PipelineData* data = this->data_; PipelineData* data = this->data_;
if (!data->is_asm()) {
if (FLAG_turbo_escape) {
Run<EscapeAnalysisPhase>();
if (data->compilation_failed()) {
info()->AbortOptimization(kCyclicObjectStateDetectedInEscapeAnalysis);
data->EndPhaseKind();
return false;
}
RunPrintAndVerify("Escape Analysed");
}
}
// Perform simplified lowering. This has to run w/o the Typer decorator, // Perform simplified lowering. This has to run w/o the Typer decorator,
// because we cannot compute meaningful types anyways, and the computed types // because we cannot compute meaningful types anyways, and the computed types
// might even conflict with the representation/truncation logic. // might even conflict with the representation/truncation logic.
......
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