KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > soot > jimple > toolkits > typing > TypeNode


1 /* Soot - a J*va Optimization Framework
2  * Copyright (C) 1997-2000 Etienne Gagnon. All rights reserved.
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
27 package soot.jimple.toolkits.typing;
28
29 import soot.*;
30 import soot.jimple.*;
31 import soot.util.*;
32 import java.util.*;
33
34 /**
35  * Each instance of this class represents one type in the class hierarchy (or basic types).
36  **/

37 class TypeNode
38 {
39   private static final boolean DEBUG = false;
40
41   private final int id;
42   private final Type type;
43   private final ClassHierarchy hierarchy;
44   
45   private TypeNode parentClass;
46   private TypeNode element;
47   private TypeNode array;
48
49   private List parents = Collections.EMPTY_LIST;
50   private final BitVector ancestors = new BitVector(0);
51   private final BitVector descendants = new BitVector(0);
52     
53   public TypeNode(int id, Type type, ClassHierarchy hierarchy)
54   {
55     if(type == null || hierarchy == null)
56       {
57     throw new InternalTypingException();
58       }
59       
60     if(!((type instanceof PrimType) || (type instanceof RefType) ||
61      (type instanceof ArrayType) || (type instanceof NullType)))
62       {
63     G.v().out.println("Unhandled type: " + type);
64     throw new InternalTypingException();
65       }
66
67     this.id = id;
68     this.type = type;
69     this.hierarchy = hierarchy;
70
71     if(DEBUG)
72       {
73     G.v().out.println("creating node " + this);
74       }
75   }
76   
77   public TypeNode(int id, RefType type, ClassHierarchy hierarchy)
78   {
79     this(id, (Type) type, hierarchy);
80     
81     {
82       SootClass sClass = type.getSootClass();
83       if( sClass == null ) throw new RuntimeException JavaDoc( "Oops, forgot to load "+type );
84       List plist = new LinkedList();
85       
86       if(sClass.hasSuperclass() &&
87      !sClass.getName().equals("java.lang.Object"))
88     {
89       TypeNode parent = hierarchy.typeNode(RefType.v(sClass.getSuperclass().getName()));
90       plist.add(parent);
91       parentClass = parent;
92     }
93
94       for(Iterator i = sClass.getInterfaces().iterator(); i.hasNext();)
95     {
96       TypeNode parent = hierarchy.typeNode(RefType.v(((SootClass) i.next()).getName()));
97       plist.add(parent);
98     }
99
100       parents = Collections.unmodifiableList(plist);
101     }
102         
103     descendants.set(hierarchy.NULL.id);
104     hierarchy.NULL.ancestors.set(id);
105
106     for( Iterator parentIt = parents.iterator(); parentIt.hasNext(); ) {
107
108         final TypeNode parent = (TypeNode) parentIt.next();
109     ancestors.set(parent.id);
110     ancestors.or(parent.ancestors);
111     parent.fixDescendants(id);
112       }
113   }
114     
115   public TypeNode(int id, ArrayType type, ClassHierarchy hierarchy)
116   {
117     this(id, (Type) type, hierarchy);
118
119     if(type.numDimensions < 1)
120       {
121     throw new InternalTypingException();
122       }
123
124     if(type.numDimensions == 1)
125       {
126     element = hierarchy.typeNode(type.baseType);
127       }
128     else
129       {
130     element = hierarchy.typeNode(ArrayType.v(type.baseType, type.numDimensions - 1));
131       }
132
133     if(element != hierarchy.INT)
134       {
135     if(element.array != null)
136       {
137         throw new InternalTypingException();
138       }
139     
140     element.array = this;
141       }
142     
143     {
144       List plist = new LinkedList();
145       if(type.baseType instanceof RefType)
146     {
147       RefType baseType = (RefType) type.baseType;
148       SootClass sClass = baseType.getSootClass();
149       if(sClass.hasSuperclass() && !sClass.getName().equals("java.lang.Object"))
150         {
151           TypeNode parent = hierarchy.typeNode(ArrayType.v(RefType.v(sClass.getSuperclass().getName()), type.numDimensions));
152           plist.add(parent);
153           parentClass = parent;
154         }
155       else if(type.numDimensions == 1)
156         {
157           plist.add(hierarchy.OBJECT);
158
159           // hack for J2ME library, reported by Stephen Cheng
160
if (!G.v().isJ2ME) {
161         plist.add(hierarchy.CLONEABLE);
162         plist.add(hierarchy.SERIALIZABLE);
163           }
164
165           parentClass = hierarchy.OBJECT;
166         }
167       else
168         {
169           plist.add(hierarchy.typeNode(ArrayType.v(hierarchy.OBJECT.type(), type.numDimensions - 1)));
170
171           // hack for J2ME library, reported by Stephen Cheng
172
if (!G.v().isJ2ME) {
173         plist.add(hierarchy.typeNode(ArrayType.v(hierarchy.CLONEABLE.type(), type.numDimensions - 1)));
174         plist.add(hierarchy.typeNode(ArrayType.v(hierarchy.SERIALIZABLE.type(), type.numDimensions - 1)));
175           }
176
177           parentClass = hierarchy.typeNode(ArrayType.v(hierarchy.OBJECT.type(), type.numDimensions - 1));
178         }
179
180       for(Iterator i = sClass.getInterfaces().iterator(); i.hasNext(); )
181         {
182           TypeNode parent = hierarchy.typeNode(ArrayType.v(RefType.v(((SootClass) i.next()).getName()), type.numDimensions));
183           plist.add(parent);
184         }
185     }
186       else if(type.numDimensions == 1)
187     {
188       plist.add(hierarchy.OBJECT);
189
190       // hack for J2ME library, reported by Stephen Cheng
191
if (!G.v().isJ2ME) {
192         plist.add(hierarchy.CLONEABLE);
193         plist.add(hierarchy.SERIALIZABLE);
194       }
195
196       parentClass = hierarchy.OBJECT;
197     }
198       else
199     {
200       plist.add(hierarchy.typeNode(ArrayType.v(hierarchy.OBJECT.type(), type.numDimensions - 1)));
201       // hack for J2ME library, reported by Stephen Cheng
202
if (!G.v().isJ2ME) {
203         plist.add(hierarchy.typeNode(ArrayType.v(hierarchy.CLONEABLE.type(), type.numDimensions - 1)));
204         plist.add(hierarchy.typeNode(ArrayType.v(hierarchy.SERIALIZABLE.type(), type.numDimensions - 1)));
205       }
206
207       parentClass = hierarchy.typeNode(ArrayType.v(hierarchy.OBJECT.type(), type.numDimensions - 1));
208     }
209             
210       parents = Collections.unmodifiableList(plist);
211     }
212
213     descendants.set(hierarchy.NULL.id);
214     hierarchy.NULL.ancestors.set(id);
215
216     for( Iterator parentIt = parents.iterator(); parentIt.hasNext(); ) {
217
218         final TypeNode parent = (TypeNode) parentIt.next();
219     ancestors.set(parent.id);
220     ancestors.or(parent.ancestors);
221     parent.fixDescendants(id);
222       }
223   }
224
225   /** Adds the given node to the list of descendants of this node and its ancestors. **/
226   private void fixDescendants(int id)
227   {
228     if(descendants.get(id))
229       {
230     return;
231       }
232
233     for( Iterator parentIt = parents.iterator(); parentIt.hasNext(); ) {
234
235         final TypeNode parent = (TypeNode) parentIt.next();
236     parent.fixDescendants(id);
237       }
238
239     descendants.set(id);
240   }
241
242   /** Returns the unique id of this type node. **/
243   public int id()
244   {
245     return id;
246   }
247
248   /** Returns the type represented by this type node. **/
249   public Type type()
250   {
251     return type;
252   }
253
254   public boolean hasAncestor(TypeNode typeNode)
255   {
256     return ancestors.get(typeNode.id);
257   }
258
259   public boolean hasAncestorOrSelf(TypeNode typeNode)
260   {
261     if(typeNode == this)
262       return true;
263
264     return ancestors.get(typeNode.id);
265   }
266
267   public boolean hasDescendant(TypeNode typeNode)
268   {
269     return descendants.get(typeNode.id);
270   }
271
272   public boolean hasDescendantOrSelf(TypeNode typeNode)
273   {
274     if(typeNode == this)
275       return true;
276
277     return descendants.get(typeNode.id);
278   }
279
280   public List parents()
281   {
282     return parents;
283   }
284
285   public TypeNode parentClass()
286   {
287     return parentClass;
288   }
289
290   public String JavaDoc toString()
291   {
292     return type.toString()+ "(" + id + ")";
293   }
294
295   public TypeNode lca(TypeNode type) throws TypeException
296   {
297     TypeNode initial = type;
298
299     if(type == null)
300       {
301     throw new InternalTypingException();
302       }
303
304     if(type == this)
305       {
306     return this;
307       }
308
309     if(hasAncestor(type))
310       {
311     return type;
312       }
313
314     if(hasDescendant(type))
315       {
316     return this;
317       }
318
319     do
320       {
321     type = type.parentClass;
322     
323     if(type == null)
324       {
325         try
326           {
327         TypeVariable.error("Type Error(12)");
328           }
329         catch(TypeException e)
330           {
331                 if(DEBUG) e.printStackTrace();
332         throw e;
333           }
334       }
335       }
336     while(!hasAncestor(type));
337
338     return type;
339   }
340
341   public TypeNode lcaIfUnique(TypeNode type) throws TypeException
342   {
343     TypeNode initial = type;
344
345     if(type == null)
346       {
347     throw new InternalTypingException();
348       }
349
350     if(type == this)
351       {
352     return this;
353       }
354
355     if(hasAncestor(type))
356       {
357     return type;
358       }
359
360     if(hasDescendant(type))
361       {
362     return this;
363       }
364
365     do
366       {
367     if(type.parents.size() == 1)
368       {
369         type = (TypeNode) type.parents.get(0);
370       }
371     else
372       {
373         if(DEBUG)
374           {
375         G.v().out.println("lca " + initial + " (" + type + ") & " + this + " =");
376         for(Iterator i = type.parents.iterator(); i.hasNext(); )
377           {
378             G.v().out.println(" " + i.next());
379           }
380           }
381         return null;
382       }
383       }
384     while(!hasAncestor(type));
385
386     return type;
387   }
388
389   public boolean hasElement()
390   {
391     return element != null;
392   }
393
394   public TypeNode element()
395   {
396     if(element == null)
397       {
398     throw new InternalTypingException();
399       }
400     
401     return element;
402   }
403
404   public TypeNode array()
405   {
406     if(array != null)
407       {
408     return array;
409       }
410
411     if(type instanceof ArrayType)
412       {
413     ArrayType atype = (ArrayType) type;
414     array = hierarchy.typeNode(ArrayType.v(atype.baseType, atype.numDimensions + 1));
415     return array;
416       }
417
418     if(type instanceof PrimType || type instanceof RefType)
419       {
420     array = hierarchy.typeNode(ArrayType.v(type, 1));
421     return array;
422       }
423
424     throw new InternalTypingException();
425   }
426
427   public boolean isNull()
428   {
429     if(type instanceof NullType)
430       {
431     return true;
432       }
433
434     return false;
435   }
436
437   public boolean isClass()
438   {
439     if(type instanceof ArrayType ||
440        type instanceof NullType ||
441        (type instanceof RefType &&
442     !((RefType) type).getSootClass().isInterface()))
443       {
444     return true;
445       }
446
447     return false;
448   }
449
450   public boolean isClassOrInterface()
451   {
452     if(type instanceof ArrayType ||
453        type instanceof NullType ||
454        type instanceof RefType)
455       {
456     return true;
457       }
458
459     return false;
460   }
461
462   public boolean isArray()
463   {
464     if(type instanceof ArrayType ||
465        type instanceof NullType)
466       {
467     return true;
468       }
469
470     return false;
471   }
472 }
473
Popular Tags