KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > soot > dava > toolkits > base > AST > transformations > DeInliningFinalFields


1 /* Soot - a J*va Optimization Framework
2  * Copyright (C) 2006 Nomair A. Naeem (nomair.naeem@mail.mcgill.ca)
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.dava.toolkits.base.AST.transformations;
21
22 import soot.*;
23 import soot.dava.*;
24 import soot.tagkit.*;
25 import soot.jimple.*;
26 //import soot.jimple.internal.*;
27
//import soot.grimp.internal.*;
28
import soot.dava.internal.AST.*;
29 import soot.dava.internal.asg.*;
30 import soot.dava.internal.javaRep.*;
31 import soot.dava.toolkits.base.AST.analysis.*;
32 //import soot.dava.toolkits.base.AST.traversals.*;
33
//import soot.dava.toolkits.base.AST.structuredAnalysis.*;
34

35
36 import java.util.*;
37
38 /**
39  * Maintained by: Nomair A. Naeem
40  */

41
42
43 /**
44  * CHANGE LOG: 2nd February 2006:
45  *
46  */

47
48 /*
49  * Both static and non-static BUT FINAL fields if initialized with constants get inlined
50  * A final initialized with an object (even if its a string) is NOT inlined
51  * e.g.
52  * public static final String temp = "hello"; //use of temp will get inlined
53  * public static final String temp1 = new String("hello"); //use of temp will NOT get inlined
54  *
55  *
56  If its a static field we can get the info from a tag
57  in the case of a non static we cant decide since the field is initialized inside a constructor and depending
58  on different constructors there coul dbe different values...conservative....
59
60  *
61  * Need to be very clear when a SootField can be used
62  * It can be used in the following places:
63
64  * a, NOT used inside a Synchronized Block ........ HOWEVER ADD IT SINCE I DONT SEE WHY THIS RESTRICTION EXISTS!!! TICK
65  * b, CAN BE USED in a condition TICK
66  * c, CAN BE USED in the for init for update TICK
67  * d, CAN BE USED in a switch TICK
68  * e, CAN BE USED in a stmt TICK
69  *
70  * These are the exact places to look for constants...a constant is
71  * StringConstant
72  * DoubleConstant
73  * FloatConstant
74  * IntConstant (shortype, booltype, charType intType, byteType
75  * LongConstant
76  *
77  */

78
79
80 public class DeInliningFinalFields extends DepthFirstAdapter{
81     SootClass sootClass=null;
82     SootMethod sootMethod=null;
83     DavaBody davaBody=null;
84
85     HashMap finalFields;
86     
87     //ASTParentNodeFinder parentFinder;
88

89     public DeInliningFinalFields(){
90     }
91     public DeInliningFinalFields(boolean verbose){
92     super(verbose);
93     }
94
95
96     public void inASTMethodNode(ASTMethodNode node){
97     DavaBody davaBody = node.getDavaBody();
98     sootMethod = davaBody.getMethod();
99     sootClass = sootMethod.getDeclaringClass();
100
101     finalFields = new HashMap();
102
103     Iterator fieldIt = sootClass.getFields().iterator();
104     while(fieldIt.hasNext()){
105         SootField f = (SootField)fieldIt.next();
106         if(f.isFinal()){
107
108         //check for constant value tags
109
Type fieldType = f.getType();
110         if(fieldType instanceof DoubleType && f.hasTag("DoubleConstantValueTag")){
111             double val = ((DoubleConstantValueTag)f.getTag("DoubleConstantValueTag")).getDoubleValue();
112             finalFields.put(new Double JavaDoc(val),f);
113         }
114         else if (fieldType instanceof FloatType && f.hasTag("FloatConstantValueTag")){
115             float val = ((FloatConstantValueTag)f.getTag("FloatConstantValueTag")).getFloatValue();
116             finalFields.put(new Float JavaDoc(val),f);
117         }
118         else if (fieldType instanceof LongType && f.hasTag("LongConstantValueTag")){
119             long val = ((LongConstantValueTag)f.getTag("LongConstantValueTag")).getLongValue();
120             finalFields.put(new Long JavaDoc(val),f);
121         }
122         else if (fieldType instanceof CharType && f.hasTag("IntegerConstantValueTag")){
123             int val = ((IntegerConstantValueTag)f.getTag("IntegerConstantValueTag")).getIntValue();
124             finalFields.put(new Integer JavaDoc(val),f);
125         }
126         else if (fieldType instanceof BooleanType && f.hasTag("IntegerConstantValueTag")){
127             int val = ((IntegerConstantValueTag)f.getTag("IntegerConstantValueTag")).getIntValue();
128             if (val ==0)
129             finalFields.put(new Boolean JavaDoc(false),f);
130             else
131             finalFields.put(new Boolean JavaDoc(true),f);
132         }
133         else if ( (fieldType instanceof IntType || fieldType instanceof ByteType || fieldType instanceof ShortType) &&
134               f.hasTag("IntegerConstantValueTag")){
135             int val = ((IntegerConstantValueTag)f.getTag("IntegerConstantValueTag")).getIntValue();
136             finalFields.put(new Integer JavaDoc(val),f);
137         }
138         else if(f.hasTag("StringConstantValueTag")){
139             String JavaDoc val = ((StringConstantValueTag)f.getTag("StringConstantValueTag")).getStringValue();
140             //System.out.println("adding string constant"+val);
141
finalFields.put(val,f);
142         }
143         }//end if final
144
}//going through fields
145
}
146
147
148
149
150     /*
151      * StringConstant
152      * DoubleConstant
153      * FloatConstant
154      * IntConstant (shortype, booltype, charType intType, byteType
155      * LongConstant
156      */

157     private boolean isConstant(Value val){
158     if(val instanceof StringConstant || val instanceof DoubleConstant ||
159        val instanceof FloatConstant || val instanceof IntConstant || val instanceof LongConstant){
160         return true;
161     }
162     return false;
163     }
164
165
166
167
168
169     /*
170      * Notice as things stand synchblocks cant have the use of a SootField
171      */

172     public void inASTSynchronizedBlockNode(ASTSynchronizedBlockNode node){
173     //hence nothing is implemented here
174
}
175
176
177
178     public void checkAndSwitch(ValueBox valBox){
179     Value val =valBox.getValue();
180
181     Object JavaDoc finalField = check(val);
182     if(finalField!=null){
183         //System.out.println("Final field with this value exists"+finalField);
184
valBox.setValue(new DStaticFieldRef(((SootField)finalField).makeRef(),true));
185     }
186     //else
187
// System.out.println("Final field not found");
188
}
189
190
191
192     public Object JavaDoc check(Value val){
193     Object JavaDoc finalField=null;
194     if(isConstant(val)){
195         //System.out.println("Found constant in code"+val);
196

197         //can be a byte or short or char......or an int ...in the case of int you also have to check for Booleans
198
if(val instanceof StringConstant){
199         String JavaDoc myString = ((StringConstant)val).toString();
200         myString = myString.substring(1,myString.length()-1);
201         //System.out.println("looking for:"+myString);
202
finalField = finalFields.get(myString);
203         }
204         else if(val instanceof DoubleConstant){
205         String JavaDoc myString = ((DoubleConstant)val).toString();
206         
207         finalField = finalFields.get(new Double JavaDoc(myString));
208         }
209         else if(val instanceof FloatConstant){
210         String JavaDoc myString = ((FloatConstant)val).toString();
211         
212         finalField = finalFields.get(new Float JavaDoc(myString));
213         }
214         else if(val instanceof LongConstant){
215         String JavaDoc myString = ((LongConstant)val).toString();
216         
217         finalField = finalFields.get(new Long JavaDoc(myString.substring(0,myString.length()-1)));
218         }
219         else if(val instanceof IntConstant){
220         String JavaDoc myString = ((IntConstant)val).toString();
221         if(myString.length()==0)
222             return null;
223
224         Type valType = ((IntConstant)val).getType();
225
226
227         boolean charact=false;
228         Integer JavaDoc myInt=null;
229         try{
230             if(myString.charAt(0)=='\''){//character
231
if(myString.length()<2)
232                 return null;
233
234             myInt = new Integer JavaDoc((int)myString.charAt(1));
235             }
236             else
237             myInt = new Integer JavaDoc(myString);
238         }
239         catch(Exception JavaDoc e){
240             //System.out.println("exception occured...gracefully exitting method..string was"+myString);
241
return finalField;
242         }
243
244
245         if(valType instanceof ByteType){
246             finalField = finalFields.get(myInt);
247         }
248         else if(valType instanceof IntType){
249             if(myString.equals("false"))
250             finalField = finalFields.get(new Boolean JavaDoc(false));
251             else if(myString.equals("true"))
252             finalField = finalFields.get(new Boolean JavaDoc(true));
253             else {
254             finalField = finalFields.get(myInt);
255             }
256         }
257         else if(valType instanceof ShortType){
258             finalField = finalFields.get(myInt);
259         }
260         }
261     }
262     return finalField;
263     }
264
265
266
267
268
269
270
271
272
273
274     /*
275       The key in a switch stmt can be a local or a SootField or a value
276       which can contain constant
277
278       Hence the some what indirect approach........notice we will work with valueBoxes so that
279       by changing the value in the value box we can deInline any field
280     */

281     public void inASTSwitchNode(ASTSwitchNode node){
282     Value val = (Value)node.get_Key();
283
284     if(isConstant(val)){
285         //find if there is a SootField with this constant
286
//System.out.println("Found constant as key to switch");
287

288         checkAndSwitch(node.getKeyBox());
289         return;
290     }
291     //val is not a constant but it might have other constants in it
292

293     Iterator it = val.getUseBoxes().iterator();
294     while(it.hasNext()){
295         ValueBox tempBox = (ValueBox)it.next();
296         //System.out.println("Checking useBox of switch key");
297
checkAndSwitch(tempBox);
298     }
299     }
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314     public void inASTStatementSequenceNode(ASTStatementSequenceNode node){
315     List statements = node.getStatements();
316     Iterator it = statements.iterator();
317     
318     while(it.hasNext()){
319         AugmentedStmt as = (AugmentedStmt)it.next();
320         Stmt s = as.get_Stmt();
321         Iterator tempIt = s.getUseBoxes().iterator();
322         while(tempIt.hasNext()){
323         ValueBox tempBox = (ValueBox)tempIt.next();
324         //System.out.println("Checking useBox of stmt");
325
checkAndSwitch(tempBox);
326         }
327     }
328     }
329
330
331
332
333
334
335
336
337   public void inASTForLoopNode(ASTForLoopNode node){
338
339     //checking uses in init
340
List init = node.getInit();
341     Iterator it = init.iterator();
342     while(it.hasNext()){
343         AugmentedStmt as = (AugmentedStmt)it.next();
344         Stmt s = as.get_Stmt();
345         Iterator tempIt = s.getUseBoxes().iterator();
346         while(tempIt.hasNext()){
347         ValueBox tempBox = (ValueBox)tempIt.next();
348         //System.out.println("Checking useBox of init stmt");
349
checkAndSwitch(tempBox);
350         }
351     }
352
353     //checking uses in condition
354
ASTCondition cond = node.get_Condition();
355     checkConditionalUses(cond,node);
356
357     
358     //checking uses in update
359
List update = node.getUpdate();
360     it = update.iterator();
361     while(it.hasNext()){
362         AugmentedStmt as = (AugmentedStmt)it.next();
363         Stmt s = as.get_Stmt();
364         Iterator tempIt = s.getUseBoxes().iterator();
365         while(tempIt.hasNext()){
366         ValueBox tempBox = (ValueBox)tempIt.next();
367         //System.out.println("Checking useBox of update stmt");
368
checkAndSwitch(tempBox);
369         }
370     }
371     }
372
373
374
375     /*
376      * checking for unary conditions doesnt matter since this was definetly lost.
377      */

378     public void checkConditionalUses(Object JavaDoc cond,ASTNode node){
379     if(cond instanceof ASTAggregatedCondition){
380         checkConditionalUses((((ASTAggregatedCondition)cond).getLeftOp()),node);
381         checkConditionalUses(((ASTAggregatedCondition)cond).getRightOp(),node );
382         return;
383     }
384     else if(cond instanceof ASTBinaryCondition){
385         //get uses from binaryCondition
386
Value val = ((ASTBinaryCondition)cond).getConditionExpr();
387         Iterator tempIt = val.getUseBoxes().iterator();
388         while(tempIt.hasNext()){
389         ValueBox tempBox = (ValueBox)tempIt.next();
390         //System.out.println("Checking useBox of binary condition");
391
checkAndSwitch(tempBox);
392         }
393     }
394     }
395
396
397
398
399
400
401
402
403     /*
404      * The condition of an if node can use a local
405      *
406      */

407     public void inASTIfNode(ASTIfNode node){
408     ASTCondition cond = node.get_Condition();
409     checkConditionalUses(cond,node);
410     }
411
412
413     /*
414      * The condition of an ifElse node can use a local
415      *
416      */

417     public void inASTIfElseNode(ASTIfElseNode node){
418     ASTCondition cond = node.get_Condition();
419     checkConditionalUses(cond,node);
420     }
421
422
423
424
425     /*
426      * The condition of a while node can use a local
427      *
428      */

429     public void inASTWhileNode(ASTWhileNode node){
430     ASTCondition cond = node.get_Condition();
431     checkConditionalUses(cond,node);
432     }
433
434
435
436     /*
437      * The condition of a doWhile node can use a local
438      *
439      */

440     public void inASTDoWhileNode(ASTDoWhileNode node){
441     ASTCondition cond = node.get_Condition();
442     checkConditionalUses(cond,node);
443     }
444 }
Popular Tags