diff options
author | Sebastien Hertz <shertz@google.com> | 2013-09-11 14:33:18 +0200 |
---|---|---|
committer | Sebastien Hertz <shertz@google.com> | 2013-09-18 09:24:45 +0200 |
commit | 3b588e09eac6fb2aff64595e2232e479703850fc (patch) | |
tree | 6a6608e3fa027631715e3da671859daed222c6f2 /runtime/interpreter/interpreter_common.h | |
parent | 3523909c99a27729d9a0d6fe3624f09dfadf351c (diff) | |
download | art-3b588e09eac6fb2aff64595e2232e479703850fc.zip art-3b588e09eac6fb2aff64595e2232e479703850fc.tar.gz art-3b588e09eac6fb2aff64595e2232e479703850fc.tar.bz2 |
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
Diffstat (limited to 'runtime/interpreter/interpreter_common.h')
-rw-r--r-- | runtime/interpreter/interpreter_common.h | 50 |
1 files changed, 23 insertions, 27 deletions
diff --git a/runtime/interpreter/interpreter_common.h b/runtime/interpreter/interpreter_common.h index 794891e..ec1f942 100644 --- a/runtime/interpreter/interpreter_common.h +++ b/runtime/interpreter/interpreter_common.h @@ -123,12 +123,12 @@ bool DoInvokeVirtualQuick(Thread* self, ShadowFrame& shadow_frame, // specialization. template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check> static bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame, - const Instruction* inst) + const Instruction* inst, uint16_t inst_data) NO_THREAD_SAFETY_ANALYSIS ALWAYS_INLINE; template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check> static inline bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame, - const Instruction* inst) { + const Instruction* inst, uint16_t inst_data) { bool is_static = (find_type == StaticObjectRead) || (find_type == StaticPrimitiveRead); uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c(); ArtField* f = FindFieldFromCode(field_idx, shadow_frame.GetMethod(), self, @@ -142,13 +142,13 @@ static inline bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame, if (is_static) { obj = f->GetDeclaringClass(); } else { - obj = shadow_frame.GetVRegReference(inst->VRegB_22c()); + obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data)); if (UNLIKELY(obj == NULL)) { ThrowNullPointerExceptionForFieldAccess(shadow_frame.GetCurrentLocationForThrow(), f, true); return false; } } - uint32_t vregA = is_static ? inst->VRegA_21c() : inst->VRegA_22c(); + uint32_t vregA = is_static ? inst->VRegA_21c(inst_data) : inst->VRegA_22c(inst_data); switch (field_type) { case Primitive::kPrimBoolean: shadow_frame.SetVReg(vregA, f->GetBoolean(obj)); @@ -180,14 +180,12 @@ static inline bool DoFieldGet(Thread* self, ShadowFrame& shadow_frame, // TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) which is failing due to template // specialization. template<Primitive::Type field_type> -static bool DoIGetQuick(Thread* self, ShadowFrame& shadow_frame, - const Instruction* inst) +static bool DoIGetQuick(ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data) NO_THREAD_SAFETY_ANALYSIS ALWAYS_INLINE; template<Primitive::Type field_type> -static inline bool DoIGetQuick(Thread* self, ShadowFrame& shadow_frame, - const Instruction* inst) { - Object* obj = shadow_frame.GetVRegReference(inst->VRegB_22c()); +static inline bool DoIGetQuick(ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data) { + Object* obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data)); if (UNLIKELY(obj == NULL)) { // We lost the reference to the field index so we cannot get a more // precised exception message. @@ -196,7 +194,7 @@ static inline bool DoIGetQuick(Thread* self, ShadowFrame& shadow_frame, } MemberOffset field_offset(inst->VRegC_22c()); const bool is_volatile = false; // iget-x-quick only on non volatile fields. - const uint32_t vregA = inst->VRegA_22c(); + const uint32_t vregA = inst->VRegA_22c(inst_data); switch (field_type) { case Primitive::kPrimInt: shadow_frame.SetVReg(vregA, static_cast<int32_t>(obj->GetField32(field_offset, is_volatile))); @@ -217,12 +215,12 @@ static inline bool DoIGetQuick(Thread* self, ShadowFrame& shadow_frame, // specialization. template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check> static bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame, - const Instruction* inst) + const Instruction* inst, uint16_t inst_data) NO_THREAD_SAFETY_ANALYSIS ALWAYS_INLINE; template<FindFieldType find_type, Primitive::Type field_type, bool do_access_check> static inline bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame, - const Instruction* inst) { + const Instruction* inst, uint16_t inst_data) { bool is_static = (find_type == StaticObjectWrite) || (find_type == StaticPrimitiveWrite); uint32_t field_idx = is_static ? inst->VRegB_21c() : inst->VRegC_22c(); ArtField* f = FindFieldFromCode(field_idx, shadow_frame.GetMethod(), self, @@ -236,14 +234,14 @@ static inline bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame, if (is_static) { obj = f->GetDeclaringClass(); } else { - obj = shadow_frame.GetVRegReference(inst->VRegB_22c()); + obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data)); if (UNLIKELY(obj == NULL)) { ThrowNullPointerExceptionForFieldAccess(shadow_frame.GetCurrentLocationForThrow(), f, false); return false; } } - uint32_t vregA = is_static ? inst->VRegA_21c() : inst->VRegA_22c(); + uint32_t vregA = is_static ? inst->VRegA_21c(inst_data) : inst->VRegA_22c(inst_data); switch (field_type) { case Primitive::kPrimBoolean: f->SetBoolean(obj, shadow_frame.GetVReg(vregA)); @@ -275,14 +273,12 @@ static inline bool DoFieldPut(Thread* self, const ShadowFrame& shadow_frame, // TODO: should be SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) which is failing due to template // specialization. template<Primitive::Type field_type> -static bool DoIPutQuick(Thread* self, ShadowFrame& shadow_frame, - const Instruction* inst) +static bool DoIPutQuick(ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data) NO_THREAD_SAFETY_ANALYSIS ALWAYS_INLINE; template<Primitive::Type field_type> -static inline bool DoIPutQuick(Thread* self, ShadowFrame& shadow_frame, - const Instruction* inst) { - Object* obj = shadow_frame.GetVRegReference(inst->VRegB_22c()); +static inline bool DoIPutQuick(ShadowFrame& shadow_frame, const Instruction* inst, uint16_t inst_data) { + Object* obj = shadow_frame.GetVRegReference(inst->VRegB_22c(inst_data)); if (UNLIKELY(obj == NULL)) { // We lost the reference to the field index so we cannot get a more // precised exception message. @@ -291,7 +287,7 @@ static inline bool DoIPutQuick(Thread* self, ShadowFrame& shadow_frame, } MemberOffset field_offset(inst->VRegC_22c()); const bool is_volatile = false; // iput-x-quick only on non volatile fields. - const uint32_t vregA = inst->VRegA_22c(); + const uint32_t vregA = inst->VRegA_22c(inst_data); switch (field_type) { case Primitive::kPrimInt: obj->SetField32(field_offset, shadow_frame.GetVReg(vregA), is_volatile); @@ -387,14 +383,14 @@ static inline bool DoLongRemainder(ShadowFrame& shadow_frame, size_t result_reg, // Returns true on success, otherwise throws an exception and returns false. template <bool is_range, bool do_access_check> bool DoFilledNewArray(const Instruction* inst, const ShadowFrame& shadow_frame, - Thread* self, JValue* result) NO_THREAD_SAFETY_ANALYSIS; + Thread* self, JValue* result) NO_THREAD_SAFETY_ANALYSIS; -static inline int32_t DoPackedSwitch(const Instruction* inst, - const ShadowFrame& shadow_frame) +static inline int32_t DoPackedSwitch(const Instruction* inst, const ShadowFrame& shadow_frame, + uint16_t inst_data) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) { DCHECK(inst->Opcode() == Instruction::PACKED_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()); + int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t(inst_data)); DCHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kPackedSwitchSignature)); uint16_t size = switch_data[1]; DCHECK_GT(size, 0); @@ -412,12 +408,12 @@ static inline int32_t DoPackedSwitch(const Instruction* inst, } } -static inline int32_t DoSparseSwitch(const Instruction* inst, - const ShadowFrame& shadow_frame) +static inline int32_t DoSparseSwitch(const Instruction* inst, const ShadowFrame& shadow_frame, + uint16_t inst_data) 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()); + int32_t test_val = shadow_frame.GetVReg(inst->VRegA_31t(inst_data)); DCHECK_EQ(switch_data[0], static_cast<uint16_t>(Instruction::kSparseSwitchSignature)); uint16_t size = switch_data[1]; DCHECK_GT(size, 0); |