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 */);
}
diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc
index 7c4a6f7..afdc37c 100644
--- a/compiler/driver/compiler_driver.cc
+++ b/compiler/driver/compiler_driver.cc
@@ -1120,8 +1120,6 @@
if (target_method->dex_file == method->GetDeclaringClass()->GetDexCache()->GetDexFile()) {
target_method->dex_method_index = method->GetDexMethodIndex();
} else {
- // TODO: support patching from one dex file to another in the boot image.
- use_dex_cache = use_dex_cache || compiling_boot;
if (no_guarantee_of_dex_cache_entry) {
// See if the method is also declared in this dex cache.
uint32_t dex_method_idx = MethodHelper(method).FindDexMethodIndexInOtherDexFile(
@@ -1129,6 +1127,10 @@
if (dex_method_idx != DexFile::kDexNoIndex) {
target_method->dex_method_index = dex_method_idx;
} else {
+ if (compiling_boot) {
+ target_method->dex_method_index = method->GetDexMethodIndex();
+ target_method->dex_file = method->GetDeclaringClass()->GetDexCache()->GetDexFile();
+ }
must_use_direct_pointers = true;
}
}
@@ -1254,6 +1256,7 @@
uint32_t referrer_method_idx,
InvokeType referrer_invoke_type,
uint32_t target_method_idx,
+ const DexFile* target_dex_file,
InvokeType target_invoke_type,
size_t literal_offset) {
MutexLock mu(Thread::Current(), compiled_methods_lock_);
@@ -1262,6 +1265,7 @@
referrer_method_idx,
referrer_invoke_type,
target_method_idx,
+ target_dex_file,
target_invoke_type,
literal_offset));
}
@@ -1270,6 +1274,7 @@
uint32_t referrer_method_idx,
InvokeType referrer_invoke_type,
uint32_t target_method_idx,
+ const DexFile* target_dex_file,
InvokeType target_invoke_type,
size_t literal_offset,
int32_t pc_relative_offset) {
@@ -1279,6 +1284,7 @@
referrer_method_idx,
referrer_invoke_type,
target_method_idx,
+ target_dex_file,
target_invoke_type,
literal_offset,
pc_relative_offset));
@@ -1288,6 +1294,7 @@
uint32_t referrer_method_idx,
InvokeType referrer_invoke_type,
uint32_t target_method_idx,
+ const DexFile* target_dex_file,
InvokeType target_invoke_type,
size_t literal_offset) {
MutexLock mu(Thread::Current(), compiled_methods_lock_);
@@ -1296,6 +1303,7 @@
referrer_method_idx,
referrer_invoke_type,
target_method_idx,
+ target_dex_file,
target_invoke_type,
literal_offset));
}
diff --git a/compiler/driver/compiler_driver.h b/compiler/driver/compiler_driver.h
index 26210c9..e0f3a1a 100644
--- a/compiler/driver/compiler_driver.h
+++ b/compiler/driver/compiler_driver.h
@@ -323,6 +323,7 @@
uint32_t referrer_method_idx,
InvokeType referrer_invoke_type,
uint32_t target_method_idx,
+ const DexFile* target_dex_file,
InvokeType target_invoke_type,
size_t literal_offset)
LOCKS_EXCLUDED(compiled_methods_lock_);
@@ -331,6 +332,7 @@
uint32_t referrer_method_idx,
InvokeType referrer_invoke_type,
uint32_t target_method_idx,
+ const DexFile* target_dex_file,
InvokeType target_invoke_type,
size_t literal_offset,
int32_t pc_relative_offset)
@@ -340,6 +342,7 @@
uint32_t referrer_method_idx,
InvokeType referrer_invoke_type,
uint32_t target_method_idx,
+ const DexFile* target_dex_file,
InvokeType target_invoke_type,
size_t literal_offset)
LOCKS_EXCLUDED(compiled_methods_lock_);
@@ -456,6 +459,9 @@
uint32_t GetTargetMethodIdx() const {
return target_method_idx_;
}
+ const DexFile* GetTargetDexFile() const {
+ return target_dex_file_;
+ }
InvokeType GetTargetInvokeType() const {
return target_invoke_type_;
}
@@ -479,18 +485,21 @@
uint32_t referrer_method_idx,
InvokeType referrer_invoke_type,
uint32_t target_method_idx,
+ const DexFile* target_dex_file,
InvokeType target_invoke_type,
size_t literal_offset)
: PatchInformation(dex_file, referrer_class_def_idx,
referrer_method_idx, literal_offset),
referrer_invoke_type_(referrer_invoke_type),
target_method_idx_(target_method_idx),
+ target_dex_file_(target_dex_file),
target_invoke_type_(target_invoke_type) {
}
private:
const InvokeType referrer_invoke_type_;
const uint32_t target_method_idx_;
+ const DexFile* target_dex_file_;
const InvokeType target_invoke_type_;
friend class CompilerDriver;
@@ -512,12 +521,13 @@
uint32_t referrer_method_idx,
InvokeType referrer_invoke_type,
uint32_t target_method_idx,
+ const DexFile* target_dex_file,
InvokeType target_invoke_type,
size_t literal_offset,
int32_t pc_relative_offset)
: CallPatchInformation(dex_file, referrer_class_def_idx,
- referrer_method_idx, referrer_invoke_type,
- target_method_idx, target_invoke_type, literal_offset),
+ referrer_method_idx, referrer_invoke_type, target_method_idx,
+ target_dex_file, target_invoke_type, literal_offset),
offset_(pc_relative_offset) {
}
diff --git a/compiler/image_writer.cc b/compiler/image_writer.cc
index 8885652..5078182 100644
--- a/compiler/image_writer.cc
+++ b/compiler/image_writer.cc
@@ -757,20 +757,20 @@
SHARED_LOCKS_REQUIRED(Locks::mutator_lock_) {
ClassLinker* class_linker = Runtime::Current()->GetClassLinker();
Thread* self = Thread::Current();
- SirtRef<mirror::DexCache> dex_cache(self, class_linker->FindDexCache(patch->GetDexFile()));
+ SirtRef<mirror::DexCache> dex_cache(self, class_linker->FindDexCache(*patch->GetTargetDexFile()));
SirtRef<mirror::ClassLoader> class_loader(self, nullptr);
- ArtMethod* method = class_linker->ResolveMethod(patch->GetDexFile(),
+ ArtMethod* method = class_linker->ResolveMethod(*patch->GetTargetDexFile(),
patch->GetTargetMethodIdx(),
dex_cache,
class_loader,
NULL,
patch->GetTargetInvokeType());
CHECK(method != NULL)
- << patch->GetDexFile().GetLocation() << " " << patch->GetTargetMethodIdx();
+ << patch->GetTargetDexFile()->GetLocation() << " " << patch->GetTargetMethodIdx();
CHECK(!method->IsRuntimeMethod())
- << patch->GetDexFile().GetLocation() << " " << patch->GetTargetMethodIdx();
+ << patch->GetTargetDexFile()->GetLocation() << " " << patch->GetTargetMethodIdx();
CHECK(dex_cache->GetResolvedMethods()->Get(patch->GetTargetMethodIdx()) == method)
- << patch->GetDexFile().GetLocation() << " " << patch->GetReferrerMethodIdx() << " "
+ << patch->GetTargetDexFile()->GetLocation() << " " << patch->GetReferrerMethodIdx() << " "
<< PrettyMethod(dex_cache->GetResolvedMethods()->Get(patch->GetTargetMethodIdx())) << " "
<< PrettyMethod(method);
return method;
@@ -864,7 +864,7 @@
if (kIsDebugBuild) {
if (patch->IsCall()) {
const CompilerDriver::CallPatchInformation* cpatch = patch->AsCall();
- const DexFile::MethodId& id = cpatch->GetDexFile().GetMethodId(cpatch->GetTargetMethodIdx());
+ const DexFile::MethodId& id = cpatch->GetTargetDexFile()->GetMethodId(cpatch->GetTargetMethodIdx());
uint32_t expected = reinterpret_cast<uintptr_t>(&id) & 0xFFFFFFFF;
uint32_t actual = *patch_location;
CHECK(actual == expected || actual == value) << std::hex