bytecode-pipeline.h 7.75 KB
Newer Older
1 2 3 4 5 6 7 8
// Copyright 2015 the V8 project authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#ifndef V8_INTERPRETER_BYTECODE_PIPELINE_H_
#define V8_INTERPRETER_BYTECODE_PIPELINE_H_

#include "src/interpreter/bytecode-register-allocator.h"
9
#include "src/interpreter/bytecode-register.h"
10
#include "src/interpreter/bytecodes.h"
11
#include "src/objects.h"
12
#include "src/zone/zone-containers.h"
13 14 15 16 17

namespace v8 {
namespace internal {
namespace interpreter {

18
class BytecodeLabel;
19 20 21 22 23 24 25 26 27 28 29 30 31
class BytecodeNode;
class BytecodeSourceInfo;

// Interface for bytecode pipeline stages.
class BytecodePipelineStage {
 public:
  virtual ~BytecodePipelineStage() {}

  // Write bytecode node |node| into pipeline. The node is only valid
  // for the duration of the call. Callee's should clone it if
  // deferring Write() to the next stage.
  virtual void Write(BytecodeNode* node) = 0;

32 33 34 35 36
  // Write jump bytecode node |node| which jumps to |label| into pipeline.
  // The node and label are only valid for the duration of the call. This call
  // implicitly ends the current basic block so should always write to the next
  // stage.
  virtual void WriteJump(BytecodeNode* node, BytecodeLabel* label) = 0;
37

38 39 40 41 42 43 44 45 46 47 48 49
  // Binds |label| to the current bytecode location. This call implicitly
  // ends the current basic block and so any deferred bytecodes should be
  // written to the next stage.
  virtual void BindLabel(BytecodeLabel* label) = 0;

  // Binds |label| to the location of |target|. This call implicitly
  // ends the current basic block and so any deferred bytecodes should be
  // written to the next stage.
  virtual void BindLabel(const BytecodeLabel& target, BytecodeLabel* label) = 0;

  // Flush the pipeline and generate a bytecode array.
  virtual Handle<BytecodeArray> ToBytecodeArray(
50
      Isolate* isolate, int fixed_register_count, int parameter_count,
51
      Handle<FixedArray> handler_table) = 0;
52 53 54 55 56 57 58
};

// Source code position information.
class BytecodeSourceInfo final {
 public:
  static const int kUninitializedPosition = -1;

59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
  BytecodeSourceInfo()
      : position_type_(PositionType::kNone),
        source_position_(kUninitializedPosition) {}

  BytecodeSourceInfo(int source_position, bool is_statement)
      : position_type_(is_statement ? PositionType::kStatement
                                    : PositionType::kExpression),
        source_position_(source_position) {
    DCHECK_GE(source_position, 0);
  }

  // Makes instance into a statement position.
  void MakeStatementPosition(int source_position) {
    // Statement positions can be replaced by other statement
    // positions. For example , "for (x = 0; x < 3; ++x) 7;" has a
    // statement position associated with 7 but no bytecode associated
    // with it. Then Next is emitted after the body and has
    // statement position and overrides the existing one.
    position_type_ = PositionType::kStatement;
    source_position_ = source_position;
  }

  // Makes instance into an expression position. Instance should not
  // be a statement position otherwise it could be lost and impair the
  // debugging experience.
  void MakeExpressionPosition(int source_position) {
    DCHECK(!is_statement());
    position_type_ = PositionType::kExpression;
    source_position_ = source_position;
  }

  // Forces an instance into an expression position.
  void ForceExpressionPosition(int source_position) {
    position_type_ = PositionType::kExpression;
    source_position_ = source_position;
  }
95

96 97 98 99 100 101 102
  // Clones a source position. The current instance is expected to be
  // invalid.
  void Clone(const BytecodeSourceInfo& other) {
    DCHECK(!is_valid());
    position_type_ = other.position_type_;
    source_position_ = other.source_position_;
  }
103 104 105 106 107 108

  int source_position() const {
    DCHECK(is_valid());
    return source_position_;
  }

109 110 111 112 113 114
  bool is_statement() const {
    return position_type_ == PositionType::kStatement;
  }
  bool is_expression() const {
    return position_type_ == PositionType::kExpression;
  }
115

116 117 118 119 120
  bool is_valid() const { return position_type_ != PositionType::kNone; }
  void set_invalid() {
    position_type_ = PositionType::kNone;
    source_position_ = kUninitializedPosition;
  }
121 122

  bool operator==(const BytecodeSourceInfo& other) const {
123 124
    return position_type_ == other.position_type_ &&
           source_position_ == other.source_position_;
125
  }
126

127
  bool operator!=(const BytecodeSourceInfo& other) const {
128 129
    return position_type_ != other.position_type_ ||
           source_position_ != other.source_position_;
130 131 132
  }

 private:
133 134 135
  enum class PositionType : uint8_t { kNone, kExpression, kStatement };

  PositionType position_type_;
136
  int source_position_;
137 138

  DISALLOW_COPY_AND_ASSIGN(BytecodeSourceInfo);
139 140 141 142 143 144
};

// A container for a generated bytecode, it's operands, and source information.
// These must be allocated by a BytecodeNodeAllocator instance.
class BytecodeNode final : ZoneObject {
 public:
145 146 147 148 149 150 151
  explicit BytecodeNode(Bytecode bytecode = Bytecode::kIllegal);
  BytecodeNode(Bytecode bytecode, uint32_t operand0);
  BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1);
  BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
               uint32_t operand2);
  BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
               uint32_t operand2, uint32_t operand3);
152

153 154 155
  BytecodeNode(const BytecodeNode& other);
  BytecodeNode& operator=(const BytecodeNode& other);

156 157 158 159 160 161
  // Replace the bytecode of this node with |bytecode| and keep the operands.
  void replace_bytecode(Bytecode bytecode) {
    DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode_),
              Bytecodes::NumberOfOperands(bytecode));
    bytecode_ = bytecode;
  }
162 163 164 165 166 167 168
  void set_bytecode(Bytecode bytecode) {
    DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 0);
    bytecode_ = bytecode;
  }
  void set_bytecode(Bytecode bytecode, uint32_t operand0) {
    DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 1);
    bytecode_ = bytecode;
169
    operands_[0] = operand0;
170 171 172 173
  }
  void set_bytecode(Bytecode bytecode, uint32_t operand0, uint32_t operand1) {
    DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 2);
    bytecode_ = bytecode;
174 175
    operands_[0] = operand0;
    operands_[1] = operand1;
176
  }
177 178 179 180
  void set_bytecode(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
                    uint32_t operand2) {
    DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 3);
    bytecode_ = bytecode;
181 182 183
    operands_[0] = operand0;
    operands_[1] = operand1;
    operands_[2] = operand2;
184
  }
185 186 187 188 189 190 191

  // Clone |other|.
  void Clone(const BytecodeNode* const other);

  // Print to stream |os|.
  void Print(std::ostream& os) const;

192 193
  // Transform to a node representing |new_bytecode| which has one
  // operand more than the current bytecode.
194
  void Transform(Bytecode new_bytecode, uint32_t extra_operand);
195

196 197 198 199 200 201
  Bytecode bytecode() const { return bytecode_; }

  uint32_t operand(int i) const {
    DCHECK_LT(i, operand_count());
    return operands_[i];
  }
202
  uint32_t* operands() { return operands_; }
203 204
  const uint32_t* operands() const { return operands_; }

205
  int operand_count() const { return Bytecodes::NumberOfOperands(bytecode_); }
206 207

  const BytecodeSourceInfo& source_info() const { return source_info_; }
208
  BytecodeSourceInfo& source_info() { return source_info_; }
209 210 211 212 213

  bool operator==(const BytecodeNode& other) const;
  bool operator!=(const BytecodeNode& other) const { return !(*this == other); }

 private:
214
  static const int kInvalidPosition = kMinInt;
215 216

  Bytecode bytecode_;
217
  uint32_t operands_[Bytecodes::kMaxOperands];
218 219 220 221 222 223 224 225 226 227 228
  BytecodeSourceInfo source_info_;
};

std::ostream& operator<<(std::ostream& os, const BytecodeSourceInfo& info);
std::ostream& operator<<(std::ostream& os, const BytecodeNode& node);

}  // namespace interpreter
}  // namespace internal
}  // namespace v8

#endif  // V8_INTERPRETER_BYTECODE_PIPELINE_H_