diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java index 2bddeef9d6ef..ade6b3c53d96 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/HeapImpl.java @@ -66,6 +66,7 @@ import com.oracle.svm.core.heap.RestrictHeapAccess; import com.oracle.svm.core.heap.RuntimeCodeInfoGCSupport; import com.oracle.svm.core.hub.DynamicHub; +import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.core.jdk.UninterruptibleUtils.AtomicReference; import com.oracle.svm.core.jfr.JfrTicks; import com.oracle.svm.core.jfr.events.SystemGCEvent; @@ -444,11 +445,8 @@ public int getImageHeapOffsetInAddressSpace() { */ imageHeapOffset = NumUtil.safeToInt(SerialAndEpsilonGCOptions.AlignedHeapChunkSize.getValue()); } - /* - * GR-53993: With ImageLayerSupport, it would be possible to fetch the startOffset from the - * loader instead of storing it in the Heap. - */ - if (SubstrateOptions.LoadImageLayer.hasBeenSet()) { + + if (ImageLayerBuildingSupport.buildingExtensionLayer()) { /* * GR-53964: The page size used to round up the start offset should be the same as the * one used in run time. diff --git a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxImageHeapProvider.java b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxImageHeapProvider.java index cb941c192b8b..f8daf0193386 100644 --- a/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxImageHeapProvider.java +++ b/substratevm/src/com.oracle.svm.core.posix/src/com/oracle/svm/core/posix/linux/LinuxImageHeapProvider.java @@ -31,20 +31,20 @@ import static com.oracle.svm.core.Isolates.IMAGE_HEAP_RELOCATABLE_END; import static com.oracle.svm.core.Isolates.IMAGE_HEAP_WRITABLE_BEGIN; import static com.oracle.svm.core.Isolates.IMAGE_HEAP_WRITABLE_END; -import static com.oracle.svm.core.layeredimage.LayeredImageHeapSymbols.SECOND_IMAGE_HEAP_A_RELOCATABLE_POINTER; -import static com.oracle.svm.core.layeredimage.LayeredImageHeapSymbols.SECOND_IMAGE_HEAP_BEGIN; -import static com.oracle.svm.core.layeredimage.LayeredImageHeapSymbols.SECOND_IMAGE_HEAP_END; -import static com.oracle.svm.core.layeredimage.LayeredImageHeapSymbols.SECOND_IMAGE_HEAP_RELOCATABLE_BEGIN; -import static com.oracle.svm.core.layeredimage.LayeredImageHeapSymbols.SECOND_IMAGE_HEAP_RELOCATABLE_END; -import static com.oracle.svm.core.layeredimage.LayeredImageHeapSymbols.SECOND_IMAGE_HEAP_WRITABLE_BEGIN; -import static com.oracle.svm.core.layeredimage.LayeredImageHeapSymbols.SECOND_IMAGE_HEAP_WRITABLE_END; +import static com.oracle.svm.core.imagelayer.ImageLayerSection.SectionEntries.HEAP_ANY_RELOCATABLE_POINTER; +import static com.oracle.svm.core.imagelayer.ImageLayerSection.SectionEntries.HEAP_BEGIN; +import static com.oracle.svm.core.imagelayer.ImageLayerSection.SectionEntries.HEAP_END; +import static com.oracle.svm.core.imagelayer.ImageLayerSection.SectionEntries.HEAP_RELOCATABLE_BEGIN; +import static com.oracle.svm.core.imagelayer.ImageLayerSection.SectionEntries.HEAP_RELOCATABLE_END; +import static com.oracle.svm.core.imagelayer.ImageLayerSection.SectionEntries.HEAP_WRITEABLE_BEGIN; +import static com.oracle.svm.core.imagelayer.ImageLayerSection.SectionEntries.HEAP_WRITEABLE_END; +import static com.oracle.svm.core.imagelayer.ImageLayerSection.SectionEntries.NEXT_SECTION; import static com.oracle.svm.core.posix.linux.ProcFSSupport.findMapping; import static com.oracle.svm.core.util.PointerUtils.roundDown; import static com.oracle.svm.core.util.UnsignedUtils.isAMultiple; import static com.oracle.svm.core.util.UnsignedUtils.roundUp; import static org.graalvm.word.WordFactory.signed; -import java.nio.ByteBuffer; import java.util.concurrent.ThreadLocalRandom; import org.graalvm.nativeimage.StackValue; @@ -56,10 +56,8 @@ import org.graalvm.word.PointerBase; import org.graalvm.word.SignedWord; import org.graalvm.word.UnsignedWord; -import org.graalvm.word.WordBase; import org.graalvm.word.WordFactory; -import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.c.CGlobalData; import com.oracle.svm.core.c.CGlobalDataFactory; @@ -68,6 +66,8 @@ import com.oracle.svm.core.config.ConfigurationValues; import com.oracle.svm.core.headers.LibC; import com.oracle.svm.core.heap.Heap; +import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; +import com.oracle.svm.core.imagelayer.ImageLayerSection; import com.oracle.svm.core.os.AbstractImageHeapProvider; import com.oracle.svm.core.os.VirtualMemoryProvider; import com.oracle.svm.core.os.VirtualMemoryProvider.Access; @@ -79,7 +79,6 @@ import com.oracle.svm.core.util.VMError; import jdk.graal.compiler.word.Word; -import jdk.vm.ci.code.Architecture; /** * An optimal image heap provider for Linux which creates isolate image heaps that retain the @@ -104,40 +103,97 @@ public class LinuxImageHeapProvider extends AbstractImageHeapProvider { private static final SignedWord UNASSIGNED_FD = signed(-1); private static final SignedWord CANNOT_OPEN_FD = signed(-2); - private static final int IMAGE_COUNT = 2; - private static final CGlobalData CACHED_IMAGE_FDS = CGlobalDataFactory.createBytes(() -> createWords(IMAGE_COUNT, UNASSIGNED_FD)); - private static final CGlobalData CACHED_IMAGE_HEAP_OFFSETS = CGlobalDataFactory.createBytes(() -> createWords(IMAGE_COUNT, WordFactory.zero())); + private static final CGlobalData CACHED_IMAGE_FDS = CGlobalDataFactory.createWord(UNASSIGNED_FD); + private static final CGlobalData CACHED_IMAGE_HEAP_OFFSETS = CGlobalDataFactory.createWord(); private static final int MAX_PATHLEN = 4096; - private static byte[] createWords(int count, WordBase initialValue) { - Architecture arch = ConfigurationValues.getTarget().arch; - assert arch.getWordSize() == Long.BYTES : "currently hard-coded for 8 byte words"; - ByteBuffer buffer = ByteBuffer.allocate(count * Long.BYTES).order(arch.getByteOrder()); - for (int i = 0; i < count; i++) { - buffer.putLong(initialValue.rawValue()); + /** + * Used for caching heap address space size when using layered images. Within layered images + * calculating this value requires iterating through multiple sections. + */ + static final CGlobalData CACHED_LAYERED_IMAGE_HEAP_ADDRESS_SPACE_SIZE = CGlobalDataFactory.createWord(); + + @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) + private static UnsignedWord getLayeredImageHeapAddressSpaceSize() { + // check if value is cached + Word currentValue = CACHED_LAYERED_IMAGE_HEAP_ADDRESS_SPACE_SIZE.get().read(); + if (currentValue.isNonNull()) { + return currentValue; } - return buffer.array(); + int imageHeapOffset = Heap.getHeap().getImageHeapOffsetInAddressSpace(); + assert imageHeapOffset >= 0; + UnsignedWord size = WordFactory.unsigned(imageHeapOffset); + UnsignedWord granularity = VirtualMemoryProvider.get().getGranularity(); + assert isAMultiple(size, granularity); + + /* + * Walk through the sections and add up the layer image heap sizes. + */ + + Pointer currentSection = ImageLayerSection.getInitialLayerSection().get(); + while (currentSection.isNonNull()) { + Word heapBegin = currentSection.readWord(ImageLayerSection.getEntryOffset(HEAP_BEGIN)); + Word heapEnd = currentSection.readWord(ImageLayerSection.getEntryOffset(HEAP_END)); + size = size.add(getImageHeapSizeInFile(heapBegin, heapEnd)); + size = roundUp(size, granularity); + currentSection = currentSection.readWord(ImageLayerSection.getEntryOffset(NEXT_SECTION)); + } + + // cache the value + CACHED_LAYERED_IMAGE_HEAP_ADDRESS_SPACE_SIZE.get().write(size); + return size; } @Override @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) protected UnsignedWord getImageHeapAddressSpaceSize() { - if (SubstrateOptions.ImageLayer.hasBeenSet() || SubstrateOptions.LoadImageLayer.hasBeenSet()) { - int imageHeapOffset = Heap.getHeap().getImageHeapOffsetInAddressSpace(); - assert imageHeapOffset >= 0; - UnsignedWord size = WordFactory.unsigned(imageHeapOffset); - UnsignedWord granularity = VirtualMemoryProvider.get().getGranularity(); - assert isAMultiple(size, granularity); - size = size.add(getImageHeapSizeInFile(IMAGE_HEAP_BEGIN.get(), IMAGE_HEAP_END.get())); - size = roundUp(size, granularity); - size = size.add(getImageHeapSizeInFile(SECOND_IMAGE_HEAP_BEGIN.get(), SECOND_IMAGE_HEAP_END.get())); - return size; + if (ImageLayerBuildingSupport.buildingImageLayer()) { + return getLayeredImageHeapAddressSpaceSize(); } else { return super.getImageHeapAddressSpaceSize(); } } + @Uninterruptible(reason = "Called during isolate initialization.") + protected int initializeLayeredImage(Pointer firstHeapStart, Pointer selfReservedHeapBase, UnsignedWord initialRemainingSize, WordPointer endPointer) { + int result = -1; + UnsignedWord remainingSize = initialRemainingSize; + + int layerCount = 0; + Pointer currentSection = ImageLayerSection.getInitialLayerSection().get(); + Pointer currentHeapStart = firstHeapStart; + while (currentSection.isNonNull()) { + var cachedFDPointer = ImageLayerSection.getCachedImageFDs().get().addressOf(layerCount); + var cachedOffsetsPointer = ImageLayerSection.getCachedImageHeapOffsets().get().addressOf(layerCount); + Word heapBegin = currentSection.readWord(ImageLayerSection.getEntryOffset(HEAP_BEGIN)); + Word heapEnd = currentSection.readWord(ImageLayerSection.getEntryOffset(HEAP_END)); + Word heapRelocBegin = currentSection.readWord(ImageLayerSection.getEntryOffset(HEAP_RELOCATABLE_BEGIN)); + Word heapRelocEnd = currentSection.readWord(ImageLayerSection.getEntryOffset(HEAP_RELOCATABLE_END)); + Word heapAnyRelocPointer = currentSection.readWord(ImageLayerSection.getEntryOffset(HEAP_ANY_RELOCATABLE_POINTER)); + Word heapWritableBegin = currentSection.readWord(ImageLayerSection.getEntryOffset(HEAP_WRITEABLE_BEGIN)); + Word heapWritableEnd = currentSection.readWord(ImageLayerSection.getEntryOffset(HEAP_WRITEABLE_END)); + + result = initializeImageHeap(currentHeapStart, remainingSize, endPointer, + cachedFDPointer, cachedOffsetsPointer, MAGIC.get(), + heapBegin, heapEnd, + heapRelocBegin, heapAnyRelocPointer, heapRelocEnd, + heapWritableBegin, heapWritableEnd); + if (result != CEntryPointErrors.NO_ERROR) { + freeImageHeap(selfReservedHeapBase); + return result; + } + Pointer newHeapStart = endPointer.read(); // aligned + remainingSize = remainingSize.subtract(newHeapStart.subtract(currentHeapStart)); + currentHeapStart = newHeapStart; + + // read the next layer + currentSection = currentSection.readWord(ImageLayerSection.getEntryOffset(NEXT_SECTION)); + layerCount++; + } + return result; + } + @Override @Uninterruptible(reason = "Called during isolate initialization.") public int initialize(Pointer reservedAddressSpace, UnsignedWord reservedSize, WordPointer basePointer, WordPointer endPointer) { @@ -185,32 +241,21 @@ public int initialize(Pointer reservedAddressSpace, UnsignedWord reservedSize, W int imageHeapOffsetInAddressSpace = Heap.getHeap().getImageHeapOffsetInAddressSpace(); basePointer.write(heapBase); - Pointer firstHeapStart = heapBase.add(imageHeapOffsetInAddressSpace); + Pointer imageHeapStart = heapBase.add(imageHeapOffsetInAddressSpace); remainingSize = remainingSize.subtract(imageHeapOffsetInAddressSpace); - boolean layeredImage = SubstrateOptions.ImageLayer.hasBeenSet() || SubstrateOptions.LoadImageLayer.hasBeenSet(); - WordPointer firstEndPtr = layeredImage ? StackValue.get(WordPointer.class) : endPointer; - int result = initializeImageHeap(firstHeapStart, remainingSize, firstEndPtr, - CACHED_IMAGE_FDS.get().addressOf(0), CACHED_IMAGE_HEAP_OFFSETS.get().addressOf(0), MAGIC.get(), - IMAGE_HEAP_BEGIN.get(), IMAGE_HEAP_END.get(), - IMAGE_HEAP_RELOCATABLE_BEGIN.get(), IMAGE_HEAP_A_RELOCATABLE_POINTER.get(), IMAGE_HEAP_RELOCATABLE_END.get(), - IMAGE_HEAP_WRITABLE_BEGIN.get(), IMAGE_HEAP_WRITABLE_END.get()); - if (result != CEntryPointErrors.NO_ERROR) { - freeImageHeap(selfReservedHeapBase); - return result; - } - if (SubstrateOptions.ImageLayer.hasBeenSet() || SubstrateOptions.LoadImageLayer.hasBeenSet()) { - Pointer secondHeapStart = firstEndPtr.read(); // aligned - remainingSize = remainingSize.subtract(secondHeapStart.subtract(firstHeapStart)); - result = initializeImageHeap(secondHeapStart, remainingSize, endPointer, - CACHED_IMAGE_FDS.get().addressOf(1), CACHED_IMAGE_HEAP_OFFSETS.get().addressOf(1), MAGIC.get(), - SECOND_IMAGE_HEAP_BEGIN.get(), SECOND_IMAGE_HEAP_END.get(), - SECOND_IMAGE_HEAP_RELOCATABLE_BEGIN.get(), SECOND_IMAGE_HEAP_A_RELOCATABLE_POINTER.get(), SECOND_IMAGE_HEAP_RELOCATABLE_END.get(), - SECOND_IMAGE_HEAP_WRITABLE_BEGIN.get(), SECOND_IMAGE_HEAP_WRITABLE_END.get()); + if (!ImageLayerBuildingSupport.buildingImageLayer()) { + int result = initializeImageHeap(imageHeapStart, remainingSize, endPointer, + CACHED_IMAGE_FDS.get(), CACHED_IMAGE_HEAP_OFFSETS.get(), MAGIC.get(), + IMAGE_HEAP_BEGIN.get(), IMAGE_HEAP_END.get(), + IMAGE_HEAP_RELOCATABLE_BEGIN.get(), IMAGE_HEAP_A_RELOCATABLE_POINTER.get(), IMAGE_HEAP_RELOCATABLE_END.get(), + IMAGE_HEAP_WRITABLE_BEGIN.get(), IMAGE_HEAP_WRITABLE_END.get()); if (result != CEntryPointErrors.NO_ERROR) { freeImageHeap(selfReservedHeapBase); } + return result; + } else { + return initializeLayeredImage(imageHeapStart, selfReservedHeapBase, remainingSize, endPointer); } - return result; } @Uninterruptible(reason = "Called during isolate initialization.") diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java index ee95439f2a0d..b556c679a058 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/SubstrateOptions.java @@ -110,8 +110,6 @@ public class SubstrateOptions { protected void onValueUpdate(EconomicMap, Object> values, Boolean oldValue, Boolean newValue) { LayeredBaseImageAnalysis.update(values, newValue); ClosedTypeWorld.update(values, !newValue); - PersistImageLayerAnalysis.update(values, newValue); - PersistImageLayerSingletons.update(values, newValue); StripDebugInfo.update(values, !newValue); AOTTrivialInline.update(values, !newValue); if (imageLayerEnabledHandler != null) { @@ -1124,12 +1122,6 @@ public static boolean closedTypeWorld() { return ClosedTypeWorld.getValue(); } - @Option(help = "Persist the image heap and the AnalysisUniverse (types, methods and fields) of the current build", type = OptionType.Debug) // - public static final HostedOptionKey PersistImageLayerAnalysis = new HostedOptionKey<>(false); - - @Option(help = "Persist the layered image singletons of the current build", type = OptionType.Debug) // - public static final HostedOptionKey PersistImageLayerSingletons = new HostedOptionKey<>(false); - @Option(help = "Throws an exception on potential type conflict during heap persisting if enabled", type = OptionType.Debug) // public static final HostedOptionKey AbortOnNameConflict = new HostedOptionKey<>(false); @@ -1149,12 +1141,6 @@ public void update(EconomicMap, Object> values, Object boxedValue) } }; - @Option(help = "Load the image heap and the AnalysisUniverse into the current build", type = OptionType.Debug) // - public static final HostedOptionKey LoadImageLayerAnalysis = new HostedOptionKey<>(true); - - @Option(help = "Load the layered image singleton information into the current build", type = OptionType.Debug) // - public static final HostedOptionKey LoadImageLayerSingletons = new HostedOptionKey<>(true); - public static class TruffleStableOptions { @Option(help = "Automatically copy the necessary language resources to the resources/languages directory next to the produced image." + diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/imagelayer/BuildingImageLayerPredicate.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/imagelayer/BuildingImageLayerPredicate.java new file mode 100644 index 000000000000..cd4d5f956a03 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/imagelayer/BuildingImageLayerPredicate.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2024, 2024, 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.core.imagelayer; + +import org.graalvm.nativeimage.Platform; +import org.graalvm.nativeimage.Platforms; + +import java.util.function.BooleanSupplier; + +@Platforms(Platform.HOSTED_ONLY.class) +public class BuildingImageLayerPredicate implements BooleanSupplier { + @Override + public boolean getAsBoolean() { + return ImageLayerBuildingSupport.buildingImageLayer(); + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/imagelayer/DynamicImageLayerInfo.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/imagelayer/DynamicImageLayerInfo.java new file mode 100644 index 000000000000..d1aa523c3eff --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/imagelayer/DynamicImageLayerInfo.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2024, 2024, 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.core.imagelayer; + +import java.util.EnumSet; + +import org.graalvm.nativeimage.ImageSingletons; + +import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; +import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; +import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; + +@AutomaticallyRegisteredImageSingleton(onlyWith = BuildingImageLayerPredicate.class) +public class DynamicImageLayerInfo implements LayeredImageSingleton { + public final int layerNumber; + public final int nextLayerNumber; + public final int numLayers; + + public DynamicImageLayerInfo() { + this(0); + } + + private DynamicImageLayerInfo(int layerNumber) { + this.layerNumber = layerNumber; + this.nextLayerNumber = layerNumber + 1; + this.numLayers = nextLayerNumber; + } + + public static DynamicImageLayerInfo singleton() { + return ImageSingletons.lookup(DynamicImageLayerInfo.class); + } + + @Override + public EnumSet getImageBuilderFlags() { + return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; + } + + @Override + public PersistFlags preparePersist(ImageSingletonWriter writer) { + writer.writeInt("nextLayerNumber", nextLayerNumber); + return PersistFlags.CREATE; + } + + @SuppressWarnings("unused") + public static Object createFromLoader(ImageSingletonLoader loader) { + return new DynamicImageLayerInfo(loader.readInt("nextLayerNumber")); + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/imagelayer/ImageLayerBuildingSupport.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/imagelayer/ImageLayerBuildingSupport.java new file mode 100644 index 000000000000..f720002043a5 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/imagelayer/ImageLayerBuildingSupport.java @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2024, 2024, 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.core.imagelayer; + +import java.util.EnumSet; + +import org.graalvm.nativeimage.ImageSingletons; + +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton; + +import jdk.graal.compiler.api.replacements.Fold; + +/** + * Support for tracking the image layer stage of this native-image build. When image layers are + * used, executing a native-image will require multiple object files produced by different native + * image builds to be linked and loaded. The "application layer" will be the final layer and will + * depend on one or more "shared layer"s. Given the layer layout below, we classify the layers as + * follows: + *
    + *
  • ImageLayers: A,B,C,D
  • + *
  • InitialLayer: A
  • + *
  • ApplicationLayer: D
  • + *
  • ExtensionLayers: B,C,D
  • + *
  • SharedLayers: A,B,C
  • + *
+ * + *
+ *     |------------------------|
+ *     | (A) Initial Layer      |
+ *     |------------------------|
+ *     | (B) Intermediate Layer |
+ *     |------------------------|
+ *     | (C) Intermediate Layer |
+ *     |------------------------|
+ *     | (D) Application Layer  |
+ *     |------------------------|
+ * 
+ */ +public abstract class ImageLayerBuildingSupport implements UnsavedSingleton { + protected final boolean buildingImageLayer; + private final boolean buildingInitialLayer; + private final boolean buildingApplicationLayer; + + protected ImageLayerBuildingSupport(boolean buildingImageLayer, boolean buildingInitialLayer, boolean buildingApplicationLayer) { + this.buildingImageLayer = buildingImageLayer; + this.buildingInitialLayer = buildingInitialLayer; + this.buildingApplicationLayer = buildingApplicationLayer; + } + + private static ImageLayerBuildingSupport singleton() { + return ImageSingletons.lookup(ImageLayerBuildingSupport.class); + } + + @Fold + public static boolean buildingImageLayer() { + return singleton().buildingImageLayer; + } + + @Fold + public static boolean buildingInitialLayer() { + return singleton().buildingInitialLayer; + } + + @Fold + public static boolean buildingApplicationLayer() { + return singleton().buildingApplicationLayer; + } + + @Fold + public static boolean buildingExtensionLayer() { + return singleton().buildingImageLayer && !singleton().buildingInitialLayer; + } + + @Fold + public static boolean buildingSharedLayer() { + return singleton().buildingImageLayer && !singleton().buildingApplicationLayer; + } + + @Override + public final EnumSet getImageBuilderFlags() { + return LayeredImageSingletonBuilderFlags.ALL_ACCESS_ALLOW_FOLDING; + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/imagelayer/ImageLayerSection.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/imagelayer/ImageLayerSection.java new file mode 100644 index 000000000000..684c9960c412 --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/imagelayer/ImageLayerSection.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2024, 2024, 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.core.imagelayer; + +import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.c.type.WordPointer; +import org.graalvm.word.Pointer; + +import com.oracle.svm.core.c.CGlobalData; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; + +import jdk.graal.compiler.api.replacements.Fold; + +public abstract class ImageLayerSection implements LayeredImageSingleton { + + protected final CGlobalData initialSectionStart; + protected final CGlobalData cachedImageFDs; + protected final CGlobalData cachedImageHeapOffsets; + + protected ImageLayerSection(CGlobalData initialSectionStart, CGlobalData cachedImageFDs, CGlobalData cachedImageHeapOffsets) { + this.initialSectionStart = initialSectionStart; + this.cachedImageFDs = cachedImageFDs; + this.cachedImageHeapOffsets = cachedImageHeapOffsets; + } + + public enum SectionEntries { + HEAP_BEGIN, + HEAP_END, + HEAP_RELOCATABLE_BEGIN, + HEAP_RELOCATABLE_END, + HEAP_ANY_RELOCATABLE_POINTER, + HEAP_WRITEABLE_BEGIN, + HEAP_WRITEABLE_END, + NEXT_SECTION + } + + private static ImageLayerSection singleton() { + return ImageSingletons.lookup(ImageLayerSection.class); + } + + @Fold + public static int getEntryOffset(SectionEntries entry) { + return singleton().getEntryOffsetInternal(entry); + } + + @Fold + public static CGlobalData getInitialLayerSection() { + return singleton().initialSectionStart; + } + + @Fold + public static CGlobalData getCachedImageFDs() { + return singleton().cachedImageFDs; + } + + @Fold + public static CGlobalData getCachedImageHeapOffsets() { + return singleton().cachedImageHeapOffsets; + } + + protected abstract int getEntryOffsetInternal(SectionEntries entry); + +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimage/LayeredImageHeapSymbols.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimage/LayeredImageHeapSymbols.java deleted file mode 100644 index 165fe15c8303..000000000000 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimage/LayeredImageHeapSymbols.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (c) 2024, 2024, 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.core.layeredimage; - -import com.oracle.svm.core.c.CGlobalData; -import com.oracle.svm.core.c.CGlobalDataFactory; - -import jdk.graal.compiler.word.Word; - -/** - * Stores the heap symbols for the application layer. This is a temporary solution and should be - * fixed with GR-53995. - */ -public class LayeredImageHeapSymbols { - public static final String SECOND_IMAGE_HEAP_BEGIN_SYMBOL_NAME = "__svm_second_heap_begin"; - public static final String SECOND_IMAGE_HEAP_END_SYMBOL_NAME = "__svm_second_heap_end"; - public static final String SECOND_IMAGE_HEAP_RELOCATABLE_BEGIN_SYMBOL_NAME = "__svm_second_heap_relocatable_begin"; - public static final String SECOND_IMAGE_HEAP_RELOCATABLE_END_SYMBOL_NAME = "__svm_second_heap_relocatable_end"; - public static final String SECOND_IMAGE_HEAP_A_RELOCATABLE_POINTER_SYMBOL_NAME = "__svm_second_heap_a_relocatable_pointer"; - public static final String SECOND_IMAGE_HEAP_WRITABLE_BEGIN_SYMBOL_NAME = "__svm_second_heap_writable_begin"; - public static final String SECOND_IMAGE_HEAP_WRITABLE_END_SYMBOL_NAME = "__svm_second_heap_writable_end"; - - public static final CGlobalData SECOND_IMAGE_HEAP_BEGIN = CGlobalDataFactory.forSymbol(SECOND_IMAGE_HEAP_BEGIN_SYMBOL_NAME); - public static final CGlobalData SECOND_IMAGE_HEAP_END = CGlobalDataFactory.forSymbol(SECOND_IMAGE_HEAP_END_SYMBOL_NAME); - public static final CGlobalData SECOND_IMAGE_HEAP_RELOCATABLE_BEGIN = CGlobalDataFactory.forSymbol(SECOND_IMAGE_HEAP_RELOCATABLE_BEGIN_SYMBOL_NAME); - public static final CGlobalData SECOND_IMAGE_HEAP_RELOCATABLE_END = CGlobalDataFactory.forSymbol(SECOND_IMAGE_HEAP_RELOCATABLE_END_SYMBOL_NAME); - public static final CGlobalData SECOND_IMAGE_HEAP_A_RELOCATABLE_POINTER = CGlobalDataFactory.forSymbol(SECOND_IMAGE_HEAP_A_RELOCATABLE_POINTER_SYMBOL_NAME); - public static final CGlobalData SECOND_IMAGE_HEAP_WRITABLE_BEGIN = CGlobalDataFactory.forSymbol(SECOND_IMAGE_HEAP_WRITABLE_BEGIN_SYMBOL_NAME); - public static final CGlobalData SECOND_IMAGE_HEAP_WRITABLE_END = CGlobalDataFactory.forSymbol(SECOND_IMAGE_HEAP_WRITABLE_END_SYMBOL_NAME); -} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/FeatureSingleton.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/FeatureSingleton.java index ac189a5a4597..99ee84654129 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/FeatureSingleton.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/FeatureSingleton.java @@ -32,7 +32,7 @@ public interface FeatureSingleton extends LayeredImageSingleton { @Override - default EnumSet getImageBuilderFlags() { - return EnumSet.of(ImageBuilderFlags.BUILDTIME_ACCESS); + default EnumSet getImageBuilderFlags() { + return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/LayeredImageSingleton.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/LayeredImageSingleton.java index 3fd99e1c5166..54e444d96185 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/LayeredImageSingleton.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/LayeredImageSingleton.java @@ -46,52 +46,7 @@ enum PersistFlags { CREATE } - enum ImageBuilderFlags { - /** - * This singleton can be accessed from the runtime. - */ - RUNTIME_ACCESS, - /** - * This singleton can be accessed from the buildtime. - */ - BUILDTIME_ACCESS, - /** - * This singleton should not have been created. Throw error if it is created. - */ - UNSUPPORTED, - /** - * This singleton should only be created in the initial layer. - */ - INITIAL_LAYER_ONLY, - /** - * Allow the singleton to be constant-folded within the generated code. - */ - ALLOW_CONSTANT_FOLDING, - /** - * Prevent the singleton to be constant-folded within the generated code. - */ - PREVENT_CONSTANT_FOLDING - } - - default boolean verifyImageBuilderFlags() { - EnumSet flags = getImageBuilderFlags(); - - if (flags.contains(ImageBuilderFlags.UNSUPPORTED)) { - assert flags.equals(EnumSet.of(ImageBuilderFlags.UNSUPPORTED)) : "Unsupported should be the only flag set " + flags; - } - - if (flags.contains(ImageBuilderFlags.RUNTIME_ACCESS)) { - assert !flags.containsAll(EnumSet.of(ImageBuilderFlags.PREVENT_CONSTANT_FOLDING, ImageBuilderFlags.ALLOW_CONSTANT_FOLDING)) : String.format("Must set one of %s or %s. flags: %s", - ImageBuilderFlags.PREVENT_CONSTANT_FOLDING, ImageBuilderFlags.ALLOW_CONSTANT_FOLDING, flags); - assert flags.contains(ImageBuilderFlags.PREVENT_CONSTANT_FOLDING) || flags.contains(ImageBuilderFlags.ALLOW_CONSTANT_FOLDING) : String.format("Must set one of %s or %s. flags: %s", - ImageBuilderFlags.PREVENT_CONSTANT_FOLDING, ImageBuilderFlags.ALLOW_CONSTANT_FOLDING, flags); - - } - - return true; - } - - EnumSet getImageBuilderFlags(); + EnumSet getImageBuilderFlags(); PersistFlags preparePersist(ImageSingletonWriter writer); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/LayeredImageSingletonBuilderFlags.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/LayeredImageSingletonBuilderFlags.java new file mode 100644 index 000000000000..bceeda445b3b --- /dev/null +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/LayeredImageSingletonBuilderFlags.java @@ -0,0 +1,95 @@ +/* + * Copyright (c) 2024, 2024, 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.core.layeredimagesingleton; + +import java.util.EnumSet; + +/** + * Flags used during build time to determine how the native image generator handles the layered + * image singleton. + */ +public enum LayeredImageSingletonBuilderFlags { + /** + * This singleton can be accessed from the runtime. + */ + RUNTIME_ACCESS, + /** + * This singleton can be accessed from the buildtime. + */ + BUILDTIME_ACCESS, + /** + * This singleton should not have been created. Throw error if it is created. + */ + UNSUPPORTED, + /** + * This singleton should only be created in the initial layer. + */ + INITIAL_LAYER_ONLY, + /** + * Allow the singleton to be constant-folded within the generated code. + */ + ALLOW_CONSTANT_FOLDING, + /** + * Prevent the singleton to be constant-folded within the generated code. + */ + PREVENT_CONSTANT_FOLDING; + + /* + * Below are some common flag patterns. + */ + + public static final EnumSet BUILDTIME_ACCESS_ONLY = EnumSet.of(BUILDTIME_ACCESS); + + public static final EnumSet RUNTIME_ACCESS_ONLY_ALLOW_FOLDING = EnumSet.of(RUNTIME_ACCESS, + ALLOW_CONSTANT_FOLDING); + + public static final EnumSet ALL_ACCESS_ALLOW_FOLDING = EnumSet.of(RUNTIME_ACCESS, + BUILDTIME_ACCESS, ALLOW_CONSTANT_FOLDING); + + public static boolean verifyImageBuilderFlags(LayeredImageSingleton singleton) { + EnumSet flags = singleton.getImageBuilderFlags(); + + if (!(flags.contains(UNSUPPORTED) || flags.contains(BUILDTIME_ACCESS) || flags.contains(RUNTIME_ACCESS))) { + assert false : String.format("At least one of the following flags must be set: %s, %s, %s", UNSUPPORTED, BUILDTIME_ACCESS, RUNTIME_ACCESS); + } + + if (flags.contains(UNSUPPORTED)) { + assert flags.equals(EnumSet.of(UNSUPPORTED)) : "Unsupported should be the only flag set " + flags; + } + + if (flags.contains(RUNTIME_ACCESS)) { + assert !flags.containsAll(EnumSet.of(PREVENT_CONSTANT_FOLDING, ALLOW_CONSTANT_FOLDING)) : String.format("Must set one of %s or %s. flags: %s", PREVENT_CONSTANT_FOLDING, + ALLOW_CONSTANT_FOLDING, flags); + assert flags.contains(PREVENT_CONSTANT_FOLDING) || flags.contains(ALLOW_CONSTANT_FOLDING) : String.format("Must set one of %s or %s. flags: %s", PREVENT_CONSTANT_FOLDING, + ALLOW_CONSTANT_FOLDING, flags); + } + + if (flags.contains(BUILDTIME_ACCESS) && !flags.contains(RUNTIME_ACCESS)) { + assert !(flags.contains(PREVENT_CONSTANT_FOLDING) || flags.contains(ALLOW_CONSTANT_FOLDING)) : "Constant folding is only applicable for runtime accesses " + flags; + } + + return true; + } +} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/RuntimeOnlyImageSingleton.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/RuntimeOnlyImageSingleton.java index bc151fb1aed8..3775ecbd8f44 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/RuntimeOnlyImageSingleton.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/RuntimeOnlyImageSingleton.java @@ -29,8 +29,8 @@ public interface RuntimeOnlyImageSingleton extends LayeredImageSingleton { @Override - default EnumSet getImageBuilderFlags() { - return EnumSet.of(ImageBuilderFlags.RUNTIME_ACCESS, ImageBuilderFlags.ALLOW_CONSTANT_FOLDING); + default EnumSet getImageBuilderFlags() { + return LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS_ONLY_ALLOW_FOLDING; } @Override diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/UnsupportedLayeredSingleton.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/UnsupportedLayeredSingleton.java index 2e608c9be612..142a1d23c73b 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/UnsupportedLayeredSingleton.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/layeredimagesingleton/UnsupportedLayeredSingleton.java @@ -34,8 +34,8 @@ public interface UnsupportedLayeredSingleton extends LayeredImageSingleton { @Override - default EnumSet getImageBuilderFlags() { - return EnumSet.of(ImageBuilderFlags.UNSUPPORTED); + default EnumSet getImageBuilderFlags() { + return EnumSet.of(LayeredImageSingletonBuilderFlags.UNSUPPORTED); } @Override diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ExtensionLayerImageFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ExtensionLayerImageFeature.java index 98657dc4c0fb..cfd57523e3f0 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ExtensionLayerImageFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ExtensionLayerImageFeature.java @@ -24,11 +24,11 @@ */ package com.oracle.svm.hosted; -import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.c.BoxedRelocatedPointer; import com.oracle.svm.core.code.ImageCodeInfo; import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.core.feature.InternalFeature; +import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.hosted.FeatureImpl.BeforeAnalysisAccessImpl; import com.oracle.svm.util.ReflectionUtil; @@ -41,7 +41,7 @@ final class ExtensionLayerImageFeature implements InternalFeature { @Override public boolean isInConfiguration(IsInConfigurationAccess access) { - return SubstrateOptions.LoadImageLayer.hasBeenSet(); + return ImageLayerBuildingSupport.buildingExtensionLayer(); } @Override diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageSingletonsSupportImpl.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageSingletonsSupportImpl.java index 21c08ab83c86..0d466847db9b 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageSingletonsSupportImpl.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ImageSingletonsSupportImpl.java @@ -35,11 +35,13 @@ import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton.PersistFlags; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonSupport; import com.oracle.svm.core.layeredimagesingleton.LoadedLayeredImageSingletonInfo; import com.oracle.svm.core.layeredimagesingleton.RuntimeOnlyWrapper; import com.oracle.svm.core.util.UserError; import com.oracle.svm.hosted.heap.SVMImageLayerLoader; +import com.oracle.svm.hosted.imagelayer.HostedImageLayerBuildingSupport; public final class ImageSingletonsSupportImpl extends ImageSingletonsSupport implements LayeredImageSingletonSupport { @@ -106,10 +108,14 @@ public static void install(HostedManagement vmConfig) { install(vmConfig, null); } - public static void install(HostedManagement vmConfig, SVMImageLayerSupport support) { + public static void install(HostedManagement vmConfig, HostedImageLayerBuildingSupport support) { UserError.guarantee(singletonDuringImageBuild == null, "Only one native image build can run at a time"); singletonDuringImageBuild = vmConfig; - if (support != null && support.loadImageSingletons()) { + if (support != null && support.getLoader() != null) { + /* + * Note eventually this may need to be moved to a later point after the Options + * Image Singleton is installed. + */ singletonDuringImageBuild.installPriorSingletonInfo(support.getLoader()); } else { singletonDuringImageBuild.doAddInternal(LoadedLayeredImageSingletonInfo.class, new LoadedLayeredImageSingletonInfo(Set.of())); @@ -138,7 +144,7 @@ public static void clear() { public static void persist() { var list = singletonDuringImageBuild.configObjects.entrySet().stream().filter(e -> e.getValue() instanceof LayeredImageSingleton).sorted(Comparator.comparing(e -> e.getKey().getName())) .toList(); - SVMImageLayerSupport.singleton().getWriter().writeImageSingletonInfo(list); + HostedImageLayerBuildingSupport.singleton().getWriter().writeImageSingletonInfo(list); } private final Map, Object> configObjects; @@ -165,13 +171,13 @@ private void doAddInternal(Class key, Object value) { Object storedValue = value; if (value instanceof LayeredImageSingleton singleton) { - assert singleton.verifyImageBuilderFlags(); + assert LayeredImageSingletonBuilderFlags.verifyImageBuilderFlags(singleton); - if (checkUnsupported && singleton.getImageBuilderFlags().contains(LayeredImageSingleton.ImageBuilderFlags.UNSUPPORTED)) { + if (checkUnsupported && singleton.getImageBuilderFlags().contains(LayeredImageSingletonBuilderFlags.UNSUPPORTED)) { throw UserError.abort("Unsupported image singleton is being installed %s %s", key.getTypeName(), singleton); } - if (!singleton.getImageBuilderFlags().contains(LayeredImageSingleton.ImageBuilderFlags.BUILDTIME_ACCESS)) { + if (!singleton.getImageBuilderFlags().contains(LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS)) { storedValue = new RuntimeOnlyWrapper(singleton); } } @@ -193,7 +199,7 @@ T doLookup(Class key, boolean stripRuntimeOnly) { } else if (result instanceof RuntimeOnlyWrapper wrapper) { if (!stripRuntimeOnly) { throw UserError.abort("A LayeredImageSingleton was accessed during image building which does not have %s access. Key: %s, object %s", - LayeredImageSingleton.ImageBuilderFlags.BUILDTIME_ACCESS, key, wrapper.wrappedObject()); + LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS, key, wrapper.wrappedObject()); } result = wrapper.wrappedObject(); 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 a7983d68f86d..0477ca1ac16f 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 @@ -173,6 +173,7 @@ import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.hub.LayoutEncoding; import com.oracle.svm.core.image.ImageHeapLayouter; +import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.core.jdk.ServiceCatalogSupport; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonSupport; import com.oracle.svm.core.option.HostedOptionValues; @@ -224,7 +225,7 @@ import com.oracle.svm.hosted.code.CEntryPointData; import com.oracle.svm.hosted.code.CFunctionSubstitutionProcessor; import com.oracle.svm.hosted.code.CompileQueue; -import com.oracle.svm.hosted.code.DynamicMethodAddressResolutionHostedSupport; +import com.oracle.svm.hosted.code.ObjectFileTransformer; import com.oracle.svm.hosted.code.HostedRuntimeConfigurationBuilder; import com.oracle.svm.hosted.code.NativeMethodSubstitutionProcessor; import com.oracle.svm.hosted.code.RestrictHeapAccessCalleesImpl; @@ -237,6 +238,7 @@ import com.oracle.svm.hosted.image.NativeImageCodeCache; import com.oracle.svm.hosted.image.NativeImageCodeCacheFactory; import com.oracle.svm.hosted.image.NativeImageHeap; +import com.oracle.svm.hosted.imagelayer.HostedImageLayerBuildingSupport; import com.oracle.svm.hosted.jdk.localization.LocalizationFeature; import com.oracle.svm.hosted.meta.HostedConstantReflectionProvider; import com.oracle.svm.hosted.meta.HostedField; @@ -529,11 +531,12 @@ public void run(Map entryPoints, setSystemPropertiesForImageLate(k); var hostedOptionValues = new HostedOptionValues(optionProvider.getHostedValues()); - SVMImageLayerSupport imageLayerSupport = SVMImageLayerSupport.initialize(hostedOptionValues); - ImageSingletonsSupportImpl.HostedManagement.install(new ImageSingletonsSupportImpl.HostedManagement(imageLayerSupport.enabled()), imageLayerSupport); + HostedImageLayerBuildingSupport imageLayerSupport = HostedImageLayerBuildingSupport.initialize(hostedOptionValues); + ImageSingletonsSupportImpl.HostedManagement.install(new ImageSingletonsSupportImpl.HostedManagement(imageLayerSupport.getLoader() != null || imageLayerSupport.getWriter() != null), + imageLayerSupport); ImageSingletons.add(LayeredImageSingletonSupport.class, (LayeredImageSingletonSupport) ImageSingletonsSupportImpl.get()); - ImageSingletons.add(SVMImageLayerSupport.class, imageLayerSupport); + ImageSingletons.add(ImageLayerBuildingSupport.class, imageLayerSupport); ImageSingletons.add(ProgressReporter.class, reporter); ImageSingletons.add(DeadlockWatchdog.class, loader.watchdog); ImageSingletons.add(TimerCollection.class, timerCollection); @@ -545,15 +548,13 @@ public void run(Map entryPoints, try (TemporaryBuildDirectoryProviderImpl tempDirectoryProvider = new TemporaryBuildDirectoryProviderImpl()) { ImageSingletons.add(TemporaryBuildDirectoryProvider.class, tempDirectoryProvider); - if (imageLayerSupport.hasWriter()) { + if (ImageLayerBuildingSupport.buildingSharedLayer()) { setupImageLayerArtifact(imageName); } doRun(entryPoints, javaMainSupport, imageName, k, harnessSubstitutions); - if (imageLayerSupport.persistImageSingletons()) { + if (ImageLayerBuildingSupport.buildingSharedLayer()) { ImageSingletonsSupportImpl.HostedManagement.persist(); - } - if (imageLayerSupport.hasWriter()) { - imageLayerSupport.getWriter().dumpFile(); + HostedImageLayerBuildingSupport.singleton().getWriter().dumpFile(); } } finally { reporter.ensureCreationStageEndCompleted(); @@ -655,8 +656,8 @@ protected void doRun(Map entryPoints, JavaMainSupport j var hConstantReflection = (HostedConstantReflectionProvider) runtimeConfiguration.getProviders().getConstantReflection(); heap = new NativeImageHeap(aUniverse, hUniverse, hMetaAccess, hConstantReflection, ImageSingletons.lookup(ImageHeapLayouter.class)); - if (SVMImageLayerSupport.singleton().persistAnalysis()) { - SVMImageLayerSupport.singleton().getWriter().setNativeImageHeap(heap); + if (ImageLayerBuildingSupport.buildingSharedLayer()) { + HostedImageLayerBuildingSupport.singleton().getWriter().setNativeImageHeap(heap); } BeforeCompilationAccessImpl beforeCompilationConfig = new BeforeCompilationAccessImpl(featureHandler, loader, aUniverse, hUniverse, heap, debug, runtimeConfiguration, nativeLibraries); @@ -715,14 +716,14 @@ protected void doRun(Map entryPoints, JavaMainSupport j createAbstractImage(k, hostedEntryPoints, heap, hMetaAccess, codeCache); - if (ImageSingletons.contains(DynamicMethodAddressResolutionHostedSupport.class)) { - ImageSingletons.lookup(DynamicMethodAddressResolutionHostedSupport.class).install(image.getObjectFile()); + if (ImageSingletons.contains(ObjectFileTransformer.class)) { + ImageSingletons.lookup(ObjectFileTransformer.class).afterAbstractImageCreation(image.getObjectFile()); } image.build(imageName, debug); - if (SVMImageLayerSupport.singleton().persistAnalysis()) { - SVMImageLayerSupport.singleton().getWriter().persistAnalysisInfo(hUniverse, bb.getUniverse()); + if (ImageLayerBuildingSupport.buildingSharedLayer()) { + HostedImageLayerBuildingSupport.singleton().getWriter().persistAnalysisInfo(hUniverse, bb.getUniverse()); } if (NativeImageOptions.PrintUniverse.getValue()) { @@ -804,7 +805,7 @@ private static void setupImageLayerArtifact(String imageName) { String fileName = ImageLayerSnapshotUtil.FILE_NAME_PREFIX + imageName.substring(imageNameStart); String filePath = imageName.substring(0, imageNameStart) + fileName; Path layerSnapshotPath = generatedFiles(HostedOptionValues.singleton()).resolve(filePath + ImageLayerSnapshotUtil.FILE_EXTENSION); - SVMImageLayerSupport.singleton().getWriter().setFileInfo(layerSnapshotPath, fileName, ImageLayerSnapshotUtil.FILE_EXTENSION); + HostedImageLayerBuildingSupport.singleton().getWriter().setFileInfo(layerSnapshotPath, fileName, ImageLayerSnapshotUtil.FILE_EXTENSION); BuildArtifacts.singleton().add(ArtifactType.LAYER_SNAPSHOT, layerSnapshotPath); } @@ -823,8 +824,8 @@ protected boolean runPointsToAnalysis(String imageName, OptionValues options, De bb.getHostVM().getClassInitializationSupport().setConfigurationSealed(true); } - if (SVMImageLayerSupport.singleton().loadAnalysis()) { - SVMImageLayerSupport.singleton().getLoader().loadLayerConstants(); + if (ImageLayerBuildingSupport.buildingExtensionLayer()) { + HostedImageLayerBuildingSupport.singleton().getLoader().loadLayerConstants(); } try (ReporterClosable c = ProgressReporter.singleton().printAnalysis(bb.getUniverse(), nativeLibraries.getLibraries())) { @@ -970,8 +971,8 @@ protected void setupNativeImage(OptionValues options, Map feature.duringSetup(config)); } - if (SVMImageLayerSupport.singleton().loadAnalysis()) { - Heap.getHeap().setStartOffset(SVMImageLayerSupport.singleton().getLoader().getImageHeapSize()); + if (ImageLayerBuildingSupport.buildingExtensionLayer()) { + Heap.getHeap().setStartOffset(HostedImageLayerBuildingSupport.singleton().getLoader().getImageHeapSize()); } initializeBigBang(bb, options, featureHandler, nativeLibraries, debug, aMetaAccess, aUniverse.getSubstitutions(), loader, true, @@ -1306,8 +1307,8 @@ protected NativeLibraries setupNativeLibraries(HostedProviders providers, CEnumC if (CAnnotationProcessorCache.Options.ExitAfterCAPCache.getValue()) { throw new InterruptImageBuilding("Exiting image generation because of " + SubstrateOptionsParser.commandArgument(CAnnotationProcessorCache.Options.ExitAfterCAPCache, "+")); } - if (SVMImageLayerSupport.singleton().hasLoader()) { - for (Path layerPath : SVMImageLayerSupport.singleton().getLoader().getLoadPaths()) { + if (ImageLayerBuildingSupport.buildingExtensionLayer()) { + for (Path layerPath : HostedImageLayerBuildingSupport.singleton().getLoader().getLoadPaths()) { Path snapshotFileName = layerPath.getFileName(); if (snapshotFileName != null) { String layerName = snapshotFileName.toString().split(ImageLayerSnapshotUtil.FILE_NAME_PREFIX)[1].split(ImageLayerSnapshotUtil.FILE_EXTENSION)[0].trim(); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/OpenTypeWorldFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/OpenTypeWorldFeature.java index 16967c3a7671..8666840e7632 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/OpenTypeWorldFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/OpenTypeWorldFeature.java @@ -41,10 +41,11 @@ import com.oracle.svm.core.feature.InternalFeature; import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.hub.DynamicHubSupport; +import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; -import com.oracle.svm.core.layeredimagesingleton.LoadedLayeredImageSingletonInfo; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.hosted.meta.HostedType; import jdk.graal.compiler.debug.Assertions; @@ -59,8 +60,10 @@ public boolean isInConfiguration(Feature.IsInConfigurationAccess access) { @Override public void beforeUniverseBuilding(BeforeUniverseBuildingAccess access) { - if (SVMImageLayerSupport.singleton().persistImageSingletons() && !LoadedLayeredImageSingletonInfo.singleton().handledDuringLoading(LayerTypeInfo.class)) { + if (ImageLayerBuildingSupport.buildingInitialLayer()) { ImageSingletons.add(LayerTypeInfo.class, new LayerTypeInfo()); + } else { + assert !(ImageLayerBuildingSupport.buildingImageLayer() && !ImageSingletons.contains(LayerTypeInfo.class)) : "Layered image is missing layer type info"; } } @@ -74,7 +77,7 @@ public void beforeCompilation(BeforeCompilationAccess access) { } public static int loadTypeInfo(Collection types) { - if (ImageSingletons.contains(LayerTypeInfo.class) && SVMImageLayerSupport.singleton().loadAnalysis()) { + if (ImageSingletons.contains(LayerTypeInfo.class) && ImageLayerBuildingSupport.buildingExtensionLayer()) { /* * Load analysis must be enabled or otherwise the same Analysis Type id will not be * reassigned across layers. @@ -169,8 +172,8 @@ public void persistTypeInfo(Collection types) { } @Override - public EnumSet getImageBuilderFlags() { - return EnumSet.of(ImageBuilderFlags.BUILDTIME_ACCESS); + public EnumSet getImageBuilderFlags() { + return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; } @Override diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java index 113bc2414174..a70849592a16 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMHost.java @@ -87,6 +87,7 @@ import com.oracle.svm.core.hub.HubType; import com.oracle.svm.core.hub.PredefinedClassesSupport; import com.oracle.svm.core.hub.ReferenceType; +import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.core.jdk.InternalVMMethod; import com.oracle.svm.core.jdk.LambdaFormHiddenMethod; import com.oracle.svm.core.option.HostedOptionKey; @@ -212,7 +213,7 @@ public SVMHost(OptionValues options, ImageClassLoader loader, ClassInitializatio } fieldValueInterceptionSupport = new FieldValueInterceptionSupport(annotationSubstitutions, classInitializationSupport); ImageSingletons.add(FieldValueInterceptionSupport.class, fieldValueInterceptionSupport); - useBaseLayer = SVMImageLayerSupport.singleton().loadAnalysis(); + useBaseLayer = ImageLayerBuildingSupport.buildingExtensionLayer(); if (SubstrateOptions.includeAll()) { initializeExcludedFields(); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMImageLayerSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMImageLayerSupport.java deleted file mode 100644 index 1f6340dd344f..000000000000 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SVMImageLayerSupport.java +++ /dev/null @@ -1,111 +0,0 @@ -/* - * Copyright (c) 2024, 2024, 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.hosted; - -import org.graalvm.nativeimage.ImageSingletons; - -import com.oracle.svm.core.SubstrateOptions; -import com.oracle.svm.core.option.HostedOptionValues; -import com.oracle.svm.hosted.heap.SVMImageLayerLoader; -import com.oracle.svm.hosted.heap.SVMImageLayerWriter; - -public final class SVMImageLayerSupport { - private final SVMImageLayerLoader loader; - private final SVMImageLayerWriter writer; - private final boolean loadImageSingletons; - private final boolean persistImageSingletons; - private final boolean loadAnalysis; - private final boolean persistAnalysis; - - private SVMImageLayerSupport(SVMImageLayerLoader loader, SVMImageLayerWriter writer, boolean loadImageSingletons, boolean persistImageSingletons, boolean loadAnalysis, boolean persistAnalysis) { - this.loader = loader; - this.writer = writer; - this.loadImageSingletons = loadImageSingletons; - this.persistImageSingletons = persistImageSingletons; - this.loadAnalysis = loadAnalysis; - this.persistAnalysis = persistAnalysis; - } - - public static SVMImageLayerSupport singleton() { - return ImageSingletons.lookup(SVMImageLayerSupport.class); - } - - public boolean enabled() { - return loader != null || writer != null; - } - - public boolean hasLoader() { - return loader != null; - } - - public SVMImageLayerLoader getLoader() { - return loader; - } - - boolean hasWriter() { - return writer != null; - } - - public SVMImageLayerWriter getWriter() { - return writer; - } - - public boolean loadImageSingletons() { - return loadImageSingletons; - } - - public boolean persistImageSingletons() { - return persistImageSingletons; - } - - public boolean loadAnalysis() { - return loadAnalysis; - } - - public boolean persistAnalysis() { - return persistAnalysis; - } - - static SVMImageLayerSupport initialize(HostedOptionValues values) { - SVMImageLayerWriter writer = null; - boolean persistImageSingletons = false; - boolean persistAnalysis = false; - if (SubstrateOptions.PersistImageLayerAnalysis.getValue(values) || SubstrateOptions.PersistImageLayerSingletons.getValue(values)) { - writer = new SVMImageLayerWriter(); - persistImageSingletons = SubstrateOptions.PersistImageLayerSingletons.getValue(values); - persistAnalysis = SubstrateOptions.PersistImageLayerAnalysis.getValue(values); - } - boolean loadImageSingletons = false; - boolean loadAnalysis = false; - SVMImageLayerLoader loader = null; - if (SubstrateOptions.LoadImageLayer.hasBeenSet(values)) { - loader = new SVMImageLayerLoader(SubstrateOptions.LoadImageLayer.getValue(values).values()); - loadImageSingletons = SubstrateOptions.LoadImageLayerSingletons.getValue(values); - loadAnalysis = SubstrateOptions.LoadImageLayerAnalysis.getValue(values); - } - - return new SVMImageLayerSupport(loader, writer, loadImageSingletons, persistImageSingletons, loadAnalysis, persistAnalysis); - } -} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/DynamicMethodAddressResolutionHostedSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/ObjectFileTransformer.java similarity index 92% rename from substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/DynamicMethodAddressResolutionHostedSupport.java rename to substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/ObjectFileTransformer.java index d75b135b1c21..cbd3932af256 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/DynamicMethodAddressResolutionHostedSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/ObjectFileTransformer.java @@ -26,8 +26,8 @@ import com.oracle.objectfile.ObjectFile; -public interface DynamicMethodAddressResolutionHostedSupport { +public interface ObjectFileTransformer { - void install(ObjectFile imageObjectFile); + void afterAbstractImageCreation(ObjectFile imageObjectFile); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/BaseLayerSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/BaseLayerSupport.java index e5d65c55f803..8ff23b0e0b96 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/BaseLayerSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/BaseLayerSupport.java @@ -38,8 +38,8 @@ import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; import com.oracle.svm.core.feature.InternalFeature; import com.oracle.svm.core.graal.code.CGlobalDataInfo; +import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.core.meta.SharedMethod; -import com.oracle.svm.hosted.SVMImageLayerSupport; import com.oracle.svm.hosted.c.CGlobalDataFeature; import com.oracle.svm.hosted.image.BaseLayerSupport.BaseLayerMethodAccessorImpl; import com.oracle.svm.hosted.meta.HostedMethod; @@ -49,7 +49,7 @@ class LoadBaseLayerFeature implements InternalFeature { @Override public boolean isInConfiguration(IsInConfigurationAccess access) { - return SVMImageLayerSupport.singleton().hasLoader(); + return ImageLayerBuildingSupport.buildingExtensionLayer(); } @Override diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java index 8037d6f860aa..bd3b2d62bdca 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java @@ -91,14 +91,13 @@ import com.oracle.svm.core.graal.code.CGlobalDataReference; import com.oracle.svm.core.image.ImageHeapLayoutInfo; import com.oracle.svm.core.image.ImageHeapPartition; -import com.oracle.svm.core.layeredimage.LayeredImageHeapSymbols; +import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.core.meta.MethodPointer; import com.oracle.svm.core.option.SubstrateOptionsParser; import com.oracle.svm.core.util.UserError; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.FeatureImpl; import com.oracle.svm.hosted.NativeImageOptions; -import com.oracle.svm.hosted.SVMImageLayerSupport; import com.oracle.svm.hosted.c.CGlobalDataFeature; import com.oracle.svm.hosted.c.NativeLibraries; import com.oracle.svm.hosted.c.codegen.CSourceCodeWriter; @@ -107,6 +106,7 @@ import com.oracle.svm.hosted.code.CEntryPointData; import com.oracle.svm.hosted.image.NativeImageHeap.ObjectInfo; import com.oracle.svm.hosted.image.RelocatableBuffer.Info; +import com.oracle.svm.hosted.imagelayer.HostedImageLayerBuildingSupport; import com.oracle.svm.hosted.meta.HostedMetaAccess; import com.oracle.svm.hosted.meta.HostedMethod; import com.oracle.svm.hosted.meta.HostedType; @@ -430,8 +430,8 @@ public void build(String imageName, DebugContext debug) { long imageHeapSize = getImageHeapSize(); - if (SVMImageLayerSupport.singleton().persistAnalysis()) { - SVMImageLayerSupport.singleton().getWriter().persistImageHeapSize(imageHeapSize); + if (ImageLayerBuildingSupport.buildingSharedLayer()) { + HostedImageLayerBuildingSupport.singleton().getWriter().persistImageHeapSize(imageHeapSize); } // Text section (code) @@ -487,48 +487,14 @@ public void build(String imageName, DebugContext debug) { long sectionOffsetOfARelocatablePointer = writer.writeHeap(debug, heapSectionBuffer); assert !SpawnIsolates.getValue() || heapSectionBuffer.getByteBuffer().getLong((int) sectionOffsetOfARelocatablePointer) == 0L; - if (!SVMImageLayerSupport.singleton().hasLoader()) { - defineDataSymbol(Isolates.IMAGE_HEAP_BEGIN_SYMBOL_NAME, heapSection, 0); - defineDataSymbol(Isolates.IMAGE_HEAP_END_SYMBOL_NAME, heapSection, imageHeapSize); - defineDataSymbol(Isolates.IMAGE_HEAP_RELOCATABLE_BEGIN_SYMBOL_NAME, heapSection, heapLayout.getReadOnlyRelocatableOffset() - heapLayout.getStartOffset()); - defineDataSymbol(Isolates.IMAGE_HEAP_RELOCATABLE_END_SYMBOL_NAME, heapSection, - heapLayout.getReadOnlyRelocatableOffset() + heapLayout.getReadOnlyRelocatableSize() - heapLayout.getStartOffset()); - defineDataSymbol(Isolates.IMAGE_HEAP_A_RELOCATABLE_POINTER_SYMBOL_NAME, heapSection, sectionOffsetOfARelocatablePointer); - defineDataSymbol(Isolates.IMAGE_HEAP_WRITABLE_BEGIN_SYMBOL_NAME, heapSection, heapLayout.getWritableOffset() - heapLayout.getStartOffset()); - defineDataSymbol(Isolates.IMAGE_HEAP_WRITABLE_END_SYMBOL_NAME, heapSection, heapLayout.getWritableOffset() + heapLayout.getWritableSize() - heapLayout.getStartOffset()); - - if (SVMImageLayerSupport.singleton().persistAnalysis()) { - objectFile.createUndefinedSymbol(LayeredImageHeapSymbols.SECOND_IMAGE_HEAP_BEGIN_SYMBOL_NAME, 0, false); - objectFile.createUndefinedSymbol(LayeredImageHeapSymbols.SECOND_IMAGE_HEAP_END_SYMBOL_NAME, 0, false); - objectFile.createUndefinedSymbol(LayeredImageHeapSymbols.SECOND_IMAGE_HEAP_RELOCATABLE_BEGIN_SYMBOL_NAME, 0, false); - objectFile.createUndefinedSymbol(LayeredImageHeapSymbols.SECOND_IMAGE_HEAP_RELOCATABLE_END_SYMBOL_NAME, 0, false); - objectFile.createUndefinedSymbol(LayeredImageHeapSymbols.SECOND_IMAGE_HEAP_A_RELOCATABLE_POINTER_SYMBOL_NAME, 0, false); - objectFile.createUndefinedSymbol(LayeredImageHeapSymbols.SECOND_IMAGE_HEAP_WRITABLE_BEGIN_SYMBOL_NAME, 0, false); - objectFile.createUndefinedSymbol(LayeredImageHeapSymbols.SECOND_IMAGE_HEAP_WRITABLE_END_SYMBOL_NAME, 0, false); - } - } else { - objectFile.createUndefinedSymbol(Isolates.IMAGE_HEAP_BEGIN_SYMBOL_NAME, 0, false); - objectFile.createUndefinedSymbol(Isolates.IMAGE_HEAP_END_SYMBOL_NAME, 0, false); - objectFile.createUndefinedSymbol(Isolates.IMAGE_HEAP_RELOCATABLE_BEGIN_SYMBOL_NAME, 0, false); - objectFile.createUndefinedSymbol(Isolates.IMAGE_HEAP_RELOCATABLE_END_SYMBOL_NAME, 0, false); - objectFile.createUndefinedSymbol(Isolates.IMAGE_HEAP_A_RELOCATABLE_POINTER_SYMBOL_NAME, 0, false); - objectFile.createUndefinedSymbol(Isolates.IMAGE_HEAP_WRITABLE_BEGIN_SYMBOL_NAME, 0, false); - objectFile.createUndefinedSymbol(Isolates.IMAGE_HEAP_WRITABLE_END_SYMBOL_NAME, 0, false); - - boolean global = true; // keep heap section alive - objectFile.createDefinedSymbol(LayeredImageHeapSymbols.SECOND_IMAGE_HEAP_BEGIN_SYMBOL_NAME, heapSection, 0, wordSize, false, global); - objectFile.createDefinedSymbol(LayeredImageHeapSymbols.SECOND_IMAGE_HEAP_END_SYMBOL_NAME, heapSection, imageHeapSize, wordSize, false, global); - objectFile.createDefinedSymbol(LayeredImageHeapSymbols.SECOND_IMAGE_HEAP_RELOCATABLE_BEGIN_SYMBOL_NAME, heapSection, - heapLayout.getReadOnlyRelocatableOffset() - heapLayout.getStartOffset(), wordSize, false, global); - objectFile.createDefinedSymbol(LayeredImageHeapSymbols.SECOND_IMAGE_HEAP_RELOCATABLE_END_SYMBOL_NAME, heapSection, - heapLayout.getReadOnlyRelocatableOffset() + heapLayout.getReadOnlyRelocatableSize() - heapLayout.getStartOffset(), wordSize, false, global); - objectFile.createDefinedSymbol(LayeredImageHeapSymbols.SECOND_IMAGE_HEAP_A_RELOCATABLE_POINTER_SYMBOL_NAME, heapSection, - sectionOffsetOfARelocatablePointer, wordSize, false, global); - objectFile.createDefinedSymbol(LayeredImageHeapSymbols.SECOND_IMAGE_HEAP_WRITABLE_BEGIN_SYMBOL_NAME, heapSection, - heapLayout.getWritableOffset() - heapLayout.getStartOffset(), wordSize, false, global); - objectFile.createDefinedSymbol(LayeredImageHeapSymbols.SECOND_IMAGE_HEAP_WRITABLE_END_SYMBOL_NAME, heapSection, - heapLayout.getWritableOffset() + heapLayout.getWritableSize() - heapLayout.getStartOffset(), wordSize, false, global); - } + defineDataSymbol(Isolates.IMAGE_HEAP_BEGIN_SYMBOL_NAME, heapSection, 0); + defineDataSymbol(Isolates.IMAGE_HEAP_END_SYMBOL_NAME, heapSection, imageHeapSize); + defineDataSymbol(Isolates.IMAGE_HEAP_RELOCATABLE_BEGIN_SYMBOL_NAME, heapSection, heapLayout.getReadOnlyRelocatableOffset() - heapLayout.getStartOffset()); + defineDataSymbol(Isolates.IMAGE_HEAP_RELOCATABLE_END_SYMBOL_NAME, heapSection, + heapLayout.getReadOnlyRelocatableOffset() + heapLayout.getReadOnlyRelocatableSize() - heapLayout.getStartOffset()); + defineDataSymbol(Isolates.IMAGE_HEAP_A_RELOCATABLE_POINTER_SYMBOL_NAME, heapSection, sectionOffsetOfARelocatablePointer); + defineDataSymbol(Isolates.IMAGE_HEAP_WRITABLE_BEGIN_SYMBOL_NAME, heapSection, heapLayout.getWritableOffset() - heapLayout.getStartOffset()); + defineDataSymbol(Isolates.IMAGE_HEAP_WRITABLE_END_SYMBOL_NAME, heapSection, heapLayout.getWritableOffset() + heapLayout.getWritableSize() - heapLayout.getStartOffset()); // Mark the sections with the relocations from the maps. markRelocationSitesFromBuffer(textBuffer, textImpl); @@ -971,7 +937,7 @@ protected void writeTextSection(DebugContext debug, final Section textSection, f HostedMethod current = pair.getLeft(); final String symName = localSymbolNameForMethod(current); final String signatureString = current.getUniqueShortName(); - defineMethodSymbol(textSection, current, methodsBySignature, signatureString, symName, SVMImageLayerSupport.singleton().persistAnalysis(), pair.getRight()); + defineMethodSymbol(textSection, current, methodsBySignature, signatureString, symName, ImageLayerBuildingSupport.buildingSharedLayer(), pair.getRight()); } // 2. fq without return type -- only for entry points! for (Map.Entry ent : methodsBySignature.entrySet()) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeap.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeap.java index 1241c7e7176a..4f01052142d9 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeap.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageHeap.java @@ -67,14 +67,15 @@ import com.oracle.svm.core.image.ImageHeapLayouter; import com.oracle.svm.core.image.ImageHeapObject; import com.oracle.svm.core.image.ImageHeapPartition; +import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.core.jdk.StringInternSupport; import com.oracle.svm.core.util.HostedStringDeduplication; import com.oracle.svm.core.util.UserError; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.HostedConfiguration; -import com.oracle.svm.hosted.SVMImageLayerSupport; import com.oracle.svm.hosted.config.DynamicHubLayout; import com.oracle.svm.hosted.config.HybridLayout; +import com.oracle.svm.hosted.imagelayer.HostedImageLayerBuildingSupport; import com.oracle.svm.hosted.meta.HostedArrayClass; import com.oracle.svm.hosted.meta.HostedClass; import com.oracle.svm.hosted.meta.HostedConstantReflectionProvider; @@ -238,8 +239,8 @@ public void addTrailingObjects() { String[] imageInternedStrings = internedStrings.keySet().toArray(new String[0]); Arrays.sort(imageInternedStrings); ImageSingletons.lookup(StringInternSupport.class).setImageInternedStrings(imageInternedStrings); - if (SVMImageLayerSupport.singleton().persistAnalysis()) { - SVMImageLayerSupport.singleton().getWriter().setImageInternedStrings(imageInternedStrings); + if (ImageLayerBuildingSupport.buildingSharedLayer()) { + HostedImageLayerBuildingSupport.singleton().getWriter().setImageInternedStrings(imageInternedStrings); } /* Manually snapshot the interned strings array. */ aUniverse.getHeapScanner().rescanObject(imageInternedStrings, OtherReason.LATE_SCAN); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/HostedImageLayerBuildingSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/HostedImageLayerBuildingSupport.java new file mode 100644 index 000000000000..1d5f1c2d7b70 --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/HostedImageLayerBuildingSupport.java @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2024, 2024, 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.hosted.imagelayer; + +import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; +import org.graalvm.nativeimage.ImageSingletons; + +import com.oracle.svm.core.SubstrateOptions; +import com.oracle.svm.core.option.HostedOptionValues; +import com.oracle.svm.hosted.heap.SVMImageLayerLoader; +import com.oracle.svm.hosted.heap.SVMImageLayerWriter; + +public final class HostedImageLayerBuildingSupport extends ImageLayerBuildingSupport { + private final SVMImageLayerLoader loader; + private final SVMImageLayerWriter writer; + + private HostedImageLayerBuildingSupport(SVMImageLayerLoader loader, SVMImageLayerWriter writer, boolean buildingImageLayer, boolean buildingInitialLayer, boolean buildingApplicationLayer) { + super(buildingImageLayer, buildingInitialLayer, buildingApplicationLayer); + this.loader = loader; + this.writer = writer; + } + + public static HostedImageLayerBuildingSupport singleton() { + return (HostedImageLayerBuildingSupport) ImageSingletons.lookup(ImageLayerBuildingSupport.class); + } + + public SVMImageLayerLoader getLoader() { + return loader; + } + + public SVMImageLayerWriter getWriter() { + return writer; + } + + public static HostedImageLayerBuildingSupport initialize(HostedOptionValues values) { + SVMImageLayerWriter writer = null; + if (SubstrateOptions.ImageLayer.getValue(values)) { + writer = new SVMImageLayerWriter(); + } + SVMImageLayerLoader loader = null; + if (SubstrateOptions.LoadImageLayer.hasBeenSet(values)) { + loader = new SVMImageLayerLoader(SubstrateOptions.LoadImageLayer.getValue(values).values()); + } + + boolean buildingImageLayer = loader != null || writer != null; + boolean buildingInitialLayer = buildingImageLayer && loader == null; + boolean buildingFinalLayer = buildingImageLayer && writer == null; + return new HostedImageLayerBuildingSupport(loader, writer, buildingImageLayer, buildingInitialLayer, buildingFinalLayer); + } +} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/ImageLayerSectionFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/ImageLayerSectionFeature.java new file mode 100644 index 000000000000..a7417b33c5e1 --- /dev/null +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/ImageLayerSectionFeature.java @@ -0,0 +1,230 @@ +/* + * Copyright (c) 2024, 2024, 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.hosted.imagelayer; + +import static org.graalvm.word.WordFactory.signed; + +import java.nio.ByteBuffer; +import java.util.EnumSet; +import java.util.List; + +import org.graalvm.nativeimage.ImageSingletons; +import org.graalvm.nativeimage.c.type.WordPointer; +import org.graalvm.nativeimage.hosted.Feature; +import org.graalvm.word.Pointer; +import org.graalvm.word.SignedWord; +import org.graalvm.word.WordBase; +import org.graalvm.word.WordFactory; + +import com.oracle.objectfile.BasicProgbitsSectionImpl; +import com.oracle.objectfile.ObjectFile; +import com.oracle.objectfile.SectionName; +import com.oracle.svm.core.Isolates; +import com.oracle.svm.core.c.CGlobalData; +import com.oracle.svm.core.c.CGlobalDataFactory; +import com.oracle.svm.core.config.ConfigurationValues; +import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; +import com.oracle.svm.core.feature.InternalFeature; +import com.oracle.svm.core.imagelayer.DynamicImageLayerInfo; +import com.oracle.svm.core.imagelayer.DynamicImageLayerInfoFeature; +import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; +import com.oracle.svm.core.imagelayer.ImageLayerSection; +import com.oracle.svm.core.layeredimagesingleton.FeatureSingleton; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; +import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton; +import com.oracle.svm.hosted.c.CGlobalDataFeature; +import com.oracle.svm.hosted.code.ObjectFileTransformer; + +import jdk.vm.ci.code.Architecture; + +/** + * Creates a section with image information specific to the current layer. + * + * Presently the layout of this section is as follows: + * + *
+ *  --------------------------------------------------------
+ *  |  byte offset | name                                  |
+ *  |  0           | heap begin                            |
+ *  |  8           | heap end                              |
+ *  |  16          | heap relocatable begin                |
+ *  |  24          | heap relocatable end                  |
+ *  |  32          | heap any relocatable pointer          |
+ *  |  40          | heap writable begin                   |
+ *  |  48          | heap writable end                     |
+ *  |  56          | next layer section (0 if final layer) |
+ *  --------------------------------------------------------
+ * 
+ */ +@AutomaticallyRegisteredFeature +public final class ImageLayerSectionFeature implements InternalFeature, FeatureSingleton, UnsavedSingleton, ObjectFileTransformer { + private static final SectionName SVM_LAYER_SECTION = new SectionName.ProgbitsSectionName("svm_layer"); + + private static final int HEAP_BEGIN_OFFSET = 0; + private static final int HEAP_END_OFFSET = 8; + private static final int HEAP_RELOCATABLE_BEGIN_OFFSET = 16; + private static final int HEAP_RELOCATABLE_END_OFFSET = 24; + private static final int HEAP_ANY_RELOCATABLE_POINTER_OFFSET = 32; + private static final int HEAP_WRITABLE_BEGIN_OFFSET = 40; + private static final int HEAP_WRITABLE_END_OFFSET = 48; + private static final int NEXT_SECTION_OFFSET = 56; + private static final int SECTION_SIZE = 64; + + private static final String CACHED_IMAGE_FDS_NAME = "__svm_layer_cached_image_fds"; + private static final String CACHED_IMAGE_HEAP_OFFSETS_NAME = "__svm_layer_cached_image_heap_offsets"; + + private static final SignedWord UNASSIGNED_FD = signed(-1); + + @Override + public boolean isInConfiguration(IsInConfigurationAccess access) { + return ImageLayerBuildingSupport.buildingImageLayer(); + } + + @Override + public List> getRequiredFeatures() { + return List.of(DynamicImageLayerInfoFeature.class); + } + + @Override + public void afterRegistration(AfterRegistrationAccess access) { + ImageSingletons.add(ImageLayerSection.class, createImageLayerSection()); + ImageSingletons.add(ObjectFileTransformer.class, this); + } + + private static byte[] createWords(int count, WordBase initialValue) { + Architecture arch = ConfigurationValues.getTarget().arch; + assert arch.getWordSize() == Long.BYTES : "currently hard-coded for 8 byte words"; + ByteBuffer buffer = ByteBuffer.allocate(count * Long.BYTES).order(arch.getByteOrder()); + for (int i = 0; i < count; i++) { + buffer.putLong(initialValue.rawValue()); + } + return buffer.array(); + } + + private static String getLayerName(int layerNumber) { + return String.format("__svm_layer_%s", layerNumber); + } + + private static ImageLayerSectionImpl createImageLayerSection() { + CGlobalData initialSectionStart = ImageLayerBuildingSupport.buildingInitialLayer() ? CGlobalDataFactory.forSymbol(getLayerName(DynamicImageLayerInfo.singleton().layerNumber)) : null; + CGlobalData cachedImageFDs; + CGlobalData cachedImageHeapOffsets; + + if (ImageLayerBuildingSupport.buildingInitialLayer()) { + cachedImageFDs = CGlobalDataFactory.forSymbol(CACHED_IMAGE_FDS_NAME); + cachedImageHeapOffsets = CGlobalDataFactory.forSymbol(CACHED_IMAGE_HEAP_OFFSETS_NAME); + } else if (ImageLayerBuildingSupport.buildingApplicationLayer()) { + cachedImageFDs = CGlobalDataFactory.createBytes(() -> createWords(DynamicImageLayerInfo.singleton().numLayers, UNASSIGNED_FD), CACHED_IMAGE_FDS_NAME); + cachedImageHeapOffsets = CGlobalDataFactory.createBytes(() -> createWords(DynamicImageLayerInfo.singleton().numLayers, WordFactory.zero()), CACHED_IMAGE_HEAP_OFFSETS_NAME); + } else { + cachedImageFDs = null; + cachedImageHeapOffsets = null; + } + + return new ImageLayerSectionImpl(initialSectionStart, cachedImageFDs, cachedImageHeapOffsets); + } + + @Override + public void beforeAnalysis(BeforeAnalysisAccess access) { + if (ImageLayerBuildingSupport.buildingApplicationLayer()) { + CGlobalDataFeature.singleton().registerWithGlobalSymbol(ImageLayerSection.getCachedImageFDs()); + CGlobalDataFeature.singleton().registerWithGlobalSymbol(ImageLayerSection.getCachedImageHeapOffsets()); + } + } + + private ObjectFile.ProgbitsSectionImpl layeredSectionData; + + /** + * Creates the SVM layer section and define all symbols within the section. Note it is necessary + * to define symbols in this section before the normal build process to ensure the CGlobals + * referring to them are able to pick up this symbol and not refer to an undefined symbol. + */ + @Override + public void afterAbstractImageCreation(ObjectFile objectFile) { + byte[] sectionBytes = new byte[SECTION_SIZE]; + layeredSectionData = new BasicProgbitsSectionImpl(sectionBytes); + + // since relocations are present the section it is considered writable + ObjectFile.Section layeredImageSection = objectFile.newProgbitsSection(SVM_LAYER_SECTION.getFormatDependentName(objectFile.getFormat()), objectFile.getPageSize(), true, false, + layeredSectionData); + + if (ImageLayerBuildingSupport.buildingSharedLayer()) { + String nextLayerSymbolName = getLayerName(DynamicImageLayerInfo.singleton().nextLayerNumber); + // this symbol will be defined in the next layer's layer section + objectFile.createUndefinedSymbol(nextLayerSymbolName, 0, false); + layeredSectionData.markRelocationSite(NEXT_SECTION_OFFSET, ObjectFile.RelocationKind.DIRECT_8, nextLayerSymbolName, 0); + } else { + /* + * Note because we provide a byte buffer initialized to zeros nothing needs to be done. + * Otherwise, the NEXT_SECTION field entry would need to be cleared within the + * application layer. + */ + } + + // this symbol must be global when it will be read by the prior section + objectFile.createDefinedSymbol(getLayerName(DynamicImageLayerInfo.singleton().layerNumber), layeredImageSection, 0, 0, false, ImageLayerBuildingSupport.buildingExtensionLayer()); + } + + @Override + public void beforeImageWrite(BeforeImageWriteAccess access) { + /* + * Note this is after all "normal" symbols, such as the heap symbols we use here, have been + * defined. At this point we can mark all relocations used within this section. + */ + layeredSectionData.markRelocationSite(HEAP_BEGIN_OFFSET, ObjectFile.RelocationKind.DIRECT_8, Isolates.IMAGE_HEAP_BEGIN_SYMBOL_NAME, 0); + layeredSectionData.markRelocationSite(HEAP_END_OFFSET, ObjectFile.RelocationKind.DIRECT_8, Isolates.IMAGE_HEAP_END_SYMBOL_NAME, 0); + layeredSectionData.markRelocationSite(HEAP_RELOCATABLE_BEGIN_OFFSET, ObjectFile.RelocationKind.DIRECT_8, Isolates.IMAGE_HEAP_RELOCATABLE_BEGIN_SYMBOL_NAME, 0); + layeredSectionData.markRelocationSite(HEAP_RELOCATABLE_END_OFFSET, ObjectFile.RelocationKind.DIRECT_8, Isolates.IMAGE_HEAP_RELOCATABLE_END_SYMBOL_NAME, 0); + layeredSectionData.markRelocationSite(HEAP_ANY_RELOCATABLE_POINTER_OFFSET, ObjectFile.RelocationKind.DIRECT_8, Isolates.IMAGE_HEAP_A_RELOCATABLE_POINTER_SYMBOL_NAME, 0); + layeredSectionData.markRelocationSite(HEAP_WRITABLE_BEGIN_OFFSET, ObjectFile.RelocationKind.DIRECT_8, Isolates.IMAGE_HEAP_WRITABLE_BEGIN_SYMBOL_NAME, 0); + layeredSectionData.markRelocationSite(HEAP_WRITABLE_END_OFFSET, ObjectFile.RelocationKind.DIRECT_8, Isolates.IMAGE_HEAP_WRITABLE_END_SYMBOL_NAME, 0); + } + + private static class ImageLayerSectionImpl extends ImageLayerSection implements UnsavedSingleton { + + ImageLayerSectionImpl(CGlobalData initialSectionStart, CGlobalData cachedImageFDs, CGlobalData cachedImageHeapOffsets) { + super(initialSectionStart, cachedImageFDs, cachedImageHeapOffsets); + } + + @Override + public int getEntryOffsetInternal(SectionEntries entry) { + return switch (entry) { + case HEAP_BEGIN -> HEAP_BEGIN_OFFSET; + case HEAP_END -> HEAP_END_OFFSET; + case HEAP_RELOCATABLE_BEGIN -> HEAP_RELOCATABLE_BEGIN_OFFSET; + case HEAP_RELOCATABLE_END -> HEAP_RELOCATABLE_END_OFFSET; + case HEAP_ANY_RELOCATABLE_POINTER -> HEAP_ANY_RELOCATABLE_POINTER_OFFSET; + case HEAP_WRITEABLE_BEGIN -> HEAP_WRITABLE_BEGIN_OFFSET; + case HEAP_WRITEABLE_END -> HEAP_WRITABLE_END_OFFSET; + case NEXT_SECTION -> NEXT_SECTION_OFFSET; + }; + } + + @Override + public EnumSet getImageBuilderFlags() { + return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; + } + } +} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java index 27a606c579f3..e0ea1ababe5d 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/snippets/SubstrateGraphBuilderPlugins.java @@ -87,6 +87,7 @@ import com.oracle.svm.core.identityhashcode.SubstrateIdentityHashCodeNode; import com.oracle.svm.core.jdk.proxy.DynamicProxyRegistry; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonSupport; import com.oracle.svm.core.option.HostedOptionKey; import com.oracle.svm.core.snippets.KnownIntrinsics; @@ -1119,7 +1120,7 @@ public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Rec public boolean apply(GraphBuilderContext b, ResolvedJavaMethod targetMethod, Receiver unused, ValueNode classNode) { Class key = constantObjectParameter(b, targetMethod, 0, Class.class, classNode); Object result = LayeredImageSingletonSupport.singleton().runtimeLookup(key); - if (result instanceof LayeredImageSingleton layeredSingleton && !layeredSingleton.getImageBuilderFlags().contains(LayeredImageSingleton.ImageBuilderFlags.RUNTIME_ACCESS)) { + if (result instanceof LayeredImageSingleton layeredSingleton && !layeredSingleton.getImageBuilderFlags().contains(LayeredImageSingletonBuilderFlags.RUNTIME_ACCESS)) { /* * Runtime compilation installs many singletons into the image which are * otherwise hosted only. Note the platform checks still apply and can be used