001: /* Soot - a J*va Optimization Framework
002: * Copyright (C) 2003 Jerome Miecznikowski
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.dava.toolkits.base.finders;
021:
022: import soot.*;
023: import java.util.*;
024: import soot.util.*;
025: import soot.dava.internal.asg.*;
026:
027: public class ExceptionNode {
028: private final IterableSet body;
029: private IterableSet tryBody, catchBody;
030: private boolean dirty;
031: private LinkedList exitList, catchList;
032: private SootClass exception;
033: private HashMap<IterableSet, SootClass> catch2except;
034: private AugmentedStmt handlerAugmentedStmt;
035:
036: public ExceptionNode(IterableSet tryBody, SootClass exception,
037: AugmentedStmt handlerAugmentedStmt) {
038: this .tryBody = tryBody;
039: this .catchBody = null;
040: this .exception = exception;
041: this .handlerAugmentedStmt = handlerAugmentedStmt;
042:
043: body = new IterableSet();
044: body.addAll(tryBody);
045:
046: dirty = true;
047: exitList = null;
048: catchList = null;
049:
050: catch2except = null;
051: }
052:
053: public boolean add_TryStmts(Collection c) {
054: Iterator it = c.iterator();
055: while (it.hasNext())
056: if (add_TryStmt((AugmentedStmt) it.next()) == false)
057: return false;
058:
059: return true;
060: }
061:
062: public boolean add_TryStmt(AugmentedStmt as) {
063: if ((body.contains(as)) || (tryBody.contains(as)))
064: return false;
065:
066: body.add(as);
067: tryBody.add(as);
068:
069: return true;
070: }
071:
072: public void refresh_CatchBody(ExceptionFinder ef) {
073: if (catchBody != null)
074: body.removeAll(catchBody);
075:
076: catchBody = ef.get_CatchBody(handlerAugmentedStmt);
077: body.addAll(catchBody);
078: }
079:
080: public IterableSet get_Body() {
081: return body;
082: }
083:
084: public IterableSet get_TryBody() {
085: return tryBody;
086: }
087:
088: public IterableSet get_CatchBody() {
089: return catchBody;
090: }
091:
092: public boolean remove(AugmentedStmt as) {
093: if (body.contains(as) == false)
094: return false;
095:
096: if (tryBody.contains(as))
097: tryBody.remove(as);
098: else if ((catchBody != null) && (catchBody.contains(as))) {
099: catchBody.remove(as);
100: dirty = true;
101: } else
102: return false;
103:
104: body.remove(as);
105:
106: return true;
107: }
108:
109: public List get_CatchExits() {
110: if (catchBody == null)
111: return null;
112:
113: if (dirty) {
114: exitList = new LinkedList();
115: dirty = false;
116:
117: Iterator it = catchBody.iterator();
118: while (it.hasNext()) {
119: AugmentedStmt as = (AugmentedStmt) it.next();
120:
121: Iterator sit = as.bsuccs.iterator();
122: while (sit.hasNext())
123: if (catchBody.contains(sit.next()) == false) {
124: exitList.add(as);
125: break;
126: }
127: }
128: }
129:
130: return exitList;
131: }
132:
133: public void splitOff_ExceptionNode(IterableSet newTryBody,
134: AugmentedStmtGraph asg, IterableSet enlist) {
135: IterableSet oldTryBody = new IterableSet();
136: oldTryBody.addAll(tryBody);
137:
138: IterableSet oldBody = new IterableSet();
139: oldBody.addAll(body);
140:
141: Iterator it = newTryBody.iterator();
142: while (it.hasNext()) {
143: AugmentedStmt as = (AugmentedStmt) it.next();
144: if (remove(as) == false) {
145:
146: StringBuffer b = new StringBuffer();
147: it = newTryBody.iterator();
148: while (it.hasNext())
149: b.append("\n"
150: + ((AugmentedStmt) it.next()).toString());
151: b.append("\n-");
152:
153: it = oldTryBody.iterator();
154: while (it.hasNext())
155: b.append("\n"
156: + ((AugmentedStmt) it.next()).toString());
157: b.append("\n-");
158:
159: it = oldBody.iterator();
160: while (it.hasNext())
161: b.append("\n"
162: + ((AugmentedStmt) it.next()).toString());
163: b.append("\n-");
164:
165: throw new RuntimeException(
166: "Tried to split off a new try body that isn't in the old one.\n"
167: + as + "\n - " + b.toString());
168: }
169: }
170:
171: asg.clone_Body(catchBody);
172:
173: AugmentedStmt oldCatchTarget = handlerAugmentedStmt, newCatchTarget = asg
174: .get_CloneOf(handlerAugmentedStmt);
175:
176: Iterator tbit = newTryBody.iterator();
177: while (tbit.hasNext()) {
178: AugmentedStmt as = (AugmentedStmt) tbit.next();
179:
180: as.remove_CSucc(oldCatchTarget);
181: oldCatchTarget.remove_CPred(as);
182: }
183:
184: tbit = tryBody.iterator();
185: while (tbit.hasNext()) {
186: AugmentedStmt as = (AugmentedStmt) tbit.next();
187:
188: as.remove_CSucc(newCatchTarget);
189: newCatchTarget.remove_CPred(as);
190: }
191:
192: Iterator enlit = enlist.snapshotIterator();
193: while (enlit.hasNext()) {
194: ExceptionNode en = (ExceptionNode) enlit.next();
195:
196: if (this == en)
197: continue;
198:
199: if (catchBody.isSupersetOf(en.get_Body())) {
200:
201: IterableSet clonedTryBody = new IterableSet();
202:
203: Iterator trit = en.get_TryBody().iterator();
204: while (trit.hasNext())
205: clonedTryBody.add(asg
206: .get_CloneOf((AugmentedStmt) trit.next()));
207:
208: enlist.addLast(new ExceptionNode(clonedTryBody,
209: en.exception, asg
210: .get_CloneOf(en.handlerAugmentedStmt)));
211: }
212: }
213:
214: enlist.addLast(new ExceptionNode(newTryBody, exception, asg
215: .get_CloneOf(handlerAugmentedStmt)));
216:
217: enlit = enlist.iterator();
218: while (enlit.hasNext())
219: ((ExceptionNode) enlit.next())
220: .refresh_CatchBody(ExceptionFinder.v());
221:
222: asg.find_Dominators();
223: }
224:
225: public void add_CatchBody(ExceptionNode other) {
226: if (other.get_CatchList() == null) {
227: add_CatchBody(other.get_CatchBody(), other.get_Exception());
228: return;
229: }
230:
231: Iterator it = other.get_CatchList().iterator();
232: while (it.hasNext()) {
233: IterableSet c = (IterableSet) it.next();
234:
235: add_CatchBody(c, other.get_Exception(c));
236: }
237: }
238:
239: public void add_CatchBody(IterableSet newCatchBody, SootClass except) {
240: if (catchList == null) {
241: catchList = new LinkedList();
242: catchList.addLast(catchBody);
243:
244: catch2except = new HashMap<IterableSet, SootClass>();
245: catch2except.put(catchBody, exception);
246: }
247:
248: body.addAll(newCatchBody);
249: catchList.addLast(newCatchBody);
250: catch2except.put(newCatchBody, except);
251: }
252:
253: public List get_CatchList() {
254: List l = catchList;
255:
256: if (l == null) {
257: l = new LinkedList();
258: l.add(catchBody);
259: }
260:
261: return l;
262: }
263:
264: public Map get_ExceptionMap() {
265: Map m = catch2except;
266:
267: if (m == null) {
268: m = new HashMap();
269: m.put(catchBody, exception);
270: }
271:
272: return m;
273: }
274:
275: public SootClass get_Exception() {
276: return exception;
277: }
278:
279: public SootClass get_Exception(IterableSet catchBody) {
280: if (catch2except == null)
281: return exception;
282:
283: return catch2except.get(catchBody);
284: }
285:
286: public void dump() {
287: G.v().out.println("try {");
288: Iterator tit = get_TryBody().iterator();
289: while (tit.hasNext())
290: G.v().out.println("\t" + tit.next());
291: G.v().out.println("}");
292:
293: Iterator cit = get_CatchList().iterator();
294: while (cit.hasNext()) {
295: IterableSet catchBody = (IterableSet) cit.next();
296:
297: G.v().out.println("catch "
298: + get_ExceptionMap().get(catchBody) + " {");
299: Iterator cbit = catchBody.iterator();
300: while (cbit.hasNext())
301: G.v().out.println("\t" + cbit.next());
302: G.v().out.println("}");
303:
304: }
305: }
306: }
|