// Copyright 2017 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_NODE_H_
|
#define V8_INTERPRETER_BYTECODE_NODE_H_
|
|
#include <algorithm>
|
|
#include "src/globals.h"
|
#include "src/interpreter/bytecode-source-info.h"
|
#include "src/interpreter/bytecodes.h"
|
|
namespace v8 {
|
namespace internal {
|
namespace interpreter {
|
|
// A container for a generated bytecode, it's operands, and source information.
|
class V8_EXPORT_PRIVATE BytecodeNode final {
|
public:
|
V8_INLINE BytecodeNode(Bytecode bytecode,
|
BytecodeSourceInfo source_info = BytecodeSourceInfo())
|
: bytecode_(bytecode),
|
operand_count_(0),
|
operand_scale_(OperandScale::kSingle),
|
source_info_(source_info) {
|
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count());
|
}
|
|
V8_INLINE BytecodeNode(Bytecode bytecode, uint32_t operand0,
|
BytecodeSourceInfo source_info = BytecodeSourceInfo())
|
: bytecode_(bytecode),
|
operand_count_(1),
|
operand_scale_(OperandScale::kSingle),
|
source_info_(source_info) {
|
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count());
|
SetOperand(0, operand0);
|
}
|
|
V8_INLINE BytecodeNode(Bytecode bytecode, uint32_t operand0,
|
uint32_t operand1,
|
BytecodeSourceInfo source_info = BytecodeSourceInfo())
|
: bytecode_(bytecode),
|
operand_count_(2),
|
operand_scale_(OperandScale::kSingle),
|
source_info_(source_info) {
|
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count());
|
SetOperand(0, operand0);
|
SetOperand(1, operand1);
|
}
|
|
V8_INLINE BytecodeNode(Bytecode bytecode, uint32_t operand0,
|
uint32_t operand1, uint32_t operand2,
|
BytecodeSourceInfo source_info = BytecodeSourceInfo())
|
: bytecode_(bytecode),
|
operand_count_(3),
|
operand_scale_(OperandScale::kSingle),
|
source_info_(source_info) {
|
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count());
|
SetOperand(0, operand0);
|
SetOperand(1, operand1);
|
SetOperand(2, operand2);
|
}
|
|
V8_INLINE BytecodeNode(Bytecode bytecode, uint32_t operand0,
|
uint32_t operand1, uint32_t operand2,
|
uint32_t operand3,
|
BytecodeSourceInfo source_info = BytecodeSourceInfo())
|
: bytecode_(bytecode),
|
operand_count_(4),
|
operand_scale_(OperandScale::kSingle),
|
source_info_(source_info) {
|
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count());
|
SetOperand(0, operand0);
|
SetOperand(1, operand1);
|
SetOperand(2, operand2);
|
SetOperand(3, operand3);
|
}
|
|
V8_INLINE BytecodeNode(Bytecode bytecode, uint32_t operand0,
|
uint32_t operand1, uint32_t operand2,
|
uint32_t operand3, uint32_t operand4,
|
BytecodeSourceInfo source_info = BytecodeSourceInfo())
|
: bytecode_(bytecode),
|
operand_count_(5),
|
operand_scale_(OperandScale::kSingle),
|
source_info_(source_info) {
|
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count());
|
SetOperand(0, operand0);
|
SetOperand(1, operand1);
|
SetOperand(2, operand2);
|
SetOperand(3, operand3);
|
SetOperand(4, operand4);
|
}
|
|
#define DEFINE_BYTECODE_NODE_CREATOR(Name, ...) \
|
template <typename... Operands> \
|
V8_INLINE static BytecodeNode Name(BytecodeSourceInfo source_info, \
|
Operands... operands) { \
|
return Create<Bytecode::k##Name, __VA_ARGS__>(source_info, operands...); \
|
}
|
BYTECODE_LIST(DEFINE_BYTECODE_NODE_CREATOR)
|
#undef DEFINE_BYTECODE_NODE_CREATOR
|
|
// Print to stream |os|.
|
void Print(std::ostream& os) const;
|
|
Bytecode bytecode() const { return bytecode_; }
|
|
uint32_t operand(int i) const {
|
DCHECK_LT(i, operand_count());
|
return operands_[i];
|
}
|
const uint32_t* operands() const { return operands_; }
|
|
void update_operand0(uint32_t operand0) { SetOperand(0, operand0); }
|
|
int operand_count() const { return operand_count_; }
|
OperandScale operand_scale() const { return operand_scale_; }
|
|
const BytecodeSourceInfo& source_info() const { return source_info_; }
|
void set_source_info(BytecodeSourceInfo source_info) {
|
source_info_ = source_info;
|
}
|
|
bool operator==(const BytecodeNode& other) const;
|
bool operator!=(const BytecodeNode& other) const { return !(*this == other); }
|
|
private:
|
template <Bytecode bytecode, AccumulatorUse accumulator_use,
|
OperandType... operand_types>
|
friend class BytecodeNodeBuilder;
|
|
V8_INLINE BytecodeNode(Bytecode bytecode, int operand_count,
|
OperandScale operand_scale,
|
BytecodeSourceInfo source_info, uint32_t operand0 = 0,
|
uint32_t operand1 = 0, uint32_t operand2 = 0,
|
uint32_t operand3 = 0, uint32_t operand4 = 0)
|
: bytecode_(bytecode),
|
operand_count_(operand_count),
|
operand_scale_(operand_scale),
|
source_info_(source_info) {
|
DCHECK_EQ(Bytecodes::NumberOfOperands(bytecode), operand_count);
|
operands_[0] = operand0;
|
operands_[1] = operand1;
|
operands_[2] = operand2;
|
operands_[3] = operand3;
|
operands_[4] = operand4;
|
}
|
|
template <Bytecode bytecode, AccumulatorUse accum_use>
|
V8_INLINE static BytecodeNode Create(BytecodeSourceInfo source_info) {
|
return BytecodeNode(bytecode, 0, OperandScale::kSingle, source_info);
|
}
|
|
template <Bytecode bytecode, AccumulatorUse accum_use,
|
OperandType operand0_type>
|
V8_INLINE static BytecodeNode Create(BytecodeSourceInfo source_info,
|
uint32_t operand0) {
|
DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 0), operand0_type);
|
OperandScale scale = OperandScale::kSingle;
|
scale = std::max(scale, ScaleForOperand<operand0_type>(operand0));
|
return BytecodeNode(bytecode, 1, scale, source_info, operand0);
|
}
|
|
template <Bytecode bytecode, AccumulatorUse accum_use,
|
OperandType operand0_type, OperandType operand1_type>
|
V8_INLINE static BytecodeNode Create(BytecodeSourceInfo source_info,
|
uint32_t operand0, uint32_t operand1) {
|
DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 0), operand0_type);
|
DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 1), operand1_type);
|
OperandScale scale = OperandScale::kSingle;
|
scale = std::max(scale, ScaleForOperand<operand0_type>(operand0));
|
scale = std::max(scale, ScaleForOperand<operand1_type>(operand1));
|
return BytecodeNode(bytecode, 2, scale, source_info, operand0, operand1);
|
}
|
|
template <Bytecode bytecode, AccumulatorUse accum_use,
|
OperandType operand0_type, OperandType operand1_type,
|
OperandType operand2_type>
|
V8_INLINE static BytecodeNode Create(BytecodeSourceInfo source_info,
|
uint32_t operand0, uint32_t operand1,
|
uint32_t operand2) {
|
DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 0), operand0_type);
|
DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 1), operand1_type);
|
DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 2), operand2_type);
|
OperandScale scale = OperandScale::kSingle;
|
scale = std::max(scale, ScaleForOperand<operand0_type>(operand0));
|
scale = std::max(scale, ScaleForOperand<operand1_type>(operand1));
|
scale = std::max(scale, ScaleForOperand<operand2_type>(operand2));
|
return BytecodeNode(bytecode, 3, scale, source_info, operand0, operand1,
|
operand2);
|
}
|
|
template <Bytecode bytecode, AccumulatorUse accum_use,
|
OperandType operand0_type, OperandType operand1_type,
|
OperandType operand2_type, OperandType operand3_type>
|
V8_INLINE static BytecodeNode Create(BytecodeSourceInfo source_info,
|
uint32_t operand0, uint32_t operand1,
|
uint32_t operand2, uint32_t operand3) {
|
DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 0), operand0_type);
|
DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 1), operand1_type);
|
DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 2), operand2_type);
|
DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 3), operand3_type);
|
OperandScale scale = OperandScale::kSingle;
|
scale = std::max(scale, ScaleForOperand<operand0_type>(operand0));
|
scale = std::max(scale, ScaleForOperand<operand1_type>(operand1));
|
scale = std::max(scale, ScaleForOperand<operand2_type>(operand2));
|
scale = std::max(scale, ScaleForOperand<operand3_type>(operand3));
|
return BytecodeNode(bytecode, 4, scale, source_info, operand0, operand1,
|
operand2, operand3);
|
}
|
|
template <Bytecode bytecode, AccumulatorUse accum_use,
|
OperandType operand0_type, OperandType operand1_type,
|
OperandType operand2_type, OperandType operand3_type,
|
OperandType operand4_type>
|
V8_INLINE static BytecodeNode Create(BytecodeSourceInfo source_info,
|
uint32_t operand0, uint32_t operand1,
|
uint32_t operand2, uint32_t operand3,
|
uint32_t operand4) {
|
DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 0), operand0_type);
|
DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 1), operand1_type);
|
DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 2), operand2_type);
|
DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 3), operand3_type);
|
DCHECK_EQ(Bytecodes::GetOperandType(bytecode, 4), operand4_type);
|
OperandScale scale = OperandScale::kSingle;
|
scale = std::max(scale, ScaleForOperand<operand0_type>(operand0));
|
scale = std::max(scale, ScaleForOperand<operand1_type>(operand1));
|
scale = std::max(scale, ScaleForOperand<operand2_type>(operand2));
|
scale = std::max(scale, ScaleForOperand<operand3_type>(operand3));
|
scale = std::max(scale, ScaleForOperand<operand4_type>(operand4));
|
return BytecodeNode(bytecode, 5, scale, source_info, operand0, operand1,
|
operand2, operand3, operand4);
|
}
|
|
template <OperandType operand_type>
|
V8_INLINE static OperandScale ScaleForOperand(uint32_t operand) {
|
if (BytecodeOperands::IsScalableUnsignedByte(operand_type)) {
|
return Bytecodes::ScaleForUnsignedOperand(operand);
|
} else if (BytecodeOperands::IsScalableSignedByte(operand_type)) {
|
return Bytecodes::ScaleForSignedOperand(operand);
|
} else {
|
return OperandScale::kSingle;
|
}
|
}
|
|
V8_INLINE void UpdateScaleForOperand(int operand_index, uint32_t operand) {
|
if (Bytecodes::OperandIsScalableSignedByte(bytecode(), operand_index)) {
|
operand_scale_ =
|
std::max(operand_scale_, Bytecodes::ScaleForSignedOperand(operand));
|
} else if (Bytecodes::OperandIsScalableUnsignedByte(bytecode(),
|
operand_index)) {
|
operand_scale_ =
|
std::max(operand_scale_, Bytecodes::ScaleForUnsignedOperand(operand));
|
}
|
}
|
|
V8_INLINE void SetOperand(int operand_index, uint32_t operand) {
|
operands_[operand_index] = operand;
|
UpdateScaleForOperand(operand_index, operand);
|
}
|
|
Bytecode bytecode_;
|
uint32_t operands_[Bytecodes::kMaxOperands];
|
int operand_count_;
|
OperandScale operand_scale_;
|
BytecodeSourceInfo source_info_;
|
};
|
|
V8_EXPORT_PRIVATE std::ostream& operator<<(std::ostream& os,
|
const BytecodeNode& node);
|
|
} // namespace interpreter
|
} // namespace internal
|
} // namespace v8
|
|
#endif // V8_INTERPRETER_BYTECODE_NODE_H_
|