diff --git a/substratevm/src/com.oracle.svm.hosted/resources/SharedLayerSnapshotCapnProtoSchema.capnp b/substratevm/src/com.oracle.svm.hosted/resources/SharedLayerSnapshotCapnProtoSchema.capnp index c5adcbaa086d..4b3254f6e335 100644 --- a/substratevm/src/com.oracle.svm.hosted/resources/SharedLayerSnapshotCapnProtoSchema.capnp +++ b/substratevm/src/com.oracle.svm.hosted/resources/SharedLayerSnapshotCapnProtoSchema.capnp @@ -37,16 +37,18 @@ struct PersistedAnalysisType { annotationList @23 :List(Annotation); classInitializationInfo @24 :ClassInitializationInfo; hasArrayType @25 :Bool; + subTypes @26 :List(TypeId); + isAnySubtypeInstantiated @27 :Bool; wrappedType :union { - none @26 :Void; # default + none @28 :Void; # default serializationGenerated :group { - rawDeclaringClass @27 :Text; - rawTargetConstructor @28 :Text; + rawDeclaringClass @29 :Text; + rawTargetConstructor @30 :Text; } lambda :group { - capturingClass @29 :Text; + capturingClass @31 :Text; } - proxyType @30 :Void; + proxyType @32 :Void; } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java index fae47d9fe170..2cc5f0887877 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/NativeImageGenerator.java @@ -1025,7 +1025,7 @@ protected void setupNativeImage(String imageName, OptionValues options, Map baseLayerMethods = new ConcurrentHashMap<>(); private final Map baseLayerFields = new ConcurrentHashMap<>(); - protected final Set> heapScannerTasks = ConcurrentHashMap.newKeySet(); + protected final Set futureBigbangTasks = ConcurrentHashMap.newKeySet(); protected final Map typeToConstant = new ConcurrentHashMap<>(); protected final Map stringToConstant = new ConcurrentHashMap<>(); protected final Map, Integer> enumToConstant = new ConcurrentHashMap<>(); @@ -609,17 +610,28 @@ public void initializeBaseLayerType(AnalysisType type) { return; } PersistedAnalysisType.Reader td = findType(id); - registerFlag(td.getIsInstantiated(), () -> type.registerAsInstantiated(PERSISTED)); - registerFlag(td.getIsUnsafeAllocated(), () -> type.registerAsUnsafeAllocated(PERSISTED)); - registerFlag(td.getIsReachable(), () -> type.registerAsReachable(PERSISTED)); + registerFlag(td.getIsInstantiated(), debug -> type.registerAsInstantiated(PERSISTED)); + registerFlag(td.getIsUnsafeAllocated(), debug -> type.registerAsUnsafeAllocated(PERSISTED)); + registerFlag(td.getIsReachable(), debug -> type.registerAsReachable(PERSISTED)); + + if (!td.getIsInstantiated() && td.getIsAnySubtypeInstantiated()) { + 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, debug -> getAnalysisTypeForBaseLayerId(subTypeReader.getId())); + } + } + } } - private void registerFlag(boolean flag, Runnable runnable) { + private void registerFlag(boolean flag, DebugContextRunnable task) { if (flag) { if (universe.getBigbang() != null) { - universe.getBigbang().postTask(debug -> runnable.run()); + universe.getBigbang().postTask(task); } else { - heapScannerTasks.add(new AnalysisFuture<>(runnable)); + futureBigbangTasks.add(task); } } } @@ -806,11 +818,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)); + registerFlag(md.getIsVirtualRootMethod(), debug -> analysisMethod.registerAsVirtualRootMethod(PERSISTED)); + registerFlag(md.getIsDirectRootMethod(), debug -> analysisMethod.registerAsDirectRootMethod(PERSISTED)); + registerFlag(md.getIsInvoked(), debug -> analysisMethod.registerAsInvoked(PERSISTED)); + registerFlag(md.getIsImplementationInvoked(), debug -> analysisMethod.registerAsImplementationInvoked(PERSISTED)); + registerFlag(md.getIsIntrinsicMethod(), debug -> analysisMethod.registerAsIntrinsicMethod(PERSISTED)); } private PersistedAnalysisMethod.Reader getMethodData(AnalysisMethod analysisMethod) { @@ -1063,10 +1075,10 @@ public void initializeBaseLayerField(AnalysisField analysisField) { if (!analysisField.isStatic() && (isAccessed || isRead)) { analysisField.getDeclaringClass().getInstanceFields(true); } - registerFlag(isAccessed, () -> analysisField.registerAsAccessed(PERSISTED)); - registerFlag(isRead, () -> analysisField.registerAsRead(PERSISTED)); - registerFlag(fieldData.getIsWritten(), () -> analysisField.registerAsWritten(PERSISTED)); - registerFlag(fieldData.getIsFolded(), () -> analysisField.registerAsFolded(PERSISTED)); + registerFlag(isAccessed, debug -> analysisField.registerAsAccessed(PERSISTED)); + registerFlag(isRead, debug -> analysisField.registerAsRead(PERSISTED)); + registerFlag(fieldData.getIsWritten(), debug -> analysisField.registerAsWritten(PERSISTED)); + registerFlag(fieldData.getIsFolded(), debug -> analysisField.registerAsFolded(PERSISTED)); } private PersistedAnalysisField.Reader getFieldData(AnalysisField analysisField) { @@ -1094,10 +1106,11 @@ private PersistedAnalysisField.Reader getFieldData(AnalysisField analysisField) return null; } - public void executeHeapScannerTasks() { - guarantee(universe.getHeapScanner() != null, "Those tasks should only be executed when the bigbang is not null."); - for (AnalysisFuture task : heapScannerTasks) { - task.ensureDone(); + public void postFutureBigbangTasks() { + BigBang bigbang = universe.getBigbang(); + guarantee(bigbang != null, "Those tasks should only be executed when the bigbang is not null."); + for (DebugContextRunnable task : futureBigbangTasks) { + bigbang.postTask(task); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerWriter.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerWriter.java index fd6d4d46ad9c..f4e78cbee458 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerWriter.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SVMImageLayerWriter.java @@ -63,6 +63,7 @@ import java.util.function.IntFunction; import java.util.function.ObjIntConsumer; import java.util.function.Supplier; +import java.util.stream.Collectors; import java.util.stream.IntStream; import java.util.stream.Stream; @@ -93,6 +94,7 @@ import com.oracle.graal.pointsto.heap.ImageHeapPrimitiveArray; import com.oracle.graal.pointsto.heap.ImageHeapRelocatableConstant; import com.oracle.graal.pointsto.infrastructure.OriginalFieldProvider; +import com.oracle.graal.pointsto.meta.AnalysisElement; import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisMethod; import com.oracle.graal.pointsto.meta.AnalysisType; @@ -451,6 +453,15 @@ private void persistType(AnalysisType type, Supplier subTypes = type.getSubTypes().stream().filter(AnalysisElement::isTrackedAcrossLayers).collect(Collectors.toSet()); + var subTypesBuilder = builder.initSubTypes(subTypes.size()); + int i = 0; + for (AnalysisType subType : subTypes) { + subTypesBuilder.set(i, subType.getId()); + i++; + } + builder.setIsAnySubtypeInstantiated(type.isAnySubtypeInstantiated()); + afterTypeAdded(type); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SharedLayerSnapshotCapnProtoSchemaHolder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SharedLayerSnapshotCapnProtoSchemaHolder.java index 314092b6d105..bad7ea968423 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SharedLayerSnapshotCapnProtoSchemaHolder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/SharedLayerSnapshotCapnProtoSchemaHolder.java @@ -34,7 +34,7 @@ @SuppressWarnings("all") public final class SharedLayerSnapshotCapnProtoSchemaHolder { public static class PersistedAnalysisType { - public static final org.capnproto.StructSize STRUCT_SIZE = new org.capnproto.StructSize((short)4,(short)13); + public static final org.capnproto.StructSize STRUCT_SIZE = new org.capnproto.StructSize((short)4,(short)14); public static final class Factory extends org.capnproto.StructFactory { public Factory() { } @@ -307,13 +307,32 @@ public final void setHasArrayType(boolean value) { _setBooleanField(104, value); } + public final boolean hasSubTypes() { + return !_pointerFieldIsNull(11); + } + public final org.capnproto.PrimitiveList.Int.Builder getSubTypes() { + return _getPointerField(org.capnproto.PrimitiveList.Int.factory, 11, null, 0); + } + public final void setSubTypes(org.capnproto.PrimitiveList.Int.Reader value) { + _setPointerField(org.capnproto.PrimitiveList.Int.factory, 11, value); + } + public final org.capnproto.PrimitiveList.Int.Builder initSubTypes(int size) { + return _initPointerField(org.capnproto.PrimitiveList.Int.factory, 11, size); + } + public final boolean getIsAnySubtypeInstantiated() { + return _getBooleanField(105); + } + public final void setIsAnySubtypeInstantiated(boolean value) { + _setBooleanField(105, value); + } + public final WrappedType.Builder getWrappedType() { return new PersistedAnalysisType.WrappedType.Builder(segment, data, pointers, dataSize, pointerCount); } public final WrappedType.Builder initWrappedType() { _setShortField(7,(short)0); - _clearPointerField(11); _clearPointerField(12); + _clearPointerField(13); return new PersistedAnalysisType.WrappedType.Builder(segment, data, pointers, dataSize, pointerCount); } @@ -461,6 +480,17 @@ public final boolean getHasArrayType() { return _getBooleanField(104); } + public final boolean hasSubTypes() { + return !_pointerFieldIsNull(11); + } + public final org.capnproto.PrimitiveList.Int.Reader getSubTypes() { + return _getPointerField(org.capnproto.PrimitiveList.Int.factory, 11, null, 0); + } + + public final boolean getIsAnySubtypeInstantiated() { + return _getBooleanField(105); + } + public WrappedType.Reader getWrappedType() { return new PersistedAnalysisType.WrappedType.Reader(segment, data, pointers, dataSize, pointerCount, nestingLimit); } @@ -468,7 +498,7 @@ public WrappedType.Reader getWrappedType() { } public static class WrappedType { - public static final org.capnproto.StructSize STRUCT_SIZE = new org.capnproto.StructSize((short)4,(short)13); + public static final org.capnproto.StructSize STRUCT_SIZE = new org.capnproto.StructSize((short)4,(short)14); public static final class Factory extends org.capnproto.StructFactory { public Factory() { } @@ -524,8 +554,8 @@ public final SerializationGenerated.Builder getSerializationGenerated() { } public final SerializationGenerated.Builder initSerializationGenerated() { _setShortField(7, (short)PersistedAnalysisType.WrappedType.Which.SERIALIZATION_GENERATED.ordinal()); - _clearPointerField(11); _clearPointerField(12); + _clearPointerField(13); return new PersistedAnalysisType.WrappedType.SerializationGenerated.Builder(segment, data, pointers, dataSize, pointerCount); } @@ -537,7 +567,7 @@ public final Lambda.Builder getLambda() { } public final Lambda.Builder initLambda() { _setShortField(7, (short)PersistedAnalysisType.WrappedType.Which.LAMBDA.ordinal()); - _clearPointerField(11); + _clearPointerField(12); return new PersistedAnalysisType.WrappedType.Lambda.Builder(segment, data, pointers, dataSize, pointerCount); } @@ -611,7 +641,7 @@ public enum Which { _NOT_IN_SCHEMA, } public static class SerializationGenerated { - public static final org.capnproto.StructSize STRUCT_SIZE = new org.capnproto.StructSize((short)4,(short)13); + public static final org.capnproto.StructSize STRUCT_SIZE = new org.capnproto.StructSize((short)4,(short)14); public static final class Factory extends org.capnproto.StructFactory { public Factory() { } @@ -639,34 +669,34 @@ public final Reader asReader() { return new Reader(segment, data, pointers, dataSize, pointerCount, 0x7fffffff); } public final boolean hasRawDeclaringClass() { - return !_pointerFieldIsNull(11); + return !_pointerFieldIsNull(12); } public final org.capnproto.Text.Builder getRawDeclaringClass() { - return _getPointerField(org.capnproto.Text.factory, 11, null, 0, 0); + return _getPointerField(org.capnproto.Text.factory, 12, null, 0, 0); } public final void setRawDeclaringClass(org.capnproto.Text.Reader value) { - _setPointerField(org.capnproto.Text.factory, 11, value); + _setPointerField(org.capnproto.Text.factory, 12, value); } public final void setRawDeclaringClass(String value) { - _setPointerField(org.capnproto.Text.factory, 11, new org.capnproto.Text.Reader(value)); + _setPointerField(org.capnproto.Text.factory, 12, new org.capnproto.Text.Reader(value)); } public final org.capnproto.Text.Builder initRawDeclaringClass(int size) { - return _initPointerField(org.capnproto.Text.factory, 11, size); + return _initPointerField(org.capnproto.Text.factory, 12, size); } public final boolean hasRawTargetConstructor() { - return !_pointerFieldIsNull(12); + return !_pointerFieldIsNull(13); } public final org.capnproto.Text.Builder getRawTargetConstructor() { - return _getPointerField(org.capnproto.Text.factory, 12, null, 0, 0); + return _getPointerField(org.capnproto.Text.factory, 13, null, 0, 0); } public final void setRawTargetConstructor(org.capnproto.Text.Reader value) { - _setPointerField(org.capnproto.Text.factory, 12, value); + _setPointerField(org.capnproto.Text.factory, 13, value); } public final void setRawTargetConstructor(String value) { - _setPointerField(org.capnproto.Text.factory, 12, new org.capnproto.Text.Reader(value)); + _setPointerField(org.capnproto.Text.factory, 13, new org.capnproto.Text.Reader(value)); } public final org.capnproto.Text.Builder initRawTargetConstructor(int size) { - return _initPointerField(org.capnproto.Text.factory, 12, size); + return _initPointerField(org.capnproto.Text.factory, 13, size); } } @@ -676,17 +706,17 @@ public static final class Reader extends org.capnproto.StructReader { } public boolean hasRawDeclaringClass() { - return !_pointerFieldIsNull(11); + return !_pointerFieldIsNull(12); } public org.capnproto.Text.Reader getRawDeclaringClass() { - return _getPointerField(org.capnproto.Text.factory, 11, null, 0, 0); + return _getPointerField(org.capnproto.Text.factory, 12, null, 0, 0); } public boolean hasRawTargetConstructor() { - return !_pointerFieldIsNull(12); + return !_pointerFieldIsNull(13); } public org.capnproto.Text.Reader getRawTargetConstructor() { - return _getPointerField(org.capnproto.Text.factory, 12, null, 0, 0); + return _getPointerField(org.capnproto.Text.factory, 13, null, 0, 0); } } @@ -695,7 +725,7 @@ public org.capnproto.Text.Reader getRawTargetConstructor() { public static class Lambda { - public static final org.capnproto.StructSize STRUCT_SIZE = new org.capnproto.StructSize((short)4,(short)13); + public static final org.capnproto.StructSize STRUCT_SIZE = new org.capnproto.StructSize((short)4,(short)14); public static final class Factory extends org.capnproto.StructFactory { public Factory() { } @@ -723,19 +753,19 @@ public final Reader asReader() { return new Reader(segment, data, pointers, dataSize, pointerCount, 0x7fffffff); } public final boolean hasCapturingClass() { - return !_pointerFieldIsNull(11); + return !_pointerFieldIsNull(12); } public final org.capnproto.Text.Builder getCapturingClass() { - return _getPointerField(org.capnproto.Text.factory, 11, null, 0, 0); + return _getPointerField(org.capnproto.Text.factory, 12, null, 0, 0); } public final void setCapturingClass(org.capnproto.Text.Reader value) { - _setPointerField(org.capnproto.Text.factory, 11, value); + _setPointerField(org.capnproto.Text.factory, 12, value); } public final void setCapturingClass(String value) { - _setPointerField(org.capnproto.Text.factory, 11, new org.capnproto.Text.Reader(value)); + _setPointerField(org.capnproto.Text.factory, 12, new org.capnproto.Text.Reader(value)); } public final org.capnproto.Text.Builder initCapturingClass(int size) { - return _initPointerField(org.capnproto.Text.factory, 11, size); + return _initPointerField(org.capnproto.Text.factory, 12, size); } } @@ -745,10 +775,10 @@ public static final class Reader extends org.capnproto.StructReader { } public boolean hasCapturingClass() { - return !_pointerFieldIsNull(11); + return !_pointerFieldIsNull(12); } public org.capnproto.Text.Reader getCapturingClass() { - return _getPointerField(org.capnproto.Text.factory, 11, null, 0, 0); + return _getPointerField(org.capnproto.Text.factory, 12, null, 0, 0); } }