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