/* * Copyright (C) 2000 Janus * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ /* LocalRefVarsAnalysisWrapper class Simple wrapper for BranchedRefVarsAnalysis, to be used by the statement printer. 1) Compute lists of (ref, value) that have been analyzed: * before a statement * after a statement fall through * after a statement branches Note: (ref, kTop) are discareded to improve readability. (This behavior can be turned off at compile time.) 2) Compute lists of references that need to be checked by a null pointer check at a given statement. Compute lists of references that DO NOT need to be checked by a null pointer check at a given statement. Notes: a) that computation can be turned off at compile time b) lists all references that (do not) need to be checked not just the ones that have been analyzed. */ package soot.jimple.toolkits.annotation.nullcheck; import soot.*; import soot.toolkits.graph.*; import soot.toolkits.scalar.*; import java.util.*; /** * @deprecated uses deprecated type {@link BranchedRefVarsAnalysis} and seems of no use * for Soot so marked for future deletion, unless clients object */ @Deprecated public class LocalRefVarsAnalysisWrapper { // compilation options private static final boolean computeChecks = true; private static final boolean discardKTop = true; Map<Unit, List<RefIntPair>> unitToVarsBefore; Map<Unit, List<RefIntPair>> unitToVarsAfterFall; Map<Unit, List<List<RefIntPair>>> unitToListsOfVarsAfterBranches; Map<Unit, List<Object>> unitToVarsNeedCheck; Map<Unit, List<RefIntPair>> unitToVarsDontNeedCheck; BranchedRefVarsAnalysis analysis; // utility method to build lists of (ref, value) pairs for a given flow set // optionally discard (ref, kTop) pairs. private final List<RefIntPair> buildList(FlowSet set) { List<RefIntPair> lst = new ArrayList<RefIntPair>(); Iterator<EquivalentValue> it = analysis.refTypeValues.iterator(); while (it.hasNext()) { EquivalentValue r = it.next(); int refInfo = analysis.refInfo(r, set); if (!(discardKTop && (refInfo == BranchedRefVarsAnalysis.kTop))) lst.add(analysis.getKRefIntPair(r, refInfo)); // remove tops from the list that will be printed for readability } return lst; } // buildList // constructor, where we do all our computations public LocalRefVarsAnalysisWrapper(ExceptionalUnitGraph graph) { analysis = new BranchedRefVarsAnalysis(graph); unitToVarsBefore = new HashMap<Unit, List<RefIntPair>>(graph.size() * 2 + 1, 0.7f); unitToVarsAfterFall = new HashMap<Unit, List<RefIntPair>>(graph.size() * 2 + 1, 0.7f); unitToListsOfVarsAfterBranches = new HashMap<Unit, List<List<RefIntPair>>>(graph.size() * 2 + 1, 0.7f); unitToVarsNeedCheck = new HashMap<Unit, List<Object>>(graph.size() * 2 + 1, 0.7f); unitToVarsDontNeedCheck = new HashMap<Unit, List<RefIntPair>>(graph.size() * 2 + 1, 0.7f); Iterator unitIt = graph.iterator(); while(unitIt.hasNext()) { FlowSet set; Unit s = (Unit) unitIt.next(); set = (FlowSet) analysis.getFallFlowAfter(s); unitToVarsAfterFall.put(s, Collections.unmodifiableList(buildList(set))); // we get a list of flow sets for branches, iterate over them { List branchesFlowsets = analysis.getBranchFlowAfter(s); List<List<RefIntPair>> lst = new ArrayList<List<RefIntPair>>(branchesFlowsets.size()); Iterator it = branchesFlowsets.iterator(); while (it.hasNext()) { set = (FlowSet) it.next(); lst.add(Collections.unmodifiableList(buildList(set))); } unitToListsOfVarsAfterBranches.put(s, lst); } // done with branches set = (FlowSet) analysis.getFlowBefore(s); unitToVarsBefore.put(s, Collections.unmodifiableList(buildList(set))); // NOTE: that set is used in the compute check bellow too if (computeChecks) { ArrayList<RefIntPair> dontNeedCheckVars = new ArrayList<RefIntPair>(); ArrayList<Object> needCheckVars = new ArrayList<Object>(); HashSet allChecksSet = new HashSet(5, 0.7f); allChecksSet.addAll(analysis.unitToArrayRefChecksSet.get(s)); allChecksSet.addAll(analysis.unitToInstanceFieldRefChecksSet.get(s)); allChecksSet.addAll(analysis.unitToInstanceInvokeExprChecksSet.get(s)); allChecksSet.addAll(analysis.unitToLengthExprChecksSet.get(s)); // set of all references that are subject to a null pointer check at this statement Iterator it = allChecksSet.iterator(); while (it.hasNext()) { Value v = (Value) it.next(); int vInfo = analysis.anyRefInfo(v, set); if (vInfo == BranchedRefVarsAnalysis.kTop) { // since it's a check, just print the name of the variable, we know it's top needCheckVars.add(v); } else if (vInfo == BranchedRefVarsAnalysis.kBottom) { // this could happen in some rare cases; cf known limitations // in the BranchedRefVarsAnalysis implementation notes needCheckVars.add(analysis.getKRefIntPair(new EquivalentValue(v), vInfo)); } else { // no check, print the pair (ref, value), so we know why we are not doing the check dontNeedCheckVars.add(analysis.getKRefIntPair(new EquivalentValue(v), vInfo)); } } unitToVarsNeedCheck.put(s, Collections.unmodifiableList(needCheckVars)); unitToVarsDontNeedCheck.put(s, Collections.unmodifiableList(dontNeedCheckVars)); } // end if computeChecks } // end while } // end constructor & computations /* Accesor methods. Public accessor methods to the various class fields containing the results of the computations. */ public List getVarsBefore(Unit s) { return unitToVarsBefore.get(s); } // end getVarsBefore public List getVarsAfterFall(Unit s) { return unitToVarsAfterFall.get(s); } // end getVarsAfterFall public List getListsOfVarsAfterBranch(Unit s) { return unitToListsOfVarsAfterBranches.get(s); } // end getListsOfVarsAfterBranch public List getVarsNeedCheck(Unit s) { if (computeChecks) return unitToVarsNeedCheck.get(s); else return new ArrayList(); } // end getVarsNeedCheck public List getVarsDontNeedCheck(Unit s) { if (computeChecks) return unitToVarsDontNeedCheck.get(s); else return new ArrayList(); } // end getVarsNeedCheck } // end class LocalRefVarsAnalysisWrapper