1 // Copyright 2021 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 #ifndef V8_BASELINE_BASELINE_COMPILER_H_ 6 #define V8_BASELINE_BASELINE_COMPILER_H_ 7 8 // TODO(v8:11421): Remove #if once baseline compiler is ported to other 9 // architectures. 10 #include "src/flags/flags.h" 11 #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 #include "src/execution/local-isolate.h" 18 #include "src/handles/handles.h" 19 #include "src/interpreter/bytecode-array-iterator.h" 20 #include "src/interpreter/bytecode-register.h" 21 #include "src/interpreter/interpreter-intrinsics.h" 22 #include "src/logging/counters.h" 23 #include "src/objects/map.h" 24 #include "src/objects/tagged-index.h" 25 26 namespace v8 { 27 namespace internal { 28 29 class BytecodeArray; 30 31 namespace baseline { 32 33 class BytecodeOffsetTableBuilder { 34 public: AddPosition(size_t pc_offset)35 void AddPosition(size_t pc_offset) { 36 size_t pc_diff = pc_offset - previous_pc_; 37 DCHECK_GE(pc_diff, 0); 38 DCHECK_LE(pc_diff, std::numeric_limits<uint32_t>::max()); 39 base::VLQEncodeUnsigned(&bytes_, static_cast<uint32_t>(pc_diff)); 40 previous_pc_ = pc_offset; 41 } 42 43 template <typename IsolateT> 44 Handle<ByteArray> ToBytecodeOffsetTable(IsolateT* isolate); 45 Reserve(size_t size)46 void Reserve(size_t size) { bytes_.reserve(size); } 47 48 private: 49 size_t previous_pc_ = 0; 50 std::vector<byte> bytes_; 51 }; 52 53 class BaselineCompiler { 54 public: 55 explicit BaselineCompiler(LocalIsolate* local_isolate, 56 Handle<SharedFunctionInfo> shared_function_info, 57 Handle<BytecodeArray> bytecode); 58 59 void GenerateCode(); 60 MaybeHandle<Code> Build(LocalIsolate* local_isolate); 61 static int EstimateInstructionSize(BytecodeArray bytecode); 62 63 private: 64 void Prologue(); 65 void PrologueFillFrame(); 66 void PrologueHandleOptimizationState(Register feedback_vector); 67 68 void PreVisitSingleBytecode(); 69 void VisitSingleBytecode(); 70 71 void VerifyFrame(); 72 void VerifyFrameSize(); 73 74 // Register operands. 75 interpreter::Register RegisterOperand(int operand_index); 76 void LoadRegister(Register output, int operand_index); 77 void StoreRegister(int operand_index, Register value); 78 void StoreRegisterPair(int operand_index, Register val0, Register val1); 79 80 // Constant pool operands. 81 template <typename Type> 82 Handle<Type> Constant(int operand_index); 83 Smi ConstantSmi(int operand_index); 84 template <typename Type> 85 void LoadConstant(Register output, int operand_index); 86 87 // Immediate value operands. 88 uint32_t Uint(int operand_index); 89 int32_t Int(int operand_index); 90 uint32_t Index(int operand_index); 91 uint32_t Flag(int operand_index); 92 uint32_t RegisterCount(int operand_index); 93 TaggedIndex IndexAsTagged(int operand_index); 94 TaggedIndex UintAsTagged(int operand_index); 95 Smi IndexAsSmi(int operand_index); 96 Smi IntAsSmi(int operand_index); 97 Smi FlagAsSmi(int operand_index); 98 99 // Jump helpers. 100 Label* NewLabel(); 101 Label* BuildForwardJumpLabel(); 102 void UpdateInterruptBudgetAndJumpToLabel(int weight, Label* label, 103 Label* skip_interrupt_label); 104 void UpdateInterruptBudgetAndDoInterpreterJump(); 105 void UpdateInterruptBudgetAndDoInterpreterJumpIfRoot(RootIndex root); 106 void UpdateInterruptBudgetAndDoInterpreterJumpIfNotRoot(RootIndex root); 107 108 // Feedback vector. 109 MemOperand FeedbackVector(); 110 void LoadFeedbackVector(Register output); 111 void LoadClosureFeedbackArray(Register output); 112 113 // Position mapping. 114 void AddPosition(); 115 116 // Misc. helpers. 117 UpdateMaxCallArgs(int max_call_args)118 void UpdateMaxCallArgs(int max_call_args) { 119 max_call_args_ = std::max(max_call_args_, max_call_args); 120 } 121 122 // Select the root boolean constant based on the jump in the given 123 // `jump_func` -- the function should jump to the given label if we want to 124 // select "true", otherwise it should fall through. 125 void SelectBooleanConstant( 126 Register output, std::function<void(Label*, Label::Distance)> jump_func); 127 128 // Jumps based on calling ToBoolean on kInterpreterAccumulatorRegister. 129 void JumpIfToBoolean(bool do_jump_if_true, Label* label, 130 Label::Distance distance = Label::kFar); 131 132 // Call helpers. 133 template <Builtin kBuiltin, typename... Args> 134 void CallBuiltin(Args... args); 135 template <typename... Args> 136 void CallRuntime(Runtime::FunctionId function, Args... args); 137 138 template <Builtin kBuiltin, typename... Args> 139 void TailCallBuiltin(Args... args); 140 141 template <ConvertReceiverMode kMode, typename... Args> 142 void BuildCall(uint32_t slot, uint32_t arg_count, Args... args); 143 144 #ifdef V8_TRACE_UNOPTIMIZED 145 void TraceBytecode(Runtime::FunctionId function_id); 146 #endif 147 148 // Single bytecode visitors. 149 #define DECLARE_VISITOR(name, ...) void Visit##name(); 150 BYTECODE_LIST(DECLARE_VISITOR) 151 #undef DECLARE_VISITOR 152 153 // Intrinsic call visitors. 154 #define DECLARE_VISITOR(name, ...) \ 155 void VisitIntrinsic##name(interpreter::RegisterList args); INTRINSICS_LIST(DECLARE_VISITOR)156 INTRINSICS_LIST(DECLARE_VISITOR) 157 #undef DECLARE_VISITOR 158 159 const interpreter::BytecodeArrayIterator& iterator() { return iterator_; } 160 161 LocalIsolate* local_isolate_; 162 RuntimeCallStats* stats_; 163 Handle<SharedFunctionInfo> shared_function_info_; 164 Handle<HeapObject> interpreter_data_; 165 Handle<BytecodeArray> bytecode_; 166 MacroAssembler masm_; 167 BaselineAssembler basm_; 168 interpreter::BytecodeArrayIterator iterator_; 169 BytecodeOffsetTableBuilder bytecode_offset_table_builder_; 170 Zone zone_; 171 172 int max_call_args_ = 0; 173 174 struct ThreadedLabel { 175 Label label; 176 ThreadedLabel* ptr; nextThreadedLabel177 ThreadedLabel** next() { return &ptr; } 178 }; 179 180 struct BaselineLabels { 181 base::ThreadedList<ThreadedLabel> linked; 182 Label unlinked; 183 }; 184 EnsureLabels(int i)185 BaselineLabels* EnsureLabels(int i) { 186 if (labels_[i] == nullptr) { 187 labels_[i] = zone_.New<BaselineLabels>(); 188 } 189 return labels_[i]; 190 } 191 192 BaselineLabels** labels_; 193 }; 194 195 } // namespace baseline 196 } // namespace internal 197 } // namespace v8 198 199 #endif // ENABLE_SPARKPLUG 200 201 #endif // V8_BASELINE_BASELINE_COMPILER_H_ 202