package cute.instrument; import soot.jimple.*; import soot.*; import soot.util.Chain; /** * . * User: Koushik Sen (ksen@cs.uiuc.edu) * Date: Nov 7, 2005 * Time: 6:03:20 PM */ public class InstrumentInvokeStatement { /** * Instruments a statement of the form o.f(...). It does not instrument a statement of the form x = o.f(...); * for the instrumentation of such statements see * {@link InstrumentAssignmentStatement#instrument(soot.jimple.Stmt, soot.Body, soot.util.Chain, boolean, SymbolTable, int)}. * The method first extracts the expression corresponding to the statement. * It then calls {@link ParseExpr#instrument(soot.Body, soot.Value, soot.util.Chain, soot.jimple.Stmt, SymbolTable, boolean, int, boolean)} * on the expression. Finally, it adds {@link cute.concolic.Call#funEnd(int) cute.Concolic.Call.funEnd(lineNo)} * instrumentation function call to the body after the statement. * @param s The statement of the from o.f(...) to be instrumented. * @param body The body of the method containing s. * @param units The units of the body of the method containing s. * @param st The {@link SymbolTable symbol table object} used for mapping local variables and field names to unique * integers. These integers are later used by the tester. * @param isConcurrent If isConcuurent is set then instrumentation calls are added to perform dynamic partial * order reduction. * @param lineNo The line number of the statement s. */ public static void instrument(Stmt s, Body body, Chain units,SymbolTable st,boolean isConcurrent,int lineNo) { InvokeExpr right = ((InvokeStmt)s).getInvokeExpr(); String name = right.getMethod().getName(); if(isConcurrent){ if(right.getArgCount()==0 && name.equals("wait")){ Local tmpLocal2 = Jimple.v().newLocal("__ct_"+body.getLocalCount(), IntType.v()); body.getLocals().add(tmpLocal2); Local tmpLocal = Jimple.v().newLocal("__ct_"+body.getLocalCount(), IntType.v()); body.getLocals().add(tmpLocal); SootMethodRef mr = Scene.v().getMethod("<cute.concolic.Call: int getLockDepth(java.lang.Object)>").makeRef(); units.insertBefore(Jimple.v().newAssignStmt(tmpLocal, Jimple.v().newStaticInvokeExpr(mr,((InstanceInvokeExpr)right).getBase())),s); AddCallWithObject.instrument(((InstanceInvokeExpr)right).getBase(),units,s,"waitBefore",true,lineNo); Stmt sinc2 = Jimple.v().newAssignStmt(tmpLocal2,Jimple.v().newAddExpr(tmpLocal2,IntConstant.v(1))); units.insertAfter(Jimple.v().newIfStmt(Jimple.v().newLtExpr(tmpLocal2,tmpLocal),sinc2),s); units.insertAfter(Jimple.v().newEnterMonitorStmt(((InstanceInvokeExpr)right).getBase()),s); units.insertAfter(sinc2,s); units.insertAfter(Jimple.v().newAssignStmt(tmpLocal2,IntConstant.v(0)),s); AddCallWithObject.instrument(((InstanceInvokeExpr)right).getBase(),units,s,"waitAfter",false,lineNo); Stmt sinc = Jimple.v().newAssignStmt(tmpLocal2,Jimple.v().newAddExpr(tmpLocal2,IntConstant.v(1))); units.insertAfter(Jimple.v().newIfStmt(Jimple.v().newLtExpr(tmpLocal2,tmpLocal),sinc),s); // mr = Scene.v().getMethod("<cute.concolic.Call: void printStr(java.lang.String)>").makeRef(); // units.insertAfter( // Jimple.v().newInvokeStmt(Jimple.v().newStaticInvokeExpr( // mr,StringConstant.v("Crossed"))),s); units.insertAfter(Jimple.v().newExitMonitorStmt(((InstanceInvokeExpr)right).getBase()),s); units.insertAfter(sinc,s); units.insertAfter(Jimple.v().newAssignStmt(tmpLocal2,IntConstant.v(0)),s); } else if(right.getArgCount()==0 && name.equals("notify")){ AddCallWithObject.instrument(((InstanceInvokeExpr)right).getBase(), units,s,"notifyBefore",true,lineNo); // addCallWithObject(((InstanceInvokeExpr)right).getBase(),units,s,"notifyAfter",false); } else if(right.getArgCount()==0 && name.equals("notifyAll")){ AddCallWithObject.instrument(((InstanceInvokeExpr)right).getBase(), units,s,"notifyAllBefore",true,lineNo); // addCallWithObject(((InstanceInvokeExpr)right).getBase(),units,s,"notifyAllAfter",false); } else if(right.getArgCount()==0 && name.equals("start") && right instanceof InstanceInvokeExpr && Utils.isThreadSubType(((InstanceInvokeExpr)right).getMethod().getDeclaringClass())){ AddCallWithObject.instrument(((InstanceInvokeExpr)right).getBase(),units,s,"startBefore",true,lineNo); AddCallWithObject.instrument(((InstanceInvokeExpr)right).getBase(),units,s,"startAfter",false,lineNo); } else if(right.getArgCount()==0 && name.equals("join") && right instanceof InstanceInvokeExpr && Utils.isThreadSubType(((InstanceInvokeExpr)right).getMethod().getDeclaringClass())){ AddCallWithObject.instrument(((InstanceInvokeExpr)right).getBase(),units,s,"joinBefore",true,lineNo); AddCallWithObject.instrument(((InstanceInvokeExpr)right).getBase(),units,s,"joinAfter",false,lineNo); } else { ParseExpr.instrument(body,right,null,units,s,st,isConcurrent,lineNo,false); } } else { ParseExpr.instrument(body,right,null,units,s,st,isConcurrent,lineNo,false); } } }