diff options
-rw-r--r-- | compiler/dex/quick/codegen_util.cc | 28 | ||||
-rw-r--r-- | compiler/dex/quick/mir_to_lir.h | 1 | ||||
-rw-r--r-- | compiler/driver/compiler_driver.cc | 34 |
3 files changed, 37 insertions, 26 deletions
diff --git a/compiler/dex/quick/codegen_util.cc b/compiler/dex/quick/codegen_util.cc index 6ccf252a14..256135df71 100644 --- a/compiler/dex/quick/codegen_util.cc +++ b/compiler/dex/quick/codegen_util.cc @@ -364,6 +364,18 @@ LIR* Mir2Lir::ScanLiteralPoolWide(LIR* data_target, int val_lo, int val_hi) { return NULL; } +/* Search the existing constants in the literal pool for an exact method match */ +LIR* Mir2Lir::ScanLiteralPoolMethod(LIR* data_target, const MethodReference& method) { + while (data_target) { + if (static_cast<uint32_t>(data_target->operands[0]) == method.dex_method_index && + UnwrapPointer(data_target->operands[1]) == method.dex_file) { + return data_target; + } + data_target = data_target->next; + } + return nullptr; +} + /* * The following are building blocks to insert constants into the pool or * instruction streams. @@ -1143,11 +1155,13 @@ void Mir2Lir::AddSlowPath(LIRSlowPath* slowpath) { 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); + LIR* data_target = ScanLiteralPoolMethod(code_literal_list_, target_method); if (data_target == NULL) { - data_target = AddWordData(&code_literal_list_, target_method_idx); + data_target = AddWordData(&code_literal_list_, target_method.dex_method_index); data_target->operands[1] = WrapPointer(const_cast<DexFile*>(target_method.dex_file)); + // NOTE: The invoke type doesn't contribute to the literal identity. In fact, we can have + // the same method invoked with kVirtual, kSuper and kInterface but the class linker will + // resolve these invokes to the same method, so we don't care which one we record here. data_target->operands[2] = type; } LIR* load_pc_rel = OpPcRelLoad(TargetReg(symbolic_reg), data_target); @@ -1157,11 +1171,13 @@ void Mir2Lir::LoadCodeAddress(const MethodReference& target_method, InvokeType t 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); + LIR* data_target = ScanLiteralPoolMethod(method_literal_list_, target_method); if (data_target == NULL) { - data_target = AddWordData(&method_literal_list_, target_method_idx); + data_target = AddWordData(&method_literal_list_, target_method.dex_method_index); data_target->operands[1] = WrapPointer(const_cast<DexFile*>(target_method.dex_file)); + // NOTE: The invoke type doesn't contribute to the literal identity. In fact, we can have + // the same method invoked with kVirtual, kSuper and kInterface but the class linker will + // resolve these invokes to the same method, so we don't care which one we record here. data_target->operands[2] = type; } LIR* load_pc_rel = OpPcRelLoad(TargetReg(symbolic_reg), data_target); diff --git a/compiler/dex/quick/mir_to_lir.h b/compiler/dex/quick/mir_to_lir.h index 3e0ba7517a..3584c33291 100644 --- a/compiler/dex/quick/mir_to_lir.h +++ b/compiler/dex/quick/mir_to_lir.h @@ -617,6 +617,7 @@ class Mir2Lir : public Backend { LIR* NewLIR5(int opcode, int dest, int src1, int src2, int info1, int info2); LIR* ScanLiteralPool(LIR* data_target, int value, unsigned int delta); LIR* ScanLiteralPoolWide(LIR* data_target, int val_lo, int val_hi); + LIR* ScanLiteralPoolMethod(LIR* data_target, const MethodReference& method); LIR* AddWordData(LIR* *constant_list_p, int value); LIR* AddWideData(LIR* *constant_list_p, int val_lo, int val_hi); void ProcessSwitchTables(); diff --git a/compiler/driver/compiler_driver.cc b/compiler/driver/compiler_driver.cc index 999d6a55a9..0f41d2b2f6 100644 --- a/compiler/driver/compiler_driver.cc +++ b/compiler/driver/compiler_driver.cc @@ -1152,28 +1152,22 @@ void CompilerDriver::GetCodeAndMethodForDirectCall(InvokeType* type, InvokeType *type = sharp_type; } } else { - if (compiling_boot) { + bool method_in_image = compiling_boot || + Runtime::Current()->GetHeap()->FindSpaceFromObject(method, false)->IsImageSpace(); + if (method_in_image) { + CHECK(!method->IsAbstract()); *type = sharp_type; - *direct_method = -1; - *direct_code = -1; + *direct_method = compiling_boot ? -1 : reinterpret_cast<uintptr_t>(method); + *direct_code = compiling_boot ? -1 : compiler_->GetEntryPointOf(method); + target_method->dex_file = method->GetDeclaringClass()->GetDexCache()->GetDexFile(); + target_method->dex_method_index = method->GetDexMethodIndex(); + } else if (!must_use_direct_pointers) { + // Set the code and rely on the dex cache for the method. + *type = sharp_type; + *direct_code = compiler_->GetEntryPointOf(method); } else { - bool method_in_image = - Runtime::Current()->GetHeap()->FindSpaceFromObject(method, false)->IsImageSpace(); - if (method_in_image) { - CHECK(!method->IsAbstract()); - *type = sharp_type; - *direct_method = reinterpret_cast<uintptr_t>(method); - *direct_code = compiler_->GetEntryPointOf(method); - target_method->dex_file = method->GetDeclaringClass()->GetDexCache()->GetDexFile(); - target_method->dex_method_index = method->GetDexMethodIndex(); - } else if (!must_use_direct_pointers) { - // Set the code and rely on the dex cache for the method. - *type = sharp_type; - *direct_code = compiler_->GetEntryPointOf(method); - } else { - // Direct pointers were required but none were available. - VLOG(compiler) << "Dex cache devirtualization failed for: " << PrettyMethod(method); - } + // Direct pointers were required but none were available. + VLOG(compiler) << "Dex cache devirtualization failed for: " << PrettyMethod(method); } } } |