v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
maglev-compiler.cc
Go to the documentation of this file.
1// Copyright 2022 the V8 project authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
6
7#include <algorithm>
8#include <iomanip>
9#include <ostream>
10#include <type_traits>
11#include <unordered_map>
12
13#include "src/base/iterator.h"
14#include "src/base/logging.h"
20#include "src/codegen/reglist.h"
21#include "src/common/globals.h"
29#include "src/flags/flags.h"
53#include "src/zone/zone.h"
54
55namespace v8 {
56namespace internal {
57namespace maglev {
58
59// static
61 MaglevCompilationInfo* compilation_info) {
62 compiler::CurrentHeapBrokerScope current_broker(compilation_info->broker());
63 Graph* graph =
64 Graph::New(compilation_info->zone(),
65 compilation_info->toplevel_compilation_unit()->is_osr());
66
67 bool is_tracing_enabled = false;
68 {
69 UnparkedScopeIfOnBackground unparked_scope(local_isolate->heap());
70
71 // Build graph.
72 if (v8_flags.print_maglev_code || v8_flags.code_comments ||
73 v8_flags.print_maglev_graph || v8_flags.print_maglev_graphs ||
74 v8_flags.trace_maglev_graph_building ||
75 v8_flags.trace_maglev_escape_analysis ||
76 v8_flags.trace_maglev_phi_untagging || v8_flags.trace_maglev_regalloc ||
77 v8_flags.trace_maglev_object_tracking) {
78 is_tracing_enabled = compilation_info->toplevel_compilation_unit()
80 .object()
81 ->PassesFilter(v8_flags.maglev_print_filter);
82 compilation_info->set_graph_labeller(new MaglevGraphLabeller());
83 }
84
85 if (is_tracing_enabled &&
86 (v8_flags.print_maglev_code || v8_flags.print_maglev_graph ||
87 v8_flags.print_maglev_graphs || v8_flags.trace_maglev_graph_building ||
88 v8_flags.trace_maglev_phi_untagging ||
89 v8_flags.trace_maglev_regalloc)) {
90 MaglevCompilationUnit* top_level_unit =
91 compilation_info->toplevel_compilation_unit();
92 std::cout << "Compiling " << Brief(*compilation_info->toplevel_function())
93 << " with Maglev\n";
94 BytecodeArray::Disassemble(top_level_unit->bytecode().object(),
95 std::cout);
96 if (v8_flags.maglev_print_feedback) {
97 Print(*top_level_unit->feedback().object(), std::cout);
98 }
99 }
100
101 MaglevGraphBuilder graph_builder(
102 local_isolate, compilation_info->toplevel_compilation_unit(), graph);
103
104 {
106 "V8.Maglev.GraphBuilding");
107 graph_builder.Build();
108
109 if (is_tracing_enabled && v8_flags.print_maglev_graphs) {
110 std::cout << "\nAfter graph building" << std::endl;
111 PrintGraph(std::cout, compilation_info, graph);
112 }
113 }
114
115#ifdef DEBUG
116 {
117 GraphProcessor<MaglevGraphVerifier, /* visit_identity_nodes */ true>
118 verifier(compilation_info);
119 verifier.ProcessGraph(graph);
120 }
121#endif
122
123 if (v8_flags.maglev_non_eager_inlining) {
125 "V8.Maglev.Inlining");
126
127 MaglevInliner inliner(compilation_info, graph);
128 inliner.Run(is_tracing_enabled);
129
130 // TODO(victorgomes): We need to remove all identity nodes before
131 // PhiRepresentationSelector. Since Identity has different semantics
132 // there. Check if we can remove the identity nodes during
133 // PhiRepresentationSelector instead.
134 GraphProcessor<SweepIdentityNodes, /* visit_identity_nodes */ true> sweep;
135 sweep.ProcessGraph(graph);
136 }
137
138#ifdef DEBUG
139 {
140 GraphProcessor<MaglevGraphVerifier, /* visit_identity_nodes */ true>
141 verifier(compilation_info);
142 verifier.ProcessGraph(graph);
143 }
144#endif
145
146 if (v8_flags.maglev_licm) {
148 "V8.Maglev.LoopOptimizations");
149
151 &graph_builder);
152 loop_optimizations.ProcessGraph(graph);
153
154 if (is_tracing_enabled && v8_flags.print_maglev_graphs) {
155 std::cout << "\nAfter loop optimizations" << std::endl;
156 PrintGraph(std::cout, compilation_info, graph);
157 }
158 }
159
160#ifdef DEBUG
161 {
162 GraphProcessor<MaglevGraphVerifier, /* visit_identity_nodes */ true>
163 verifier(compilation_info);
164 verifier.ProcessGraph(graph);
165 }
166#endif
167
168 if (v8_flags.maglev_untagged_phis) {
170 "V8.Maglev.PhiUntagging");
171
173 &graph_builder);
174 representation_selector.ProcessGraph(graph);
175
176 if (is_tracing_enabled && v8_flags.print_maglev_graphs) {
177 std::cout << "\nAfter Phi untagging" << std::endl;
178 PrintGraph(std::cout, compilation_info, graph);
179 }
180 }
181 }
182
183#ifdef DEBUG
184 {
185 GraphProcessor<MaglevGraphVerifier, /* visit_identity_nodes */ true>
186 verifier(compilation_info);
187 verifier.ProcessGraph(graph);
188 }
189#endif
190
191 {
192 // Post-hoc optimisation:
193 // - Dead node marking
194 // - Cleaning up identity nodes
196 "V8.Maglev.DeadCodeMarking");
198 processor.ProcessGraph(graph);
199 }
200
201 if (is_tracing_enabled && v8_flags.print_maglev_graphs) {
202 UnparkedScopeIfOnBackground unparked_scope(local_isolate->heap());
203 std::cout << "After use marking" << std::endl;
204 PrintGraph(std::cout, compilation_info, graph);
205 }
206
207#ifdef DEBUG
208 {
209 GraphProcessor<MaglevGraphVerifier, /* visit_identity_nodes */ true>
210 verifier(compilation_info);
211 verifier.ProcessGraph(graph);
212 }
213#endif
214
215 {
216 RegallocInfo regalloc_info;
217 {
218 // Preprocessing for register allocation and code gen:
219 // - Remove dead nodes
220 // - Collect input/output location constraints
221 // - Find the maximum number of stack arguments passed to calls
222 // - Collect use information, for SSA liveness and next-use distance.
223 // - Mark
225 "V8.Maglev.NodeProcessing");
230 processor(DeadNodeSweepingProcessor{compilation_info},
231 LiveRangeAndNextUseProcessor{compilation_info, graph,
232 &regalloc_info});
233 processor.ProcessGraph(graph);
234 }
235
236 if (is_tracing_enabled && v8_flags.print_maglev_graphs) {
237 UnparkedScopeIfOnBackground unparked_scope(local_isolate->heap());
238 std::cout << "After register allocation pre-processing" << std::endl;
239 PrintGraph(std::cout, compilation_info, graph);
240 }
241
242 {
244 "V8.Maglev.RegisterAllocation");
245 StraightForwardRegisterAllocator allocator(compilation_info, graph,
246 &regalloc_info);
247 }
248
249 if (is_tracing_enabled &&
250 (v8_flags.print_maglev_graph || v8_flags.print_maglev_graphs)) {
251 UnparkedScopeIfOnBackground unparked_scope(local_isolate->heap());
252 std::cout << "After register allocation" << std::endl;
253 PrintGraph(std::cout, compilation_info, graph);
254 }
255 }
256
257 {
259 "V8.Maglev.CodeAssembly");
260 UnparkedScopeIfOnBackground unparked_scope(local_isolate->heap());
261 std::unique_ptr<MaglevCodeGenerator> code_generator =
262 std::make_unique<MaglevCodeGenerator>(local_isolate, compilation_info,
263 graph);
264 bool success = code_generator->Assemble();
265 if (!success) {
266 return false;
267 }
268
269 // Stash the compiled code_generator on the compilation info.
270 compilation_info->set_code_generator(std::move(code_generator));
271 }
272
273 return true;
274}
275
276// static
277std::pair<MaybeHandle<Code>, BailoutReason> MaglevCompiler::GenerateCode(
278 Isolate* isolate, MaglevCompilationInfo* compilation_info) {
279 compiler::CurrentHeapBrokerScope current_broker(compilation_info->broker());
280 MaglevCodeGenerator* const code_generator =
281 compilation_info->code_generator();
282 DCHECK_NOT_NULL(code_generator);
283
285 {
287 "V8.Maglev.CodeGeneration");
288 if (compilation_info->is_detached() ||
289 !code_generator->Generate(isolate).ToHandle(&code)) {
290 compilation_info->toplevel_compilation_unit()
292 .object()
293 ->set_maglev_compilation_failed(true);
294 return {{}, BailoutReason::kCodeGenerationFailed};
295 }
296 }
297
298 {
300 "V8.Maglev.CommittingDependencies");
301 if (!compilation_info->broker()->dependencies()->Commit(code)) {
302 // Don't `set_maglev_compilation_failed` s.t. we may reattempt
303 // compilation.
304 // TODO(v8:7700): Make this more robust, i.e.: don't recompile endlessly.
305 compilation_info->toplevel_function()->SetInterruptBudget(
307 return {{}, BailoutReason::kBailedOutDueToDependencyChange};
308 }
309 }
310
311 if (v8_flags.print_maglev_code) {
312#ifdef OBJECT_PRINT
313 std::unique_ptr<char[]> debug_name =
314 compilation_info->toplevel_function()->shared()->DebugNameCStr();
315 CodeTracer::StreamScope tracing_scope(isolate->GetCodeTracer());
316 auto& os = tracing_scope.stream();
317 code->CodePrint(os, debug_name.get());
318#else
319 Print(*code);
320#endif
321 }
322
323 return {code, BailoutReason::kNoReason};
324}
325
326} // namespace maglev
327} // namespace internal
328} // namespace v8
TFGraph * graph
V8_EXPORT_PRIVATE void Disassemble(std::ostream &os)
IndirectHandle< BytecodeArray > object() const
V8_WARN_UNUSED_RESULT bool Commit(Handle< Code > code)
IndirectHandle< FeedbackVector > object() const
CompilationDependencies * dependencies() const
IndirectHandle< SharedFunctionInfo > object() const
static Graph * New(Zone *zone, bool is_osr)
MaybeHandle< Code > Generate(Isolate *isolate)
void set_graph_labeller(MaglevGraphLabeller *graph_labeller)
IndirectHandle< JSFunction > toplevel_function() const
MaglevCompilationUnit * toplevel_compilation_unit() const
compiler::SharedFunctionInfoRef shared_function_info() const
compiler::BytecodeArrayRef bytecode() const
compiler::FeedbackVectorRef feedback() const
static bool Compile(LocalIsolate *local_isolate, MaglevCompilationInfo *compilation_info)
static std::pair< MaybeHandle< Code >, BailoutReason > GenerateCode(Isolate *isolate, MaglevCompilationInfo *compilation_info)
void Run(bool is_tracing_maglev_graphs_enabled)
Handle< Code > code
void PrintGraph(std::ostream &os, MaglevCompilationInfo *compilation_info, Graph *const graph)
void Print(Tagged< Object > obj)
Definition objects.h:774
V8_EXPORT_PRIVATE FlagValues v8_flags
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define TRACE_EVENT0(category_group, name)
#define TRACE_DISABLED_BY_DEFAULT(name)