summaryrefslogtreecommitdiff
path: root/compiler
diff options
context:
space:
mode:
author Vladimir Marko <vmarko@google.com> 2014-04-04 13:18:51 +0000
committer Gerrit Code Review <noreply-gerritcodereview@google.com> 2014-04-04 13:18:52 +0000
commit09dfce73c4e849afda37035146dd2932220708d3 (patch)
tree156c4e805e8f46c3e86d197313f92b0ea25d60c5 /compiler
parent3734bffdf77e2bc293eb9722f9bd4389fbaa0d92 (diff)
parentb3e527b2a9ee28ecaba2045f4415b00c8b395039 (diff)
Merge "Clean up special method inlining."
Diffstat (limited to 'compiler')
-rw-r--r--compiler/dex/local_value_numbering.cc14
-rw-r--r--compiler/dex/quick/dex_file_method_inliner.cc96
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());