Index: src/interpreter/bytecodes.cc |
diff --git a/src/interpreter/bytecodes.cc b/src/interpreter/bytecodes.cc |
index 8b78ee2e4929036f0acd5e54af2e27e9654d88eb..c58f4685a2d3d03bf344ea350366be359ba8c148 100644 |
--- a/src/interpreter/bytecodes.cc |
+++ b/src/interpreter/bytecodes.cc |
@@ -7,14 +7,55 @@ |
#include <iomanip> |
#include "src/base/bits.h" |
-#include "src/globals.h" |
#include "src/interpreter/bytecode-traits.h" |
namespace v8 { |
namespace internal { |
namespace interpreter { |
-STATIC_CONST_MEMBER_DEFINITION const int Bytecodes::kMaxOperands; |
+// clang-format off |
+const OperandType* const Bytecodes::kOperandTypes[] = { |
+#define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandTypes, |
+ BYTECODE_LIST(ENTRY) |
+#undef ENTRY |
+}; |
+ |
+const OperandTypeInfo* const Bytecodes::kOperandTypeInfos[] = { |
+#define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandTypeInfos, |
+ BYTECODE_LIST(ENTRY) |
+#undef ENTRY |
+}; |
+ |
+const int Bytecodes::kOperandCount[] = { |
+#define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kOperandCount, |
+ BYTECODE_LIST(ENTRY) |
+#undef ENTRY |
+}; |
+ |
+const AccumulatorUse Bytecodes::kAccumulatorUse[] = { |
+#define ENTRY(Name, ...) BytecodeTraits<__VA_ARGS__>::kAccumulatorUse, |
+ BYTECODE_LIST(ENTRY) |
+#undef ENTRY |
+}; |
+ |
+const int Bytecodes::kBytecodeSizes[][3] = { |
+#define ENTRY(Name, ...) \ |
+ { BytecodeTraits<__VA_ARGS__>::kSingleScaleSize, \ |
+ BytecodeTraits<__VA_ARGS__>::kDoubleScaleSize, \ |
+ BytecodeTraits<__VA_ARGS__>::kQuadrupleScaleSize }, |
+ BYTECODE_LIST(ENTRY) |
+#undef ENTRY |
+}; |
+ |
+const OperandSize* const Bytecodes::kOperandSizes[][3] = { |
+#define ENTRY(Name, ...) \ |
+ { BytecodeTraits<__VA_ARGS__>::kSingleScaleOperandSizes, \ |
+ BytecodeTraits<__VA_ARGS__>::kDoubleScaleOperandSizes, \ |
+ BytecodeTraits<__VA_ARGS__>::kQuadrupleScaleOperandSizes }, |
+ BYTECODE_LIST(ENTRY) |
+#undef ENTRY |
+}; |
+// clang-format on |
// static |
const char* Bytecodes::ToString(Bytecode bytecode) { |
@@ -44,77 +85,6 @@ std::string Bytecodes::ToString(Bytecode bytecode, OperandScale operand_scale) { |
} |
// static |
-const char* Bytecodes::AccumulatorUseToString(AccumulatorUse accumulator_use) { |
- switch (accumulator_use) { |
- case AccumulatorUse::kNone: |
- return "None"; |
- case AccumulatorUse::kRead: |
- return "Read"; |
- case AccumulatorUse::kWrite: |
- return "Write"; |
- case AccumulatorUse::kReadWrite: |
- return "ReadWrite"; |
- } |
- UNREACHABLE(); |
- return ""; |
-} |
- |
-// static |
-const char* Bytecodes::OperandTypeToString(OperandType operand_type) { |
- switch (operand_type) { |
-#define CASE(Name, _) \ |
- case OperandType::k##Name: \ |
- return #Name; |
- OPERAND_TYPE_LIST(CASE) |
-#undef CASE |
- } |
- UNREACHABLE(); |
- return ""; |
-} |
- |
-// static |
-const char* Bytecodes::OperandScaleToString(OperandScale operand_scale) { |
- switch (operand_scale) { |
-#define CASE(Name, _) \ |
- case OperandScale::k##Name: \ |
- return #Name; |
- OPERAND_SCALE_LIST(CASE) |
-#undef CASE |
- } |
- UNREACHABLE(); |
- return ""; |
-} |
- |
-// static |
-const char* Bytecodes::OperandSizeToString(OperandSize operand_size) { |
- switch (operand_size) { |
- case OperandSize::kNone: |
- return "None"; |
- case OperandSize::kByte: |
- return "Byte"; |
- case OperandSize::kShort: |
- return "Short"; |
- case OperandSize::kQuad: |
- return "Quad"; |
- } |
- UNREACHABLE(); |
- return ""; |
-} |
- |
-// static |
-uint8_t Bytecodes::ToByte(Bytecode bytecode) { |
- DCHECK_LE(bytecode, Bytecode::kLast); |
- return static_cast<uint8_t>(bytecode); |
-} |
- |
-// static |
-Bytecode Bytecodes::FromByte(uint8_t value) { |
- Bytecode bytecode = static_cast<Bytecode>(value); |
- DCHECK(bytecode <= Bytecode::kLast); |
- return bytecode; |
-} |
- |
-// static |
Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) { |
DCHECK(!IsDebugBreak(bytecode)); |
if (bytecode == Bytecode::kWide) { |
@@ -124,7 +94,7 @@ Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) { |
return Bytecode::kDebugBreakExtraWide; |
} |
int bytecode_size = Size(bytecode, OperandScale::kSingle); |
-#define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name, ...) \ |
+#define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name) \ |
if (bytecode_size == Size(Bytecode::k##Name, OperandScale::kSingle)) { \ |
return Bytecode::k##Name; \ |
} |
@@ -135,224 +105,6 @@ Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) { |
} |
// static |
-int Bytecodes::Size(Bytecode bytecode, OperandScale operand_scale) { |
- int size = 1; |
- for (int i = 0; i < NumberOfOperands(bytecode); i++) { |
- OperandSize operand_size = GetOperandSize(bytecode, i, operand_scale); |
- int delta = static_cast<int>(operand_size); |
- DCHECK(base::bits::IsPowerOfTwo32(static_cast<uint32_t>(delta))); |
- size += delta; |
- } |
- return size; |
-} |
- |
-// static |
-size_t Bytecodes::ReturnCount(Bytecode bytecode) { |
- return bytecode == Bytecode::kReturn ? 1 : 0; |
-} |
- |
-// static |
-int Bytecodes::NumberOfOperands(Bytecode bytecode) { |
- DCHECK(bytecode <= Bytecode::kLast); |
- switch (bytecode) { |
-#define CASE(Name, ...) \ |
- case Bytecode::k##Name: \ |
- return BytecodeTraits<__VA_ARGS__>::kOperandCount; |
- BYTECODE_LIST(CASE) |
-#undef CASE |
- } |
- UNREACHABLE(); |
- return 0; |
-} |
- |
-// static |
-int Bytecodes::NumberOfRegisterOperands(Bytecode bytecode) { |
- DCHECK(bytecode <= Bytecode::kLast); |
- switch (bytecode) { |
-#define CASE(Name, ...) \ |
- case Bytecode::k##Name: \ |
- typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \ |
- return Name##Trait::kRegisterOperandCount; |
- BYTECODE_LIST(CASE) |
-#undef CASE |
- } |
- UNREACHABLE(); |
- return false; |
-} |
- |
-// static |
-Bytecode Bytecodes::OperandScaleToPrefixBytecode(OperandScale operand_scale) { |
- switch (operand_scale) { |
- case OperandScale::kQuadruple: |
- return Bytecode::kExtraWide; |
- case OperandScale::kDouble: |
- return Bytecode::kWide; |
- default: |
- UNREACHABLE(); |
- return Bytecode::kIllegal; |
- } |
-} |
- |
-// static |
-bool Bytecodes::OperandScaleRequiresPrefixBytecode(OperandScale operand_scale) { |
- return operand_scale != OperandScale::kSingle; |
-} |
- |
-// static |
-OperandScale Bytecodes::PrefixBytecodeToOperandScale(Bytecode bytecode) { |
- switch (bytecode) { |
- case Bytecode::kExtraWide: |
- case Bytecode::kDebugBreakExtraWide: |
- return OperandScale::kQuadruple; |
- case Bytecode::kWide: |
- case Bytecode::kDebugBreakWide: |
- return OperandScale::kDouble; |
- default: |
- UNREACHABLE(); |
- return OperandScale::kSingle; |
- } |
-} |
- |
-// static |
-AccumulatorUse Bytecodes::GetAccumulatorUse(Bytecode bytecode) { |
- DCHECK(bytecode <= Bytecode::kLast); |
- switch (bytecode) { |
-#define CASE(Name, ...) \ |
- case Bytecode::k##Name: \ |
- return BytecodeTraits<__VA_ARGS__>::kAccumulatorUse; |
- BYTECODE_LIST(CASE) |
-#undef CASE |
- } |
- UNREACHABLE(); |
- return AccumulatorUse::kNone; |
-} |
- |
-// static |
-bool Bytecodes::ReadsAccumulator(Bytecode bytecode) { |
- return (GetAccumulatorUse(bytecode) & AccumulatorUse::kRead) == |
- AccumulatorUse::kRead; |
-} |
- |
-// static |
-bool Bytecodes::WritesAccumulator(Bytecode bytecode) { |
- return (GetAccumulatorUse(bytecode) & AccumulatorUse::kWrite) == |
- AccumulatorUse::kWrite; |
-} |
- |
-// static |
-bool Bytecodes::WritesBooleanToAccumulator(Bytecode bytecode) { |
- switch (bytecode) { |
- case Bytecode::kLdaTrue: |
- case Bytecode::kLdaFalse: |
- case Bytecode::kToBooleanLogicalNot: |
- case Bytecode::kLogicalNot: |
- case Bytecode::kTestEqual: |
- case Bytecode::kTestNotEqual: |
- case Bytecode::kTestEqualStrict: |
- case Bytecode::kTestLessThan: |
- case Bytecode::kTestLessThanOrEqual: |
- case Bytecode::kTestGreaterThan: |
- case Bytecode::kTestGreaterThanOrEqual: |
- case Bytecode::kTestInstanceOf: |
- case Bytecode::kTestIn: |
- case Bytecode::kForInContinue: |
- return true; |
- default: |
- return false; |
- } |
-} |
- |
-// static |
-bool Bytecodes::IsAccumulatorLoadWithoutEffects(Bytecode bytecode) { |
- switch (bytecode) { |
- case Bytecode::kLdaZero: |
- case Bytecode::kLdaSmi: |
- case Bytecode::kLdaUndefined: |
- case Bytecode::kLdaNull: |
- case Bytecode::kLdaTheHole: |
- case Bytecode::kLdaTrue: |
- case Bytecode::kLdaFalse: |
- case Bytecode::kLdaConstant: |
- case Bytecode::kLdar: |
- return true; |
- default: |
- return false; |
- } |
-} |
- |
-// static |
-bool Bytecodes::IsJumpWithoutEffects(Bytecode bytecode) { |
- return IsJump(bytecode) && !IsJumpIfToBoolean(bytecode); |
-} |
- |
-// static |
-bool Bytecodes::IsRegisterLoadWithoutEffects(Bytecode bytecode) { |
- switch (bytecode) { |
- case Bytecode::kMov: |
- case Bytecode::kPopContext: |
- case Bytecode::kPushContext: |
- case Bytecode::kStar: |
- case Bytecode::kLdrUndefined: |
- return true; |
- default: |
- return false; |
- } |
-} |
- |
-// static |
-bool Bytecodes::IsWithoutExternalSideEffects(Bytecode bytecode) { |
- // These bytecodes only manipulate interpreter frame state and will |
- // never throw. |
- return (IsAccumulatorLoadWithoutEffects(bytecode) || |
- IsRegisterLoadWithoutEffects(bytecode) || |
- bytecode == Bytecode::kNop || IsJumpWithoutEffects(bytecode)); |
-} |
- |
-// static |
-OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) { |
- DCHECK_LE(bytecode, Bytecode::kLast); |
- DCHECK_LT(i, NumberOfOperands(bytecode)); |
- DCHECK_GE(i, 0); |
- return GetOperandTypes(bytecode)[i]; |
-} |
- |
-// static |
-const OperandType* Bytecodes::GetOperandTypes(Bytecode bytecode) { |
- DCHECK_LE(bytecode, Bytecode::kLast); |
- switch (bytecode) { |
-#define CASE(Name, ...) \ |
- case Bytecode::k##Name: \ |
- return BytecodeTraits<__VA_ARGS__>::GetOperandTypes(); |
- BYTECODE_LIST(CASE) |
-#undef CASE |
- } |
- UNREACHABLE(); |
- return nullptr; |
-} |
- |
-// static |
-const OperandTypeInfo* Bytecodes::GetOperandTypeInfos(Bytecode bytecode) { |
- DCHECK(bytecode <= Bytecode::kLast); |
- switch (bytecode) { |
-#define CASE(Name, ...) \ |
- case Bytecode::k##Name: \ |
- return BytecodeTraits<__VA_ARGS__>::GetOperandTypeInfos(); |
- BYTECODE_LIST(CASE) |
-#undef CASE |
- } |
- UNREACHABLE(); |
- return nullptr; |
-} |
- |
-// static |
-OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i, |
- OperandScale operand_scale) { |
- DCHECK_LT(i, NumberOfOperands(bytecode)); |
- OperandType operand_type = GetOperandType(bytecode, i); |
- return SizeOfOperand(operand_type, operand_scale); |
-} |
- |
-// static |
int Bytecodes::GetOperandOffset(Bytecode bytecode, int i, |
OperandScale operand_scale) { |
DCHECK_LT(i, Bytecodes::NumberOfOperands(bytecode)); |
@@ -367,71 +119,6 @@ int Bytecodes::GetOperandOffset(Bytecode bytecode, int i, |
} |
// static |
-OperandSize Bytecodes::SizeOfOperand(OperandType operand_type, |
- OperandScale operand_scale) { |
- DCHECK_LE(operand_type, OperandType::kLast); |
- DCHECK_GE(operand_scale, OperandScale::kSingle); |
- DCHECK_LE(operand_scale, OperandScale::kLast); |
- return static_cast<OperandSize>( |
- ScaledOperandSize(operand_type, operand_scale)); |
-} |
- |
-// static |
-bool Bytecodes::IsConditionalJumpImmediate(Bytecode bytecode) { |
- return bytecode == Bytecode::kJumpIfTrue || |
- bytecode == Bytecode::kJumpIfFalse || |
- bytecode == Bytecode::kJumpIfToBooleanTrue || |
- bytecode == Bytecode::kJumpIfToBooleanFalse || |
- bytecode == Bytecode::kJumpIfNotHole || |
- bytecode == Bytecode::kJumpIfNull || |
- bytecode == Bytecode::kJumpIfUndefined; |
-} |
- |
-// static |
-bool Bytecodes::IsConditionalJumpConstant(Bytecode bytecode) { |
- return bytecode == Bytecode::kJumpIfTrueConstant || |
- bytecode == Bytecode::kJumpIfFalseConstant || |
- bytecode == Bytecode::kJumpIfToBooleanTrueConstant || |
- bytecode == Bytecode::kJumpIfToBooleanFalseConstant || |
- bytecode == Bytecode::kJumpIfNotHoleConstant || |
- bytecode == Bytecode::kJumpIfNullConstant || |
- bytecode == Bytecode::kJumpIfUndefinedConstant; |
-} |
- |
-// static |
-bool Bytecodes::IsConditionalJump(Bytecode bytecode) { |
- return IsConditionalJumpImmediate(bytecode) || |
- IsConditionalJumpConstant(bytecode); |
-} |
- |
- |
-// static |
-bool Bytecodes::IsJumpImmediate(Bytecode bytecode) { |
- return bytecode == Bytecode::kJump || bytecode == Bytecode::kJumpLoop || |
- IsConditionalJumpImmediate(bytecode); |
-} |
- |
- |
-// static |
-bool Bytecodes::IsJumpConstant(Bytecode bytecode) { |
- return bytecode == Bytecode::kJumpConstant || |
- IsConditionalJumpConstant(bytecode); |
-} |
- |
-// static |
-bool Bytecodes::IsJump(Bytecode bytecode) { |
- return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode); |
-} |
- |
-// static |
-bool Bytecodes::IsJumpIfToBoolean(Bytecode bytecode) { |
- return bytecode == Bytecode::kJumpIfToBooleanTrue || |
- bytecode == Bytecode::kJumpIfToBooleanFalse || |
- bytecode == Bytecode::kJumpIfToBooleanTrueConstant || |
- bytecode == Bytecode::kJumpIfToBooleanFalseConstant; |
-} |
- |
-// static |
Bytecode Bytecodes::GetJumpWithoutToBoolean(Bytecode bytecode) { |
switch (bytecode) { |
case Bytecode::kJumpIfToBooleanTrue: |
@@ -450,19 +137,6 @@ Bytecode Bytecodes::GetJumpWithoutToBoolean(Bytecode bytecode) { |
} |
// static |
-bool Bytecodes::IsCallOrNew(Bytecode bytecode) { |
- return bytecode == Bytecode::kCall || bytecode == Bytecode::kTailCall || |
- bytecode == Bytecode::kNew; |
-} |
- |
-// static |
-bool Bytecodes::IsCallRuntime(Bytecode bytecode) { |
- return bytecode == Bytecode::kCallRuntime || |
- bytecode == Bytecode::kCallRuntimeForPair || |
- bytecode == Bytecode::kInvokeIntrinsic; |
-} |
- |
-// static |
bool Bytecodes::IsDebugBreak(Bytecode bytecode) { |
switch (bytecode) { |
#define CASE(Name, ...) case Bytecode::k##Name: |
@@ -476,53 +150,6 @@ bool Bytecodes::IsDebugBreak(Bytecode bytecode) { |
} |
// static |
-bool Bytecodes::IsLdarOrStar(Bytecode bytecode) { |
- return bytecode == Bytecode::kLdar || bytecode == Bytecode::kStar; |
-} |
- |
-// static |
-bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) { |
- switch (bytecode) { |
-#define CASE(Name, ...) \ |
- case Bytecode::k##Name: \ |
- typedef BytecodeTraits<__VA_ARGS__> Name##Trait; \ |
- return Name##Trait::IsScalable(); |
- BYTECODE_LIST(CASE) |
-#undef CASE |
- } |
- UNREACHABLE(); |
- return false; |
-} |
- |
-// static |
-bool Bytecodes::IsPrefixScalingBytecode(Bytecode bytecode) { |
- switch (bytecode) { |
- case Bytecode::kExtraWide: |
- case Bytecode::kDebugBreakExtraWide: |
- case Bytecode::kWide: |
- case Bytecode::kDebugBreakWide: |
- return true; |
- default: |
- return false; |
- } |
-} |
- |
-// static |
-bool Bytecodes::PutsNameInAccumulator(Bytecode bytecode) { |
- return bytecode == Bytecode::kTypeOf; |
-} |
- |
-// static |
-bool Bytecodes::IsJumpOrReturn(Bytecode bytecode) { |
- return bytecode == Bytecode::kReturn || IsJump(bytecode); |
-} |
- |
-// static |
-bool Bytecodes::IsMaybeRegisterOperandType(OperandType operand_type) { |
- return operand_type == OperandType::kMaybeReg; |
-} |
- |
-// static |
bool Bytecodes::IsRegisterOperandType(OperandType operand_type) { |
switch (operand_type) { |
#define CASE(Name, _) \ |
@@ -603,21 +230,11 @@ bool Bytecodes::IsStarLookahead(Bytecode bytecode, OperandScale operand_scale) { |
} |
// static |
-int Bytecodes::GetNumberOfRegistersRepresentedBy(OperandType operand_type) { |
- switch (operand_type) { |
- case OperandType::kMaybeReg: |
- case OperandType::kReg: |
- case OperandType::kRegOut: |
- return 1; |
- case OperandType::kRegPair: |
- case OperandType::kRegOutPair: |
- return 2; |
- case OperandType::kRegOutTriple: |
- return 3; |
- default: |
- return 0; |
+bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) { |
+ for (int i = 0; i < NumberOfOperands(bytecode); i++) { |
+ if (OperandIsScalable(bytecode, i)) return true; |
} |
- return 0; |
+ return false; |
} |
// static |
@@ -634,25 +251,28 @@ bool Bytecodes::IsUnsignedOperandType(OperandType operand_type) { |
} |
// static |
-OperandSize Bytecodes::SizeForSignedOperand(int value) { |
- if (value >= kMinInt8 && value <= kMaxInt8) { |
- return OperandSize::kByte; |
- } else if (value >= kMinInt16 && value <= kMaxInt16) { |
- return OperandSize::kShort; |
- } else { |
- return OperandSize::kQuad; |
- } |
-} |
- |
-// static |
-OperandSize Bytecodes::SizeForUnsignedOperand(uint32_t value) { |
- if (value <= kMaxUInt8) { |
- return OperandSize::kByte; |
- } else if (value <= kMaxUInt16) { |
- return OperandSize::kShort; |
- } else { |
- return OperandSize::kQuad; |
- } |
+OperandSize Bytecodes::SizeOfOperand(OperandType operand_type, |
+ OperandScale operand_scale) { |
+ DCHECK_LE(operand_type, OperandType::kLast); |
+ DCHECK_GE(operand_scale, OperandScale::kSingle); |
+ DCHECK_LE(operand_scale, OperandScale::kLast); |
+ STATIC_ASSERT(static_cast<int>(OperandScale::kQuadruple) == 4 && |
+ OperandScale::kLast == OperandScale::kQuadruple); |
+ int scale_index = static_cast<int>(operand_scale) >> 1; |
+ // clang-format off |
+ static const OperandSize kOperandSizes[][3] = { |
+#define ENTRY(Name, ...) \ |
+ { OperandScaler<OperandType::k##Name, \ |
+ OperandScale::kSingle>::kOperandSize, \ |
+ OperandScaler<OperandType::k##Name, \ |
+ OperandScale::kDouble>::kOperandSize, \ |
+ OperandScaler<OperandType::k##Name, \ |
+ OperandScale::kQuadruple>::kOperandSize }, |
+ OPERAND_TYPE_LIST(ENTRY) |
+#undef ENTRY |
+ }; |
+ // clang-format on |
+ return kOperandSizes[static_cast<size_t>(operand_type)][scale_index]; |
} |
// static |
@@ -666,22 +286,6 @@ std::ostream& operator<<(std::ostream& os, const Bytecode& bytecode) { |
return os << Bytecodes::ToString(bytecode); |
} |
-std::ostream& operator<<(std::ostream& os, const AccumulatorUse& use) { |
- return os << Bytecodes::AccumulatorUseToString(use); |
-} |
- |
-std::ostream& operator<<(std::ostream& os, const OperandSize& operand_size) { |
- return os << Bytecodes::OperandSizeToString(operand_size); |
-} |
- |
-std::ostream& operator<<(std::ostream& os, const OperandScale& operand_scale) { |
- return os << Bytecodes::OperandScaleToString(operand_scale); |
-} |
- |
-std::ostream& operator<<(std::ostream& os, const OperandType& operand_type) { |
- return os << Bytecodes::OperandTypeToString(operand_type); |
-} |
- |
} // namespace interpreter |
} // namespace internal |
} // namespace v8 |