Add Method/Field iterator to ClassAccessor

Enables ranged based for loops on fields and methods.

For visiting both fields and methods, VisitFieldsAndMethods will
be faster because of not needing to decode the fields twice for
seeking purposes.

Added test.

Bug: 79758018
Bug: 77709234
Test: test-art-host-gtest

Change-Id: I593e23ccd138b87a27d8bab6927ff2b685c057f3
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc
index 68155d8..fb6a72b 100644
--- a/compiler/dex/dex_to_dex_compiler.cc
+++ b/compiler/dex/dex_to_dex_compiler.cc
@@ -635,13 +635,13 @@
   std::unordered_set<const DexFile::CodeItem*> seen_code_items;
   for (const DexFile* dex_file : dex_files) {
     for (ClassAccessor accessor : dex_file->GetClasses()) {
-      accessor.VisitMethods([&](const ClassAccessor::Method& method) {
+      for (const ClassAccessor::Method& method : accessor.GetMethods()) {
         const DexFile::CodeItem* code_item = method.GetCodeItem();
         // Detect the shared code items.
         if (!seen_code_items.insert(code_item).second) {
           shared_code_items_.insert(code_item);
         }
-      });
+      }
     }
   }
   VLOG(compiler) << "Shared code items " << shared_code_items_.size();
diff --git a/compiler/dex/dex_to_dex_decompiler_test.cc b/compiler/dex/dex_to_dex_decompiler_test.cc
index 082e609..75de238 100644
--- a/compiler/dex/dex_to_dex_decompiler_test.cc
+++ b/compiler/dex/dex_to_dex_decompiler_test.cc
@@ -85,10 +85,9 @@
     for (uint32_t i = 0; i < updated_dex_file->NumClassDefs(); ++i) {
       // Unquicken each method.
       ClassAccessor accessor(*updated_dex_file, updated_dex_file->GetClassDef(i));
-      accessor.VisitMethods([&](const ClassAccessor::Method& method) {
+      for (const ClassAccessor::Method& method : accessor.GetMethods()) {
         CompiledMethod* compiled_method = compiler_driver_->GetCompiledMethod(
-            MethodReference(updated_dex_file,
-                            method.GetIndex()));
+            method.GetReference());
         ArrayRef<const uint8_t> table;
         if (compiled_method != nullptr) {
           table = compiled_method->GetVmapTable();
@@ -97,7 +96,7 @@
                                    *accessor.GetCodeItem(method),
                                    table,
                                    /* decompile_return_instruction */ true);
-      });
+      }
     }
 
     // Make sure after unquickening we go back to the same contents as the original dex file.
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index decb330..16f2d0f 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -790,8 +790,7 @@
         // FIXME: Make sure that inlining honors this. b/26687569
         continue;
       }
-      accessor.VisitMethods([&](const ClassAccessor::Method& method)
-          REQUIRES_SHARED(Locks::mutator_lock_) {
+      for (const ClassAccessor::Method& method : accessor.GetMethods()) {
         // Resolve const-strings in the code. Done to have deterministic allocation behavior. Right
         // now this is single-threaded for simplicity.
         // TODO: Collect the relevant string indices in parallel, then allocate them sequentially
@@ -812,7 +811,7 @@
               break;
           }
         }
-      });
+      }
     }
   }
 }
@@ -880,10 +879,9 @@
       }
 
       // Direct and virtual methods.
-      accessor.VisitMethods([&](const ClassAccessor::Method& method)
-          REQUIRES_SHARED(Locks::mutator_lock_) {
+      for (const ClassAccessor::Method& method : accessor.GetMethods()) {
         InitializeTypeCheckBitstrings(driver, class_linker, dex_cache, *dex_file, method);
-      });
+      }
     }
   }
 }
@@ -1949,9 +1947,9 @@
           // - We're only going to compile methods that did verify.
           // - Quickening will not do checkcast ellision.
           // TODO(ngeoffray): Reconsider this once we refactor compiler filters.
-          accessor.VisitMethods([&](const ClassAccessor::Method& method) {
+          for (const ClassAccessor::Method& method : accessor.GetMethods()) {
             verification_results_->CreateVerifiedMethodFor(method.GetReference());
-          });
+          }
         }
       } else if (!compiler_only_verifies) {
         // Make sure later compilation stages know they should not try to verify
@@ -2747,12 +2745,12 @@
 
     // Compile direct and virtual methods.
     int64_t previous_method_idx = -1;
-    accessor.VisitMethods([&](const ClassAccessor::Method& method) {
+    for (const ClassAccessor::Method& method : accessor.GetMethods()) {
       const uint32_t method_idx = method.GetIndex();
       if (method_idx == previous_method_idx) {
         // smali can create dex files with two encoded_methods sharing the same method_idx
         // http://code.google.com/p/smali/issues/detail?id=119
-        return;
+        continue;
       }
       previous_method_idx = method_idx;
       compile_fn(soa.Self(),
@@ -2767,7 +2765,7 @@
                  dex_to_dex_compilation_level,
                  compilation_enabled,
                  dex_cache);
-    });
+    }
   };
   context.ForAllLambda(0, dex_file.NumClassDefs(), compile, thread_count);
 }
diff --git a/compiler/verifier_deps_test.cc b/compiler/verifier_deps_test.cc
index 103862b..c0892ff 100644
--- a/compiler/verifier_deps_test.cc
+++ b/compiler/verifier_deps_test.cc
@@ -155,8 +155,7 @@
     bool has_failures = true;
     bool found_method = false;
 
-    accessor.VisitMethods([&](const ClassAccessor::Method& method)
-        REQUIRES_SHARED(Locks::mutator_lock_) {
+    for (const ClassAccessor::Method& method : accessor.GetMethods()) {
       ArtMethod* resolved_method =
           class_linker_->ResolveMethod<ClassLinker::ResolveMode::kNoChecks>(
               method.GetIndex(),
@@ -186,7 +185,7 @@
         has_failures = verifier.HasFailures();
         found_method = true;
       }
-    });
+    }
     CHECK(found_method) << "Expected to find method " << method_name;
     return !has_failures;
   }