001: /* Soot - a J*va Optimization Framework
002: * Copyright (C) 2004 Jennifer 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: /*
021: * Modified by the Sable Research Group and others 1997-1999.
022: * See the 'credits' file distributed with Soot for the complete list of
023: * contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
024: */
025:
026: package soot.jimple.toolkits.base;
027:
028: import soot.options.*;
029:
030: import soot.*;
031: import soot.toolkits.scalar.*;
032: import soot.jimple.*;
033: import soot.toolkits.graph.*;
034: import soot.util.*;
035: import java.util.*;
036:
037: public class PartialConstructorFolder extends BodyTransformer {
038: //public JimpleConstructorFolder( Singletons.Global g ) {}
039: //public static JimpleConstructorFolder v() { return G.v().JimpleConstructorFolder(); }
040:
041: private List types;
042:
043: public void setTypes(List t) {
044: types = t;
045: }
046:
047: public List getTypes() {
048: return types;
049: }
050:
051: /** This method pushes all newExpr down to be the stmt directly before every
052: * invoke of the init only if they are in the types list*/
053:
054: public void internalTransform(Body b, String phaseName, Map options) {
055: JimpleBody body = (JimpleBody) b;
056:
057: if (Options.v().verbose())
058: G.v().out.println("[" + body.getMethod().getName()
059: + "] Folding Jimple constructors...");
060:
061: Chain units = body.getUnits();
062: List<Unit> stmtList = new ArrayList<Unit>();
063: stmtList.addAll(units);
064:
065: Iterator<Unit> it = stmtList.iterator();
066: Iterator<Unit> nextStmtIt = stmtList.iterator();
067: // start ahead one
068: nextStmtIt.next();
069:
070: ExceptionalUnitGraph graph = new ExceptionalUnitGraph(body);
071:
072: LocalDefs localDefs = new SmartLocalDefs(graph,
073: new SimpleLiveLocals(graph));
074: LocalUses localUses = new SimpleLocalUses(graph, localDefs);
075:
076: /* fold in NewExpr's with specialinvoke's */
077: while (it.hasNext()) {
078: Stmt s = (Stmt) it.next();
079:
080: if (!(s instanceof AssignStmt))
081: continue;
082:
083: /* this should be generalized to ArrayRefs */
084: // only deal with stmts that are an local = newExpr
085: Value lhs = ((AssignStmt) s).getLeftOp();
086: if (!(lhs instanceof Local))
087: continue;
088:
089: Value rhs = ((AssignStmt) s).getRightOp();
090: if (!(rhs instanceof NewExpr))
091: continue;
092:
093: //check if very next statement is invoke -->
094: //this indicates there is no control flow between
095: //new and invoke and should do nothing
096: if (nextStmtIt.hasNext()) {
097: Stmt next = (Stmt) nextStmtIt.next();
098: if (next instanceof InvokeStmt) {
099: InvokeStmt invoke = (InvokeStmt) next;
100:
101: if (invoke.getInvokeExpr() instanceof SpecialInvokeExpr) {
102: SpecialInvokeExpr invokeExpr = (SpecialInvokeExpr) invoke
103: .getInvokeExpr();
104: if (invokeExpr.getBase() == lhs) {
105: break;
106: }
107: }
108: }
109: }
110:
111: // check if new is in the types list - only process these
112: if (!types.contains(((NewExpr) rhs).getType()))
113: continue;
114:
115: List lu = localUses.getUsesOf(s);
116: Iterator luIter = lu.iterator();
117: boolean MadeNewInvokeExpr = false;
118:
119: while (luIter.hasNext()) {
120: Unit use = ((UnitValueBoxPair) (luIter.next())).unit;
121: if (!(use instanceof InvokeStmt))
122: continue;
123: InvokeStmt is = (InvokeStmt) use;
124: if (!(is.getInvokeExpr() instanceof SpecialInvokeExpr)
125: || lhs != ((SpecialInvokeExpr) is
126: .getInvokeExpr()).getBase())
127: continue;
128:
129: //make a new one here
130: AssignStmt constructStmt = Jimple.v().newAssignStmt(
131: ((DefinitionStmt) s).getLeftOp(),
132: ((DefinitionStmt) s).getRightOp());
133: constructStmt.setRightOp(Jimple.v().newNewExpr(
134: ((NewExpr) rhs).getBaseType()));
135: MadeNewInvokeExpr = true;
136:
137: // redirect jumps
138: use.redirectJumpsToThisTo(constructStmt);
139: // insert new one here
140: units.insertBefore(constructStmt, use);
141:
142: constructStmt.addTag(s.getTag("SourceLnPosTag"));
143: }
144: if (MadeNewInvokeExpr) {
145: units.remove(s);
146: }
147: }
148: }
149: }
|