1 19 20 package edu.umd.cs.findbugs.ba; 21 22 import org.apache.bcel.Constants; 23 import org.apache.bcel.classfile.Method; 24 import org.apache.bcel.generic.Instruction; 25 import org.apache.bcel.generic.InstructionHandle; 26 import org.apache.bcel.generic.MethodGen; 27 import org.apache.bcel.generic.ReturnInstruction; 28 29 import edu.umd.cs.findbugs.SystemProperties; 30 import edu.umd.cs.findbugs.ba.vna.ValueNumber; 31 import edu.umd.cs.findbugs.ba.vna.ValueNumberAnalysis; 32 import edu.umd.cs.findbugs.ba.vna.ValueNumberDataflow; 33 import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame; 34 35 43 public class LockAnalysis extends ForwardDataflowAnalysis<LockSet> { 44 private static final boolean DEBUG = SystemProperties.getBoolean("la.debug"); 45 46 private MethodGen methodGen; 47 private ValueNumberDataflow vnaDataflow; 48 private ValueNumberAnalysis vna; 49 private boolean isSynchronized; 50 private boolean isStatic; 51 52 public LockAnalysis(MethodGen methodGen, ValueNumberDataflow vnaDataflow, DepthFirstSearch dfs) { 53 super(dfs); 54 this.methodGen = methodGen; 55 this.vnaDataflow = vnaDataflow; 56 this.vna = vnaDataflow.getAnalysis(); 57 this.isSynchronized = methodGen.isSynchronized(); 58 this.isStatic = methodGen.isStatic(); 59 if (DEBUG) System.out.println("Analyzing Locks in " + methodGen.getClassName() + "." + methodGen.getName()); 60 } 61 62 public LockSet createFact() { 63 return new LockSet(); 64 } 65 66 public void copy(LockSet source, LockSet dest) { 67 dest.copyFrom(source); 68 } 69 70 public void initEntryFact(LockSet result) { 71 result.clear(); 72 result.setDefaultLockCount(0); 73 74 if (isSynchronized && !isStatic) { 75 ValueNumber thisValue = vna.getThisValue(); 76 result.setLockCount(thisValue.getNumber(), 1); 77 } else if (isSynchronized && isStatic) { 78 ValueNumber thisValue = vna.getClassObjectValue(methodGen.getClassName()); 79 result.setLockCount(thisValue.getNumber(), 1); 80 } 81 } 82 83 public void initResultFact(LockSet result) { 84 result.clear(); 85 result.setDefaultLockCount(LockSet.TOP); 86 } 87 88 public void makeFactTop(LockSet fact) { 89 fact.clear(); 90 fact.setDefaultLockCount(LockSet.TOP); 91 } 92 public boolean isTop(LockSet fact) { 93 return fact.isTop(); 94 } 95 public boolean same(LockSet fact1, LockSet fact2) { 96 return fact1.sameAs(fact2); 97 } 98 99 public void meetInto(LockSet fact, Edge edge, LockSet result) throws DataflowAnalysisException { 100 result.meetWith(fact); 101 } 102 103 @Override 104 public void transferInstruction(InstructionHandle handle, BasicBlock basicBlock, LockSet fact) 105 throws DataflowAnalysisException { 106 107 Instruction ins = handle.getInstruction(); 108 short opcode = ins.getOpcode(); 109 if (opcode == Constants.MONITORENTER || opcode == Constants.MONITOREXIT) { 110 ValueNumberFrame frame = vnaDataflow.getFactAtLocation(new Location(handle, basicBlock)); 111 112 if (frame.isValid()) { 115 int lockNumber = frame.getTopValue().getNumber(); 116 lockOp(fact, lockNumber, opcode == Constants.MONITORENTER ? 1 : -1); 117 } 118 } else if ((ins instanceof ReturnInstruction) && isSynchronized && !isStatic) { 119 lockOp(fact, vna.getThisValue().getNumber(), -1); 120 } 121 } 122 123 private void lockOp(LockSet fact, int lockNumber, int delta) { 124 int value = fact.getLockCount(lockNumber); 125 if (value < 0) return; 127 value += delta; 128 if (value < 0) 129 value = LockSet.BOTTOM; 130 if (DEBUG) System.out.println("Setting " + lockNumber + " to " + value + " in " + methodGen.getClassName() + "." + methodGen.getName()); 131 fact.setLockCount(lockNumber, value); 132 } 133 134 @Override 135 public boolean isFactValid(LockSet fact) { 136 return true; 137 } 138 139 public static void main(String [] argv) throws Exception { 140 if (argv.length != 1) { 141 System.err.println("Usage: " + LockAnalysis.class.getName() + " <classfile>"); 142 System.exit(1); 143 } 144 145 DataflowTestDriver<LockSet, LockAnalysis> driver = new DataflowTestDriver<LockSet, LockAnalysis>() { 146 @Override 147 public Dataflow<LockSet, LockAnalysis> createDataflow(ClassContext classContext, Method method) 148 throws CFGBuilderException, DataflowAnalysisException { 149 return classContext.getLockDataflow(method); 150 } 151 }; 152 153 driver.execute(argv[0]); 154 } 155 } 156 157 | Popular Tags |