ART: Add pointer-size template to some reflection functions

The unstarted runtime may run code for a different pointer size,
even when no transaction is active (e.g., during startup). To
retain performance when the runtime is up and executing under
normal conditions, add a template parameter and use sizeof(void*)
in places where it is adequate.

For maintainability, it is necessary to drop the default for
the transaction template parameter. Implicit conversions from
bool to size_t may lead to incorrect code and hard to diagnose
problems. So instead ensure that all callers must give all
template parameter values.

Test: m test-art-host
Change-Id: I3076883422c8553ede4de5642409c5684a5a9aa8
diff --git a/runtime/dex_file.cc b/runtime/dex_file.cc
index 5d9ae14..2a2d2c0 100644
--- a/runtime/dex_file.cc
+++ b/runtime/dex_file.cc
@@ -1638,8 +1638,15 @@
   mirror::Class* annotation_member_class =
       WellKnownClasses::ToClass(WellKnownClasses::libcore_reflect_AnnotationMember);
   Handle<mirror::Object> new_member(hs.NewHandle(annotation_member_class->AllocObject(self)));
-  Handle<mirror::Method> method_object(
-      hs.NewHandle(mirror::Method::CreateFromArtMethod(self, annotation_method)));
+  mirror::Method* method_obj_ptr;
+  DCHECK(!Runtime::Current()->IsActiveTransaction());
+  if (pointer_size == 8U) {
+    method_obj_ptr = mirror::Method::CreateFromArtMethod<8U, false>(self, annotation_method);
+  } else {
+    DCHECK_EQ(pointer_size, 4U);
+    method_obj_ptr = mirror::Method::CreateFromArtMethod<4U, false>(self, annotation_method);
+  }
+  Handle<mirror::Method> method_object(hs.NewHandle(method_obj_ptr));
 
   if (new_member.Get() == nullptr || string_name.Get() == nullptr ||
       method_object.Get() == nullptr || method_return.Get() == nullptr) {
@@ -1947,16 +1954,29 @@
         StackHandleScope<2> hs(self);
         Handle<mirror::DexCache> dex_cache(hs.NewHandle(klass->GetDexCache()));
         Handle<mirror::ClassLoader> class_loader(hs.NewHandle(klass->GetClassLoader()));
-        ArtMethod* method = Runtime::Current()->GetClassLinker()->ResolveMethodWithoutInvokeType(
+        ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+        ArtMethod* method = class_linker->ResolveMethodWithoutInvokeType(
             klass->GetDexFile(), index, dex_cache, class_loader);
         if (method == nullptr) {
           return false;
         }
+        size_t pointer_size = class_linker->GetImagePointerSize();
         set_object = true;
+        DCHECK(!Runtime::Current()->IsActiveTransaction());
         if (method->IsConstructor()) {
-          element_object = mirror::Constructor::CreateFromArtMethod(self, method);
+          if (pointer_size == 8U) {
+            element_object = mirror::Constructor::CreateFromArtMethod<8U, false>(self, method);
+          } else {
+            DCHECK_EQ(pointer_size, 4U);
+            element_object = mirror::Constructor::CreateFromArtMethod<4U, false>(self, method);
+          }
         } else {
-          element_object = mirror::Method::CreateFromArtMethod(self, method);
+          if (pointer_size == 8U) {
+            element_object = mirror::Method::CreateFromArtMethod<8U, false>(self, method);
+          } else {
+            DCHECK_EQ(pointer_size, 4U);
+            element_object = mirror::Method::CreateFromArtMethod<4U, false>(self, method);
+          }
         }
         if (element_object == nullptr) {
           return false;
@@ -1978,7 +1998,13 @@
           return false;
         }
         set_object = true;
-        element_object = mirror::Field::CreateFromArtField(self, field, true);
+        size_t pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
+        if (pointer_size == 8) {
+          element_object = mirror::Field::CreateFromArtField<8U>(self, field, true);
+        } else {
+          DCHECK_EQ(pointer_size, 4U);
+          element_object = mirror::Field::CreateFromArtField<4U>(self, field, true);
+        }
         if (element_object == nullptr) {
           return false;
         }
diff --git a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
index 49043f6..0306bd6 100644
--- a/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_trampoline_entrypoints.cc
@@ -876,8 +876,10 @@
   DCHECK(interface_method != nullptr) << PrettyMethod(proxy_method);
   DCHECK(!interface_method->IsProxyMethod()) << PrettyMethod(interface_method);
   self->EndAssertNoThreadSuspension(old_cause);
+  DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), sizeof(void*));
+  DCHECK(!Runtime::Current()->IsActiveTransaction());
   jobject interface_method_jobj = soa.AddLocalReference<jobject>(
-      mirror::Method::CreateFromArtMethod(soa.Self(), interface_method));
+      mirror::Method::CreateFromArtMethod<sizeof(void*), false>(soa.Self(), interface_method));
 
   // All naked Object*s should now be in jobjects, so its safe to go into the main invoke code
   // that performs allocations.
diff --git a/runtime/interpreter/unstarted_runtime.cc b/runtime/interpreter/unstarted_runtime.cc
index 1f473e4..793260d 100644
--- a/runtime/interpreter/unstarted_runtime.cc
+++ b/runtime/interpreter/unstarted_runtime.cc
@@ -300,11 +300,25 @@
                            PrettyDescriptor(klass).c_str());
     return;
   }
-  if (Runtime::Current()->IsActiveTransaction()) {
-    result->SetL(mirror::Field::CreateFromArtField<true>(self, found, true));
+  Runtime* runtime = Runtime::Current();
+  size_t pointer_size = runtime->GetClassLinker()->GetImagePointerSize();
+  mirror::Field* field;
+  if (runtime->IsActiveTransaction()) {
+    if (pointer_size == 8) {
+      field = mirror::Field::CreateFromArtField<8U, true>(self, found, true);
+    } else {
+      DCHECK_EQ(pointer_size, 4U);
+      field = mirror::Field::CreateFromArtField<4U, true>(self, found, true);
+    }
   } else {
-    result->SetL(mirror::Field::CreateFromArtField<false>(self, found, true));
+    if (pointer_size == 8) {
+      field = mirror::Field::CreateFromArtField<8U, false>(self, found, true);
+    } else {
+      DCHECK_EQ(pointer_size, 4U);
+      field = mirror::Field::CreateFromArtField<4U, false>(self, found, true);
+    }
   }
+  result->SetL(field);
 }
 
 // This is required for Enum(Set) code, as that uses reflection to inspect enum classes.
@@ -319,11 +333,26 @@
   mirror::String* name = shadow_frame->GetVRegReference(arg_offset + 1)->AsString();
   mirror::ObjectArray<mirror::Class>* args =
       shadow_frame->GetVRegReference(arg_offset + 2)->AsObjectArray<mirror::Class>();
-  if (Runtime::Current()->IsActiveTransaction()) {
-    result->SetL(mirror::Class::GetDeclaredMethodInternal<true>(self, klass, name, args));
+  Runtime* runtime = Runtime::Current();
+  bool transaction = runtime->IsActiveTransaction();
+  size_t pointer_size = runtime->GetClassLinker()->GetImagePointerSize();
+  mirror::Method* method;
+  if (transaction) {
+    if (pointer_size == 8U) {
+      method = mirror::Class::GetDeclaredMethodInternal<8U, true>(self, klass, name, args);
+    } else {
+      DCHECK_EQ(pointer_size, 4U);
+      method = mirror::Class::GetDeclaredMethodInternal<4U, true>(self, klass, name, args);
+    }
   } else {
-    result->SetL(mirror::Class::GetDeclaredMethodInternal<false>(self, klass, name, args));
+    if (pointer_size == 8U) {
+      method = mirror::Class::GetDeclaredMethodInternal<8U, false>(self, klass, name, args);
+    } else {
+      DCHECK_EQ(pointer_size, 4U);
+      method = mirror::Class::GetDeclaredMethodInternal<4U, false>(self, klass, name, args);
+    }
   }
+  result->SetL(method);
 }
 
 // Special managed code cut-out to allow constructor lookup in a un-started runtime.
@@ -336,11 +365,26 @@
   }
   mirror::ObjectArray<mirror::Class>* args =
       shadow_frame->GetVRegReference(arg_offset + 1)->AsObjectArray<mirror::Class>();
-  if (Runtime::Current()->IsActiveTransaction()) {
-    result->SetL(mirror::Class::GetDeclaredConstructorInternal<true>(self, klass, args));
+  Runtime* runtime = Runtime::Current();
+  bool transaction = runtime->IsActiveTransaction();
+  size_t pointer_size = runtime->GetClassLinker()->GetImagePointerSize();
+  mirror::Constructor* constructor;
+  if (transaction) {
+    if (pointer_size == 8U) {
+      constructor = mirror::Class::GetDeclaredConstructorInternal<8U, true>(self, klass, args);
+    } else {
+      DCHECK_EQ(pointer_size, 4U);
+      constructor = mirror::Class::GetDeclaredConstructorInternal<4U, true>(self, klass, args);
+    }
   } else {
-    result->SetL(mirror::Class::GetDeclaredConstructorInternal<false>(self, klass, args));
+    if (pointer_size == 8U) {
+      constructor = mirror::Class::GetDeclaredConstructorInternal<8U, false>(self, klass, args);
+    } else {
+      DCHECK_EQ(pointer_size, 4U);
+      constructor = mirror::Class::GetDeclaredConstructorInternal<4U, false>(self, klass, args);
+    }
   }
+  result->SetL(constructor);
 }
 
 void UnstartedRuntime::UnstartedClassGetEnclosingClass(
diff --git a/runtime/jni_internal.cc b/runtime/jni_internal.cc
index 8cdf96d..6ef3999 100644
--- a/runtime/jni_internal.cc
+++ b/runtime/jni_internal.cc
@@ -375,10 +375,12 @@
     ScopedObjectAccess soa(env);
     ArtMethod* m = soa.DecodeMethod(mid);
     mirror::AbstractMethod* method;
+    DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), sizeof(void*));
+    DCHECK(!Runtime::Current()->IsActiveTransaction());
     if (m->IsConstructor()) {
-      method = mirror::Constructor::CreateFromArtMethod(soa.Self(), m);
+      method = mirror::Constructor::CreateFromArtMethod<sizeof(void*), false>(soa.Self(), m);
     } else {
-      method = mirror::Method::CreateFromArtMethod(soa.Self(), m);
+      method = mirror::Method::CreateFromArtMethod<sizeof(void*), false>(soa.Self(), m);
     }
     return soa.AddLocalReference<jobject>(method);
   }
@@ -387,7 +389,8 @@
     CHECK_NON_NULL_ARGUMENT(fid);
     ScopedObjectAccess soa(env);
     ArtField* f = soa.DecodeField(fid);
-    return soa.AddLocalReference<jobject>(mirror::Field::CreateFromArtField(soa.Self(), f, true));
+    return soa.AddLocalReference<jobject>(
+        mirror::Field::CreateFromArtField<sizeof(void*)>(soa.Self(), f, true));
   }
 
   static jclass GetObjectClass(JNIEnv* env, jobject java_object) {
diff --git a/runtime/mirror/abstract_method.cc b/runtime/mirror/abstract_method.cc
index 5a07dee..ef39132 100644
--- a/runtime/mirror/abstract_method.cc
+++ b/runtime/mirror/abstract_method.cc
@@ -21,12 +21,9 @@
 namespace art {
 namespace mirror {
 
-template <bool kTransactionActive>
+template <size_t kPointerSize, bool kTransactionActive>
 bool AbstractMethod::CreateFromArtMethod(ArtMethod* method) {
-  auto* interface_method = method->GetInterfaceMethodIfProxy(
-      kTransactionActive
-          ? Runtime::Current()->GetClassLinker()->GetImagePointerSize()
-          : sizeof(void*));
+  auto* interface_method = method->GetInterfaceMethodIfProxy(kPointerSize);
   SetArtMethod<kTransactionActive>(method);
   SetFieldObject<kTransactionActive>(DeclaringClassOffset(), method->GetDeclaringClass());
   SetFieldObject<kTransactionActive>(
@@ -36,8 +33,10 @@
   return true;
 }
 
-template bool AbstractMethod::CreateFromArtMethod<false>(ArtMethod* method);
-template bool AbstractMethod::CreateFromArtMethod<true>(ArtMethod* method);
+template bool AbstractMethod::CreateFromArtMethod<4U, false>(ArtMethod* method);
+template bool AbstractMethod::CreateFromArtMethod<4U, true>(ArtMethod* method);
+template bool AbstractMethod::CreateFromArtMethod<8U, false>(ArtMethod* method);
+template bool AbstractMethod::CreateFromArtMethod<8U, true>(ArtMethod* method);
 
 ArtMethod* AbstractMethod::GetArtMethod() {
   return reinterpret_cast<ArtMethod*>(GetField64(ArtMethodOffset()));
diff --git a/runtime/mirror/abstract_method.h b/runtime/mirror/abstract_method.h
index a39f94d..936b14c 100644
--- a/runtime/mirror/abstract_method.h
+++ b/runtime/mirror/abstract_method.h
@@ -34,7 +34,7 @@
 class MANAGED AbstractMethod : public AccessibleObject {
  public:
   // Called from Constructor::CreateFromArtMethod, Method::CreateFromArtMethod.
-  template <bool kTransactionActive = false>
+  template <size_t kPointerSize, bool kTransactionActive>
   bool CreateFromArtMethod(ArtMethod* method) SHARED_REQUIRES(Locks::mutator_lock_)
       REQUIRES(!Roles::uninterruptible_);
 
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index 1c31c57..375cb2f 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -1053,7 +1053,7 @@
   return (type_id == nullptr) ? DexFile::kDexNoIndex : dex_file.GetIndexForTypeId(*type_id);
 }
 
-template <bool kTransactionActive>
+template <size_t kPointerSize, bool kTransactionActive>
 mirror::Method* Class::GetDeclaredMethodInternal(Thread* self,
                                                  mirror::Class* klass,
                                                  mirror::String* name,
@@ -1074,11 +1074,8 @@
   auto h_args = hs.NewHandle(args);
   Handle<mirror::Class> h_klass = hs.NewHandle(klass);
   ArtMethod* result = nullptr;
-  const size_t pointer_size = kTransactionActive
-                                  ? Runtime::Current()->GetClassLinker()->GetImagePointerSize()
-                                  : sizeof(void*);
-  for (auto& m : h_klass->GetDeclaredVirtualMethods(pointer_size)) {
-    auto* np_method = m.GetInterfaceMethodIfProxy(pointer_size);
+  for (auto& m : h_klass->GetDeclaredVirtualMethods(kPointerSize)) {
+    auto* np_method = m.GetInterfaceMethodIfProxy(kPointerSize);
     // May cause thread suspension.
     mirror::String* np_name = np_method->GetNameAsString(self);
     if (!np_name->Equals(h_method_name.Get()) || !np_method->EqualParameters(h_args)) {
@@ -1089,19 +1086,19 @@
     }
     auto modifiers = m.GetAccessFlags();
     if ((modifiers & kSkipModifiers) == 0) {
-      return mirror::Method::CreateFromArtMethod<kTransactionActive>(self, &m);
+      return mirror::Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(self, &m);
     }
     if ((modifiers & kAccMiranda) == 0) {
       result = &m;  // Remember as potential result if it's not a miranda method.
     }
   }
   if (result == nullptr) {
-    for (auto& m : h_klass->GetDirectMethods(pointer_size)) {
+    for (auto& m : h_klass->GetDirectMethods(kPointerSize)) {
       auto modifiers = m.GetAccessFlags();
       if ((modifiers & kAccConstructor) != 0) {
         continue;
       }
-      auto* np_method = m.GetInterfaceMethodIfProxy(pointer_size);
+      auto* np_method = m.GetInterfaceMethodIfProxy(kPointerSize);
       // May cause thread suspension.
       mirror::String* np_name = np_method->GetNameAsString(self);
       if (np_name == nullptr) {
@@ -1115,50 +1112,69 @@
         continue;
       }
       if ((modifiers & kSkipModifiers) == 0) {
-        return mirror::Method::CreateFromArtMethod<kTransactionActive>(self, &m);
+        return mirror::Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(self, &m);
       }
       // Direct methods cannot be miranda methods, so this potential result must be synthetic.
       result = &m;
     }
   }
   return result != nullptr
-      ? mirror::Method::CreateFromArtMethod<kTransactionActive>(self, result)
+      ? mirror::Method::CreateFromArtMethod<kPointerSize, kTransactionActive>(self, result)
       : nullptr;
 }
 
 template
-mirror::Method* Class::GetDeclaredMethodInternal<false>(Thread* self,
-                                                        mirror::Class* klass,
-                                                        mirror::String* name,
-                                                        mirror::ObjectArray<mirror::Class>* args);
+mirror::Method* Class::GetDeclaredMethodInternal<4U, false>(
+    Thread* self,
+    mirror::Class* klass,
+    mirror::String* name,
+    mirror::ObjectArray<mirror::Class>* args);
 template
-mirror::Method* Class::GetDeclaredMethodInternal<true>(Thread* self,
-                                                       mirror::Class* klass,
-                                                       mirror::String* name,
-                                                       mirror::ObjectArray<mirror::Class>* args);
+mirror::Method* Class::GetDeclaredMethodInternal<4U, true>(
+    Thread* self,
+    mirror::Class* klass,
+    mirror::String* name,
+    mirror::ObjectArray<mirror::Class>* args);
+template
+mirror::Method* Class::GetDeclaredMethodInternal<8U, false>(
+    Thread* self,
+    mirror::Class* klass,
+    mirror::String* name,
+    mirror::ObjectArray<mirror::Class>* args);
+template
+mirror::Method* Class::GetDeclaredMethodInternal<8U, true>(
+    Thread* self,
+    mirror::Class* klass,
+    mirror::String* name,
+    mirror::ObjectArray<mirror::Class>* args);
 
-template <bool kTransactionActive>
+template <size_t kPointerSize, bool kTransactionActive>
 mirror::Constructor* Class::GetDeclaredConstructorInternal(
     Thread* self,
     mirror::Class* klass,
     mirror::ObjectArray<mirror::Class>* args) {
   StackHandleScope<1> hs(self);
-  const size_t pointer_size = kTransactionActive
-                                  ? Runtime::Current()->GetClassLinker()->GetImagePointerSize()
-                                  : sizeof(void*);
-  ArtMethod* result = klass->GetDeclaredConstructor(self, hs.NewHandle(args), pointer_size);
+  ArtMethod* result = klass->GetDeclaredConstructor(self, hs.NewHandle(args), kPointerSize);
   return result != nullptr
-      ? mirror::Constructor::CreateFromArtMethod<kTransactionActive>(self, result)
+      ? mirror::Constructor::CreateFromArtMethod<kPointerSize, kTransactionActive>(self, result)
       : nullptr;
 }
 
 // mirror::Constructor::CreateFromArtMethod<kTransactionActive>(self, result)
 
-template mirror::Constructor* Class::GetDeclaredConstructorInternal<false>(
+template mirror::Constructor* Class::GetDeclaredConstructorInternal<4U, false>(
     Thread* self,
     mirror::Class* klass,
     mirror::ObjectArray<mirror::Class>* args);
-template mirror::Constructor* Class::GetDeclaredConstructorInternal<true>(
+template mirror::Constructor* Class::GetDeclaredConstructorInternal<4U, true>(
+    Thread* self,
+    mirror::Class* klass,
+    mirror::ObjectArray<mirror::Class>* args);
+template mirror::Constructor* Class::GetDeclaredConstructorInternal<8U, false>(
+    Thread* self,
+    mirror::Class* klass,
+    mirror::ObjectArray<mirror::Class>* args);
+template mirror::Constructor* Class::GetDeclaredConstructorInternal<8U, true>(
     Thread* self,
     mirror::Class* klass,
     mirror::ObjectArray<mirror::Class>* args);
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index 9be9f01..32ed337 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -754,13 +754,13 @@
         size_t pointer_size)
       SHARED_REQUIRES(Locks::mutator_lock_);
 
-  template <bool kTransactionActive = false>
+  template <size_t kPointerSize, bool kTransactionActive>
   static Method* GetDeclaredMethodInternal(Thread* self,
                                            mirror::Class* klass,
                                            mirror::String* name,
                                            mirror::ObjectArray<mirror::Class>* args)
       SHARED_REQUIRES(Locks::mutator_lock_);
-  template <bool kTransactionActive = false>
+  template <size_t kPointerSize, bool kTransactionActive>
   static Constructor* GetDeclaredConstructorInternal(Thread* self,
                                                      mirror::Class* klass,
                                                      mirror::ObjectArray<mirror::Class>* args)
diff --git a/runtime/mirror/field-inl.h b/runtime/mirror/field-inl.h
index 8a0daec..4183476 100644
--- a/runtime/mirror/field-inl.h
+++ b/runtime/mirror/field-inl.h
@@ -27,7 +27,7 @@
 
 namespace mirror {
 
-template <bool kTransactionActive>
+template <size_t kPointerSize, bool kTransactionActive>
 inline mirror::Field* Field::CreateFromArtField(Thread* self, ArtField* field,
                                                 bool force_resolve) {
   StackHandleScope<2> hs(self);
@@ -54,10 +54,8 @@
     self->AssertPendingOOMException();
     return nullptr;
   }
-  const auto pointer_size = kTransactionActive ?
-      Runtime::Current()->GetClassLinker()->GetImagePointerSize() : sizeof(void*);
   auto dex_field_index = field->GetDexFieldIndex();
-  auto* resolved_field = field->GetDexCache()->GetResolvedField(dex_field_index, pointer_size);
+  auto* resolved_field = field->GetDexCache()->GetResolvedField(dex_field_index, kPointerSize);
   if (field->GetDeclaringClass()->IsProxyClass()) {
     DCHECK(field->IsStatic());
     DCHECK_LT(dex_field_index, 2U);
@@ -70,7 +68,7 @@
     } else {
       // We rely on the field being resolved so that we can back to the ArtField
       // (i.e. FromReflectedMethod).
-      field->GetDexCache()->SetResolvedField(dex_field_index, field, pointer_size);
+      field->GetDexCache()->SetResolvedField(dex_field_index, field, kPointerSize);
     }
   }
   ret->SetType<kTransactionActive>(type.Get());
diff --git a/runtime/mirror/field.h b/runtime/mirror/field.h
index edaddbd..2bd6132 100644
--- a/runtime/mirror/field.h
+++ b/runtime/mirror/field.h
@@ -92,7 +92,7 @@
   // Slow, try to use only for PrettyField and such.
   ArtField* GetArtField() SHARED_REQUIRES(Locks::mutator_lock_);
 
-  template <bool kTransactionActive = false>
+  template <size_t kPointerSize, bool kTransactionActive = false>
   static mirror::Field* CreateFromArtField(Thread* self, ArtField* field,
                                            bool force_resolve)
       SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
diff --git a/runtime/mirror/method.cc b/runtime/mirror/method.cc
index 9838b71..3cc70e1 100644
--- a/runtime/mirror/method.cc
+++ b/runtime/mirror/method.cc
@@ -51,18 +51,21 @@
   array_class_ = GcRoot<Class>(nullptr);
 }
 
-template <bool kTransactionActive>
+template <size_t kPointerSize, bool kTransactionActive>
 Method* Method::CreateFromArtMethod(Thread* self, ArtMethod* method) {
   DCHECK(!method->IsConstructor()) << PrettyMethod(method);
   auto* ret = down_cast<Method*>(StaticClass()->AllocObject(self));
   if (LIKELY(ret != nullptr)) {
-    static_cast<AbstractMethod*>(ret)->CreateFromArtMethod<kTransactionActive>(method);
+    static_cast<AbstractMethod*>(ret)->
+        CreateFromArtMethod<kPointerSize, kTransactionActive>(method);
   }
   return ret;
 }
 
-template Method* Method::CreateFromArtMethod<false>(Thread* self, ArtMethod* method);
-template Method* Method::CreateFromArtMethod<true>(Thread* self, ArtMethod* method);
+template Method* Method::CreateFromArtMethod<4U, false>(Thread* self, ArtMethod* method);
+template Method* Method::CreateFromArtMethod<4U, true>(Thread* self, ArtMethod* method);
+template Method* Method::CreateFromArtMethod<8U, false>(Thread* self, ArtMethod* method);
+template Method* Method::CreateFromArtMethod<8U, true>(Thread* self, ArtMethod* method);
 
 void Method::VisitRoots(RootVisitor* visitor) {
   static_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
@@ -96,18 +99,21 @@
   array_class_.VisitRootIfNonNull(visitor, RootInfo(kRootStickyClass));
 }
 
-template <bool kTransactionActive>
+template <size_t kPointerSize, bool kTransactionActive>
 Constructor* Constructor::CreateFromArtMethod(Thread* self, ArtMethod* method) {
   DCHECK(method->IsConstructor()) << PrettyMethod(method);
   auto* ret = down_cast<Constructor*>(StaticClass()->AllocObject(self));
   if (LIKELY(ret != nullptr)) {
-    static_cast<AbstractMethod*>(ret)->CreateFromArtMethod<kTransactionActive>(method);
+    static_cast<AbstractMethod*>(ret)->
+        CreateFromArtMethod<kPointerSize, kTransactionActive>(method);
   }
   return ret;
 }
 
-template Constructor* Constructor::CreateFromArtMethod<false>(Thread* self, ArtMethod* method);
-template Constructor* Constructor::CreateFromArtMethod<true>(Thread* self, ArtMethod* method);
+template Constructor* Constructor::CreateFromArtMethod<4U, false>(Thread* self, ArtMethod* method);
+template Constructor* Constructor::CreateFromArtMethod<4U, true>(Thread* self, ArtMethod* method);
+template Constructor* Constructor::CreateFromArtMethod<8U, false>(Thread* self, ArtMethod* method);
+template Constructor* Constructor::CreateFromArtMethod<8U, true>(Thread* self, ArtMethod* method);
 
 }  // namespace mirror
 }  // namespace art
diff --git a/runtime/mirror/method.h b/runtime/mirror/method.h
index 0b56964..ecd6a74 100644
--- a/runtime/mirror/method.h
+++ b/runtime/mirror/method.h
@@ -28,7 +28,7 @@
 // C++ mirror of java.lang.reflect.Method.
 class MANAGED Method : public AbstractMethod {
  public:
-  template <bool kTransactionActive = false>
+  template <size_t kPointerSize, bool kTransactionActive>
   static Method* CreateFromArtMethod(Thread* self, ArtMethod* method)
       SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
 
@@ -60,7 +60,7 @@
 // C++ mirror of java.lang.reflect.Constructor.
 class MANAGED Constructor: public AbstractMethod {
  public:
-  template <bool kTransactionActive = false>
+  template <size_t kPointerSize, bool kTransactionActive>
   static Constructor* CreateFromArtMethod(Thread* self, ArtMethod* method)
       SHARED_REQUIRES(Locks::mutator_lock_) REQUIRES(!Roles::uninterruptible_);
 
diff --git a/runtime/native/java_lang_Class.cc b/runtime/native/java_lang_Class.cc
index 0624da3..02a97f5 100644
--- a/runtime/native/java_lang_Class.cc
+++ b/runtime/native/java_lang_Class.cc
@@ -136,7 +136,9 @@
   }
   for (ArtField& field : ifields) {
     if (!public_only || field.IsPublic()) {
-      auto* reflect_field = mirror::Field::CreateFromArtField(self, &field, force_resolve);
+      auto* reflect_field = mirror::Field::CreateFromArtField<sizeof(void*)>(self,
+                                                                             &field,
+                                                                             force_resolve);
       if (reflect_field == nullptr) {
         if (kIsDebugBuild) {
           self->AssertPendingException();
@@ -149,7 +151,9 @@
   }
   for (ArtField& field : sfields) {
     if (!public_only || field.IsPublic()) {
-      auto* reflect_field = mirror::Field::CreateFromArtField(self, &field, force_resolve);
+      auto* reflect_field = mirror::Field::CreateFromArtField<sizeof(void*)>(self,
+                                                                             &field,
+                                                                             force_resolve);
       if (reflect_field == nullptr) {
         if (kIsDebugBuild) {
           self->AssertPendingException();
@@ -222,11 +226,15 @@
     SHARED_REQUIRES(Locks::mutator_lock_) {
   ArtField* art_field = FindFieldByName(self, name, c->GetIFieldsPtr());
   if (art_field != nullptr) {
-    return mirror::Field::CreateFromArtField(self, art_field, true);
+    return mirror::Field::CreateFromArtField<sizeof(void*)>(self,
+                                                            art_field,
+                                                            true);
   }
   art_field = FindFieldByName(self, name, c->GetSFieldsPtr());
   if (art_field != nullptr) {
-    return mirror::Field::CreateFromArtField(self, art_field, true);
+    return mirror::Field::CreateFromArtField<sizeof(void*)>(self,
+                                                            art_field,
+                                                            true);
   }
   return nullptr;
 }
@@ -323,7 +331,9 @@
 static jobject Class_getDeclaredConstructorInternal(
     JNIEnv* env, jobject javaThis, jobjectArray args) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Constructor* result = mirror::Class::GetDeclaredConstructorInternal(
+  DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), sizeof(void*));
+  DCHECK(!Runtime::Current()->IsActiveTransaction());
+  mirror::Constructor* result = mirror::Class::GetDeclaredConstructorInternal<sizeof(void*), false>(
       soa.Self(),
       DecodeClass(soa, javaThis),
       soa.Decode<mirror::ObjectArray<mirror::Class>*>(args));
@@ -355,7 +365,10 @@
   constructor_count = 0;
   for (auto& m : h_klass->GetDirectMethods(sizeof(void*))) {
     if (MethodMatchesConstructor(&m, publicOnly != JNI_FALSE)) {
-      auto* constructor = mirror::Constructor::CreateFromArtMethod(soa.Self(), &m);
+      DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), sizeof(void*));
+      DCHECK(!Runtime::Current()->IsActiveTransaction());
+      auto* constructor = mirror::Constructor::CreateFromArtMethod<sizeof(void*), false>(
+          soa.Self(), &m);
       if (UNLIKELY(constructor == nullptr)) {
         soa.Self()->AssertPendingOOMException();
         return nullptr;
@@ -369,7 +382,9 @@
 static jobject Class_getDeclaredMethodInternal(JNIEnv* env, jobject javaThis,
                                                jobject name, jobjectArray args) {
   ScopedFastNativeObjectAccess soa(env);
-  mirror::Method* result = mirror::Class::GetDeclaredMethodInternal(
+  DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), sizeof(void*));
+  DCHECK(!Runtime::Current()->IsActiveTransaction());
+  mirror::Method* result = mirror::Class::GetDeclaredMethodInternal<sizeof(void*), false>(
       soa.Self(),
       DecodeClass(soa, javaThis),
       soa.Decode<mirror::String*>(name),
@@ -398,7 +413,9 @@
     auto modifiers = m.GetAccessFlags();
     if ((publicOnly == JNI_FALSE || (modifiers & kAccPublic) != 0) &&
         (modifiers & kAccConstructor) == 0) {
-      auto* method = mirror::Method::CreateFromArtMethod(soa.Self(), &m);
+      DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), sizeof(void*));
+      DCHECK(!Runtime::Current()->IsActiveTransaction());
+      auto* method = mirror::Method::CreateFromArtMethod<sizeof(void*), false>(soa.Self(), &m);
       if (method == nullptr) {
         soa.Self()->AssertPendingException();
         return nullptr;
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index 4d9ca6d..1ce7e48 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -60,29 +60,31 @@
 
     jsize array_index = 0;
     // Fill the method array
+    DCHECK_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), sizeof(void*));
     ArtMethod* method = javaLangObject->FindDeclaredVirtualMethod(
         "equals", "(Ljava/lang/Object;)Z", sizeof(void*));
     CHECK(method != nullptr);
+    DCHECK(!Runtime::Current()->IsActiveTransaction());
     soa.Env()->SetObjectArrayElement(
         proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
-            mirror::Method::CreateFromArtMethod(soa.Self(), method)));
+            mirror::Method::CreateFromArtMethod<sizeof(void*), false>(soa.Self(), method)));
     method = javaLangObject->FindDeclaredVirtualMethod("hashCode", "()I", sizeof(void*));
     CHECK(method != nullptr);
     soa.Env()->SetObjectArrayElement(
         proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
-            mirror::Method::CreateFromArtMethod(soa.Self(), method)));
+            mirror::Method::CreateFromArtMethod<sizeof(void*), false>(soa.Self(), method)));
     method = javaLangObject->FindDeclaredVirtualMethod(
         "toString", "()Ljava/lang/String;", sizeof(void*));
     CHECK(method != nullptr);
     soa.Env()->SetObjectArrayElement(
         proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
-            mirror::Method::CreateFromArtMethod(soa.Self(), method)));
+            mirror::Method::CreateFromArtMethod<sizeof(void*), false>(soa.Self(), method)));
     // Now adds all interfaces virtual methods.
     for (mirror::Class* interface : interfaces) {
       for (auto& m : interface->GetDeclaredVirtualMethods(sizeof(void*))) {
         soa.Env()->SetObjectArrayElement(
             proxyClassMethods, array_index++, soa.AddLocalReference<jobject>(
-                mirror::Method::CreateFromArtMethod(soa.Self(), &m)));
+                mirror::Method::CreateFromArtMethod<sizeof(void*), false>(soa.Self(), &m)));
       }
     }
     CHECK_EQ(array_index, methods_count);
@@ -226,14 +228,20 @@
   EXPECT_EQ(static_fields1->At(0).GetDeclaringClass(), proxyClass1.Get());
   EXPECT_EQ(static_fields1->At(1).GetDeclaringClass(), proxyClass1.Get());
 
+  ASSERT_EQ(Runtime::Current()->GetClassLinker()->GetImagePointerSize(), sizeof(void*));
+  ASSERT_FALSE(Runtime::Current()->IsActiveTransaction());
   Handle<mirror::Field> field00 =
-      hs.NewHandle(mirror::Field::CreateFromArtField(soa.Self(), &static_fields0->At(0), true));
+      hs.NewHandle(mirror::Field::CreateFromArtField<sizeof(void*), false>(
+          soa.Self(), &static_fields0->At(0), true));
   Handle<mirror::Field> field01 =
-      hs.NewHandle(mirror::Field::CreateFromArtField(soa.Self(), &static_fields0->At(1), true));
+      hs.NewHandle(mirror::Field::CreateFromArtField<sizeof(void*), false>(
+          soa.Self(), &static_fields0->At(1), true));
   Handle<mirror::Field> field10 =
-      hs.NewHandle(mirror::Field::CreateFromArtField(soa.Self(), &static_fields1->At(0), true));
+      hs.NewHandle(mirror::Field::CreateFromArtField<sizeof(void*), false>(
+          soa.Self(), &static_fields1->At(0), true));
   Handle<mirror::Field> field11 =
-      hs.NewHandle(mirror::Field::CreateFromArtField(soa.Self(), &static_fields1->At(1), true));
+      hs.NewHandle(mirror::Field::CreateFromArtField<sizeof(void*), false>(
+          soa.Self(), &static_fields1->At(1), true));
   EXPECT_EQ(field00->GetArtField(), &static_fields0->At(0));
   EXPECT_EQ(field01->GetArtField(), &static_fields0->At(1));
   EXPECT_EQ(field10->GetArtField(), &static_fields1->At(0));