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