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