1 19 20 package edu.umd.cs.findbugs.ba.bcp; 21 22 import java.util.BitSet ; 23 import java.util.IdentityHashMap ; 24 import java.util.Iterator ; 25 import java.util.LinkedList ; 26 27 import org.apache.bcel.classfile.Method; 28 import org.apache.bcel.generic.ConstantPoolGen; 29 import org.apache.bcel.generic.InstructionHandle; 30 31 import edu.umd.cs.findbugs.SystemProperties; 32 import edu.umd.cs.findbugs.annotations.Nullable; 33 import edu.umd.cs.findbugs.ba.BasicBlock; 34 import edu.umd.cs.findbugs.ba.CFG; 35 import edu.umd.cs.findbugs.ba.CFGBuilderException; 36 import edu.umd.cs.findbugs.ba.ClassContext; 37 import edu.umd.cs.findbugs.ba.DFSEdgeTypes; 38 import edu.umd.cs.findbugs.ba.DataflowAnalysisException; 39 import edu.umd.cs.findbugs.ba.DepthFirstSearch; 40 import edu.umd.cs.findbugs.ba.DominatorsAnalysis; 41 import edu.umd.cs.findbugs.ba.Edge; 42 import edu.umd.cs.findbugs.ba.Location; 43 import edu.umd.cs.findbugs.ba.vna.ValueNumberDataflow; 44 import edu.umd.cs.findbugs.ba.vna.ValueNumberFrame; 45 46 56 public class PatternMatcher implements DFSEdgeTypes { 57 private static final boolean DEBUG = SystemProperties.getBoolean("bcp.debug"); 58 private static final boolean SHOW_WILD = SystemProperties.getBoolean("bcp.showWild"); 59 60 private ByteCodePattern pattern; 61 private CFG cfg; 62 private ConstantPoolGen cpg; 63 private DepthFirstSearch dfs; 64 private ValueNumberDataflow vnaDataflow; 65 private DominatorsAnalysis domAnalysis; 66 private LinkedList <BasicBlock> workList; 67 private IdentityHashMap <BasicBlock, BasicBlock> visitedBlockMap; 68 private LinkedList <ByteCodePatternMatch> resultList; 69 70 77 public PatternMatcher(ByteCodePattern pattern, ClassContext classContext, Method method) 78 throws CFGBuilderException, DataflowAnalysisException { 79 this.pattern = pattern; 80 this.cfg = classContext.getCFG(method); 81 this.cpg = classContext.getConstantPoolGen(); 82 this.dfs = classContext.getDepthFirstSearch(method); 83 this.vnaDataflow = classContext.getValueNumberDataflow(method); 84 this.domAnalysis = classContext.getNonExceptionDominatorsAnalysis(method); 85 this.workList = new LinkedList <BasicBlock>(); 86 this.visitedBlockMap = new IdentityHashMap <BasicBlock, BasicBlock>(); 87 this.resultList = new LinkedList <ByteCodePatternMatch>(); 88 } 89 90 97 public PatternMatcher execute() throws DataflowAnalysisException { 98 workList.addLast(cfg.getEntry()); 99 100 while (!workList.isEmpty()) { 101 BasicBlock basicBlock = workList.removeLast(); 102 visitedBlockMap.put(basicBlock, basicBlock); 103 104 BasicBlock.InstructionIterator i = basicBlock.instructionIterator(); 106 while (i.hasNext()) { 107 attemptMatch(basicBlock, i.duplicate()); 108 i.next(); 109 } 110 111 Iterator <BasicBlock> succIterator = cfg.successorIterator(basicBlock); 113 while (succIterator.hasNext()) { 114 BasicBlock succ = succIterator.next(); 115 if (visitedBlockMap.get(succ) == null) 116 workList.addLast(succ); 117 } 118 } 119 120 return this; 121 } 122 123 127 public Iterator <ByteCodePatternMatch> byteCodePatternMatchIterator() { 128 return resultList.iterator(); 129 } 130 131 138 private void attemptMatch(BasicBlock basicBlock, BasicBlock.InstructionIterator instructionIterator) 139 throws DataflowAnalysisException { 140 work(new State(basicBlock, instructionIterator, pattern.getFirst())); 141 } 142 143 148 private class State { 149 private BasicBlock basicBlock; 150 private BasicBlock.InstructionIterator instructionIterator; 151 private PatternElement patternElement; 152 private int matchCount; 153 private PatternElementMatch currentMatch; 154 private BindingSet bindingSet; 155 private boolean canFork; 156 157 166 public State(BasicBlock basicBlock, BasicBlock.InstructionIterator instructionIterator, 167 PatternElement patternElement) { 168 this(basicBlock, instructionIterator, patternElement, 0, null, null, true); 169 } 170 171 174 public State(BasicBlock basicBlock, BasicBlock.InstructionIterator instructionIterator, 175 PatternElement patternElement, int matchCount, @Nullable PatternElementMatch currentMatch, 176 @Nullable BindingSet bindingSet, boolean canFork) { 177 this.basicBlock = basicBlock; 178 this.instructionIterator = instructionIterator; 179 this.patternElement = patternElement; 180 this.matchCount = matchCount; 181 this.currentMatch = currentMatch; 182 this.bindingSet = bindingSet; 183 this.canFork = canFork; 184 } 185 186 189 public State duplicate() { 190 return new State(basicBlock, instructionIterator, patternElement, matchCount, currentMatch, bindingSet, canFork); 191 } 192 193 196 public BasicBlock getBasicBlock() { 197 return basicBlock; 198 } 199 200 203 public PatternElement getPatternElement() { 204 return patternElement; 205 } 206 207 210 public PatternElementMatch getCurrentMatch() { 211 return currentMatch; 212 } 213 214 217 public boolean isComplete() { 218 return patternElement == null; 221 } 222 223 226 public ByteCodePatternMatch getResult() { 227 if (!isComplete()) throw new IllegalStateException ("match not complete!"); 228 return new ByteCodePatternMatch(bindingSet, currentMatch); 229 } 230 231 236 public State advanceToNextElement() { 237 if (!canFork || matchCount < patternElement.minOccur()) 238 return null; 241 242 State advance = new State(basicBlock, instructionIterator.duplicate(), patternElement.getNext(), 245 0, currentMatch, bindingSet, true); 246 247 this.canFork = false; 250 251 return advance; 252 } 253 254 258 public boolean currentElementCanContinue() { 259 return matchCount < patternElement.maxOccur(); 260 } 261 262 265 public boolean moreInstructionsInBasicBlock() { 266 return instructionIterator.hasNext(); 267 } 268 269 274 public MatchResult matchNextInBasicBlock() throws DataflowAnalysisException { 275 if (!moreInstructionsInBasicBlock()) throw new IllegalStateException ("At end of BB!"); 276 277 Location location = new Location(instructionIterator.next(), basicBlock); 279 return matchLocation(location); 280 } 281 282 286 public boolean canAdvanceToNextBasicBlock() { 287 return currentMatch == null || currentMatch.allowTrailingEdges(); 288 } 289 290 293 public InstructionHandle getLastMatchedInstruction() { 294 if (currentMatch == null) throw new IllegalStateException ("no current match!"); 295 return currentMatch.getMatchedInstructionInstructionHandle(); 296 } 297 298 306 public State advanceToSuccessor(Edge edge, MatchResult matchResult) { 307 if (matchResult != null && 313 !matchResult.getPatternElement().acceptBranch(edge, getLastMatchedInstruction())) 314 return null; 315 316 return new State(edge.getTarget(), edge.getTarget().instructionIterator(), 317 patternElement, matchCount, currentMatch, bindingSet, canFork); 318 } 319 320 324 public boolean lookForDominatedInstruction() { 325 return patternElement.getDominatedBy() != null && matchCount == 0; 326 } 327 328 332 public Iterator <State> dominatedInstructionStateIterator() throws DataflowAnalysisException { 333 if (!lookForDominatedInstruction()) throw new IllegalStateException (); 334 LinkedList <State> stateList = new LinkedList <State>(); 335 336 State dup = this.duplicate(); 337 338 if (currentMatch != null) { 339 PatternElementMatch dominator = currentMatch.getFirstLabeledMatch(patternElement.getDominatedBy()); 341 BasicBlock domBlock = dominator.getBasicBlock(); 342 343 for (Iterator <BasicBlock> i = cfg.blockIterator(); i.hasNext();) { 345 BasicBlock block = i.next(); 346 if (block == domBlock) 347 continue; 348 349 BitSet dominators = domAnalysis.getResultFact(block); 350 if (dominators.get(domBlock.getId())) { 351 for (Iterator <InstructionHandle> j = block.instructionIterator(); j.hasNext();) { 355 MatchResult matchResult = dup.matchLocation(new Location(j.next(), block)); 356 if (matchResult != null) { 357 stateList.add(dup); 358 dup = this.duplicate(); 359 } 360 } 361 } 362 } 363 } 364 365 return stateList.iterator(); 366 } 367 368 private MatchResult matchLocation(Location location) throws DataflowAnalysisException { 369 ValueNumberFrame before = vnaDataflow.getFactAtLocation(location); 371 ValueNumberFrame after = vnaDataflow.getFactAfterLocation(location); 372 373 boolean debug = DEBUG && (!(patternElement instanceof Wild) || SHOW_WILD); 375 if (debug) 376 System.out.println("Match " + patternElement + 377 " against " + location.getHandle() + " " + 378 (bindingSet != null ? bindingSet.toString() : "[]") + "..."); 379 MatchResult matchResult = patternElement.match(location.getHandle(), 380 cpg, before, after, bindingSet); 381 if (debug) 382 System.out.println("\t" + 383 ((matchResult != null) ? " ==> MATCH" : " ==> NOT A MATCH")); 384 if (matchResult != null) { 385 ++matchCount; 388 canFork = true; 389 currentMatch = new PatternElementMatch(matchResult.getPatternElement(), 390 location.getHandle(), location.getBasicBlock(), matchCount, currentMatch); 391 bindingSet = matchResult.getBindingSet(); 392 } 393 return matchResult; 394 } 395 } 396 397 405 private void work(State state) throws DataflowAnalysisException { 406 if (state.isComplete()) { 408 if (DEBUG) System.out.println("FINISHED A MATCH!"); 410 resultList.add(state.getResult()); 411 return; 412 } 413 414 State advance = state.advanceToNextElement(); 419 if (advance != null) { 420 work(advance); 421 } 422 423 if (!state.currentElementCanContinue()) 426 return; 427 428 MatchResult matchResult = null; 429 430 if (state.lookForDominatedInstruction()) { 433 for (Iterator <State> i = state.dominatedInstructionStateIterator(); i.hasNext();) 434 work(i.next()); 435 return; 436 } 437 438 if (state.moreInstructionsInBasicBlock()) { 440 matchResult = state.matchNextInBasicBlock(); 442 if (matchResult == null) 443 return; 444 } 445 446 if (state.moreInstructionsInBasicBlock()) { 449 work(state); 451 } else if (state.canAdvanceToNextBasicBlock()) { 452 Iterator <Edge> i = cfg.outgoingEdgeIterator(state.getBasicBlock()); 456 BitSet visitedSuccessorSet = new BitSet (); 457 while (i.hasNext()) { 458 Edge edge = i.next(); 459 if (dfs.getDFSEdgeType(edge) == BACK_EDGE) 460 continue; 461 462 BasicBlock destBlock = edge.getTarget(); 463 int destId = destBlock.getId(); 464 465 if (visitedSuccessorSet.get(destId)) 467 continue; 468 visitedSuccessorSet.set(destId, true); 469 470 State succState = state.advanceToSuccessor(edge, matchResult); 472 if (succState != null) { 473 work(succState); 474 } 475 } 476 } 477 478 } 479 } 480 481 | Popular Tags |