Revert "Revert "Allow preopted apps to have sharpened calls for non-x86 architectures.""

Should really say it allows pre-linked calls instead of sharpened calls.

Bug: 19100762
Change-Id: Ia2045a9eda92255e87a7f6187de18d6370b8f060
diff --git a/compiler/dex/quick/arm64/call_arm64.cc b/compiler/dex/quick/arm64/call_arm64.cc
index 6492442..d2204f5 100644
--- a/compiler/dex/quick/arm64/call_arm64.cc
+++ b/compiler/dex/quick/arm64/call_arm64.cc
@@ -400,9 +400,8 @@
 }
 
 static bool Arm64UseRelativeCall(CompilationUnit* cu, const MethodReference& target_method) {
-  UNUSED(cu, target_method);
-  // Always emit relative calls.
-  return true;
+  // Emit relative calls anywhere in the image or within a dex file otherwise.
+  return cu->compiler_driver->IsImage() || cu->dex_file == target_method.dex_file;
 }
 
 /*
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 2d8c9d4..b8a8936 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -1285,7 +1285,15 @@
     *stats_flags |= kFlagDirectCallToBoot | kFlagDirectMethodToBoot;
   }
   if (!use_dex_cache && force_relocations) {
-    if (!IsImage() || !IsImageClass(method->GetDeclaringClassDescriptor())) {
+    bool is_in_image;
+    if (IsImage()) {
+      is_in_image = IsImageClass(method->GetDeclaringClassDescriptor());
+    } else {
+      is_in_image = instruction_set_ != kX86 && instruction_set_ != kX86_64 &&
+                    Runtime::Current()->GetHeap()->FindSpaceFromObject(method->GetDeclaringClass(),
+                                                                       false)->IsImageSpace();
+    }
+    if (!is_in_image) {
       // We can only branch directly to Methods that are resolved in the DexCache.
       // Otherwise we won't invoke the resolution trampoline.
       use_dex_cache = true;
diff --git a/compiler/oat_writer.cc b/compiler/oat_writer.cc
index 3c36ffa..7516811 100644
--- a/compiler/oat_writer.cc
+++ b/compiler/oat_writer.cc
@@ -1103,10 +1103,18 @@
     if (UNLIKELY(target_offset == 0)) {
       mirror::ArtMethod* target = GetTargetMethod(patch);
       DCHECK(target != nullptr);
-      DCHECK_EQ(target->GetQuickOatCodeOffset(), 0u);
-      target_offset = target->IsNative()
-          ? writer_->oat_header_->GetQuickGenericJniTrampolineOffset()
-          : writer_->oat_header_->GetQuickToInterpreterBridgeOffset();
+      size_t size = GetInstructionSetPointerSize(writer_->compiler_driver_->GetInstructionSet());
+      const void* oat_code_offset = target->GetEntryPointFromQuickCompiledCodePtrSize(size);
+      if (oat_code_offset != 0) {
+        DCHECK(!Runtime::Current()->GetClassLinker()->IsQuickResolutionStub(oat_code_offset));
+        DCHECK(!Runtime::Current()->GetClassLinker()->IsQuickToInterpreterBridge(oat_code_offset));
+        DCHECK(!Runtime::Current()->GetClassLinker()->IsQuickGenericJniStub(oat_code_offset));
+        target_offset = PointerToLowMemUInt32(oat_code_offset);
+      } else {
+        target_offset = target->IsNative()
+            ? writer_->oat_header_->GetQuickGenericJniTrampolineOffset()
+            : writer_->oat_header_->GetQuickToInterpreterBridgeOffset();
+      }
     }
     return target_offset;
   }
@@ -1138,10 +1146,9 @@
 
   void PatchCodeAddress(std::vector<uint8_t>* code, uint32_t offset, uint32_t target_offset)
       SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
-    // NOTE: Direct calls across oat files don't use linker patches.
-    DCHECK(writer_->image_writer_ != nullptr);
-    uint32_t address = PointerToLowMemUInt32(writer_->image_writer_->GetOatFileBegin() +
-                                             writer_->oat_data_offset_ + target_offset);
+    uint32_t address = writer_->image_writer_ == nullptr ? target_offset :
+        PointerToLowMemUInt32(writer_->image_writer_->GetOatFileBegin() +
+                              writer_->oat_data_offset_ + target_offset);
     DCHECK_LE(offset + 4, code->size());
     uint8_t* data = &(*code)[offset];
     data[0] = address & 0xffu;