Optimize branch instructions in interpreter.
This CL cleans up branch instructions handling by optimizing instruction
displacement with an offset by changing the way we compute the next
instruction. On ARM, it saves at least 3 instructions for GOTO and 4
instructions for IF-XX/Z.
This CL also transforms the Instruction::At CHECK into a DCHECK. This improves
the compiled code when computing next instruction.
Change-Id: I901699201012d2dbbaef4d9158cc97b63bfbbe84
diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc
index 2e87dfd..705e265 100644
--- a/src/interpreter/interpreter.cc
+++ b/src/interpreter/interpreter.cc
@@ -1202,22 +1202,22 @@
}
case Instruction::GOTO: {
PREAMBLE();
- inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegA_10t());
+ inst = inst->RelativeAt(inst->VRegA_10t());
break;
}
case Instruction::GOTO_16: {
PREAMBLE();
- inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegA_20t());
+ inst = inst->RelativeAt(inst->VRegA_20t());
break;
}
case Instruction::GOTO_32: {
PREAMBLE();
- inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegA_30t());
+ inst = inst->RelativeAt(inst->VRegA_30t());
break;
}
case Instruction::PACKED_SWITCH: {
PREAMBLE();
- const uint16_t* switch_data = insns + inst->GetDexPc(insns) + inst->VRegB_31t();
+ const uint16_t* switch_data = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t());
DCHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kPackedSwitchSignature));
uint16_t size = switch_data[1];
@@ -1229,7 +1229,7 @@
DCHECK(IsAligned<4>(targets));
int32_t index = test_val - first_key;
if (index >= 0 && index < size) {
- inst = Instruction::At(insns + inst->GetDexPc(insns) + targets[index]);
+ inst = inst->RelativeAt(targets[index]);
} else {
inst = inst->Next_3xx();
}
@@ -1237,8 +1237,7 @@
}
case Instruction::SPARSE_SWITCH: {
PREAMBLE();
- uint32_t dex_pc = inst->GetDexPc(insns);
- const uint16_t* switch_data = insns + dex_pc + inst->VRegB_31t();
+ const uint16_t* switch_data = reinterpret_cast<const uint16_t*>(inst) + inst->VRegB_31t();
int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t());
CHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kSparseSwitchSignature));
uint16_t size = switch_data[1];
@@ -1249,6 +1248,7 @@
CHECK(IsAligned<4>(entries));
int lo = 0;
int hi = size - 1;
+ const Instruction* current_inst = inst;
inst = inst->Next_3xx();
while (lo <= hi) {
int mid = (lo + hi) / 2;
@@ -1258,7 +1258,7 @@
} else if (test_val > foundVal) {
lo = mid + 1;
} else {
- inst = Instruction::At(insns + dex_pc + entries[mid]);
+ inst = current_inst->RelativeAt(entries[mid]);
break;
}
}
@@ -1348,7 +1348,7 @@
case Instruction::IF_EQ: {
PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_22t()) == shadow_frame.GetVReg(inst->VRegB_22t())) {
- inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegC_22t());
+ inst = inst->RelativeAt(inst->VRegC_22t());
} else {
inst = inst->Next_2xx();
}
@@ -1357,7 +1357,7 @@
case Instruction::IF_NE: {
PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_22t()) != shadow_frame.GetVReg(inst->VRegB_22t())) {
- inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegC_22t());
+ inst = inst->RelativeAt(inst->VRegC_22t());
} else {
inst = inst->Next_2xx();
}
@@ -1366,7 +1366,7 @@
case Instruction::IF_LT: {
PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_22t()) < shadow_frame.GetVReg(inst->VRegB_22t())) {
- inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegC_22t());
+ inst = inst->RelativeAt(inst->VRegC_22t());
} else {
inst = inst->Next_2xx();
}
@@ -1375,7 +1375,7 @@
case Instruction::IF_GE: {
PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_22t()) >= shadow_frame.GetVReg(inst->VRegB_22t())) {
- inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegC_22t());
+ inst = inst->RelativeAt(inst->VRegC_22t());
} else {
inst = inst->Next_2xx();
}
@@ -1384,7 +1384,7 @@
case Instruction::IF_GT: {
PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_22t()) > shadow_frame.GetVReg(inst->VRegB_22t())) {
- inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegC_22t());
+ inst = inst->RelativeAt(inst->VRegC_22t());
} else {
inst = inst->Next_2xx();
}
@@ -1393,7 +1393,7 @@
case Instruction::IF_LE: {
PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_22t()) <= shadow_frame.GetVReg(inst->VRegB_22t())) {
- inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegC_22t());
+ inst = inst->RelativeAt(inst->VRegC_22t());
} else {
inst = inst->Next_2xx();
}
@@ -1402,7 +1402,7 @@
case Instruction::IF_EQZ: {
PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_21t()) == 0) {
- inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegB_21t());
+ inst = inst->RelativeAt(inst->VRegB_21t());
} else {
inst = inst->Next_2xx();
}
@@ -1411,7 +1411,7 @@
case Instruction::IF_NEZ: {
PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_21t()) != 0) {
- inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegB_21t());
+ inst = inst->RelativeAt(inst->VRegB_21t());
} else {
inst = inst->Next_2xx();
}
@@ -1420,7 +1420,7 @@
case Instruction::IF_LTZ: {
PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_21t()) < 0) {
- inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegB_21t());
+ inst = inst->RelativeAt(inst->VRegB_21t());
} else {
inst = inst->Next_2xx();
}
@@ -1429,7 +1429,7 @@
case Instruction::IF_GEZ: {
PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_21t()) >= 0) {
- inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegB_21t());
+ inst = inst->RelativeAt(inst->VRegB_21t());
} else {
inst = inst->Next_2xx();
}
@@ -1438,7 +1438,7 @@
case Instruction::IF_GTZ: {
PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_21t()) > 0) {
- inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegB_21t());
+ inst = inst->RelativeAt(inst->VRegB_21t());
} else {
inst = inst->Next_2xx();
}
@@ -1447,7 +1447,7 @@
case Instruction::IF_LEZ: {
PREAMBLE();
if (shadow_frame.GetVReg(inst->VRegA_21t()) <= 0) {
- inst = Instruction::At(insns + inst->GetDexPc(insns) + inst->VRegB_21t());
+ inst = inst->RelativeAt(inst->VRegB_21t());
} else {
inst = inst->Next_2xx();
}
@@ -2305,6 +2305,14 @@
inst = inst->Next_1xx();
break;
}
+ case Instruction::DIV_INT_2ADDR: {
+ PREAMBLE();
+ uint32_t vregA = inst->VRegA_12x();
+ DoIntDivide(self, shadow_frame, vregA, shadow_frame.GetVReg(vregA),
+ shadow_frame.GetVReg(inst->VRegB_12x()));
+ inst = inst->Next_1xx();
+ break;
+ }
case Instruction::REM_INT_2ADDR: {
PREAMBLE();
uint32_t vregA = inst->VRegA_12x();
@@ -2367,14 +2375,6 @@
inst = inst->Next_1xx();
break;
}
- case Instruction::DIV_INT_2ADDR: {
- PREAMBLE();
- uint32_t vregA = inst->VRegA_12x();
- DoIntDivide(self, shadow_frame, vregA, shadow_frame.GetVReg(vregA),
- shadow_frame.GetVReg(inst->VRegB_12x()));
- inst = inst->Next_1xx();
- break;
- }
case Instruction::ADD_LONG_2ADDR: {
PREAMBLE();
uint32_t vregA = inst->VRegA_12x();