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 LoadableDescriptorsMapper extends AbstractAttributeMapper<LoadableDescriptorsAttribute> {
315         public static final LoadableDescriptorsMapper INSTANCE = new LoadableDescriptorsMapper();
316 
317         private LoadableDescriptorsMapper() {
318             super(NAME_LOADABLE_DESCRIPTORS, AttributeStability.CP_REFS);
319         }
320 
321         @Override
322         public LoadableDescriptorsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
323             return new BoundAttribute.BoundLoadableDescriptorsAttribute(cf, this, p);
324         }
325 
326         @Override
327         protected void writeBody(BufWriter buf, LoadableDescriptorsAttribute attr) {
328             Util.writeListIndices(buf, attr.loadableDescriptors());
329         }
330     }
331 
332     public static final class LocalVariableTableMapper extends AbstractAttributeMapper<LocalVariableTableAttribute> {
333         public static final LocalVariableTableMapper INSTANCE = new LocalVariableTableMapper();
334 
335         private LocalVariableTableMapper() {
336             super(NAME_LOCAL_VARIABLE_TABLE, AttributeStability.LABELS, true);
337         }
338 
339         @Override
340         public LocalVariableTableAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
341             return new BoundAttribute.BoundLocalVariableTableAttribute(e, cf, this, p);
342         }
343 
344         @Override
345         protected void writeBody(BufWriter bufWriter, LocalVariableTableAttribute attr) {
346             List<LocalVariableInfo> infos = attr.localVariables();
347             BufWriterImpl buf = (BufWriterImpl) bufWriter;
348             buf.writeU2(infos.size());
349             for (LocalVariableInfo info : infos) {
350                 buf.writeU2U2(info.startPc(), info.length());
351                 buf.writeU2U2U2(buf.cpIndex(info.name()), buf.cpIndex(info.type()), info.slot());
352             }
353         }
354     }
355 
356     public static final class LocalVariableTypeTableMapper extends AbstractAttributeMapper<LocalVariableTypeTableAttribute> {
357         public static final LocalVariableTypeTableMapper INSTANCE = new LocalVariableTypeTableMapper();
358 
359         private LocalVariableTypeTableMapper() {
360             super(NAME_LOCAL_VARIABLE_TYPE_TABLE, AttributeStability.LABELS, true);
361         }
362 
363         @Override
364         public LocalVariableTypeTableAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
365             return new BoundAttribute.BoundLocalVariableTypeTableAttribute(e, cf, this, p);
366         }
367 
368         @Override
369         protected void writeBody(BufWriter bufWriter, LocalVariableTypeTableAttribute attr) {
370             List<LocalVariableTypeInfo> infos = attr.localVariableTypes();
371             BufWriterImpl buf = (BufWriterImpl) bufWriter;
372             buf.writeU2(infos.size());
373             for (LocalVariableTypeInfo info : infos) {
374                 buf.writeU2U2(info.startPc(), info.length());
375                 buf.writeU2U2U2(buf.cpIndex(info.name()), buf.cpIndex(info.signature()), info.slot());
376             }
377         }
378     }
379 
380     public static final class MethodParametersMapper extends AbstractAttributeMapper<MethodParametersAttribute> {
381         public static final MethodParametersMapper INSTANCE = new MethodParametersMapper();
382 
383         private MethodParametersMapper() {
384             super(NAME_METHOD_PARAMETERS, AttributeStability.CP_REFS);
385         }
386 
387         @Override
388         public MethodParametersAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
389             return new BoundAttribute.BoundMethodParametersAttribute(cf, this, p);
390         }
391 
392         @Override
393         protected void writeBody(BufWriter bufWriter, MethodParametersAttribute attr) {
394             List<MethodParameterInfo> parameters = attr.parameters();
395             BufWriterImpl buf = (BufWriterImpl) bufWriter;
396             buf.writeU1(parameters.size());
397             for (MethodParameterInfo info : parameters) {
398                 buf.writeU2U2(buf.cpIndexOrZero(info.name().orElse(null)),
399                         info.flagsMask());
400             }
401         }
402     }
403 
404     public static final class ModuleMapper extends AbstractAttributeMapper<ModuleAttribute> {
405         public static final ModuleMapper INSTANCE = new ModuleMapper();
406 
407         private ModuleMapper() {
408             super(NAME_MODULE, AttributeStability.CP_REFS);
409         }
410 
411         @Override
412         public ModuleAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
413             return new BoundAttribute.BoundModuleAttribute(cf, this, p);
414         }
415 
416         @Override
417         protected void writeBody(BufWriter bufWriter, ModuleAttribute attr) {
418             BufWriterImpl buf = (BufWriterImpl) bufWriter;
419             buf.writeU2U2U2(buf.cpIndex(attr.moduleName()),
420                     attr.moduleFlagsMask(),
421                     buf.cpIndexOrZero(attr.moduleVersion().orElse(null)));
422             buf.writeU2(attr.requires().size());
423             for (ModuleRequireInfo require : attr.requires()) {
424                 buf.writeU2U2U2(buf.cpIndex(require.requires()),
425                         require.requiresFlagsMask(),
426                         buf.cpIndexOrZero(require.requiresVersion().orElse(null)));
427             }
428             buf.writeU2(attr.exports().size());
429             for (ModuleExportInfo export : attr.exports()) {
430                 buf.writeU2U2(buf.cpIndex(export.exportedPackage()),
431                         export.exportsFlagsMask());
432                 Util.writeListIndices(buf, export.exportsTo());
433             }
434             buf.writeU2(attr.opens().size());
435             for (ModuleOpenInfo open : attr.opens()) {
436                 buf.writeU2U2(buf.cpIndex(open.openedPackage()),
437                         open.opensFlagsMask());
438                 Util.writeListIndices(buf, open.opensTo());
439             }
440             Util.writeListIndices(buf, attr.uses());
441             buf.writeU2(attr.provides().size());
442             for (ModuleProvideInfo provide : attr.provides()) {
443                 buf.writeIndex(provide.provides());
444                 Util.writeListIndices(buf, provide.providesWith());
445             }
446         }
447     }
448 
449     public static final class ModuleHashesMapper extends AbstractAttributeMapper<ModuleHashesAttribute> {
450         public static final ModuleHashesMapper INSTANCE = new ModuleHashesMapper();
451 
452         private ModuleHashesMapper() {
453             super(NAME_MODULE_HASHES, AttributeStability.CP_REFS);
454         }
455 
456         @Override
457         public ModuleHashesAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
458             return new BoundAttribute.BoundModuleHashesAttribute(cf, this, p);
459         }
460 
461         @Override
462         protected void writeBody(BufWriter bufWriter, ModuleHashesAttribute attr) {
463             List<ModuleHashInfo> hashes = attr.hashes();
464             BufWriterImpl buf = (BufWriterImpl) bufWriter;
465             buf.writeU2U2(buf.cpIndex(attr.algorithm()), hashes.size());
466             for (ModuleHashInfo hash : hashes) {
467                 buf.writeU2U2(buf.cpIndex(hash.moduleName()),
468                         hash.hash().length);
469                 buf.writeBytes(hash.hash());
470             }
471         }
472     }
473 
474     public static final class ModuleMainClassMapper extends AbstractAttributeMapper<ModuleMainClassAttribute> {
475         public static final ModuleMainClassMapper INSTANCE = new ModuleMainClassMapper();
476 
477         private ModuleMainClassMapper() {
478             super(NAME_MODULE_MAIN_CLASS, AttributeStability.CP_REFS);
479         }
480 
481         @Override
482         public ModuleMainClassAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
483             return new BoundAttribute.BoundModuleMainClassAttribute(cf, this, p);
484         }
485 
486         @Override
487         protected void writeBody(BufWriter buf, ModuleMainClassAttribute attr) {
488             buf.writeIndex(attr.mainClass());
489         }
490     }
491 
492     public static final class ModulePackagesMapper extends AbstractAttributeMapper<ModulePackagesAttribute> {
493         public static final ModulePackagesMapper INSTANCE = new ModulePackagesMapper();
494 
495         private ModulePackagesMapper() {
496             super(NAME_MODULE_PACKAGES, AttributeStability.CP_REFS);
497         }
498 
499         @Override
500         public ModulePackagesAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
501             return new BoundAttribute.BoundModulePackagesAttribute(cf, this, p);
502         }
503 
504         @Override
505         protected void writeBody(BufWriter buf, ModulePackagesAttribute attr) {
506             Util.writeListIndices(buf, attr.packages());
507         }
508     }
509 
510     public static final class ModuleResolutionMapper extends AbstractAttributeMapper<ModuleResolutionAttribute> {
511         public static final ModuleResolutionMapper INSTANCE = new ModuleResolutionMapper();
512 
513         private ModuleResolutionMapper() {
514             super(NAME_MODULE_RESOLUTION, AttributeStability.STATELESS);
515         }
516 
517         @Override
518         public ModuleResolutionAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
519             return new BoundAttribute.BoundModuleResolutionAttribute(cf, this, p);
520         }
521 
522         @Override
523         protected void writeBody(BufWriter buf, ModuleResolutionAttribute attr) {
524             buf.writeU2(attr.resolutionFlags());
525         }
526     }
527 
528     public static final class ModuleTargetMapper extends AbstractAttributeMapper<ModuleTargetAttribute> {
529         public static final ModuleTargetMapper INSTANCE = new ModuleTargetMapper();
530 
531         private ModuleTargetMapper() {
532             super(NAME_MODULE_TARGET, AttributeStability.CP_REFS);
533         }
534 
535         @Override
536         public ModuleTargetAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
537             return new BoundAttribute.BoundModuleTargetAttribute(cf, this, p);
538         }
539 
540         @Override
541         protected void writeBody(BufWriter buf, ModuleTargetAttribute attr) {
542             buf.writeIndex(attr.targetPlatform());
543         }
544     }
545 
546     public static final class NestHostMapper extends AbstractAttributeMapper<NestHostAttribute> {
547         public static final NestHostMapper INSTANCE = new NestHostMapper();
548 
549         private NestHostMapper() {
550             super(NAME_NEST_HOST, AttributeStability.CP_REFS);
551         }
552 
553         @Override
554         public NestHostAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
555             return new BoundAttribute.BoundNestHostAttribute(cf, this, p);
556         }
557 
558         @Override
559         protected void writeBody(BufWriter buf, NestHostAttribute attr) {
560             buf.writeIndex(attr.nestHost());
561         }
562     }
563 
564     public static final class NestMembersMapper extends AbstractAttributeMapper<NestMembersAttribute> {
565         public static final NestMembersMapper INSTANCE = new NestMembersMapper();
566 
567         private NestMembersMapper() {
568             super(NAME_NEST_MEMBERS, AttributeStability.CP_REFS);
569         }
570 
571         @Override
572         public NestMembersAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
573             return new BoundAttribute.BoundNestMembersAttribute(cf, this, p);
574         }
575 
576         @Override
577         protected void writeBody(BufWriter buf, NestMembersAttribute attr) {
578             Util.writeListIndices(buf, attr.nestMembers());
579         }
580     }
581 
582     public static final class PermittedSubclassesMapper extends AbstractAttributeMapper<PermittedSubclassesAttribute> {
583         public static final PermittedSubclassesMapper INSTANCE = new PermittedSubclassesMapper();
584 
585         private PermittedSubclassesMapper() {
586             super(NAME_PERMITTED_SUBCLASSES, AttributeStability.CP_REFS);
587         }
588 
589         @Override
590         public PermittedSubclassesAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
591             return new BoundAttribute.BoundPermittedSubclassesAttribute(cf, this, p);
592         }
593 
594         @Override
595         protected void writeBody(BufWriter buf, PermittedSubclassesAttribute attr) {
596             Util.writeListIndices(buf, attr.permittedSubclasses());
597         }
598     }
599 
600     public static final class RecordMapper extends AbstractAttributeMapper<RecordAttribute> {
601         public static final RecordMapper INSTANCE = new RecordMapper();
602 
603         private RecordMapper() {
604             super(NAME_RECORD, AttributeStability.CP_REFS);
605         }
606 
607         @Override
608         public RecordAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
609             return new BoundAttribute.BoundRecordAttribute(cf, this, p);
610         }
611 
612         @Override
613         protected void writeBody(BufWriter bufWriter, RecordAttribute attr) {
614             List<RecordComponentInfo> components = attr.components();
615             BufWriterImpl buf = (BufWriterImpl) bufWriter;
616             buf.writeU2(components.size());
617             for (RecordComponentInfo info : components) {
618                 buf.writeU2U2(buf.cpIndex(info.name()),
619                         buf.cpIndex(info.descriptor()));
620                 Util.writeAttributes(buf, info.attributes());
621             }
622         }
623     }
624 
625     public static final class RuntimeInvisibleAnnotationsMapper extends AbstractAttributeMapper<RuntimeInvisibleAnnotationsAttribute> {
626         public static final RuntimeInvisibleAnnotationsMapper INSTANCE = new RuntimeInvisibleAnnotationsMapper();
627 
628         private RuntimeInvisibleAnnotationsMapper() {
629             super(NAME_RUNTIME_INVISIBLE_ANNOTATIONS, AttributeStability.CP_REFS);
630         }
631 
632         @Override
633         public RuntimeInvisibleAnnotationsAttribute readAttribute(AttributedElement enclosing, ClassReader cf, int pos) {
634             return new BoundAttribute.BoundRuntimeInvisibleAnnotationsAttribute(cf, pos);
635         }
636 
637         @Override
638         protected void writeBody(BufWriter buf, RuntimeInvisibleAnnotationsAttribute attr) {
639             AnnotationReader.writeAnnotations(buf, attr.annotations());
640         }
641     }
642 
643     public static final class RuntimeInvisibleParameterAnnotationsMapper extends AbstractAttributeMapper<RuntimeInvisibleParameterAnnotationsAttribute> {
644         public static final RuntimeInvisibleParameterAnnotationsMapper INSTANCE = new RuntimeInvisibleParameterAnnotationsMapper();
645 
646         private RuntimeInvisibleParameterAnnotationsMapper() {
647             super(NAME_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS, AttributeStability.CP_REFS);
648         }
649 
650         @Override
651         public RuntimeInvisibleParameterAnnotationsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
652             return new BoundAttribute.BoundRuntimeInvisibleParameterAnnotationsAttribute(cf, this, p);
653         }
654 
655         @Override
656         protected void writeBody(BufWriter buf, RuntimeInvisibleParameterAnnotationsAttribute attr) {
657             List<List<Annotation>> lists = attr.parameterAnnotations();
658             buf.writeU1(lists.size());
659             for (List<Annotation> list : lists)
660                 AnnotationReader.writeAnnotations(buf, list);
661         }
662     }
663 
664     public static final class RuntimeInvisibleTypeAnnotationsMapper extends AbstractAttributeMapper<RuntimeInvisibleTypeAnnotationsAttribute> {
665         public static final RuntimeInvisibleTypeAnnotationsMapper INSTANCE = new RuntimeInvisibleTypeAnnotationsMapper();
666 
667         private RuntimeInvisibleTypeAnnotationsMapper() {
668             super(NAME_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS, AttributeStability.UNSTABLE);
669         }
670 
671         @Override
672         public RuntimeInvisibleTypeAnnotationsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
673             return new BoundAttribute.BoundRuntimeInvisibleTypeAnnotationsAttribute(e, cf, this, p);
674         }
675 
676         @Override
677         protected void writeBody(BufWriter buf, RuntimeInvisibleTypeAnnotationsAttribute attr) {
678             AnnotationReader.writeTypeAnnotations(buf, attr.annotations());
679         }
680     }
681 
682     public static final class RuntimeVisibleAnnotationsMapper extends AbstractAttributeMapper<RuntimeVisibleAnnotationsAttribute> {
683         public static final RuntimeVisibleAnnotationsMapper INSTANCE = new RuntimeVisibleAnnotationsMapper();
684 
685         private RuntimeVisibleAnnotationsMapper() {
686             super(NAME_RUNTIME_VISIBLE_ANNOTATIONS, AttributeStability.CP_REFS);
687         }
688 
689         @Override
690         public RuntimeVisibleAnnotationsAttribute readAttribute(AttributedElement enclosing, ClassReader cf, int pos) {
691             return new BoundAttribute.BoundRuntimeVisibleAnnotationsAttribute(cf, pos);
692         }
693 
694         @Override
695         protected void writeBody(BufWriter buf, RuntimeVisibleAnnotationsAttribute attr) {
696             AnnotationReader.writeAnnotations(buf, attr.annotations());
697         }
698     }
699 
700     public static final class RuntimeVisibleParameterAnnotationsMapper extends AbstractAttributeMapper<RuntimeVisibleParameterAnnotationsAttribute> {
701         public static final RuntimeVisibleParameterAnnotationsMapper INSTANCE = new RuntimeVisibleParameterAnnotationsMapper();
702 
703         private RuntimeVisibleParameterAnnotationsMapper() {
704             super(NAME_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, AttributeStability.CP_REFS);
705         }
706 
707         @Override
708         public RuntimeVisibleParameterAnnotationsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
709             return new BoundAttribute.BoundRuntimeVisibleParameterAnnotationsAttribute(cf, this, p);
710         }
711 
712         @Override
713         protected void writeBody(BufWriter buf, RuntimeVisibleParameterAnnotationsAttribute attr) {
714             List<List<Annotation>> lists = attr.parameterAnnotations();
715             buf.writeU1(lists.size());
716             for (List<Annotation> list : lists)
717                 AnnotationReader.writeAnnotations(buf, list);
718         }
719     }
720 
721     public static final class RuntimeVisibleTypeAnnotationsMapper extends AbstractAttributeMapper<RuntimeVisibleTypeAnnotationsAttribute> {
722         public static final RuntimeVisibleTypeAnnotationsMapper INSTANCE = new RuntimeVisibleTypeAnnotationsMapper();
723 
724         private RuntimeVisibleTypeAnnotationsMapper() {
725             super(NAME_RUNTIME_VISIBLE_TYPE_ANNOTATIONS, AttributeStability.UNSTABLE);
726         }
727 
728         @Override
729         public RuntimeVisibleTypeAnnotationsAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
730             return new BoundAttribute.BoundRuntimeVisibleTypeAnnotationsAttribute(e, cf, this, p);
731         }
732 
733         @Override
734         protected void writeBody(BufWriter buf, RuntimeVisibleTypeAnnotationsAttribute attr) {
735             AnnotationReader.writeTypeAnnotations(buf, attr.annotations());
736         }
737     }
738 
739     public static final class SignatureMapper extends AbstractAttributeMapper<SignatureAttribute> {
740         public static final SignatureMapper INSTANCE = new SignatureMapper();
741 
742         private SignatureMapper() {
743             super(NAME_SIGNATURE, AttributeStability.CP_REFS);
744         }
745 
746         @Override
747         public SignatureAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
748             return new BoundAttribute.BoundSignatureAttribute(cf, this, p);
749         }
750 
751         @Override
752         protected void writeBody(BufWriter buf, SignatureAttribute attr) {
753             buf.writeIndex(attr.signature());
754         }
755     }
756 
757     public static final class SourceDebugExtensionMapper extends AbstractAttributeMapper<SourceDebugExtensionAttribute> {
758         public static final SourceDebugExtensionMapper INSTANCE = new SourceDebugExtensionMapper();
759 
760         private SourceDebugExtensionMapper() {
761             super(NAME_SOURCE_DEBUG_EXTENSION, AttributeStability.STATELESS);
762         }
763 
764         @Override
765         public SourceDebugExtensionAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
766             return new BoundAttribute.BoundSourceDebugExtensionAttribute(cf, this, p);
767         }
768 
769         @Override
770         protected void writeBody(BufWriter buf, SourceDebugExtensionAttribute attr) {
771             buf.writeBytes(attr.contents());
772         }
773     }
774 
775     public static final class SourceFileMapper extends AbstractAttributeMapper<SourceFileAttribute> {
776         public static final SourceFileMapper INSTANCE = new SourceFileMapper();
777 
778         private SourceFileMapper() {
779             super(NAME_SOURCE_FILE, AttributeStability.CP_REFS);
780         }
781 
782         @Override
783         public SourceFileAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
784             return new BoundAttribute.BoundSourceFileAttribute(cf, this, p);
785         }
786 
787         @Override
788         protected void writeBody(BufWriter buf, SourceFileAttribute attr) {
789             buf.writeIndex(attr.sourceFile());
790         }
791     }
792 
793     public static final class SourceIDMapper extends AbstractAttributeMapper<SourceIDAttribute> {
794         public static final SourceIDMapper INSTANCE = new SourceIDMapper();
795 
796         private SourceIDMapper() {
797             super(NAME_SOURCE_ID, AttributeStability.CP_REFS);
798         }
799 
800         @Override
801         public SourceIDAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
802             return new BoundAttribute.BoundSourceIDAttribute(cf, this, p);
803         }
804 
805         @Override
806         protected void writeBody(BufWriter buf, SourceIDAttribute attr) {
807             buf.writeIndex(attr.sourceId());
808         }
809     }
810 
811     public static final class StackMapTableMapper extends AbstractAttributeMapper<StackMapTableAttribute> {
812         public static final StackMapTableMapper INSTANCE = new StackMapTableMapper();
813 
814         private StackMapTableMapper() {
815             super(NAME_STACK_MAP_TABLE, AttributeStability.LABELS);
816         }
817 
818         @Override
819         public StackMapTableAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
820             return new BoundAttribute.BoundStackMapTableAttribute((CodeImpl)e, cf, this, p);
821         }
822 
823         @Override
824         protected void writeBody(BufWriter b, StackMapTableAttribute attr) {
825             StackMapDecoder.writeFrames(b, attr.entries());
826         }
827     }
828 
829     public static final class SyntheticMapper extends AbstractAttributeMapper<SyntheticAttribute> {
830         public static final SyntheticMapper INSTANCE = new SyntheticMapper();
831 
832         private SyntheticMapper() {
833             super(NAME_SYNTHETIC, AttributeStability.STATELESS, true);
834         }
835 
836         @Override
837         public SyntheticAttribute readAttribute(AttributedElement e, ClassReader cf, int p) {
838             return new BoundAttribute.BoundSyntheticAttribute(cf, this, p);
839         }
840 
841         @Override
842         protected void writeBody(BufWriter buf, SyntheticAttribute attr) {
843             // empty
844         }
845     }
846 }