diff options
author | 2013-06-28 10:01:18 +0200 | |
---|---|---|
committer | 2013-07-01 10:11:23 +0200 | |
commit | 2cb33b8f7377f532cebed755be89bb351c150a22 (patch) | |
tree | de5847bf78f6b6f1b9c87bbf3f4a99453014a9ea | |
parent | dfe193532cbbe09a54cb4edfa8626a759b67c116 (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.cc | 55 |
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: { |