Commit 9622c948 authored by Skylot's avatar Skylot

refactor: use mode flags instead ThreadLocal in type inference

parent baea5247
...@@ -89,6 +89,9 @@ public class TypeSearch { ...@@ -89,6 +89,9 @@ public class TypeSearch {
applySuccess = false; applySuccess = false;
} }
} }
if (!applySuccess) {
LOG.warn("Multi-variable search result apply rejected in {}", mth);
}
return applySuccess; return applySuccess;
} }
......
...@@ -31,11 +31,12 @@ import static jadx.core.dex.visitors.typeinference.TypeUpdateResult.SAME; ...@@ -31,11 +31,12 @@ import static jadx.core.dex.visitors.typeinference.TypeUpdateResult.SAME;
public final class TypeUpdate { public final class TypeUpdate {
private static final Logger LOG = LoggerFactory.getLogger(TypeUpdate.class); private static final Logger LOG = LoggerFactory.getLogger(TypeUpdate.class);
private static final TypeUpdateFlags FLAGS_EMPTY = new TypeUpdateFlags();
private static final TypeUpdateFlags FLAGS_WIDER = new TypeUpdateFlags().allowWider();
private final Map<InsnType, ITypeListener> listenerRegistry; private final Map<InsnType, ITypeListener> listenerRegistry;
private final TypeCompare comparator; private final TypeCompare comparator;
private ThreadLocal<Boolean> allowWider = new ThreadLocal<>();
public TypeUpdate(RootNode root) { public TypeUpdate(RootNode root) {
this.listenerRegistry = initListenerRegistry(); this.listenerRegistry = initListenerRegistry();
this.comparator = new TypeCompare(root); this.comparator = new TypeCompare(root);
...@@ -45,14 +46,22 @@ public final class TypeUpdate { ...@@ -45,14 +46,22 @@ public final class TypeUpdate {
* Perform recursive type checking and type propagation for all related variables * Perform recursive type checking and type propagation for all related variables
*/ */
public TypeUpdateResult apply(SSAVar ssaVar, ArgType candidateType) { public TypeUpdateResult apply(SSAVar ssaVar, ArgType candidateType) {
if (candidateType == null) { return apply(ssaVar, candidateType, FLAGS_EMPTY);
return REJECT; }
}
if (!candidateType.isTypeKnown()/* && ssaVar.getTypeInfo().getType().isTypeKnown() */) { /**
* Allow wider types for apply from debug info and some special cases
*/
public TypeUpdateResult applyWithWiderAllow(SSAVar ssaVar, ArgType candidateType) {
return apply(ssaVar, candidateType, FLAGS_WIDER);
}
private TypeUpdateResult apply(SSAVar ssaVar, ArgType candidateType, TypeUpdateFlags flags) {
if (candidateType == null || !candidateType.isTypeKnown()) {
return REJECT; return REJECT;
} }
TypeUpdateInfo updateInfo = new TypeUpdateInfo(); TypeUpdateInfo updateInfo = new TypeUpdateInfo(flags);
TypeUpdateResult result = updateTypeChecked(updateInfo, ssaVar.getAssign(), candidateType); TypeUpdateResult result = updateTypeChecked(updateInfo, ssaVar.getAssign(), candidateType);
if (result == REJECT) { if (result == REJECT) {
return result; return result;
...@@ -61,7 +70,7 @@ public final class TypeUpdate { ...@@ -61,7 +70,7 @@ public final class TypeUpdate {
if (updates.isEmpty()) { if (updates.isEmpty()) {
return SAME; return SAME;
} }
if (Consts.DEBUG && LOG.isDebugEnabled()) { if (Consts.DEBUG) {
LOG.debug("Applying types, init for {} -> {}", ssaVar, candidateType); LOG.debug("Applying types, init for {} -> {}", ssaVar, candidateType);
updates.forEach(updateEntry -> LOG.debug(" {} -> {}", updateEntry.getType(), updateEntry.getArg())); updates.forEach(updateEntry -> LOG.debug(" {} -> {}", updateEntry.getType(), updateEntry.getArg()));
} }
...@@ -69,18 +78,6 @@ public final class TypeUpdate { ...@@ -69,18 +78,6 @@ public final class TypeUpdate {
return CHANGED; return CHANGED;
} }
/**
* Allow wider types for apply from debug info and some special cases
*/
public TypeUpdateResult applyWithWiderAllow(SSAVar ssaVar, ArgType candidateType) {
try {
allowWider.set(true);
return apply(ssaVar, candidateType);
} finally {
allowWider.set(false);
}
}
private TypeUpdateResult updateTypeChecked(TypeUpdateInfo updateInfo, InsnArg arg, ArgType candidateType) { private TypeUpdateResult updateTypeChecked(TypeUpdateInfo updateInfo, InsnArg arg, ArgType candidateType) {
if (candidateType == null) { if (candidateType == null) {
throw new JadxRuntimeException("Null type update for arg: " + arg); throw new JadxRuntimeException("Null type update for arg: " + arg);
...@@ -100,13 +97,11 @@ public final class TypeUpdate { ...@@ -100,13 +97,11 @@ public final class TypeUpdate {
} }
return SAME; return SAME;
} }
if (compareResult.isWider()) { if (compareResult.isWider() && !updateInfo.getFlags().isAllowWider()) {
if (allowWider.get() != Boolean.TRUE) { if (Consts.DEBUG) {
if (Consts.DEBUG) { LOG.debug("Type rejected for {}: candidate={} is wider than current={}", arg, candidateType, currentType);
LOG.debug("Type rejected for {}: candidate={} is wider than current={}", arg, candidateType, currentType);
}
return REJECT;
} }
return REJECT;
} }
if (arg instanceof RegisterArg) { if (arg instanceof RegisterArg) {
RegisterArg reg = (RegisterArg) arg; RegisterArg reg = (RegisterArg) arg;
...@@ -278,7 +273,8 @@ public final class TypeUpdate { ...@@ -278,7 +273,8 @@ public final class TypeUpdate {
if (changeArg.getType().isTypeKnown()) { if (changeArg.getType().isTypeKnown()) {
// allow result to be wider // allow result to be wider
TypeCompareEnum compareTypes = comparator.compareTypes(candidateType, changeArg.getType()); TypeCompareEnum compareTypes = comparator.compareTypes(candidateType, changeArg.getType());
boolean correctType = assignChanged ? compareTypes.isWider() : compareTypes.isNarrow(); boolean correctType = compareTypes == TypeCompareEnum.EQUAL
|| (assignChanged ? compareTypes.isWider() : compareTypes.isNarrow());
if (correctType && inBounds(changeArg, candidateType)) { if (correctType && inBounds(changeArg, candidateType)) {
allowReject = true; allowReject = true;
} else { } else {
......
package jadx.core.dex.visitors.typeinference;
public class TypeUpdateFlags {
private boolean allowWider;
public TypeUpdateFlags allowWider() {
this.allowWider = true;
return this;
}
public boolean isAllowWider() {
return allowWider;
}
}
...@@ -7,8 +7,13 @@ import jadx.core.dex.instructions.args.ArgType; ...@@ -7,8 +7,13 @@ import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.InsnArg; import jadx.core.dex.instructions.args.InsnArg;
public class TypeUpdateInfo { public class TypeUpdateInfo {
private final TypeUpdateFlags flags;
private final List<TypeUpdateEntry> updates = new ArrayList<>(); private final List<TypeUpdateEntry> updates = new ArrayList<>();
public TypeUpdateInfo(TypeUpdateFlags flags) {
this.flags = flags;
}
public void requestUpdate(InsnArg arg, ArgType changeType) { public void requestUpdate(InsnArg arg, ArgType changeType) {
updates.add(new TypeUpdateEntry(arg, changeType)); updates.add(new TypeUpdateEntry(arg, changeType));
} }
...@@ -32,4 +37,8 @@ public class TypeUpdateInfo { ...@@ -32,4 +37,8 @@ public class TypeUpdateInfo {
public List<TypeUpdateEntry> getUpdates() { public List<TypeUpdateEntry> getUpdates() {
return updates; return updates;
} }
public TypeUpdateFlags getFlags() {
return flags;
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment