• 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 #include "src/codegen/optimized-compilation-info.h"
6 
7 #include "src/api/api.h"
8 #include "src/codegen/source-position.h"
9 #include "src/debug/debug.h"
10 #include "src/execution/isolate.h"
11 #include "src/objects/objects-inl.h"
12 #include "src/objects/shared-function-info.h"
13 #include "src/tracing/trace-event.h"
14 #include "src/tracing/traced-value.h"
15 #include "src/wasm/function-compiler.h"
16 
17 namespace v8 {
18 namespace internal {
19 
OptimizedCompilationInfo(Zone * zone,Isolate * isolate,Handle<SharedFunctionInfo> shared,Handle<JSFunction> closure,CodeKind code_kind)20 OptimizedCompilationInfo::OptimizedCompilationInfo(
21     Zone* zone, Isolate* isolate, Handle<SharedFunctionInfo> shared,
22     Handle<JSFunction> closure, CodeKind code_kind)
23     : code_kind_(code_kind),
24       zone_(zone),
25       optimization_id_(isolate->NextOptimizationId()) {
26   DCHECK_EQ(*shared, closure->shared());
27   DCHECK(shared->is_compiled());
28   bytecode_array_ = handle(shared->GetBytecodeArray(), isolate);
29   shared_info_ = shared;
30   closure_ = closure;
31 
32   // Collect source positions for optimized code when profiling or if debugger
33   // is active, to be able to get more precise source positions at the price of
34   // more memory consumption.
35   if (isolate->NeedsDetailedOptimizedCodeLineInfo()) {
36     set_source_positions();
37   }
38 
39   SetTracingFlags(shared->PassesFilter(FLAG_trace_turbo_filter));
40   ConfigureFlags();
41 }
42 
OptimizedCompilationInfo(Vector<const char> debug_name,Zone * zone,CodeKind code_kind)43 OptimizedCompilationInfo::OptimizedCompilationInfo(
44     Vector<const char> debug_name, Zone* zone, CodeKind code_kind)
45     : code_kind_(code_kind),
46       zone_(zone),
47       optimization_id_(kNoOptimizationId),
48       debug_name_(debug_name) {
49   SetTracingFlags(
50       PassesFilter(debug_name, CStrVector(FLAG_trace_turbo_filter)));
51   ConfigureFlags();
52 }
53 
54 #ifdef DEBUG
FlagSetIsValid(Flag flag) const55 bool OptimizedCompilationInfo::FlagSetIsValid(Flag flag) const {
56   switch (flag) {
57     case kPoisonRegisterArguments:
58       return untrusted_code_mitigations();
59     case kFunctionContextSpecializing:
60       return !IsNativeContextIndependent();
61     default:
62       return true;
63   }
64   UNREACHABLE();
65 }
66 
FlagGetIsValid(Flag flag) const67 bool OptimizedCompilationInfo::FlagGetIsValid(Flag flag) const {
68   switch (flag) {
69     case kPoisonRegisterArguments:
70       if (!GetFlag(kPoisonRegisterArguments)) return true;
71       return untrusted_code_mitigations() && called_with_code_start_register();
72     default:
73       return true;
74   }
75   UNREACHABLE();
76 }
77 #endif  // DEBUG
78 
ConfigureFlags()79 void OptimizedCompilationInfo::ConfigureFlags() {
80   if (FLAG_untrusted_code_mitigations) set_untrusted_code_mitigations();
81 
82   switch (code_kind_) {
83     case CodeKind::TURBOFAN:
84       if (FLAG_function_context_specialization) {
85         set_function_context_specializing();
86       }
87       V8_FALLTHROUGH;
88     case CodeKind::TURBOPROP:
89     case CodeKind::NATIVE_CONTEXT_INDEPENDENT:
90       set_called_with_code_start_register();
91       set_switch_jump_table();
92       if (FLAG_turbo_splitting) set_splitting();
93       if (FLAG_untrusted_code_mitigations) set_poison_register_arguments();
94       // TODO(yangguo): Disable this in case of debugging for crbug.com/826613
95       if (FLAG_analyze_environment_liveness) set_analyze_environment_liveness();
96       break;
97     case CodeKind::BYTECODE_HANDLER:
98       set_called_with_code_start_register();
99       if (FLAG_turbo_splitting) set_splitting();
100       break;
101     case CodeKind::BUILTIN:
102     case CodeKind::FOR_TESTING:
103       if (FLAG_turbo_splitting) set_splitting();
104 #if ENABLE_GDB_JIT_INTERFACE && DEBUG
105       set_source_positions();
106 #endif  // ENABLE_GDB_JIT_INTERFACE && DEBUG
107       break;
108     case CodeKind::WASM_FUNCTION:
109     case CodeKind::WASM_TO_CAPI_FUNCTION:
110       set_switch_jump_table();
111       break;
112     default:
113       break;
114   }
115 }
116 
~OptimizedCompilationInfo()117 OptimizedCompilationInfo::~OptimizedCompilationInfo() {
118   if (disable_future_optimization() && has_shared_info()) {
119     shared_info()->DisableOptimization(bailout_reason());
120   }
121 }
122 
ReopenHandlesInNewHandleScope(Isolate * isolate)123 void OptimizedCompilationInfo::ReopenHandlesInNewHandleScope(Isolate* isolate) {
124   if (!shared_info_.is_null()) {
125     shared_info_ = Handle<SharedFunctionInfo>(*shared_info_, isolate);
126   }
127   if (!bytecode_array_.is_null()) {
128     bytecode_array_ = Handle<BytecodeArray>(*bytecode_array_, isolate);
129   }
130   if (!closure_.is_null()) {
131     closure_ = Handle<JSFunction>(*closure_, isolate);
132   }
133   DCHECK(code_.is_null());
134 }
135 
AbortOptimization(BailoutReason reason)136 void OptimizedCompilationInfo::AbortOptimization(BailoutReason reason) {
137   DCHECK_NE(reason, BailoutReason::kNoReason);
138   if (bailout_reason_ == BailoutReason::kNoReason) {
139     bailout_reason_ = reason;
140   }
141   set_disable_future_optimization();
142 }
143 
RetryOptimization(BailoutReason reason)144 void OptimizedCompilationInfo::RetryOptimization(BailoutReason reason) {
145   DCHECK_NE(reason, BailoutReason::kNoReason);
146   if (disable_future_optimization()) return;
147   bailout_reason_ = reason;
148 }
149 
GetDebugName() const150 std::unique_ptr<char[]> OptimizedCompilationInfo::GetDebugName() const {
151   if (!shared_info().is_null()) {
152     return shared_info()->DebugName().ToCString();
153   }
154   Vector<const char> name_vec = debug_name_;
155   if (name_vec.empty()) name_vec = ArrayVector("unknown");
156   std::unique_ptr<char[]> name(new char[name_vec.length() + 1]);
157   memcpy(name.get(), name_vec.begin(), name_vec.length());
158   name[name_vec.length()] = '\0';
159   return name;
160 }
161 
GetOutputStackFrameType() const162 StackFrame::Type OptimizedCompilationInfo::GetOutputStackFrameType() const {
163   switch (code_kind()) {
164     case CodeKind::FOR_TESTING:
165     case CodeKind::BYTECODE_HANDLER:
166     case CodeKind::BUILTIN:
167       return StackFrame::STUB;
168     case CodeKind::WASM_FUNCTION:
169       return StackFrame::WASM;
170     case CodeKind::WASM_TO_CAPI_FUNCTION:
171       return StackFrame::WASM_EXIT;
172     case CodeKind::JS_TO_WASM_FUNCTION:
173       return StackFrame::JS_TO_WASM;
174     case CodeKind::WASM_TO_JS_FUNCTION:
175       return StackFrame::WASM_TO_JS;
176     case CodeKind::C_WASM_ENTRY:
177       return StackFrame::C_WASM_ENTRY;
178     default:
179       UNIMPLEMENTED();
180       return StackFrame::NONE;
181   }
182 }
183 
SetCode(Handle<Code> code)184 void OptimizedCompilationInfo::SetCode(Handle<Code> code) {
185   DCHECK_EQ(code->kind(), code_kind());
186   code_ = code;
187 }
188 
SetWasmCompilationResult(std::unique_ptr<wasm::WasmCompilationResult> wasm_compilation_result)189 void OptimizedCompilationInfo::SetWasmCompilationResult(
190     std::unique_ptr<wasm::WasmCompilationResult> wasm_compilation_result) {
191   wasm_compilation_result_ = std::move(wasm_compilation_result);
192 }
193 
194 std::unique_ptr<wasm::WasmCompilationResult>
ReleaseWasmCompilationResult()195 OptimizedCompilationInfo::ReleaseWasmCompilationResult() {
196   return std::move(wasm_compilation_result_);
197 }
198 
has_context() const199 bool OptimizedCompilationInfo::has_context() const {
200   return !closure().is_null();
201 }
202 
context() const203 Context OptimizedCompilationInfo::context() const {
204   DCHECK(has_context());
205   return closure()->context();
206 }
207 
has_native_context() const208 bool OptimizedCompilationInfo::has_native_context() const {
209   return !closure().is_null() && !closure()->native_context().is_null();
210 }
211 
native_context() const212 NativeContext OptimizedCompilationInfo::native_context() const {
213   DCHECK(has_native_context());
214   return closure()->native_context();
215 }
216 
has_global_object() const217 bool OptimizedCompilationInfo::has_global_object() const {
218   return has_native_context();
219 }
220 
global_object() const221 JSGlobalObject OptimizedCompilationInfo::global_object() const {
222   DCHECK(has_global_object());
223   return native_context().global_object();
224 }
225 
AddInlinedFunction(Handle<SharedFunctionInfo> inlined_function,Handle<BytecodeArray> inlined_bytecode,SourcePosition pos)226 int OptimizedCompilationInfo::AddInlinedFunction(
227     Handle<SharedFunctionInfo> inlined_function,
228     Handle<BytecodeArray> inlined_bytecode, SourcePosition pos) {
229   int id = static_cast<int>(inlined_functions_.size());
230   inlined_functions_.push_back(
231       InlinedFunctionHolder(inlined_function, inlined_bytecode, pos));
232   return id;
233 }
234 
SetTracingFlags(bool passes_filter)235 void OptimizedCompilationInfo::SetTracingFlags(bool passes_filter) {
236   if (!passes_filter) return;
237   if (FLAG_trace_turbo) set_trace_turbo_json();
238   if (FLAG_trace_turbo_graph) set_trace_turbo_graph();
239   if (FLAG_trace_turbo_scheduled) set_trace_turbo_scheduled();
240   if (FLAG_trace_turbo_alloc) set_trace_turbo_allocation();
241   if (FLAG_trace_heap_broker) set_trace_heap_broker();
242 }
243 
InlinedFunctionHolder(Handle<SharedFunctionInfo> inlined_shared_info,Handle<BytecodeArray> inlined_bytecode,SourcePosition pos)244 OptimizedCompilationInfo::InlinedFunctionHolder::InlinedFunctionHolder(
245     Handle<SharedFunctionInfo> inlined_shared_info,
246     Handle<BytecodeArray> inlined_bytecode, SourcePosition pos)
247     : shared_info(inlined_shared_info), bytecode_array(inlined_bytecode) {
248   position.position = pos;
249   // initialized when generating the deoptimization literals
250   position.inlined_function_id = DeoptimizationData::kNotInlinedIndex;
251 }
252 
253 }  // namespace internal
254 }  // namespace v8
255