📄 unconditionalvaluederefanalysis.java
字号:
XMethod called = XFactory.createXMethod( inv, methodGen.getConstantPool()); SignatureParser sigParser = new SignatureParser(called.getSignature()); int numParams = sigParser.getNumParameters(); IsNullValueFrame invFrame = invDataflow.getFactAtLocation(location); if (!invFrame.isValid()) return; for (int i = 0; i < numParams; i++) { int offset = sigParser.getSlotsFromTopOfStackForParameter(i); int slot = invFrame.getStackLocation(offset); IsNullValue value = invFrame.getValue(slot); if (reportDereference(invFrame, slot) && database.parameterMustBeNonNull(called, i)) { // Get the corresponding value number ValueNumber vn = vnaFrame.getArgument(inv, methodGen.getConstantPool(), i, sigParser); fact.addDeref(vn, location); } } } /** * Check to see if the instruction has a null check associated with it, * and if so, add a dereference. * * @param location the Location of the instruction * @param vnaFrame ValueNumberFrame at the Location of the instruction * @param fact the dataflow value to modify * @throws DataflowAnalysisException */ private void checkInstance( Location location, ValueNumberFrame vnaFrame, UnconditionalValueDerefSet fact) throws DataflowAnalysisException { // See if this instruction has a null check. // If it does, the fall through predecessor will be // identify itself as the null check. if (!location.isFirstInstructionInBasicBlock()) { return; } if (invDataflow == null) return; BasicBlock fallThroughPredecessor = cfg.getPredecessorWithEdgeType(location.getBasicBlock(), EdgeTypes.FALL_THROUGH_EDGE); if (fallThroughPredecessor == null || !fallThroughPredecessor.isNullCheck()) { return; } // Get the null-checked value ValueNumber vn = vnaFrame.getInstance(location.getHandle().getInstruction(), methodGen.getConstantPool()); // Ignore dereferences of this if (!methodGen.isStatic()) { ValueNumber v = vnaFrame.getValue(0); if (v.equals(vn)) return; } if (vn.hasFlag(ValueNumber.CONSTANT_CLASS_OBJECT)) return; IsNullValueFrame startFact = null; startFact = invDataflow.getStartFact(fallThroughPredecessor); if (!startFact.isValid()) return; int slot = startFact.getInstanceSlot( location.getHandle().getInstruction(), methodGen.getConstantPool()); if (!reportDereference(startFact, slot)) return; if (DEBUG) { System.out.println("FOUND GUARANTEED DEREFERENCE"); System.out.println("Load: " + vnaFrame.getLoad(vn)); System.out.println("Pred: " + fallThroughPredecessor); System.out.println("startFact: " + startFact); System.out.println("Location: " + location); System.out.println("Value number frame: " + vnaFrame); System.out.println("Dereferenced valueNumber: " + vn); System.out.println("invDataflow: " + startFact); System.out.println("IGNORE_DEREF_OF_NCP: " + IGNORE_DEREF_OF_NCP); } // Mark the value number as being dereferenced at this location fact.addDeref(vn, location); } private boolean reportDereference(IsNullValueFrame invFrameAtNullCheck, int instance) { return reportDereference( invFrameAtNullCheck.getValue(instance)); } private boolean reportDereference(IsNullValue value) { if (value.isDefinitelyNotNull()) return false; if (value.isDefinitelyNull()) return false; if (IGNORE_DEREF_OF_NCP && value.isNullOnComplicatedPath()) return false; return true; } /** * Return whether or not given instruction is an assertion. * * @param handle the instruction * @return true if instruction is an assertion, false otherwise */ private boolean isAssertion(InstructionHandle handle) { return assertionMethods.isAssertionInstruction ( handle.getInstruction() , methodGen.getConstantPool()); } /* (non-Javadoc) * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#copy(java.lang.Object, java.lang.Object) */ public void copy(UnconditionalValueDerefSet source, UnconditionalValueDerefSet dest) { dest.makeSameAs(source); } /* (non-Javadoc) * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#createFact() */ public UnconditionalValueDerefSet createFact() { return new UnconditionalValueDerefSet(vnaDataflow.getAnalysis().getNumValuesAllocated()); } /* (non-Javadoc) * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#initEntryFact(java.lang.Object) */ public void initEntryFact(UnconditionalValueDerefSet result) throws DataflowAnalysisException { result.clear(); } /* (non-Javadoc) * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#initResultFact(java.lang.Object) */ public void initResultFact(UnconditionalValueDerefSet result) { result.setIsTop(); } /* (non-Javadoc) * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#makeFactTop(java.lang.Object) */ public void makeFactTop(UnconditionalValueDerefSet fact) { fact.setIsTop(); } public boolean isTop(UnconditionalValueDerefSet fact) { return fact.isTop(); } /* (non-Javadoc) * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#meetInto(java.lang.Object, edu.umd.cs.findbugs.ba.Edge, java.lang.Object) */ public void meetInto(UnconditionalValueDerefSet fact, Edge edge, UnconditionalValueDerefSet result) throws DataflowAnalysisException { meetInto(fact, edge, result, false); } /* (non-Javadoc) * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#meetInto(java.lang.Object, edu.umd.cs.findbugs.ba.Edge, java.lang.Object) */ public void meetInto(UnconditionalValueDerefSet fact, Edge edge, UnconditionalValueDerefSet result, boolean onlyEdge) throws DataflowAnalysisException { if (isExceptionEdge(edge) && !onlyEdge) { if (DEBUG) System.out.println("Skipping exception edge"); return; } ValueNumber knownNonnullOnBranch = null; // Edge transfer function if (isFactValid(fact)) { fact = propagateDerefSetsToMergeInputValues(fact, edge); if (invDataflow != null) { knownNonnullOnBranch = findValueKnownNonnullOnBranch(fact, edge); if (knownNonnullOnBranch != null) { fact = duplicateFact(fact); fact.clearDerefSet(knownNonnullOnBranch); } } } boolean isBackEdge = edge.isBackwardInBytecode(); Set<Integer> loopExitBranches = ClassContext.getLoopExitBranches(method, methodGen); assert loopExitBranches != null; boolean sourceIsTopOfLoop = edge.sourceIsTopOfLoop(loopExitBranches); if (sourceIsTopOfLoop && edge.getType() == EdgeTypes.FALL_THROUGH_EDGE) isBackEdge = true; if (false && (edge.getType() == EdgeTypes.IFCMP_EDGE || sourceIsTopOfLoop)) { System.out.println("Meet into " + edge); System.out.println(" foo2: " + sourceIsTopOfLoop); System.out.println(" getType: " + edge.getType() ); System.out.println(" Backedge according to bytecode: " + isBackEdge); System.out.println(" Fact hashCode: " + System.identityHashCode(result)); System.out.println(" Initial fact: " + result); System.out.println(" Edge fact: " + fact); } if (result.isTop() || fact.isBottom()) { // Make result identical to other fact copy(fact, result); if (ASSUME_NONZERO_TRIP_LOOPS && isBackEdge && !fact.isTop()) result.resultsFromBackEdge = true; } else if (ASSUME_NONZERO_TRIP_LOOPS && isBackEdge && !fact.isTop()) { result.unionWith(fact, vnaDataflow.getAnalysis().getFactory()); result.resultsFromBackEdge = true; if (DEBUG) { System.out.println("\n Forcing union of " + System.identityHashCode(result) + " due to backedge info"); System.out.println(" result: " + result); } } else if (result.isBottom() || fact.isTop()) { // No change in result fact } else { // Dataflow merge // (intersection of unconditional deref values) if (ASSUME_NONZERO_TRIP_LOOPS && result.resultsFromBackEdge) { result.backEdgeUpdateCount++; if (result.backEdgeUpdateCount < 10) { if (DEBUG) System.out.println("\n Union update of " + System.identityHashCode(result) + " due to backedge info"); result.unionWith(fact, vnaDataflow.getAnalysis().getFactory()); return; } } result.mergeWith(fact, knownNonnullOnBranch, vnaDataflow.getAnalysis().getFactory()); if (DEBUG) { System.out.println(" updated: " + System.identityHashCode(result)); System.out.println(" result: " + result); } } if (DEBUG && isBackEdge && edge.getType() == EdgeTypes.IFCMP_EDGE) { System.out.println(" result: " + result); } } /** * Find out if any VNs in the source block * contribute to unconditionally dereferenced VNs in the * target block. If so, the VN in the source block is * also unconditionally dereferenced, and we must propagate * the target VN's dereferences. * * @param fact a dataflow value * @param edge edge to check for merge input values * @return possibly-modified dataflow value */ private UnconditionalValueDerefSet propagateDerefSetsToMergeInputValues( UnconditionalValueDerefSet fact, Edge edge) { ValueNumberFrame blockValueNumberFrame = vnaDataflow.getResultFact(edge.getSource()); ValueNumberFrame targetValueNumberFrame = vnaDataflow.getStartFact(edge.getTarget()); UnconditionalValueDerefSet originalFact = fact; fact = duplicateFact(fact); if (blockValueNumberFrame.isValid() && targetValueNumberFrame.isValid() && blockValueNumberFrame.getNumSlots() == targetValueNumberFrame.getNumSlots()) { if (DEBUG) { System.out.println("** Valid VNA frames for " + edge); System.out.println("** Block : " + blockValueNumberFrame); System.out.println("** Target: " + targetValueNumberFrame); } for (int i = 0; i < blockValueNumberFrame.getNumSlots(); i++) { ValueNumber blockVN = blockValueNumberFrame.getValue(i); ValueNumber targetVN = targetValueNumberFrame.getValue(i); if (blockVN.equals(targetVN)) continue; fact.clearDerefSet(blockVN); if (originalFact.isUnconditionallyDereferenced(targetVN)) fact.setDerefSet(blockVN, originalFact.getUnconditionalDerefLocationSet(targetVN)); } // for all slots for(ValueNumber blockVN : blockValueNumberFrame.valueNumbersForLoads()) { AvailableLoad load = blockValueNumberFrame.getLoad(blockVN); if (load == null) continue; ValueNumber [] targetVNs = targetValueNumberFrame.getAvailableLoad(load); if (targetVNs != null) for(ValueNumber targetVN : targetVNs) if (targetVN.hasFlag(ValueNumber.PHI_NODE) && fact.isUnconditionallyDereferenced(targetVN) && !fact.isUnconditionallyDereferenced(blockVN)) { // Block VN is also dereferenced unconditionally. AvailableLoad targetLoad = targetValueNumberFrame.getLoad(targetVN); if (!load.equals(targetLoad)) continue; if (DEBUG) { System.out.println("** Copy vn derefs for " + load +" from " + targetVN + " --> " + blockVN); System.out.println("** block phi for " + System.identityHashCode(blockValueNumberFrame) + " is " + blockValueNumberFrame.phiNodeForLoads); System.out.println("** target phi for " + System.identityHashCode(targetValueNumberFrame) + " is " + targetValueNumberFrame.phiNodeForLoads); } fact.setDerefSet(blockVN, fact.getUnconditionalDerefLocationSet(targetVN)); } } } if (DEBUG) { System.out.println("Target VNF: " + targetValueNumberFrame); System.out.println("Block VNF: " + blockValueNumberFrame); System.out.println("fact: " + fact); } fact.cleanDerefSet(null, blockValueNumberFrame); return fact; } /** * Return a duplicate of given dataflow fact. * * @param fact a dataflow fact * @return a duplicate of the input dataflow fact */ private UnconditionalValueDerefSet duplicateFact(UnconditionalValueDerefSet fact) { UnconditionalValueDerefSet copyOfFact = createFact(); copy(fact, copyOfFact); fact = copyOfFact; return fact; } /** * Clear deref sets of values if this edge is the non-null branch * of an if comparison. * * @param fact a datflow fact * @param edge edge to check * @return possibly-modified dataflow fact */ private @CheckForNull ValueNumber findValueKnownNonnullOnBranch( UnconditionalValueDerefSet fact, Edge edge) { IsNullValueFrame invFrame = invDataflow.getResultFact(edge.getSource()); if (!invFrame.isValid()) { return null; } IsNullConditionDecision decision = invFrame.getDecision(); if (decision == null) { return null; } IsNullValue inv = decision.getDecision(edge.getType()); if (inv == null || !inv.isDefinitelyNotNull()) { return null; } ValueNumber value = decision.getValue(); if (DEBUG) { System.out.println("Value number " + value + " is known nonnull on " + edge); } return value; } /** * Determine whether dataflow should be propagated on given edge. * * @param edge the edge * @return true if dataflow should be propagated on the edge, false otherwise */ private boolean isExceptionEdge(Edge edge) { boolean isExceptionEdge = edge.isExceptionEdge(); if (DEBUG && isExceptionEdge) System.out.println("Ignoring " + edge); return isExceptionEdge; } /* (non-Javadoc) * @see edu.umd.cs.findbugs.ba.DataflowAnalysis#same(java.lang.Object, java.lang.Object) */ public boolean same(UnconditionalValueDerefSet fact1, UnconditionalValueDerefSet fact2) { return fact1.resultsFromBackEdge || fact1.isSameAs(fact2); } @Override public void startIteration() { // System.out.println("analysis iteration in " + methodGen.getClassName() + " on " + methodGen.toString()); } @Override public int getLastUpdateTimestamp(UnconditionalValueDerefSet fact) { return fact.getLastUpdateTimestamp(); } @Override public void setLastUpdateTimestamp(UnconditionalValueDerefSet fact, int lastUpdate) { fact.setLastUpdateTimestamp(lastUpdate); } public static void main(String[] args) throws Exception { if (args.length != 1) { System.err.println("Usage: " + UnconditionalValueDerefAnalysis.class.getName() + " <classfile>"); System.exit(1); } DataflowTestDriver<UnconditionalValueDerefSet, UnconditionalValueDerefAnalysis> driver = new DataflowTestDriver<UnconditionalValueDerefSet, UnconditionalValueDerefAnalysis>() { /* (non-Javadoc) * @see edu.umd.cs.findbugs.ba.DataflowTestDriver#createDataflow(edu.umd.cs.findbugs.ba.ClassContext, org.apache.bcel.classfile.Method) */ @Override public Dataflow<UnconditionalValueDerefSet, UnconditionalValueDerefAnalysis> createDataflow(ClassContext classContext, Method method) throws CFGBuilderException, DataflowAnalysisException { return classContext.getUnconditionalValueDerefDataflow(method); } }; if (SystemProperties.getBoolean("forwardcfg")) { driver.overrideIsForwards(); } driver.execute(args[0]); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -