refactor: use mode flags instead ThreadLocal in type inference

This commit is contained in:
Skylot
2019-05-11 22:49:10 +03:00
parent baea5247f4
commit 9622c948c9
4 changed files with 50 additions and 27 deletions
@@ -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 {
@@ -0,0 +1,15 @@
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;
}
}