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