work(basicBlock, instructionIterator, patternElement, matchCount, currentMatch, bindingSet, canFork); } else if (currentMatch == null || currentMatch.allowTrailingEdges()) {
work(state); } else if (state.canAdvanceToNextBasicBlock()) {
	private void work(BasicBlock basicBlock, BasicBlock.InstructionIterator instructionIterator,		PatternElement patternElement, int matchCount,		PatternElementMatch currentMatch, BindingSet bindingSet,		boolean canFork)		throws DataflowAnalysisException {		// Have we reached the end of the pattern?		if (patternElement == null) {			// This is a complete match.			if (DEBUG) System.out.println("FINISHED A MATCH!");			resultList.add(new ByteCodePatternMatch(bindingSet, currentMatch));			return;		}		// If we've reached the minimum number of occurrences for this		// pattern element, we can advance to the next pattern element without trying		// to match this instruction again.  We make sure that we only advance to		// the next element once for this matchCount.		if (canFork && matchCount >= patternElement.minOccur()) {			work(basicBlock, instructionIterator.duplicate(), patternElement.getNext(), 0, currentMatch, bindingSet, true);			canFork = false;		}		// If we've reached the maximum number of occurrences for this		// pattern element, then we can't continue.		if (matchCount >= patternElement.maxOccur())			return;		InstructionHandle matchedInstruction = null;		PatternElement matchedPatternElement = null;		// Is there another instruction in this basic block?		if (instructionIterator.hasNext()) {			InstructionHandle handle = instructionIterator.next();			// Get the ValueNumberFrames before and after the instruction			ValueNumberFrame before = vnaDataflow.getFactAtLocation(new Location(handle, basicBlock));			BasicBlock.InstructionIterator dupIter = instructionIterator.duplicate();			ValueNumberFrame after = dupIter.hasNext()				? vnaDataflow.getFactAtLocation(new Location(dupIter.next(), basicBlock))				: vnaDataflow.getResultFact(basicBlock);			// Try to match the instruction against the pattern element.			boolean isWild = patternElement instanceof Wild;			if (DEBUG && (!isWild || SHOW_WILD)) System.out.println("Match " + patternElement + " against " + handle + " " +				(bindingSet != null ? bindingSet.toString() : "[]") + "...");			MatchResult matchResult = patternElement.match(handle, cpg, before, after, bindingSet);			if (DEBUG && (!isWild || SHOW_WILD)) System.out.println("\t" + ((matchResult != null) ? " ==> MATCH" : " ==> NOT A MATCH"));			if (matchResult == null)				// Not a match.				return;			// Successful match!			matchedInstruction = handle;			matchedPatternElement = matchResult.getPatternElement();			++matchCount;			canFork = true;			currentMatch = new PatternElementMatch(matchedPatternElement, handle, basicBlock,				matchCount, currentMatch);			bindingSet = matchResult.getBindingSet();		}		// Continue the match at each successor instruction,		// using the same PatternElement.		if (instructionIterator.hasNext()) {			// Easy case; continue matching in the same basic block.			work(basicBlock, instructionIterator, patternElement, matchCount, currentMatch, bindingSet, canFork);		} else if (currentMatch == null || currentMatch.allowTrailingEdges()) {			// We've reached the end of the basic block.			// Try to advance to the successors of this basic block,			// ignoring loop backedges.			Iterator<Edge> i = cfg.outgoingEdgeIterator(basicBlock);			BitSet visitedSuccessorSet = new BitSet();			while (i.hasNext()) {				Edge edge = i.next();				if (dfs.getDFSEdgeType(edge) == BACK_EDGE)					continue;				// If we have just matched an instruction, then we allow the				// matching PatternElement to choose which edges are acceptable.				// This allows PatternElements to select particular control edges;				// for example, only continue the pattern on the true branch				// of an "if" comparison.				if (matchedInstruction == null || matchedPatternElement.acceptBranch(edge, matchedInstruction)) {					BasicBlock destBlock = edge.getTarget();					int destId = destBlock.getId();					// CFGs can have duplicate edges					if (visitedSuccessorSet.get(destId))						continue;					visitedSuccessorSet.set(destId, true);					work(destBlock, destBlock.instructionIterator(), patternElement, matchCount, currentMatch, bindingSet, canFork);				}			}		}	}