Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Optimize/asmmethodsource loop unroll remove necessity to reverse #722

4 changes: 4 additions & 0 deletions sootup.core/src/main/java/sootup/core/jimple/Jimple.java
Original file line number Diff line number Diff line change
Expand Up @@ -349,6 +349,7 @@ public static JStaticInvokeExpr newStaticInvokeExpr(
return new JStaticInvokeExpr(method, args);
}

@Deprecated // use the version with List<Immediate> args instead
public static JStaticInvokeExpr newStaticInvokeExpr(MethodSignature method, Immediate... args) {
return newStaticInvokeExpr(method, Arrays.asList(args));
}
Expand All @@ -374,6 +375,7 @@ public static JSpecialInvokeExpr newSpecialInvokeExpr(
* Constructs a NewSpecialInvokeExpr(Local base, SootMethod method, List of Immediate) grammar
* chunk.
*/
@Deprecated // use the version with List<Immediate> args instead
public static JSpecialInvokeExpr newSpecialInvokeExpr(
Local base, MethodSignature method, Immediate... args) {
return newSpecialInvokeExpr(base, method, Arrays.asList(args));
Expand Down Expand Up @@ -427,6 +429,7 @@ public static JVirtualInvokeExpr newVirtualInvokeExpr(
* Constructs a NewVirtualInvokeExpr(Local base, SootMethod method, List of Immediate) grammar
* chunk.
*/
@Deprecated // use the version with List<Immediate> args instead
public static JVirtualInvokeExpr newVirtualInvokeExpr(
Local base, MethodSignature method, Immediate... args) {
return newVirtualInvokeExpr(base, method, Arrays.asList(args));
Expand Down Expand Up @@ -454,6 +457,7 @@ public static JInterfaceInvokeExpr newInterfaceInvokeExpr(
* Constructs a NewInterfaceInvokeExpr(Local base, SootMethod method, List of Immediate) grammar
* chunk.
*/
@Deprecated // use the version with List<Immediate> args instead
public static JInterfaceInvokeExpr newInterfaceInvokeExpr(
Local base, MethodSignature method, Immediate... args) {
return newInterfaceInvokeExpr(base, method, Arrays.asList(args));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,25 +21,12 @@
* #L%
*/

import static org.objectweb.asm.tree.AbstractInsnNode.FIELD_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.FRAME;
import static org.objectweb.asm.tree.AbstractInsnNode.IINC_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.INT_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.INVOKE_DYNAMIC_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.JUMP_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.LABEL;
import static org.objectweb.asm.tree.AbstractInsnNode.LDC_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.LINE;
import static org.objectweb.asm.tree.AbstractInsnNode.LOOKUPSWITCH_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.METHOD_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.MULTIANEWARRAY_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.TABLESWITCH_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.TYPE_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.VAR_INSN;
import static org.objectweb.asm.tree.AbstractInsnNode.*;

import com.google.common.base.Suppliers;
import com.google.common.collect.*;
import com.google.common.collect.HashBasedTable;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Table;
import java.util.*;
import java.util.Map.Entry;
import java.util.function.BiFunction;
Expand All @@ -55,37 +42,19 @@
import sootup.core.graph.MutableBlockStmtGraph;
import sootup.core.jimple.Jimple;
import sootup.core.jimple.basic.*;
import sootup.core.jimple.common.constant.DoubleConstant;
import sootup.core.jimple.common.constant.FloatConstant;
import sootup.core.jimple.common.constant.IntConstant;
import sootup.core.jimple.common.constant.LongConstant;
import sootup.core.jimple.common.constant.MethodHandle;
import sootup.core.jimple.common.constant.NullConstant;
import sootup.core.jimple.common.expr.AbstractBinopExpr;
import sootup.core.jimple.common.expr.AbstractConditionExpr;
import sootup.core.jimple.common.expr.AbstractInstanceInvokeExpr;
import sootup.core.jimple.common.expr.AbstractInvokeExpr;
import sootup.core.jimple.common.expr.AbstractUnopExpr;
import sootup.core.jimple.common.expr.Expr;
import sootup.core.jimple.common.expr.JAddExpr;
import sootup.core.jimple.common.expr.JCastExpr;
import sootup.core.jimple.common.expr.JDynamicInvokeExpr;
import sootup.core.jimple.common.expr.JInstanceOfExpr;
import sootup.core.jimple.common.expr.JNewArrayExpr;
import sootup.core.jimple.common.expr.JNewMultiArrayExpr;
import sootup.core.jimple.common.constant.*;
import sootup.core.jimple.common.expr.*;
import sootup.core.jimple.common.ref.*;
import sootup.core.jimple.common.stmt.*;
import sootup.core.jimple.javabytecode.stmt.JSwitchStmt;
import sootup.core.model.*;
import sootup.core.model.Body;
import sootup.core.model.FullPosition;
import sootup.core.model.MethodModifier;
import sootup.core.model.Position;
import sootup.core.signatures.FieldSignature;
import sootup.core.signatures.MethodSignature;
import sootup.core.transform.BodyInterceptor;
import sootup.core.types.ArrayType;
import sootup.core.types.ClassType;
import sootup.core.types.PrimitiveType;
import sootup.core.types.Type;
import sootup.core.types.UnknownType;
import sootup.core.types.VoidType;
import sootup.core.types.*;
import sootup.core.views.View;
import sootup.java.core.JavaIdentifierFactory;
import sootup.java.core.jimple.basic.JavaLocal;
Expand Down Expand Up @@ -1230,59 +1199,68 @@
MethodSignature methodSignature =
identifierFactory.getMethodSignature(cls, insn.name, returnType, sigTypes);
int nrArgs = sigTypes.size();
final Operand[] args;
List<Immediate> argList = Collections.emptyList();
if (!isInstance) {
args = nrArgs == 0 ? null : new Operand[nrArgs];
if (args != null) {
argList = new ArrayList<>(nrArgs);
}
} else {
args = new Operand[nrArgs + 1];
if (nrArgs != 0) {
argList = new ArrayList<>(nrArgs);
}
}
while (nrArgs-- != 0) {
args[nrArgs] = operandStack.popImmediate(sigTypes.get(nrArgs));
argList.add((Immediate) args[nrArgs].stackOrValue());
}
if (argList.size() > 1) {
Collections.reverse(argList);
}
if (isInstance) {
args[args.length - 1] = operandStack.popLocal();
}
final Operand[] operands;
AbstractInvokeExpr invoke;
if (!isInstance) {
invoke = Jimple.newStaticInvokeExpr(methodSignature, argList);
} else {
Operand baseOperand = args[args.length - 1];
if (isInstance) {
final List<Immediate> args;
if (nrArgs == 0) {
operands = new Operand[1];
args = Collections.emptyList();
} else {
Immediate[] argList = new Immediate[nrArgs];
operands = new Operand[nrArgs + 1];

while (nrArgs-- > 0) {
operands[nrArgs] = operandStack.popImmediate(sigTypes.get(nrArgs));
argList[nrArgs] = (Immediate) operands[nrArgs].stackOrValue();
}
args = Arrays.asList(argList);
}

final Operand baseOperand = operandStack.popLocal();
operands[operands.length - 1] = baseOperand;
Local base = (Local) baseOperand.stackOrValue();

AbstractInstanceInvokeExpr iinvoke;
switch (op) {
case INVOKESPECIAL:
iinvoke = Jimple.newSpecialInvokeExpr(base, methodSignature, argList);
invoke = Jimple.newSpecialInvokeExpr(base, methodSignature, args);
break;
case INVOKEVIRTUAL:
iinvoke = Jimple.newVirtualInvokeExpr(base, methodSignature, argList);
invoke = Jimple.newVirtualInvokeExpr(base, methodSignature, args);
break;
case INVOKEINTERFACE:
iinvoke = Jimple.newInterfaceInvokeExpr(base, methodSignature, argList);
invoke = Jimple.newInterfaceInvokeExpr(base, methodSignature, args);
break;
default:
throw new UnsupportedOperationException("Unknown invoke op:" + op);
}

invoke = iinvoke;
baseOperand.addUsageInExpr(invoke);

} else {
if (nrArgs == 0) {
operands = null;
invoke = Jimple.newStaticInvokeExpr(methodSignature, Collections.emptyList());

} else {

operands = new Operand[nrArgs];
Immediate[] argList = new Immediate[nrArgs];

do {
nrArgs--;
operands[nrArgs] = operandStack.popImmediate(sigTypes.get(nrArgs));
argList[nrArgs] = (Immediate) operands[nrArgs].stackOrValue();
} while (nrArgs > 0);

invoke = Jimple.newStaticInvokeExpr(methodSignature, Arrays.asList(argList));
}
}
if (args != null) {

if (operands != null) {
for (int i = 0; i < sigTypes.size(); i++) {
args[i].addUsageInExpr(invoke);
operands[i].addUsageInExpr(invoke);
}
frame.setIn(args);
frame.setIn(operands);
}
opr = new Operand(insn, invoke, this);
frame.setOut(opr);
Expand All @@ -1292,25 +1270,29 @@
List<Type> types = expr.getMethodSignature().getParameterTypes();
Operand[] oprs;
int nrArgs = types.size();
// TODO: check equivalent to isInstance?
assert (isInstance); // TODO: check equivalent to isInstance?
boolean isInstanceMethod = expr instanceof AbstractInstanceInvokeExpr;
if (!isInstanceMethod) {
oprs = nrArgs == 0 ? null : new Operand[nrArgs];
} else {
if (isInstanceMethod) {
oprs = new Operand[nrArgs + 1];
}
if (oprs != null) {
while (nrArgs-- != 0) {
oprs[nrArgs] = operandStack.pop(types.get(nrArgs));
}
if (isInstanceMethod) {
oprs[oprs.length - 1] = operandStack.pop();
}

oprs[oprs.length - 1] = operandStack.pop();
frame.mergeIn(currentLineNumber, oprs);
} else {
if (nrArgs > 0) {
oprs = new Operand[nrArgs];

Check warning on line 1284 in sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java

View check run for this annotation

Codecov / codecov/patch

sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java#L1284

Added line #L1284 was not covered by tests
do {
nrArgs--;
oprs[nrArgs] = operandStack.pop(types.get(nrArgs));

Check warning on line 1287 in sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java

View check run for this annotation

Codecov / codecov/patch

sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java#L1286-L1287

Added lines #L1286 - L1287 were not covered by tests
} while (nrArgs > 0);

frame.mergeIn(currentLineNumber, oprs);

Check warning on line 1290 in sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java

View check run for this annotation

Codecov / codecov/patch

sootup.java.bytecode/src/main/java/sootup/java/bytecode/frontend/AsmMethodSource.java#L1290

Added line #L1290 was not covered by tests
}
}
returnType = expr.getMethodSignature().getType();
}

if (AsmUtil.isDWord(returnType)) {
operandStack.pushDual(opr);
} else if (returnType != VoidType.getInstance()) {
Expand Down Expand Up @@ -1346,33 +1328,29 @@

// Generate parameters & returnType & parameterTypes
List<Type> types = AsmUtil.toJimpleSignatureDesc(insn.desc);
int nrArgs = types.size() - 1; // don't handle the return type here
List<Type> parameterTypes = new ArrayList<>(nrArgs);
List<Immediate> methodArgs = new ArrayList<>(nrArgs);
int nrArgs = types.size() - 1;
Type[] parameterTypes = new Type[nrArgs];
Immediate[] methodArgs = new Immediate[nrArgs];

Operand[] args = new Operand[nrArgs];
// Beware: Call stack is FIFO, Jimple is linear

for (int i = nrArgs - 1; i >= 0; i--) {
final Type type = types.get(i);
parameterTypes.add(type);
args[i] = operandStack.popImmediate(type);
methodArgs.add((Immediate) args[i].stackOrValue());
}
if (methodArgs.size() > 1) {
Collections.reverse(methodArgs); // Call stack is FIFO, Jimple is linear
Collections.reverse(parameterTypes);
parameterTypes[i] = types.get(i);
args[i] = operandStack.popImmediate(types.get(i));
methodArgs[i] = (Immediate) args[i].stackOrValue();
}
returnType = types.get(types.size() - 1);

// we always model invokeDynamic method refs as static method references
// of methods on the type SootClass.INVOKEDYNAMIC_DUMMY_CLASS_NAME
MethodSignature methodSig =
identifierFactory.getMethodSignature(bclass, insn.name, returnType, parameterTypes);
identifierFactory.getMethodSignature(
bclass, insn.name, returnType, Arrays.asList(parameterTypes));

JDynamicInvokeExpr indy =
Jimple.newDynamicInvokeExpr(
bsmMethodRef, bsmMethodArgs, methodSig, insn.bsm.getTag(), methodArgs);
bsmMethodRef, bsmMethodArgs, methodSig, insn.bsm.getTag(), Arrays.asList(methodArgs));
for (int i = 0; i < types.size() - 1; i++) {
args[i].addUsageInExpr(indy);
}
Expand Down