use of jadx.api.plugins.input.data.IMethodProto in project jadx by skylot.
the class InvokeDecoder method decode.
@Override
public void decode(CodeDecodeState state) {
DataReader reader = state.reader();
int mthIdx = reader.readS2();
if (payloadSize == 4) {
reader.skip(2);
}
JavaInsnData insn = state.insn();
insn.setIndex(mthIdx);
boolean instanceCall;
IMethodProto mthProto;
if (apiOpcode == Opcode.INVOKE_CUSTOM) {
ICallSite callSite = insn.getIndexAsCallSite();
insn.setPayload(callSite);
mthProto = (IMethodProto) callSite.getValues().get(2).getValue();
// 'this' arg already included in proto args
instanceCall = false;
} else {
IMethodRef mthRef = insn.getIndexAsMethod();
mthRef.load();
insn.setPayload(mthRef);
mthProto = mthRef;
instanceCall = apiOpcode != Opcode.INVOKE_STATIC;
}
int argsCount = mthProto.getArgTypes().size();
if (instanceCall) {
argsCount++;
}
// allocate twice of the size for worst case
insn.setRegsCount(argsCount * 2);
int[] regs = insn.getRegsArray();
// calculate actual count of registers
// set '1' in regs to be filled with stack values later, '0' for skip
int regsCount = 0;
if (instanceCall) {
regs[regsCount++] = 1;
}
for (String type : mthProto.getArgTypes()) {
int size = getRegsCountForType(type);
regs[regsCount++] = 1;
if (size == 2) {
regs[regsCount++] = 0;
}
}
insn.setRegsCount(regsCount);
for (int i = regsCount - 1; i >= 0; i--) {
if (regs[i] == 1) {
state.pop(i);
}
}
String returnType = mthProto.getReturnType();
if (!returnType.equals("V")) {
insn.setResultReg(state.push(returnType));
} else {
insn.setResultReg(-1);
}
}
use of jadx.api.plugins.input.data.IMethodProto in project jadx by skylot.
the class CustomLambdaCall method buildMethodCall.
@NotNull
private static InvokeCustomNode buildMethodCall(MethodNode mth, InsnData insn, boolean isRange, List<EncodedValue> values, IMethodHandle callMthHandle) {
RootNode root = mth.root();
IMethodProto lambdaProto = (IMethodProto) values.get(2).getValue();
MethodInfo lambdaInfo = MethodInfo.fromMethodProto(root, mth.getParentClass().getClassInfo(), "", lambdaProto);
MethodHandleType methodHandleType = callMthHandle.getType();
InvokeCustomNode invokeCustomNode = new InvokeCustomNode(lambdaInfo, insn, false, isRange);
invokeCustomNode.setHandleType(methodHandleType);
ClassInfo implCls = ClassInfo.fromType(root, lambdaInfo.getReturnType());
String implName = (String) values.get(1).getValue();
IMethodProto implProto = (IMethodProto) values.get(3).getValue();
MethodInfo implMthInfo = MethodInfo.fromMethodProto(root, implCls, implName, implProto);
invokeCustomNode.setImplMthInfo(implMthInfo);
MethodInfo callMthInfo = MethodInfo.fromRef(root, callMthHandle.getMethodRef());
InvokeNode invokeNode = buildInvokeNode(methodHandleType, invokeCustomNode, callMthInfo);
if (methodHandleType == MethodHandleType.INVOKE_CONSTRUCTOR) {
ConstructorInsn ctrInsn = new ConstructorInsn(mth, invokeNode);
invokeCustomNode.setCallInsn(ctrInsn);
} else {
invokeCustomNode.setCallInsn(invokeNode);
}
MethodNode callMth = root.resolveMethod(callMthInfo);
if (callMth != null) {
invokeCustomNode.getCallInsn().addAttr(callMth);
if (callMth.getAccessFlags().isSynthetic() && callMth.getParentClass().equals(mth.getParentClass())) {
// inline only synthetic methods from same class
callMth.add(AFlag.DONT_GENERATE);
invokeCustomNode.setInlineInsn(true);
}
}
if (!invokeCustomNode.isInlineInsn()) {
IMethodProto effectiveMthProto = (IMethodProto) values.get(5).getValue();
List<ArgType> args = Utils.collectionMap(effectiveMthProto.getArgTypes(), ArgType::parse);
boolean sameArgs = args.equals(callMthInfo.getArgumentsTypes());
invokeCustomNode.setUseRef(sameArgs);
}
// prevent args inlining into not generated invoke custom node
for (InsnArg arg : invokeCustomNode.getArguments()) {
arg.add(AFlag.DONT_INLINE);
}
return invokeCustomNode;
}
Aggregations