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