Binary search stack maps by native pc.

Test: test.py --host -r -b -t 018 -t 510
Change-Id: I07042e8dfd82adcd24fdfe1a1970a7ccdc09ce46
diff --git a/runtime/stack_map.h b/runtime/stack_map.h
index 64a084f..7aac792 100644
--- a/runtime/stack_map.h
+++ b/runtime/stack_map.h
@@ -412,21 +412,7 @@
     return StackMap();
   }
 
-  StackMap GetStackMapForNativePcOffset(uint32_t pc, InstructionSet isa = kRuntimeISA) const {
-    // TODO: Safepoint stack maps are sorted by native_pc_offset but catch stack
-    //       maps are not. If we knew that the method does not have try/catch,
-    //       we could do binary search.
-    for (size_t i = 0, e = GetNumberOfStackMaps(); i < e; ++i) {
-      StackMap stack_map = GetStackMapAt(i);
-      if (stack_map.GetNativePcOffset(isa) == pc) {
-        StackMap::Kind kind = static_cast<StackMap::Kind>(stack_map.GetKind());
-        if (kind == StackMap::Kind::Default || kind == StackMap::Kind::OSR) {
-          return stack_map;
-        }
-      }
-    }
-    return StackMap();
-  }
+  StackMap GetStackMapForNativePcOffset(uint32_t pc, InstructionSet isa = kRuntimeISA) const;
 
   InvokeInfo GetInvokeInfoForNativePcOffset(uint32_t native_pc_offset) {
     for (size_t index = 0; index < invoke_infos_.NumRows(); index++) {
@@ -450,6 +436,10 @@
   void AddSizeStats(/*out*/ Stats* parent) const;
 
  private:
+  // Returns lower bound (fist stack map which has pc greater or equal than the desired one).
+  // It ignores catch stack maps at the end (it is the same as if they had maximum pc value).
+  BitTable<StackMap>::const_iterator BinarySearchNativePc(uint32_t packed_pc) const;
+
   // Scan backward to determine dex register locations at given stack map.
   void DecodeDexRegisterMap(uint32_t stack_map_index,
                             uint32_t first_dex_register,