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) {
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}
// node is not in a sub-type relation to the type of the the {original} node.
Type* const replacement_type = NodeProperties::GetType(replacement);
......@@ -115,6 +116,7 @@ Node* MaybeGuard(JSGraph* jsgraph, Node* original, Node* replacement) {
Node* const control = NodeProperties::GetControlInput(original);
replacement = jsgraph->graph()->NewNode(
jsgraph->common()->TypeGuard(original_type), replacement, control);
NodeProperties::SetType(replacement, original_type);
}
return replacement;
}
......@@ -132,7 +134,7 @@ Reduction EscapeAnalysisReducer::ReduceLoad(Node* node) {
isolate()->counters()->turbo_escape_loads_replaced()->Increment();
TRACE("Replaced #%d (%s) with #%d (%s)\n", node->id(),
node->op()->mnemonic(), rep->id(), rep->op()->mnemonic());
rep = MaybeGuard(jsgraph(), node, rep);
rep = MaybeGuard(jsgraph(), zone(), node, rep);
ReplaceWithValue(node, rep);
return Replace(rep);
}
......
......@@ -431,7 +431,6 @@ bool IsEquivalentPhi(Node* phi, ZoneVector<Node*>& inputs) {
}
return true;
}
} // namespace
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());
Node* rep = GetField(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);
cache->fields().push_back(control);
Node* phi = graph->NewNode(
common->Phi(MachineRepresentation::kTagged, value_input_count),
value_input_count + 1, &cache->fields().front());
NodeProperties::SetType(phi, phi_type);
SetField(i, phi, true);
#ifdef DEBUG
if (FLAG_trace_turbo_escape) {
PrintF(" Creating Phi #%d as merge of", phi->id());
......@@ -865,7 +873,11 @@ EscapeAnalysis::EscapeAnalysis(Graph* graph, CommonOperatorBuilder* common,
virtual_states_(zone),
replacements_(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() {}
......@@ -1398,10 +1410,16 @@ void EscapeAnalysis::ProcessLoadFromPhi(int offset, Node* from, Node* load,
Node* rep = replacement(load);
if (!rep || !IsEquivalentPhi(rep, cache_->fields())) {
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));
Node* phi = graph()->NewNode(
common()->Phi(MachineRepresentation::kTagged, value_input_count),
value_input_count + 1, &cache_->fields().front());
NodeProperties::SetType(phi, phi_type);
status_analysis_->ResizeStatusVector();
SetReplacement(load, phi);
TRACE(" got phi created.\n");
......@@ -1595,6 +1613,7 @@ Node* EscapeAnalysis::GetOrCreateObjectState(Node* effect, Node* node) {
Node* new_object_state =
graph()->NewNode(common()->ObjectState(input_count), input_count,
&cache_->fields().front());
NodeProperties::SetType(new_object_state, Type::OtherInternal());
vobj->SetObjectState(new_object_state);
TRACE(
"Creating object state #%d for vobj %p (from node #%d) at effect "
......
......@@ -111,6 +111,7 @@ class PipelineData {
javascript_ = new (graph_zone_) JSOperatorBuilder(graph_zone_);
jsgraph_ = new (graph_zone_)
JSGraph(isolate_, graph_, common_, javascript_, simplified_, machine_);
is_asm_ = info->shared_info()->asm_function();
}
// For WASM compile entry point.
......@@ -133,7 +134,10 @@ class PipelineData {
instruction_zone_(instruction_zone_scope_.zone()),
register_allocation_zone_scope_(zone_stats_, ZONE_NAME),
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.
PipelineData(ZoneStats* zone_stats, CompilationInfo* info, Graph* graph,
......@@ -149,8 +153,9 @@ class PipelineData {
instruction_zone_scope_(zone_stats_, ZONE_NAME),
instruction_zone_(instruction_zone_scope_.zone()),
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.
PipelineData(ZoneStats* zone_stats, CompilationInfo* info,
InstructionSequence* sequence)
......@@ -163,7 +168,10 @@ class PipelineData {
instruction_zone_(sequence->zone()),
sequence_(sequence),
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() {
DeleteRegisterAllocationZone();
......@@ -178,6 +186,7 @@ class PipelineData {
bool compilation_failed() const { return compilation_failed_; }
void set_compilation_failed() { compilation_failed_ = true; }
bool is_asm() const { return is_asm_; }
bool verify_graph() const { return verify_graph_; }
void set_verify_graph(bool value) { verify_graph_ = value; }
......@@ -328,6 +337,7 @@ class PipelineData {
PipelineStatistics* pipeline_statistics_ = nullptr;
bool compilation_failed_ = false;
bool verify_graph_ = false;
bool is_asm_ = false;
Handle<Code> code_ = Handle<Code>::null();
// All objects in the following group of fields are allocated in graph_zone_.
......@@ -979,14 +989,20 @@ struct LoopExitEliminationPhase {
}
};
struct GenericLoweringPrepPhase {
static const char* phase_name() { return "generic lowering prep"; }
struct ConcurrentOptimizationPrepPhase {
static const char* phase_name() {
return "concurrent optimization preparation";
}
void Run(PipelineData* data, Zone* temp_zone) {
// Make sure we cache these code stubs.
data->jsgraph()->CEntryStubConstant(1);
data->jsgraph()->CEntryStubConstant(2);
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() {
Run<LoadEliminationPhase>();
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.
Run<GenericLoweringPrepPhase>();
// Do some hacky things to prepare for the optimization phase.
// (caching handles, etc.).
Run<ConcurrentOptimizationPrepPhase>();
data->EndPhaseKind();
......@@ -1564,6 +1571,18 @@ bool PipelineImpl::CreateGraph() {
bool PipelineImpl::OptimizeGraph(Linkage* linkage) {
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,
// because we cannot compute meaningful types anyways, and the computed types
// 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