1/*
2 * ProGuard -- shrinking, optimization, obfuscation, and preverification
3 *             of Java bytecode.
4 *
5 * Copyright (c) 2002-2014 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.*;
31import proguard.classfile.instruction.*;
32import proguard.classfile.instruction.visitor.InstructionVisitor;
33import proguard.classfile.util.*;
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           ParameterInfoVisitor,
56           LocalVariableInfoVisitor,
57           LocalVariableTypeInfoVisitor,
58//         AnnotationVisitor,
59//         ElementValueVisitor,
60           InstructionVisitor
61{
62    // A visitor info flag to indicate the ProgramMember object is being used,
63    // if its Clazz can be determined as being used as well.
64    private static final Object POSSIBLY_USED = new Object();
65    // A visitor info flag to indicate the visitor accepter is being used.
66    private static final Object USED          = new Object();
67
68
69    private final MyInterfaceUsageMarker          interfaceUsageMarker           = new MyInterfaceUsageMarker();
70    private final MyPossiblyUsedMemberUsageMarker possiblyUsedMemberUsageMarker  = new MyPossiblyUsedMemberUsageMarker();
71    private final MemberVisitor                   nonEmptyMethodUsageMarker      = new AllAttributeVisitor(
72                                                                                   new MyNonEmptyMethodUsageMarker());
73    private final ConstantVisitor                 parameterlessConstructorMarker = new ConstantTagFilter(new int[] { ClassConstants.CONSTANT_String, ClassConstants.CONSTANT_Class },
74                                                                                   new ReferencedClassVisitor(
75                                                                                   new NamedMethodVisitor(ClassConstants.METHOD_NAME_INIT,
76                                                                                                          ClassConstants.METHOD_TYPE_INIT,
77                                                                                                          this)));
78
79    // Implementations for ClassVisitor.
80
81    public void visitProgramClass(ProgramClass programClass)
82    {
83        if (shouldBeMarkedAsUsed(programClass))
84        {
85            // Mark this class.
86            markAsUsed(programClass);
87
88            markProgramClassBody(programClass);
89        }
90    }
91
92
93    protected void markProgramClassBody(ProgramClass programClass)
94    {
95        // Mark this class's name.
96        markConstant(programClass, programClass.u2thisClass);
97
98        // Mark the superclass.
99        if (programClass.u2superClass != 0)
100        {
101            markConstant(programClass, programClass.u2superClass);
102        }
103
104        // Give the interfaces preliminary marks.
105        programClass.hierarchyAccept(false, false, true, false,
106                                     interfaceUsageMarker);
107
108        // Explicitly mark the <clinit> method, if it's not empty.
109        programClass.methodAccept(ClassConstants.METHOD_NAME_CLINIT,
110                                  ClassConstants.METHOD_TYPE_CLINIT,
111                                  nonEmptyMethodUsageMarker);
112
113        // Process all class members that have already been marked as possibly used.
114        programClass.fieldsAccept(possiblyUsedMemberUsageMarker);
115        programClass.methodsAccept(possiblyUsedMemberUsageMarker);
116
117        // Mark the attributes.
118        programClass.attributesAccept(this);
119    }
120
121
122    public void visitLibraryClass(LibraryClass libraryClass)
123    {
124        if (shouldBeMarkedAsUsed(libraryClass))
125        {
126            markAsUsed(libraryClass);
127
128            // We're not going to analyze all library code. We're assuming that
129            // if this class is being used, all of its methods will be used as
130            // well. We'll mark them as such (here and in all subclasses).
131
132            // Mark the superclass.
133            Clazz superClass = libraryClass.superClass;
134            if (superClass != null)
135            {
136                superClass.accept(this);
137            }
138
139            // Mark the interfaces.
140            Clazz[] interfaceClasses = libraryClass.interfaceClasses;
141            if (interfaceClasses != null)
142            {
143                for (int index = 0; index < interfaceClasses.length; index++)
144                {
145                    if (interfaceClasses[index] != null)
146                    {
147                        interfaceClasses[index].accept(this);
148                    }
149                }
150            }
151
152            // Mark all methods.
153            libraryClass.methodsAccept(this);
154        }
155    }
156
157
158    /**
159     * This ClassVisitor marks ProgramClass objects as possibly used,
160     * and it visits LibraryClass objects with its outer UsageMarker.
161     */
162    private class MyInterfaceUsageMarker
163    implements    ClassVisitor
164    {
165        public void visitProgramClass(ProgramClass programClass)
166        {
167            if (shouldBeMarkedAsPossiblyUsed(programClass))
168            {
169                // We can't process the interface yet, because it might not
170                // be required. Give it a preliminary mark.
171                markAsPossiblyUsed(programClass);
172            }
173        }
174
175        public void visitLibraryClass(LibraryClass libraryClass)
176        {
177            // Make sure all library interface methods are marked.
178            UsageMarker.this.visitLibraryClass(libraryClass);
179        }
180    }
181
182
183    /**
184     * This MemberVisitor marks ProgramField and ProgramMethod objects that
185     * have already been marked as possibly used.
186     */
187    private class MyPossiblyUsedMemberUsageMarker
188    extends       SimplifiedVisitor
189    implements    MemberVisitor
190    {
191        // Implementations for MemberVisitor.
192
193        public void visitProgramField(ProgramClass programClass, ProgramField programField)
194        {
195            // Has the method already been referenced?
196            if (isPossiblyUsed(programField))
197            {
198                markAsUsed(programField);
199
200                // Mark the name and descriptor.
201                markConstant(programClass, programField.u2nameIndex);
202                markConstant(programClass, programField.u2descriptorIndex);
203
204                // Mark the attributes.
205                programField.attributesAccept(programClass, UsageMarker.this);
206
207                // Mark the classes referenced in the descriptor string.
208                programField.referencedClassesAccept(UsageMarker.this);
209            }
210        }
211
212
213        public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
214        {
215            // Has the method already been referenced?
216            if (isPossiblyUsed(programMethod))
217            {
218                markAsUsed(programMethod);
219
220                // Mark the method body.
221                markProgramMethodBody(programClass, programMethod);
222
223                // Note that, if the method has been marked as possibly used,
224                // the method hierarchy has already been marked (cfr. below).
225            }
226        }
227    }
228
229
230    /**
231     * This AttributeVisitor marks ProgramMethod objects of non-empty methods.
232     */
233    private class MyNonEmptyMethodUsageMarker
234    extends       SimplifiedVisitor
235    implements    AttributeVisitor
236    {
237        // Implementations for AttributeVisitor.
238
239        public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
240
241
242        public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
243        {
244            if (codeAttribute.u4codeLength > 1)
245            {
246                method.accept(clazz, UsageMarker.this);
247            }
248        }
249    }
250
251
252    // Implementations for MemberVisitor.
253
254    public void visitProgramField(ProgramClass programClass, ProgramField programField)
255    {
256        if (shouldBeMarkedAsUsed(programField))
257        {
258            // Is the field's class used?
259            if (isUsed(programClass))
260            {
261                markAsUsed(programField);
262
263                // Mark the field body.
264                markProgramFieldBody(programClass, programField);
265            }
266
267            // Hasn't the field been marked as possibly being used yet?
268            else if (shouldBeMarkedAsPossiblyUsed(programField))
269            {
270                // We can't process the field yet, because the class isn't
271                // marked as being used (yet). Give it a preliminary mark.
272                markAsPossiblyUsed(programField);
273            }
274        }
275    }
276
277
278    public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
279    {
280        if (shouldBeMarkedAsUsed(programMethod))
281        {
282            // Is the method's class used?
283            if (isUsed(programClass))
284            {
285                markAsUsed(programMethod);
286
287                // Mark the method body.
288                markProgramMethodBody(programClass, programMethod);
289
290                // Mark the method hierarchy.
291                markMethodHierarchy(programClass, programMethod);
292            }
293
294            // Hasn't the method been marked as possibly being used yet?
295            else if (shouldBeMarkedAsPossiblyUsed(programMethod))
296            {
297                // We can't process the method yet, because the class isn't
298                // marked as being used (yet). Give it a preliminary mark.
299                markAsPossiblyUsed(programMethod);
300
301                // Mark the method hierarchy.
302                markMethodHierarchy(programClass, programMethod);
303            }
304        }
305    }
306
307
308    public void visitLibraryField(LibraryClass programClass, LibraryField programField) {}
309
310
311    public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
312    {
313        if (shouldBeMarkedAsUsed(libraryMethod))
314        {
315            markAsUsed(libraryMethod);
316
317            // Mark the method hierarchy.
318            markMethodHierarchy(libraryClass, libraryMethod);
319        }
320    }
321
322
323    protected void markProgramFieldBody(ProgramClass programClass, ProgramField programField)
324    {
325        // Mark the name and descriptor.
326        markConstant(programClass, programField.u2nameIndex);
327        markConstant(programClass, programField.u2descriptorIndex);
328
329        // Mark the attributes.
330        programField.attributesAccept(programClass, this);
331
332        // Mark the classes referenced in the descriptor string.
333        programField.referencedClassesAccept(this);
334    }
335
336
337    protected void markProgramMethodBody(ProgramClass programClass, ProgramMethod programMethod)
338    {
339        // Mark the name and descriptor.
340        markConstant(programClass, programMethod.u2nameIndex);
341        markConstant(programClass, programMethod.u2descriptorIndex);
342
343        // Mark the attributes.
344        programMethod.attributesAccept(programClass, this);
345
346        // Mark the classes referenced in the descriptor string.
347        programMethod.referencedClassesAccept(this);
348    }
349
350
351    /**
352     * Marks the hierarchy of implementing or overriding methods corresponding
353     * to the given method, if any.
354     */
355    protected void markMethodHierarchy(Clazz clazz, Method method)
356    {
357        int accessFlags = method.getAccessFlags();
358        if ((accessFlags &
359             (ClassConstants.ACC_PRIVATE |
360              ClassConstants.ACC_STATIC)) == 0 &&
361            !ClassUtil.isInitializer(method.getName(clazz)))
362        {
363            // We can skip private and static methods in the hierarchy, and
364            // also abstract methods, unless they might widen a current
365            // non-public access.
366            int requiredUnsetAccessFlags =
367                ClassConstants.ACC_PRIVATE |
368                ClassConstants.ACC_STATIC  |
369                ((accessFlags & ClassConstants.ACC_PUBLIC) == 0 ? 0 :
370                     ClassConstants.ACC_ABSTRACT);
371
372            clazz.accept(new ConcreteClassDownTraveler(
373                         new ClassHierarchyTraveler(true, true, false, true,
374                         new NamedMethodVisitor(method.getName(clazz),
375                                                method.getDescriptor(clazz),
376                         new MemberAccessFilter(0, requiredUnsetAccessFlags,
377                         this)))));
378        }
379    }
380
381
382    // Implementations for ConstantVisitor.
383
384    public void visitIntegerConstant(Clazz clazz, IntegerConstant integerConstant)
385    {
386        if (shouldBeMarkedAsUsed(integerConstant))
387        {
388            markAsUsed(integerConstant);
389        }
390    }
391
392
393    public void visitLongConstant(Clazz clazz, LongConstant longConstant)
394    {
395        if (shouldBeMarkedAsUsed(longConstant))
396        {
397            markAsUsed(longConstant);
398        }
399    }
400
401
402    public void visitFloatConstant(Clazz clazz, FloatConstant floatConstant)
403    {
404        if (shouldBeMarkedAsUsed(floatConstant))
405        {
406            markAsUsed(floatConstant);
407        }
408    }
409
410
411    public void visitDoubleConstant(Clazz clazz, DoubleConstant doubleConstant)
412    {
413        if (shouldBeMarkedAsUsed(doubleConstant))
414        {
415            markAsUsed(doubleConstant);
416        }
417    }
418
419
420    public void visitStringConstant(Clazz clazz, StringConstant stringConstant)
421    {
422        if (shouldBeMarkedAsUsed(stringConstant))
423        {
424            markAsUsed(stringConstant);
425
426            markConstant(clazz, stringConstant.u2stringIndex);
427
428            // Mark the referenced class and class member, if any.
429            stringConstant.referencedClassAccept(this);
430            stringConstant.referencedMemberAccept(this);
431        }
432    }
433
434
435    public void visitUtf8Constant(Clazz clazz, Utf8Constant utf8Constant)
436    {
437        if (shouldBeMarkedAsUsed(utf8Constant))
438        {
439            markAsUsed(utf8Constant);
440        }
441    }
442
443
444    public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
445    {
446        if (shouldBeMarkedAsUsed(invokeDynamicConstant))
447        {
448            markAsUsed(invokeDynamicConstant);
449
450            markConstant(clazz, invokeDynamicConstant.u2nameAndTypeIndex);
451
452            // Mark the referenced descriptor classes.
453            invokeDynamicConstant.referencedClassesAccept(this);
454
455            // Mark the bootstrap methods attribute.
456            clazz.attributesAccept(new MyBootStrapMethodUsageMarker(invokeDynamicConstant.u2bootstrapMethodAttributeIndex));
457        }
458    }
459
460
461    public void visitMethodHandleConstant(Clazz clazz, MethodHandleConstant methodHandleConstant)
462    {
463        if (shouldBeMarkedAsUsed(methodHandleConstant))
464        {
465            markAsUsed(methodHandleConstant);
466
467            markConstant(clazz, methodHandleConstant.u2referenceIndex);
468        }
469    }
470
471
472    public void visitAnyRefConstant(Clazz clazz, RefConstant refConstant)
473    {
474        if (shouldBeMarkedAsUsed(refConstant))
475        {
476            markAsUsed(refConstant);
477
478            markConstant(clazz, refConstant.u2classIndex);
479            markConstant(clazz, refConstant.u2nameAndTypeIndex);
480
481            // When compiled with "-target 1.2" or higher, the class or
482            // interface actually containing the referenced class member may
483            // be higher up the hierarchy. Make sure it's marked, in case it
484            // isn't used elsewhere.
485            refConstant.referencedClassAccept(this);
486
487            // Mark the referenced class member itself.
488            refConstant.referencedMemberAccept(this);
489        }
490    }
491
492
493    public void visitClassConstant(Clazz clazz, ClassConstant classConstant)
494    {
495        if (shouldBeMarkedAsUsed(classConstant))
496        {
497            markAsUsed(classConstant);
498
499            markConstant(clazz, classConstant.u2nameIndex);
500
501            // Mark the referenced class itself.
502            classConstant.referencedClassAccept(this);
503        }
504    }
505
506
507    public void visitMethodTypeConstant(Clazz clazz, MethodTypeConstant methodTypeConstant)
508    {
509        if (shouldBeMarkedAsUsed(methodTypeConstant))
510        {
511            markAsUsed(methodTypeConstant);
512
513            markConstant(clazz, methodTypeConstant.u2descriptorIndex);
514
515            // Mark the referenced descriptor classes.
516            methodTypeConstant.referencedClassesAccept(this);
517        }
518    }
519
520
521    public void visitNameAndTypeConstant(Clazz clazz, NameAndTypeConstant nameAndTypeConstant)
522    {
523        if (shouldBeMarkedAsUsed(nameAndTypeConstant))
524        {
525            markAsUsed(nameAndTypeConstant);
526
527            markConstant(clazz, nameAndTypeConstant.u2nameIndex);
528            markConstant(clazz, nameAndTypeConstant.u2descriptorIndex);
529        }
530    }
531
532
533    /**
534     * This AttributeVisitor marks the bootstrap methods attributes, their
535     * method entries, their method handles, and their arguments.
536     */
537    private class MyBootStrapMethodUsageMarker
538    extends       SimplifiedVisitor
539    implements    AttributeVisitor,
540                  BootstrapMethodInfoVisitor
541    {
542        private int bootstrapMethodIndex;
543
544
545        private MyBootStrapMethodUsageMarker(int bootstrapMethodIndex)
546        {
547            this.bootstrapMethodIndex = bootstrapMethodIndex;
548        }
549
550
551        // Implementations for AttributeVisitor.
552
553        public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
554
555
556        public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
557        {
558            if (shouldBeMarkedAsUsed(bootstrapMethodsAttribute))
559            {
560                markAsUsed(bootstrapMethodsAttribute);
561
562                markConstant(clazz, bootstrapMethodsAttribute.u2attributeNameIndex);
563            }
564
565            bootstrapMethodsAttribute.bootstrapMethodEntryAccept(clazz,
566                                                                 bootstrapMethodIndex,
567                                                                 this);
568        }
569
570
571        // Implementations for BootstrapMethodInfoVisitor.
572
573        public void visitBootstrapMethodInfo(Clazz clazz, BootstrapMethodInfo bootstrapMethodInfo)
574        {
575            markAsUsed(bootstrapMethodInfo);
576
577            markConstant(clazz, bootstrapMethodInfo.u2methodHandleIndex);
578
579            // Mark the constant pool entries referenced by the arguments.
580            bootstrapMethodInfo.methodArgumentsAccept(clazz, UsageMarker.this);
581        }
582    }
583
584
585    // Implementations for AttributeVisitor.
586    // Note that attributes are typically only referenced once, so we don't
587    // test if they have been marked already.
588
589    public void visitUnknownAttribute(Clazz clazz, UnknownAttribute unknownAttribute)
590    {
591        // This is the best we can do for unknown attributes.
592        markAsUsed(unknownAttribute);
593
594        markConstant(clazz, unknownAttribute.u2attributeNameIndex);
595    }
596
597
598    public void visitBootstrapMethodsAttribute(Clazz clazz, BootstrapMethodsAttribute bootstrapMethodsAttribute)
599    {
600        // Don't mark the attribute and its name here. We may mark it in
601        // MyBootStrapMethodsAttributeUsageMarker.
602    }
603
604
605    public void visitSourceFileAttribute(Clazz clazz, SourceFileAttribute sourceFileAttribute)
606    {
607        markAsUsed(sourceFileAttribute);
608
609        markConstant(clazz, sourceFileAttribute.u2attributeNameIndex);
610        markConstant(clazz, sourceFileAttribute.u2sourceFileIndex);
611    }
612
613
614    public void visitSourceDirAttribute(Clazz clazz, SourceDirAttribute sourceDirAttribute)
615    {
616        markAsUsed(sourceDirAttribute);
617
618        markConstant(clazz, sourceDirAttribute.u2attributeNameIndex);
619        markConstant(clazz, sourceDirAttribute.u2sourceDirIndex);
620    }
621
622
623    public void visitInnerClassesAttribute(Clazz clazz, InnerClassesAttribute innerClassesAttribute)
624    {
625        // Don't mark the attribute and its name yet. We may mark it later, in
626        // InnerUsageMarker.
627        //markAsUsed(innerClassesAttribute);
628
629        //markConstant(clazz, innerClassesAttribute.u2attrNameIndex);
630
631        // Do mark the outer class entries.
632        innerClassesAttribute.innerClassEntriesAccept(clazz, this);
633    }
634
635
636    public void visitEnclosingMethodAttribute(Clazz clazz, EnclosingMethodAttribute enclosingMethodAttribute)
637    {
638        markAsUsed(enclosingMethodAttribute);
639
640        markConstant(clazz, enclosingMethodAttribute.u2attributeNameIndex);
641        markConstant(clazz, enclosingMethodAttribute.u2classIndex);
642
643        if (enclosingMethodAttribute.u2nameAndTypeIndex != 0)
644        {
645            markConstant(clazz, enclosingMethodAttribute.u2nameAndTypeIndex);
646        }
647    }
648
649
650    public void visitDeprecatedAttribute(Clazz clazz, DeprecatedAttribute deprecatedAttribute)
651    {
652        markAsUsed(deprecatedAttribute);
653
654        markConstant(clazz, deprecatedAttribute.u2attributeNameIndex);
655    }
656
657
658    public void visitSyntheticAttribute(Clazz clazz, SyntheticAttribute syntheticAttribute)
659    {
660        markAsUsed(syntheticAttribute);
661
662        markConstant(clazz, syntheticAttribute.u2attributeNameIndex);
663    }
664
665
666    public void visitSignatureAttribute(Clazz clazz, SignatureAttribute signatureAttribute)
667    {
668        markAsUsed(signatureAttribute);
669
670        markConstant(clazz, signatureAttribute.u2attributeNameIndex);
671        markConstant(clazz, signatureAttribute.u2signatureIndex);
672
673        // Don't mark the referenced classes. We'll clean them up in
674        // ClassShrinker, if they appear unused.
675        //// Mark the classes referenced in the descriptor string.
676        //signatureAttribute.referencedClassesAccept(this);
677    }
678
679
680    public void visitConstantValueAttribute(Clazz clazz, Field field, ConstantValueAttribute constantValueAttribute)
681    {
682        markAsUsed(constantValueAttribute);
683
684        markConstant(clazz, constantValueAttribute.u2attributeNameIndex);
685        markConstant(clazz, constantValueAttribute.u2constantValueIndex);
686    }
687
688
689    public void visitMethodParametersAttribute(Clazz clazz, Method method, MethodParametersAttribute methodParametersAttribute)
690    {
691        markAsUsed(methodParametersAttribute);
692
693        markConstant(clazz, methodParametersAttribute.u2attributeNameIndex);
694
695        // Mark the constant pool entries referenced by the parameter information.
696        methodParametersAttribute.parametersAccept(clazz, method, this);
697    }
698
699
700    public void visitExceptionsAttribute(Clazz clazz, Method method, ExceptionsAttribute exceptionsAttribute)
701    {
702        markAsUsed(exceptionsAttribute);
703
704        markConstant(clazz, exceptionsAttribute.u2attributeNameIndex);
705
706        // Mark the constant pool entries referenced by the exceptions.
707        exceptionsAttribute.exceptionEntriesAccept((ProgramClass)clazz, this);
708    }
709
710
711    public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
712    {
713        markAsUsed(codeAttribute);
714
715        markConstant(clazz, codeAttribute.u2attributeNameIndex);
716
717        // Mark the constant pool entries referenced by the instructions,
718        // by the exceptions, and by the attributes.
719        codeAttribute.instructionsAccept(clazz, method, this);
720        codeAttribute.exceptionsAccept(clazz, method, this);
721        codeAttribute.attributesAccept(clazz, method, this);
722    }
723
724
725    public void visitStackMapAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapAttribute stackMapAttribute)
726    {
727        markAsUsed(stackMapAttribute);
728
729        markConstant(clazz, stackMapAttribute.u2attributeNameIndex);
730
731        // Mark the constant pool entries referenced by the stack map frames.
732        stackMapAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
733    }
734
735
736    public void visitStackMapTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, StackMapTableAttribute stackMapTableAttribute)
737    {
738        markAsUsed(stackMapTableAttribute);
739
740        markConstant(clazz, stackMapTableAttribute.u2attributeNameIndex);
741
742        // Mark the constant pool entries referenced by the stack map frames.
743        stackMapTableAttribute.stackMapFramesAccept(clazz, method, codeAttribute, this);
744    }
745
746
747    public void visitLineNumberTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LineNumberTableAttribute lineNumberTableAttribute)
748    {
749        markAsUsed(lineNumberTableAttribute);
750
751        markConstant(clazz, lineNumberTableAttribute.u2attributeNameIndex);
752    }
753
754
755    public void visitLocalVariableTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTableAttribute localVariableTableAttribute)
756    {
757        // Don't mark the attribute and its contents yet. We may mark them later,
758        // in LocalVariableTypeUsageMarker.
759        //markAsUsed(localVariableTableAttribute);
760        //
761        //markConstant(clazz, localVariableTableAttribute.u2attributeNameIndex);
762        //
763        //// Mark the constant pool entries referenced by the local variables.
764        //localVariableTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
765    }
766
767
768    public void visitLocalVariableTypeTableAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeTableAttribute localVariableTypeTableAttribute)
769    {
770        // Don't mark the attribute and its contents yet. We may mark them later,
771        // in LocalVariableTypeUsageMarker.
772        //markAsUsed(localVariableTypeTableAttribute);
773        //
774        //markConstant(clazz, localVariableTypeTableAttribute.u2attributeNameIndex);
775        //
776        //// Mark the constant pool entries referenced by the local variable types.
777        //localVariableTypeTableAttribute.localVariablesAccept(clazz, method, codeAttribute, this);
778    }
779
780
781    public void visitAnyAnnotationsAttribute(Clazz clazz, AnnotationsAttribute annotationsAttribute)
782    {
783        // Don't mark the attribute and its contents yet. We may mark them later,
784        // in AnnotationUsageMarker.
785        //markAsUsed(annotationsAttribute);
786        //
787        //markConstant(clazz, annotationsAttribute.u2attributeNameIndex);
788        //
789        //// Mark the constant pool entries referenced by the annotations.
790        //annotationsAttribute.annotationsAccept(clazz, this);
791    }
792
793
794    public void visitAnyParameterAnnotationsAttribute(Clazz clazz, Method method, ParameterAnnotationsAttribute parameterAnnotationsAttribute)
795    {
796        // Don't mark the attribute and its contents yet. We may mark them later,
797        // in AnnotationUsageMarker.
798        //markAsUsed(parameterAnnotationsAttribute);
799        //
800        //markConstant(clazz, parameterAnnotationsAttribute.u2attributeNameIndex);
801        //
802        //// Mark the constant pool entries referenced by the annotations.
803        //parameterAnnotationsAttribute.annotationsAccept(clazz, method, this);
804    }
805
806
807    public void visitAnnotationDefaultAttribute(Clazz clazz, Method method, AnnotationDefaultAttribute annotationDefaultAttribute)
808    {
809        // Don't mark the attribute and its contents yet. We may mark them later,
810        // in AnnotationUsageMarker.
811        //markAsUsed(annotationDefaultAttribute);
812        //
813        //markConstant(clazz, annotationDefaultAttribute.u2attributeNameIndex);
814        //
815        //// Mark the constant pool entries referenced by the element value.
816        //annotationDefaultAttribute.defaultValueAccept(clazz, this);
817    }
818
819
820    // Implementations for ExceptionInfoVisitor.
821
822    public void visitExceptionInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, ExceptionInfo exceptionInfo)
823    {
824        markAsUsed(exceptionInfo);
825
826        if (exceptionInfo.u2catchType != 0)
827        {
828            markConstant(clazz, exceptionInfo.u2catchType);
829        }
830    }
831
832
833    // Implementations for InnerClassesInfoVisitor.
834
835    public void visitInnerClassesInfo(Clazz clazz, InnerClassesInfo innerClassesInfo)
836    {
837        // At this point, we only mark outer classes of this class.
838        // Inner class can be marked later, by InnerUsageMarker.
839        if (innerClassesInfo.u2innerClassIndex != 0 &&
840            clazz.getName().equals(clazz.getClassName(innerClassesInfo.u2innerClassIndex)))
841        {
842            markAsUsed(innerClassesInfo);
843
844            innerClassesInfo.innerClassConstantAccept(clazz, this);
845            innerClassesInfo.outerClassConstantAccept(clazz, this);
846            innerClassesInfo.innerNameConstantAccept(clazz, this);
847        }
848    }
849
850
851    // Implementations for StackMapFrameVisitor.
852
853    public void visitAnyStackMapFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, StackMapFrame stackMapFrame) {}
854
855
856    public void visitSameOneFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SameOneFrame sameOneFrame)
857    {
858        // Mark the constant pool entries referenced by the verification types.
859        sameOneFrame.stackItemAccept(clazz, method, codeAttribute, offset, this);
860    }
861
862
863    public void visitMoreZeroFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, MoreZeroFrame moreZeroFrame)
864    {
865        // Mark the constant pool entries referenced by the verification types.
866        moreZeroFrame.additionalVariablesAccept(clazz, method, codeAttribute, offset, this);
867    }
868
869
870    public void visitFullFrame(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, FullFrame fullFrame)
871    {
872        // Mark the constant pool entries referenced by the verification types.
873        fullFrame.variablesAccept(clazz, method, codeAttribute, offset, this);
874        fullFrame.stackAccept(clazz, method, codeAttribute, offset, this);
875    }
876
877
878    // Implementations for VerificationTypeVisitor.
879
880    public void visitAnyVerificationType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VerificationType verificationType) {}
881
882
883    public void visitObjectType(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ObjectType objectType)
884    {
885        markConstant(clazz, objectType.u2classIndex);
886    }
887
888
889    // Implementations for ParameterInfoVisitor.
890
891    public void visitParameterInfo(Clazz clazz, Method method, int parameterIndex, ParameterInfo parameterInfo)
892    {
893        markConstant(clazz, parameterInfo.u2nameIndex);
894    }
895
896
897    // Implementations for LocalVariableInfoVisitor.
898
899    public void visitLocalVariableInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableInfo localVariableInfo)
900    {
901        markConstant(clazz, localVariableInfo.u2nameIndex);
902        markConstant(clazz, localVariableInfo.u2descriptorIndex);
903    }
904
905
906    // Implementations for LocalVariableTypeInfoVisitor.
907
908    public void visitLocalVariableTypeInfo(Clazz clazz, Method method, CodeAttribute codeAttribute, LocalVariableTypeInfo localVariableTypeInfo)
909    {
910        markConstant(clazz, localVariableTypeInfo.u2nameIndex);
911        markConstant(clazz, localVariableTypeInfo.u2signatureIndex);
912    }
913
914
915//    // Implementations for AnnotationVisitor.
916//
917//    public void visitAnnotation(Clazz clazz, Annotation annotation)
918//    {
919//        markConstant(clazz, annotation.u2typeIndex);
920//
921//        // Mark the constant pool entries referenced by the element values.
922//        annotation.elementValuesAccept(clazz, this);
923//    }
924//
925//
926//    // Implementations for ElementValueVisitor.
927//
928//    public void visitConstantElementValue(Clazz clazz, Annotation annotation, ConstantElementValue constantElementValue)
929//    {
930//        if (constantElementValue.u2elementNameIndex != 0)
931//        {
932//            markConstant(clazz, constantElementValue.u2elementNameIndex);
933//        }
934//
935//        markConstant(clazz, constantElementValue.u2constantValueIndex);
936//    }
937//
938//
939//    public void visitEnumConstantElementValue(Clazz clazz, Annotation annotation, EnumConstantElementValue enumConstantElementValue)
940//    {
941//        if (enumConstantElementValue.u2elementNameIndex != 0)
942//        {
943//            markConstant(clazz, enumConstantElementValue.u2elementNameIndex);
944//        }
945//
946//        markConstant(clazz, enumConstantElementValue.u2typeNameIndex);
947//        markConstant(clazz, enumConstantElementValue.u2constantNameIndex);
948//    }
949//
950//
951//    public void visitClassElementValue(Clazz clazz, Annotation annotation, ClassElementValue classElementValue)
952//    {
953//        if (classElementValue.u2elementNameIndex != 0)
954//        {
955//            markConstant(clazz, classElementValue.u2elementNameIndex);
956//        }
957//
958//        // Mark the referenced class constant pool entry.
959//        markConstant(clazz, classElementValue.u2classInfoIndex);
960//    }
961//
962//
963//    public void visitAnnotationElementValue(Clazz clazz, Annotation annotation, AnnotationElementValue annotationElementValue)
964//    {
965//        if (annotationElementValue.u2elementNameIndex != 0)
966//        {
967//            markConstant(clazz, annotationElementValue.u2elementNameIndex);
968//        }
969//
970//        // Mark the constant pool entries referenced by the annotation.
971//        annotationElementValue.annotationAccept(clazz, this);
972//    }
973//
974//
975//    public void visitArrayElementValue(Clazz clazz, Annotation annotation, ArrayElementValue arrayElementValue)
976//    {
977//        if (arrayElementValue.u2elementNameIndex != 0)
978//        {
979//            markConstant(clazz, arrayElementValue.u2elementNameIndex);
980//        }
981//
982//        // Mark the constant pool entries referenced by the element values.
983//        arrayElementValue.elementValuesAccept(clazz, annotation, this);
984//    }
985
986
987    // Implementations for InstructionVisitor.
988
989    public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
990
991
992    public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
993    {
994        markConstant(clazz, constantInstruction.constantIndex);
995
996        // Also mark the parameterless constructor of the class, in case the
997        // string constant or class constant is being used in a Class.forName
998        // or a .class construct.
999        clazz.constantPoolEntryAccept(constantInstruction.constantIndex,
1000                                      parameterlessConstructorMarker);
1001    }
1002
1003
1004    // Small utility methods.
1005
1006    /**
1007     * Marks the given visitor accepter as being used.
1008     */
1009    protected void markAsUsed(VisitorAccepter visitorAccepter)
1010    {
1011        visitorAccepter.setVisitorInfo(USED);
1012    }
1013
1014
1015    /**
1016     * Returns whether the given visitor accepter should still be marked as
1017     * being used.
1018     */
1019    protected boolean shouldBeMarkedAsUsed(VisitorAccepter visitorAccepter)
1020    {
1021        return visitorAccepter.getVisitorInfo() != USED;
1022    }
1023
1024
1025    /**
1026     * Returns whether the given visitor accepter has been marked as being used.
1027     */
1028    protected boolean isUsed(VisitorAccepter visitorAccepter)
1029    {
1030        return visitorAccepter.getVisitorInfo() == USED;
1031    }
1032
1033
1034    /**
1035     * Marks the given visitor accepter as possibly being used.
1036     */
1037    protected void markAsPossiblyUsed(VisitorAccepter visitorAccepter)
1038    {
1039        visitorAccepter.setVisitorInfo(POSSIBLY_USED);
1040    }
1041
1042
1043    /**
1044     * Returns whether the given visitor accepter should still be marked as
1045     * possibly being used.
1046     */
1047    protected boolean shouldBeMarkedAsPossiblyUsed(VisitorAccepter visitorAccepter)
1048    {
1049        return visitorAccepter.getVisitorInfo() != USED &&
1050               visitorAccepter.getVisitorInfo() != POSSIBLY_USED;
1051    }
1052
1053
1054    /**
1055     * Returns whether the given visitor accepter has been marked as possibly
1056     * being used.
1057     */
1058    protected boolean isPossiblyUsed(VisitorAccepter visitorAccepter)
1059    {
1060        return visitorAccepter.getVisitorInfo() == POSSIBLY_USED;
1061    }
1062
1063
1064    /**
1065     * Clears any usage marks from the given visitor accepter.
1066     */
1067    protected void markAsUnused(VisitorAccepter visitorAccepter)
1068    {
1069        visitorAccepter.setVisitorInfo(null);
1070    }
1071
1072
1073    /**
1074     * Marks the given constant pool entry of the given class. This includes
1075     * visiting any referenced objects.
1076     */
1077    private void markConstant(Clazz clazz, int index)
1078    {
1079        clazz.constantPoolEntryAccept(index, this);
1080    }
1081}
1082