summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Sebastien Hertz <shertz@google.com> 2013-06-28 10:01:18 +0200
committer Sebastien Hertz <shertz@google.com> 2013-07-01 10:11:23 +0200
commit2cb33b8f7377f532cebed755be89bb351c150a22 (patch)
treede5847bf78f6b6f1b9c87bbf3f4a99453014a9ea
parentdfe193532cbbe09a54cb4edfa8626a759b67c116 (diff)
Improve SPARSE_SWITCH handling in interpreter.
This CL avoids to set "next" instruction twice. We used to first set "next" instruction to the instruction following the SPARSE_SWITCH. Then, we set it to the instruction corresponding to the entry we find in the table. We now set it only once: either we branch or we continue. Change-Id: Ic93cd0abae00edb1fb952c34bc9031fffc7f4a35
-rw-r--r--src/interpreter/interpreter.cc55
1 files changed, 30 insertions, 25 deletions
diff --git a/src/interpreter/interpreter.cc b/src/interpreter/interpreter.cc
index 39c8f0e02a..1e8ee9c63c 100644
--- a/src/interpreter/interpreter.cc
+++ b/src/interpreter/interpreter.cc
@@ -891,6 +891,35 @@ static inline bool DoFilledNewArray(const Instruction* inst,
return true;
}
+static inline const Instruction* DoSparseSwitch(const Instruction* inst,
+ const ShadowFrame& shadow_frame)
+ SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+ DCHECK(inst->Opcode() == Instruction::SPARSE_SWITCH);
+ 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::kSparseSwitchSignature));
+ uint16_t size = switch_data[1];
+ DCHECK_GT(size, 0);
+ const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]);
+ DCHECK(IsAligned<4>(keys));
+ const int32_t* entries = keys + size;
+ DCHECK(IsAligned<4>(entries));
+ int lo = 0;
+ int hi = size - 1;
+ while (lo <= hi) {
+ int mid = (lo + hi) / 2;
+ int32_t foundVal = keys[mid];
+ if (test_val < foundVal) {
+ hi = mid - 1;
+ } else if (test_val > foundVal) {
+ lo = mid + 1;
+ } else {
+ return inst->RelativeAt(entries[mid]);
+ }
+ }
+ return inst->Next_3xx();
+}
+
static inline const Instruction* FindNextInstructionFollowingException(Thread* self,
ShadowFrame& shadow_frame,
uint32_t dex_pc,
@@ -1427,31 +1456,7 @@ static JValue ExecuteImpl(Thread* self, MethodHelper& mh, const DexFile::CodeIte
}
case Instruction::SPARSE_SWITCH: {
PREAMBLE();
- 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::kSparseSwitchSignature));
- uint16_t size = switch_data[1];
- DCHECK_GT(size, 0);
- const int32_t* keys = reinterpret_cast<const int32_t*>(&switch_data[2]);
- DCHECK(IsAligned<4>(keys));
- const int32_t* entries = keys + size;
- DCHECK(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;
- int32_t foundVal = keys[mid];
- if (test_val < foundVal) {
- hi = mid - 1;
- } else if (test_val > foundVal) {
- lo = mid + 1;
- } else {
- inst = current_inst->RelativeAt(entries[mid]);
- break;
- }
- }
+ inst = DoSparseSwitch(inst, shadow_frame);
break;
}
case Instruction::CMPL_FLOAT: {