• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
12 namespace v8 {
13 namespace internal {
14 namespace interpreter {
15 
16 class BytecodeLabel;
17 class BytecodeNode;
18 class BytecodeSourceInfo;
19 
20 // Interface for bytecode pipeline stages.
21 class BytecodePipelineStage {
22  public:
~BytecodePipelineStage()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.
53 class BytecodeSourceInfo final {
54  public:
55   static const int kUninitializedPosition = -1;
56 
BytecodeSourceInfo()57   BytecodeSourceInfo()
58       : position_type_(PositionType::kNone),
59         source_position_(kUninitializedPosition) {}
60 
BytecodeSourceInfo(int source_position,bool is_statement)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.
MakeStatementPosition(int source_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.
MakeExpressionPosition(int source_position)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.
ForceExpressionPosition(int source_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.
Clone(const BytecodeSourceInfo & other)96   void Clone(const BytecodeSourceInfo& other) {
97     DCHECK(!is_valid());
98     position_type_ = other.position_type_;
99     source_position_ = other.source_position_;
100   }
101 
source_position()102   int source_position() const {
103     DCHECK(is_valid());
104     return source_position_;
105   }
106 
is_statement()107   bool is_statement() const {
108     return position_type_ == PositionType::kStatement;
109   }
is_expression()110   bool is_expression() const {
111     return position_type_ == PositionType::kExpression;
112   }
113 
is_valid()114   bool is_valid() const { return position_type_ != PositionType::kNone; }
set_invalid()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.
141 class 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 
bytecode()167   Bytecode bytecode() const { return bytecode_; }
168 
operand(int i)169   uint32_t operand(int i) const {
170     DCHECK_LT(i, operand_count());
171     return operands_[i];
172   }
operands()173   uint32_t* operands() { return operands_; }
operands()174   const uint32_t* operands() const { return operands_; }
175 
operand_count()176   int operand_count() const { return Bytecodes::NumberOfOperands(bytecode_); }
177 
source_info()178   const BytecodeSourceInfo& source_info() const { return source_info_; }
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 
193 std::ostream& operator<<(std::ostream& os, const BytecodeSourceInfo& info);
194 std::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