1 /*
  2  * Copyright (c) 2022, 2024, 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 writer, T attr) {
 66         BufWriterImpl buf = (BufWriterImpl) writer;
 67         buf.writeIndex(buf.constantPool().utf8Entry(name));
 68         int lengthIndex = buf.skip(4);
 69         writeBody(buf, attr);
 70         int written = buf.size() - lengthIndex - 4;
 71         buf.patchInt(lengthIndex, 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             AnnotationReader.writeAnnotationValue((BufWriterImpl) buf, attr.defaultValue());
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             var b = (BufWriterImpl) buf;
123             b.writeU2(attr.bootstrapMethodsSize());
124             for (var bsm : attr.bootstrapMethods()) {
125                 ((BootstrapMethodEntryImpl) bsm).writeTo(b);
126             }
127         }
128     }
129 
130     public static final class CharacterRangeTableMapper extends AbstractAttributeMapper<CharacterRangeTableAttribute> {
131         public static final CharacterRangeTableMapper INSTANCE = new CharacterRangeTableMapper();
132 
133         private CharacterRangeTableMapper() {
134             super(NAME_CHARACTER_RANGE_TABLE, AttributeStability.LABELS, true);
135         }
136 
137         @Override
138         public CharacterRangeTableAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
139             return new BoundAttribute.BoundCharacterRangeTableAttribute(cf, this, p);
140         }
141 
142         @Override
143         protected void writeBody(BufWriter bufWriter, CharacterRangeTableAttribute attr) {
144             List<CharacterRangeInfo> ranges = attr.characterRangeTable();
145             BufWriterImpl buf = (BufWriterImpl) bufWriter;
146             buf.writeU2(ranges.size());
147             for (CharacterRangeInfo info : ranges) {
148                 buf.writeU2U2(info.startPc(), info.endPc());
149                 buf.writeIntInt(info.characterRangeStart(), info.characterRangeEnd());
150                 buf.writeU2(info.flags());
151             }
152         }
153     }
154 
155     public static final class CodeMapper extends AbstractAttributeMapper<CodeAttribute> {
156         public static final CodeMapper INSTANCE = new CodeMapper();
157 
158         private CodeMapper() {
159             super(NAME_CODE, AttributeStability.CP_REFS);
160         }
161 
162         @Override
163         public CodeAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
164             return new CodeImpl(e, cf, this, p);
165         }
166 
167         @Override
168         protected void writeBody(BufWriter buf, CodeAttribute attr) {
169             throw new UnsupportedOperationException("Code attribute does not support direct write");
170         }
171     }
172 
173     public static final class CompilationIDMapper extends AbstractAttributeMapper<CompilationIDAttribute> {
174         public static final CompilationIDMapper INSTANCE = new CompilationIDMapper();
175 
176         private CompilationIDMapper() {
177             super(NAME_COMPILATION_ID, AttributeStability.CP_REFS);
178         }
179 
180         @Override
181         public CompilationIDAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
182             return new BoundAttribute.BoundCompilationIDAttribute(cf, this, p);
183         }
184 
185         @Override
186         protected void writeBody(BufWriter buf, CompilationIDAttribute attr) {
187             buf.writeIndex(attr.compilationId());
188         }
189     }
190 
191     public static final class ConstantValueMapper extends AbstractAttributeMapper<ConstantValueAttribute> {
192         public static final ConstantValueMapper INSTANCE = new ConstantValueMapper();
193 
194         private ConstantValueMapper() {
195             super(NAME_CONSTANT_VALUE, AttributeStability.CP_REFS);
196         }
197 
198         @Override
199         public ConstantValueAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
200             return new BoundAttribute.BoundConstantValueAttribute(cf, this, p);
201         }
202 
203         @Override
204         protected void writeBody(BufWriter buf, ConstantValueAttribute attr) {
205             buf.writeIndex(attr.constant());
206         }
207     }
208 
209     public static final class DeprecatedMapper extends AbstractAttributeMapper<DeprecatedAttribute> {
210         public static final DeprecatedMapper INSTANCE = new DeprecatedMapper();
211 
212         private DeprecatedMapper() {
213             super(NAME_DEPRECATED, AttributeStability.STATELESS, true);
214         }
215 
216         @Override
217         public DeprecatedAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
218             return new BoundAttribute.BoundDeprecatedAttribute(cf, this, p);
219         }
220 
221         @Override
222         protected void writeBody(BufWriter buf, DeprecatedAttribute attr) {
223             // empty
224         }
225     }
226 
227     public static final class EnclosingMethodMapper extends AbstractAttributeMapper<EnclosingMethodAttribute> {
228         public static final EnclosingMethodMapper INSTANCE = new EnclosingMethodMapper();
229 
230         private EnclosingMethodMapper() {
231             super(NAME_ENCLOSING_METHOD, AttributeStability.CP_REFS);
232         }
233 
234         @Override
235         public EnclosingMethodAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
236             return new BoundAttribute.BoundEnclosingMethodAttribute(cf, this, p);
237         }
238 
239         @Override
240         protected void writeBody(BufWriter bufWriter, EnclosingMethodAttribute attr) {
241             BufWriterImpl buf = (BufWriterImpl) bufWriter;
242             buf.writeU2U2(buf.cpIndex(attr.enclosingClass()),
243                     buf.cpIndexOrZero(attr.enclosingMethod().orElse(null)));
244         }
245     }
246 
247     public static final class ExceptionsMapper extends AbstractAttributeMapper<ExceptionsAttribute> {
248         public static final ExceptionsMapper INSTANCE = new ExceptionsMapper();
249 
250         private ExceptionsMapper() {
251             super(NAME_EXCEPTIONS, AttributeStability.CP_REFS);
252         }
253 
254         @Override
255         public ExceptionsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
256             return new BoundAttribute.BoundExceptionsAttribute(cf, this, p);
257         }
258 
259         @Override
260         protected void writeBody(BufWriter buf, ExceptionsAttribute attr) {
261             Util.writeListIndices(buf, attr.exceptions());
262         }
263     }
264 
265     public static final class InnerClassesMapper extends AbstractAttributeMapper<InnerClassesAttribute> {
266         public static final InnerClassesMapper INSTANCE = new InnerClassesMapper();
267 
268         private InnerClassesMapper() {
269             super(NAME_INNER_CLASSES, AttributeStability.CP_REFS);
270         }
271 
272         @Override
273         public InnerClassesAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
274             return new BoundAttribute.BoundInnerClassesAttribute(cf, this, p);
275         }
276 
277         @Override
278         protected void writeBody(BufWriter bufWriter, InnerClassesAttribute attr) {
279             List<InnerClassInfo> classes = attr.classes();
280             BufWriterImpl buf = (BufWriterImpl) bufWriter;
281             buf.writeU2(classes.size());
282             for (InnerClassInfo ic : classes) {
283                 buf.writeU2U2U2(buf.cpIndex(ic.innerClass()),
284                         buf.cpIndexOrZero(ic.outerClass().orElse(null)),
285                         buf.cpIndexOrZero(ic.innerName().orElse(null)));
286                 buf.writeU2(ic.flagsMask());
287             }
288         }
289     }
290 
291     public static final class LineNumberTableMapper extends AbstractAttributeMapper<LineNumberTableAttribute> {
292         public static final LineNumberTableMapper INSTANCE = new LineNumberTableMapper();
293 
294         private LineNumberTableMapper() {
295             super(NAME_LINE_NUMBER_TABLE, AttributeStability.LABELS, true);
296         }
297 
298         @Override
299         public LineNumberTableAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
300             return new BoundAttribute.BoundLineNumberTableAttribute(cf, this, p);
301         }
302 
303         @Override
304         protected void writeBody(BufWriter bufWriter, LineNumberTableAttribute attr) {
305             List<LineNumberInfo> lines = attr.lineNumbers();
306             BufWriterImpl buf = (BufWriterImpl) bufWriter;
307             buf.writeU2(lines.size());
308             for (LineNumberInfo line : lines) {
309                 buf.writeU2U2(line.startPc(), line.lineNumber());
310             }
311         }
312     }
313 
314     public static final class LocalVariableTableMapper extends AbstractAttributeMapper<LocalVariableTableAttribute> {
315         public static final LocalVariableTableMapper INSTANCE = new LocalVariableTableMapper();
316 
317         private LocalVariableTableMapper() {
318             super(NAME_LOCAL_VARIABLE_TABLE, AttributeStability.LABELS, true);
319         }
320 
321         @Override
322         public LocalVariableTableAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
323             return new BoundAttribute.BoundLocalVariableTableAttribute(e, cf, this, p);
324         }
325 
326         @Override
327         protected void writeBody(BufWriter bufWriter, LocalVariableTableAttribute attr) {
328             List<LocalVariableInfo> infos = attr.localVariables();
329             BufWriterImpl buf = (BufWriterImpl) bufWriter;
330             buf.writeU2(infos.size());
331             for (LocalVariableInfo info : infos) {
332                 buf.writeU2U2(info.startPc(), info.length());
333                 buf.writeU2U2U2(buf.cpIndex(info.name()), buf.cpIndex(info.type()), info.slot());
334             }
335         }
336     }
337 
338     public static final class LocalVariableTypeTableMapper extends AbstractAttributeMapper<LocalVariableTypeTableAttribute> {
339         public static final LocalVariableTypeTableMapper INSTANCE = new LocalVariableTypeTableMapper();
340 
341         private LocalVariableTypeTableMapper() {
342             super(NAME_LOCAL_VARIABLE_TYPE_TABLE, AttributeStability.LABELS, true);
343         }
344 
345         @Override
346         public LocalVariableTypeTableAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
347             return new BoundAttribute.BoundLocalVariableTypeTableAttribute(e, cf, this, p);
348         }
349 
350         @Override
351         protected void writeBody(BufWriter bufWriter, LocalVariableTypeTableAttribute attr) {
352             List<LocalVariableTypeInfo> infos = attr.localVariableTypes();
353             BufWriterImpl buf = (BufWriterImpl) bufWriter;
354             buf.writeU2(infos.size());
355             for (LocalVariableTypeInfo info : infos) {
356                 buf.writeU2U2(info.startPc(), info.length());
357                 buf.writeU2U2U2(buf.cpIndex(info.name()), buf.cpIndex(info.signature()), info.slot());
358             }
359         }
360     }
361 
362     public static final class MethodParametersMapper extends AbstractAttributeMapper<MethodParametersAttribute> {
363         public static final MethodParametersMapper INSTANCE = new MethodParametersMapper();
364 
365         private MethodParametersMapper() {
366             super(NAME_METHOD_PARAMETERS, AttributeStability.CP_REFS);
367         }
368 
369         @Override
370         public MethodParametersAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
371             return new BoundAttribute.BoundMethodParametersAttribute(cf, this, p);
372         }
373 
374         @Override
375         protected void writeBody(BufWriter bufWriter, MethodParametersAttribute attr) {
376             List<MethodParameterInfo> parameters = attr.parameters();
377             BufWriterImpl buf = (BufWriterImpl) bufWriter;
378             buf.writeU1(parameters.size());
379             for (MethodParameterInfo info : parameters) {
380                 buf.writeU2U2(buf.cpIndexOrZero(info.name().orElse(null)),
381                         info.flagsMask());
382             }
383         }
384     }
385 
386     public static final class ModuleMapper extends AbstractAttributeMapper<ModuleAttribute> {
387         public static final ModuleMapper INSTANCE = new ModuleMapper();
388 
389         private ModuleMapper() {
390             super(NAME_MODULE, AttributeStability.CP_REFS);
391         }
392 
393         @Override
394         public ModuleAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
395             return new BoundAttribute.BoundModuleAttribute(cf, this, p);
396         }
397 
398         @Override
399         protected void writeBody(BufWriter bufWriter, ModuleAttribute attr) {
400             BufWriterImpl buf = (BufWriterImpl) bufWriter;
401             buf.writeU2U2U2(buf.cpIndex(attr.moduleName()),
402                     attr.moduleFlagsMask(),
403                     buf.cpIndexOrZero(attr.moduleVersion().orElse(null)));
404             buf.writeU2(attr.requires().size());
405             for (ModuleRequireInfo require : attr.requires()) {
406                 buf.writeU2U2U2(buf.cpIndex(require.requires()),
407                         require.requiresFlagsMask(),
408                         buf.cpIndexOrZero(require.requiresVersion().orElse(null)));
409             }
410             buf.writeU2(attr.exports().size());
411             for (ModuleExportInfo export : attr.exports()) {
412                 buf.writeU2U2(buf.cpIndex(export.exportedPackage()),
413                         export.exportsFlagsMask());
414                 Util.writeListIndices(buf, export.exportsTo());
415             }
416             buf.writeU2(attr.opens().size());
417             for (ModuleOpenInfo open : attr.opens()) {
418                 buf.writeU2U2(buf.cpIndex(open.openedPackage()),
419                         open.opensFlagsMask());
420                 Util.writeListIndices(buf, open.opensTo());
421             }
422             Util.writeListIndices(buf, attr.uses());
423             buf.writeU2(attr.provides().size());
424             for (ModuleProvideInfo provide : attr.provides()) {
425                 buf.writeIndex(provide.provides());
426                 Util.writeListIndices(buf, provide.providesWith());
427             }
428         }
429     }
430 
431     public static final class ModuleHashesMapper extends AbstractAttributeMapper<ModuleHashesAttribute> {
432         public static final ModuleHashesMapper INSTANCE = new ModuleHashesMapper();
433 
434         private ModuleHashesMapper() {
435             super(NAME_MODULE_HASHES, AttributeStability.CP_REFS);
436         }
437 
438         @Override
439         public ModuleHashesAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
440             return new BoundAttribute.BoundModuleHashesAttribute(cf, this, p);
441         }
442 
443         @Override
444         protected void writeBody(BufWriter bufWriter, ModuleHashesAttribute attr) {
445             List<ModuleHashInfo> hashes = attr.hashes();
446             BufWriterImpl buf = (BufWriterImpl) bufWriter;
447             buf.writeU2U2(buf.cpIndex(attr.algorithm()), hashes.size());
448             for (ModuleHashInfo hash : hashes) {
449                 buf.writeU2U2(buf.cpIndex(hash.moduleName()),
450                         hash.hash().length);
451                 buf.writeBytes(hash.hash());
452             }
453         }
454     }
455 
456     public static final class ModuleMainClassMapper extends AbstractAttributeMapper<ModuleMainClassAttribute> {
457         public static final ModuleMainClassMapper INSTANCE = new ModuleMainClassMapper();
458 
459         private ModuleMainClassMapper() {
460             super(NAME_MODULE_MAIN_CLASS, AttributeStability.CP_REFS);
461         }
462 
463         @Override
464         public ModuleMainClassAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
465             return new BoundAttribute.BoundModuleMainClassAttribute(cf, this, p);
466         }
467 
468         @Override
469         protected void writeBody(BufWriter buf, ModuleMainClassAttribute attr) {
470             buf.writeIndex(attr.mainClass());
471         }
472     }
473 
474     public static final class ModulePackagesMapper extends AbstractAttributeMapper<ModulePackagesAttribute> {
475         public static final ModulePackagesMapper INSTANCE = new ModulePackagesMapper();
476 
477         private ModulePackagesMapper() {
478             super(NAME_MODULE_PACKAGES, AttributeStability.CP_REFS);
479         }
480 
481         @Override
482         public ModulePackagesAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
483             return new BoundAttribute.BoundModulePackagesAttribute(cf, this, p);
484         }
485 
486         @Override
487         protected void writeBody(BufWriter buf, ModulePackagesAttribute attr) {
488             Util.writeListIndices(buf, attr.packages());
489         }
490     }
491 
492     public static final class ModuleResolutionMapper extends AbstractAttributeMapper<ModuleResolutionAttribute> {
493         public static final ModuleResolutionMapper INSTANCE = new ModuleResolutionMapper();
494 
495         private ModuleResolutionMapper() {
496             super(NAME_MODULE_RESOLUTION, AttributeStability.STATELESS);
497         }
498 
499         @Override
500         public ModuleResolutionAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
501             return new BoundAttribute.BoundModuleResolutionAttribute(cf, this, p);
502         }
503 
504         @Override
505         protected void writeBody(BufWriter buf, ModuleResolutionAttribute attr) {
506             buf.writeU2(attr.resolutionFlags());
507         }
508     }
509 
510     public static final class ModuleTargetMapper extends AbstractAttributeMapper<ModuleTargetAttribute> {
511         public static final ModuleTargetMapper INSTANCE = new ModuleTargetMapper();
512 
513         private ModuleTargetMapper() {
514             super(NAME_MODULE_TARGET, AttributeStability.CP_REFS);
515         }
516 
517         @Override
518         public ModuleTargetAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
519             return new BoundAttribute.BoundModuleTargetAttribute(cf, this, p);
520         }
521 
522         @Override
523         protected void writeBody(BufWriter buf, ModuleTargetAttribute attr) {
524             buf.writeIndex(attr.targetPlatform());
525         }
526     }
527 
528     public static final class NestHostMapper extends AbstractAttributeMapper<NestHostAttribute> {
529         public static final NestHostMapper INSTANCE = new NestHostMapper();
530 
531         private NestHostMapper() {
532             super(NAME_NEST_HOST, AttributeStability.CP_REFS);
533         }
534 
535         @Override
536         public NestHostAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
537             return new BoundAttribute.BoundNestHostAttribute(cf, this, p);
538         }
539 
540         @Override
541         protected void writeBody(BufWriter buf, NestHostAttribute attr) {
542             buf.writeIndex(attr.nestHost());
543         }
544     }
545 
546     public static final class NestMembersMapper extends AbstractAttributeMapper<NestMembersAttribute> {
547         public static final NestMembersMapper INSTANCE = new NestMembersMapper();
548 
549         private NestMembersMapper() {
550             super(NAME_NEST_MEMBERS, AttributeStability.CP_REFS);
551         }
552 
553         @Override
554         public NestMembersAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
555             return new BoundAttribute.BoundNestMembersAttribute(cf, this, p);
556         }
557 
558         @Override
559         protected void writeBody(BufWriter buf, NestMembersAttribute attr) {
560             Util.writeListIndices(buf, attr.nestMembers());
561         }
562     }
563 
564     public static final class PermittedSubclassesMapper extends AbstractAttributeMapper<PermittedSubclassesAttribute> {
565         public static final PermittedSubclassesMapper INSTANCE = new PermittedSubclassesMapper();
566 
567         private PermittedSubclassesMapper() {
568             super(NAME_PERMITTED_SUBCLASSES, AttributeStability.CP_REFS);
569         }
570 
571         @Override
572         public PermittedSubclassesAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
573             return new BoundAttribute.BoundPermittedSubclassesAttribute(cf, this, p);
574         }
575 
576         @Override
577         protected void writeBody(BufWriter buf, PermittedSubclassesAttribute attr) {
578             Util.writeListIndices(buf, attr.permittedSubclasses());
579         }
580     }
581 
582     public static final class RecordMapper extends AbstractAttributeMapper<RecordAttribute> {
583         public static final RecordMapper INSTANCE = new RecordMapper();
584 
585         private RecordMapper() {
586             super(NAME_RECORD, AttributeStability.CP_REFS);
587         }
588 
589         @Override
590         public RecordAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
591             return new BoundAttribute.BoundRecordAttribute(cf, this, p);
592         }
593 
594         @Override
595         protected void writeBody(BufWriter bufWriter, RecordAttribute attr) {
596             List<RecordComponentInfo> components = attr.components();
597             BufWriterImpl buf = (BufWriterImpl) bufWriter;
598             buf.writeU2(components.size());
599             for (RecordComponentInfo info : components) {
600                 buf.writeU2U2(buf.cpIndex(info.name()),
601                         buf.cpIndex(info.descriptor()));
602                 Util.writeAttributes(buf, info.attributes());
603             }
604         }
605     }
606 
607     public static final class RuntimeInvisibleAnnotationsMapper extends AbstractAttributeMapper<RuntimeInvisibleAnnotationsAttribute> {
608         public static final RuntimeInvisibleAnnotationsMapper INSTANCE = new RuntimeInvisibleAnnotationsMapper();
609 
610         private RuntimeInvisibleAnnotationsMapper() {
611             super(NAME_RUNTIME_INVISIBLE_ANNOTATIONS, AttributeStability.CP_REFS);
612         }
613 
614         @Override
615         public RuntimeInvisibleAnnotationsAttribute readAttribute(AttributedElement enclosing, ClassReader cf, int pos) {
616             return new BoundAttribute.BoundRuntimeInvisibleAnnotationsAttribute(cf, pos);
617         }
618 
619         @Override
620         protected void writeBody(BufWriter buf, RuntimeInvisibleAnnotationsAttribute attr) {
621             AnnotationReader.writeAnnotations(buf, attr.annotations());
622         }
623     }
624 
625     public static final class RuntimeInvisibleParameterAnnotationsMapper extends AbstractAttributeMapper<RuntimeInvisibleParameterAnnotationsAttribute> {
626         public static final RuntimeInvisibleParameterAnnotationsMapper INSTANCE = new RuntimeInvisibleParameterAnnotationsMapper();
627 
628         private RuntimeInvisibleParameterAnnotationsMapper() {
629             super(NAME_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS, AttributeStability.CP_REFS);
630         }
631 
632         @Override
633         public RuntimeInvisibleParameterAnnotationsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
634             return new BoundAttribute.BoundRuntimeInvisibleParameterAnnotationsAttribute(cf, this, p);
635         }
636 
637         @Override
638         protected void writeBody(BufWriter buf, RuntimeInvisibleParameterAnnotationsAttribute attr) {
639             List<List<Annotation>> lists = attr.parameterAnnotations();
640             buf.writeU1(lists.size());
641             for (List<Annotation> list : lists)
642                 AnnotationReader.writeAnnotations(buf, list);
643         }
644     }
645 
646     public static final class RuntimeInvisibleTypeAnnotationsMapper extends AbstractAttributeMapper<RuntimeInvisibleTypeAnnotationsAttribute> {
647         public static final RuntimeInvisibleTypeAnnotationsMapper INSTANCE = new RuntimeInvisibleTypeAnnotationsMapper();
648 
649         private RuntimeInvisibleTypeAnnotationsMapper() {
650             super(NAME_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS, AttributeStability.UNSTABLE);
651         }
652 
653         @Override
654         public RuntimeInvisibleTypeAnnotationsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
655             return new BoundAttribute.BoundRuntimeInvisibleTypeAnnotationsAttribute(e, cf, this, p);
656         }
657 
658         @Override
659         protected void writeBody(BufWriter buf, RuntimeInvisibleTypeAnnotationsAttribute attr) {
660             AnnotationReader.writeTypeAnnotations(buf, attr.annotations());
661         }
662     }
663 
664     public static final class RuntimeVisibleAnnotationsMapper extends AbstractAttributeMapper<RuntimeVisibleAnnotationsAttribute> {
665         public static final RuntimeVisibleAnnotationsMapper INSTANCE = new RuntimeVisibleAnnotationsMapper();
666 
667         private RuntimeVisibleAnnotationsMapper() {
668             super(NAME_RUNTIME_VISIBLE_ANNOTATIONS, AttributeStability.CP_REFS);
669         }
670 
671         @Override
672         public RuntimeVisibleAnnotationsAttribute readAttribute(AttributedElement enclosing, ClassReader cf, int pos) {
673             return new BoundAttribute.BoundRuntimeVisibleAnnotationsAttribute(cf, pos);
674         }
675 
676         @Override
677         protected void writeBody(BufWriter buf, RuntimeVisibleAnnotationsAttribute attr) {
678             AnnotationReader.writeAnnotations(buf, attr.annotations());
679         }
680     }
681 
682     public static final class RuntimeVisibleParameterAnnotationsMapper extends AbstractAttributeMapper<RuntimeVisibleParameterAnnotationsAttribute> {
683         public static final RuntimeVisibleParameterAnnotationsMapper INSTANCE = new RuntimeVisibleParameterAnnotationsMapper();
684 
685         private RuntimeVisibleParameterAnnotationsMapper() {
686             super(NAME_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, AttributeStability.CP_REFS);
687         }
688 
689         @Override
690         public RuntimeVisibleParameterAnnotationsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
691             return new BoundAttribute.BoundRuntimeVisibleParameterAnnotationsAttribute(cf, this, p);
692         }
693 
694         @Override
695         protected void writeBody(BufWriter buf, RuntimeVisibleParameterAnnotationsAttribute attr) {
696             List<List<Annotation>> lists = attr.parameterAnnotations();
697             buf.writeU1(lists.size());
698             for (List<Annotation> list : lists)
699                 AnnotationReader.writeAnnotations(buf, list);
700         }
701     }
702 
703     public static final class RuntimeVisibleTypeAnnotationsMapper extends AbstractAttributeMapper<RuntimeVisibleTypeAnnotationsAttribute> {
704         public static final RuntimeVisibleTypeAnnotationsMapper INSTANCE = new RuntimeVisibleTypeAnnotationsMapper();
705 
706         private RuntimeVisibleTypeAnnotationsMapper() {
707             super(NAME_RUNTIME_VISIBLE_TYPE_ANNOTATIONS, AttributeStability.UNSTABLE);
708         }
709 
710         @Override
711         public RuntimeVisibleTypeAnnotationsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
712             return new BoundAttribute.BoundRuntimeVisibleTypeAnnotationsAttribute(e, cf, this, p);
713         }
714 
715         @Override
716         protected void writeBody(BufWriter buf, RuntimeVisibleTypeAnnotationsAttribute attr) {
717             AnnotationReader.writeTypeAnnotations(buf, attr.annotations());
718         }
719     }
720 
721     public static final class SignatureMapper extends AbstractAttributeMapper<SignatureAttribute> {
722         public static final SignatureMapper INSTANCE = new SignatureMapper();
723 
724         private SignatureMapper() {
725             super(NAME_SIGNATURE, AttributeStability.CP_REFS);
726         }
727 
728         @Override
729         public SignatureAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
730             return new BoundAttribute.BoundSignatureAttribute(cf, this, p);
731         }
732 
733         @Override
734         protected void writeBody(BufWriter buf, SignatureAttribute attr) {
735             buf.writeIndex(attr.signature());
736         }
737     }
738 
739     public static final class SourceDebugExtensionMapper extends AbstractAttributeMapper<SourceDebugExtensionAttribute> {
740         public static final SourceDebugExtensionMapper INSTANCE = new SourceDebugExtensionMapper();
741 
742         private SourceDebugExtensionMapper() {
743             super(NAME_SOURCE_DEBUG_EXTENSION, AttributeStability.STATELESS);
744         }
745 
746         @Override
747         public SourceDebugExtensionAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
748             return new BoundAttribute.BoundSourceDebugExtensionAttribute(cf, this, p);
749         }
750 
751         @Override
752         protected void writeBody(BufWriter buf, SourceDebugExtensionAttribute attr) {
753             buf.writeBytes(attr.contents());
754         }
755     }
756 
757     public static final class SourceFileMapper extends AbstractAttributeMapper<SourceFileAttribute> {
758         public static final SourceFileMapper INSTANCE = new SourceFileMapper();
759 
760         private SourceFileMapper() {
761             super(NAME_SOURCE_FILE, AttributeStability.CP_REFS);
762         }
763 
764         @Override
765         public SourceFileAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
766             return new BoundAttribute.BoundSourceFileAttribute(cf, this, p);
767         }
768 
769         @Override
770         protected void writeBody(BufWriter buf, SourceFileAttribute attr) {
771             buf.writeIndex(attr.sourceFile());
772         }
773     }
774 
775     public static final class SourceIDMapper extends AbstractAttributeMapper<SourceIDAttribute> {
776         public static final SourceIDMapper INSTANCE = new SourceIDMapper();
777 
778         private SourceIDMapper() {
779             super(NAME_SOURCE_ID, AttributeStability.CP_REFS);
780         }
781 
782         @Override
783         public SourceIDAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
784             return new BoundAttribute.BoundSourceIDAttribute(cf, this, p);
785         }
786 
787         @Override
788         protected void writeBody(BufWriter buf, SourceIDAttribute attr) {
789             buf.writeIndex(attr.sourceId());
790         }
791     }
792 
793     public static final class StackMapTableMapper extends AbstractAttributeMapper<StackMapTableAttribute> {
794         public static final StackMapTableMapper INSTANCE = new StackMapTableMapper();
795 
796         private StackMapTableMapper() {
797             super(NAME_STACK_MAP_TABLE, AttributeStability.LABELS);
798         }
799 
800         @Override
801         public StackMapTableAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
802             return new BoundAttribute.BoundStackMapTableAttribute((CodeImpl)e, cf, this, p);
803         }
804 
805         @Override
806         protected void writeBody(BufWriter b, StackMapTableAttribute attr) {
807             StackMapDecoder.writeFrames(b, attr.entries());
808         }
809     }
810 
811     public static final class SyntheticMapper extends AbstractAttributeMapper<SyntheticAttribute> {
812         public static final SyntheticMapper INSTANCE = new SyntheticMapper();
813 
814         private SyntheticMapper() {
815             super(NAME_SYNTHETIC, AttributeStability.STATELESS, true);
816         }
817 
818         @Override
819         public SyntheticAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
820             return new BoundAttribute.BoundSyntheticAttribute(cf, this, p);
821         }
822 
823         @Override
824         protected void writeBody(BufWriter buf, SyntheticAttribute attr) {
825             // empty
826         }
827     }
828 }