1 /*
  2  * Copyright (c) 2022, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 package jdk.internal.classfile.impl;
 26 
 27 import java.lang.classfile.Annotation;
 28 import java.lang.classfile.Attribute;
 29 import java.lang.classfile.AttributeMapper;
 30 import java.lang.classfile.AttributedElement;
 31 import java.lang.classfile.BufWriter;
 32 import java.lang.classfile.ClassReader;
 33 import java.lang.classfile.attribute.*;
 34 import java.util.List;
 35 
 36 import static java.lang.classfile.Attributes.*;
 37 
 38 public sealed abstract class AbstractAttributeMapper<T extends Attribute<T>>
 39         implements AttributeMapper<T> {
 40 
 41     private final String name;
 42     private final AttributeMapper.AttributeStability stability;
 43     private final boolean allowMultiple;
 44 
 45     protected abstract void writeBody(BufWriter buf, T attr);
 46 
 47     public AbstractAttributeMapper(String name, AttributeMapper.AttributeStability stability) {
 48         this(name, stability, false);
 49     }
 50 
 51     public AbstractAttributeMapper(String name,
 52                                    AttributeMapper.AttributeStability stability,
 53                                    boolean allowMultiple) {
 54         this.name = name;
 55         this.stability = stability;
 56         this.allowMultiple = allowMultiple;
 57     }
 58 
 59     @Override
 60     public final String name() {
 61         return name;
 62     }
 63 
 64     @Override
 65     public final void writeAttribute(BufWriter buf, T attr) {
 66         buf.writeIndex(buf.constantPool().utf8Entry(name));
 67         buf.writeInt(0);
 68         int start = buf.size();
 69         writeBody(buf, attr);
 70         int written = buf.size() - start;
 71         buf.patchInt(start - 4, 4, written);
 72     }
 73 
 74     @Override
 75     public AttributeMapper.AttributeStability stability() {
 76         return stability;
 77     }
 78 
 79     @Override
 80     public boolean allowMultiple() {
 81         return allowMultiple;
 82     }
 83 
 84     @Override
 85     public String toString() {
 86         return String.format("AttributeMapper[name=%s, allowMultiple=%b, stability=%s]",
 87                 name, allowMultiple, stability());
 88     }
 89 
 90     public static final class AnnotationDefaultMapper extends AbstractAttributeMapper<AnnotationDefaultAttribute> {
 91         public static final AnnotationDefaultMapper INSTANCE = new AnnotationDefaultMapper();
 92 
 93         private AnnotationDefaultMapper() {
 94             super(NAME_ANNOTATION_DEFAULT, AttributeStability.CP_REFS);
 95         }
 96 
 97         @Override
 98         public AnnotationDefaultAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
 99             return new BoundAttribute.BoundAnnotationDefaultAttr(cf, this, p);
100         }
101 
102         @Override
103         protected void writeBody(BufWriter buf, AnnotationDefaultAttribute attr) {
104             attr.defaultValue().writeTo(buf);
105         }
106     }
107 
108     public static final class BootstrapMethodsMapper extends AbstractAttributeMapper<BootstrapMethodsAttribute> {
109         public static final BootstrapMethodsMapper INSTANCE = new BootstrapMethodsMapper();
110 
111         private BootstrapMethodsMapper() {
112             super(NAME_BOOTSTRAP_METHODS, AttributeStability.CP_REFS);
113         }
114 
115         @Override
116         public BootstrapMethodsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
117             return new BoundAttribute.BoundBootstrapMethodsAttribute(cf, this, p);
118         }
119 
120         @Override
121         protected void writeBody(BufWriter buf, BootstrapMethodsAttribute attr) {
122             buf.writeList(attr.bootstrapMethods());
123         }
124     }
125 
126     public static final class CharacterRangeTableMapper extends AbstractAttributeMapper<CharacterRangeTableAttribute> {
127         public static final CharacterRangeTableMapper INSTANCE = new CharacterRangeTableMapper();
128 
129         private CharacterRangeTableMapper() {
130             super(NAME_CHARACTER_RANGE_TABLE, AttributeStability.LABELS, true);
131         }
132 
133         @Override
134         public CharacterRangeTableAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
135             return new BoundAttribute.BoundCharacterRangeTableAttribute(cf, this, p);
136         }
137 
138         @Override
139         protected void writeBody(BufWriter buf, CharacterRangeTableAttribute attr) {
140             List<CharacterRangeInfo> ranges = attr.characterRangeTable();
141             buf.writeU2(ranges.size());
142             for (CharacterRangeInfo info : ranges) {
143                 buf.writeU2(info.startPc());
144                 buf.writeU2(info.endPc());
145                 buf.writeInt(info.characterRangeStart());
146                 buf.writeInt(info.characterRangeEnd());
147                 buf.writeU2(info.flags());
148             }
149         }
150     }
151 
152     public static final class CodeMapper extends AbstractAttributeMapper<CodeAttribute> {
153         public static final CodeMapper INSTANCE = new CodeMapper();
154 
155         private CodeMapper() {
156             super(NAME_CODE, AttributeStability.CP_REFS);
157         }
158 
159         @Override
160         public CodeAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
161             return new CodeImpl(e, cf, this, p);
162         }
163 
164         @Override
165         protected void writeBody(BufWriter buf, CodeAttribute attr) {
166             throw new UnsupportedOperationException("Code attribute does not support direct write");
167         }
168     }
169 
170     public static final class CompilationIDMapper extends AbstractAttributeMapper<CompilationIDAttribute> {
171         public static final CompilationIDMapper INSTANCE = new CompilationIDMapper();
172 
173         private CompilationIDMapper() {
174             super(NAME_COMPILATION_ID, AttributeStability.CP_REFS);
175         }
176 
177         @Override
178         public CompilationIDAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
179             return new BoundAttribute.BoundCompilationIDAttribute(cf, this, p);
180         }
181 
182         @Override
183         protected void writeBody(BufWriter buf, CompilationIDAttribute attr) {
184             buf.writeIndex(attr.compilationId());
185         }
186     }
187 
188     public static final class ConstantValueMapper extends AbstractAttributeMapper<ConstantValueAttribute> {
189         public static final ConstantValueMapper INSTANCE = new ConstantValueMapper();
190 
191         private ConstantValueMapper() {
192             super(NAME_CONSTANT_VALUE, AttributeStability.CP_REFS);
193         }
194 
195         @Override
196         public ConstantValueAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
197             return new BoundAttribute.BoundConstantValueAttribute(cf, this, p);
198         }
199 
200         @Override
201         protected void writeBody(BufWriter buf, ConstantValueAttribute attr) {
202             buf.writeIndex(attr.constant());
203         }
204     }
205 
206     public static final class DeprecatedMapper extends AbstractAttributeMapper<DeprecatedAttribute> {
207         public static final DeprecatedMapper INSTANCE = new DeprecatedMapper();
208 
209         private DeprecatedMapper() {
210             super(NAME_DEPRECATED, AttributeStability.STATELESS, true);
211         }
212 
213         @Override
214         public DeprecatedAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
215             return new BoundAttribute.BoundDeprecatedAttribute(cf, this, p);
216         }
217 
218         @Override
219         protected void writeBody(BufWriter buf, DeprecatedAttribute attr) {
220             // empty
221         }
222     }
223 
224     public static final class EnclosingMethodMapper extends AbstractAttributeMapper<EnclosingMethodAttribute> {
225         public static final EnclosingMethodMapper INSTANCE = new EnclosingMethodMapper();
226 
227         private EnclosingMethodMapper() {
228             super(NAME_ENCLOSING_METHOD, AttributeStability.CP_REFS);
229         }
230 
231         @Override
232         public EnclosingMethodAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
233             return new BoundAttribute.BoundEnclosingMethodAttribute(cf, this, p);
234         }
235 
236         @Override
237         protected void writeBody(BufWriter buf, EnclosingMethodAttribute attr) {
238             buf.writeIndex(attr.enclosingClass());
239             buf.writeIndexOrZero(attr.enclosingMethod().orElse(null));
240         }
241     }
242 
243     public static final class ExceptionsMapper extends AbstractAttributeMapper<ExceptionsAttribute> {
244         public static final ExceptionsMapper INSTANCE = new ExceptionsMapper();
245 
246         private ExceptionsMapper() {
247             super(NAME_EXCEPTIONS, AttributeStability.CP_REFS);
248         }
249 
250         @Override
251         public ExceptionsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
252             return new BoundAttribute.BoundExceptionsAttribute(cf, this, p);
253         }
254 
255         @Override
256         protected void writeBody(BufWriter buf, ExceptionsAttribute attr) {
257             buf.writeListIndices(attr.exceptions());
258         }
259     }
260 
261     public static final class InnerClassesMapper extends AbstractAttributeMapper<InnerClassesAttribute> {
262         public static final InnerClassesMapper INSTANCE = new InnerClassesMapper();
263 
264         private InnerClassesMapper() {
265             super(NAME_INNER_CLASSES, AttributeStability.CP_REFS);
266         }
267 
268         @Override
269         public InnerClassesAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
270             return new BoundAttribute.BoundInnerClassesAttribute(cf, this, p);
271         }
272 
273         @Override
274         protected void writeBody(BufWriter buf, InnerClassesAttribute attr) {
275             List<InnerClassInfo> classes = attr.classes();
276             buf.writeU2(classes.size());
277             for (InnerClassInfo ic : classes) {
278                 buf.writeIndex(ic.innerClass());
279                 buf.writeIndexOrZero(ic.outerClass().orElse(null));
280                 buf.writeIndexOrZero(ic.innerName().orElse(null));
281                 buf.writeU2(ic.flagsMask());
282             }
283         }
284     }
285 
286     public static final class LineNumberTableMapper extends AbstractAttributeMapper<LineNumberTableAttribute> {
287         public static final LineNumberTableMapper INSTANCE = new LineNumberTableMapper();
288 
289         private LineNumberTableMapper() {
290             super(NAME_LINE_NUMBER_TABLE, AttributeStability.LABELS, true);
291         }
292 
293         @Override
294         public LineNumberTableAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
295             return new BoundAttribute.BoundLineNumberTableAttribute(cf, this, p);
296         }
297 
298         @Override
299         protected void writeBody(BufWriter buf, LineNumberTableAttribute attr) {
300             List<LineNumberInfo> lines = attr.lineNumbers();
301             buf.writeU2(lines.size());
302             for (LineNumberInfo line : lines) {
303                 buf.writeU2(line.startPc());
304                 buf.writeU2(line.lineNumber());
305             }
306         }
307     }
308 
309     public static final class LoadableDescriptorsMapper extends AbstractAttributeMapper<LoadableDescriptorsAttribute> {
310         public static final LoadableDescriptorsMapper INSTANCE = new LoadableDescriptorsMapper();
311 
312         private LoadableDescriptorsMapper() {
313             super(NAME_LOADABLE_DESCRIPTORS, AttributeStability.CP_REFS);
314         }
315 
316         @Override
317         public LoadableDescriptorsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
318             return new BoundAttribute.BoundLoadableDescriptorsAttribute(cf, this, p);
319         }
320 
321         @Override
322         protected void writeBody(BufWriter buf, LoadableDescriptorsAttribute attr) {
323             buf.writeListIndices(attr.loadableDescriptors());
324         }
325     }
326 
327     public static final class LocalVariableTableMapper extends AbstractAttributeMapper<LocalVariableTableAttribute> {
328         public static final LocalVariableTableMapper INSTANCE = new LocalVariableTableMapper();
329 
330         private LocalVariableTableMapper() {
331             super(NAME_LOCAL_VARIABLE_TABLE, AttributeStability.LABELS, true);
332         }
333 
334         @Override
335         public LocalVariableTableAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
336             return new BoundAttribute.BoundLocalVariableTableAttribute(e, cf, this, p);
337         }
338 
339         @Override
340         protected void writeBody(BufWriter buf, LocalVariableTableAttribute attr) {
341             List<LocalVariableInfo> infos = attr.localVariables();
342             buf.writeU2(infos.size());
343             for (LocalVariableInfo info : infos) {
344                 buf.writeU2(info.startPc());
345                 buf.writeU2(info.length());
346                 buf.writeIndex(info.name());
347                 buf.writeIndex(info.type());
348                 buf.writeU2(info.slot());
349             }
350         }
351     }
352 
353     public static final class LocalVariableTypeTableMapper extends AbstractAttributeMapper<LocalVariableTypeTableAttribute> {
354         public static final LocalVariableTypeTableMapper INSTANCE = new LocalVariableTypeTableMapper();
355 
356         private LocalVariableTypeTableMapper() {
357             super(NAME_LOCAL_VARIABLE_TYPE_TABLE, AttributeStability.LABELS, true);
358         }
359 
360         @Override
361         public LocalVariableTypeTableAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
362             return new BoundAttribute.BoundLocalVariableTypeTableAttribute(e, cf, this, p);
363         }
364 
365         @Override
366         protected void writeBody(BufWriter buf, LocalVariableTypeTableAttribute attr) {
367             List<LocalVariableTypeInfo> infos = attr.localVariableTypes();
368             buf.writeU2(infos.size());
369             for (LocalVariableTypeInfo info : infos) {
370                 buf.writeU2(info.startPc());
371                 buf.writeU2(info.length());
372                 buf.writeIndex(info.name());
373                 buf.writeIndex(info.signature());
374                 buf.writeU2(info.slot());
375             }
376         }
377     }
378 
379     public static final class MethodParametersMapper extends AbstractAttributeMapper<MethodParametersAttribute> {
380         public static final MethodParametersMapper INSTANCE = new MethodParametersMapper();
381 
382         private MethodParametersMapper() {
383             super(NAME_METHOD_PARAMETERS, AttributeStability.CP_REFS);
384         }
385 
386         @Override
387         public MethodParametersAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
388             return new BoundAttribute.BoundMethodParametersAttribute(cf, this, p);
389         }
390 
391         @Override
392         protected void writeBody(BufWriter buf, MethodParametersAttribute attr) {
393             List<MethodParameterInfo> parameters = attr.parameters();
394             buf.writeU1(parameters.size());
395             for (MethodParameterInfo info : parameters) {
396                 buf.writeIndexOrZero(info.name().orElse(null));
397                 buf.writeU2(info.flagsMask());
398             }
399         }
400     }
401 
402     public static final class ModuleMapper extends AbstractAttributeMapper<ModuleAttribute> {
403         public static final ModuleMapper INSTANCE = new ModuleMapper();
404 
405         private ModuleMapper() {
406             super(NAME_MODULE, AttributeStability.CP_REFS);
407         }
408 
409         @Override
410         public ModuleAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
411             return new BoundAttribute.BoundModuleAttribute(cf, this, p);
412         }
413 
414         @Override
415         protected void writeBody(BufWriter buf, ModuleAttribute attr) {
416             buf.writeIndex(attr.moduleName());
417             buf.writeU2(attr.moduleFlagsMask());
418             buf.writeIndexOrZero(attr.moduleVersion().orElse(null));
419             buf.writeU2(attr.requires().size());
420             for (ModuleRequireInfo require : attr.requires()) {
421                 buf.writeIndex(require.requires());
422                 buf.writeU2(require.requiresFlagsMask());
423                 buf.writeIndexOrZero(require.requiresVersion().orElse(null));
424             }
425             buf.writeU2(attr.exports().size());
426             for (ModuleExportInfo export : attr.exports()) {
427                 buf.writeIndex(export.exportedPackage());
428                 buf.writeU2(export.exportsFlagsMask());
429                 buf.writeListIndices(export.exportsTo());
430             }
431             buf.writeU2(attr.opens().size());
432             for (ModuleOpenInfo open : attr.opens()) {
433                 buf.writeIndex(open.openedPackage());
434                 buf.writeU2(open.opensFlagsMask());
435                 buf.writeListIndices(open.opensTo());
436             }
437             buf.writeListIndices(attr.uses());
438             buf.writeU2(attr.provides().size());
439             for (ModuleProvideInfo provide : attr.provides()) {
440                 buf.writeIndex(provide.provides());
441                 buf.writeListIndices(provide.providesWith());
442             }
443         }
444     }
445 
446     public static final class ModuleHashesMapper extends AbstractAttributeMapper<ModuleHashesAttribute> {
447         public static final ModuleHashesMapper INSTANCE = new ModuleHashesMapper();
448 
449         private ModuleHashesMapper() {
450             super(NAME_MODULE_HASHES, AttributeStability.CP_REFS);
451         }
452 
453         @Override
454         public ModuleHashesAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
455             return new BoundAttribute.BoundModuleHashesAttribute(cf, this, p);
456         }
457 
458         @Override
459         protected void writeBody(BufWriter buf, ModuleHashesAttribute attr) {
460             buf.writeIndex(attr.algorithm());
461             List<ModuleHashInfo> hashes = attr.hashes();
462             buf.writeU2(hashes.size());
463             for (ModuleHashInfo hash : hashes) {
464                 buf.writeIndex(hash.moduleName());
465                 buf.writeU2(hash.hash().length);
466                 buf.writeBytes(hash.hash());
467             }
468         }
469     }
470 
471     public static final class ModuleMainClassMapper extends AbstractAttributeMapper<ModuleMainClassAttribute> {
472         public static final ModuleMainClassMapper INSTANCE = new ModuleMainClassMapper();
473 
474         private ModuleMainClassMapper() {
475             super(NAME_MODULE_MAIN_CLASS, AttributeStability.CP_REFS);
476         }
477 
478         @Override
479         public ModuleMainClassAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
480             return new BoundAttribute.BoundModuleMainClassAttribute(cf, this, p);
481         }
482 
483         @Override
484         protected void writeBody(BufWriter buf, ModuleMainClassAttribute attr) {
485             buf.writeIndex(attr.mainClass());
486         }
487     }
488 
489     public static final class ModulePackagesMapper extends AbstractAttributeMapper<ModulePackagesAttribute> {
490         public static final ModulePackagesMapper INSTANCE = new ModulePackagesMapper();
491 
492         private ModulePackagesMapper() {
493             super(NAME_MODULE_PACKAGES, AttributeStability.CP_REFS);
494         }
495 
496         @Override
497         public ModulePackagesAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
498             return new BoundAttribute.BoundModulePackagesAttribute(cf, this, p);
499         }
500 
501         @Override
502         protected void writeBody(BufWriter buf, ModulePackagesAttribute attr) {
503             buf.writeListIndices(attr.packages());
504         }
505     }
506 
507     public static final class ModuleResolutionMapper extends AbstractAttributeMapper<ModuleResolutionAttribute> {
508         public static final ModuleResolutionMapper INSTANCE = new ModuleResolutionMapper();
509 
510         private ModuleResolutionMapper() {
511             super(NAME_MODULE_RESOLUTION, AttributeStability.STATELESS);
512         }
513 
514         @Override
515         public ModuleResolutionAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
516             return new BoundAttribute.BoundModuleResolutionAttribute(cf, this, p);
517         }
518 
519         @Override
520         protected void writeBody(BufWriter buf, ModuleResolutionAttribute attr) {
521             buf.writeU2(attr.resolutionFlags());
522         }
523     }
524 
525     public static final class ModuleTargetMapper extends AbstractAttributeMapper<ModuleTargetAttribute> {
526         public static final ModuleTargetMapper INSTANCE = new ModuleTargetMapper();
527 
528         private ModuleTargetMapper() {
529             super(NAME_MODULE_TARGET, AttributeStability.CP_REFS);
530         }
531 
532         @Override
533         public ModuleTargetAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
534             return new BoundAttribute.BoundModuleTargetAttribute(cf, this, p);
535         }
536 
537         @Override
538         protected void writeBody(BufWriter buf, ModuleTargetAttribute attr) {
539             buf.writeIndex(attr.targetPlatform());
540         }
541     }
542 
543     public static final class NestHostMapper extends AbstractAttributeMapper<NestHostAttribute> {
544         public static final NestHostMapper INSTANCE = new NestHostMapper();
545 
546         private NestHostMapper() {
547             super(NAME_NEST_HOST, AttributeStability.CP_REFS);
548         }
549 
550         @Override
551         public NestHostAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
552             return new BoundAttribute.BoundNestHostAttribute(cf, this, p);
553         }
554 
555         @Override
556         protected void writeBody(BufWriter buf, NestHostAttribute attr) {
557             buf.writeIndex(attr.nestHost());
558         }
559     }
560 
561     public static final class NestMembersMapper extends AbstractAttributeMapper<NestMembersAttribute> {
562         public static final NestMembersMapper INSTANCE = new NestMembersMapper();
563 
564         private NestMembersMapper() {
565             super(NAME_NEST_MEMBERS, AttributeStability.CP_REFS);
566         }
567 
568         @Override
569         public NestMembersAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
570             return new BoundAttribute.BoundNestMembersAttribute(cf, this, p);
571         }
572 
573         @Override
574         protected void writeBody(BufWriter buf, NestMembersAttribute attr) {
575             buf.writeListIndices(attr.nestMembers());
576         }
577     }
578 
579     public static final class PermittedSubclassesMapper extends AbstractAttributeMapper<PermittedSubclassesAttribute> {
580         public static final PermittedSubclassesMapper INSTANCE = new PermittedSubclassesMapper();
581 
582         private PermittedSubclassesMapper() {
583             super(NAME_PERMITTED_SUBCLASSES, AttributeStability.CP_REFS);
584         }
585 
586         @Override
587         public PermittedSubclassesAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
588             return new BoundAttribute.BoundPermittedSubclassesAttribute(cf, this, p);
589         }
590 
591         @Override
592         protected void writeBody(BufWriter buf, PermittedSubclassesAttribute attr) {
593             buf.writeListIndices(attr.permittedSubclasses());
594         }
595     }
596 
597     public static final class RecordMapper extends AbstractAttributeMapper<RecordAttribute> {
598         public static final RecordMapper INSTANCE = new RecordMapper();
599 
600         private RecordMapper() {
601             super(NAME_RECORD, AttributeStability.CP_REFS);
602         }
603 
604         @Override
605         public RecordAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
606             return new BoundAttribute.BoundRecordAttribute(cf, this, p);
607         }
608 
609         @Override
610         protected void writeBody(BufWriter buf, RecordAttribute attr) {
611             List<RecordComponentInfo> components = attr.components();
612             buf.writeU2(components.size());
613             for (RecordComponentInfo info : components) {
614                 buf.writeIndex(info.name());
615                 buf.writeIndex(info.descriptor());
616                 buf.writeList(info.attributes());
617             }
618         }
619     }
620 
621     public static final class RuntimeInvisibleAnnotationsMapper extends AbstractAttributeMapper<RuntimeInvisibleAnnotationsAttribute> {
622         public static final RuntimeInvisibleAnnotationsMapper INSTANCE = new RuntimeInvisibleAnnotationsMapper();
623 
624         private RuntimeInvisibleAnnotationsMapper() {
625             super(NAME_RUNTIME_INVISIBLE_ANNOTATIONS, AttributeStability.CP_REFS);
626         }
627 
628         @Override
629         public RuntimeInvisibleAnnotationsAttribute readAttribute(AttributedElement enclosing, ClassReader cf, int pos) {
630             return new BoundAttribute.BoundRuntimeInvisibleAnnotationsAttribute(cf, pos);
631         }
632 
633         @Override
634         protected void writeBody(BufWriter buf, RuntimeInvisibleAnnotationsAttribute attr) {
635             buf.writeList(attr.annotations());
636         }
637     }
638 
639     public static final class RuntimeInvisibleParameterAnnotationsMapper extends AbstractAttributeMapper<RuntimeInvisibleParameterAnnotationsAttribute> {
640         public static final RuntimeInvisibleParameterAnnotationsMapper INSTANCE = new RuntimeInvisibleParameterAnnotationsMapper();
641 
642         private RuntimeInvisibleParameterAnnotationsMapper() {
643             super(NAME_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS, AttributeStability.CP_REFS);
644         }
645 
646         @Override
647         public RuntimeInvisibleParameterAnnotationsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
648             return new BoundAttribute.BoundRuntimeInvisibleParameterAnnotationsAttribute(cf, this, p);
649         }
650 
651         @Override
652         protected void writeBody(BufWriter buf, RuntimeInvisibleParameterAnnotationsAttribute attr) {
653             List<List<Annotation>> lists = attr.parameterAnnotations();
654             buf.writeU1(lists.size());
655             for (List<Annotation> list : lists)
656                 buf.writeList(list);
657         }
658     }
659 
660     public static final class RuntimeInvisibleTypeAnnotationsMapper extends AbstractAttributeMapper<RuntimeInvisibleTypeAnnotationsAttribute> {
661         public static final RuntimeInvisibleTypeAnnotationsMapper INSTANCE = new RuntimeInvisibleTypeAnnotationsMapper();
662 
663         private RuntimeInvisibleTypeAnnotationsMapper() {
664             super(NAME_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS, AttributeStability.UNSTABLE);
665         }
666 
667         @Override
668         public RuntimeInvisibleTypeAnnotationsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
669             return new BoundAttribute.BoundRuntimeInvisibleTypeAnnotationsAttribute(e, cf, this, p);
670         }
671 
672         @Override
673         protected void writeBody(BufWriter buf, RuntimeInvisibleTypeAnnotationsAttribute attr) {
674             buf.writeList(attr.annotations());
675         }
676     }
677 
678     public static final class RuntimeVisibleAnnotationsMapper extends AbstractAttributeMapper<RuntimeVisibleAnnotationsAttribute> {
679         public static final RuntimeVisibleAnnotationsMapper INSTANCE = new RuntimeVisibleAnnotationsMapper();
680 
681         private RuntimeVisibleAnnotationsMapper() {
682             super(NAME_RUNTIME_VISIBLE_ANNOTATIONS, AttributeStability.CP_REFS);
683         }
684 
685         @Override
686         public RuntimeVisibleAnnotationsAttribute readAttribute(AttributedElement enclosing, ClassReader cf, int pos) {
687             return new BoundAttribute.BoundRuntimeVisibleAnnotationsAttribute(cf, pos);
688         }
689 
690         @Override
691         protected void writeBody(BufWriter buf, RuntimeVisibleAnnotationsAttribute attr) {
692             buf.writeList(attr.annotations());
693         }
694     }
695 
696     public static final class RuntimeVisibleParameterAnnotationsMapper extends AbstractAttributeMapper<RuntimeVisibleParameterAnnotationsAttribute> {
697         public static final RuntimeVisibleParameterAnnotationsMapper INSTANCE = new RuntimeVisibleParameterAnnotationsMapper();
698 
699         private RuntimeVisibleParameterAnnotationsMapper() {
700             super(NAME_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, AttributeStability.CP_REFS);
701         }
702 
703         @Override
704         public RuntimeVisibleParameterAnnotationsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
705             return new BoundAttribute.BoundRuntimeVisibleParameterAnnotationsAttribute(cf, this, p);
706         }
707 
708         @Override
709         protected void writeBody(BufWriter buf, RuntimeVisibleParameterAnnotationsAttribute attr) {
710             List<List<Annotation>> lists = attr.parameterAnnotations();
711             buf.writeU1(lists.size());
712             for (List<Annotation> list : lists)
713                 buf.writeList(list);
714         }
715     }
716 
717     public static final class RuntimeVisibleTypeAnnotationsMapper extends AbstractAttributeMapper<RuntimeVisibleTypeAnnotationsAttribute> {
718         public static final RuntimeVisibleTypeAnnotationsMapper INSTANCE = new RuntimeVisibleTypeAnnotationsMapper();
719 
720         private RuntimeVisibleTypeAnnotationsMapper() {
721             super(NAME_RUNTIME_VISIBLE_TYPE_ANNOTATIONS, AttributeStability.UNSTABLE);
722         }
723 
724         @Override
725         public RuntimeVisibleTypeAnnotationsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
726             return new BoundAttribute.BoundRuntimeVisibleTypeAnnotationsAttribute(e, cf, this, p);
727         }
728 
729         @Override
730         protected void writeBody(BufWriter buf, RuntimeVisibleTypeAnnotationsAttribute attr) {
731             buf.writeList(attr.annotations());
732         }
733     }
734 
735     public static final class SignatureMapper extends AbstractAttributeMapper<SignatureAttribute> {
736         public static final SignatureMapper INSTANCE = new SignatureMapper();
737 
738         private SignatureMapper() {
739             super(NAME_SIGNATURE, AttributeStability.CP_REFS);
740         }
741 
742         @Override
743         public SignatureAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
744             return new BoundAttribute.BoundSignatureAttribute(cf, this, p);
745         }
746 
747         @Override
748         protected void writeBody(BufWriter buf, SignatureAttribute attr) {
749             buf.writeIndex(attr.signature());
750         }
751     }
752 
753     public static final class SourceDebugExtensionMapper extends AbstractAttributeMapper<SourceDebugExtensionAttribute> {
754         public static final SourceDebugExtensionMapper INSTANCE = new SourceDebugExtensionMapper();
755 
756         private SourceDebugExtensionMapper() {
757             super(NAME_SOURCE_DEBUG_EXTENSION, AttributeStability.STATELESS);
758         }
759 
760         @Override
761         public SourceDebugExtensionAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
762             return new BoundAttribute.BoundSourceDebugExtensionAttribute(cf, this, p);
763         }
764 
765         @Override
766         protected void writeBody(BufWriter buf, SourceDebugExtensionAttribute attr) {
767             buf.writeBytes(attr.contents());
768         }
769     }
770 
771     public static final class SourceFileMapper extends AbstractAttributeMapper<SourceFileAttribute> {
772         public static final SourceFileMapper INSTANCE = new SourceFileMapper();
773 
774         private SourceFileMapper() {
775             super(NAME_SOURCE_FILE, AttributeStability.CP_REFS);
776         }
777 
778         @Override
779         public SourceFileAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
780             return new BoundAttribute.BoundSourceFileAttribute(cf, this, p);
781         }
782 
783         @Override
784         protected void writeBody(BufWriter buf, SourceFileAttribute attr) {
785             buf.writeIndex(attr.sourceFile());
786         }
787     }
788 
789     public static final class SourceIDMapper extends AbstractAttributeMapper<SourceIDAttribute> {
790         public static final SourceIDMapper INSTANCE = new SourceIDMapper();
791 
792         private SourceIDMapper() {
793             super(NAME_SOURCE_ID, AttributeStability.CP_REFS);
794         }
795 
796         @Override
797         public SourceIDAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
798             return new BoundAttribute.BoundSourceIDAttribute(cf, this, p);
799         }
800 
801         @Override
802         protected void writeBody(BufWriter buf, SourceIDAttribute attr) {
803             buf.writeIndex(attr.sourceId());
804         }
805     }
806 
807     public static final class StackMapTableMapper extends AbstractAttributeMapper<StackMapTableAttribute> {
808         public static final StackMapTableMapper INSTANCE = new StackMapTableMapper();
809 
810         private StackMapTableMapper() {
811             super(NAME_STACK_MAP_TABLE, AttributeStability.LABELS);
812         }
813 
814         @Override
815         public StackMapTableAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
816             return new BoundAttribute.BoundStackMapTableAttribute((CodeImpl)e, cf, this, p);
817         }
818 
819         @Override
820         protected void writeBody(BufWriter b, StackMapTableAttribute attr) {
821             StackMapDecoder.writeFrames(b, attr.entries());
822         }
823     }
824 
825     public static final class SyntheticMapper extends AbstractAttributeMapper<SyntheticAttribute> {
826         public static final SyntheticMapper INSTANCE = new SyntheticMapper();
827 
828         private SyntheticMapper() {
829             super(NAME_SYNTHETIC, AttributeStability.STATELESS, true);
830         }
831 
832         @Override
833         public SyntheticAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
834             return new BoundAttribute.BoundSyntheticAttribute(cf, this, p);
835         }
836 
837         @Override
838         protected void writeBody(BufWriter buf, SyntheticAttribute attr) {
839             // empty
840         }
841     }
842 }