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
21namespace v8 {
22namespace internal {
23
24OptimizedCompilationInfo::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
55OptimizedCompilationInfo::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
66void 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
106OptimizedCompilationInfo::~OptimizedCompilationInfo() {
107  if (disable_future_optimization() && has_shared_info()) {
108    shared_info()->DisableOptimization(bailout_reason());
109  }
110}
111
112void 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
125void 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
133void OptimizedCompilationInfo::RetryOptimization(BailoutReason reason) {
134  DCHECK_NE(reason, BailoutReason::kNoReason);
135  if (disable_future_optimization()) return;
136  bailout_reason_ = reason;
137}
138
139std::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
151StackFrame::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
174void OptimizedCompilationInfo::SetCode(Handle<Code> code) {
175  DCHECK_EQ(code->kind(), code_kind());
176  code_ = code;
177}
178
179#if V8_ENABLE_WEBASSEMBLY
180void OptimizedCompilationInfo::SetWasmCompilationResult(
181    std::unique_ptr<wasm::WasmCompilationResult> wasm_compilation_result) {
182  wasm_compilation_result_ = std::move(wasm_compilation_result);
183}
184
185std::unique_ptr<wasm::WasmCompilationResult>
186OptimizedCompilationInfo::ReleaseWasmCompilationResult() {
187  return std::move(wasm_compilation_result_);
188}
189#endif  // V8_ENABLE_WEBASSEMBLY
190
191bool OptimizedCompilationInfo::has_context() const {
192  return !closure().is_null();
193}
194
195Context OptimizedCompilationInfo::context() const {
196  DCHECK(has_context());
197  return closure()->context();
198}
199
200bool OptimizedCompilationInfo::has_native_context() const {
201  return !closure().is_null() && !closure()->native_context().is_null();
202}
203
204NativeContext OptimizedCompilationInfo::native_context() const {
205  DCHECK(has_native_context());
206  return closure()->native_context();
207}
208
209bool OptimizedCompilationInfo::has_global_object() const {
210  return has_native_context();
211}
212
213JSGlobalObject OptimizedCompilationInfo::global_object() const {
214  DCHECK(has_global_object());
215  return native_context().global_object();
216}
217
218int 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
227void 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
236OptimizedCompilationInfo::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