Move mapping table and vmap table offsets to OatMethodHeader.

This change has a libcore/ companion CL
  "Remove ArtMethod's quick fields mapping table and vmap table."
  https://android-review.googlesource.com/91254

Bug: 11767815
Change-Id: I46ce2067e1ecd915da3890606498e31ffc332813
diff --git a/compiler/common_compiler_test.h b/compiler/common_compiler_test.h
index fdf09a5..8bba84a 100644
--- a/compiler/common_compiler_test.h
+++ b/compiler/common_compiler_test.h
@@ -132,34 +132,24 @@
 
 class CommonCompilerTest : public CommonRuntimeTest {
  public:
-  static void MakeExecutable(const std::vector<uint8_t>& code) {
-    CHECK_NE(code.size(), 0U);
-    MakeExecutable(&code[0], code.size());
-  }
-
   // Create an OatMethod based on pointers (for unit tests).
   OatFile::OatMethod CreateOatMethod(const void* code,
                                      const size_t frame_size_in_bytes,
                                      const uint32_t core_spill_mask,
                                      const uint32_t fp_spill_mask,
-                                     const uint8_t* mapping_table,
-                                     const uint8_t* vmap_table,
                                      const uint8_t* gc_map) {
+    CHECK(code != nullptr);
     const byte* base;
-    uint32_t code_offset, mapping_table_offset, vmap_table_offset, gc_map_offset;
-    if (mapping_table == nullptr && vmap_table == nullptr && gc_map == nullptr) {
+    uint32_t code_offset, gc_map_offset;
+    if (gc_map == nullptr) {
       base = reinterpret_cast<const byte*>(code);  // Base of data points at code.
       base -= kPointerSize;  // Move backward so that code_offset != 0.
       code_offset = kPointerSize;
-      mapping_table_offset = 0;
-      vmap_table_offset = 0;
       gc_map_offset = 0;
     } else {
       // TODO: 64bit support.
       base = nullptr;  // Base of data in oat file, ie 0.
       code_offset = PointerToLowMemUInt32(code);
-      mapping_table_offset = PointerToLowMemUInt32(mapping_table);
-      vmap_table_offset = PointerToLowMemUInt32(vmap_table);
       gc_map_offset = PointerToLowMemUInt32(gc_map);
     }
     return OatFile::OatMethod(base,
@@ -167,8 +157,6 @@
                               frame_size_in_bytes,
                               core_spill_mask,
                               fp_spill_mask,
-                              mapping_table_offset,
-                              vmap_table_offset,
                               gc_map_offset);
   }
 
@@ -185,19 +173,44 @@
     }
     if (compiled_method != nullptr) {
       const std::vector<uint8_t>* code = compiled_method->GetQuickCode();
-      if (code == nullptr) {
+      const void* code_ptr;
+      if (code != nullptr) {
+        uint32_t code_size = code->size();
+        CHECK_NE(0u, code_size);
+        const std::vector<uint8_t>& vmap_table = compiled_method->GetVmapTable();
+        uint32_t vmap_table_offset = vmap_table.empty() ? 0u
+            : sizeof(OatMethodHeader) + vmap_table.size();
+        const std::vector<uint8_t>& mapping_table = compiled_method->GetMappingTable();
+        uint32_t mapping_table_offset = mapping_table.empty() ? 0u
+            : sizeof(OatMethodHeader) + vmap_table.size() + mapping_table.size();
+        OatMethodHeader method_header(vmap_table_offset, mapping_table_offset, code_size);
+
+        header_code_and_maps_chunks_.push_back(std::vector<uint8_t>());
+        std::vector<uint8_t>* chunk = &header_code_and_maps_chunks_.back();
+        size_t size = sizeof(method_header) + code_size + vmap_table.size() + mapping_table.size();
+        size_t code_offset = compiled_method->AlignCode(size - code_size);
+        size_t padding = code_offset - (size - code_size);
+        chunk->reserve(padding + size);
+        chunk->resize(sizeof(method_header));
+        memcpy(&(*chunk)[0], &method_header, sizeof(method_header));
+        chunk->insert(chunk->begin(), vmap_table.begin(), vmap_table.end());
+        chunk->insert(chunk->begin(), mapping_table.begin(), mapping_table.end());
+        chunk->insert(chunk->begin(), padding, 0);
+        chunk->insert(chunk->end(), code->begin(), code->end());
+        CHECK_EQ(padding + size, chunk->size());
+        code_ptr = &(*chunk)[code_offset];
+      } else {
         code = compiled_method->GetPortableCode();
+        code_ptr = &(*code)[0];
       }
-      MakeExecutable(*code);
-      const void* method_code = CompiledMethod::CodePointer(&(*code)[0],
+      MakeExecutable(code_ptr, code->size());
+      const void* method_code = CompiledMethod::CodePointer(code_ptr,
                                                             compiled_method->GetInstructionSet());
       LOG(INFO) << "MakeExecutable " << PrettyMethod(method) << " code=" << method_code;
       OatFile::OatMethod oat_method = CreateOatMethod(method_code,
                                                       compiled_method->GetFrameSizeInBytes(),
                                                       compiled_method->GetCoreSpillMask(),
                                                       compiled_method->GetFpSpillMask(),
-                                                      &compiled_method->GetMappingTable()[0],
-                                                      &compiled_method->GetVmapTable()[0],
                                                       nullptr);
       oat_method.LinkMethod(method);
       method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
@@ -211,8 +224,6 @@
                                                         kStackAlignment,
                                                         0,
                                                         0,
-                                                        nullptr,
-                                                        nullptr,
                                                         nullptr);
         oat_method.LinkMethod(method);
         method->SetEntryPointFromInterpreter(interpreter::artInterpreterToInterpreterBridge);
@@ -230,8 +241,6 @@
                                                             sirt_size,
                                                         callee_save_method->GetCoreSpillMask(),
                                                         callee_save_method->GetFpSpillMask(),
-                                                        nullptr,
-                                                        nullptr,
                                                         nullptr);
         oat_method.LinkMethod(method);
         method->SetEntryPointFromInterpreter(artInterpreterToCompiledCodeBridge);
@@ -436,6 +445,9 @@
 
  private:
   UniquePtr<MemMap> image_reservation_;
+
+  // Chunks must not move their storage after being created - use the node-based std::list.
+  std::list<std::vector<uint8_t> > header_code_and_maps_chunks_;
 };
 
 }  // namespace art
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 3400b01..c35d400 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -680,14 +680,6 @@
         copy->SetNativeMethod<kVerifyNone>(GetOatAddress(jni_dlsym_lookup_offset_));
       } else {
         // Normal (non-abstract non-native) methods have various tables to relocate.
-        uint32_t mapping_table_off = orig->GetOatMappingTableOffset();
-        const byte* mapping_table = GetOatAddress(mapping_table_off);
-        copy->SetMappingTable<kVerifyNone>(mapping_table);
-
-        uint32_t vmap_table_offset = orig->GetOatVmapTableOffset();
-        const byte* vmap_table = GetOatAddress(vmap_table_offset);
-        copy->SetVmapTable<kVerifyNone>(vmap_table);
-
         uint32_t native_gc_map_offset = orig->GetOatNativeGcMapOffset();
         const byte* native_gc_map = GetOatAddress(native_gc_map_offset);
         copy->SetNativeGcMap<kVerifyNone>(reinterpret_cast<const uint8_t*>(native_gc_map));
diff --git a/compiler/oat_test.cc b/compiler/oat_test.cc
index 766ef7b..b5d3923 100644
--- a/compiler/oat_test.cc
+++ b/compiler/oat_test.cc
@@ -176,7 +176,8 @@
   // If this test is failing and you have to update these constants,
   // it is time to update OatHeader::kOatVersion
   EXPECT_EQ(80U, sizeof(OatHeader));
-  EXPECT_EQ(28U, sizeof(OatMethodOffsets));
+  EXPECT_EQ(20U, sizeof(OatMethodOffsets));
+  EXPECT_EQ(12U, sizeof(OatMethodHeader));
 }
 
 TEST_F(OatTest, OatHeaderIsValid) {
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 2114fe9..bbc9c3e 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -155,12 +155,15 @@
   }
 
   static uint32_t GetOffset(OatClass* oat_class, size_t method_offsets_index) ALWAYS_INLINE {
-    return oat_class->method_offsets_[method_offsets_index].mapping_table_offset_;
+    uint32_t offset = oat_class->method_headers_[method_offsets_index].mapping_table_offset_;
+    return offset == 0u ? 0u :
+        (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset;
   }
 
   static void SetOffset(OatClass* oat_class, size_t method_offsets_index, uint32_t offset)
       ALWAYS_INLINE {
-    oat_class->method_offsets_[method_offsets_index].mapping_table_offset_ = offset;
+    oat_class->method_headers_[method_offsets_index].mapping_table_offset_ =
+        (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset;
   }
 
   static const char* Name() ALWAYS_INLINE {
@@ -174,12 +177,15 @@
   }
 
   static uint32_t GetOffset(OatClass* oat_class, size_t method_offsets_index) ALWAYS_INLINE {
-    return oat_class->method_offsets_[method_offsets_index].vmap_table_offset_;
+    uint32_t offset = oat_class->method_headers_[method_offsets_index].vmap_table_offset_;
+    return offset == 0u ? 0u :
+        (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset;
   }
 
   static void SetOffset(OatClass* oat_class, size_t method_offsets_index, uint32_t offset)
       ALWAYS_INLINE {
-    oat_class->method_offsets_[method_offsets_index].vmap_table_offset_ = offset;
+    oat_class->method_headers_[method_offsets_index].vmap_table_offset_ =
+        (oat_class->method_offsets_[method_offsets_index].code_offset_ & ~1) - offset;
   }
 
   static const char* Name() ALWAYS_INLINE {
@@ -368,17 +374,22 @@
           }
         }
 
+        DCHECK_LT(method_offsets_index_, oat_class->method_headers_.size());
+        OatMethodHeader* method_header = &oat_class->method_headers_[method_offsets_index_];
+        method_header->code_size_ = code_size;
+
         // Deduplicate code arrays.
-        auto code_iter = dedupe_map_.find(quick_code);
+        auto code_iter = dedupe_map_.find(compiled_method);
         if (code_iter != dedupe_map_.end()) {
           quick_code_offset = code_iter->second;
+          FixupMethodHeader(method_header, quick_code_offset - thumb_offset);
         } else {
-          dedupe_map_.Put(quick_code, quick_code_offset);
-          OatMethodHeader method_header(code_size);
-          offset_ += sizeof(method_header);  // Method header is prepended before code.
-          writer_->oat_header_->UpdateChecksum(&method_header, sizeof(method_header));
-          offset_ += code_size;
+          dedupe_map_.Put(compiled_method, quick_code_offset);
+          FixupMethodHeader(method_header, quick_code_offset - thumb_offset);
+          writer_->oat_header_->UpdateChecksum(method_header, sizeof(*method_header));
+          offset_ += sizeof(*method_header);  // Method header is prepended before code.
           writer_->oat_header_->UpdateChecksum(&(*quick_code)[0], code_size);
+          offset_ += code_size;
         }
       }
       frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
@@ -420,9 +431,22 @@
   }
 
  private:
+  static void FixupMethodHeader(OatMethodHeader* method_header, uint32_t code_offset) {
+    // The code offset was 0 when the mapping/vmap table offset was set, so it's set
+    // to 0-offset and we need to adjust it by code_offset.
+    if (method_header->mapping_table_offset_ != 0u) {
+      method_header->mapping_table_offset_ += code_offset;
+      DCHECK_LT(method_header->mapping_table_offset_, code_offset);
+    }
+    if (method_header->vmap_table_offset_ != 0u) {
+      method_header->vmap_table_offset_ += code_offset;
+      DCHECK_LT(method_header->vmap_table_offset_, code_offset);
+    }
+  }
+
   // Deduplication is already done on a pointer basis by the compiler driver,
   // so we can simply compare the pointers to find out if things are duplicated.
-  SafeMap<const std::vector<uint8_t>*, uint32_t> dedupe_map_;
+  SafeMap<const CompiledMethod*, uint32_t, CodeOffsetsKeyComparator> dedupe_map_;
 };
 
 template <typename DataAccess>
@@ -477,7 +501,7 @@
     OatClass* oat_class = writer_->oat_classes_[oat_class_index_];
     CompiledMethod* compiled_method = oat_class->GetCompiledMethod(class_def_method_index);
 
-    OatMethodOffsets offsets(0u, kStackAlignment, 0u, 0u, 0u, 0u, 0u);
+    OatMethodOffsets offsets(0u, kStackAlignment, 0u, 0u, 0u);
     if (compiled_method != nullptr) {
       DCHECK_LT(method_offsets_index_, oat_class->method_offsets_.size());
       offsets = oat_class->method_offsets_[method_offsets_index_];
@@ -511,8 +535,6 @@
       offsets.frame_size_in_bytes_ = callee_save_method->GetFrameSizeInBytes() + sirt_size;
       offsets.core_spill_mask_ = callee_save_method->GetCoreSpillMask();
       offsets.fp_spill_mask_ = callee_save_method->GetFpSpillMask();
-      DCHECK_EQ(offsets.mapping_table_offset_, 0u);
-      DCHECK_EQ(offsets.vmap_table_offset_, 0u);
       DCHECK_EQ(offsets.gc_map_offset_, 0u);
     }
 
@@ -528,10 +550,8 @@
     method->SetFrameSizeInBytes(offsets.frame_size_in_bytes_);
     method->SetCoreSpillMask(offsets.core_spill_mask_);
     method->SetFpSpillMask(offsets.fp_spill_mask_);
-    method->SetOatMappingTableOffset(offsets.mapping_table_offset_);
     // Portable code offsets are set by ElfWriterMclinker::FixupCompiledCodeOffset after linking.
     method->SetQuickOatCodeOffset(offsets.code_offset_);
-    method->SetOatVmapTableOffset(offsets.vmap_table_offset_);
     method->SetOatNativeGcMapOffset(offsets.gc_map_offset_);
 
     return true;
@@ -584,7 +604,7 @@
                    offset_ + sizeof(OatMethodHeader) + compiled_method->CodeDelta())
             << PrettyMethod(it.GetMemberIndex(), *dex_file_);
         if (method_offsets.code_offset_ >= offset_) {
-          OatMethodHeader method_header(code_size);
+          const OatMethodHeader& method_header = oat_class->method_headers_[method_offsets_index_];
           if (!out->WriteFully(&method_header, sizeof(method_header))) {
             ReportWriteFailure("method header", it);
             return false;
@@ -1153,6 +1173,7 @@
 
   status_ = status;
   method_offsets_.resize(num_non_null_compiled_methods);
+  method_headers_.resize(num_non_null_compiled_methods);
 
   uint32_t oat_method_offsets_offset_from_oat_class = sizeof(type_) + sizeof(status_);
   if (type_ == kOatClassSomeCompiled) {
diff --git a/compiler/oat_writer.h b/compiler/oat_writer.h
index 1abacd8..7cdd532 100644
--- a/compiler/oat_writer.h
+++ b/compiler/oat_writer.h
@@ -225,12 +225,13 @@
     // not is kOatClassBitmap, the bitmap will be NULL.
     BitVector* method_bitmap_;
 
-    // OatMethodOffsets for each CompiledMethod present in the
-    // OatClass. Note that some may be missing if
+    // OatMethodOffsets and OatMethodHeaders for each CompiledMethod
+    // present in the OatClass. Note that some may be missing if
     // OatClass::compiled_methods_ contains NULL values (and
     // oat_method_offsets_offsets_from_oat_class_ should contain 0
     // values in this case).
     std::vector<OatMethodOffsets> method_offsets_;
+    std::vector<OatMethodHeader> method_headers_;
 
    private:
     DISALLOW_COPY_AND_ASSIGN(OatClass);
@@ -299,6 +300,22 @@
   uint32_t size_oat_class_method_bitmaps_;
   uint32_t size_oat_class_method_offsets_;
 
+  struct CodeOffsetsKeyComparator {
+    bool operator()(const CompiledMethod* lhs, const CompiledMethod* rhs) const {
+      if (lhs->GetQuickCode() != rhs->GetQuickCode()) {
+        return lhs->GetQuickCode() < rhs->GetQuickCode();
+      }
+      // If the code is the same, all other fields are likely to be the same as well.
+      if (UNLIKELY(&lhs->GetMappingTable() != &rhs->GetMappingTable())) {
+        return &lhs->GetMappingTable() < &rhs->GetMappingTable();
+      }
+      if (UNLIKELY(&lhs->GetVmapTable() != &rhs->GetVmapTable())) {
+        return &lhs->GetVmapTable() < &rhs->GetVmapTable();
+      }
+      return false;
+    }
+  };
+
   DISALLOW_COPY_AND_ASSIGN(OatWriter);
 };
 
diff --git a/oatdump/oatdump.cc b/oatdump/oatdump.cc
index 5054f96..1a67952 100644
--- a/oatdump/oatdump.cc
+++ b/oatdump/oatdump.cc
@@ -44,6 +44,7 @@
 #include "mirror/object_array-inl.h"
 #include "noop_compiler_callbacks.h"
 #include "oat.h"
+#include "oat_file-inl.h"
 #include "object_utils.h"
 #include "os.h"
 #include "runtime.h"
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 58b82f0..338133c 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -185,7 +185,8 @@
       quick_resolution_trampoline_(nullptr),
       portable_imt_conflict_trampoline_(nullptr),
       quick_imt_conflict_trampoline_(nullptr),
-      quick_generic_jni_trampoline_(nullptr) {
+      quick_generic_jni_trampoline_(nullptr),
+      quick_to_interpreter_bridge_trampoline_(nullptr) {
   CHECK_EQ(arraysize(class_roots_descriptors_), size_t(kClassRootsMax));
   memset(find_array_class_cache_, 0, kFindArrayCacheSize * sizeof(mirror::Class*));
 }
@@ -1002,6 +1003,7 @@
   portable_imt_conflict_trampoline_ = oat_file.GetOatHeader().GetPortableImtConflictTrampoline();
   quick_imt_conflict_trampoline_ = oat_file.GetOatHeader().GetQuickImtConflictTrampoline();
   quick_generic_jni_trampoline_ = oat_file.GetOatHeader().GetQuickGenericJniTrampoline();
+  quick_to_interpreter_bridge_trampoline_ = oat_file.GetOatHeader().GetQuickToInterpreterBridge();
   mirror::Object* dex_caches_object = space->GetImageHeader().GetImageRoot(ImageHeader::kDexCaches);
   mirror::ObjectArray<mirror::DexCache>* dex_caches =
       dex_caches_object->AsObjectArray<mirror::DexCache>();
diff --git a/runtime/class_linker.h b/runtime/class_linker.h
index a14d1d1..9771318 100644
--- a/runtime/class_linker.h
+++ b/runtime/class_linker.h
@@ -369,6 +369,10 @@
     return quick_imt_conflict_trampoline_;
   }
 
+  const void* GetQuickToInterpreterBridgeTrampoline() const {
+    return quick_to_interpreter_bridge_trampoline_;
+  }
+
   InternTable* GetInternTable() const {
     return intern_table_;
   }
@@ -658,6 +662,7 @@
   const void* portable_imt_conflict_trampoline_;
   const void* quick_imt_conflict_trampoline_;
   const void* quick_generic_jni_trampoline_;
+  const void* quick_to_interpreter_bridge_trampoline_;
 
   friend class ImageWriter;  // for GetClassRoots
   FRIEND_TEST(ClassLinkerTest, ClassRootDescriptors);
diff --git a/runtime/class_linker_test.cc b/runtime/class_linker_test.cc
index 5b72a44..1218357 100644
--- a/runtime/class_linker_test.cc
+++ b/runtime/class_linker_test.cc
@@ -485,8 +485,6 @@
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, entry_point_from_portable_compiled_code_), "entryPointFromPortableCompiledCode"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, entry_point_from_quick_compiled_code_),    "entryPointFromQuickCompiledCode"));
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, gc_map_),                                  "gcMap"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, quick_mapping_table_),                     "quickMappingTable"));
-    offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, quick_vmap_table_),                        "quickVmapTable"));
 
     // alphabetical 32-bit
     offsets.push_back(CheckOffset(OFFSETOF_MEMBER(mirror::ArtMethod, access_flags_),                   "accessFlags"));
diff --git a/runtime/entrypoints/entrypoint_utils.h b/runtime/entrypoints/entrypoint_utils.h
index 8b48b36..05912bf 100644
--- a/runtime/entrypoints/entrypoint_utils.h
+++ b/runtime/entrypoints/entrypoint_utils.h
@@ -761,6 +761,10 @@
   return class_linker->GetQuickGenericJniTrampoline();
 }
 
+static inline const void* GetQuickToInterpreterBridgeTrampoline(ClassLinker* class_linker) {
+  return class_linker->GetQuickToInterpreterBridgeTrampoline();
+}
+
 extern "C" void art_portable_proxy_invoke_handler();
 static inline const void* GetPortableProxyInvokeHandler() {
   return reinterpret_cast<void*>(art_portable_proxy_invoke_handler);
diff --git a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
index 633f580..60c5377 100644
--- a/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
+++ b/runtime/entrypoints/quick/quick_instrumentation_entrypoints.cc
@@ -32,6 +32,7 @@
   FinishCalleeSaveFrameSetup(self, sp, Runtime::kRefsAndArgs);
   instrumentation::Instrumentation* instrumentation = Runtime::Current()->GetInstrumentation();
   const void* result = instrumentation->GetQuickCodeFor(method);
+  DCHECK(result != GetQuickToInterpreterBridgeTrampoline(Runtime::Current()->GetClassLinker()));
   bool interpreter_entry = (result == GetQuickToInterpreterBridge());
   instrumentation->PushInstrumentationStackFrame(self, method->IsStatic() ? NULL : this_object,
                                                  method, lr, interpreter_entry);
diff --git a/runtime/exception_test.cc b/runtime/exception_test.cc
index 208eb74..97a8367 100644
--- a/runtime/exception_test.cc
+++ b/runtime/exception_test.cc
@@ -49,10 +49,6 @@
     dex_ = my_klass_->GetDexCache()->GetDexFile();
 
     uint32_t code_size = 12;
-    fake_code_.push_back((code_size >> 24) & 0xFF);
-    fake_code_.push_back((code_size >> 16) & 0xFF);
-    fake_code_.push_back((code_size >>  8) & 0xFF);
-    fake_code_.push_back((code_size >>  0) & 0xFF);
     for (size_t i = 0 ; i < code_size; i++) {
       fake_code_.push_back(0x70 | i);
     }
@@ -74,20 +70,35 @@
     fake_gc_map_.push_back(0);  // 0 entries.
     fake_gc_map_.push_back(0);
 
+    const std::vector<uint8_t>& fake_vmap_table_data = fake_vmap_table_data_.GetData();
+    const std::vector<uint8_t>& fake_mapping_data = fake_mapping_data_.GetData();
+    uint32_t vmap_table_offset = sizeof(OatMethodHeader) + fake_vmap_table_data.size();
+    uint32_t mapping_table_offset = vmap_table_offset + fake_mapping_data.size();
+    OatMethodHeader method_header(vmap_table_offset, mapping_table_offset, code_size);
+    fake_header_code_and_maps_.resize(sizeof(method_header));
+    memcpy(&fake_header_code_and_maps_[0], &method_header, sizeof(method_header));
+    fake_header_code_and_maps_.insert(fake_header_code_and_maps_.begin(),
+                                      fake_vmap_table_data.begin(), fake_vmap_table_data.end());
+    fake_header_code_and_maps_.insert(fake_header_code_and_maps_.begin(),
+                                      fake_mapping_data.begin(), fake_mapping_data.end());
+    fake_header_code_and_maps_.insert(fake_header_code_and_maps_.end(),
+                                      fake_code_.begin(), fake_code_.end());
+
+    // NOTE: Don't align the code (it will not be executed) but check that the Thumb2
+    // adjustment will be a NOP, see ArtMethod::EntryPointToCodePointer().
+    CHECK_EQ(mapping_table_offset & 1u, 0u);
+    const uint8_t* code_ptr = &fake_header_code_and_maps_[mapping_table_offset];
+
     method_f_ = my_klass_->FindVirtualMethod("f", "()I");
     ASSERT_TRUE(method_f_ != NULL);
     method_f_->SetFrameSizeInBytes(4 * kPointerSize);
-    method_f_->SetEntryPointFromQuickCompiledCode(&fake_code_[sizeof(code_size)]);
-    method_f_->SetMappingTable(&fake_mapping_data_.GetData()[0]);
-    method_f_->SetVmapTable(&fake_vmap_table_data_.GetData()[0]);
+    method_f_->SetEntryPointFromQuickCompiledCode(code_ptr);
     method_f_->SetNativeGcMap(&fake_gc_map_[0]);
 
     method_g_ = my_klass_->FindVirtualMethod("g", "(I)V");
     ASSERT_TRUE(method_g_ != NULL);
     method_g_->SetFrameSizeInBytes(4 * kPointerSize);
-    method_g_->SetEntryPointFromQuickCompiledCode(&fake_code_[sizeof(code_size)]);
-    method_g_->SetMappingTable(&fake_mapping_data_.GetData()[0]);
-    method_g_->SetVmapTable(&fake_vmap_table_data_.GetData()[0]);
+    method_g_->SetEntryPointFromQuickCompiledCode(code_ptr);
     method_g_->SetNativeGcMap(&fake_gc_map_[0]);
   }
 
@@ -97,6 +108,7 @@
   Leb128EncodingVector fake_mapping_data_;
   Leb128EncodingVector fake_vmap_table_data_;
   std::vector<uint8_t> fake_gc_map_;
+  std::vector<uint8_t> fake_header_code_and_maps_;
 
   mirror::ArtMethod* method_f_;
   mirror::ArtMethod* method_g_;
diff --git a/runtime/instrumentation.cc b/runtime/instrumentation.cc
index 2cd7f49..77d29dd 100644
--- a/runtime/instrumentation.cc
+++ b/runtime/instrumentation.cc
@@ -94,6 +94,7 @@
   }
   if (!method->IsResolutionMethod()) {
     if (quick_code == GetQuickToInterpreterBridge() ||
+        quick_code == GetQuickToInterpreterBridgeTrampoline(Runtime::Current()->GetClassLinker()) ||
         (quick_code == GetQuickResolutionTrampoline(Runtime::Current()->GetClassLinker()) &&
          Runtime::Current()->GetInstrumentation()->IsForcedInterpretOnly()
          && !method->IsNative() && !method->IsProxyMethod())) {
@@ -147,6 +148,7 @@
         // Do not overwrite interpreter to prevent from posting method entry/exit events twice.
         new_portable_code = class_linker->GetPortableOatCodeFor(method, &have_portable_code);
         new_quick_code = class_linker->GetQuickOatCodeFor(method);
+        DCHECK(new_quick_code != GetQuickToInterpreterBridgeTrampoline(class_linker));
         if (entry_exit_stubs_installed_ && new_quick_code != GetQuickToInterpreterBridge()) {
           DCHECK(new_portable_code != GetPortableToInterpreterBridge());
           new_portable_code = GetPortableToInterpreterBridge();
@@ -562,7 +564,8 @@
       new_quick_code = GetQuickToInterpreterBridge();
       new_have_portable_code = false;
     } else if (quick_code == GetQuickResolutionTrampoline(Runtime::Current()->GetClassLinker()) ||
-               quick_code == GetQuickToInterpreterBridge()) {
+        quick_code == GetQuickToInterpreterBridgeTrampoline(Runtime::Current()->GetClassLinker()) ||
+        quick_code == GetQuickToInterpreterBridge()) {
       DCHECK((portable_code == GetPortableResolutionTrampoline(Runtime::Current()->GetClassLinker())) ||
              (portable_code == GetPortableToInterpreterBridge()));
       new_portable_code = portable_code;
@@ -709,9 +712,10 @@
   Runtime* runtime = Runtime::Current();
   if (LIKELY(!instrumentation_stubs_installed_)) {
     const void* code = method->GetEntryPointFromQuickCompiledCode();
-    DCHECK(code != NULL);
-    if (LIKELY(code != GetQuickResolutionTrampoline(runtime->GetClassLinker()) &&
-               code != GetQuickToInterpreterBridge())) {
+    DCHECK(code != nullptr);
+    if (LIKELY(code != GetQuickResolutionTrampoline(runtime->GetClassLinker())) &&
+        LIKELY(code != GetQuickToInterpreterBridgeTrampoline(runtime->GetClassLinker())) &&
+        LIKELY(code != GetQuickToInterpreterBridge())) {
       return code;
     }
   }
diff --git a/runtime/mirror/art_method-inl.h b/runtime/mirror/art_method-inl.h
index 5d62b88..6e1f062 100644
--- a/runtime/mirror/art_method-inl.h
+++ b/runtime/mirror/art_method-inl.h
@@ -78,13 +78,11 @@
 
 inline uint32_t ArtMethod::GetCodeSize() {
   DCHECK(!IsRuntimeMethod() && !IsProxyMethod()) << PrettyMethod(this);
-  uintptr_t code = reinterpret_cast<uintptr_t>(GetEntryPointFromQuickCompiledCode());
-  if (code == 0) {
-    return 0;
+  const void* code = EntryPointToCodePointer(GetEntryPointFromQuickCompiledCode());
+  if (code == nullptr) {
+    return 0u;
   }
-  // TODO: make this Thumb2 specific
-  code &= ~0x1;
-  return reinterpret_cast<OatMethodHeader*>(code)[-1].code_size_;
+  return reinterpret_cast<const OatMethodHeader*>(code)[-1].code_size_;
 }
 
 inline bool ArtMethod::CheckIncompatibleClassChange(InvokeType type) {
@@ -124,7 +122,8 @@
     return;
   }
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  if (code == GetQuickResolutionTrampoline(class_linker)) {
+  if (code == GetQuickResolutionTrampoline(class_linker) ||
+      code == GetQuickToInterpreterBridgeTrampoline(class_linker)) {
     return;
   }
   DCHECK(IsWithinQuickCode(pc))
@@ -154,26 +153,6 @@
   SetEntryPointFromPortableCompiledCode(reinterpret_cast<void*>(code_offset));
 }
 
-inline uint32_t ArtMethod::GetOatMappingTableOffset() {
-  DCHECK(!Runtime::Current()->IsStarted());
-  return PointerToLowMemUInt32(GetMappingTable());
-}
-
-inline void ArtMethod::SetOatMappingTableOffset(uint32_t mapping_table_offset) {
-  DCHECK(!Runtime::Current()->IsStarted());
-  SetMappingTable(reinterpret_cast<const uint8_t*>(mapping_table_offset));
-}
-
-inline uint32_t ArtMethod::GetOatVmapTableOffset() {
-  DCHECK(!Runtime::Current()->IsStarted());
-  return PointerToLowMemUInt32(GetVmapTable());
-}
-
-inline void ArtMethod::SetOatVmapTableOffset(uint32_t vmap_table_offset) {
-  DCHECK(!Runtime::Current()->IsStarted());
-  SetVmapTable(reinterpret_cast<uint8_t*>(vmap_table_offset));
-}
-
 inline void ArtMethod::SetOatNativeGcMapOffset(uint32_t gc_map_offset) {
   DCHECK(!Runtime::Current()->IsStarted());
   SetNativeGcMap(reinterpret_cast<uint8_t*>(gc_map_offset));
diff --git a/runtime/mirror/art_method.cc b/runtime/mirror/art_method.cc
index ee5a0a4..8da57bd 100644
--- a/runtime/mirror/art_method.cc
+++ b/runtime/mirror/art_method.cc
@@ -374,5 +374,43 @@
   RegisterNative(self, GetJniDlsymLookupStub(), false);
 }
 
+const void* ArtMethod::GetOatCodePointer() {
+  if (IsPortableCompiled() || IsNative() || IsAbstract() || IsRuntimeMethod() || IsProxyMethod()) {
+    return nullptr;
+  }
+  Runtime* runtime = Runtime::Current();
+  const void* entry_point = runtime->GetInstrumentation()->GetQuickCodeFor(this);
+  // On failure, instead of nullptr we get the quick-to-interpreter-bridge (but not the trampoline).
+  DCHECK(entry_point != GetQuickToInterpreterBridgeTrampoline(runtime->GetClassLinker()));
+  if (entry_point == GetQuickToInterpreterBridge()) {
+    return nullptr;
+  }
+  return EntryPointToCodePointer(entry_point);
+}
+
+const uint8_t* ArtMethod::GetMappingTable() {
+  const void* code = GetOatCodePointer();
+  if (code == nullptr) {
+    return nullptr;
+  }
+  uint32_t offset = reinterpret_cast<const OatMethodHeader*>(code)[-1].mapping_table_offset_;
+  if (UNLIKELY(offset == 0u)) {
+    return nullptr;
+  }
+  return reinterpret_cast<const uint8_t*>(code) - offset;
+}
+
+const uint8_t* ArtMethod::GetVmapTable() {
+  const void* code = GetOatCodePointer();
+  if (code == nullptr) {
+    return nullptr;
+  }
+  uint32_t offset = reinterpret_cast<const OatMethodHeader*>(code)[-1].vmap_table_offset_;
+  if (UNLIKELY(offset == 0u)) {
+    return nullptr;
+  }
+  return reinterpret_cast<const uint8_t*>(code) - offset;
+}
+
 }  // namespace mirror
 }  // namespace art
diff --git a/runtime/mirror/art_method.h b/runtime/mirror/art_method.h
index ee23c40..8d2c39c 100644
--- a/runtime/mirror/art_method.h
+++ b/runtime/mirror/art_method.h
@@ -21,6 +21,7 @@
 #include "dex_file.h"
 #include "invoke_type.h"
 #include "modifiers.h"
+#include "oat.h"
 #include "object.h"
 #include "object_callbacks.h"
 
@@ -261,7 +262,6 @@
         EntryPointFromQuickCompiledCodeOffset(), entry_point_from_quick_compiled_code, false);
   }
 
-
   uint32_t GetCodeSize() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   bool IsWithinQuickCode(uintptr_t pc) SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
@@ -286,37 +286,20 @@
   void SetQuickOatCodeOffset(uint32_t code_offset);
   void SetPortableOatCodeOffset(uint32_t code_offset);
 
+  static const void* EntryPointToCodePointer(const void* entry_point) ALWAYS_INLINE {
+    uintptr_t code = reinterpret_cast<uintptr_t>(entry_point);
+    code &= ~0x1;  // TODO: Make this Thumb2 specific.
+    return reinterpret_cast<const void*>(code);
+  }
+
+  // Actual pointer to compiled oat code or nullptr.
+  const void* GetOatCodePointer() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
+
   // Callers should wrap the uint8_t* in a MappingTable instance for convenient access.
-  const uint8_t* GetMappingTable() {
-    return GetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_mapping_table_),
-        false);
-  }
-
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  void SetMappingTable(const uint8_t* mapping_table) {
-    SetFieldPtr<false, true, kVerifyFlags>(
-        OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_mapping_table_), mapping_table, false);
-  }
-
-  uint32_t GetOatMappingTableOffset();
-
-  void SetOatMappingTableOffset(uint32_t mapping_table_offset);
+  const uint8_t* GetMappingTable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   // Callers should wrap the uint8_t* in a VmapTable instance for convenient access.
-  const uint8_t* GetVmapTable() {
-    return GetFieldPtr<const uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_vmap_table_),
-        false);
-  }
-
-  template<VerifyObjectFlags kVerifyFlags = kDefaultVerifyFlags>
-  void SetVmapTable(const uint8_t* vmap_table) {
-    SetFieldPtr<false, true, kVerifyFlags>(
-        OFFSET_OF_OBJECT_MEMBER(ArtMethod, quick_vmap_table_), vmap_table, false);
-  }
-
-  uint32_t GetOatVmapTableOffset();
-
-  void SetOatVmapTableOffset(uint32_t vmap_table_offset);
+  const uint8_t* GetVmapTable() SHARED_LOCKS_REQUIRED(Locks::mutator_lock_);
 
   const uint8_t* GetNativeGcMap() {
     return GetFieldPtr<uint8_t*>(OFFSET_OF_OBJECT_MEMBER(ArtMethod, gc_map_), false);
@@ -468,20 +451,6 @@
   // offsets for the quick compiler and dex PCs for the portable.
   uint64_t gc_map_;
 
-  // --- Quick compiler meta-data. ---
-  // TODO: merge and place in native heap, such as done with the code size.
-
-  // Pointer to a data structure created by the quick compiler to map between dex PCs and native
-  // PCs, and vice-versa.
-  uint64_t quick_mapping_table_;
-
-  // When a register is promoted into a register, the spill mask holds which registers hold dex
-  // registers. The first promoted register's corresponding dex register is vmap_table_[1], the Nth
-  // is vmap_table_[N]. vmap_table_[0] holds the length of the table.
-  uint64_t quick_vmap_table_;
-
-  // --- End of quick compiler meta-data. ---
-
   // Access flags; low 16 bits are defined by spec.
   uint32_t access_flags_;
 
diff --git a/runtime/oat.cc b/runtime/oat.cc
index d01dc72..c1a48e9 100644
--- a/runtime/oat.cc
+++ b/runtime/oat.cc
@@ -22,7 +22,7 @@
 namespace art {
 
 const uint8_t OatHeader::kOatMagic[] = { 'o', 'a', 't', '\n' };
-const uint8_t OatHeader::kOatVersion[] = { '0', '2', '1', '\0' };
+const uint8_t OatHeader::kOatVersion[] = { '0', '2', '2', '\0' };
 
 OatHeader::OatHeader() {
   memset(this, 0, sizeof(*this));
@@ -348,8 +348,6 @@
     frame_size_in_bytes_(0),
     core_spill_mask_(0),
     fp_spill_mask_(0),
-    mapping_table_offset_(0),
-    vmap_table_offset_(0),
     gc_map_offset_(0)
 {}
 
@@ -357,27 +355,28 @@
                                    uint32_t frame_size_in_bytes,
                                    uint32_t core_spill_mask,
                                    uint32_t fp_spill_mask,
-                                   uint32_t mapping_table_offset,
-                                   uint32_t vmap_table_offset,
                                    uint32_t gc_map_offset
                                    )
   : code_offset_(code_offset),
     frame_size_in_bytes_(frame_size_in_bytes),
     core_spill_mask_(core_spill_mask),
     fp_spill_mask_(fp_spill_mask),
-    mapping_table_offset_(mapping_table_offset),
-    vmap_table_offset_(vmap_table_offset),
     gc_map_offset_(gc_map_offset)
 {}
 
 OatMethodOffsets::~OatMethodOffsets() {}
 
 OatMethodHeader::OatMethodHeader()
-  : code_size_(0)
+  : mapping_table_offset_(0),
+    vmap_table_offset_(0),
+    code_size_(0)
 {}
 
-OatMethodHeader::OatMethodHeader(uint32_t code_size)
-  : code_size_(code_size)
+OatMethodHeader::OatMethodHeader(uint32_t vmap_table_offset, uint32_t mapping_table_offset,
+                                 uint32_t code_size)
+  : mapping_table_offset_(mapping_table_offset),
+    vmap_table_offset_(vmap_table_offset),
+    code_size_(code_size)
 {}
 
 OatMethodHeader::~OatMethodHeader() {}
diff --git a/runtime/oat.h b/runtime/oat.h
index 035aba1..e9dfae9 100644
--- a/runtime/oat.h
+++ b/runtime/oat.h
@@ -119,9 +119,9 @@
   DISALLOW_COPY_AND_ASSIGN(OatHeader);
 };
 
-// OatMethodOffsets are currently 7x32-bits=224-bits long, so if we can
+// OatMethodOffsets are currently 5x32-bits=160-bits long, so if we can
 // save even one OatMethodOffsets struct, the more complicated encoding
-// using a bitmap pays for itself since few classes will have 224
+// using a bitmap pays for itself since few classes will have 160
 // methods.
 enum OatClassType {
   kOatClassAllCompiled = 0,   // OatClass is followed by an OatMethodOffsets for each method.
@@ -140,8 +140,6 @@
                    uint32_t frame_size_in_bytes,
                    uint32_t core_spill_mask,
                    uint32_t fp_spill_mask,
-                   uint32_t mapping_table_offset,
-                   uint32_t vmap_table_offset,
                    uint32_t gc_map_offset);
 
   ~OatMethodOffsets();
@@ -150,8 +148,6 @@
   uint32_t frame_size_in_bytes_;
   uint32_t core_spill_mask_;
   uint32_t fp_spill_mask_;
-  uint32_t mapping_table_offset_;
-  uint32_t vmap_table_offset_;
   uint32_t gc_map_offset_;
 };
 
@@ -160,10 +156,15 @@
  public:
   OatMethodHeader();
 
-  explicit OatMethodHeader(uint32_t code_size);
+  explicit OatMethodHeader(uint32_t mapping_table_offset, uint32_t vmap_table_offset,
+                           uint32_t code_size);
 
   ~OatMethodHeader();
 
+  // The offset in bytes from the start of the mapping table to the end of the header.
+  uint32_t mapping_table_offset_;
+  // The offset in bytes from the start of the vmap table to the end of the header.
+  uint32_t vmap_table_offset_;
   // The code size in bytes.
   uint32_t code_size_;
 };
diff --git a/runtime/oat_file-inl.h b/runtime/oat_file-inl.h
new file mode 100644
index 0000000..00ae797
--- /dev/null
+++ b/runtime/oat_file-inl.h
@@ -0,0 +1,60 @@
+/*
+ * Copyright (C) 2014 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_RUNTIME_OAT_FILE_INL_H_
+#define ART_RUNTIME_OAT_FILE_INL_H_
+
+#include "oat_file.h"
+
+namespace art {
+
+inline uint32_t OatFile::OatMethod::GetMappingTableOffset() const {
+  const uint8_t* mapping_table = GetMappingTable();
+  return static_cast<uint32_t>(mapping_table != nullptr ? mapping_table - begin_ : 0u);
+}
+
+inline uint32_t OatFile::OatMethod::GetVmapTableOffset() const {
+  const uint8_t* vmap_table = GetVmapTable();
+  return static_cast<uint32_t>(vmap_table != nullptr ? vmap_table - begin_ : 0u);
+}
+
+inline const uint8_t* OatFile::OatMethod::GetMappingTable() const {
+  const void* code = mirror::ArtMethod::EntryPointToCodePointer(GetQuickCode());
+  if (code == nullptr) {
+    return nullptr;
+  }
+  uint32_t offset = reinterpret_cast<const OatMethodHeader*>(code)[-1].mapping_table_offset_;
+  if (UNLIKELY(offset == 0u)) {
+    return nullptr;
+  }
+  return reinterpret_cast<const uint8_t*>(code) - offset;
+}
+
+inline const uint8_t* OatFile::OatMethod::GetVmapTable() const {
+  const void* code = mirror::ArtMethod::EntryPointToCodePointer(GetQuickCode());
+  if (code == nullptr) {
+    return nullptr;
+  }
+  uint32_t offset = reinterpret_cast<const OatMethodHeader*>(code)[-1].vmap_table_offset_;
+  if (UNLIKELY(offset == 0u)) {
+    return nullptr;
+  }
+  return reinterpret_cast<const uint8_t*>(code) - offset;
+}
+
+}  // namespace art
+
+#endif  // ART_RUNTIME_OAT_FILE_INL_H_
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index 0aff8c3..56e1f05 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -464,7 +464,7 @@
   // NOTE: We don't keep the number of methods and cannot do a bounds check for method_index.
   if (methods_pointer_ == NULL) {
     CHECK_EQ(kOatClassNoneCompiled, type_);
-    return OatMethod(NULL, 0, 0, 0, 0, 0, 0, 0);
+    return OatMethod(NULL, 0, 0, 0, 0, 0);
   }
   size_t methods_pointer_index;
   if (bitmap_ == NULL) {
@@ -473,7 +473,7 @@
   } else {
     CHECK_EQ(kOatClassSomeCompiled, type_);
     if (!BitVector::IsBitSet(bitmap_, method_index)) {
-      return OatMethod(NULL, 0, 0, 0, 0, 0, 0, 0);
+      return OatMethod(NULL, 0, 0, 0, 0, 0);
     }
     size_t num_set_bits = BitVector::NumSetBits(bitmap_, method_index);
     methods_pointer_index = num_set_bits;
@@ -485,8 +485,6 @@
       oat_method_offsets.frame_size_in_bytes_,
       oat_method_offsets.core_spill_mask_,
       oat_method_offsets.fp_spill_mask_,
-      oat_method_offsets.mapping_table_offset_,
-      oat_method_offsets.vmap_table_offset_,
       oat_method_offsets.gc_map_offset_);
 }
 
@@ -495,32 +493,13 @@
                               const size_t frame_size_in_bytes,
                               const uint32_t core_spill_mask,
                               const uint32_t fp_spill_mask,
-                              const uint32_t mapping_table_offset,
-                              const uint32_t vmap_table_offset,
                               const uint32_t gc_map_offset)
   : begin_(base),
     code_offset_(code_offset),
     frame_size_in_bytes_(frame_size_in_bytes),
     core_spill_mask_(core_spill_mask),
     fp_spill_mask_(fp_spill_mask),
-    mapping_table_offset_(mapping_table_offset),
-    vmap_table_offset_(vmap_table_offset),
     native_gc_map_offset_(gc_map_offset) {
-  if (kIsDebugBuild) {
-    if (mapping_table_offset_ != 0) {  // implies non-native, non-stub code
-      if (vmap_table_offset_ == 0) {
-        CHECK_EQ(0U, static_cast<uint32_t>(__builtin_popcount(core_spill_mask_) +
-                                           __builtin_popcount(fp_spill_mask_)));
-      } else {
-        VmapTable vmap_table(reinterpret_cast<const uint8_t*>(begin_ + vmap_table_offset_));
-
-        CHECK_EQ(vmap_table.Size(), static_cast<uint32_t>(__builtin_popcount(core_spill_mask_) +
-                                                          __builtin_popcount(fp_spill_mask_)));
-      }
-    } else {
-      CHECK_EQ(vmap_table_offset_, 0U);
-    }
-  }
 }
 
 OatFile::OatMethod::~OatMethod() {}
@@ -543,8 +522,6 @@
   method->SetFrameSizeInBytes(frame_size_in_bytes_);
   method->SetCoreSpillMask(core_spill_mask_);
   method->SetFpSpillMask(fp_spill_mask_);
-  method->SetMappingTable(GetMappingTable());
-  method->SetVmapTable(GetVmapTable());
   method->SetNativeGcMap(GetNativeGcMap());  // Used by native methods in work around JNI mode.
 }
 
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 10f64cc..5f6cb1e 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -87,12 +87,6 @@
     uint32_t GetFpSpillMask() const {
       return fp_spill_mask_;
     }
-    uint32_t GetMappingTableOffset() const {
-      return mapping_table_offset_;
-    }
-    uint32_t GetVmapTableOffset() const {
-      return vmap_table_offset_;
-    }
     uint32_t GetNativeGcMapOffset() const {
       return native_gc_map_offset_;
     }
@@ -122,16 +116,15 @@
     }
     uint32_t GetQuickCodeSize() const;
 
-    const uint8_t* GetMappingTable() const {
-      return GetOatPointer<const uint8_t*>(mapping_table_offset_);
-    }
-    const uint8_t* GetVmapTable() const {
-      return GetOatPointer<const uint8_t*>(vmap_table_offset_);
-    }
     const uint8_t* GetNativeGcMap() const {
       return GetOatPointer<const uint8_t*>(native_gc_map_offset_);
     }
 
+    uint32_t GetMappingTableOffset() const;
+    uint32_t GetVmapTableOffset() const;
+    const uint8_t* GetMappingTable() const;
+    const uint8_t* GetVmapTable() const;
+
     ~OatMethod();
 
     // Create an OatMethod with offsets relative to the given base address
@@ -140,8 +133,6 @@
               const size_t frame_size_in_bytes,
               const uint32_t core_spill_mask,
               const uint32_t fp_spill_mask,
-              const uint32_t mapping_table_offset,
-              const uint32_t vmap_table_offset,
               const uint32_t gc_map_offset);
 
    private:
@@ -159,8 +150,6 @@
     size_t frame_size_in_bytes_;
     uint32_t core_spill_mask_;
     uint32_t fp_spill_mask_;
-    uint32_t mapping_table_offset_;
-    uint32_t vmap_table_offset_;
     uint32_t native_gc_map_offset_;
 
     friend class OatClass;