112#if V8_ENABLE_WEBASSEMBLY
134#if V8_TARGET_ARCH_ARM64
140#if V8_ENABLE_WASM_SIMD256_REVEC
150 "pipeline-compilation-job-zone";
152#define RUN_MAYBE_ABORT(phase, ...) \
153 if (V8_UNLIKELY(!Run<phase>(__VA_ARGS__))) return {};
155#define PIPELINE_RUN_MAYBE_ABORT(pipeline, phase, ...) \
156 if (V8_UNLIKELY(!(pipeline).Run<phase>(__VA_ARGS__))) return {};
178#if V8_ENABLE_WASM_SIMD256_REVEC
184 bool has_dummy_end_block);
207class SourcePositionWrapper final :
public Reducer {
211 ~SourcePositionWrapper()
final =
default;
212 SourcePositionWrapper(
const SourcePositionWrapper&) =
delete;
213 SourcePositionWrapper& operator=(
const SourcePositionWrapper&) =
delete;
215 const char* reducer_name()
const override {
return reducer_->reducer_name(); }
220 return reducer_->Reduce(node,
nullptr);
223 void Finalize()
final {
reducer_->Finalize(); }
230class NodeOriginsWrapper final :
public Reducer {
232 NodeOriginsWrapper(Reducer* reducer, NodeOriginTable* table)
234 ~NodeOriginsWrapper() final = default;
235 NodeOriginsWrapper(const NodeOriginsWrapper&) = delete;
236 NodeOriginsWrapper& operator=(const NodeOriginsWrapper&) = delete;
238 const
char* reducer_name()
const override {
return reducer_->reducer_name(); }
240 Reduction Reduce(Node* node)
final {
241 NodeOriginTable::Scope
position(table_, reducer_name(), node);
242 return reducer_->Reduce(node,
nullptr);
245 void Finalize() final {
reducer_->Finalize(); }
249 NodeOriginTable*
const table_;
254#ifdef V8_RUNTIME_CALL_STATS
256 TFPipelineData* data,
const char* phase_name,
257 RuntimeCallCounterId runtime_call_counter_id,
258 RuntimeCallStats::CounterMode counter_mode = RuntimeCallStats::kExact)
259 :
phase_scope_(data->pipeline_statistics(), phase_name),
262 runtime_call_timer_scope(data->runtime_call_stats(),
263 runtime_call_counter_id, counter_mode) {
267 PipelineRunScope(TFPipelineData* data,
const char* phase_name)
268 :
phase_scope_(data->pipeline_statistics(), phase_name),
281#ifdef V8_RUNTIME_CALL_STATS
282 RuntimeCallTimerScope runtime_call_timer_scope;
290 explicit LocalIsolateScope(JSHeapBroker*
broker,
291 OptimizedCompilationInfo* info,
292 LocalIsolate* local_isolate)
295 info_->tick_counter().AttachLocalHeap(local_isolate->heap());
298 ~LocalIsolateScope() {
299 info_->tick_counter().DetachLocalHeap();
308void PrintFunctionSource(OptimizedCompilationInfo* info, Isolate* isolate,
310 DirectHandle<SharedFunctionInfo> shared) {
311 if (!IsUndefined(shared->script(), isolate)) {
314 if (!IsUndefined(script->source(), isolate)) {
315 CodeTracer::StreamScope tracing_scope(isolate->GetCodeTracer());
317 auto& os = tracing_scope.stream();
318 os <<
"--- FUNCTION SOURCE (";
319 if (IsString(source_name)) {
320 os << Cast<String>(source_name)->ToCString().get() <<
":";
322 os << shared->DebugNameCStr().get() <<
") id{";
323 os << info->optimization_id() <<
"," << source_id <<
"} start{";
324 os << shared->StartPosition() <<
"} ---\n";
327 int start = shared->StartPosition();
328 int len = shared->EndPosition() -
start;
331 for (
auto c : source) {
332 os << AsReversiblyEscapedUC16(c);
336 os <<
"\n--- END ---\n";
343void PrintInlinedFunctionInfo(
344 OptimizedCompilationInfo* info, Isolate* isolate,
int source_id,
345 int inlining_id,
const OptimizedCompilationInfo::InlinedFunctionHolder& h) {
346 CodeTracer::StreamScope tracing_scope(isolate->GetCodeTracer());
347 auto& os = tracing_scope.stream();
348 os <<
"INLINE (" << h.shared_info->DebugNameCStr().get() <<
") id{"
349 << info->optimization_id() <<
"," << source_id <<
"} AS " << inlining_id
351 const SourcePosition
position = h.position.position;
353 os <<
"<" <<
position.InliningId() <<
":" <<
position.ScriptOffset() <<
">";
362void PrintParticipatingSource(OptimizedCompilationInfo* info,
364 SourceIdAssigner id_assigner(info->inlined_functions().size());
365 PrintFunctionSource(info, isolate, -1, info->shared_info());
366 const auto& inlined = info->inlined_functions();
367 for (
unsigned id = 0;
id < inlined.size();
id++) {
368 const int source_id = id_assigner.GetIdFor(inlined[
id].shared_info);
369 PrintFunctionSource(info, isolate, source_id, inlined[
id].shared_info);
370 PrintInlinedFunctionInfo(info, isolate, source_id,
id, inlined[
id]);
374void TraceScheduleAndVerify(OptimizedCompilationInfo* info,
375 TFPipelineData* data, Schedule*
schedule,
376 const char* phase_name) {
378 RuntimeCallCounterId::kOptimizeTraceScheduleAndVerify,
379 RuntimeCallStats::kThreadSpecific);
381 "V8.TraceScheduleAndVerify");
388void AddReducer(TFPipelineData* data, GraphReducer* graph_reducer,
390 if (data->info()->source_positions()) {
391 SourcePositionWrapper*
const wrapper =
392 data->graph_zone()->New<SourcePositionWrapper>(
393 reducer, data->source_positions());
396 if (data->info()->trace_turbo_json()) {
397 NodeOriginsWrapper*
const wrapper =
398 data->graph_zone()->New<NodeOriginsWrapper>(reducer,
399 data->node_origins());
403 graph_reducer->AddReducer(reducer);
406TurbofanPipelineStatistics* CreatePipelineStatistics(
407 DirectHandle<Script> script, OptimizedCompilationInfo* info,
408 Isolate* isolate, ZoneStats* zone_stats) {
409 TurbofanPipelineStatistics* pipeline_statistics =
nullptr;
411 bool tracing_enabled;
415 pipeline_statistics =
new TurbofanPipelineStatistics(
416 info, isolate->GetTurboStatistics(), zone_stats);
417 pipeline_statistics->BeginPhaseKind(
"V8.TFInitializing");
420 if (info->trace_turbo_json()) {
421 TurboJsonFile json_of(info, std::ios_base::trunc);
422 json_of <<
"{\"function\" : ";
424 info->shared_info());
425 json_of <<
",\n\"phases\":[";
428 return pipeline_statistics;
431#if V8_ENABLE_WEBASSEMBLY
432TurbofanPipelineStatistics* CreatePipelineStatistics(
433 WasmCompilationData& compilation_data,
const wasm::WasmModule* wasm_module,
434 OptimizedCompilationInfo* info, ZoneStats* zone_stats) {
435 TurbofanPipelineStatistics* pipeline_statistics =
nullptr;
437 bool tracing_enabled;
440 if (tracing_enabled ||
v8_flags.turbo_stats_wasm) {
441 pipeline_statistics =
new TurbofanPipelineStatistics(
443 pipeline_statistics->BeginPhaseKind(
"V8.WasmInitializing");
446 if (info->trace_turbo_json()) {
447 TurboJsonFile json_of(info, std::ios_base::trunc);
448 std::unique_ptr<char[]> function_name = info->GetDebugName();
449 json_of <<
"{\"function\":\"" << function_name.get() <<
"\", \"source\":\"";
450 std::ostringstream disassembly;
452 base::Vector<const uint8_t> function_bytes{compilation_data.func_body.start,
453 compilation_data.body_size()};
454 base::Vector<const uint8_t> module_bytes{
nullptr, 0};
455 std::optional<wasm::ModuleWireBytes> maybe_wire_bytes =
456 compilation_data.wire_bytes_storage->GetModuleBytes();
457 if (maybe_wire_bytes) module_bytes = maybe_wire_bytes->module_bytes();
460 wasm_module, compilation_data.func_index, function_bytes, module_bytes,
462 for (
const auto& c : disassembly.str()) {
463 json_of << AsEscapedUC16ForJSON(c);
465 json_of <<
"\",\n\"sourceLineToBytecodePosition\" : [";
466 bool insert_comma =
false;
474 json_of <<
"],\n\"phases\":[";
477 return pipeline_statistics;
482[[nodiscard]]
bool GenerateCodeFromTurboshaftGraph(
483 Linkage*
linkage, turboshaft::Pipeline& turboshaft_pipeline,
484 PipelineImpl* turbofan_pipeline =
nullptr,
485 std::shared_ptr<OsrHelper> osr_helper = {}) {
486 turboshaft::PipelineData* turboshaft_data = turboshaft_pipeline.data();
487 turboshaft_data->InitializeCodegenComponent(osr_helper);
489 if (!turboshaft_pipeline.PrepareForInstructionSelection())
return false;
490 if (!turboshaft_pipeline.SelectInstructions(
linkage))
return false;
492 turboshaft_data->ClearGraphComponent();
494 if (!turboshaft_pipeline.AllocateRegisters(
498 if (!turboshaft_pipeline.AssembleCode(
linkage)) {
562 if (info->trace_turbo_json()) {
567 json_of <<
"{\"name\":\"" << phase_name <<
"\",\"type\":\"schedule\""
569 std::stringstream schedule_stream;
571 std::string schedule_string(schedule_stream.str());
572 for (
const auto& c : schedule_string) {
578 if (info->trace_turbo_graph() ||
v8_flags.trace_turbo_scheduler) {
583 tracing_scope.
stream() <<
"----- " << phase_name <<
" -----\n" << *
schedule;
590 if (
v8_flags.print_opt_source && info->IsOptimizing()) {
591 PrintParticipatingSource(info, isolate);
594#ifdef ENABLE_DISASSEMBLER
595 const bool print_code =
597 (info->IsOptimizing() &&
v8_flags.print_opt_code &&
598 info->shared_info()->PassesFilter(
v8_flags.print_opt_code_filter));
600 std::unique_ptr<char[]> debug_name = info->GetDebugName();
602 std::ostream& os = tracing_scope.
stream();
605 const bool print_source = info->IsOptimizing();
608 if (IsScript(shared->script()) &&
609 !IsUndefined(
Cast<Script>(shared->script())->source(), isolate)) {
610 os <<
"--- Raw source ---\n";
613 shared->StartPosition());
616 int source_len = shared->EndPosition() - shared->StartPosition() + 1;
617 for (
int i = 0;
i < source_len;
i++) {
625 if (info->IsOptimizing()) {
626 os <<
"--- Optimized code ---\n"
627 <<
"optimization_id = " << info->optimization_id() <<
"\n";
629 os <<
"--- Code ---\n";
633 os <<
"source_position = " << shared->StartPosition() <<
"\n";
635 code->Disassemble(debug_name.get(), os, isolate);
636 os <<
"--- End code ---\n";
675 data_->set_runtime_call_stats(stats);
677 PipelineJobScope(turboshaft::PipelineData* turboshaft_data,
678 RuntimeCallStats* stats)
684 ~PipelineJobScope() {
685 if (
data_)
data_->set_runtime_call_stats(
nullptr);
691 V8::GetCurrentPlatform()};
705 v8_flags.max_optimized_bytecode_size) {
718 if (
v8_flags.turbo_allocation_folding) {
729 ->function_context_independent_compiled() &&
752 isolate->heap()->PublishMainThreadPendingAllocations();
759 isolate->heap()->PublishMainThreadPendingAllocations();
768 PipelineJobScope scope(&
data_, stats);
802 const bool success = GenerateCodeFromTurboshaftGraph(
812 RCS_SCOPE(isolate, RuntimeCallCounterId::kOptimizeFinalizePipelineJob);
825 if (context->IsDetached()) {
842#ifdef V8_RUNTIME_CALL_STATS
843 PipelineRunScope scope(this->
data_, Phase::phase_name(),
844 Phase::kRuntimeCallCounterId, Phase::kCounterMode);
846 PipelineRunScope scope(this->
data_, Phase::phase_name());
850 phase.Run(this->
data_, scope.zone(), std::forward<Args>(
args)...);
851 return !
info()->was_cancelled();
859 if (data->info()->analyze_environment_liveness()) {
860 flags |= BytecodeGraphBuilderFlag::kAnalyzeEnvironmentLiveness;
862 if (data->info()->bailout_on_uninitialized()) {
863 flags |= BytecodeGraphBuilderFlag::kBailoutOnUninitialized;
874 data->jsgraph(), frequency, data->source_positions(),
875 data->node_origins(), SourcePosition::kNotInlined,
876 data->info()->code_kind(), flags, &data->info()->tick_counter(),
878 data->info()->node_observer()});
886 linkage->GetIncomingDescriptor()->ParameterSlotCount());
895 GraphReducer graph_reducer(temp_zone, data->graph(), &info->tick_counter(),
896 data->broker(), data->jsgraph()->Dead(),
897 data->observe_node_manager());
899 data->common(), temp_zone);
902 &graph_reducer, data->
graph(), data->broker(), data->common(),
903 data->machine(), temp_zone, BranchSemantics::kJS);
905 if (data->info()->bailout_on_uninitialized()) {
906 call_reducer_flags |= JSCallReducer::kBailoutOnUninitialized;
908 if (data->info()->inline_js_wasm_calls() && data->info()->inlining()) {
909 call_reducer_flags |= JSCallReducer::kInlineJSToWasmCalls;
911 JSCallReducer call_reducer(&graph_reducer, data->jsgraph(), data->broker(),
912 temp_zone, call_reducer_flags);
914 &graph_reducer, data->jsgraph(), data->broker(),
915 data->specialization_context(),
916 data->info()->function_context_specializing()
917 ? data->info()->closure()
920 JSNativeContextSpecialization::kNoFlags;
921 if (data->info()->bailout_on_uninitialized()) {
922 flags |= JSNativeContextSpecialization::kBailoutOnUninitialized;
928 &graph_reducer, data->jsgraph(), data->broker(), flags, temp_zone,
931 &graph_reducer, temp_zone, data->info(), data->jsgraph(),
932 data->broker(), data->source_positions(), data->node_origins(),
933 JSInliningHeuristic::kJSOnly,
nullptr,
nullptr);
937 AddReducer(data, &graph_reducer, &dead_code_elimination);
938 AddReducer(data, &graph_reducer, &checkpoint_elimination);
939 AddReducer(data, &graph_reducer, &common_reducer);
940 AddReducer(data, &graph_reducer, &native_context_specialization);
941 AddReducer(data, &graph_reducer, &context_specialization);
942 AddReducer(data, &graph_reducer, &intrinsic_lowering);
943 AddReducer(data, &graph_reducer, &call_reducer);
944 if (data->info()->inlining()) {
945 AddReducer(data, &graph_reducer, &inlining);
948 info->set_inlined_bytecode_size(inlining.total_inlined_bytecode_size());
950#if V8_ENABLE_WEBASSEMBLY
953 if (call_reducer.has_js_wasm_calls()) {
955 call_reducer.wasm_module_for_inlining();
957 data->set_wasm_module_for_inlining(wasm_module);
964 if (!data->source_positions()->IsEnabled()) {
965 data->source_positions()->Enable();
966 data->source_positions()->AddDecorator();
973#if V8_ENABLE_WEBASSEMBLY
974struct JSWasmInliningPhase {
976 void Run(TFPipelineData* data,
Zone* temp_zone) {
977 DCHECK(data->has_js_wasm_calls());
981 GraphReducer graph_reducer(temp_zone, data->graph(), &info->tick_counter(),
982 data->broker(), data->jsgraph()->Dead());
983 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
984 data->common(), temp_zone);
985 CommonOperatorReducer common_reducer(
986 &graph_reducer, data->graph(), data->broker(), data->common(),
987 data->machine(), temp_zone, BranchSemantics::kMachine);
992 JSInliningHeuristic::Mode mode =
993 (
v8_flags.turboshaft_wasm_in_js_inlining)
994 ? JSInliningHeuristic::kWasmWrappersOnly
995 : JSInliningHeuristic::kWasmFullInlining;
996 JSInliningHeuristic inlining(
997 &graph_reducer, temp_zone, data->info(), data->jsgraph(),
998 data->broker(), data->source_positions(), data->node_origins(), mode,
999 data->wasm_module_for_inlining(), data->js_wasm_calls_sidetable());
1000 AddReducer(data, &graph_reducer, &dead_code_elimination);
1001 AddReducer(data, &graph_reducer, &common_reducer);
1002 AddReducer(data, &graph_reducer, &inlining);
1003 graph_reducer.ReduceGraph();
1007struct JSWasmLoweringPhase {
1009 void Run(TFPipelineData* data,
Zone* temp_zone) {
1010 DCHECK(data->has_js_wasm_calls());
1013 OptimizedCompilationInfo* info = data->info();
1014 GraphReducer graph_reducer(temp_zone, data->graph(), &info->tick_counter(),
1015 data->broker(), data->jsgraph()->Dead());
1017 const bool disable_trap_handler =
true;
1018 WasmGCLowering lowering(&graph_reducer, data->jsgraph(),
1019 data->wasm_module_for_inlining(),
1020 disable_trap_handler, data->source_positions());
1021 AddReducer(data, &graph_reducer, &lowering);
1022 graph_reducer.ReduceGraph();
1033 data->jsgraph()->GetCachedNodes(&roots);
1044 data->jsgraph()->GetCachedNodes(&roots);
1047 roots.
push_back(data->jsgraph()->TrueConstant());
1048 roots.
push_back(data->jsgraph()->FalseConstant());
1051 data->common(), temp_zone);
1052 if (
v8_flags.turbo_loop_variable) induction_vars.
Run();
1056 typer->Run(roots, &induction_vars);
1064 class RemoveTypeReducer final :
public Reducer {
1066 const char* reducer_name()
const override {
return "RemoveTypeReducer"; }
1068 if (NodeProperties::IsTyped(node)) {
1069 NodeProperties::RemoveType(node);
1070 return Changed(node);
1077 data->jsgraph()->GetCachedNodes(&roots);
1078 for (
Node* node : roots) {
1079 NodeProperties::RemoveType(node);
1083 temp_zone, data->graph(), &data->info()->tick_counter(), data->broker(),
1084 data->jsgraph()->Dead(), data->observe_node_manager());
1085 RemoveTypeReducer remove_type_reducer;
1086 AddReducer(data, &graph_reducer, &remove_type_reducer);
1095 data->broker()->AttachCompilationInfo(data->info());
1096 data->broker()->InitializeAndStartSerializing(data->native_context());
1105 temp_zone, data->graph(), &data->info()->tick_counter(), data->broker(),
1106 data->jsgraph()->Dead(), data->observe_node_manager());
1108 data->common(), temp_zone);
1110 data->broker(), temp_zone);
1112 data->broker(), temp_zone);
1114 &graph_reducer, data->jsgraph(), data->broker());
1116 data->jsgraph(), data->broker());
1118 &graph_reducer, data->jsgraph(), data->broker(), BranchSemantics::kJS);
1121 &graph_reducer, data->
graph(), data->broker(), data->common(),
1122 data->machine(), temp_zone, BranchSemantics::kJS);
1123 AddReducer(data, &graph_reducer, &dead_code_elimination);
1125 AddReducer(data, &graph_reducer, &create_lowering);
1126 AddReducer(data, &graph_reducer, &constant_folding_reducer);
1127 AddReducer(data, &graph_reducer, &typed_lowering);
1128 AddReducer(data, &graph_reducer, &typed_optimization);
1129 AddReducer(data, &graph_reducer, &simple_reducer);
1130 AddReducer(data, &graph_reducer, &checkpoint_elimination);
1131 AddReducer(data, &graph_reducer, &common_reducer);
1146 &data->info()->tick_counter(), temp_zone);
1147 escape_analysis.ReduceGraph();
1150 &data->info()->tick_counter(), data->broker(),
1151 data->jsgraph()->Dead(), data->observe_node_manager());
1153 &reducer, data->jsgraph(), data->broker(),
1156 AddReducer(data, &reducer, &escape_reducer);
1173 temp_zone, data->graph(), Scheduler::kTempSchedule,
1174 &data->info()->tick_counter(), data->profile_data());
1185 data->source_positions(), data->node_origins(),
1186 &data->info()->tick_counter(),
linkage,
1187 data->info(), data->observe_node_manager());
1192 lowering.LowerAllNodes();
1202 data->jsgraph()->GetCachedNodes(&roots);
1209 LoopTree* loop_tree = LoopFinder::BuildLoopTree(
1210 data->jsgraph()->graph(), &data->info()->tick_counter(), temp_zone);
1214 LoopPeeler(data->graph(), data->common(), loop_tree, temp_zone,
1215 data->source_positions(), data->node_origins())
1224 LoopPeeler::EliminateLoopExits(data->graph(), temp_zone);
1233 temp_zone, data->graph(), &data->info()->tick_counter(), data->broker(),
1234 data->jsgraph()->Dead(), data->observe_node_manager());
1237 AddReducer(data, &graph_reducer, &generic_lowering);
1251 temp_zone, data->graph(), &data->info()->tick_counter(), data->broker(),
1252 data->jsgraph()->Dead(), data->observe_node_manager());
1254 data->common(), temp_zone);
1257 BranchSemantics::kMachine);
1259 data->jsgraph(), temp_zone);
1262 &graph_reducer, data->jsgraph(),
1263 MachineOperatorReducer::kPropagateSignallingNan);
1265 &graph_reducer, data->
graph(), data->broker(), data->common(),
1266 data->machine(), temp_zone, BranchSemantics::kMachine);
1267 AddReducer(data, &graph_reducer, &dead_code_elimination);
1268 AddReducer(data, &graph_reducer, &simple_reducer);
1269 AddReducer(data, &graph_reducer, &redundancy_elimination);
1270 AddReducer(data, &graph_reducer, &machine_reducer);
1271 AddReducer(data, &graph_reducer, &common_reducer);
1272 AddReducer(data, &graph_reducer, &value_numbering);
1282 temp_zone, data->graph(), &data->info()->tick_counter(), data->broker(),
1283 data->jsgraph()->Dead(), data->observe_node_manager());
1285 &graph_reducer, data->jsgraph(), temp_zone, BranchElimination::kEARLY);
1287 data->common(), temp_zone);
1289 data->jsgraph(), temp_zone);
1291 data->jsgraph(), temp_zone);
1295 &graph_reducer, data->
graph(), data->broker(), data->common(),
1296 data->machine(), temp_zone, BranchSemantics::kJS);
1298 data->jsgraph(), data->broker());
1300 &graph_reducer, data->jsgraph(), data->broker());
1304 AddReducer(data, &graph_reducer, &branch_condition_elimination);
1305 AddReducer(data, &graph_reducer, &dead_code_elimination);
1306 AddReducer(data, &graph_reducer, &redundancy_elimination);
1307 AddReducer(data, &graph_reducer, &load_elimination);
1308 AddReducer(data, &graph_reducer, &type_narrowing_reducer);
1309 AddReducer(data, &graph_reducer, &constant_folding_reducer);
1310 AddReducer(data, &graph_reducer, &typed_optimization);
1311 AddReducer(data, &graph_reducer, &checkpoint_elimination);
1312 AddReducer(data, &graph_reducer, &common_reducer);
1313 AddReducer(data, &graph_reducer, &value_numbering);
1329 data->jsgraph()->GetCachedNodes(&roots);
1337#if V8_ENABLE_WEBASSEMBLY
1338 bool is_wasm = data->info()->IsWasm() || data->info()->IsWasmBuiltin();
1340 bool is_wasm =
false;
1343 data->broker(), data->jsgraph(), temp_zone,
1344 data->info()->allocation_folding()
1345 ? MemoryLowering::AllocationFolding::kDoAllocationFolding
1346 : MemoryLowering::AllocationFolding::kDontAllocationFolding,
1347 data->debug_name(), &data->info()->tick_counter(), is_wasm);
1352#if V8_ENABLE_WEBASSEMBLY
1353struct WasmTypingPhase {
1356 void Run(TFPipelineData* data,
Zone* temp_zone, uint32_t function_index) {
1357 MachineGraph* mcgraph = data->mcgraph() ? data->mcgraph() : data->jsgraph();
1358 GraphReducer graph_reducer(
1359 temp_zone, data->graph(), &data->info()->tick_counter(), data->broker(),
1360 data->jsgraph()->Dead(), data->observe_node_manager());
1361 WasmTyper typer(&graph_reducer, mcgraph, function_index);
1362 AddReducer(data, &graph_reducer, &typer);
1363 graph_reducer.ReduceGraph();
1367struct WasmGCOptimizationPhase {
1370 void Run(TFPipelineData* data,
Zone* temp_zone,
1371 const wasm::WasmModule* module, MachineGraph* mcgraph) {
1372 GraphReducer graph_reducer(
1373 temp_zone, data->graph(), &data->info()->tick_counter(), data->broker(),
1374 data->jsgraph()->Dead(), data->observe_node_manager());
1375 WasmLoadElimination load_elimination(&graph_reducer, data->jsgraph(),
1377 WasmGCOperatorReducer wasm_gc(&graph_reducer, temp_zone, mcgraph, module,
1378 data->source_positions());
1379 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
1380 data->common(), temp_zone);
1381 AddReducer(data, &graph_reducer, &load_elimination);
1382 AddReducer(data, &graph_reducer, &wasm_gc);
1383 AddReducer(data, &graph_reducer, &dead_code_elimination);
1384 graph_reducer.ReduceGraph();
1388struct SimplifyLoopsPhase {
1391 void Run(TFPipelineData* data,
Zone* temp_zone) {
1392 GraphReducer graph_reducer(
1393 temp_zone, data->graph(), &data->info()->tick_counter(), data->broker(),
1394 data->jsgraph()->Dead(), data->observe_node_manager());
1395 SimplifyTFLoops simplify_loops(&graph_reducer, data->mcgraph());
1396 AddReducer(data, &graph_reducer, &simplify_loops);
1397 graph_reducer.ReduceGraph();
1401struct WasmGCLoweringPhase {
1404 void Run(TFPipelineData* data,
Zone* temp_zone,
1405 const wasm::WasmModule* module) {
1406 GraphReducer graph_reducer(
1407 temp_zone, data->graph(), &data->info()->tick_counter(), data->broker(),
1408 data->jsgraph()->Dead(), data->observe_node_manager());
1409 WasmGCLowering lowering(&graph_reducer, data->mcgraph(), module,
false,
1410 data->source_positions());
1411 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
1412 data->common(), temp_zone);
1413 AddReducer(data, &graph_reducer, &lowering);
1414 AddReducer(data, &graph_reducer, &dead_code_elimination);
1415 graph_reducer.ReduceGraph();
1419struct WasmOptimizationPhase {
1422 void Run(TFPipelineData* data,
Zone* temp_zone,
1423 MachineOperatorReducer::SignallingNanPropagation
1424 signalling_nan_propagation,
1425 wasm::WasmDetectedFeatures detected_features) {
1430 if (detected_features.has_gc()) {
1431 GraphReducer graph_reducer(temp_zone, data->graph(),
1432 &data->info()->tick_counter(), data->broker(),
1433 data->jsgraph()->Dead(),
1434 data->observe_node_manager());
1435 MachineOperatorReducer machine_reducer(&graph_reducer, data->jsgraph(),
1436 signalling_nan_propagation);
1437 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
1438 data->common(), temp_zone);
1439 CommonOperatorReducer common_reducer(
1440 &graph_reducer, data->graph(), data->broker(), data->common(),
1441 data->machine(), temp_zone, BranchSemantics::kMachine);
1442 ValueNumberingReducer value_numbering(temp_zone, data->graph()->zone());
1443 CsaLoadElimination load_elimination(&graph_reducer, data->jsgraph(),
1445 WasmEscapeAnalysis escape(&graph_reducer, data->mcgraph());
1446 AddReducer(data, &graph_reducer, &machine_reducer);
1447 AddReducer(data, &graph_reducer, &dead_code_elimination);
1448 AddReducer(data, &graph_reducer, &common_reducer);
1449 AddReducer(data, &graph_reducer, &value_numbering);
1450 AddReducer(data, &graph_reducer, &load_elimination);
1451 AddReducer(data, &graph_reducer, &escape);
1452 graph_reducer.ReduceGraph();
1455 GraphReducer graph_reducer(temp_zone, data->graph(),
1456 &data->info()->tick_counter(), data->broker(),
1457 data->jsgraph()->Dead(),
1458 data->observe_node_manager());
1459 MachineOperatorReducer machine_reducer(&graph_reducer, data->jsgraph(),
1460 signalling_nan_propagation);
1461 DeadCodeElimination dead_code_elimination(&graph_reducer, data->graph(),
1462 data->common(), temp_zone);
1463 CommonOperatorReducer common_reducer(
1464 &graph_reducer, data->graph(), data->broker(), data->common(),
1465 data->machine(), temp_zone, BranchSemantics::kMachine);
1466 ValueNumberingReducer value_numbering(temp_zone, data->graph()->zone());
1467 BranchElimination branch_condition_elimination(
1468 &graph_reducer, data->jsgraph(), temp_zone);
1469 AddReducer(data, &graph_reducer, &machine_reducer);
1470 AddReducer(data, &graph_reducer, &dead_code_elimination);
1471 AddReducer(data, &graph_reducer, &common_reducer);
1472 AddReducer(data, &graph_reducer, &value_numbering);
1473 AddReducer(data, &graph_reducer, &branch_condition_elimination);
1474 graph_reducer.ReduceGraph();
1485 temp_zone, data->graph(),
1486 data->info()->splitting() ? Scheduler::kSplitNodes
1487 : Scheduler::kNoFlags,
1488 &data->info()->tick_counter(), data->profile_data());
1493#if V8_ENABLE_WASM_SIMD256_REVEC
1494struct RevectorizePhase {
1497 void Run(TFPipelineData* data,
Zone* temp_zone) {
1498 Revectorizer revec(temp_zone, data->graph(), data->mcgraph(),
1499 data->source_positions());
1500 revec.TryRevectorize(data->info()->GetDebugName().get());
1510 TFGraph* graph = data->graph();
1511 if (info->trace_turbo_json()) {
1512 UnparkedScopeIfNeeded scope(data->broker());
1513 AllowHandleDereference allow_deref;
1515 TurboJsonFile json_of(info, std::ios_base::app);
1516 json_of <<
"{\"name\":\"" << phase <<
"\",\"type\":\"graph\",\"data\":"
1517 << AsJSON(*graph, data->source_positions(), data->node_origins())
1521 if (info->trace_turbo_scheduled()) {
1522 AccountingAllocator allocator;
1523 Schedule* schedule = data->schedule();
1524 if (schedule == nullptr) {
1525 schedule = Scheduler::ComputeSchedule(
1526 temp_zone, data->graph(), Scheduler::kNoFlags,
1527 &info->tick_counter(), data->profile_data());
1534 <<
"----- Graph after " << phase <<
" ----- " << std::endl
1536 }
else if (info->trace_turbo_graph()) {
1537 UnparkedScopeIfNeeded scope(data->broker());
1538 AllowHandleDereference allow_deref;
1539 CodeTracer::StreamScope tracing_scope(data->GetCodeTracer());
1540 tracing_scope.stream()
1541 <<
"----- Graph after " << phase <<
" ----- " << std::endl
1551 bool values_only = false) {
1553 switch (data->info()->code_kind()) {
1554 case CodeKind::WASM_FUNCTION:
1555 case CodeKind::WASM_TO_CAPI_FUNCTION:
1556 case CodeKind::WASM_TO_JS_FUNCTION:
1557 case CodeKind::JS_TO_WASM_FUNCTION:
1558 case CodeKind::C_WASM_ENTRY:
1559 code_type = Verifier::kWasm;
1562 code_type = Verifier::kDefault;
1570#undef DECL_MAIN_THREAD_PIPELINE_PHASE_CONSTANTS
1571#undef DECL_PIPELINE_PHASE_CONSTANTS
1572#undef DECL_PIPELINE_PHASE_CONSTANTS_HELPER
1574#if V8_ENABLE_WEBASSEMBLY
1577 WasmHeapStubCompilationJob(
Isolate* isolate, CallDescriptor* call_descriptor,
1578 std::unique_ptr<Zone> zone, TFGraph* graph,
1586 debug_name_(
std::move(debug_name)),
1587 info_(
base::CStrVector(debug_name_.get()), graph->zone(),
kind),
1588 call_descriptor_(call_descriptor),
1589 zone_stats_(zone->allocator()),
1595 data_(&zone_stats_, &
info_, isolate,
wasm::GetWasmEngine()->allocator(),
1596 graph_, nullptr, nullptr, nullptr,
1597 zone_->New<NodeOriginTable>(
graph_), nullptr, options, nullptr),
1598 pipeline_(&
data_) {}
1600 WasmHeapStubCompilationJob(
const WasmHeapStubCompilationJob&) =
delete;
1601 WasmHeapStubCompilationJob& operator=(
const WasmHeapStubCompilationJob&) =
1605 Status PrepareJobImpl(
Isolate* isolate)
final;
1606 Status ExecuteJobImpl(RuntimeCallStats* stats,
1607 LocalIsolate* local_isolate)
final;
1608 Status FinalizeJobImpl(
Isolate* isolate)
final;
1611 const std::unique_ptr<char[]> debug_name_;
1612 OptimizedCompilationInfo
info_;
1613 CallDescriptor*
const call_descriptor_;
1614 ZoneStats zone_stats_;
1615 const std::unique_ptr<Zone>
zone_;
1618 TFPipelineData
data_;
1619 PipelineImpl pipeline_;
1622#if V8_ENABLE_WEBASSEMBLY
1623class WasmTurboshaftWrapperCompilationJob final
1624 :
public turboshaft::TurboshaftCompilationJob {
1626 WasmTurboshaftWrapperCompilationJob(Isolate* isolate,
1627 const wasm::CanonicalSig* sig,
1628 wasm::WrapperCompilationInfo wrapper_info,
1629 std::unique_ptr<
char[]> debug_name,
1630 const AssemblerOptions& options)
1634 : TurboshaftCompilationJob(&
info_,
1635 CompilationJob::State::kReadyToExecute),
1637 debug_name_(
std::move(debug_name)),
1639 wrapper_info.code_kind),
1641 wrapper_info_(wrapper_info),
1643 GetCallDescriptor(&
zone_, sig, wrapper_info_.code_kind)),
1644 zone_stats_(
zone_.allocator()),
1647 wrapper_info_.code_kind == CodeKind::JS_TO_WASM_FUNCTION
1648 ? turboshaft::TurboshaftPipelineKind::kJSToWasm
1649 : turboshaft::TurboshaftPipelineKind::kWasm,
1650 isolate, &
info_, options),
1651 data_(&zone_stats_, &
info_, isolate,
wasm::GetWasmEngine()->allocator(),
1652 nullptr, nullptr, nullptr, nullptr, nullptr, nullptr, options,
1654 pipeline_(&
data_) {}
1656 WasmTurboshaftWrapperCompilationJob(
1657 const WasmTurboshaftWrapperCompilationJob&) =
delete;
1658 WasmTurboshaftWrapperCompilationJob& operator=(
1659 const WasmTurboshaftWrapperCompilationJob&) =
delete;
1662 Status PrepareJobImpl(Isolate* isolate)
final;
1663 Status ExecuteJobImpl(RuntimeCallStats* stats,
1664 LocalIsolate* local_isolate)
final;
1665 Status FinalizeJobImpl(Isolate* isolate)
final;
1668 static CallDescriptor* GetCallDescriptor(
Zone* zone,
1669 const wasm::CanonicalSig* sig,
1670 CodeKind code_kind) {
1671 if (code_kind == CodeKind::WASM_TO_JS_FUNCTION) {
1672 CallDescriptor* call_descriptor = compiler::GetWasmCallDescriptor(
1673 zone, sig, WasmCallKind::kWasmImportWrapper);
1674 return Is64() ? call_descriptor
1675 : GetI32WasmCallDescriptor(zone, call_descriptor);
1677 DCHECK_EQ(code_kind, CodeKind::JS_TO_WASM_FUNCTION);
1678 return Linkage::GetJSCallDescriptor(
1679 zone,
false,
static_cast<int>(
sig->parameter_count()) + 1,
1680 CallDescriptor::kNoFlags);
1684 const std::unique_ptr<char[]> debug_name_;
1685 OptimizedCompilationInfo
info_;
1686 const wasm::CanonicalSig*
const sig_;
1687 const wasm::WrapperCompilationInfo wrapper_info_;
1688 CallDescriptor*
const call_descriptor_;
1689 ZoneStats zone_stats_;
1691 TFPipelineData
data_;
1692 PipelineImpl pipeline_;
1693 std::unique_ptr<TurbofanPipelineStatistics> pipeline_statistics_;
1697std::unique_ptr<TurbofanCompilationJob> Pipeline::NewWasmHeapStubCompilationJob(
1698 Isolate* isolate, CallDescriptor* call_descriptor,
1699 std::unique_ptr<Zone> zone, TFGraph* graph,
CodeKind kind,
1700 std::unique_ptr<
char[]> debug_name,
const AssemblerOptions& options) {
1701 return std::make_unique<WasmHeapStubCompilationJob>(
1702 isolate, call_descriptor, std::move(zone), graph,
kind,
1703 std::move(debug_name), options);
1707std::unique_ptr<turboshaft::TurboshaftCompilationJob>
1708Pipeline::NewWasmTurboshaftWrapperCompilationJob(
1709 Isolate* isolate,
const wasm::CanonicalSig*
sig,
1710 wasm::WrapperCompilationInfo wrapper_info,
1711 std::unique_ptr<
char[]> debug_name,
const AssemblerOptions& options) {
1712 return std::make_unique<WasmTurboshaftWrapperCompilationJob>(
1713 isolate,
sig, wrapper_info, std::move(debug_name), options);
1725void TraceWrapperCompilation(
const char* compiler,
1726 OptimizedCompilationInfo* info,
1727 TFPipelineData* data) {
1728 if (info->trace_turbo_json() || info->trace_turbo_graph()) {
1729 CodeTracer::StreamScope tracing_scope(data->GetCodeTracer());
1730 tracing_scope.stream()
1731 <<
"---------------------------------------------------\n"
1732 <<
"Begin compiling method " << info->GetDebugName().get() <<
" using "
1733 << compiler << std::endl;
1736 if (info->trace_turbo_json()) {
1737 TurboJsonFile json_of(info, std::ios_base::trunc);
1738 json_of <<
"{\"function\":\"" << info->GetDebugName().get()
1739 <<
"\", \"source\":\"\",\n\"phases\":[";
1743void TraceWrapperCompilation(OptimizedCompilationInfo* info,
1744 turboshaft::PipelineData* data) {
1745 if (info->trace_turbo_json() || info->trace_turbo_graph()) {
1746 CodeTracer::StreamScope tracing_scope(data->GetCodeTracer());
1747 tracing_scope.stream()
1748 <<
"---------------------------------------------------\n"
1749 <<
"Begin compiling method " << info->GetDebugName().get()
1750 <<
" using Turboshaft" << std::endl;
1753 if (info->trace_turbo_json()) {
1754 TurboJsonFile json_of(info, std::ios_base::trunc);
1755 json_of <<
"{\"function\":\"" << info->GetDebugName().get()
1756 <<
"\", \"source\":\"\",\n\"phases\":[";
1761 turboshaft::PipelineData* turboshaft_data, OptimizedCompilationInfo* info,
1762 CallDescriptor* call_descriptor, Isolate* isolate,
1763 const char* method_name) {
1765 turboshaft::Pipeline pipeline(turboshaft_data);
1766 if (!pipeline.FinalizeCode(call_descriptor).ToHandle(&code)) {
1770 info->SetCode(code);
1771#ifdef ENABLE_DISASSEMBLER
1773 CodeTracer::StreamScope tracing_scope(isolate->GetCodeTracer());
1774 code->Disassemble(info->GetDebugName().get(), tracing_scope.stream(),
1779 if (isolate->IsLoggingCodeCreation()) {
1780 PROFILE(isolate, CodeCreateEvent(LogEventListener::CodeTag::kStub,
1782 info->GetDebugName().get()));
1784 if (code->kind() == CodeKind::WASM_TO_JS_FUNCTION) {
1785 code->set_wasm_js_tagged_parameter_count(
1786 call_descriptor->GetTaggedParameterSlots() & 0xffff);
1787 code->set_wasm_js_first_tagged_parameter(
1788 call_descriptor->GetTaggedParameterSlots() >> 16);
1795 RuntimeCallStats* stats, LocalIsolate* local_isolate) {
1796 std::unique_ptr<TurbofanPipelineStatistics> pipeline_statistics;
1798 pipeline_statistics.reset(
new TurbofanPipelineStatistics(
1801 pipeline_statistics->BeginPhaseKind(
"V8.WasmStubCodegen");
1803 TraceWrapperCompilation(
"Turbofan", &
info_, &
data_);
1804 pipeline_.RunPrintAndVerify(
"V8.WasmMachineCode",
true);
1805 if (!pipeline_.Run<MemoryOptimizationPhase>())
return FAILED;
1806 if (!pipeline_.ComputeScheduledGraph())
return FAILED;
1811 Linkage
linkage(call_descriptor_);
1812 if (!turboshaft_pipeline.CreateGraphFromTurbofan(&
data_, &
linkage)) {
1818 if (!turboshaft_pipeline.RunSimplificationAndNormalizationPhase()) {
1822 const bool success = GenerateCodeFromTurboshaftGraph(
1823 &
linkage, turboshaft_pipeline, &pipeline_,
data_.osr_helper_ptr());
1824 return success ? SUCCEEDED : FAILED;
1829 return FinalizeWrapperCompilation(
1831 "WasmHeapStubCompilationJob::FinalizeJobImpl");
1840 RuntimeCallStats* stats, LocalIsolate* local_isolate) {
1843 pipeline_statistics_ = std::make_unique<TurbofanPipelineStatistics>(
1846 pipeline_statistics_->BeginPhaseKind(
"V8.WasmStubCodegen");
1849 Linkage
linkage(call_descriptor_);
1854 AccountingAllocator allocator;
1857 sig_, wrapper_info_);
1858 CodeTracer* code_tracer =
nullptr;
1859 if (
info_.trace_turbo_graph()) {
1867 code_tracer,
"Graph generation");
1874 if (!turboshaft_pipeline.Run<turboshaft::WasmOptimizePhase>()) {
1882 if (!turboshaft_pipeline.Run<turboshaft::WasmDebugMemoryLoweringPhase>()) {
1889 if (!turboshaft_pipeline.Run<turboshaft::Int64LoweringPhase>()) {
1894 if (!turboshaft_pipeline.Run<turboshaft::WasmDeadCodeEliminationPhase>()) {
1901 if (!turboshaft_pipeline.Run<turboshaft::DebugFeatureLoweringPhase>()) {
1906 turboshaft_pipeline.BeginPhaseKind(
"V8.InstructionSelection");
1908 const bool success = GenerateCodeFromTurboshaftGraph(
1909 &
linkage, turboshaft_pipeline, &pipeline_);
1910 return success ? SUCCEEDED : FAILED;
1915 return FinalizeWrapperCompilation(
1917 "WasmTurboshaftWrapperCompilationJob::FinalizeJobImpl");
1923 if (
info()->trace_turbo_json() ||
info()->trace_turbo_graph()) {
1936 if (
info()->trace_turbo_json() ||
info()->trace_turbo_graph()) {
1939 <<
"---------------------------------------------------\n"
1941 <<
" using TurboFan" << std::endl;
1943 if (
info()->trace_turbo_json()) {
1947 if (data->info()->has_bytecode_array()) {
1948 if (data->info()->bytecode_array()->SourcePositionTable()->DataSize() ==
1950 data->source_positions()->Disable();
1952 data->source_positions()->AddDecorator();
1954 if (data->info()->trace_turbo_json()) {
1955 data->node_origins()->AddDecorator();
1959 data->broker()->StopSerializing();
1960 data->EndPhaseKind();
1969 data->BeginPhaseKind(
"V8.TFGraphCreation");
1981 MakeRef(data->broker(), info()->shared_info());
1982 if (
is_sloppy(shared_info.language_mode()) &&
1983 shared_info.IsUserJavaScript()) {
1993 data->EndPhaseKind();
2016 if (data->info()->loop_peeling()) {
2024 if (
v8_flags.turbo_load_elimination) {
2028 data->DeleteTyper();
2046#if V8_ENABLE_WEBASSEMBLY
2047 if (data->has_js_wasm_calls()) {
2048 DCHECK(data->info()->inline_js_wasm_calls());
2056 RUN_MAYBE_ABORT(WasmGCOptimizationPhase, data->wasm_module_for_inlining(),
2063 if (
v8_flags.turbo_optimize_inlined_js_wasm_wrappers &&
v8_flags.wasm_opt) {
2089 data->BeginPhaseKind(
"V8.TFBlockBuilding");
2091 data->InitializeFrameData(
linkage->GetIncomingDescriptor());
2097 data->source_positions()->RemoveDecorator();
2098 if (data->info()->trace_turbo_json()) {
2099 data->node_origins()->RemoveDecorator();
2113 const auto op_hash =
2117 constexpr bool kTraceHashing =
false;
2118 if constexpr (kTraceHashing) {
2119 std::cout <<
"[" << std::setw(3) << graph->Index(derived)
2120 <<
"] Type: " << std::setw(30)
2123 std::cout <<
" + 0x" << std::setw(20) << std::left << std::hex
2124 << op_hash <<
" => 0x" << hash << std::dec << std::endl;
2138int HashGraphForPGO(
const TFGraph* graph) {
2139 AccountingAllocator allocator;
2142 constexpr NodeId kUnassigned =
static_cast<NodeId>(-1);
2158 ZoneVector<uint8_t>
state(graph->NodeCount(),
kUnvisited, &local_zone);
2159 ZoneVector<NodeId> traversal_numbers(graph->NodeCount(), kUnassigned,
2161 ZoneStack<Node*>
stack(&local_zone);
2163 NodeId visited_count = 0;
2166 stack.push(graph->end());
2167 state[graph->end()->id()] =
kOnStack;
2168 traversal_numbers[graph->end()->id()] = visited_count++;
2169 while (!stack.empty()) {
2170 Node* n = stack.top();
2172 for (Node*
const i : n->inputs()) {
2175 traversal_numbers[
i->
id()] = visited_count++;
2186 for (Node*
const i : n->inputs()) {
2187 DCHECK(traversal_numbers[
i->
id()] != kUnassigned);
2195template <
typename Graph>
2196int ComputeInitialGraphHash(
Builtin builtin,
2197 const ProfileDataFromFile* profile_data,
2198 const Graph* graph) {
2199 int initial_graph_hash = 0;
2201 profile_data !=
nullptr) {
2202 initial_graph_hash = HashGraphForPGO(graph);
2203 if (
v8_flags.dump_builtins_hashes_to_file) {
2204 std::ofstream out(
v8_flags.dump_builtins_hashes_to_file,
2205 std::ios_base::app);
2206 out <<
"Builtin: " <<
Builtins::name(builtin) <<
", hash: 0x" << std::hex
2207 << initial_graph_hash << std::endl;
2210 return initial_graph_hash;
2213const ProfileDataFromFile* ValidateProfileData(
2214 const ProfileDataFromFile* profile_data,
int initial_graph_hash,
2215 const char* debug_name) {
2216 if (profile_data !=
nullptr && profile_data->hash() != initial_graph_hash) {
2220 if (
v8_flags.abort_on_bad_builtin_profile_data ||
2221 v8_flags.warn_about_builtin_profile_data) {
2222 base::EmbeddedVector<char, 256> msg;
2224 "Rejected profile data for %s due to function change. "
2225 "Please use tools/builtins-pgo/generate.py to refresh it.",
2227 if (
v8_flags.abort_on_bad_builtin_profile_data) {
2238 FATAL(
"%s", msg.begin());
2240 PrintF(
"%s\n", msg.begin());
2243#ifdef LOG_BUILTIN_BLOCK_COUNT
2244 if (
v8_flags.turbo_log_builtins_count_input) {
2245 PrintF(
"The hash came from execution count file for %s was not match!\n",
2251 return profile_data;
2266 data.set_verify_graph(
v8_flags.verify_csa);
2276 CodeKind code_kind,
const char* name,
2279 State::kReadyToPrepare),
2281 installer_(installer),
2282 profile_data_(profile_data),
2284 zone_stats_(isolate->allocator()),
2285 code_assembler_state_(isolate, &
zone_, get_call_descriptor(&
zone_),
2286 code_kind, name, builtin),
2287 assembler_options_(assembler_options),
2288 compilation_info_(
base::CStrVector(name), &
zone_, code_kind),
2291 finalize_order_(finalize_order) {
2292 DCHECK(code_kind == CodeKind::BUILTIN ||
2293 code_kind == CodeKind::BYTECODE_HANDLER ||
2294 code_kind == CodeKind::FOR_TESTING);