Optimize instruction data fetch in interpreter.
The computed goto implementation prevents the compiler from detecting we are
loading the first 16 bits of instruction twice: first one to get the opcode and
second one to fetch first instruction's operand(s) like vA and vB.
We now load the 16 bits into a local variable and decode opcode and operands
from this variable. And do the same in the switch-based implementation for
consistency.
The performance improvement is 5% in average on benchmark applications suite.
Also remove unused "Thread* self" parameter from DoIGetQuick and DoIPutQuick.
Bug: 10703860
Change-Id: I83026ed6e78f642ac3dcdc6edbb6056fe012005f
diff --git a/runtime/dex_instruction.h b/runtime/dex_instruction.h
index 13b0f1c..e8db3bc 100644
--- a/runtime/dex_instruction.h
+++ b/runtime/dex_instruction.h
@@ -217,44 +217,122 @@
// VRegA
bool HasVRegA() const;
int32_t VRegA() const;
- int8_t VRegA_10t() const;
- uint8_t VRegA_10x() const;
- uint4_t VRegA_11n() const;
- uint8_t VRegA_11x() const;
- uint4_t VRegA_12x() const;
+
+ int8_t VRegA_10t() const {
+ return VRegA_10t(Fetch16(0));
+ }
+ uint8_t VRegA_10x() const {
+ return VRegA_10x(Fetch16(0));
+ }
+ uint4_t VRegA_11n() const {
+ return VRegA_11n(Fetch16(0));
+ }
+ uint8_t VRegA_11x() const {
+ return VRegA_11x(Fetch16(0));
+ }
+ uint4_t VRegA_12x() const {
+ return VRegA_12x(Fetch16(0));
+ }
int16_t VRegA_20t() const;
- uint8_t VRegA_21c() const;
- uint8_t VRegA_21h() const;
- uint8_t VRegA_21s() const;
- uint8_t VRegA_21t() const;
- uint8_t VRegA_22b() const;
- uint4_t VRegA_22c() const;
- uint4_t VRegA_22s() const;
- uint4_t VRegA_22t() const;
- uint8_t VRegA_22x() const;
- uint8_t VRegA_23x() const;
+ uint8_t VRegA_21c() const {
+ return VRegA_21c(Fetch16(0));
+ }
+ uint8_t VRegA_21h() const {
+ return VRegA_21h(Fetch16(0));
+ }
+ uint8_t VRegA_21s() const {
+ return VRegA_21s(Fetch16(0));
+ }
+ uint8_t VRegA_21t() const {
+ return VRegA_21t(Fetch16(0));
+ }
+ uint8_t VRegA_22b() const {
+ return VRegA_22b(Fetch16(0));
+ }
+ uint4_t VRegA_22c() const {
+ return VRegA_22c(Fetch16(0));
+ }
+ uint4_t VRegA_22s() const {
+ return VRegA_22s(Fetch16(0));
+ }
+ uint4_t VRegA_22t() const {
+ return VRegA_22t(Fetch16(0));
+ }
+ uint8_t VRegA_22x() const {
+ return VRegA_22x(Fetch16(0));
+ }
+ uint8_t VRegA_23x() const {
+ return VRegA_23x(Fetch16(0));
+ }
int32_t VRegA_30t() const;
- uint8_t VRegA_31c() const;
- uint8_t VRegA_31i() const;
- uint8_t VRegA_31t() const;
+ uint8_t VRegA_31c() const {
+ return VRegA_31c(Fetch16(0));
+ }
+ uint8_t VRegA_31i() const {
+ return VRegA_31i(Fetch16(0));
+ }
+ uint8_t VRegA_31t() const {
+ return VRegA_31t(Fetch16(0));
+ }
uint16_t VRegA_32x() const;
- uint4_t VRegA_35c() const;
- uint8_t VRegA_3rc() const;
- uint8_t VRegA_51l() const;
+ uint4_t VRegA_35c() const {
+ return VRegA_35c(Fetch16(0));
+ }
+ uint8_t VRegA_3rc() const {
+ return VRegA_3rc(Fetch16(0));
+ }
+ uint8_t VRegA_51l() const {
+ return VRegA_51l(Fetch16(0));
+ }
+
+ // The following methods return the vA operand for various instruction formats. The "inst_data"
+ // parameter holds the first 16 bits of instruction which the returned value is decoded from.
+ int8_t VRegA_10t(uint16_t inst_data) const;
+ uint8_t VRegA_10x(uint16_t inst_data) const;
+ uint4_t VRegA_11n(uint16_t inst_data) const;
+ uint8_t VRegA_11x(uint16_t inst_data) const;
+ uint4_t VRegA_12x(uint16_t inst_data) const;
+ uint8_t VRegA_21c(uint16_t inst_data) const;
+ uint8_t VRegA_21h(uint16_t inst_data) const;
+ uint8_t VRegA_21s(uint16_t inst_data) const;
+ uint8_t VRegA_21t(uint16_t inst_data) const;
+ uint8_t VRegA_22b(uint16_t inst_data) const;
+ uint4_t VRegA_22c(uint16_t inst_data) const;
+ uint4_t VRegA_22s(uint16_t inst_data) const;
+ uint4_t VRegA_22t(uint16_t inst_data) const;
+ uint8_t VRegA_22x(uint16_t inst_data) const;
+ uint8_t VRegA_23x(uint16_t inst_data) const;
+ uint8_t VRegA_31c(uint16_t inst_data) const;
+ uint8_t VRegA_31i(uint16_t inst_data) const;
+ uint8_t VRegA_31t(uint16_t inst_data) const;
+ uint4_t VRegA_35c(uint16_t inst_data) const;
+ uint8_t VRegA_3rc(uint16_t inst_data) const;
+ uint8_t VRegA_51l(uint16_t inst_data) const;
// VRegB
bool HasVRegB() const;
int32_t VRegB() const;
- int4_t VRegB_11n() const;
- uint4_t VRegB_12x() const;
+
+ int4_t VRegB_11n() const {
+ return VRegB_11n(Fetch16(0));
+ }
+ uint4_t VRegB_12x() const {
+ return VRegB_12x(Fetch16(0));
+ }
uint16_t VRegB_21c() const;
uint16_t VRegB_21h() const;
int16_t VRegB_21s() const;
int16_t VRegB_21t() const;
uint8_t VRegB_22b() const;
- uint4_t VRegB_22c() const;
- uint4_t VRegB_22s() const;
- uint4_t VRegB_22t() const;
+ uint4_t VRegB_22c() const {
+ return VRegB_22c(Fetch16(0));
+ }
+ uint4_t VRegB_22s() const {
+ return VRegB_22s(Fetch16(0));
+ }
+ uint4_t VRegB_22t() const {
+ return VRegB_22t(Fetch16(0));
+ }
uint16_t VRegB_22x() const;
uint8_t VRegB_23x() const;
uint32_t VRegB_31c() const;
@@ -265,9 +343,19 @@
uint16_t VRegB_3rc() const;
uint64_t VRegB_51l() const; // vB_wide
+ // The following methods return the vB operand for all instruction formats where it is encoded in
+ // the first 16 bits of instruction. The "inst_data" parameter holds these 16 bits. The returned
+ // value is decoded from it.
+ int4_t VRegB_11n(uint16_t inst_data) const;
+ uint4_t VRegB_12x(uint16_t inst_data) const;
+ uint4_t VRegB_22c(uint16_t inst_data) const;
+ uint4_t VRegB_22s(uint16_t inst_data) const;
+ uint4_t VRegB_22t(uint16_t inst_data) const;
+
// VRegC
bool HasVRegC() const;
int32_t VRegC() const;
+
int8_t VRegC_22b() const;
uint16_t VRegC_22c() const;
int16_t VRegC_22s() const;
@@ -279,9 +367,16 @@
// Fills the given array with the 'arg' array of the instruction.
void GetArgs(uint32_t args[5]) const;
- // Returns the opcode field of the instruction.
+ // Returns the opcode field of the instruction. The given "inst_data" parameter must be the first
+ // 16 bits of instruction.
+ Code Opcode(uint16_t inst_data) const {
+ DCHECK_EQ(inst_data, Fetch16(0));
+ return static_cast<Code>(inst_data & 0xFF);
+ }
+
+ // Returns the opcode field of the instruction from the first 16 bits of instruction.
Code Opcode() const {
- return static_cast<Code>(Fetch16(0) & 0xFF);
+ return Opcode(Fetch16(0));
}
void SetOpcode(Code opcode) {
@@ -395,28 +490,43 @@
// Dump code_units worth of this instruction, padding to code_units for shorter instructions
std::string DumpHex(size_t code_units) const;
- private:
- size_t SizeInCodeUnitsComplexOpcode() const;
-
uint16_t Fetch16(size_t offset) const {
const uint16_t* insns = reinterpret_cast<const uint16_t*>(this);
return insns[offset];
}
+ private:
+ size_t SizeInCodeUnitsComplexOpcode() const;
+
uint32_t Fetch32(size_t offset) const {
return (Fetch16(offset) | ((uint32_t) Fetch16(offset + 1) << 16));
}
uint4_t InstA() const {
- return static_cast<uint4_t>((Fetch16(0) >> 8) & 0x0f);
+ return InstA(Fetch16(0));
}
uint4_t InstB() const {
- return static_cast<uint4_t>(Fetch16(0) >> 12);
+ return InstB(Fetch16(0));
}
uint8_t InstAA() const {
- return static_cast<uint8_t>(Fetch16(0) >> 8);
+ return InstAA(Fetch16(0));
+ }
+
+ uint4_t InstA(uint16_t inst_data) const {
+ DCHECK_EQ(inst_data, Fetch16(0));
+ return static_cast<uint4_t>((inst_data >> 8) & 0x0f);
+ }
+
+ uint4_t InstB(uint16_t inst_data) const {
+ DCHECK_EQ(inst_data, Fetch16(0));
+ return static_cast<uint4_t>(inst_data >> 12);
+ }
+
+ uint8_t InstAA(uint16_t inst_data) const {
+ DCHECK_EQ(inst_data, Fetch16(0));
+ return static_cast<uint8_t>(inst_data >> 8);
}
static const char* const kInstructionNames[];