Be more precise about narrowing after an instance-of

Only do the additional narrowing when all predecessors of the instance-of
are equivalent move instructions.
This commit is contained in:
Ben Gruver 2016-10-16 13:45:30 -07:00
parent 22e85fc3ff
commit a6593575e7

View File

@ -1216,35 +1216,57 @@ public class MethodAnalyzer {
} }
AnalyzedInstruction prevAnalyzedInstruction = analyzedInstruction.getPredecessors().first(); AnalyzedInstruction prevAnalyzedInstruction = analyzedInstruction.getPredecessors().first();
if (prevAnalyzedInstruction.instruction.getOpcode() == Opcode.INSTANCE_OF) { if (prevAnalyzedInstruction.instruction.getOpcode() == Opcode.INSTANCE_OF) {
Instruction22c instanceOfInstruction = (Instruction22c)prevAnalyzedInstruction.instruction;
if (canNarrowAfterInstanceOf(prevAnalyzedInstruction, analyzedInstruction, classPath)) { if (canNarrowAfterInstanceOf(prevAnalyzedInstruction, analyzedInstruction, classPath)) {
List<Integer> narrowingRegisters = Lists.newArrayList(); List<Integer> narrowingRegisters = Lists.newArrayList();
RegisterType newType = RegisterType.getRegisterType(classPath, RegisterType newType = RegisterType.getRegisterType(classPath,
(TypeReference)((Instruction22c)prevAnalyzedInstruction.instruction).getReference()); (TypeReference)instanceOfInstruction.getReference());
if (instructionIndex > 1) { if (instructionIndex > 1) {
// If we have something like: // If we have something like:
// move-object/from16 v0, p1 // move-object/from16 v0, p1
// instance-of v2, v0, Lblah; // instance-of v2, v0, Lblah;
// if-eqz v2, :target // if-eqz v2, :target
// Then we need to narrow both v0 AND p1 // Then we need to narrow both v0 AND p1, but only if all predecessors of instance-of are a
AnalyzedInstruction prevPrevAnalyzedInstruction = // move-object for the same registers
analyzedInstructions.valueAt(instructionIndex - 2);
Opcode opcode = prevPrevAnalyzedInstruction.instruction.getOpcode(); int additionalNarrowingRegister = -1;
if (opcode == Opcode.MOVE_OBJECT || opcode == Opcode.MOVE_OBJECT_16 || for (AnalyzedInstruction prevPrevAnalyzedInstruction: prevAnalyzedInstruction.predecessors) {
opcode == Opcode.MOVE_OBJECT_FROM16) { Opcode opcode = prevPrevAnalyzedInstruction.instruction.getOpcode();
TwoRegisterInstruction moveInstruction = if (opcode == Opcode.MOVE_OBJECT || opcode == Opcode.MOVE_OBJECT_16 ||
((TwoRegisterInstruction)prevPrevAnalyzedInstruction.instruction); opcode == Opcode.MOVE_OBJECT_FROM16) {
RegisterType originalType = TwoRegisterInstruction moveInstruction =
prevPrevAnalyzedInstruction.getPostInstructionRegisterType( ((TwoRegisterInstruction)prevPrevAnalyzedInstruction.instruction);
moveInstruction.getRegisterB()); RegisterType originalType =
if (originalType.type != null) { prevPrevAnalyzedInstruction.getPostInstructionRegisterType(
if (isNarrowingConversion(originalType, newType)) { moveInstruction.getRegisterB());
narrowingRegisters.add( if (moveInstruction.getRegisterA() != instanceOfInstruction.getRegisterB()) {
((TwoRegisterInstruction)prevPrevAnalyzedInstruction.instruction).getRegisterB()); additionalNarrowingRegister = -1;
break;
} }
if (originalType.type == null) {
additionalNarrowingRegister = -1;
break;
}
if (isNarrowingConversion(originalType, newType)) {
if (additionalNarrowingRegister != -1) {
if (additionalNarrowingRegister != moveInstruction.getRegisterB()) {
additionalNarrowingRegister = -1;
break;
}
} else {
additionalNarrowingRegister = moveInstruction.getRegisterB();
}
}
} else {
additionalNarrowingRegister = -1;
break;
} }
} }
if (additionalNarrowingRegister != -1) {
narrowingRegisters.add(additionalNarrowingRegister);
}
} }
// Propagate the original type to the failing branch, and the new type to the successful branch // Propagate the original type to the failing branch, and the new type to the successful branch