Remove disable card marks, fix SetPatchLocation.

Should slightly improve performance. Added a no thread suspension allowed in patch oat code and
methods.

Added a new function to class linker, GetOatCodeFor which takes in a method reference instead of
pointer.

This fixes the issue where pruned methods were getting re-loaded during code and method patching.

Change-Id: I676bb88cb021b6d2e0db00adbcf1f2f04f82b72a
diff --git a/src/image_writer.cc b/src/image_writer.cc
index 497ca22..642cee6 100644
--- a/src/image_writer.cc
+++ b/src/image_writer.cc
@@ -99,14 +99,11 @@
     CheckNonImageClassesRemoved();
   }
 #endif
-  heap->DisableCardMarking();
-  {
-    Thread::Current()->TransitionFromSuspendedToRunnable();
-    CalculateNewObjectOffsets();
-    CopyAndFixupObjects();
-    PatchOatCodeAndMethods(compiler);
-    Thread::Current()->TransitionFromRunnableToSuspended(kNative);
-  }
+  Thread::Current()->TransitionFromSuspendedToRunnable();
+  CalculateNewObjectOffsets();
+  CopyAndFixupObjects();
+  PatchOatCodeAndMethods(compiler);
+  Thread::Current()->TransitionFromRunnableToSuspended(kNative);
 
   UniquePtr<File> file(OS::OpenFile(image_filename.c_str(), true));
   if (file.get() == NULL) {
@@ -192,7 +189,7 @@
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   // TODO: Check image spaces only?
   Heap* heap = Runtime::Current()->GetHeap();
-  ReaderMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
+  WriterMutexLock mu(Thread::Current(), *Locks::heap_bitmap_lock_);
   heap->FlushAllocStack();
   heap->GetLiveBitmap()->Walk(ComputeEagerResolvedStringsCallback, this);
 }
@@ -397,11 +394,8 @@
   image_end_ += RoundUp(sizeof(ImageHeader), 8); // 64-bit-alignment
 
   {
-    ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
+    WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
     heap->FlushAllocStack();
-  }
-
-  {
     // TODO: Image spaces only?
     // TODO: Add InOrderWalk to heap bitmap.
     const char* old = self->StartAssertNoThreadSuspension("ImageWriter");
@@ -434,7 +428,7 @@
   // TODO: heap validation can't handle this fix up pass
   heap->DisableObjectValidation();
   // TODO: Image spaces only?
-  ReaderMutexLock mu(self, *Locks::heap_bitmap_lock_);
+  WriterMutexLock mu(self, *Locks::heap_bitmap_lock_);
   heap->FlushAllocStack();
   heap->GetLiveBitmap()->Walk(CopyAndFixupObjectsCallback, this);
   self->EndAssertNoThreadSuspension(old_cause);
@@ -553,7 +547,7 @@
 void ImageWriter::FixupObjectArray(const ObjectArray<Object>* orig, ObjectArray<Object>* copy) {
   for (int32_t i = 0; i < orig->GetLength(); ++i) {
     const Object* element = orig->Get(i);
-    copy->SetWithoutChecks(i, GetImageAddress(element));
+    copy->SetPtrWithoutChecks(i, GetImageAddress(element));
   }
 }
 
@@ -587,7 +581,8 @@
       size_t right_shift = CLZ(ref_offsets);
       MemberOffset byte_offset = CLASS_OFFSET_FROM_CLZ(right_shift);
       const Object* ref = orig->GetFieldObject<const Object*>(byte_offset, false);
-      copy->SetFieldObject(byte_offset, GetImageAddress(ref), false);
+      // Use SetFieldPtr to avoid card marking since we are writing to the image.
+      copy->SetFieldPtr(byte_offset, GetImageAddress(ref), false);
       ref_offsets &= ~(CLASS_HIGH_BIT >> right_shift);
     }
   } else {
@@ -607,34 +602,13 @@
                         : klass->GetInstanceField(i));
         MemberOffset field_offset = field->GetOffset();
         const Object* ref = orig->GetFieldObject<const Object*>(field_offset, false);
-        copy->SetFieldObject(field_offset, GetImageAddress(ref), false);
+        // Use SetFieldPtr to avoid card marking since we are writing to the image.
+        copy->SetFieldPtr(field_offset, GetImageAddress(ref), false);
       }
     }
   }
 }
 
-static AbstractMethod* GetReferrerMethod(const Compiler::PatchInformation* patch)
-    SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-  ScopedObjectAccessUnchecked soa(Thread::Current());
-  ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  DexCache* dex_cache = class_linker->FindDexCache(patch->GetDexFile());
-  AbstractMethod* method = class_linker->ResolveMethod(patch->GetDexFile(),
-                                               patch->GetReferrerMethodIdx(),
-                                               dex_cache,
-                                               NULL,
-                                               NULL,
-                                               patch->GetReferrerInvokeType());
-  CHECK(method != NULL)
-    << patch->GetDexFile().GetLocation() << " " << patch->GetReferrerMethodIdx();
-  CHECK(!method->IsRuntimeMethod())
-    << patch->GetDexFile().GetLocation() << " " << patch->GetReferrerMethodIdx();
-  CHECK(dex_cache->GetResolvedMethods()->Get(patch->GetReferrerMethodIdx()) == method)
-    << patch->GetDexFile().GetLocation() << " " << patch->GetReferrerMethodIdx() << " "
-    << PrettyMethod(dex_cache->GetResolvedMethods()->Get(patch->GetReferrerMethodIdx())) << " "
-    << PrettyMethod(method);
-  return method;
-}
-
 static AbstractMethod* GetTargetMethod(const Compiler::PatchInformation* patch)
     SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
@@ -657,9 +631,12 @@
 }
 
 void ImageWriter::PatchOatCodeAndMethods(const Compiler& compiler) {
+  Thread* self = Thread::Current();
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
+  const char* old_cause = self->StartAssertNoThreadSuspension("ImageWriter");
 
-  const std::vector<const Compiler::PatchInformation*>& code_to_patch = compiler.GetCodeToPatch();
+  typedef std::vector<const Compiler::PatchInformation*> Patches;
+  const Patches& code_to_patch = compiler.GetCodeToPatch();
   for (size_t i = 0; i < code_to_patch.size(); i++) {
     const Compiler::PatchInformation* patch = code_to_patch[i];
     AbstractMethod* target = GetTargetMethod(patch);
@@ -669,8 +646,7 @@
     SetPatchLocation(patch, reinterpret_cast<uint32_t>(GetOatAddress(code_offset)));
   }
 
-  const std::vector<const Compiler::PatchInformation*>& methods_to_patch
-      = compiler.GetMethodsToPatch();
+  const Patches& methods_to_patch = compiler.GetMethodsToPatch();
   for (size_t i = 0; i < methods_to_patch.size(); i++) {
     const Compiler::PatchInformation* patch = methods_to_patch[i];
     AbstractMethod* target = GetTargetMethod(patch);
@@ -680,16 +656,16 @@
   // Update the image header with the new checksum after patching
   ImageHeader* image_header = reinterpret_cast<ImageHeader*>(image_->Begin());
   image_header->SetOatChecksum(oat_file_->GetOatHeader().GetChecksum());
+  self->EndAssertNoThreadSuspension(old_cause);
 }
 
 void ImageWriter::SetPatchLocation(const Compiler::PatchInformation* patch, uint32_t value) {
   ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
-  AbstractMethod* method = GetReferrerMethod(patch);
-  // Goodbye const, we are about to modify some code.
-  void* code = const_cast<void*>(class_linker->GetOatCodeFor(method));
+  const void* oat_code = class_linker->GetOatCodeFor(patch->GetDexFile(),
+                                                     patch->GetReferrerMethodIdx());
   OatHeader& oat_header = const_cast<OatHeader&>(oat_file_->GetOatHeader());
   // TODO: make this Thumb2 specific
-  uint8_t* base = reinterpret_cast<uint8_t*>(reinterpret_cast<uint32_t>(code) & ~0x1);
+  uint8_t* base = reinterpret_cast<uint8_t*>(reinterpret_cast<uint32_t>(oat_code) & ~0x1);
   uint32_t* patch_location = reinterpret_cast<uint32_t*>(base + patch->GetLiteralOffset());
 #ifndef NDEBUG
   const DexFile::MethodId& id = patch->GetDexFile().GetMethodId(patch->GetTargetMethodIdx());