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