Return an invalid StackMap when one cannot be found.

This avoids aborting when handling a crash.

Change-Id: Ie5b5d48061fa9258b349b0284f7b00c5855d9fbd
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index 9518c9d..079a231 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -201,29 +201,32 @@
   uint32_t sought_offset = pc - reinterpret_cast<uintptr_t>(entry_point);
   if (IsOptimized(sizeof(void*))) {
     CodeInfo code_info = GetOptimizedCodeInfo();
-    return code_info.GetStackMapForNativePcOffset(sought_offset).GetDexPc(code_info);
-  }
-
-  MappingTable table(entry_point != nullptr ?
-      GetMappingTable(EntryPointToCodePointer(entry_point), sizeof(void*)) : nullptr);
-  if (table.TotalSize() == 0) {
-    // NOTE: Special methods (see Mir2Lir::GenSpecialCase()) have an empty mapping
-    // but they have no suspend checks and, consequently, we never call ToDexPc() for them.
-    DCHECK(IsNative() || IsCalleeSaveMethod() || IsProxyMethod()) << PrettyMethod(this);
-    return DexFile::kDexNoIndex;   // Special no mapping case
-  }
-  // Assume the caller wants a pc-to-dex mapping so check here first.
-  typedef MappingTable::PcToDexIterator It;
-  for (It cur = table.PcToDexBegin(), end = table.PcToDexEnd(); cur != end; ++cur) {
-    if (cur.NativePcOffset() == sought_offset) {
-      return cur.DexPc();
+    StackMap stack_map = code_info.GetStackMapForNativePcOffset(sought_offset);
+    if (stack_map.IsValid()) {
+      return stack_map.GetDexPc(code_info);
     }
-  }
-  // Now check dex-to-pc mappings.
-  typedef MappingTable::DexToPcIterator It2;
-  for (It2 cur = table.DexToPcBegin(), end = table.DexToPcEnd(); cur != end; ++cur) {
-    if (cur.NativePcOffset() == sought_offset) {
-      return cur.DexPc();
+  } else {
+    MappingTable table(entry_point != nullptr ?
+        GetMappingTable(EntryPointToCodePointer(entry_point), sizeof(void*)) : nullptr);
+    if (table.TotalSize() == 0) {
+      // NOTE: Special methods (see Mir2Lir::GenSpecialCase()) have an empty mapping
+      // but they have no suspend checks and, consequently, we never call ToDexPc() for them.
+      DCHECK(IsNative() || IsCalleeSaveMethod() || IsProxyMethod()) << PrettyMethod(this);
+      return DexFile::kDexNoIndex;   // Special no mapping case
+    }
+    // Assume the caller wants a pc-to-dex mapping so check here first.
+    typedef MappingTable::PcToDexIterator It;
+    for (It cur = table.PcToDexBegin(), end = table.PcToDexEnd(); cur != end; ++cur) {
+      if (cur.NativePcOffset() == sought_offset) {
+        return cur.DexPc();
+      }
+    }
+    // Now check dex-to-pc mappings.
+    typedef MappingTable::DexToPcIterator It2;
+    for (It2 cur = table.DexToPcBegin(), end = table.DexToPcEnd(); cur != end; ++cur) {
+      if (cur.NativePcOffset() == sought_offset) {
+        return cur.DexPc();
+      }
     }
   }
   if (abort_on_failure) {
diff --git a/runtime/stack.cc b/runtime/stack.cc
index 6795516..f7b96ea 100644
--- a/runtime/stack.cc
+++ b/runtime/stack.cc
@@ -109,6 +109,7 @@
   uint32_t native_pc_offset = outer_method->NativeQuickPcOffset(cur_quick_frame_pc_);
   CodeInfo code_info = outer_method->GetOptimizedCodeInfo();
   StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
+  DCHECK(stack_map.IsValid());
   return code_info.GetInlineInfoOf(stack_map);
 }
 
@@ -269,6 +270,7 @@
 
   uint32_t native_pc_offset = outer_method->NativeQuickPcOffset(cur_quick_frame_pc_);
   StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
+  DCHECK(stack_map.IsValid());
   size_t depth_in_stack_map = current_inlining_depth_ - 1;
 
   DexRegisterMap dex_register_map = IsInInlinedFrame()
@@ -749,7 +751,7 @@
           CodeInfo code_info = method->GetOptimizedCodeInfo();
           uint32_t native_pc_offset = method->NativeQuickPcOffset(cur_quick_frame_pc_);
           StackMap stack_map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
-          if (stack_map.HasInlineInfo(code_info)) {
+          if (stack_map.IsValid() && stack_map.HasInlineInfo(code_info)) {
             InlineInfo inline_info = code_info.GetInlineInfoOf(stack_map);
             DCHECK_EQ(current_inlining_depth_, 0u);
             for (current_inlining_depth_ = inline_info.GetDepth();
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index f07fb74..f710460 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -641,6 +641,9 @@
 class StackMap {
  public:
   explicit StackMap(MemoryRegion region) : region_(region) {}
+  StackMap() {}
+
+  bool IsValid() const { return region_.pointer() != nullptr; }
 
   uint32_t GetDexPc(const CodeInfo& info) const;
 
@@ -1029,8 +1032,7 @@
         return stack_map;
       }
     }
-    LOG(FATAL) << "Unreachable";
-    UNREACHABLE();
+    return StackMap();
   }
 
   StackMap GetStackMapForNativePcOffset(uint32_t native_pc_offset) const {
@@ -1041,8 +1043,7 @@
         return stack_map;
       }
     }
-    LOG(FATAL) << "Unreachable";
-    UNREACHABLE();
+    return StackMap();
   }
 
   void Dump(std::ostream& os, uint16_t number_of_dex_registers) const;
diff --git a/runtime/thread.cc b/runtime/thread.cc
index 2145c9c..9b1600f 100644
--- a/runtime/thread.cc
+++ b/runtime/thread.cc
@@ -2248,6 +2248,7 @@
         uintptr_t native_pc_offset = m->NativeQuickPcOffset(GetCurrentQuickFramePc(), entry_point);
         CodeInfo code_info = m->GetOptimizedCodeInfo();
         StackMap map = code_info.GetStackMapForNativePcOffset(native_pc_offset);
+        DCHECK(map.IsValid());
         MemoryRegion mask = map.GetStackMask(code_info);
         // Visit stack entries that hold pointers.
         for (size_t i = 0; i < mask.size_in_bits(); ++i) {