Upgrade V8 to version 4.9.385.28
https://chromium.googlesource.com/v8/v8/+/4.9.385.28
FPIIM-449
Change-Id: I4b2e74289d4bf3667f2f3dc8aa2e541f63e26eb4
diff --git a/src/compiler/pipeline.cc b/src/compiler/pipeline.cc
index c7432c6..4d6aacd 100644
--- a/src/compiler/pipeline.cc
+++ b/src/compiler/pipeline.cc
@@ -7,27 +7,46 @@
#include <fstream> // NOLINT(readability/streams)
#include <sstream>
+#include "src/base/adapters.h"
#include "src/base/platform/elapsed-timer.h"
#include "src/compiler/ast-graph-builder.h"
#include "src/compiler/ast-loop-assignment-analyzer.h"
#include "src/compiler/basic-block-instrumentor.h"
+#include "src/compiler/branch-elimination.h"
+#include "src/compiler/bytecode-graph-builder.h"
#include "src/compiler/change-lowering.h"
#include "src/compiler/code-generator.h"
#include "src/compiler/common-operator-reducer.h"
-#include "src/compiler/control-reducer.h"
+#include "src/compiler/control-flow-optimizer.h"
+#include "src/compiler/dead-code-elimination.h"
+#include "src/compiler/escape-analysis.h"
+#include "src/compiler/escape-analysis-reducer.h"
+#include "src/compiler/frame-elider.h"
#include "src/compiler/graph-replay.h"
+#include "src/compiler/graph-trimmer.h"
#include "src/compiler/graph-visualizer.h"
+#include "src/compiler/greedy-allocator.h"
#include "src/compiler/instruction.h"
#include "src/compiler/instruction-selector.h"
#include "src/compiler/js-builtin-reducer.h"
+#include "src/compiler/js-call-reducer.h"
+#include "src/compiler/js-context-relaxation.h"
#include "src/compiler/js-context-specialization.h"
+#include "src/compiler/js-frame-specialization.h"
#include "src/compiler/js-generic-lowering.h"
-#include "src/compiler/js-inlining.h"
+#include "src/compiler/js-global-object-specialization.h"
+#include "src/compiler/js-inlining-heuristic.h"
+#include "src/compiler/js-intrinsic-lowering.h"
+#include "src/compiler/js-native-context-specialization.h"
#include "src/compiler/js-typed-lowering.h"
#include "src/compiler/jump-threading.h"
+#include "src/compiler/live-range-separator.h"
#include "src/compiler/load-elimination.h"
+#include "src/compiler/loop-analysis.h"
+#include "src/compiler/loop-peeling.h"
#include "src/compiler/machine-operator-reducer.h"
#include "src/compiler/move-optimizer.h"
+#include "src/compiler/osr.h"
#include "src/compiler/pipeline-statistics.h"
#include "src/compiler/register-allocator.h"
#include "src/compiler/register-allocator-verifier.h"
@@ -35,12 +54,17 @@
#include "src/compiler/scheduler.h"
#include "src/compiler/select-lowering.h"
#include "src/compiler/simplified-lowering.h"
+#include "src/compiler/simplified-operator.h"
#include "src/compiler/simplified-operator-reducer.h"
+#include "src/compiler/tail-call-optimization.h"
+#include "src/compiler/type-hint-analyzer.h"
#include "src/compiler/typer.h"
#include "src/compiler/value-numbering-reducer.h"
#include "src/compiler/verifier.h"
#include "src/compiler/zone-pool.h"
#include "src/ostreams.h"
+#include "src/register-configuration.h"
+#include "src/type-info.h"
#include "src/utils.h"
namespace v8 {
@@ -49,8 +73,79 @@
class PipelineData {
public:
- explicit PipelineData(ZonePool* zone_pool, CompilationInfo* info)
- : isolate_(info->zone()->isolate()),
+ // For main entry point.
+ PipelineData(ZonePool* zone_pool, CompilationInfo* info,
+ PipelineStatistics* pipeline_statistics)
+ : isolate_(info->isolate()),
+ info_(info),
+ outer_zone_(info_->zone()),
+ zone_pool_(zone_pool),
+ pipeline_statistics_(pipeline_statistics),
+ compilation_failed_(false),
+ code_(Handle<Code>::null()),
+ graph_zone_scope_(zone_pool_),
+ graph_zone_(graph_zone_scope_.zone()),
+ graph_(nullptr),
+ loop_assignment_(nullptr),
+ simplified_(nullptr),
+ machine_(nullptr),
+ common_(nullptr),
+ javascript_(nullptr),
+ jsgraph_(nullptr),
+ schedule_(nullptr),
+ instruction_zone_scope_(zone_pool_),
+ instruction_zone_(instruction_zone_scope_.zone()),
+ sequence_(nullptr),
+ frame_(nullptr),
+ register_allocation_zone_scope_(zone_pool_),
+ register_allocation_zone_(register_allocation_zone_scope_.zone()),
+ register_allocation_data_(nullptr) {
+ PhaseScope scope(pipeline_statistics, "init pipeline data");
+ graph_ = new (graph_zone_) Graph(graph_zone_);
+ source_positions_.Reset(new SourcePositionTable(graph_));
+ simplified_ = new (graph_zone_) SimplifiedOperatorBuilder(graph_zone_);
+ machine_ = new (graph_zone_) MachineOperatorBuilder(
+ graph_zone_, MachineType::PointerRepresentation(),
+ InstructionSelector::SupportedMachineOperatorFlags());
+ common_ = new (graph_zone_) CommonOperatorBuilder(graph_zone_);
+ javascript_ = new (graph_zone_) JSOperatorBuilder(graph_zone_);
+ jsgraph_ = new (graph_zone_)
+ JSGraph(isolate_, graph_, common_, javascript_, simplified_, machine_);
+ }
+
+ // For machine graph testing entry point.
+ PipelineData(ZonePool* zone_pool, CompilationInfo* info, Graph* graph,
+ Schedule* schedule)
+ : isolate_(info->isolate()),
+ info_(info),
+ outer_zone_(nullptr),
+ zone_pool_(zone_pool),
+ pipeline_statistics_(nullptr),
+ compilation_failed_(false),
+ code_(Handle<Code>::null()),
+ graph_zone_scope_(zone_pool_),
+ graph_zone_(nullptr),
+ graph_(graph),
+ source_positions_(new SourcePositionTable(graph_)),
+ loop_assignment_(nullptr),
+ simplified_(nullptr),
+ machine_(nullptr),
+ common_(nullptr),
+ javascript_(nullptr),
+ jsgraph_(nullptr),
+ schedule_(schedule),
+ instruction_zone_scope_(zone_pool_),
+ instruction_zone_(instruction_zone_scope_.zone()),
+ sequence_(nullptr),
+ frame_(nullptr),
+ register_allocation_zone_scope_(zone_pool_),
+ register_allocation_zone_(register_allocation_zone_scope_.zone()),
+ register_allocation_data_(nullptr) {}
+
+ // For register allocation testing entry point.
+ PipelineData(ZonePool* zone_pool, CompilationInfo* info,
+ InstructionSequence* sequence)
+ : isolate_(info->isolate()),
info_(info),
outer_zone_(nullptr),
zone_pool_(zone_pool),
@@ -61,57 +156,26 @@
graph_zone_(nullptr),
graph_(nullptr),
loop_assignment_(nullptr),
+ simplified_(nullptr),
machine_(nullptr),
common_(nullptr),
javascript_(nullptr),
jsgraph_(nullptr),
- typer_(nullptr),
- context_node_(nullptr),
schedule_(nullptr),
instruction_zone_scope_(zone_pool_),
- instruction_zone_(nullptr),
- sequence_(nullptr),
+ instruction_zone_(sequence->zone()),
+ sequence_(sequence),
frame_(nullptr),
- register_allocator_(nullptr) {}
+ register_allocation_zone_scope_(zone_pool_),
+ register_allocation_zone_(register_allocation_zone_scope_.zone()),
+ register_allocation_data_(nullptr) {}
~PipelineData() {
+ DeleteRegisterAllocationZone();
DeleteInstructionZone();
DeleteGraphZone();
}
- // For main entry point.
- void Initialize(PipelineStatistics* pipeline_statistics) {
- PhaseScope scope(pipeline_statistics, "init pipeline data");
- outer_zone_ = info()->zone();
- pipeline_statistics_ = pipeline_statistics;
- graph_zone_ = graph_zone_scope_.zone();
- graph_ = new (graph_zone()) Graph(graph_zone());
- source_positions_.Reset(new SourcePositionTable(graph()));
- machine_ = new (graph_zone()) MachineOperatorBuilder(
- graph_zone(), kMachPtr,
- InstructionSelector::SupportedMachineOperatorFlags());
- common_ = new (graph_zone()) CommonOperatorBuilder(graph_zone());
- javascript_ = new (graph_zone()) JSOperatorBuilder(graph_zone());
- jsgraph_ =
- new (graph_zone()) JSGraph(graph(), common(), javascript(), machine());
- typer_.Reset(new Typer(graph(), info()->context()));
- instruction_zone_ = instruction_zone_scope_.zone();
- }
-
- // For machine graph testing entry point.
- void InitializeTorTesting(Graph* graph, Schedule* schedule) {
- graph_ = graph;
- source_positions_.Reset(new SourcePositionTable(graph));
- schedule_ = schedule;
- instruction_zone_ = instruction_zone_scope_.zone();
- }
-
- // For register allocation testing entry point.
- void InitializeTorTesting(InstructionSequence* sequence) {
- instruction_zone_ = sequence->zone();
- sequence_ = sequence;
- }
-
Isolate* isolate() const { return isolate_; }
CompilationInfo* info() const { return info_; }
ZonePool* zone_pool() const { return zone_pool_; }
@@ -136,46 +200,55 @@
CommonOperatorBuilder* common() const { return common_; }
JSOperatorBuilder* javascript() const { return javascript_; }
JSGraph* jsgraph() const { return jsgraph_; }
- Typer* typer() const { return typer_.get(); }
+ MaybeHandle<Context> native_context() const {
+ if (info()->is_native_context_specializing()) {
+ return handle(info()->native_context(), isolate());
+ }
+ return MaybeHandle<Context>();
+ }
LoopAssignmentAnalysis* loop_assignment() const { return loop_assignment_; }
void set_loop_assignment(LoopAssignmentAnalysis* loop_assignment) {
- DCHECK_EQ(nullptr, loop_assignment_);
+ DCHECK(!loop_assignment_);
loop_assignment_ = loop_assignment;
}
- Node* context_node() const { return context_node_; }
- void set_context_node(Node* context_node) {
- DCHECK_EQ(nullptr, context_node_);
- context_node_ = context_node;
+ TypeHintAnalysis* type_hint_analysis() const { return type_hint_analysis_; }
+ void set_type_hint_analysis(TypeHintAnalysis* type_hint_analysis) {
+ DCHECK_NULL(type_hint_analysis_);
+ type_hint_analysis_ = type_hint_analysis;
}
Schedule* schedule() const { return schedule_; }
void set_schedule(Schedule* schedule) {
- DCHECK_EQ(nullptr, schedule_);
+ DCHECK(!schedule_);
schedule_ = schedule;
}
Zone* instruction_zone() const { return instruction_zone_; }
InstructionSequence* sequence() const { return sequence_; }
Frame* frame() const { return frame_; }
- RegisterAllocator* register_allocator() const { return register_allocator_; }
+
+ Zone* register_allocation_zone() const { return register_allocation_zone_; }
+ RegisterAllocationData* register_allocation_data() const {
+ return register_allocation_data_;
+ }
void DeleteGraphZone() {
// Destroy objects with destructors first.
source_positions_.Reset(nullptr);
- typer_.Reset(nullptr);
if (graph_zone_ == nullptr) return;
// Destroy zone and clear pointers.
graph_zone_scope_.Destroy();
graph_zone_ = nullptr;
graph_ = nullptr;
loop_assignment_ = nullptr;
+ type_hint_analysis_ = nullptr;
+ simplified_ = nullptr;
machine_ = nullptr;
common_ = nullptr;
javascript_ = nullptr;
jsgraph_ = nullptr;
- context_node_ = nullptr;
schedule_ = nullptr;
}
@@ -185,26 +258,40 @@
instruction_zone_ = nullptr;
sequence_ = nullptr;
frame_ = nullptr;
- register_allocator_ = nullptr;
+ }
+
+ void DeleteRegisterAllocationZone() {
+ if (register_allocation_zone_ == nullptr) return;
+ register_allocation_zone_scope_.Destroy();
+ register_allocation_zone_ = nullptr;
+ register_allocation_data_ = nullptr;
}
void InitializeInstructionSequence() {
- DCHECK_EQ(nullptr, sequence_);
+ DCHECK(sequence_ == nullptr);
InstructionBlocks* instruction_blocks =
InstructionSequence::InstructionBlocksFor(instruction_zone(),
schedule());
- sequence_ = new (instruction_zone())
- InstructionSequence(instruction_zone(), instruction_blocks);
+ sequence_ = new (instruction_zone()) InstructionSequence(
+ info()->isolate(), instruction_zone(), instruction_blocks);
}
- void InitializeRegisterAllocator(Zone* local_zone,
- const RegisterConfiguration* config,
- const char* debug_name) {
- DCHECK_EQ(nullptr, register_allocator_);
- DCHECK_EQ(nullptr, frame_);
- frame_ = new (instruction_zone()) Frame();
- register_allocator_ = new (instruction_zone())
- RegisterAllocator(config, local_zone, frame(), sequence(), debug_name);
+ void InitializeRegisterAllocationData(const RegisterConfiguration* config,
+ CallDescriptor* descriptor,
+ const char* debug_name) {
+ DCHECK(frame_ == nullptr);
+ DCHECK(register_allocation_data_ == nullptr);
+ int fixed_frame_size = 0;
+ if (descriptor != nullptr) {
+ fixed_frame_size = (descriptor->IsCFunctionCall())
+ ? StandardFrameConstants::kFixedSlotCountAboveFp +
+ StandardFrameConstants::kCPSlotCount
+ : StandardFrameConstants::kFixedSlotCount;
+ }
+ frame_ = new (instruction_zone()) Frame(fixed_frame_size, descriptor);
+ register_allocation_data_ = new (register_allocation_zone())
+ RegisterAllocationData(config, register_allocation_zone(), frame(),
+ sequence(), debug_name);
}
private:
@@ -217,43 +304,42 @@
Handle<Code> code_;
// All objects in the following group of fields are allocated in graph_zone_.
- // They are all set to NULL when the graph_zone_ is destroyed.
+ // They are all set to nullptr when the graph_zone_ is destroyed.
ZonePool::Scope graph_zone_scope_;
Zone* graph_zone_;
Graph* graph_;
// TODO(dcarney): make this into a ZoneObject.
- SmartPointer<SourcePositionTable> source_positions_;
+ base::SmartPointer<SourcePositionTable> source_positions_;
LoopAssignmentAnalysis* loop_assignment_;
+ TypeHintAnalysis* type_hint_analysis_ = nullptr;
+ SimplifiedOperatorBuilder* simplified_;
MachineOperatorBuilder* machine_;
CommonOperatorBuilder* common_;
JSOperatorBuilder* javascript_;
JSGraph* jsgraph_;
- // TODO(dcarney): make this into a ZoneObject.
- SmartPointer<Typer> typer_;
- Node* context_node_;
Schedule* schedule_;
// All objects in the following group of fields are allocated in
- // instruction_zone_. They are all set to NULL when the instruction_zone_ is
+ // instruction_zone_. They are all set to nullptr when the instruction_zone_
+ // is
// destroyed.
ZonePool::Scope instruction_zone_scope_;
Zone* instruction_zone_;
InstructionSequence* sequence_;
Frame* frame_;
- RegisterAllocator* register_allocator_;
+
+ // All objects in the following group of fields are allocated in
+ // register_allocation_zone_. They are all set to nullptr when the zone is
+ // destroyed.
+ ZonePool::Scope register_allocation_zone_scope_;
+ Zone* register_allocation_zone_;
+ RegisterAllocationData* register_allocation_data_;
DISALLOW_COPY_AND_ASSIGN(PipelineData);
};
-static inline bool VerifyGraphs() {
-#ifdef DEBUG
- return true;
-#else
- return FLAG_turbo_verify;
-#endif
-}
-
+namespace {
struct TurboCfgFile : public std::ofstream {
explicit TurboCfgFile(Isolate* isolate)
@@ -262,48 +348,47 @@
};
-static void TraceSchedule(Schedule* schedule) {
+void TraceSchedule(CompilationInfo* info, Schedule* schedule) {
+ if (FLAG_trace_turbo) {
+ FILE* json_file = OpenVisualizerLogFile(info, nullptr, "json", "a+");
+ if (json_file != nullptr) {
+ OFStream json_of(json_file);
+ json_of << "{\"name\":\"Schedule\",\"type\":\"schedule\",\"data\":\"";
+ std::stringstream schedule_stream;
+ schedule_stream << *schedule;
+ std::string schedule_string(schedule_stream.str());
+ for (const auto& c : schedule_string) {
+ json_of << AsEscapedUC16ForJSON(c);
+ }
+ json_of << "\"},\n";
+ fclose(json_file);
+ }
+ }
if (!FLAG_trace_turbo_graph && !FLAG_trace_turbo_scheduler) return;
OFStream os(stdout);
os << "-- Schedule --------------------------------------\n" << *schedule;
}
-static SmartArrayPointer<char> GetDebugName(CompilationInfo* info) {
- SmartArrayPointer<char> name;
- if (info->IsStub()) {
- if (info->code_stub() != NULL) {
- CodeStub::Major major_key = info->code_stub()->MajorKey();
- const char* major_name = CodeStub::MajorName(major_key, false);
- size_t len = strlen(major_name);
- name.Reset(new char[len]);
- memcpy(name.get(), major_name, len);
- }
- } else {
- AllowHandleDereference allow_deref;
- name = info->function()->debug_name()->ToCString();
- }
- return name;
-}
-
-
-class AstGraphBuilderWithPositions : public AstGraphBuilder {
+class AstGraphBuilderWithPositions final : public AstGraphBuilder {
public:
AstGraphBuilderWithPositions(Zone* local_zone, CompilationInfo* info,
JSGraph* jsgraph,
LoopAssignmentAnalysis* loop_assignment,
+ TypeHintAnalysis* type_hint_analysis,
SourcePositionTable* source_positions)
- : AstGraphBuilder(local_zone, info, jsgraph, loop_assignment),
- source_positions_(source_positions) {}
+ : AstGraphBuilder(local_zone, info, jsgraph, loop_assignment,
+ type_hint_analysis),
+ source_positions_(source_positions),
+ start_position_(info->shared_info()->start_position()) {}
- bool CreateGraph() {
- SourcePositionTable::Scope pos(source_positions_,
- SourcePosition::Unknown());
- return AstGraphBuilder::CreateGraph();
+ bool CreateGraph(bool stack_check) {
+ SourcePositionTable::Scope pos_scope(source_positions_, start_position_);
+ return AstGraphBuilder::CreateGraph(stack_check);
}
#define DEF_VISIT(type) \
- void Visit##type(type* node) OVERRIDE { \
+ void Visit##type(type* node) override { \
SourcePositionTable::Scope pos(source_positions_, \
SourcePosition(node->position())); \
AstGraphBuilder::Visit##type(node); \
@@ -311,13 +396,55 @@
AST_NODE_LIST(DEF_VISIT)
#undef DEF_VISIT
- Node* GetFunctionContext() { return AstGraphBuilder::GetFunctionContext(); }
+ private:
+ SourcePositionTable* const source_positions_;
+ SourcePosition const start_position_;
+};
+
+
+class SourcePositionWrapper final : public Reducer {
+ public:
+ SourcePositionWrapper(Reducer* reducer, SourcePositionTable* table)
+ : reducer_(reducer), table_(table) {}
+ ~SourcePositionWrapper() final {}
+
+ Reduction Reduce(Node* node) final {
+ SourcePosition const pos = table_->GetSourcePosition(node);
+ SourcePositionTable::Scope position(table_, pos);
+ return reducer_->Reduce(node);
+ }
+
+ void Finalize() final { reducer_->Finalize(); }
private:
- SourcePositionTable* source_positions_;
+ Reducer* const reducer_;
+ SourcePositionTable* const table_;
+
+ DISALLOW_COPY_AND_ASSIGN(SourcePositionWrapper);
};
+class JSGraphReducer final : public GraphReducer {
+ public:
+ JSGraphReducer(JSGraph* jsgraph, Zone* zone)
+ : GraphReducer(zone, jsgraph->graph(), jsgraph->Dead()) {}
+ ~JSGraphReducer() final {}
+};
+
+
+void AddReducer(PipelineData* data, GraphReducer* graph_reducer,
+ Reducer* reducer) {
+ if (data->info()->is_source_positions_enabled()) {
+ void* const buffer = data->graph_zone()->New(sizeof(SourcePositionWrapper));
+ SourcePositionWrapper* const wrapper =
+ new (buffer) SourcePositionWrapper(reducer, data->source_positions());
+ graph_reducer->AddReducer(wrapper);
+ } else {
+ graph_reducer->AddReducer(reducer);
+ }
+}
+
+
class PipelineRunScope {
public:
PipelineRunScope(PipelineData* data, const char* phase_name)
@@ -333,6 +460,8 @@
ZonePool::Scope zone_scope_;
};
+} // namespace
+
template <typename Phase>
void Pipeline::Run() {
@@ -361,33 +490,39 @@
};
-struct GraphBuilderPhase {
- static const char* phase_name() { return "graph builder"; }
+struct TypeHintAnalysisPhase {
+ static const char* phase_name() { return "type hint analysis"; }
void Run(PipelineData* data, Zone* temp_zone) {
- AstGraphBuilderWithPositions graph_builder(
- temp_zone, data->info(), data->jsgraph(), data->loop_assignment(),
- data->source_positions());
- if (graph_builder.CreateGraph()) {
- data->set_context_node(graph_builder.GetFunctionContext());
- } else {
- data->set_compilation_failed();
- }
+ TypeHintAnalyzer analyzer(data->graph_zone());
+ Handle<Code> code(data->info()->shared_info()->code(), data->isolate());
+ TypeHintAnalysis* type_hint_analysis = analyzer.Analyze(code);
+ data->set_type_hint_analysis(type_hint_analysis);
}
};
-struct ContextSpecializerPhase {
- static const char* phase_name() { return "context specializing"; }
+struct GraphBuilderPhase {
+ static const char* phase_name() { return "graph builder"; }
void Run(PipelineData* data, Zone* temp_zone) {
- SourcePositionTable::Scope pos(data->source_positions(),
- SourcePosition::Unknown());
- JSContextSpecializer spec(data->info(), data->jsgraph(),
- data->context_node());
- GraphReducer graph_reducer(data->graph(), temp_zone);
- graph_reducer.AddReducer(&spec);
- graph_reducer.ReduceGraph();
+ bool stack_check = !data->info()->IsStub();
+ bool succeeded = false;
+
+ if (data->info()->shared_info()->HasBytecodeArray()) {
+ BytecodeGraphBuilder graph_builder(temp_zone, data->info(),
+ data->jsgraph());
+ succeeded = graph_builder.CreateGraph(stack_check);
+ } else {
+ AstGraphBuilderWithPositions graph_builder(
+ temp_zone, data->info(), data->jsgraph(), data->loop_assignment(),
+ data->type_hint_analysis(), data->source_positions());
+ succeeded = graph_builder.CreateGraph(stack_check);
+ }
+
+ if (!succeeded) {
+ data->set_compilation_failed();
+ }
}
};
@@ -396,10 +531,51 @@
static const char* phase_name() { return "inlining"; }
void Run(PipelineData* data, Zone* temp_zone) {
- SourcePositionTable::Scope pos(data->source_positions(),
- SourcePosition::Unknown());
- JSInliner inliner(temp_zone, data->info(), data->jsgraph());
- inliner.Inline();
+ JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
+ DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
+ data->common());
+ CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
+ data->common(), data->machine());
+ JSCallReducer call_reducer(data->jsgraph(),
+ data->info()->is_deoptimization_enabled()
+ ? JSCallReducer::kDeoptimizationEnabled
+ : JSCallReducer::kNoFlags,
+ data->native_context());
+ JSContextSpecialization context_specialization(
+ &graph_reducer, data->jsgraph(),
+ data->info()->is_function_context_specializing()
+ ? data->info()->context()
+ : MaybeHandle<Context>());
+ JSFrameSpecialization frame_specialization(data->info()->osr_frame(),
+ data->jsgraph());
+ JSGlobalObjectSpecialization global_object_specialization(
+ &graph_reducer, data->jsgraph(),
+ data->info()->is_deoptimization_enabled()
+ ? JSGlobalObjectSpecialization::kDeoptimizationEnabled
+ : JSGlobalObjectSpecialization::kNoFlags,
+ data->native_context(), data->info()->dependencies());
+ JSNativeContextSpecialization native_context_specialization(
+ &graph_reducer, data->jsgraph(),
+ data->info()->is_deoptimization_enabled()
+ ? JSNativeContextSpecialization::kDeoptimizationEnabled
+ : JSNativeContextSpecialization::kNoFlags,
+ data->native_context(), data->info()->dependencies(), temp_zone);
+ JSInliningHeuristic inlining(&graph_reducer,
+ data->info()->is_inlining_enabled()
+ ? JSInliningHeuristic::kGeneralInlining
+ : JSInliningHeuristic::kRestrictedInlining,
+ temp_zone, data->info(), data->jsgraph());
+ AddReducer(data, &graph_reducer, &dead_code_elimination);
+ AddReducer(data, &graph_reducer, &common_reducer);
+ if (data->info()->is_frame_specializing()) {
+ AddReducer(data, &graph_reducer, &frame_specialization);
+ }
+ AddReducer(data, &graph_reducer, &global_object_specialization);
+ AddReducer(data, &graph_reducer, &native_context_specialization);
+ AddReducer(data, &graph_reducer, &context_specialization);
+ AddReducer(data, &graph_reducer, &call_reducer);
+ AddReducer(data, &graph_reducer, &inlining);
+ graph_reducer.ReduceGraph();
}
};
@@ -407,7 +583,21 @@
struct TyperPhase {
static const char* phase_name() { return "typer"; }
- void Run(PipelineData* data, Zone* temp_zone) { data->typer()->Run(); }
+ void Run(PipelineData* data, Zone* temp_zone, Typer* typer) {
+ NodeVector roots(temp_zone);
+ data->jsgraph()->GetCachedNodes(&roots);
+ typer->Run(roots);
+ }
+};
+
+
+struct OsrDeconstructionPhase {
+ static const char* phase_name() { return "OSR deconstruction"; }
+
+ void Run(PipelineData* data, Zone* temp_zone) {
+ OsrHelper osr_helper(data->info());
+ osr_helper.Deconstruct(data->jsgraph(), data->common(), temp_zone);
+ }
};
@@ -415,21 +605,66 @@
static const char* phase_name() { return "typed lowering"; }
void Run(PipelineData* data, Zone* temp_zone) {
- SourcePositionTable::Scope pos(data->source_positions(),
- SourcePosition::Unknown());
- ValueNumberingReducer vn_reducer(temp_zone);
- LoadElimination load_elimination;
- JSBuiltinReducer builtin_reducer(data->jsgraph());
- JSTypedLowering typed_lowering(data->jsgraph(), temp_zone);
- SimplifiedOperatorReducer simple_reducer(data->jsgraph());
- CommonOperatorReducer common_reducer;
- GraphReducer graph_reducer(data->graph(), temp_zone);
- graph_reducer.AddReducer(&vn_reducer);
- graph_reducer.AddReducer(&builtin_reducer);
- graph_reducer.AddReducer(&typed_lowering);
- graph_reducer.AddReducer(&load_elimination);
- graph_reducer.AddReducer(&simple_reducer);
- graph_reducer.AddReducer(&common_reducer);
+ JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
+ DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
+ data->common());
+ LoadElimination load_elimination(&graph_reducer);
+ JSBuiltinReducer builtin_reducer(&graph_reducer, data->jsgraph());
+ JSTypedLowering::Flags typed_lowering_flags = JSTypedLowering::kNoFlags;
+ if (data->info()->is_deoptimization_enabled()) {
+ typed_lowering_flags |= JSTypedLowering::kDeoptimizationEnabled;
+ }
+ if (data->info()->shared_info()->HasBytecodeArray()) {
+ typed_lowering_flags |= JSTypedLowering::kDisableBinaryOpReduction;
+ }
+ JSTypedLowering typed_lowering(&graph_reducer, data->info()->dependencies(),
+ typed_lowering_flags, data->jsgraph(),
+ temp_zone);
+ JSIntrinsicLowering intrinsic_lowering(
+ &graph_reducer, data->jsgraph(),
+ data->info()->is_deoptimization_enabled()
+ ? JSIntrinsicLowering::kDeoptimizationEnabled
+ : JSIntrinsicLowering::kDeoptimizationDisabled);
+ CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
+ data->common(), data->machine());
+ AddReducer(data, &graph_reducer, &dead_code_elimination);
+ AddReducer(data, &graph_reducer, &builtin_reducer);
+ AddReducer(data, &graph_reducer, &typed_lowering);
+ AddReducer(data, &graph_reducer, &intrinsic_lowering);
+ AddReducer(data, &graph_reducer, &load_elimination);
+ AddReducer(data, &graph_reducer, &common_reducer);
+ graph_reducer.ReduceGraph();
+ }
+};
+
+
+struct BranchEliminationPhase {
+ static const char* phase_name() { return "branch condition elimination"; }
+
+ void Run(PipelineData* data, Zone* temp_zone) {
+ JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
+ BranchElimination branch_condition_elimination(&graph_reducer,
+ data->jsgraph(), temp_zone);
+ DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
+ data->common());
+ AddReducer(data, &graph_reducer, &branch_condition_elimination);
+ AddReducer(data, &graph_reducer, &dead_code_elimination);
+ graph_reducer.ReduceGraph();
+ }
+};
+
+
+struct EscapeAnalysisPhase {
+ static const char* phase_name() { return "escape analysis"; }
+
+ void Run(PipelineData* data, Zone* temp_zone) {
+ EscapeAnalysis escape_analysis(data->graph(), data->jsgraph()->common(),
+ temp_zone);
+ escape_analysis.Run();
+ JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
+ EscapeAnalysisReducer escape_reducer(&graph_reducer, data->jsgraph(),
+ &escape_analysis, temp_zone);
+ AddReducer(data, &graph_reducer, &escape_reducer);
graph_reducer.ReduceGraph();
}
};
@@ -439,63 +674,96 @@
static const char* phase_name() { return "simplified lowering"; }
void Run(PipelineData* data, Zone* temp_zone) {
- SourcePositionTable::Scope pos(data->source_positions(),
- SourcePosition::Unknown());
- SimplifiedLowering lowering(data->jsgraph(), temp_zone);
+ SimplifiedLowering lowering(data->jsgraph(), temp_zone,
+ data->source_positions());
lowering.LowerAllNodes();
- ValueNumberingReducer vn_reducer(temp_zone);
+ JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
+ DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
+ data->common());
SimplifiedOperatorReducer simple_reducer(data->jsgraph());
+ ValueNumberingReducer value_numbering(temp_zone);
MachineOperatorReducer machine_reducer(data->jsgraph());
- CommonOperatorReducer common_reducer;
- GraphReducer graph_reducer(data->graph(), temp_zone);
- graph_reducer.AddReducer(&vn_reducer);
- graph_reducer.AddReducer(&simple_reducer);
- graph_reducer.AddReducer(&machine_reducer);
- graph_reducer.AddReducer(&common_reducer);
+ CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
+ data->common(), data->machine());
+ AddReducer(data, &graph_reducer, &dead_code_elimination);
+ AddReducer(data, &graph_reducer, &simple_reducer);
+ AddReducer(data, &graph_reducer, &value_numbering);
+ AddReducer(data, &graph_reducer, &machine_reducer);
+ AddReducer(data, &graph_reducer, &common_reducer);
graph_reducer.ReduceGraph();
}
};
+struct ControlFlowOptimizationPhase {
+ static const char* phase_name() { return "control flow optimization"; }
+
+ void Run(PipelineData* data, Zone* temp_zone) {
+ ControlFlowOptimizer optimizer(data->graph(), data->common(),
+ data->machine(), temp_zone);
+ optimizer.Optimize();
+ }
+};
+
+
struct ChangeLoweringPhase {
static const char* phase_name() { return "change lowering"; }
void Run(PipelineData* data, Zone* temp_zone) {
- SourcePositionTable::Scope pos(data->source_positions(),
- SourcePosition::Unknown());
- Linkage linkage(data->graph_zone(), data->info());
- ValueNumberingReducer vn_reducer(temp_zone);
+ JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
+ DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
+ data->common());
SimplifiedOperatorReducer simple_reducer(data->jsgraph());
- ChangeLowering lowering(data->jsgraph(), &linkage);
+ ValueNumberingReducer value_numbering(temp_zone);
+ ChangeLowering lowering(data->jsgraph());
MachineOperatorReducer machine_reducer(data->jsgraph());
- CommonOperatorReducer common_reducer;
- GraphReducer graph_reducer(data->graph(), temp_zone);
- graph_reducer.AddReducer(&vn_reducer);
- graph_reducer.AddReducer(&simple_reducer);
- graph_reducer.AddReducer(&lowering);
- graph_reducer.AddReducer(&machine_reducer);
- graph_reducer.AddReducer(&common_reducer);
+ CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
+ data->common(), data->machine());
+ AddReducer(data, &graph_reducer, &dead_code_elimination);
+ AddReducer(data, &graph_reducer, &simple_reducer);
+ AddReducer(data, &graph_reducer, &value_numbering);
+ AddReducer(data, &graph_reducer, &lowering);
+ AddReducer(data, &graph_reducer, &machine_reducer);
+ AddReducer(data, &graph_reducer, &common_reducer);
graph_reducer.ReduceGraph();
}
};
-struct ControlReductionPhase {
+struct EarlyGraphTrimmingPhase {
+ static const char* phase_name() { return "early graph trimming"; }
void Run(PipelineData* data, Zone* temp_zone) {
- SourcePositionTable::Scope pos(data->source_positions(),
- SourcePosition::Unknown());
- ControlReducer::ReduceGraph(temp_zone, data->jsgraph(), data->common());
+ GraphTrimmer trimmer(temp_zone, data->graph());
+ NodeVector roots(temp_zone);
+ data->jsgraph()->GetCachedNodes(&roots);
+ trimmer.TrimGraph(roots.begin(), roots.end());
}
};
-struct EarlyControlReductionPhase : ControlReductionPhase {
- static const char* phase_name() { return "early control reduction"; }
+struct LateGraphTrimmingPhase {
+ static const char* phase_name() { return "late graph trimming"; }
+ void Run(PipelineData* data, Zone* temp_zone) {
+ GraphTrimmer trimmer(temp_zone, data->graph());
+ NodeVector roots(temp_zone);
+ data->jsgraph()->GetCachedNodes(&roots);
+ trimmer.TrimGraph(roots.begin(), roots.end());
+ }
};
-struct LateControlReductionPhase : ControlReductionPhase {
- static const char* phase_name() { return "late control reduction"; }
+struct StressLoopPeelingPhase {
+ static const char* phase_name() { return "stress loop peeling"; }
+
+ void Run(PipelineData* data, Zone* temp_zone) {
+ // Peel the first outer loop for testing.
+ // TODO(titzer): peel all loops? the N'th loop? Innermost loops?
+ LoopTree* loop_tree = LoopFinder::BuildLoopTree(data->graph(), temp_zone);
+ if (loop_tree != nullptr && loop_tree->outer_loops().size() > 0) {
+ LoopPeeler::Peel(data->graph(), data->common(), loop_tree,
+ loop_tree->outer_loops()[0], temp_zone);
+ }
+ }
};
@@ -503,13 +771,23 @@
static const char* phase_name() { return "generic lowering"; }
void Run(PipelineData* data, Zone* temp_zone) {
- SourcePositionTable::Scope pos(data->source_positions(),
- SourcePosition::Unknown());
- JSGenericLowering generic(data->info(), data->jsgraph());
- SelectLowering select(data->jsgraph()->graph(), data->jsgraph()->common());
- GraphReducer graph_reducer(data->graph(), temp_zone);
- graph_reducer.AddReducer(&generic);
- graph_reducer.AddReducer(&select);
+ JSGraphReducer graph_reducer(data->jsgraph(), temp_zone);
+ JSContextRelaxation context_relaxing;
+ DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
+ data->common());
+ CommonOperatorReducer common_reducer(&graph_reducer, data->graph(),
+ data->common(), data->machine());
+ JSGenericLowering generic_lowering(data->info()->is_typing_enabled(),
+ data->jsgraph());
+ SelectLowering select_lowering(data->jsgraph()->graph(),
+ data->jsgraph()->common());
+ TailCallOptimization tco(data->common(), data->graph());
+ AddReducer(data, &graph_reducer, &context_relaxing);
+ AddReducer(data, &graph_reducer, &dead_code_elimination);
+ AddReducer(data, &graph_reducer, &common_reducer);
+ AddReducer(data, &graph_reducer, &generic_lowering);
+ AddReducer(data, &graph_reducer, &select_lowering);
+ AddReducer(data, &graph_reducer, &tco);
graph_reducer.ReduceGraph();
}
};
@@ -519,9 +797,11 @@
static const char* phase_name() { return "scheduling"; }
void Run(PipelineData* data, Zone* temp_zone) {
- Schedule* schedule = Scheduler::ComputeSchedule(temp_zone, data->graph());
- TraceSchedule(schedule);
- if (VerifyGraphs()) ScheduleVerifier::Run(schedule);
+ Schedule* schedule = Scheduler::ComputeSchedule(
+ temp_zone, data->graph(), data->info()->is_splitting_enabled()
+ ? Scheduler::kSplitNodes
+ : Scheduler::kNoFlags);
+ if (FLAG_turbo_verify) ScheduleVerifier::Run(schedule);
data->set_schedule(schedule);
}
};
@@ -531,9 +811,12 @@
static const char* phase_name() { return "select instructions"; }
void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) {
- InstructionSelector selector(temp_zone, data->graph(), linkage,
- data->sequence(), data->schedule(),
- data->source_positions());
+ InstructionSelector selector(
+ temp_zone, data->graph()->NodeCount(), linkage, data->sequence(),
+ data->schedule(), data->source_positions(),
+ data->info()->is_source_positions_enabled()
+ ? InstructionSelector::kAllSourcePositions
+ : InstructionSelector::kCallSourcePositions);
selector.SelectInstructions();
}
};
@@ -543,7 +826,8 @@
static const char* phase_name() { return "meet register constraints"; }
void Run(PipelineData* data, Zone* temp_zone) {
- data->register_allocator()->MeetRegisterConstraints();
+ ConstraintBuilder builder(data->register_allocation_data());
+ builder.MeetRegisterConstraints();
}
};
@@ -552,7 +836,8 @@
static const char* phase_name() { return "resolve phis"; }
void Run(PipelineData* data, Zone* temp_zone) {
- data->register_allocator()->ResolvePhis();
+ ConstraintBuilder builder(data->register_allocation_data());
+ builder.ResolvePhis();
}
};
@@ -561,34 +846,73 @@
static const char* phase_name() { return "build live ranges"; }
void Run(PipelineData* data, Zone* temp_zone) {
- data->register_allocator()->BuildLiveRanges();
+ LiveRangeBuilder builder(data->register_allocation_data(), temp_zone);
+ builder.BuildLiveRanges();
}
};
+struct SplinterLiveRangesPhase {
+ static const char* phase_name() { return "splinter live ranges"; }
+
+ void Run(PipelineData* data, Zone* temp_zone) {
+ LiveRangeSeparator live_range_splinterer(data->register_allocation_data(),
+ temp_zone);
+ live_range_splinterer.Splinter();
+ }
+};
+
+
+template <typename RegAllocator>
struct AllocateGeneralRegistersPhase {
static const char* phase_name() { return "allocate general registers"; }
void Run(PipelineData* data, Zone* temp_zone) {
- data->register_allocator()->AllocateGeneralRegisters();
+ RegAllocator allocator(data->register_allocation_data(), GENERAL_REGISTERS,
+ temp_zone);
+ allocator.AllocateRegisters();
}
};
+template <typename RegAllocator>
struct AllocateDoubleRegistersPhase {
static const char* phase_name() { return "allocate double registers"; }
void Run(PipelineData* data, Zone* temp_zone) {
- data->register_allocator()->AllocateDoubleRegisters();
+ RegAllocator allocator(data->register_allocation_data(), DOUBLE_REGISTERS,
+ temp_zone);
+ allocator.AllocateRegisters();
}
};
-struct ReuseSpillSlotsPhase {
- static const char* phase_name() { return "reuse spill slots"; }
+struct MergeSplintersPhase {
+ static const char* phase_name() { return "merge splintered ranges"; }
+ void Run(PipelineData* pipeline_data, Zone* temp_zone) {
+ RegisterAllocationData* data = pipeline_data->register_allocation_data();
+ LiveRangeMerger live_range_merger(data, temp_zone);
+ live_range_merger.Merge();
+ }
+};
+
+
+struct LocateSpillSlotsPhase {
+ static const char* phase_name() { return "locate spill slots"; }
void Run(PipelineData* data, Zone* temp_zone) {
- data->register_allocator()->ReuseSpillSlots();
+ SpillSlotLocator locator(data->register_allocation_data());
+ locator.LocateSpillSlots();
+ }
+};
+
+
+struct AssignSpillSlotsPhase {
+ static const char* phase_name() { return "assign spill slots"; }
+
+ void Run(PipelineData* data, Zone* temp_zone) {
+ OperandAssigner assigner(data->register_allocation_data());
+ assigner.AssignSpillSlots();
}
};
@@ -597,16 +921,18 @@
static const char* phase_name() { return "commit assignment"; }
void Run(PipelineData* data, Zone* temp_zone) {
- data->register_allocator()->CommitAssignment();
+ OperandAssigner assigner(data->register_allocation_data());
+ assigner.CommitAssignment();
}
};
-struct PopulatePointerMapsPhase {
+struct PopulateReferenceMapsPhase {
static const char* phase_name() { return "populate pointer maps"; }
void Run(PipelineData* data, Zone* temp_zone) {
- data->register_allocator()->PopulatePointerMaps();
+ ReferenceMapPopulator populator(data->register_allocation_data());
+ populator.PopulateReferenceMaps();
}
};
@@ -615,7 +941,8 @@
static const char* phase_name() { return "connect ranges"; }
void Run(PipelineData* data, Zone* temp_zone) {
- data->register_allocator()->ConnectRanges();
+ LiveRangeConnector connector(data->register_allocation_data());
+ connector.ConnectRanges(temp_zone);
}
};
@@ -624,7 +951,8 @@
static const char* phase_name() { return "resolve control flow"; }
void Run(PipelineData* data, Zone* temp_zone) {
- data->register_allocator()->ResolveControlFlow();
+ LiveRangeConnector connector(data->register_allocation_data());
+ connector.ResolveControlFlow(temp_zone);
}
};
@@ -639,11 +967,20 @@
};
+struct FrameElisionPhase {
+ static const char* phase_name() { return "frame elision"; }
+
+ void Run(PipelineData* data, Zone* temp_zone) {
+ FrameElider(data->sequence()).Run();
+ }
+};
+
+
struct JumpThreadingPhase {
static const char* phase_name() { return "jump threading"; }
void Run(PipelineData* data, Zone* temp_zone) {
- ZoneVector<BasicBlock::RpoNumber> result(temp_zone);
+ ZoneVector<RpoNumber> result(temp_zone);
if (JumpThreading::ComputeForwarding(temp_zone, result, data->sequence())) {
JumpThreading::ApplyForwarding(result, data->sequence());
}
@@ -668,52 +1005,21 @@
void Run(PipelineData* data, Zone* temp_zone, const char* phase) {
CompilationInfo* info = data->info();
Graph* graph = data->graph();
- char buffer[256];
- Vector<char> filename(buffer, sizeof(buffer));
- SmartArrayPointer<char> functionname;
- if (!info->shared_info().is_null()) {
- functionname = info->shared_info()->DebugName()->ToCString();
- if (strlen(functionname.get()) > 0) {
- SNPrintF(filename, "turbo-%s-%s", functionname.get(), phase);
- } else {
- SNPrintF(filename, "turbo-%p-%s", static_cast<void*>(info), phase);
- }
- } else {
- SNPrintF(filename, "turbo-none-%s", phase);
- }
- std::replace(filename.start(), filename.start() + filename.length(), ' ',
- '_');
-
- { // Print dot.
- char dot_buffer[256];
- Vector<char> dot_filename(dot_buffer, sizeof(dot_buffer));
- SNPrintF(dot_filename, "%s.dot", filename.start());
- FILE* dot_file = base::OS::FOpen(dot_filename.start(), "w+");
- if (dot_file == nullptr) return;
- OFStream dot_of(dot_file);
- dot_of << AsDOT(*graph);
- fclose(dot_file);
- }
{ // Print JSON.
- char json_buffer[256];
- Vector<char> json_filename(json_buffer, sizeof(json_buffer));
- SNPrintF(json_filename, "%s.json", filename.start());
- FILE* json_file = base::OS::FOpen(json_filename.start(), "w+");
+ FILE* json_file = OpenVisualizerLogFile(info, nullptr, "json", "a+");
if (json_file == nullptr) return;
OFStream json_of(json_file);
- json_of << AsJSON(*graph);
+ json_of << "{\"name\":\"" << phase << "\",\"type\":\"graph\",\"data\":"
+ << AsJSON(*graph, data->source_positions()) << "},\n";
fclose(json_file);
}
- OFStream os(stdout);
if (FLAG_trace_turbo_graph) { // Simple textual RPO.
+ OFStream os(stdout);
os << "-- Graph after " << phase << " -- " << std::endl;
os << AsRPO(*graph);
}
-
- os << "-- " << phase << " graph printed to file " << filename.start()
- << std::endl;
}
};
@@ -730,7 +1036,7 @@
void Pipeline::BeginPhaseKind(const char* phase_kind_name) {
- if (data_->pipeline_statistics() != NULL) {
+ if (data_->pipeline_statistics() != nullptr) {
data_->pipeline_statistics()->BeginPhaseKind(phase_kind_name);
}
}
@@ -740,45 +1046,62 @@
if (FLAG_trace_turbo) {
Run<PrintGraphPhase>(phase);
}
- if (VerifyGraphs()) {
+ if (FLAG_turbo_verify) {
Run<VerifyGraphPhase>(untyped);
}
}
Handle<Code> Pipeline::GenerateCode() {
- // This list must be kept in sync with DONT_TURBOFAN_NODE in ast.cc.
- if (info()->function()->dont_optimize_reason() == kTryCatchStatement ||
- info()->function()->dont_optimize_reason() == kTryFinallyStatement ||
- // TODO(turbofan): Make ES6 for-of work and remove this bailout.
- info()->function()->dont_optimize_reason() == kForOfStatement ||
- // TODO(turbofan): Make super work and remove this bailout.
- info()->function()->dont_optimize_reason() == kSuperReference ||
- // TODO(turbofan): Make class literals work and remove this bailout.
- info()->function()->dont_optimize_reason() == kClassLiteral ||
- // TODO(turbofan): Make OSR work and remove this bailout.
- info()->is_osr()) {
+ // TODO(mstarzinger): This is just a temporary hack to make TurboFan work,
+ // the correct solution is to restore the context register after invoking
+ // builtins from full-codegen.
+ if (Context::IsJSBuiltin(isolate()->native_context(), info()->closure())) {
return Handle<Code>::null();
}
- ZonePool zone_pool(isolate());
- SmartPointer<PipelineStatistics> pipeline_statistics;
+ ZonePool zone_pool;
+ base::SmartPointer<PipelineStatistics> pipeline_statistics;
if (FLAG_turbo_stats) {
pipeline_statistics.Reset(new PipelineStatistics(info(), &zone_pool));
pipeline_statistics->BeginPhaseKind("initializing");
}
- PipelineData data(&zone_pool, info());
+ if (FLAG_trace_turbo) {
+ FILE* json_file = OpenVisualizerLogFile(info(), nullptr, "json", "w+");
+ if (json_file != nullptr) {
+ OFStream json_of(json_file);
+ Handle<Script> script = info()->script();
+ FunctionLiteral* function = info()->literal();
+ base::SmartArrayPointer<char> function_name = info()->GetDebugName();
+ int pos = info()->shared_info()->start_position();
+ json_of << "{\"function\":\"" << function_name.get()
+ << "\", \"sourcePosition\":" << pos << ", \"source\":\"";
+ if (!script->IsUndefined() && !script->source()->IsUndefined()) {
+ DisallowHeapAllocation no_allocation;
+ int start = function->start_position();
+ int len = function->end_position() - start;
+ String::SubStringRange source(String::cast(script->source()), start,
+ len);
+ for (const auto& c : source) {
+ json_of << AsEscapedUC16ForJSON(c);
+ }
+ }
+ json_of << "\",\n\"phases\":[";
+ fclose(json_file);
+ }
+ }
+
+ PipelineData data(&zone_pool, info(), pipeline_statistics.get());
this->data_ = &data;
- data.Initialize(pipeline_statistics.get());
BeginPhaseKind("graph creation");
if (FLAG_trace_turbo) {
OFStream os(stdout);
os << "---------------------------------------------------\n"
- << "Begin compiling method " << GetDebugName(info()).get()
+ << "Begin compiling method " << info()->GetDebugName().get()
<< " using Turbofan" << std::endl;
TurboCfgFile tcf(isolate());
tcf << AsC1VCompilation(info());
@@ -790,35 +1113,42 @@
Run<LoopAssignmentAnalysisPhase>();
}
+ if (info()->is_typing_enabled()) {
+ Run<TypeHintAnalysisPhase>();
+ }
+
Run<GraphBuilderPhase>();
if (data.compilation_failed()) return Handle<Code>::null();
RunPrintAndVerify("Initial untyped", true);
- Run<EarlyControlReductionPhase>();
- RunPrintAndVerify("Early Control reduced", true);
-
- if (info()->is_context_specializing()) {
- // Specialize the code to the context as aggressively as possible.
- Run<ContextSpecializerPhase>();
- RunPrintAndVerify("Context specialized", true);
+ // Perform OSR deconstruction.
+ if (info()->is_osr()) {
+ Run<OsrDeconstructionPhase>();
+ RunPrintAndVerify("OSR deconstruction", true);
}
- if (info()->is_inlining_enabled()) {
- Run<InliningPhase>();
- RunPrintAndVerify("Inlined", true);
- }
+ // Perform function context specialization and inlining (if enabled).
+ Run<InliningPhase>();
+ RunPrintAndVerify("Inlined", true);
+
+ // Remove dead->live edges from the graph.
+ Run<EarlyGraphTrimmingPhase>();
+ RunPrintAndVerify("Early trimmed", true);
if (FLAG_print_turbo_replay) {
// Print a replay of the initial graph.
GraphReplayPrinter::PrintReplay(data.graph());
}
- // Bailout here in case target architecture is not supported.
- if (!SupportedTarget()) return Handle<Code>::null();
-
+ base::SmartPointer<Typer> typer;
if (info()->is_typing_enabled()) {
// Type the graph.
- Run<TyperPhase>();
+ typer.Reset(new Typer(isolate(), data.graph(),
+ info()->is_deoptimization_enabled()
+ ? Typer::kDeoptimizationEnabled
+ : Typer::kNoFlags,
+ info()->dependencies()));
+ Run<TyperPhase>(typer.get());
RunPrintAndVerify("Typed");
}
@@ -829,17 +1159,33 @@
Run<TypedLoweringPhase>();
RunPrintAndVerify("Lowered typed");
+ if (FLAG_turbo_stress_loop_peeling) {
+ Run<StressLoopPeelingPhase>();
+ RunPrintAndVerify("Loop peeled");
+ }
+
+ if (FLAG_turbo_escape) {
+ Run<EscapeAnalysisPhase>();
+ RunPrintAndVerify("Escape Analysed");
+ }
+
// Lower simplified operators and insert changes.
Run<SimplifiedLoweringPhase>();
RunPrintAndVerify("Lowered simplified");
+ Run<BranchEliminationPhase>();
+ RunPrintAndVerify("Branch conditions eliminated");
+
+ // Optimize control flow.
+ if (FLAG_turbo_cf_optimization) {
+ Run<ControlFlowOptimizationPhase>();
+ RunPrintAndVerify("Control flow optimized");
+ }
+
// Lower changes that have been inserted before.
Run<ChangeLoweringPhase>();
- // // TODO(jarin, rossberg): Remove UNTYPED once machine typing works.
+ // TODO(jarin, rossberg): Remove UNTYPED once machine typing works.
RunPrintAndVerify("Lowered changes", true);
-
- Run<LateControlReductionPhase>();
- RunPrintAndVerify("Late Control reduced");
}
// Lower any remaining generic JSOperators.
@@ -847,32 +1193,55 @@
// TODO(jarin, rossberg): Remove UNTYPED once machine typing works.
RunPrintAndVerify("Lowered generic", true);
+ Run<LateGraphTrimmingPhase>();
+ // TODO(jarin, rossberg): Remove UNTYPED once machine typing works.
+ RunPrintAndVerify("Late trimmed", true);
+
BeginPhaseKind("block building");
data.source_positions()->RemoveDecorator();
- // Compute a schedule.
- Run<ComputeSchedulePhase>();
+ // Kill the Typer and thereby uninstall the decorator (if any).
+ typer.Reset(nullptr);
- {
- // Generate optimized code.
- Linkage linkage(data.instruction_zone(), info());
- GenerateCode(&linkage);
+ return ScheduleAndGenerateCode(
+ Linkage::ComputeIncoming(data.instruction_zone(), info()));
+}
+
+
+Handle<Code> Pipeline::GenerateCodeForCodeStub(Isolate* isolate,
+ CallDescriptor* call_descriptor,
+ Graph* graph, Schedule* schedule,
+ Code::Kind kind,
+ const char* debug_name) {
+ CompilationInfo info(debug_name, isolate, graph->zone());
+ info.set_output_code_kind(kind);
+
+ // Construct a pipeline for scheduling and code generation.
+ ZonePool zone_pool;
+ PipelineData data(&zone_pool, &info, graph, schedule);
+ base::SmartPointer<PipelineStatistics> pipeline_statistics;
+ if (FLAG_turbo_stats) {
+ pipeline_statistics.Reset(new PipelineStatistics(&info, &zone_pool));
+ pipeline_statistics->BeginPhaseKind("stub codegen");
}
- Handle<Code> code = data.code();
- info()->SetCode(code);
- // Print optimized code.
- v8::internal::CodeGenerator::PrintCode(code, info());
+ Pipeline pipeline(&info);
+ pipeline.data_ = &data;
+ DCHECK_NOT_NULL(data.schedule());
if (FLAG_trace_turbo) {
- OFStream os(stdout);
- os << "---------------------------------------------------\n"
- << "Finished compiling method " << GetDebugName(info()).get()
- << " using Turbofan" << std::endl;
+ FILE* json_file = OpenVisualizerLogFile(&info, nullptr, "json", "w+");
+ if (json_file != nullptr) {
+ OFStream json_of(json_file);
+ json_of << "{\"function\":\"" << info.GetDebugName().get()
+ << "\", \"source\":\"\",\n\"phases\":[";
+ fclose(json_file);
+ }
+ pipeline.Run<PrintGraphPhase>("Machine");
}
- return code;
+ return pipeline.ScheduleAndGenerateCode(call_descriptor);
}
@@ -885,70 +1254,53 @@
}
-Handle<Code> Pipeline::GenerateCodeForTesting(CallDescriptor* call_descriptor,
- Graph* graph,
- Schedule* schedule) {
- CompilationInfo info(graph->zone()->isolate(), graph->zone());
- return GenerateCodeForTesting(&info, call_descriptor, graph, schedule);
-}
-
-
Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info,
CallDescriptor* call_descriptor,
Graph* graph,
Schedule* schedule) {
- CHECK(SupportedBackend());
- ZonePool zone_pool(info->isolate());
+ // Construct a pipeline for scheduling and code generation.
+ ZonePool zone_pool;
+ PipelineData data(&zone_pool, info, graph, schedule);
+ base::SmartPointer<PipelineStatistics> pipeline_statistics;
+ if (FLAG_turbo_stats) {
+ pipeline_statistics.Reset(new PipelineStatistics(info, &zone_pool));
+ pipeline_statistics->BeginPhaseKind("test codegen");
+ }
+
Pipeline pipeline(info);
- PipelineData data(&zone_pool, info);
pipeline.data_ = &data;
- data.InitializeTorTesting(graph, schedule);
- if (schedule == NULL) {
+ if (data.schedule() == nullptr) {
// TODO(rossberg): Should this really be untyped?
pipeline.RunPrintAndVerify("Machine", true);
- pipeline.Run<ComputeSchedulePhase>();
- } else {
- TraceSchedule(schedule);
}
- Linkage linkage(info->zone(), call_descriptor);
- pipeline.GenerateCode(&linkage);
- Handle<Code> code = data.code();
-
-#if ENABLE_DISASSEMBLER
- if (!code.is_null() && FLAG_print_opt_code) {
- CodeTracer::Scope tracing_scope(info->isolate()->GetCodeTracer());
- OFStream os(tracing_scope.file());
- code->Disassemble("test code", os);
- }
-#endif
- return code;
+ return pipeline.ScheduleAndGenerateCode(call_descriptor);
}
bool Pipeline::AllocateRegistersForTesting(const RegisterConfiguration* config,
InstructionSequence* sequence,
bool run_verifier) {
- CompilationInfo info(sequence->zone()->isolate(), sequence->zone());
- ZonePool zone_pool(sequence->zone()->isolate());
- PipelineData data(&zone_pool, &info);
- data.InitializeTorTesting(sequence);
+ CompilationInfo info("testing", sequence->isolate(), sequence->zone());
+ ZonePool zone_pool;
+ PipelineData data(&zone_pool, &info, sequence);
Pipeline pipeline(&info);
pipeline.data_ = &data;
- pipeline.AllocateRegisters(config, run_verifier);
+ pipeline.AllocateRegisters(config, nullptr, run_verifier);
return !data.compilation_failed();
}
-void Pipeline::GenerateCode(Linkage* linkage) {
+Handle<Code> Pipeline::ScheduleAndGenerateCode(
+ CallDescriptor* call_descriptor) {
PipelineData* data = this->data_;
- DCHECK_NOT_NULL(linkage);
DCHECK_NOT_NULL(data->graph());
- DCHECK_NOT_NULL(data->schedule());
- CHECK(SupportedBackend());
- BasicBlockProfiler::Data* profiler_data = NULL;
+ if (data->schedule() == nullptr) Run<ComputeSchedulePhase>();
+ TraceSchedule(data->info(), data->schedule());
+
+ BasicBlockProfiler::Data* profiler_data = nullptr;
if (FLAG_turbo_profiling) {
profiler_data = BasicBlockInstrumentor::Instrument(info(), data->graph(),
data->schedule());
@@ -957,7 +1309,8 @@
data->InitializeInstructionSequence();
// Select and schedule instructions covering the scheduled graph.
- Run<InstructionSelectionPhase>(linkage);
+ Linkage linkage(call_descriptor);
+ Run<InstructionSelectionPhase>(&linkage);
if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) {
TurboCfgFile tcf(isolate());
@@ -965,19 +1318,24 @@
data->sequence());
}
+ std::ostringstream source_position_output;
+ if (FLAG_trace_turbo) {
+ // Output source position information before the graph is deleted.
+ data_->source_positions()->Print(source_position_output);
+ }
+
data->DeleteGraphZone();
BeginPhaseKind("register allocation");
- bool run_verifier = false;
-#ifdef DEBUG
- run_verifier = true;
-#endif
+ bool run_verifier = FLAG_turbo_verify_allocation;
// Allocate registers.
- AllocateRegisters(RegisterConfiguration::ArchDefault(), run_verifier);
+ AllocateRegisters(
+ RegisterConfiguration::ArchDefault(RegisterConfiguration::TURBOFAN),
+ call_descriptor, run_verifier);
if (data->compilation_failed()) {
info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc);
- return;
+ return Handle<Code>();
}
BeginPhaseKind("code generation");
@@ -988,45 +1346,74 @@
}
// Generate final machine code.
- Run<GenerateCodePhase>(linkage);
+ Run<GenerateCodePhase>(&linkage);
- if (profiler_data != NULL) {
+ Handle<Code> code = data->code();
+ if (profiler_data != nullptr) {
#if ENABLE_DISASSEMBLER
std::ostringstream os;
- data->code()->Disassemble(NULL, os);
+ code->Disassemble(nullptr, os);
profiler_data->SetCode(&os);
#endif
}
+
+ info()->SetCode(code);
+ v8::internal::CodeGenerator::PrintCode(code, info());
+
+ if (FLAG_trace_turbo) {
+ FILE* json_file = OpenVisualizerLogFile(info(), nullptr, "json", "a+");
+ if (json_file != nullptr) {
+ OFStream json_of(json_file);
+ json_of
+ << "{\"name\":\"disassembly\",\"type\":\"disassembly\",\"data\":\"";
+#if ENABLE_DISASSEMBLER
+ std::stringstream disassembly_stream;
+ code->Disassemble(nullptr, disassembly_stream);
+ std::string disassembly_string(disassembly_stream.str());
+ for (const auto& c : disassembly_string) {
+ json_of << AsEscapedUC16ForJSON(c);
+ }
+#endif // ENABLE_DISASSEMBLER
+ json_of << "\"}\n],\n";
+ json_of << "\"nodePositions\":";
+ json_of << source_position_output.str();
+ json_of << "}";
+ fclose(json_file);
+ }
+ OFStream os(stdout);
+ os << "---------------------------------------------------\n"
+ << "Finished compiling method " << info()->GetDebugName().get()
+ << " using Turbofan" << std::endl;
+ }
+
+ return code;
}
void Pipeline::AllocateRegisters(const RegisterConfiguration* config,
+ CallDescriptor* descriptor,
bool run_verifier) {
PipelineData* data = this->data_;
- int node_count = data->sequence()->VirtualRegisterCount();
- if (node_count > UnallocatedOperand::kMaxVirtualRegisters) {
- data->set_compilation_failed();
- return;
- }
-
// Don't track usage for this zone in compiler stats.
- SmartPointer<Zone> verifier_zone;
+ base::SmartPointer<Zone> verifier_zone;
RegisterAllocatorVerifier* verifier = nullptr;
if (run_verifier) {
- verifier_zone.Reset(new Zone(info()->isolate()));
+ verifier_zone.Reset(new Zone());
verifier = new (verifier_zone.get()) RegisterAllocatorVerifier(
verifier_zone.get(), config, data->sequence());
}
- SmartArrayPointer<char> debug_name;
+ base::SmartArrayPointer<char> debug_name;
#ifdef DEBUG
- debug_name = GetDebugName(data->info());
+ debug_name = info()->GetDebugName();
#endif
- ZonePool::Scope zone_scope(data->zone_pool());
- data->InitializeRegisterAllocator(zone_scope.zone(), config,
- debug_name.get());
+ data->InitializeRegisterAllocationData(config, descriptor, debug_name.get());
+ if (info()->is_osr()) {
+ OsrHelper osr_helper(info());
+ osr_helper.SetupFrame(data->frame());
+ }
Run<MeetRegisterConstraintsPhase>();
Run<ResolvePhisPhase>();
@@ -1038,23 +1425,36 @@
<< printable;
}
if (verifier != nullptr) {
- CHECK(!data->register_allocator()->ExistsUseWithoutDefinition());
+ CHECK(!data->register_allocation_data()->ExistsUseWithoutDefinition());
+ CHECK(data->register_allocation_data()
+ ->RangesDefinedInDeferredStayInDeferred());
}
- Run<AllocateGeneralRegistersPhase>();
- if (!data->register_allocator()->AllocationOk()) {
- data->set_compilation_failed();
- return;
+
+ if (FLAG_turbo_preprocess_ranges) {
+ Run<SplinterLiveRangesPhase>();
}
- Run<AllocateDoubleRegistersPhase>();
- if (!data->register_allocator()->AllocationOk()) {
- data->set_compilation_failed();
- return;
+
+ if (FLAG_turbo_greedy_regalloc) {
+ Run<AllocateGeneralRegistersPhase<GreedyAllocator>>();
+ Run<AllocateDoubleRegistersPhase<GreedyAllocator>>();
+ } else {
+ Run<AllocateGeneralRegistersPhase<LinearScanAllocator>>();
+ Run<AllocateDoubleRegistersPhase<LinearScanAllocator>>();
}
- if (FLAG_turbo_reuse_spill_slots) {
- Run<ReuseSpillSlotsPhase>();
+
+ if (FLAG_turbo_preprocess_ranges) {
+ Run<MergeSplintersPhase>();
}
+
+ if (FLAG_turbo_frame_elision) {
+ Run<LocateSpillSlotsPhase>();
+ Run<FrameElisionPhase>();
+ }
+
+ Run<AssignSpillSlotsPhase>();
+
Run<CommitAssignmentPhase>();
- Run<PopulatePointerMapsPhase>();
+ Run<PopulateReferenceMapsPhase>();
Run<ConnectRangesPhase>();
Run<ResolveControlFlowPhase>();
if (FLAG_turbo_move_optimization) {
@@ -1075,18 +1475,11 @@
if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) {
TurboCfgFile tcf(data->isolate());
- tcf << AsC1VAllocator("CodeGen", data->register_allocator());
+ tcf << AsC1VRegisterAllocationData("CodeGen",
+ data->register_allocation_data());
}
-}
-
-void Pipeline::SetUp() {
- InstructionOperand::SetUpCaches();
-}
-
-
-void Pipeline::TearDown() {
- InstructionOperand::TearDownCaches();
+ data->DeleteRegisterAllocationZone();
}
} // namespace compiler