summaryrefslogtreecommitdiffstats
path: root/runtime/interpreter/interpreter_common.h
diff options
context:
space:
mode:
authorSebastien Hertz <shertz@google.com>2013-09-11 14:33:18 +0200
committerSebastien Hertz <shertz@google.com>2013-09-18 09:24:45 +0200
commit3b588e09eac6fb2aff64595e2232e479703850fc (patch)
tree6a6608e3fa027631715e3da671859daed222c6f2 /runtime/interpreter/interpreter_common.h
parent3523909c99a27729d9a0d6fe3624f09dfadf351c (diff)
downloadart-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.h50
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);