Support unrecognized methods in profman

If one tried to use profman files from the future (I.E. internal
master on AOSP) profman would LOG(FATAL) due to not finding the
methods listed. This is undesirable and a better solution is to simply
silently ignore this error since the profile files are only
occasionally updated.

Test: m droid
Bug: 168941430
Bug: 183514504
Change-Id: I1cf48173c7c708b1d732868bed3b268138c83063
diff --git a/libdexfile/dex/dex_file.cc b/libdexfile/dex/dex_file.cc
index 030b43b..f50e5cf 100644
--- a/libdexfile/dex/dex_file.cc
+++ b/libdexfile/dex/dex_file.cc
@@ -225,16 +225,23 @@
   return nullptr;
 }
 
-uint32_t DexFile::FindCodeItemOffset(const ClassDef& class_def, uint32_t method_idx) const {
+std::optional<uint32_t> DexFile::GetCodeItemOffset(const ClassDef &class_def,
+                                                   uint32_t method_idx) const {
   ClassAccessor accessor(*this, class_def);
   CHECK(accessor.HasClassData());
-  for (const ClassAccessor::Method& method : accessor.GetMethods()) {
+  for (const ClassAccessor::Method &method : accessor.GetMethods()) {
     if (method.GetIndex() == method_idx) {
       return method.GetCodeItemOffset();
     }
   }
-  LOG(FATAL) << "Unable to find method " << method_idx;
-  UNREACHABLE();
+  return std::nullopt;
+}
+
+uint32_t DexFile::FindCodeItemOffset(const dex::ClassDef &class_def,
+                                     uint32_t dex_method_idx) const {
+  std::optional<uint32_t> val = GetCodeItemOffset(class_def, dex_method_idx);
+  CHECK(val.has_value()) << "Unable to find method " << dex_method_idx;
+  return *val;
 }
 
 const FieldId* DexFile::FindFieldId(const TypeId& declaring_klass,
diff --git a/libdexfile/dex/dex_file.h b/libdexfile/dex/dex_file.h
index d97327c..6a1ca98 100644
--- a/libdexfile/dex/dex_file.h
+++ b/libdexfile/dex/dex_file.h
@@ -18,6 +18,7 @@
 #define ART_LIBDEXFILE_DEX_DEX_FILE_H_
 
 #include <memory>
+#include <optional>
 #include <string>
 #include <string_view>
 #include <vector>
@@ -333,6 +334,13 @@
                                   const dex::StringId& name,
                                   const dex::TypeId& type) const;
 
+  // Return the code-item offset associated with the class and method or nullopt
+  // if the method does not exist or has no code.
+  std::optional<uint32_t> GetCodeItemOffset(const dex::ClassDef& class_def,
+                                            uint32_t dex_method_idx) const;
+
+  // Return the code-item offset associated with the class and method or
+  // LOG(FATAL) if the method does not exist or has no code.
   uint32_t FindCodeItemOffset(const dex::ClassDef& class_def,
                               uint32_t dex_method_idx) const;
 
diff --git a/profman/profman.cc b/profman/profman.cc
index 9672f2b..b51029d 100644
--- a/profman/profman.cc
+++ b/profman/profman.cc
@@ -1109,12 +1109,17 @@
   template <typename Visitor>
   void VisitAllInstructions(const TypeReference& class_ref, uint16_t method_idx, Visitor visitor) {
     const DexFile* dex_file = class_ref.dex_file;
-    uint32_t offset =
-        dex_file->FindCodeItemOffset(*dex_file->FindClassDef(class_ref.TypeIndex()), method_idx);
-    for (const DexInstructionPcPair& inst :
-         CodeItemInstructionAccessor(*dex_file, dex_file->GetCodeItem(offset))) {
-      if (!visitor(inst)) {
-        break;
+    const dex::ClassDef* def = dex_file->FindClassDef(class_ref.TypeIndex());
+    if (def == nullptr) {
+      return;
+    }
+    std::optional<uint32_t> offset = dex_file->GetCodeItemOffset(*def, method_idx);
+    if (offset.has_value()) {
+      for (const DexInstructionPcPair& inst :
+          CodeItemInstructionAccessor(*dex_file, dex_file->GetCodeItem(*offset))) {
+        if (!visitor(inst)) {
+          break;
+        }
       }
     }
   }