View Javadoc

1   // CompilationState.java, created Oct 4, 2003 11:09:20 PM by joewhaley
2   // Copyright (C) 2003 John Whaley <jwhaley@alum.mit.edu>
3   // Licensed under the terms of the GNU LGPL; see COPYING for details.
4   package joeq.Compiler;
5   
6   import java.util.Collection;
7   import java.util.HashMap;
8   import java.util.Set;
9   import joeq.Class.PrimordialClassLoader;
10  import joeq.Class.jq_Class;
11  import joeq.Class.jq_Member;
12  import joeq.Class.jq_Method;
13  import joeq.Class.jq_Type;
14  import joeq.Compiler.Quad.Quad;
15  import joeq.Compiler.Quad.Operator.CheckCast;
16  import joeq.Compiler.Quad.Operator.Invoke;
17  import joeq.Main.jq;
18  import joeq.Runtime.TypeCheck;
19  import joeq.UTF.Utf8;
20  import joeq.Util.Templates.List;
21  import joeq.Util.Templates.UnmodifiableList;
22  
23  /***
24   * CompilationState
25   * 
26   * @author John Whaley
27   * @version $Id: CompilationState.java 1931 2004-09-22 22:17:47Z joewhaley $
28   */
29  public abstract class CompilationState implements CompilationConstants {
30      
31      /*** Default compilation state object.
32       * This is here temporarily until we remove all static calls in the compiler. */
33      public static CompilationState DEFAULT;
34      
35      public static final boolean VerifyAssertions = true;
36      
37      public abstract boolean needsDynamicLink(jq_Method method, jq_Member member);
38      public abstract boolean needsDynamicLink(jq_Method method, jq_Type type);
39      
40      public abstract jq_Member tryResolve(jq_Member m);
41      public abstract jq_Member resolve(jq_Member m);
42      
43      public abstract byte isSubtype(jq_Type t1, jq_Type t2);
44      public abstract jq_Type findCommonSuperclass(jq_Type t1, jq_Type t2);
45      
46      public abstract byte declaresInterface(jq_Class klass, Collection interfaces);
47      public abstract byte implementsInterface(jq_Class klass, jq_Class inter);
48      
49      public abstract jq_Type getOrCreateType(Utf8 desc);
50  
51      public List.jq_Class getThrownExceptions(Quad q) {
52          return q.getOperator().getThrownExceptions();
53      }
54      
55      static {
56          if (jq.nullVM) {
57              DEFAULT = new StaticCompilation();
58          } else if (jq.IsBootstrapping) {
59              DEFAULT = new BootstrapCompilation();
60          } else {
61              DEFAULT = new DynamicCompilation();
62          }
63      }
64      
65      public static class StaticCompilation extends CompilationState {
66  
67          /* (non-Javadoc)
68           * @see joeq.Compiler.CompilationState#needsDynamicLink(Class.jq_Method, Class.jq_Member)
69           */
70          public boolean needsDynamicLink(jq_Method method, jq_Member member) {
71              if (member.isPrepared()) return false;
72              member.getDeclaringClass().prepare();
73              return !member.isPrepared();
74          }
75  
76          /* (non-Javadoc)
77           * @see joeq.Compiler.CompilationState#needsDynamicLink(Class.jq_Method, Class.jq_Type)
78           */
79          public boolean needsDynamicLink(jq_Method method, jq_Type type) {
80              type.prepare();
81              return !type.isPrepared();
82          }
83  
84          /* (non-Javadoc)
85           * @see joeq.Compiler.CompilationState#tryResolve(Class.jq_Member)
86           */
87          public jq_Member tryResolve(jq_Member m) {
88              try {
89                  m = m.resolve();
90              } catch (Error _) { }
91              return m;
92          }
93  
94          /* (non-Javadoc)
95           * @see joeq.Compiler.CompilationState#resolve(Class.jq_Member)
96           */
97          public jq_Member resolve(jq_Member m) {
98              return m.resolve();
99          }
100 
101         /* (non-Javadoc)
102          * @see joeq.Compiler.CompilationState#isSubtype(Class.jq_Type, Class.jq_Type)
103          */
104         public byte isSubtype(jq_Type t1, jq_Type t2) {
105             t1.prepare(); t2.prepare();
106             return t1.isSubtypeOf(t2) ? YES : NO;
107         }
108 
109         /* (non-Javadoc)
110          * @see joeq.Compiler.CompilationState#findCommonSuperclass(Class.jq_Type, Class.jq_Type)
111          */
112         public jq_Type findCommonSuperclass(jq_Type t1, jq_Type t2) {
113             return TypeCheck.findCommonSuperclass(t1, t2, true);
114         }
115 
116         /* (non-Javadoc)
117          * @see joeq.Compiler.CompilationState#declaresInterface(Class.jq_Class, java.util.Collection)
118          */
119         public byte declaresInterface(jq_Class klass, Collection interfaces) {
120             return TypeCheck.declaresInterface(klass, interfaces, true);
121         }
122 
123         /* (non-Javadoc)
124          * @see joeq.Compiler.CompilationState#implementsInterface(Class.jq_Class, Class.jq_Class)
125          */
126         public byte implementsInterface(jq_Class klass, jq_Class inter) {
127             klass.prepare();
128             inter.prepare();
129             return klass.isSubtypeOf(inter) ? YES : NO;
130         }
131 
132         /* (non-Javadoc)
133          * @see joeq.Compiler.CompilationState#getOrCreateType(UTF.Utf8)
134          */
135         public jq_Type getOrCreateType(Utf8 desc) {
136             return PrimordialClassLoader.loader.getOrCreateBSType(desc);
137         }
138 
139         /*** Assume jq_Method.getThrownExceptions() returns correct information */
140         public static boolean ASSUME_CORRECT_EXCEPTIONS = true;
141 
142         /* (non-Javadoc)
143          * @see joeq.Compiler.CompilationState#getThrownExceptions(Quad)
144          */
145         public List.jq_Class getThrownExceptions(Quad q) {
146             if (q.getOperator() == CheckCast.CHECKCAST.INSTANCE) {
147                 return new UnmodifiableList.jq_Class(PrimordialClassLoader
148                         .getJavaLangClassCastException());
149             }
150             if (ASSUME_CORRECT_EXCEPTIONS && q.getOperator() instanceof Invoke) {
151                 jq_Method m = (jq_Method) resolve(Invoke.getMethod(q)
152                         .getMethod());
153                 UnmodifiableList.jq_Class exclist;
154                 exclist = (UnmodifiableList.jq_Class) cachedThrownExcListByMethod
155                         .get(m);
156                 if (exclist != null)
157                     return exclist;
158                 /*
159                  * Exception lists reflect exactly what was given in the
160                  * 'throws' clause at compile time. These lists can (and do)
161                  * contain redundant declarations of various kinds of Errors
162                  * and RuntimeExceptions. It is possible to have entries that
163                  * are superclasses of other entries in this list. We always
164                  * add Error and RuntimeException because every method can
165                  * throw these. See also VM Spec Section 4.7.4
166                  */
167                 jq_Class[] exc = m.getThrownExceptionsTable();
168                 int exclistLength = defaultThrowables.length;
169                 if (exc != null)
170                     exclistLength += exc.length;
171                 jq_Class[] tlist = new jq_Class[exclistLength];
172                 System.arraycopy(defaultThrowables, 0, tlist, 0,
173                         defaultThrowables.length);
174                 if (exc != null)
175                     System.arraycopy(exc, 0, tlist, defaultThrowables.length,
176                             exc.length);
177                 // potential for memory savings here: could sort and intern
178                 // identical exclists
179                 cachedThrownExcListByMethod.put(m,
180                         exclist = new UnmodifiableList.jq_Class(tlist));
181                 return exclist;
182             }
183             return super.getThrownExceptions(q);
184         }
185         private static HashMap/* <jq_Method, UnmodifiableList.jq_Class> */cachedThrownExcListByMethod = new HashMap();
186         private static final jq_Class[] defaultThrowables = new jq_Class[]{
187                 PrimordialClassLoader.getJavaLangRuntimeException(),
188                 PrimordialClassLoader.getJavaLangError()};
189     }
190 
191     public static class BootstrapCompilation extends CompilationState {
192 
193         Set/*<jq_Type>*/ boot_types;
194 
195         public void setBootTypes(Set boot_types) {
196             this.boot_types = boot_types;
197         }
198 
199         /* (non-Javadoc)
200          * @see joeq.Compiler.CompilationState#needsDynamicLink(Class.jq_Method, Class.jq_Member)
201          */
202         public boolean needsDynamicLink(jq_Method method, jq_Member member) {
203             if (member.isPrepared()) return false;
204             return boot_types == null ||
205                    !boot_types.contains(member.getDeclaringClass());
206         }
207 
208         /* (non-Javadoc)
209          * @see joeq.Compiler.CompilationState#needsDynamicLink(Class.jq_Method, Class.jq_Type)
210          */
211         public boolean needsDynamicLink(jq_Method method, jq_Type type) {
212             if (type.isPrepared()) return false;
213             return boot_types == null ||
214                    !boot_types.contains(type);
215         }
216 
217         /* (non-Javadoc)
218          * @see joeq.Compiler.CompilationState#tryResolve(Class.jq_Member)
219          */
220         public jq_Member tryResolve(jq_Member m) {
221             try {
222                 m = m.resolve();
223             } catch (Error _) { }
224             return m;
225         }
226 
227         /* (non-Javadoc)
228          * @see joeq.Compiler.CompilationState#resolve(Class.jq_Member)
229          */
230         public jq_Member resolve(jq_Member m) {
231             return m.resolve();
232         }
233 
234         /* (non-Javadoc)
235          * @see joeq.Compiler.CompilationState#isSubtype(Class.jq_Type, Class.jq_Type)
236          */
237         public byte isSubtype(jq_Type t1, jq_Type t2) {
238             return TypeCheck.isAssignable_noload(t1, t2);
239         }
240 
241         /* (non-Javadoc)
242          * @see joeq.Compiler.CompilationState#findCommonSuperclass(Class.jq_Type, Class.jq_Type)
243          */
244         public jq_Type findCommonSuperclass(jq_Type t1, jq_Type t2) {
245             return TypeCheck.findCommonSuperclass(t1, t2, false);
246         }
247 
248         /* (non-Javadoc)
249          * @see joeq.Compiler.CompilationState#declaresInterface(Class.jq_Class, java.util.Collection)
250          */
251         public byte declaresInterface(jq_Class klass, Collection interfaces) {
252             return TypeCheck.declaresInterface(klass, interfaces, false);
253         }
254 
255         /* (non-Javadoc)
256          * @see joeq.Compiler.CompilationState#implementsInterface(Class.jq_Class, Class.jq_Class)
257          */
258         public byte implementsInterface(jq_Class klass, jq_Class inter) {
259             return TypeCheck.implementsInterface_noload(klass, inter);
260         }
261 
262         /* (non-Javadoc)
263          * @see joeq.Compiler.CompilationState#getOrCreateType(UTF.Utf8)
264          */
265         public jq_Type getOrCreateType(Utf8 desc) {
266             return PrimordialClassLoader.loader.getOrCreateBSType(desc);
267         }
268         
269     }
270     
271     public static class DynamicCompilation extends CompilationState {
272 
273         /* (non-Javadoc)
274          * @see joeq.Compiler.CompilationState#needsDynamicLink(Class.jq_Method, Class.jq_Member)
275          */
276         public boolean needsDynamicLink(jq_Method method, jq_Member member) {
277             if (member.isStatic() &&
278                 method.getDeclaringClass() != member.getDeclaringClass() &&
279                 !member.getDeclaringClass().isClsInitialized())
280                 return true;
281             if (member instanceof jq_Method)
282                 return !member.isInitialized();
283             return !member.isPrepared();
284         }
285 
286         /* (non-Javadoc)
287          * @see joeq.Compiler.CompilationState#needsDynamicLink(Class.jq_Method, Class.jq_Type)
288          */
289         public boolean needsDynamicLink(jq_Method method, jq_Type type) {
290             return method.getDeclaringClass() != type &&
291                    !type.isClsInitialized();
292         }
293 
294         /* (non-Javadoc)
295          * @see joeq.Compiler.CompilationState#tryResolve(Class.jq_Member)
296          */
297         public jq_Member tryResolve(jq_Member m) {
298             if (m.getDeclaringClass().isPrepared()) {
299                 try {
300                     m = m.resolve();
301                 } catch (Error _) { }
302             }
303             return m;
304         }
305 
306         /* (non-Javadoc)
307          * @see joeq.Compiler.CompilationState#resolve(Class.jq_Member)
308          */
309         public jq_Member resolve(jq_Member m) {
310             try {
311                 m = m.resolve();
312             } catch (Error _) { }
313             return m;
314         }
315 
316         /* (non-Javadoc)
317          * @see joeq.Compiler.CompilationState#isSubtype(Class.jq_Type, Class.jq_Type)
318          */
319         public byte isSubtype(jq_Type t1, jq_Type t2) {
320             return TypeCheck.isAssignable_noload(t1, t2);
321         }
322 
323         /* (non-Javadoc)
324          * @see joeq.Compiler.CompilationState#findCommonSuperclass(Class.jq_Type, Class.jq_Type)
325          */
326         public jq_Type findCommonSuperclass(jq_Type t1, jq_Type t2) {
327             return TypeCheck.findCommonSuperclass(t1, t2, false);
328         }
329 
330         /* (non-Javadoc)
331          * @see joeq.Compiler.CompilationState#declaresInterface(Class.jq_Class, java.util.Collection)
332          */
333         public byte declaresInterface(jq_Class klass, Collection interfaces) {
334             return TypeCheck.declaresInterface(klass, interfaces, false);
335         }
336 
337         /* (non-Javadoc)
338          * @see joeq.Compiler.CompilationState#implementsInterface(Class.jq_Class, Class.jq_Class)
339          */
340         public byte implementsInterface(jq_Class klass, jq_Class inter) {
341             return TypeCheck.implementsInterface_noload(klass, inter);
342         }
343 
344         /* (non-Javadoc)
345          * @see joeq.Compiler.CompilationState#getOrCreateType(UTF.Utf8)
346          */
347         public jq_Type getOrCreateType(Utf8 desc) {
348             return PrimordialClassLoader.loader.getOrCreateBSType(desc);
349         }
350     }
351     
352 }