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