Add AccessibleObject and Field to mirror

Main motivation is to remove all the functionality / field access on
java side to ArtField. Also comes with some reflection speedups /
slowdowns.

Summary results:
getDeclaredField/getField are slower mostly due to JNI overhead.
However, there is a large speedup in getInt, setInt,
GetInstanceField, and GetStaticField.

Before timings (N5 --compiler-filter=everything):

                       benchmark      ns linear runtime
          Class_getDeclaredField  782.86 ===
                  Class_getField  832.77 ===
                    Field_getInt  160.17 =
                    Field_setInt  195.88 =
                GetInstanceField 3214.38 ==============
                  GetStaticField 6809.49 ==============================

After:
          Class_getDeclaredField 1068.15 ============
                  Class_getField 1180.00 ==============
                    Field_getInt  121.85 =
                    Field_setInt  139.98 =
                GetInstanceField 1986.15 =======================
                  GetStaticField 2523.63 ==============================

Bug: 19264997

Change-Id: Ic0d0fc1b56b95cd6d60f8e76f19caeaa23045c77
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 60d14e9..3cb6b36 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -17,21 +17,28 @@
 #include "java_lang_Class.h"
 
 #include "class_linker.h"
+#include "common_throws.h"
 #include "dex_file-inl.h"
 #include "jni_internal.h"
 #include "nth_caller_visitor.h"
+#include "mirror/art_field-inl.h"
 #include "mirror/class-inl.h"
 #include "mirror/class_loader.h"
+#include "mirror/field.h"
 #include "mirror/object-inl.h"
+#include "mirror/object_array-inl.h"
+#include "mirror/string-inl.h"
 #include "scoped_thread_state_change.h"
 #include "scoped_fast_native_object_access.h"
 #include "ScopedLocalRef.h"
 #include "ScopedUtfChars.h"
+#include "utf.h"
 #include "well_known_classes.h"
 
 namespace art {
 
-static mirror::Class* DecodeClass(const ScopedFastNativeObjectAccess& soa, jobject java_class)
+ALWAYS_INLINE static inline mirror::Class* DecodeClass(
+    const ScopedFastNativeObjectAccess& soa, jobject java_class)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   mirror::Class* c = soa.Decode<mirror::Class*>(java_class);
   DCHECK(c != NULL);
@@ -97,10 +104,170 @@
   return soa.AddLocalReference<jobjectArray>(c->GetInterfaces()->Clone(soa.Self()));
 }
 
+static mirror::ObjectArray<mirror::Field>* GetDeclaredFields(
+    Thread* self, mirror::Class* klass, bool public_only, bool force_resolve)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  StackHandleScope<3> hs(self);
+  auto h_ifields = hs.NewHandle(klass->GetIFields());
+  auto h_sfields = hs.NewHandle(klass->GetSFields());
+  const int32_t num_ifields = h_ifields.Get() != nullptr ? h_ifields->GetLength() : 0;
+  const int32_t num_sfields = h_sfields.Get() != nullptr ? h_sfields->GetLength() : 0;
+  int32_t array_size = num_ifields + num_sfields;
+  if (public_only) {
+    // Lets go subtract all the non public fields.
+    for (int32_t i = 0; i < num_ifields; ++i) {
+      if (!h_ifields->GetWithoutChecks(i)->IsPublic()) {
+        --array_size;
+      }
+    }
+    for (int32_t i = 0; i < num_sfields; ++i) {
+      if (!h_sfields->GetWithoutChecks(i)->IsPublic()) {
+        --array_size;
+      }
+    }
+  }
+  int32_t array_idx = 0;
+  auto object_array = hs.NewHandle(mirror::ObjectArray<mirror::Field>::Alloc(
+      self, mirror::Field::ArrayClass(), array_size));
+  if (object_array.Get() == nullptr) {
+    return nullptr;
+  }
+  for (int32_t i = 0; i < num_ifields; ++i) {
+    auto* art_field = h_ifields->GetWithoutChecks(i);
+    if (!public_only || art_field->IsPublic()) {
+      auto* field = mirror::Field::CreateFromArtField(self, art_field, force_resolve);
+      if (field == nullptr) {
+        if (kIsDebugBuild) {
+          self->AssertPendingException();
+        }
+        // Maybe null due to OOME or type resolving exception.
+        return nullptr;
+      }
+      object_array->SetWithoutChecks<false>(array_idx++, field);
+    }
+  }
+  for (int32_t i = 0; i < num_sfields; ++i) {
+    auto* art_field = h_sfields->GetWithoutChecks(i);
+    if (!public_only || art_field->IsPublic()) {
+      auto* field = mirror::Field::CreateFromArtField(self, art_field, force_resolve);
+      if (field == nullptr) {
+        if (kIsDebugBuild) {
+          self->AssertPendingException();
+        }
+        return nullptr;
+      }
+      object_array->SetWithoutChecks<false>(array_idx++, field);
+    }
+  }
+  CHECK_EQ(array_idx, array_size);
+  return object_array.Get();
+}
+
+static jobjectArray Class_getDeclaredFieldsUnchecked(JNIEnv* env, jobject javaThis,
+                                                     jboolean publicOnly) {
+  ScopedFastNativeObjectAccess soa(env);
+  return soa.AddLocalReference<jobjectArray>(
+      GetDeclaredFields(soa.Self(), DecodeClass(soa, javaThis), publicOnly != JNI_FALSE, false));
+}
+
+static jobjectArray Class_getDeclaredFields(JNIEnv* env, jobject javaThis) {
+  ScopedFastNativeObjectAccess soa(env);
+  return soa.AddLocalReference<jobjectArray>(
+      GetDeclaredFields(soa.Self(), DecodeClass(soa, javaThis), false, true));
+}
+
+static jobjectArray Class_getPublicDeclaredFields(JNIEnv* env, jobject javaThis) {
+  ScopedFastNativeObjectAccess soa(env);
+  return soa.AddLocalReference<jobjectArray>(
+      GetDeclaredFields(soa.Self(), DecodeClass(soa, javaThis), true, true));
+}
+
+// Performs a binary search through an array of fields, TODO: Is this fast enough if we don't use
+// the dex cache for lookups? I think CompareModifiedUtf8ToUtf16AsCodePointValues should be fairly
+// fast.
+ALWAYS_INLINE static inline mirror::ArtField* FindFieldByName(
+    Thread* self ATTRIBUTE_UNUSED, mirror::String* name,
+    mirror::ObjectArray<mirror::ArtField>* fields)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  uint32_t low = 0;
+  uint32_t high = fields->GetLength();
+  const uint16_t* const data = name->GetCharArray()->GetData() + name->GetOffset();
+  const size_t length = name->GetLength();
+  while (low < high) {
+    auto mid = (low + high) / 2;
+    mirror::ArtField* const field = fields->GetWithoutChecks(mid);
+    int result = CompareModifiedUtf8ToUtf16AsCodePointValues(field->GetName(), data, length);
+    // Alternate approach, only a few % faster at the cost of more allocations.
+    // int result = field->GetStringName(self, true)->CompareTo(name);
+    if (result < 0) {
+      low = mid + 1;
+    } else if (result > 0) {
+      high = mid;
+    } else {
+      return field;
+    }
+  }
+  if (kIsDebugBuild) {
+    for (int32_t i = 0; i < fields->GetLength(); ++i) {
+      CHECK_NE(fields->GetWithoutChecks(i)->GetName(), name->ToModifiedUtf8());
+    }
+  }
+  return nullptr;
+}
+
+ALWAYS_INLINE static inline mirror::Field* GetDeclaredField(
+    Thread* self, mirror::Class* c, mirror::String* name)
+    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+  auto* instance_fields = c->GetIFields();
+  if (instance_fields != nullptr) {
+    auto* art_field = FindFieldByName(self, name, instance_fields);
+    if (art_field != nullptr) {
+      return mirror::Field::CreateFromArtField(self, art_field, true);
+    }
+  }
+  auto* static_fields = c->GetSFields();
+  if (static_fields != nullptr) {
+    auto* art_field = FindFieldByName(self, name, static_fields);
+    if (art_field != nullptr) {
+      return mirror::Field::CreateFromArtField(self, art_field, true);
+    }
+  }
+  return nullptr;
+}
+
+static jobject Class_getDeclaredFieldInternal(JNIEnv* env, jobject javaThis, jstring name) {
+  ScopedFastNativeObjectAccess soa(env);
+  auto* name_string = soa.Decode<mirror::String*>(name);
+  return soa.AddLocalReference<jobject>(
+      GetDeclaredField(soa.Self(), DecodeClass(soa, javaThis), name_string));
+}
+
+static jobject Class_getDeclaredField(JNIEnv* env, jobject javaThis, jstring name) {
+  ScopedFastNativeObjectAccess soa(env);
+  auto* name_string = soa.Decode<mirror::String*>(name);
+  if (name == nullptr) {
+    ThrowNullPointerException("name == null");
+    return nullptr;
+  }
+  auto* klass = DecodeClass(soa, javaThis);
+  mirror::Field* result = GetDeclaredField(soa.Self(), klass, name_string);
+  if (result == nullptr) {
+    std::string name_str = name_string->ToModifiedUtf8();
+    soa.Self()->ThrowNewException("Ljava/lang/NoSuchFieldException;", name_str.c_str());
+    return nullptr;
+  }
+  return soa.AddLocalReference<jobject>(result);
+}
+
 static JNINativeMethod gMethods[] = {
   NATIVE_METHOD(Class, classForName, "!(Ljava/lang/String;ZLjava/lang/ClassLoader;)Ljava/lang/Class;"),
   NATIVE_METHOD(Class, getNameNative, "!()Ljava/lang/String;"),
   NATIVE_METHOD(Class, getProxyInterfaces, "!()[Ljava/lang/Class;"),
+  NATIVE_METHOD(Class, getDeclaredFields, "!()[Ljava/lang/reflect/Field;"),
+  NATIVE_METHOD(Class, getPublicDeclaredFields, "!()[Ljava/lang/reflect/Field;"),
+  NATIVE_METHOD(Class, getDeclaredFieldsUnchecked, "!(Z)[Ljava/lang/reflect/Field;"),
+  NATIVE_METHOD(Class, getDeclaredFieldInternal, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"),
+  NATIVE_METHOD(Class, getDeclaredField, "!(Ljava/lang/String;)Ljava/lang/reflect/Field;"),
 };
 
 void register_java_lang_Class(JNIEnv* env) {