diff options
Diffstat (limited to 'compiler/dex/quick/codegen_util.cc')
-rw-r--r-- | compiler/dex/quick/codegen_util.cc | 28 |
1 files changed, 22 insertions, 6 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); |