KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > soot > jimple > toolkits > annotation > arraycheck > ClassFieldAnalysis


1 /* Soot - a J*va Optimization Framework
2  * Copyright (C) 2000 Feng Qian
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 /*
21  * Modified by the Sable Research Group and others 1997-1999.
22  * See the 'credits' file distributed with Soot for the complete list of
23  * contributors. (Soot is distributed at http://www.sable.mcgill.ca/soot)
24  */

25
26 package soot.jimple.toolkits.annotation.arraycheck;
27 import soot.options.*;
28
29 import soot.*;
30 import soot.jimple.*;
31 import soot.util.*;
32 import soot.tagkit.*;
33 import soot.toolkits.scalar.*;
34 import soot.toolkits.graph.*;
35 import java.io.*;
36 import java.util.*;
37
38
39 public class ClassFieldAnalysis
40 {
41     public ClassFieldAnalysis( Singletons.Global g ) {}
42     public static ClassFieldAnalysis v() { return G.v().soot_jimple_toolkits_annotation_arraycheck_ClassFieldAnalysis(); }
43
44     private boolean final_in = true;
45     private boolean private_in = true;
46
47     /* A map hold class object to other information
48      *
49      * SootClass --> FieldInfoTable
50      */

51  
52     private Map classToFieldInfoMap = new HashMap();
53   
54     protected void internalTransform(SootClass c)
55     {
56     if (classToFieldInfoMap.containsKey(c))
57         return;
58      
59     /* Summerize class information here. */
60     Date start = new Date();
61     if (Options.v().verbose())
62         G.v().out.println("[] ClassFieldAnalysis started on : "
63                    +start+" for "
64                    +c.getPackageName()+c.getName());
65     
66     Hashtable fieldInfoTable = new Hashtable();
67     classToFieldInfoMap.put(c, fieldInfoTable);
68     
69     /* Who is the candidate for analysis?
70        Int, Array, field. Also it should be PRIVATE now.
71     */

72     HashSet candidSet = new HashSet();
73
74     int arrayTypeFieldNum = 0;
75
76     Iterator fieldIt = c.getFields().iterator();
77     while(fieldIt.hasNext())
78     {
79         SootField field = (SootField)fieldIt.next();
80         int modifiers = field.getModifiers();
81
82         Type type = field.getType();
83         if (type instanceof ArrayType)
84         {
85         if ( (final_in
86               && ((modifiers & Modifier.FINAL) != 0))
87              || (private_in
88              && ((modifiers & Modifier.PRIVATE) != 0)))
89         {
90             candidSet.add(field);
91             arrayTypeFieldNum ++;
92         }
93         }
94     }
95
96     if (arrayTypeFieldNum == 0)
97     {
98         if (Options.v().verbose())
99         G.v().out.println("[] ClassFieldAnalysis finished with nothing");
100         return;
101     }
102
103     /* For FINAL field, it only needs to scan the <clinit> and <init> methods. */
104
105     /* For PRIVATE field, <clinit> is scanned to make sure that it is always
106            assigned a value before other uses. And no other assignment in other methods.*/

107        
108
109     /* The fastest way to determine the value of one field may get.
110        Scan all method to get all definitions, and summerize the final value.
111        For PRIVATE STATIC field, if it is not always assigned value, it may count null pointer
112        exception before array exception */

113
114     Iterator methodIt = c.methodIterator();
115     while (methodIt.hasNext())
116     {
117         ScanMethod ((SootMethod)methodIt.next(),
118             candidSet,
119             fieldInfoTable);
120     }
121
122     Date finish = new Date();
123     if (Options.v().verbose())
124     {
125         long runtime=finish.getTime()-start.getTime();
126         long mins=runtime/60000;
127         long secs=(runtime%60000)/1000;
128         G.v().out.println("[] ClassFieldAnalysis finished normally. "
129                    +"It took "+mins+" mins and "+secs+" secs.");
130     }
131     }
132
133     public Object JavaDoc getFieldInfo(SootField field)
134     {
135     SootClass c = field.getDeclaringClass();
136
137     Hashtable fieldInfoTable = (Hashtable)classToFieldInfoMap.get(c);
138
139     if (fieldInfoTable == null)
140     {
141         internalTransform(c);
142         fieldInfoTable = (Hashtable)classToFieldInfoMap.get(c);
143     }
144     
145     return fieldInfoTable.get(field);
146     }
147
148     /* method, to be scanned
149        candidates, the candidate set of fields, fields with value TOP are moved out of the set.
150        fieldinfo, keep the field -> value.
151     */

152
153     public void ScanMethod (SootMethod method,
154                    Set candidates,
155                    Hashtable fieldinfo)
156     {
157     if (!method.isConcrete())
158         return;
159
160     Body body = method.retrieveActiveBody();
161
162     if (body == null)
163         return;
164
165     /* no array locals, then definitely it has no array type field references. */
166     {
167         boolean hasArrayLocal = false;
168
169         Chain locals = body.getLocals();
170
171         Iterator localIt = locals.iterator();
172         while (localIt.hasNext())
173         {
174         Local local = (Local)localIt.next();
175         Type type = local.getType();
176
177         if (type instanceof ArrayType)
178         {
179             hasArrayLocal = true;
180             break;
181         }
182         }
183
184         if (!hasArrayLocal)
185         {
186         return;
187         }
188     }
189
190     /* only take care of the first dimension of array size */
191     /* check the assignment of fields. */
192     
193     /* Linearly scan the method body, if it has field references in candidate set. */
194     /* Only a.f = ... needs consideration.
195        this.f, or other.f are treated as same because we summerize the field as a class's field.
196     */

197
198     HashMap stmtfield = new HashMap();
199
200     {
201         Iterator unitIt = body.getUnits().iterator();
202         while (unitIt.hasNext())
203         {
204         Stmt stmt = (Stmt)unitIt.next();
205         if (stmt.containsFieldRef())
206         {
207             Value leftOp = ((AssignStmt)stmt).getLeftOp();
208             if (leftOp instanceof FieldRef)
209             {
210             FieldRef fref = (FieldRef)leftOp;
211             SootField field = fref.getField();
212
213             if (candidates.contains(field))
214                 stmtfield.put(stmt, field);
215             }
216         }
217         }
218
219         if (stmtfield.size() == 0)
220         {
221         return;
222         }
223     }
224
225
226     if (Options.v().verbose())
227     {
228         G.v().out.println("[] ScanMethod for field started.");
229     }
230
231     /* build D/U web, find the value of each candidate */
232     {
233             UnitGraph g = new ExceptionalUnitGraph(body);
234         LocalDefs localDefs = new SmartLocalDefs(g, new SimpleLiveLocals(g));
235         
236         Set entries = stmtfield.entrySet();
237
238         Iterator entryIt = entries.iterator();
239         while (entryIt.hasNext())
240         {
241         Map.Entry entry = (Map.Entry)entryIt.next();
242         Stmt where = (Stmt)entry.getKey();
243         SootField which = (SootField)entry.getValue();
244
245         IntValueContainer length = new IntValueContainer();
246
247         // take out the right side of assign stmt
248
Value rightOp = ((AssignStmt)where).getRightOp();
249
250         if (rightOp instanceof Local)
251         {
252             // tracing down the defs of right side local.
253
Local local = (Local)rightOp;
254             DefinitionStmt usestmt = (DefinitionStmt)where;
255
256             while (length.isBottom())
257             {
258             List defs = localDefs.getDefsOfAt(local, usestmt);
259             if (defs.size() == 1)
260             {
261                 usestmt = (DefinitionStmt)defs.get(0);
262
263                 if (Options.v().debug())
264                 G.v().out.println(" "+usestmt);
265
266                 Value tmp_rhs = usestmt.getRightOp();
267                 if ( (tmp_rhs instanceof NewArrayExpr)
268                  ||(tmp_rhs instanceof NewMultiArrayExpr))
269                 {
270                 Value size;
271
272                 if (tmp_rhs instanceof NewArrayExpr)
273                     size = ((NewArrayExpr)tmp_rhs).getSize();
274                 else
275                     size = ((NewMultiArrayExpr)tmp_rhs).getSize(0);
276                 
277                 if (size instanceof IntConstant)
278                     length.setValue(((IntConstant)size).value);
279                 else
280                 if (size instanceof Local)
281                 {
282                     local = (Local)size;
283                     
284                     // defs = localDefs.getDefsOfAt((Local)size, (Unit)usestmt);
285

286                     continue;
287                 }
288                 else
289                     length.setTop();
290                 }
291                 else
292                 if (tmp_rhs instanceof IntConstant)
293                 {
294                 length.setValue(((IntConstant)tmp_rhs).value);
295                 }
296                 else
297                 if (tmp_rhs instanceof Local)
298                 {
299                 // defs = localDefs.getDefsOfAt((Local)tmp_rhs, usestmt);
300
local = (Local)tmp_rhs;
301
302                 continue;
303                 }
304                 else
305                 length.setTop();
306             }
307             else
308                 length.setTop();
309             }
310         }
311         else
312             /* it could be null */
313             continue;
314
315         IntValueContainer oldv = (IntValueContainer)fieldinfo.get(which);
316
317         /* the length is top, set the field to top */
318         if (length.isTop())
319         {
320             if (oldv == null)
321             fieldinfo.put(which, length.dup());
322             else
323             oldv.setTop();
324
325             /* remove from the candidate set. */
326             candidates.remove(which);
327         }
328         else
329         if (length.isInteger())
330         {
331             if (oldv == null)
332             {
333             fieldinfo.put(which, length.dup());
334             }
335             else
336             {
337             if (oldv.isInteger()
338               && oldv.getValue() != length.getValue())
339             {
340                 oldv.setTop();
341                 candidates.remove(which);
342             }
343             }
344         }
345         }
346     }
347     
348     if (Options.v().verbose())
349     {
350         G.v().out.println("[] ScanMethod finished.");
351     }
352     }
353 }
354
355
356
357
358
Popular Tags