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