Allow patching between dex files in the boot classpath.

Change-Id: I53f219a5382d0fcd580e96e50025fdad4fc399df
diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc
index 34d3834..d0ac8aa 100644
--- a/compiler/dex/quick/codegen_util.cc
+++ b/compiler/dex/quick/codegen_util.cc
@@ -409,46 +409,52 @@
   // Push code and method literals, record offsets for the compiler to patch.
   data_lir = code_literal_list_;
   while (data_lir != NULL) {
-    uint32_t target = data_lir->operands[0];
+    uint32_t target_method_idx = data_lir->operands[0];
+    const DexFile* target_dex_file =
+        reinterpret_cast<const DexFile*>(UnwrapPointer(data_lir->operands[1]));
     cu_->compiler_driver->AddCodePatch(cu_->dex_file,
                                        cu_->class_def_idx,
                                        cu_->method_idx,
                                        cu_->invoke_type,
-                                       target,
-                                       static_cast<InvokeType>(data_lir->operands[1]),
+                                       target_method_idx,
+                                       target_dex_file,
+                                       static_cast<InvokeType>(data_lir->operands[2]),
                                        code_buffer_.size());
-    const DexFile::MethodId& id = cu_->dex_file->GetMethodId(target);
+    const DexFile::MethodId& target_method_id = target_dex_file->GetMethodId(target_method_idx);
     // unique value based on target to ensure code deduplication works
-    PushPointer(code_buffer_, &id, cu_->target64);
+    PushPointer(code_buffer_, &target_method_id, cu_->target64);
     data_lir = NEXT_LIR(data_lir);
   }
   data_lir = method_literal_list_;
   while (data_lir != NULL) {
-    uint32_t target = data_lir->operands[0];
+    uint32_t target_method_idx = data_lir->operands[0];
+    const DexFile* target_dex_file =
+        reinterpret_cast<const DexFile*>(UnwrapPointer(data_lir->operands[1]));
     cu_->compiler_driver->AddMethodPatch(cu_->dex_file,
                                          cu_->class_def_idx,
                                          cu_->method_idx,
                                          cu_->invoke_type,
-                                         target,
-                                         static_cast<InvokeType>(data_lir->operands[1]),
+                                         target_method_idx,
+                                         target_dex_file,
+                                         static_cast<InvokeType>(data_lir->operands[2]),
                                          code_buffer_.size());
-    const DexFile::MethodId& id = cu_->dex_file->GetMethodId(target);
+    const DexFile::MethodId& target_method_id = target_dex_file->GetMethodId(target_method_idx);
     // unique value based on target to ensure code deduplication works
-    PushPointer(code_buffer_, &id, cu_->target64);
+    PushPointer(code_buffer_, &target_method_id, cu_->target64);
     data_lir = NEXT_LIR(data_lir);
   }
   // Push class literals.
   data_lir = class_literal_list_;
   while (data_lir != NULL) {
-    uint32_t target = data_lir->operands[0];
+    uint32_t target_method_idx = data_lir->operands[0];
     cu_->compiler_driver->AddClassPatch(cu_->dex_file,
                                         cu_->class_def_idx,
                                         cu_->method_idx,
-                                        target,
+                                        target_method_idx,
                                         code_buffer_.size());
-    const DexFile::TypeId& id = cu_->dex_file->GetTypeId(target);
+    const DexFile::TypeId& target_method_id = cu_->dex_file->GetTypeId(target_method_idx);
     // unique value based on target to ensure code deduplication works
-    PushPointer(code_buffer_, &id, cu_->target64);
+    PushPointer(code_buffer_, &target_method_id, cu_->target64);
     data_lir = NEXT_LIR(data_lir);
   }
 }
@@ -1197,22 +1203,28 @@
   slow_paths_.Insert(slowpath);
 }
 
-void Mir2Lir::LoadCodeAddress(int dex_method_index, InvokeType type, SpecialTargetRegister symbolic_reg) {
-  LIR* data_target = ScanLiteralPool(code_literal_list_, dex_method_index, 0);
+void Mir2Lir::LoadCodeAddress(const MethodReference& target_method, InvokeType type,
+                              SpecialTargetRegister symbolic_reg) {
+  int target_method_idx = target_method.dex_method_index;
+  LIR* data_target = ScanLiteralPool(code_literal_list_, target_method_idx, 0);
   if (data_target == NULL) {
-    data_target = AddWordData(&code_literal_list_, dex_method_index);
-    data_target->operands[1] = type;
+    data_target = AddWordData(&code_literal_list_, target_method_idx);
+    data_target->operands[1] = WrapPointer(const_cast<DexFile*>(target_method.dex_file));
+    data_target->operands[2] = type;
   }
   LIR* load_pc_rel = OpPcRelLoad(TargetReg(symbolic_reg), data_target);
   AppendLIR(load_pc_rel);
   DCHECK_NE(cu_->instruction_set, kMips) << reinterpret_cast<void*>(data_target);
 }
 
-void Mir2Lir::LoadMethodAddress(int dex_method_index, InvokeType type, SpecialTargetRegister symbolic_reg) {
-  LIR* data_target = ScanLiteralPool(method_literal_list_, dex_method_index, 0);
+void Mir2Lir::LoadMethodAddress(const MethodReference& target_method, InvokeType type,
+                                SpecialTargetRegister symbolic_reg) {
+  int target_method_idx = target_method.dex_method_index;
+  LIR* data_target = ScanLiteralPool(method_literal_list_, target_method_idx, 0);
   if (data_target == NULL) {
-    data_target = AddWordData(&method_literal_list_, dex_method_index);
-    data_target->operands[1] = type;
+    data_target = AddWordData(&method_literal_list_, target_method_idx);
+    data_target->operands[1] = WrapPointer(const_cast<DexFile*>(target_method.dex_file));
+    data_target->operands[2] = type;
   }
   LIR* load_pc_rel = OpPcRelLoad(TargetReg(symbolic_reg), data_target);
   AppendLIR(load_pc_rel);
diff --git a/compiler/dex/quick/gen_invoke.cc b/compiler/dex/quick/gen_invoke.cc
index 1907012..5ffaa90 100644
--- a/compiler/dex/quick/gen_invoke.cc
+++ b/compiler/dex/quick/gen_invoke.cc
@@ -386,14 +386,12 @@
           cg->LoadConstant(cg->TargetReg(kInvokeTgt), direct_code);
         }
       } else if (cu->instruction_set != kX86) {
-        CHECK_EQ(cu->dex_file, target_method.dex_file);
-        cg->LoadCodeAddress(target_method.dex_method_index, type, kInvokeTgt);
+        cg->LoadCodeAddress(target_method, type, kInvokeTgt);
       }
       if (direct_method != static_cast<unsigned int>(-1)) {
         cg->LoadConstant(cg->TargetReg(kArg0), direct_method);
       } else {
-        CHECK_EQ(cu->dex_file, target_method.dex_file);
-        cg->LoadMethodAddress(target_method.dex_method_index, type, kArg0);
+        cg->LoadMethodAddress(target_method, type, kArg0);
       }
       break;
     default:
@@ -413,9 +411,8 @@
         if (direct_code != static_cast<unsigned int>(-1)) {
           cg->LoadConstant(cg->TargetReg(kInvokeTgt), direct_code);
         } else if (cu->instruction_set != kX86) {
-          CHECK_EQ(cu->dex_file, target_method.dex_file);
           CHECK_LT(target_method.dex_method_index, target_method.dex_file->NumMethodIds());
-          cg->LoadCodeAddress(target_method.dex_method_index, type, kInvokeTgt);
+          cg->LoadCodeAddress(target_method, type, kInvokeTgt);
         }
       }
       break;
@@ -508,7 +505,6 @@
 
   switch (state) {
     case 0:  // Set target method index in case of conflict [set kHiddenArg, kHiddenFpArg (x86)]
-      CHECK_EQ(cu->dex_file, target_method.dex_file);
       CHECK_LT(target_method.dex_method_index, target_method.dex_file->NumMethodIds());
       cg->LoadConstant(cg->TargetReg(kHiddenArg), target_method.dex_method_index);
       if (cu->instruction_set == kX86) {
@@ -1457,8 +1453,7 @@
       if (method_info.DirectCode() == static_cast<uintptr_t>(-1)) {
         // We can have the linker fixup a call relative.
         call_inst =
-          reinterpret_cast<X86Mir2Lir*>(this)->CallWithLinkerFixup(
-              target_method.dex_method_index, info->type);
+          reinterpret_cast<X86Mir2Lir*>(this)->CallWithLinkerFixup(target_method, info->type);
       } else {
         call_inst = OpMem(kOpBlx, TargetReg(kArg0),
                           mirror::ArtMethod::EntryPointFromQuickCompiledCodeOffset().Int32Value());
diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h
index 6955577..9350677 100644
--- a/compiler/dex/quick/mir_to_lir.h
+++ b/compiler/dex/quick/mir_to_lir.h
@@ -751,22 +751,22 @@
 
     /*
      * @brief Load the address of the dex method into the register.
-     * @param dex_method_index The index of the method to be invoked.
+     * @param target_method The MethodReference of the method to be invoked.
      * @param type How the method will be invoked.
      * @param register that will contain the code address.
      * @note register will be passed to TargetReg to get physical register.
      */
-    void LoadCodeAddress(int dex_method_index, InvokeType type,
+    void LoadCodeAddress(const MethodReference& target_method, InvokeType type,
                          SpecialTargetRegister symbolic_reg);
 
     /*
      * @brief Load the Method* of a dex method into the register.
-     * @param dex_method_index The index of the method to be invoked.
+     * @param target_method The MethodReference of the method to be invoked.
      * @param type How the method will be invoked.
      * @param register that will contain the code address.
      * @note register will be passed to TargetReg to get physical register.
      */
-    virtual void LoadMethodAddress(int dex_method_index, InvokeType type,
+    virtual void LoadMethodAddress(const MethodReference& target_method, InvokeType type,
                                    SpecialTargetRegister symbolic_reg);
 
     /*
diff --git a/compiler/dex/quick/x86/codegen_x86.h b/compiler/dex/quick/x86/codegen_x86.h
index 7cc2c08..8269898 100644
--- a/compiler/dex/quick/x86/codegen_x86.h
+++ b/compiler/dex/quick/x86/codegen_x86.h
@@ -274,12 +274,12 @@
 
     /*
      * @brief Load the Method* of a dex method into the register.
-     * @param dex_method_index The index of the method to be invoked.
+     * @param target_method The MethodReference of the method to be invoked.
      * @param type How the method will be invoked.
      * @param register that will contain the code address.
      * @note register will be passed to TargetReg to get physical register.
      */
-    void LoadMethodAddress(int dex_method_index, InvokeType type,
+    void LoadMethodAddress(const MethodReference& target_method, InvokeType type,
                            SpecialTargetRegister symbolic_reg);
 
     /*
@@ -292,11 +292,11 @@
 
     /*
      * @brief Generate a relative call to the method that will be patched at link time.
-     * @param dex_method_index The index of the method to be invoked.
+     * @param target_method The MethodReference of the method to be invoked.
      * @param type How the method will be invoked.
      * @returns Call instruction
      */
-    LIR * CallWithLinkerFixup(int dex_method_index, InvokeType type);
+    LIR * CallWithLinkerFixup(const MethodReference& target_method, InvokeType type);
 
     /*
      * @brief Handle x86 specific literals
diff --git a/compiler/dex/quick/x86/target_x86.cc b/compiler/dex/quick/x86/target_x86.cc
index 083fccb..0c83731 100644
--- a/compiler/dex/quick/x86/target_x86.cc
+++ b/compiler/dex/quick/x86/target_x86.cc
@@ -832,19 +832,22 @@
   Mir2Lir::Materialize();
 }
 
-void X86Mir2Lir::LoadMethodAddress(int dex_method_index, InvokeType type,
+void X86Mir2Lir::LoadMethodAddress(const MethodReference& target_method, InvokeType type,
                                    SpecialTargetRegister symbolic_reg) {
   /*
    * For x86, just generate a 32 bit move immediate instruction, that will be filled
    * in at 'link time'.  For now, put a unique value based on target to ensure that
    * code deduplication works.
    */
-  const DexFile::MethodId& id = cu_->dex_file->GetMethodId(dex_method_index);
-  uintptr_t ptr = reinterpret_cast<uintptr_t>(&id);
+  int target_method_idx = target_method.dex_method_index;
+  const DexFile* target_dex_file = target_method.dex_file;
+  const DexFile::MethodId& target_method_id = target_dex_file->GetMethodId(target_method_idx);
+  uintptr_t target_method_id_ptr = reinterpret_cast<uintptr_t>(&target_method_id);
 
-  // Generate the move instruction with the unique pointer and save index and type.
+  // Generate the move instruction with the unique pointer and save index, dex_file, and type.
   LIR *move = RawLIR(current_dalvik_offset_, kX86Mov32RI, TargetReg(symbolic_reg),
-                     static_cast<int>(ptr), dex_method_index, type);
+                     static_cast<int>(target_method_id_ptr), target_method_idx,
+                     WrapPointer(const_cast<DexFile*>(target_dex_file)), type);
   AppendLIR(move);
   method_address_insns_.Insert(move);
 }
@@ -865,18 +868,20 @@
   class_type_address_insns_.Insert(move);
 }
 
-LIR *X86Mir2Lir::CallWithLinkerFixup(int dex_method_index, InvokeType type) {
+LIR *X86Mir2Lir::CallWithLinkerFixup(const MethodReference& target_method, InvokeType type) {
   /*
    * For x86, just generate a 32 bit call relative instruction, that will be filled
    * in at 'link time'.  For now, put a unique value based on target to ensure that
    * code deduplication works.
    */
-  const DexFile::MethodId& id = cu_->dex_file->GetMethodId(dex_method_index);
-  uintptr_t ptr = reinterpret_cast<uintptr_t>(&id);
+  int target_method_idx = target_method.dex_method_index;
+  const DexFile* target_dex_file = target_method.dex_file;
+  const DexFile::MethodId& target_method_id = target_dex_file->GetMethodId(target_method_idx);
+  uintptr_t target_method_id_ptr = reinterpret_cast<uintptr_t>(&target_method_id);
 
-  // Generate the call instruction with the unique pointer and save index and type.
-  LIR *call = RawLIR(current_dalvik_offset_, kX86CallI, static_cast<int>(ptr), dex_method_index,
-                     type);
+  // Generate the call instruction with the unique pointer and save index, dex_file, and type.
+  LIR *call = RawLIR(current_dalvik_offset_, kX86CallI, static_cast<int>(target_method_id_ptr),
+                     target_method_idx, WrapPointer(const_cast<DexFile*>(target_dex_file)), type);
   AppendLIR(call);
   call_method_insns_.Insert(call);
   return call;
@@ -892,13 +897,16 @@
   for (uint32_t i = 0; i < method_address_insns_.Size(); i++) {
       LIR* p = method_address_insns_.Get(i);
       DCHECK_EQ(p->opcode, kX86Mov32RI);
-      uint32_t target = p->operands[2];
+      uint32_t target_method_idx = p->operands[2];
+      const DexFile* target_dex_file =
+          reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[3]));
 
       // The offset to patch is the last 4 bytes of the instruction.
       int patch_offset = p->offset + p->flags.size - 4;
       cu_->compiler_driver->AddMethodPatch(cu_->dex_file, cu_->class_def_idx,
                                            cu_->method_idx, cu_->invoke_type,
-                                           target, static_cast<InvokeType>(p->operands[3]),
+                                           target_method_idx, target_dex_file,
+                                           static_cast<InvokeType>(p->operands[4]),
                                            patch_offset);
   }
 
@@ -906,25 +914,28 @@
   for (uint32_t i = 0; i < class_type_address_insns_.Size(); i++) {
       LIR* p = class_type_address_insns_.Get(i);
       DCHECK_EQ(p->opcode, kX86Mov32RI);
-      uint32_t target = p->operands[2];
+      uint32_t target_method_idx = p->operands[2];
 
       // The offset to patch is the last 4 bytes of the instruction.
       int patch_offset = p->offset + p->flags.size - 4;
       cu_->compiler_driver->AddClassPatch(cu_->dex_file, cu_->class_def_idx,
-                                          cu_->method_idx, target, patch_offset);
+                                          cu_->method_idx, target_method_idx, patch_offset);
   }
 
   // And now the PC-relative calls to methods.
   for (uint32_t i = 0; i < call_method_insns_.Size(); i++) {
       LIR* p = call_method_insns_.Get(i);
       DCHECK_EQ(p->opcode, kX86CallI);
-      uint32_t target = p->operands[1];
+      uint32_t target_method_idx = p->operands[1];
+      const DexFile* target_dex_file =
+          reinterpret_cast<const DexFile*>(UnwrapPointer(p->operands[2]));
 
       // The offset to patch is the last 4 bytes of the instruction.
       int patch_offset = p->offset + p->flags.size - 4;
       cu_->compiler_driver->AddRelativeCodePatch(cu_->dex_file, cu_->class_def_idx,
-                                                 cu_->method_idx, cu_->invoke_type, target,
-                                                 static_cast<InvokeType>(p->operands[2]),
+                                                 cu_->method_idx, cu_->invoke_type,
+                                                 target_method_idx, target_dex_file,
+                                                 static_cast<InvokeType>(p->operands[3]),
                                                  patch_offset, -4 /* offset */);
   }