Skip to content

Commit

Permalink
8331291: java.lang.classfile.Attributes class performs a lot of stati…
Browse files Browse the repository at this point in the history
…c initializations

Reviewed-by: liach, redestad, vromero
  • Loading branch information
asotona committed May 24, 2024
1 parent 0c934ff commit cfdc64f
Show file tree
Hide file tree
Showing 149 changed files with 1,670 additions and 1,324 deletions.
1,228 changes: 343 additions & 885 deletions src/java.base/share/classes/java/lang/classfile/Attributes.java

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
import java.lang.classfile.constantpool.Utf8Entry;
import jdk.internal.access.SharedSecrets;

import static java.lang.classfile.Attributes.*;

public abstract sealed class BoundAttribute<T extends Attribute<T>>
extends AbstractElement
implements Attribute<T> {
Expand Down Expand Up @@ -140,7 +142,7 @@ public static List<Attribute<?>> readAttributes(AttributedElement enclosing, Cla
throw new IllegalArgumentException("attribute " + name.stringValue() + " too big to handle");
}

var mapper = Attributes.standardAttribute(name);
var mapper = standardAttribute(name);
if (mapper == null) {
mapper = customAttributes.apply(name);
}
Expand Down Expand Up @@ -889,7 +891,7 @@ public static final class BoundRuntimeInvisibleAnnotationsAttribute

public BoundRuntimeInvisibleAnnotationsAttribute(ClassReader cf,
int payloadStart) {
super(cf, Attributes.RUNTIME_INVISIBLE_ANNOTATIONS, payloadStart);
super(cf, Attributes.runtimeInvisibleAnnotations(), payloadStart);
}

@Override
Expand All @@ -907,7 +909,7 @@ public static final class BoundRuntimeVisibleAnnotationsAttribute

public BoundRuntimeVisibleAnnotationsAttribute(ClassReader cf,
int payloadStart) {
super(cf, Attributes.RUNTIME_VISIBLE_ANNOTATIONS, payloadStart);
super(cf, Attributes.runtimeVisibleAnnotations(), payloadStart);
}

@Override
Expand Down Expand Up @@ -983,4 +985,88 @@ public byte[] codeArray() {
return classReader.readBytes(payloadStart + 8, codeLength());
}
}

/**
* {@return the attribute mapper for a standard attribute}
*
* @param name the name of the attribute to find
*/
public static AttributeMapper<?> standardAttribute(Utf8Entry name) {
// critical bootstrap path, so no lambdas nor method handles here
return switch (name.hashCode()) {
case 0x78147009 ->
name.equalsString(NAME_ANNOTATION_DEFAULT) ? annotationDefault() : null;
case 0x665e3a3a ->
name.equalsString(NAME_BOOTSTRAP_METHODS) ? bootstrapMethods() : null;
case 0xcb7e162 ->
name.equalsString(NAME_CHARACTER_RANGE_TABLE) ? characterRangeTable() : null;
case 0x21e41e7e ->
name.equalsString(NAME_CODE) ? code() : null;
case 0x5a306b41 ->
name.equalsString(NAME_COMPILATION_ID) ? compilationId() : null;
case 0x3e191c7c ->
name.equalsString(NAME_CONSTANT_VALUE) ? constantValue() : null;
case 0x5e88ed0c ->
name.equalsString(NAME_DEPRECATED) ? deprecated() : null;
case 0x7284695e ->
name.equalsString(NAME_ENCLOSING_METHOD) ? enclosingMethod() : null;
case 0x21df25db ->
name.equalsString(NAME_EXCEPTIONS) ? exceptions() : null;
case 0x11392da9 ->
name.equalsString(NAME_INNER_CLASSES) ? innerClasses() : null;
case 0x167536fc ->
name.equalsString(NAME_LINE_NUMBER_TABLE) ? lineNumberTable() : null;
case 0x46939abc ->
name.equalsString(NAME_LOCAL_VARIABLE_TABLE) ? localVariableTable() : null;
case 0x63ee67f4 ->
name.equalsString(NAME_LOCAL_VARIABLE_TYPE_TABLE) ? localVariableTypeTable() : null;
case 0x2b597e15 ->
name.equalsString(NAME_METHOD_PARAMETERS) ? methodParameters() : null;
case 0x19f20ade ->
name.equalsString(NAME_MODULE) ? module() : null;
case 0x47f6395e ->
name.equalsString(NAME_MODULE_HASHES) ? moduleHashes() : null;
case 0x54db809 ->
name.equalsString(NAME_MODULE_MAIN_CLASS) ? moduleMainClass() : null;
case 0x1abd1c2c ->
name.equalsString(NAME_MODULE_PACKAGES) ? modulePackages() : null;
case 0x6ba46dd ->
name.equalsString(NAME_MODULE_RESOLUTION) ? moduleResolution() : null;
case 0x46f7d91d ->
name.equalsString(NAME_MODULE_TARGET) ? moduleTarget() : null;
case 0x5137f53 ->
name.equalsString(NAME_NEST_HOST) ? nestHost() : null;
case 0x4a8fa3b6 ->
name.equalsString(NAME_NEST_MEMBERS) ? nestMembers() : null;
case 0x55c73cb6 ->
name.equalsString(NAME_PERMITTED_SUBCLASSES) ? permittedSubclasses() : null;
case 0x3fe76d4e ->
name.equalsString(NAME_RECORD) ? record() : null;
case 0x180d6925 ->
name.equalsString(NAME_RUNTIME_INVISIBLE_ANNOTATIONS) ? runtimeInvisibleAnnotations() : null;
case 0x7be22752 ->
name.equalsString(NAME_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS) ? runtimeInvisibleParameterAnnotations() : null;
case 0x5299824 ->
name.equalsString(NAME_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS) ? runtimeInvisibleTypeAnnotations() : null;
case 0x3534786e ->
name.equalsString(NAME_RUNTIME_VISIBLE_ANNOTATIONS) ? runtimeVisibleAnnotations() : null;
case 0xb4b4ac6 ->
name.equalsString(NAME_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS) ? runtimeVisibleParameterAnnotations() : null;
case 0x6926482 ->
name.equalsString(NAME_RUNTIME_VISIBLE_TYPE_ANNOTATIONS) ? runtimeVisibleTypeAnnotations() : null;
case 0x16a42b7c ->
name.equalsString(NAME_SIGNATURE) ? signature() : null;
case 0x400ab245 ->
name.equalsString(NAME_SOURCE_DEBUG_EXTENSION) ? sourceDebugExtension() : null;
case 0x2af490d4 ->
name.equalsString(NAME_SOURCE_FILE) ? sourceFile() : null;
case 0x303e0c58 ->
name.equalsString(NAME_SOURCE_ID) ? sourceId() : null;
case 0x19c7d0cd ->
name.equalsString(NAME_STACK_MAP_TABLE) ? stackMapTable() : null;
case 0x3dc79b7a ->
name.equalsString(NAME_SYNTHETIC) ? synthetic() : null;
default -> null;
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,32 +24,36 @@
*/
package jdk.internal.classfile.impl;

import java.util.Collection;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Collectors;

import java.lang.classfile.ClassBuilder;
import java.lang.classfile.constantpool.ClassEntry;
import java.lang.reflect.AccessFlag;
import java.lang.classfile.AccessFlags;
import java.lang.classfile.Attribute;
import java.lang.classfile.AttributeMapper;
import java.lang.classfile.Attributes;
import java.lang.classfile.ClassElement;
import java.lang.classfile.ClassModel;
import java.lang.classfile.ClassReader;
import java.lang.classfile.ClassTransform;
import java.lang.classfile.ClassFile;
import java.lang.classfile.ClassFileVersion;
import java.lang.classfile.CustomAttribute;
import java.lang.classfile.constantpool.ConstantPool;
import java.lang.classfile.constantpool.ConstantPoolBuilder;
import java.lang.classfile.FieldModel;
import java.lang.classfile.Interfaces;
import java.lang.classfile.MethodModel;
import java.lang.classfile.Superclass;
import java.lang.classfile.attribute.InnerClassesAttribute;
import java.lang.classfile.attribute.ModuleAttribute;
import java.lang.classfile.attribute.ModuleHashesAttribute;
import java.lang.classfile.attribute.ModuleMainClassAttribute;
import java.lang.classfile.attribute.ModulePackagesAttribute;
import java.lang.classfile.attribute.ModuleResolutionAttribute;
import java.lang.classfile.attribute.ModuleTargetAttribute;
import java.lang.classfile.attribute.RuntimeInvisibleAnnotationsAttribute;
import java.lang.classfile.attribute.RuntimeVisibleAnnotationsAttribute;
import java.lang.classfile.attribute.SourceDebugExtensionAttribute;
import java.lang.classfile.attribute.SourceFileAttribute;
import jdk.internal.access.SharedSecrets;

public final class ClassImpl
Expand Down Expand Up @@ -202,28 +206,21 @@ public String toString() {
}

private boolean verifyModuleAttributes() {
if (findAttribute(Attributes.MODULE).isEmpty())
if (findAttribute(Attributes.module()).isEmpty())
return false;

Set<AttributeMapper<?>> found = attributes().stream()
.map(Attribute::attributeMapper)
.collect(Collectors.toSet());

found.removeAll(allowedModuleAttributes);
found.retainAll(Attributes.PREDEFINED_ATTRIBUTES);
return found.isEmpty();
}

private static final Set<AttributeMapper<?>> allowedModuleAttributes
= Set.of(Attributes.MODULE,
Attributes.MODULE_HASHES,
Attributes.MODULE_MAIN_CLASS,
Attributes.MODULE_PACKAGES,
Attributes.MODULE_RESOLUTION,
Attributes.MODULE_TARGET,
Attributes.INNER_CLASSES,
Attributes.SOURCE_FILE,
Attributes.SOURCE_DEBUG_EXTENSION,
Attributes.RUNTIME_VISIBLE_ANNOTATIONS,
Attributes.RUNTIME_INVISIBLE_ANNOTATIONS);
return attributes().stream().allMatch(a ->
a instanceof ModuleAttribute
|| a instanceof ModulePackagesAttribute
|| a instanceof ModuleHashesAttribute
|| a instanceof ModuleMainClassAttribute
|| a instanceof ModuleResolutionAttribute
|| a instanceof ModuleTargetAttribute
|| a instanceof InnerClassesAttribute
|| a instanceof SourceFileAttribute
|| a instanceof SourceDebugExtensionAttribute
|| a instanceof RuntimeVisibleAnnotationsAttribute
|| a instanceof RuntimeInvisibleAnnotationsAttribute
|| a instanceof CustomAttribute);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ BootstrapMethodsAttribute bootstrapMethodsAttribute() {

if (bootstrapMethodsAttribute == null) {
bootstrapMethodsAttribute
= containedClass.findAttribute(Attributes.BOOTSTRAP_METHODS)
= containedClass.findAttribute(Attributes.bootstrapMethods())
.orElse(new UnboundAttribute.EmptyBootstrapAttribute());
}

Expand Down Expand Up @@ -324,7 +324,7 @@ ClassModel getContainedClass() {

boolean writeBootstrapMethods(BufWriter buf) {
Optional<BootstrapMethodsAttribute> a
= containedClass.findAttribute(Attributes.BOOTSTRAP_METHODS);
= containedClass.findAttribute(Attributes.bootstrapMethods());
if (a.isEmpty())
return false;
a.get().writeTo(buf);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ private void inflateLabel(int bci) {

private void inflateLineNumbers() {
for (Attribute<?> a : attributes()) {
if (a.attributeMapper() == Attributes.LINE_NUMBER_TABLE) {
if (a.attributeMapper() == Attributes.lineNumberTable()) {
BoundLineNumberTableAttribute attr = (BoundLineNumberTableAttribute) a;
if (lineNumbers == null)
lineNumbers = new int[codeLength + 1];
Expand All @@ -252,7 +252,7 @@ private void inflateLineNumbers() {
}

private void inflateJumpTargets() {
Optional<StackMapTableAttribute> a = findAttribute(Attributes.STACK_MAP_TABLE);
Optional<StackMapTableAttribute> a = findAttribute(Attributes.stackMapTable());
if (a.isEmpty()) {
if (classReader.readU2(6) <= ClassFile.JAVA_6_VERSION) {
//fallback to jump targets inflation without StackMapTableAttribute
Expand Down Expand Up @@ -325,8 +325,8 @@ else if (frameType < 128) {
}

private void inflateTypeAnnotations() {
findAttribute(Attributes.RUNTIME_VISIBLE_TYPE_ANNOTATIONS).ifPresent(RuntimeVisibleTypeAnnotationsAttribute::annotations);
findAttribute(Attributes.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS).ifPresent(RuntimeInvisibleTypeAnnotationsAttribute::annotations);
findAttribute(Attributes.runtimeVisibleTypeAnnotations()).ifPresent(RuntimeVisibleTypeAnnotationsAttribute::annotations);
findAttribute(Attributes.runtimeInvisibleTypeAnnotations()).ifPresent(RuntimeInvisibleTypeAnnotationsAttribute::annotations);
}

private void generateCatchTargets(Consumer<CodeElement> consumer) {
Expand All @@ -345,7 +345,7 @@ public void accept(int s, int e, int h, int c) {

private void generateDebugElements(Consumer<CodeElement> consumer) {
for (Attribute<?> a : attributes()) {
if (a.attributeMapper() == Attributes.CHARACTER_RANGE_TABLE) {
if (a.attributeMapper() == Attributes.characterRangeTable()) {
var attr = (BoundCharacterRangeTableAttribute) a;
int cnt = classReader.readU2(attr.payloadStart);
int p = attr.payloadStart + 2;
Expand All @@ -357,7 +357,7 @@ private void generateDebugElements(Consumer<CodeElement> consumer) {
consumer.accept(instruction);
}
}
else if (a.attributeMapper() == Attributes.LOCAL_VARIABLE_TABLE) {
else if (a.attributeMapper() == Attributes.localVariableTable()) {
var attr = (BoundLocalVariableTableAttribute) a;
int cnt = classReader.readU2(attr.payloadStart);
int p = attr.payloadStart + 2;
Expand All @@ -369,7 +369,7 @@ else if (a.attributeMapper() == Attributes.LOCAL_VARIABLE_TABLE) {
consumer.accept(instruction);
}
}
else if (a.attributeMapper() == Attributes.LOCAL_VARIABLE_TYPE_TABLE) {
else if (a.attributeMapper() == Attributes.localVariableTypeTable()) {
var attr = (BoundLocalVariableTypeTableAttribute) a;
int cnt = classReader.readU2(attr.payloadStart);
int p = attr.payloadStart + 2;
Expand All @@ -381,10 +381,10 @@ else if (a.attributeMapper() == Attributes.LOCAL_VARIABLE_TYPE_TABLE) {
consumer.accept(instruction);
}
}
else if (a.attributeMapper() == Attributes.RUNTIME_VISIBLE_TYPE_ANNOTATIONS) {
else if (a.attributeMapper() == Attributes.runtimeVisibleTypeAnnotations()) {
consumer.accept((BoundRuntimeVisibleTypeAnnotationsAttribute) a);
}
else if (a.attributeMapper() == Attributes.RUNTIME_INVISIBLE_TYPE_ANNOTATIONS) {
else if (a.attributeMapper() == Attributes.runtimeInvisibleTypeAnnotations()) {
consumer.accept((BoundRuntimeInvisibleTypeAnnotationsAttribute) a);
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -230,7 +230,7 @@ private void buildContent() {

if (context.debugElementsOption() == ClassFile.DebugElementsOption.PASS_DEBUG) {
if (!characterRanges.isEmpty()) {
Attribute<?> a = new UnboundAttribute.AdHocAttribute<>(Attributes.CHARACTER_RANGE_TABLE) {
Attribute<?> a = new UnboundAttribute.AdHocAttribute<>(Attributes.characterRangeTable()) {

@Override
public void writeBody(BufWriter b) {
Expand Down Expand Up @@ -262,7 +262,7 @@ public void writeBody(BufWriter b) {
}

if (!localVariables.isEmpty()) {
Attribute<?> a = new UnboundAttribute.AdHocAttribute<>(Attributes.LOCAL_VARIABLE_TABLE) {
Attribute<?> a = new UnboundAttribute.AdHocAttribute<>(Attributes.localVariableTable()) {
@Override
public void writeBody(BufWriter b) {
int pos = b.size();
Expand All @@ -285,7 +285,7 @@ public void writeBody(BufWriter b) {
}

if (!localVariableTypes.isEmpty()) {
Attribute<?> a = new UnboundAttribute.AdHocAttribute<>(Attributes.LOCAL_VARIABLE_TYPE_TABLE) {
Attribute<?> a = new UnboundAttribute.AdHocAttribute<>(Attributes.localVariableTypeTable()) {
@Override
public void writeBody(BufWriter b) {
int pos = b.size();
Expand All @@ -312,7 +312,7 @@ public void writeBody(BufWriter b) {
attributes.withAttribute(lineNumberWriter);
}

content = new UnboundAttribute.AdHocAttribute<>(Attributes.CODE) {
content = new UnboundAttribute.AdHocAttribute<>(Attributes.code()) {

private void writeCounters(boolean codeMatch, BufWriterImpl buf) {
if (codeMatch) {
Expand Down Expand Up @@ -368,7 +368,7 @@ public void writeBody(BufWriter b) {
if (codeAndExceptionsMatch(codeLength)) {
switch (context.stackMapsOption()) {
case STACK_MAPS_WHEN_REQUIRED -> {
attributes.withAttribute(original.findAttribute(Attributes.STACK_MAP_TABLE).orElse(null));
attributes.withAttribute(original.findAttribute(Attributes.stackMapTable()).orElse(null));
writeCounters(true, buf);
}
case GENERATE_STACK_MAPS ->
Expand Down Expand Up @@ -401,7 +401,7 @@ private static class DedupLineNumberTableAttribute extends UnboundAttribute.AdHo
private int lastPc, lastLine, writtenLine;

public DedupLineNumberTableAttribute(ConstantPoolBuilder constantPool, ClassFileImpl context) {
super(Attributes.LINE_NUMBER_TABLE);
super(Attributes.lineNumberTable());
buf = new BufWriterImpl(constantPool, context);
lastPc = -1;
writtenLine = -1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ public void writeTo(BufWriter b) {

@Override
public Optional<CodeModel> code() {
return findAttribute(Attributes.CODE).map(a -> (CodeModel) a);
return findAttribute(Attributes.code()).map(a -> (CodeModel) a);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ public boolean writeBootstrapMethods(BufWriter buf) {
}
else {
Attribute<BootstrapMethodsAttribute> a
= new UnboundAttribute.AdHocAttribute<>(Attributes.BOOTSTRAP_METHODS) {
= new UnboundAttribute.AdHocAttribute<>(Attributes.bootstrapMethods()) {

@Override
public void writeBody(BufWriter b) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ private void removeRangeFromExcTable(int rangeStart, int rangeEnd) {
* @return <code>StackMapTableAttribute</code> or null if stack map is empty
*/
public Attribute<? extends StackMapTableAttribute> stackMapTableAttribute() {
return frames.isEmpty() ? null : new UnboundAttribute.AdHocAttribute<>(Attributes.STACK_MAP_TABLE) {
return frames.isEmpty() ? null : new UnboundAttribute.AdHocAttribute<>(Attributes.stackMapTable()) {
@Override
public void writeBody(BufWriter b) {
b.writeU2(frames.size());
Expand Down
Loading

0 comments on commit cfdc64f

Please sign in to comment.