1
2
3
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
68
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
77
78
79 public boolean needsDynamicLink(jq_Method method, jq_Type type) {
80 type.prepare();
81 return !type.isPrepared();
82 }
83
84
85
86
87 public jq_Member tryResolve(jq_Member m) {
88 try {
89 m = m.resolve();
90 } catch (Error _) { }
91 return m;
92 }
93
94
95
96
97 public jq_Member resolve(jq_Member m) {
98 return m.resolve();
99 }
100
101
102
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
110
111
112 public jq_Type findCommonSuperclass(jq_Type t1, jq_Type t2) {
113 return TypeCheck.findCommonSuperclass(t1, t2, true);
114 }
115
116
117
118
119 public byte declaresInterface(jq_Class klass, Collection interfaces) {
120 return TypeCheck.declaresInterface(klass, interfaces, true);
121 }
122
123
124
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
133
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
143
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
160
161
162
163
164
165
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
178
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
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
194
195 public void setBootTypes(Set boot_types) {
196 this.boot_types = boot_types;
197 }
198
199
200
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
209
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
218
219
220 public jq_Member tryResolve(jq_Member m) {
221 try {
222 m = m.resolve();
223 } catch (Error _) { }
224 return m;
225 }
226
227
228
229
230 public jq_Member resolve(jq_Member m) {
231 return m.resolve();
232 }
233
234
235
236
237 public byte isSubtype(jq_Type t1, jq_Type t2) {
238 return TypeCheck.isAssignable_noload(t1, t2);
239 }
240
241
242
243
244 public jq_Type findCommonSuperclass(jq_Type t1, jq_Type t2) {
245 return TypeCheck.findCommonSuperclass(t1, t2, false);
246 }
247
248
249
250
251 public byte declaresInterface(jq_Class klass, Collection interfaces) {
252 return TypeCheck.declaresInterface(klass, interfaces, false);
253 }
254
255
256
257
258 public byte implementsInterface(jq_Class klass, jq_Class inter) {
259 return TypeCheck.implementsInterface_noload(klass, inter);
260 }
261
262
263
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
274
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
287
288
289 public boolean needsDynamicLink(jq_Method method, jq_Type type) {
290 return method.getDeclaringClass() != type &&
291 !type.isClsInitialized();
292 }
293
294
295
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
307
308
309 public jq_Member resolve(jq_Member m) {
310 try {
311 m = m.resolve();
312 } catch (Error _) { }
313 return m;
314 }
315
316
317
318
319 public byte isSubtype(jq_Type t1, jq_Type t2) {
320 return TypeCheck.isAssignable_noload(t1, t2);
321 }
322
323
324
325
326 public jq_Type findCommonSuperclass(jq_Type t1, jq_Type t2) {
327 return TypeCheck.findCommonSuperclass(t1, t2, false);
328 }
329
330
331
332
333 public byte declaresInterface(jq_Class klass, Collection interfaces) {
334 return TypeCheck.declaresInterface(klass, interfaces, false);
335 }
336
337
338
339
340 public byte implementsInterface(jq_Class klass, jq_Class inter) {
341 return TypeCheck.implementsInterface_noload(klass, inter);
342 }
343
344
345
346
347 public jq_Type getOrCreateType(Utf8 desc) {
348 return PrimordialClassLoader.loader.getOrCreateBSType(desc);
349 }
350 }
351
352 }