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