public boolean _inlineTokenMethodsIn(SootMethod method, JimpleBody body,
Unit unit, ValueBox box, SimpleLocalDefs localDefs,
SimpleLocalUses localUses, TypeSpecializerAnalysis typeAnalysis,
int depth, Set unsafeLocalSet, boolean debug) {
Hierarchy hierarchy = Scene.v().getActiveHierarchy();
boolean doneSomething = false;
Value value = box.getValue();
// If we have a call to evaluateParseTree, then we can't
// inline any of those locals. This sucks, but I can't think
// of a better way to statically determine the value of the
// token. In some cases, this doesn't work because things are
// inlined on an unsafe local before we know it is unsafe!
if (value instanceof InvokeExpr) {
InvokeExpr r = (InvokeExpr) value;
if (unit instanceof AssignStmt
&& r.getMethod().getName().equals("evaluateParseTree")) {
AssignStmt stmt = (AssignStmt) unit;
unsafeLocalSet.add(stmt.getLeftOp());
unsafeLocalSet.addAll(_computeTokenLocalsDefinedFrom(localUses,
stmt));
if (debug) {
System.out.println("unsafeLocalSet = " + unsafeLocalSet);
}
}
}
if (value instanceof VirtualInvokeExpr
|| value instanceof InterfaceInvokeExpr
|| value instanceof SpecialInvokeExpr) {
InstanceInvokeExpr r = (InstanceInvokeExpr) value;
Local local = (Local) r.getBase();
Type baseType = local.getType();
if (baseType instanceof NullType) {
// replace with NullPointerException..
if (debug) {
System.out.println("Invoke base is null, replacing with "
+ "NullPointerException");
}
Local exception = SootUtilities.createRuntimeException(body,
unit, "NullPointerException");
body.getUnits().insertBefore(
Jimple.v().newThrowStmt(exception), unit);
body.getUnits().remove(unit);
}
boolean isInlineableTokenMethod = _isLocalTokenTypeWithDepth(local,
typeAnalysis, unsafeLocalSet, depth, debug);
if (debug) {
System.out.println("checking inline for " + r);
}
// Check if token arguments are being used. This makes
// sure we get methods like Scale._scaleOnRight and
// DB._doFunction inlined. It would be better if the
// token inliner modified the functions, but it doesn't.
if (baseType instanceof RefType
&& Scene.v().getApplicationClasses().contains(
((RefType) baseType).getSootClass())) {
Type returnType = r.getMethod().getReturnType();
isInlineableTokenMethod |= _isInlineableTokenType(returnType);
for (Iterator args = r.getArgs().iterator(); args.hasNext()
&& !isInlineableTokenMethod;) {
Object arg = args.next();
if (arg instanceof Local) {
Local argLocal = (Local) arg;
if (debug) {
System.out.println("argtype = "
+ argLocal.getType());
}
isInlineableTokenMethod = _isLocalTokenTypeWithDepth(
argLocal, typeAnalysis, unsafeLocalSet, depth,
debug);
if (debug) {
System.out.println("isInlineableTokenMethod = "
+ isInlineableTokenMethod);
}
}
}
}
if (!isInlineableTokenMethod) {
return false;
}
// System.out.println("baseType = " + baseType);
RefType type = (RefType) typeAnalysis.getSpecializedSootType(local);
// System.out.println("specializedType = " + type);
// Then determine the method that was
// actually invoked.
List methodList;
if (value instanceof SpecialInvokeExpr) {
SootMethod targetMethod = hierarchy.resolveSpecialDispatch(
(SpecialInvokeExpr) r, method);
methodList = new LinkedList();
methodList.add(targetMethod);
} else {
methodList =
// invokeGraph.getTargetsOf((Stmt)unit);
hierarchy.resolveAbstractDispatch(type.getSootClass(), r
.getMethod());
}
// If there was only one possible method...
if (methodList.size() == 1) {
// Then inline its code
SootMethod inlinee = (SootMethod) methodList.get(0);
if (inlinee.getName().equals("getClass")) {
SootClass typeClass = type.getSootClass();
int subclasses = hierarchy.getSubclassesOf(typeClass)
.size();
if (subclasses == 0) {
// FIXME: do something better here.
SootMethod newGetClassMethod = Scene.v().getMethod(
"<java.lang.Class: java.lang.Class "
+ "forName(java.lang.String)>");
box.setValue(Jimple.v().newStaticInvokeExpr(
newGetClassMethod.makeRef(),
StringConstant.v(typeClass.getName())));
doneSomething = true;
}
} else if (inlinee.getName().equals("isNil")) {
box.setValue(IntConstant.v(0));
// } else if (inlinee.getSignature().equals(PtolemyUtilities.arrayTokenConstructor.getSignature())) {
// System.out.println("method = " + method);
// System.out.println("inlinee = " + inlinee.getSignature());
// throw new RuntimeException("Cannot inline arrayTokens that do not have a type explicitly specified.");
} else {
SootClass declaringClass = inlinee.getDeclaringClass();
if (!declaringClass.isApplicationClass()) {
declaringClass.setLibraryClass();
}
if (!inlinee.isAbstract() && !inlinee.isNative()) {
// FIXME: only inline things where we are
// also inlining the constructor???
if (debug) {
System.out.println("inlining " + inlinee);
}
inlinee.retrieveActiveBody();
// Then we know exactly what method will
// be called, so inline it.
SiteInliner.inlineSite(inlinee, (Stmt) unit, method);
doneSomething = true;
} else {
throw new RuntimeException("inlinee is not concrete!: "
+ inlinee);
}
}
} else {
if (debug) {
System.out.println("uninlinable method invocation = " + r);
for (Iterator j = methodList.iterator(); j.hasNext();) {
System.out.println("method = " + j.next());
}
}
}
} else if (value instanceof SpecialInvokeExpr) {
SpecialInvokeExpr r = (SpecialInvokeExpr) value;
if (debug) {
System.out.println("special invoking = " + r.getMethod());
}
Type baseType = typeAnalysis.getSpecializedSootType((Local) r
.getBase());
if (baseType instanceof RefType) {
RefType type = (RefType) baseType;
boolean isInlineableTokenMethod = SootUtilities.derivesFrom(
type.getSootClass(), PtolemyUtilities.tokenClass);
// If it is a token, then check to
// make sure that it has the
// appropriate type
if (isInlineableTokenMethod) {
type = (RefType) typeAnalysis
.getSpecializedSootType((Local) r.getBase());
if (PtolemyUtilities.getTypeDepth(typeAnalysis
.getSpecializedType((Local) r.getBase())) != depth) {
if (debug) {
System.out
.println("skipping, type depth = "
+ PtolemyUtilities
.getTypeDepth(typeAnalysis
.getSpecializedType((Local) r
.getBase()))
+ ", but only inlining depth "
+ depth);
}
return false;
//continue;
}
}
if (isInlineableTokenMethod) {
SootMethod inlinee = hierarchy.resolveSpecialDispatch(r,
method);
SootClass declaringClass = inlinee.getDeclaringClass();
if (!declaringClass.isApplicationClass()) {
declaringClass.setLibraryClass();