use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.
the class TypeInferenceVisitor method insertSoftUseCast.
private boolean insertSoftUseCast(MethodNode mth, RegisterArg useArg) {
InsnNode useInsn = useArg.getParentInsn();
if (useInsn == null || useInsn.getType() == InsnType.PHI) {
return false;
}
if (useInsn.getType() == InsnType.IF && useInsn.getArg(1).isZeroLiteral()) {
// cast not needed if compare with null
return false;
}
BlockNode useBlock = BlockUtils.getBlockByInsn(mth, useInsn);
if (useBlock == null) {
return false;
}
RegisterArg newUseArg = useArg.duplicateWithNewSSAVar(mth);
useInsn.replaceArg(useArg, newUseArg);
IndexInsnNode castInsn = makeSoftCastInsn(newUseArg, useArg, useArg.getInitType());
return BlockUtils.insertBeforeInsn(useBlock, useInsn, castInsn);
}
use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.
the class BlockUtils method calcImmediatePostDominator.
@Nullable
public static BlockNode calcImmediatePostDominator(MethodNode mth, BlockNode block, Map<BlockNode, BitSet> postDomsMap) {
BlockNode oneSuccessor = Utils.getOne(block.getSuccessors());
if (oneSuccessor != null) {
return oneSuccessor;
}
List<BlockNode> basicBlocks = mth.getBasicBlocks();
BitSet postDoms = postDomsMap.get(block);
BitSet bs = copyBlocksBitSet(mth, postDoms);
for (int i = bs.nextSetBit(0); i >= 0; i = bs.nextSetBit(i + 1)) {
BlockNode pdomBlock = basicBlocks.get(i);
BitSet pdoms = postDomsMap.get(pdomBlock);
if (pdoms != null) {
bs.andNot(pdoms);
}
}
return bitSetToOneBlock(mth, bs);
}
use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.
the class LoopInfo method getExitNodes.
/**
* Return source blocks of exit edges. <br>
* Exit nodes belongs to loop (contains in {@code loopBlocks})
*/
public Set<BlockNode> getExitNodes() {
Set<BlockNode> nodes = new HashSet<>();
Set<BlockNode> blocks = getLoopBlocks();
for (BlockNode block : blocks) {
// exit: successor node not from this loop, (don't change to getCleanSuccessors)
for (BlockNode s : block.getSuccessors()) {
if (!blocks.contains(s) && !s.contains(AType.EXC_HANDLER)) {
nodes.add(block);
}
}
}
return nodes;
}
use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.
the class LoopRegionVisitor method checkIterableForEach.
private static boolean checkIterableForEach(MethodNode mth, LoopRegion loopRegion, IfCondition condition) {
List<RegisterArg> condArgs = condition.getRegisterArgs();
if (condArgs.size() != 1) {
return false;
}
RegisterArg iteratorArg = condArgs.get(0);
SSAVar sVar = iteratorArg.getSVar();
if (sVar == null || sVar.isUsedInPhi()) {
return false;
}
List<RegisterArg> itUseList = sVar.getUseList();
InsnNode assignInsn = iteratorArg.getAssignInsn();
if (itUseList.size() != 2) {
return false;
}
if (!checkInvoke(assignInsn, null, "iterator()Ljava/util/Iterator;")) {
return false;
}
InsnArg iterableArg = assignInsn.getArg(0);
InsnNode hasNextCall = itUseList.get(0).getParentInsn();
InsnNode nextCall = itUseList.get(1).getParentInsn();
if (!checkInvoke(hasNextCall, "java.util.Iterator", "hasNext()Z") || !checkInvoke(nextCall, "java.util.Iterator", "next()Ljava/lang/Object;")) {
return false;
}
List<InsnNode> toSkip = new LinkedList<>();
RegisterArg iterVar;
if (nextCall.contains(AFlag.WRAPPED)) {
InsnArg wrapArg = BlockUtils.searchWrappedInsnParent(mth, nextCall);
if (wrapArg != null && wrapArg.getParentInsn() != null) {
InsnNode parentInsn = wrapArg.getParentInsn();
BlockNode block = BlockUtils.getBlockByInsn(mth, parentInsn);
if (block == null) {
return false;
}
if (!RegionUtils.isRegionContainsBlock(loopRegion, block)) {
return false;
}
if (parentInsn.getType() == InsnType.CHECK_CAST) {
iterVar = parentInsn.getResult();
if (iterVar == null || !fixIterableType(mth, iterableArg, iterVar)) {
return false;
}
InsnArg castArg = BlockUtils.searchWrappedInsnParent(mth, parentInsn);
if (castArg != null && castArg.getParentInsn() != null) {
castArg.getParentInsn().replaceArg(castArg, iterVar);
} else {
// cast not inlined
toSkip.add(parentInsn);
}
} else {
iterVar = nextCall.getResult();
if (iterVar == null) {
return false;
}
// restore variable from inlined insn
iterVar.remove(AFlag.REMOVE);
nextCall.add(AFlag.DONT_GENERATE);
if (!fixIterableType(mth, iterableArg, iterVar)) {
return false;
}
parentInsn.replaceArg(wrapArg, iterVar);
}
} else {
LOG.warn(" checkIterableForEach: Wrapped insn not found: {}, mth: {}", nextCall, mth);
return false;
}
} else {
iterVar = nextCall.getResult();
if (iterVar == null) {
return false;
}
if (!usedOnlyInLoop(mth, loopRegion, iterVar)) {
return false;
}
if (!assignOnlyInLoop(mth, loopRegion, iterVar)) {
return false;
}
toSkip.add(nextCall);
}
assignInsn.add(AFlag.DONT_GENERATE);
assignInsn.getResult().add(AFlag.DONT_GENERATE);
for (InsnNode insnNode : toSkip) {
insnNode.add(AFlag.DONT_GENERATE);
}
for (RegisterArg itArg : itUseList) {
itArg.add(AFlag.DONT_GENERATE);
}
ForEachLoop forEachLoop = new ForEachLoop(iterVar, iterableArg);
forEachLoop.injectFakeInsns(loopRegion);
loopRegion.setType(forEachLoop);
return true;
}
use of jadx.core.dex.nodes.BlockNode in project jadx by skylot.
the class RegionMaker method addBreakLabel.
private void addBreakLabel(Edge exitEdge, BlockNode exit, InsnNode breakInsn) {
BlockNode outBlock = BlockUtils.getNextBlock(exitEdge.getTarget());
if (outBlock == null) {
return;
}
List<LoopInfo> exitLoop = mth.getAllLoopsForBlock(outBlock);
if (!exitLoop.isEmpty()) {
return;
}
List<LoopInfo> inLoops = mth.getAllLoopsForBlock(exitEdge.getSource());
if (inLoops.size() < 2) {
return;
}
// search for parent loop
LoopInfo parentLoop = null;
for (LoopInfo loop : inLoops) {
if (loop.getParentLoop() == null) {
parentLoop = loop;
break;
}
}
if (parentLoop == null) {
return;
}
if (parentLoop.getEnd() != exit && !parentLoop.getExitNodes().contains(exit)) {
LoopLabelAttr labelAttr = new LoopLabelAttr(parentLoop);
breakInsn.addAttr(labelAttr);
parentLoop.getStart().addAttr(labelAttr);
}
}
Aggregations