Index: src/interpreter/bytecodes.cc |
diff --git a/src/interpreter/bytecodes.cc b/src/interpreter/bytecodes.cc |
index 5f7a9085aec33bdba04bcd4764a8cfac73a6e667..ae5b349a241c7221ea5d1073ad52a005a7bce472 100644 |
--- a/src/interpreter/bytecodes.cc |
+++ b/src/interpreter/bytecodes.cc |
@@ -29,7 +29,7 @@ const char* Bytecodes::ToString(Bytecode bytecode) { |
// static |
const char* Bytecodes::OperandTypeToString(OperandType operand_type) { |
switch (operand_type) { |
-#define CASE(Name, _) \ |
+#define CASE(Name, _, __) \ |
case OperandType::k##Name: \ |
return #Name; |
OPERAND_TYPE_LIST(CASE) |
@@ -49,6 +49,8 @@ const char* Bytecodes::OperandSizeToString(OperandSize operand_size) { |
return "Byte"; |
case OperandSize::kShort: |
return "Short"; |
+ case OperandSize::kQuad: |
+ return "Quad"; |
} |
UNREACHABLE(); |
return ""; |
@@ -71,32 +73,28 @@ Bytecode Bytecodes::FromByte(uint8_t value) { |
// static |
-Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode) { |
- switch (Size(bytecode)) { |
-#define CASE(Name, ...) \ |
- case BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::kSize: \ |
- return Bytecode::k##Name; |
- DEBUG_BREAK_BYTECODE_LIST(CASE) |
-#undef CASE |
- default: |
- break; |
+Bytecode Bytecodes::GetDebugBreak(Bytecode bytecode, int operand_scale) { |
+ int bytecode_size = Size(bytecode, operand_scale); |
+#define RETURN_IF_DEBUG_BREAK_SIZE_MATCHES(Name, ...) \ |
+ if (bytecode_size == Size(Bytecode::k##Name, operand_scale)) { \ |
+ return Bytecode::k##Name; \ |
} |
+ DEBUG_BREAK_BYTECODE_LIST(RETURN_IF_DEBUG_BREAK_SIZE_MATCHES) |
+#undef RETURN_IF_DEBUG_BREAK_SIZE_MATCHES |
UNREACHABLE(); |
return static_cast<Bytecode>(-1); |
} |
// static |
-int Bytecodes::Size(Bytecode bytecode) { |
- DCHECK(bytecode <= Bytecode::kLast); |
- switch (bytecode) { |
-#define CASE(Name, ...) \ |
- case Bytecode::k##Name: \ |
- return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::kSize; |
- BYTECODE_LIST(CASE) |
-#undef CASE |
+int Bytecodes::Size(Bytecode bytecode, int 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; |
} |
- UNREACHABLE(); |
- return 0; |
+ return size; |
} |
@@ -131,6 +129,18 @@ int Bytecodes::NumberOfRegisterOperands(Bytecode bytecode) { |
} |
// static |
+int Bytecodes::GetPrefixBytecodeScale(Bytecode bytecode) { |
+ switch (bytecode) { |
rmcilroy
2016/03/10 16:45:37
Could we make this DCHECK if it is passed a non-pr
oth
2016/03/11 16:26:12
Not really, this is one of the main ways of determ
oth
2016/03/17 13:48:38
Done.
|
+ case Bytecode::kExtraWide: |
+ return 4; |
+ case Bytecode::kWide: |
+ return 2; |
+ default: |
+ return 1; |
+ } |
+} |
+ |
+// static |
OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) { |
DCHECK(bytecode <= Bytecode::kLast); |
switch (bytecode) { |
@@ -144,23 +154,47 @@ OperandType Bytecodes::GetOperandType(Bytecode bytecode, int i) { |
return OperandType::kNone; |
} |
+// TODO(oth): TEMPORARY |
+namespace { |
-// static |
-OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i) { |
- DCHECK(bytecode <= Bytecode::kLast); |
- switch (bytecode) { |
-#define CASE(Name, ...) \ |
- case Bytecode::k##Name: \ |
- return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::GetOperandSize(i); |
- BYTECODE_LIST(CASE) |
+template <OperandTypeTrait O> |
+struct OperandScaler { |
+ static int Multiply(int size, int scale) { return 0; } |
+}; |
+ |
+template <> |
+struct OperandScaler<OperandTypeTrait::kFixed> { |
+ static int Multiply(int size, int scale) { return size; } |
+}; |
+ |
+template <> |
+struct OperandScaler<OperandTypeTrait::kScalable> { |
+ static int Multiply(int size, int scale) { return size * scale; } |
+}; |
+ |
+} // namespace |
+ |
+// TODO(oth): TEMPORARY |
+static int ScaledOperandSize(OperandType operand_type, int scale) { |
+ switch (operand_type) { |
+#define CASE(Name, Size, Trait) \ |
+ case OperandType::k##Name: \ |
+ return OperandScaler<Trait>::Multiply(static_cast<int>(Size), scale); |
+ OPERAND_TYPE_LIST(CASE) |
#undef CASE |
} |
UNREACHABLE(); |
- return OperandSize::kNone; |
+ return 0; |
} |
// static |
+OperandSize Bytecodes::GetOperandSize(Bytecode bytecode, int i, int scale) { |
+ OperandType op_type = GetOperandType(bytecode, i); |
+ return static_cast<OperandSize>(ScaledOperandSize(op_type, scale)); |
+} |
+ |
+// static |
int Bytecodes::GetRegisterOperandBitmap(Bytecode bytecode) { |
DCHECK(bytecode <= Bytecode::kLast); |
switch (bytecode) { |
@@ -176,31 +210,18 @@ int Bytecodes::GetRegisterOperandBitmap(Bytecode bytecode) { |
} |
// static |
-int Bytecodes::GetOperandOffset(Bytecode bytecode, int i) { |
- DCHECK(bytecode <= Bytecode::kLast); |
- switch (bytecode) { |
-#define CASE(Name, ...) \ |
- case Bytecode::k##Name: \ |
- return BytecodeTraits<__VA_ARGS__, OPERAND_TERM>::GetOperandOffset(i); |
- BYTECODE_LIST(CASE) |
-#undef CASE |
+int Bytecodes::GetOperandOffset(Bytecode bytecode, int i, int scale) { |
+ int offset = 1; |
+ for (int operand_index = 0; operand_index < i; ++operand_index) { |
+ OperandSize operand_size = GetOperandSize(bytecode, operand_index, scale); |
+ offset += static_cast<int>(operand_size); |
} |
- UNREACHABLE(); |
- return 0; |
+ return offset; |
} |
- |
// static |
-OperandSize Bytecodes::SizeOfOperand(OperandType operand_type) { |
- switch (operand_type) { |
-#define CASE(Name, Size) \ |
- case OperandType::k##Name: \ |
- return Size; |
- OPERAND_TYPE_LIST(CASE) |
-#undef CASE |
- } |
- UNREACHABLE(); |
- return OperandSize::kNone; |
+OperandSize Bytecodes::SizeOfOperand(OperandType operand_type, int scale) { |
+ return static_cast<OperandSize>(ScaledOperandSize(operand_type, scale)); |
} |
@@ -227,24 +248,10 @@ bool Bytecodes::IsConditionalJumpConstant(Bytecode bytecode) { |
bytecode == Bytecode::kJumpIfUndefinedConstant; |
} |
- |
-// static |
-bool Bytecodes::IsConditionalJumpConstantWide(Bytecode bytecode) { |
- return bytecode == Bytecode::kJumpIfTrueConstantWide || |
- bytecode == Bytecode::kJumpIfFalseConstantWide || |
- bytecode == Bytecode::kJumpIfToBooleanTrueConstantWide || |
- bytecode == Bytecode::kJumpIfToBooleanFalseConstantWide || |
- bytecode == Bytecode::kJumpIfNotHoleConstantWide || |
- bytecode == Bytecode::kJumpIfNullConstantWide || |
- bytecode == Bytecode::kJumpIfUndefinedConstantWide; |
-} |
- |
- |
// static |
bool Bytecodes::IsConditionalJump(Bytecode bytecode) { |
return IsConditionalJumpImmediate(bytecode) || |
- IsConditionalJumpConstant(bytecode) || |
- IsConditionalJumpConstantWide(bytecode); |
+ IsConditionalJumpConstant(bytecode); |
} |
@@ -260,34 +267,22 @@ bool Bytecodes::IsJumpConstant(Bytecode bytecode) { |
IsConditionalJumpConstant(bytecode); |
} |
- |
-// static |
-bool Bytecodes::IsJumpConstantWide(Bytecode bytecode) { |
- return bytecode == Bytecode::kJumpConstantWide || |
- IsConditionalJumpConstantWide(bytecode); |
-} |
- |
- |
// static |
bool Bytecodes::IsJump(Bytecode bytecode) { |
- return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode) || |
- IsJumpConstantWide(bytecode); |
+ return IsJumpImmediate(bytecode) || IsJumpConstant(bytecode); |
} |
// static |
bool Bytecodes::IsCallOrNew(Bytecode bytecode) { |
return bytecode == Bytecode::kCall || bytecode == Bytecode::kTailCall || |
- bytecode == Bytecode::kNew || bytecode == Bytecode::kCallWide || |
- bytecode == Bytecode::kTailCallWide || bytecode == Bytecode::kNewWide; |
+ bytecode == Bytecode::kNew; |
} |
// static |
bool Bytecodes::IsCallRuntime(Bytecode bytecode) { |
return bytecode == Bytecode::kCallRuntime || |
- bytecode == Bytecode::kCallRuntimeWide || |
- bytecode == Bytecode::kCallRuntimeForPair || |
- bytecode == Bytecode::kCallRuntimeForPairWide; |
+ bytecode == Bytecode::kCallRuntimeForPair; |
} |
// static |
@@ -304,42 +299,63 @@ bool Bytecodes::IsDebugBreak(Bytecode bytecode) { |
} |
// static |
+bool Bytecodes::IsBytecodeWithScalableOperands(Bytecode bytecode) { |
+ switch (bytecode) { |
+#define CASE(Name, ...) \ |
+ case Bytecode::k##Name: \ |
+ typedef BytecodeTraits<__VA_ARGS__, OPERAND_TERM> Name##Trait; \ |
+ return Name##Trait::IsScalable(); |
+ BYTECODE_LIST(CASE) |
+#undef CASE |
+ } |
+ UNREACHABLE(); |
+ return false; |
+} |
+ |
+// static |
bool Bytecodes::IsJumpOrReturn(Bytecode bytecode) { |
return bytecode == Bytecode::kReturn || IsJump(bytecode); |
} |
// static |
+bool Bytecodes::IsFlagOperandType(OperandType operand_type) { |
+ return operand_type == OperandType::kFlag8; |
+} |
+ |
+// static |
bool Bytecodes::IsIndexOperandType(OperandType operand_type) { |
- return operand_type == OperandType::kIdx8 || |
- operand_type == OperandType::kIdx16; |
+ return operand_type == OperandType::kIdx; |
} |
// static |
bool Bytecodes::IsImmediateOperandType(OperandType operand_type) { |
- return operand_type == OperandType::kImm8; |
+ return operand_type == OperandType::kImm; |
} |
// static |
bool Bytecodes::IsRegisterCountOperandType(OperandType operand_type) { |
- return (operand_type == OperandType::kRegCount8 || |
- operand_type == OperandType::kRegCount16); |
+ return operand_type == OperandType::kRegCount; |
} |
// static |
bool Bytecodes::IsMaybeRegisterOperandType(OperandType operand_type) { |
- return (operand_type == OperandType::kMaybeReg8 || |
- operand_type == OperandType::kMaybeReg16); |
+ return operand_type == OperandType::kMaybeReg; |
+} |
+ |
+// static |
+bool Bytecodes::IsRuntimeIdOperandType(OperandType operand_type) { |
rmcilroy
2016/03/10 16:45:37
Wondering whether these IsXXXOperandType are neces
oth
2016/03/11 16:26:12
Done. Removed all except the still useful IsRegist
|
+ return operand_type == OperandType::kRuntimeId; |
} |
// static |
bool Bytecodes::IsRegisterOperandType(OperandType operand_type) { |
switch (operand_type) { |
-#define CASE(Name, _) \ |
+#define CASE(Name, _, __) \ |
case OperandType::k##Name: \ |
return true; |
REGISTER_OPERAND_TYPE_LIST(CASE) |
#undef CASE |
-#define CASE(Name, _) \ |
+#define CASE(Name, _, __) \ |
case OperandType::k##Name: \ |
break; |
NON_REGISTER_OPERAND_TYPE_LIST(CASE) |
@@ -351,12 +367,12 @@ bool Bytecodes::IsRegisterOperandType(OperandType operand_type) { |
// static |
bool Bytecodes::IsRegisterInputOperandType(OperandType operand_type) { |
switch (operand_type) { |
-#define CASE(Name, _) \ |
+#define CASE(Name, _, __) \ |
case OperandType::k##Name: \ |
return true; |
REGISTER_INPUT_OPERAND_TYPE_LIST(CASE) |
#undef CASE |
-#define CASE(Name, _) \ |
+#define CASE(Name, _, __) \ |
case OperandType::k##Name: \ |
break; |
NON_REGISTER_OPERAND_TYPE_LIST(CASE) |
@@ -369,12 +385,12 @@ bool Bytecodes::IsRegisterInputOperandType(OperandType operand_type) { |
// static |
bool Bytecodes::IsRegisterOutputOperandType(OperandType operand_type) { |
switch (operand_type) { |
-#define CASE(Name, _) \ |
+#define CASE(Name, _, __) \ |
case OperandType::k##Name: \ |
return true; |
REGISTER_OUTPUT_OPERAND_TYPE_LIST(CASE) |
#undef CASE |
-#define CASE(Name, _) \ |
+#define CASE(Name, _, __) \ |
case OperandType::k##Name: \ |
break; |
NON_REGISTER_OPERAND_TYPE_LIST(CASE) |
@@ -386,18 +402,52 @@ bool Bytecodes::IsRegisterOutputOperandType(OperandType operand_type) { |
namespace { |
static Register DecodeRegister(const uint8_t* operand_start, |
- OperandType operand_type) { |
- switch (Bytecodes::SizeOfOperand(operand_type)) { |
+ OperandType operand_type, int operand_scale) { |
+ switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) { |
case OperandSize::kByte: |
return Register::FromOperand(*operand_start); |
case OperandSize::kShort: |
return Register::FromWideOperand(ReadUnalignedUInt16(operand_start)); |
+ case OperandSize::kQuad: |
+ return Register::FromWideOperand(ReadUnalignedUInt32(operand_start)); |
case OperandSize::kNone: { |
UNREACHABLE(); |
} |
} |
return Register(); |
} |
+ |
+static uint32_t DecodeUnsignedOperand(const uint8_t* operand_start, |
+ OperandType operand_type, |
+ int operand_scale) { |
+ switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) { |
+ case OperandSize::kByte: |
+ return *operand_start; |
+ case OperandSize::kShort: |
+ return ReadUnalignedUInt16(operand_start); |
+ case OperandSize::kQuad: |
+ return ReadUnalignedUInt32(operand_start); |
+ case OperandSize::kNone: |
+ UNREACHABLE(); |
+ } |
+ return 0; |
+} |
+ |
+static int32_t DecodeSignedOperand(const uint8_t* operand_start, |
+ OperandType operand_type, |
+ int operand_scale) { |
+ switch (Bytecodes::SizeOfOperand(operand_type, operand_scale)) { |
+ case OperandSize::kByte: |
+ return static_cast<int8_t>(*operand_start); |
+ case OperandSize::kShort: |
+ return static_cast<int16_t>(ReadUnalignedUInt16(operand_start)); |
+ case OperandSize::kQuad: |
+ return static_cast<int32_t>(ReadUnalignedUInt32(operand_start)); |
+ case OperandSize::kNone: |
+ UNREACHABLE(); |
+ } |
+ return 0; |
+} |
} // namespace |
@@ -407,18 +457,31 @@ std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, |
Vector<char> buf = Vector<char>::New(50); |
Bytecode bytecode = Bytecodes::FromByte(bytecode_start[0]); |
- int bytecode_size = Bytecodes::Size(bytecode); |
+ int prefix_offset = 0; |
+ int operand_scale = Bytecodes::GetPrefixBytecodeScale(bytecode); |
+ if (operand_scale > 1) { |
+ prefix_offset += 1; |
+ bytecode = Bytecodes::FromByte(bytecode_start[1]); |
+ } |
- for (int i = 0; i < bytecode_size; i++) { |
+ int bytecode_size = Bytecodes::Size(bytecode, operand_scale); |
+ |
+ for (int i = 0; i < prefix_offset + bytecode_size; i++) { |
SNPrintF(buf, "%02x ", bytecode_start[i]); |
os << buf.start(); |
} |
const int kBytecodeColumnSize = 6; |
- for (int i = bytecode_size; i < kBytecodeColumnSize; i++) { |
+ for (int i = prefix_offset + bytecode_size; i < kBytecodeColumnSize; i++) { |
os << " "; |
} |
- os << bytecode << " "; |
+ os << bytecode; |
+ if (operand_scale == 2) { |
+ os << "." << Bytecodes::ToString(Bytecode::kWide); |
+ } else if (operand_scale == 4) { |
+ os << "." << Bytecodes::ToString(Bytecode::kExtraWide); |
+ } |
+ os << " "; |
// Operands for the debug break are from the original instruction. |
if (IsDebugBreak(bytecode)) return os; |
@@ -428,42 +491,41 @@ std::ostream& Bytecodes::Decode(std::ostream& os, const uint8_t* bytecode_start, |
for (int i = 0; i < number_of_operands; i++) { |
OperandType op_type = GetOperandType(bytecode, i); |
const uint8_t* operand_start = |
- &bytecode_start[GetOperandOffset(bytecode, i)]; |
+ &bytecode_start[prefix_offset + |
+ GetOperandOffset(bytecode, i, operand_scale)]; |
switch (op_type) { |
- case interpreter::OperandType::kRegCount8: |
- os << "#" << static_cast<unsigned int>(*operand_start); |
- break; |
- case interpreter::OperandType::kRegCount16: |
- os << '#' << ReadUnalignedUInt16(operand_start); |
+ case interpreter::OperandType::kRegCount: |
+ os << "#" |
+ << DecodeUnsignedOperand(operand_start, op_type, operand_scale); |
break; |
- case interpreter::OperandType::kIdx8: |
- os << "[" << static_cast<unsigned int>(*operand_start) << "]"; |
+ case interpreter::OperandType::kIdx: |
+ case interpreter::OperandType::kRuntimeId: |
+ os << "[" |
+ << DecodeUnsignedOperand(operand_start, op_type, operand_scale) |
+ << "]"; |
break; |
- case interpreter::OperandType::kIdx16: |
- os << "[" << ReadUnalignedUInt16(operand_start) << "]"; |
+ case interpreter::OperandType::kImm: |
+ os << "[" << DecodeSignedOperand(operand_start, op_type, operand_scale) |
+ << "]"; |
break; |
- case interpreter::OperandType::kImm8: |
- os << "#" << static_cast<int>(static_cast<int8_t>(*operand_start)); |
+ case interpreter::OperandType::kFlag8: |
+ os << "#" |
+ << DecodeUnsignedOperand(operand_start, op_type, operand_scale); |
break; |
- case interpreter::OperandType::kMaybeReg8: |
- case interpreter::OperandType::kMaybeReg16: |
- case interpreter::OperandType::kReg8: |
- case interpreter::OperandType::kReg16: |
- case interpreter::OperandType::kRegOut8: |
- case interpreter::OperandType::kRegOut16: { |
- Register reg = DecodeRegister(operand_start, op_type); |
+ case interpreter::OperandType::kMaybeReg: |
+ case interpreter::OperandType::kReg: |
+ case interpreter::OperandType::kRegOut: { |
+ Register reg = DecodeRegister(operand_start, op_type, operand_scale); |
os << reg.ToString(parameter_count); |
break; |
} |
- case interpreter::OperandType::kRegOutTriple8: |
- case interpreter::OperandType::kRegOutTriple16: |
+ case interpreter::OperandType::kRegOutTriple: |
range += 1; |
- case interpreter::OperandType::kRegOutPair8: |
- case interpreter::OperandType::kRegOutPair16: |
- case interpreter::OperandType::kRegPair8: |
- case interpreter::OperandType::kRegPair16: { |
+ case interpreter::OperandType::kRegOutPair: |
+ case interpreter::OperandType::kRegPair: { |
range += 1; |
- Register first_reg = DecodeRegister(operand_start, op_type); |
+ Register first_reg = |
+ DecodeRegister(operand_start, op_type, operand_scale); |
Register last_reg = Register(first_reg.index() + range); |
os << first_reg.ToString(parameter_count) << "-" |
<< last_reg.ToString(parameter_count); |