diff options
Diffstat (limited to 'deps/v8/src/interpreter/bytecode-pipeline.h')
-rw-r--r-- | deps/v8/src/interpreter/bytecode-pipeline.h | 228 |
1 files changed, 228 insertions, 0 deletions
diff --git a/deps/v8/src/interpreter/bytecode-pipeline.h b/deps/v8/src/interpreter/bytecode-pipeline.h new file mode 100644 index 0000000000..1668bab9c1 --- /dev/null +++ b/deps/v8/src/interpreter/bytecode-pipeline.h @@ -0,0 +1,228 @@ +// 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" +#include "src/interpreter/bytecode-register.h" +#include "src/interpreter/bytecodes.h" +#include "src/objects.h" +#include "src/zone-containers.h" + +namespace v8 { +namespace internal { +namespace interpreter { + +class BytecodeLabel; +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; + + // 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; + + // 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( + Isolate* isolate, int fixed_register_count, int parameter_count, + Handle<FixedArray> handler_table) = 0; +}; + +// Source code position information. +class BytecodeSourceInfo final { + public: + static const int kUninitializedPosition = -1; + + 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; + } + + // 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_; + } + + int source_position() const { + DCHECK(is_valid()); + return source_position_; + } + + bool is_statement() const { + return position_type_ == PositionType::kStatement; + } + bool is_expression() const { + return position_type_ == PositionType::kExpression; + } + + bool is_valid() const { return position_type_ != PositionType::kNone; } + void set_invalid() { + position_type_ = PositionType::kNone; + source_position_ = kUninitializedPosition; + } + + bool operator==(const BytecodeSourceInfo& other) const { + return position_type_ == other.position_type_ && + source_position_ == other.source_position_; + } + + bool operator!=(const BytecodeSourceInfo& other) const { + return position_type_ != other.position_type_ || + source_position_ != other.source_position_; + } + + private: + enum class PositionType : uint8_t { kNone, kExpression, kStatement }; + + PositionType position_type_; + int source_position_; + + DISALLOW_COPY_AND_ASSIGN(BytecodeSourceInfo); +}; + +// 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: + 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); + + BytecodeNode(const BytecodeNode& other); + BytecodeNode& operator=(const BytecodeNode& other); + + // 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; + } + 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; + operands_[0] = operand0; + } + void set_bytecode(Bytecode bytecode, uint32_t operand0, uint32_t operand1) { + DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 2); + bytecode_ = bytecode; + operands_[0] = operand0; + operands_[1] = operand1; + } + void set_bytecode(Bytecode bytecode, uint32_t operand0, uint32_t operand1, + uint32_t operand2) { + DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), 3); + bytecode_ = bytecode; + operands_[0] = operand0; + operands_[1] = operand1; + operands_[2] = operand2; + } + + // Clone |other|. + void Clone(const BytecodeNode* const other); + + // Print to stream |os|. + void Print(std::ostream& os) const; + + // Transform to a node representing |new_bytecode| which has one + // operand more than the current bytecode. + void Transform(Bytecode new_bytecode, uint32_t extra_operand); + + Bytecode bytecode() const { return bytecode_; } + + uint32_t operand(int i) const { + DCHECK_LT(i, operand_count()); + return operands_[i]; + } + uint32_t* operands() { return operands_; } + const uint32_t* operands() const { return operands_; } + + int operand_count() const { return Bytecodes::NumberOfOperands(bytecode_); } + + const BytecodeSourceInfo& source_info() const { return source_info_; } + BytecodeSourceInfo& source_info() { return source_info_; } + + bool operator==(const BytecodeNode& other) const; + bool operator!=(const BytecodeNode& other) const { return !(*this == other); } + + private: + static const int kInvalidPosition = kMinInt; + + Bytecode bytecode_; + uint32_t operands_[Bytecodes::kMaxOperands]; + 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_ |