[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
profiling questions
Hi.
I'm trying to compute the number of silent stores in a Java program. A
silent store occurs when the value stored is identical to the value
already there. I have three questions:
Q1) Why does the single variable "y" in the following code get split
into "b1" and "b2" in the Jimple representation:
public class HelloWorld {
public static void main(String[] args) {
int y;
y = 2;
y = 2;
}
}
-->
public class HelloWorld extends java.lang.Object
{
public void <init>()
{
HelloWorld r0;
r0 := @this: HelloWorld;
specialinvoke r0.<java.lang.Object: void <init>()>();
return;
}
public static void main(java.lang.String[] )
{
java.lang.String[] r0;
byte b0, b1;
r0 := @parameter0: java.lang.String[];
b0 = 2;
b1 = 2;
return;
}
}
Q2) How can I test whether a variable (register?) has been initialized
at runtime. Currently, for the Jimple code:
b0 = 2;
I can transform it to produce:
if b0 == null goto label0;
if b0 != 2 goto label0;
tmp = <HelloWorld: long silentStoreCounter>;
tmp = tmp + 1L;
<HelloWorld: long silentStoreCounter> = tmp;
label0:
b0 = 2;
However, even with that null test there, I still get the following error
at runtime:
Exception in thread "main" java.lang.VerifyError: (class: HelloWorld,
method: main signature: ([Ljava/lang/String;)V) Accessing value from
uninitialized register 1
Is there a a way to test? Or do I have to keep track of which variables
have been initialized inside my internalTransform() method? If there is
a way to test, can I use it on statics and fields as well as locals?
Q3) Can I otherwise use NeqExpr to compare any two values? Does this
work for object references or do I have to do something else? I want to
know if the operands actually refer to the same object, so I don't think
EquivTo() works here.
Cheers,
Chris
Attached please find the files I am talking about.
public class HelloWorld {
//static int x;
public static void main(String[] args) {
//System.out.println("Hello World!");
int y;
/*x = 5;
y = x;
if (y == 5)
y = x;
*/
y = 2;
y = 2;
}
}
import soot.*;
import soot.jimple.*;
import soot.jimple.internal.*;
import soot.util.*;
import java.io.*;
import java.util.*;
public class SilentStoreMain {
public static void main(String[] args) {
if (args.length == 0) {
System.out.println(
"Syntax: java SilentStoreMain [soot options] classfile");
System.exit(0);
}
Scene.v().getPack("jtp").add(
new Transform("jtp.silentstore", SilentStoreTransformer.v()));
soot.Main.main(args);
}
}
/**
This class transforms a body to count the number of silent stores.
*/
class SilentStoreTransformer extends BodyTransformer {
/* standard BodyTransformer stuff */
private static SilentStoreTransformer instance =
new SilentStoreTransformer();
private SilentStoreTransformer() {}
public static SilentStoreTransformer v() { return instance; }
public String getDeclaredOptions() { return super.getDeclaredOptions(); }
private boolean addedFieldsToMainClassAndLoadedPrintStream = false;
private SootClass javaIoPrintStream;
/* the next three methods exist so that the number of silent stores or the
number of stores can be printed out
*/
private Local addTmpRef(Body body) {
Local tmpRef = Jimple.v().newLocal(
"tmpRef", RefType.v("java.io.PrintStream"));
body.getLocals().add(tmpRef);
return tmpRef;
}
private Local addTmpLong(Body body) {
Local tmpLong = Jimple.v().newLocal("tmpLong", LongType.v());
body.getLocals().add(tmpLong);
return tmpLong;
}
private void addPrintCounter(Chain units,
Stmt s,
SootField counter,
Local tmpRef,
Local tmpLong) {
// insert "tmpRef = java.lang.System.out;"
units.insertBefore(Jimple.v().newAssignStmt(
tmpRef, Jimple.v().newStaticFieldRef(
Scene.v().getField(
"<java.lang.System: java.io.PrintStream out>"))), s);
// insert "tmpLong = counter;"
units.insertBefore(Jimple.v().newAssignStmt(
tmpLong, Jimple.v().newStaticFieldRef(counter)), s);
// insert "tmpRef.println(tmpLong);"
SootMethod toCall = javaIoPrintStream.getMethod("void println(long)");
units.insertBefore(Jimple.v().newInvokeStmt(
Jimple.v().newVirtualInvokeExpr(tmpRef, toCall, tmpLong)), s);
}
private void addCounterIncrement(Chain units,
Stmt s,
SootField counter,
Local tmpLocal) {
AssignStmt toAdd1 = Jimple.v().newAssignStmt(tmpLocal,
Jimple.v().newStaticFieldRef(counter));
AssignStmt toAdd2 = Jimple.v().newAssignStmt(tmpLocal,
Jimple.v().newAddExpr(tmpLocal, LongConstant.v(1L)));
AssignStmt toAdd3 = Jimple.v().newAssignStmt(
Jimple.v().newStaticFieldRef(counter),tmpLocal);
// insert "tmpLocal = counter;"
units.insertBefore(toAdd1, s);
// insert "tmpLocal = tmpLocal + 1L;"
units.insertBefore(toAdd2, s);
// insert "counter = tmpLocal;"
units.insertBefore(toAdd3, s);
}
private boolean addSilentStoreTest(Chain units, AssignStmt s,
SootField counter,
Local tmpLocal) {
/* inserts a test to see if a store is silent before an AssignStmt,
and returns true if the insertion worked properly.
*/
/* create a new ImmediateBox with a dummy value */
ImmediateBox iBox = new ImmediateBox(LongConstant.v(1L));
/* now test that the left and right ops can fit in the box */
if (iBox.canContainValue(s.getLeftOp()) &&
iBox.canContainValue(s.getRightOp())) {
EqExpr cond1 =
Jimple.v().newEqExpr(s.getLeftOp(),NullConstant.v());
IfStmt toAdd1 = Jimple.v().newIfStmt(cond1,s);
// System.out.println(toAdd1);
NeExpr cond2 = Jimple.v().newNeExpr(s.getLeftOp(),s.getRightOp());
IfStmt toAdd2 = Jimple.v().newIfStmt(cond2,s);
// insert "if (op1 == null) goto <AssignStmt>"
units.insertBefore(toAdd1, s);
// insert "if (op1 != op2) goto <AssignStmt>"
units.insertBefore(toAdd2, s);
// insert silentStoreCounter increment
addCounterIncrement(units, s, counter, tmpLocal);
// fix-up goto targets
toAdd1.setTarget(s);
toAdd2.setTarget(s);
return true;
}
return false;
}
protected void internalTransform(Body body,
String phaseName,
Map options) {
SootClass sClass = body.getMethod().getDeclaringClass();
SootField storeCounter = null;
SootField silentStoreCounter = null;
boolean addedLocals = false;
Local tmpRef = null, tmpLong = null;
Chain units = body.getUnits();
Local tmpLocal = Jimple.v().newLocal("tmp", LongType.v());
body.getLocals().add(tmpLocal);
boolean isMainMethod = body.getMethod().getSubSignature().equals(
"void main(java.lang.String[])");
Iterator stmtIt = units.snapshotIterator();
boolean initializedCounters = false;
synchronized(this) {
/* just check that there is a main method.
*/
if (!Scene.v().getMainClass().
declaresMethod("void main(java.lang.String[])"))
throw new RuntimeException(
"couldn't find main() in mainClass");
/* now add two field to the main class for counting stores
and silent stores at runtime.
*/
System.out.println(addedFieldsToMainClassAndLoadedPrintStream);
if (addedFieldsToMainClassAndLoadedPrintStream) {
storeCounter = Scene.v().getMainClass().
getFieldByName("storeCounter");
silentStoreCounter = Scene.v().getMainClass().
getFieldByName("silentStoreCounter");
}
else {
/* add storeCounter and silentStoreCounter fields */
storeCounter = new SootField(
"storeCounter", LongType.v(), Modifier.STATIC);
Scene.v().getMainClass().addField(storeCounter);
silentStoreCounter = new SootField(
"silentStoreCounter", LongType.v(), Modifier.STATIC);
Scene.v().getMainClass().addField(silentStoreCounter);
/* just in case, resolve the PrintStream SootClass */
Scene.v().loadClassAndSupport("java.io.PrintStream");
javaIoPrintStream = Scene.v().
getSootClass("java.io.PrintStream");
addedFieldsToMainClassAndLoadedPrintStream = true;
}
}
/*
Scene.v().getJimpleStmtPrinter().printStatementsInBody(body,
new PrintWriter(System.out), true, true);
*/
while(stmtIt.hasNext()) {
Stmt s = (Stmt) stmtIt.next();
// System.out.println(s);
if (isMainMethod && !initializedCounters) {
units.insertBefore(Jimple.v().newAssignStmt(
Jimple.v().newStaticFieldRef(storeCounter),
LongConstant.v(0L)),s);
units.insertBefore(Jimple.v().newAssignStmt(
Jimple.v().newStaticFieldRef(silentStoreCounter),
LongConstant.v(0L)),s);
initializedCounters = true;
}
if (s instanceof AssignStmt) {
addCounterIncrement(units, s, storeCounter, tmpLocal);
addSilentStoreTest(units, (AssignStmt)s, silentStoreCounter,
tmpLocal);
}
if (s instanceof InvokeStmt) {
InvokeExpr iexpr =
(InvokeExpr)((InvokeStmt)s).getInvokeExpr();
if (iexpr instanceof StaticInvokeExpr) {
SootMethod target =
((StaticInvokeExpr)iexpr).getMethod();
if (target.getSignature().equals(
"<java.lang.System: void exit(int)>")) {
if (!addedLocals) {
tmpRef = addTmpRef(body);
tmpLong = addTmpLong(body);
addedLocals = true;
}
addPrintCounter(units,
s, storeCounter, tmpRef, tmpLong);
addPrintCounter(units,
s, silentStoreCounter, tmpRef, tmpLong);
}
}
}
if (isMainMethod && (s instanceof ReturnStmt ||
s instanceof ReturnVoidStmt)) {
if (!addedLocals) {
tmpRef = addTmpRef(body);
tmpLong = addTmpLong(body);
addedLocals = true;
}
addPrintCounter(units, s, storeCounter, tmpRef, tmpLong);
addPrintCounter(units, s, silentStoreCounter, tmpRef, tmpLong);
}
}
/*
Scene.v().getJimpleStmtPrinter().printStatementsInBody(body,
new PrintWriter(System.out), true, true);
*/
}
}