Refactor the use of Method by the compiler.

Remove the dependence on the Method object in dex2oat, allowing lazier
resolution.
Introduce new find and iterators in DexFile to simplify common
operations and avoid misuse of class data items.

Change-Id: I39fb8252190f543d89d8b233076355cec310fe08
diff --git a/src/oat_writer.cc b/src/oat_writer.cc
index 664dcfe..f3e78e6 100644
--- a/src/oat_writer.cc
+++ b/src/oat_writer.cc
@@ -24,6 +24,8 @@
   compiler_ = &compiler;
   class_loader_ = class_loader;
   dex_files_ = &dex_files;
+  oat_header_ = NULL;
+  executable_offset_padding_length_ = 0;
 
   size_t offset = InitOatHeader();
   offset = InitOatDexFiles(offset);
@@ -36,6 +38,13 @@
   CHECK_EQ(dex_files_->size(), oat_classes_.size());
 }
 
+OatWriter::~OatWriter() {
+  delete oat_header_;
+  STLDeleteElements(&oat_dex_files_);
+  STLDeleteElements(&oat_classes_);
+  STLDeleteElements(&oat_methods_);
+}
+
 size_t OatWriter::InitOatHeader() {
   // create the OatHeader
   oat_header_ = new OatHeader(dex_files_);
@@ -83,10 +92,13 @@
       oat_classes_[i]->methods_offsets_[class_def_index] = offset;
       const DexFile::ClassDef& class_def = dex_file->GetClassDef(class_def_index);
       const byte* class_data = dex_file->GetClassData(class_def);
-      DexFile::ClassDataHeader header = dex_file->ReadClassDataHeader(&class_data);
-      size_t num_direct_methods = header.direct_methods_size_;
-      size_t num_virtual_methods = header.virtual_methods_size_;
-      uint32_t num_methods = num_direct_methods + num_virtual_methods;
+      uint32_t num_methods = 0;
+      if (class_data != NULL) {  // ie not an empty class, such as a marker interface
+        ClassDataItemIterator it(*dex_file, class_data);
+        size_t num_direct_methods = it.NumDirectMethods();
+        size_t num_virtual_methods = it.NumVirtualMethods();
+        num_methods = num_direct_methods + num_virtual_methods;
+      }
       OatMethods* oat_methods = new OatMethods(num_methods);
       oat_methods_.push_back(oat_methods);
       offset += oat_methods->SizeOf();
@@ -135,46 +147,46 @@
                                       const DexFile& dex_file,
                                       const DexFile::ClassDef& class_def) {
   const byte* class_data = dex_file.GetClassData(class_def);
-  DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data);
-  size_t num_virtual_methods = header.virtual_methods_size_;
-  const char* descriptor = dex_file.GetClassDescriptor(class_def);
-
-  // TODO: remove code ByteArrays from Class/Method (and therefore ClassLoader)
-  // TODO: don't write code for shared stubs
-  Class* klass = Runtime::Current()->GetClassLinker()->FindClass(descriptor, class_loader_);
-  if (klass == NULL) {
-    LOG(WARNING) << "Didn't find class '" << descriptor << "' in dex file " << dex_file.GetLocation();
-    Thread* thread = Thread::Current();
-    DCHECK(thread->IsExceptionPending());
-    thread->ClearException();
+  if (class_data == NULL) {
+    // empty class, such as a marker interface
     return offset;
   }
-  CHECK_EQ(klass->GetClassLoader(), class_loader_);
+  ClassDataItemIterator it(dex_file, class_data);
   CHECK_EQ(oat_methods_[oat_class_index]->method_offsets_.size(),
-           klass->NumDirectMethods() + num_virtual_methods);
+           it.NumDirectMethods() + it.NumVirtualMethods());
+  // Skip fields
+  while (it.HasNextStaticField()) {
+    it.Next();
+  }
+  while (it.HasNextInstanceField()) {
+    it.Next();
+  }
+  // Process methods
   size_t class_def_method_index = 0;
-  for (size_t i = 0; i < klass->NumDirectMethods(); i++, class_def_method_index++) {
-    Method* method = klass->GetDirectMethod(i);
-    CHECK(method != NULL) << descriptor << " direct " << i;
-    offset = InitOatCodeMethod(offset, oat_class_index, class_def_method_index, method);
+  while (it.HasNextDirectMethod()) {
+    bool is_static = (it.GetMemberAccessFlags() & kAccStatic) != 0;
+    offset = InitOatCodeMethod(offset, oat_class_index, class_def_method_index, is_static, true,
+                               it.GetMemberIndex(), &dex_file);
+    class_def_method_index++;
+    it.Next();
   }
-  // note that num_virtual_methods != klass->NumVirtualMethods() because of miranda methods
-  for (size_t i = 0; i < num_virtual_methods; i++, class_def_method_index++) {
-    Method* method = klass->GetVirtualMethod(i);
-    CHECK(method != NULL) << descriptor << " virtual " << i;
-    offset = InitOatCodeMethod(offset, oat_class_index, class_def_method_index, method);
+  while (it.HasNextVirtualMethod()) {
+    CHECK_EQ(it.GetMemberAccessFlags() & kAccStatic, 0U);
+    offset = InitOatCodeMethod(offset, oat_class_index, class_def_method_index, false, false,
+                               it.GetMemberIndex(), &dex_file);
+    class_def_method_index++;
+    it.Next();
   }
+  DCHECK(!it.HasNext());
   return offset;
 }
 
-size_t OatWriter::InitOatCodeMethod(size_t offset,
-                                    size_t oat_class_index,
-                                    size_t class_def_method_index,
-                                    Method* method) {
+size_t OatWriter::InitOatCodeMethod(size_t offset, size_t oat_class_index,
+                                    size_t class_def_method_index, bool is_static, bool is_direct,
+                                    uint32_t method_idx, const DexFile* dex_file) {
   // derived from CompiledMethod if available
   uint32_t code_offset = 0;
   uint32_t frame_size_in_bytes = kStackAlignment;
-  uint32_t return_pc_offset_in_bytes = 0;
   uint32_t core_spill_mask = 0;
   uint32_t fp_spill_mask = 0;
   uint32_t mapping_table_offset = 0;
@@ -182,7 +194,8 @@
   // derived from CompiledInvokeStub if available
   uint32_t invoke_stub_offset = 0;
 
-  const CompiledMethod* compiled_method = compiler_->GetCompiledMethod(method);
+  CompiledMethod* compiled_method =
+      compiler_->GetCompiledMethod(art::Compiler::MethodReference(dex_file, method_idx));
   if (compiled_method != NULL) {
     offset = compiled_method->AlignCode(offset);
     DCHECK_ALIGNED(offset, kArmAlignment);
@@ -202,7 +215,6 @@
     }
 
     frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
-    return_pc_offset_in_bytes = compiled_method->GetReturnPcOffsetInBytes();
     core_spill_mask = compiled_method->GetCoreSpillMask();
     fp_spill_mask = compiled_method->GetFpSpillMask();
   }
@@ -210,9 +222,6 @@
   offset += sizeof(frame_size_in_bytes);
   oat_header_->UpdateChecksum(&frame_size_in_bytes, sizeof(frame_size_in_bytes));
 
-  offset += sizeof(return_pc_offset_in_bytes);
-  oat_header_->UpdateChecksum(&return_pc_offset_in_bytes, sizeof(return_pc_offset_in_bytes));
-
   offset += sizeof(core_spill_mask);
   oat_header_->UpdateChecksum(&core_spill_mask, sizeof(core_spill_mask));
 
@@ -249,7 +258,8 @@
     }
   }
 
-  const CompiledInvokeStub* compiled_invoke_stub = compiler_->GetCompiledInvokeStub(method);
+  const char* shorty = dex_file->GetMethodShorty(dex_file->GetMethodId(method_idx));
+  const CompiledInvokeStub* compiled_invoke_stub = compiler_->FindInvokeStub(is_static, shorty);
   if (compiled_invoke_stub != NULL) {
     offset = CompiledMethod::AlignCode(offset, compiler_->GetInstructionSet());
     DCHECK_ALIGNED(offset, kArmAlignment);
@@ -271,22 +281,26 @@
   oat_methods_[oat_class_index]->method_offsets_[class_def_method_index]
       = OatMethodOffsets(code_offset,
                          frame_size_in_bytes,
-                         return_pc_offset_in_bytes,
                          core_spill_mask,
                          fp_spill_mask,
                          mapping_table_offset,
                          vmap_table_offset,
                          invoke_stub_offset);
 
-  // Note that we leave the offset and values back in the Method where ImageWriter will find them
-  method->SetOatCodeOffset(code_offset);
-  method->SetFrameSizeInBytes(frame_size_in_bytes);
-  method->SetCoreSpillMask(core_spill_mask);
-  method->SetFpSpillMask(fp_spill_mask);
-  method->SetOatMappingTableOffset(mapping_table_offset);
-  method->SetOatVmapTableOffset(vmap_table_offset);
-  method->SetOatInvokeStubOffset(invoke_stub_offset);
-
+  if (compiler_->IsImage()) {
+    ClassLinker* linker = Runtime::Current()->GetClassLinker();
+    DexCache* dex_cache = linker->FindDexCache(*dex_file);
+    Method* method = linker->ResolveMethod(*dex_file, method_idx, dex_cache, class_loader_,
+                                           is_direct);
+    CHECK(method != NULL);
+    method->SetFrameSizeInBytes(frame_size_in_bytes);
+    method->SetCoreSpillMask(core_spill_mask);
+    method->SetFpSpillMask(fp_spill_mask);
+    method->SetOatMappingTableOffset(mapping_table_offset);
+    method->SetOatCodeOffset(code_offset);
+    method->SetOatVmapTableOffset(vmap_table_offset);
+    method->SetOatInvokeStubOffset(invoke_stub_offset);
+  }
   return offset;
 }
 
@@ -354,10 +368,11 @@
 }
 
 size_t OatWriter::WriteCodeDexFiles(File* file, size_t code_offset) {
+  size_t oat_class_index = 0;
   for (size_t i = 0; i != oat_classes_.size(); ++i) {
     const DexFile* dex_file = (*dex_files_)[i];
     CHECK(dex_file != NULL);
-    code_offset = WriteCodeDexFile(file, code_offset, *dex_file);
+    code_offset = WriteCodeDexFile(file, code_offset, oat_class_index, *dex_file);
     if (code_offset == 0) {
       return 0;
     }
@@ -365,10 +380,12 @@
   return code_offset;
 }
 
-size_t OatWriter::WriteCodeDexFile(File* file, size_t code_offset, const DexFile& dex_file) {
-  for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs(); class_def_index++) {
+size_t OatWriter::WriteCodeDexFile(File* file, size_t code_offset, size_t& oat_class_index,
+                                   const DexFile& dex_file) {
+  for (size_t class_def_index = 0; class_def_index < dex_file.NumClassDefs();
+      class_def_index++, oat_class_index++) {
     const DexFile::ClassDef& class_def = dex_file.GetClassDef(class_def_index);
-    code_offset = WriteCodeClassDef(file, code_offset, dex_file, class_def);
+    code_offset = WriteCodeClassDef(file, code_offset, oat_class_index, dex_file, class_def);
     if (code_offset == 0) {
       return 0;
     }
@@ -376,54 +393,68 @@
   return code_offset;
 }
 
-void OatWriter::ReportWriteFailure(const char* what, Method* m, File* f) {
-  PLOG(ERROR) << "Failed to write " << what << " for " << PrettyMethod(m) << " to " << f->name();
+void OatWriter::ReportWriteFailure(const char* what, uint32_t method_idx,
+                                   const DexFile& dex_file, File* f) const {
+  PLOG(ERROR) << "Failed to write " << what << " for " << PrettyMethod(method_idx, dex_file)
+      << " to " << f->name();
 }
 
 size_t OatWriter::WriteCodeClassDef(File* file,
-                                    size_t code_offset,
+                                    size_t code_offset, size_t oat_class_index,
                                     const DexFile& dex_file,
                                     const DexFile::ClassDef& class_def) {
   const byte* class_data = dex_file.GetClassData(class_def);
-  DexFile::ClassDataHeader header = dex_file.ReadClassDataHeader(&class_data);
-  size_t num_virtual_methods = header.virtual_methods_size_;
-  const char* descriptor = dex_file.GetClassDescriptor(class_def);
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  Class* klass = class_linker->FindClass(descriptor, class_loader_);
-  if (klass == NULL) {
-    LOG(WARNING) << "Didn't find class '" << descriptor << "' in dex file " << dex_file.GetLocation();
-    Thread* thread = Thread::Current();
-    DCHECK(thread->IsExceptionPending());
-    thread->ClearException();
+  if (class_data == NULL) {
+    // ie. an empty class such as a marker interface
     return code_offset;
   }
-
-  // Note that we clear the code array here, image_writer will use GetCodeOffset to find it
-  for (size_t i = 0; i < klass->NumDirectMethods(); i++) {
-    Method* method = klass->GetDirectMethod(i);
-    code_offset = WriteCodeMethod(file, code_offset, method);
+  ClassDataItemIterator it(dex_file, class_data);
+  // Skip fields
+  while (it.HasNextStaticField()) {
+    it.Next();
+  }
+  while (it.HasNextInstanceField()) {
+    it.Next();
+  }
+  // Process methods
+  size_t class_def_method_index = 0;
+  while (it.HasNextDirectMethod()) {
+    bool is_static = (it.GetMemberAccessFlags() & kAccStatic) != 0;
+    code_offset = WriteCodeMethod(file, code_offset, oat_class_index, class_def_method_index,
+                                  is_static, it.GetMemberIndex(), dex_file);
     if (code_offset == 0) {
       return 0;
     }
+    class_def_method_index++;
+    it.Next();
   }
-  // note that num_virtual_methods != klass->NumVirtualMethods() because of miranda methods
-  for (size_t i = 0; i < num_virtual_methods; i++) {
-    Method* method = klass->GetVirtualMethod(i);
-    code_offset = WriteCodeMethod(file, code_offset, method);
+  while (it.HasNextVirtualMethod()) {
+    code_offset = WriteCodeMethod(file, code_offset, oat_class_index, class_def_method_index,
+                                  false, it.GetMemberIndex(), dex_file);
     if (code_offset == 0) {
       return 0;
     }
-  }
-  for (size_t i = num_virtual_methods; i < klass->NumVirtualMethods(); i++) {
-    Method* method = klass->GetVirtualMethod(i);
-    CHECK(compiler_->GetCompiledMethod(method) == NULL) << PrettyMethod(method);
+    class_def_method_index++;
+    it.Next();
   }
   return code_offset;
 }
 
-size_t OatWriter::WriteCodeMethod(File* file, size_t code_offset, Method* method) {
-  const CompiledMethod* compiled_method = compiler_->GetCompiledMethod(method);
-  if (compiled_method != NULL) {
+size_t OatWriter::WriteCodeMethod(File* file, size_t code_offset, size_t oat_class_index,
+                                  size_t class_def_method_index, bool is_static,
+                                  uint32_t method_idx, const DexFile& dex_file) {
+  const CompiledMethod* compiled_method =
+      compiler_->GetCompiledMethod(art::Compiler::MethodReference(&dex_file, method_idx));
+
+  uint32_t frame_size_in_bytes = 0;
+  uint32_t core_spill_mask = 0;
+  uint32_t fp_spill_mask = 0;
+
+  OatMethodOffsets method_offsets =
+      oat_methods_[oat_class_index]->method_offsets_[class_def_method_index];
+
+
+  if (compiled_method != NULL) {  // ie. not an abstract method
     uint32_t aligned_code_offset = compiled_method->AlignCode(code_offset);
     uint32_t aligned_code_delta = aligned_code_offset - code_offset;
     if (aligned_code_delta != 0) {
@@ -443,42 +474,38 @@
     // Deduplicate code arrays
     size_t offset = code_offset + compiled_method->CodeDelta();
     std::map<const std::vector<uint8_t>*, uint32_t>::iterator code_iter = code_offsets_.find(&code);
-    if (code_iter != code_offsets_.end() && offset != method->GetOatCodeOffset()) {
-      DCHECK((code_size == 0 && method->GetOatCodeOffset() == 0)
-             || code_iter->second == method->GetOatCodeOffset()) << PrettyMethod(method);
+    if (code_iter != code_offsets_.end() && offset != method_offsets.code_offset_) {
+      DCHECK((code_size == 0 && method_offsets.code_offset_ == 0)
+             || code_iter->second == method_offsets.code_offset_)
+             << PrettyMethod(method_idx, dex_file);
     } else {
-      DCHECK((code_size == 0 && method->GetOatCodeOffset() == 0)
-             || offset == method->GetOatCodeOffset()) << PrettyMethod(method);
+      DCHECK((code_size == 0 && method_offsets.code_offset_ == 0)
+             || offset == method_offsets.code_offset_)
+             << PrettyMethod(method_idx, dex_file);
       if (!file->WriteFully(&code[0], code_size)) {
-        ReportWriteFailure("method code", method, file);
+        ReportWriteFailure("method code", method_idx, dex_file, file);
         return false;
       }
       code_offset += code_size;
     }
     DCHECK_CODE_OFFSET();
+    frame_size_in_bytes = compiled_method->GetFrameSizeInBytes();
+    core_spill_mask = compiled_method->GetCoreSpillMask();
+    fp_spill_mask = compiled_method->GetFpSpillMask();
   }
 
-  uint32_t frame_size_in_bytes = method->GetFrameSizeInBytes();
-  uint32_t return_pc_offset_in_bytes = method->GetReturnPcOffsetInBytes();
-  uint32_t core_spill_mask = method->GetCoreSpillMask();
-  uint32_t fp_spill_mask = method->GetFpSpillMask();
   if (!file->WriteFully(&frame_size_in_bytes, sizeof(frame_size_in_bytes))) {
-    ReportWriteFailure("method frame size", method, file);
+    ReportWriteFailure("method frame size", method_idx, dex_file, file);
     return false;
   }
   code_offset += sizeof(frame_size_in_bytes);
-  if (!file->WriteFully(&return_pc_offset_in_bytes, sizeof(return_pc_offset_in_bytes))) {
-    ReportWriteFailure("method return pc", method, file);
-    return false;
-  }
-  code_offset += sizeof(return_pc_offset_in_bytes);
   if (!file->WriteFully(&core_spill_mask, sizeof(core_spill_mask))) {
-    ReportWriteFailure("method core spill mask", method, file);
+    ReportWriteFailure("method core spill mask", method_idx, dex_file, file);
     return false;
   }
   code_offset += sizeof(core_spill_mask);
   if (!file->WriteFully(&fp_spill_mask, sizeof(fp_spill_mask))) {
-    ReportWriteFailure("method fp spill mask", method, file);
+    ReportWriteFailure("method fp spill mask", method_idx, dex_file, file);
     return false;
   }
   code_offset += sizeof(fp_spill_mask);
@@ -488,15 +515,19 @@
     size_t mapping_table_size = mapping_table.size() * sizeof(mapping_table[0]);
 
     // Deduplicate mapping tables
-    std::map<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter = mapping_table_offsets_.find(&mapping_table);
-    if (mapping_iter != mapping_table_offsets_.end() && code_offset != method->GetOatMappingTableOffset()) {
-      DCHECK((mapping_table_size == 0 && method->GetOatMappingTableOffset() == 0)
-          || mapping_iter->second == method->GetOatMappingTableOffset()) << PrettyMethod(method);
+    std::map<const std::vector<uint32_t>*, uint32_t>::iterator mapping_iter =
+        mapping_table_offsets_.find(&mapping_table);
+    if (mapping_iter != mapping_table_offsets_.end() &&
+        code_offset != method_offsets.mapping_table_offset_) {
+      DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0)
+          || mapping_iter->second == method_offsets.mapping_table_offset_)
+          << PrettyMethod(method_idx, dex_file);
     } else {
-      DCHECK((mapping_table_size == 0 && method->GetOatMappingTableOffset() == 0)
-          || code_offset == method->GetOatMappingTableOffset()) << PrettyMethod(method);
+      DCHECK((mapping_table_size == 0 && method_offsets.mapping_table_offset_ == 0)
+          || code_offset == method_offsets.mapping_table_offset_)
+          << PrettyMethod(method_idx, dex_file);
       if (!file->WriteFully(&mapping_table[0], mapping_table_size)) {
-        ReportWriteFailure("mapping table", method, file);
+        ReportWriteFailure("mapping table", method_idx, dex_file, file);
         return false;
       }
       code_offset += mapping_table_size;
@@ -507,23 +538,27 @@
     size_t vmap_table_size = vmap_table.size() * sizeof(vmap_table[0]);
 
     // Deduplicate vmap tables
-    std::map<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter = vmap_table_offsets_.find(&vmap_table);
-    if (vmap_iter != vmap_table_offsets_.end() && code_offset != method->GetOatVmapTableOffset()) {
-      DCHECK((vmap_table_size == 0 && method->GetOatVmapTableOffset() == 0)
-          || vmap_iter->second == method->GetOatVmapTableOffset()) << PrettyMethod(method);
+    std::map<const std::vector<uint16_t>*, uint32_t>::iterator vmap_iter =
+        vmap_table_offsets_.find(&vmap_table);
+    if (vmap_iter != vmap_table_offsets_.end() &&
+        code_offset != method_offsets.vmap_table_offset_) {
+      DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0)
+          || vmap_iter->second == method_offsets.vmap_table_offset_)
+          << PrettyMethod(method_idx, dex_file);
     } else {
-      DCHECK((vmap_table_size == 0 && method->GetOatVmapTableOffset() == 0)
-          || code_offset == method->GetOatVmapTableOffset()) << PrettyMethod(method);
+      DCHECK((vmap_table_size == 0 && method_offsets.vmap_table_offset_ == 0)
+          || code_offset == method_offsets.vmap_table_offset_)
+          << PrettyMethod(method_idx, dex_file);
       if (!file->WriteFully(&vmap_table[0], vmap_table_size)) {
-        ReportWriteFailure("vmap table", method, file);
+        ReportWriteFailure("vmap table", method_idx, dex_file, file);
         return false;
       }
       code_offset += vmap_table_size;
     }
     DCHECK_CODE_OFFSET();
   }
-
-  const CompiledInvokeStub* compiled_invoke_stub = compiler_->GetCompiledInvokeStub(method);
+  const char* shorty = dex_file.GetMethodShorty(dex_file.GetMethodId(method_idx));
+  const CompiledInvokeStub* compiled_invoke_stub = compiler_->FindInvokeStub(is_static, shorty);
   if (compiled_invoke_stub != NULL) {
     uint32_t aligned_code_offset = CompiledMethod::AlignCode(code_offset,
                                                              compiler_->GetInstructionSet());
@@ -543,37 +578,34 @@
     size_t invoke_stub_size = invoke_stub.size() * sizeof(invoke_stub[0]);
 
     // Deduplicate invoke stubs
-    std::map<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter = code_offsets_.find(&invoke_stub);
-    if (stub_iter != code_offsets_.end() && code_offset != method->GetOatInvokeStubOffset()) {
-      DCHECK((invoke_stub_size == 0 && method->GetOatInvokeStubOffset() == 0)
-          || stub_iter->second == method->GetOatInvokeStubOffset()) << PrettyMethod(method);
+    std::map<const std::vector<uint8_t>*, uint32_t>::iterator stub_iter =
+        code_offsets_.find(&invoke_stub);
+    if (stub_iter != code_offsets_.end() &&
+        code_offset != method_offsets.invoke_stub_offset_) {
+      DCHECK((invoke_stub_size == 0 && method_offsets.invoke_stub_offset_ == 0)
+          || stub_iter->second == method_offsets.invoke_stub_offset_)
+          << PrettyMethod(method_idx, dex_file);
     } else {
-      DCHECK((invoke_stub_size == 0 && method->GetOatInvokeStubOffset() == 0)
-          || code_offset == method->GetOatInvokeStubOffset()) << PrettyMethod(method);
+      DCHECK((invoke_stub_size == 0 && method_offsets.invoke_stub_offset_ == 0)
+          || code_offset == method_offsets.invoke_stub_offset_)
+          << PrettyMethod(method_idx, dex_file);
       if (!file->WriteFully(&invoke_stub[0], invoke_stub_size)) {
-        ReportWriteFailure("invoke stub code", method, file);
+        ReportWriteFailure("invoke stub code", method_idx, dex_file, file);
         return false;
       }
       code_offset += invoke_stub_size;
     }
     DCHECK_CODE_OFFSET();
   }
-
   return code_offset;
 }
 
-OatWriter::~OatWriter() {
-  delete oat_header_;
-  STLDeleteElements(&oat_dex_files_);
-  STLDeleteElements(&oat_classes_);
-  STLDeleteElements(&oat_methods_);
-}
-
 OatWriter::OatDexFile::OatDexFile(const DexFile& dex_file) {
   const std::string& location = dex_file.GetLocation();
   dex_file_location_size_ = location.size();
   dex_file_location_data_ = reinterpret_cast<const uint8_t*>(location.data());
   dex_file_checksum_ = dex_file.GetHeader().checksum_;
+  classes_offset_ = 0;
 }
 
 size_t OatWriter::OatDexFile::SizeOf() const {