Source code: Bootstrap/BootstrapRootSet.java
1 // BootstrapRootSet.java, created Wed Jun 26 12:27:23 2002 by joewhaley
2 // Copyright (C) 2001-3 John Whaley <jwhaley@alum.mit.edu>
3 // Licensed under the terms of the GNU LGPL; see COPYING for details.
4 package Bootstrap;
5
6 import java.util.HashSet;
7 import java.util.Iterator;
8 import java.util.LinkedHashSet;
9 import java.util.LinkedList;
10 import java.util.List;
11 import java.util.Set;
12
13 import Clazz.jq_Array;
14 import Clazz.jq_Class;
15 import Clazz.jq_ClassInitializer;
16 import Clazz.jq_Field;
17 import Clazz.jq_FieldVisitor;
18 import Clazz.jq_Initializer;
19 import Clazz.jq_InstanceField;
20 import Clazz.jq_InstanceMethod;
21 import Clazz.jq_Member;
22 import Clazz.jq_Method;
23 import Clazz.jq_MethodVisitor;
24 import Clazz.jq_Primitive;
25 import Clazz.jq_Reference;
26 import Clazz.jq_StaticField;
27 import Clazz.jq_StaticMethod;
28 import Clazz.jq_Type;
29 import Clazz.jq_TypeVisitor;
30 import Memory.CodeAddress;
31 import Memory.HeapAddress;
32 import Memory.StackAddress;
33 import Run_Time.ExceptionDeliverer;
34 import Run_Time.Reflection;
35 import Run_Time.SystemInterface;
36 import Run_Time.Unsafe;
37 import Util.Assert;
38 import Util.Collections.IdentityHashCodeWrapper;
39
40 /**
41 * BootstrapRootSet
42 *
43 * @author John Whaley <jwhaley@alum.mit.edu>
44 * @version $Id: BootstrapRootSet.java,v 1.26 2003/05/12 10:04:52 joewhaley Exp $
45 */
46 public class BootstrapRootSet {
47
48 public static /*final*/ boolean TRACE = false;
49 public static final java.io.PrintStream out = System.out;
50
51 protected final Set/*jq_Type*/ instantiatedTypes;
52 protected final Set/*jq_Type*/ necessaryTypes;
53 protected final Set/*jq_Field*/ necessaryFields;
54 protected final Set/*jq_Method*/ necessaryMethods;
55
56 protected final LinkedHashSet/*Object*/ visitedObjects;
57
58 protected List/*jq_TypeVisitor*/ instantiatedTypesListeners;
59 protected List/*jq_TypeVisitor*/ necessaryTypesListeners;
60 protected List/*jq_FieldVisitor*/ necessaryFieldsListeners;
61 protected List/*jq_MethodVisitor*/ necessaryMethodsListeners;
62
63 public boolean AddAllFields;
64
65 /** Creates new BootstrapRootSet */
66 public BootstrapRootSet(boolean addall) {
67 this.instantiatedTypes = new HashSet();
68 this.necessaryTypes = new HashSet();
69 this.necessaryFields = new HashSet();
70 this.necessaryMethods = new HashSet();
71 this.visitedObjects = new LinkedHashSet();
72 this.AddAllFields = addall;
73 }
74
75 public Set/*jq_Type*/ getInstantiatedTypes() { return instantiatedTypes; }
76 public Set/*jq_Type*/ getNecessaryTypes() { return necessaryTypes; }
77 public Set/*jq_Field*/ getNecessaryFields() { return necessaryFields; }
78 public Set/*jq_Method*/ getNecessaryMethods() { return necessaryMethods; }
79
80 public void registerInstantiatedTypeListener(jq_TypeVisitor tv) {
81 if (instantiatedTypesListeners == null)
82 instantiatedTypesListeners = new LinkedList();
83 instantiatedTypesListeners.add(tv);
84 }
85 public void unregisterInstantiatedTypeListener(jq_TypeVisitor tv) {
86 instantiatedTypesListeners.remove(tv);
87 }
88 public void registerNecessaryTypeListener(jq_TypeVisitor tv) {
89 if (necessaryTypesListeners == null)
90 necessaryTypesListeners = new LinkedList();
91 necessaryTypesListeners.add(tv);
92 }
93 public void unregisterNecessaryTypeListener(jq_TypeVisitor tv) {
94 necessaryTypesListeners.remove(tv);
95 }
96 public void registerNecessaryFieldListener(jq_FieldVisitor tv) {
97 if (necessaryFieldsListeners == null)
98 necessaryFieldsListeners = new LinkedList();
99 necessaryFieldsListeners.add(tv);
100 }
101 public void unregisterNecessaryFieldListener(jq_FieldVisitor tv) {
102 necessaryFieldsListeners.remove(tv);
103 }
104 public void registerNecessaryMethodListener(jq_MethodVisitor tv) {
105 if (necessaryMethodsListeners == null)
106 necessaryMethodsListeners = new LinkedList();
107 necessaryMethodsListeners.add(tv);
108 }
109 public void unregisterNecessaryMethodListener(jq_MethodVisitor tv) {
110 necessaryMethodsListeners.remove(tv);
111 }
112
113 public boolean addInstantiatedType(jq_Type t) {
114 Assert._assert(t != null);
115 addNecessaryType(t);
116 boolean b = instantiatedTypes.add(t);
117 if (b) {
118 if (TRACE) out.println("New instantiated type: "+t);
119 if (instantiatedTypesListeners != null) {
120 for (Iterator i=instantiatedTypesListeners.iterator(); i.hasNext(); ) {
121 jq_TypeVisitor tv = (jq_TypeVisitor)i.next();
122 t.accept(tv);
123 }
124 }
125 }
126 return b;
127 }
128
129 public jq_Type addNecessaryType(String desc) {
130 String className = desc.substring(1, desc.length()-1).replace('/', '.');
131 try {
132 // attempt to load class in host VM first.
133 Class.forName(className);
134 jq_Type t = null;
135 try {
136 t = PrimordialClassLoader.loader.getOrCreateBSType(desc);
137 t.load();
138 addNecessaryType(t);
139 return t;
140 } catch (NoClassDefFoundError x) {
141 System.out.println("Note: Cannot load class "+t+" present in host Jvm");
142 PrimordialClassLoader.unloadType(PrimordialClassLoader.loader, t);
143 }
144 } catch (ClassNotFoundException x) { }
145 return null;
146 }
147
148 public boolean addNecessaryType(jq_Type t) {
149 if (t == null) return false;
150 t.prepare();
151 boolean b = necessaryTypes.add(t);
152 if (b) {
153 if (TRACE) out.println("New necessary type: "+t);
154 if (necessaryTypesListeners != null) {
155 for (Iterator i=necessaryTypesListeners.iterator(); i.hasNext(); ) {
156 jq_TypeVisitor tv = (jq_TypeVisitor)i.next();
157 t.accept(tv);
158 }
159 }
160 if (t instanceof jq_Class) {
161 jq_Class klass = (jq_Class)t;
162 if (AddAllFields) {
163 jq_StaticField[] sfs = klass.getDeclaredStaticFields();
164 for (int i=0; i<sfs.length; ++i) {
165 addNecessaryField(sfs[i]);
166 }
167 }
168 // add superclass as necessary, as well.
169 addNecessaryType(klass.getSuperclass());
170 }
171 }
172 return b;
173 }
174
175 public jq_StaticField addNecessaryStaticField(jq_Class c, String name, String desc) {
176 if (c == null) return null;
177 jq_StaticField f = c.getOrCreateStaticField(name, desc);
178 addNecessaryField(f);
179 return f;
180 }
181
182 public jq_InstanceField addNecessaryInstanceField(jq_Class c, String name, String desc) {
183 if (c == null) return null;
184 jq_InstanceField f = c.getOrCreateInstanceField(name, desc);
185 addNecessaryField(f);
186 return f;
187 }
188
189 public boolean addNecessaryField(jq_Field t) {
190 addNecessaryType(t.getDeclaringClass());
191 boolean b = necessaryFields.add(t);
192 if (b) {
193 if (TRACE) out.println("New necessary field: "+t);
194 if (necessaryFieldsListeners != null) {
195 for (Iterator i=necessaryFieldsListeners.iterator(); i.hasNext(); ) {
196 jq_FieldVisitor tv = (jq_FieldVisitor)i.next();
197 t.accept(tv);
198 }
199 }
200 }
201 return b;
202 }
203
204 public jq_StaticMethod addNecessaryStaticMethod(jq_Class c, String name, String desc) {
205 if (c == null) return null;
206 jq_StaticMethod f = c.getOrCreateStaticMethod(name, desc);
207 addNecessaryMethod(f);
208 return f;
209 }
210
211 public jq_InstanceMethod addNecessaryInstanceMethod(jq_Class c, String name, String desc) {
212 if (c == null) return null;
213 jq_InstanceMethod f = c.getOrCreateInstanceMethod(name, desc);
214 addNecessaryMethod(f);
215 return f;
216 }
217
218 public boolean addNecessaryMethod(jq_Method t) {
219 addNecessaryType(t.getDeclaringClass());
220 boolean b = necessaryMethods.add(t);
221 if (b) {
222 if (TRACE) out.println("New necessary method: "+t);
223 if (necessaryMethodsListeners != null) {
224 for (Iterator i=necessaryMethodsListeners.iterator(); i.hasNext(); ) {
225 jq_MethodVisitor tv = (jq_MethodVisitor)i.next();
226 t.accept(tv);
227 }
228 }
229 }
230 return b;
231 }
232
233 public void addDefaultRoots() {
234 jq_Class c;
235 jq_StaticField s_f; jq_InstanceField i_f;
236 jq_StaticMethod s_m; jq_InstanceMethod i_m;
237
238 // some internal vm data structures are necessary for correct execution
239 // under just about any circumstances.
240 addNecessaryType(jq_Class._class);
241 addNecessaryType(jq_Primitive._class);
242 addNecessaryType(jq_Array._class);
243 addNecessaryType(jq_InstanceField._class);
244 addNecessaryType(jq_StaticField._class);
245 addNecessaryType(jq_InstanceMethod._class);
246 addNecessaryType(jq_StaticMethod._class);
247 addNecessaryType(jq_Initializer._class);
248 addNecessaryType(jq_ClassInitializer._class);
249 addNecessaryType(CodeAddress._class);
250 addNecessaryType(HeapAddress._class);
251 addNecessaryType(StackAddress._class);
252 addNecessaryField(jq_Reference._vtable);
253
254 // the bootstrap loader uses the static fields in the SystemInterface class.
255 SystemInterface._class.load();
256 jq_StaticField[] sfs = SystemInterface._class.getDeclaredStaticFields();
257 for (int i=0; i<sfs.length; ++i) {
258 addNecessaryField(sfs[i]);
259 }
260 // even if there are no calls to these Unsafe methods, we need their definitions
261 // to stick around so that we can check against them.
262 Unsafe._class.load();
263 jq_StaticMethod[] sms = Unsafe._class.getDeclaredStaticMethods();
264 for (int i=0; i<sms.length; ++i) {
265 if (sms[i] instanceof jq_ClassInitializer) continue;
266 addNecessaryMethod(sms[i]);
267 }
268 //addNecessaryField(Unsafe._remapper_object);
269
270 // We need to be able to allocate objects and code.
271 addNecessaryType(Allocator.SimpleAllocator._class);
272 addNecessaryType(PrimordialClassLoader.loader.getOrCreateBSType("LAllocator/RuntimeCodeAllocator;"));
273
274 // setIn0, setOut0, and setErr0 use these fields, but the trimmer doesn't detect the uses.
275 c = PrimordialClassLoader.getJavaLangSystem();
276 addNecessaryStaticField(c, "in", "Ljava/io/InputStream;");
277 addNecessaryStaticField(c, "out", "Ljava/io/PrintStream;");
278 addNecessaryStaticField(c, "err", "Ljava/io/PrintStream;");
279
280 // private method initializeSystemClass is called reflectively
281 addNecessaryStaticMethod(c, "initializeSystemClass", "()V");
282
283 // an instance of this class is created via reflection during VM initialization.
284 c = (jq_Class)Reflection.getJQType(sun.io.CharToByteConverter.getDefault().getClass());
285 addNecessaryInstanceMethod(c, "<init>", "()V");
286
287 // an instance of this class is created via reflection during VM initialization.
288 c = (jq_Class)Reflection.getJQType(sun.io.ByteToCharConverter.getDefault().getClass());
289 addNecessaryInstanceMethod(c, "<init>", "()V");
290
291 // the trap handler can be implicitly called from any bytecode than can trigger a hardware exception.
292 s_m = ExceptionDeliverer._trap_handler;
293 addNecessaryMethod(s_m);
294
295 // we want the compiler to be able to run at run time, too.
296 i_m = jq_Method._compile;
297 addNecessaryMethod(i_m);
298
299 // debugger is large, so compile it on demand.
300 if (false) {
301 s_m = ExceptionDeliverer._debug_trap_handler;
302 addNecessaryMethod(s_m);
303 }
304
305 // entrypoint for new threads
306 addNecessaryMethod(Scheduler.jq_NativeThread._nativeThreadEntry);
307 // thread switch interrupt
308 addNecessaryMethod(Scheduler.jq_NativeThread._threadSwitch);
309 // ctrl-break handler
310 addNecessaryMethod(Scheduler.jq_NativeThread._ctrl_break_handler);
311 // entrypoint for interrupter thread
312 addNecessaryMethod(Scheduler.jq_InterrupterThread._run);
313
314 // dunno why this doesn't show up
315 addNecessaryType(Assembler.x86.Heap2HeapReference._class);
316
317 try {
318 // an instance of this class is created via reflection during VM initialization.
319 c = (jq_Class)Reflection.getJQType(sun.io.ByteToCharConverter.getConverter("ISO-8859-1").getClass());
320 addNecessaryInstanceMethod(c, "<init>", "()V");
321 // an instance of this class is created via reflection during VM initialization.
322 c = (jq_Class)Reflection.getJQType(sun.io.CharToByteConverter.getConverter("ISO-8859-1").getClass());
323 addNecessaryInstanceMethod(c, "<init>", "()V");
324 } catch (java.io.UnsupportedEncodingException x) { }
325
326 // JDK1.4: an instance of this class is created via reflection during VM initialization.
327 c = (jq_Class) addNecessaryType("Lsun/nio/cs/ISO_8859_1;");
328 addNecessaryInstanceMethod(c, "<init>", "()V");
329
330 addNecessaryType("Lsun/nio/cs/ISO_8859_1$Encoder;");
331 addNecessaryType("Lsun/nio/cs/ISO_8859_1$Decoder;");
332 addNecessaryType("Lsun/nio/cs/ISO_8859_1$1;");
333
334 // for JDK1.4.2
335 addNecessaryType("Lsun/net/www/protocol/jar/Handler;");
336 addNecessaryType("Ljava/util/logging/LogManager$Cleaner;");
337
338 // tracing in the compiler uses these
339 //c = jq._class; c.prepare();
340 //addToWorklist(jq._hex8);
341 //addToWorklist(jq._hex16);
342 }
343
344 public boolean addObjectAndSubfields(Object o) {
345 return addObjectAndSubfields(o, visitedObjects);
346 }
347 private boolean addObjectAndSubfields(Object o, LinkedHashSet objs) {
348 if (o == null) return false;
349 IdentityHashCodeWrapper a = IdentityHashCodeWrapper.create(o);
350 if (visitedObjects.contains(a) || objs.contains(a))
351 return false;
352 objs.add(a);
353 Class objType = o.getClass();
354 jq_Reference jqType = (jq_Reference)Reflection.getJQType(objType);
355 if (TRACE) out.println("Adding object of type "+jqType+": "+o);
356 addInstantiatedType(jqType);
357 /*
358 addClassInitializer((jq_Class)jqType);
359 addSuperclassVirtualMethods((jq_Class)jqType);
360 addClassInterfaceImplementations((jq_Class)jqType);
361 */
362 if (jqType.isArrayType()) {
363 jq_Type elemType = ((jq_Array)jqType).getElementType();
364 if (elemType.isAddressType()) {
365 // no need to visit.
366 } else if (elemType.isReferenceType()) {
367 int length = java.lang.reflect.Array.getLength(o);
368 Object[] v = (Object[])o;
369 if (TRACE) out.println("Visiting "+jqType+" of "+length+" elements");
370 for (int k=0; k<length; ++k) {
371 Object o2 = Reflection.arrayload_A(v, k);
372 addObjectAndSubfields(o2, objs);
373 }
374 }
375 } else {
376 Assert._assert(jqType.isClassType());
377 jq_Class clazz = (jq_Class)jqType;
378 jq_InstanceField[] fields = clazz.getInstanceFields();
379 for (int k=0; k<fields.length; ++k) {
380 jq_InstanceField f = fields[k];
381 if (!AddAllFields && !necessaryFields.contains(f))
382 continue;
383 jq_Type ftype = f.getType();
384 if (ftype.isAddressType()) {
385 // no need to visit.
386 } else if (ftype.isReferenceType()) {
387 if (TRACE) out.println("Visiting field "+f);
388 Object o2 = Reflection.getfield_A(o, f);
389 addObjectAndSubfields(o2, objs);
390 }
391 }
392 }
393 return true;
394 }
395
396 public void addNecessarySubfieldsOfVisitedObjects() {
397 if (AddAllFields) return;
398 LinkedHashSet objs = visitedObjects;
399 for (;;) {
400 LinkedHashSet objs2 = new LinkedHashSet();
401 boolean change = false;
402 for (Iterator i = objs.iterator(); i.hasNext(); ) {
403 Object o = ((IdentityHashCodeWrapper)i.next()).getObject();
404 Class objType = o.getClass();
405 jq_Reference jqType = (jq_Reference)Reflection.getJQType(objType);
406 if (jqType.isArrayType()) continue;
407 Assert._assert(jqType.isClassType());
408 jq_Class clazz = (jq_Class)jqType;
409 jq_InstanceField[] fields = clazz.getInstanceFields();
410 for (int k=0; k<fields.length; ++k) {
411 jq_InstanceField f = fields[k];
412 if (!necessaryFields.contains(f))
413 continue;
414 jq_Type ftype = f.getType();
415 if (ftype.isAddressType()) {
416 // no need to visit.
417 } else if (ftype.isReferenceType()) {
418 if (TRACE) out.println("Visiting field "+f+" of object of type "+clazz);
419 Object o2 = Reflection.getfield_A(o, f);
420 if (addObjectAndSubfields(o2, objs2))
421 change = true;
422 }
423 }
424 }
425 if (!change) break;
426 if (TRACE) out.println("Objects added: "+objs2.size()+", iterating over those objects.");
427 visitedObjects.addAll(objs2);
428 objs = objs2;
429 }
430 }
431
432 public void addAllInterfaceMethodImplementations(jq_InstanceMethod i_m) {
433 addNecessaryMethod(i_m);
434 jq_Class interf = i_m.getDeclaringClass();
435 Assert._assert(interf.isInterface());
436 Iterator i = necessaryTypes.iterator();
437 while (i.hasNext()) {
438 jq_Type t = (jq_Type)i.next();
439 if (!t.isReferenceType()) continue;
440 if (t.isAddressType()) continue;
441 jq_Reference r = (jq_Reference)t;
442 if (!r.implementsInterface(interf)) continue;
443 jq_InstanceMethod m2 = r.getVirtualMethod(i_m.getNameAndDesc());
444 if (m2 == null) {
445 // error:
446 if (TRACE) out.println("Error: class "+r+" does not implement interface method "+i_m);
447 continue;
448 }
449 addNecessaryMethod(m2);
450 }
451 }
452
453 public void addAllVirtualMethodImplementations(jq_InstanceMethod i_m) {
454 addNecessaryMethod(i_m);
455 addAllVirtualMethodImplementations(i_m.getDeclaringClass(), i_m);
456 }
457
458 public void addAllVirtualMethodImplementations(jq_Class c, jq_InstanceMethod i_m) {
459 if (!i_m.isOverridden())
460 return;
461 jq_Class[] subclasses = c.getSubClasses();
462 for (int i=0; i<subclasses.length; ++i) {
463 jq_Class subclass = subclasses[i];
464 subclass.prepare();
465 jq_Method m2 = (jq_Method)subclass.getDeclaredMember(i_m.getNameAndDesc());
466 if (m2 != null && !m2.isStatic()) {
467 addNecessaryMethod(m2);
468 }
469 addAllVirtualMethodImplementations(subclass, i_m);
470 }
471 }
472
473 // not thread safe.
474 public void trimClass(jq_Class clazz) {
475 Assert._assert(clazz.isPrepared());
476
477 jq_Class super_class = clazz.getSuperclass();
478 if (super_class != null)
479 trimClass(super_class);
480
481 Set instantiatedTypes = getInstantiatedTypes();
482 Set necessaryFields = getNecessaryFields();
483 Set necessaryMethods = getNecessaryMethods();
484
485 Iterator it = clazz.getMembers().iterator();
486 while (it.hasNext()) {
487 jq_Member m = (jq_Member)it.next();
488 if (m instanceof jq_Field) {
489 if (!necessaryFields.contains(m)) {
490 if (TRACE) out.println("Eliminating field: "+m);
491 it.remove();
492 }
493 } else {
494 Assert._assert(m instanceof jq_Method);
495 if (!necessaryMethods.contains(m)) {
496 if (TRACE) out.println("Eliminating method: "+m);
497 it.remove();
498 }
499 }
500 }
501
502 int n;
503 n=0;
504 jq_InstanceField[] declared_instance_fields = clazz.getDeclaredInstanceFields();
505 for (int i=0; i<declared_instance_fields.length; ++i) {
506 jq_InstanceField f = declared_instance_fields[i];
507 f.unprepare();
508 if (necessaryMethods.contains(f)) ++n;
509 }
510 jq_InstanceField[] ifs = new jq_InstanceField[n];
511 for (int i=0, j=-1; j<n-1; ++i) {
512 jq_InstanceField f = declared_instance_fields[i];
513 if (necessaryFields.contains(f)) {
514 ifs[++j] = f;
515 ++jq_Class.NumOfIFieldsKept;
516 } else {
517 if (TRACE) out.println("Eliminating instance field: "+f);
518 ++jq_Class.NumOfIFieldsEliminated;
519 }
520 }
521 clazz.setDeclaredInstanceFields(ifs);
522
523 jq_StaticField[] static_fields = clazz.getDeclaredStaticFields();
524 int static_data_size=0;
525 n=0;
526 for (int i=0; i<static_fields.length; ++i) {
527 jq_StaticField f = static_fields[i];
528 f.unprepare();
529 if (necessaryFields.contains(f)) ++n;
530 }
531 jq_StaticField[] sfs = new jq_StaticField[n];
532 for (int i=0, j=-1; j<n-1; ++i) {
533 jq_StaticField f = static_fields[i];
534 if (necessaryFields.contains(f)) {
535 sfs[++j] = f;
536 static_data_size += f.getWidth();
537 ++jq_Class.NumOfSFieldsKept;
538 }
539 else {
540 if (TRACE) out.println("Eliminating static field: "+f);
541 ++jq_Class.NumOfSFieldsEliminated;
542 }
543 }
544 clazz.setDeclaredStaticFields(sfs);
545
546 n=0;
547 jq_InstanceMethod[] declared_instance_methods = clazz.getDeclaredInstanceMethods();
548 for (int i=0; i<declared_instance_methods.length; ++i) {
549 jq_InstanceMethod f = declared_instance_methods[i];
550 f.unprepare();
551 f.clearOverrideFlags();
552 if (necessaryMethods.contains(f)) ++n;
553 }
554 jq_InstanceMethod[] ims = new jq_InstanceMethod[n];
555 for (int i=0, j=-1; j<n-1; ++i) {
556 jq_InstanceMethod f = declared_instance_methods[i];
557 if (necessaryMethods.contains(f)) {
558 ims[++j] = f;
559 ++jq_Class.NumOfIMethodsKept;
560 } else {
561 if (BootstrapRootSet.TRACE) BootstrapRootSet.out.println("Eliminating instance method: "+f);
562 ++jq_Class.NumOfIMethodsEliminated;
563 }
564 }
565 clazz.setDeclaredInstanceMethods(ims);
566
567 n=0;
568 jq_StaticMethod[] static_methods = clazz.getDeclaredStaticMethods();
569 for (int i=0; i<static_methods.length; ++i) {
570 jq_StaticMethod f = static_methods[i];
571 f.unprepare();
572 if (necessaryMethods.contains(f)) ++n;
573 }
574 jq_StaticMethod[] sms = new jq_StaticMethod[n];
575 for (int i=0, j=-1; j<n-1; ++i) {
576 jq_StaticMethod f = static_methods[i];
577 if (necessaryMethods.contains(f)) {
578 sms[++j] = f;
579 ++jq_Class.NumOfSMethodsKept;
580 } else {
581 if (BootstrapRootSet.TRACE) BootstrapRootSet.out.println("Eliminating static method: "+f);
582 ++jq_Class.NumOfSMethodsEliminated;
583 }
584 }
585 clazz.setDeclaredStaticMethods(sms);
586
587 /*
588 n=0;
589 for (int i=0; i<declared_interfaces.length; ++i) {
590 jq_Class f = declared_interfaces[i];
591 if (instantiatedTypes.contains(f)) ++n;
592 }
593 jq_Class[] is = new jq_Class[n];
594 for (int i=0, j=-1; j<n-1; ++i) {
595 jq_Class f = declared_interfaces[i];
596 if (instantiatedTypes.contains(f))
597 is[++j] = f;
598 else
599 if (trim.TRACE) trim.out.println("Eliminating interface: "+f);
600 }
601 declared_interfaces = is;
602 */
603
604 clazz.getCP().trim(necessaryFields, necessaryMethods);
605
606 clazz.prepare();
607 }
608 }