summaryrefslogtreecommitdiff
path: root/runtime/native/java_lang_Class.cc
diff options
context:
space:
mode:
author Alex Light <allight@google.com> 2015-10-01 13:35:09 -0700
committer Alex Light <allight@google.com> 2015-10-01 16:58:42 -0700
commit72f9075e92cfc4632d6c50f282a0f6319b718882 (patch)
tree59da1347488e2298af46017992d0ab9f44c5966a /runtime/native/java_lang_Class.cc
parent9b29f3ef7df18c84d922634709e38a1913709ad7 (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.cc60
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;"),