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/interpreter/bytecode-register-allocator.h" 9#include "src/interpreter/bytecodes.h" 10#include "src/zone-containers.h" 11 12namespace v8 { 13namespace internal { 14namespace interpreter { 15 16class BytecodeLabel; 17class BytecodeNode; 18class BytecodeSourceInfo; 19 20// Interface for bytecode pipeline stages. 21class BytecodePipelineStage { 22 public: 23 virtual ~BytecodePipelineStage() {} 24 25 // Write bytecode node |node| into pipeline. The node is only valid 26 // for the duration of the call. Callee's should clone it if 27 // deferring Write() to the next stage. 28 virtual void Write(BytecodeNode* node) = 0; 29 30 // Write jump bytecode node |node| which jumps to |label| into pipeline. 31 // The node and label are only valid for the duration of the call. This call 32 // implicitly ends the current basic block so should always write to the next 33 // stage. 34 virtual void WriteJump(BytecodeNode* node, BytecodeLabel* label) = 0; 35 36 // Binds |label| to the current bytecode location. This call implicitly 37 // ends the current basic block and so any deferred bytecodes should be 38 // written to the next stage. 39 virtual void BindLabel(BytecodeLabel* label) = 0; 40 41 // Binds |label| to the location of |target|. This call implicitly 42 // ends the current basic block and so any deferred bytecodes should be 43 // written to the next stage. 44 virtual void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) = 0; 45 46 // Flush the pipeline and generate a bytecode array. 47 virtual Handle<BytecodeArray> ToBytecodeArray( 48 int fixed_register_count, int parameter_count, 49 Handle<FixedArray> handler_table) = 0; 50}; 51 52// Source code position information. 53class BytecodeSourceInfo final { 54 public: 55 static const int kUninitializedPosition = -1; 56 57 BytecodeSourceInfo() 58 : position_type_(PositionType::kNone), 59 source_position_(kUninitializedPosition) {} 60 61 BytecodeSourceInfo(int source_position, bool is_statement) 62 : position_type_(is_statement ? PositionType::kStatement 63 : PositionType::kExpression), 64 source_position_(source_position) { 65 DCHECK_GE(source_position, 0); 66 } 67 68 // Makes instance into a statement position. 69 void MakeStatementPosition(int source_position) { 70 // Statement positions can be replaced by other statement 71 // positions. For example , "for (x = 0; x < 3; ++x) 7;" has a 72 // statement position associated with 7 but no bytecode associated 73 // with it. Then Next is emitted after the body and has 74 // statement position and overrides the existing one. 75 position_type_ = PositionType::kStatement; 76 source_position_ = source_position; 77 } 78 79 // Makes instance into an expression position. Instance should not 80 // be a statement position otherwise it could be lost and impair the 81 // debugging experience. 82 void MakeExpressionPosition(int source_position) { 83 DCHECK(!is_statement()); 84 position_type_ = PositionType::kExpression; 85 source_position_ = source_position; 86 } 87 88 // Forces an instance into an expression position. 89 void ForceExpressionPosition(int source_position) { 90 position_type_ = PositionType::kExpression; 91 source_position_ = source_position; 92 } 93 94 // Clones a source position. The current instance is expected to be 95 // invalid. 96 void Clone(const BytecodeSourceInfo& other) { 97 DCHECK(!is_valid()); 98 position_type_ = other.position_type_; 99 source_position_ = other.source_position_; 100 } 101 102 int source_position() const { 103 DCHECK(is_valid()); 104 return source_position_; 105 } 106 107 bool is_statement() const { 108 return position_type_ == PositionType::kStatement; 109 } 110 bool is_expression() const { 111 return position_type_ == PositionType::kExpression; 112 } 113 114 bool is_valid() const { return position_type_ != PositionType::kNone; } 115 void set_invalid() { 116 position_type_ = PositionType::kNone; 117 source_position_ = kUninitializedPosition; 118 } 119 120 bool operator==(const BytecodeSourceInfo& other) const { 121 return position_type_ == other.position_type_ && 122 source_position_ == other.source_position_; 123 } 124 125 bool operator!=(const BytecodeSourceInfo& other) const { 126 return position_type_ != other.position_type_ || 127 source_position_ != other.source_position_; 128 } 129 130 private: 131 enum class PositionType : uint8_t { kNone, kExpression, kStatement }; 132 133 PositionType position_type_; 134 int source_position_; 135 136 DISALLOW_COPY_AND_ASSIGN(BytecodeSourceInfo); 137}; 138 139// A container for a generated bytecode, it's operands, and source information. 140// These must be allocated by a BytecodeNodeAllocator instance. 141class BytecodeNode final : ZoneObject { 142 public: 143 explicit BytecodeNode(Bytecode bytecode = Bytecode::kIllegal); 144 BytecodeNode(Bytecode bytecode, uint32_t operand0); 145 BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1); 146 BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1, 147 uint32_t operand2); 148 BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1, 149 uint32_t operand2, uint32_t operand3); 150 151 BytecodeNode(const BytecodeNode& other); 152 BytecodeNode& operator=(const BytecodeNode& other); 153 154 void set_bytecode(Bytecode bytecode); 155 void set_bytecode(Bytecode bytecode, uint32_t operand0); 156 157 // Clone |other|. 158 void Clone(const BytecodeNode* const other); 159 160 // Print to stream |os|. 161 void Print(std::ostream& os) const; 162 163 // Transform to a node representing |new_bytecode| which has one 164 // operand more than the current bytecode. 165 void Transform(Bytecode new_bytecode, uint32_t extra_operand); 166 167 Bytecode bytecode() const { return bytecode_; } 168 169 uint32_t operand(int i) const { 170 DCHECK_LT(i, operand_count()); 171 return operands_[i]; 172 } 173 uint32_t* operands() { return operands_; } 174 const uint32_t* operands() const { return operands_; } 175 176 int operand_count() const { return Bytecodes::NumberOfOperands(bytecode_); } 177 178 const BytecodeSourceInfo& source_info() const { return source_info_; } 179 BytecodeSourceInfo& source_info() { return source_info_; } 180 181 bool operator==(const BytecodeNode& other) const; 182 bool operator!=(const BytecodeNode& other) const { return !(*this == other); } 183 184 private: 185 static const int kInvalidPosition = kMinInt; 186 static const size_t kMaxOperands = 4; 187 188 Bytecode bytecode_; 189 uint32_t operands_[kMaxOperands]; 190 BytecodeSourceInfo source_info_; 191}; 192 193std::ostream& operator<<(std::ostream& os, const BytecodeSourceInfo& info); 194std::ostream& operator<<(std::ostream& os, const BytecodeNode& node); 195 196} // namespace interpreter 197} // namespace internal 198} // namespace v8 199 200#endif // V8_INTERPRETER_BYTECODE_PIPELINE_H_ 201