未验证 提交 9ac9c052 编写于 作者: S Skylot

fix: simplify cascading casts (#1336)

上级 b7daf79b
......@@ -655,7 +655,7 @@ public abstract class ArgType {
if (from.equals(to)) {
return false;
}
TypeCompareEnum result = root.getTypeUpdate().getTypeCompare().compareTypes(from, to);
TypeCompareEnum result = root.getTypeCompare().compareTypes(from, to);
return !result.isNarrow();
}
......
......@@ -38,6 +38,7 @@ import jadx.core.dex.nodes.MethodNode;
import jadx.core.dex.nodes.RootNode;
import jadx.core.dex.regions.conditions.IfCondition;
import jadx.core.dex.visitors.shrink.CodeShrinkVisitor;
import jadx.core.dex.visitors.typeinference.TypeCompareEnum;
import jadx.core.utils.BlockUtils;
import jadx.core.utils.InsnList;
import jadx.core.utils.InsnRemover;
......@@ -82,7 +83,7 @@ public class SimplifyVisitor extends AbstractVisitor {
for (int i = 0; i < list.size(); i++) {
InsnNode insn = list.get(i);
int insnCount = list.size();
InsnNode modInsn = simplifyInsn(mth, insn);
InsnNode modInsn = simplifyInsn(mth, insn, null);
if (modInsn != null) {
modInsn.rebindArgs();
if (i < list.size() && list.get(i) == insn) {
......@@ -110,7 +111,7 @@ public class SimplifyVisitor extends AbstractVisitor {
for (InsnArg arg : insn.getArguments()) {
if (arg.isInsnWrap()) {
InsnNode wrapInsn = ((InsnWrapArg) arg).getWrapInsn();
InsnNode replaceInsn = simplifyInsn(mth, wrapInsn);
InsnNode replaceInsn = simplifyInsn(mth, wrapInsn, insn);
if (replaceInsn != null) {
arg.wrapInstruction(mth, replaceInsn);
InsnRemover.unbindInsn(mth, wrapInsn);
......@@ -123,7 +124,7 @@ public class SimplifyVisitor extends AbstractVisitor {
}
}
private InsnNode simplifyInsn(MethodNode mth, InsnNode insn) {
private InsnNode simplifyInsn(MethodNode mth, InsnNode insn, @Nullable InsnNode parentInsn) {
if (insn.contains(AFlag.DONT_GENERATE)) {
return null;
}
......@@ -146,8 +147,9 @@ public class SimplifyVisitor extends AbstractVisitor {
case SPUT:
return convertFieldArith(mth, insn);
case CAST:
case CHECK_CAST:
return processCast(mth, (IndexInsnNode) insn);
return processCast(mth, (IndexInsnNode) insn, parentInsn);
case MOVE:
InsnArg firstArg = insn.getArg(0);
......@@ -212,7 +214,7 @@ public class SimplifyVisitor extends AbstractVisitor {
return null;
}
private static InsnNode processCast(MethodNode mth, IndexInsnNode castInsn) {
private static InsnNode processCast(MethodNode mth, IndexInsnNode castInsn, @Nullable InsnNode parentInsn) {
if (castInsn.contains(AFlag.EXPLICIT_CAST)) {
return null;
}
......@@ -229,7 +231,8 @@ public class SimplifyVisitor extends AbstractVisitor {
ArgType castToType = (ArgType) castInsn.getIndex();
if (!ArgType.isCastNeeded(mth.root(), argType, castToType)
|| isCastDuplicate(castInsn)) {
|| isCastDuplicate(castInsn)
|| shadowedByOuterCast(mth.root(), castToType, parentInsn)) {
InsnNode insnNode = new InsnNode(InsnType.MOVE, 1);
insnNode.setOffset(castInsn.getOffset());
insnNode.setResult(castInsn.getResult());
......@@ -254,6 +257,15 @@ public class SimplifyVisitor extends AbstractVisitor {
return false;
}
private static boolean shadowedByOuterCast(RootNode root, ArgType castType, @Nullable InsnNode parentInsn) {
if (parentInsn != null && parentInsn.getType() == InsnType.CAST) {
ArgType parentCastType = (ArgType) ((IndexInsnNode) parentInsn).getIndex();
TypeCompareEnum result = root.getTypeCompare().compareTypes(parentCastType, castType);
return result.isNarrow();
}
return false;
}
/**
* Simplify 'cmp' instruction in if condition
*/
......
......@@ -98,6 +98,10 @@ public class TypeCompare {
|| secondPrimitiveType == PrimitiveType.BOOLEAN) {
return CONFLICT;
}
if (swapEquals(firstPrimitiveType, secondPrimitiveType, PrimitiveType.CHAR, PrimitiveType.BYTE)
|| swapEquals(firstPrimitiveType, secondPrimitiveType, PrimitiveType.CHAR, PrimitiveType.SHORT)) {
return CONFLICT;
}
return firstPrimitiveType.compareTo(secondPrimitiveType) > 0 ? WIDER : NARROW;
}
......@@ -105,6 +109,10 @@ public class TypeCompare {
return TypeCompareEnum.CONFLICT;
}
private boolean swapEquals(PrimitiveType first, PrimitiveType second, PrimitiveType a, PrimitiveType b) {
return (first == a && second == b) || (first == b && second == a);
}
private TypeCompareEnum compareArrayWithOtherType(ArgType array, ArgType other) {
if (!other.isTypeKnown()) {
if (other.contains(PrimitiveType.ARRAY)) {
......
......@@ -63,10 +63,15 @@ public class TypeCompareTest {
public void comparePrimitives() {
check(INT, UNKNOWN_OBJECT, TypeCompareEnum.CONFLICT);
check(INT, OBJECT, TypeCompareEnum.CONFLICT);
check(INT, BOOLEAN, TypeCompareEnum.CONFLICT);
check(INT, CHAR, TypeCompareEnum.WIDER);
check(INT, SHORT, TypeCompareEnum.WIDER);
check(BOOLEAN, INT, TypeCompareEnum.CONFLICT);
check(BOOLEAN, CHAR, TypeCompareEnum.CONFLICT);
check(CHAR, BYTE, TypeCompareEnum.CONFLICT);
check(CHAR, SHORT, TypeCompareEnum.CONFLICT);
firstIsNarrow(CHAR, NARROW_INTEGRAL);
firstIsNarrow(array(CHAR), UNKNOWN_OBJECT);
}
......
......@@ -31,6 +31,6 @@ public class TestInline2 extends IntegrationTest {
assertThat(code, containsOne("int[] a = {1, 2, 4, 6, 8};"));
assertThat(code, containsOne("for (int i = 0; i < a.length; i += 2) {"));
assertThat(code, containsOne("for (long i2 = (long) b; i2 > 0; i2--) {"));
assertThat(code, containsOne("for (long i2 = b; i2 > 0; i2--) {"));
}
}
......@@ -17,16 +17,24 @@ public class TestPrimitiveCasts extends IntegrationTest {
useByte((byte) getInt());
useChar((char) 0);
useChar((char) getInt());
useShort((short) 0L);
useShort((short) getLong());
useByte((byte) 0L);
useByte((byte) getLong());
useChar((char) 0L);
useChar((char) getLong());
useShort((short) ' ');
useShort((short) getChar());
useByte((byte) ' ');
useByte((byte) getChar());
useInt((byte) 7);
useInt((char) ' ');
useInt(getChar());
useInt((int) 2L);
useInt((int) getLong());
}
private long getLong() {
......@@ -49,6 +57,9 @@ public class TestPrimitiveCasts extends IntegrationTest {
private void useShort(short s) {
}
private void useInt(int i) {
}
}
@TestWithProfiles({ TestProfile.DX_J8, TestProfile.JAVA8 })
......@@ -56,6 +67,7 @@ public class TestPrimitiveCasts extends IntegrationTest {
noDebugInfo();
assertThat(getClassNode(TestCls.class))
.code()
.doesNotContain("(0)");
.doesNotContain("(0)")
.doesNotContain(") ((int) getLong())");
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册