diff options
| author | 2015-10-01 13:35:09 -0700 | |
|---|---|---|
| committer | 2015-10-01 16:58:42 -0700 | |
| commit | 72f9075e92cfc4632d6c50f282a0f6319b718882 (patch) | |
| tree | 59da1347488e2298af46017992d0ab9f44c5966a /runtime/native/java_lang_Class.cc | |
| parent | 9b29f3ef7df18c84d922634709e38a1913709ad7 (diff) | |
Move getPublicFieldRecursive to native JNI
Benchmark: libcore/benchmarks/src/benchmarks/regression/ReflectionBenchmark.java
Previous benchmarks:
Class_getField 814.26 ns; σ=6.44 ns @ 3 trials
GetInterfaceStaticField 1552.28 ns; σ=38.22 ns @ 10 trials
GetSuperClassField 939.85 ns; σ=2.94 ns @ 3 trials
New benchmarks:
Class_getField 735.97 ns; σ=0.98 ns @ 3 trials
GetInterfaceStaticField 1178.98 ns; σ=6.14 ns @ 3 trials
GetSuperClassField 853.76 ns; σ=16.86 ns @ 10 trials
Bug: 24209213
Change-Id: I08073cb36b007ac33af010dab917a6f1e51107c0
Diffstat (limited to 'runtime/native/java_lang_Class.cc')
| -rw-r--r-- | runtime/native/java_lang_Class.cc | 60 |
1 files changed, 60 insertions, 0 deletions
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc index 8fd6849363..5da15df25b 100644 --- a/runtime/native/java_lang_Class.cc +++ b/runtime/native/java_lang_Class.cc @@ -229,6 +229,65 @@ ALWAYS_INLINE static inline mirror::Field* GetDeclaredField( return nullptr; } +static mirror::Field* GetPublicFieldRecursive( + Thread* self, mirror::Class* clazz, mirror::String* name) + SHARED_REQUIRES(Locks::mutator_lock_) { + DCHECK(clazz != nullptr); + DCHECK(name != nullptr); + DCHECK(self != nullptr); + + StackHandleScope<1> hs(self); + MutableHandle<mirror::Class> h_clazz(hs.NewHandle(clazz)); + + // We search the current class, its direct interfaces then its superclass. + while (h_clazz.Get() != nullptr) { + mirror::Field* result = GetDeclaredField(self, h_clazz.Get(), name); + if ((result != nullptr) && (result->GetAccessFlags() & kAccPublic)) { + return result; + } else if (UNLIKELY(self->IsExceptionPending())) { + // Something went wrong. Bail out. + return nullptr; + } + + uint32_t num_direct_interfaces = h_clazz->NumDirectInterfaces(); + for (uint32_t i = 0; i < num_direct_interfaces; i++) { + mirror::Class *iface = mirror::Class::GetDirectInterface(self, h_clazz, i); + if (UNLIKELY(iface == nullptr)) { + self->AssertPendingException(); + return nullptr; + } + result = GetPublicFieldRecursive(self, iface, name); + if (result != nullptr) { + DCHECK(result->GetAccessFlags() & kAccPublic); + return result; + } else if (UNLIKELY(self->IsExceptionPending())) { + // Something went wrong. Bail out. + return nullptr; + } + } + + // We don't try the superclass if we are an interface. + if (h_clazz->IsInterface()) { + break; + } + + // Get the next class. + h_clazz.Assign(h_clazz->GetSuperClass()); + } + return nullptr; +} + +static jobject Class_getPublicFieldRecursive(JNIEnv* env, jobject javaThis, jstring name) { + ScopedFastNativeObjectAccess soa(env); + auto* name_string = soa.Decode<mirror::String*>(name); + if (UNLIKELY(name_string == nullptr)) { + ThrowNullPointerException("name == null"); + return nullptr; + } + return soa.AddLocalReference<jobject>( + GetPublicFieldRecursive(soa.Self(), DecodeClass(soa, javaThis), name_string)); +} + static jobject Class_getDeclaredFieldInternal(JNIEnv* env, jobject javaThis, jstring name) { ScopedFastNativeObjectAccess soa(env); auto* name_string = soa.Decode<mirror::String*>(name); @@ -678,6 +737,7 @@ static JNINativeMethod gMethods[] = { "!([Ljava/lang/Class;)Ljava/lang/reflect/Constructor;"), NATIVE_METHOD(Class, getDeclaredConstructorsInternal, "!(Z)[Ljava/lang/reflect/Constructor;"), NATIVE_METHOD(Class, getDeclaredField, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"), + NATIVE_METHOD(Class, getPublicFieldRecursive, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"), NATIVE_METHOD(Class, getDeclaredFieldInternal, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"), NATIVE_METHOD(Class, getDeclaredFields, "!()[Ljava/lang/reflect/Field;"), NATIVE_METHOD(Class, getDeclaredFieldsUnchecked, "!(Z)[Ljava/lang/reflect/Field;"), |