From 6b7fa501530a118ba19cd00f9df228262d1d9105 Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Thu, 1 Aug 2024 11:01:32 +0200 Subject: [PATCH 1/3] force resolution of global symbols we define in our code --- .../src/com/oracle/svm/core/SubstrateOptions.java | 2 -- .../oracle/svm/hosted/image/CCLinkerInvocation.java | 12 ++++++++---- .../imagelayer/HostedImageLayerBuildingSupport.java | 1 - 3 files changed, 8 insertions(+), 7 deletions(-) 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 6f1fb90054ba..9d217e7cf3e4 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 @@ -856,8 +856,6 @@ public static boolean useLIRBackend() { */ @Option(help = "Use linker option to prevent unreferenced symbols in image.")// public static final HostedOptionKey RemoveUnusedSymbols = new HostedOptionKey<>(OS.getCurrent() != OS.DARWIN); - @Option(help = "Ignore undefined symbols referenced from the built image.")// - public static final HostedOptionKey IgnoreUndefinedReferences = new HostedOptionKey<>(false); @Option(help = "Use linker option to remove all local symbols from image.")// public static final HostedOptionKey DeleteLocalSymbols = new HostedOptionKey<>(true); @Option(help = "Compatibility option to make symbols used for the image heap global. " + diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/CCLinkerInvocation.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/CCLinkerInvocation.java index ec24b88a904f..ec406fa64ceb 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/CCLinkerInvocation.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/CCLinkerInvocation.java @@ -48,8 +48,8 @@ import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.c.libc.BionicLibC; import com.oracle.svm.core.c.libc.LibCBase; -import com.oracle.svm.core.option.HostedOptionKey; import com.oracle.svm.core.option.AccumulatingLocatableMultiOptionValue; +import com.oracle.svm.core.option.HostedOptionKey; import com.oracle.svm.core.util.UserError; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.c.CGlobalDataFeature; @@ -270,9 +270,13 @@ private static class BinutilsCCLinkerInvocation extends CCLinkerInvocation { /* Perform garbage collection of unused input sections. */ additionalPreOptions.add("-Wl,--gc-sections"); } - if (SubstrateOptions.IgnoreUndefinedReferences.getValue()) { - /* Ignore references to undefined symbols from the object files. */ - additionalPreOptions.add("-Wl,--unresolved-symbols=ignore-in-object-files"); + + if (!imageKind.isExecutable) { + /* + * We do not want interposition to affect the resolution of symbols we define and + * reference within this library. + */ + additionalPreOptions.add("-Wl,-Bsymbolic"); } /* Use --version-script to control the visibility of image symbols. */ 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 index 38596aca900b..4325904e66b0 100644 --- 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 @@ -130,7 +130,6 @@ public static void processLayerOptions(EconomicMap, Object> values) SubstrateOptions.LayeredBaseImageAnalysis.update(values, true); SubstrateOptions.ClosedTypeWorld.update(values, false); - SubstrateOptions.StripDebugInfo.update(values, false); if (imageLayerEnabledHandler != null) { imageLayerEnabledHandler.onOptionEnabled(values); } From afb2c21eb22f615eb8c4d3e960e90b4a7fba3f02 Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Thu, 1 Aug 2024 16:55:31 +0200 Subject: [PATCH 2/3] Refactor prior layer method logic. --- .../com/oracle/graal/pointsto/api/HostVM.java | 4 + .../pointsto/flow/MethodTypeFlowBuilder.java | 2 +- .../graal/pointsto/heap/ImageLayerLoader.java | 5 + .../graal/pointsto/meta/AnalysisMethod.java | 7 + .../graal/pointsto/meta/AnalysisType.java | 3 +- .../pointsto/results/StrengthenGraphs.java | 2 +- .../aarch64/SubstrateAArch64Backend.java | 28 +++- .../amd64/AMD64CGlobalDataLoadAddressOp.java | 33 ++-- .../graal/amd64/SubstrateAMD64Backend.java | 41 +++-- .../com/oracle/svm/core/SubstrateOptions.java | 5 + .../graal/snippets/NonSnippetLowerings.java | 8 +- .../imagelayer/DynamicImageLayerInfo.java | 6 +- .../svm/hosted/HostedConfiguration.java | 2 +- .../src/com/oracle/svm/hosted/SVMHost.java | 21 +++ .../oracle/svm/hosted/code/CompileQueue.java | 150 +++++++----------- .../aarch64/AArch64HostedPatcherFeature.java | 17 +- .../code/amd64/AMD64HostedPatcherFeature.java | 1 + .../svm/hosted/heap/SVMImageLayerLoader.java | 2 +- .../hosted/image/LIRNativeImageCodeCache.java | 5 +- .../oracle/svm/hosted/image/NativeImage.java | 15 +- .../hosted/image/NativeImageCodeCache.java | 26 +-- .../imagelayer/HostedDynamicLayerInfo.java | 35 +++- .../HostedImageLayerBuildingSupport.java | 4 + .../imagelayer/PriorLayerSymbolTracker.java | 76 --------- .../svm/hosted/meta/UniverseBuilder.java | 4 +- 25 files changed, 234 insertions(+), 268 deletions(-) delete mode 100644 substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/PriorLayerSymbolTracker.java diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/api/HostVM.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/api/HostVM.java index 2d66c8fc18c2..c49b4506370c 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/api/HostVM.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/api/HostVM.java @@ -172,6 +172,10 @@ public boolean useBaseLayer() { return false; } + public boolean analyzedInPriorLayer(@SuppressWarnings("unused") AnalysisMethod method) { + return false; + } + /** * Check if an {@link AnalysisType} is initialized. */ diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java index ee8097982b71..8cc99c0d954f 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodTypeFlowBuilder.java @@ -620,7 +620,7 @@ protected void apply(boolean forceReparse, Object reason) { assert !processed : "can only call apply once per MethodTypeFlowBuilder"; processed = true; - if (bb.getHostVM().useBaseLayer() && method.isInBaseLayer()) { + if (method.analyzedInPriorLayer()) { /* * We don't need to analyze this method. We already know its return type state from the * open world analysis. We just install a return flow to link it with its uses. diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageLayerLoader.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageLayerLoader.java index d51dbc06dbe7..18bf9ad19e9b 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageLayerLoader.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/heap/ImageLayerLoader.java @@ -701,6 +701,11 @@ protected void initializeBaseLayerMethod(AnalysisMethod analysisMethod, Economic /* No flags to load in the AnalysisMethod */ } + /** + * Currently we save analysis parsed graphs for methods considered + * {@link AnalysisMethod#isReachable}. See {@link ImageLayerWriter#persistMethodGraphs} for + * implementation. + */ public boolean hasAnalysisParsedGraph(AnalysisMethod analysisMethod) { EconomicMap methodData = getMethodData(analysisMethod); return get(methodData, ANALYSIS_PARSED_GRAPH_TAG) != null; diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java index e6ef63d0ed48..8b6dc0412a31 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisMethod.java @@ -120,6 +120,7 @@ public record Signature(String name, AnalysisType[] parameterTypes) { private final int id; /** Marks a method loaded from a base layer. */ private final boolean isInBaseLayer; + private final boolean analyzedInPriorLayer; private final boolean hasNeverInlineDirective; private final ExceptionHandler[] exceptionHandlers; private final LocalVariableTable localVariableTable; @@ -226,6 +227,7 @@ protected AnalysisMethod(AnalysisUniverse universe, ResolvedJavaMethod wrapped, id = universe.computeNextMethodId(); isInBaseLayer = false; } + analyzedInPriorLayer = isInBaseLayer && universe.hostVM().analyzedInPriorLayer(this); ExceptionHandler[] original = wrapped.getExceptionHandlers(); exceptionHandlers = new ExceptionHandler[original.length]; @@ -268,6 +270,7 @@ protected AnalysisMethod(AnalysisMethod original, MultiMethodKey multiMethodKey) wrapped = original.wrapped; id = original.id; isInBaseLayer = original.isInBaseLayer; + analyzedInPriorLayer = original.analyzedInPriorLayer; declaringClass = original.declaringClass; signature = original.signature; hasNeverInlineDirective = original.hasNeverInlineDirective; @@ -378,6 +381,10 @@ public boolean isInBaseLayer() { return isInBaseLayer; } + public boolean analyzedInPriorLayer() { + return analyzedInPriorLayer; + } + /** * Registers this method as intrinsified to Graal nodes via a {@link InvocationPlugin graph * builder plugin}. Such a method is treated similar to an invoked method. For example, method diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java index 80b63d735a8f..aa9fb5f004b6 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java @@ -1071,7 +1071,8 @@ public AnalysisMethod resolveConcreteMethod(ResolvedJavaMethod method, ResolvedJ ResolvedJavaType originalCallerType = originalMethod.getDeclaringClass(); try { - newResolvedMethod = universe.lookup(wrapped.resolveConcreteMethod(originalMethod, originalCallerType)); + var concreteMethod = originalMethod instanceof BaseLayerMethod ? originalMethod : wrapped.resolveConcreteMethod(originalMethod, originalCallerType); + newResolvedMethod = universe.lookup(concreteMethod); if (newResolvedMethod == null) { newResolvedMethod = getUniverse().getBigbang().fallbackResolveConcreteMethod(this, (AnalysisMethod) method); } diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StrengthenGraphs.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StrengthenGraphs.java index f253b52645f7..b19681634af5 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StrengthenGraphs.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/results/StrengthenGraphs.java @@ -227,7 +227,7 @@ public final void applyResults(AnalysisMethod method) { return; } - if (method.isInBaseLayer()) { + if (method.analyzedInPriorLayer()) { useSharedLayerGraph(method); return; } diff --git a/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64Backend.java b/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64Backend.java index f1192ddf8600..809276b6a6ab 100755 --- a/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64Backend.java +++ b/substratevm/src/com.oracle.svm.core.graal.aarch64/src/com/oracle/svm/core/graal/aarch64/SubstrateAArch64Backend.java @@ -65,6 +65,7 @@ import com.oracle.svm.core.graal.nodes.ComputedIndirectCallTargetNode; import com.oracle.svm.core.heap.ReferenceAccess; import com.oracle.svm.core.heap.SubstrateReferenceMapBuilder; +import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.core.meta.CompressedNullConstant; import com.oracle.svm.core.meta.SharedField; import com.oracle.svm.core.meta.SharedMethod; @@ -1092,14 +1093,25 @@ private static JavaConstant getZeroConstant(AllocatableValue dst) { } } + public AArch64LIRInstruction createLoadMethodPointerConstant(AllocatableValue dst, SubstrateMethodPointerConstant constant) { + if (ImageLayerBuildingSupport.buildingExtensionLayer()) { + if (constant.pointer().getMethod() instanceof SharedMethod sharedMethod && sharedMethod.forceIndirectCall()) { + // GR-53498 AArch64 layered image support + throw VMError.unimplemented("AArch64 does not currently support layered images."); + } + } + + return new AArch64LoadMethodPointerConstantOp(dst, constant); + } + @Override public AArch64LIRInstruction createLoad(AllocatableValue dst, Constant src) { if (CompressedNullConstant.COMPRESSED_NULL.equals(src)) { return super.createLoad(dst, getZeroConstant(dst)); - } else if (src instanceof CompressibleConstant) { - return loadObjectConstant(dst, (CompressibleConstant) src); - } else if (src instanceof SubstrateMethodPointerConstant) { - return new AArch64LoadMethodPointerConstantOp(dst, (SubstrateMethodPointerConstant) src); + } else if (src instanceof CompressibleConstant constant) { + return loadObjectConstant(dst, constant); + } else if (src instanceof SubstrateMethodPointerConstant constant) { + return createLoadMethodPointerConstant(dst, constant); } return super.createLoad(dst, src); } @@ -1108,10 +1120,10 @@ public AArch64LIRInstruction createLoad(AllocatableValue dst, Constant src) { public LIRInstruction createStackLoad(AllocatableValue dst, Constant src) { if (CompressedNullConstant.COMPRESSED_NULL.equals(src)) { return super.createStackLoad(dst, getZeroConstant(dst)); - } else if (src instanceof CompressibleConstant) { - return loadObjectConstant(dst, (CompressibleConstant) src); - } else if (src instanceof SubstrateMethodPointerConstant) { - return new AArch64LoadMethodPointerConstantOp(dst, (SubstrateMethodPointerConstant) src); + } else if (src instanceof CompressibleConstant constant) { + return loadObjectConstant(dst, constant); + } else if (src instanceof SubstrateMethodPointerConstant constant) { + return createLoadMethodPointerConstant(dst, constant); } return super.createStackLoad(dst, src); } diff --git a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/AMD64CGlobalDataLoadAddressOp.java b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/AMD64CGlobalDataLoadAddressOp.java index 2fc9bd89ff07..e7860f9cb42b 100644 --- a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/AMD64CGlobalDataLoadAddressOp.java +++ b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/AMD64CGlobalDataLoadAddressOp.java @@ -24,20 +24,21 @@ */ package com.oracle.svm.core.graal.amd64; -import static jdk.vm.ci.code.ValueUtil.asRegister; import static jdk.graal.compiler.lir.LIRInstruction.OperandFlag.REG; +import static jdk.vm.ci.code.ValueUtil.asRegister; -import jdk.graal.compiler.asm.amd64.AMD64Address; -import jdk.graal.compiler.asm.amd64.AMD64MacroAssembler; -import jdk.graal.compiler.lir.LIRInstructionClass; -import jdk.graal.compiler.lir.amd64.AMD64LIRInstruction; -import jdk.graal.compiler.lir.asm.CompilationResultBuilder; import org.graalvm.word.Pointer; import com.oracle.svm.core.SubstrateUtil; import com.oracle.svm.core.graal.code.CGlobalDataInfo; import com.oracle.svm.core.graal.code.CGlobalDataReference; +import jdk.graal.compiler.asm.amd64.AMD64Address; +import jdk.graal.compiler.asm.amd64.AMD64MacroAssembler; +import jdk.graal.compiler.lir.LIRInstructionClass; +import jdk.graal.compiler.lir.amd64.AMD64LIRInstruction; +import jdk.graal.compiler.lir.asm.CompilationResultBuilder; +import jdk.vm.ci.code.Register; import jdk.vm.ci.meta.AllocatableValue; public final class AMD64CGlobalDataLoadAddressOp extends AMD64LIRInstruction { @@ -46,36 +47,46 @@ public final class AMD64CGlobalDataLoadAddressOp extends AMD64LIRInstruction { @Def(REG) private AllocatableValue result; private final CGlobalDataInfo dataInfo; + private final int addend; - AMD64CGlobalDataLoadAddressOp(CGlobalDataInfo dataInfo, AllocatableValue result) { + AMD64CGlobalDataLoadAddressOp(CGlobalDataInfo dataInfo, AllocatableValue result, int addend) { super(TYPE); assert dataInfo != null; this.dataInfo = dataInfo; this.result = result; + this.addend = addend; + } + + AMD64CGlobalDataLoadAddressOp(CGlobalDataInfo dataInfo, AllocatableValue result) { + this(dataInfo, result, 0); } @Override public void emitCode(CompilationResultBuilder crb, AMD64MacroAssembler masm) { + Register resultReg = asRegister(result); if (SubstrateUtil.HOSTED) { // AOT compilation: record patch that is fixed up later int before = masm.position(); AMD64Address address = masm.getPlaceholder(before); if (dataInfo.isSymbolReference()) { // Pure symbol reference: the data contains the symbol's address, load it - masm.movq(asRegister(result), address); + masm.movq(resultReg, address); } else { // Data: load its address - masm.leaq(asRegister(result), address); + masm.leaq(resultReg, address); } crb.compilationResult.recordDataPatch(before, new CGlobalDataReference(dataInfo)); } else { // Runtime compilation: compute the actual address Pointer globalsBase = CGlobalDataInfo.CGLOBALDATA_RUNTIME_BASE_ADDRESS.get(); Pointer address = globalsBase.add(dataInfo.getOffset()); - masm.movq(asRegister(result), address.rawValue()); + masm.movq(resultReg, address.rawValue()); if (dataInfo.isSymbolReference()) { // load data, which contains symbol's address - masm.movq(asRegister(result), new AMD64Address(asRegister(result))); + masm.movq(resultReg, new AMD64Address(asRegister(result))); } } + if (addend != 0) { + masm.addq(resultReg, addend); + } } } diff --git a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java index b2153f40f7e9..131301ce4ba8 100644 --- a/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java +++ b/substratevm/src/com.oracle.svm.core.graal.amd64/src/com/oracle/svm/core/graal/amd64/SubstrateAMD64Backend.java @@ -47,7 +47,6 @@ import java.util.function.BiConsumer; import org.graalvm.collections.EconomicMap; -import org.graalvm.collections.Pair; import org.graalvm.nativeimage.ImageSingletons; import com.oracle.svm.core.CPUFeatureAccess; @@ -62,7 +61,6 @@ import com.oracle.svm.core.deopt.Deoptimizer; import com.oracle.svm.core.graal.RuntimeCompilation; import com.oracle.svm.core.graal.code.AssignedLocation; -import com.oracle.svm.core.graal.code.CGlobalDataInfo; import com.oracle.svm.core.graal.code.PatchConsumerFactory; import com.oracle.svm.core.graal.code.SharedCompilationResult; import com.oracle.svm.core.graal.code.StubCallingConvention; @@ -88,6 +86,7 @@ import com.oracle.svm.core.heap.ReferenceAccess; import com.oracle.svm.core.heap.SubstrateReferenceMapBuilder; import com.oracle.svm.core.imagelayer.DynamicImageLayerInfo; +import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.core.meta.CompressedNullConstant; import com.oracle.svm.core.meta.SharedField; import com.oracle.svm.core.meta.SharedMethod; @@ -680,10 +679,10 @@ protected Value emitIndirectForeignCallAddress(ForeignCallLinkage linkage) { * Load the address for the start of the text section and then add in the offset for * this specific method. */ - Pair methodLocation = DynamicImageLayerInfo.singleton().getPriorLayerMethodLocation(targetMethod); + var methodLocation = DynamicImageLayerInfo.singleton().getPriorLayerMethodLocation(targetMethod); AllocatableValue basePointerAddress = newVariable(getLIRKindTool().getWordKind()); - append(new AMD64CGlobalDataLoadAddressOp(methodLocation.getLeft(), basePointerAddress)); - Value codeOffsetInSection = emitConstant(getLIRKindTool().getWordKind(), JavaConstant.forLong(methodLocation.getRight())); + append(new AMD64CGlobalDataLoadAddressOp(methodLocation.base(), basePointerAddress)); + Value codeOffsetInSection = emitConstant(getLIRKindTool().getWordKind(), JavaConstant.forLong(methodLocation.offset())); return getArithmetic().emitAdd(basePointerAddress, codeOffsetInSection, false); } if (!shouldEmitOnlyIndirectCalls()) { @@ -1462,14 +1461,30 @@ private static JavaConstant getZeroConstant(AllocatableValue dst) { } } + public AMD64LIRInstruction createLoadMethodPointerConstant(AllocatableValue dst, SubstrateMethodPointerConstant constant) { + if (ImageLayerBuildingSupport.buildingExtensionLayer()) { + if (constant.pointer().getMethod() instanceof SharedMethod sharedMethod && sharedMethod.forceIndirectCall()) { + /* + * AMD64LoadMethodPointerConstantOp retrieves the address via a PC-relative + * load. This is not possible to do in extension layers when referring to + * methods defined in prior layers. + */ + var methodLocation = DynamicImageLayerInfo.singleton().getPriorLayerMethodLocation(sharedMethod); + return new AMD64CGlobalDataLoadAddressOp(methodLocation.base(), dst, methodLocation.offset()); + } + } + + return new AMD64LoadMethodPointerConstantOp(dst, constant); + } + @Override public AMD64LIRInstruction createLoad(AllocatableValue dst, Constant src) { if (CompressedNullConstant.COMPRESSED_NULL.equals(src)) { return super.createLoad(dst, getZeroConstant(dst)); - } else if (src instanceof CompressibleConstant) { - return loadObjectConstant(dst, (CompressibleConstant) src); - } else if (src instanceof SubstrateMethodPointerConstant) { - return new AMD64LoadMethodPointerConstantOp(dst, (SubstrateMethodPointerConstant) src); + } else if (src instanceof CompressibleConstant constant) { + return loadObjectConstant(dst, constant); + } else if (src instanceof SubstrateMethodPointerConstant constant) { + return createLoadMethodPointerConstant(dst, constant); } return super.createLoad(dst, src); } @@ -1478,10 +1493,10 @@ public AMD64LIRInstruction createLoad(AllocatableValue dst, Constant src) { public LIRInstruction createStackLoad(AllocatableValue dst, Constant src) { if (CompressedNullConstant.COMPRESSED_NULL.equals(src)) { return super.createStackLoad(dst, getZeroConstant(dst)); - } else if (src instanceof CompressibleConstant) { - return loadObjectConstant(dst, (CompressibleConstant) src); - } else if (src instanceof SubstrateMethodPointerConstant) { - return new AMD64LoadMethodPointerConstantOp(dst, (SubstrateMethodPointerConstant) src); + } else if (src instanceof CompressibleConstant constant) { + return loadObjectConstant(dst, constant); + } else if (src instanceof SubstrateMethodPointerConstant constant) { + return createLoadMethodPointerConstant(dst, constant); } return super.createStackLoad(dst, src); } 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 9d217e7cf3e4..b1f9188e7127 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 @@ -198,6 +198,7 @@ protected void onValueUpdate(EconomicMap, Object> values, String ol public static final String KEEP_ALIVE_PREFIX = "-keepalive"; private static ValueUpdateHandler optimizeValueUpdateHandler; public static OptionEnabledHandler imageLayerEnabledHandler; + public static OptionEnabledHandler imageLayerCreateEnabledHandler; @Fold public static boolean getSourceLevelDebug() { @@ -433,6 +434,10 @@ public static void setImageLayerEnabledHandler(OptionEnabledHandler upd SubstrateOptions.imageLayerEnabledHandler = updateHandler; } + public static void setImageLayerCreateEnabledHandler(OptionEnabledHandler updateHandler) { + SubstrateOptions.imageLayerCreateEnabledHandler = updateHandler; + } + @Option(help = "Track NodeSourcePositions during runtime-compilation")// public static final HostedOptionKey IncludeNodeSourcePositions = new HostedOptionKey<>(false); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/NonSnippetLowerings.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/NonSnippetLowerings.java index a67d57ed3ca2..69be8161cd6c 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/NonSnippetLowerings.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/NonSnippetLowerings.java @@ -33,7 +33,6 @@ import java.util.Map; import java.util.function.Predicate; -import org.graalvm.collections.Pair; import org.graalvm.word.LocationIdentity; import com.oracle.svm.core.FrameAccess; @@ -41,7 +40,6 @@ import com.oracle.svm.core.SubstrateUtil; import com.oracle.svm.core.c.BoxedRelocatedPointer; import com.oracle.svm.core.config.ConfigurationValues; -import com.oracle.svm.core.graal.code.CGlobalDataInfo; import com.oracle.svm.core.graal.code.SubstrateBackend; import com.oracle.svm.core.graal.meta.KnownOffsets; import com.oracle.svm.core.graal.meta.RuntimeConfiguration; @@ -384,10 +382,10 @@ public void lower(FixedNode node, LoweringTool tool) { * address offset of the text section start and then add in the offset for * this specific method. */ - Pair methodLocation = DynamicImageLayerInfo.singleton().getPriorLayerMethodLocation(targetMethod); + var methodLocation = DynamicImageLayerInfo.singleton().getPriorLayerMethodLocation(targetMethod); AddressNode methodPointerAddress = graph.addOrUniqueWithInputs( - new OffsetAddressNode(new CGlobalDataLoadAddressNode(methodLocation.getLeft()), - ConstantNode.forIntegerKind(ConfigurationValues.getWordKind(), methodLocation.getRight()))); + new OffsetAddressNode(new CGlobalDataLoadAddressNode(methodLocation.base()), + ConstantNode.forIntegerKind(ConfigurationValues.getWordKind(), methodLocation.offset()))); loweredCallTarget = createIndirectCall(graph, callTarget, parameters, method, signature, callType, invokeKind, methodPointerAddress); } else if (!SubstrateBackend.shouldEmitOnlyIndirectCalls()) { loweredCallTarget = createDirectCall(graph, callTarget, parameters, signature, callType, invokeKind, targetMethod, node); 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 index 113915fbf098..c09d1665b895 100644 --- 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 @@ -24,7 +24,6 @@ */ package com.oracle.svm.core.imagelayer; -import org.graalvm.collections.Pair; import org.graalvm.nativeimage.ImageSingletons; import com.oracle.svm.core.graal.code.CGlobalDataInfo; @@ -45,8 +44,11 @@ public static DynamicImageLayerInfo singleton() { return ImageSingletons.lookup(DynamicImageLayerInfo.class); } + public record PriorLayerMethodLocation(CGlobalDataInfo base, int offset) { + } + /** * Returns a (Base, Offset) pair which can be used to call a method defined in a prior layer. */ - public abstract Pair getPriorLayerMethodLocation(SharedMethod method); + public abstract PriorLayerMethodLocation getPriorLayerMethodLocation(SharedMethod method); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java index 95dc1af08714..c6bf47ac5f34 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/HostedConfiguration.java @@ -345,7 +345,7 @@ public NativeImageCodeCacheFactory newCodeCacheFactory() { return new NativeImageCodeCacheFactory() { @Override public NativeImageCodeCache newCodeCache(CompileQueue compileQueue, NativeImageHeap heap, Platform targetPlatform, Path tempDir) { - return new LIRNativeImageCodeCache(compileQueue.getCompilationResults(), compileQueue.getBaseLayerMethods(), heap); + return new LIRNativeImageCodeCache(compileQueue.getCompilationResults(), heap); } }; } 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 600ce9024967..24f3cce3cc9b 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 @@ -58,6 +58,7 @@ import com.oracle.graal.pointsto.api.HostVM; import com.oracle.graal.pointsto.api.PointstoOptions; import com.oracle.graal.pointsto.constraints.UnsupportedFeatureException; +import com.oracle.graal.pointsto.heap.ImageLayerLoader; import com.oracle.graal.pointsto.infrastructure.OriginalClassProvider; import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; @@ -113,6 +114,8 @@ import com.oracle.svm.hosted.code.SubstrateCompilationDirectives; import com.oracle.svm.hosted.code.UninterruptibleAnnotationChecker; import com.oracle.svm.hosted.heap.PodSupport; +import com.oracle.svm.hosted.imagelayer.HostedDynamicLayerInfo; +import com.oracle.svm.hosted.imagelayer.HostedImageLayerBuildingSupport; import com.oracle.svm.hosted.meta.HostedField; import com.oracle.svm.hosted.meta.HostedType; import com.oracle.svm.hosted.meta.HostedUniverse; @@ -235,6 +238,24 @@ public boolean useBaseLayer() { return useBaseLayer; } + /** + * If we are skipping the analysis of a prior layer method, we must ensure analysis was + * performed in the prior layer and the analysis results have been serialized. Currently this + * approximates to either: + *
    + *
  1. We have an analyzed graph available. See {@link ImageLayerLoader#hasAnalysisParsedGraph} + * for which analysis graphs are persisted.
  2. + *
  3. A compile target exists this layer can call.
  4. + *
+ * + * This criteria will be further improved as part of GR-57021. + */ + @Override + public boolean analyzedInPriorLayer(AnalysisMethod method) { + ImageLayerLoader imageLayerLoader = HostedImageLayerBuildingSupport.singleton().getLoader(); + return imageLayerLoader.hasAnalysisParsedGraph(method) || HostedDynamicLayerInfo.singleton().isCompiled(method); + } + protected InlineBeforeAnalysisPolicyUtils getInlineBeforeAnalysisPolicyUtils() { return new InlineBeforeAnalysisPolicyUtils(); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java index 5786036da661..7b6c3de537d7 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java @@ -34,7 +34,6 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; -import java.util.Set; import java.util.TreeMap; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -61,6 +60,7 @@ import com.oracle.svm.core.graal.phases.OptimizeExceptionPathsPhase; import com.oracle.svm.core.heap.RestrictHeapAccess; import com.oracle.svm.core.heap.RestrictHeapAccessCallees; +import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.core.meta.MethodPointer; import com.oracle.svm.core.meta.SubstrateMethodPointerConstant; import com.oracle.svm.core.util.InterruptImageBuilding; @@ -164,8 +164,6 @@ protected PhaseSuite getAfterParseSuite() { protected final List policies; protected CompletionExecutor executor; protected final ConcurrentMap compilations; - /** Collect referenced base layer methods. They will be registered as external symbols. */ - protected final Set baseLayerMethods; protected final RuntimeConfiguration runtimeConfig; protected final MetaAccessProvider metaAccess; private Suites regularSuites = null; @@ -183,6 +181,14 @@ protected PhaseSuite getAfterParseSuite() { private final boolean printMethodHistogram = NativeImageOptions.PrintMethodHistogram.getValue(); private final boolean optionAOTTrivialInline = SubstrateOptions.AOTTrivialInline.getValue(); + /** + * Indicates we need to force compilation of all possible methods so that all calls to the prior + * layers have a target. + * + * The criteria for this will become more nuanced as part of GR-57021. + */ + private final boolean layeredForceCompilation = ImageLayerBuildingSupport.buildingSharedLayer() && !SubstrateOptions.UseSharedLayerGraphs.getValue(); + public record UnpublishedTrivialMethods(CompilationGraph unpublishedGraph, boolean newlyTrivial) { } @@ -373,12 +379,6 @@ public CompileQueue(DebugContext debug, FeatureHandler featureHandler, HostedUni this.graphTransplanter = createGraphTransplanter(); this.defaultParseHooks = new ParseHooks(this); - if (universe.hostVM().useBaseLayer()) { - this.baseLayerMethods = ConcurrentHashMap.newKeySet(); - } else { - this.baseLayerMethods = null; - } - callForReplacements(debug, runtimeConfig); } @@ -637,24 +637,21 @@ private void parseAheadOfTimeCompiledMethods() { */ continue; } + if (layeredForceCompilation) { + // when layered force compilation is enabled we try to parse all graphs + if (method.wrapped.getAnalyzedGraph() != null) { + ensureParsed(method, null, new EntryPointReason()); + } + continue; + } if (hMethod.isEntryPoint() || SubstrateCompilationDirectives.singleton().isForcedCompilation(hMethod) || hMethod.wrapped.isDirectRootMethod() && hMethod.wrapped.isSimplyImplementationInvoked()) { - if (compiledInPriorLayer(hMethod)) { - baseLayerMethods.add(hMethod); - } - if (hasGraph(hMethod)) { - ensureParsed(hMethod, null, new EntryPointReason()); - } + ensureParsed(hMethod, null, new EntryPointReason()); } if (hMethod.wrapped.isVirtualRootMethod()) { for (HostedMethod impl : hMethod.getImplementations()) { - if (compiledInPriorLayer(impl)) { - baseLayerMethods.add(impl); - } VMError.guarantee(impl.wrapped.isImplementationInvoked()); - if (hasGraph(impl)) { - ensureParsed(impl, null, new EntryPointReason()); - } + ensureParsed(impl, null, new EntryPointReason()); } } } @@ -664,22 +661,12 @@ private void parseAheadOfTimeCompiledMethods() { for (SubstrateForeignCallLinkage linkage : foreignCallsProvider.getForeignCalls().values()) { HostedMethod method = (HostedMethod) linkage.getDescriptor().findMethod(runtimeConfig.getProviders().getMetaAccess()); if (method.wrapped.isDirectRootMethod() && method.wrapped.isSimplyImplementationInvoked()) { - if (compiledInPriorLayer(method)) { - baseLayerMethods.add(method); - } - if (hasGraph(method)) { - ensureParsed(method, null, new EntryPointReason()); - } + ensureParsed(method, null, new EntryPointReason()); } if (method.wrapped.isVirtualRootMethod()) { for (HostedMethod impl : method.getImplementations()) { - if (compiledInPriorLayer(impl)) { - baseLayerMethods.add(impl); - } VMError.guarantee(impl.wrapped.isImplementationInvoked()); - if (hasGraph(impl)) { - ensureParsed(impl, null, new EntryPointReason()); - } + ensureParsed(impl, null, new EntryPointReason()); } } } @@ -938,31 +925,28 @@ public void scheduleEntryPoints() { continue; } - if (hMethod.isEntryPoint() || SubstrateCompilationDirectives.singleton().isForcedCompilation(hMethod) || - hMethod.wrapped.isDirectRootMethod() && hMethod.wrapped.isSimplyImplementationInvoked()) { - if (compiledInPriorLayer(hMethod)) { - baseLayerMethods.add(hMethod); - } - if (canBeCompiled(hMethod)) { + if (layeredForceCompilation) { + /* + * when layeredForceCompilation is enabled we try to parse all graphs. + */ + if (method.compilationInfo.getCompilationGraph() != null) { ensureCompiled(hMethod, new EntryPointReason()); } + continue; + } + + if (hMethod.isEntryPoint() || SubstrateCompilationDirectives.singleton().isForcedCompilation(hMethod) || + hMethod.wrapped.isDirectRootMethod() && hMethod.wrapped.isSimplyImplementationInvoked()) { + ensureCompiled(hMethod, new EntryPointReason()); } if (hMethod.wrapped.isVirtualRootMethod()) { MultiMethod.MultiMethodKey key = hMethod.getMultiMethodKey(); assert key != DEOPT_TARGET_METHOD && key != SubstrateCompilationDirectives.RUNTIME_COMPILED_METHOD : "unexpected method as virtual root " + hMethod; for (HostedMethod impl : hMethod.getImplementations()) { - if (compiledInPriorLayer(impl)) { - baseLayerMethods.add(impl); - } VMError.guarantee(impl.wrapped.isImplementationInvoked()); - if (canBeCompiled(impl)) { - ensureCompiled(impl, new EntryPointReason()); - } + ensureCompiled(impl, new EntryPointReason()); } } - if (hMethod.wrapped.isIntrinsicMethod() && hMethod.wrapped.isInBaseLayer()) { - baseLayerMethods.add(hMethod); - } } } } @@ -982,7 +966,19 @@ public void scheduleDeoptTargets() { } } + private static boolean parseInCurrentLayer(HostedMethod method) { + var hasAnalyzedGraph = method.wrapped.getAnalyzedGraph() != null; + if (!hasAnalyzedGraph) { + assert method.isCompiledInPriorLayer() || method.compilationInfo.inParseQueue.get() : method; + } + return hasAnalyzedGraph; + } + protected void ensureParsed(HostedMethod method, HostedMethod callerMethod, CompileReason reason) { + if (!parseInCurrentLayer(method)) { + return; + } + if (!(NativeImageOptions.AllowFoldMethods.getValue() || method.getAnnotation(Fold.class) == null || (callerMethod != null && metaAccess.lookupJavaType(GeneratedFoldInvocationPlugin.class).isAssignableFrom(callerMethod.getDeclaringClass())))) { throw VMError.shouldNotReachHere("Parsing method annotated with @" + Fold.class.getSimpleName() + ": " + @@ -1070,13 +1066,8 @@ private void defaultParseFunction(DebugContext debug, HostedMethod method, Compi private void ensureParsed(HostedMethod method, CompileReason reason, CallTargetNode targetNode, HostedMethod invokeTarget, boolean isIndirect) { if (isIndirect) { for (HostedMethod invokeImplementation : invokeTarget.getImplementations()) { - if (compiledInPriorLayer(invokeImplementation)) { - baseLayerMethods.add(invokeImplementation); - } handleSpecialization(method, targetNode, invokeTarget, invokeImplementation); - if (hasGraph(invokeImplementation)) { - ensureParsed(invokeImplementation, method, new VirtualCallReason(method, invokeImplementation, reason)); - } + ensureParsed(invokeImplementation, method, new VirtualCallReason(method, invokeImplementation, reason)); } } else { /* @@ -1090,29 +1081,12 @@ private void ensureParsed(HostedMethod method, CompileReason reason, CallTargetN * implementation invoked status. */ if (invokeTarget.wrapped.isSimplyImplementationInvoked() || invokeTarget.wrapped.isInBaseLayer()) { - if (compiledInPriorLayer(invokeTarget)) { - baseLayerMethods.add(invokeTarget); - } handleSpecialization(method, targetNode, invokeTarget, invokeTarget); - if (hasGraph(invokeTarget)) { - ensureParsed(invokeTarget, method, new DirectCallReason(method, reason)); - } + ensureParsed(invokeTarget, method, new DirectCallReason(method, reason)); } } } - private static boolean compiledInPriorLayer(HostedMethod method) { - return method.isCompiledInPriorLayer() || (!SubstrateOptions.UseSharedLayerGraphs.getValue() && method.wrapped.isInBaseLayer()); - } - - private static boolean hasGraph(HostedMethod method) { - return !method.wrapped.isInBaseLayer() || method.wrapped.getAnalyzedGraph() != null; - } - - private static boolean canBeCompiled(HostedMethod method) { - return !method.wrapped.isInBaseLayer() || method.compilationInfo.getCompilationGraph() != null; - } - @SuppressWarnings("unused") protected void notifyBeforeEncode(HostedMethod method, StructuredGraph graph) { HostedProviders providers = (HostedProviders) runtimeConfig.lookupBackend(method).getProviders(); @@ -1181,6 +1155,13 @@ private static void handleSpecialization(final HostedMethod method, CallTargetNo } protected void ensureCompiled(HostedMethod method, CompileReason reason) { + if (method.isCompiledInPriorLayer()) { + /* + * Since this method was compiled in a prior layer we should not compile it again. + */ + return; + } + CompilationInfo compilationInfo = method.compilationInfo; assert method.getMultiMethodKey() != SubstrateCompilationDirectives.RUNTIME_COMPILED_METHOD; @@ -1353,20 +1334,10 @@ protected void ensureCalleesCompiled(HostedMethod method, CompileReason reason, if (infopoint instanceof Call call) { HostedMethod callTarget = (HostedMethod) call.target; if (call.direct || isDynamicallyResolvedCall(result, call)) { - if (compiledInPriorLayer(callTarget)) { - baseLayerMethods.add(callTarget); - } - if (canBeCompiled(callTarget)) { - ensureCompiled(callTarget, new DirectCallReason(method, reason)); - } + ensureCompiled(callTarget, new DirectCallReason(method, reason)); } else if (callTarget != null && callTarget.getImplementations() != null) { for (HostedMethod impl : callTarget.getImplementations()) { - if (compiledInPriorLayer(impl)) { - baseLayerMethods.add(impl); - } - if (canBeCompiled(impl)) { - ensureCompiled(impl, new VirtualCallReason(method, callTarget, reason)); - } + ensureCompiled(impl, new VirtualCallReason(method, callTarget, reason)); } } } @@ -1390,21 +1361,12 @@ protected final void ensureCompiledForMethodPointerConstants(HostedMethod method if (constant instanceof SubstrateMethodPointerConstant) { MethodPointer pointer = ((SubstrateMethodPointerConstant) constant).pointer(); HostedMethod referencedMethod = (HostedMethod) pointer.getMethod(); - if (compiledInPriorLayer(referencedMethod)) { - baseLayerMethods.add(referencedMethod); - } - if (canBeCompiled(referencedMethod)) { - ensureCompiled(referencedMethod, new MethodPointerConstantReason(method, referencedMethod, reason)); - } + ensureCompiled(referencedMethod, new MethodPointerConstantReason(method, referencedMethod, reason)); } } } } - public Set getBaseLayerMethods() { - return baseLayerMethods; - } - public Map getCompilationResults() { Map result = new TreeMap<>(HostedUniverse.METHOD_COMPARATOR); for (Entry entry : compilations.entrySet()) { diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/aarch64/AArch64HostedPatcherFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/aarch64/AArch64HostedPatcherFeature.java index 847311eac18c..a6f88eec1c93 100755 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/aarch64/AArch64HostedPatcherFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/aarch64/AArch64HostedPatcherFeature.java @@ -26,14 +26,6 @@ import java.util.function.Consumer; -import com.oracle.svm.core.meta.MethodPointer; -import com.oracle.svm.hosted.meta.HostedMethod; -import jdk.graal.compiler.asm.Assembler.CodeAnnotation; -import jdk.graal.compiler.asm.aarch64.AArch64Assembler.SingleInstructionAnnotation; -import jdk.graal.compiler.asm.aarch64.AArch64MacroAssembler; -import jdk.graal.compiler.asm.aarch64.AArch64MacroAssembler.MovSequenceAnnotation.MovAction; -import jdk.graal.compiler.code.CompilationResult; -import jdk.vm.ci.meta.VMConstant; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; @@ -44,14 +36,22 @@ import com.oracle.svm.core.feature.InternalFeature; import com.oracle.svm.core.graal.code.CGlobalDataReference; import com.oracle.svm.core.graal.code.PatchConsumerFactory; +import com.oracle.svm.core.meta.MethodPointer; import com.oracle.svm.core.meta.SubstrateMethodPointerConstant; import com.oracle.svm.core.util.VMError; import com.oracle.svm.hosted.code.HostedPatcher; import com.oracle.svm.hosted.image.RelocatableBuffer; +import com.oracle.svm.hosted.meta.HostedMethod; +import jdk.graal.compiler.asm.Assembler.CodeAnnotation; +import jdk.graal.compiler.asm.aarch64.AArch64Assembler.SingleInstructionAnnotation; +import jdk.graal.compiler.asm.aarch64.AArch64MacroAssembler; +import jdk.graal.compiler.asm.aarch64.AArch64MacroAssembler.MovSequenceAnnotation.MovAction; +import jdk.graal.compiler.code.CompilationResult; import jdk.vm.ci.code.site.ConstantReference; import jdk.vm.ci.code.site.DataSectionReference; import jdk.vm.ci.code.site.Reference; +import jdk.vm.ci.meta.VMConstant; @AutomaticallyRegisteredFeature @Platforms({Platform.AARCH64.class}) @@ -178,6 +178,7 @@ public void relocate(Reference ref, RelocatableBuffer relocs, int compStart) { if (constant instanceof SubstrateMethodPointerConstant methodPointerConstant) { MethodPointer pointer = methodPointerConstant.pointer(); HostedMethod hMethod = (HostedMethod) pointer.getMethod(); + VMError.guarantee(!hMethod.isCompiledInPriorLayer(), "Method %s was compiled in a prior layer", hMethod); VMError.guarantee(hMethod.isCompiled(), "Method %s is not compiled although there is a method pointer constant created for it.", hMethod); relocVal = pointer; } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/amd64/AMD64HostedPatcherFeature.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/amd64/AMD64HostedPatcherFeature.java index cc957e03f926..cfa9d528bec9 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/amd64/AMD64HostedPatcherFeature.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/amd64/AMD64HostedPatcherFeature.java @@ -130,6 +130,7 @@ public void relocate(Reference ref, RelocatableBuffer relocs, int compStart) { if (constant instanceof SubstrateMethodPointerConstant methodPointerConstant) { MethodPointer pointer = methodPointerConstant.pointer(); HostedMethod hMethod = (HostedMethod) pointer.getMethod(); + VMError.guarantee(!hMethod.isCompiledInPriorLayer(), "Method %s was compiled in a prior layer", hMethod); VMError.guarantee(hMethod.isCompiled(), "Method %s is not compiled although there is a method pointer constant created for it.", hMethod); RelocationKind kindPCRelative = RelocationKind.getPCRelative(annotation.operandSize); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/SVMImageLayerLoader.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/SVMImageLayerLoader.java index f55470187f25..2bac473f2f5e 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/SVMImageLayerLoader.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/heap/SVMImageLayerLoader.java @@ -114,7 +114,7 @@ protected Annotation[] getAnnotations(EconomicMap elementData) { @Override protected void initializeBaseLayerMethod(AnalysisMethod analysisMethod, EconomicMap methodData) { - if (!HostedDynamicLayerInfo.singleton().isCompiled(analysisMethod.getId()) && hasAnalysisParsedGraph(analysisMethod)) { + if (!HostedDynamicLayerInfo.singleton().isCompiled(analysisMethod) && hasAnalysisParsedGraph(analysisMethod)) { /* * GR-55294: When the analysis elements from the base layer will be able to be * materialized after the analysis, this will not be needed anymore. diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/LIRNativeImageCodeCache.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/LIRNativeImageCodeCache.java index cdbd53c1a02a..ec9560771674 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/LIRNativeImageCodeCache.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/LIRNativeImageCodeCache.java @@ -30,7 +30,6 @@ import java.util.HashSet; import java.util.List; import java.util.Map; -import java.util.Set; import java.util.stream.Collectors; import java.util.stream.StreamSupport; @@ -69,8 +68,8 @@ public class LIRNativeImageCodeCache extends NativeImageCodeCache { private final TargetDescription target; @SuppressWarnings("this-escape") - public LIRNativeImageCodeCache(Map compilations, Set baseLayerMethods, NativeImageHeap imageHeap) { - super(compilations, imageHeap, baseLayerMethods); + public LIRNativeImageCodeCache(Map compilations, NativeImageHeap imageHeap) { + super(compilations, imageHeap); target = ConfigurationValues.getTarget(); trampolineMap = new HashMap<>(); orderedTrampolineMap = new HashMap<>(); 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 a4672cbbacea..a24f93076b70 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 @@ -107,8 +107,8 @@ 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.HostedDynamicLayerInfo; import com.oracle.svm.hosted.imagelayer.HostedImageLayerBuildingSupport; -import com.oracle.svm.hosted.imagelayer.PriorLayerSymbolTracker; import com.oracle.svm.hosted.meta.HostedMetaAccess; import com.oracle.svm.hosted.meta.HostedMethod; import com.oracle.svm.hosted.meta.HostedType; @@ -509,9 +509,8 @@ public void build(String imageName, DebugContext debug) { 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()); - var symbolTracker = PriorLayerSymbolTracker.singletonOrNull(); - if (symbolTracker != null) { - symbolTracker.defineSymbols(objectFile); + if (ImageLayerBuildingSupport.buildingExtensionLayer()) { + HostedDynamicLayerInfo.singleton().defineSymbolsForPriorLayerMethods(objectFile); } // Mark the sections with the relocations from the maps. @@ -948,14 +947,6 @@ protected void writeTextSection(DebugContext debug, final Section textSection, f final Map methodsBySignature = new HashMap<>(); // 1. fq with return type - if (codeCache.getBaseLayerMethods() != null) { - // register base layer methods symbols - var symbolTracker = PriorLayerSymbolTracker.singletonOrNull(); - for (HostedMethod current : codeCache.getBaseLayerMethods()) { - symbolTracker.registerPriorLayerReference(current); - } - } - for (Pair pair : codeCache.getOrderedCompilations()) { HostedMethod current = pair.getLeft(); final String symName = localSymbolNameForMethod(current); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java index c4c090d2caa5..f314b06ff28d 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImageCodeCache.java @@ -48,8 +48,6 @@ import java.util.Set; import java.util.stream.Collectors; -import com.oracle.svm.core.meta.CompressedNullConstant; -import com.oracle.svm.core.interpreter.InterpreterSupport; import org.graalvm.collections.Pair; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.Platform; @@ -83,6 +81,8 @@ import com.oracle.svm.core.configure.ConditionalRuntimeValue; import com.oracle.svm.core.deopt.DeoptEntryInfopoint; import com.oracle.svm.core.graal.code.SubstrateDataBuilder; +import com.oracle.svm.core.interpreter.InterpreterSupport; +import com.oracle.svm.core.meta.CompressedNullConstant; import com.oracle.svm.core.meta.MethodPointer; import com.oracle.svm.core.meta.SubstrateMethodPointerConstant; import com.oracle.svm.core.option.HostedOptionKey; @@ -98,7 +98,6 @@ import com.oracle.svm.hosted.code.SubstrateCompilationDirectives; import com.oracle.svm.hosted.code.SubstrateCompilationDirectives.DeoptSourceFrameInfo; import com.oracle.svm.hosted.image.NativeImage.NativeTextSectionImpl; -import com.oracle.svm.hosted.imagelayer.PriorLayerSymbolTracker; import com.oracle.svm.hosted.meta.HostedField; import com.oracle.svm.hosted.meta.HostedMetaAccess; import com.oracle.svm.hosted.meta.HostedMethod; @@ -129,7 +128,6 @@ public abstract class NativeImageCodeCache { private final Map embeddedConstants = new HashMap<>(); - private final Set baseLayerMethods; public static class Options { @Option(help = "Verify that all possible deoptimization entry points have been properly compiled and registered in the metadata")// @@ -151,11 +149,7 @@ public static class Options { private final Map constantReasons = new HashMap<>(); public NativeImageCodeCache(Map compilationResultMap, NativeImageHeap imageHeap) { - this(compilationResultMap, imageHeap, ImageSingletons.lookup(Platform.class), null); - } - - public NativeImageCodeCache(Map compilationResultMap, NativeImageHeap imageHeap, Set baseLayerMethods) { - this(compilationResultMap, imageHeap, ImageSingletons.lookup(Platform.class), baseLayerMethods); + this(compilationResultMap, imageHeap, ImageSingletons.lookup(Platform.class)); } public void purge() { @@ -165,14 +159,8 @@ public void purge() { @SuppressWarnings("this-escape")// public NativeImageCodeCache(Map compilations, NativeImageHeap imageHeap, Platform targetPlatform) { - this(compilations, imageHeap, targetPlatform, null); - } - - @SuppressWarnings("this-escape")// - public NativeImageCodeCache(Map compilations, NativeImageHeap imageHeap, Platform targetPlatform, Set baseLayerMethods) { this.compilations = compilations; this.imageHeap = imageHeap; - this.baseLayerMethods = baseLayerMethods; this.dataSection = new DataSection(); this.targetPlatform = targetPlatform; this.orderedCompilations = computeCompilationOrder(compilations); @@ -208,10 +196,6 @@ public List> getOrderedCompilations() { return orderedCompilations; } - public Set getBaseLayerMethods() { - return baseLayerMethods; - } - public abstract int codeSizeFor(HostedMethod method); protected CompilationResult compilationResultFor(HostedMethod method) { @@ -406,13 +390,9 @@ protected void buildRuntimeMetadata(DebugContext debug, SnippetReflectionProvide } })); - var symbolTracker = PriorLayerSymbolTracker.singletonOrNull(); configurationExecutables.forEach((declaringClass, classMethods) -> classMethods.forEach((analysisMethod, reflectMethod) -> { if (includedMethods.add(analysisMethod)) { HostedMethod method = hUniverse.lookup(analysisMethod); - if (analysisMethod.isInBaseLayer()) { - symbolTracker.registerPriorLayerReference(method); - } Object accessor = reflectionSupport.getAccessor(analysisMethod); runtimeMetadataEncoder.addReflectionExecutableMetadata(hMetaAccess, method, reflectMethod, accessor); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/HostedDynamicLayerInfo.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/HostedDynamicLayerInfo.java index 4eb35be13871..7507fcdf1b2f 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/HostedDynamicLayerInfo.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/HostedDynamicLayerInfo.java @@ -24,23 +24,28 @@ */ package com.oracle.svm.hosted.imagelayer; +import static com.oracle.svm.hosted.image.NativeImage.localSymbolNameForMethod; + import java.util.ArrayList; import java.util.BitSet; import java.util.Collection; import java.util.EnumSet; import java.util.HashMap; +import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Set; -import org.graalvm.collections.Pair; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.word.PointerBase; +import com.oracle.graal.pointsto.meta.AnalysisMethod; +import com.oracle.objectfile.ObjectFile; +import com.oracle.svm.core.BuildPhaseProvider; import com.oracle.svm.core.c.CGlobalData; import com.oracle.svm.core.c.CGlobalDataFactory; 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.DynamicImageLayerInfo; import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport; import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; @@ -58,6 +63,7 @@ public class HostedDynamicLayerInfo extends DynamicImageLayerInfo implements LayeredImageSingleton { private final Map methodIdToOffsetMap; private final CGlobalData cGlobalData; + private Set priorLayerHostedMethods = new HashSet<>(); HostedDynamicLayerInfo() { this(0, null, new HashMap<>()); @@ -74,21 +80,23 @@ private HostedDynamicLayerInfo(int layerNumber, String codeSectionStartSymbol, M } @Override - public Pair getPriorLayerMethodLocation(SharedMethod sMethod) { + public PriorLayerMethodLocation getPriorLayerMethodLocation(SharedMethod sMethod) { assert ImageLayerBuildingSupport.buildingExtensionLayer() : "This should only be called within extension images. Within the initial layer the direct calls can be performed"; HostedMethod method = (HostedMethod) sMethod; assert method.wrapped.isInBaseLayer() && methodIdToOffsetMap.containsKey(method.getWrapped().getId()) : method; var basePointer = CGlobalDataFeature.singleton().registerAsAccessedOrGet(cGlobalData); var offset = methodIdToOffsetMap.get(method.getWrapped().getId()); - return Pair.create(basePointer, offset); + return new PriorLayerMethodLocation(basePointer, offset); } - public boolean isCompiled(int id) { - return methodIdToOffsetMap.containsKey(id); + public boolean isCompiled(AnalysisMethod aMethod) { + assert !BuildPhaseProvider.isCompileQueueFinished(); + return methodIdToOffsetMap.containsKey(aMethod.getId()); } void registerOffset(HostedMethod method) { + assert BuildPhaseProvider.isCompileQueueFinished(); int offset = method.getCodeAddressOffset(); int methodID = method.getWrapped().getId(); @@ -96,6 +104,21 @@ void registerOffset(HostedMethod method) { methodIdToOffsetMap.put(methodID, offset); } + public void registerHostedMethod(HostedMethod hMethod) { + assert !BuildPhaseProvider.isHostedUniverseBuilt(); + AnalysisMethod aMethod = hMethod.getWrapped(); + if (isCompiled(aMethod)) { + assert aMethod.isInBaseLayer() : hMethod; + priorLayerHostedMethods.add(hMethod); + hMethod.setCompiledInPriorLayer(); + } + } + + public void defineSymbolsForPriorLayerMethods(ObjectFile objectFile) { + assert BuildPhaseProvider.isHeapLayoutFinished(); + priorLayerHostedMethods.forEach(m -> objectFile.createUndefinedSymbol(localSymbolNameForMethod(m), 0, true)); + } + @Override public EnumSet getImageBuilderFlags() { return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; 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 index 4325904e66b0..f3d9dadbf46e 100644 --- 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 @@ -29,6 +29,7 @@ import static com.oracle.svm.core.SubstrateOptions.LayerCreate; import static com.oracle.svm.core.SubstrateOptions.LayerUse; import static com.oracle.svm.core.SubstrateOptions.imageLayerEnabledHandler; +import static com.oracle.svm.core.SubstrateOptions.imageLayerCreateEnabledHandler; import static com.oracle.svm.hosted.imagelayer.LayerArchiveSupport.MODULE_OPTION; import static com.oracle.svm.hosted.imagelayer.LayerArchiveSupport.PACKAGE_OPTION; @@ -133,6 +134,9 @@ public static void processLayerOptions(EconomicMap, Object> values) if (imageLayerEnabledHandler != null) { imageLayerEnabledHandler.onOptionEnabled(values); } + if (imageLayerCreateEnabledHandler != null) { + imageLayerCreateEnabledHandler.onOptionEnabled(values); + } SubstrateOptions.UseContainerSupport.update(values, false); } } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/PriorLayerSymbolTracker.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/PriorLayerSymbolTracker.java deleted file mode 100644 index 0b6a120d911d..000000000000 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/PriorLayerSymbolTracker.java +++ /dev/null @@ -1,76 +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.imagelayer; - -import static com.oracle.svm.hosted.image.NativeImage.localSymbolNameForMethod; - -import java.util.EnumSet; -import java.util.Set; -import java.util.concurrent.ConcurrentHashMap; - -import org.graalvm.nativeimage.ImageSingletons; - -import com.oracle.objectfile.ObjectFile; -import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; -import com.oracle.svm.core.imagelayer.BuildingExtensionLayerPredicate; -import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags; -import com.oracle.svm.core.layeredimagesingleton.UnsavedSingleton; -import com.oracle.svm.core.util.VMError; -import com.oracle.svm.hosted.meta.HostedMethod; - -/** - * Tracks references to symbols defined in prior layers so that we can define them as undefined - * symbols in the layer. - */ -@AutomaticallyRegisteredImageSingleton(onlyWith = BuildingExtensionLayerPredicate.class) -public class PriorLayerSymbolTracker implements UnsavedSingleton { - - private final Set referencedMethods = ConcurrentHashMap.newKeySet(); - boolean sealed = false; - - public static PriorLayerSymbolTracker singletonOrNull() { - if (ImageSingletons.contains(PriorLayerSymbolTracker.class)) { - return ImageSingletons.lookup(PriorLayerSymbolTracker.class); - } - - return null; - } - - public void registerPriorLayerReference(HostedMethod method) { - VMError.guarantee(method.getWrapped().isInBaseLayer(), "Can only register methods in a prior layer"); - VMError.guarantee(!sealed, "Too late to register methods"); - referencedMethods.add(method); - } - - public void defineSymbols(ObjectFile objectFile) { - sealed = true; - referencedMethods.forEach(m -> objectFile.createUndefinedSymbol(localSymbolNameForMethod(m), 0, true)); - } - - @Override - public EnumSet getImageBuilderFlags() { - return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY; - } -} diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java index c1af300c33ff..cf7716610176 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/UniverseBuilder.java @@ -359,8 +359,8 @@ private HostedMethod makeMethod(AnalysisMethod aMethod) { } HostedMethod hMethod = HostedMethod.create(hUniverse, aMethod, hDeclaringClass, signature, constantPool, sHandlers); - if (HostedImageLayerBuildingSupport.buildingExtensionLayer() && HostedDynamicLayerInfo.singleton().isCompiled(hMethod.wrapped.getId())) { - hMethod.setCompiledInPriorLayer(); + if (HostedImageLayerBuildingSupport.buildingExtensionLayer()) { + HostedDynamicLayerInfo.singleton().registerHostedMethod(hMethod); } boolean isCFunction = aMethod.getAnnotation(CFunction.class) != null; From 0397550dfbd85cc77213c83540100389a7e9f44c Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Thu, 8 Aug 2024 12:30:26 +0200 Subject: [PATCH 3/3] fix spelling error --- .../com/oracle/svm/hosted/ImageSingletonsSupportImpl.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) 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 3c54460a3895..06d0197976a7 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 @@ -97,7 +97,7 @@ public static final class HostedManagement { * Marker for ImageSingleton keys which cannot have a value installed. This can happen when * a {@link LayeredImageSingleton} specified {@link PersistFlags#FORBIDDEN}. */ - private static final Object SINGLETON_INSTALLATION_FOBIDDEN = new Object(); + private static final Object SINGLETON_INSTALLATION_FORBIDDEN = new Object(); /** * The {@link ImageSingletons} removes static state from the image generator, and in theory @@ -146,7 +146,7 @@ public static void install(HostedManagement vmConfig, HostedImageLayerBuildingSu } private void installPriorSingletonInfo(SVMImageLayerLoader info) { - var result = info.loadImageSingletons(SINGLETON_INSTALLATION_FOBIDDEN); + var result = info.loadImageSingletons(SINGLETON_INSTALLATION_FORBIDDEN); Set> installedKeys = new HashSet<>(); for (var entry : result.entrySet()) { Object singletonToInstall = entry.getKey(); @@ -247,7 +247,7 @@ T doLookup(Class key, boolean stripRuntimeOnly) { Object result = configObjects.get(key); if (result == null) { throw UserError.abort("ImageSingletons do not contain key %s", key.getTypeName()); - } else if (result == SINGLETON_INSTALLATION_FOBIDDEN) { + } else if (result == SINGLETON_INSTALLATION_FORBIDDEN) { throw UserError.abort("A LayeredImageSingleton was installed in a prior layer which forbids creating the singleton in a subsequent layer. Key %s", key.getTypeName()); } else if (result instanceof RuntimeOnlyWrapper wrapper) { if (!stripRuntimeOnly) { @@ -263,7 +263,7 @@ T doLookup(Class key, boolean stripRuntimeOnly) { boolean doContains(Class key) { checkKey(key); var value = configObjects.get(key); - return value != null && value != SINGLETON_INSTALLATION_FOBIDDEN; + return value != null && value != SINGLETON_INSTALLATION_FORBIDDEN; } private static void checkKey(Class key) {