NativePcOffsetToReferenceMap

Rather than translate a native PC to a Dex PC and then to the reference
bitmap, just go straight from the native PC to the reference bitmap.
Encode the native PC offsets using a hash rather than linearly
searching.

Change-Id: Iee1073d93c941c0a31f639e5f23cea9e9f747bee
diff --git a/src/verifier/gc_map.cc b/src/verifier/dex_gc_map.cc
similarity index 97%
rename from src/verifier/gc_map.cc
rename to src/verifier/dex_gc_map.cc
index 66cb6c7..c1c9a29 100644
--- a/src/verifier/gc_map.cc
+++ b/src/verifier/dex_gc_map.cc
@@ -14,7 +14,7 @@
  * limitations under the License.
  */
 
-#include "gc_map.h"
+#include "verifier/dex_gc_map.h"
 
 #include "logging.h"
 
diff --git a/src/verifier/gc_map.h b/src/verifier/dex_gc_map.h
similarity index 88%
rename from src/verifier/gc_map.h
rename to src/verifier/dex_gc_map.h
index d6a1c46..d588cfd 100644
--- a/src/verifier/gc_map.h
+++ b/src/verifier/dex_gc_map.h
@@ -14,8 +14,8 @@
  * limitations under the License.
  */
 
-#ifndef ART_SRC_VERIFIER_GC_MAP_H_
-#define ART_SRC_VERIFIER_GC_MAP_H_
+#ifndef ART_SRC_VERIFIER_DEX_GC_MAP_H_
+#define ART_SRC_VERIFIER_DEX_GC_MAP_H_
 
 #include "logging.h"
 #include "macros.h"
@@ -37,8 +37,7 @@
 // Lightweight wrapper for Dex PC to reference bit maps.
 class DexPcToReferenceMap {
  public:
-  DexPcToReferenceMap(const uint8_t* data, size_t data_length) {
-    data_ = data;
+  DexPcToReferenceMap(const uint8_t* data, size_t data_length) : data_(data) {
     CHECK(data_ != NULL);
     // Check the size of the table agrees with the number of entries
     size_t data_size = data_length - 4;
@@ -53,7 +52,7 @@
   // Get the Dex PC at the given index
   uint16_t GetDexPc(size_t index) const {
     size_t entry_offset = index * EntryWidth();
-    if (PcWidth() == 1) {
+    if (DexPcWidth() == 1) {
       return Table()[entry_offset];
     } else {
       return Table()[entry_offset] | (Table()[entry_offset + 1] << 8);
@@ -63,7 +62,7 @@
   // Return address of bitmap encoding what are live references
   const uint8_t* GetBitMap(size_t index) const {
     size_t entry_offset = index * EntryWidth();
-    return &Table()[entry_offset + PcWidth()];
+    return &Table()[entry_offset + DexPcWidth()];
   }
 
   // Find the bitmap associated with the given dex pc
@@ -86,7 +85,7 @@
   }
 
   // Number of bytes used to encode a dex pc
-  size_t PcWidth() const {
+  size_t DexPcWidth() const {
     RegisterMapFormat format = Format();
     switch (format) {
       case kRegMapFormatCompact8:
@@ -101,7 +100,7 @@
 
   // The width of an entry in the table
   size_t EntryWidth() const {
-    return PcWidth() + RegWidth();
+    return DexPcWidth() + RegWidth();
   }
 
   const uint8_t* GetData() const {
@@ -113,10 +112,10 @@
   static const int kRegMapFormatShift = 5;
   static const uint8_t kRegMapFormatMask = 0x7;
 
-  const uint8_t* data_;  // The header and table data
+  const uint8_t* const data_;  // The header and table data
 };
 
 }  // namespace verifier
 }  // namespace art
 
-#endif  // ART_SRC_VERIFIER_GC_MAP_H_
+#endif  // ART_SRC_VERIFIER_DEX_GC_MAP_H_
diff --git a/src/verifier/method_verifier.cc b/src/verifier/method_verifier.cc
index a01aa8d..73aee9c 100644
--- a/src/verifier/method_verifier.cc
+++ b/src/verifier/method_verifier.cc
@@ -24,7 +24,7 @@
 #include "dex_file.h"
 #include "dex_instruction.h"
 #include "dex_instruction_visitor.h"
-#include "gc_map.h"
+#include "verifier/dex_gc_map.h"
 #include "intern_table.h"
 #include "leb128.h"
 #include "logging.h"
@@ -549,8 +549,9 @@
 bool MethodVerifier::VerifyInstructions() {
   const Instruction* inst = Instruction::At(code_item_->insns_);
 
-  /* Flag the start of the method as a branch target. */
+  /* Flag the start of the method as a branch target, and a GC point due to stack overflow errors */
   insn_flags_[0].SetBranchTarget();
+  insn_flags_[0].SetGcPoint();
 
   uint32_t insns_size = code_item_->insns_size_in_code_units_;
   for (uint32_t dex_pc = 0; dex_pc < insns_size;) {
@@ -945,7 +946,7 @@
   return true;
 }
 
-const std::vector<uint8_t>* CreateLengthPrefixedGcMap(const std::vector<uint8_t>& gc_map) {
+static const std::vector<uint8_t>* CreateLengthPrefixedDexGcMap(const std::vector<uint8_t>& gc_map) {
   std::vector<uint8_t>* length_prefixed_gc_map = new std::vector<uint8_t>;
   length_prefixed_gc_map->push_back((gc_map.size() & 0xff000000) >> 24);
   length_prefixed_gc_map->push_back((gc_map.size() & 0x00ff0000) >> 16);
@@ -1004,12 +1005,8 @@
 #ifndef NDEBUG
   VerifyGcMap(*map);
 #endif
-  const std::vector<uint8_t>* gc_map = CreateLengthPrefixedGcMap(*(map.get()));
-  verifier::MethodVerifier::SetGcMap(ref, *gc_map);
-
-  if (foo_method_ != NULL) {
-    foo_method_->SetGcMap(&gc_map->at(0));
-  }
+  const std::vector<uint8_t>* dex_gc_map = CreateLengthPrefixedDexGcMap(*(map.get()));
+  verifier::MethodVerifier::SetDexGcMap(ref, *dex_gc_map);
 
 #else  // defined(ART_USE_LLVM_COMPILER) || defined(ART_USE_GREENLAND_COMPILER)
   /* Generate Inferred Register Category for LLVM-based Code Generator */
@@ -3212,31 +3209,31 @@
   }
 }
 
-void MethodVerifier::SetGcMap(Compiler::MethodReference ref, const std::vector<uint8_t>& gc_map) {
+void MethodVerifier::SetDexGcMap(Compiler::MethodReference ref, const std::vector<uint8_t>& gc_map) {
   {
-    MutexLock mu(*gc_maps_lock_);
-    GcMapTable::iterator it = gc_maps_->find(ref);
-    if (it != gc_maps_->end()) {
+    MutexLock mu(*dex_gc_maps_lock_);
+    DexGcMapTable::iterator it = dex_gc_maps_->find(ref);
+    if (it != dex_gc_maps_->end()) {
       delete it->second;
-      gc_maps_->erase(it);
+      dex_gc_maps_->erase(it);
     }
-    gc_maps_->Put(ref, &gc_map);
+    dex_gc_maps_->Put(ref, &gc_map);
   }
-  CHECK(GetGcMap(ref) != NULL);
+  CHECK(GetDexGcMap(ref) != NULL);
 }
 
-const std::vector<uint8_t>* MethodVerifier::GetGcMap(Compiler::MethodReference ref) {
-  MutexLock mu(*gc_maps_lock_);
-  GcMapTable::const_iterator it = gc_maps_->find(ref);
-  if (it == gc_maps_->end()) {
+const std::vector<uint8_t>* MethodVerifier::GetDexGcMap(Compiler::MethodReference ref) {
+  MutexLock mu(*dex_gc_maps_lock_);
+  DexGcMapTable::const_iterator it = dex_gc_maps_->find(ref);
+  if (it == dex_gc_maps_->end()) {
     return NULL;
   }
   CHECK(it->second != NULL);
   return it->second;
 }
 
-Mutex* MethodVerifier::gc_maps_lock_ = NULL;
-MethodVerifier::GcMapTable* MethodVerifier::gc_maps_ = NULL;
+Mutex* MethodVerifier::dex_gc_maps_lock_ = NULL;
+MethodVerifier::DexGcMapTable* MethodVerifier::dex_gc_maps_ = NULL;
 
 Mutex* MethodVerifier::rejected_classes_lock_ = NULL;
 MethodVerifier::RejectedClassesTable* MethodVerifier::rejected_classes_ = NULL;
@@ -3247,10 +3244,10 @@
 #endif
 
 void MethodVerifier::Init() {
-  gc_maps_lock_ = new Mutex("verifier GC maps lock");
+  dex_gc_maps_lock_ = new Mutex("verifier GC maps lock");
   {
-    MutexLock mu(*gc_maps_lock_);
-    gc_maps_ = new MethodVerifier::GcMapTable;
+    MutexLock mu(*dex_gc_maps_lock_);
+    dex_gc_maps_ = new MethodVerifier::DexGcMapTable;
   }
 
   rejected_classes_lock_ = new Mutex("verifier rejected classes lock");
@@ -3270,13 +3267,13 @@
 
 void MethodVerifier::Shutdown() {
   {
-    MutexLock mu(*gc_maps_lock_);
-    STLDeleteValues(gc_maps_);
-    delete gc_maps_;
-    gc_maps_ = NULL;
+    MutexLock mu(*dex_gc_maps_lock_);
+    STLDeleteValues(dex_gc_maps_);
+    delete dex_gc_maps_;
+    dex_gc_maps_ = NULL;
   }
-  delete gc_maps_lock_;
-  gc_maps_lock_ = NULL;
+  delete dex_gc_maps_lock_;
+  dex_gc_maps_lock_ = NULL;
 
   {
     MutexLock mu(*rejected_classes_lock_);
diff --git a/src/verifier/method_verifier.h b/src/verifier/method_verifier.h
index 92621ef..c1c2562 100644
--- a/src/verifier/method_verifier.h
+++ b/src/verifier/method_verifier.h
@@ -188,8 +188,8 @@
   // information
   void Dump(std::ostream& os) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
-  static const std::vector<uint8_t>* GetGcMap(Compiler::MethodReference ref)
-      LOCKS_EXCLUDED(gc_maps_lock_);
+  static const std::vector<uint8_t>* GetDexGcMap(Compiler::MethodReference ref)
+      LOCKS_EXCLUDED(dex_gc_maps_lock_);
 
   // Fills 'monitor_enter_dex_pcs' with the dex pcs of the monitor-enter instructions corresponding
   // to the locks held at 'dex_pc' in 'm'.
@@ -578,11 +578,11 @@
   InsnFlags* CurrentInsnFlags();
 
   // All the GC maps that the verifier has created
-  typedef SafeMap<const Compiler::MethodReference, const std::vector<uint8_t>*> GcMapTable;
-  static Mutex* gc_maps_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
-  static GcMapTable* gc_maps_ GUARDED_BY(gc_maps_lock_);
-  static void SetGcMap(Compiler::MethodReference ref, const std::vector<uint8_t>& gc_map)
-      LOCKS_EXCLUDED(gc_maps_lock_);
+  typedef SafeMap<const Compiler::MethodReference, const std::vector<uint8_t>*> DexGcMapTable;
+  static Mutex* dex_gc_maps_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;
+  static DexGcMapTable* dex_gc_maps_ GUARDED_BY(dex_gc_maps_lock_);
+  static void SetDexGcMap(Compiler::MethodReference ref, const std::vector<uint8_t>& dex_gc_map)
+      LOCKS_EXCLUDED(dex_gc_maps_lock_);
 
   typedef std::set<Compiler::ClassReference> RejectedClassesTable;
   static Mutex* rejected_classes_lock_ DEFAULT_MUTEX_ACQUIRED_AFTER;