diff options
| author | 2014-04-04 13:18:51 +0000 | |
|---|---|---|
| committer | 2014-04-04 13:18:52 +0000 | |
| commit | 09dfce73c4e849afda37035146dd2932220708d3 (patch) | |
| tree | 156c4e805e8f46c3e86d197313f92b0ea25d60c5 /compiler | |
| parent | 3734bffdf77e2bc293eb9722f9bd4389fbaa0d92 (diff) | |
| parent | b3e527b2a9ee28ecaba2045f4415b00c8b395039 (diff) | |
Merge "Clean up special method inlining."
Diffstat (limited to 'compiler')
| -rw-r--r-- | compiler/dex/local_value_numbering.cc | 14 | ||||
| -rw-r--r-- | compiler/dex/quick/dex_file_method_inliner.cc | 96 |
2 files changed, 66 insertions, 44 deletions
diff --git a/compiler/dex/local_value_numbering.cc b/compiler/dex/local_value_numbering.cc index 8dbc2bb9c3..c0068b2331 100644 --- a/compiler/dex/local_value_numbering.cc +++ b/compiler/dex/local_value_numbering.cc @@ -215,17 +215,13 @@ uint16_t LocalValueNumbering::GetValueNumber(MIR* mir) { case Instruction::CONST_STRING_JUMBO: case Instruction::CONST_CLASS: case Instruction::NEW_ARRAY: - if ((mir->optimization_flags & MIR_INLINED) == 0) { - // 1 result, treat as unique each time, use result s_reg - will be unique. - res = MarkNonAliasingNonNull(mir); - } + // 1 result, treat as unique each time, use result s_reg - will be unique. + res = MarkNonAliasingNonNull(mir); break; case Instruction::MOVE_RESULT_WIDE: - if ((mir->optimization_flags & MIR_INLINED) == 0) { - // 1 wide result, treat as unique each time, use result s_reg - will be unique. - res = GetOperandValueWide(mir->ssa_rep->defs[0]); - SetOperandValueWide(mir->ssa_rep->defs[0], res); - } + // 1 wide result, treat as unique each time, use result s_reg - will be unique. + res = GetOperandValueWide(mir->ssa_rep->defs[0]); + SetOperandValueWide(mir->ssa_rep->defs[0], res); break; case kMirOpPhi: diff --git a/compiler/dex/quick/dex_file_method_inliner.cc b/compiler/dex/quick/dex_file_method_inliner.cc index fa6de963a0..80a88b8eb5 100644 --- a/compiler/dex/quick/dex_file_method_inliner.cc +++ b/compiler/dex/quick/dex_file_method_inliner.cc @@ -47,6 +47,22 @@ MIR* AllocReplacementMIR(MIRGraph* mir_graph, MIR* invoke, MIR* move_return) { return insn; } +uint32_t GetInvokeReg(MIR* invoke, uint32_t arg) { + DCHECK_LT(arg, invoke->dalvikInsn.vA); + if (Instruction::FormatOf(invoke->dalvikInsn.opcode) == Instruction::k3rc) { + return invoke->dalvikInsn.vC + arg; // Non-range invoke. + } else { + DCHECK_EQ(Instruction::FormatOf(invoke->dalvikInsn.opcode), Instruction::k35c); + return invoke->dalvikInsn.arg[arg]; // Range invoke. + } +} + +bool WideArgIsInConsecutiveDalvikRegs(MIR* invoke, uint32_t arg) { + DCHECK_LT(arg + 1, invoke->dalvikInsn.vA); + return Instruction::FormatOf(invoke->dalvikInsn.opcode) == Instruction::k3rc || + invoke->dalvikInsn.arg[arg + 1u] == invoke->dalvikInsn.arg[arg] + 1u; +} + } // anonymous namespace const uint32_t DexFileMethodInliner::kIndexUnresolved; @@ -578,25 +594,24 @@ bool DexFileMethodInliner::GenInlineReturnArg(MIRGraph* mir_graph, BasicBlock* b // Select opcode and argument. const InlineReturnArgData& data = method.d.return_data; Instruction::Code opcode = Instruction::MOVE_FROM16; + uint32_t arg = GetInvokeReg(invoke, data.arg); if (move_result->dalvikInsn.opcode == Instruction::MOVE_RESULT_OBJECT) { DCHECK_EQ(data.is_object, 1u); + DCHECK_EQ(data.is_wide, 0u); opcode = Instruction::MOVE_OBJECT_FROM16; } else if (move_result->dalvikInsn.opcode == Instruction::MOVE_RESULT_WIDE) { DCHECK_EQ(data.is_wide, 1u); + DCHECK_EQ(data.is_object, 0u); opcode = Instruction::MOVE_WIDE_FROM16; + if (!WideArgIsInConsecutiveDalvikRegs(invoke, data.arg)) { + // The two halfs of the source value are not in consecutive dalvik registers in INVOKE. + return false; + } } else { DCHECK(move_result->dalvikInsn.opcode == Instruction::MOVE_RESULT); DCHECK_EQ(data.is_wide, 0u); DCHECK_EQ(data.is_object, 0u); } - DCHECK_LT(data.is_wide ? data.arg + 1u : data.arg, invoke->dalvikInsn.vA); - int arg; - if (Instruction::FormatOf(invoke->dalvikInsn.opcode) == Instruction::k35c) { - arg = invoke->dalvikInsn.arg[data.arg]; // Non-range invoke. - } else { - DCHECK_EQ(Instruction::FormatOf(invoke->dalvikInsn.opcode), Instruction::k3rc); - arg = invoke->dalvikInsn.vC + data.arg; // Range invoke. - } // Insert the move instruction MIR* insn = AllocReplacementMIR(mir_graph, invoke, move_result); @@ -616,33 +631,35 @@ bool DexFileMethodInliner::GenInlineIGet(MIRGraph* mir_graph, BasicBlock* bb, MI } const InlineIGetIPutData& data = method.d.ifield_data; - if (invoke->dalvikInsn.opcode == Instruction::INVOKE_STATIC || - invoke->dalvikInsn.opcode == Instruction::INVOKE_STATIC_RANGE || - data.object_arg != 0) { - // TODO: Implement inlining of IGET on non-"this" registers (needs correct stack trace for NPE). - return false; - } + Instruction::Code opcode = static_cast<Instruction::Code>(Instruction::IGET + data.op_variant); + DCHECK_EQ(InlineMethodAnalyser::IGetVariant(opcode), data.op_variant); + uint32_t object_reg = GetInvokeReg(invoke, data.object_arg); if (move_result == nullptr) { // Result is unused. If volatile, we still need to emit the IGET but we have no destination. return !data.is_volatile; } - Instruction::Code opcode = static_cast<Instruction::Code>(Instruction::IGET + data.op_variant); - DCHECK_EQ(InlineMethodAnalyser::IGetVariant(opcode), data.op_variant); + DCHECK_EQ(data.method_is_static != 0u, + invoke->dalvikInsn.opcode == Instruction::INVOKE_STATIC || + invoke->dalvikInsn.opcode == Instruction::INVOKE_STATIC_RANGE); + bool object_is_this = (data.method_is_static == 0u && data.object_arg == 0u); + if (!object_is_this) { + // TODO: Implement inlining of IGET on non-"this" registers (needs correct stack trace for NPE). + return false; + } + + if (object_is_this) { + // Mark invoke as NOP, null-check is done on IGET. No aborts after this. + invoke->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop); + } MIR* insn = AllocReplacementMIR(mir_graph, invoke, move_result); insn->width += insn->offset - invoke->offset; insn->offset = invoke->offset; insn->dalvikInsn.opcode = opcode; insn->dalvikInsn.vA = move_result->dalvikInsn.vA; - DCHECK_LT(data.object_arg, invoke->dalvikInsn.vA); - if (Instruction::FormatOf(invoke->dalvikInsn.opcode) == Instruction::k3rc) { - insn->dalvikInsn.vB = invoke->dalvikInsn.vC + data.object_arg; - } else { - DCHECK_EQ(Instruction::FormatOf(invoke->dalvikInsn.opcode), Instruction::k35c); - insn->dalvikInsn.vB = invoke->dalvikInsn.arg[data.object_arg]; - } + insn->dalvikInsn.vB = object_reg; mir_graph->ComputeInlineIFieldLoweringInfo(data.field_idx, invoke, insn); DCHECK(mir_graph->GetIFieldLoweringInfo(insn).IsResolved()); @@ -662,25 +679,34 @@ bool DexFileMethodInliner::GenInlineIPut(MIRGraph* mir_graph, BasicBlock* bb, MI } const InlineIGetIPutData& data = method.d.ifield_data; - if (invoke->dalvikInsn.opcode == Instruction::INVOKE_STATIC || - invoke->dalvikInsn.opcode == Instruction::INVOKE_STATIC_RANGE || - data.object_arg != 0) { + Instruction::Code opcode = static_cast<Instruction::Code>(Instruction::IPUT + data.op_variant); + DCHECK_EQ(InlineMethodAnalyser::IPutVariant(opcode), data.op_variant); + uint32_t object_reg = GetInvokeReg(invoke, data.object_arg); + uint32_t src_reg = GetInvokeReg(invoke, data.src_arg); + + if (opcode == Instruction::IPUT_WIDE && !WideArgIsInConsecutiveDalvikRegs(invoke, data.src_arg)) { + // The two halfs of the source value are not in consecutive dalvik registers in INVOKE. + return false; + } + + DCHECK_EQ(data.method_is_static != 0u, + invoke->dalvikInsn.opcode == Instruction::INVOKE_STATIC || + invoke->dalvikInsn.opcode == Instruction::INVOKE_STATIC_RANGE); + bool object_is_this = (data.method_is_static == 0u && data.object_arg == 0u); + if (!object_is_this) { // TODO: Implement inlining of IPUT on non-"this" registers (needs correct stack trace for NPE). return false; } - Instruction::Code opcode = static_cast<Instruction::Code>(Instruction::IPUT + data.op_variant); - DCHECK_EQ(InlineMethodAnalyser::IPutVariant(opcode), data.op_variant); + if (object_is_this) { + // Mark invoke as NOP, null-check is done on IPUT. No aborts after this. + invoke->dalvikInsn.opcode = static_cast<Instruction::Code>(kMirOpNop); + } MIR* insn = AllocReplacementMIR(mir_graph, invoke, nullptr); insn->dalvikInsn.opcode = opcode; - if (Instruction::FormatOf(invoke->dalvikInsn.opcode) == Instruction::k3rc) { - insn->dalvikInsn.vA = invoke->dalvikInsn.vC + data.src_arg; - insn->dalvikInsn.vB = invoke->dalvikInsn.vC + data.object_arg; - } else { - insn->dalvikInsn.vA = invoke->dalvikInsn.arg[data.src_arg]; - insn->dalvikInsn.vB = invoke->dalvikInsn.arg[data.object_arg]; - } + insn->dalvikInsn.vA = src_reg; + insn->dalvikInsn.vB = object_reg; mir_graph->ComputeInlineIFieldLoweringInfo(data.field_idx, invoke, insn); DCHECK(mir_graph->GetIFieldLoweringInfo(insn).IsResolved()); |