1 // Copyright 2017 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_INTERPRETER_BYTECODE_NODE_H_
6 #define V8_INTERPRETER_BYTECODE_NODE_H_
7 
8 #include <algorithm>
9 
10 #include "src/globals.h"
11 #include "src/interpreter/bytecode-source-info.h"
12 #include "src/interpreter/bytecodes.h"
13 
14 namespace v8 {
15 namespace internal {
16 namespace interpreter {
17 
18 // A container for a generated bytecode, it's operands, and source information.
19 class V8_EXPORT_PRIVATE BytecodeNode final {
20  public:
21   INLINE(BytecodeNode(Bytecode bytecode,
22                       BytecodeSourceInfo source_info = BytecodeSourceInfo()))
bytecode_(bytecode)23       : bytecode_(bytecode),
24         operand_count_(0),
25         operand_scale_(OperandScale::kSingle),
26         source_info_(source_info) {
27     DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count());
28   }
29 
30   INLINE(BytecodeNode(Bytecode bytecode, uint32_t operand0,
31                       BytecodeSourceInfo source_info = BytecodeSourceInfo()))
bytecode_(bytecode)32       : bytecode_(bytecode),
33         operand_count_(1),
34         operand_scale_(OperandScale::kSingle),
35         source_info_(source_info) {
36     DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count());
37     SetOperand(0, operand0);
38   }
39 
40   INLINE(BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
41                       BytecodeSourceInfo source_info = BytecodeSourceInfo()))
bytecode_(bytecode)42       : bytecode_(bytecode),
43         operand_count_(2),
44         operand_scale_(OperandScale::kSingle),
45         source_info_(source_info) {
46     DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count());
47     SetOperand(0, operand0);
48     SetOperand(1, operand1);
49   }
50 
51   INLINE(BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
52                       uint32_t operand2,
53                       BytecodeSourceInfo source_info = BytecodeSourceInfo()))
bytecode_(bytecode)54       : bytecode_(bytecode),
55         operand_count_(3),
56         operand_scale_(OperandScale::kSingle),
57         source_info_(source_info) {
58     DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count());
59     SetOperand(0, operand0);
60     SetOperand(1, operand1);
61     SetOperand(2, operand2);
62   }
63 
64   INLINE(BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
65                       uint32_t operand2, uint32_t operand3,
66                       BytecodeSourceInfo source_info = BytecodeSourceInfo()))
bytecode_(bytecode)67       : bytecode_(bytecode),
68         operand_count_(4),
69         operand_scale_(OperandScale::kSingle),
70         source_info_(source_info) {
71     DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count());
72     SetOperand(0, operand0);
73     SetOperand(1, operand1);
74     SetOperand(2, operand2);
75     SetOperand(3, operand3);
76   }
77 
78   INLINE(BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
79                       uint32_t operand2, uint32_t operand3, uint32_t operand4,
80                       BytecodeSourceInfo source_info = BytecodeSourceInfo()))
bytecode_(bytecode)81       : bytecode_(bytecode),
82         operand_count_(5),
83         operand_scale_(OperandScale::kSingle),
84         source_info_(source_info) {
85     DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count());
86     SetOperand(0, operand0);
87     SetOperand(1, operand1);
88     SetOperand(2, operand2);
89     SetOperand(3, operand3);
90     SetOperand(4, operand4);
91   }
92 
93 #define DEFINE_BYTECODE_NODE_CREATOR(Name, ...)                              \
94   template <typename... Operands>                                            \
95   INLINE(static BytecodeNode Name(BytecodeSourceInfo source_info,            \
96                                   Operands... operands)) {                   \
97     return Create<Bytecode::k##Name, __VA_ARGS__>(source_info, operands...); \
98   }
99   BYTECODE_LIST(DEFINE_BYTECODE_NODE_CREATOR)
100 #undef DEFINE_BYTECODE_NODE_CREATOR
101 
102   // Print to stream |os|.
103   void Print(std::ostream& os) const;
104 
bytecode()105   Bytecode bytecode() const { return bytecode_; }
106 
operand(int i)107   uint32_t operand(int i) const {
108     DCHECK_LT(i, operand_count());
109     return operands_[i];
110   }
operands()111   const uint32_t* operands() const { return operands_; }
112 
update_operand0(uint32_t operand0)113   void update_operand0(uint32_t operand0) { SetOperand(0, operand0); }
114 
operand_count()115   int operand_count() const { return operand_count_; }
operand_scale()116   OperandScale operand_scale() const { return operand_scale_; }
117 
source_info()118   const BytecodeSourceInfo& source_info() const { return source_info_; }
set_source_info(BytecodeSourceInfo source_info)119   void set_source_info(BytecodeSourceInfo source_info) {
120     source_info_ = source_info;
121   }
122 
123   bool operator==(const BytecodeNode& other) const;
124   bool operator!=(const BytecodeNode& other) const { return !(*this == other); }
125 
126  private:
127   template <Bytecode bytecode, AccumulatorUse accumulator_use,
128             OperandType... operand_types>
129   friend class BytecodeNodeBuilder;
130 
131   INLINE(BytecodeNode(Bytecode bytecode, int operand_count,
132                       OperandScale operand_scale,
133                       BytecodeSourceInfo source_info, uint32_t operand0 = 0,
134                       uint32_t operand1 = 0, uint32_t operand2 = 0,
135                       uint32_t operand3 = 0, uint32_t operand4 = 0))
bytecode_(bytecode)136       : bytecode_(bytecode),
137         operand_count_(operand_count),
138         operand_scale_(operand_scale),
139         source_info_(source_info) {
140     DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count);
141     operands_[0] = operand0;
142     operands_[1] = operand1;
143     operands_[2] = operand2;
144     operands_[3] = operand3;
145     operands_[4] = operand4;
146   }
147 
148   template <Bytecode bytecode, AccumulatorUse accum_use>
INLINE(static BytecodeNode Create (BytecodeSourceInfo source_info))149   INLINE(static BytecodeNode Create(BytecodeSourceInfo source_info)) {
150     return BytecodeNode(bytecode, 0, OperandScale::kSingle, source_info);
151   }
152 
153   template <Bytecode bytecode, AccumulatorUse accum_use,
154             OperandType operand0_type>
INLINE(static BytecodeNode Create (BytecodeSourceInfo source_info,uint32_t operand0))155   INLINE(static BytecodeNode Create(BytecodeSourceInfo source_info,
156                                     uint32_t operand0)) {
157     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 0), operand0_type);
158     OperandScale scale = OperandScale::kSingle;
159     scale = std::max(scale, ScaleForOperand<operand0_type>(operand0));
160     return BytecodeNode(bytecode, 1, scale, source_info, operand0);
161   }
162 
163   template <Bytecode bytecode, AccumulatorUse accum_use,
164             OperandType operand0_type, OperandType operand1_type>
INLINE(static BytecodeNode Create (BytecodeSourceInfo source_info,uint32_t operand0,uint32_t operand1))165   INLINE(static BytecodeNode Create(BytecodeSourceInfo source_info,
166                                     uint32_t operand0, uint32_t operand1)) {
167     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 0), operand0_type);
168     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 1), operand1_type);
169     OperandScale scale = OperandScale::kSingle;
170     scale = std::max(scale, ScaleForOperand<operand0_type>(operand0));
171     scale = std::max(scale, ScaleForOperand<operand1_type>(operand1));
172     return BytecodeNode(bytecode, 2, scale, source_info, operand0, operand1);
173   }
174 
175   template <Bytecode bytecode, AccumulatorUse accum_use,
176             OperandType operand0_type, OperandType operand1_type,
177             OperandType operand2_type>
INLINE(static BytecodeNode Create (BytecodeSourceInfo source_info,uint32_t operand0,uint32_t operand1,uint32_t operand2))178   INLINE(static BytecodeNode Create(BytecodeSourceInfo source_info,
179                                     uint32_t operand0, uint32_t operand1,
180                                     uint32_t operand2)) {
181     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 0), operand0_type);
182     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 1), operand1_type);
183     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 2), operand2_type);
184     OperandScale scale = OperandScale::kSingle;
185     scale = std::max(scale, ScaleForOperand<operand0_type>(operand0));
186     scale = std::max(scale, ScaleForOperand<operand1_type>(operand1));
187     scale = std::max(scale, ScaleForOperand<operand2_type>(operand2));
188     return BytecodeNode(bytecode, 3, scale, source_info, operand0, operand1,
189                         operand2);
190   }
191 
192   template <Bytecode bytecode, AccumulatorUse accum_use,
193             OperandType operand0_type, OperandType operand1_type,
194             OperandType operand2_type, OperandType operand3_type>
INLINE(static BytecodeNode Create (BytecodeSourceInfo source_info,uint32_t operand0,uint32_t operand1,uint32_t operand2,uint32_t operand3))195   INLINE(static BytecodeNode Create(BytecodeSourceInfo source_info,
196                                     uint32_t operand0, uint32_t operand1,
197                                     uint32_t operand2, uint32_t operand3)) {
198     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 0), operand0_type);
199     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 1), operand1_type);
200     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 2), operand2_type);
201     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 3), operand3_type);
202     OperandScale scale = OperandScale::kSingle;
203     scale = std::max(scale, ScaleForOperand<operand0_type>(operand0));
204     scale = std::max(scale, ScaleForOperand<operand1_type>(operand1));
205     scale = std::max(scale, ScaleForOperand<operand2_type>(operand2));
206     scale = std::max(scale, ScaleForOperand<operand3_type>(operand3));
207     return BytecodeNode(bytecode, 4, scale, source_info, operand0, operand1,
208                         operand2, operand3);
209   }
210 
211   template <Bytecode bytecode, AccumulatorUse accum_use,
212             OperandType operand0_type, OperandType operand1_type,
213             OperandType operand2_type, OperandType operand3_type,
214             OperandType operand4_type>
INLINE(static BytecodeNode Create (BytecodeSourceInfo source_info,uint32_t operand0,uint32_t operand1,uint32_t operand2,uint32_t operand3,uint32_t operand4))215   INLINE(static BytecodeNode Create(BytecodeSourceInfo source_info,
216                                     uint32_t operand0, uint32_t operand1,
217                                     uint32_t operand2, uint32_t operand3,
218                                     uint32_t operand4)) {
219     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 0), operand0_type);
220     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 1), operand1_type);
221     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 2), operand2_type);
222     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 3), operand3_type);
223     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 4), operand4_type);
224     OperandScale scale = OperandScale::kSingle;
225     scale = std::max(scale, ScaleForOperand<operand0_type>(operand0));
226     scale = std::max(scale, ScaleForOperand<operand1_type>(operand1));
227     scale = std::max(scale, ScaleForOperand<operand2_type>(operand2));
228     scale = std::max(scale, ScaleForOperand<operand3_type>(operand3));
229     scale = std::max(scale, ScaleForOperand<operand4_type>(operand4));
230     return BytecodeNode(bytecode, 5, scale, source_info, operand0, operand1,
231                         operand2, operand3, operand4);
232   }
233 
234   template <OperandType operand_type>
INLINE(static OperandScale ScaleForOperand (uint32_t operand))235   INLINE(static OperandScale ScaleForOperand(uint32_t operand)) {
236     if (BytecodeOperands::IsScalableUnsignedByte(operand_type)) {
237       return Bytecodes::ScaleForUnsignedOperand(operand);
238     } else if (BytecodeOperands::IsScalableSignedByte(operand_type)) {
239       return Bytecodes::ScaleForSignedOperand(operand);
240     } else {
241       return OperandScale::kSingle;
242     }
243   }
244 
INLINE(void UpdateScaleForOperand (int operand_index,uint32_t operand))245   INLINE(void UpdateScaleForOperand(int operand_index, uint32_t operand)) {
246     if (Bytecodes::OperandIsScalableSignedByte(bytecode(), operand_index)) {
247       operand_scale_ =
248           std::max(operand_scale_, Bytecodes::ScaleForSignedOperand(operand));
249     } else if (Bytecodes::OperandIsScalableUnsignedByte(bytecode(),
250                                                         operand_index)) {
251       operand_scale_ =
252           std::max(operand_scale_, Bytecodes::ScaleForUnsignedOperand(operand));
253     }
254   }
255 
INLINE(void SetOperand (int operand_index,uint32_t operand))256   INLINE(void SetOperand(int operand_index, uint32_t operand)) {
257     operands_[operand_index] = operand;
258     UpdateScaleForOperand(operand_index, operand);
259   }
260 
261   Bytecode bytecode_;
262   uint32_t operands_[Bytecodes::kMaxOperands];
263   int operand_count_;
264   OperandScale operand_scale_;
265   BytecodeSourceInfo source_info_;
266 };
267 
268 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
269                                            const BytecodeNode& node);
270 
271 }  // namespace interpreter
272 }  // namespace internal
273 }  // namespace v8
274 
275 #endif  // V8_INTERPRETER_BYTECODE_NODE_H_
276