Merge "Revert "Revert "Revert "Revert "Make dex2dex return a CompiledMethod after quickening."""""
diff --git a/compiler/compiled_method.cc b/compiler/compiled_method.cc
index d1acada..74ef35e 100644
--- a/compiler/compiled_method.cc
+++ b/compiler/compiled_method.cc
@@ -23,20 +23,12 @@
                            const ArrayRef<const uint8_t>& quick_code, bool owns_code_array)
     : compiler_driver_(compiler_driver), instruction_set_(instruction_set),
       owns_code_array_(owns_code_array), quick_code_(nullptr) {
-  SetCode(&quick_code);
-}
-
-void CompiledCode::SetCode(const ArrayRef<const uint8_t>* quick_code) {
-  if (quick_code != nullptr) {
-    CHECK(!quick_code->empty());
-    if (owns_code_array_) {
-      // If we are supposed to own the code, don't deduplicate it.
-      CHECK(quick_code_ == nullptr);
-      quick_code_ = new SwapVector<uint8_t>(quick_code->begin(), quick_code->end(),
-                                            compiler_driver_->GetSwapSpaceAllocator());
-    } else {
-      quick_code_ = compiler_driver_->DeduplicateCode(*quick_code);
-    }
+  if (owns_code_array_) {
+    // If we are supposed to own the code, don't deduplicate it.
+    quick_code_ = new SwapVector<uint8_t>(quick_code.begin(), quick_code.end(),
+                                          compiler_driver_->GetSwapSpaceAllocator());
+  } else {
+    quick_code_ = compiler_driver_->DeduplicateCode(quick_code);
   }
 }
 
diff --git a/compiler/compiled_method.h b/compiler/compiled_method.h
index 45a62bc..a4d2387 100644
--- a/compiler/compiled_method.h
+++ b/compiler/compiled_method.h
@@ -47,8 +47,6 @@
     return quick_code_;
   }
 
-  void SetCode(const ArrayRef<const uint8_t>* quick_code);
-
   bool operator==(const CompiledCode& rhs) const;
 
   // To align an offset from a page-aligned value to make it suitable
diff --git a/compiler/dex/dex_to_dex_compiler.cc b/compiler/dex/dex_to_dex_compiler.cc
index bd59046..4b56b69 100644
--- a/compiler/dex/dex_to_dex_compiler.cc
+++ b/compiler/dex/dex_to_dex_compiler.cc
@@ -18,6 +18,7 @@
 #include "art_method-inl.h"
 #include "base/logging.h"
 #include "base/mutex.h"
+#include "compiled_method.h"
 #include "dex_file-inl.h"
 #include "dex_instruction-inl.h"
 #include "driver/compiler_driver.h"
@@ -34,6 +35,13 @@
 // Control check-cast elision.
 const bool kEnableCheckCastEllision = true;
 
+struct QuickenedInfo {
+  QuickenedInfo(uint32_t pc, uint16_t index) : dex_pc(pc), dex_member_index(index) {}
+
+  uint32_t dex_pc;
+  uint16_t dex_member_index;
+};
+
 class DexCompiler {
  public:
   DexCompiler(art::CompilerDriver& compiler,
@@ -47,6 +55,10 @@
 
   void Compile();
 
+  const std::vector<QuickenedInfo>& GetQuickenedInfo() const {
+    return quickened_info_;
+  }
+
  private:
   const DexFile& GetDexFile() const {
     return *unit_.GetDexFile();
@@ -87,6 +99,11 @@
   const DexCompilationUnit& unit_;
   const DexToDexCompilationLevel dex_to_dex_compilation_level_;
 
+  // Filled by the compiler when quickening, in order to encode that information
+  // in the .oat file. The runtime will use that information to get to the original
+  // opcodes.
+  std::vector<QuickenedInfo> quickened_info_;
+
   DISALLOW_COPY_AND_ASSIGN(DexCompiler);
 };
 
@@ -248,6 +265,7 @@
     inst->SetOpcode(new_opcode);
     // Replace field index by field offset.
     inst->SetVRegC_22c(static_cast<uint16_t>(field_offset.Int32Value()));
+    quickened_info_.push_back(QuickenedInfo(dex_pc, field_idx));
   }
 }
 
@@ -287,24 +305,60 @@
       } else {
         inst->SetVRegB_35c(static_cast<uint16_t>(vtable_idx));
       }
+      quickened_info_.push_back(QuickenedInfo(dex_pc, method_idx));
     }
   }
 }
 
-}  // namespace optimizer
-}  // namespace art
-
-extern "C" void ArtCompileDEX(art::CompilerDriver& driver, const art::DexFile::CodeItem* code_item,
-                              uint32_t access_flags, art::InvokeType invoke_type,
-                              uint16_t class_def_idx, uint32_t method_idx, jobject class_loader,
-                              const art::DexFile& dex_file,
-                              art::DexToDexCompilationLevel dex_to_dex_compilation_level) {
-  UNUSED(invoke_type);
+extern "C" CompiledMethod* ArtCompileDEX(
+    art::CompilerDriver& driver,
+    const art::DexFile::CodeItem* code_item,
+    uint32_t access_flags,
+    art::InvokeType invoke_type ATTRIBUTE_UNUSED,
+    uint16_t class_def_idx,
+    uint32_t method_idx,
+    jobject class_loader,
+    const art::DexFile& dex_file,
+    art::DexToDexCompilationLevel dex_to_dex_compilation_level) {
   if (dex_to_dex_compilation_level != art::kDontDexToDexCompile) {
     art::DexCompilationUnit unit(nullptr, class_loader, art::Runtime::Current()->GetClassLinker(),
                                  dex_file, code_item, class_def_idx, method_idx, access_flags,
                                  driver.GetVerifiedMethod(&dex_file, method_idx));
     art::optimizer::DexCompiler dex_compiler(driver, unit, dex_to_dex_compilation_level);
     dex_compiler.Compile();
+    if (dex_compiler.GetQuickenedInfo().empty()) {
+      // No need to create a CompiledMethod if there are no quickened opcodes.
+      return nullptr;
+    }
+
+    // Create a `CompiledMethod`, with the quickened information in the vmap table.
+    Leb128EncodingVector builder;
+    for (QuickenedInfo info : dex_compiler.GetQuickenedInfo()) {
+      builder.PushBackUnsigned(info.dex_pc);
+      builder.PushBackUnsigned(info.dex_member_index);
+    }
+    InstructionSet instruction_set = driver.GetInstructionSet();
+    if (instruction_set == kThumb2) {
+      // Don't use the thumb2 instruction set to avoid the one off code delta.
+      instruction_set = kArm;
+    }
+    return CompiledMethod::SwapAllocCompiledMethod(
+        &driver,
+        instruction_set,
+        ArrayRef<const uint8_t>(),                   // no code
+        0,
+        0,
+        0,
+        nullptr,                                     // src_mapping_table
+        ArrayRef<const uint8_t>(),                   // mapping_table
+        ArrayRef<const uint8_t>(builder.GetData()),  // vmap_table
+        ArrayRef<const uint8_t>(),                   // gc_map
+        ArrayRef<const uint8_t>(),                   // cfi data
+        ArrayRef<const LinkerPatch>());
   }
+  return nullptr;
 }
+
+}  // namespace optimizer
+
+}  // namespace art
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 7890108..a52bfae 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -2291,10 +2291,16 @@
       // TODO: add a command-line option to disable DEX-to-DEX compilation ?
       // Do not optimize if a VerifiedMethod is missing. SafeCast elision, for example, relies on
       // it.
-      (*dex_to_dex_compiler_)(*this, code_item, access_flags,
-                              invoke_type, class_def_idx,
-                              method_idx, class_loader, dex_file,
-                              has_verified_method ? dex_to_dex_compilation_level : kRequired);
+      compiled_method = (*dex_to_dex_compiler_)(
+          *this,
+          code_item,
+          access_flags,
+          invoke_type,
+          class_def_idx,
+          method_idx,
+          class_loader,
+          dex_file,
+          has_verified_method ? dex_to_dex_compilation_level : kRequired);
     }
   }
   if (kTimeCompileMethod) {
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 2d7ceae..5cf4044 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -675,12 +675,13 @@
   typedef void (*CompilerCallbackFn)(CompilerDriver& driver);
   typedef MutexLock* (*CompilerMutexLockFn)(CompilerDriver& driver);
 
-  typedef void (*DexToDexCompilerFn)(CompilerDriver& driver,
-                                     const DexFile::CodeItem* code_item,
-                                     uint32_t access_flags, InvokeType invoke_type,
-                                     uint32_t class_dex_idx, uint32_t method_idx,
-                                     jobject class_loader, const DexFile& dex_file,
-                                     DexToDexCompilationLevel dex_to_dex_compilation_level);
+  typedef CompiledMethod* (*DexToDexCompilerFn)(
+      CompilerDriver& driver,
+      const DexFile::CodeItem* code_item,
+      uint32_t access_flags, InvokeType invoke_type,
+      uint32_t class_dex_idx, uint32_t method_idx,
+      jobject class_loader, const DexFile& dex_file,
+      DexToDexCompilationLevel dex_to_dex_compilation_level);
   DexToDexCompilerFn dex_to_dex_compiler_;
 
   void* compiler_context_;
diff --git a/compiler/elf_writer_debug.cc b/compiler/elf_writer_debug.cc
index c68bbc0..c10ffeb 100644
--- a/compiler/elf_writer_debug.cc
+++ b/compiler/elf_writer_debug.cc
@@ -249,16 +249,16 @@
   // Find all addresses (low_pc) which contain deduped methods.
   // The first instance of method is not marked deduped_, but the rest is.
   std::unordered_set<uint32_t> deduped_addresses;
-  for (auto it = method_infos.begin(); it != method_infos.end(); ++it) {
-    if (it->deduped_) {
-      deduped_addresses.insert(it->low_pc_);
+  for (const OatWriter::DebugInfo& mi : method_infos) {
+    if (mi.deduped_) {
+      deduped_addresses.insert(mi.low_pc_);
     }
   }
 
   // Group the methods into compilation units based on source file.
   std::vector<std::vector<const OatWriter::DebugInfo*>> compilation_units;
   const char* last_source_file = nullptr;
-  for (const auto& mi : method_infos) {
+  for (const OatWriter::DebugInfo& mi : method_infos) {
     // Attribute given instruction range only to single method.
     // Otherwise the debugger might get really confused.
     if (!mi.deduped_) {
diff --git a/compiler/image_writer.h b/compiler/image_writer.h
index 754fe84..1523383 100644
--- a/compiler/image_writer.h
+++ b/compiler/image_writer.h
@@ -199,7 +199,7 @@
   const uint8_t* GetOatAddress(uint32_t offset) const {
     // With Quick, code is within the OatFile, as there are all in one
     // .o ELF object.
-    DCHECK_LT(offset, oat_file_->Size());
+    DCHECK_LE(offset, oat_file_->Size());
     DCHECK(oat_data_begin_ != nullptr);
     return offset == 0u ? nullptr : oat_data_begin_ + offset;
   }
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index a98a304..4318ea5 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -374,9 +374,7 @@
       uint32_t quick_code_offset = 0;
 
       const SwapVector<uint8_t>* quick_code = compiled_method->GetQuickCode();
-      CHECK(quick_code != nullptr);
       uint32_t code_size = quick_code->size() * sizeof(uint8_t);
-      CHECK_NE(code_size, 0U);
       uint32_t thumb_offset = compiled_method->CodeDelta();
 
       // Deduplicate code arrays if we are not producing debuggable code.
@@ -394,16 +392,18 @@
         }
       }
 
-      MethodReference method_ref(dex_file_, it.GetMemberIndex());
-      auto method_lb = writer_->method_offset_map_.map.lower_bound(method_ref);
-      if (method_lb != writer_->method_offset_map_.map.end() &&
-          !writer_->method_offset_map_.map.key_comp()(method_ref, method_lb->first)) {
-        // TODO: Should this be a hard failure?
-        LOG(WARNING) << "Multiple definitions of "
-            << PrettyMethod(method_ref.dex_method_index, *method_ref.dex_file)
-            << ((method_lb->second != quick_code_offset) ? "; OFFSET MISMATCH" : "");
-      } else {
-        writer_->method_offset_map_.map.PutBefore(method_lb, method_ref, quick_code_offset);
+      if (code_size != 0) {
+        MethodReference method_ref(dex_file_, it.GetMemberIndex());
+        auto method_lb = writer_->method_offset_map_.map.lower_bound(method_ref);
+        if (method_lb != writer_->method_offset_map_.map.end() &&
+            !writer_->method_offset_map_.map.key_comp()(method_ref, method_lb->first)) {
+          // TODO: Should this be a hard failure?
+          LOG(WARNING) << "Multiple definitions of "
+              << PrettyMethod(method_ref.dex_method_index, *method_ref.dex_file)
+              << ((method_lb->second != quick_code_offset) ? "; OFFSET MISMATCH" : "");
+        } else {
+          writer_->method_offset_map_.map.PutBefore(method_lb, method_ref, quick_code_offset);
+        }
       }
 
       // Update quick method header.
@@ -411,21 +411,24 @@
       OatQuickMethodHeader* method_header = &oat_class->method_headers_[method_offsets_index_];
       uint32_t mapping_table_offset = method_header->mapping_table_offset_;
       uint32_t vmap_table_offset = method_header->vmap_table_offset_;
+      // If we don't have quick code, then we must have a vmap, as that is how the dex2dex
+      // compiler records its transformations.
+      DCHECK(quick_code != nullptr || vmap_table_offset != 0);
       uint32_t gc_map_offset = method_header->gc_map_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.
       uint32_t code_offset = quick_code_offset - thumb_offset;
-      if (mapping_table_offset != 0u) {
+      if (mapping_table_offset != 0u && code_offset != 0u) {
         mapping_table_offset += code_offset;
-        DCHECK_LT(mapping_table_offset, code_offset);
+        DCHECK_LT(mapping_table_offset, code_offset) << "Overflow in oat offsets";
       }
-      if (vmap_table_offset != 0u) {
+      if (vmap_table_offset != 0u && code_offset != 0u) {
         vmap_table_offset += code_offset;
-        DCHECK_LT(vmap_table_offset, code_offset);
+        DCHECK_LT(vmap_table_offset, code_offset) << "Overflow in oat offsets";
       }
-      if (gc_map_offset != 0u) {
+      if (gc_map_offset != 0u && code_offset != 0u) {
         gc_map_offset += code_offset;
-        DCHECK_LT(gc_map_offset, code_offset);
+        DCHECK_LT(gc_map_offset, code_offset) << "Overflow in oat offsets";
       }
       uint32_t frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
       uint32_t core_spill_mask = compiled_method->GetCoreSpillMask();
@@ -534,7 +537,7 @@
                               const ClassDataItemIterator& it,
                               uint32_t thumb_offset) {
     offset_ = writer_->relative_patcher_->ReserveSpace(
-              offset_, compiled_method, MethodReference(dex_file_, it.GetMemberIndex()));
+        offset_, compiled_method, MethodReference(dex_file_, it.GetMemberIndex()));
     offset_ = compiled_method->AlignCode(offset_);
     DCHECK_ALIGNED_PARAM(offset_,
                          GetInstructionSetAlignment(compiled_method->GetInstructionSet()));
@@ -619,15 +622,19 @@
         *dex_file_, it.GetMemberIndex(), dex_cache, NullHandle<mirror::ClassLoader>(), nullptr,
         invoke_type);
     if (method == nullptr) {
-      LOG(ERROR) << "Unexpected failure to resolve a method: "
-                 << PrettyMethod(it.GetMemberIndex(), *dex_file_, true);
+      LOG(INTERNAL_FATAL) << "Unexpected failure to resolve a method: "
+                          << PrettyMethod(it.GetMemberIndex(), *dex_file_, true);
       soa.Self()->AssertPendingException();
       mirror::Throwable* exc = soa.Self()->GetException();
       std::string dump = exc->Dump();
       LOG(FATAL) << dump;
+      UNREACHABLE();
     }
-    method->SetEntryPointFromQuickCompiledCodePtrSize(reinterpret_cast<void*>(offsets.code_offset_),
-                                                      pointer_size_);
+
+    if (compiled_method != nullptr && compiled_method->GetQuickCode()->size() != 0) {
+      method->SetEntryPointFromQuickCompiledCodePtrSize(
+          reinterpret_cast<void*>(offsets.code_offset_), pointer_size_);
+    }
 
     return true;
   }
@@ -689,85 +696,82 @@
       OutputStream* out = out_;
 
       const SwapVector<uint8_t>* quick_code = compiled_method->GetQuickCode();
-      if (quick_code != nullptr) {
-        // Need a wrapper if we create a copy for patching.
-        ArrayRef<const uint8_t> wrapped(*quick_code);
-        uint32_t code_size = quick_code->size() * sizeof(uint8_t);
-        CHECK_NE(code_size, 0U);
+      // Need a wrapper if we create a copy for patching.
+      ArrayRef<const uint8_t> wrapped(*quick_code);
+      uint32_t code_size = quick_code->size() * sizeof(uint8_t);
 
-        // Deduplicate code arrays.
-        const OatMethodOffsets& method_offsets = oat_class->method_offsets_[method_offsets_index_];
-        if (method_offsets.code_offset_ >= offset_) {
-          offset_ = writer_->relative_patcher_->WriteThunks(out, offset_);
-          if (offset_ == 0u) {
-            ReportWriteFailure("relative call thunk", it);
-            return false;
-          }
-          uint32_t aligned_offset = compiled_method->AlignCode(offset_);
-          uint32_t aligned_code_delta = aligned_offset - offset_;
-          if (aligned_code_delta != 0) {
-            if (!writer_->WriteCodeAlignment(out, aligned_code_delta)) {
-              ReportWriteFailure("code alignment padding", it);
-              return false;
-            }
-            offset_ += aligned_code_delta;
-            DCHECK_OFFSET_();
-          }
-          DCHECK_ALIGNED_PARAM(offset_,
-                               GetInstructionSetAlignment(compiled_method->GetInstructionSet()));
-          DCHECK_EQ(method_offsets.code_offset_,
-                    offset_ + sizeof(OatQuickMethodHeader) + compiled_method->CodeDelta())
-              << PrettyMethod(it.GetMemberIndex(), *dex_file_);
-          const OatQuickMethodHeader& method_header =
-              oat_class->method_headers_[method_offsets_index_];
-          writer_->oat_header_->UpdateChecksum(&method_header, sizeof(method_header));
-          if (!out->WriteFully(&method_header, sizeof(method_header))) {
-            ReportWriteFailure("method header", it);
-            return false;
-          }
-          writer_->size_method_header_ += sizeof(method_header);
-          offset_ += sizeof(method_header);
-          DCHECK_OFFSET_();
-
-          if (!compiled_method->GetPatches().empty()) {
-            patched_code_.assign(quick_code->begin(), quick_code->end());
-            wrapped = ArrayRef<const uint8_t>(patched_code_);
-            for (const LinkerPatch& patch : compiled_method->GetPatches()) {
-              if (patch.Type() == kLinkerPatchCallRelative) {
-                // NOTE: Relative calls across oat files are not supported.
-                uint32_t target_offset = GetTargetOffset(patch);
-                uint32_t literal_offset = patch.LiteralOffset();
-                writer_->relative_patcher_->PatchCall(&patched_code_, literal_offset,
-                                                       offset_ + literal_offset, target_offset);
-              } else if (patch.Type() == kLinkerPatchDexCacheArray) {
-                uint32_t target_offset = GetDexCacheOffset(patch);
-                uint32_t literal_offset = patch.LiteralOffset();
-                writer_->relative_patcher_->PatchDexCacheReference(&patched_code_, patch,
-                                                                   offset_ + literal_offset,
-                                                                   target_offset);
-              } else if (patch.Type() == kLinkerPatchCall) {
-                uint32_t target_offset = GetTargetOffset(patch);
-                PatchCodeAddress(&patched_code_, patch.LiteralOffset(), target_offset);
-              } else if (patch.Type() == kLinkerPatchMethod) {
-                ArtMethod* method = GetTargetMethod(patch);
-                PatchMethodAddress(&patched_code_, patch.LiteralOffset(), method);
-              } else if (patch.Type() == kLinkerPatchType) {
-                mirror::Class* type = GetTargetType(patch);
-                PatchObjectAddress(&patched_code_, patch.LiteralOffset(), type);
-              }
-            }
-          }
-
-          writer_->oat_header_->UpdateChecksum(wrapped.data(), code_size);
-          if (!out->WriteFully(wrapped.data(), code_size)) {
-            ReportWriteFailure("method code", it);
-            return false;
-          }
-          writer_->size_code_ += code_size;
-          offset_ += code_size;
+      // Deduplicate code arrays.
+      const OatMethodOffsets& method_offsets = oat_class->method_offsets_[method_offsets_index_];
+      if (method_offsets.code_offset_ > offset_) {
+        offset_ = writer_->relative_patcher_->WriteThunks(out, offset_);
+        if (offset_ == 0u) {
+          ReportWriteFailure("relative call thunk", it);
+          return false;
         }
+        uint32_t aligned_offset = compiled_method->AlignCode(offset_);
+        uint32_t aligned_code_delta = aligned_offset - offset_;
+        if (aligned_code_delta != 0) {
+          if (!writer_->WriteCodeAlignment(out, aligned_code_delta)) {
+            ReportWriteFailure("code alignment padding", it);
+            return false;
+          }
+          offset_ += aligned_code_delta;
+          DCHECK_OFFSET_();
+        }
+        DCHECK_ALIGNED_PARAM(offset_,
+                             GetInstructionSetAlignment(compiled_method->GetInstructionSet()));
+        DCHECK_EQ(method_offsets.code_offset_,
+                  offset_ + sizeof(OatQuickMethodHeader) + compiled_method->CodeDelta())
+            << PrettyMethod(it.GetMemberIndex(), *dex_file_);
+        const OatQuickMethodHeader& method_header =
+            oat_class->method_headers_[method_offsets_index_];
+        writer_->oat_header_->UpdateChecksum(&method_header, sizeof(method_header));
+        if (!out->WriteFully(&method_header, sizeof(method_header))) {
+          ReportWriteFailure("method header", it);
+          return false;
+        }
+        writer_->size_method_header_ += sizeof(method_header);
+        offset_ += sizeof(method_header);
         DCHECK_OFFSET_();
+
+        if (!compiled_method->GetPatches().empty()) {
+          patched_code_.assign(quick_code->begin(), quick_code->end());
+          wrapped = ArrayRef<const uint8_t>(patched_code_);
+          for (const LinkerPatch& patch : compiled_method->GetPatches()) {
+            if (patch.Type() == kLinkerPatchCallRelative) {
+              // NOTE: Relative calls across oat files are not supported.
+              uint32_t target_offset = GetTargetOffset(patch);
+              uint32_t literal_offset = patch.LiteralOffset();
+              writer_->relative_patcher_->PatchCall(&patched_code_, literal_offset,
+                                                     offset_ + literal_offset, target_offset);
+            } else if (patch.Type() == kLinkerPatchDexCacheArray) {
+              uint32_t target_offset = GetDexCacheOffset(patch);
+              uint32_t literal_offset = patch.LiteralOffset();
+              writer_->relative_patcher_->PatchDexCacheReference(&patched_code_, patch,
+                                                                 offset_ + literal_offset,
+                                                                 target_offset);
+            } else if (patch.Type() == kLinkerPatchCall) {
+              uint32_t target_offset = GetTargetOffset(patch);
+              PatchCodeAddress(&patched_code_, patch.LiteralOffset(), target_offset);
+            } else if (patch.Type() == kLinkerPatchMethod) {
+              ArtMethod* method = GetTargetMethod(patch);
+              PatchMethodAddress(&patched_code_, patch.LiteralOffset(), method);
+            } else if (patch.Type() == kLinkerPatchType) {
+              mirror::Class* type = GetTargetType(patch);
+              PatchObjectAddress(&patched_code_, patch.LiteralOffset(), type);
+            }
+          }
+        }
+
+        writer_->oat_header_->UpdateChecksum(wrapped.data(), code_size);
+        if (!out->WriteFully(wrapped.data(), code_size)) {
+          ReportWriteFailure("method code", it);
+          return false;
+        }
+        writer_->size_code_ += code_size;
+        offset_ += code_size;
       }
+      DCHECK_OFFSET_();
       ++method_offsets_index_;
     }
 
diff --git a/runtime/class_linker.cc b/runtime/class_linker.cc
index 0694227..1ec02aa 100644
--- a/runtime/class_linker.cc
+++ b/runtime/class_linker.cc
@@ -55,6 +55,7 @@
 #include "linear_alloc.h"
 #include "oat.h"
 #include "oat_file.h"
+#include "oat_file-inl.h"
 #include "oat_file_assistant.h"
 #include "object_lock.h"
 #include "mirror/class.h"
diff --git a/runtime/oat_file-inl.h b/runtime/oat_file-inl.h
index 6b3b666..37d025a 100644
--- a/runtime/oat_file-inl.h
+++ b/runtime/oat_file-inl.h
@@ -38,14 +38,6 @@
   return reinterpret_cast<const uint8_t*>(method_header) - begin_;
 }
 
-inline uint32_t OatFile::OatMethod::GetQuickCodeSize() const {
-  const void* code = ArtMethod::EntryPointToCodePointer(GetQuickCode());
-  if (code == nullptr) {
-    return 0u;
-  }
-  return reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].code_size_;
-}
-
 inline uint32_t OatFile::OatMethod::GetQuickCodeSizeOffset() const {
   const OatQuickMethodHeader* method_header = GetOatQuickMethodHeader();
   if (method_header == nullptr) {
@@ -78,7 +70,7 @@
   return reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].frame_info_.FpSpillMask();
 }
 
-const uint8_t* OatFile::OatMethod::GetGcMap() const {
+inline const uint8_t* OatFile::OatMethod::GetGcMap() const {
   const void* code = ArtMethod::EntryPointToCodePointer(GetQuickCode());
   if (code == nullptr) {
     return nullptr;
@@ -90,12 +82,12 @@
   return reinterpret_cast<const uint8_t*>(code) - offset;
 }
 
-uint32_t OatFile::OatMethod::GetGcMapOffset() const {
+inline uint32_t OatFile::OatMethod::GetGcMapOffset() const {
   const uint8_t* gc_map = GetGcMap();
   return static_cast<uint32_t>(gc_map != nullptr ? gc_map - begin_ : 0u);
 }
 
-uint32_t OatFile::OatMethod::GetGcMapOffsetOffset() const {
+inline uint32_t OatFile::OatMethod::GetGcMapOffsetOffset() const {
   const OatQuickMethodHeader* method_header = GetOatQuickMethodHeader();
   if (method_header == nullptr) {
     return 0u;
@@ -153,6 +145,22 @@
   return reinterpret_cast<const uint8_t*>(code) - offset;
 }
 
+inline uint32_t OatFile::OatMethod::GetQuickCodeSize() const {
+  const void* code = ArtMethod::EntryPointToCodePointer(GetOatPointer<const void*>(code_offset_));
+  if (code == nullptr) {
+    return 0u;
+  }
+  return reinterpret_cast<const OatQuickMethodHeader*>(code)[-1].code_size_;
+}
+
+inline uint32_t OatFile::OatMethod::GetCodeOffset() const {
+  return (GetQuickCodeSize() == 0) ? 0 : code_offset_;
+}
+
+inline const void* OatFile::OatMethod::GetQuickCode() const {
+  return GetOatPointer<const void*>(GetCodeOffset());
+}
+
 }  // namespace art
 
 #endif  // ART_RUNTIME_OAT_FILE_INL_H_
diff --git a/runtime/oat_file.cc b/runtime/oat_file.cc
index ad5741e..098fe61 100644
--- a/runtime/oat_file.cc
+++ b/runtime/oat_file.cc
@@ -41,6 +41,7 @@
 #include "mem_map.h"
 #include "mirror/class.h"
 #include "mirror/object-inl.h"
+#include "oat_file-inl.h"
 #include "os.h"
 #include "runtime.h"
 #include "utils.h"
diff --git a/runtime/oat_file.h b/runtime/oat_file.h
index 1a782de..7c4ef8b 100644
--- a/runtime/oat_file.h
+++ b/runtime/oat_file.h
@@ -100,13 +100,9 @@
    public:
     void LinkMethod(ArtMethod* method) const;
 
-    uint32_t GetCodeOffset() const {
-      return code_offset_;
-    }
+    uint32_t GetCodeOffset() const;
 
-    const void* GetQuickCode() const {
-      return GetOatPointer<const void*>(code_offset_);
-    }
+    const void* GetQuickCode() const;
 
     // Returns size of quick code.
     uint32_t GetQuickCodeSize() const;