/** * 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 (isExceptionEdge) { if (DEBUG) { System.out.println("NOT Ignoring " + edge); } return true; // false } if (edge.getType() != EdgeTypes.FALL_THROUGH_EDGE) { return false; } InstructionHandle h = edge.getSource().getLastInstruction(); if (h != null && h.getInstruction() instanceof IFNONNULL && isNullCheck(h, methodGen.getConstantPool())) { return true; } return false; }
/** * 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; }
/** * 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()) { int slots = 0; if (targetValueNumberFrame.getNumSlots() == blockValueNumberFrame.getNumSlots()) { slots = targetValueNumberFrame.getNumSlots(); } else if (targetValueNumberFrame.getNumLocals() == blockValueNumberFrame.getNumLocals()) { slots = targetValueNumberFrame.getNumLocals(); } if (slots > 0) { 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 < slots; 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; }
public void meetInto( UnconditionalValueDerefSet fact, Edge edge, UnconditionalValueDerefSet result, boolean onlyEdge) { 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); } }