diff options
author | Vladimir Marko <vmarko@google.com> | 2015-04-09 14:13:13 +0100 |
---|---|---|
committer | Vladimir Marko <vmarko@google.com> | 2015-04-10 18:46:03 +0100 |
commit | c136312832d4be25db2ecc5673967d71d0ad4b9c (patch) | |
tree | b9cdcccdd947632b2031ae2b4c3a9c3658ef3366 | |
parent | 1576be32be4a99a1cffdaaf209a3cd67e8b2f88a (diff) | |
download | art-c136312832d4be25db2ecc5673967d71d0ad4b9c.zip art-c136312832d4be25db2ecc5673967d71d0ad4b9c.tar.gz art-c136312832d4be25db2ecc5673967d71d0ad4b9c.tar.bz2 |
Avoid using dex cache array pointers in libart.
In preparation for making dex cache arrays native, avoid
using them in Java code.
This causes a performance regression for our reflection
benchmarks. Class_getDeclaredMethod and Class_getMethod
take an up to 30% hit, measured using the Quick compiler.
We accept this hit at this stage and we will tune the
performance after we're done with the larger effort.
Companion libcore/ change:
https://android-review.googlesource.com/146069
Bug: 20134538
Change-Id: Ibbef3b50043a1311cd40723ed42e1f1c609b8fc1
-rw-r--r-- | runtime/mirror/art_method-inl.h | 2 | ||||
-rw-r--r-- | runtime/mirror/art_method.h | 13 | ||||
-rw-r--r-- | runtime/mirror/dex_cache-inl.h | 2 | ||||
-rw-r--r-- | runtime/native/java_lang_Class.cc | 14 | ||||
-rw-r--r-- | runtime/native/java_lang_DexCache.cc | 30 |
5 files changed, 52 insertions, 9 deletions
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h index 0ccf5db..fb427dc 100644 --- a/runtime/mirror/art_method-inl.h +++ b/runtime/mirror/art_method-inl.h @@ -36,7 +36,7 @@ namespace art { namespace mirror { inline uint32_t ArtMethod::ClassSize() { - uint32_t vtable_entries = Object::kVTableLength + 8; + uint32_t vtable_entries = Object::kVTableLength + 7; return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0); } diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h index 22481ce..55b8068 100644 --- a/runtime/mirror/art_method.h +++ b/runtime/mirror/art_method.h @@ -183,6 +183,10 @@ class MANAGED ArtMethod FINAL : public Object { SetField32<false>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_), new_method_index); } + static MemberOffset DexMethodIndexOffset() { + return OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_method_index_); + } + static MemberOffset MethodIndexOffset() { return OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_); } @@ -214,6 +218,8 @@ class MANAGED ArtMethod FINAL : public Object { return OFFSET_OF_OBJECT_MEMBER(ArtMethod, dex_cache_resolved_types_); } + ALWAYS_INLINE ObjectArray<ArtMethod>* GetDexCacheResolvedMethods() + SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); ALWAYS_INLINE ArtMethod* GetDexCacheResolvedMethod(uint16_t method_idx) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); ALWAYS_INLINE void SetDexCacheResolvedMethod(uint16_t method_idx, ArtMethod* new_method) @@ -434,10 +440,6 @@ class MANAGED ArtMethod FINAL : public Object { EntryPointFromJniOffset(pointer_size), entrypoint, pointer_size); } - static MemberOffset GetMethodIndexOffset() { - return OFFSET_OF_OBJECT_MEMBER(ArtMethod, method_index_); - } - // Is this a CalleSaveMethod or ResolutionMethod and therefore doesn't adhere to normal // conventions for a method of managed code. Returns false for Proxy methods. bool IsRuntimeMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); @@ -604,9 +606,6 @@ class MANAGED ArtMethod FINAL : public Object { private: ALWAYS_INLINE void CheckObjectSizeEqualsMirrorSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ALWAYS_INLINE ObjectArray<ArtMethod>* GetDexCacheResolvedMethods() - SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); - ALWAYS_INLINE ObjectArray<Class>* GetDexCacheResolvedTypes() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_); diff --git a/runtime/mirror/dex_cache-inl.h b/runtime/mirror/dex_cache-inl.h index 288e88e..6758e22 100644 --- a/runtime/mirror/dex_cache-inl.h +++ b/runtime/mirror/dex_cache-inl.h @@ -27,7 +27,7 @@ namespace art { namespace mirror { inline uint32_t DexCache::ClassSize() { - uint32_t vtable_entries = Object::kVTableLength + 1; + uint32_t vtable_entries = Object::kVTableLength + 5; return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0); } diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc index c893f0a..b657aec 100644 --- a/runtime/native/java_lang_Class.cc +++ b/runtime/native/java_lang_Class.cc @@ -91,6 +91,18 @@ static jclass Class_classForName(JNIEnv* env, jclass, jstring javaName, jboolean return soa.AddLocalReference<jclass>(c.Get()); } +static jobject Class_findOverriddenMethodIfProxy(JNIEnv* env, jclass, jobject art_method) { + ScopedFastNativeObjectAccess soa(env); + mirror::ArtMethod* method = soa.Decode<mirror::ArtMethod*>(art_method); + mirror::Class* declaring_klass = method->GetDeclaringClass(); + if (!declaring_klass->IsProxyClass()) { + return art_method; + } + uint32_t dex_method_index = method->GetDexMethodIndex(); + mirror::ArtMethod* overriden_method = method->GetDexCacheResolvedMethods()->Get(dex_method_index); + return soa.AddLocalReference<jobject>(overriden_method); +} + static jstring Class_getNameNative(JNIEnv* env, jobject javaThis) { ScopedFastNativeObjectAccess soa(env); StackHandleScope<1> hs(soa.Self()); @@ -264,6 +276,8 @@ static jobject Class_getDeclaredField(JNIEnv* env, jobject javaThis, jstring nam static JNINativeMethod gMethods[] = { NATIVE_METHOD(Class, classForName, "!(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"), + NATIVE_METHOD(Class, findOverriddenMethodIfProxy, + "!(Ljava/lang/reflect/ArtMethod;)Ljava/lang/reflect/ArtMethod;"), NATIVE_METHOD(Class, getNameNative, "!()Ljava/lang/String;"), NATIVE_METHOD(Class, getProxyInterfaces, "!()[Ljava/lang/Class;"), NATIVE_METHOD(Class, getDeclaredFields, "!()[Ljava/lang/reflect/Field;"), diff --git a/runtime/native/java_lang_DexCache.cc b/runtime/native/java_lang_DexCache.cc index 27eae46..8944270 100644 --- a/runtime/native/java_lang_DexCache.cc +++ b/runtime/native/java_lang_DexCache.cc @@ -48,8 +48,38 @@ static jobject DexCache_getDexNative(JNIEnv* env, jobject javaDexCache) { args); } +static jobject DexCache_getResolvedType(JNIEnv* env, jobject javaDexCache, jint type_index) { + ScopedFastNativeObjectAccess soa(env); + mirror::DexCache* dex_cache = soa.Decode<mirror::DexCache*>(javaDexCache); + return soa.AddLocalReference<jobject>(dex_cache->GetResolvedType(type_index)); +} + +static jobject DexCache_getResolvedString(JNIEnv* env, jobject javaDexCache, jint string_index) { + ScopedFastNativeObjectAccess soa(env); + mirror::DexCache* dex_cache = soa.Decode<mirror::DexCache*>(javaDexCache); + return soa.AddLocalReference<jobject>(dex_cache->GetResolvedString(string_index)); +} + +static void DexCache_setResolvedType(JNIEnv* env, jobject javaDexCache, jint type_index, + jobject type) { + ScopedFastNativeObjectAccess soa(env); + mirror::DexCache* dex_cache = soa.Decode<mirror::DexCache*>(javaDexCache); + dex_cache->SetResolvedType(type_index, soa.Decode<mirror::Class*>(type)); +} + +static void DexCache_setResolvedString(JNIEnv* env, jobject javaDexCache, jint string_index, + jobject string) { + ScopedFastNativeObjectAccess soa(env); + mirror::DexCache* dex_cache = soa.Decode<mirror::DexCache*>(javaDexCache); + dex_cache->SetResolvedString(string_index, soa.Decode<mirror::String*>(string)); +} + static JNINativeMethod gMethods[] = { NATIVE_METHOD(DexCache, getDexNative, "!()Lcom/android/dex/Dex;"), + NATIVE_METHOD(DexCache, getResolvedType, "!(I)Ljava/lang/Class;"), + NATIVE_METHOD(DexCache, getResolvedString, "!(I)Ljava/lang/String;"), + NATIVE_METHOD(DexCache, setResolvedType, "!(ILjava/lang/Class;)V"), + NATIVE_METHOD(DexCache, setResolvedString, "!(ILjava/lang/String;)V"), }; void register_java_lang_DexCache(JNIEnv* env) { |