diff options
Diffstat (limited to 'deps/v8/src/compiler/pipeline.cc')
-rw-r--r-- | deps/v8/src/compiler/pipeline.cc | 512 |
1 files changed, 355 insertions, 157 deletions
diff --git a/deps/v8/src/compiler/pipeline.cc b/deps/v8/src/compiler/pipeline.cc index 9ad3763403..045d695ecf 100644 --- a/deps/v8/src/compiler/pipeline.cc +++ b/deps/v8/src/compiler/pipeline.cc @@ -12,6 +12,7 @@ #include "src/base/adapters.h" #include "src/base/optional.h" #include "src/base/platform/elapsed-timer.h" +#include "src/bootstrapper.h" #include "src/compilation-info.h" #include "src/compiler.h" #include "src/compiler/basic-block-instrumentor.h" @@ -71,19 +72,23 @@ #include "src/ostreams.h" #include "src/parsing/parse-info.h" #include "src/register-configuration.h" -#include "src/trap-handler/trap-handler.h" #include "src/utils.h" namespace v8 { namespace internal { + +namespace trap_handler { +struct ProtectedInstructionData; +} // namespace trap_handler + namespace compiler { class PipelineData { public: // For main entry point. - PipelineData(ZoneStats* zone_stats, CompilationInfo* info, + PipelineData(ZoneStats* zone_stats, Isolate* isolate, CompilationInfo* info, PipelineStatistics* pipeline_statistics) - : isolate_(info->isolate()), + : isolate_(isolate), info_(info), debug_name_(info_->GetDebugName()), may_have_unverifiable_graph_(false), @@ -112,12 +117,12 @@ class PipelineData { } // For WebAssembly compile entry point. - PipelineData(ZoneStats* zone_stats, CompilationInfo* info, JSGraph* jsgraph, - PipelineStatistics* pipeline_statistics, + PipelineData(ZoneStats* zone_stats, Isolate* isolate, CompilationInfo* info, + JSGraph* jsgraph, PipelineStatistics* pipeline_statistics, SourcePositionTable* source_positions, - ZoneVector<trap_handler::ProtectedInstructionData>* + std::vector<trap_handler::ProtectedInstructionData>* protected_instructions) - : isolate_(info->isolate()), + : isolate_(isolate), info_(info), debug_name_(info_->GetDebugName()), zone_stats_(zone_stats), @@ -135,14 +140,14 @@ class PipelineData { codegen_zone_(codegen_zone_scope_.zone()), register_allocation_zone_scope_(zone_stats_, ZONE_NAME), register_allocation_zone_(register_allocation_zone_scope_.zone()), - protected_instructions_(protected_instructions) { - } + protected_instructions_(protected_instructions) {} // For machine graph testing entry point. - PipelineData(ZoneStats* zone_stats, CompilationInfo* info, Graph* graph, - Schedule* schedule, SourcePositionTable* source_positions, + PipelineData(ZoneStats* zone_stats, CompilationInfo* info, Isolate* isolate, + Graph* graph, Schedule* schedule, + SourcePositionTable* source_positions, JumpOptimizationInfo* jump_opt) - : isolate_(info->isolate()), + : isolate_(isolate), info_(info), debug_name_(info_->GetDebugName()), zone_stats_(zone_stats), @@ -157,10 +162,11 @@ class PipelineData { register_allocation_zone_scope_(zone_stats_, ZONE_NAME), register_allocation_zone_(register_allocation_zone_scope_.zone()), jump_optimization_info_(jump_opt) {} + // For register allocation testing entry point. - PipelineData(ZoneStats* zone_stats, CompilationInfo* info, + PipelineData(ZoneStats* zone_stats, CompilationInfo* info, Isolate* isolate, InstructionSequence* sequence) - : isolate_(info->isolate()), + : isolate_(isolate), info_(info), debug_name_(info_->GetDebugName()), zone_stats_(zone_stats), @@ -171,8 +177,7 @@ class PipelineData { codegen_zone_scope_(zone_stats_, ZONE_NAME), codegen_zone_(codegen_zone_scope_.zone()), register_allocation_zone_scope_(zone_stats_, ZONE_NAME), - register_allocation_zone_(register_allocation_zone_scope_.zone()) { - } + register_allocation_zone_(register_allocation_zone_scope_.zone()) {} ~PipelineData() { delete code_generator_; // Must happen before zones are destroyed. @@ -248,7 +253,7 @@ class PipelineData { source_position_output_ = source_position_output; } - ZoneVector<trap_handler::ProtectedInstructionData>* protected_instructions() + std::vector<trap_handler::ProtectedInstructionData>* protected_instructions() const { return protected_instructions_; } @@ -297,8 +302,8 @@ class PipelineData { InstructionBlocks* instruction_blocks = InstructionSequence::InstructionBlocksFor(instruction_zone(), schedule()); - sequence_ = new (instruction_zone()) InstructionSequence( - info()->isolate(), instruction_zone(), instruction_blocks); + sequence_ = new (instruction_zone()) + InstructionSequence(isolate(), instruction_zone(), instruction_blocks); if (descriptor && descriptor->RequiresFrameAsIncoming()) { sequence_->instruction_blocks()[0]->mark_needs_frame(); } else { @@ -336,9 +341,10 @@ class PipelineData { void InitializeCodeGenerator(Linkage* linkage) { DCHECK_NULL(code_generator_); - code_generator_ = new CodeGenerator( - codegen_zone(), frame(), linkage, sequence(), info(), osr_helper_, - start_source_position_, jump_optimization_info_); + code_generator_ = + new CodeGenerator(codegen_zone(), frame(), linkage, sequence(), info(), + isolate(), osr_helper_, start_source_position_, + jump_optimization_info_, protected_instructions_); } void BeginPhaseKind(const char* phase_kind_name) { @@ -409,7 +415,7 @@ class PipelineData { // Source position output for --trace-turbo. std::string source_position_output_; - ZoneVector<trap_handler::ProtectedInstructionData>* protected_instructions_ = + std::vector<trap_handler::ProtectedInstructionData>* protected_instructions_ = nullptr; JumpOptimizationInfo* jump_optimization_info_ = nullptr; @@ -455,6 +461,151 @@ class PipelineImpl final { namespace { +// Print function's source if it was not printed before. +// Return a sequential id under which this function was printed. +int PrintFunctionSource(CompilationInfo* info, Isolate* isolate, + std::vector<Handle<SharedFunctionInfo>>* printed, + int inlining_id, Handle<SharedFunctionInfo> shared) { + // Outermost function has source id -1 and inlined functions take + // source ids starting from 0. + int source_id = -1; + if (inlining_id != SourcePosition::kNotInlined) { + for (unsigned i = 0; i < printed->size(); i++) { + if (printed->at(i).is_identical_to(shared)) { + return i; + } + } + source_id = static_cast<int>(printed->size()); + printed->push_back(shared); + } + + if (!shared->script()->IsUndefined(isolate)) { + Handle<Script> script(Script::cast(shared->script()), isolate); + + if (!script->source()->IsUndefined(isolate)) { + CodeTracer::Scope tracing_scope(isolate->GetCodeTracer()); + Object* source_name = script->name(); + OFStream os(tracing_scope.file()); + os << "--- FUNCTION SOURCE ("; + if (source_name->IsString()) { + os << String::cast(source_name)->ToCString().get() << ":"; + } + os << shared->DebugName()->ToCString().get() << ") id{"; + os << info->optimization_id() << "," << source_id << "} start{"; + os << shared->start_position() << "} ---\n"; + { + DisallowHeapAllocation no_allocation; + int start = shared->start_position(); + int len = shared->end_position() - start; + String::SubStringRange source(String::cast(script->source()), start, + len); + for (const auto& c : source) { + os << AsReversiblyEscapedUC16(c); + } + } + + os << "\n--- END ---\n"; + } + } + + return source_id; +} + +// Print information for the given inlining: which function was inlined and +// where the inlining occurred. +void PrintInlinedFunctionInfo(CompilationInfo* info, Isolate* isolate, + int source_id, int inlining_id, + const CompilationInfo::InlinedFunctionHolder& h) { + CodeTracer::Scope tracing_scope(isolate->GetCodeTracer()); + OFStream os(tracing_scope.file()); + os << "INLINE (" << h.shared_info->DebugName()->ToCString().get() << ") id{" + << info->optimization_id() << "," << source_id << "} AS " << inlining_id + << " AT "; + const SourcePosition position = h.position.position; + if (position.IsKnown()) { + os << "<" << position.InliningId() << ":" << position.ScriptOffset() << ">"; + } else { + os << "<?>"; + } + os << std::endl; +} + +// Print the source of all functions that participated in this optimizing +// compilation. For inlined functions print source position of their inlining. +void DumpParticipatingSource(CompilationInfo* info, Isolate* isolate) { + AllowDeferredHandleDereference allow_deference_for_print_code; + + std::vector<Handle<SharedFunctionInfo>> printed; + printed.reserve(info->inlined_functions().size()); + + PrintFunctionSource(info, isolate, &printed, SourcePosition::kNotInlined, + info->shared_info()); + const auto& inlined = info->inlined_functions(); + for (unsigned id = 0; id < inlined.size(); id++) { + const int source_id = PrintFunctionSource(info, isolate, &printed, id, + inlined[id].shared_info); + PrintInlinedFunctionInfo(info, isolate, source_id, id, inlined[id]); + } +} + +// Print the code after compiling it. +void PrintCode(Handle<Code> code, CompilationInfo* info) { + Isolate* isolate = code->GetIsolate(); + if (FLAG_print_opt_source && info->IsOptimizing()) { + DumpParticipatingSource(info, isolate); + } + +#ifdef ENABLE_DISASSEMBLER + AllowDeferredHandleDereference allow_deference_for_print_code; + bool print_code = + isolate->bootstrapper()->IsActive() + ? FLAG_print_builtin_code + : (FLAG_print_code || (info->IsStub() && FLAG_print_code_stubs) || + (info->IsOptimizing() && FLAG_print_opt_code && + info->shared_info()->PassesFilter(FLAG_print_opt_code_filter)) || + (info->IsWasm() && FLAG_print_wasm_code)); + if (print_code) { + std::unique_ptr<char[]> debug_name = info->GetDebugName(); + CodeTracer::Scope tracing_scope(isolate->GetCodeTracer()); + OFStream os(tracing_scope.file()); + + // Print the source code if available. + bool print_source = code->kind() == Code::OPTIMIZED_FUNCTION; + if (print_source) { + Handle<SharedFunctionInfo> shared = info->shared_info(); + if (shared->script()->IsScript() && + !Script::cast(shared->script())->source()->IsUndefined(isolate)) { + os << "--- Raw source ---\n"; + StringCharacterStream stream( + String::cast(Script::cast(shared->script())->source()), + shared->start_position()); + // fun->end_position() points to the last character in the stream. We + // need to compensate by adding one to calculate the length. + int source_len = shared->end_position() - shared->start_position() + 1; + for (int i = 0; i < source_len; i++) { + if (stream.HasMore()) { + os << AsReversiblyEscapedUC16(stream.GetNext()); + } + } + os << "\n\n"; + } + } + if (info->IsOptimizing()) { + os << "--- Optimized code ---\n" + << "optimization_id = " << info->optimization_id() << "\n"; + } else { + os << "--- Code ---\n"; + } + if (print_source) { + Handle<SharedFunctionInfo> shared = info->shared_info(); + os << "source_position = " << shared->start_position() << "\n"; + } + code->Disassemble(debug_name.get(), os); + os << "--- End code ---\n"; + } +#endif // ENABLE_DISASSEMBLER +} + struct TurboCfgFile : public std::ofstream { explicit TurboCfgFile(Isolate* isolate) : std::ofstream(isolate->GetTurboCfgFileName().c_str(), @@ -467,7 +618,8 @@ struct TurboJsonFile : public std::ofstream { mode) {} }; -void TraceSchedule(CompilationInfo* info, Schedule* schedule) { +void TraceSchedule(CompilationInfo* info, Isolate* isolate, + Schedule* schedule) { if (FLAG_trace_turbo) { AllowHandleDereference allow_deref; TurboJsonFile json_of(info, std::ios_base::app); @@ -482,7 +634,7 @@ void TraceSchedule(CompilationInfo* info, Schedule* schedule) { } if (FLAG_trace_turbo_graph || FLAG_trace_turbo_scheduler) { AllowHandleDereference allow_deref; - CodeTracer::Scope tracing_scope(info->isolate()->GetCodeTracer()); + CodeTracer::Scope tracing_scope(isolate->GetCodeTracer()); OFStream os(tracing_scope.file()); os << "-- Schedule --------------------------------------\n" << *schedule; } @@ -551,11 +703,12 @@ class PipelineRunScope { PipelineStatistics* CreatePipelineStatistics(Handle<Script> script, CompilationInfo* info, + Isolate* isolate, ZoneStats* zone_stats) { PipelineStatistics* pipeline_statistics = nullptr; if (FLAG_turbo_stats || FLAG_turbo_stats_nvp) { - pipeline_statistics = new PipelineStatistics(info, zone_stats); + pipeline_statistics = new PipelineStatistics(info, isolate, zone_stats); pipeline_statistics->BeginPhaseKind("initializing"); } @@ -565,7 +718,6 @@ PipelineStatistics* CreatePipelineStatistics(Handle<Script> script, int pos = info->IsStub() ? 0 : info->shared_info()->start_position(); json_of << "{\"function\":\"" << function_name.get() << "\", \"sourcePosition\":" << pos << ", \"source\":\""; - Isolate* isolate = info->isolate(); if (!script.is_null() && !script->source()->IsUndefined(isolate)) { DisallowHeapAllocation no_allocation; int start = info->shared_info()->start_position(); @@ -590,25 +742,27 @@ class PipelineCompilationJob final : public CompilationJob { Handle<JSFunction> function) // Note that the CompilationInfo is not initialized at the time we pass it // to the CompilationJob constructor, but it is not dereferenced there. - : CompilationJob(function->GetIsolate(), parse_info, &compilation_info_, - "TurboFan"), + : CompilationJob(parse_info->stack_limit(), parse_info, + &compilation_info_, "TurboFan"), parse_info_(parse_info), zone_stats_(function->GetIsolate()->allocator()), compilation_info_(parse_info_.get()->zone(), function->GetIsolate(), shared_info, function), - pipeline_statistics_(CreatePipelineStatistics( - parse_info_->script(), compilation_info(), &zone_stats_)), - data_(&zone_stats_, compilation_info(), pipeline_statistics_.get()), + pipeline_statistics_( + CreatePipelineStatistics(parse_info_->script(), compilation_info(), + function->GetIsolate(), &zone_stats_)), + data_(&zone_stats_, function->GetIsolate(), compilation_info(), + pipeline_statistics_.get()), pipeline_(&data_), linkage_(nullptr) {} protected: - Status PrepareJobImpl() final; + Status PrepareJobImpl(Isolate* isolate) final; Status ExecuteJobImpl() final; - Status FinalizeJobImpl() final; + Status FinalizeJobImpl(Isolate* isolate) final; // Registers weak object to optimized code dependencies. - void RegisterWeakObjectsInOptimizedCode(Handle<Code> code); + void RegisterWeakObjectsInOptimizedCode(Handle<Code> code, Isolate* isolate); private: std::unique_ptr<ParseInfo> parse_info_; @@ -622,7 +776,8 @@ class PipelineCompilationJob final : public CompilationJob { DISALLOW_COPY_AND_ASSIGN(PipelineCompilationJob); }; -PipelineCompilationJob::Status PipelineCompilationJob::PrepareJobImpl() { +PipelineCompilationJob::Status PipelineCompilationJob::PrepareJobImpl( + Isolate* isolate) { if (!FLAG_always_opt) { compilation_info()->MarkAsBailoutOnUninitialized(); } @@ -636,7 +791,7 @@ PipelineCompilationJob::Status PipelineCompilationJob::PrepareJobImpl() { compilation_info()->MarkAsAccessorInliningEnabled(); } if (compilation_info()->closure()->feedback_vector_cell()->map() == - isolate()->heap()->one_closure_cell_map()) { + isolate->heap()->one_closure_cell_map()) { compilation_info()->MarkAsFunctionContextSpecializing(); } @@ -647,7 +802,7 @@ PipelineCompilationJob::Status PipelineCompilationJob::PrepareJobImpl() { Linkage::ComputeIncoming(compilation_info()->zone(), compilation_info())); if (!pipeline_.CreateGraph()) { - if (isolate()->has_pending_exception()) return FAILED; // Stack overflowed. + if (isolate->has_pending_exception()) return FAILED; // Stack overflowed. return AbortOptimization(kGraphBuildingFailed); } @@ -656,7 +811,7 @@ PipelineCompilationJob::Status PipelineCompilationJob::PrepareJobImpl() { // Make sure that we have generated the maximal number of deopt entries. // This is in order to avoid triggering the generation of deopt entries later // during code assembly. - Deoptimizer::EnsureCodeForMaxDeoptimizationEntries(isolate()); + Deoptimizer::EnsureCodeForMaxDeoptimizationEntries(isolate); return SUCCEEDED; } @@ -667,7 +822,8 @@ PipelineCompilationJob::Status PipelineCompilationJob::ExecuteJobImpl() { return SUCCEEDED; } -PipelineCompilationJob::Status PipelineCompilationJob::FinalizeJobImpl() { +PipelineCompilationJob::Status PipelineCompilationJob::FinalizeJobImpl( + Isolate* isolate) { Handle<Code> code = pipeline_.FinalizeCode(); if (code.is_null()) { if (compilation_info()->bailout_reason() == kNoReason) { @@ -679,7 +835,7 @@ PipelineCompilationJob::Status PipelineCompilationJob::FinalizeJobImpl() { compilation_info()->SetCode(code); compilation_info()->context()->native_context()->AddOptimizedCode(*code); - RegisterWeakObjectsInOptimizedCode(code); + RegisterWeakObjectsInOptimizedCode(code, isolate); return SUCCEEDED; } @@ -702,7 +858,7 @@ void AddWeakObjectToCodeDependency(Isolate* isolate, Handle<HeapObject> object, } // namespace void PipelineCompilationJob::RegisterWeakObjectsInOptimizedCode( - Handle<Code> code) { + Handle<Code> code, Isolate* isolate) { DCHECK(code->is_optimized_code()); std::vector<Handle<Map>> maps; std::vector<Handle<HeapObject>> objects; @@ -714,7 +870,7 @@ void PipelineCompilationJob::RegisterWeakObjectsInOptimizedCode( if (mode == RelocInfo::EMBEDDED_OBJECT && code->IsWeakObjectInOptimizedCode(it.rinfo()->target_object())) { Handle<HeapObject> object(HeapObject::cast(it.rinfo()->target_object()), - isolate()); + isolate); if (object->IsMap()) { maps.push_back(Handle<Map>::cast(object)); } else { @@ -725,12 +881,12 @@ void PipelineCompilationJob::RegisterWeakObjectsInOptimizedCode( } for (Handle<Map> map : maps) { if (map->dependent_code()->IsEmpty(DependentCode::kWeakCodeGroup)) { - isolate()->heap()->AddRetainedMap(map); + isolate->heap()->AddRetainedMap(map); } Map::AddDependentCode(map, DependentCode::kWeakCodeGroup, code); } for (Handle<HeapObject> object : objects) { - AddWeakObjectToCodeDependency(isolate(), object, code); + AddWeakObjectToCodeDependency(isolate, object, code); } code->set_can_have_weak_objects(true); } @@ -738,25 +894,25 @@ void PipelineCompilationJob::RegisterWeakObjectsInOptimizedCode( class PipelineWasmCompilationJob final : public CompilationJob { public: explicit PipelineWasmCompilationJob( - CompilationInfo* info, JSGraph* jsgraph, CallDescriptor* descriptor, - SourcePositionTable* source_positions, - ZoneVector<trap_handler::ProtectedInstructionData>* protected_insts, + CompilationInfo* info, Isolate* isolate, JSGraph* jsgraph, + CallDescriptor* descriptor, SourcePositionTable* source_positions, + std::vector<trap_handler::ProtectedInstructionData>* protected_insts, bool asmjs_origin) - : CompilationJob(info->isolate(), nullptr, info, "TurboFan", - State::kReadyToExecute), - zone_stats_(info->isolate()->allocator()), - pipeline_statistics_(CreatePipelineStatistics(Handle<Script>::null(), - info, &zone_stats_)), - data_(&zone_stats_, info, jsgraph, pipeline_statistics_.get(), + : CompilationJob(isolate->stack_guard()->real_climit(), nullptr, info, + "TurboFan", State::kReadyToExecute), + zone_stats_(isolate->allocator()), + pipeline_statistics_(CreatePipelineStatistics( + Handle<Script>::null(), info, isolate, &zone_stats_)), + data_(&zone_stats_, isolate, info, jsgraph, pipeline_statistics_.get(), source_positions, protected_insts), pipeline_(&data_), linkage_(descriptor), asmjs_origin_(asmjs_origin) {} protected: - Status PrepareJobImpl() final; + Status PrepareJobImpl(Isolate* isolate) final; Status ExecuteJobImpl() final; - Status FinalizeJobImpl() final; + Status FinalizeJobImpl(Isolate* isolate) final; private: size_t AllocatedMemory() const override; @@ -775,8 +931,8 @@ class PipelineWasmCompilationJob final : public CompilationJob { bool asmjs_origin_; }; -PipelineWasmCompilationJob::Status -PipelineWasmCompilationJob::PrepareJobImpl() { +PipelineWasmCompilationJob::Status PipelineWasmCompilationJob::PrepareJobImpl( + Isolate* isolate) { UNREACHABLE(); // Prepare should always be skipped for WasmCompilationJob. return SUCCEEDED; } @@ -795,7 +951,7 @@ PipelineWasmCompilationJob::ExecuteJobImpl() { PipelineRunScope scope(data, "Wasm optimization"); JSGraphReducer graph_reducer(data->jsgraph(), scope.zone()); DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(), - data->common()); + data->common(), scope.zone()); ValueNumberingReducer value_numbering(scope.zone(), data->graph()->zone()); MachineOperatorReducer machine_reducer(data->jsgraph(), asmjs_origin_); CommonOperatorReducer common_reducer(&graph_reducer, data->graph(), @@ -817,10 +973,24 @@ size_t PipelineWasmCompilationJob::AllocatedMemory() const { return pipeline_.data_->zone_stats()->GetCurrentAllocatedBytes(); } -PipelineWasmCompilationJob::Status -PipelineWasmCompilationJob::FinalizeJobImpl() { - pipeline_.FinalizeCode(); - ValidateImmovableEmbeddedObjects(); +PipelineWasmCompilationJob::Status PipelineWasmCompilationJob::FinalizeJobImpl( + Isolate* isolate) { + if (!FLAG_wasm_jit_to_native) { + pipeline_.FinalizeCode(); + ValidateImmovableEmbeddedObjects(); + } else { + CodeGenerator* code_generator = pipeline_.data_->code_generator(); + CompilationInfo::WasmCodeDesc* wasm_code_desc = + compilation_info()->wasm_code_desc(); + code_generator->tasm()->GetCode(isolate, &wasm_code_desc->code_desc); + wasm_code_desc->safepoint_table_offset = + code_generator->GetSafepointTableOffset(); + wasm_code_desc->frame_slot_count = + code_generator->frame()->GetTotalFrameSlotCount(); + wasm_code_desc->source_positions_table = + code_generator->GetSourcePositionTable(); + wasm_code_desc->handler_table = code_generator->GetHandlerTable(); + } return SUCCEEDED; } @@ -844,7 +1014,7 @@ void PipelineWasmCompilationJob::ValidateImmovableEmbeddedObjects() const { case RelocInfo::CODE_TARGET: // this would be either one of the stubs or builtins, because // we didn't link yet. - target = reinterpret_cast<Object*>(it.rinfo()->target_address()); + target = Code::GetCodeFromTargetAddress(it.rinfo()->target_address()); break; case RelocInfo::EMBEDDED_OBJECT: target = it.rinfo()->target_object(); @@ -855,7 +1025,18 @@ void PipelineWasmCompilationJob::ValidateImmovableEmbeddedObjects() const { CHECK_NOT_NULL(target); bool is_immovable = target->IsSmi() || Heap::IsImmovable(HeapObject::cast(target)); - CHECK(is_immovable); + bool is_wasm = target->IsCode() && + (Code::cast(target)->kind() == Code::WASM_FUNCTION || + Code::cast(target)->kind() == Code::WASM_TO_JS_FUNCTION || + Code::cast(target)->kind() == Code::WASM_TO_WASM_FUNCTION); + bool is_allowed_stub = false; + if (target->IsCode()) { + Code* code = Code::cast(target); + is_allowed_stub = + code->kind() == Code::STUB && + CodeStub::MajorKeyFromKey(code->stub_key()) == CodeStub::DoubleToI; + } + CHECK(is_immovable || is_wasm || is_allowed_stub); } } @@ -929,7 +1110,7 @@ struct InliningPhase { void Run(PipelineData* data, Zone* temp_zone) { JSGraphReducer graph_reducer(data->jsgraph(), temp_zone); DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(), - data->common()); + data->common(), temp_zone); CheckpointElimination checkpoint_elimination(&graph_reducer); CommonOperatorReducer common_reducer(&graph_reducer, data->graph(), data->common(), data->machine()); @@ -1023,7 +1204,7 @@ struct TypedLoweringPhase { void Run(PipelineData* data, Zone* temp_zone) { JSGraphReducer graph_reducer(data->jsgraph(), temp_zone); DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(), - data->common()); + data->common(), temp_zone); JSBuiltinReducer builtin_reducer( &graph_reducer, data->jsgraph(), data->info()->dependencies(), data->native_context()); @@ -1136,7 +1317,7 @@ struct EarlyOptimizationPhase { void Run(PipelineData* data, Zone* temp_zone) { JSGraphReducer graph_reducer(data->jsgraph(), temp_zone); DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(), - data->common()); + data->common(), temp_zone); SimplifiedOperatorReducer simple_reducer(&graph_reducer, data->jsgraph()); RedundancyElimination redundancy_elimination(&graph_reducer, temp_zone); ValueNumberingReducer value_numbering(temp_zone, data->graph()->zone()); @@ -1167,50 +1348,53 @@ struct EffectControlLinearizationPhase { static const char* phase_name() { return "effect linearization"; } void Run(PipelineData* data, Zone* temp_zone) { - // The scheduler requires the graphs to be trimmed, so trim now. - // TODO(jarin) Remove the trimming once the scheduler can handle untrimmed - // graphs. - GraphTrimmer trimmer(temp_zone, data->graph()); - NodeVector roots(temp_zone); - data->jsgraph()->GetCachedNodes(&roots); - trimmer.TrimGraph(roots.begin(), roots.end()); - - // Schedule the graph without node splitting so that we can - // fix the effect and control flow for nodes with low-level side - // effects (such as changing representation to tagged or - // 'floating' allocation regions.) - Schedule* schedule = Scheduler::ComputeSchedule(temp_zone, data->graph(), - Scheduler::kTempSchedule); - if (FLAG_turbo_verify) ScheduleVerifier::Run(schedule); - TraceSchedule(data->info(), schedule); - - // Post-pass for wiring the control/effects - // - connect allocating representation changes into the control&effect - // chains and lower them, - // - get rid of the region markers, - // - introduce effect phis and rewire effects to get SSA again. - EffectControlLinearizer linearizer(data->jsgraph(), schedule, temp_zone, - data->source_positions()); - linearizer.Run(); - } -}; - -// The store-store elimination greatly benefits from doing a common operator -// reducer and dead code elimination just before it, to eliminate conditional -// deopts with a constant condition. - -struct DeadCodeEliminationPhase { - static const char* phase_name() { return "dead code elimination"; } - - void Run(PipelineData* data, Zone* temp_zone) { - 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()); - AddReducer(data, &graph_reducer, &dead_code_elimination); - AddReducer(data, &graph_reducer, &common_reducer); - graph_reducer.ReduceGraph(); + { + // The scheduler requires the graphs to be trimmed, so trim now. + // TODO(jarin) Remove the trimming once the scheduler can handle untrimmed + // graphs. + GraphTrimmer trimmer(temp_zone, data->graph()); + NodeVector roots(temp_zone); + data->jsgraph()->GetCachedNodes(&roots); + trimmer.TrimGraph(roots.begin(), roots.end()); + + // Schedule the graph without node splitting so that we can + // fix the effect and control flow for nodes with low-level side + // effects (such as changing representation to tagged or + // 'floating' allocation regions.) + Schedule* schedule = Scheduler::ComputeSchedule(temp_zone, data->graph(), + Scheduler::kTempSchedule); + if (FLAG_turbo_verify) ScheduleVerifier::Run(schedule); + TraceSchedule(data->info(), data->isolate(), schedule); + + // Post-pass for wiring the control/effects + // - connect allocating representation changes into the control&effect + // chains and lower them, + // - get rid of the region markers, + // - introduce effect phis and rewire effects to get SSA again. + EffectControlLinearizer::MaskArrayIndexEnable mask_array_index = + data->info()->has_untrusted_code_mitigations() + ? EffectControlLinearizer::kMaskArrayIndex + : EffectControlLinearizer::kDoNotMaskArrayIndex; + EffectControlLinearizer linearizer(data->jsgraph(), schedule, temp_zone, + data->source_positions(), + mask_array_index); + linearizer.Run(); + } + { + // The {EffectControlLinearizer} might leave {Dead} nodes behind, so we + // run {DeadCodeElimination} to prune these parts of the graph. + // Also, the following store-store elimination phase greatly benefits from + // doing a common operator reducer and dead code elimination just before + // it, to eliminate conditional deopts with a constant condition. + JSGraphReducer graph_reducer(data->jsgraph(), temp_zone); + DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(), + data->common(), temp_zone); + CommonOperatorReducer common_reducer(&graph_reducer, data->graph(), + data->common(), data->machine()); + AddReducer(data, &graph_reducer, &dead_code_elimination); + AddReducer(data, &graph_reducer, &common_reducer); + graph_reducer.ReduceGraph(); + } } }; @@ -1235,7 +1419,7 @@ struct LoadEliminationPhase { BranchElimination branch_condition_elimination(&graph_reducer, data->jsgraph(), temp_zone); DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(), - data->common()); + data->common(), temp_zone); RedundancyElimination redundancy_elimination(&graph_reducer, temp_zone); LoadElimination load_elimination(&graph_reducer, data->jsgraph(), temp_zone); @@ -1278,7 +1462,7 @@ struct LateOptimizationPhase { BranchElimination branch_condition_elimination(&graph_reducer, data->jsgraph(), temp_zone); DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(), - data->common()); + data->common(), temp_zone); ValueNumberingReducer value_numbering(temp_zone, data->graph()->zone()); MachineOperatorReducer machine_reducer(data->jsgraph()); CommonOperatorReducer common_reducer(&graph_reducer, data->graph(), @@ -1347,7 +1531,7 @@ struct InstructionSelectionPhase { FLAG_turbo_instruction_scheduling ? InstructionSelector::kEnableScheduling : InstructionSelector::kDisableScheduling, - data->info()->will_serialize() + data->isolate()->serializer_enabled() ? InstructionSelector::kEnableSerialization : InstructionSelector::kDisableSerialization); if (!selector.SelectInstructions()) { @@ -1562,13 +1746,13 @@ struct PrintGraphPhase { } AllowHandleDereference allow_deref; - CodeTracer::Scope tracing_scope(info->isolate()->GetCodeTracer()); + CodeTracer::Scope tracing_scope(data->isolate()->GetCodeTracer()); OFStream os(tracing_scope.file()); os << "-- Graph after " << phase << " -- " << std::endl; os << AsScheduledGraph(schedule); } else if (FLAG_trace_turbo_graph) { // Simple textual RPO. AllowHandleDereference allow_deref; - CodeTracer::Scope tracing_scope(info->isolate()->GetCodeTracer()); + CodeTracer::Scope tracing_scope(data->isolate()->GetCodeTracer()); OFStream os(tracing_scope.file()); os << "-- Graph after " << phase << " -- " << std::endl; os << AsRPO(*graph); @@ -1582,8 +1766,22 @@ struct VerifyGraphPhase { void Run(PipelineData* data, Zone* temp_zone, const bool untyped, bool values_only = false) { + Verifier::CodeType code_type; + switch (data->info()->code_kind()) { + case Code::WASM_FUNCTION: + case Code::WASM_TO_JS_FUNCTION: + case Code::WASM_TO_WASM_FUNCTION: + case Code::JS_TO_WASM_FUNCTION: + case Code::WASM_INTERPRETER_ENTRY: + case Code::C_WASM_ENTRY: + code_type = Verifier::kWasm; + break; + default: + code_type = Verifier::kDefault; + } Verifier::Run(data->graph(), !untyped ? Verifier::TYPED : Verifier::UNTYPED, - values_only ? Verifier::kValuesOnly : Verifier::kAll); + values_only ? Verifier::kValuesOnly : Verifier::kAll, + code_type); } }; @@ -1720,9 +1918,6 @@ bool PipelineImpl::OptimizeGraph(Linkage* linkage) { Run<EffectControlLinearizationPhase>(); RunPrintAndVerify("Effect and control linearized", true); - Run<DeadCodeEliminationPhase>(); - RunPrintAndVerify("Dead code elimination", true); - if (FLAG_turbo_store_elimination) { Run<StoreStoreEliminationPhase>(); RunPrintAndVerify("Store-store elimination", true); @@ -1749,24 +1944,24 @@ bool PipelineImpl::OptimizeGraph(Linkage* linkage) { return ScheduleAndSelectInstructions(linkage, true); } -Handle<Code> Pipeline::GenerateCodeForCodeStub(Isolate* isolate, - CallDescriptor* call_descriptor, - Graph* graph, Schedule* schedule, - Code::Kind kind, - const char* debug_name, - JumpOptimizationInfo* jump_opt) { - CompilationInfo info(CStrVector(debug_name), isolate, graph->zone(), kind); - if (isolate->serializer_enabled()) info.MarkAsSerializing(); +Handle<Code> Pipeline::GenerateCodeForCodeStub( + Isolate* isolate, CallDescriptor* call_descriptor, Graph* graph, + Schedule* schedule, Code::Kind kind, const char* debug_name, + uint32_t stub_key, int32_t builtin_index, JumpOptimizationInfo* jump_opt) { + CompilationInfo info(CStrVector(debug_name), graph->zone(), kind); + info.set_builtin_index(builtin_index); + info.set_stub_key(stub_key); // Construct a pipeline for scheduling and code generation. ZoneStats zone_stats(isolate->allocator()); SourcePositionTable source_positions(graph); - PipelineData data(&zone_stats, &info, graph, schedule, &source_positions, - jump_opt); + PipelineData data(&zone_stats, &info, isolate, graph, schedule, + &source_positions, jump_opt); data.set_verify_graph(FLAG_verify_csa); std::unique_ptr<PipelineStatistics> pipeline_statistics; if (FLAG_turbo_stats || FLAG_turbo_stats_nvp) { - pipeline_statistics.reset(new PipelineStatistics(&info, &zone_stats)); + pipeline_statistics.reset( + new PipelineStatistics(&info, isolate, &zone_stats)); pipeline_statistics->BeginPhaseKind("stub codegen"); } @@ -1791,14 +1986,17 @@ Handle<Code> Pipeline::GenerateCodeForCodeStub(Isolate* isolate, } // static -Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info) { - ZoneStats zone_stats(info->isolate()->allocator()); +Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info, + Isolate* isolate) { + ZoneStats zone_stats(isolate->allocator()); std::unique_ptr<PipelineStatistics> pipeline_statistics( - CreatePipelineStatistics(Handle<Script>::null(), info, &zone_stats)); - PipelineData data(&zone_stats, info, pipeline_statistics.get()); + CreatePipelineStatistics(Handle<Script>::null(), info, isolate, + &zone_stats)); + PipelineData data(&zone_stats, isolate, info, pipeline_statistics.get()); PipelineImpl pipeline(&data); Linkage linkage(Linkage::ComputeIncoming(data.instruction_zone(), info)); + Deoptimizer::EnsureCodeForMaxDeoptimizationEntries(isolate); if (!pipeline.CreateGraph()) return Handle<Code>::null(); if (!pipeline.OptimizeGraph(&linkage)) return Handle<Code>::null(); @@ -1808,28 +2006,30 @@ Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info) { // static Handle<Code> Pipeline::GenerateCodeForTesting(CompilationInfo* info, - Graph* graph, + Isolate* isolate, Graph* graph, Schedule* schedule) { CallDescriptor* call_descriptor = Linkage::ComputeIncoming(info->zone(), info); - return GenerateCodeForTesting(info, call_descriptor, graph, schedule); + return GenerateCodeForTesting(info, isolate, call_descriptor, graph, + schedule); } // static Handle<Code> Pipeline::GenerateCodeForTesting( - CompilationInfo* info, CallDescriptor* call_descriptor, Graph* graph, - Schedule* schedule, SourcePositionTable* source_positions) { + CompilationInfo* info, Isolate* isolate, CallDescriptor* call_descriptor, + Graph* graph, Schedule* schedule, SourcePositionTable* source_positions) { // Construct a pipeline for scheduling and code generation. - ZoneStats zone_stats(info->isolate()->allocator()); + ZoneStats zone_stats(isolate->allocator()); // TODO(wasm): Refactor code generation to check for non-existing source // table, then remove this conditional allocation. if (!source_positions) source_positions = new (info->zone()) SourcePositionTable(graph); - PipelineData data(&zone_stats, info, graph, schedule, source_positions, - nullptr); + PipelineData data(&zone_stats, info, isolate, graph, schedule, + source_positions, nullptr); std::unique_ptr<PipelineStatistics> pipeline_statistics; if (FLAG_turbo_stats || FLAG_turbo_stats_nvp) { - pipeline_statistics.reset(new PipelineStatistics(info, &zone_stats)); + pipeline_statistics.reset( + new PipelineStatistics(info, isolate, &zone_stats)); pipeline_statistics->BeginPhaseKind("test codegen"); } @@ -1861,11 +2061,11 @@ CompilationJob* Pipeline::NewCompilationJob(Handle<JSFunction> function, // static CompilationJob* Pipeline::NewWasmCompilationJob( - CompilationInfo* info, JSGraph* jsgraph, CallDescriptor* descriptor, - SourcePositionTable* source_positions, - ZoneVector<trap_handler::ProtectedInstructionData>* protected_instructions, + CompilationInfo* info, Isolate* isolate, JSGraph* jsgraph, + CallDescriptor* descriptor, SourcePositionTable* source_positions, + std::vector<trap_handler::ProtectedInstructionData>* protected_instructions, wasm::ModuleOrigin asmjs_origin) { - return new PipelineWasmCompilationJob(info, jsgraph, descriptor, + return new PipelineWasmCompilationJob(info, isolate, jsgraph, descriptor, source_positions, protected_instructions, asmjs_origin); } @@ -1873,10 +2073,9 @@ CompilationJob* Pipeline::NewWasmCompilationJob( bool Pipeline::AllocateRegistersForTesting(const RegisterConfiguration* config, InstructionSequence* sequence, bool run_verifier) { - CompilationInfo info(ArrayVector("testing"), sequence->isolate(), - sequence->zone(), Code::STUB); + CompilationInfo info(ArrayVector("testing"), sequence->zone(), Code::STUB); ZoneStats zone_stats(sequence->isolate()->allocator()); - PipelineData data(&zone_stats, &info, sequence); + PipelineData data(&zone_stats, &info, sequence->isolate(), sequence); PipelineImpl pipeline(&data); pipeline.data_->InitializeFrameData(nullptr); pipeline.AllocateRegisters(config, nullptr, run_verifier); @@ -1895,11 +2094,11 @@ bool PipelineImpl::ScheduleAndSelectInstructions(Linkage* linkage, RunPrintAndVerify("Late trimmed", true); } if (data->schedule() == nullptr) Run<ComputeSchedulePhase>(); - TraceSchedule(data->info(), data->schedule()); + TraceSchedule(data->info(), data->isolate(), data->schedule()); if (FLAG_turbo_profiling) { data->set_profiler_data(BasicBlockInstrumentor::Instrument( - info(), data->graph(), data->schedule())); + info(), data->graph(), data->schedule(), data->isolate())); } bool verify_stub_graph = data->verify_graph(); @@ -1917,8 +2116,7 @@ bool PipelineImpl::ScheduleAndSelectInstructions(Linkage* linkage, !strcmp(FLAG_turbo_verify_machine_graph, data->debug_name())))) { if (FLAG_trace_verify_csa) { AllowHandleDereference allow_deref; - CompilationInfo* info = data->info(); - CodeTracer::Scope tracing_scope(info->isolate()->GetCodeTracer()); + CodeTracer::Scope tracing_scope(data->isolate()->GetCodeTracer()); OFStream os(tracing_scope.file()); os << "--------------------------------------------------\n" << "--- Verifying " << data->debug_name() << " generated by TurboFan\n" @@ -2019,7 +2217,7 @@ Handle<Code> PipelineImpl::FinalizeCode() { } info()->SetCode(code); - v8::internal::CodeGenerator::PrintCode(code, info()); + PrintCode(code, info()); if (FLAG_trace_turbo) { TurboJsonFile json_of(info(), std::ios_base::app); @@ -2152,7 +2350,7 @@ void PipelineImpl::AllocateRegisters(const RegisterConfiguration* config, CompilationInfo* PipelineImpl::info() const { return data_->info(); } -Isolate* PipelineImpl::isolate() const { return info()->isolate(); } +Isolate* PipelineImpl::isolate() const { return data_->isolate(); } } // namespace compiler } // namespace internal |