v8
V8 is Google’s open source high-performance JavaScript and WebAssembly engine, written in C++.
Loading...
Searching...
No Matches
optimized-compilation-info.h
Go to the documentation of this file.
1// Copyright 2016 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
5#ifndef V8_CODEGEN_OPTIMIZED_COMPILATION_INFO_H_
6#define V8_CODEGEN_OPTIMIZED_COMPILATION_INFO_H_
7
8#include <memory>
9
10#include "src/base/vector.h"
14#include "src/common/globals.h"
17#include "src/handles/handles.h"
19#include "src/objects/objects.h"
20#include "src/objects/tagged.h"
22#include "src/utils/utils.h"
23
24#if V8_ENABLE_WEBASSEMBLY
26#endif
27
28namespace v8 {
29
30namespace tracing {
31class TracedValue;
32} // namespace tracing
33
34namespace internal {
35
36class FunctionLiteral;
37class Isolate;
38class JavaScriptFrame;
39class JSGlobalObject;
40class Zone;
41
42namespace compiler {
43class NodeObserver;
44class JSHeapBroker;
45}
46
47namespace wasm {
48struct WasmCompilationResult;
49} // namespace wasm
50
51// OptimizedCompilationInfo encapsulates the information needed to compile
52// optimized code for a given function, and the results of the optimized
53// compilation.
55 public:
56 // Various configuration flags for a compilation, as well as some properties
57 // of the compiled code produced by a compilation.
58
59#define FLAGS(V) \
60 V(FunctionContextSpecializing, function_context_specializing, 0) \
61 V(Inlining, inlining, 1) \
62 V(DisableFutureOptimization, disable_future_optimization, 2) \
63 V(Splitting, splitting, 3) \
64 V(SourcePositions, source_positions, 4) \
65 V(BailoutOnUninitialized, bailout_on_uninitialized, 5) \
66 V(LoopPeeling, loop_peeling, 6) \
67 V(SwitchJumpTable, switch_jump_table, 7) \
68 V(CalledWithCodeStartRegister, called_with_code_start_register, 8) \
69 V(AllocationFolding, allocation_folding, 9) \
70 V(AnalyzeEnvironmentLiveness, analyze_environment_liveness, 10) \
71 V(TraceTurboJson, trace_turbo_json, 11) \
72 V(TraceTurboGraph, trace_turbo_graph, 12) \
73 V(TraceTurboScheduled, trace_turbo_scheduled, 13) \
74 V(TraceTurboAllocation, trace_turbo_allocation, 14) \
75 V(TraceHeapBroker, trace_heap_broker, 15) \
76 V(DiscardResultForTesting, discard_result_for_testing, 16) \
77 V(InlineJSWasmCalls, inline_js_wasm_calls, 17) \
78 V(TurboshaftTraceReduction, turboshaft_trace_reduction, 18) \
79 V(CouldNotInlineAllCandidates, could_not_inline_all_candidates, 19) \
80 V(ShadowStackCompliantLazyDeopt, shadow_stack_compliant_lazy_deopt, 20)
81
82 enum Flag {
83#define DEF_ENUM(Camel, Lower, Bit) k##Camel = 1 << Bit,
85#undef DEF_ENUM
86 };
87
88#define DEF_GETTER(Camel, Lower, Bit) \
89 bool Lower() const { \
90 return GetFlag(k##Camel); \
91 }
93#undef DEF_GETTER
94
95#define DEF_SETTER(Camel, Lower, Bit) \
96 void set_##Lower() { \
97 SetFlag(k##Camel); \
98 }
100#undef DEF_SETTER
101
102 // Construct a compilation info for optimized compilation.
103 OptimizedCompilationInfo(Zone* zone, Isolate* isolate,
104 IndirectHandle<SharedFunctionInfo> shared,
105 IndirectHandle<JSFunction> closure,
106 CodeKind code_kind, BytecodeOffset osr_offset);
107 // For testing.
111 CodeKind code_kind)
112 : OptimizedCompilationInfo(zone, isolate, shared, closure, code_kind,
113 BytecodeOffset::None()) {}
114 // Construct a compilation info for stub compilation, Wasm, and testing.
116 CodeKind code_kind,
117 Builtin builtin = Builtin::kNoBuiltinId);
118
121
123
124 Zone* zone() { return zone_; }
125 bool is_osr() const { return !osr_offset_.IsNone(); }
127 return shared_info_;
128 }
129 bool has_shared_info() const { return !shared_info().is_null(); }
131 return bytecode_array_;
132 }
133 bool has_bytecode_array() const { return !bytecode_array_.is_null(); }
134 IndirectHandle<JSFunction> closure() const { return closure_; }
135 IndirectHandle<Code> code() const { return code_; }
136 CodeKind code_kind() const { return code_kind_; }
137 Builtin builtin() const { return builtin_; }
138 void set_builtin(Builtin builtin) { builtin_ = builtin; }
139 BytecodeOffset osr_offset() const { return osr_offset_; }
141 DCHECK_NULL(node_observer_);
142 node_observer_ = observer;
143 }
144 compiler::NodeObserver* node_observer() const { return node_observer_; }
145
146 // Code getters and setters.
147
148 void SetCode(IndirectHandle<Code> code);
149
150 bool has_context() const;
151 Tagged<Context> context() const;
152
153 bool has_native_context() const;
155
156 bool has_global_object() const;
157 Tagged<JSGlobalObject> global_object() const;
158
159 // Accessors for the different compilation modes.
160 bool IsOptimizing() const {
161 return CodeKindIsOptimizedJSFunction(code_kind());
162 }
163#if V8_ENABLE_WEBASSEMBLY
164 bool IsWasm() const { return code_kind() == CodeKind::WASM_FUNCTION; }
165 bool IsWasmBuiltin() const {
166 return code_kind() == CodeKind::WASM_TO_JS_FUNCTION ||
167 code_kind() == CodeKind::WASM_TO_CAPI_FUNCTION ||
168 code_kind() == CodeKind::JS_TO_WASM_FUNCTION ||
169 (code_kind() == CodeKind::BUILTIN &&
170 (builtin() == Builtin::kJSToWasmWrapper ||
171 builtin() == Builtin::kJSToWasmHandleReturns ||
172 builtin() == Builtin::kWasmToJsWrapperCSA ||
173 wasm::BuiltinLookup::IsWasmBuiltinId(builtin())));
174 }
175#endif // V8_ENABLE_WEBASSEMBLY
176
178 std::unique_ptr<PersistentHandles> persistent_handles) {
179 DCHECK_NULL(ph_);
180 ph_ = std::move(persistent_handles);
181 DCHECK_NOT_NULL(ph_);
182 }
183
185 std::unique_ptr<CanonicalHandlesMap> canonical_handles) {
186 DCHECK_NULL(canonical_handles_);
187 canonical_handles_ = std::move(canonical_handles);
188 DCHECK_NOT_NULL(canonical_handles_);
189 }
190
191 template <typename T>
193 DCHECK_NOT_NULL(canonical_handles_);
194 DCHECK(PersistentHandlesScope::IsActive(isolate));
195 auto find_result = canonical_handles_->FindOrInsert(object);
196 if (!find_result.already_exists) {
197 *find_result.entry = IndirectHandle<T>(object, isolate).location();
198 }
199 return IndirectHandle<T>(*find_result.entry);
200 }
201
202 void ReopenAndCanonicalizeHandlesInNewScope(Isolate* isolate);
203
204 void AbortOptimization(BailoutReason reason);
205
206 void RetryOptimization(BailoutReason reason);
207
209
210 int optimization_id() const {
211 DCHECK(IsOptimizing());
212 return optimization_id_;
213 }
214
215 unsigned inlined_bytecode_size() const { return inlined_bytecode_size_; }
216
217 void set_inlined_bytecode_size(unsigned size) {
218 inlined_bytecode_size_ = size;
219 }
220
224 bytecode_array; // Explicit to prevent flushing.
226
228 IndirectHandle<SharedFunctionInfo> inlined_shared_info,
230
231 void RegisterInlinedFunctionId(size_t inlined_function_id) {
232 position.inlined_function_id = static_cast<int>(inlined_function_id);
233 }
234 };
235
236 using InlinedFunctionList = std::vector<InlinedFunctionHolder>;
237 InlinedFunctionList& inlined_functions() { return inlined_functions_; }
238
239 // Returns the inlining id for source position tracking.
240 int AddInlinedFunction(IndirectHandle<SharedFunctionInfo> inlined_function,
241 IndirectHandle<BytecodeArray> inlined_bytecode,
243
244 std::unique_ptr<char[]> GetDebugName() const;
245
246 StackFrame::Type GetOutputStackFrameType() const;
247
248 const char* trace_turbo_filename() const {
249 return trace_turbo_filename_.get();
250 }
251
252 void set_trace_turbo_filename(std::unique_ptr<char[]> filename) {
253 trace_turbo_filename_ = std::move(filename);
254 }
255
256 TickCounter& tick_counter() { return tick_counter_; }
257
258 bool was_cancelled() const {
259 return was_cancelled_.load(std::memory_order_relaxed);
260 }
261
262 void mark_cancelled();
263
264 BasicBlockProfilerData* profiler_data() const { return profiler_data_; }
266 profiler_data_ = profiler_data;
267 }
268
269 std::unique_ptr<PersistentHandles> DetachPersistentHandles() {
270 DCHECK_NOT_NULL(ph_);
271 return std::move(ph_);
272 }
273
274 std::unique_ptr<CanonicalHandlesMap> DetachCanonicalHandles() {
275 DCHECK_NOT_NULL(canonical_handles_);
276 return std::move(canonical_handles_);
277 }
278
279 private:
280 void ConfigureFlags();
281
282 void SetFlag(Flag flag) { flags_ |= flag; }
283 bool GetFlag(Flag flag) const { return (flags_ & flag) != 0; }
284
285 void SetTracingFlags(bool passes_filter);
286
287 // Storing the raw pointer to the CanonicalHandlesMap is generally not safe.
288 // Use DetachCanonicalHandles() to transfer ownership instead.
289 // We explicitly allow the JSHeapBroker to store the raw pointer as it is
290 // guaranteed that the OptimizedCompilationInfo's lifetime exceeds the
291 // lifetime of the broker.
292 CanonicalHandlesMap* canonical_handles() { return canonical_handles_.get(); }
294
295 // Compilation flags.
296 unsigned flags_ = 0;
297
298 // Take care when accessing this on any background thread.
300
302 Builtin builtin_ = Builtin::kNoBuiltinId;
303
304 // We retain a reference the bytecode array specifically to ensure it doesn't
305 // get flushed while we are optimizing the code.
309
310 // The compiled code.
312
313 // Basic block profiling support.
314 BasicBlockProfilerData* profiler_data_ = nullptr;
315
316 // Entry point when compiling for OSR, {BytecodeOffset::None} otherwise.
317 const BytecodeOffset osr_offset_ = BytecodeOffset::None();
318
319 // The zone from which the compilation pipeline working on this
320 // OptimizedCompilationInfo allocates.
321 Zone* const zone_;
322
323 compiler::NodeObserver* node_observer_ = nullptr;
324
325 BailoutReason bailout_reason_ = BailoutReason::kNoReason;
326
328
329 static constexpr int kNoOptimizationId = -1;
331 unsigned inlined_bytecode_size_ = 0;
332
334 std::unique_ptr<char[]> trace_turbo_filename_;
335
337
338 std::atomic<bool> was_cancelled_ = false;
339
340 // 1) PersistentHandles created via PersistentHandlesScope inside of
341 // CompilationHandleScope
342 // 2) Owned by OptimizedCompilationInfo
343 // 3) Owned by the broker's LocalHeap when entering the LocalHeapScope.
344 // 4) Back to OptimizedCompilationInfo when exiting the LocalHeapScope.
345 //
346 // In normal execution it gets destroyed when PipelineData gets destroyed.
347 // There is a special case in GenerateCodeForTesting where the JSHeapBroker
348 // will not be retired in that same method. In this case, we need to re-attach
349 // the PersistentHandles container to the JSHeapBroker.
350 std::unique_ptr<PersistentHandles> ph_;
351
352 // Canonical handles follow the same path as described by the persistent
353 // handles above. The only difference is that is created in the
354 // CanonicalHandleScope(i.e step 1) is different).
355 std::unique_ptr<CanonicalHandlesMap> canonical_handles_;
356};
357
358} // namespace internal
359} // namespace v8
360
361#endif // V8_CODEGEN_OPTIMIZED_COMPILATION_INFO_H_
friend Zone
Definition asm-types.cc:195
#define DEF_ENUM(Name,...)
Definition builtins.h:50
SourcePosition pos
V8_INLINE Address * location() const
Definition handles.h:80
BasicBlockProfilerData * profiler_data() const
void set_trace_turbo_filename(std::unique_ptr< char[]> filename)
std::unique_ptr< PersistentHandles > ph_
void set_canonical_handles(std::unique_ptr< CanonicalHandlesMap > canonical_handles)
void set_profiler_data(BasicBlockProfilerData *profiler_data)
IndirectHandle< SharedFunctionInfo > shared_info_
OptimizedCompilationInfo(Zone *zone, Isolate *isolate, IndirectHandle< SharedFunctionInfo > shared, IndirectHandle< JSFunction > closure, CodeKind code_kind)
IndirectHandle< SharedFunctionInfo > shared_info() const
std::vector< InlinedFunctionHolder > InlinedFunctionList
void set_persistent_handles(std::unique_ptr< PersistentHandles > persistent_handles)
IndirectHandle< BytecodeArray > bytecode_array_
std::unique_ptr< CanonicalHandlesMap > canonical_handles_
OptimizedCompilationInfo & operator=(const OptimizedCompilationInfo &)=delete
IndirectHandle< JSFunction > closure() const
std::unique_ptr< PersistentHandles > DetachPersistentHandles()
void SetNodeObserver(compiler::NodeObserver *observer)
OptimizedCompilationInfo(const OptimizedCompilationInfo &)=delete
IndirectHandle< BytecodeArray > bytecode_array() const
IndirectHandle< T > CanonicalHandle(Tagged< T > object, Isolate *isolate)
std::unique_ptr< CanonicalHandlesMap > DetachCanonicalHandles()
compiler::NodeObserver * node_observer() const
Zone * zone_
JSRegExp::Flags flags_
ZoneList< RegExpInstruction > code_
std::string filename
TNode< Context > context
Builtin builtin
LiftoffBailoutReason bailout_reason_
int position
Definition liveedit.cc:290
constexpr bool CodeKindIsOptimizedJSFunction(CodeKind kind)
Definition code-kind.h:66
!IsContextMap !IsContextMap native_context
Definition map-inl.h:877
Definition c-api.cc:87
#define FLAGS(V)
#define DEF_GETTER(Camel, Lower, Bit)
#define DEF_SETTER(Camel, Lower, Bit)
#define DCHECK_NULL(val)
Definition logging.h:491
#define DCHECK_NOT_NULL(val)
Definition logging.h:492
#define DCHECK(condition)
Definition logging.h:482
#define V8_EXPORT_PRIVATE
Definition macros.h:460