Skip to content

[GR-64703] Clear caches after analysis phase. #11177

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
May 13, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -159,25 +159,25 @@ public RuntimeMetadataEncoder create(SnippetReflectionProvider snippetReflection
private final CodeInfoEncoder.Encoders encoders;
private final ReflectionDataAccessors accessors;
private final ReflectionDataBuilder dataBuilder;
private final TreeSet<HostedType> sortedTypes = new TreeSet<>(Comparator.comparingLong(t -> t.getHub().getTypeID()));
private final Map<HostedType, ClassMetadata> classData = new HashMap<>();
private final Map<HostedType, Map<Object, FieldMetadata>> fieldData = new HashMap<>();
private final Map<HostedType, Map<Object, MethodMetadata>> methodData = new HashMap<>();
private final Map<HostedType, Map<Object, ConstructorMetadata>> constructorData = new HashMap<>();

private final Map<HostedType, Throwable> classLookupErrors = new HashMap<>();
private final Map<HostedType, Throwable> fieldLookupErrors = new HashMap<>();
private final Map<HostedType, Throwable> methodLookupErrors = new HashMap<>();
private final Map<HostedType, Throwable> constructorLookupErrors = new HashMap<>();
private final Map<HostedType, Throwable> recordComponentLookupErrors = new HashMap<>();

private final Set<AccessibleObjectMetadata> heapData = new HashSet<>();

private final Map<AccessibleObject, byte[]> annotationsEncodings = new HashMap<>();
private final Map<Executable, byte[]> parameterAnnotationsEncodings = new HashMap<>();
private final Map<Method, byte[]> annotationDefaultEncodings = new HashMap<>();
private final Map<AccessibleObject, byte[]> typeAnnotationsEncodings = new HashMap<>();
private final Map<Executable, byte[]> reflectParametersEncodings = new HashMap<>();
private TreeSet<HostedType> sortedTypes = new TreeSet<>(Comparator.comparingLong(t -> t.getHub().getTypeID()));
private Map<HostedType, ClassMetadata> classData = new HashMap<>();
private Map<HostedType, Map<Object, FieldMetadata>> fieldData = new HashMap<>();
private Map<HostedType, Map<Object, MethodMetadata>> methodData = new HashMap<>();
private Map<HostedType, Map<Object, ConstructorMetadata>> constructorData = new HashMap<>();

private Map<HostedType, Throwable> classLookupErrors = new HashMap<>();
private Map<HostedType, Throwable> fieldLookupErrors = new HashMap<>();
private Map<HostedType, Throwable> methodLookupErrors = new HashMap<>();
private Map<HostedType, Throwable> constructorLookupErrors = new HashMap<>();
private Map<HostedType, Throwable> recordComponentLookupErrors = new HashMap<>();

private Set<AccessibleObjectMetadata> heapData = new HashSet<>();

private Map<AccessibleObject, byte[]> annotationsEncodings = new HashMap<>();
private Map<Executable, byte[]> parameterAnnotationsEncodings = new HashMap<>();
private Map<Method, byte[]> annotationDefaultEncodings = new HashMap<>();
private Map<AccessibleObject, byte[]> typeAnnotationsEncodings = new HashMap<>();
private Map<Executable, byte[]> reflectParametersEncodings = new HashMap<>();

public RuntimeMetadataEncoderImpl(SnippetReflectionProvider snippetReflection, CodeInfoEncoder.Encoders encoders) {
this.snippetReflection = snippetReflection;
Expand Down Expand Up @@ -853,7 +853,35 @@ public void encodeAllAndInstall() {
}
install(buf);
/* Enable field recomputers in reflection objects to see the computed values */
ImageSingletons.add(EncodedRuntimeMetadataSupplier.class, this);
EncodedRuntimeMetadataSupplierImpl supplierImpl = new EncodedRuntimeMetadataSupplierImpl(annotationsEncodings, parameterAnnotationsEncodings, annotationDefaultEncodings,
typeAnnotationsEncodings, reflectParametersEncodings);
clearDataAfterEncoding();
ImageSingletons.add(EncodedRuntimeMetadataSupplier.class, supplierImpl);
}

/**
* After the buffer has been created and installed, all other data can be cleaned.
*/
private void clearDataAfterEncoding() {
this.annotationsEncodings = null;
this.parameterAnnotationsEncodings = null;
this.annotationDefaultEncodings = null;
this.typeAnnotationsEncodings = null;
this.reflectParametersEncodings = null;

this.sortedTypes = null;
this.classData = null;
this.fieldData = null;
this.methodData = null;
this.constructorData = null;

this.classLookupErrors = null;
this.fieldLookupErrors = null;
this.methodLookupErrors = null;
this.constructorLookupErrors = null;
this.recordComponentLookupErrors = null;

this.heapData = null;
}

private int encodeErrorIndex(Throwable error) {
Expand Down Expand Up @@ -1271,4 +1299,40 @@ public static Object createFromLoader(ImageSingletonLoader loader) {
return new LayeredRuntimeMetadataSingleton(registeredMethods, registeredFields);
}
}

/**
* Container for data required in later phases. Cleaner separation, rest of
* RuntimeMetadataEncoderImpl can be cleaned after encoding.
*/
public record EncodedRuntimeMetadataSupplierImpl(Map<AccessibleObject, byte[]> annotationsEncodings,
Map<Executable, byte[]> parameterAnnotationsEncodings,
Map<Method, byte[]> annotationDefaultEncodings,
Map<AccessibleObject, byte[]> typeAnnotationsEncodings,
Map<Executable, byte[]> reflectParametersEncodings) implements EncodedRuntimeMetadataSupplier {

@Override
public byte[] getAnnotationsEncoding(AccessibleObject object) {
return annotationsEncodings.get(object);
}

@Override
public byte[] getParameterAnnotationsEncoding(Executable object) {
return parameterAnnotationsEncodings.get(object);
}

@Override
public byte[] getAnnotationDefaultEncoding(Method object) {
return annotationDefaultEncodings.get(object);
}

@Override
public byte[] getTypeAnnotationsEncoding(AccessibleObject object) {
return typeAnnotationsEncodings.get(object);
}

@Override
public byte[] getReflectParametersEncoding(Executable object) {
return reflectParametersEncodings.get(object);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -95,8 +95,8 @@ public boolean handleInvoke(GraphBuilderContext b, ResolvedJavaMethod m, ValueNo
* that end up in the same class or in the JDK.
*/
EnumSwitchFeature feature = ImageSingletons.lookup(EnumSwitchFeature.class);
method.ensureGraphParsed(feature.bb);
Boolean methodSafeForExecution = feature.methodsSafeForExecution.get(method);
method.ensureGraphParsed(feature.getBigBang());
Boolean methodSafeForExecution = feature.isMethodsSafeForExecution(method);
assert methodSafeForExecution != null : "after-parsing hook not executed for method " + method.format("%H.%n(%p)");
if (!methodSafeForExecution.booleanValue()) {
return false;
Expand All @@ -121,9 +121,9 @@ public boolean handleInvoke(GraphBuilderContext b, ResolvedJavaMethod m, ValueNo
@AutomaticallyRegisteredFeature
final class EnumSwitchFeature implements InternalFeature {

BigBang bb;
private BigBang bb;

final ConcurrentMap<AnalysisMethod, Boolean> methodsSafeForExecution = new ConcurrentHashMap<>();
private ConcurrentMap<AnalysisMethod, Boolean> methodsSafeForExecution = new ConcurrentHashMap<>();

@Override
public void duringSetup(DuringSetupAccess a) {
Expand All @@ -142,10 +142,19 @@ private void onMethodParsed(AnalysisMethod method, StructuredGraph graph) {
@Override
public void afterAnalysis(AfterAnalysisAccess access) {
bb = null;
methodsSafeForExecution = null;
}

@Override
public void registerGraphBuilderPlugins(Providers providers, Plugins plugins, ParsingReason reason) {
plugins.appendNodePlugin(new EnumSwitchPlugin(reason));
}

Boolean isMethodsSafeForExecution(AnalysisMethod method) {
return methodsSafeForExecution.get(method);
}

public BigBang getBigBang() {
return bb;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,8 @@ public class ReflectionDataBuilder extends ConditionalConfigurationRegistry impl
private final Map<Class<?>, Throwable> recordComponentsLookupExceptions = new ConcurrentHashMap<>();

// Intermediate bookkeeping
private final Map<Type, Set<Integer>> processedTypes = new ConcurrentHashMap<>();
private final Map<Class<?>, Set<Method>> pendingRecordClasses;
private Map<Type, Set<Integer>> processedTypes = new ConcurrentHashMap<>();
private Map<Class<?>, Set<Method>> pendingRecordClasses;

record ConditionalTask(ConfigurationCondition condition, Consumer<ConfigurationCondition> task) {
}
Expand Down Expand Up @@ -1133,9 +1133,9 @@ private static void reportLinkingErrors(Class<?> clazz, List<Throwable> errors)

protected void afterAnalysis() {
sealed = true;
processedTypes.clear();
processedTypes = null;
if (!throwMissingRegistrationErrors()) {
pendingRecordClasses.clear();
pendingRecordClasses = null;
}
}

Expand Down