• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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