001: /* Soot - a J*va Optimization Framework
002: * Copyright (C) 1999 Patrick Lam
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.grimp.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.grimp.*;
035: import soot.util.*;
036: import java.util.*;
037:
038: public class ConstructorFolder extends BodyTransformer {
039: public ConstructorFolder(Singletons.Global g) {
040: }
041:
042: public static ConstructorFolder v() {
043: return G.v().soot_grimp_toolkits_base_ConstructorFolder();
044: }
045:
046: /** This method change all new Obj/<init>(args) pairs to new Obj(args) idioms. */
047: protected void internalTransform(Body b, String phaseName,
048: Map options) {
049: GrimpBody body = (GrimpBody) b;
050:
051: if (Options.v().verbose())
052: G.v().out.println("[" + body.getMethod().getName()
053: + "] Folding constructors...");
054:
055: Chain units = body.getUnits();
056: List<Unit> stmtList = new ArrayList<Unit>();
057: stmtList.addAll(units);
058:
059: Iterator<Unit> it = stmtList.iterator();
060:
061: ExceptionalUnitGraph graph = new ExceptionalUnitGraph(body);
062:
063: LocalDefs localDefs = new SmartLocalDefs(graph,
064: new SimpleLiveLocals(graph));
065: LocalUses localUses = new SimpleLocalUses(graph, localDefs);
066:
067: /* fold in NewExpr's with specialinvoke's */
068: while (it.hasNext()) {
069: Stmt s = (Stmt) it.next();
070:
071: if (!(s instanceof AssignStmt))
072: continue;
073:
074: /* this should be generalized to ArrayRefs */
075: Value lhs = ((AssignStmt) s).getLeftOp();
076: if (!(lhs instanceof Local))
077: continue;
078:
079: Value rhs = ((AssignStmt) s).getRightOp();
080: if (!(rhs instanceof NewExpr))
081: continue;
082:
083: /* TO BE IMPLEMENTED LATER: move any copy of the object reference
084: for lhs down beyond the NewInvokeExpr, with the rationale
085: being that you can't modify the object before the constructor
086: call in any case.
087:
088: Also, do note that any new's (object creation) without
089: corresponding constructors must be dead. */
090:
091: List lu = localUses.getUsesOf(s);
092: Iterator luIter = lu.iterator();
093: boolean MadeNewInvokeExpr = false;
094:
095: while (luIter.hasNext()) {
096: Unit use = ((UnitValueBoxPair) (luIter.next())).unit;
097: if (!(use instanceof InvokeStmt))
098: continue;
099: InvokeStmt is = (InvokeStmt) use;
100: if (!(is.getInvokeExpr() instanceof SpecialInvokeExpr)
101: || lhs != ((SpecialInvokeExpr) is
102: .getInvokeExpr()).getBase())
103: continue;
104:
105: SpecialInvokeExpr oldInvoke = ((SpecialInvokeExpr) is
106: .getInvokeExpr());
107: LinkedList invokeArgs = new LinkedList();
108: for (int i = 0; i < oldInvoke.getArgCount(); i++)
109: invokeArgs.add(oldInvoke.getArg(i));
110:
111: AssignStmt constructStmt = Grimp.v().newAssignStmt(
112: (AssignStmt) s);
113: constructStmt.setRightOp(Grimp.v().newNewInvokeExpr(
114: ((NewExpr) rhs).getBaseType(),
115: oldInvoke.getMethodRef(), invokeArgs));
116: MadeNewInvokeExpr = true;
117:
118: use.redirectJumpsToThisTo(constructStmt);
119: units.insertBefore(constructStmt, use);
120: units.remove(use);
121: }
122: if (MadeNewInvokeExpr) {
123: units.remove(s);
124: }
125: }
126: }
127: }
|