use of jadx.core.dex.instructions.args.RegisterArg in project jadx by skylot.
the class CodeShrinker method shrinkBlock.
private static void shrinkBlock(MethodNode mth, BlockNode block) {
if (block.getInstructions().isEmpty()) {
return;
}
InsnList insnList = new InsnList(block.getInstructions());
int insnCount = insnList.size();
List<ArgsInfo> argsList = new ArrayList<ArgsInfo>(insnCount);
for (int i = 0; i < insnCount; i++) {
argsList.add(new ArgsInfo(insnList.get(i), argsList, i));
}
List<WrapInfo> wrapList = new ArrayList<WrapInfo>();
for (ArgsInfo argsInfo : argsList) {
List<RegisterArg> args = argsInfo.getArgs();
if (args.isEmpty()) {
continue;
}
ListIterator<RegisterArg> it = args.listIterator(args.size());
while (it.hasPrevious()) {
RegisterArg arg = it.previous();
// if (arg.getName() != null) {
// continue;
// }
SSAVar sVar = arg.getSVar();
// allow inline only one use arg or 'this'
if (sVar == null || sVar.getVariableUseCount() != 1 && !arg.isThis() || sVar.contains(AFlag.DONT_INLINE)) {
continue;
}
InsnNode assignInsn = sVar.getAssign().getParentInsn();
if (assignInsn == null || assignInsn.contains(AFlag.DONT_INLINE)) {
continue;
}
int assignPos = insnList.getIndex(assignInsn);
if (assignPos != -1) {
WrapInfo wrapInfo = argsInfo.checkInline(assignPos, arg);
if (wrapInfo != null) {
wrapList.add(wrapInfo);
}
} else {
// another block
BlockNode assignBlock = BlockUtils.getBlockByInsn(mth, assignInsn);
if (assignBlock != null && assignInsn != arg.getParentInsn() && canMoveBetweenBlocks(assignInsn, assignBlock, block, argsInfo.getInsn())) {
inline(arg, assignInsn, assignBlock);
}
}
}
}
if (!wrapList.isEmpty()) {
for (WrapInfo wrapInfo : wrapList) {
inline(wrapInfo.getArg(), wrapInfo.getInsn(), block);
}
}
}
use of jadx.core.dex.instructions.args.RegisterArg in project jadx by skylot.
the class ConstInlineVisitor method replaceConst.
private static boolean replaceConst(MethodNode mth, InsnNode constInsn, long literal) {
SSAVar sVar = constInsn.getResult().getSVar();
List<RegisterArg> use = new ArrayList<RegisterArg>(sVar.getUseList());
int replaceCount = 0;
for (RegisterArg arg : use) {
InsnNode useInsn = arg.getParentInsn();
if (useInsn == null || useInsn.getType() == InsnType.PHI || useInsn.getType() == InsnType.MERGE) {
continue;
}
LiteralArg litArg;
ArgType argType = arg.getType();
if (argType.isObject() && literal != 0) {
argType = ArgType.NARROW_NUMBERS;
}
if (use.size() == 1 || arg.isTypeImmutable()) {
// arg used only in one place
litArg = InsnArg.lit(literal, argType);
} else if (useInsn.getType() == InsnType.MOVE && !useInsn.getResult().getType().isTypeKnown()) {
// save type for 'move' instructions (hard to find type in chains of 'move')
litArg = InsnArg.lit(literal, argType);
} else {
// in most cases type not equal arg.getType()
// just set unknown type and run type fixer
litArg = InsnArg.lit(literal, ArgType.UNKNOWN);
}
if (useInsn.replaceArg(arg, litArg)) {
fixTypes(mth, useInsn, litArg);
replaceCount++;
if (useInsn.getType() == InsnType.RETURN) {
useInsn.setSourceLine(constInsn.getSourceLine());
}
FieldNode f = null;
ArgType litArgType = litArg.getType();
if (litArgType.isTypeKnown()) {
f = mth.getParentClass().getConstFieldByLiteralArg(litArg);
} else if (litArgType.contains(PrimitiveType.INT)) {
f = mth.getParentClass().getConstField((int) literal, false);
}
if (f != null) {
litArg.wrapInstruction(new IndexInsnNode(InsnType.SGET, f.getFieldInfo(), 0));
}
}
}
return replaceCount == use.size();
}
use of jadx.core.dex.instructions.args.RegisterArg in project jadx by skylot.
the class PhiInsn method removeArg.
@Override
public boolean removeArg(InsnArg arg) {
if (!(arg instanceof RegisterArg)) {
return false;
}
RegisterArg reg = (RegisterArg) arg;
if (super.removeArg(reg)) {
blockBinds.remove(reg);
InstructionRemover.fixUsedInPhiFlag(reg);
return true;
}
return false;
}
use of jadx.core.dex.instructions.args.RegisterArg in project jadx by skylot.
the class DebugInfoParser method merge.
private static void merge(InsnArg arg, LocalVar var) {
if (arg == null || !arg.isRegister()) {
return;
}
RegisterArg reg = (RegisterArg) arg;
if (var.getRegNum() != reg.getRegNum()) {
return;
}
boolean mergeRequired = false;
SSAVar ssaVar = reg.getSVar();
if (ssaVar != null) {
int ssaEnd = ssaVar.getEndAddr();
int ssaStart = ssaVar.getStartAddr();
int localStart = var.getStartAddr();
int localEnd = var.getEndAddr();
boolean isIntersected = !(localEnd < ssaStart || ssaEnd < localStart);
if (isIntersected && ssaEnd <= localEnd) {
mergeRequired = true;
}
} else {
mergeRequired = true;
}
if (mergeRequired) {
reg.mergeDebugInfo(var.getType(), var.getName());
}
}
use of jadx.core.dex.instructions.args.RegisterArg in project jadx by skylot.
the class IfMakerHelper method getNextIfNode.
private static BlockNode getNextIfNode(BlockNode block) {
if (block == null || block.contains(AType.LOOP) || block.contains(AFlag.SKIP)) {
return null;
}
List<InsnNode> insns = block.getInstructions();
if (insns.size() == 1 && insns.get(0).getType() == InsnType.IF) {
return block;
}
// skip this block and search in successors chain
List<BlockNode> successors = block.getSuccessors();
if (successors.size() != 1) {
return null;
}
BlockNode next = successors.get(0);
if (next.getPredecessors().size() != 1) {
return null;
}
boolean pass = true;
if (!insns.isEmpty()) {
// check that all instructions can be inlined
for (InsnNode insn : insns) {
RegisterArg res = insn.getResult();
if (res == null) {
pass = false;
break;
}
List<RegisterArg> useList = res.getSVar().getUseList();
if (useList.size() != 1) {
pass = false;
break;
}
InsnArg arg = useList.get(0);
InsnNode usePlace = arg.getParentInsn();
if (!BlockUtils.blockContains(block, usePlace) && !BlockUtils.blockContains(next, usePlace)) {
pass = false;
break;
}
}
}
if (pass) {
return getNextIfNode(next);
}
return null;
}
Aggregations