baseline-compiler.h 5.91 KB
Newer Older
1 2 3 4 5 6 7 8 9
// Copyright 2021 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.

#ifndef V8_BASELINE_BASELINE_COMPILER_H_
#define V8_BASELINE_BASELINE_COMPILER_H_

// TODO(v8:11421): Remove #if once baseline compiler is ported to other
// architectures.
10 11
#include "src/flags/flags.h"
#if ENABLE_SPARKPLUG
12 13

#include "src/base/logging.h"
14
#include "src/base/threaded-list.h"
15
#include "src/base/vlq.h"
16
#include "src/baseline/baseline-assembler.h"
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
#include "src/handles/handles.h"
#include "src/interpreter/bytecode-array-iterator.h"
#include "src/interpreter/bytecode-register.h"
#include "src/interpreter/interpreter-intrinsics.h"
#include "src/logging/counters.h"
#include "src/objects/map.h"
#include "src/objects/tagged-index.h"

namespace v8 {
namespace internal {

class BytecodeArray;

namespace baseline {

class BytecodeOffsetTableBuilder {
 public:
34
  void AddPosition(size_t pc_offset) {
35 36 37 38
    size_t pc_diff = pc_offset - previous_pc_;
    DCHECK_GE(pc_diff, 0);
    DCHECK_LE(pc_diff, std::numeric_limits<uint32_t>::max());
    base::VLQEncodeUnsigned(&bytes_, static_cast<uint32_t>(pc_diff));
39 40 41
    previous_pc_ = pc_offset;
  }

42 43
  template <typename IsolateT>
  Handle<ByteArray> ToBytecodeOffsetTable(IsolateT* isolate);
44

45 46
  void Reserve(size_t size) { bytes_.reserve(size); }

47 48 49 50 51 52 53
 private:
  size_t previous_pc_ = 0;
  std::vector<byte> bytes_;
};

class BaselineCompiler {
 public:
54 55 56 57 58
  enum CodeLocation { kOffHeap, kOnHeap };
  explicit BaselineCompiler(
      Isolate* isolate, Handle<SharedFunctionInfo> shared_function_info,
      Handle<BytecodeArray> bytecode,
      CodeLocation code_location = CodeLocation::kOffHeap);
59 60

  void GenerateCode();
61
  MaybeHandle<Code> Build(Isolate* isolate);
62
  static int EstimateInstructionSize(BytecodeArray bytecode);
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111

 private:
  void Prologue();
  void PrologueFillFrame();
  void PrologueHandleOptimizationState(Register feedback_vector);

  void PreVisitSingleBytecode();
  void VisitSingleBytecode();

  void VerifyFrame();
  void VerifyFrameSize();

  // Register operands.
  interpreter::Register RegisterOperand(int operand_index);
  void LoadRegister(Register output, int operand_index);
  void StoreRegister(int operand_index, Register value);
  void StoreRegisterPair(int operand_index, Register val0, Register val1);

  // Constant pool operands.
  template <typename Type>
  Handle<Type> Constant(int operand_index);
  Smi ConstantSmi(int operand_index);
  template <typename Type>
  void LoadConstant(Register output, int operand_index);

  // Immediate value operands.
  uint32_t Uint(int operand_index);
  int32_t Int(int operand_index);
  uint32_t Index(int operand_index);
  uint32_t Flag(int operand_index);
  uint32_t RegisterCount(int operand_index);
  TaggedIndex IndexAsTagged(int operand_index);
  TaggedIndex UintAsTagged(int operand_index);
  Smi IndexAsSmi(int operand_index);
  Smi IntAsSmi(int operand_index);
  Smi FlagAsSmi(int operand_index);

  // Jump helpers.
  Label* NewLabel();
  Label* BuildForwardJumpLabel();
  void UpdateInterruptBudgetAndJumpToLabel(int weight, Label* label,
                                           Label* skip_interrupt_label);
  void UpdateInterruptBudgetAndDoInterpreterJump();
  void UpdateInterruptBudgetAndDoInterpreterJumpIfRoot(RootIndex root);
  void UpdateInterruptBudgetAndDoInterpreterJumpIfNotRoot(RootIndex root);

  // Feedback vector.
  MemOperand FeedbackVector();
  void LoadFeedbackVector(Register output);
112
  void LoadClosureFeedbackArray(Register output);
113 114 115 116 117 118

  // Position mapping.
  void AddPosition();

  // Misc. helpers.

119 120 121 122
  void UpdateMaxCallArgs(int max_call_args) {
    max_call_args_ = std::max(max_call_args_, max_call_args);
  }

123 124 125 126 127 128
  // Select the root boolean constant based on the jump in the given
  // `jump_func` -- the function should jump to the given label if we want to
  // select "true", otherwise it should fall through.
  void SelectBooleanConstant(
      Register output, std::function<void(Label*, Label::Distance)> jump_func);

129 130
  // Jumps based on calling ToBoolean on kInterpreterAccumulatorRegister.
  void JumpIfToBoolean(bool do_jump_if_true, Label* label,
131 132 133
                       Label::Distance distance = Label::kFar);

  // Call helpers.
134
  template <Builtin kBuiltin, typename... Args>
135
  void CallBuiltin(Args... args);
136 137 138
  template <typename... Args>
  void CallRuntime(Runtime::FunctionId function, Args... args);

139
  template <Builtin kBuiltin, typename... Args>
140
  void TailCallBuiltin(Args... args);
141

142 143
  template <ConvertReceiverMode kMode, typename... Args>
  void BuildCall(uint32_t slot, uint32_t arg_count, Args... args);
144

145
#ifdef V8_TRACE_UNOPTIMIZED
146 147 148 149 150 151 152 153 154 155 156 157 158 159
  void TraceBytecode(Runtime::FunctionId function_id);
#endif

  // Single bytecode visitors.
#define DECLARE_VISITOR(name, ...) void Visit##name();
  BYTECODE_LIST(DECLARE_VISITOR)
#undef DECLARE_VISITOR

  // Intrinsic call visitors.
#define DECLARE_VISITOR(name, ...) \
  void VisitIntrinsic##name(interpreter::RegisterList args);
  INTRINSICS_LIST(DECLARE_VISITOR)
#undef DECLARE_VISITOR

160
  const interpreter::BytecodeArrayIterator& iterator() { return iterator_; }
161 162 163 164 165 166 167 168 169 170 171

  Isolate* isolate_;
  RuntimeCallStats* stats_;
  Handle<SharedFunctionInfo> shared_function_info_;
  Handle<BytecodeArray> bytecode_;
  MacroAssembler masm_;
  BaselineAssembler basm_;
  interpreter::BytecodeArrayIterator iterator_;
  BytecodeOffsetTableBuilder bytecode_offset_table_builder_;
  Zone zone_;

172 173
  int max_call_args_ = 0;

174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
  struct ThreadedLabel {
    Label label;
    ThreadedLabel* ptr;
    ThreadedLabel** next() { return &ptr; }
  };

  struct BaselineLabels {
    base::ThreadedList<ThreadedLabel> linked;
    Label unlinked;
  };

  BaselineLabels* EnsureLabels(int i) {
    if (labels_[i] == nullptr) {
      labels_[i] = zone_.New<BaselineLabels>();
    }
    return labels_[i];
  }

  BaselineLabels** labels_;
193 194 195 196 197 198
};

}  // namespace baseline
}  // namespace internal
}  // namespace v8

199
#endif  // ENABLE_SPARKPLUG
200 201

#endif  // V8_BASELINE_BASELINE_COMPILER_H_