From 501a82bc4bea6f958509ba52d6d4fdcb9d9618e6 Mon Sep 17 00:00:00 2001 From: Sacha Coppey Date: Mon, 6 Oct 2025 18:56:23 +0200 Subject: [PATCH 1/2] [GR-70562] Load instantiated subtypes of loaded base layer types, even if the type is already instantiated --- .../imagelayer/SVMImageLayerLoader.java | 43 +++++++++++-------- 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerLoader.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerLoader.java index 6edc749261b1..6296e92c97b9 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerLoader.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerLoader.java @@ -739,24 +739,29 @@ private void initializeBaseLayerTypeBeforePublishing(AnalysisType type, Persiste public void initializeBaseLayerType(AnalysisType type) { VMError.guarantee(type.isInBaseLayer()); PersistedAnalysisType.Reader td = findType(getBaseLayerTypeId(type)); - registerFlag(td.getIsInstantiated(), _ -> type.registerAsInstantiated(PERSISTED)); - registerFlag(td.getIsUnsafeAllocated(), _ -> type.registerAsUnsafeAllocated(PERSISTED)); - registerFlag(td.getIsReachable(), _ -> type.registerAsReachable(PERSISTED)); + postTask(td.getIsInstantiated(), _ -> type.registerAsInstantiated(PERSISTED)); + postTask(td.getIsUnsafeAllocated(), _ -> type.registerAsUnsafeAllocated(PERSISTED)); + postTask(td.getIsReachable(), _ -> type.registerAsReachable(PERSISTED)); - if (!td.getIsInstantiated() && td.getIsAnySubtypeInstantiated()) { + if (td.getIsAnySubtypeInstantiated()) { + /* + * Once a base layer type is loaded, loading all its instantiated subtypes ensures that + * the application layer typestate is coherent with the base layer typestate. Otherwise, + * unwanted optimizations could occur as the typestate would not contain some missed + * types from the base layer. + */ var subTypesReader = td.getSubTypes(); for (int i = 0; i < subTypesReader.size(); ++i) { int tid = subTypesReader.get(i); var subTypeReader = findType(tid); - if (subTypeReader.getIsInstantiated()) { - registerFlag(true, _ -> getAnalysisTypeForBaseLayerId(subTypeReader.getId())); - } + /* Only load instantiated subtypes. */ + postTask(subTypeReader.getIsInstantiated(), _ -> getAnalysisTypeForBaseLayerId(subTypeReader.getId())); } } } - private void registerFlag(boolean flag, DebugContextRunnable task) { - if (flag) { + private void postTask(boolean condition, DebugContextRunnable task) { + if (condition) { if (universe.getBigbang() != null) { universe.getBigbang().postTask(task); } else { @@ -1022,11 +1027,11 @@ public void addBaseLayerMethod(AnalysisMethod analysisMethod) { methods.putIfAbsent(analysisMethod.getId(), analysisMethod); PersistedAnalysisMethod.Reader md = getMethodData(analysisMethod); - registerFlag(md.getIsVirtualRootMethod(), _ -> analysisMethod.registerAsVirtualRootMethod(PERSISTED)); - registerFlag(md.getIsDirectRootMethod(), _ -> analysisMethod.registerAsDirectRootMethod(PERSISTED)); - registerFlag(md.getIsInvoked(), _ -> analysisMethod.registerAsInvoked(PERSISTED)); - registerFlag(md.getIsImplementationInvoked(), _ -> analysisMethod.registerAsImplementationInvoked(PERSISTED)); - registerFlag(md.getIsIntrinsicMethod(), _ -> analysisMethod.registerAsIntrinsicMethod(PERSISTED)); + postTask(md.getIsVirtualRootMethod(), _ -> analysisMethod.registerAsVirtualRootMethod(PERSISTED)); + postTask(md.getIsDirectRootMethod(), _ -> analysisMethod.registerAsDirectRootMethod(PERSISTED)); + postTask(md.getIsInvoked(), _ -> analysisMethod.registerAsInvoked(PERSISTED)); + postTask(md.getIsImplementationInvoked(), _ -> analysisMethod.registerAsImplementationInvoked(PERSISTED)); + postTask(md.getIsIntrinsicMethod(), _ -> analysisMethod.registerAsIntrinsicMethod(PERSISTED)); AnalysisMethod.CompilationBehavior compilationBehavior = AnalysisMethod.CompilationBehavior.values()[md.getCompilationBehaviorOrdinal()]; analysisMethod.setCompilationBehavior(compilationBehavior); @@ -1309,17 +1314,17 @@ public void initializeBaseLayerField(AnalysisField analysisField) { if (!analysisField.isStatic() && (isAccessed || isRead)) { analysisField.getDeclaringClass().getInstanceFields(true); } - registerFlag(isAccessed, _ -> { + postTask(isAccessed, _ -> { analysisField.injectDeclaredType(); analysisField.registerAsAccessed(PERSISTED); }); - registerFlag(isRead, _ -> analysisField.registerAsRead(PERSISTED)); - registerFlag(fieldData.getIsWritten(), _ -> { + postTask(isRead, _ -> analysisField.registerAsRead(PERSISTED)); + postTask(fieldData.getIsWritten(), _ -> { analysisField.injectDeclaredType(); analysisField.registerAsWritten(PERSISTED); }); - registerFlag(fieldData.getIsFolded(), _ -> analysisField.registerAsFolded(PERSISTED)); - registerFlag(fieldData.getIsUnsafeAccessed(), _ -> analysisField.registerAsUnsafeAccessed(PERSISTED)); + postTask(fieldData.getIsFolded(), _ -> analysisField.registerAsFolded(PERSISTED)); + postTask(fieldData.getIsUnsafeAccessed(), _ -> analysisField.registerAsUnsafeAccessed(PERSISTED)); /* * Inject the base layer position. If the position computed for this layer, either before From 76c571002ae34ebc1d84daaa53d61c2504037df7 Mon Sep 17 00:00:00 2001 From: Sacha Coppey Date: Tue, 7 Oct 2025 10:06:12 +0200 Subject: [PATCH 2/2] [GR-70350] Implement isClassInitializer for BaseLayerMethod --- .../src/com/oracle/graal/pointsto/meta/BaseLayerMethod.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/BaseLayerMethod.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/BaseLayerMethod.java index 2d32cc0189ab..8305ddbbccfc 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/BaseLayerMethod.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/BaseLayerMethod.java @@ -51,6 +51,8 @@ * method, using the information from the base layer. */ public class BaseLayerMethod extends BaseLayerElement implements ResolvedJavaMethod { + private static final String CLINIT = ""; + private final int id; private final ResolvedJavaType declaringClass; private final String name; @@ -153,7 +155,7 @@ public boolean isDeclared() { @Override public boolean isClassInitializer() { - throw unimplemented(); + return name.equals(CLINIT); } @Override