Home | History | Annotate | Download | only in interpreter
      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