001: /* Soot - a J*va Optimization Framework
002: * Copyright (C) 2003 Ondrej Lhotak
003: *
004: * This library is free software; you can redistribute it and/or
005: * modify it under the terms of the GNU Lesser General Public
006: * License as published by the Free Software Foundation; either
007: * version 2.1 of the License, or (at your option) any later version.
008: *
009: * This library is distributed in the hope that it will be useful,
010: * but WITHOUT ANY WARRANTY; without even the implied warranty of
011: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
012: * Lesser General Public License for more details.
013: *
014: * You should have received a copy of the GNU Lesser General Public
015: * License along with this library; if not, write to the
016: * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
017: * Boston, MA 02111-1307, USA.
018: */
019:
020: package soot.jimple.toolkits.pointer;
021:
022: import soot.*;
023: import java.util.*;
024: import soot.jimple.toolkits.callgraph.*;
025: import soot.jimple.*;
026:
027: public class FieldRWTagger extends BodyTransformer {
028: public FieldRWTagger(Singletons.Global g) {
029: }
030:
031: public static FieldRWTagger v() {
032: return G.v().soot_jimple_toolkits_pointer_FieldRWTagger();
033: }
034:
035: public int numRWs = 0;
036: public int numWRs = 0;
037: public int numRRs = 0;
038: public int numWWs = 0;
039: public int numNatives = 0;
040: public Date startTime = null;
041: boolean optionDontTag = false;
042: boolean optionNaive = false;
043: private CallGraph cg;
044:
045: protected class UniqueRWSets {
046: protected ArrayList<RWSet> l = new ArrayList<RWSet>();
047:
048: RWSet getUnique(RWSet s) {
049: if (s == null)
050: return s;
051: for (RWSet ret : l) {
052: if (ret.isEquivTo(s))
053: return ret;
054: }
055: l.add(s);
056: return s;
057: }
058:
059: Iterator<RWSet> iterator() {
060: return l.iterator();
061: }
062:
063: short indexOf(RWSet s) {
064: short i = 0;
065: for (RWSet ret : l) {
066: if (ret.isEquivTo(s))
067: return i;
068: i++;
069: }
070: return -1;
071: }
072: }
073:
074: protected void initializationStuff(String phaseName) {
075: if (G.v().Union_factory == null) {
076: G.v().Union_factory = new UnionFactory() {
077: public Union newUnion() {
078: return FullObjectSet.v();
079: }
080: };
081: }
082: if (startTime == null) {
083: startTime = new Date();
084: }
085: cg = Scene.v().getCallGraph();
086: }
087:
088: protected Object keyFor(Stmt s) {
089: if (s.containsInvokeExpr()) {
090: if (optionNaive)
091: throw new RuntimeException("shouldn't get here");
092: Iterator it = cg.edgesOutOf(s);
093: if (!it.hasNext()) {
094: return Collections.EMPTY_LIST;
095: }
096: ArrayList ret = new ArrayList();
097: while (it.hasNext()) {
098: ret.add(it.next());
099: }
100: return ret;
101: } else {
102: return s;
103: }
104: }
105:
106: protected void internalTransform(Body body, String phaseName,
107: Map options) {
108: initializationStuff(phaseName);
109: SideEffectAnalysis sea = new SideEffectAnalysis(
110: DumbPointerAnalysis.v(), Scene.v().getCallGraph());
111: sea.findNTRWSets(body.getMethod());
112: HashMap<Object, RWSet> stmtToReadSet = new HashMap<Object, RWSet>();
113: HashMap<Object, RWSet> stmtToWriteSet = new HashMap<Object, RWSet>();
114: UniqueRWSets sets = new UniqueRWSets();
115: optionDontTag = PhaseOptions.getBoolean(options, "dont-tag");
116: boolean justDoTotallyConservativeThing = body.getMethod()
117: .getName().equals("<clinit>");
118: for (Iterator stmtIt = body.getUnits().iterator(); stmtIt
119: .hasNext();) {
120: final Stmt stmt = (Stmt) stmtIt.next();
121: if (!stmt.containsInvokeExpr())
122: continue;
123: if (justDoTotallyConservativeThing) {
124: stmtToReadSet
125: .put(stmt, sets.getUnique(new FullRWSet()));
126: stmtToWriteSet.put(stmt, sets
127: .getUnique(new FullRWSet()));
128: continue;
129: }
130: Object key = keyFor(stmt);
131: if (!stmtToReadSet.containsKey(key)) {
132: stmtToReadSet.put(key, sets.getUnique(sea.readSet(body
133: .getMethod(), stmt)));
134: stmtToWriteSet.put(key, sets.getUnique(sea.writeSet(
135: body.getMethod(), stmt)));
136: }
137: }
138: /*
139: DependenceGraph graph = new DependenceGraph();
140: for( Iterator outerIt = sets.iterator(); outerIt.hasNext(); ) {
141: final RWSet outer = (RWSet) outerIt.next();
142:
143: for( Iterator innerIt = sets.iterator(); innerIt.hasNext(); ) {
144:
145: final RWSet inner = (RWSet) innerIt.next();
146: if( inner == outer ) break;
147: if( outer.hasNonEmptyIntersection( inner ) ) {
148: graph.addEdge( sets.indexOf( outer ), sets.indexOf( inner ) );
149: }
150: }
151: }
152: if( !optionDontTag ) {
153: body.getMethod().addTag( graph );
154: }
155: for( Iterator stmtIt = body.getUnits().iterator(); stmtIt.hasNext(); ) {
156: final Stmt stmt = (Stmt) stmtIt.next();
157: Object key;
158: if( optionNaive && stmt.containsInvokeExpr() ) {
159: key = stmt;
160: } else {
161: key = keyFor( stmt );
162: }
163: RWSet read = (RWSet) stmtToReadSet.get( key );
164: RWSet write = (RWSet) stmtToWriteSet.get( key );
165: if( read != null || write != null ) {
166: DependenceTag tag = new DependenceTag();
167: if( read != null && read.getCallsNative() ) {
168: tag.setCallsNative();
169: numNatives++;
170: } else if( write != null && write.getCallsNative() ) {
171: tag.setCallsNative();
172: numNatives++;
173: }
174: tag.setRead( sets.indexOf( read ) );
175: tag.setWrite( sets.indexOf( write ) );
176: if( !optionDontTag ) stmt.addTag( tag );
177:
178: // The loop below is just fro calculating stats.
179: if( !justDoTotallyConservativeThing ) {
180: for( Iterator innerIt = body.getUnits().iterator(); innerIt.hasNext(); ) {
181: final Stmt inner = (Stmt) innerIt.next();
182: Object ikey;
183: if( optionNaive && inner.containsInvokeExpr() ) {
184: ikey = inner;
185: } else {
186: ikey = keyFor( inner );
187: }
188: RWSet innerRead = (RWSet) stmtToReadSet.get( ikey );
189: RWSet innerWrite = (RWSet) stmtToWriteSet.get( ikey );
190: if( graph.areAdjacent( sets.indexOf( read ),
191: sets.indexOf( innerWrite ) ) ) numRWs++;
192: if( graph.areAdjacent( sets.indexOf( write ),
193: sets.indexOf( innerRead ) ) ) numWRs++;
194: if( inner == stmt ) continue;
195: if( graph.areAdjacent( sets.indexOf( write ),
196: sets.indexOf( innerWrite ) ) ) numWWs++;
197: if( graph.areAdjacent( sets.indexOf( read ),
198: sets.indexOf( innerRead ) ) ) numRRs++;
199: }
200: }
201: }
202: }
203: */
204: }
205: }
|