KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > soot > jimple > toolkits > base > ThisInliner


1 /* Soot - a J*va Optimization Framework
2  * Copyright (C) 2004 Jennifer Lhotak
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */

19
20 package soot.jimple.toolkits.base;
21
22 import soot.*;
23 import soot.jimple.*;
24 import soot.util.*;
25 import java.util.*;
26 import soot.jimple.toolkits.scalar.*;
27
28 public class ThisInliner extends BodyTransformer{
29
30     public void internalTransform(Body b, String JavaDoc phaseName, Map options){
31         
32         // assure body is a constructor
33
if (!b.getMethod().getName().equals("<init>")) return;
34
35         // if the first invoke is a this() and not a super() inline the this()
36
InvokeStmt invokeStmt = getFirstSpecialInvoke(b);
37         if (invokeStmt == null) return;
38         SpecialInvokeExpr specInvokeExpr = (SpecialInvokeExpr)invokeStmt.getInvokeExpr();
39         if (specInvokeExpr.getMethod().getDeclaringClass().equals(b.getMethod().getDeclaringClass())){
40             
41             // put locals from inlinee into container
42
if (!specInvokeExpr.getMethod().hasActiveBody()){
43                 specInvokeExpr.getMethod().retrieveActiveBody();
44             }
45
46             HashMap oldLocalsToNew = new HashMap();
47             
48             Iterator localsIt = specInvokeExpr.getMethod().getActiveBody().getLocals().iterator();
49             while (localsIt.hasNext()){
50                 Local l = (Local)localsIt.next();
51                 Local newLocal = (Local)l.clone();
52                 b.getLocals().add(newLocal);
53                 oldLocalsToNew.put(l, newLocal);
54             }
55            
56             //find identity stmt of original method
57
IdentityStmt origIdStmt = findIdentityStmt(b);
58            
59             HashMap oldStmtsToNew = new HashMap();
60             
61             //System.out.println("locals: "+b.getLocals());
62
Chain containerUnits = b.getUnits();
63             Iterator inlineeIt = specInvokeExpr.getMethod().getActiveBody().getUnits().iterator();
64             while (inlineeIt.hasNext()){
65                 Stmt inlineeStmt = (Stmt)inlineeIt.next();
66                
67                 // handle identity stmts
68
if (inlineeStmt instanceof IdentityStmt){
69                     IdentityStmt idStmt = (IdentityStmt)inlineeStmt;
70                     
71                     if (idStmt.getRightOp() instanceof ThisRef) {
72                         Stmt newThis = Jimple.v().newAssignStmt((Local)oldLocalsToNew.get(idStmt.getLeftOp()), origIdStmt.getLeftOp());
73                         containerUnits.insertBefore(newThis, invokeStmt);
74                         oldStmtsToNew.put(inlineeStmt, newThis);
75                     }
76                     
77                     else if (idStmt.getRightOp() instanceof CaughtExceptionRef){
78                         Stmt newInlinee = (Stmt)inlineeStmt.clone();
79                         Iterator localsToPatch = newInlinee.getUseAndDefBoxes().iterator();
80                         while (localsToPatch.hasNext()){
81                             ValueBox next = (ValueBox)localsToPatch.next();
82                             if (next.getValue() instanceof Local){
83                                 next.setValue((Local)oldLocalsToNew.get(next.getValue()));
84                             }
85                         }
86                     
87                        
88                         containerUnits.insertBefore(newInlinee, invokeStmt);
89                         oldStmtsToNew.put(inlineeStmt, newInlinee);
90                     }
91                     else if (idStmt.getRightOp() instanceof ParameterRef) {
92                         Stmt newParam = Jimple.v().newAssignStmt((Local)oldLocalsToNew.get(idStmt.getLeftOp()), specInvokeExpr.getArg(((ParameterRef)idStmt.getRightOp()).getIndex()));
93                         containerUnits.insertBefore(newParam, invokeStmt);
94                         oldStmtsToNew.put(inlineeStmt, newParam);
95                     }
96                 }
97
98                 // handle return void stmts (cannot return anything else
99
// from a constructor)
100
else if (inlineeStmt instanceof ReturnVoidStmt){
101                     Stmt newRet = Jimple.v().newGotoStmt((Stmt)containerUnits.getSuccOf(invokeStmt));
102                     containerUnits.insertBefore(newRet, invokeStmt);
103                     System.out.println("adding to stmt map: "+inlineeStmt+" and "+newRet);
104                     oldStmtsToNew.put(inlineeStmt, newRet);
105                 }
106
107                 else {
108                     Stmt newInlinee = (Stmt)inlineeStmt.clone();
109                     Iterator localsToPatch = newInlinee.getUseAndDefBoxes().iterator();
110                     while (localsToPatch.hasNext()){
111                         ValueBox next = (ValueBox)localsToPatch.next();
112                         if (next.getValue() instanceof Local){
113                             next.setValue((Local)oldLocalsToNew.get(next.getValue()));
114                         }
115                     }
116
117                        
118                     containerUnits.insertBefore(newInlinee, invokeStmt);
119                     oldStmtsToNew.put(inlineeStmt, newInlinee);
120                 }
121                 
122             }
123                 
124             // handleTraps
125
Iterator trapsIt = specInvokeExpr.getMethod().getActiveBody().getTraps().iterator();
126             while (trapsIt.hasNext()){
127                 Trap t = (Trap)trapsIt.next();
128                 System.out.println("begin: "+t.getBeginUnit());
129                 Stmt newBegin = (Stmt)oldStmtsToNew.get(t.getBeginUnit());
130                 System.out.println("end: "+t.getEndUnit());
131                 Stmt newEnd = (Stmt)oldStmtsToNew.get(t.getEndUnit());
132                 System.out.println("handler: "+t.getHandlerUnit());
133                 Stmt newHandler = (Stmt)oldStmtsToNew.get(t.getHandlerUnit());
134
135                 if (newBegin == null || newEnd == null || newHandler == null)
136                     throw new RuntimeException JavaDoc("couldn't map trap!");
137
138                 b.getTraps().add(Jimple.v().newTrap(t.getException(), newBegin, newEnd, newHandler));
139             }
140
141             // patch gotos
142
inlineeIt = specInvokeExpr.getMethod().getActiveBody().getUnits().iterator();
143             while (inlineeIt.hasNext()){
144                 Stmt inlineeStmt = (Stmt)inlineeIt.next();
145                 if (inlineeStmt instanceof GotoStmt){
146                     System.out.println("inlinee goto target: "+((GotoStmt)inlineeStmt).getTarget());
147                     ((GotoStmt)oldStmtsToNew.get(inlineeStmt)).setTarget((Stmt)oldStmtsToNew.get(((GotoStmt)inlineeStmt).getTarget()));
148                 }
149                        
150             }
151                 
152             // remove original invoke
153
containerUnits.remove(invokeStmt);
154                
155             // resolve name collisions
156
LocalNameStandardizer.v().transform(b, "ji.lns");
157
158             
159         }
160         //System.out.println("locals: "+b.getLocals());
161
//System.out.println("units: "+b.getUnits());
162
}
163
164     private InvokeStmt getFirstSpecialInvoke(Body b){
165         Iterator it = b.getUnits().iterator();
166         while (it.hasNext()){
167             Stmt s = (Stmt)it.next();
168             if (!(s instanceof InvokeStmt)) continue;
169
170             InvokeExpr invokeExpr = ((InvokeStmt)s).getInvokeExpr();
171             if (!(invokeExpr instanceof SpecialInvokeExpr)) continue;
172     
173             return (InvokeStmt)s;
174         }
175         // but there will always be either a call to this() or to super()
176
// from the constructor
177
return null;
178     }
179
180     private IdentityStmt findIdentityStmt(Body b){
181         Iterator it = b.getUnits().iterator();
182         while (it.hasNext()){
183             Stmt s = (Stmt)it.next();
184             if ((s instanceof IdentityStmt) && (((IdentityStmt)s).getRightOp() instanceof ThisRef)){
185                 return (IdentityStmt)s;
186             }
187         }
188         return null;
189     }
190 }
191
Popular Tags