1 19 20 package edu.umd.cs.findbugs.ba.npe2; 21 22 import java.util.BitSet ; 23 import java.util.HashMap ; 24 import java.util.Map ; 25 26 import org.apache.bcel.Constants; 27 import org.apache.bcel.classfile.Method; 28 import org.apache.bcel.generic.InstructionHandle; 29 30 import edu.umd.cs.findbugs.ba.BasicBlock; 31 import edu.umd.cs.findbugs.ba.CFGBuilderException; 32 import edu.umd.cs.findbugs.ba.ClassContext; 33 import edu.umd.cs.findbugs.ba.CompactLocationNumbering; 34 import edu.umd.cs.findbugs.ba.Dataflow; 35 import edu.umd.cs.findbugs.ba.DataflowAnalysisException; 36 import edu.umd.cs.findbugs.ba.DataflowTestDriver; 37 import edu.umd.cs.findbugs.ba.DepthFirstSearch; 38 import edu.umd.cs.findbugs.ba.Edge; 39 import edu.umd.cs.findbugs.ba.EdgeTypes; 40 import edu.umd.cs.findbugs.ba.ForwardDataflowAnalysis; 41 import edu.umd.cs.findbugs.ba.Location; 42 import edu.umd.cs.findbugs.ba.npe.WillBeDereferencedInfo; 43 import edu.umd.cs.findbugs.ba.vna.ValueNumber; 44 import edu.umd.cs.findbugs.ba.vna.ValueNumberDataflow; 45 import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame; 46 47 53 public class DefinitelyNullSetAnalysis extends ForwardDataflowAnalysis<DefinitelyNullSet> { 54 private ValueNumberDataflow vnaDataflow; 55 private CompactLocationNumbering compactLocationNumbering; 56 private Map <BasicBlock, Condition> conditionMap; 57 58 private static final BitSet IFNULL_OPCODE_SET = new BitSet (); 59 private static final BitSet IFACMP_OPCODE_SET = new BitSet (); 60 private static final BitSet REFCMP_OPCODE_SET = new BitSet (); 61 static { 62 IFNULL_OPCODE_SET.set(Constants.IFNULL); 63 IFNULL_OPCODE_SET.set(Constants.IFNONNULL); 64 65 IFACMP_OPCODE_SET.set(Constants.IF_ACMPEQ); 66 IFACMP_OPCODE_SET.set(Constants.IF_ACMPNE); 67 68 REFCMP_OPCODE_SET.or(IFNULL_OPCODE_SET); 69 REFCMP_OPCODE_SET.or(IFACMP_OPCODE_SET); 70 } 71 72 79 public DefinitelyNullSetAnalysis( 80 DepthFirstSearch dfs, 81 ValueNumberDataflow vnaDataflow, 82 CompactLocationNumbering compactLocationNumbering) { 83 super(dfs); 84 this.vnaDataflow = vnaDataflow; 85 this.compactLocationNumbering = compactLocationNumbering; 86 this.conditionMap = new HashMap <BasicBlock, Condition>(); 87 } 88 89 92 @Override 93 public boolean isFactValid(DefinitelyNullSet fact) { 94 return fact.isValid(); 95 } 96 97 100 @Override 101 public void transferInstruction(InstructionHandle handle, BasicBlock basicBlock, DefinitelyNullSet fact) throws DataflowAnalysisException { 102 Location location = new Location(handle, basicBlock); 103 ValueNumberFrame vnaFrame = vnaDataflow.getFactAfterLocation(location); 104 105 if (!vnaFrame.isValid()) { 106 fact.setTop(); 107 return; 108 } 109 110 114 short opcode = handle.getInstruction().getOpcode(); 115 116 if (opcode == Constants.ACONST_NULL) { 117 setTOS(vnaFrame, location, fact, NullnessValue.definitelyNullValue()); 118 } else if (opcode == Constants.LDC || opcode == Constants.NEW) { 119 setTOS(vnaFrame, location, fact, NullnessValue.definitelyNotNullValue()); 120 } 121 122 124 if (handle == basicBlock.getLastInstruction() && REFCMP_OPCODE_SET.get(opcode)) { 126 Condition condition = getCondition(basicBlock); 127 if (condition != null) { 128 condition.refresh(vnaDataflow.getFactAtLocation(location), fact); 130 } 131 } 132 } 133 134 142 private Condition getCondition(BasicBlock basicBlock) 143 throws DataflowAnalysisException { 144 Condition condition = conditionMap.get(basicBlock); 145 if (condition == null) { 146 Location location = new Location(basicBlock.getLastInstruction(), basicBlock); 147 short opcode = basicBlock.getLastInstruction().getInstruction().getOpcode(); 148 if (IFNULL_OPCODE_SET.get(opcode)) { 149 condition = new IfNullCondition(location); 150 } else if (IFACMP_OPCODE_SET.get(opcode)) { 151 return null; 153 } else { 154 return null; 155 } 156 conditionMap.put(basicBlock, condition); 157 } 158 return condition; 159 } 160 161 164 @Override 165 public void edgeTransfer(Edge edge, DefinitelyNullSet fact) throws DataflowAnalysisException { 166 if (!fact.isValid()) { 167 return; 168 } 169 170 if (edge.getSource().isEmpty()) { 171 return; 172 } 173 174 Condition condition = getCondition(edge.getSource()); 175 if (condition == null) { 176 return; 177 } 178 179 Decision decision = condition.getDecision(edge); 180 if (!decision.isFeasible()) { 181 fact.setTop(); 185 return; 186 } 187 188 System.out.println("Setting " + condition.getValueNumber() + " to " + decision.getNullnessValue() + " on edge " + edge); 189 190 changeNullnessOfValue( 191 condition.getValueNumber(), 192 condition.getLocation(), 193 fact, 194 decision.getNullnessValue()); 195 } 196 197 206 private void setTOS(ValueNumberFrame vnaFrame, Location location, DefinitelyNullSet fact, NullnessValue nullnessValue) 207 throws DataflowAnalysisException { 208 ValueNumber valueNumber = vnaFrame.getTopValue(); 209 changeNullnessOfValue(valueNumber, location, fact, nullnessValue); 210 } 211 212 221 private void changeNullnessOfValue(ValueNumber valueNumber, Location location, DefinitelyNullSet fact, NullnessValue nullnessValue) throws DataflowAnalysisException { 222 229 fact.setNullnessValue(valueNumber, nullnessValue); 230 231 if (fact.getNulllessValue(valueNumber) != nullnessValue) { 232 throw new IllegalStateException (); 233 } 234 235 } 237 238 241 public void copy(DefinitelyNullSet source, DefinitelyNullSet dest) { 242 dest.makeSameAs(source); 243 } 244 245 248 public DefinitelyNullSet createFact() { 249 return new DefinitelyNullSet(vnaDataflow.getAnalysis().getNumValuesAllocated()); 251 } 252 253 256 public void initEntryFact(DefinitelyNullSet result) throws DataflowAnalysisException { 257 result.clear(); 259 } 260 261 264 public void initResultFact(DefinitelyNullSet result) { 265 result.setTop(); 266 } 267 268 271 public void makeFactTop(DefinitelyNullSet fact) { 272 fact.setTop(); 273 } 274 public boolean isTop(DefinitelyNullSet fact) { 275 return fact.isTop(); 276 } 277 280 public void meetInto(DefinitelyNullSet fact, Edge edge, DefinitelyNullSet result) throws DataflowAnalysisException { 281 283 result.mergeWith(fact); 284 } 285 286 289 public boolean same(DefinitelyNullSet fact1, DefinitelyNullSet fact2) { 290 return fact1.equals(fact2); 291 } 292 293 public static void main(String [] args) throws Exception { 294 if (args.length != 1) { 295 System.err.println("Usage: " + DefinitelyNullSetAnalysis.class.getName() + " <classfile>"); 296 System.exit(1); 297 } 298 299 DataflowTestDriver<DefinitelyNullSet, DefinitelyNullSetAnalysis> driver = 300 new DataflowTestDriver<DefinitelyNullSet, DefinitelyNullSetAnalysis>() { 301 304 @Override 305 public Dataflow<DefinitelyNullSet, DefinitelyNullSetAnalysis> createDataflow(ClassContext classContext, Method method) throws CFGBuilderException, DataflowAnalysisException { 306 return classContext.getDefinitelyNullSetDataflow(method); 307 } 308 }; 309 310 driver.execute(args[0]); 311 } 312 } 313 | Popular Tags |