use of soot.jimple.SpecialInvokeExpr in project robovm by robovm.
the class MethodCompiler method invokeExpr.
private Value invokeExpr(Stmt stmt, InvokeExpr expr) {
SootMethodRef methodRef = expr.getMethodRef();
ArrayList<Value> args = new ArrayList<Value>();
args.add(env);
if (!(expr instanceof StaticInvokeExpr)) {
Value base = immediate(stmt, (Immediate) ((InstanceInvokeExpr) expr).getBase());
checkNull(stmt, base);
args.add(base);
}
int i = 0;
for (soot.Value sootArg : (List<soot.Value>) expr.getArgs()) {
Value arg = immediate(stmt, (Immediate) sootArg);
args.add(narrowFromI32Value(stmt, getType(methodRef.parameterType(i)), arg));
i++;
}
Value result = null;
FunctionRef functionRef = config.isDebug() ? null : Intrinsics.getIntrinsic(sootMethod, stmt, expr);
if (functionRef == null) {
Trampoline trampoline = null;
String targetClassName = getInternalName(methodRef.declaringClass());
String methodName = methodRef.name();
String methodDesc = getDescriptor(methodRef);
if (expr instanceof SpecialInvokeExpr) {
soot.Type runtimeType = ((SpecialInvokeExpr) expr).getBase().getType();
String runtimeClassName = runtimeType == NullType.v() ? targetClassName : getInternalName(runtimeType);
trampoline = new Invokespecial(this.className, targetClassName, methodName, methodDesc, runtimeClassName);
} else if (expr instanceof StaticInvokeExpr) {
trampoline = new Invokestatic(this.className, targetClassName, methodName, methodDesc);
} else if (expr instanceof VirtualInvokeExpr) {
soot.Type runtimeType = ((VirtualInvokeExpr) expr).getBase().getType();
String runtimeClassName = runtimeType == NullType.v() ? targetClassName : getInternalName(runtimeType);
trampoline = new Invokevirtual(this.className, targetClassName, methodName, methodDesc, runtimeClassName);
} else if (expr instanceof InterfaceInvokeExpr) {
trampoline = new Invokeinterface(this.className, targetClassName, methodName, methodDesc);
}
trampolines.add(trampoline);
if (canCallDirectly(expr)) {
SootMethod method = this.sootMethod.getDeclaringClass().getMethod(methodRef.name(), methodRef.parameterTypes(), methodRef.returnType());
if (method.isSynchronized()) {
functionRef = FunctionBuilder.synchronizedWrapper(method).ref();
} else {
functionRef = createMethodFunction(method).ref();
}
} else {
functionRef = trampoline.getFunctionRef();
}
}
result = call(stmt, functionRef, args.toArray(new Value[0]));
if (result != null) {
return widenToI32Value(stmt, result, methodRef.returnType().equals(CharType.v()));
} else {
return null;
}
}
use of soot.jimple.SpecialInvokeExpr in project robovm by robovm.
the class MethodCompiler method canCallDirectly.
private boolean canCallDirectly(InvokeExpr expr) {
if (expr instanceof InterfaceInvokeExpr) {
// Never possible
return false;
}
SootClass sootClass = this.sootMethod.getDeclaringClass();
SootMethodRef methodRef = expr.getMethodRef();
if (!methodRef.declaringClass().equals(sootClass)) {
return false;
}
try {
SootMethod method = sootClass.getMethod(methodRef.name(), methodRef.parameterTypes(), methodRef.returnType());
if (method.isAbstract()) {
return false;
}
/*
* The method exists and isn't abstract. Non virtual (invokespecial)
* as well as static calls and calls to final methods can be done directly.
*/
if (method.isStatic()) {
// want an exception to be thrown so we need a trampoline.
return expr instanceof StaticInvokeExpr;
}
if (expr instanceof SpecialInvokeExpr) {
return true;
}
if (expr instanceof VirtualInvokeExpr) {
// the method must be private
return Modifier.isFinal(sootClass.getModifiers()) || Modifier.isFinal(method.getModifiers()) || method.isPrivate();
}
return false;
} catch (RuntimeException e) {
// isn't declared in the class.
return false;
}
}
Aggregations