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 {
applySuccess = false;
}
}
if (!applySuccess) {
LOG.warn("Multi-variable search result apply rejected in {}", mth);
}
return applySuccess;
}
......
......@@ -31,11 +31,12 @@ import static jadx.core.dex.visitors.typeinference.TypeUpdateResult.SAME;
public final class TypeUpdate {
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 TypeCompare comparator;
private ThreadLocal<Boolean> allowWider = new ThreadLocal<>();
public TypeUpdate(RootNode root) {
this.listenerRegistry = initListenerRegistry();
this.comparator = new TypeCompare(root);
......@@ -45,14 +46,22 @@ public final class TypeUpdate {
* Perform recursive type checking and type propagation for all related variables
*/
public TypeUpdateResult apply(SSAVar ssaVar, ArgType candidateType) {
if (candidateType == null) {
return REJECT;
}
if (!candidateType.isTypeKnown()/* && ssaVar.getTypeInfo().getType().isTypeKnown() */) {
return apply(ssaVar, candidateType, FLAGS_EMPTY);
}
/**
* 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;
}
TypeUpdateInfo updateInfo = new TypeUpdateInfo();
TypeUpdateInfo updateInfo = new TypeUpdateInfo(flags);
TypeUpdateResult result = updateTypeChecked(updateInfo, ssaVar.getAssign(), candidateType);
if (result == REJECT) {
return result;
......@@ -61,7 +70,7 @@ public final class TypeUpdate {
if (updates.isEmpty()) {
return SAME;
}
if (Consts.DEBUG && LOG.isDebugEnabled()) {
if (Consts.DEBUG) {
LOG.debug("Applying types, init for {} -> {}", ssaVar, candidateType);
updates.forEach(updateEntry -> LOG.debug(" {} -> {}", updateEntry.getType(), updateEntry.getArg()));
}
......@@ -69,18 +78,6 @@ public final class TypeUpdate {
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) {
if (candidateType == null) {
throw new JadxRuntimeException("Null type update for arg: " + arg);
......@@ -100,13 +97,11 @@ public final class TypeUpdate {
}
return SAME;
}
if (compareResult.isWider()) {
if (allowWider.get() != Boolean.TRUE) {
if (Consts.DEBUG) {
LOG.debug("Type rejected for {}: candidate={} is wider than current={}", arg, candidateType, currentType);
}
return REJECT;
if (compareResult.isWider() && !updateInfo.getFlags().isAllowWider()) {
if (Consts.DEBUG) {
LOG.debug("Type rejected for {}: candidate={} is wider than current={}", arg, candidateType, currentType);
}
return REJECT;
}
if (arg instanceof RegisterArg) {
RegisterArg reg = (RegisterArg) arg;
......@@ -278,7 +273,8 @@ public final class TypeUpdate {
if (changeArg.getType().isTypeKnown()) {
// allow result to be wider
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)) {
allowReject = true;
} 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;
import jadx.core.dex.instructions.args.InsnArg;
public class TypeUpdateInfo {
private final TypeUpdateFlags flags;
private final List<TypeUpdateEntry> updates = new ArrayList<>();
public TypeUpdateInfo(TypeUpdateFlags flags) {
this.flags = flags;
}
public void requestUpdate(InsnArg arg, ArgType changeType) {
updates.add(new TypeUpdateEntry(arg, changeType));
}
......@@ -32,4 +37,8 @@ public class TypeUpdateInfo {
public List<TypeUpdateEntry> getUpdates() {
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