optimized-compilation-info.h 11.4 KB
Newer Older
1 2 3 4
// Copyright 2016 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

5 6
#ifndef V8_CODEGEN_OPTIMIZED_COMPILATION_INFO_H_
#define V8_CODEGEN_OPTIMIZED_COMPILATION_INFO_H_
7 8 9

#include <memory>

10 11
#include "src/codegen/bailout-reason.h"
#include "src/codegen/source-position-table.h"
12
#include "src/codegen/tick-counter.h"
13
#include "src/common/globals.h"
14
#include "src/diagnostics/basic-block-profiler.h"
15
#include "src/execution/frames.h"
16
#include "src/handles/handles.h"
17
#include "src/handles/persistent-handles.h"
18
#include "src/objects/objects.h"
19
#include "src/utils/identity-map.h"
20 21
#include "src/utils/utils.h"
#include "src/utils/vector.h"
22 23

namespace v8 {
24 25 26

namespace tracing {
class TracedValue;
27
}  // namespace tracing
28

29 30 31 32
namespace internal {

class FunctionLiteral;
class Isolate;
33
class JavaScriptFrame;
34
class JSGlobalObject;
35 36
class Zone;

37 38
namespace wasm {
struct WasmCompilationResult;
39
}  // namespace wasm
40

41 42 43 44
// OptimizedCompilationInfo encapsulates the information needed to compile
// optimized code for a given function, and the results of the optimized
// compilation.
class V8_EXPORT_PRIVATE OptimizedCompilationInfo final {
45 46 47
 public:
  // Various configuration flags for a compilation, as well as some properties
  // of the compiled code produced by a compilation.
48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70

#define FLAGS(V)                                                              \
  V(FunctionContextSpecializing, function_context_specializing, 0)            \
  V(Inlining, inlining, 1)                                                    \
  V(DisableFutureOptimization, disable_future_optimization, 2)                \
  V(Splitting, splitting, 3)                                                  \
  V(SourcePositions, source_positions, 4)                                     \
  V(BailoutOnUninitialized, bailout_on_uninitialized, 5)                      \
  V(LoopPeeling, loop_peeling, 6)                                             \
  V(UntrustedCodeMitigations, untrusted_code_mitigations, 7)                  \
  V(SwitchJumpTable, switch_jump_table, 8)                                    \
  V(CalledWithCodeStartRegister, called_with_code_start_register, 9)          \
  V(PoisonRegisterArguments, poison_register_arguments, 10)                   \
  V(AllocationFolding, allocation_folding, 11)                                \
  V(AnalyzeEnvironmentLiveness, analyze_environment_liveness, 12)             \
  V(TraceTurboJson, trace_turbo_json, 13)                                     \
  V(TraceTurboGraph, trace_turbo_graph, 14)                                   \
  V(TraceTurboScheduled, trace_turbo_scheduled, 15)                           \
  V(TraceTurboAllocation, trace_turbo_allocation, 16)                         \
  V(TraceHeapBroker, trace_heap_broker, 17)                                   \
  V(WasmRuntimeExceptionSupport, wasm_runtime_exception_support, 18)          \
  V(TurboControlFlowAwareAllocation, turbo_control_flow_aware_allocation, 19) \
  V(TurboPreprocessRanges, turbo_preprocess_ranges, 20)                       \
71
  V(ConcurrentInlining, concurrent_inlining, 21)
72

73
  enum Flag {
74 75 76
#define DEF_ENUM(Camel, Lower, Bit) k##Camel = 1 << Bit,
    FLAGS(DEF_ENUM)
#undef DEF_ENUM
77 78
  };

79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99
#define DEF_GETTER(Camel, Lower, Bit) \
  bool Lower() const {                \
    DCHECK(FlagGetIsValid(k##Camel)); \
    return GetFlag(k##Camel);         \
  }
  FLAGS(DEF_GETTER)
#undef DEF_GETTER

#define DEF_SETTER(Camel, Lower, Bit) \
  void set_##Lower() {                \
    DCHECK(FlagSetIsValid(k##Camel)); \
    SetFlag(k##Camel);                \
  }
  FLAGS(DEF_SETTER)
#undef DEF_SETTER

#ifdef DEBUG
  bool FlagGetIsValid(Flag flag) const;
  bool FlagSetIsValid(Flag flag) const;
#endif  // DEBUG

100
  // Construct a compilation info for optimized compilation.
101 102
  OptimizedCompilationInfo(Zone* zone, Isolate* isolate,
                           Handle<SharedFunctionInfo> shared,
103
                           Handle<JSFunction> closure, CodeKind code_kind);
104
  // Construct a compilation info for stub compilation, Wasm, and testing.
105
  OptimizedCompilationInfo(Vector<const char> debug_name, Zone* zone,
106
                           CodeKind code_kind);
107

108
  ~OptimizedCompilationInfo();
109 110

  Zone* zone() { return zone_; }
111
  bool is_osr() const { return !osr_offset_.IsNone(); }
112 113
  Handle<SharedFunctionInfo> shared_info() const { return shared_info_; }
  bool has_shared_info() const { return !shared_info().is_null(); }
114 115
  Handle<BytecodeArray> bytecode_array() const { return bytecode_array_; }
  bool has_bytecode_array() const { return !bytecode_array_.is_null(); }
116
  Handle<JSFunction> closure() const { return closure_; }
117
  Handle<Code> code() const { return code_; }
118
  CodeKind code_kind() const { return code_kind_; }
119 120
  int32_t builtin_index() const { return builtin_index_; }
  void set_builtin_index(int32_t index) { builtin_index_ = index; }
121
  BailoutId osr_offset() const { return osr_offset_; }
122
  JavaScriptFrame* osr_frame() const { return osr_frame_; }
123

124 125 126 127 128 129
  void SetPoisoningMitigationLevel(PoisoningMitigationLevel poisoning_level) {
    poisoning_level_ = poisoning_level;
  }
  PoisoningMitigationLevel GetPoisoningMitigationLevel() const {
    return poisoning_level_;
  }
130

131
  // Code getters and setters.
132

133
  void SetCode(Handle<Code> code);
134

135 136 137
  void SetWasmCompilationResult(std::unique_ptr<wasm::WasmCompilationResult>);
  std::unique_ptr<wasm::WasmCompilationResult> ReleaseWasmCompilationResult();

138
  bool has_context() const;
139
  Context context() const;
140

141
  bool has_native_context() const;
142
  NativeContext native_context() const;
143 144

  bool has_global_object() const;
145
  JSGlobalObject global_object() const;
146 147

  // Accessors for the different compilation modes.
148 149
  bool IsOptimizing() const {
    return CodeKindIsOptimizedJSFunction(code_kind());
150
  }
151 152 153 154 155 156
  bool IsNativeContextIndependent() const {
    return code_kind() == CodeKind::NATIVE_CONTEXT_INDEPENDENT;
  }
  bool IsStub() const { return code_kind() == CodeKind::STUB; }
  bool IsWasm() const { return code_kind() == CodeKind::WASM_FUNCTION; }

157
  void SetOptimizingForOsr(BailoutId osr_offset, JavaScriptFrame* osr_frame) {
158
    DCHECK(IsOptimizing());
159
    osr_offset_ = osr_offset;
160 161 162
    osr_frame_ = osr_frame;
  }

163
  void set_persistent_handles(
164 165 166 167 168 169 170 171 172 173 174 175
      std::unique_ptr<PersistentHandles> persistent_handles) {
    DCHECK_NULL(ph_);
    ph_ = std::move(persistent_handles);
    DCHECK_NOT_NULL(ph_);
  }

  void set_canonical_handles(
      std::unique_ptr<CanonicalHandlesMap> canonical_handles) {
    DCHECK_NULL(canonical_handles_);
    canonical_handles_ = std::move(canonical_handles);
    DCHECK_NOT_NULL(canonical_handles_);
  }
176

177
  void ReopenHandlesInNewHandleScope(Isolate* isolate);
178

179
  void AbortOptimization(BailoutReason reason);
180

181
  void RetryOptimization(BailoutReason reason);
182 183 184

  BailoutReason bailout_reason() const { return bailout_reason_; }

185 186 187 188
  int optimization_id() const {
    DCHECK(IsOptimizing());
    return optimization_id_;
  }
189

190 191 192 193 194 195
  unsigned inlined_bytecode_size() const { return inlined_bytecode_size_; }

  void set_inlined_bytecode_size(unsigned size) {
    inlined_bytecode_size_ = size;
  }

196 197
  struct InlinedFunctionHolder {
    Handle<SharedFunctionInfo> shared_info;
198
    Handle<BytecodeArray> bytecode_array;  // Explicit to prevent flushing.
199 200
    InliningPosition position;

201
    InlinedFunctionHolder(Handle<SharedFunctionInfo> inlined_shared_info,
202
                          Handle<BytecodeArray> inlined_bytecode,
203
                          SourcePosition pos);
204 205 206 207

    void RegisterInlinedFunctionId(size_t inlined_function_id) {
      position.inlined_function_id = static_cast<int>(inlined_function_id);
    }
208 209
  };

210
  using InlinedFunctionList = std::vector<InlinedFunctionHolder>;
211
  InlinedFunctionList& inlined_functions() { return inlined_functions_; }
212

213 214
  // Returns the inlining id for source position tracking.
  int AddInlinedFunction(Handle<SharedFunctionInfo> inlined_function,
215
                         Handle<BytecodeArray> inlined_bytecode,
216
                         SourcePosition pos);
217 218 219 220 221

  std::unique_ptr<char[]> GetDebugName() const;

  StackFrame::Type GetOutputStackFrameType() const;

222 223 224 225 226 227 228 229
  const char* trace_turbo_filename() const {
    return trace_turbo_filename_.get();
  }

  void set_trace_turbo_filename(std::unique_ptr<char[]> filename) {
    trace_turbo_filename_ = std::move(filename);
  }

230 231
  TickCounter& tick_counter() { return tick_counter_; }

232 233 234 235 236
  BasicBlockProfilerData* profiler_data() const { return profiler_data_; }
  void set_profiler_data(BasicBlockProfilerData* profiler_data) {
    profiler_data_ = profiler_data;
  }

237
  std::unique_ptr<PersistentHandles> DetachPersistentHandles() {
238
    DCHECK_NOT_NULL(ph_);
239 240 241
    return std::move(ph_);
  }

242 243 244 245 246
  std::unique_ptr<CanonicalHandlesMap> DetachCanonicalHandles() {
    DCHECK_NOT_NULL(canonical_handles_);
    return std::move(canonical_handles_);
  }

247
 private:
248
  void ConfigureFlags();
249 250 251 252

  void SetFlag(Flag flag) { flags_ |= flag; }
  bool GetFlag(Flag flag) const { return (flags_ & flag) != 0; }

253 254
  void SetTracingFlags(bool passes_filter);

255
  // Compilation flags.
256
  unsigned flags_ = 0;
257 258
  PoisoningMitigationLevel poisoning_level_ =
      PoisoningMitigationLevel::kDontPoison;
259

260
  const CodeKind code_kind_;
261
  int32_t builtin_index_ = -1;
262

263 264 265
  // We retain a reference the bytecode array specifically to ensure it doesn't
  // get flushed while we are optimizing the code.
  Handle<BytecodeArray> bytecode_array_;
266
  Handle<SharedFunctionInfo> shared_info_;
267 268 269
  Handle<JSFunction> closure_;

  // The compiled code.
270
  Handle<Code> code_;
271

272 273 274
  // Basic block profiling support.
  BasicBlockProfilerData* profiler_data_ = nullptr;

275 276 277
  // The WebAssembly compilation result, not published in the NativeModule yet.
  std::unique_ptr<wasm::WasmCompilationResult> wasm_compilation_result_;

278
  // Entry point when compiling for OSR, {BailoutId::None} otherwise.
279
  BailoutId osr_offset_ = BailoutId::None();
280 281

  // The zone from which the compilation pipeline working on this
282
  // OptimizedCompilationInfo allocates.
283
  Zone* const zone_;
284

285
  BailoutReason bailout_reason_ = BailoutReason::kNoReason;
286 287 288

  InlinedFunctionList inlined_functions_;

289 290
  static constexpr int kNoOptimizationId = -1;
  const int optimization_id_;
291
  unsigned inlined_bytecode_size_ = 0;
292 293 294 295 296

  // The current OSR frame for specialization or {nullptr}.
  JavaScriptFrame* osr_frame_ = nullptr;

  Vector<const char> debug_name_;
297
  std::unique_ptr<char[]> trace_turbo_filename_;
298

299 300
  TickCounter tick_counter_;

301 302 303 304 305 306 307 308 309 310 311 312 313
  // 1) PersistentHandles created via PersistentHandlesScope inside of
  //    CompilationHandleScope
  // 2) Owned by OptimizedCompilationInfo
  // 3) Owned by JSHeapBroker
  // 4) Owned by the broker's LocalHeap
  // 5) Back to the broker for a brief moment (after tearing down the
  //   LocalHeap as part of exiting LocalHeapScope)
  // 6) Back to OptimizedCompilationInfo when exiting the LocalHeapScope.
  //
  // In normal execution it gets destroyed when PipelineData gets destroyed.
  // There is a special case in GenerateCodeForTesting where the JSHeapBroker
  // will not be retired in that same method. In this case, we need to re-attach
  // the PersistentHandles container to the JSHeapBroker.
314 315
  std::unique_ptr<PersistentHandles> ph_;

316 317 318 319 320
  // Canonical handles follow the same path as described by the persistent
  // handles above. The only difference is that is created in the
  // CanonicalHandleScope(i.e step 1) is different).
  std::unique_ptr<CanonicalHandlesMap> canonical_handles_;

321
  DISALLOW_COPY_AND_ASSIGN(OptimizedCompilationInfo);
322 323 324 325 326
};

}  // namespace internal
}  // namespace v8

327
#endif  // V8_CODEGEN_OPTIMIZED_COMPILATION_INFO_H_