Update V8 to version 4.1.0.21
This is a cherry-pick of all commits up to and including the
4.1.0.21 cherry-pick in Chromium.
Original commit message:
Version 4.1.0.21 (cherry-pick)
Merged 206e9136bde0f2b5ae8cb77afbb1e7833e5bd412
Unlink pages from the space page list after evacuation.
BUG=430201
LOG=N
R=jkummerow@chromium.org
Review URL: https://codereview.chromium.org/953813002
Cr-Commit-Position: refs/branch-heads/4.1@{#22}
Cr-Branched-From: 2e08d2a7aa9d65d269d8c57aba82eb38a8cb0a18-refs/heads/candidates@{#25353}
---
FPIIM-449
Change-Id: I8c23c7bbb70772b4858fe8a47b64fa97ee0d1f8c
diff --git a/src/compiler/pipeline.cc b/src/compiler/pipeline.cc
index 9889b6a..c7432c6 100644
--- a/src/compiler/pipeline.cc
+++ b/src/compiler/pipeline.cc
@@ -4,29 +4,42 @@
#include "src/compiler/pipeline.h"
+#include <fstream> // NOLINT(readability/streams)
+#include <sstream>
+
#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/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/graph-replay.h"
#include "src/compiler/graph-visualizer.h"
#include "src/compiler/instruction.h"
#include "src/compiler/instruction-selector.h"
+#include "src/compiler/js-builtin-reducer.h"
#include "src/compiler/js-context-specialization.h"
#include "src/compiler/js-generic-lowering.h"
#include "src/compiler/js-inlining.h"
#include "src/compiler/js-typed-lowering.h"
+#include "src/compiler/jump-threading.h"
+#include "src/compiler/load-elimination.h"
#include "src/compiler/machine-operator-reducer.h"
-#include "src/compiler/phi-reducer.h"
+#include "src/compiler/move-optimizer.h"
+#include "src/compiler/pipeline-statistics.h"
#include "src/compiler/register-allocator.h"
+#include "src/compiler/register-allocator-verifier.h"
#include "src/compiler/schedule.h"
#include "src/compiler/scheduler.h"
+#include "src/compiler/select-lowering.h"
#include "src/compiler/simplified-lowering.h"
#include "src/compiler/simplified-operator-reducer.h"
#include "src/compiler/typer.h"
#include "src/compiler/value-numbering-reducer.h"
#include "src/compiler/verifier.h"
-#include "src/hydrogen.h"
+#include "src/compiler/zone-pool.h"
#include "src/ostreams.h"
#include "src/utils.h"
@@ -34,47 +47,202 @@
namespace internal {
namespace compiler {
-class PhaseStats {
+class PipelineData {
public:
- enum PhaseKind { CREATE_GRAPH, OPTIMIZATION, CODEGEN };
+ explicit PipelineData(ZonePool* zone_pool, CompilationInfo* info)
+ : isolate_(info->zone()->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_(nullptr),
+ loop_assignment_(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),
+ frame_(nullptr),
+ register_allocator_(nullptr) {}
- PhaseStats(CompilationInfo* info, PhaseKind kind, const char* name)
- : info_(info),
- kind_(kind),
- name_(name),
- size_(info->zone()->allocation_size()) {
- if (FLAG_turbo_stats) {
- timer_.Start();
- }
+ ~PipelineData() {
+ DeleteInstructionZone();
+ DeleteGraphZone();
}
- ~PhaseStats() {
- if (FLAG_turbo_stats) {
- base::TimeDelta delta = timer_.Elapsed();
- size_t bytes = info_->zone()->allocation_size() - size_;
- HStatistics* stats = info_->isolate()->GetTStatistics();
- stats->SaveTiming(name_, delta, static_cast<int>(bytes));
+ // 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();
+ }
- switch (kind_) {
- case CREATE_GRAPH:
- stats->IncrementCreateGraph(delta);
- break;
- case OPTIMIZATION:
- stats->IncrementOptimizeGraph(delta);
- break;
- case CODEGEN:
- stats->IncrementGenerateCode(delta);
- break;
- }
- }
+ // 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_; }
+ PipelineStatistics* pipeline_statistics() { return pipeline_statistics_; }
+ bool compilation_failed() const { return compilation_failed_; }
+ void set_compilation_failed() { compilation_failed_ = true; }
+ Handle<Code> code() { return code_; }
+ void set_code(Handle<Code> code) {
+ DCHECK(code_.is_null());
+ code_ = code;
+ }
+
+ // RawMachineAssembler generally produces graphs which cannot be verified.
+ bool MayHaveUnverifiableGraph() const { return outer_zone_ == nullptr; }
+
+ Zone* graph_zone() const { return graph_zone_; }
+ Graph* graph() const { return graph_; }
+ SourcePositionTable* source_positions() const {
+ return source_positions_.get();
+ }
+ MachineOperatorBuilder* machine() const { return machine_; }
+ CommonOperatorBuilder* common() const { return common_; }
+ JSOperatorBuilder* javascript() const { return javascript_; }
+ JSGraph* jsgraph() const { return jsgraph_; }
+ Typer* typer() const { return typer_.get(); }
+
+ LoopAssignmentAnalysis* loop_assignment() const { return loop_assignment_; }
+ void set_loop_assignment(LoopAssignmentAnalysis* loop_assignment) {
+ DCHECK_EQ(nullptr, 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;
+ }
+
+ Schedule* schedule() const { return schedule_; }
+ void set_schedule(Schedule* schedule) {
+ DCHECK_EQ(nullptr, 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_; }
+
+ 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;
+ machine_ = nullptr;
+ common_ = nullptr;
+ javascript_ = nullptr;
+ jsgraph_ = nullptr;
+ context_node_ = nullptr;
+ schedule_ = nullptr;
+ }
+
+ void DeleteInstructionZone() {
+ if (instruction_zone_ == nullptr) return;
+ instruction_zone_scope_.Destroy();
+ instruction_zone_ = nullptr;
+ sequence_ = nullptr;
+ frame_ = nullptr;
+ register_allocator_ = nullptr;
+ }
+
+ void InitializeInstructionSequence() {
+ DCHECK_EQ(nullptr, sequence_);
+ InstructionBlocks* instruction_blocks =
+ InstructionSequence::InstructionBlocksFor(instruction_zone(),
+ schedule());
+ sequence_ = new (instruction_zone())
+ InstructionSequence(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);
}
private:
+ Isolate* isolate_;
CompilationInfo* info_;
- PhaseKind kind_;
- const char* name_;
- size_t size_;
- base::ElapsedTimer timer_;
+ Zone* outer_zone_;
+ ZonePool* const zone_pool_;
+ PipelineStatistics* pipeline_statistics_;
+ bool compilation_failed_;
+ 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.
+ ZonePool::Scope graph_zone_scope_;
+ Zone* graph_zone_;
+ Graph* graph_;
+ // TODO(dcarney): make this into a ZoneObject.
+ SmartPointer<SourcePositionTable> source_positions_;
+ LoopAssignmentAnalysis* loop_assignment_;
+ 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
+ // destroyed.
+ ZonePool::Scope instruction_zone_scope_;
+ Zone* instruction_zone_;
+ InstructionSequence* sequence_;
+ Frame* frame_;
+ RegisterAllocator* register_allocator_;
+
+ DISALLOW_COPY_AND_ASSIGN(PipelineData);
};
@@ -87,41 +255,46 @@
}
-void Pipeline::VerifyAndPrintGraph(Graph* graph, const char* phase) {
- if (FLAG_trace_turbo) {
- char buffer[256];
- Vector<char> filename(buffer, sizeof(buffer));
- if (!info_->shared_info().is_null()) {
- SmartArrayPointer<char> functionname =
- info_->shared_info()->DebugName()->ToCString();
- if (strlen(functionname.get()) > 0) {
- SNPrintF(filename, "turbo-%s-%s.dot", functionname.get(), phase);
- } else {
- SNPrintF(filename, "turbo-%p-%s.dot", static_cast<void*>(info_), phase);
- }
- } else {
- SNPrintF(filename, "turbo-none-%s.dot", phase);
- }
- std::replace(filename.start(), filename.start() + filename.length(), ' ',
- '_');
- FILE* file = base::OS::FOpen(filename.start(), "w+");
- OFStream of(file);
- of << AsDOT(*graph);
- fclose(file);
+struct TurboCfgFile : public std::ofstream {
+ explicit TurboCfgFile(Isolate* isolate)
+ : std::ofstream(isolate->GetTurboCfgFileName().c_str(),
+ std::ios_base::app) {}
+};
- OFStream os(stdout);
- os << "-- " << phase << " graph printed to file " << filename.start()
- << "\n";
+
+static void TraceSchedule(Schedule* schedule) {
+ 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();
}
- if (VerifyGraphs()) Verifier::Run(graph);
+ return name;
}
class AstGraphBuilderWithPositions : public AstGraphBuilder {
public:
- explicit AstGraphBuilderWithPositions(CompilationInfo* info, JSGraph* jsgraph,
- SourcePositionTable* source_positions)
- : AstGraphBuilder(info, jsgraph), source_positions_(source_positions) {}
+ AstGraphBuilderWithPositions(Zone* local_zone, CompilationInfo* info,
+ JSGraph* jsgraph,
+ LoopAssignmentAnalysis* loop_assignment,
+ SourcePositionTable* source_positions)
+ : AstGraphBuilder(local_zone, info, jsgraph, loop_assignment),
+ source_positions_(source_positions) {}
bool CreateGraph() {
SourcePositionTable::Scope pos(source_positions_,
@@ -130,7 +303,7 @@
}
#define DEF_VISIT(type) \
- virtual void Visit##type(type* node) OVERRIDE { \
+ void Visit##type(type* node) OVERRIDE { \
SourcePositionTable::Scope pos(source_positions_, \
SourcePosition(node->position())); \
AstGraphBuilder::Visit##type(node); \
@@ -138,220 +311,613 @@
AST_NODE_LIST(DEF_VISIT)
#undef DEF_VISIT
+ Node* GetFunctionContext() { return AstGraphBuilder::GetFunctionContext(); }
+
private:
SourcePositionTable* source_positions_;
};
-static void TraceSchedule(Schedule* schedule) {
- if (!FLAG_trace_turbo) return;
- OFStream os(stdout);
- os << "-- Schedule --------------------------------------\n" << *schedule;
+class PipelineRunScope {
+ public:
+ PipelineRunScope(PipelineData* data, const char* phase_name)
+ : phase_scope_(
+ phase_name == nullptr ? nullptr : data->pipeline_statistics(),
+ phase_name),
+ zone_scope_(data->zone_pool()) {}
+
+ Zone* zone() { return zone_scope_.zone(); }
+
+ private:
+ PhaseScope phase_scope_;
+ ZonePool::Scope zone_scope_;
+};
+
+
+template <typename Phase>
+void Pipeline::Run() {
+ PipelineRunScope scope(this->data_, Phase::phase_name());
+ Phase phase;
+ phase.Run(this->data_, scope.zone());
+}
+
+
+template <typename Phase, typename Arg0>
+void Pipeline::Run(Arg0 arg_0) {
+ PipelineRunScope scope(this->data_, Phase::phase_name());
+ Phase phase;
+ phase.Run(this->data_, scope.zone(), arg_0);
+}
+
+
+struct LoopAssignmentAnalysisPhase {
+ static const char* phase_name() { return "loop assignment analysis"; }
+
+ void Run(PipelineData* data, Zone* temp_zone) {
+ AstLoopAssignmentAnalyzer analyzer(data->graph_zone(), data->info());
+ LoopAssignmentAnalysis* loop_assignment = analyzer.Analyze();
+ data->set_loop_assignment(loop_assignment);
+ }
+};
+
+
+struct GraphBuilderPhase {
+ static const char* phase_name() { return "graph builder"; }
+
+ 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();
+ }
+ }
+};
+
+
+struct ContextSpecializerPhase {
+ static const char* phase_name() { return "context specializing"; }
+
+ 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();
+ }
+};
+
+
+struct InliningPhase {
+ 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();
+ }
+};
+
+
+struct TyperPhase {
+ static const char* phase_name() { return "typer"; }
+
+ void Run(PipelineData* data, Zone* temp_zone) { data->typer()->Run(); }
+};
+
+
+struct TypedLoweringPhase {
+ 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);
+ graph_reducer.ReduceGraph();
+ }
+};
+
+
+struct SimplifiedLoweringPhase {
+ 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);
+ lowering.LowerAllNodes();
+ ValueNumberingReducer vn_reducer(temp_zone);
+ SimplifiedOperatorReducer simple_reducer(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(&machine_reducer);
+ graph_reducer.AddReducer(&common_reducer);
+ graph_reducer.ReduceGraph();
+ }
+};
+
+
+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);
+ SimplifiedOperatorReducer simple_reducer(data->jsgraph());
+ ChangeLowering lowering(data->jsgraph(), &linkage);
+ 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);
+ graph_reducer.ReduceGraph();
+ }
+};
+
+
+struct ControlReductionPhase {
+ void Run(PipelineData* data, Zone* temp_zone) {
+ SourcePositionTable::Scope pos(data->source_positions(),
+ SourcePosition::Unknown());
+ ControlReducer::ReduceGraph(temp_zone, data->jsgraph(), data->common());
+ }
+};
+
+
+struct EarlyControlReductionPhase : ControlReductionPhase {
+ static const char* phase_name() { return "early control reduction"; }
+};
+
+
+struct LateControlReductionPhase : ControlReductionPhase {
+ static const char* phase_name() { return "late control reduction"; }
+};
+
+
+struct GenericLoweringPhase {
+ 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);
+ graph_reducer.ReduceGraph();
+ }
+};
+
+
+struct ComputeSchedulePhase {
+ 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);
+ data->set_schedule(schedule);
+ }
+};
+
+
+struct InstructionSelectionPhase {
+ 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());
+ selector.SelectInstructions();
+ }
+};
+
+
+struct MeetRegisterConstraintsPhase {
+ static const char* phase_name() { return "meet register constraints"; }
+
+ void Run(PipelineData* data, Zone* temp_zone) {
+ data->register_allocator()->MeetRegisterConstraints();
+ }
+};
+
+
+struct ResolvePhisPhase {
+ static const char* phase_name() { return "resolve phis"; }
+
+ void Run(PipelineData* data, Zone* temp_zone) {
+ data->register_allocator()->ResolvePhis();
+ }
+};
+
+
+struct BuildLiveRangesPhase {
+ static const char* phase_name() { return "build live ranges"; }
+
+ void Run(PipelineData* data, Zone* temp_zone) {
+ data->register_allocator()->BuildLiveRanges();
+ }
+};
+
+
+struct AllocateGeneralRegistersPhase {
+ static const char* phase_name() { return "allocate general registers"; }
+
+ void Run(PipelineData* data, Zone* temp_zone) {
+ data->register_allocator()->AllocateGeneralRegisters();
+ }
+};
+
+
+struct AllocateDoubleRegistersPhase {
+ static const char* phase_name() { return "allocate double registers"; }
+
+ void Run(PipelineData* data, Zone* temp_zone) {
+ data->register_allocator()->AllocateDoubleRegisters();
+ }
+};
+
+
+struct ReuseSpillSlotsPhase {
+ static const char* phase_name() { return "reuse spill slots"; }
+
+ void Run(PipelineData* data, Zone* temp_zone) {
+ data->register_allocator()->ReuseSpillSlots();
+ }
+};
+
+
+struct CommitAssignmentPhase {
+ static const char* phase_name() { return "commit assignment"; }
+
+ void Run(PipelineData* data, Zone* temp_zone) {
+ data->register_allocator()->CommitAssignment();
+ }
+};
+
+
+struct PopulatePointerMapsPhase {
+ static const char* phase_name() { return "populate pointer maps"; }
+
+ void Run(PipelineData* data, Zone* temp_zone) {
+ data->register_allocator()->PopulatePointerMaps();
+ }
+};
+
+
+struct ConnectRangesPhase {
+ static const char* phase_name() { return "connect ranges"; }
+
+ void Run(PipelineData* data, Zone* temp_zone) {
+ data->register_allocator()->ConnectRanges();
+ }
+};
+
+
+struct ResolveControlFlowPhase {
+ static const char* phase_name() { return "resolve control flow"; }
+
+ void Run(PipelineData* data, Zone* temp_zone) {
+ data->register_allocator()->ResolveControlFlow();
+ }
+};
+
+
+struct OptimizeMovesPhase {
+ static const char* phase_name() { return "optimize moves"; }
+
+ void Run(PipelineData* data, Zone* temp_zone) {
+ MoveOptimizer move_optimizer(temp_zone, data->sequence());
+ move_optimizer.Run();
+ }
+};
+
+
+struct JumpThreadingPhase {
+ static const char* phase_name() { return "jump threading"; }
+
+ void Run(PipelineData* data, Zone* temp_zone) {
+ ZoneVector<BasicBlock::RpoNumber> result(temp_zone);
+ if (JumpThreading::ComputeForwarding(temp_zone, result, data->sequence())) {
+ JumpThreading::ApplyForwarding(result, data->sequence());
+ }
+ }
+};
+
+
+struct GenerateCodePhase {
+ static const char* phase_name() { return "generate code"; }
+
+ void Run(PipelineData* data, Zone* temp_zone, Linkage* linkage) {
+ CodeGenerator generator(data->frame(), linkage, data->sequence(),
+ data->info());
+ data->set_code(generator.GenerateCode());
+ }
+};
+
+
+struct PrintGraphPhase {
+ static const char* phase_name() { return nullptr; }
+
+ 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+");
+ if (json_file == nullptr) return;
+ OFStream json_of(json_file);
+ json_of << AsJSON(*graph);
+ fclose(json_file);
+ }
+
+ OFStream os(stdout);
+ if (FLAG_trace_turbo_graph) { // Simple textual RPO.
+ os << "-- Graph after " << phase << " -- " << std::endl;
+ os << AsRPO(*graph);
+ }
+
+ os << "-- " << phase << " graph printed to file " << filename.start()
+ << std::endl;
+ }
+};
+
+
+struct VerifyGraphPhase {
+ static const char* phase_name() { return nullptr; }
+
+ void Run(PipelineData* data, Zone* temp_zone, const bool untyped) {
+ Verifier::Run(data->graph(), FLAG_turbo_types && !untyped
+ ? Verifier::TYPED
+ : Verifier::UNTYPED);
+ }
+};
+
+
+void Pipeline::BeginPhaseKind(const char* phase_kind_name) {
+ if (data_->pipeline_statistics() != NULL) {
+ data_->pipeline_statistics()->BeginPhaseKind(phase_kind_name);
+ }
+}
+
+
+void Pipeline::RunPrintAndVerify(const char* phase, bool untyped) {
+ if (FLAG_trace_turbo) {
+ Run<PrintGraphPhase>(phase);
+ }
+ if (VerifyGraphs()) {
+ 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()) {
return Handle<Code>::null();
}
- if (FLAG_turbo_stats) isolate()->GetTStatistics()->Initialize(info_);
+ ZonePool zone_pool(isolate());
+ 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());
+ this->data_ = &data;
+ data.Initialize(pipeline_statistics.get());
+
+ BeginPhaseKind("graph creation");
if (FLAG_trace_turbo) {
OFStream os(stdout);
os << "---------------------------------------------------\n"
- << "Begin compiling method "
- << info()->function()->debug_name()->ToCString().get()
- << " using Turbofan" << endl;
+ << "Begin compiling method " << GetDebugName(info()).get()
+ << " using Turbofan" << std::endl;
+ TurboCfgFile tcf(isolate());
+ tcf << AsC1VCompilation(info());
}
- // Build the graph.
- Graph graph(zone());
- SourcePositionTable source_positions(&graph);
- source_positions.AddDecorator();
- // TODO(turbofan): there is no need to type anything during initial graph
- // construction. This is currently only needed for the node cache, which the
- // typer could sweep over later.
- Typer typer(zone());
- MachineOperatorBuilder machine;
- CommonOperatorBuilder common(zone());
- JSOperatorBuilder javascript(zone());
- JSGraph jsgraph(&graph, &common, &javascript, &typer, &machine);
- Node* context_node;
- {
- PhaseStats graph_builder_stats(info(), PhaseStats::CREATE_GRAPH,
- "graph builder");
- AstGraphBuilderWithPositions graph_builder(info(), &jsgraph,
- &source_positions);
- graph_builder.CreateGraph();
- context_node = graph_builder.GetFunctionContext();
- }
- {
- PhaseStats phi_reducer_stats(info(), PhaseStats::CREATE_GRAPH,
- "phi reduction");
- PhiReducer phi_reducer;
- GraphReducer graph_reducer(&graph);
- graph_reducer.AddReducer(&phi_reducer);
- graph_reducer.ReduceGraph();
- // TODO(mstarzinger): Running reducer once ought to be enough for everyone.
- graph_reducer.ReduceGraph();
- graph_reducer.ReduceGraph();
+ data.source_positions()->AddDecorator();
+
+ if (FLAG_loop_assignment_analysis) {
+ Run<LoopAssignmentAnalysisPhase>();
}
- VerifyAndPrintGraph(&graph, "Initial untyped");
+ 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()) {
- SourcePositionTable::Scope pos(&source_positions,
- SourcePosition::Unknown());
// Specialize the code to the context as aggressively as possible.
- JSContextSpecializer spec(info(), &jsgraph, context_node);
- spec.SpecializeToContext();
- VerifyAndPrintGraph(&graph, "Context specialized");
+ Run<ContextSpecializerPhase>();
+ RunPrintAndVerify("Context specialized", true);
}
if (info()->is_inlining_enabled()) {
- SourcePositionTable::Scope pos(&source_positions,
- SourcePosition::Unknown());
- JSInliner inliner(info(), &jsgraph);
- inliner.Inline();
- VerifyAndPrintGraph(&graph, "Inlined");
+ Run<InliningPhase>();
+ RunPrintAndVerify("Inlined", true);
}
- // Print a replay of the initial graph.
if (FLAG_print_turbo_replay) {
- GraphReplayPrinter::PrintReplay(&graph);
+ // 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();
+
if (info()->is_typing_enabled()) {
- {
- // Type the graph.
- PhaseStats typer_stats(info(), PhaseStats::CREATE_GRAPH, "typer");
- typer.Run(&graph, info()->context());
- VerifyAndPrintGraph(&graph, "Typed");
- }
- // All new nodes must be typed.
- typer.DecorateGraph(&graph);
- {
- // Lower JSOperators where we can determine types.
- PhaseStats lowering_stats(info(), PhaseStats::CREATE_GRAPH,
- "typed lowering");
- SourcePositionTable::Scope pos(&source_positions,
- SourcePosition::Unknown());
- JSTypedLowering lowering(&jsgraph);
- GraphReducer graph_reducer(&graph);
- graph_reducer.AddReducer(&lowering);
- graph_reducer.ReduceGraph();
-
- VerifyAndPrintGraph(&graph, "Lowered typed");
- }
- {
- // Lower simplified operators and insert changes.
- PhaseStats lowering_stats(info(), PhaseStats::CREATE_GRAPH,
- "simplified lowering");
- SourcePositionTable::Scope pos(&source_positions,
- SourcePosition::Unknown());
- SimplifiedLowering lowering(&jsgraph);
- lowering.LowerAllNodes();
-
- VerifyAndPrintGraph(&graph, "Lowered simplified");
- }
- {
- // Lower changes that have been inserted before.
- PhaseStats lowering_stats(info(), PhaseStats::OPTIMIZATION,
- "change lowering");
- SourcePositionTable::Scope pos(&source_positions,
- SourcePosition::Unknown());
- Linkage linkage(info());
- // TODO(turbofan): Value numbering disabled for now.
- // ValueNumberingReducer vn_reducer(zone());
- SimplifiedOperatorReducer simple_reducer(&jsgraph);
- ChangeLowering lowering(&jsgraph, &linkage);
- MachineOperatorReducer mach_reducer(&jsgraph);
- GraphReducer graph_reducer(&graph);
- // TODO(titzer): Figure out if we should run all reducers at once here.
- // graph_reducer.AddReducer(&vn_reducer);
- graph_reducer.AddReducer(&simple_reducer);
- graph_reducer.AddReducer(&lowering);
- graph_reducer.AddReducer(&mach_reducer);
- graph_reducer.ReduceGraph();
-
- VerifyAndPrintGraph(&graph, "Lowered changes");
- }
+ // Type the graph.
+ Run<TyperPhase>();
+ RunPrintAndVerify("Typed");
}
- Handle<Code> code = Handle<Code>::null();
- if (SupportedTarget()) {
- {
- // Lower any remaining generic JSOperators.
- PhaseStats lowering_stats(info(), PhaseStats::CREATE_GRAPH,
- "generic lowering");
- SourcePositionTable::Scope pos(&source_positions,
- SourcePosition::Unknown());
- JSGenericLowering lowering(info(), &jsgraph);
- GraphReducer graph_reducer(&graph);
- graph_reducer.AddReducer(&lowering);
- graph_reducer.ReduceGraph();
+ BeginPhaseKind("lowering");
- VerifyAndPrintGraph(&graph, "Lowered generic");
- }
+ if (info()->is_typing_enabled()) {
+ // Lower JSOperators where we can determine types.
+ Run<TypedLoweringPhase>();
+ RunPrintAndVerify("Lowered typed");
- {
- // Compute a schedule.
- Schedule* schedule = ComputeSchedule(&graph);
- // Generate optimized code.
- PhaseStats codegen_stats(info(), PhaseStats::CODEGEN, "codegen");
- Linkage linkage(info());
- code = GenerateCode(&linkage, &graph, schedule, &source_positions);
- info()->SetCode(code);
- }
+ // Lower simplified operators and insert changes.
+ Run<SimplifiedLoweringPhase>();
+ RunPrintAndVerify("Lowered simplified");
- // Print optimized code.
- v8::internal::CodeGenerator::PrintCode(code, info());
+ // Lower changes that have been inserted before.
+ Run<ChangeLoweringPhase>();
+ // // TODO(jarin, rossberg): Remove UNTYPED once machine typing works.
+ RunPrintAndVerify("Lowered changes", true);
+
+ Run<LateControlReductionPhase>();
+ RunPrintAndVerify("Late Control reduced");
}
+ // Lower any remaining generic JSOperators.
+ Run<GenericLoweringPhase>();
+ // TODO(jarin, rossberg): Remove UNTYPED once machine typing works.
+ RunPrintAndVerify("Lowered generic", true);
+
+ BeginPhaseKind("block building");
+
+ data.source_positions()->RemoveDecorator();
+
+ // Compute a schedule.
+ Run<ComputeSchedulePhase>();
+
+ {
+ // Generate optimized code.
+ Linkage linkage(data.instruction_zone(), info());
+ GenerateCode(&linkage);
+ }
+ Handle<Code> code = data.code();
+ info()->SetCode(code);
+
+ // Print optimized code.
+ v8::internal::CodeGenerator::PrintCode(code, info());
+
if (FLAG_trace_turbo) {
OFStream os(stdout);
- os << "--------------------------------------------------\n"
- << "Finished compiling method "
- << info()->function()->debug_name()->ToCString().get()
- << " using Turbofan" << endl;
+ os << "---------------------------------------------------\n"
+ << "Finished compiling method " << GetDebugName(info()).get()
+ << " using Turbofan" << std::endl;
}
return code;
}
-Schedule* Pipeline::ComputeSchedule(Graph* graph) {
- PhaseStats schedule_stats(info(), PhaseStats::CODEGEN, "scheduling");
- Schedule* schedule = Scheduler::ComputeSchedule(graph);
- TraceSchedule(schedule);
- if (VerifyGraphs()) ScheduleVerifier::Run(schedule);
- return schedule;
+Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info,
+ Graph* graph,
+ Schedule* schedule) {
+ CallDescriptor* call_descriptor =
+ Linkage::ComputeIncoming(info->zone(), info);
+ return GenerateCodeForTesting(info, call_descriptor, graph, schedule);
}
-Handle<Code> Pipeline::GenerateCodeForMachineGraph(Linkage* linkage,
- Graph* graph,
- Schedule* schedule) {
- CHECK(SupportedBackend());
- if (schedule == NULL) {
- VerifyAndPrintGraph(graph, "Machine");
- schedule = ComputeSchedule(graph);
- }
- TraceSchedule(schedule);
+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);
+}
- SourcePositionTable source_positions(graph);
- Handle<Code> code = GenerateCode(linkage, graph, schedule, &source_positions);
+
+Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info,
+ CallDescriptor* call_descriptor,
+ Graph* graph,
+ Schedule* schedule) {
+ CHECK(SupportedBackend());
+ ZonePool zone_pool(info->isolate());
+ Pipeline pipeline(info);
+ PipelineData data(&zone_pool, info);
+ pipeline.data_ = &data;
+ data.InitializeTorTesting(graph, schedule);
+ if (schedule == NULL) {
+ // 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(isolate()->GetCodeTracer());
+ CodeTracer::Scope tracing_scope(info->isolate()->GetCodeTracer());
OFStream os(tracing_scope.file());
code->Disassemble("test code", os);
}
@@ -360,51 +926,157 @@
}
-Handle<Code> Pipeline::GenerateCode(Linkage* linkage, Graph* graph,
- Schedule* schedule,
- SourcePositionTable* source_positions) {
- DCHECK_NOT_NULL(graph);
+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);
+ Pipeline pipeline(&info);
+ pipeline.data_ = &data;
+ pipeline.AllocateRegisters(config, run_verifier);
+ return !data.compilation_failed();
+}
+
+
+void Pipeline::GenerateCode(Linkage* linkage) {
+ PipelineData* data = this->data_;
+
DCHECK_NOT_NULL(linkage);
- DCHECK_NOT_NULL(schedule);
+ DCHECK_NOT_NULL(data->graph());
+ DCHECK_NOT_NULL(data->schedule());
CHECK(SupportedBackend());
- InstructionSequence sequence(linkage, graph, schedule);
+ BasicBlockProfiler::Data* profiler_data = NULL;
+ if (FLAG_turbo_profiling) {
+ profiler_data = BasicBlockInstrumentor::Instrument(info(), data->graph(),
+ data->schedule());
+ }
+
+ data->InitializeInstructionSequence();
// Select and schedule instructions covering the scheduled graph.
- {
- InstructionSelector selector(&sequence, source_positions);
- selector.SelectInstructions();
+ Run<InstructionSelectionPhase>(linkage);
+
+ if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) {
+ TurboCfgFile tcf(isolate());
+ tcf << AsC1V("CodeGen", data->schedule(), data->source_positions(),
+ data->sequence());
}
- if (FLAG_trace_turbo) {
- OFStream os(stdout);
- os << "----- Instruction sequence before register allocation -----\n"
- << sequence;
- }
+ data->DeleteGraphZone();
+ BeginPhaseKind("register allocation");
+
+ bool run_verifier = false;
+#ifdef DEBUG
+ run_verifier = true;
+#endif
// Allocate registers.
- {
- int node_count = graph->NodeCount();
- if (node_count > UnallocatedOperand::kMaxVirtualRegisters) {
- linkage->info()->AbortOptimization(kNotEnoughVirtualRegistersForValues);
- return Handle<Code>::null();
- }
- RegisterAllocator allocator(&sequence);
- if (!allocator.Allocate()) {
- linkage->info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc);
- return Handle<Code>::null();
- }
+ AllocateRegisters(RegisterConfiguration::ArchDefault(), run_verifier);
+ if (data->compilation_failed()) {
+ info()->AbortOptimization(kNotEnoughVirtualRegistersRegalloc);
+ return;
}
- if (FLAG_trace_turbo) {
+ BeginPhaseKind("code generation");
+
+ // Optimimize jumps.
+ if (FLAG_turbo_jt) {
+ Run<JumpThreadingPhase>();
+ }
+
+ // Generate final machine code.
+ Run<GenerateCodePhase>(linkage);
+
+ if (profiler_data != NULL) {
+#if ENABLE_DISASSEMBLER
+ std::ostringstream os;
+ data->code()->Disassemble(NULL, os);
+ profiler_data->SetCode(&os);
+#endif
+ }
+}
+
+
+void Pipeline::AllocateRegisters(const RegisterConfiguration* config,
+ 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;
+ RegisterAllocatorVerifier* verifier = nullptr;
+ if (run_verifier) {
+ verifier_zone.Reset(new Zone(info()->isolate()));
+ verifier = new (verifier_zone.get()) RegisterAllocatorVerifier(
+ verifier_zone.get(), config, data->sequence());
+ }
+
+ SmartArrayPointer<char> debug_name;
+#ifdef DEBUG
+ debug_name = GetDebugName(data->info());
+#endif
+
+ ZonePool::Scope zone_scope(data->zone_pool());
+ data->InitializeRegisterAllocator(zone_scope.zone(), config,
+ debug_name.get());
+
+ Run<MeetRegisterConstraintsPhase>();
+ Run<ResolvePhisPhase>();
+ Run<BuildLiveRangesPhase>();
+ if (FLAG_trace_turbo_graph) {
OFStream os(stdout);
- os << "----- Instruction sequence after register allocation -----\n"
- << sequence;
+ PrintableInstructionSequence printable = {config, data->sequence()};
+ os << "----- Instruction sequence before register allocation -----\n"
+ << printable;
+ }
+ if (verifier != nullptr) {
+ CHECK(!data->register_allocator()->ExistsUseWithoutDefinition());
+ }
+ Run<AllocateGeneralRegistersPhase>();
+ if (!data->register_allocator()->AllocationOk()) {
+ data->set_compilation_failed();
+ return;
+ }
+ Run<AllocateDoubleRegistersPhase>();
+ if (!data->register_allocator()->AllocationOk()) {
+ data->set_compilation_failed();
+ return;
+ }
+ if (FLAG_turbo_reuse_spill_slots) {
+ Run<ReuseSpillSlotsPhase>();
+ }
+ Run<CommitAssignmentPhase>();
+ Run<PopulatePointerMapsPhase>();
+ Run<ConnectRangesPhase>();
+ Run<ResolveControlFlowPhase>();
+ if (FLAG_turbo_move_optimization) {
+ Run<OptimizeMovesPhase>();
}
- // Generate native sequence.
- CodeGenerator generator(&sequence);
- return generator.GenerateCode();
+ if (FLAG_trace_turbo_graph) {
+ OFStream os(stdout);
+ PrintableInstructionSequence printable = {config, data->sequence()};
+ os << "----- Instruction sequence after register allocation -----\n"
+ << printable;
+ }
+
+ if (verifier != nullptr) {
+ verifier->VerifyAssignment();
+ verifier->VerifyGapMoves();
+ }
+
+ if (FLAG_trace_turbo && !data->MayHaveUnverifiableGraph()) {
+ TurboCfgFile tcf(data->isolate());
+ tcf << AsC1VAllocator("CodeGen", data->register_allocator());
+ }
}