Line data Source code
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_OPTIMIZED_COMPILATION_INFO_H_
6 : #define V8_OPTIMIZED_COMPILATION_INFO_H_
7 :
8 : #include <memory>
9 :
10 : #include "src/bailout-reason.h"
11 : #include "src/frames.h"
12 : #include "src/globals.h"
13 : #include "src/handles.h"
14 : #include "src/objects.h"
15 : #include "src/source-position-table.h"
16 : #include "src/utils.h"
17 : #include "src/vector.h"
18 :
19 : namespace v8 {
20 :
21 : namespace tracing {
22 : class TracedValue;
23 : }
24 :
25 : namespace internal {
26 :
27 : class DeferredHandles;
28 : class FunctionLiteral;
29 : class Isolate;
30 : class JavaScriptFrame;
31 : class JSGlobalObject;
32 : class Zone;
33 :
34 : namespace wasm {
35 : struct WasmCompilationResult;
36 : }
37 :
38 : // OptimizedCompilationInfo encapsulates the information needed to compile
39 : // optimized code for a given function, and the results of the optimized
40 : // compilation.
41 : class V8_EXPORT_PRIVATE OptimizedCompilationInfo final {
42 : public:
43 : // Various configuration flags for a compilation, as well as some properties
44 : // of the compiled code produced by a compilation.
45 : enum Flag {
46 : kAccessorInliningEnabled = 1 << 0,
47 : kFunctionContextSpecializing = 1 << 1,
48 : kInliningEnabled = 1 << 2,
49 : kDisableFutureOptimization = 1 << 3,
50 : kSplittingEnabled = 1 << 4,
51 : kSourcePositionsEnabled = 1 << 5,
52 : kBailoutOnUninitialized = 1 << 6,
53 : kLoopPeelingEnabled = 1 << 7,
54 : kUntrustedCodeMitigations = 1 << 8,
55 : kSwitchJumpTableEnabled = 1 << 9,
56 : kCalledWithCodeStartRegister = 1 << 10,
57 : kPoisonRegisterArguments = 1 << 11,
58 : kAllocationFoldingEnabled = 1 << 12,
59 : kAnalyzeEnvironmentLiveness = 1 << 13,
60 : kTraceTurboJson = 1 << 14,
61 : kTraceTurboGraph = 1 << 15,
62 : kTraceTurboScheduled = 1 << 16,
63 : kWasmRuntimeExceptionSupport = 1 << 17,
64 : kTurboControlFlowAwareAllocation = 1 << 18,
65 : kTurboPreprocessRanges = 1 << 19
66 : };
67 :
68 : // Construct a compilation info for optimized compilation.
69 : OptimizedCompilationInfo(Zone* zone, Isolate* isolate,
70 : Handle<SharedFunctionInfo> shared,
71 : Handle<JSFunction> closure);
72 : // Construct a compilation info for stub compilation, Wasm, and testing.
73 : OptimizedCompilationInfo(Vector<const char> debug_name, Zone* zone,
74 : Code::Kind code_kind);
75 :
76 : ~OptimizedCompilationInfo();
77 :
78 : Zone* zone() { return zone_; }
79 3104393 : bool is_osr() const { return !osr_offset_.IsNone(); }
80 : Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
81 : bool has_shared_info() const { return !shared_info().is_null(); }
82 : Handle<BytecodeArray> bytecode_array() const { return bytecode_array_; }
83 : bool has_bytecode_array() const { return !bytecode_array_.is_null(); }
84 : Handle<JSFunction> closure() const { return closure_; }
85 : Handle<Code> code() const { return code_; }
86 : Code::Kind code_kind() const { return code_kind_; }
87 : int32_t builtin_index() const { return builtin_index_; }
88 67268 : void set_builtin_index(int32_t index) { builtin_index_ = index; }
89 : BailoutId osr_offset() const { return osr_offset_; }
90 : JavaScriptFrame* osr_frame() const { return osr_frame_; }
91 :
92 : // Flags used by optimized compilation.
93 :
94 : void MarkAsTurboControlFlowAwareAllocation() {
95 : SetFlag(kTurboControlFlowAwareAllocation);
96 : }
97 : bool is_turbo_control_flow_aware_allocation() const {
98 : return GetFlag(kTurboControlFlowAwareAllocation);
99 : }
100 :
101 : void MarkAsTurboPreprocessRanges() { SetFlag(kTurboPreprocessRanges); }
102 : bool is_turbo_preprocess_ranges() const {
103 : return GetFlag(kTurboPreprocessRanges);
104 : }
105 :
106 : void MarkAsFunctionContextSpecializing() {
107 : SetFlag(kFunctionContextSpecializing);
108 : }
109 : bool is_function_context_specializing() const {
110 : return GetFlag(kFunctionContextSpecializing);
111 : }
112 :
113 : void MarkAsAccessorInliningEnabled() { SetFlag(kAccessorInliningEnabled); }
114 : bool is_accessor_inlining_enabled() const {
115 : return GetFlag(kAccessorInliningEnabled);
116 : }
117 :
118 : void MarkAsSourcePositionsEnabled() { SetFlag(kSourcePositionsEnabled); }
119 : bool is_source_positions_enabled() const {
120 : return GetFlag(kSourcePositionsEnabled);
121 : }
122 :
123 : void MarkAsInliningEnabled() { SetFlag(kInliningEnabled); }
124 : bool is_inlining_enabled() const { return GetFlag(kInliningEnabled); }
125 :
126 : void SetPoisoningMitigationLevel(PoisoningMitigationLevel poisoning_level) {
127 460732 : poisoning_level_ = poisoning_level;
128 : }
129 : PoisoningMitigationLevel GetPoisoningMitigationLevel() const {
130 : return poisoning_level_;
131 : }
132 :
133 : void MarkAsSplittingEnabled() { SetFlag(kSplittingEnabled); }
134 : bool is_splitting_enabled() const { return GetFlag(kSplittingEnabled); }
135 :
136 : void MarkAsBailoutOnUninitialized() { SetFlag(kBailoutOnUninitialized); }
137 : bool is_bailout_on_uninitialized() const {
138 : return GetFlag(kBailoutOnUninitialized);
139 : }
140 :
141 : void MarkAsLoopPeelingEnabled() { SetFlag(kLoopPeelingEnabled); }
142 : bool is_loop_peeling_enabled() const { return GetFlag(kLoopPeelingEnabled); }
143 :
144 : bool has_untrusted_code_mitigations() const {
145 : return GetFlag(kUntrustedCodeMitigations);
146 : }
147 :
148 : bool switch_jump_table_enabled() const {
149 : return GetFlag(kSwitchJumpTableEnabled);
150 : }
151 :
152 : bool called_with_code_start_register() const {
153 : bool enabled = GetFlag(kCalledWithCodeStartRegister);
154 : return enabled;
155 : }
156 :
157 : void MarkAsPoisoningRegisterArguments() {
158 : DCHECK(has_untrusted_code_mitigations());
159 : SetFlag(kPoisonRegisterArguments);
160 : }
161 : bool is_poisoning_register_arguments() const {
162 : bool enabled = GetFlag(kPoisonRegisterArguments);
163 : DCHECK_IMPLIES(enabled, has_untrusted_code_mitigations());
164 : DCHECK_IMPLIES(enabled, called_with_code_start_register());
165 : return enabled;
166 : }
167 :
168 : void MarkAsAllocationFoldingEnabled() { SetFlag(kAllocationFoldingEnabled); }
169 : bool is_allocation_folding_enabled() const {
170 : return GetFlag(kAllocationFoldingEnabled);
171 : }
172 :
173 : void MarkAsAnalyzeEnvironmentLiveness() {
174 : SetFlag(kAnalyzeEnvironmentLiveness);
175 : }
176 : bool is_analyze_environment_liveness() const {
177 : return GetFlag(kAnalyzeEnvironmentLiveness);
178 : }
179 :
180 : void SetWasmRuntimeExceptionSupport() {
181 : SetFlag(kWasmRuntimeExceptionSupport);
182 : }
183 :
184 : bool wasm_runtime_exception_support() {
185 : return GetFlag(kWasmRuntimeExceptionSupport);
186 : }
187 :
188 : bool trace_turbo_json_enabled() const { return GetFlag(kTraceTurboJson); }
189 :
190 : bool trace_turbo_graph_enabled() const { return GetFlag(kTraceTurboGraph); }
191 :
192 : bool trace_turbo_scheduled_enabled() const {
193 : return GetFlag(kTraceTurboScheduled);
194 : }
195 :
196 : // Code getters and setters.
197 :
198 2049596 : void SetCode(Handle<Code> code) { code_ = code; }
199 :
200 : void SetWasmCompilationResult(std::unique_ptr<wasm::WasmCompilationResult>);
201 : std::unique_ptr<wasm::WasmCompilationResult> ReleaseWasmCompilationResult();
202 :
203 : bool has_context() const;
204 : Context context() const;
205 :
206 : bool has_native_context() const;
207 : Context native_context() const;
208 :
209 : bool has_global_object() const;
210 : JSGlobalObject global_object() const;
211 :
212 : // Accessors for the different compilation modes.
213 : bool IsOptimizing() const { return code_kind() == Code::OPTIMIZED_FUNCTION; }
214 : bool IsWasm() const { return code_kind() == Code::WASM_FUNCTION; }
215 : bool IsNotOptimizedFunctionOrWasmFunction() const {
216 1163 : return code_kind() != Code::OPTIMIZED_FUNCTION &&
217 : code_kind() != Code::WASM_FUNCTION;
218 : }
219 : void SetOptimizingForOsr(BailoutId osr_offset, JavaScriptFrame* osr_frame) {
220 : DCHECK(IsOptimizing());
221 479822 : osr_offset_ = osr_offset;
222 479822 : osr_frame_ = osr_frame;
223 : }
224 :
225 : void set_deferred_handles(std::shared_ptr<DeferredHandles> deferred_handles);
226 : void set_deferred_handles(DeferredHandles* deferred_handles);
227 : std::shared_ptr<DeferredHandles> deferred_handles() {
228 : return deferred_handles_;
229 : }
230 :
231 : void ReopenHandlesInNewHandleScope(Isolate* isolate);
232 :
233 : void AbortOptimization(BailoutReason reason);
234 :
235 : void RetryOptimization(BailoutReason reason);
236 :
237 : BailoutReason bailout_reason() const { return bailout_reason_; }
238 :
239 : bool is_disable_future_optimization() const {
240 : return GetFlag(kDisableFutureOptimization);
241 : }
242 :
243 : int optimization_id() const {
244 : DCHECK(IsOptimizing());
245 : return optimization_id_;
246 : }
247 :
248 : struct InlinedFunctionHolder {
249 : Handle<SharedFunctionInfo> shared_info;
250 : Handle<BytecodeArray> bytecode_array; // Explicit to prevent flushing.
251 : InliningPosition position;
252 :
253 : InlinedFunctionHolder(Handle<SharedFunctionInfo> inlined_shared_info,
254 : Handle<BytecodeArray> inlined_bytecode,
255 : SourcePosition pos);
256 :
257 : void RegisterInlinedFunctionId(size_t inlined_function_id) {
258 65483 : position.inlined_function_id = static_cast<int>(inlined_function_id);
259 : }
260 : };
261 :
262 : typedef std::vector<InlinedFunctionHolder> InlinedFunctionList;
263 : InlinedFunctionList& inlined_functions() { return inlined_functions_; }
264 :
265 : // Returns the inlining id for source position tracking.
266 : int AddInlinedFunction(Handle<SharedFunctionInfo> inlined_function,
267 : Handle<BytecodeArray> inlined_bytecode,
268 : SourcePosition pos);
269 :
270 : std::unique_ptr<char[]> GetDebugName() const;
271 :
272 : StackFrame::Type GetOutputStackFrameType() const;
273 :
274 : const char* trace_turbo_filename() const {
275 : return trace_turbo_filename_.get();
276 : }
277 :
278 : void set_trace_turbo_filename(std::unique_ptr<char[]> filename) {
279 : trace_turbo_filename_ = std::move(filename);
280 : }
281 :
282 : std::unique_ptr<v8::tracing::TracedValue> ToTracedValue();
283 :
284 : private:
285 : OptimizedCompilationInfo(Code::Kind code_kind, Zone* zone);
286 : void ConfigureFlags();
287 :
288 7348979 : void SetFlag(Flag flag) { flags_ |= flag; }
289 249530342 : bool GetFlag(Flag flag) const { return (flags_ & flag) != 0; }
290 :
291 : void SetTracingFlags(bool passes_filter);
292 :
293 : // Compilation flags.
294 : unsigned flags_ = 0;
295 : PoisoningMitigationLevel poisoning_level_ =
296 : PoisoningMitigationLevel::kDontPoison;
297 :
298 : Code::Kind code_kind_;
299 : int32_t builtin_index_ = -1;
300 :
301 : // We retain a reference the bytecode array specifically to ensure it doesn't
302 : // get flushed while we are optimizing the code.
303 : Handle<BytecodeArray> bytecode_array_;
304 :
305 : Handle<SharedFunctionInfo> shared_info_;
306 :
307 : Handle<JSFunction> closure_;
308 :
309 : // The compiled code.
310 : Handle<Code> code_;
311 :
312 : // The WebAssembly compilation result, not published in the NativeModule yet.
313 : std::unique_ptr<wasm::WasmCompilationResult> wasm_compilation_result_;
314 :
315 : // Entry point when compiling for OSR, {BailoutId::None} otherwise.
316 : BailoutId osr_offset_ = BailoutId::None();
317 :
318 : // The zone from which the compilation pipeline working on this
319 : // OptimizedCompilationInfo allocates.
320 : Zone* zone_;
321 :
322 : std::shared_ptr<DeferredHandles> deferred_handles_;
323 :
324 : BailoutReason bailout_reason_ = BailoutReason::kNoReason;
325 :
326 : InlinedFunctionList inlined_functions_;
327 :
328 : int optimization_id_ = -1;
329 :
330 : // The current OSR frame for specialization or {nullptr}.
331 : JavaScriptFrame* osr_frame_ = nullptr;
332 :
333 : Vector<const char> debug_name_;
334 : std::unique_ptr<char[]> trace_turbo_filename_;
335 :
336 : DISALLOW_COPY_AND_ASSIGN(OptimizedCompilationInfo);
337 : };
338 :
339 : } // namespace internal
340 : } // namespace v8
341 :
342 : #endif // V8_OPTIMIZED_COMPILATION_INFO_H_
|