diff options
author | Mathieu Chartier <mathieuc@google.com> | 2014-09-26 14:32:37 -0700 |
---|---|---|
committer | Mathieu Chartier <mathieuc@google.com> | 2014-09-26 19:54:39 -0700 |
commit | 76433275dbe39e5ced1c223b006d1b900b1937f6 (patch) | |
tree | a72c101defa86ceff8b633cf2eaa606c87f783eb /runtime/reflection.cc | |
parent | 88adf36315237947d3a5d10b28fdf8b9da7794a4 (diff) | |
download | android_art-76433275dbe39e5ced1c223b006d1b900b1937f6.tar.gz android_art-76433275dbe39e5ced1c223b006d1b900b1937f6.tar.bz2 android_art-76433275dbe39e5ced1c223b006d1b900b1937f6.zip |
Optimize get/set reflection performance
Speedups mostly from reducing how often access checks are needed,
and adding more inlining, and adding templates.
Field_getInt from ~850ns -> 350ns.
Field_setInt from ~900ns -> 370ns.
Bug: 14063288
(cherry picked from commit ffc788cb7b5b9f53734d7bb8af2d5e45d885546b)
Change-Id: I2441581ff3478c6ae43b6aa49939ff3f07555ec8
Diffstat (limited to 'runtime/reflection.cc')
-rw-r--r-- | runtime/reflection.cc | 95 |
1 files changed, 10 insertions, 85 deletions
diff --git a/runtime/reflection.cc b/runtime/reflection.cc index 9fe296a6b1..0705d402b6 100644 --- a/runtime/reflection.cc +++ b/runtime/reflection.cc @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "reflection.h" +#include "reflection-inl.h" #include "class_linker.h" #include "common_throws.h" @@ -592,7 +592,7 @@ jobject InvokeMethod(const ScopedObjectAccessAlreadyRunnable& soa, jobject javaM } // If method is not set to be accessible, verify it can be accessed by the caller. - if (!accessible && !VerifyAccess(receiver, declaring_class, m->GetAccessFlags())) { + if (!accessible && !VerifyAccess(soa.Self(), receiver, declaring_class, m->GetAccessFlags())) { ThrowIllegalAccessException(nullptr, StringPrintf("Cannot access method: %s", PrettyMethod(m).c_str()).c_str()); return nullptr; @@ -644,80 +644,6 @@ bool VerifyObjectIsClass(mirror::Object* o, mirror::Class* c) { return true; } -bool ConvertPrimitiveValue(const ThrowLocation* throw_location, bool unbox_for_result, - Primitive::Type srcType, Primitive::Type dstType, - const JValue& src, JValue* dst) { - DCHECK(srcType != Primitive::kPrimNot && dstType != Primitive::kPrimNot); - if (LIKELY(srcType == dstType)) { - dst->SetJ(src.GetJ()); - return true; - } - switch (dstType) { - case Primitive::kPrimBoolean: // Fall-through. - case Primitive::kPrimChar: // Fall-through. - case Primitive::kPrimByte: - // Only expect assignment with source and destination of identical type. - break; - case Primitive::kPrimShort: - if (srcType == Primitive::kPrimByte) { - dst->SetS(src.GetI()); - return true; - } - break; - case Primitive::kPrimInt: - if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar || - srcType == Primitive::kPrimShort) { - dst->SetI(src.GetI()); - return true; - } - break; - case Primitive::kPrimLong: - if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar || - srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) { - dst->SetJ(src.GetI()); - return true; - } - break; - case Primitive::kPrimFloat: - if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar || - srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) { - dst->SetF(src.GetI()); - return true; - } else if (srcType == Primitive::kPrimLong) { - dst->SetF(src.GetJ()); - return true; - } - break; - case Primitive::kPrimDouble: - if (srcType == Primitive::kPrimByte || srcType == Primitive::kPrimChar || - srcType == Primitive::kPrimShort || srcType == Primitive::kPrimInt) { - dst->SetD(src.GetI()); - return true; - } else if (srcType == Primitive::kPrimLong) { - dst->SetD(src.GetJ()); - return true; - } else if (srcType == Primitive::kPrimFloat) { - dst->SetD(src.GetF()); - return true; - } - break; - default: - break; - } - if (!unbox_for_result) { - ThrowIllegalArgumentException(throw_location, - StringPrintf("Invalid primitive conversion from %s to %s", - PrettyDescriptor(srcType).c_str(), - PrettyDescriptor(dstType).c_str()).c_str()); - } else { - ThrowClassCastException(throw_location, - StringPrintf("Couldn't convert result of type %s to %s", - PrettyDescriptor(srcType).c_str(), - PrettyDescriptor(dstType).c_str()).c_str()); - } - return false; -} - mirror::Object* BoxPrimitive(Primitive::Type src_class, const JValue& value) { if (src_class == Primitive::kPrimNot) { return value.GetL(); @@ -889,16 +815,18 @@ bool UnboxPrimitiveForResult(const ThrowLocation& throw_location, mirror::Object return UnboxPrimitive(&throw_location, o, dst_class, nullptr, unboxed_value); } -bool VerifyAccess(mirror::Object* obj, mirror::Class* declaring_class, uint32_t access_flags) { - NthCallerVisitor visitor(Thread::Current(), 2); +bool VerifyAccess(Thread* self, mirror::Object* obj, mirror::Class* declaring_class, uint32_t access_flags) { + if ((access_flags & kAccPublic) != 0) { + return true; + } + NthCallerVisitor visitor(self, 2); visitor.WalkStack(); if (UNLIKELY(visitor.caller == nullptr)) { // The caller is an attached native thread. - return (access_flags & kAccPublic) != 0; + return false; } mirror::Class* caller_class = visitor.caller->GetDeclaringClass(); - - if (((access_flags & kAccPublic) != 0) || (caller_class == declaring_class)) { + if (caller_class == declaring_class) { return true; } if ((access_flags & kAccPrivate) != 0) { @@ -912,10 +840,7 @@ bool VerifyAccess(mirror::Object* obj, mirror::Class* declaring_class, uint32_t return true; } } - if (!declaring_class->IsInSamePackage(caller_class)) { - return false; - } - return true; + return declaring_class->IsInSamePackage(caller_class); } } // namespace art |