diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java index c2e8a6ce01f2..566880010c5b 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/DynamicHub.java @@ -71,13 +71,14 @@ import com.oracle.svm.core.annotate.TargetElement; import com.oracle.svm.core.annotate.Uninterruptible; import com.oracle.svm.core.annotate.UnknownObjectField; +import com.oracle.svm.core.annotate.UnknownPrimitiveField; import com.oracle.svm.core.classinitialization.ClassInitializationInfo; import com.oracle.svm.core.classinitialization.EnsureClassInitializedNode; import com.oracle.svm.core.jdk.JDK11OrEarlier; import com.oracle.svm.core.jdk.JDK17OrLater; import com.oracle.svm.core.jdk.Resources; import com.oracle.svm.core.meta.SharedType; -import com.oracle.svm.core.reflect.MethodMetadataDecoder; +import com.oracle.svm.core.reflect.ReflectionMetadataDecoder; import com.oracle.svm.core.reflect.Target_java_lang_reflect_RecordComponent; import com.oracle.svm.core.reflect.Target_jdk_internal_reflect_ConstantPool; import com.oracle.svm.core.util.LazyFinalReference; @@ -323,24 +324,24 @@ public void setModule(Module module) { @TargetElement(onlyWith = JDK11OrEarlier.class) // private Class newInstanceCallerCache; - @UnknownObjectField(types = {byte[].class}) private byte[] enclosingMethodInfo; + @UnknownPrimitiveField private int enclosingMethodInfoIndex; - @UnknownObjectField(types = {byte[].class}) private byte[] annotations; + @UnknownPrimitiveField private int annotationsIndex; - @UnknownObjectField(types = {byte[].class}) private byte[] typeAnnotations; + @UnknownPrimitiveField private int typeAnnotationsIndex; - @UnknownObjectField(types = {byte[].class}) byte[] fieldsEncoding; + @UnknownPrimitiveField int fieldsEncodingIndex; - @UnknownObjectField(types = {byte[].class}) byte[] methodsEncoding; + @UnknownPrimitiveField int methodsEncodingIndex; - @UnknownObjectField(types = {byte[].class}) byte[] constructorsEncoding; + @UnknownPrimitiveField int constructorsEncodingIndex; - @UnknownObjectField(types = {byte[].class}) byte[] classesEncoding; + @UnknownPrimitiveField int classesEncodingIndex; @TargetElement(onlyWith = JDK17OrLater.class)// - @UnknownObjectField(types = {byte[].class}) byte[] recordComponentsEncoding; + @UnknownPrimitiveField int recordComponentsEncodingIndex; - @UnknownObjectField(types = {byte[].class}) byte[] permittedSubclassesEncoding; + @UnknownPrimitiveField int permittedSubclassesEncodingIndex; @Platforms(Platform.HOSTED_ONLY.class) public DynamicHub(Class hostedJavaClass, String name, HubType hubType, ReferenceType referenceType, Object isLocalClass, Object isAnonymousClass, DynamicHub superType, DynamicHub componentHub, @@ -475,48 +476,48 @@ public String getSignature() { } @Platforms(Platform.HOSTED_ONLY.class) - public void setFieldsEncoding(byte[] encoding) { - this.fieldsEncoding = encoding; + public void setFieldsEncodingIndex(int encodingIndex) { + this.fieldsEncodingIndex = encodingIndex; } @Platforms(Platform.HOSTED_ONLY.class) - public void setMethodsEncoding(byte[] encoding) { - this.methodsEncoding = encoding; + public void setMethodsEncodingIndex(int encodingIndex) { + this.methodsEncodingIndex = encodingIndex; } @Platforms(Platform.HOSTED_ONLY.class) - public void setConstructorsEncoding(byte[] encoding) { - this.constructorsEncoding = encoding; + public void setConstructorsEncodingIndex(int encodingIndex) { + this.constructorsEncodingIndex = encodingIndex; } @Platforms(Platform.HOSTED_ONLY.class) - public void setClassesEncoding(byte[] encoding) { - this.classesEncoding = encoding; + public void setClassesEncodingIndex(int encodingIndex) { + this.classesEncodingIndex = encodingIndex; } @Platforms(Platform.HOSTED_ONLY.class) - public void setRecordComponentsEncoding(byte[] encoding) { - this.recordComponentsEncoding = encoding; + public void setRecordComponentsEncodingIndex(int encodingIndex) { + this.recordComponentsEncodingIndex = encodingIndex; } @Platforms(Platform.HOSTED_ONLY.class) - public void setPermittedSubclassesEncoding(byte[] encoding) { - this.permittedSubclassesEncoding = encoding; + public void setPermittedSubclassesEncodingIndex(int encodingIndex) { + this.permittedSubclassesEncodingIndex = encodingIndex; } @Platforms(Platform.HOSTED_ONLY.class) - public void setAnnotationsEncoding(byte[] encoding) { - this.annotations = encoding; + public void setAnnotationsEncodingIndex(int encodingIndex) { + this.annotationsIndex = encodingIndex; } @Platforms(Platform.HOSTED_ONLY.class) - public void setTypeAnnotationsEncoding(byte[] encoding) { - this.typeAnnotations = encoding; + public void setTypeAnnotationsEncodingIndex(int encodingIndex) { + this.typeAnnotationsIndex = encodingIndex; } @Platforms(Platform.HOSTED_ONLY.class) - public void setEnclosingMethodInfo(byte[] encoding) { - this.enclosingMethodInfo = encoding; + public void setEnclosingMethodInfoIndex(int encodingIndex) { + this.enclosingMethodInfoIndex = encodingIndex; } /** Executed at runtime. */ @@ -1001,12 +1002,12 @@ public T[] getAnnotationsByType(Class annotationClass) @Substitute @TargetElement(onlyWith = JDK17OrLater.class) private Target_java_lang_reflect_RecordComponent[] getRecordComponents0() { - if (recordComponentsEncoding == null) { + if (recordComponentsEncodingIndex == ReflectionMetadataDecoder.NULL_ARRAY) { /* See ReflectionDataBuilder.buildRecordComponents() for details. */ throw VMError.unsupportedFeature("Record components not available for record class " + getTypeName() + ". " + "All record component accessor methods of this record class must be included in the reflection configuration at image build time, then this method can be called."); } - return ImageSingletons.lookup(MethodMetadataDecoder.class).parseRecordComponents(this, recordComponentsEncoding); + return ImageSingletons.lookup(ReflectionMetadataDecoder.class).parseRecordComponents(this, recordComponentsEncodingIndex); } @KeepOriginal @@ -1329,10 +1330,10 @@ public Optional describeConstable() { @Substitute private Object[] getEnclosingMethod0() { - if (enclosingMethodInfo == null) { + if (enclosingMethodInfoIndex == ReflectionMetadataDecoder.NULL_ARRAY) { return null; } - Object[] enclosingMethod = ImageSingletons.lookup(MethodMetadataDecoder.class).parseEnclosingMethod(enclosingMethodInfo); + Object[] enclosingMethod = ImageSingletons.lookup(ReflectionMetadataDecoder.class).parseEnclosingMethod(enclosingMethodInfoIndex); if (enclosingMethod != null) { PredefinedClassesSupport.throwIfUnresolvable((Class) enclosingMethod[0], getClassLoader0()); } @@ -1365,12 +1366,12 @@ private String getGenericSignature0() { @Substitute byte[] getRawAnnotations() { - return annotations; + return ImageSingletons.lookup(ReflectionMetadataDecoder.class).parseByteArray(annotationsIndex); } @Substitute byte[] getRawTypeAnnotations() { - return typeAnnotations; + return ImageSingletons.lookup(ReflectionMetadataDecoder.class).parseByteArray(typeAnnotationsIndex); } @Substitute @@ -1380,22 +1381,22 @@ Target_jdk_internal_reflect_ConstantPool getConstantPool() { @Substitute private Field[] getDeclaredFields0(boolean publicOnly) { - return ImageSingletons.lookup(MethodMetadataDecoder.class).parseFields(this, fieldsEncoding, publicOnly, true); + return ImageSingletons.lookup(ReflectionMetadataDecoder.class).parseFields(this, fieldsEncodingIndex, publicOnly, true); } @Substitute private Method[] getDeclaredMethods0(boolean publicOnly) { - return ImageSingletons.lookup(MethodMetadataDecoder.class).parseMethods(this, methodsEncoding, publicOnly, true); + return ImageSingletons.lookup(ReflectionMetadataDecoder.class).parseMethods(this, methodsEncodingIndex, publicOnly, true); } @Substitute private Constructor[] getDeclaredConstructors0(boolean publicOnly) { - return ImageSingletons.lookup(MethodMetadataDecoder.class).parseConstructors(this, constructorsEncoding, publicOnly, true); + return ImageSingletons.lookup(ReflectionMetadataDecoder.class).parseConstructors(this, constructorsEncodingIndex, publicOnly, true); } @Substitute private Class[] getDeclaredClasses0() { - Class[] declaredClasses = ImageSingletons.lookup(MethodMetadataDecoder.class).parseClasses(classesEncoding); + Class[] declaredClasses = ImageSingletons.lookup(ReflectionMetadataDecoder.class).parseClasses(classesEncodingIndex); for (Class clazz : declaredClasses) { PredefinedClassesSupport.throwIfUnresolvable(clazz, getClassLoader0()); } @@ -1447,10 +1448,10 @@ private native Target_java_lang_Class_ReflectionData newReflectionData(So @Substitute @TargetElement(onlyWith = JDK17OrLater.class) private Class[] getPermittedSubclasses0() { - if (permittedSubclassesEncoding.length == 0) { + if (permittedSubclassesEncodingIndex == ReflectionMetadataDecoder.NULL_ARRAY) { return null; } - Class[] permittedSubclasses = ImageSingletons.lookup(MethodMetadataDecoder.class).parseClasses(permittedSubclassesEncoding); + Class[] permittedSubclasses = ImageSingletons.lookup(ReflectionMetadataDecoder.class).parseClasses(permittedSubclassesEncodingIndex); for (Class clazz : permittedSubclasses) { PredefinedClassesSupport.throwIfUnresolvable(clazz, getClassLoader0()); } @@ -1478,7 +1479,7 @@ private Class[] getPermittedSubclasses0() { private static Method[] filterHidingMethods(Method... methods) { List filtered = new ArrayList<>(); for (Method method : methods) { - if (!ImageSingletons.lookup(MethodMetadataDecoder.class).isHidingMethod(method.getModifiers())) { + if (!ImageSingletons.lookup(ReflectionMetadataDecoder.class).isHidingMethod(method.getModifiers())) { filtered.add(method); } } @@ -1531,15 +1532,15 @@ private static void setNewInstanceCallerCache(DynamicHub that, Class value) { } public Field[] getReachableFields() { - return ImageSingletons.lookup(MethodMetadataDecoder.class).parseFields(this, fieldsEncoding, false, false); + return ImageSingletons.lookup(ReflectionMetadataDecoder.class).parseFields(this, fieldsEncodingIndex, false, false); } public Method[] getReachableMethods() { - return ImageSingletons.lookup(MethodMetadataDecoder.class).parseMethods(this, methodsEncoding, false, false); + return ImageSingletons.lookup(ReflectionMetadataDecoder.class).parseMethods(this, methodsEncodingIndex, false, false); } public Constructor[] getReachableConstructors() { - return ImageSingletons.lookup(MethodMetadataDecoder.class).parseConstructors(this, constructorsEncoding, false, false); + return ImageSingletons.lookup(ReflectionMetadataDecoder.class).parseConstructors(this, constructorsEncodingIndex, false, false); } } @@ -1640,7 +1641,7 @@ Method getMostSpecific() { } } /* Filter out hiding methods after the retursive lookup is done */ - return ImageSingletons.lookup(MethodMetadataDecoder.class).isHidingMethod(m.getModifiers()) ? null : m; + return ImageSingletons.lookup(ReflectionMetadataDecoder.class).isHidingMethod(m.getModifiers()) ? null : m; } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/MethodMetadataDecoder.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/ReflectionMetadataDecoder.java similarity index 76% rename from substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/MethodMetadataDecoder.java rename to substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/ReflectionMetadataDecoder.java index 0d7442fe974a..a566335a87a8 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/MethodMetadataDecoder.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/reflect/ReflectionMetadataDecoder.java @@ -32,20 +32,26 @@ import com.oracle.svm.core.hub.DynamicHub; -public interface MethodMetadataDecoder { - Field[] parseFields(DynamicHub declaringType, byte[] encoding, boolean publicOnly, boolean reflectOnly); +public interface ReflectionMetadataDecoder { + int NULL_ARRAY = -1; - Method[] parseMethods(DynamicHub declaringType, byte[] encoding, boolean publicOnly, boolean reflectOnly); + Field[] parseFields(DynamicHub declaringType, int index, boolean publicOnly, boolean reflectOnly); - Constructor[] parseConstructors(DynamicHub declaringType, byte[] encoding, boolean publicOnly, boolean reflectOnly); + Method[] parseMethods(DynamicHub declaringType, int index, boolean publicOnly, boolean reflectOnly); - Class[] parseClasses(byte[] encoding); + Constructor[] parseConstructors(DynamicHub declaringType, int index, boolean publicOnly, boolean reflectOnly); - Target_java_lang_reflect_RecordComponent[] parseRecordComponents(DynamicHub declaringType, byte[] encoding); + Class[] parseClasses(int index); + + Target_java_lang_reflect_RecordComponent[] parseRecordComponents(DynamicHub declaringType, int index); Parameter[] parseReflectParameters(Executable executable, byte[] encoding); - Object[] parseEnclosingMethod(byte[] encoding); + Object[] parseEnclosingMethod(int index); + + byte[] parseByteArray(int index); boolean isHidingMethod(int modifiers); + + long getMetadataByteLength(); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java index f4ec9fdf0ec3..2bc642aca595 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ProgressReporter.java @@ -45,7 +45,6 @@ import java.util.concurrent.TimeUnit; import java.util.function.Consumer; -import com.oracle.graal.pointsto.util.TimerCollection; import org.graalvm.compiler.debug.DebugOptions; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.serviceprovider.GraalServices; @@ -60,6 +59,7 @@ import com.oracle.graal.pointsto.meta.AnalysisUniverse; import com.oracle.graal.pointsto.reports.ReportUtils; import com.oracle.graal.pointsto.util.Timer; +import com.oracle.graal.pointsto.util.TimerCollection; import com.oracle.svm.core.BuildArtifacts; import com.oracle.svm.core.BuildArtifacts.ArtifactType; import com.oracle.svm.core.OS; @@ -69,6 +69,7 @@ import com.oracle.svm.core.code.CodeInfoTable; import com.oracle.svm.core.heap.Heap; import com.oracle.svm.core.option.HostedOptionValues; +import com.oracle.svm.core.reflect.ReflectionMetadataDecoder; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.c.codegen.CCompilerInvoker; import com.oracle.svm.hosted.code.CompileQueue.CompileTask; @@ -105,7 +106,6 @@ public class ProgressReporter { private GCStats lastGCStats = GCStats.getCurrent(); private long numRuntimeCompiledMethods = -1; private long graphEncodingByteLength = 0; - private long metadataByteLength = 0; private int numJNIClasses = -1; private int numJNIFields = -1; private int numJNIMethods = -1; @@ -207,10 +207,6 @@ public void setGraphEncodingByteLength(int value) { graphEncodingByteLength = value; } - public void setMetadataByteLength(int value) { - metadataByteLength = value; - } - public void setJNIInfo(int numClasses, int numFields, int numMethods) { numJNIClasses = numClasses; numJNIFields = numFields; @@ -507,8 +503,9 @@ private Map calculateHeapBreakdown(Collection heapObje classNameToSize.put(BREAKDOWN_BYTE_ARRAY_PREFIX + linkStrategy.asDocLink("code metadata", "#glossary-code-metadata"), codeInfoSize); remainingBytes -= codeInfoSize; } + long metadataByteLength = ImageSingletons.lookup(ReflectionMetadataDecoder.class).getMetadataByteLength(); if (metadataByteLength > 0) { - classNameToSize.put(BREAKDOWN_BYTE_ARRAY_PREFIX + linkStrategy.asDocLink("method metadata", "#glossary-method-metadata"), metadataByteLength); + classNameToSize.put(BREAKDOWN_BYTE_ARRAY_PREFIX + linkStrategy.asDocLink("reflection metadata", "#glossary-method-metadata"), metadataByteLength); remainingBytes -= metadataByteLength; } if (graphEncodingByteLength > 0) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java index 626b8e6841e5..17bdf1ee7211 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java @@ -237,11 +237,11 @@ public void buildRuntimeMetadata(CFunctionPointer firstMethod, UnsignedWord code codeInfoEncoder.addMethod(method, compilation, method.getCodeAddressOffset()); } - MethodMetadataEncoder methodMetadataEncoder = ImageSingletons.lookup(MethodMetadataEncoderFactory.class).create(encoders); + ReflectionMetadataEncoder reflectionMetadataEncoder = ImageSingletons.lookup(ReflectionMetadataEncoderFactory.class).create(encoders); for (HostedType type : imageHeap.getUniverse().getTypes()) { Map, Set>> innerClasses = ImageSingletons.lookup(RuntimeReflectionSupport.class).getReflectionInnerClasses(); if (type.getWrapped().isReachable()) { - methodMetadataEncoder.addClassMetadata(imageHeap.getMetaAccess(), type, innerClasses.getOrDefault(type.getJavaClass(), Collections.emptySet()).toArray(new Class[0])); + reflectionMetadataEncoder.addClassMetadata(imageHeap.getMetaAccess(), type, innerClasses.getOrDefault(type.getJavaClass(), Collections.emptySet()).toArray(new Class[0])); } } Set includedFields = new HashSet<>(); @@ -253,12 +253,12 @@ public void buildRuntimeMetadata(CFunctionPointer firstMethod, UnsignedWord code if (object instanceof Method || object instanceof Constructor) { includedMethods.add(imageHeap.getMetaAccess().lookupJavaMethod((Executable) object)); } - methodMetadataEncoder.addHeapObjectMetadata(imageHeap.getMetaAccess(), object); + reflectionMetadataEncoder.addHeapObjectMetadata(imageHeap.getMetaAccess(), object); } for (Field reflectField : ImageSingletons.lookup(RuntimeReflectionSupport.class).getReflectionFields()) { HostedField field = imageHeap.getMetaAccess().lookupJavaField(reflectField); if (!includedFields.contains(field)) { - methodMetadataEncoder.addReflectionFieldMetadata(imageHeap.getMetaAccess(), field, reflectField); + reflectionMetadataEncoder.addReflectionFieldMetadata(imageHeap.getMetaAccess(), field, reflectField); includedFields.add(field); } } @@ -266,7 +266,7 @@ public void buildRuntimeMetadata(CFunctionPointer firstMethod, UnsignedWord code HostedMethod method = imageHeap.getMetaAccess().lookupJavaMethod(reflectMethod); if (!includedMethods.contains(method)) { Object accessor = ImageSingletons.lookup(RuntimeReflectionSupport.class).getAccessor(reflectMethod); - methodMetadataEncoder.addReflectionExecutableMetadata(imageHeap.getMetaAccess(), method, reflectMethod, accessor); + reflectionMetadataEncoder.addReflectionExecutableMetadata(imageHeap.getMetaAccess(), method, reflectMethod, accessor); includedMethods.add(method); } } @@ -283,7 +283,7 @@ public void buildRuntimeMetadata(CFunctionPointer firstMethod, UnsignedWord code } int modifiers = hidingMethod.getModifiers(); HostedType returnType = imageHeap.getUniverse().lookup(hidingMethod.getSignature().getReturnType(null)); - methodMetadataEncoder.addHidingMethodMetadata(declaringType, name, parameterTypes, modifiers, returnType); + reflectionMetadataEncoder.addHidingMethodMetadata(declaringType, name, parameterTypes, modifiers, returnType); if (hostedMethod != null) { includedMethods.add(hostedMethod); } @@ -292,12 +292,12 @@ public void buildRuntimeMetadata(CFunctionPointer firstMethod, UnsignedWord code if (SubstrateOptions.IncludeMethodData.getValue()) { for (HostedField field : imageHeap.getUniverse().getFields()) { if (field.isAccessed() && !includedFields.contains(field)) { - methodMetadataEncoder.addReachableFieldMetadata(field); + reflectionMetadataEncoder.addReachableFieldMetadata(field); } } for (HostedMethod method : imageHeap.getUniverse().getMethods()) { if (method.getWrapped().isReachable() && !method.getWrapped().isIntrinsicMethod() && !includedMethods.contains(method)) { - methodMetadataEncoder.addReachableMethodMetadata(method); + reflectionMetadataEncoder.addReachableMethodMetadata(method); } } } @@ -309,7 +309,7 @@ public void buildRuntimeMetadata(CFunctionPointer firstMethod, UnsignedWord code HostedImageCodeInfo imageCodeInfo = CodeInfoTable.getImageCodeCache().getHostedImageCodeInfo(); codeInfoEncoder.encodeAllAndInstall(imageCodeInfo, new InstantReferenceAdjuster()); - methodMetadataEncoder.encodeAllAndInstall(); + reflectionMetadataEncoder.encodeAllAndInstall(); imageCodeInfo.setCodeStart(firstMethod); imageCodeInfo.setCodeSize(codeSize); imageCodeInfo.setDataOffset(codeSize); @@ -601,7 +601,7 @@ protected boolean isDeoptEntry(ResolvedJavaMethod method, Infopoint infopoint) { } } - public interface MethodMetadataEncoder { + public interface ReflectionMetadataEncoder { void addClassMetadata(MetaAccessProvider metaAccess, HostedType type, Class[] reflectionClasses); void addReflectionFieldMetadata(MetaAccessProvider metaAccess, HostedField sharedField, Field reflectField); @@ -629,7 +629,7 @@ public interface MethodMetadataEncoder { byte[] getReflectParametersEncoding(Executable object); } - public interface MethodMetadataEncoderFactory { - MethodMetadataEncoder create(CodeInfoEncoder.Encoders encoders); + public interface ReflectionMetadataEncoderFactory { + ReflectionMetadataEncoder create(CodeInfoEncoder.Encoders encoders); } } diff --git a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/hosted/ReflectionDataBuilder.java b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/hosted/ReflectionDataBuilder.java index b8f414391958..3339ea1ef660 100644 --- a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/hosted/ReflectionDataBuilder.java +++ b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/hosted/ReflectionDataBuilder.java @@ -24,7 +24,7 @@ */ package com.oracle.svm.reflect.hosted; -import static com.oracle.svm.reflect.hosted.MethodMetadataEncoderImpl.getTypeAnnotations; +import static com.oracle.svm.reflect.hosted.ReflectionMetadataEncoderImpl.getTypeAnnotations; import java.lang.annotation.Annotation; import java.lang.reflect.AccessibleObject; @@ -246,7 +246,7 @@ private void processReachableTypes(DuringAnalysisAccessImpl access) { } /** - * See {@link MethodMetadataEncoderImpl} for details. + * See {@link ReflectionMetadataEncoderImpl} for details. */ protected void processMethodMetadata(DuringAnalysisAccessImpl access) { for (AnalysisType type : access.getUniverse().getTypes()) { diff --git a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/hosted/ReflectionMetadata.java b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/hosted/ReflectionMetadata.java index 7ddc2e33fd25..225e7d1cbd79 100644 --- a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/hosted/ReflectionMetadata.java +++ b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/hosted/ReflectionMetadata.java @@ -32,20 +32,22 @@ import org.graalvm.nativeimage.hosted.Feature; import com.oracle.svm.core.annotate.AutomaticFeature; -import com.oracle.svm.core.reflect.MethodMetadataDecoder; -import com.oracle.svm.hosted.image.NativeImageCodeCache.MethodMetadataEncoderFactory; +import com.oracle.svm.core.reflect.ReflectionMetadataDecoder; +import com.oracle.svm.hosted.image.NativeImageCodeCache.ReflectionMetadataEncoderFactory; import com.oracle.svm.hosted.meta.HostedType; -import com.oracle.svm.reflect.target.MethodMetadataDecoderImpl; +import com.oracle.svm.reflect.target.ReflectionMetadataDecoderImpl; +import com.oracle.svm.reflect.target.ReflectionMetadataEncoding; import jdk.vm.ci.meta.JavaConstant; import sun.reflect.annotation.TypeAnnotation; @AutomaticFeature -class MethodMetadataFeature implements Feature { +class ReflectionMetadataFeature implements Feature { @Override public void afterRegistration(AfterRegistrationAccess access) { - ImageSingletons.add(MethodMetadataEncoderFactory.class, new MethodMetadataEncoderImpl.Factory()); - ImageSingletons.add(MethodMetadataDecoder.class, new MethodMetadataDecoderImpl()); + ImageSingletons.add(ReflectionMetadataEncoderFactory.class, new ReflectionMetadataEncoderImpl.Factory()); + ImageSingletons.add(ReflectionMetadataDecoder.class, new ReflectionMetadataDecoderImpl()); + ImageSingletons.add(ReflectionMetadataEncoding.class, new ReflectionMetadataEncoding()); } } diff --git a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/hosted/MethodMetadataEncoderImpl.java b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/hosted/ReflectionMetadataEncoderImpl.java similarity index 90% rename from substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/hosted/MethodMetadataEncoderImpl.java rename to substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/hosted/ReflectionMetadataEncoderImpl.java index 7fafb0e45ed3..a3066bf623f8 100644 --- a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/hosted/MethodMetadataEncoderImpl.java +++ b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/hosted/ReflectionMetadataEncoderImpl.java @@ -24,10 +24,10 @@ */ package com.oracle.svm.reflect.hosted; -import static com.oracle.svm.reflect.target.MethodMetadataDecoderImpl.COMPLETE_FLAG_MASK; -import static com.oracle.svm.reflect.target.MethodMetadataDecoderImpl.HIDING_FLAG_MASK; -import static com.oracle.svm.reflect.target.MethodMetadataDecoderImpl.IN_HEAP_FLAG_MASK; -import static com.oracle.svm.reflect.target.MethodMetadataDecoderImpl.NULL_OBJECT; +import static com.oracle.svm.reflect.target.ReflectionMetadataDecoderImpl.COMPLETE_FLAG_MASK; +import static com.oracle.svm.reflect.target.ReflectionMetadataDecoderImpl.HIDING_FLAG_MASK; +import static com.oracle.svm.reflect.target.ReflectionMetadataDecoderImpl.IN_HEAP_FLAG_MASK; +import static com.oracle.svm.reflect.target.ReflectionMetadataDecoderImpl.NULL_OBJECT; import java.lang.annotation.Annotation; import java.lang.reflect.AccessibleObject; @@ -64,12 +64,12 @@ import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.meta.SharedField; import com.oracle.svm.core.meta.SubstrateObjectConstant; +import com.oracle.svm.core.reflect.ReflectionMetadataDecoder; import com.oracle.svm.core.reflect.Target_jdk_internal_reflect_ConstantPool; import com.oracle.svm.core.util.ByteArrayReader; import com.oracle.svm.core.util.VMError; -import com.oracle.svm.hosted.ProgressReporter; -import com.oracle.svm.hosted.image.NativeImageCodeCache.MethodMetadataEncoder; -import com.oracle.svm.hosted.image.NativeImageCodeCache.MethodMetadataEncoderFactory; +import com.oracle.svm.hosted.image.NativeImageCodeCache.ReflectionMetadataEncoder; +import com.oracle.svm.hosted.image.NativeImageCodeCache.ReflectionMetadataEncoderFactory; import com.oracle.svm.hosted.meta.HostedField; import com.oracle.svm.hosted.meta.HostedMetaAccess; import com.oracle.svm.hosted.meta.HostedMethod; @@ -83,7 +83,8 @@ import com.oracle.svm.reflect.hosted.ReflectionMetadata.MethodMetadata; import com.oracle.svm.reflect.hosted.ReflectionMetadata.RecordComponentMetadata; import com.oracle.svm.reflect.hosted.ReflectionMetadata.ReflectParameterMetadata; -import com.oracle.svm.reflect.target.MethodMetadataDecoderImpl; +import com.oracle.svm.reflect.target.ReflectionMetadataDecoderImpl; +import com.oracle.svm.reflect.target.ReflectionMetadataEncoding; import com.oracle.svm.reflect.target.Target_sun_reflect_annotation_AnnotationParser; import com.oracle.svm.util.ReflectionUtil; @@ -115,12 +116,12 @@ * phase, the values are encoded as byte arrays and stored in {@link DynamicHub} arrays (see * {@link #encodeAllAndInstall()}). */ -public class MethodMetadataEncoderImpl implements MethodMetadataEncoder { +public class ReflectionMetadataEncoderImpl implements ReflectionMetadataEncoder { - static class Factory implements MethodMetadataEncoderFactory { + static class Factory implements ReflectionMetadataEncoderFactory { @Override - public MethodMetadataEncoder create(CodeInfoEncoder.Encoders encoders) { - return new MethodMetadataEncoderImpl(encoders); + public ReflectionMetadataEncoder create(CodeInfoEncoder.Encoders encoders) { + return new ReflectionMetadataEncoderImpl(encoders); } } @@ -140,7 +141,7 @@ public MethodMetadataEncoder create(CodeInfoEncoder.Encoders encoders) { private final Map typeAnnotationsEncodings = new HashMap<>(); private final Map reflectParametersEncodings = new HashMap<>(); - public MethodMetadataEncoderImpl(CodeInfoEncoder.Encoders encoders) { + public ReflectionMetadataEncoderImpl(CodeInfoEncoder.Encoders encoders) { this.encoders = encoders; } @@ -202,6 +203,7 @@ public void addClassMetadata(MetaAccessProvider metaAccess, HostedType type, Cla TypeAnnotation[] typeAnnotations = getTypeAnnotations(javaClass); /* Register string and class values in annotations */ + encoders.sourceClasses.addObject(javaClass); if (enclosingMethodInfo != null) { encoders.sourceClasses.addObject(enclosingMethodDeclaringClass.getJavaClass()); encoders.sourceMethodNames.addObject(enclosingMethodName); @@ -672,73 +674,90 @@ private static Method getRecordComponentAccessor(Object recordComponent) { } /** - * See {@link MethodMetadataDecoderImpl} for the encoding format description. + * See {@link ReflectionMetadataDecoderImpl} for the encoding format description. */ @Override public void encodeAllAndInstall() { - int metadataByteLength = 0; + UnsafeArrayTypeWriter buf = UnsafeArrayTypeWriter.create(ByteArrayReader.supportsUnalignedMemoryAccess()); + encodeAndAddCollection(buf, sortedTypes.toArray(new HostedType[0]), this::encodeType, (ignored) -> { + }, false); for (HostedType declaringType : sortedTypes) { DynamicHub hub = declaringType.getHub(); ClassMetadata classMetadata = classData.get(declaringType); - metadataByteLength += encodeAndInstallCollection(classMetadata.classes, this::encodeType, hub::setClassesEncoding, false); - if (classMetadata.enclosingMethodDeclaringClass != null || classMetadata.enclosingMethodName != null || classMetadata.enclosingMethodDescriptor != null) { - metadataByteLength += encodeAndInstall(new Object[]{classMetadata.enclosingMethodDeclaringClass, classMetadata.enclosingMethodName, classMetadata.enclosingMethodDescriptor}, - this::encodeEnclosingMethod, hub::setEnclosingMethodInfo); - } + encodeAndAddCollection(buf, classMetadata.classes, this::encodeType, hub::setClassesEncodingIndex, false); + encodeAndAddElement(buf, new Object[]{classMetadata.enclosingMethodDeclaringClass, classMetadata.enclosingMethodName, classMetadata.enclosingMethodDescriptor}, + this::encodeEnclosingMethod, hub::setEnclosingMethodInfoIndex); if (JavaVersionUtil.JAVA_SPEC >= 17) { - metadataByteLength += encodeAndInstallCollection(classMetadata.recordComponents, this::encodeRecordComponent, hub::setRecordComponentsEncoding, true); - metadataByteLength += encodeAndInstallCollection(classMetadata.permittedSubclasses, this::encodeType, hub::setPermittedSubclassesEncoding, true); + encodeAndAddCollection(buf, classMetadata.recordComponents, this::encodeRecordComponent, hub::setRecordComponentsEncodingIndex, true); + encodeAndAddCollection(buf, classMetadata.permittedSubclasses, this::encodeType, hub::setPermittedSubclassesEncodingIndex, true); } - metadataByteLength += encodeAndInstall(classMetadata.annotations, this::encodeAnnotations, hub::setAnnotationsEncoding); - metadataByteLength += encodeAndInstall(classMetadata.typeAnnotations, this::encodeTypeAnnotations, - hub::setTypeAnnotationsEncoding); - metadataByteLength += encodeAndInstallCollection(fieldData.getOrDefault(declaringType, Collections.emptySet()).toArray(new FieldMetadata[0]), this::encodeField, hub::setFieldsEncoding, + encodeAndAddEncodedElement(buf, classMetadata.annotations, this::encodeAnnotations, hub::setAnnotationsEncodingIndex); + encodeAndAddEncodedElement(buf, classMetadata.typeAnnotations, this::encodeTypeAnnotations, + hub::setTypeAnnotationsEncodingIndex); + encodeAndAddCollection(buf, fieldData.getOrDefault(declaringType, Collections.emptySet()).toArray(new FieldMetadata[0]), this::encodeField, hub::setFieldsEncodingIndex, false); - metadataByteLength += encodeAndInstallCollection(methodData.getOrDefault(declaringType, Collections.emptySet()).toArray(new MethodMetadata[0]), this::encodeExecutable, - hub::setMethodsEncoding, false); - metadataByteLength += encodeAndInstallCollection(constructorData.getOrDefault(declaringType, Collections.emptySet()).toArray(new ConstructorMetadata[0]), this::encodeExecutable, - hub::setConstructorsEncoding, false); + encodeAndAddCollection(buf, methodData.getOrDefault(declaringType, Collections.emptySet()).toArray(new MethodMetadata[0]), this::encodeExecutable, + hub::setMethodsEncodingIndex, false); + encodeAndAddCollection(buf, constructorData.getOrDefault(declaringType, Collections.emptySet()).toArray(new ConstructorMetadata[0]), this::encodeExecutable, + hub::setConstructorsEncodingIndex, false); } for (AccessibleObjectMetadata metadata : heapData) { AccessibleObject heapObject = (AccessibleObject) SubstrateObjectConstant.asObject(metadata.heapObject); - metadataByteLength += encodeAndInstall(metadata.annotations, this::encodeAnnotations, (array) -> annotationsEncodings.put(heapObject, array)); - metadataByteLength += encodeAndInstall(metadata.typeAnnotations, this::encodeTypeAnnotations, (array) -> typeAnnotationsEncodings.put(heapObject, array)); + encodeAndAddHeapElement(metadata.annotations, this::encodeAnnotations, (array) -> annotationsEncodings.put(heapObject, array)); + encodeAndAddHeapElement(metadata.typeAnnotations, this::encodeTypeAnnotations, (array) -> typeAnnotationsEncodings.put(heapObject, array)); if (metadata instanceof ExecutableMetadata) { - metadataByteLength += encodeAndInstall(((ExecutableMetadata) metadata).parameterAnnotations, this::encodeParameterAnnotations, + encodeAndAddHeapElement(((ExecutableMetadata) metadata).parameterAnnotations, this::encodeParameterAnnotations, (array) -> parameterAnnotationsEncodings.put((Executable) heapObject, array)); if (((ExecutableMetadata) metadata).reflectParameters != null) { - metadataByteLength += encodeAndInstall(((ExecutableMetadata) metadata).reflectParameters, this::encodeReflectParameters, + encodeAndAddHeapElement(((ExecutableMetadata) metadata).reflectParameters, this::encodeReflectParameters, (array) -> reflectParametersEncodings.put((Executable) heapObject, array)); } if (metadata instanceof MethodMetadata && ((Method) SubstrateObjectConstant.asObject(metadata.heapObject)).getDeclaringClass().isAnnotation() && ((MethodMetadata) metadata).annotationDefault != null) { - metadataByteLength += encodeAndInstall(((MethodMetadata) metadata).annotationDefault, this::encodeMemberValue, + encodeAndAddHeapElement(((MethodMetadata) metadata).annotationDefault, this::encodeMemberValue, (array) -> annotationDefaultEncodings.put((Method) heapObject, array)); } } } + install(buf); /* Enable field recomputers in reflection objects to see the computed values */ - ImageSingletons.add(MethodMetadataEncoder.class, this); - ProgressReporter.singleton().setMetadataByteLength(metadataByteLength); + ImageSingletons.add(ReflectionMetadataEncoder.class, this); } - private static int encodeAndInstallCollection(T[] data, BiConsumer encodeCallback, Consumer saveCallback, boolean canBeNull) { - UnsafeArrayTypeWriter encodingBuffer = UnsafeArrayTypeWriter.create(ByteArrayReader.supportsUnalignedMemoryAccess()); - encodeArray(encodingBuffer, data, element -> encodeCallback.accept(encodingBuffer, element), canBeNull); - return install(encodingBuffer, saveCallback); + private static void encodeAndAddCollection(UnsafeArrayTypeWriter buf, T[] data, BiConsumer encodeCallback, Consumer saveCallback, boolean canBeNull) { + int offset = ReflectionMetadataDecoder.NULL_ARRAY; + if (!canBeNull || data != null) { + offset = TypeConversion.asS4(buf.getBytesWritten()); + encodeArray(buf, data, element -> encodeCallback.accept(buf, element)); + } + saveCallback.accept(offset); } - private static int encodeAndInstall(T data, Function encodeCallback, Consumer saveCallback) { - UnsafeArrayTypeWriter encodingBuffer = UnsafeArrayTypeWriter.create(ByteArrayReader.supportsUnalignedMemoryAccess()); - encodeBytes(encodingBuffer, encodeCallback.apply(data)); - return install(encodingBuffer, saveCallback); + private static void encodeAndAddElement(UnsafeArrayTypeWriter buf, T data, Function encodeCallback, Consumer saveCallback) { + byte[] encoding = encodeCallback.apply(data); + int offset = ReflectionMetadataDecoder.NULL_ARRAY; + if (encoding != null) { + offset = TypeConversion.asS4(buf.getBytesWritten()); + encodeBytes(buf, encoding); + } + saveCallback.accept(offset); } - private static int install(UnsafeArrayTypeWriter encodingBuffer, Consumer saveCallback) { + private static void encodeAndAddEncodedElement(UnsafeArrayTypeWriter buf, T data, Function encodeCallback, Consumer saveCallback) { + int offset = TypeConversion.asS4(buf.getBytesWritten()); + encodeByteArray(buf, encodeCallback.apply(data)); + saveCallback.accept(offset); + } + + private static void encodeAndAddHeapElement(T data, Function encodeCallback, Consumer saveCallback) { + byte[] encoding = encodeCallback.apply(data); + saveCallback.accept(encoding); + } + + private static void install(UnsafeArrayTypeWriter encodingBuffer) { int encodingSize = TypeConversion.asS4(encodingBuffer.getBytesWritten()); byte[] dataEncoding = new byte[encodingSize]; - saveCallback.accept(encodingBuffer.toArray(dataEncoding)); - return encodingSize; + ImageSingletons.lookup(ReflectionMetadataEncoding.class).setEncoding(encodingBuffer.toArray(dataEncoding)); } private void encodeField(UnsafeArrayTypeWriter buf, FieldMetadata field) { @@ -817,13 +836,6 @@ private void encodeObject(UnsafeArrayTypeWriter buf, JavaConstant object) { } private static void encodeArray(UnsafeArrayTypeWriter buf, T[] array, Consumer elementEncoder) { - encodeArray(buf, array, elementEncoder, false); - } - - private static void encodeArray(UnsafeArrayTypeWriter buf, T[] array, Consumer elementEncoder, boolean canBeNull) { - if (canBeNull && array == null) { - return; - } buf.putUV(array.length); for (T elem : array) { elementEncoder.accept(elem); @@ -1187,6 +1199,10 @@ private void encodeRecordComponent(UnsafeArrayTypeWriter buf, RecordComponentMet } private byte[] encodeEnclosingMethod(Object[] enclosingMethod) { + assert enclosingMethod.length == 3; + if (enclosingMethod[0] == null && enclosingMethod[1] == null && enclosingMethod[2] == null) { + return null; + } UnsafeArrayTypeWriter buf = UnsafeArrayTypeWriter.create(ByteArrayReader.supportsUnalignedMemoryAccess()); encodeType(buf, (HostedType) enclosingMethod[0]); encodeName(buf, (String) enclosingMethod[1]); diff --git a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/MethodMetadataDecoderImpl.java b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/ReflectionMetadataDecoderImpl.java similarity index 91% rename from substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/MethodMetadataDecoderImpl.java rename to substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/ReflectionMetadataDecoderImpl.java index b2f796530fb3..d3613b092898 100644 --- a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/MethodMetadataDecoderImpl.java +++ b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/ReflectionMetadataDecoderImpl.java @@ -36,6 +36,7 @@ import org.graalvm.compiler.core.common.util.UnsafeArrayTypeReader; import org.graalvm.compiler.serviceprovider.JavaVersionUtil; +import org.graalvm.nativeimage.ImageSingletons; import com.oracle.svm.core.SubstrateUtil; import com.oracle.svm.core.c.NonmovableArrays; @@ -43,7 +44,7 @@ import com.oracle.svm.core.code.CodeInfoAccess; import com.oracle.svm.core.code.CodeInfoTable; import com.oracle.svm.core.hub.DynamicHub; -import com.oracle.svm.core.reflect.MethodMetadataDecoder; +import com.oracle.svm.core.reflect.ReflectionMetadataDecoder; import com.oracle.svm.core.reflect.Target_java_lang_reflect_RecordComponent; import com.oracle.svm.core.util.ByteArrayReader; @@ -106,7 +107,7 @@ * } SimpleMethodEncoding; * */ -public class MethodMetadataDecoderImpl implements MethodMetadataDecoder { +public class ReflectionMetadataDecoderImpl implements ReflectionMetadataDecoder { public static final int NO_METHOD_METADATA = -1; public static final int NULL_OBJECT = -1; public static final int COMPLETE_FLAG_INDEX = 31; @@ -116,37 +117,41 @@ public class MethodMetadataDecoderImpl implements MethodMetadataDecoder { public static final int HIDING_FLAG_INDEX = 29; public static final int HIDING_FLAG_MASK = 1 << HIDING_FLAG_INDEX; + static byte[] getEncoding() { + return ImageSingletons.lookup(ReflectionMetadataEncoding.class).getEncoding(); + } + @Override - public Field[] parseFields(DynamicHub declaringType, byte[] encoding, boolean publicOnly, boolean reflectOnly) { - UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(encoding, 0, ByteArrayReader.supportsUnalignedMemoryAccess()); + public Field[] parseFields(DynamicHub declaringType, int index, boolean publicOnly, boolean reflectOnly) { + UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(getEncoding(), index, ByteArrayReader.supportsUnalignedMemoryAccess()); CodeInfo codeInfo = CodeInfoTable.getImageCodeInfo(); return decodeArray(reader, Field.class, (i) -> decodeField(reader, codeInfo, DynamicHub.toClass(declaringType), publicOnly, reflectOnly)); } @Override - public Method[] parseMethods(DynamicHub declaringType, byte[] encoding, boolean publicOnly, boolean reflectOnly) { - UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(encoding, 0, ByteArrayReader.supportsUnalignedMemoryAccess()); + public Method[] parseMethods(DynamicHub declaringType, int index, boolean publicOnly, boolean reflectOnly) { + UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(getEncoding(), index, ByteArrayReader.supportsUnalignedMemoryAccess()); CodeInfo codeInfo = CodeInfoTable.getImageCodeInfo(); return decodeArray(reader, Method.class, (i) -> decodeMethod(reader, codeInfo, DynamicHub.toClass(declaringType), publicOnly, reflectOnly)); } @Override - public Constructor[] parseConstructors(DynamicHub declaringType, byte[] encoding, boolean publicOnly, boolean reflectOnly) { - UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(encoding, 0, ByteArrayReader.supportsUnalignedMemoryAccess()); + public Constructor[] parseConstructors(DynamicHub declaringType, int index, boolean publicOnly, boolean reflectOnly) { + UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(getEncoding(), index, ByteArrayReader.supportsUnalignedMemoryAccess()); CodeInfo codeInfo = CodeInfoTable.getImageCodeInfo(); return decodeArray(reader, Constructor.class, (i) -> decodeConstructor(reader, codeInfo, DynamicHub.toClass(declaringType), publicOnly, reflectOnly)); } @Override - public Class[] parseClasses(byte[] encoding) { - UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(encoding, 0, ByteArrayReader.supportsUnalignedMemoryAccess()); + public Class[] parseClasses(int index) { + UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(getEncoding(), index, ByteArrayReader.supportsUnalignedMemoryAccess()); CodeInfo codeInfo = CodeInfoTable.getImageCodeInfo(); return decodeArray(reader, Class.class, (i) -> decodeType(reader, codeInfo)); } @Override - public Target_java_lang_reflect_RecordComponent[] parseRecordComponents(DynamicHub declaringType, byte[] encoding) { - UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(encoding, 0, ByteArrayReader.supportsUnalignedMemoryAccess()); + public Target_java_lang_reflect_RecordComponent[] parseRecordComponents(DynamicHub declaringType, int index) { + UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(getEncoding(), index, ByteArrayReader.supportsUnalignedMemoryAccess()); CodeInfo codeInfo = CodeInfoTable.getImageCodeInfo(); return decodeArray(reader, Target_java_lang_reflect_RecordComponent.class, (i) -> decodeRecordComponent(reader, codeInfo, DynamicHub.toClass(declaringType))); } @@ -159,8 +164,8 @@ public Parameter[] parseReflectParameters(Executable executable, byte[] encoding } @Override - public Object[] parseEnclosingMethod(byte[] encoding) { - UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(encoding, 0, ByteArrayReader.supportsUnalignedMemoryAccess()); + public Object[] parseEnclosingMethod(int index) { + UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(getEncoding(), index, ByteArrayReader.supportsUnalignedMemoryAccess()); CodeInfo codeInfo = CodeInfoTable.getImageCodeInfo(); Class declaringClass = decodeType(reader, codeInfo); String name = decodeName(reader, codeInfo); @@ -168,11 +173,22 @@ public Object[] parseEnclosingMethod(byte[] encoding) { return new Object[]{declaringClass, name, descriptor}; } + @Override + public byte[] parseByteArray(int index) { + UnsafeArrayTypeReader reader = UnsafeArrayTypeReader.create(getEncoding(), index, ByteArrayReader.supportsUnalignedMemoryAccess()); + return decodeByteArray(reader); + } + @Override public boolean isHidingMethod(int modifiers) { return (modifiers & HIDING_FLAG_MASK) != 0; } + @Override + public long getMetadataByteLength() { + return ImageSingletons.lookup(ReflectionMetadataEncoding.class).getEncoding().length; + } + private static Field decodeField(UnsafeArrayTypeReader buf, CodeInfo info, Class declaringClass, boolean publicOnly, boolean reflectOnly) { int modifiers = buf.getUVInt(); boolean inHeap = (modifiers & IN_HEAP_FLAG_MASK) != 0; diff --git a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/ReflectionMetadataEncoding.java b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/ReflectionMetadataEncoding.java new file mode 100644 index 000000000000..fc33ab2c2b53 --- /dev/null +++ b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/ReflectionMetadataEncoding.java @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. Oracle designates this + * particular file as subject to the "Classpath" exception as provided + * by Oracle in the LICENSE file that accompanied this code. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ +package com.oracle.svm.reflect.target; + +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; + +import com.oracle.svm.core.annotate.UnknownObjectField; + +public class ReflectionMetadataEncoding { + @UnknownObjectField(types = {byte[].class}) private byte[] encoding; + + public byte[] getEncoding() { + return encoding; + } + + @Platforms(Platform.HOSTED_ONLY.class) + public void setEncoding(byte[] encoding) { + this.encoding = encoding; + } +} diff --git a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_AccessibleObject.java b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_AccessibleObject.java index a9da42b99f9b..df50222f2c57 100644 --- a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_AccessibleObject.java +++ b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_AccessibleObject.java @@ -69,7 +69,7 @@ public RecomputeFieldValue.ValueAvailability valueAvailability() { @Override public Object compute(MetaAccessProvider metaAccess, ResolvedJavaField original, ResolvedJavaField annotated, Object receiver) { - return ImageSingletons.lookup(NativeImageCodeCache.MethodMetadataEncoder.class).getTypeAnnotationsEncoding((AccessibleObject) receiver); + return ImageSingletons.lookup(NativeImageCodeCache.ReflectionMetadataEncoder.class).getTypeAnnotationsEncoding((AccessibleObject) receiver); } } } diff --git a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Constructor.java b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Constructor.java index f1778a3b3937..2fa6e30e8bc9 100644 --- a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Constructor.java +++ b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Constructor.java @@ -85,7 +85,7 @@ public RecomputeFieldValue.ValueAvailability valueAvailability() { @Override public Object compute(MetaAccessProvider metaAccess, ResolvedJavaField original, ResolvedJavaField annotated, Object receiver) { - return ImageSingletons.lookup(NativeImageCodeCache.MethodMetadataEncoder.class).getAnnotationsEncoding((AccessibleObject) receiver); + return ImageSingletons.lookup(NativeImageCodeCache.ReflectionMetadataEncoder.class).getAnnotationsEncoding((AccessibleObject) receiver); } } @@ -98,7 +98,7 @@ public RecomputeFieldValue.ValueAvailability valueAvailability() { @Override public Object compute(MetaAccessProvider metaAccess, ResolvedJavaField original, ResolvedJavaField annotated, Object receiver) { - return ImageSingletons.lookup(NativeImageCodeCache.MethodMetadataEncoder.class).getParameterAnnotationsEncoding((Executable) receiver); + return ImageSingletons.lookup(NativeImageCodeCache.ReflectionMetadataEncoder.class).getParameterAnnotationsEncoding((Executable) receiver); } } } diff --git a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Executable.java b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Executable.java index 0bdfee943d97..72813c6aef51 100644 --- a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Executable.java +++ b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Executable.java @@ -39,7 +39,7 @@ import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.annotate.TargetClass; import com.oracle.svm.core.annotate.UnknownObjectField; -import com.oracle.svm.core.reflect.MethodMetadataDecoder; +import com.oracle.svm.core.reflect.ReflectionMetadataDecoder; import com.oracle.svm.hosted.image.NativeImageCodeCache; import jdk.vm.ci.meta.MetaAccessProvider; @@ -62,7 +62,7 @@ private Parameter[] getParameters0() { if (rawParameters == null) { return null; } - return ImageSingletons.lookup(MethodMetadataDecoder.class).parseReflectParameters(SubstrateUtil.cast(this, Executable.class), rawParameters); + return ImageSingletons.lookup(ReflectionMetadataDecoder.class).parseReflectParameters(SubstrateUtil.cast(this, Executable.class), rawParameters); } @Substitute @@ -79,7 +79,7 @@ public RecomputeFieldValue.ValueAvailability valueAvailability() { @Override public Object compute(MetaAccessProvider metaAccess, ResolvedJavaField original, ResolvedJavaField annotated, Object receiver) { - return ImageSingletons.lookup(NativeImageCodeCache.MethodMetadataEncoder.class).getReflectParametersEncoding((Executable) receiver); + return ImageSingletons.lookup(NativeImageCodeCache.ReflectionMetadataEncoder.class).getReflectParametersEncoding((Executable) receiver); } } } diff --git a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Field.java b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Field.java index 045580fa6599..e1b3e7dbe8d6 100644 --- a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Field.java +++ b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Field.java @@ -143,7 +143,7 @@ public RecomputeFieldValue.ValueAvailability valueAvailability() { @Override public Object compute(MetaAccessProvider metaAccess, ResolvedJavaField original, ResolvedJavaField annotated, Object receiver) { - return ImageSingletons.lookup(NativeImageCodeCache.MethodMetadataEncoder.class).getAnnotationsEncoding((AccessibleObject) receiver); + return ImageSingletons.lookup(NativeImageCodeCache.ReflectionMetadataEncoder.class).getAnnotationsEncoding((AccessibleObject) receiver); } } } diff --git a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Method.java b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Method.java index 7707edfcbe19..08f89e20e68b 100644 --- a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Method.java +++ b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_java_lang_reflect_Method.java @@ -88,7 +88,7 @@ public RecomputeFieldValue.ValueAvailability valueAvailability() { @Override public Object compute(MetaAccessProvider metaAccess, ResolvedJavaField original, ResolvedJavaField annotated, Object receiver) { - return ImageSingletons.lookup(NativeImageCodeCache.MethodMetadataEncoder.class).getAnnotationsEncoding((AccessibleObject) receiver); + return ImageSingletons.lookup(NativeImageCodeCache.ReflectionMetadataEncoder.class).getAnnotationsEncoding((AccessibleObject) receiver); } } @@ -101,7 +101,7 @@ public RecomputeFieldValue.ValueAvailability valueAvailability() { @Override public Object compute(MetaAccessProvider metaAccess, ResolvedJavaField original, ResolvedJavaField annotated, Object receiver) { - return ImageSingletons.lookup(NativeImageCodeCache.MethodMetadataEncoder.class).getParameterAnnotationsEncoding((Executable) receiver); + return ImageSingletons.lookup(NativeImageCodeCache.ReflectionMetadataEncoder.class).getParameterAnnotationsEncoding((Executable) receiver); } } @@ -114,7 +114,7 @@ public RecomputeFieldValue.ValueAvailability valueAvailability() { @Override public Object compute(MetaAccessProvider metaAccess, ResolvedJavaField original, ResolvedJavaField annotated, Object receiver) { - return ImageSingletons.lookup(NativeImageCodeCache.MethodMetadataEncoder.class).getAnnotationDefaultEncoding((Method) receiver); + return ImageSingletons.lookup(NativeImageCodeCache.ReflectionMetadataEncoder.class).getAnnotationDefaultEncoding((Method) receiver); } } } diff --git a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_sun_reflect_annotation_AnnotationParser.java b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_sun_reflect_annotation_AnnotationParser.java index e900235c1769..b7253aef0c8c 100644 --- a/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_sun_reflect_annotation_AnnotationParser.java +++ b/substratevm/src/com.oracle.svm.reflect/src/com/oracle/svm/reflect/target/Target_sun_reflect_annotation_AnnotationParser.java @@ -40,7 +40,7 @@ import com.oracle.svm.core.code.CodeInfoTable; import com.oracle.svm.core.reflect.Target_jdk_internal_reflect_ConstantPool; import com.oracle.svm.core.util.VMError; -import com.oracle.svm.reflect.hosted.MethodMetadataEncoderImpl; +import com.oracle.svm.reflect.hosted.ReflectionMetadataEncoderImpl; import sun.reflect.annotation.AnnotationParser; import sun.reflect.annotation.AnnotationType; @@ -49,8 +49,8 @@ /** * Substitutions in this class are required to adapt the JDK encoding for annotations to our - * modified version of it. See {@link MethodMetadataEncoderImpl#encodeAnnotations(Annotation[])} for - * a description of the changes and the rationale behind them. + * modified version of it. See {@link ReflectionMetadataEncoderImpl#encodeAnnotations(Annotation[])} + * for a description of the changes and the rationale behind them. */ @TargetClass(AnnotationParser.class) public final class Target_sun_reflect_annotation_AnnotationParser {