if (!stmt.containsInvokeExpr()) {
continue;
}
ValueBox box = stmt.getInvokeExprBox();
Value value = stmt.getInvokeExpr();
if (value instanceof InstanceInvokeExpr) {
InstanceInvokeExpr r = (InstanceInvokeExpr) value;
if (r.getBase().getType() instanceof RefType) {
RefType type = (RefType) r.getBase().getType();
// Inline calls to connections changed.
if (r.getMethod().equals(
PtolemyUtilities.connectionsChangedMethod)) {
// If we are calling connections changed on one of the classes
// we are generating code for, then inline it.
if (type.getSootClass().isApplicationClass()) {
SootMethod inlinee = null;
if (r instanceof VirtualInvokeExpr) {
// Now inline the resulting call.
List methodList = Scene
.v()
.getActiveHierarchy()
.resolveAbstractDispatch(
type.getSootClass(),
PtolemyUtilities.connectionsChangedMethod);
if (methodList.size() == 1) {
// Inline the method.
inlinee = (SootMethod) methodList.get(0);
} else {
String string = "Can't inline " + stmt
+ " in method " + method + "\n";
for (int i = 0; i < methodList.size(); i++) {
string += ("target = "
+ methodList.get(i) + "\n");
}
System.out.println(string);
}
} else if (r instanceof SpecialInvokeExpr) {
inlinee = Scene.v().getActiveHierarchy()
.resolveSpecialDispatch(
(SpecialInvokeExpr) r, method);
}
if (inlinee != null
&& !inlinee.getDeclaringClass()
.isApplicationClass()) {
inlinee.getDeclaringClass().setLibraryClass();
}
inlinee.retrieveActiveBody();
if (debug) {
System.out
.println("Inlining method call: " + r);
}
SiteInliner.inlineSite(inlinee, stmt, method);
doneSomething = true;
} else {
// FIXME: this is a bit of a hack, but
// for right now it seems to work.
// How many things that aren't
// the actors we are generating
// code for do we really care about here?
// Can we do this without having to create
// a class for the port too????
body.getUnits().remove(stmt);
doneSomething = true;
}
}
// Statically evaluate constant arguments.
Value[] argValues = new Value[r.getArgCount()];
int constantArgCount = 0;
for (Iterator args = r.getArgs().iterator(); args.hasNext();) {
Value arg = (Value) args.next();
//System.out.println("arg = " + arg);
if (Evaluator.isValueConstantValued(arg)) {
argValues[constantArgCount++] = Evaluator
.getConstantValueOf(arg);
// System.out.println("argument = " + argValues[argCount-1]);
} else {
break;
}
}
//boolean allArgsAreConstant = (r.getArgCount() == constantArgCount);
if (SootUtilities.derivesFrom(type.getSootClass(),
PtolemyUtilities.componentPortClass)) {
// If we are invoking a method on a port
// class, then attempt to get the constant
// value of the port.
TypedIOPort port = (TypedIOPort) analysis
.getObject((Local) r.getBase());
// System.out.println("reference to port = " + port);
if (port == null) {
continue;
}
// If we do this, then we have to get rid of
// the ports.
if (port instanceof Typeable) {
PtolemyUtilities.inlineTypeableMethods(body, stmt,
box, r, port);
}
// Inline namedObj methods on the attribute.
if (r.getMethod().getSubSignature().equals(
PtolemyUtilities.getFullNameMethod
.getSubSignature())) {
box.setValue(StringConstant.v(port.getFullName()));
}
if (r.getMethod().getSubSignature().equals(
PtolemyUtilities.getNameMethod
.getSubSignature())) {
box.setValue(StringConstant.v(port.getName()));
}
String methodName = r.getMethod().getName();
if ((port.getWidth() == 0)
&& (methodName.equals("hasToken")
|| methodName.equals("hasRoom")
|| methodName.equals("get") || methodName
.equals("put"))) {
// NOTE: broadcast is legal on a zero
// width port.
// If we try to get on a port with
// zero width, then throw a runtime
// exception.
Local local = SootUtilities
.createRuntimeException(
body,
stmt,
methodName
+ "() called on a port with zero width: "
+ port.getFullName() + "!");
body.getUnits().insertBefore(
Jimple.v().newThrowStmt(local), stmt);
if (stmt instanceof DefinitionStmt) {
// be sure we replace with the
// right return type.
if (methodName.equals("hasToken")
|| methodName.equals("hasRoom")) {
box.setValue(IntConstant.v(0));
} else {
box.setValue(NullConstant.v());
}
} else {
body.getUnits().remove(stmt);
}
continue;
}
if (r.getMethod().getName().equals("isInput")) {
if (debug) {
System.out.println("replacing isInput at "
+ stmt);
}
if (port.isInput()) {
box.setValue(IntConstant.v(1));
} else {
box.setValue(IntConstant.v(0));
}
} else if (r.getMethod().getName().equals("isOutput")) {
if (debug) {
System.out.println("replacing isOutput at "
+ stmt);
}
if (port.isOutput()) {
box.setValue(IntConstant.v(1));
} else {
box.setValue(IntConstant.v(0));
}
} else if (r.getMethod().getName()
.equals("isMultiport")) {
if (debug) {
System.out.println("replacing isMultiport at "
+ stmt);
}
if (port.isMultiport()) {
box.setValue(IntConstant.v(1));
} else {
box.setValue(IntConstant.v(0));
}
} else if (r.getMethod().getName().equals("getWidth")
|| r.getMethod().getName().equals(
"numberOfSources")
|| r.getMethod().getName().equals(
"numberOfSinks")) {
if (debug) {
System.out.println("replacing getWidth at "
+ stmt);
}
// Reflect and invoke the same method on our port
Object object = SootUtilities
.reflectAndInvokeMethod(port,
r.getMethod(), argValues);
// System.out.println("method result = " + constant);
Constant constant = SootUtilities
.convertArgumentToConstantValue(object);
// replace the method invocation.
box.setValue(constant);
} else if (r.getMethod().getName().equals("hasToken")) {
// return true.
if (debug) {
System.out.println("replacing hasToken at "
+ stmt);
}
box.setValue(IntConstant.v(1));
} else if (r.getMethod().getName().equals("hasRoom")) {
// return true.
if (debug) {
System.out.println("replacing hasRoom at "
+ stmt);
}
box.setValue(IntConstant.v(1));
} else if (r.getMethod().getName().equals("get")) {
// Could be get that takes a channel and
// returns a token, or get that takes a
// channel and a count and returns an
// array of tokens. In either case,