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 */);
}