UsageMarker.java revision 9f606f95f03a75961498803e24bee6799a7c0885
1/*
2 * ProGuard -- shrinking, optimization, obfuscation, and preverification
3 *             of Java bytecode.
4 *
5 * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
6 *
7 * This program is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU General Public License as published by the Free
9 * Software Foundation; either version 2 of the License, or (at your option)
10 * any later version.
11 *
12 * This program is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15 * more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 */
21package proguard.shrink;
22
23import proguard.classfile.*;
24import proguard.classfile.attribute.*;
25import proguard.classfile.attribute.annotation.*;
26import proguard.classfile.attribute.preverification.*;
27import proguard.classfile.attribute.preverification.visitor.*;
28import proguard.classfile.attribute.visitor.*;
29import proguard.classfile.constant.*;
30import proguard.classfile.constant.visitor.ConstantVisitor;
31import proguard.classfile.instruction.*;
32import proguard.classfile.instruction.visitor.InstructionVisitor;
33import proguard.classfile.util.SimplifiedVisitor;
34import proguard.classfile.visitor.*;
35
36
37/**
38 * This ClassVisitor and MemberVisitor recursively marks all classes and class
39 * elements that are being used.
40 *
41 * @see ClassShrinker
42 *
43 * @author Eric Lafortune
44 */
45class      UsageMarker
46extends    SimplifiedVisitor
47implements ClassVisitor,
48           MemberVisitor,
49           ConstantVisitor,
50           AttributeVisitor,
51           InnerClassesInfoVisitor,
52           ExceptionInfoVisitor,
53           StackMapFrameVisitor,
54           VerificationTypeVisitor,
55           LocalVariableInfoVisitor,
56           LocalVariableTypeInfoVisitor,
57//         AnnotationVisitor,
58//         ElementValueVisitor,
59           InstructionVisitor
60{
61    // A visitor info flag to indicate the ProgramMember object is being used,
62    // if its Clazz can be determined as being used as well.
63    private static final Object POSSIBLY_USED = new Object();
64    // A visitor info flag to indicate the visitor accepter is being used.
65    private static final Object USED          = new Object();
66
67
68    private final MyInterfaceUsageMarker          interfaceUsageMarker          = new MyInterfaceUsageMarker();
69    private final MyPossiblyUsedMemberUsageMarker possiblyUsedMemberUsageMarker = new MyPossiblyUsedMemberUsageMarker();
70//    private ClassVisitor       dynamicClassMarker   =
71//        new MultiClassVisitor(
72//        new ClassVisitor[]
73//        {
74//            this,
75//            new NamedMethodVisitor(ClassConstants.INTERNAL_METHOD_NAME_INIT,
76//                                   ClassConstants.INTERNAL_METHOD_TYPE_INIT,
77//                                   this)
78//        });
79
80
81    // Implementations for ClassVisitor.
82
83    public void visitProgramClass(ProgramClass programClass)
84    {
85        if (shouldBeMarkedAsUsed(programClass))
86        {
87            // Mark this class.
88            markAsUsed(programClass);
89
90            markProgramClassBody(programClass);
91        }
92    }
93
94
95    protected void markProgramClassBody(ProgramClass programClass)
96    {
97        // Mark this class's name.
98        markConstant(programClass, programClass.u2thisClass);
99
100        // Mark the superclass.
101        if (programClass.u2superClass != 0)
102        {
103            markConstant(programClass, programClass.u2superClass);
104        }
105
106        // Give the interfaces preliminary marks.
107        programClass.hierarchyAccept(false, false, true, false,
108                                     interfaceUsageMarker);
109
110        // Explicitly mark the <clinit> method.
111        programClass.methodAccept(ClassConstants.INTERNAL_METHOD_NAME_CLINIT,
112                                  ClassConstants.INTERNAL_METHOD_TYPE_CLINIT,
113                                  this);
114
115        // Explicitly mark the parameterless <init> method.
116        programClass.methodAccept(ClassConstants.INTERNAL_METHOD_NAME_INIT,
117                                  ClassConstants.INTERNAL_METHOD_TYPE_INIT,
118                                  this);
119
120        // Process all class members that have already been marked as possibly used.
121        programClass.fieldsAccept(possiblyUsedMemberUsageMarker);
122        programClass.methodsAccept(possiblyUsedMemberUsageMarker);
123
124        // Mark the attributes.
125        programClass.attributesAccept(this);
126    }
127
128
129    public void visitLibraryClass(LibraryClass libraryClass)
130    {
131        if (shouldBeMarkedAsUsed(libraryClass))
132        {
133            markAsUsed(libraryClass);
134
135            // We're not going to analyze all library code. We're assuming that
136            // if this class is being used, all of its methods will be used as
137            // well. We'll mark them as such (here and in all subclasses).
138
139            // Mark the superclass.
140            Clazz superClass = libraryClass.superClass;
141            if (superClass != null)
142            {
143                superClass.accept(this);
144            }
145
146            // Mark the interfaces.
147            Clazz[] interfaceClasses = libraryClass.interfaceClasses;
148            if (interfaceClasses != null)
149            {
150                for (int index = 0; index < interfaceClasses.length; index++)
151                {
152                    if (interfaceClasses[index] != null)
153                    {
154                        interfaceClasses[index].accept(this);
155                    }
156                }
157            }
158
159            // Mark all methods.
160            libraryClass.methodsAccept(this);
161        }
162    }
163
164
165    /**
166     * This ClassVisitor marks ProgramClass objects as possibly used,
167     * and it visits LibraryClass objects with its outer UsageMarker.
168     */
169    private class MyInterfaceUsageMarker
170    implements    ClassVisitor
171    {
172        public void visitProgramClass(ProgramClass programClass)
173        {
174            if (shouldBeMarkedAsPossiblyUsed(programClass))
175            {
176                // We can't process the interface yet, because it might not
177                // be required. Give it a preliminary mark.
178                markAsPossiblyUsed(programClass);
179            }
180        }
181
182        public void visitLibraryClass(LibraryClass libraryClass)
183        {
184            // Make sure all library interface methods are marked.
185            UsageMarker.this.visitLibraryClass(libraryClass);
186        }
187    }
188
189
190    private class MyPossiblyUsedMemberUsageMarker
191    extends       SimplifiedVisitor
192    implements    MemberVisitor
193    {
194        // Implementations for MemberVisitor.
195
196        public void visitProgramField(ProgramClass programClass, ProgramField programField)
197        {
198            // Has the method already been referenced?
199            if (isPossiblyUsed(programField))
200            {
201                markAsUsed(programField);
202
203                // Mark the name and descriptor.
204                markConstant(programClass, programField.u2nameIndex);
205                markConstant(programClass, programField.u2descriptorIndex);
206
207                // Mark the attributes.
208                programField.attributesAccept(programClass, UsageMarker.this);
209
210                // Mark the classes referenced in the descriptor string.
211                programField.referencedClassesAccept(UsageMarker.this);
212            }
213        }
214
215
216        public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
217        {
218            // Has the method already been referenced?
219            if (isPossiblyUsed(programMethod))
220            {
221                markAsUsed(programMethod);
222
223                // Mark the method body.
224                markProgramMethodBody(programClass, programMethod);
225
226                // Note that, if the method has been marked as possibly used,
227                // the method hierarchy has already been marked (cfr. below).
228            }
229        }
230    }
231
232
233    // Implementations for MemberVisitor.
234
235    public void visitProgramField(ProgramClass programClass, ProgramField programField)
236    {
237        if (shouldBeMarkedAsUsed(programField))
238        {
239            // Is the field's class used?
240            if (isUsed(programClass))
241            {
242                markAsUsed(programField);
243
244                // Mark the field body.
245                markProgramFieldBody(programClass, programField);
246            }
247
248            // Hasn't the field been marked as possibly being used yet?
249            else if (shouldBeMarkedAsPossiblyUsed(programField))
250            {
251                // We can't process the field yet, because the class isn't
252                // marked as being used (yet). Give it a preliminary mark.
253                markAsPossiblyUsed(programField);
254            }
255        }
256    }
257
258
259    public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
260    {
261        if (shouldBeMarkedAsUsed(programMethod))
262        {
263            // Is the method's class used?
264            if (isUsed(programClass))
265            {
266                markAsUsed(programMethod);
267
268                // Mark the method body.
269                markProgramMethodBody(programClass, programMethod);
270
271                // Mark the method hierarchy.
272                markMethodHierarchy(programClass, programMethod);
273            }
274
275            // Hasn't the method been marked as possibly being used yet?
276            else if (shouldBeMarkedAsPossiblyUsed(programMethod))
277            {
278                // We can't process the method yet, because the class isn't
279                // marked as being used (yet). Give it a preliminary mark.
280                markAsPossiblyUsed(programMethod);
281
282                // Mark the method hierarchy.
283                markMethodHierarchy(programClass, programMethod);
284            }
285        }
286    }
287
288
289    public void visitLibraryField(LibraryClass programClass, LibraryField programField) {}
290
291
292    public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
293    {
294        if (shouldBeMarkedAsUsed(libraryMethod))
295        {
296            markAsUsed(libraryMethod);
297
298            // Mark the method hierarchy.
299            markMethodHierarchy(libraryClass, libraryMethod);
300        }
301    }
302
303
304    protected void markProgramFieldBody(ProgramClass programClass, ProgramField programField)
305    {
306        // Mark the name and descriptor.
307        markConstant(programClass, programField.u2nameIndex);
308        markConstant(programClass, programField.u2descriptorIndex);
309
310        // Mark the attributes.
311        programField.attributesAccept(programClass, this);
312
313        // Mark the classes referenced in the descriptor string.
314        programField.referencedClassesAccept(this);
315    }
316
317
318    protected void markProgramMethodBody(ProgramClass programClass, ProgramMethod programMethod)
319    {
320        // Mark the name and descriptor.
321        markConstant(programClass, programMethod.u2nameIndex);
322        markConstant(programClass, programMethod.u2descriptorIndex);
323
324        // Mark the attributes.
325        programMethod.attributesAccept(programClass, this);
326
327        // Mark the classes referenced in the descriptor string.
328        programMethod.referencedClassesAccept(this);
329    }
330
331
332    /**
333     * Marks the hierarchy of implementing or overriding methods corresponding
334     * to the given method, if any.
335     */
336    protected void markMethodHierarchy(Clazz clazz, Method method)
337    {
338        if ((method.getAccessFlags() &
339             (ClassConstants.INTERNAL_ACC_PRIVATE |
340              ClassConstants.INTERNAL_ACC_STATIC)) == 0)
341        {
342            clazz.accept(new ConcreteClassDownTraveler(
343                         new ClassHierarchyTraveler(true, true, false, true,
344                         new NamedMethodVisitor(method.getName(clazz),
345                                                method.getDescriptor(clazz),
346                         new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE | ClassConstants.INTERNAL_ACC_STATIC | ClassConstants.INTERNAL_ACC_ABSTRACT,
347                         this)))));
348        }
349    }
350
351
352    // Implementations for ConstantVisitor.
353
354    public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
355    {
356        if (shouldBeMarkedAsUsed(integerConstant))
357        {
358            markAsUsed(integerConstant);
359        }
360    }
361
362
363    public void visitLongConstant(Clazz clazz, LongConstant longConstant)
364    {
365        if (shouldBeMarkedAsUsed(longConstant))
366        {
367            markAsUsed(longConstant);
368        }
369    }
370
371
372    public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
373    {
374        if (shouldBeMarkedAsUsed(floatConstant))
375        {
376            markAsUsed(floatConstant);
377        }
378    }
379
380
381    public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
382    {
383        if (shouldBeMarkedAsUsed(doubleConstant))
384        {
385            markAsUsed(doubleConstant);
386        }
387    }
388
389
390    public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
391    {
392        if (shouldBeMarkedAsUsed(stringConstant))
393        {
394            markAsUsed(stringConstant);
395
396            markConstant(clazz, stringConstant.u2stringIndex);
397
398            // Mark the referenced class and its parameterless constructor,
399            // if the string is being used in a Class.forName construct.
400            //stringConstant.referencedClassAccept(dynamicClassMarker);
401
402            // Mark the referenced class or class member, if any.
403            stringConstant.referencedClassAccept(this);
404            stringConstant.referencedMemberAccept(this);
405        }
406    }
407
408
409    public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
410    {
411        if (shouldBeMarkedAsUsed(utf8Constant))
412        {
413            markAsUsed(utf8Constant);
414        }
415    }
416
417
418    public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
419    {
420        if (shouldBeMarkedAsUsed(refConstant))
421        {
422            markAsUsed(refConstant);
423
424            markConstant(clazz, refConstant.u2classIndex);
425            markConstant(clazz, refConstant.u2nameAndTypeIndex);
426
427            // When compiled with "-target 1.2" or higher, the class or
428            // interface actually containing the referenced class member may
429            // be higher up the hierarchy. Make sure it's marked, in case it
430            // isn't used elsewhere.
431            refConstant.referencedClassAccept(this);
432
433            // Mark the referenced class member itself.
434            refConstant.referencedMemberAccept(this);
435        }
436    }
437
438
439    public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
440    {
441        if (shouldBeMarkedAsUsed(classConstant))
442        {
443            markAsUsed(classConstant);
444
445            markConstant(clazz, classConstant.u2nameIndex);
446
447            // Mark the referenced class itself.
448            classConstant.referencedClassAccept(this);
449        }
450    }
451
452
453    public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
454    {
455        if (shouldBeMarkedAsUsed(nameAndTypeConstant))
456        {
457            markAsUsed(nameAndTypeConstant);
458
459            markConstant(clazz, nameAndTypeConstant.u2nameIndex);
460            markConstant(clazz, nameAndTypeConstant.u2descriptorIndex);
461        }
462    }
463
464
465    // Implementations for AttributeVisitor.
466    // Note that attributes are typically only referenced once, so we don't
467    // test if they have been marked already.
468
469    public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
470    {
471        // This is the best we can do for unknown attributes.
472        markAsUsed(unknownAttribute);
473
474        markConstant(clazz, unknownAttribute.u2attributeNameIndex);
475    }
476
477
478    public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
479    {
480        markAsUsed(sourceFileAttribute);
481
482        markConstant(clazz, sourceFileAttribute.u2attributeNameIndex);
483        markConstant(clazz, sourceFileAttribute.u2sourceFileIndex);
484    }
485
486
487    public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
488    {
489        markAsUsed(sourceDirAttribute);
490
491        markConstant(clazz, sourceDirAttribute.u2attributeNameIndex);
492        markConstant(clazz, sourceDirAttribute.u2sourceDirIndex);
493    }
494
495
496    public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
497    {
498        // Don't mark the attribute and its name yet. We may mark it later, in
499        // InnerUsageMarker.
500        //markAsUsed(innerClassesAttribute);
501
502        //markConstant(clazz, innerClassesAttribute.u2attrNameIndex);
503
504        // Do mark the outer class entries.
505        innerClassesAttribute.innerClassEntriesAccept(clazz, this);
506    }
507
508
509    public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
510    {
511        markAsUsed(enclosingMethodAttribute);
512
513        markConstant(clazz, enclosingMethodAttribute.u2attributeNameIndex);
514        markConstant(clazz, enclosingMethodAttribute.u2classIndex);
515
516        if (enclosingMethodAttribute.u2nameAndTypeIndex != 0)
517        {
518            markConstant(clazz, enclosingMethodAttribute.u2nameAndTypeIndex);
519        }
520    }
521
522
523    public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
524    {
525        markAsUsed(deprecatedAttribute);
526
527        markConstant(clazz, deprecatedAttribute.u2attributeNameIndex);
528    }
529
530
531    public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
532    {
533        markAsUsed(syntheticAttribute);
534
535        markConstant(clazz, syntheticAttribute.u2attributeNameIndex);
536    }
537
538
539    public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
540    {
541        markAsUsed(signatureAttribute);
542
543        markConstant(clazz, signatureAttribute.u2attributeNameIndex);
544        markConstant(clazz, signatureAttribute.u2signatureIndex);
545    }
546
547
548    public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
549    {
550        markAsUsed(constantValueAttribute);
551
552        markConstant(clazz, constantValueAttribute.u2attributeNameIndex);
553        markConstant(clazz, constantValueAttribute.u2constantValueIndex);
554    }
555
556
557    public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
558    {
559        markAsUsed(exceptionsAttribute);
560
561        markConstant(clazz, exceptionsAttribute.u2attributeNameIndex);
562
563        // Mark the constant pool entries referenced by the exceptions.
564        exceptionsAttribute.exceptionEntriesAccept((ProgramClass)clazz, this);
565    }
566
567
568    public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
569    {
570        markAsUsed(codeAttribute);
571
572        markConstant(clazz, codeAttribute.u2attributeNameIndex);
573
574        // Mark the constant pool entries referenced by the instructions,
575        // by the exceptions, and by the attributes.
576        codeAttribute.instructionsAccept(clazz, method, this);
577        codeAttribute.exceptionsAccept(clazz, method, this);
578        codeAttribute.attributesAccept(clazz, method, this);
579    }
580
581
582    public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
583    {
584        markAsUsed(stackMapAttribute);
585
586        markConstant(clazz, stackMapAttribute.u2attributeNameIndex);
587
588        // Mark the constant pool entries referenced by the stack map frames.
589        stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
590    }
591
592
593    public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
594    {
595        markAsUsed(stackMapTableAttribute);
596
597        markConstant(clazz, stackMapTableAttribute.u2attributeNameIndex);
598
599        // Mark the constant pool entries referenced by the stack map frames.
600        stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
601    }
602
603
604    public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
605    {
606        markAsUsed(lineNumberTableAttribute);
607
608        markConstant(clazz, lineNumberTableAttribute.u2attributeNameIndex);
609    }
610
611
612    public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
613    {
614        markAsUsed(localVariableTableAttribute);
615
616        markConstant(clazz, localVariableTableAttribute.u2attributeNameIndex);
617
618        // Mark the constant pool entries referenced by the local variables.
619        localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
620    }
621
622
623    public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
624    {
625        markAsUsed(localVariableTypeTableAttribute);
626
627        markConstant(clazz, localVariableTypeTableAttribute.u2attributeNameIndex);
628
629        // Mark the constant pool entries referenced by the local variable types.
630        localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
631    }
632
633
634    public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
635    {
636        // Don't mark the attribute and its contents yet. We may mark them later,
637        // in AnnotationUsageMarker.
638//        markAsUsed(annotationsAttribute);
639//
640//        markConstant(clazz, annotationsAttribute.u2attributeNameIndex);
641//
642//        // Mark the constant pool entries referenced by the annotations.
643//        annotationsAttribute.annotationsAccept(clazz, this);
644    }
645
646
647    public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
648    {
649        // Don't mark the attribute and its contents yet. We may mark them later,
650        // in AnnotationUsageMarker.
651//        markAsUsed(parameterAnnotationsAttribute);
652//
653//        markConstant(clazz, parameterAnnotationsAttribute.u2attributeNameIndex);
654//
655//        // Mark the constant pool entries referenced by the annotations.
656//        parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
657    }
658
659
660    public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
661    {
662        // Don't mark the attribute and its contents yet. We may mark them later,
663        // in AnnotationUsageMarker.
664//        markAsUsed(annotationDefaultAttribute);
665//
666//        markConstant(clazz, annotationDefaultAttribute.u2attributeNameIndex);
667//
668//        // Mark the constant pool entries referenced by the element value.
669//        annotationDefaultAttribute.defaultValueAccept(clazz, this);
670    }
671
672
673    // Implementations for ExceptionInfoVisitor.
674
675    public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
676    {
677        markAsUsed(exceptionInfo);
678
679        if (exceptionInfo.u2catchType != 0)
680        {
681            markConstant(clazz, exceptionInfo.u2catchType);
682        }
683    }
684
685
686    // Implementations for InnerClassesInfoVisitor.
687
688    public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
689    {
690        // At this point, we only mark outer classes of this class.
691        // Inner class can be marked later, by InnerUsageMarker.
692        if (innerClassesInfo.u2innerClassIndex != 0 &&
693            clazz.getName().equals(clazz.getClassName(innerClassesInfo.u2innerClassIndex)))
694        {
695            markAsUsed(innerClassesInfo);
696
697            innerClassesInfo.innerClassConstantAccept(clazz, this);
698            innerClassesInfo.outerClassConstantAccept(clazz, this);
699            innerClassesInfo.innerNameConstantAccept(clazz, this);
700        }
701    }
702
703
704    // Implementations for StackMapFrameVisitor.
705
706    public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame) {}
707
708
709    public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
710    {
711        // Mark the constant pool entries referenced by the verification types.
712        sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this);
713    }
714
715
716    public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
717    {
718        // Mark the constant pool entries referenced by the verification types.
719        moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this);
720    }
721
722
723    public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)
724    {
725        // Mark the constant pool entries referenced by the verification types.
726        fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this);
727        fullFrame.stackAccept(clazz, method, codeAttribute, offset, this);
728    }
729
730
731    // Implementations for VerificationTypeVisitor.
732
733    public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) {}
734
735
736    public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType)
737    {
738        markConstant(clazz, objectType.u2classIndex);
739    }
740
741
742    // Implementations for LocalVariableInfoVisitor.
743
744    public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
745    {
746        markConstant(clazz, localVariableInfo.u2nameIndex);
747        markConstant(clazz, localVariableInfo.u2descriptorIndex);
748    }
749
750
751    // Implementations for LocalVariableTypeInfoVisitor.
752
753    public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
754    {
755        markConstant(clazz, localVariableTypeInfo.u2nameIndex);
756        markConstant(clazz, localVariableTypeInfo.u2signatureIndex);
757    }
758
759
760//    // Implementations for AnnotationVisitor.
761//
762//    public void visitAnnotation(Clazz clazz, Annotation annotation)
763//    {
764//        markConstant(clazz, annotation.u2typeIndex);
765//
766//        // Mark the constant pool entries referenced by the element values.
767//        annotation.elementValuesAccept(clazz, this);
768//    }
769//
770//
771//    // Implementations for ElementValueVisitor.
772//
773//    public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
774//    {
775//        if (constantElementValue.u2elementNameIndex != 0)
776//        {
777//            markConstant(clazz, constantElementValue.u2elementNameIndex);
778//        }
779//
780//        markConstant(clazz, constantElementValue.u2constantValueIndex);
781//    }
782//
783//
784//    public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
785//    {
786//        if (enumConstantElementValue.u2elementNameIndex != 0)
787//        {
788//            markConstant(clazz, enumConstantElementValue.u2elementNameIndex);
789//        }
790//
791//        markConstant(clazz, enumConstantElementValue.u2typeNameIndex);
792//        markConstant(clazz, enumConstantElementValue.u2constantNameIndex);
793//    }
794//
795//
796//    public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
797//    {
798//        if (classElementValue.u2elementNameIndex != 0)
799//        {
800//            markConstant(clazz, classElementValue.u2elementNameIndex);
801//        }
802//
803//        // Mark the referenced class constant pool entry.
804//        markConstant(clazz, classElementValue.u2classInfoIndex);
805//    }
806//
807//
808//    public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
809//    {
810//        if (annotationElementValue.u2elementNameIndex != 0)
811//        {
812//            markConstant(clazz, annotationElementValue.u2elementNameIndex);
813//        }
814//
815//        // Mark the constant pool entries referenced by the annotation.
816//        annotationElementValue.annotationAccept(clazz, this);
817//    }
818//
819//
820//    public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
821//    {
822//        if (arrayElementValue.u2elementNameIndex != 0)
823//        {
824//            markConstant(clazz, arrayElementValue.u2elementNameIndex);
825//        }
826//
827//        // Mark the constant pool entries referenced by the element values.
828//        arrayElementValue.elementValuesAccept(clazz, annotation, this);
829//    }
830
831
832    // Implementations for InstructionVisitor.
833
834    public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
835
836
837    public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
838    {
839        markConstant(clazz, constantInstruction.constantIndex);
840    }
841
842
843    // Small utility methods.
844
845    /**
846     * Marks the given visitor accepter as being used.
847     */
848    protected void markAsUsed(VisitorAccepter visitorAccepter)
849    {
850        visitorAccepter.setVisitorInfo(USED);
851    }
852
853
854    /**
855     * Returns whether the given visitor accepter should still be marked as
856     * being used.
857     */
858    protected boolean shouldBeMarkedAsUsed(VisitorAccepter visitorAccepter)
859    {
860        return visitorAccepter.getVisitorInfo() != USED;
861    }
862
863
864    /**
865     * Returns whether the given visitor accepter has been marked as being used.
866     */
867    protected boolean isUsed(VisitorAccepter visitorAccepter)
868    {
869        return visitorAccepter.getVisitorInfo() == USED;
870    }
871
872
873    /**
874     * Marks the given visitor accepter as possibly being used.
875     */
876    protected void markAsPossiblyUsed(VisitorAccepter visitorAccepter)
877    {
878        visitorAccepter.setVisitorInfo(POSSIBLY_USED);
879    }
880
881
882    /**
883     * Returns whether the given visitor accepter should still be marked as
884     * possibly being used.
885     */
886    protected boolean shouldBeMarkedAsPossiblyUsed(VisitorAccepter visitorAccepter)
887    {
888        return visitorAccepter.getVisitorInfo() != USED &&
889               visitorAccepter.getVisitorInfo() != POSSIBLY_USED;
890    }
891
892
893    /**
894     * Returns whether the given visitor accepter has been marked as possibly
895     * being used.
896     */
897    protected boolean isPossiblyUsed(VisitorAccepter visitorAccepter)
898    {
899        return visitorAccepter.getVisitorInfo() == POSSIBLY_USED;
900    }
901
902
903    /**
904     * Clears any usage marks from the given visitor accepter.
905     */
906    protected void markAsUnused(VisitorAccepter visitorAccepter)
907    {
908        visitorAccepter.setVisitorInfo(null);
909    }
910
911
912    /**
913     * Marks the given constant pool entry of the given class. This includes
914     * visiting any referenced objects.
915     */
916    private void markConstant(Clazz clazz, int index)
917    {
918         clazz.constantPoolEntryAccept(index, this);
919    }
920}
921