blob: e2beff2c8e3ca94e19172c033248e8e0e6743ee4 [file] [log] [blame]
Ben Murdochc5610432016-08-08 18:44:38 +01001// 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
Ben Murdoch61f157c2016-09-16 13:49:30 +010016class BytecodeLabel;
Ben Murdochc5610432016-08-08 18:44:38 +010017class 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
Ben Murdoch61f157c2016-09-16 13:49:30 +010030 // 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;
Ben Murdochc5610432016-08-08 18:44:38 +010035
Ben Murdoch61f157c2016-09-16 13:49:30 +010036 // 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;
Ben Murdochc5610432016-08-08 18:44:38 +010050};
51
52// Source code position information.
53class BytecodeSourceInfo final {
54 public:
55 static const int kUninitializedPosition = -1;
56
Ben Murdoch61f157c2016-09-16 13:49:30 +010057 BytecodeSourceInfo()
58 : position_type_(PositionType::kNone),
59 source_position_(kUninitializedPosition) {}
Ben Murdochc5610432016-08-08 18:44:38 +010060
Ben Murdoch61f157c2016-09-16 13:49:30 +010061 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 }
Ben Murdochc5610432016-08-08 18:44:38 +0100101
102 int source_position() const {
103 DCHECK(is_valid());
104 return source_position_;
105 }
106
Ben Murdoch61f157c2016-09-16 13:49:30 +0100107 bool is_statement() const {
108 return position_type_ == PositionType::kStatement;
109 }
110 bool is_expression() const {
111 return position_type_ == PositionType::kExpression;
112 }
Ben Murdochc5610432016-08-08 18:44:38 +0100113
Ben Murdoch61f157c2016-09-16 13:49:30 +0100114 bool is_valid() const { return position_type_ != PositionType::kNone; }
115 void set_invalid() {
116 position_type_ = PositionType::kNone;
117 source_position_ = kUninitializedPosition;
118 }
Ben Murdochc5610432016-08-08 18:44:38 +0100119
120 bool operator==(const BytecodeSourceInfo& other) const {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100121 return position_type_ == other.position_type_ &&
122 source_position_ == other.source_position_;
Ben Murdochc5610432016-08-08 18:44:38 +0100123 }
Ben Murdoch61f157c2016-09-16 13:49:30 +0100124
Ben Murdochc5610432016-08-08 18:44:38 +0100125 bool operator!=(const BytecodeSourceInfo& other) const {
Ben Murdoch61f157c2016-09-16 13:49:30 +0100126 return position_type_ != other.position_type_ ||
127 source_position_ != other.source_position_;
Ben Murdochc5610432016-08-08 18:44:38 +0100128 }
129
130 private:
Ben Murdoch61f157c2016-09-16 13:49:30 +0100131 enum class PositionType : uint8_t { kNone, kExpression, kStatement };
132
133 PositionType position_type_;
Ben Murdochc5610432016-08-08 18:44:38 +0100134 int source_position_;
Ben Murdochc5610432016-08-08 18:44:38 +0100135
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);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100144 BytecodeNode(Bytecode bytecode, uint32_t operand0);
145 BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1);
Ben Murdochc5610432016-08-08 18:44:38 +0100146 BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100147 uint32_t operand2);
Ben Murdochc5610432016-08-08 18:44:38 +0100148 BytecodeNode(Bytecode bytecode, uint32_t operand0, uint32_t operand1,
Ben Murdoch61f157c2016-09-16 13:49:30 +0100149 uint32_t operand2, uint32_t operand3);
150
151 BytecodeNode(const BytecodeNode& other);
152 BytecodeNode& operator=(const BytecodeNode& other);
Ben Murdochc5610432016-08-08 18:44:38 +0100153
154 void set_bytecode(Bytecode bytecode);
Ben Murdoch61f157c2016-09-16 13:49:30 +0100155 void set_bytecode(Bytecode bytecode, uint32_t operand0);
Ben Murdochc5610432016-08-08 18:44:38 +0100156
157 // Clone |other|.
158 void Clone(const BytecodeNode* const other);
159
160 // Print to stream |os|.
161 void Print(std::ostream& os) const;
162
Ben Murdoch61f157c2016-09-16 13:49:30 +0100163 // 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);
Ben Murdochc5610432016-08-08 18:44:38 +0100166
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_); }
Ben Murdochc5610432016-08-08 18:44:38 +0100177
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];
Ben Murdochc5610432016-08-08 18:44:38 +0100190 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_