diff options
author | 2017-05-15 15:11:56 -0700 | |
---|---|---|
committer | 2017-05-16 09:54:18 -0700 | |
commit | b3937e31102538baf27a6e9088638c5e3ff1ca34 (patch) | |
tree | 599d6fe4f65f5837993d6936a8aae7537c4cabbb | |
parent | a1633a7077781d9c64a77b27deb1707d1a56906d (diff) |
ART: Collect instruction flags in a struct
Use small backing types for the enums, where possible. Then collect
the flags in a InstructionDescriptor struct. This improves locality
for combined lookups, e.g., in the verifier.
Bug: 10921004
Test: m test-art-host
Change-Id: I2925bce59d2f6fa5fcd8da5007e9567562b1b070
-rw-r--r-- | runtime/dex_instruction.cc | 69 | ||||
-rw-r--r-- | runtime/dex_instruction.h | 73 |
2 files changed, 69 insertions, 73 deletions
diff --git a/runtime/dex_instruction.cc b/runtime/dex_instruction.cc index 7f73ad2eef..b2267e5573 100644 --- a/runtime/dex_instruction.cc +++ b/runtime/dex_instruction.cc @@ -38,50 +38,39 @@ const char* const Instruction::kInstructionNames[] = { #undef INSTRUCTION_NAME }; -Instruction::Format const Instruction::kInstructionFormats[] = { -#define INSTRUCTION_FORMAT(o, c, p, format, i, a, e, v) format, -#include "dex_instruction_list.h" - DEX_INSTRUCTION_LIST(INSTRUCTION_FORMAT) -#undef DEX_INSTRUCTION_LIST -#undef INSTRUCTION_FORMAT -}; - -Instruction::IndexType const Instruction::kInstructionIndexTypes[] = { -#define INSTRUCTION_INDEX_TYPE(o, c, p, f, index, a, e, v) index, -#include "dex_instruction_list.h" - DEX_INSTRUCTION_LIST(INSTRUCTION_INDEX_TYPE) -#undef DEX_INSTRUCTION_LIST -#undef INSTRUCTION_FLAGS -}; - -int const Instruction::kInstructionFlags[] = { -#define INSTRUCTION_FLAGS(o, c, p, f, i, flags, e, v) flags, -#include "dex_instruction_list.h" - DEX_INSTRUCTION_LIST(INSTRUCTION_FLAGS) -#undef DEX_INSTRUCTION_LIST -#undef INSTRUCTION_FLAGS -}; +static_assert(sizeof(Instruction::InstructionDescriptor) == 8u, "Unexpected descriptor size"); -int const Instruction::kInstructionVerifyFlags[] = { -#define INSTRUCTION_VERIFY_FLAGS(o, c, p, f, i, a, e, vflags) vflags, -#include "dex_instruction_list.h" - DEX_INSTRUCTION_LIST(INSTRUCTION_VERIFY_FLAGS) -#undef DEX_INSTRUCTION_LIST -#undef INSTRUCTION_VERIFY_FLAGS -}; +static constexpr int8_t InstructionSizeInCodeUnitsByOpcode(Instruction::Code opcode, + Instruction::Format format) { + if (opcode == Instruction::Code::NOP) { + return -1; + } else if ((format >= Instruction::Format::k10x) && (format <= Instruction::Format::k10t)) { + return 1; + } else if ((format >= Instruction::Format::k20t) && (format <= Instruction::Format::k22c)) { + return 2; + } else if ((format >= Instruction::Format::k32x) && (format <= Instruction::Format::k3rc)) { + return 3; + } else if ((format >= Instruction::Format::k45cc) && (format <= Instruction::Format::k4rcc)) { + return 4; + } else if (format == Instruction::Format::k51l) { + return 5; + } else { + return -1; + } +} -int const Instruction::kInstructionSizeInCodeUnits[] = { -#define INSTRUCTION_SIZE(opcode, c, p, format, i, a, e, v) \ - (((opcode) == NOP) ? -1 : \ - (((format) >= k10x) && ((format) <= k10t)) ? 1 : \ - (((format) >= k20t) && ((format) <= k22c)) ? 2 : \ - (((format) >= k32x) && ((format) <= k3rc)) ? 3 : \ - (((format) >= k45cc) && ((format) <= k4rcc)) ? 4 : \ - ((format) == k51l) ? 5 : -1), +Instruction::InstructionDescriptor const Instruction::kInstructionDescriptors[] = { +#define INSTRUCTION_DESCR(opcode, c, p, format, index, flags, eflags, vflags) \ + { vflags, \ + format, \ + index, \ + flags, \ + InstructionSizeInCodeUnitsByOpcode((c), (format)), \ + }, #include "dex_instruction_list.h" - DEX_INSTRUCTION_LIST(INSTRUCTION_SIZE) + DEX_INSTRUCTION_LIST(INSTRUCTION_DESCR) #undef DEX_INSTRUCTION_LIST -#undef INSTRUCTION_SIZE +#undef INSTRUCTION_DESCR }; int32_t Instruction::GetTargetOffset() const { diff --git a/runtime/dex_instruction.h b/runtime/dex_instruction.h index 58144b29d4..9a1757601c 100644 --- a/runtime/dex_instruction.h +++ b/runtime/dex_instruction.h @@ -88,7 +88,7 @@ class Instruction { RSUB_INT_LIT16 = RSUB_INT, }; - enum Format { + enum Format : uint8_t { k10x, // op k12x, // op vA, vB k11n, // op vA, #+B @@ -124,7 +124,7 @@ class Instruction { k51l, // op vAA, #+BBBBBBBBBBBBBBBB }; - enum IndexType { + enum IndexType : uint8_t { kIndexUnknown = 0, kIndexNone, // has no index kIndexTypeRef, // type reference index @@ -137,7 +137,7 @@ class Instruction { kIndexCallSiteRef, // call site reference index }; - enum Flags { + enum Flags : uint8_t { kBranch = 0x01, // conditional or unconditional branch kContinue = 0x02, // flow can continue to next statement kSwitch = 0x04, // switch statement @@ -169,7 +169,7 @@ class Instruction { kRegBFieldOrConstant = 0x0800000, // is the second virtual register a field or literal constant (vB) }; - enum VerifyFlag { + enum VerifyFlag : uint32_t { kVerifyNone = 0x0000000, kVerifyRegA = 0x0000001, kVerifyRegAWide = 0x0000002, @@ -198,13 +198,22 @@ class Instruction { kVerifyRegBCallSite = 0x1000000 }; + // Collect the enums in a struct for better locality. + struct InstructionDescriptor { + uint32_t verify_flags; // Set of VerifyFlag. + Format format; + IndexType index_type; + uint8_t flags; // Set of Flags. + int8_t size_in_code_units; + }; + static constexpr uint32_t kMaxVarArgRegs = 5; static constexpr bool kHaveExperimentalInstructions = false; // Returns the size (in 2 byte code units) of this instruction. size_t SizeInCodeUnits() const { - int result = kInstructionSizeInCodeUnits[Opcode()]; + int8_t result = kInstructionDescriptors[Opcode()].size_in_code_units; if (UNLIKELY(result < 0)) { return SizeInCodeUnitsComplexOpcode(); } else { @@ -503,32 +512,32 @@ class Instruction { // Returns the format of the given opcode. static Format FormatOf(Code opcode) { - return kInstructionFormats[opcode]; + return kInstructionDescriptors[opcode].format; } // Returns the index type of the given opcode. static IndexType IndexTypeOf(Code opcode) { - return kInstructionIndexTypes[opcode]; + return kInstructionDescriptors[opcode].index_type; } // Returns the flags for the given opcode. - static int FlagsOf(Code opcode) { - return kInstructionFlags[opcode]; + static uint8_t FlagsOf(Code opcode) { + return kInstructionDescriptors[opcode].flags; } // Return the verify flags for the given opcode. - static int VerifyFlagsOf(Code opcode) { - return kInstructionVerifyFlags[opcode]; + static uint32_t VerifyFlagsOf(Code opcode) { + return kInstructionDescriptors[opcode].verify_flags; } // Returns true if this instruction is a branch. bool IsBranch() const { - return (kInstructionFlags[Opcode()] & kBranch) != 0; + return (kInstructionDescriptors[Opcode()].flags & kBranch) != 0; } // Returns true if this instruction is a unconditional branch. bool IsUnconditional() const { - return (kInstructionFlags[Opcode()] & kUnconditional) != 0; + return (kInstructionDescriptors[Opcode()].flags & kUnconditional) != 0; } // Returns the branch offset if this instruction is a branch. @@ -539,23 +548,23 @@ class Instruction { // Returns true if the instruction is a quickened instruction. bool IsQuickened() const { - return (kInstructionIndexTypes[Opcode()] == kIndexFieldOffset) || - (kInstructionIndexTypes[Opcode()] == kIndexVtableOffset); + return (kInstructionDescriptors[Opcode()].index_type == kIndexFieldOffset) || + (kInstructionDescriptors[Opcode()].index_type == kIndexVtableOffset); } // Returns true if this instruction is a switch. bool IsSwitch() const { - return (kInstructionFlags[Opcode()] & kSwitch) != 0; + return (kInstructionDescriptors[Opcode()].flags & kSwitch) != 0; } // Returns true if this instruction can throw. bool IsThrow() const { - return (kInstructionFlags[Opcode()] & kThrow) != 0; + return (kInstructionDescriptors[Opcode()].flags & kThrow) != 0; } // Determine if the instruction is any of 'return' instructions. bool IsReturn() const { - return (kInstructionFlags[Opcode()] & kReturn) != 0; + return (kInstructionDescriptors[Opcode()].flags & kReturn) != 0; } // Determine if this instruction ends execution of its basic block. @@ -565,41 +574,41 @@ class Instruction { // Determine if this instruction is an invoke. bool IsInvoke() const { - return (kInstructionFlags[Opcode()] & kInvoke) != 0; + return (kInstructionDescriptors[Opcode()].flags & kInvoke) != 0; } // Determine if this instruction is experimental. bool IsExperimental() const { - return (kInstructionFlags[Opcode()] & kExperimental) != 0; + return (kInstructionDescriptors[Opcode()].flags & kExperimental) != 0; } int GetVerifyTypeArgumentA() const { - return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegA | kVerifyRegAWide)); + return (kInstructionDescriptors[Opcode()].verify_flags & (kVerifyRegA | kVerifyRegAWide)); } int GetVerifyTypeArgumentB() const { - return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegB | kVerifyRegBField | + return (kInstructionDescriptors[Opcode()].verify_flags & (kVerifyRegB | kVerifyRegBField | kVerifyRegBMethod | kVerifyRegBNewInstance | kVerifyRegBString | kVerifyRegBType | kVerifyRegBWide)); } int GetVerifyTypeArgumentC() const { - return (kInstructionVerifyFlags[Opcode()] & (kVerifyRegC | kVerifyRegCField | + return (kInstructionDescriptors[Opcode()].verify_flags & (kVerifyRegC | kVerifyRegCField | kVerifyRegCNewArray | kVerifyRegCType | kVerifyRegCWide)); } int GetVerifyTypeArgumentH() const { - return (kInstructionVerifyFlags[Opcode()] & kVerifyRegHPrototype); + return (kInstructionDescriptors[Opcode()].verify_flags & kVerifyRegHPrototype); } int GetVerifyExtraFlags() const { - return (kInstructionVerifyFlags[Opcode()] & (kVerifyArrayData | kVerifyBranchTarget | - kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgNonZero | kVerifyVarArgRange | - kVerifyVarArgRangeNonZero | kVerifyError)); + return (kInstructionDescriptors[Opcode()].verify_flags & (kVerifyArrayData | + kVerifyBranchTarget | kVerifySwitchTargets | kVerifyVarArg | kVerifyVarArgNonZero | + kVerifyVarArgRange | kVerifyVarArgRangeNonZero | kVerifyError)); } bool GetVerifyIsRuntimeOnly() const { - return (kInstructionVerifyFlags[Opcode()] & kVerifyRuntimeOnly) != 0; + return (kInstructionDescriptors[Opcode()].verify_flags & kVerifyRuntimeOnly) != 0; } // Get the dex PC of this instruction as a offset in code units from the beginning of insns. @@ -657,11 +666,9 @@ class Instruction { } static const char* const kInstructionNames[]; - static Format const kInstructionFormats[]; - static IndexType const kInstructionIndexTypes[]; - static int const kInstructionFlags[]; - static int const kInstructionVerifyFlags[]; - static int const kInstructionSizeInCodeUnits[]; + + static const InstructionDescriptor kInstructionDescriptors[]; + DISALLOW_IMPLICIT_CONSTRUCTORS(Instruction); }; std::ostream& operator<<(std::ostream& os, const Instruction::Code& code); |