コード例 #1
0
 private final Iterator<IExplodedBasicBlock> getSuccs(IExplodedBasicBlock bb) {
   if (pdg.isIgnoreExceptions()) {
     return ecfg.getNormalSuccessors(bb).iterator();
   } else {
     return ecfg.getSuccNodes(bb);
   }
 }
コード例 #2
0
  private Set<CGNode> findLoopingMethods(IProgressMonitor progress) throws CancelException {
    CallGraph cg = sdg.getCallGraph();
    Set<CGNode> loops = HashSetFactory.make();

    progress.subTask("Searching methods with potential endless loops");

    for (CGNode node : cg) {
      IR ir = node.getIR();
      if (ir != null) {
        ControlFlowGraph<SSAInstruction, ISSABasicBlock> cfg = ir.getControlFlowGraph();
        final boolean ac = Acyclic.isAcyclic(cfg, cfg.entry());
        if (!ac && !loopsAreSimple(ir)) {
          loops.add(node);
        }
      } else {
        // Conservatively assume that methods may not terminate, iff we dont
        // have their code
        loops.add(node);
      }

      progress.worked(1);
    }

    progress.done();

    return loops;
  }
コード例 #3
0
 /**
  * Is there a path between src and dst using only non-exception controlflow
  *
  * @param src
  * @param dst
  * @return
  */
 public boolean isInNormalSuccessors(CFGNode src, CFGNode dst) {
   if (pdg.isIgnoreExceptions()) {
     return true;
   } else {
     IExplodedBasicBlock bbSrc = node2bb.get(src);
     IExplodedBasicBlock bbDst = node2bb.get(dst);
     if (bbDst == bbSrc) {
       return true;
     } else {
       Collection<IExplodedBasicBlock> bbNormSucc = ecfg.getNormalSuccessors(bbSrc);
       return bbNormSucc.contains(bbDst);
     }
   }
 }
コード例 #4
0
  private void addPhiConstraints(
      CGNode node, ControlFlowGraph<SSAInstruction, ISSABasicBlock> cfg, ISSABasicBlock b) {

    // visit each phi instruction in each successor block
    for (Iterator<? extends IBasicBlock> sbs = cfg.getSuccNodes(b); sbs.hasNext(); ) {
      ISSABasicBlock sb = (ISSABasicBlock) sbs.next();
      if (sb.isExitBlock()) {
        // an optimization based on invariant that exit blocks should have no
        // phis.
        continue;
      }
      int n = 0;
      // set n to be whichPred(this, sb);
      for (Iterator<? extends IBasicBlock> back = cfg.getPredNodes(sb); back.hasNext(); n++) {
        if (back.next() == b) {
          break;
        }
      }
      assert n < cfg.getPredNodeCount(sb);
      for (Iterator<SSAPhiInstruction> phis = sb.iteratePhis(); phis.hasNext(); ) {
        SSAPhiInstruction phi = phis.next();
        if (phi == null) {
          continue;
        }
        PointerKey def = heapModel.getPointerKeyForLocal(node, phi.getDef());
        if (phi.getUse(n) > 0) {
          PointerKey use = heapModel.getPointerKeyForLocal(node, phi.getUse(n));
          addNode(def);
          addNode(use);
          addEdge(def, use);
        }
        // }
        // }
      }
    }
  }
コード例 #5
0
  private void createCFG() {
    for (IExplodedBasicBlock block : ecfg) {
      Set<CFGNode> last = lastNodesOfBB(block);

      Iterator<IExplodedBasicBlock> it = getSuccs(block);
      while (it.hasNext()) {
        IExplodedBasicBlock succ = it.next();
        if (succ == null) {
          Log.warn("Basic block is null in " + Util.methodName(ecfg.getMethod()));
          continue;
        }

        Set<CFGNode> firstOfSucc = firstNodesOfBB(succ);
        for (CFGNode from : last) {
          for (CFGNode to : firstOfSucc) {
            cfg.addEdge(from, to);
          }
        }
      }
    }

    cfg.addEdge(entry, exit);
  }
コード例 #6
0
 public IMethod getMethod() {
   return ecfg.getMethod();
 }
コード例 #7
0
  private void createFirstAndLastNodes(IExplodedBasicBlock block) {
    final SSAInstruction instr = block.getInstruction();

    if (block == ecfg.entry()) {
      assert (entry == null);

      CFGNode cfgNode = createNode(block);

      Set<CFGNode> first = HashSetFactory.make(1);
      first.add(cfgNode);
      firstNodes.put(block, first);

      entry = cfgNode;

      Set<? extends AbstractParameterNode> after = getAllHeapLocatedFormIns();

      CFGNode current = cfgNode;
      for (AbstractParameterNode p : after) {
        CFGNode param = findOrCreateNode(block, p);
        cfg.addEdge(current, param);
        current = param;
        numberOfParameterNodes++;
      }

      if (instr != null) {
        AbstractPDGNode node = pdg.getMainNodeForInstruction(instr);
        if (node != null) {
          CFGNode artificialNode = createArtificialNode(block, node);
          cfg.addEdge(current, artificialNode);
          current = artificialNode;
        }
      }

      Set<CFGNode> last = HashSetFactory.make(1);
      last.add(current);
      lastNodes.put(block, last);
    } else if (block == ecfg.exit()) {
      assert (exit == null);

      CFGNode cfgNode = createNode(block);

      Set<AbstractParameterNode> before = getAllHeapLocatedFormOuts();
      if (!pdg.isIgnoreExceptions() && pdg.getExceptionalExit() != null) {
        before.add(pdg.getExceptionalExit());
      }

      if (before.isEmpty()) {
        Set<CFGNode> first = HashSetFactory.make(1);
        first.add(cfgNode);
        firstNodes.put(block, first);
      } else {
        CFGNode current = null;
        for (AbstractParameterNode p : before) {
          CFGNode param = findOrCreateNode(block, p);
          if (current == null) {
            Set<CFGNode> first = HashSetFactory.make(1);
            first.add(param);
            firstNodes.put(block, first);
          } else {
            cfg.addEdge(current, param);
          }
          current = param;
          numberOfParameterNodes++;
        }

        cfg.addEdge(current, cfgNode);
      }

      exit = cfgNode;

      Set<CFGNode> last = HashSetFactory.make(1);
      last.add(cfgNode);
      lastNodes.put(block, last);
    } else if (block.isCatchBlock() && instr != null) {
      // special case where a single cfg node corresponds to 2 statements...

      CFGNode cfgNode = createNode(block);
      Set<CFGNode> first = HashSetFactory.make(1);
      first.add(cfgNode);
      firstNodes.put(block, first);
      AbstractPDGNode pdgNode = pdg.getMainNodeForInstruction(instr);
      CFGNode lastNode = createArtificialNode(block, pdgNode);
      Set<CFGNode> last = HashSetFactory.make(1);
      last.add(lastNode);
      lastNodes.put(block, last);
      cfg.addEdge(cfgNode, lastNode);

      List<AbstractPDGNode> nodes = pdg.getNodesForInstruction(instr);
      for (AbstractPDGNode node : nodes) {
        if (node instanceof ExpressionNode) {
          sdg2cfg.put((ExpressionNode) node, lastNode);
        }
      }
    } else if (instr instanceof SSAInvokeInstruction) {
      // method call found - add actual in nodes before and actual-out
      // nodes after the call
      Set<CFGNode> first = HashSetFactory.make();
      Set<CFGNode> last = HashSetFactory.make();

      Set<CallNode> calls = getCallsForInstruction((SSAInvokeInstruction) instr);

      CFGNode compoundCallNode = null;
      if (calls.size() > 1) {
        compoundCallNode = createNode(block);
        first.add(compoundCallNode);
      }

      for (CallNode call : calls) {
        CFGNode cfgNode = createNode(block, call);

        Set<? extends AbstractParameterNode> actIns = getAllHeapLocatedActualIns(call);
        numberOfParameterNodes += actIns.size();

        if (actIns.size() == 0) {
          if (compoundCallNode == null) {
            first.add(cfgNode);
          } else {
            cfg.addEdge(compoundCallNode, cfgNode);
          }
        } else {
          CFGNode current = null;
          for (AbstractParameterNode p : actIns) {
            CFGNode param = findOrCreateNode(block, p);
            if (current == null) {
              if (compoundCallNode == null) {
                first.add(param);
              } else {
                cfg.addEdge(compoundCallNode, param);
              }
            } else {
              cfg.addEdge(current, param);
            }

            current = param;
          }

          cfg.addEdge(current, cfgNode);
        }

        Set<? extends AbstractParameterNode> actOuts = getAllHeapLocatedActualOuts(call);
        numberOfParameterNodes += actOuts.size();

        CFGNode current = cfgNode;
        for (AbstractParameterNode p : actOuts) {
          CFGNode param = findOrCreateNode(block, p);
          cfg.addEdge(current, param);
          current = param;
        }
        last.add(current);
      }

      firstNodes.put(block, first);
      lastNodes.put(block, last);
    } else {
      CFGNode cfgNode = createNode(block);

      AbstractPDGNode node = null;
      if (instr != null) {
        node = pdg.getMainNodeForInstruction(instr);
      }

      if (node instanceof ExpressionNode) {
        ExpressionNode expr = (ExpressionNode) node;

        sdg2cfg.put((ExpressionNode) node, cfgNode);

        if (expr.isFieldAccess() || expr.isArrayAccess()) {
          Set<CFGNode> first = HashSetFactory.make(1);
          Set<CFGNode> last = HashSetFactory.make(1);
          last.add(cfgNode);

          CFGNode pred = null;

          if (!expr.isStaticFieldAccess()) {
            CFGNode baseCfg = createArtificialNode(block, expr.getBaseValue());
            first.add(baseCfg);
            pred = baseCfg;
          }

          if (expr.isArrayAccess()) {
            CFGNode indexCfg = createArtificialNode(block, expr.getIndexValue());
            if (pred != null) {
              cfg.addEdge(pred, indexCfg);
            } else {
              first.add(indexCfg);
            }
            pred = indexCfg;
          }

          if (expr.isGet()) {
            CFGNode fieldCfg = createArtificialNode(block, expr.getFieldValue());
            if (pred != null) {
              cfg.addEdge(pred, fieldCfg);
            } else {
              first.add(fieldCfg);
            }
            pred = fieldCfg;
          }

          if (expr.isSet()) {
            CFGNode valCfg = createArtificialNode(block, expr.getSetValue());
            if (pred != null) {
              cfg.addEdge(pred, valCfg);
            } else {
              first.add(valCfg);
            }
            pred = valCfg;
          }

          if (pred != null) {
            cfg.addEdge(pred, cfgNode);
          } else {
            first.add(cfgNode);
          }

          firstNodes.put(block, first);
          lastNodes.put(block, last);
        } else {
          Set<CFGNode> firstAndLast = HashSetFactory.make(1);
          firstAndLast.add(cfgNode);
          firstNodes.put(block, firstAndLast);
          lastNodes.put(block, firstAndLast);
        }
      } else {
        Set<CFGNode> firstAndLast = HashSetFactory.make(1);
        firstAndLast.add(cfgNode);
        firstNodes.put(block, firstAndLast);
        lastNodes.put(block, firstAndLast);
      }
    }
  }
コード例 #8
0
  @SuppressWarnings("unused")
  private boolean loopsAreSimple(
      ControlFlowGraph<SSAInstruction, ISSABasicBlock> cfg, Set<ISSABasicBlock> scc)
      throws CancelException {
    boolean isSimple = true;

    MutableIntSet sccInts = MutableSparseIntSet.createMutableSparseIntSet(scc.size());
    for (ISSABasicBlock bb : scc) {
      sccInts.add(cfg.getNumber(bb));
    }

    boolean noExit = true;

    for (ISSABasicBlock bb : scc) {
      if (cfg.getSuccNodeCount(bb) > 1 && !cfg.getSuccNodeNumbers(bb).isSubset(sccInts)) {
        noExit = false;
        // if preds are no subset of the scc block we have a jump to the outside of the scc
        SSAInstruction last = bb.getLastInstruction();
        int[] uses = new int[last.getNumberOfUses()];

        for (int i = 0; i < uses.length; i++) {
          uses[i] = last.getUse(i);
        }

        TransitiveDataDependence tdep = new TransitiveDataDependence(scc);
        tdep.solve(null);

        for (ISSABasicBlock bb2 : scc) {
          if (bb2 == bb) {
            continue;
          }

          for (SSAInstruction ii : bb2) {
            for (int use : uses) {
              isSimple &= !tdep.influences(ii, use);
            }

            //						IntSet is = tdep.influences((SSAInstruction) ii);
            //						System.err.println(ii + ": " + is);

            if (!isSimple) {
              break;
            }
          }

          if (!isSimple) {
            break;
          }
        }

        // TODO check if condition is simple...
        //				if (isSimple) {
        //					System.err.println("Simple: " + last + " -> " +
        // PrettyWalaNames.methodName(bb.getMethod()));
        //				} else {
        //					System.err.println("Not Simple: " + last + " -> " +
        // PrettyWalaNames.methodName(bb.getMethod()));
        //				}

        if (!isSimple) {
          break;
        }
      }
    }

    return isSimple && !noExit;
  }