/* Soot - a J*va Optimization Framework * Copyright (C) 2007 Manu Sridharan * * 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. */ package soot.jimple.spark.ondemand; import java.util.HashSet; import java.util.Set; import soot.PointsToSet; import soot.Type; import soot.jimple.ClassConstant; import soot.jimple.spark.ondemand.genericutil.ArraySet; import soot.jimple.spark.ondemand.genericutil.ImmutableStack; import soot.jimple.spark.pag.AllocNode; import soot.jimple.spark.pag.ClassConstantNode; import soot.jimple.spark.pag.Node; import soot.jimple.spark.pag.StringConstantNode; import soot.jimple.spark.sets.EqualsSupportingPointsToSet; import soot.jimple.spark.sets.P2SetVisitor; import soot.jimple.spark.sets.PointsToSetInternal; public final class AllocAndContextSet extends ArraySet<AllocAndContext> implements EqualsSupportingPointsToSet { public boolean hasNonEmptyIntersection(PointsToSet other) { if (other instanceof AllocAndContextSet) { return nonEmptyHelper((AllocAndContextSet) other); } else if (other instanceof WrappedPointsToSet) { return hasNonEmptyIntersection(((WrappedPointsToSet) other).getWrapped()); } else if (other instanceof PointsToSetInternal) { return ((PointsToSetInternal) other).forall(new P2SetVisitor() { @Override public void visit(Node n) { if (!returnValue) { for (AllocAndContext allocAndContext : AllocAndContextSet.this) { if (n.equals(allocAndContext.alloc)) { returnValue = true; break; } } } } }); } throw new UnsupportedOperationException("can't check intersection with set of type " + other.getClass()); } private boolean nonEmptyHelper(AllocAndContextSet other) { for (AllocAndContext otherAllocAndContext : other) { for (AllocAndContext myAllocAndContext : this) { if (otherAllocAndContext.alloc.equals(myAllocAndContext.alloc)) { ImmutableStack<Integer> myContext = myAllocAndContext.context; ImmutableStack<Integer> otherContext = otherAllocAndContext.context; if (myContext.topMatches(otherContext) || otherContext.topMatches(myContext)) { return true; } } } } return false; } public Set<ClassConstant> possibleClassConstants() { Set<ClassConstant> res = new HashSet<ClassConstant>(); for (AllocAndContext allocAndContext : this) { AllocNode n = allocAndContext.alloc; if( n instanceof ClassConstantNode ) { res.add( ((ClassConstantNode)n).getClassConstant() ); } else { return null; } } return res; } public Set<String> possibleStringConstants() { Set<String> res = new HashSet<String>(); for (AllocAndContext allocAndContext : this) { AllocNode n = allocAndContext.alloc; if( n instanceof StringConstantNode ) { res.add( ((StringConstantNode)n).getString() ); } else { return null; } } return res; } public Set<Type> possibleTypes() { Set res = new HashSet<Type>(); for (AllocAndContext allocAndContext : this) { res.add(allocAndContext.alloc.getType()); } return res; } /** * Computes a hash code based on the contents of the points-to set. * Note that hashCode() is not overwritten on purpose. * This is because Spark relies on comparison by object identity. */ public int pointsToSetHashCode() { final int PRIME = 31; int result = 1; for (AllocAndContext elem : this) { result = PRIME * result + elem.hashCode(); } return result; } /** * Returns <code>true</code> if and only if other holds the same alloc nodes as this. * Note that equals() is not overwritten on purpose. * This is because Spark relies on comparison by object identity. */ public boolean pointsToSetEquals(Object other) { if(this==other) { return true; } if(!(other instanceof AllocAndContextSet)) { return false; } AllocAndContextSet otherPts = (AllocAndContextSet) other; //both sets are equal if they are supersets of each other return superSetOf(otherPts, this) && superSetOf(this, otherPts); } /** * Returns <code>true</code> if <code>onePts</code> is a (non-strict) superset of <code>otherPts</code>. */ private boolean superSetOf(AllocAndContextSet onePts, final AllocAndContextSet otherPts) { return onePts.containsAll(otherPts); } }