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/dex_gc_map.h b/src/verifier/dex_gc_map.h
new file mode 100644
index 0000000..d588cfd
--- /dev/null
+++ b/src/verifier/dex_gc_map.h
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef ART_SRC_VERIFIER_DEX_GC_MAP_H_
+#define ART_SRC_VERIFIER_DEX_GC_MAP_H_
+
+#include "logging.h"
+#include "macros.h"
+#include <stdint.h>
+
+namespace art {
+namespace verifier {
+
+/*
+ * Format enumeration for RegisterMap data area.
+ */
+enum RegisterMapFormat {
+  kRegMapFormatUnknown = 0,
+  kRegMapFormatNone = 1,      // Indicates no map data follows.
+  kRegMapFormatCompact8 = 2,  // Compact layout, 8-bit addresses.
+  kRegMapFormatCompact16 = 3, // Compact layout, 16-bit addresses.
+};
+
+// Lightweight wrapper for Dex PC to reference bit maps.
+class DexPcToReferenceMap {
+ public:
+  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;
+    DCHECK_EQ(EntryWidth() * NumEntries(), data_size);
+  }
+
+  // The number of entries in the table
+  size_t NumEntries() const {
+    return GetData()[2] | (GetData()[3] << 8);
+  }
+
+  // Get the Dex PC at the given index
+  uint16_t GetDexPc(size_t index) const {
+    size_t entry_offset = index * EntryWidth();
+    if (DexPcWidth() == 1) {
+      return Table()[entry_offset];
+    } else {
+      return Table()[entry_offset] | (Table()[entry_offset + 1] << 8);
+    }
+  }
+
+  // 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 + DexPcWidth()];
+  }
+
+  // Find the bitmap associated with the given dex pc
+  const uint8_t* FindBitMap(uint16_t dex_pc, bool error_if_not_present = true) const;
+
+  // The number of bytes used to encode registers
+  size_t RegWidth() const {
+    return GetData()[1] | ((GetData()[0] & ~kRegMapFormatMask) << kRegMapFormatShift);
+  }
+
+ private:
+  // Table of num_entries * (dex pc, bitmap)
+  const uint8_t* Table() const {
+    return GetData() + 4;
+  }
+
+  // The format of the table of the PCs for the table
+  RegisterMapFormat Format() const {
+    return static_cast<RegisterMapFormat>(GetData()[0] & kRegMapFormatMask);
+  }
+
+  // Number of bytes used to encode a dex pc
+  size_t DexPcWidth() const {
+    RegisterMapFormat format = Format();
+    switch (format) {
+      case kRegMapFormatCompact8:
+        return 1;
+      case kRegMapFormatCompact16:
+        return 2;
+      default:
+        LOG(FATAL) << "Invalid format " << static_cast<int>(format);
+        return -1;
+    }
+  }
+
+  // The width of an entry in the table
+  size_t EntryWidth() const {
+    return DexPcWidth() + RegWidth();
+  }
+
+  const uint8_t* GetData() const {
+    return data_;
+  }
+
+  friend class MethodVerifier;
+
+  static const int kRegMapFormatShift = 5;
+  static const uint8_t kRegMapFormatMask = 0x7;
+
+  const uint8_t* const data_;  // The header and table data
+};
+
+}  // namespace verifier
+}  // namespace art
+
+#endif  // ART_SRC_VERIFIER_DEX_GC_MAP_H_