Clean up Class::GetDirectInterface().

Fetch array interfaces from the `IfTable`. This removes the
only use of the `Thread* self` argument, so we can remove
that argument. We also make the function non-static to avoid
the explicit `klass` argument. Similarly clean up arguments
of `Class::FindClass()` and `Class::FindStaticClass()`.

Test: m test-art-host-gtest
Test: testrunner.py --host --optimizing
Bug: 181943478
Change-Id: Id639b675b4eb331a777cf318eb61bd19e05de4f0
diff --git a/dex2oat/driver/compiler_driver.cc b/dex2oat/driver/compiler_driver.cc
index 9029693..26f606e 100644
--- a/dex2oat/driver/compiler_driver.cc
+++ b/dex2oat/driver/compiler_driver.cc
@@ -1124,7 +1124,7 @@
     image_classes->insert(descriptor);
     VLOG(compiler) << "Adding " << descriptor << " to image classes";
     for (size_t i = 0, num_interfaces = klass->NumDirectInterfaces(); i != num_interfaces; ++i) {
-      ObjPtr<mirror::Class> interface = mirror::Class::GetDirectInterface(self, klass, i);
+      ObjPtr<mirror::Class> interface = klass->GetDirectInterface(i);
       DCHECK(interface != nullptr);
       MaybeAddToImageClasses(self, interface, image_classes);
     }
@@ -2468,7 +2468,7 @@
   }
 
   // In this phase the classes containing class initializers are ignored. Make sure no
-  // clinit appears in kalss's super class chain and interfaces.
+  // clinit appears in klass's super class chain and interfaces.
   bool NoClinitInDependency(const Handle<mirror::Class>& klass,
                             Thread* self,
                             Handle<mirror::ClassLoader>* class_loader)
@@ -2490,8 +2490,8 @@
 
     uint32_t num_if = klass->NumDirectInterfaces();
     for (size_t i = 0; i < num_if; i++) {
-      ObjPtr<mirror::Class>
-          interface = mirror::Class::GetDirectInterface(self, klass.Get(), i);
+      ObjPtr<mirror::Class> interface = klass->GetDirectInterface(i);
+      DCHECK(interface != nullptr);
       StackHandleScope<1> hs(self);
       Handle<mirror::Class> handle_interface(hs.NewHandle(interface));
       if (!NoClinitInDependency(handle_interface, self, class_loader)) {
diff --git a/openjdkjvmti/ti_heap.cc b/openjdkjvmti/ti_heap.cc
index f4e34dd..27fed28 100644
--- a/openjdkjvmti/ti_heap.cc
+++ b/openjdkjvmti/ti_heap.cc
@@ -415,8 +415,7 @@
         Visit(self, klass->GetSuperClass(), visitor);
       }
       for (uint32_t i = 0; i != klass->NumDirectInterfaces(); ++i) {
-        art::ObjPtr<art::mirror::Class> inf_klass =
-            art::mirror::Class::GetDirectInterface(self, klass, i);
+        art::ObjPtr<art::mirror::Class> inf_klass = klass->GetDirectInterface(i);
         DCHECK(inf_klass != nullptr);
         VisitInterface(self, inf_klass, visitor);
       }
@@ -436,8 +435,7 @@
 
       // Now visit the superinterfaces.
       for (uint32_t i = 0; i != inf_klass->NumDirectInterfaces(); ++i) {
-        art::ObjPtr<art::mirror::Class> super_inf_klass =
-            art::mirror::Class::GetDirectInterface(self, inf_klass, i);
+        art::ObjPtr<art::mirror::Class> super_inf_klass = inf_klass->GetDirectInterface(i);
         DCHECK(super_inf_klass != nullptr);
         VisitInterface(self, super_inf_klass, visitor);
       }
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 50b5357..0eeda74 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -897,15 +897,11 @@
   object_array_class->GetIfTable()->SetInterface(0, java_lang_Cloneable.Get());
   object_array_class->GetIfTable()->SetInterface(1, java_io_Serializable.Get());
 
-  // Check Class[] and Object[]'s interfaces. GetDirectInterface may cause thread suspension.
-  CHECK_EQ(java_lang_Cloneable.Get(),
-           mirror::Class::GetDirectInterface(self, class_array_class.Get(), 0));
-  CHECK_EQ(java_io_Serializable.Get(),
-           mirror::Class::GetDirectInterface(self, class_array_class.Get(), 1));
-  CHECK_EQ(java_lang_Cloneable.Get(),
-           mirror::Class::GetDirectInterface(self, object_array_class.Get(), 0));
-  CHECK_EQ(java_io_Serializable.Get(),
-           mirror::Class::GetDirectInterface(self, object_array_class.Get(), 1));
+  // Check Class[] and Object[]'s interfaces.
+  CHECK_EQ(java_lang_Cloneable.Get(), class_array_class->GetDirectInterface(0));
+  CHECK_EQ(java_io_Serializable.Get(), class_array_class->GetDirectInterface(1));
+  CHECK_EQ(java_lang_Cloneable.Get(), object_array_class->GetDirectInterface(0));
+  CHECK_EQ(java_io_Serializable.Get(), object_array_class->GetDirectInterface(1));
 
   CHECK_EQ(object_array_string.Get(),
            FindSystemClass(self, GetClassRootDescriptor(ClassRoot::kJavaLangStringArrayClass)));
@@ -1859,10 +1855,9 @@
       return true;
     };
     class_table->Visit(verify_direct_interfaces_in_table);
-    Thread* self = Thread::Current();
     for (ObjPtr<mirror::Class> klass : classes) {
       for (uint32_t i = 0, num = klass->NumDirectInterfaces(); i != num; ++i) {
-        CHECK(klass->GetDirectInterface(self, klass, i) != nullptr)
+        CHECK(klass->GetDirectInterface(i) != nullptr)
             << klass->PrettyDescriptor() << " iface #" << i;
       }
     }
@@ -5401,7 +5396,7 @@
       StackHandleScope<1> hs_iface(self);
       MutableHandle<mirror::Class> handle_scope_iface(hs_iface.NewHandle<mirror::Class>(nullptr));
       for (size_t i = 0; i < num_direct_interfaces; i++) {
-        handle_scope_iface.Assign(mirror::Class::GetDirectInterface(self, klass.Get(), i));
+        handle_scope_iface.Assign(klass->GetDirectInterface(i));
         CHECK(handle_scope_iface != nullptr) << klass->PrettyDescriptor() << " iface #" << i;
         CHECK(handle_scope_iface->IsInterface());
         if (handle_scope_iface->HasBeenRecursivelyInitialized()) {
@@ -5554,7 +5549,7 @@
     MutableHandle<mirror::Class> handle_super_iface(hs.NewHandle<mirror::Class>(nullptr));
     // First we initialize all of iface's super-interfaces recursively.
     for (size_t i = 0; i < num_direct_ifaces; i++) {
-      ObjPtr<mirror::Class> super_iface = mirror::Class::GetDirectInterface(self, iface.Get(), i);
+      ObjPtr<mirror::Class> super_iface = iface->GetDirectInterface(i);
       CHECK(super_iface != nullptr) << iface->PrettyDescriptor() << " iface #" << i;
       if (!super_iface->HasBeenRecursivelyInitialized()) {
         // Recursive step
@@ -7185,8 +7180,7 @@
 // super_ifcount entries filled in with the transitive closure of the interfaces of the superclass.
 // The other entries are uninitialized.  We will fill in the remaining entries in this function. The
 // iftable must be large enough to hold all interfaces without changing its size.
-static size_t FillIfTable(Thread* self,
-                          ObjPtr<mirror::Class> klass,
+static size_t FillIfTable(ObjPtr<mirror::Class> klass,
                           ObjPtr<mirror::ObjectArray<mirror::Class>> interfaces,
                           ObjPtr<mirror::IfTable> iftable,
                           size_t super_ifcount,
@@ -7207,9 +7201,8 @@
   size_t filled_ifcount = super_ifcount;
   const bool have_interfaces = interfaces != nullptr;
   for (size_t i = 0; i != num_interfaces; ++i) {
-    ObjPtr<mirror::Class> interface = have_interfaces
-        ? interfaces->Get(i)
-        : mirror::Class::GetDirectInterface(self, klass, i);
+    ObjPtr<mirror::Class> interface =
+        have_interfaces ? interfaces->Get(i) : klass->GetDirectInterface(i);
 
     // Let us call the first filled_ifcount elements of iftable the current-iface-list.
     // At this point in the loop current-iface-list has the invariant that:
@@ -7301,9 +7294,8 @@
   size_t ifcount = super_ifcount + num_interfaces;
   // Check that every class being implemented is an interface.
   for (size_t i = 0; i < num_interfaces; i++) {
-    ObjPtr<mirror::Class> interface = have_interfaces
-        ? interfaces->GetWithoutChecks(i)
-        : mirror::Class::GetDirectInterface(self, klass.Get(), i);
+    ObjPtr<mirror::Class> interface =
+        have_interfaces ? interfaces->GetWithoutChecks(i) : klass->GetDirectInterface(i);
     DCHECK(interface != nullptr);
     if (UNLIKELY(!interface->IsInterface())) {
       std::string temp;
@@ -7335,8 +7327,8 @@
   // doesn't really do anything.
   self->AllowThreadSuspension();
 
-  const size_t new_ifcount = FillIfTable(
-      self, klass.Get(), interfaces.Get(), iftable.Get(), super_ifcount, num_interfaces);
+  const size_t new_ifcount =
+      FillIfTable(klass.Get(), interfaces.Get(), iftable.Get(), super_ifcount, num_interfaces);
 
   self->AllowThreadSuspension();
 
@@ -9313,18 +9305,15 @@
                                          ObjPtr<mirror::ClassLoader> class_loader,
                                          uint32_t field_idx,
                                          bool is_static) {
-  ArtField* resolved = nullptr;
-  Thread* self = is_static ? Thread::Current() : nullptr;
-  const DexFile& dex_file = *dex_cache->GetDexFile();
-
-  resolved = is_static ? mirror::Class::FindStaticField(self, klass, dex_cache, field_idx)
-                       : klass->FindInstanceField(dex_cache, field_idx);
+  ArtField* resolved = is_static ? klass->FindStaticField(dex_cache, field_idx)
+                                 : klass->FindInstanceField(dex_cache, field_idx);
 
   if (resolved == nullptr) {
+    const DexFile& dex_file = *dex_cache->GetDexFile();
     const dex::FieldId& field_id = dex_file.GetFieldId(field_idx);
     const char* name = dex_file.GetFieldName(field_id);
     const char* type = dex_file.GetFieldTypeDescriptor(field_id);
-    resolved = is_static ? mirror::Class::FindStaticField(self, klass, name, type)
+    resolved = is_static ? klass->FindStaticField(name, type)
                          : klass->FindInstanceField(name, type);
   }
 
@@ -9346,8 +9335,7 @@
                                             ObjPtr<mirror::DexCache> dex_cache,
                                             ObjPtr<mirror::ClassLoader> class_loader,
                                             uint32_t field_idx) {
-  Thread* self = Thread::Current();
-  ArtField* resolved = mirror::Class::FindField(self, klass, dex_cache, field_idx);
+  ArtField* resolved = klass->FindField(dex_cache, field_idx);
 
   if (resolved != nullptr &&
       hiddenapi::ShouldDenyAccessToMember(resolved,
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index c561c4d..5dc194f 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -231,12 +231,10 @@
     EXPECT_TRUE(array->ShouldHaveEmbeddedVTable());
     EXPECT_EQ(2, array->GetIfTableCount());
     ASSERT_TRUE(array->GetIfTable() != nullptr);
-    ObjPtr<mirror::Class> direct_interface0 =
-        mirror::Class::GetDirectInterface(self, array.Get(), 0);
+    ObjPtr<mirror::Class> direct_interface0 = array->GetDirectInterface(0);
     EXPECT_TRUE(direct_interface0 != nullptr);
     EXPECT_STREQ(direct_interface0->GetDescriptor(&temp), "Ljava/lang/Cloneable;");
-    ObjPtr<mirror::Class> direct_interface1 =
-        mirror::Class::GetDirectInterface(self, array.Get(), 1);
+    ObjPtr<mirror::Class> direct_interface1 = array->GetDirectInterface(1);
     EXPECT_STREQ(direct_interface1->GetDescriptor(&temp), "Ljava/io/Serializable;");
     EXPECT_OBJ_PTR_EQ(class_linker_->FindArrayClass(self, array->GetComponentType()), array.Get());
 
@@ -1182,48 +1180,47 @@
 
   EXPECT_EQ(9U, statics->NumStaticFields());
 
-  ArtField* s0 = mirror::Class::FindStaticField(soa.Self(), statics.Get(), "s0", "Z");
+  ArtField* s0 = statics->FindStaticField("s0", "Z");
   EXPECT_EQ(s0->GetTypeAsPrimitiveType(), Primitive::kPrimBoolean);
   EXPECT_EQ(true, s0->GetBoolean(statics.Get()));
   s0->SetBoolean<false>(statics.Get(), false);
 
-  ArtField* s1 = mirror::Class::FindStaticField(soa.Self(), statics.Get(), "s1", "B");
+  ArtField* s1 = statics->FindStaticField("s1", "B");
   EXPECT_EQ(s1->GetTypeAsPrimitiveType(), Primitive::kPrimByte);
   EXPECT_EQ(5, s1->GetByte(statics.Get()));
   s1->SetByte<false>(statics.Get(), 6);
 
-  ArtField* s2 = mirror::Class::FindStaticField(soa.Self(), statics.Get(), "s2", "C");
+  ArtField* s2 = statics->FindStaticField("s2", "C");
   EXPECT_EQ(s2->GetTypeAsPrimitiveType(), Primitive::kPrimChar);
   EXPECT_EQ('a', s2->GetChar(statics.Get()));
   s2->SetChar<false>(statics.Get(), 'b');
 
-  ArtField* s3 = mirror::Class::FindStaticField(soa.Self(), statics.Get(), "s3", "S");
+  ArtField* s3 = statics->FindStaticField("s3", "S");
   EXPECT_EQ(s3->GetTypeAsPrimitiveType(), Primitive::kPrimShort);
   EXPECT_EQ(-536, s3->GetShort(statics.Get()));
   s3->SetShort<false>(statics.Get(), -535);
 
-  ArtField* s4 = mirror::Class::FindStaticField(soa.Self(), statics.Get(), "s4", "I");
+  ArtField* s4 = statics->FindStaticField("s4", "I");
   EXPECT_EQ(s4->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
   EXPECT_EQ(2000000000, s4->GetInt(statics.Get()));
   s4->SetInt<false>(statics.Get(), 2000000001);
 
-  ArtField* s5 = mirror::Class::FindStaticField(soa.Self(), statics.Get(), "s5", "J");
+  ArtField* s5 = statics->FindStaticField("s5", "J");
   EXPECT_EQ(s5->GetTypeAsPrimitiveType(), Primitive::kPrimLong);
   EXPECT_EQ(0x1234567890abcdefLL, s5->GetLong(statics.Get()));
   s5->SetLong<false>(statics.Get(), INT64_C(0x34567890abcdef12));
 
-  ArtField* s6 = mirror::Class::FindStaticField(soa.Self(), statics.Get(), "s6", "F");
+  ArtField* s6 = statics->FindStaticField("s6", "F");
   EXPECT_EQ(s6->GetTypeAsPrimitiveType(), Primitive::kPrimFloat);
   EXPECT_DOUBLE_EQ(0.5, s6->GetFloat(statics.Get()));
   s6->SetFloat<false>(statics.Get(), 0.75);
 
-  ArtField* s7 = mirror::Class::FindStaticField(soa.Self(), statics.Get(), "s7", "D");
+  ArtField* s7 = statics->FindStaticField("s7", "D");
   EXPECT_EQ(s7->GetTypeAsPrimitiveType(), Primitive::kPrimDouble);
   EXPECT_DOUBLE_EQ(16777217.0, s7->GetDouble(statics.Get()));
   s7->SetDouble<false>(statics.Get(), 16777219);
 
-  ArtField* s8 = mirror::Class::FindStaticField(
-      soa.Self(), statics.Get(), "s8", "Ljava/lang/String;");
+  ArtField* s8 = statics->FindStaticField("s8", "Ljava/lang/String;");
   EXPECT_EQ(s8->GetTypeAsPrimitiveType(), Primitive::kPrimNot);
   EXPECT_TRUE(s8->GetObject(statics.Get())->AsString()->Equals("android"));
   ObjPtr<mirror::String> str_value = mirror::String::AllocFromModifiedUtf8(soa.Self(), "robot");
@@ -1300,14 +1297,10 @@
   EXPECT_EQ(Aj1, A->FindVirtualMethodForVirtualOrInterface(Jj1, kRuntimePointerSize));
   EXPECT_EQ(Aj2, A->FindVirtualMethodForVirtualOrInterface(Jj2, kRuntimePointerSize));
 
-  ArtField* Afoo =
-      mirror::Class::FindStaticField(soa.Self(), A.Get(), "foo", "Ljava/lang/String;");
-  ArtField* Bfoo =
-      mirror::Class::FindStaticField(soa.Self(), B.Get(), "foo", "Ljava/lang/String;");
-  ArtField* Jfoo =
-      mirror::Class::FindStaticField(soa.Self(), J.Get(), "foo", "Ljava/lang/String;");
-  ArtField* Kfoo =
-      mirror::Class::FindStaticField(soa.Self(), K.Get(), "foo", "Ljava/lang/String;");
+  ArtField* Afoo = A->FindStaticField("foo", "Ljava/lang/String;");
+  ArtField* Bfoo = B->FindStaticField("foo", "Ljava/lang/String;");
+  ArtField* Jfoo = J->FindStaticField("foo", "Ljava/lang/String;");
+  ArtField* Kfoo = K->FindStaticField("foo", "Ljava/lang/String;");
   ASSERT_TRUE(Afoo != nullptr);
   EXPECT_EQ(Afoo, Bfoo);
   EXPECT_EQ(Afoo, Jfoo);
diff --git a/runtime/jni/jni_internal.cc b/runtime/jni/jni_internal.cc
index f483ad3..45fbf00 100644
--- a/runtime/jni/jni_internal.cc
+++ b/runtime/jni/jni_internal.cc
@@ -476,8 +476,7 @@
   }
   std::string temp;
   if (is_static) {
-    field = mirror::Class::FindStaticField(
-        soa.Self(), c.Get(), name, field_type->GetDescriptor(&temp));
+    field = c->FindStaticField(name, field_type->GetDescriptor(&temp));
   } else {
     field = c->FindInstanceField(name, field_type->GetDescriptor(&temp));
   }
diff --git a/runtime/mirror/class.cc b/runtime/mirror/class.cc
index e6397cb..8bec7e4 100644
--- a/runtime/mirror/class.cc
+++ b/runtime/mirror/class.cc
@@ -378,6 +378,7 @@
 }
 
 void Class::DumpClass(std::ostream& os, int flags) {
+  ScopedAssertNoThreadSuspension ants(__FUNCTION__);
   if ((flags & kDumpClassFullDetail) == 0) {
     os << PrettyClass();
     if ((flags & kDumpClassClassLoader) != 0) {
@@ -390,22 +391,19 @@
     return;
   }
 
-  Thread* const self = Thread::Current();
-  StackHandleScope<2> hs(self);
-  Handle<Class> h_this(hs.NewHandle(this));
-  Handle<Class> h_super(hs.NewHandle(GetSuperClass()));
+  ObjPtr<Class> super = GetSuperClass();
   auto image_pointer_size = Runtime::Current()->GetClassLinker()->GetImagePointerSize();
 
   std::string temp;
   os << "----- " << (IsInterface() ? "interface" : "class") << " "
-     << "'" << GetDescriptor(&temp) << "' cl=" << GetClassLoader() << " -----\n",
-  os << "  objectSize=" << SizeOf() << " "
-     << "(" << (h_super != nullptr ? h_super->SizeOf() : -1) << " from super)\n",
-  os << StringPrintf("  access=0x%04x.%04x\n",
-      GetAccessFlags() >> 16, GetAccessFlags() & kAccJavaFlagsMask);
-  if (h_super != nullptr) {
-    os << "  super='" << h_super->PrettyClass() << "' (cl=" << h_super->GetClassLoader()
-       << ")\n";
+     << "'" << GetDescriptor(&temp) << "' cl=" << GetClassLoader() << " -----\n"
+     << "  objectSize=" << SizeOf() << " "
+     << "(" << (super != nullptr ? super->SizeOf() : -1) << " from super)\n"
+     << StringPrintf("  access=0x%04x.%04x\n",
+                     GetAccessFlags() >> 16,
+                     GetAccessFlags() & kAccJavaFlagsMask);
+  if (super != nullptr) {
+    os << "  super='" << super->PrettyClass() << "' (cl=" << super->GetClassLoader() << ")\n";
   }
   if (IsArrayClass()) {
     os << "  componentType=" << PrettyClass(GetComponentType()) << "\n";
@@ -414,7 +412,7 @@
   if (num_direct_interfaces > 0) {
     os << "  interfaces (" << num_direct_interfaces << "):\n";
     for (size_t i = 0; i < num_direct_interfaces; ++i) {
-      ObjPtr<Class> interface = GetDirectInterface(self, h_this.Get(), i);
+      ObjPtr<Class> interface = GetDirectInterface(i);
       if (interface == nullptr) {
         os << StringPrintf("    %2zd: nullptr!\n", i);
       } else {
@@ -426,35 +424,33 @@
   if (!IsLoaded()) {
     os << "  class not yet loaded";
   } else {
-    // After this point, this may have moved due to GetDirectInterface.
-    os << "  vtable (" << h_this->NumVirtualMethods() << " entries, "
-        << (h_super != nullptr ? h_super->NumVirtualMethods() : 0) << " in super):\n";
+    os << "  vtable (" << NumVirtualMethods() << " entries, "
+        << (super != nullptr ? super->NumVirtualMethods() : 0) << " in super):\n";
     for (size_t i = 0; i < NumVirtualMethods(); ++i) {
       os << StringPrintf("    %2zd: %s\n", i, ArtMethod::PrettyMethod(
-          h_this->GetVirtualMethodDuringLinking(i, image_pointer_size)).c_str());
+          GetVirtualMethodDuringLinking(i, image_pointer_size)).c_str());
     }
-    os << "  direct methods (" << h_this->NumDirectMethods() << " entries):\n";
-    for (size_t i = 0; i < h_this->NumDirectMethods(); ++i) {
+    os << "  direct methods (" << NumDirectMethods() << " entries):\n";
+    for (size_t i = 0; i < NumDirectMethods(); ++i) {
       os << StringPrintf("    %2zd: %s\n", i, ArtMethod::PrettyMethod(
-          h_this->GetDirectMethod(i, image_pointer_size)).c_str());
+          GetDirectMethod(i, image_pointer_size)).c_str());
     }
-    if (h_this->NumStaticFields() > 0) {
-      os << "  static fields (" << h_this->NumStaticFields() << " entries):\n";
-      if (h_this->IsResolved()) {
-        for (size_t i = 0; i < h_this->NumStaticFields(); ++i) {
-          os << StringPrintf("    %2zd: %s\n", i,
-                             ArtField::PrettyField(h_this->GetStaticField(i)).c_str());
+    if (NumStaticFields() > 0) {
+      os << "  static fields (" << NumStaticFields() << " entries):\n";
+      if (IsResolved()) {
+        for (size_t i = 0; i < NumStaticFields(); ++i) {
+          os << StringPrintf("    %2zd: %s\n", i, ArtField::PrettyField(GetStaticField(i)).c_str());
         }
       } else {
         os << "    <not yet available>";
       }
     }
-    if (h_this->NumInstanceFields() > 0) {
-      os << "  instance fields (" << h_this->NumInstanceFields() << " entries):\n";
-      if (h_this->IsResolved()) {
-        for (size_t i = 0; i < h_this->NumInstanceFields(); ++i) {
+    if (NumInstanceFields() > 0) {
+      os << "  instance fields (" << NumInstanceFields() << " entries):\n";
+      if (IsResolved()) {
+        for (size_t i = 0; i < NumInstanceFields(); ++i) {
           os << StringPrintf("    %2zd: %s\n", i,
-                             ArtField::PrettyField(h_this->GetInstanceField(i)).c_str());
+                             ArtField::PrettyField(GetInstanceField(i)).c_str());
         }
       } else {
         os << "    <not yet available>";
@@ -1035,13 +1031,11 @@
   return nullptr;
 }
 
-ArtField* Class::FindStaticField(Thread* self,
-                                 ObjPtr<Class> klass,
-                                 std::string_view name,
-                                 std::string_view type) {
+ArtField* Class::FindStaticField(std::string_view name, std::string_view type) {
+  ScopedAssertNoThreadSuspension ants(__FUNCTION__);
   // Is the field in this class (or its interfaces), or any of its
   // superclasses (or their interfaces)?
-  for (ObjPtr<Class> k = klass; k != nullptr; k = k->GetSuperClass()) {
+  for (ObjPtr<Class> k = this; k != nullptr; k = k->GetSuperClass()) {
     // Is the field in this class?
     ArtField* f = k->FindDeclaredStaticField(name, type);
     if (f != nullptr) {
@@ -1049,9 +1043,9 @@
     }
     // Is this field in any of this class' interfaces?
     for (uint32_t i = 0, num_interfaces = k->NumDirectInterfaces(); i != num_interfaces; ++i) {
-      ObjPtr<Class> interface = GetDirectInterface(self, k, i);
+      ObjPtr<Class> interface = k->GetDirectInterface(i);
       DCHECK(interface != nullptr);
-      f = FindStaticField(self, interface, name, type);
+      f = interface->FindStaticField(name, type);
       if (f != nullptr) {
         return f;
       }
@@ -1060,24 +1054,19 @@
   return nullptr;
 }
 
-ArtField* Class::FindStaticField(Thread* self,
-                                 ObjPtr<Class> klass,
-                                 ObjPtr<DexCache> dex_cache,
-                                 uint32_t dex_field_idx) {
-  for (ObjPtr<Class> k = klass; k != nullptr; k = k->GetSuperClass()) {
+ArtField* Class::FindStaticField(ObjPtr<DexCache> dex_cache, uint32_t dex_field_idx) {
+  ScopedAssertNoThreadSuspension ants(__FUNCTION__);
+  for (ObjPtr<Class> k = this; k != nullptr; k = k->GetSuperClass()) {
     // Is the field in this class?
     ArtField* f = k->FindDeclaredStaticField(dex_cache, dex_field_idx);
     if (f != nullptr) {
       return f;
     }
-    // Though GetDirectInterface() should not cause thread suspension when called
-    // from here, it takes a Handle as an argument, so we need to wrap `k`.
-    ScopedAssertNoThreadSuspension ants(__FUNCTION__);
     // Is this field in any of this class' interfaces?
     for (uint32_t i = 0, num_interfaces = k->NumDirectInterfaces(); i != num_interfaces; ++i) {
-      ObjPtr<Class> interface = GetDirectInterface(self, k, i);
+      ObjPtr<Class> interface = k->GetDirectInterface(i);
       DCHECK(interface != nullptr);
-      f = FindStaticField(self, interface, dex_cache, dex_field_idx);
+      f = interface->FindStaticField(dex_cache, dex_field_idx);
       if (f != nullptr) {
         return f;
       }
@@ -1088,22 +1077,20 @@
 
 // Find a field using the JLS field resolution order
 FLATTEN
-ArtField* Class::FindField(Thread* self,
-                           ObjPtr<Class> klass,
-                           ObjPtr<mirror::DexCache> dex_cache,
-                           uint32_t field_idx) {
+ArtField* Class::FindField(ObjPtr<mirror::DexCache> dex_cache, uint32_t field_idx) {
   // FIXME: Hijacking a proxy class by a custom class loader can break this assumption.
-  DCHECK(!klass->IsProxyClass());
+  DCHECK(!IsProxyClass());
+
+  ScopedAssertNoThreadSuspension ants(__FUNCTION__);
 
   // First try to find a declared field by `field_idx` if we have a `dex_cache` match.
-  ObjPtr<DexCache> klass_dex_cache = klass->GetDexCache();
-  if (klass_dex_cache == dex_cache) {
+  ObjPtr<DexCache> this_dex_cache = GetDexCache();
+  if (this_dex_cache == dex_cache) {
     // Lookup is always performed in the class referenced by the FieldId.
-    DCHECK_EQ(klass->dex_type_idx_,
-              klass_dex_cache->GetDexFile()->GetFieldId(field_idx).class_idx_.index_);
-    ArtField* f = klass->FindDeclaredInstanceField(klass_dex_cache, field_idx);
+    DCHECK_EQ(dex_type_idx_, this_dex_cache->GetDexFile()->GetFieldId(field_idx).class_idx_.index_);
+    ArtField* f = FindDeclaredInstanceField(this_dex_cache, field_idx);
     if (f == nullptr) {
-      f = klass->FindDeclaredStaticField(klass_dex_cache, field_idx);
+      f = FindDeclaredStaticField(this_dex_cache, field_idx);
     }
     if (f != nullptr) {
       return f;
@@ -1136,9 +1123,9 @@
     if (num_interfaces != 0u) {
       ensure_name_and_type_initialized();
       for (uint32_t i = 0; i != num_interfaces; ++i) {
-        ObjPtr<Class> interface = GetDirectInterface(self, k, i);
+        ObjPtr<Class> interface = k->GetDirectInterface(i);
         DCHECK(interface != nullptr);
-        ArtField* f = FindStaticField(self, interface, name, type);
+        ArtField* f = interface->FindStaticField(name, type);
         if (f != nullptr) {
           return f;
         }
@@ -1148,12 +1135,11 @@
   };
 
   // If we had a dex cache mismatch, search declared fields by name and type.
-  if (klass_dex_cache != dex_cache &&
-      (klass->GetIFieldsPtr() != nullptr || klass->GetSFieldsPtr() != nullptr)) {
+  if (this_dex_cache != dex_cache && (GetIFieldsPtr() != nullptr || GetSFieldsPtr() != nullptr)) {
     ensure_name_and_type_initialized();
-    ArtField* f = klass->FindDeclaredInstanceField(name, type);
+    ArtField* f = FindDeclaredInstanceField(name, type);
     if (f == nullptr) {
-      f = klass->FindDeclaredStaticField(name, type);
+      f = FindDeclaredStaticField(name, type);
     }
     if (f != nullptr) {
       return f;
@@ -1162,14 +1148,14 @@
 
   // Search direct interfaces.
   {
-    ArtField* f = search_direct_interfaces(klass);
+    ArtField* f = search_direct_interfaces(this);
     if (f != nullptr) {
       return f;
     }
   }
 
   // Continue searching in superclasses.
-  for (ObjPtr<Class> k = klass->GetSuperClass(); k != nullptr; k = k->GetSuperClass()) {
+  for (ObjPtr<Class> k = GetSuperClass(); k != nullptr; k = k->GetSuperClass()) {
     // Is the field in this class?
     ObjPtr<DexCache> k_dex_cache = k->GetDexCache();
     if (k_dex_cache == dex_cache) {
@@ -1292,35 +1278,30 @@
   return GetInterfaceTypeList()->GetTypeItem(idx).type_idx_;
 }
 
-ObjPtr<Class> Class::GetDirectInterface(Thread* self, ObjPtr<Class> klass, uint32_t idx) {
-  DCHECK(klass != nullptr);
-  DCHECK(!klass->IsPrimitive());
-  if (klass->IsArrayClass()) {
-    ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-    // Use ClassLinker::LookupClass(); avoid poisoning ObjPtr<>s by ClassLinker::FindSystemClass().
-    ObjPtr<Class> interface;
-    if (idx == 0) {
-      interface = class_linker->LookupClass(self, "Ljava/lang/Cloneable;", nullptr);
-    } else {
-      DCHECK_EQ(1U, idx);
-      interface = class_linker->LookupClass(self, "Ljava/io/Serializable;", nullptr);
-    }
+ObjPtr<Class> Class::GetDirectInterface(uint32_t idx) {
+  DCHECK(!IsPrimitive());
+  if (IsArrayClass()) {
+    ObjPtr<IfTable> iftable = GetIfTable();
+    DCHECK(iftable != nullptr);
+    DCHECK_EQ(iftable->Count(), 2u);
+    DCHECK_LT(idx, 2u);
+    ObjPtr<Class> interface = iftable->GetInterface(idx);
     DCHECK(interface != nullptr);
     return interface;
-  } else if (klass->IsProxyClass()) {
-    ObjPtr<ObjectArray<Class>> interfaces = klass->GetProxyInterfaces();
+  } else if (IsProxyClass()) {
+    ObjPtr<ObjectArray<Class>> interfaces = GetProxyInterfaces();
     DCHECK(interfaces != nullptr);
     return interfaces->Get(idx);
   } else {
-    dex::TypeIndex type_idx = klass->GetDirectInterfaceTypeIdx(idx);
+    dex::TypeIndex type_idx = GetDirectInterfaceTypeIdx(idx);
     ObjPtr<Class> interface = Runtime::Current()->GetClassLinker()->LookupResolvedType(
-        type_idx, klass->GetDexCache(), klass->GetClassLoader());
+        type_idx, GetDexCache(), GetClassLoader());
     return interface;
   }
 }
 
 ObjPtr<Class> Class::ResolveDirectInterface(Thread* self, Handle<Class> klass, uint32_t idx) {
-  ObjPtr<Class> interface = GetDirectInterface(self, klass.Get(), idx);
+  ObjPtr<Class> interface = klass->GetDirectInterface(idx);
   if (interface == nullptr) {
     DCHECK(!klass->IsArrayClass());
     DCHECK(!klass->IsProxyClass());
diff --git a/runtime/mirror/class.h b/runtime/mirror/class.h
index aff98ca..35ef358 100644
--- a/runtime/mirror/class.h
+++ b/runtime/mirror/class.h
@@ -1092,10 +1092,7 @@
   ArtField* GetStaticField(uint32_t i) REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Find a static or instance field using the JLS resolution order
-  static ArtField* FindField(Thread* self,
-                             ObjPtr<Class> klass,
-                             ObjPtr<mirror::DexCache> dex_cache,
-                             uint32_t field_idx)
+  ArtField* FindField(ObjPtr<mirror::DexCache> dex_cache, uint32_t field_idx)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Finds the given instance field in this class or a superclass.
@@ -1114,18 +1111,12 @@
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Finds the given static field in this class or a superclass.
-  static ArtField* FindStaticField(Thread* self,
-                                   ObjPtr<Class> klass,
-                                   std::string_view name,
-                                   std::string_view type)
+  ArtField* FindStaticField(std::string_view name, std::string_view type)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Finds the given static field in this class or superclass, only searches classes that
   // have the same dex cache.
-  static ArtField* FindStaticField(Thread* self,
-                                   ObjPtr<Class> klass,
-                                   ObjPtr<DexCache> dex_cache,
-                                   uint32_t dex_field_idx)
+  ArtField* FindStaticField(ObjPtr<DexCache> dex_cache, uint32_t dex_field_idx)
       REQUIRES_SHARED(Locks::mutator_lock_);
 
   ArtField* FindDeclaredStaticField(std::string_view name, std::string_view type)
@@ -1219,11 +1210,10 @@
 
   dex::TypeIndex GetDirectInterfaceTypeIdx(uint32_t idx) REQUIRES_SHARED(Locks::mutator_lock_);
 
-  // Get the direct interface of the `klass` at index `idx` if resolved, otherwise return null.
+  // Get the direct interface at index `idx` if resolved, otherwise return null.
   // If the caller expects the interface to be resolved, for example for a resolved `klass`,
   // that assumption should be checked by `DCHECK(result != nullptr)`.
-  static ObjPtr<Class> GetDirectInterface(Thread* self, ObjPtr<Class> klass, uint32_t idx)
-      REQUIRES_SHARED(Locks::mutator_lock_);
+  ObjPtr<Class> GetDirectInterface(uint32_t idx) REQUIRES_SHARED(Locks::mutator_lock_);
 
   // Resolve and get the direct interface of the `klass` at index `idx`.
   // Returns null with a pending exception if the resolution fails.
diff --git a/runtime/mirror/object_test.cc b/runtime/mirror/object_test.cc
index 80ed832..e26cf42 100644
--- a/runtime/mirror/object_test.cc
+++ b/runtime/mirror/object_test.cc
@@ -147,9 +147,9 @@
   Handle<mirror::Class> klass(hs.NewHandle(oa->GetClass()));
   ASSERT_EQ(2U, klass->NumDirectInterfaces());
   EXPECT_OBJ_PTR_EQ(class_linker_->FindSystemClass(soa.Self(), "Ljava/lang/Cloneable;"),
-                    mirror::Class::GetDirectInterface(soa.Self(), klass.Get(), 0));
+                    klass->GetDirectInterface(0));
   EXPECT_OBJ_PTR_EQ(class_linker_->FindSystemClass(soa.Self(), "Ljava/io/Serializable;"),
-                    mirror::Class::GetDirectInterface(soa.Self(), klass.Get(), 1));
+                    klass->GetDirectInterface(1));
 }
 
 TEST_F(ObjectTest, AllocArray) {
@@ -758,20 +758,16 @@
 
   // Wrong type.
   EXPECT_TRUE(c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", "I") == nullptr);
-  EXPECT_TRUE(mirror::Class::FindStaticField(
-      soa.Self(), c.Get(), "CASE_INSENSITIVE_ORDER", "I") == nullptr);
+  EXPECT_TRUE(c->FindStaticField("CASE_INSENSITIVE_ORDER", "I") == nullptr);
 
   // Wrong name.
   EXPECT_TRUE(c->FindDeclaredStaticField(
       "cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;") == nullptr);
-  EXPECT_TRUE(
-      mirror::Class::FindStaticField(
-          soa.Self(), c.Get(), "cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;") == nullptr);
+  EXPECT_TRUE(c->FindStaticField("cASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;") == nullptr);
 
   // Right name and type.
   ArtField* f1 = c->FindDeclaredStaticField("CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
-  ArtField* f2 = mirror::Class::FindStaticField(
-      soa.Self(), c.Get(), "CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
+  ArtField* f2 = c->FindStaticField("CASE_INSENSITIVE_ORDER", "Ljava/util/Comparator;");
   EXPECT_TRUE(f1 != nullptr);
   EXPECT_TRUE(f2 != nullptr);
   EXPECT_EQ(f1, f2);
diff --git a/runtime/oat_file_assistant_test.cc b/runtime/oat_file_assistant_test.cc
index 3760885..9acb0b7 100644
--- a/runtime/oat_file_assistant_test.cc
+++ b/runtime/oat_file_assistant_test.cc
@@ -1419,8 +1419,7 @@
   linker->EnsureInitialized(soa.Self(), dexfile, true, true);
 
   for (std::pair<OatFileAssistant::DexOptNeeded, const char*> field : mapping) {
-    ArtField* art_field = mirror::Class::FindStaticField(
-        soa.Self(), dexfile.Get(), field.second, "I");
+    ArtField* art_field = dexfile->FindStaticField(field.second, "I");
     ASSERT_FALSE(art_field == nullptr);
     EXPECT_EQ(art_field->GetTypeAsPrimitiveType(), Primitive::kPrimInt);
     EXPECT_EQ(field.first, art_field->GetInt(dexfile.Get()));
diff --git a/runtime/proxy_test.cc b/runtime/proxy_test.cc
index d8e170b..d055186 100644
--- a/runtime/proxy_test.cc
+++ b/runtime/proxy_test.cc
@@ -68,8 +68,8 @@
   ASSERT_TRUE(proxy_class->IsInitialized());
 
   EXPECT_EQ(2U, proxy_class->NumDirectInterfaces());  // Interfaces$I and Interfaces$J.
-  EXPECT_OBJ_PTR_EQ(I.Get(), mirror::Class::GetDirectInterface(soa.Self(), proxy_class.Get(), 0));
-  EXPECT_OBJ_PTR_EQ(J.Get(), mirror::Class::GetDirectInterface(soa.Self(), proxy_class.Get(), 1));
+  EXPECT_OBJ_PTR_EQ(I.Get(), proxy_class->GetDirectInterface(0));
+  EXPECT_OBJ_PTR_EQ(J.Get(), proxy_class->GetDirectInterface(1));
   std::string temp;
   const char* proxy_class_descriptor = proxy_class->GetDescriptor(&temp);
   EXPECT_STREQ("L$Proxy1234;", proxy_class_descriptor);