diff options
author | Ben Gruver <bgruv@google.com> | 2016-10-16 13:45:30 -0700 |
---|---|---|
committer | Ben Gruver <bgruv@google.com> | 2016-10-16 13:45:30 -0700 |
commit | a6593575e71a9cccf2d9711b774223aca12c22df (patch) | |
tree | 9949478247d8b9a5fb32d463f3a046266e93eed9 | |
parent | 22e85fc3ff3d85e8a30fc42438ccb942fc5d80df (diff) | |
download | smali-a6593575e71a9cccf2d9711b774223aca12c22df.tar.gz |
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.
-rw-r--r-- | dexlib2/src/main/java/org/jf/dexlib2/analysis/MethodAnalyzer.java | 52 |
1 files changed, 37 insertions, 15 deletions
diff --git a/dexlib2/src/main/java/org/jf/dexlib2/analysis/MethodAnalyzer.java b/dexlib2/src/main/java/org/jf/dexlib2/analysis/MethodAnalyzer.java index 0da57f16..0c073b39 100644 --- a/dexlib2/src/main/java/org/jf/dexlib2/analysis/MethodAnalyzer.java +++ b/dexlib2/src/main/java/org/jf/dexlib2/analysis/MethodAnalyzer.java @@ -1216,35 +1216,57 @@ public class MethodAnalyzer { } AnalyzedInstruction prevAnalyzedInstruction = analyzedInstruction.getPredecessors().first(); if (prevAnalyzedInstruction.instruction.getOpcode() == Opcode.INSTANCE_OF) { + Instruction22c instanceOfInstruction = (Instruction22c)prevAnalyzedInstruction.instruction; if (canNarrowAfterInstanceOf(prevAnalyzedInstruction, analyzedInstruction, classPath)) { List<Integer> narrowingRegisters = Lists.newArrayList(); RegisterType newType = RegisterType.getRegisterType(classPath, - (TypeReference)((Instruction22c)prevAnalyzedInstruction.instruction).getReference()); + (TypeReference)instanceOfInstruction.getReference()); if (instructionIndex > 1) { // If we have something like: // move-object/from16 v0, p1 // instance-of v2, v0, Lblah; // if-eqz v2, :target - // Then we need to narrow both v0 AND p1 - AnalyzedInstruction prevPrevAnalyzedInstruction = - analyzedInstructions.valueAt(instructionIndex - 2); - Opcode opcode = prevPrevAnalyzedInstruction.instruction.getOpcode(); - if (opcode == Opcode.MOVE_OBJECT || opcode == Opcode.MOVE_OBJECT_16 || - opcode == Opcode.MOVE_OBJECT_FROM16) { - TwoRegisterInstruction moveInstruction = - ((TwoRegisterInstruction)prevPrevAnalyzedInstruction.instruction); - RegisterType originalType = - prevPrevAnalyzedInstruction.getPostInstructionRegisterType( - moveInstruction.getRegisterB()); - if (originalType.type != null) { + // Then we need to narrow both v0 AND p1, but only if all predecessors of instance-of are a + // move-object for the same registers + + int additionalNarrowingRegister = -1; + for (AnalyzedInstruction prevPrevAnalyzedInstruction: prevAnalyzedInstruction.predecessors) { + Opcode opcode = prevPrevAnalyzedInstruction.instruction.getOpcode(); + if (opcode == Opcode.MOVE_OBJECT || opcode == Opcode.MOVE_OBJECT_16 || + opcode == Opcode.MOVE_OBJECT_FROM16) { + TwoRegisterInstruction moveInstruction = + ((TwoRegisterInstruction)prevPrevAnalyzedInstruction.instruction); + RegisterType originalType = + prevPrevAnalyzedInstruction.getPostInstructionRegisterType( + moveInstruction.getRegisterB()); + if (moveInstruction.getRegisterA() != instanceOfInstruction.getRegisterB()) { + additionalNarrowingRegister = -1; + break; + } + if (originalType.type == null) { + additionalNarrowingRegister = -1; + break; + } if (isNarrowingConversion(originalType, newType)) { - narrowingRegisters.add( - ((TwoRegisterInstruction)prevPrevAnalyzedInstruction.instruction).getRegisterB()); + 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 |