1 // Copyright 2015 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_PIPELINE_H_ 6 #define V8_INTERPRETER_BYTECODE_PIPELINE_H_ 7 8 #include "src/base/compiler-specific.h" 9 #include "src/globals.h" 10 #include "src/interpreter/bytecode-register-allocator.h" 11 #include "src/interpreter/bytecode-register.h" 12 #include "src/interpreter/bytecodes.h" 13 #include "src/objects.h" 14 #include "src/zone/zone-containers.h" 15 16 namespace v8 { 17 namespace internal { 18 namespace interpreter { 19 20 class BytecodeLabel; 21 class BytecodeNode; 22 class BytecodeSourceInfo; 23 24 // Interface for bytecode pipeline stages. 25 class BytecodePipelineStage { 26 public: 27 virtual ~BytecodePipelineStage() {} 28 29 // Write bytecode node |node| into pipeline. The node is only valid 30 // for the duration of the call. Callee's should clone it if 31 // deferring Write() to the next stage. 32 virtual void Write(BytecodeNode* node) = 0; 33 34 // Write jump bytecode node |node| which jumps to |label| into pipeline. 35 // The node and label are only valid for the duration of the call. This call 36 // implicitly ends the current basic block so should always write to the next 37 // stage. 38 virtual void WriteJump(BytecodeNode* node, BytecodeLabel* label) = 0; 39 40 // Binds |label| to the current bytecode location. This call implicitly 41 // ends the current basic block and so any deferred bytecodes should be 42 // written to the next stage. 43 virtual void BindLabel(BytecodeLabel* label) = 0; 44 45 // Binds |label| to the location of |target|. This call implicitly 46 // ends the current basic block and so any deferred bytecodes should be 47 // written to the next stage. 48 virtual void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) = 0; 49 50 // Flush the pipeline and generate a bytecode array. 51 virtual Handle<BytecodeArray> ToBytecodeArray( 52 Isolate* isolate, int register_count, int parameter_count, 53 Handle<FixedArray> handler_table) = 0; 54 }; 55 56 // Source code position information. 57 class BytecodeSourceInfo final { 58 public: 59 static const int kUninitializedPosition = -1; 60 61 BytecodeSourceInfo() 62 : position_type_(PositionType::kNone), 63 source_position_(kUninitializedPosition) {} 64 65 BytecodeSourceInfo(int source_position, bool is_statement) 66 : position_type_(is_statement ? PositionType::kStatement 67 : PositionType::kExpression), 68 source_position_(source_position) { 69 DCHECK_GE(source_position, 0); 70 } 71 72 // Makes instance into a statement position. 73 void MakeStatementPosition(int source_position) { 74 // Statement positions can be replaced by other statement 75 // positions. For example , "for (x = 0; x < 3; ++x) 7;" has a 76 // statement position associated with 7 but no bytecode associated 77 // with it. Then Next is emitted after the body and has 78 // statement position and overrides the existing one. 79 position_type_ = PositionType::kStatement; 80 source_position_ = source_position; 81 } 82 83 // Makes instance into an expression position. Instance should not 84 // be a statement position otherwise it could be lost and impair the 85 // debugging experience. 86 void MakeExpressionPosition(int source_position) { 87 DCHECK(!is_statement()); 88 position_type_ = PositionType::kExpression; 89 source_position_ = source_position; 90 } 91 92 // Forces an instance into an expression position. 93 void ForceExpressionPosition(int source_position) { 94 position_type_ = PositionType::kExpression; 95 source_position_ = source_position; 96 } 97 98 int source_position() const { 99 DCHECK(is_valid()); 100 return source_position_; 101 } 102 103 bool is_statement() const { 104 return position_type_ == PositionType::kStatement; 105 } 106 bool is_expression() const { 107 return position_type_ == PositionType::kExpression; 108 } 109 110 bool is_valid() const { return position_type_ != PositionType::kNone; } 111 void set_invalid() { 112 position_type_ = PositionType::kNone; 113 source_position_ = kUninitializedPosition; 114 } 115 116 bool operator==(const BytecodeSourceInfo& other) const { 117 return position_type_ == other.position_type_ && 118 source_position_ == other.source_position_; 119 } 120 121 bool operator!=(const BytecodeSourceInfo& other) const { 122 return position_type_ != other.position_type_ || 123 source_position_ != other.source_position_; 124 } 125 126 private: 127 enum class PositionType : uint8_t { kNone, kExpression, kStatement }; 128 129 PositionType position_type_; 130 int source_position_; 131 }; 132 133 // A container for a generated bytecode, it's operands, and source information. 134 // These must be allocated by a BytecodeNodeAllocator instance. 135 class V8_EXPORT_PRIVATE BytecodeNode final : NON_EXPORTED_BASE(ZoneObject) { 136 public: 137 INLINE(BytecodeNode(Bytecode bytecode, 138 BytecodeSourceInfo source_info = BytecodeSourceInfo())) 139 : bytecode_(bytecode), 140 operand_count_(0), 141 operand_scale_(OperandScale::kSingle), 142 source_info_(source_info) { 143 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count()); 144 } 145 146 INLINE(BytecodeNode(Bytecode bytecode, uint32_t operand0, 147 BytecodeSourceInfo source_info = BytecodeSourceInfo())) 148 : bytecode_(bytecode), 149 operand_count_(1), 150 operand_scale_(OperandScale::kSingle), 151 source_info_(source_info) { 152 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count()); 153 SetOperand(0, operand0); 154 } 155 156 INLINE(BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1, 157 BytecodeSourceInfo source_info = BytecodeSourceInfo())) 158 : bytecode_(bytecode), 159 operand_count_(2), 160 operand_scale_(OperandScale::kSingle), 161 source_info_(source_info) { 162 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count()); 163 SetOperand(0, operand0); 164 SetOperand(1, operand1); 165 } 166 167 INLINE(BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1, 168 uint32_t operand2, 169 BytecodeSourceInfo source_info = BytecodeSourceInfo())) 170 : bytecode_(bytecode), 171 operand_count_(3), 172 operand_scale_(OperandScale::kSingle), 173 source_info_(source_info) { 174 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count()); 175 SetOperand(0, operand0); 176 SetOperand(1, operand1); 177 SetOperand(2, operand2); 178 } 179 180 INLINE(BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1, 181 uint32_t operand2, uint32_t operand3, 182 BytecodeSourceInfo source_info = BytecodeSourceInfo())) 183 : bytecode_(bytecode), 184 operand_count_(4), 185 operand_scale_(OperandScale::kSingle), 186 source_info_(source_info) { 187 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count()); 188 SetOperand(0, operand0); 189 SetOperand(1, operand1); 190 SetOperand(2, operand2); 191 SetOperand(3, operand3); 192 } 193 194 // Replace the bytecode of this node with |bytecode| and keep the operands. 195 void replace_bytecode(Bytecode bytecode) { 196 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode_), 197 Bytecodes::NumberOfOperands(bytecode)); 198 bytecode_ = bytecode; 199 } 200 201 void set_bytecode(Bytecode bytecode) { 202 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0); 203 bytecode_ = bytecode; 204 operand_count_ = 0; 205 operand_scale_ = OperandScale::kSingle; 206 } 207 208 void set_bytecode(Bytecode bytecode, uint32_t operand0) { 209 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 1); 210 bytecode_ = bytecode; 211 operand_count_ = 1; 212 operand_scale_ = OperandScale::kSingle; 213 SetOperand(0, operand0); 214 } 215 216 void set_bytecode(Bytecode bytecode, uint32_t operand0, uint32_t operand1) { 217 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 2); 218 bytecode_ = bytecode; 219 operand_count_ = 2; 220 operand_scale_ = OperandScale::kSingle; 221 SetOperand(0, operand0); 222 SetOperand(1, operand1); 223 } 224 225 void set_bytecode(Bytecode bytecode, uint32_t operand0, uint32_t operand1, 226 uint32_t operand2) { 227 DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 3); 228 bytecode_ = bytecode; 229 operand_count_ = 3; 230 operand_scale_ = OperandScale::kSingle; 231 SetOperand(0, operand0); 232 SetOperand(1, operand1); 233 SetOperand(2, operand2); 234 } 235 236 // Print to stream |os|. 237 void Print(std::ostream& os) const; 238 239 // Transform to a node representing |new_bytecode| which has one 240 // operand more than the current bytecode. 241 void Transform(Bytecode new_bytecode, uint32_t extra_operand) { 242 DCHECK_EQ(Bytecodes::NumberOfOperands(new_bytecode), 243 Bytecodes::NumberOfOperands(bytecode()) + 1); 244 DCHECK(Bytecodes::NumberOfOperands(bytecode()) < 1 || 245 Bytecodes::GetOperandType(new_bytecode, 0) == 246 Bytecodes::GetOperandType(bytecode(), 0)); 247 DCHECK(Bytecodes::NumberOfOperands(bytecode()) < 2 || 248 Bytecodes::GetOperandType(new_bytecode, 1) == 249 Bytecodes::GetOperandType(bytecode(), 1)); 250 DCHECK(Bytecodes::NumberOfOperands(bytecode()) < 3 || 251 Bytecodes::GetOperandType(new_bytecode, 2) == 252 Bytecodes::GetOperandType(bytecode(), 2)); 253 DCHECK(Bytecodes::NumberOfOperands(bytecode()) < 4); 254 255 bytecode_ = new_bytecode; 256 operand_count_++; 257 SetOperand(operand_count() - 1, extra_operand); 258 } 259 260 Bytecode bytecode() const { return bytecode_; } 261 262 uint32_t operand(int i) const { 263 DCHECK_LT(i, operand_count()); 264 return operands_[i]; 265 } 266 const uint32_t* operands() const { return operands_; } 267 268 int operand_count() const { return operand_count_; } 269 OperandScale operand_scale() const { return operand_scale_; } 270 271 const BytecodeSourceInfo& source_info() const { return source_info_; } 272 void set_source_info(BytecodeSourceInfo source_info) { 273 source_info_ = source_info; 274 } 275 276 bool operator==(const BytecodeNode& other) const; 277 bool operator!=(const BytecodeNode& other) const { return !(*this == other); } 278 279 private: 280 INLINE(void UpdateScaleForOperand(int operand_index, uint32_t operand)) { 281 if (Bytecodes::OperandIsScalableSignedByte(bytecode(), operand_index)) { 282 operand_scale_ = 283 std::max(operand_scale_, Bytecodes::ScaleForSignedOperand(operand)); 284 } else if (Bytecodes::OperandIsScalableUnsignedByte(bytecode(), 285 operand_index)) { 286 operand_scale_ = 287 std::max(operand_scale_, Bytecodes::ScaleForUnsignedOperand(operand)); 288 } 289 } 290 291 INLINE(void SetOperand(int operand_index, uint32_t operand)) { 292 operands_[operand_index] = operand; 293 UpdateScaleForOperand(operand_index, operand); 294 } 295 296 Bytecode bytecode_; 297 uint32_t operands_[Bytecodes::kMaxOperands]; 298 int operand_count_; 299 OperandScale operand_scale_; 300 BytecodeSourceInfo source_info_; 301 }; 302 303 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, 304 const BytecodeSourceInfo& info); 305 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os, 306 const BytecodeNode& node); 307 308 } // namespace interpreter 309 } // namespace internal 310 } // namespace v8 311 312 #endif // V8_INTERPRETER_BYTECODE_PIPELINE_H_ 313