Add AbstractMethod, Constructor, Method

Moves functionality to ART from libcore. Precursor to moving
ArtMethods to native. Mostly performance improvements.

N5 perf before (irrelevant results removed):
            Class_getConstructor  962.87 ===========
         Class_getDeclaredMethod 2394.37 ============================
                 Class_getMethod 2509.20 ==============================
               Class_newInstance 1999.81 =======================
                  Method_invokeI 1439.02 =================
          Method_invokePreBoxedI 1415.82 ================
            Method_invokeStaticI 1456.24 =================
    Method_invokeStaticPreBoxedI 1427.32 =================
            Method_invokeStaticV  814.47 =========
                  Method_invokeV  816.56 =========
After:
                       benchmark      ns linear runtime
            Class_getConstructor 1302.04 ================
         Class_getDeclaredMethod 1459.01 ==================
                 Class_getMethod 1560.40 ===================
               Class_newInstance 2029.94 =========================
                  Method_invokeI 1312.89 ================
          Method_invokePreBoxedI 1255.01 ===============
            Method_invokeStaticI 1289.13 ===============
    Method_invokeStaticPreBoxedI 1196.52 ==============
            Method_invokeStaticV  790.82 =========
                  Method_invokeV  791.73 =========

Performance improvements are more than just fixing regressions introduced
in: http://android-review.googlesource.com/#/c/146069/

Bug: 19264997

Change-Id: Ife79c469fdb09f30e3aefcfc3e0ce5ed32303fce
diff --git a/runtime/mirror/abstract_method.cc b/runtime/mirror/abstract_method.cc
new file mode 100644
index 0000000..81c656b
--- /dev/null
+++ b/runtime/mirror/abstract_method.cc
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "abstract_method.h"
+
+#include "mirror/art_method-inl.h"
+
+namespace art {
+namespace mirror {
+
+bool AbstractMethod::CreateFromArtMethod(mirror::ArtMethod* method) {
+  auto* interface_method = method->GetInterfaceMethodIfProxy();
+  SetFieldObject<false>(ArtMethodOffset(), method);
+  SetFieldObject<false>(DeclaringClassOffset(), method->GetDeclaringClass());
+  SetFieldObject<false>(
+      DeclaringClassOfOverriddenMethodOffset(), interface_method->GetDeclaringClass());
+  SetField32<false>(AccessFlagsOffset(), method->GetAccessFlags());
+  SetField32<false>(DexMethodIndexOffset(), method->GetDexMethodIndex());
+  return true;
+}
+
+mirror::ArtMethod* AbstractMethod::GetArtMethod() {
+  return GetFieldObject<mirror::ArtMethod>(ArtMethodOffset());
+}
+
+mirror::Class* AbstractMethod::GetDeclaringClass() {
+  return GetFieldObject<mirror::Class>(DeclaringClassOffset());
+}
+
+}  // namespace mirror
+}  // namespace art
diff --git a/runtime/mirror/abstract_method.h b/runtime/mirror/abstract_method.h
new file mode 100644
index 0000000..ef51d7f
--- /dev/null
+++ b/runtime/mirror/abstract_method.h
@@ -0,0 +1,73 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_ABSTRACT_METHOD_H_
+#define ART_RUNTIME_MIRROR_ABSTRACT_METHOD_H_
+
+#include "accessible_object.h"
+#include "gc_root.h"
+#include "object.h"
+#include "object_callbacks.h"
+#include "read_barrier_option.h"
+
+namespace art {
+
+struct AbstractMethodOffsets;
+
+namespace mirror {
+
+class ArtMethod;
+
+// C++ mirror of java.lang.reflect.AbstractMethod.
+class MANAGED AbstractMethod : public AccessibleObject {
+ public:
+  // Called from Constructor::CreateFromArtMethod, Method::CreateFromArtMethod.
+  bool CreateFromArtMethod(mirror::ArtMethod* method) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  mirror::ArtMethod* GetArtMethod() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  mirror::Class* GetDeclaringClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ private:
+  static MemberOffset ArtMethodOffset() {
+    return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, art_method_));
+  }
+  static MemberOffset DeclaringClassOffset() {
+    return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, declaring_class_));
+  }
+  static MemberOffset DeclaringClassOfOverriddenMethodOffset() {
+    return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, declaring_class_of_overridden_method_));
+  }
+  static MemberOffset AccessFlagsOffset() {
+    return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, access_flags_));
+  }
+  static MemberOffset DexMethodIndexOffset() {
+    return MemberOffset(OFFSETOF_MEMBER(AbstractMethod, dex_method_index_));
+  }
+
+  HeapReference<mirror::ArtMethod> art_method_;
+  HeapReference<mirror::Class> declaring_class_;
+  HeapReference<mirror::Class> declaring_class_of_overridden_method_;
+  uint32_t access_flags_;
+  uint32_t dex_method_index_;
+
+  friend struct art::AbstractMethodOffsets;  // for verifying offset information
+  DISALLOW_IMPLICIT_CONSTRUCTORS(AbstractMethod);
+};
+
+}  // namespace mirror
+}  // namespace art
+
+#endif  // ART_RUNTIME_MIRROR_ABSTRACT_METHOD_H_
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index a300d52..5fc96ad 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -36,7 +36,7 @@
 namespace mirror {
 
 inline uint32_t ArtMethod::ClassSize() {
-  uint32_t vtable_entries = Object::kVTableLength + 7;
+  uint32_t vtable_entries = Object::kVTableLength;
   return Class::ComputeClassSize(true, vtable_entries, 0, 0, 0, 0, 0);
 }
 
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index 92aea1f..9483ba6 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -16,6 +16,7 @@
 
 #include "art_method.h"
 
+#include "abstract_method.h"
 #include "arch/context.h"
 #include "art_field-inl.h"
 #include "art_method-inl.h"
@@ -53,14 +54,11 @@
 
 ArtMethod* ArtMethod::FromReflectedMethod(const ScopedObjectAccessAlreadyRunnable& soa,
                                           jobject jlr_method) {
-  ArtField* f =
-      soa.DecodeField(WellKnownClasses::java_lang_reflect_AbstractMethod_artMethod);
-  mirror::ArtMethod* method = f->GetObject(soa.Decode<mirror::Object*>(jlr_method))->AsArtMethod();
-  DCHECK(method != nullptr);
-  return method;
+  auto* abstract_method = soa.Decode<mirror::AbstractMethod*>(jlr_method);
+  DCHECK(abstract_method != nullptr);
+  return abstract_method->GetArtMethod();
 }
 
-
 void ArtMethod::VisitRoots(RootVisitor* visitor) {
   java_lang_reflect_ArtMethod_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
 }
@@ -547,5 +545,31 @@
   RegisterNative(GetJniDlsymLookupStub(), false);
 }
 
+bool ArtMethod::EqualParameters(Handle<mirror::ObjectArray<mirror::Class>> params) {
+  auto* dex_cache = GetDexCache();
+  auto* dex_file = dex_cache->GetDexFile();
+  const auto& method_id = dex_file->GetMethodId(GetDexMethodIndex());
+  const auto& proto_id = dex_file->GetMethodPrototype(method_id);
+  const DexFile::TypeList* proto_params = dex_file->GetProtoParameters(proto_id);
+  auto count = proto_params != nullptr ? proto_params->Size() : 0u;
+  auto param_len = params.Get() != nullptr ? params->GetLength() : 0u;
+  if (param_len != count) {
+    return false;
+  }
+  auto* cl = Runtime::Current()->GetClassLinker();
+  for (size_t i = 0; i < count; ++i) {
+    auto type_idx = proto_params->GetTypeItem(i).type_idx_;
+    auto* type = cl->ResolveType(type_idx, this);
+    if (type == nullptr) {
+      Thread::Current()->AssertPendingException();
+      return false;
+    }
+    if (type != params->GetWithoutChecks(i)) {
+      return false;
+    }
+  }
+  return true;
+}
+
 }  // namespace mirror
 }  // namespace art
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index 55b8068..b899b25 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -541,6 +541,10 @@
 
   ALWAYS_INLINE ArtMethod* GetInterfaceMethodIfProxy() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  // May cause thread suspension due to class resolution.
+  bool EqualParameters(Handle<mirror::ObjectArray<mirror::Class>> params)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   static size_t SizeWithoutPointerFields(size_t pointer_size) {
     size_t total = sizeof(ArtMethod) - sizeof(PtrSizedFields);
 #ifdef ART_METHOD_HAS_PADDING_FIELD_ON_64_BIT
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 2afb4af..1739019 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -25,6 +25,7 @@
 #include "dex_file-inl.h"
 #include "gc/accounting/card_table-inl.h"
 #include "handle_scope-inl.h"
+#include "method.h"
 #include "object_array-inl.h"
 #include "object-inl.h"
 #include "runtime.h"
@@ -876,5 +877,26 @@
   return Runtime::Current()->GetClassLinker()->GetDescriptorForProxy(this) == match;
 }
 
+mirror::ArtMethod* Class::GetDeclaredConstructor(
+    Thread* self, Handle<mirror::ObjectArray<mirror::Class>> args) {
+  auto* direct_methods = GetDirectMethods();
+  size_t count = direct_methods != nullptr ? direct_methods->GetLength() : 0u;
+  for (size_t i = 0; i < count; ++i) {
+    auto* m = direct_methods->GetWithoutChecks(i);
+    // Skip <clinit> which is a static constructor, as well as non constructors.
+    if (m->IsStatic() || !m->IsConstructor()) {
+      continue;
+    }
+    // May cause thread suspension and exceptions.
+    if (m->EqualParameters(args)) {
+      return m;
+    }
+    if (self->IsExceptionPending()) {
+      return nullptr;
+    }
+  }
+  return nullptr;
+}
+
 }  // namespace mirror
 }  // namespace art
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 20f2387..5005346 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -47,6 +47,7 @@
 
 class ArtMethod;
 class ClassLoader;
+class Constructor;
 class DexCache;
 class IfTable;
 
@@ -1052,6 +1053,11 @@
     return OFFSET_OF_OBJECT_MEMBER(Class, dex_cache_strings_);
   }
 
+  // May cause thread suspension due to EqualParameters.
+  mirror::ArtMethod* GetDeclaredConstructor(
+      Thread* self, Handle<mirror::ObjectArray<mirror::Class>> args)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   // Used to initialize a class in the allocation code path to ensure it is guarded by a StoreStore
   // fence.
   class InitializeClassVisitor {
diff --git a/runtime/mirror/field.h b/runtime/mirror/field.h
index 9988f84..d927f0c 100644
--- a/runtime/mirror/field.h
+++ b/runtime/mirror/field.h
@@ -82,15 +82,12 @@
   }
 
   static void SetClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
-  static void SetArrayClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
-
   static void ResetClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
+  static void SetArrayClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
   static void ResetArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  static void VisitRoots(RootVisitor* visitor)
-      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+  static void VisitRoots(RootVisitor* visitor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Slow, try to use only for PrettyField and such.
   ArtField* GetArtField() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
diff --git a/runtime/mirror/method.cc b/runtime/mirror/method.cc
new file mode 100644
index 0000000..81530bb
--- /dev/null
+++ b/runtime/mirror/method.cc
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "method.h"
+
+#include "mirror/art_method.h"
+#include "mirror/object-inl.h"
+
+namespace art {
+namespace mirror {
+
+GcRoot<Class> Method::static_class_;
+GcRoot<Class> Method::array_class_;
+GcRoot<Class> Constructor::static_class_;
+GcRoot<Class> Constructor::array_class_;
+
+void Method::SetClass(Class* klass) {
+  CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
+  CHECK(klass != nullptr);
+  static_class_ = GcRoot<Class>(klass);
+}
+
+void Method::ResetClass() {
+  CHECK(!static_class_.IsNull());
+  static_class_ = GcRoot<Class>(nullptr);
+}
+
+void Method::SetArrayClass(Class* klass) {
+  CHECK(array_class_.IsNull()) << array_class_.Read() << " " << klass;
+  CHECK(klass != nullptr);
+  array_class_ = GcRoot<Class>(klass);
+}
+
+void Method::ResetArrayClass() {
+  CHECK(!array_class_.IsNull());
+  array_class_ = GcRoot<Class>(nullptr);
+}
+
+Method* Method::CreateFromArtMethod(Thread* self, mirror::ArtMethod* method) {
+  DCHECK(!method->IsConstructor()) << PrettyMethod(method);
+  auto* ret = down_cast<Method*>(StaticClass()->AllocObject(self));
+  if (LIKELY(ret != nullptr)) {
+    static_cast<AbstractMethod*>(ret)->CreateFromArtMethod(method);
+  }
+  return ret;
+}
+
+void Method::VisitRoots(RootVisitor* visitor) {
+  static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
+  array_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
+}
+
+void Constructor::SetClass(Class* klass) {
+  CHECK(static_class_.IsNull()) << static_class_.Read() << " " << klass;
+  CHECK(klass != nullptr);
+  static_class_ = GcRoot<Class>(klass);
+}
+
+void Constructor::ResetClass() {
+  CHECK(!static_class_.IsNull());
+  static_class_ = GcRoot<Class>(nullptr);
+}
+
+void Constructor::SetArrayClass(Class* klass) {
+  CHECK(array_class_.IsNull()) << array_class_.Read() << " " << klass;
+  CHECK(klass != nullptr);
+  array_class_ = GcRoot<Class>(klass);
+}
+
+void Constructor::ResetArrayClass() {
+  CHECK(!array_class_.IsNull());
+  array_class_ = GcRoot<Class>(nullptr);
+}
+
+void Constructor::VisitRoots(RootVisitor* visitor) {
+  static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
+  array_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
+}
+
+Constructor* Constructor::CreateFromArtMethod(Thread* self, mirror::ArtMethod* method) {
+  DCHECK(method->IsConstructor()) << PrettyMethod(method);
+  auto* ret = down_cast<Constructor*>(StaticClass()->AllocObject(self));
+  if (LIKELY(ret != nullptr)) {
+    static_cast<AbstractMethod*>(ret)->CreateFromArtMethod(method);
+  }
+  return ret;
+}
+
+}  // namespace mirror
+}  // namespace art
diff --git a/runtime/mirror/method.h b/runtime/mirror/method.h
new file mode 100644
index 0000000..88100f0
--- /dev/null
+++ b/runtime/mirror/method.h
@@ -0,0 +1,93 @@
+/*
+ * Copyright (C) 2015 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_RUNTIME_MIRROR_METHOD_H_
+#define ART_RUNTIME_MIRROR_METHOD_H_
+
+#include "abstract_method.h"
+#include "gc_root.h"
+
+namespace art {
+namespace mirror {
+
+class Class;
+
+// C++ mirror of java.lang.reflect.Method.
+class MANAGED Method : public AbstractMethod {
+ public:
+  static Method* CreateFromArtMethod(Thread* self, mirror::ArtMethod* method)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static mirror::Class* StaticClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return static_class_.Read();
+  }
+
+  static void SetClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static void ResetClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static mirror::Class* ArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return array_class_.Read();
+  }
+
+  static void SetArrayClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static void ResetArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static void VisitRoots(RootVisitor* visitor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ private:
+  static GcRoot<Class> static_class_;  // java.lang.reflect.Method.class.
+  static GcRoot<Class> array_class_;  // [java.lang.reflect.Method.class.
+
+  DISALLOW_COPY_AND_ASSIGN(Method);
+};
+
+// C++ mirror of java.lang.reflect.Constructor.
+class MANAGED Constructor: public AbstractMethod {
+ public:
+  static Constructor* CreateFromArtMethod(Thread* self, mirror::ArtMethod* method)
+      SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static mirror::Class* StaticClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return static_class_.Read();
+  }
+
+  static void SetClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static void ResetClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static mirror::Class* ArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
+    return array_class_.Read();
+  }
+
+  static void SetArrayClass(Class* klass) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static void ResetArrayClass() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+  static void VisitRoots(RootVisitor* visitor) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
+ private:
+  static GcRoot<Class> static_class_;  // java.lang.reflect.Constructor.class.
+  static GcRoot<Class> array_class_;  // [java.lang.reflect.Constructor.class.
+
+  DISALLOW_COPY_AND_ASSIGN(Constructor);
+};
+
+}  // namespace mirror
+}  // namespace art
+
+#endif  // ART_RUNTIME_MIRROR_METHOD_H_