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 #define DEFINE_BYTECODE_NODE_CREATOR(Name, ...)                              \
    195   template <typename... Operands>                                            \
    196   INLINE(static BytecodeNode Name(BytecodeSourceInfo source_info,            \
    197                                   Operands... operands)) {                   \
    198     return Create<Bytecode::k##Name, __VA_ARGS__>(source_info, operands...); \
    199   }
    200   BYTECODE_LIST(DEFINE_BYTECODE_NODE_CREATOR)
    201 #undef DEFINE_BYTECODE_NODE_CREATOR
    202 
    203   // Replace the bytecode of this node with |bytecode| and keep the operands.
    204   void replace_bytecode(Bytecode bytecode) {
    205     DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode_),
    206               Bytecodes::NumberOfOperands(bytecode));
    207     bytecode_ = bytecode;
    208   }
    209 
    210   void update_operand0(uint32_t operand0) { SetOperand(0, operand0); }
    211 
    212   // Print to stream |os|.
    213   void Print(std::ostream& os) const;
    214 
    215   // Transform to a node representing |new_bytecode| which has one
    216   // operand more than the current bytecode.
    217   void Transform(Bytecode new_bytecode, uint32_t extra_operand) {
    218     DCHECK_EQ(Bytecodes::NumberOfOperands(new_bytecode),
    219               Bytecodes::NumberOfOperands(bytecode()) + 1);
    220     DCHECK(Bytecodes::NumberOfOperands(bytecode()) < 1 ||
    221            Bytecodes::GetOperandType(new_bytecode, 0) ==
    222                Bytecodes::GetOperandType(bytecode(), 0));
    223     DCHECK(Bytecodes::NumberOfOperands(bytecode()) < 2 ||
    224            Bytecodes::GetOperandType(new_bytecode, 1) ==
    225                Bytecodes::GetOperandType(bytecode(), 1));
    226     DCHECK(Bytecodes::NumberOfOperands(bytecode()) < 3 ||
    227            Bytecodes::GetOperandType(new_bytecode, 2) ==
    228                Bytecodes::GetOperandType(bytecode(), 2));
    229     DCHECK(Bytecodes::NumberOfOperands(bytecode()) < 4);
    230 
    231     bytecode_ = new_bytecode;
    232     operand_count_++;
    233     SetOperand(operand_count() - 1, extra_operand);
    234   }
    235 
    236   Bytecode bytecode() const { return bytecode_; }
    237 
    238   uint32_t operand(int i) const {
    239     DCHECK_LT(i, operand_count());
    240     return operands_[i];
    241   }
    242   const uint32_t* operands() const { return operands_; }
    243 
    244   int operand_count() const { return operand_count_; }
    245   OperandScale operand_scale() const { return operand_scale_; }
    246 
    247   const BytecodeSourceInfo& source_info() const { return source_info_; }
    248   void set_source_info(BytecodeSourceInfo source_info) {
    249     source_info_ = source_info;
    250   }
    251 
    252   bool operator==(const BytecodeNode& other) const;
    253   bool operator!=(const BytecodeNode& other) const { return !(*this == other); }
    254 
    255  private:
    256   template <Bytecode bytecode, AccumulatorUse accumulator_use,
    257             OperandType... operand_types>
    258   friend class BytecodeNodeBuilder;
    259 
    260   INLINE(BytecodeNode(Bytecode bytecode, int operand_count,
    261                       OperandScale operand_scale,
    262                       BytecodeSourceInfo source_info, uint32_t operand0 = 0,
    263                       uint32_t operand1 = 0, uint32_t operand2 = 0,
    264                       uint32_t operand3 = 0))
    265       : bytecode_(bytecode),
    266         operand_count_(operand_count),
    267         operand_scale_(operand_scale),
    268         source_info_(source_info) {
    269     DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count);
    270     operands_[0] = operand0;
    271     operands_[1] = operand1;
    272     operands_[2] = operand2;
    273     operands_[3] = operand3;
    274   }
    275 
    276   template <Bytecode bytecode, AccumulatorUse accum_use>
    277   INLINE(static BytecodeNode Create(BytecodeSourceInfo source_info)) {
    278     return BytecodeNode(bytecode, 0, OperandScale::kSingle, source_info);
    279   }
    280 
    281   template <Bytecode bytecode, AccumulatorUse accum_use,
    282             OperandType operand0_type>
    283   INLINE(static BytecodeNode Create(BytecodeSourceInfo source_info,
    284                                     uint32_t operand0)) {
    285     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 0), operand0_type);
    286     OperandScale scale = OperandScale::kSingle;
    287     scale = std::max(scale, ScaleForOperand<operand0_type>(operand0));
    288     return BytecodeNode(bytecode, 1, scale, source_info, operand0);
    289   }
    290 
    291   template <Bytecode bytecode, AccumulatorUse accum_use,
    292             OperandType operand0_type, OperandType operand1_type>
    293   INLINE(static BytecodeNode Create(BytecodeSourceInfo source_info,
    294                                     uint32_t operand0, uint32_t operand1)) {
    295     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 0), operand0_type);
    296     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 1), operand1_type);
    297     OperandScale scale = OperandScale::kSingle;
    298     scale = std::max(scale, ScaleForOperand<operand0_type>(operand0));
    299     scale = std::max(scale, ScaleForOperand<operand1_type>(operand1));
    300     return BytecodeNode(bytecode, 2, scale, source_info, operand0, operand1);
    301   }
    302 
    303   template <Bytecode bytecode, AccumulatorUse accum_use,
    304             OperandType operand0_type, OperandType operand1_type,
    305             OperandType operand2_type>
    306   INLINE(static BytecodeNode Create(BytecodeSourceInfo source_info,
    307                                     uint32_t operand0, uint32_t operand1,
    308                                     uint32_t operand2)) {
    309     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 0), operand0_type);
    310     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 1), operand1_type);
    311     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 2), operand2_type);
    312     OperandScale scale = OperandScale::kSingle;
    313     scale = std::max(scale, ScaleForOperand<operand0_type>(operand0));
    314     scale = std::max(scale, ScaleForOperand<operand1_type>(operand1));
    315     scale = std::max(scale, ScaleForOperand<operand2_type>(operand2));
    316     return BytecodeNode(bytecode, 3, scale, source_info, operand0, operand1,
    317                         operand2);
    318   }
    319 
    320   template <Bytecode bytecode, AccumulatorUse accum_use,
    321             OperandType operand0_type, OperandType operand1_type,
    322             OperandType operand2_type, OperandType operand3_type>
    323   INLINE(static BytecodeNode Create(BytecodeSourceInfo source_info,
    324                                     uint32_t operand0, uint32_t operand1,
    325                                     uint32_t operand2, uint32_t operand3)) {
    326     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 0), operand0_type);
    327     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 1), operand1_type);
    328     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 2), operand2_type);
    329     DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 3), operand3_type);
    330     OperandScale scale = OperandScale::kSingle;
    331     scale = std::max(scale, ScaleForOperand<operand0_type>(operand0));
    332     scale = std::max(scale, ScaleForOperand<operand1_type>(operand1));
    333     scale = std::max(scale, ScaleForOperand<operand2_type>(operand2));
    334     scale = std::max(scale, ScaleForOperand<operand3_type>(operand3));
    335     return BytecodeNode(bytecode, 4, scale, source_info, operand0, operand1,
    336                         operand2, operand3);
    337   }
    338 
    339   template <OperandType operand_type>
    340   INLINE(static OperandScale ScaleForOperand(uint32_t operand)) {
    341     if (BytecodeOperands::IsScalableUnsignedByte(operand_type)) {
    342       return Bytecodes::ScaleForUnsignedOperand(operand);
    343     } else if (BytecodeOperands::IsScalableSignedByte(operand_type)) {
    344       return Bytecodes::ScaleForSignedOperand(operand);
    345     } else {
    346       return OperandScale::kSingle;
    347     }
    348   }
    349 
    350   INLINE(void UpdateScaleForOperand(int operand_index, uint32_t operand)) {
    351     if (Bytecodes::OperandIsScalableSignedByte(bytecode(), operand_index)) {
    352       operand_scale_ =
    353           std::max(operand_scale_, Bytecodes::ScaleForSignedOperand(operand));
    354     } else if (Bytecodes::OperandIsScalableUnsignedByte(bytecode(),
    355                                                         operand_index)) {
    356       operand_scale_ =
    357           std::max(operand_scale_, Bytecodes::ScaleForUnsignedOperand(operand));
    358     }
    359   }
    360 
    361   INLINE(void SetOperand(int operand_index, uint32_t operand)) {
    362     operands_[operand_index] = operand;
    363     UpdateScaleForOperand(operand_index, operand);
    364   }
    365 
    366   Bytecode bytecode_;
    367   uint32_t operands_[Bytecodes::kMaxOperands];
    368   int operand_count_;
    369   OperandScale operand_scale_;
    370   BytecodeSourceInfo source_info_;
    371 };
    372 
    373 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
    374                                            const BytecodeSourceInfo& info);
    375 V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
    376                                            const BytecodeNode& node);
    377 
    378 }  // namespace interpreter
    379 }  // namespace internal
    380 }  // namespace v8
    381 
    382 #endif  // V8_INTERPRETER_BYTECODE_PIPELINE_H_
    383