/* Soot - a J*va Optimization Framework * Copyright (C) 2003 Ondrej Lhotak * * 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.toolkits.pointer; import soot.*; import soot.jimple.*; import java.util.*; // ArrayRef, // CaughtExceptionRef, // FieldRef, // IdentityRef, // InstanceFieldRef, // InstanceInvokeExpr, // Local, // StaticFieldRef public class PASideEffectTester implements SideEffectTester { PointsToAnalysis pa = Scene.v().getPointsToAnalysis(); SideEffectAnalysis sea = Scene.v().getSideEffectAnalysis(); HashMap<Unit, RWSet> unitToRead; HashMap<Unit, RWSet> unitToWrite; HashMap<Local, PointsToSet> localToReachingObjects; SootMethod currentMethod; public PASideEffectTester() { if( G.v().Union_factory == null ) { G.v().Union_factory = new UnionFactory() { public Union newUnion() { return FullObjectSet.v(); } }; } } /** Call this when starting to analyze a new method to setup the cache. */ public void newMethod( SootMethod m ) { unitToRead = new HashMap<Unit, RWSet>(); unitToWrite = new HashMap<Unit, RWSet>(); localToReachingObjects = new HashMap<Local, PointsToSet>(); currentMethod = m; sea.findNTRWSets( currentMethod ); } protected RWSet readSet( Unit u ) { RWSet ret = unitToRead.get( u ); if( ret == null ) { unitToRead.put( u, ret = sea.readSet( currentMethod, (Stmt) u ) ); } return ret; } protected RWSet writeSet( Unit u ) { RWSet ret = unitToWrite.get( u ); if( ret == null ) { unitToWrite.put( u, ret = sea.writeSet( currentMethod, (Stmt) u ) ); } return ret; } protected PointsToSet reachingObjects( Local l ) { PointsToSet ret = localToReachingObjects.get( l ); if( ret == null ) { localToReachingObjects.put( l, ret = pa.reachingObjects( l ) ); } return ret; } /** Returns true if the unit can read from v. * Does not deal with expressions; deals with Refs. */ public boolean unitCanReadFrom(Unit u, Value v) { return valueTouchesRWSet( readSet( u ), v, u.getUseBoxes() ); } /** Returns true if the unit can read from v. * Does not deal with expressions; deals with Refs. */ public boolean unitCanWriteTo(Unit u, Value v) { return valueTouchesRWSet( writeSet( u ), v, u.getDefBoxes() ); } protected boolean valueTouchesRWSet(RWSet s, Value v, List boxes) { for( Iterator useIt = v.getUseBoxes().iterator(); useIt.hasNext(); ) { final ValueBox use = (ValueBox) useIt.next(); if( valueTouchesRWSet( s, use.getValue(), boxes ) ) return true; } // This doesn't really make any sense, but we need to return something. if (v instanceof Constant) return false; if (v instanceof Expr) throw new RuntimeException("can't deal with expr"); for( Iterator boxIt = boxes.iterator(); boxIt.hasNext(); ) { final ValueBox box = (ValueBox) boxIt.next(); Value boxed = box.getValue(); if( boxed.equivTo( v ) ) return true; } if (v instanceof Local) { return false; } if( v instanceof InstanceFieldRef ) { InstanceFieldRef ifr = (InstanceFieldRef) v; if( s == null ) return false; PointsToSet o1 = s.getBaseForField( ifr.getField() ); if( o1 == null ) return false; PointsToSet o2 = reachingObjects( (Local) ifr.getBase() ); if( o2 == null ) return false; return o1.hasNonEmptyIntersection( o2 ); } if( v instanceof ArrayRef ) { ArrayRef ar = (ArrayRef) v; if( s == null ) return false; PointsToSet o1 = s.getBaseForField( PointsToAnalysis.ARRAY_ELEMENTS_NODE ); if( o1 == null ) return false; PointsToSet o2 = reachingObjects( (Local) ar.getBase() ); if( o2 == null ) return false; return o1.hasNonEmptyIntersection( o2 ); } if( v instanceof StaticFieldRef ) { StaticFieldRef sfr = (StaticFieldRef) v; if( s == null ) return false; return s.getGlobals().contains( sfr.getField() ); } throw new RuntimeException( "Forgot to handle value "+v ); } }