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 c25fd61ea8ac..f41076dd6ed1 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 @@ -444,6 +444,12 @@ public int getImageHeapNullRegionSize() { return 0; } + @Fold + @Override + public boolean allowPageSizeMismatch() { + return true; + } + @Override public boolean walkImageHeapObjects(ObjectVisitor visitor) { VMOperation.guaranteeInProgressAtSafepoint("Must only be called at a safepoint"); diff --git a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsPlatformThreads.java b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsPlatformThreads.java index 61cad73b39eb..bc3a406c228a 100644 --- a/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsPlatformThreads.java +++ b/substratevm/src/com.oracle.svm.core.windows/src/com/oracle/svm/core/windows/WindowsPlatformThreads.java @@ -115,6 +115,8 @@ public boolean joinThreadUnmanaged(OSThreadHandle threadHandle, WordPointer thre if (SynchAPI.NoTransitions.WaitForSingleObject((WinBase.HANDLE) threadHandle, SynchAPI.INFINITE()) != SynchAPI.WAIT_OBJECT_0()) { return false; } + // Since only an int is written, first clear word + threadExitStatus.write(WordFactory.zero()); if (Process.NoTransitions.GetExitCodeThread((WinBase.HANDLE) threadHandle, (CIntPointer) threadExitStatus) == 0) { return false; } 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 e33dedc1eb31..2f4195a73340 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 @@ -830,6 +830,7 @@ public ReportingSupport(Path reportingPath) { @Option(help = "Define PageSize of a machine that runs the image. The default = 0 (== same as host machine page size)")// protected static final HostedOptionKey PageSize = new HostedOptionKey<>(0); + @Fold public static int getPageSize() { int value = PageSize.getValue(); if (value == 0) { @@ -844,6 +845,7 @@ public static int getPageSize() { return 4096; } } + assert value > 0; return value; } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/CEntryPointErrors.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/CEntryPointErrors.java index 772924d5353d..8ca7d3021dfa 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/CEntryPointErrors.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/c/function/CEntryPointErrors.java @@ -125,6 +125,9 @@ private CEntryPointErrors() { @Description("Current target does not support the following CPU features that are required by the image.") // public static final int CPU_FEATURE_CHECK_FAILED = 23; + @Description("Image page size is incompatible with run-time page size. Rebuild image with -H:PageSize=[pagesize] to set appropriately.") // + public static final int PAGE_SIZE_CHECK_FAILED = 24; + public static String getDescription(int code) { String result = null; if (code >= 0 && code < DESCRIPTIONS.length) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java index 524b263a2eab..1a818b24a79f 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/CEntryPointSnippets.java @@ -62,6 +62,7 @@ import org.graalvm.nativeimage.c.type.WordPointer; import org.graalvm.word.LocationIdentity; import org.graalvm.word.PointerBase; +import org.graalvm.word.UnsignedWord; import org.graalvm.word.WordFactory; import com.oracle.svm.core.CPUFeatureAccess; @@ -69,6 +70,7 @@ import com.oracle.svm.core.IsolateListenerSupport; import com.oracle.svm.core.Isolates; import com.oracle.svm.core.JavaMainWrapper.JavaMainSupport; +import com.oracle.svm.core.NeverInline; import com.oracle.svm.core.RuntimeAssertionsSupport; import com.oracle.svm.core.SubstrateDiagnostics; import com.oracle.svm.core.SubstrateOptions; @@ -86,6 +88,7 @@ import com.oracle.svm.core.graal.nodes.CEntryPointEnterNode; import com.oracle.svm.core.graal.nodes.CEntryPointLeaveNode; import com.oracle.svm.core.graal.nodes.CEntryPointUtilityNode; +import com.oracle.svm.core.heap.Heap; import com.oracle.svm.core.heap.ReferenceHandler; import com.oracle.svm.core.heap.ReferenceHandlerThread; import com.oracle.svm.core.heap.RestrictHeapAccess; @@ -94,6 +97,7 @@ import com.oracle.svm.core.log.Log; import com.oracle.svm.core.option.RuntimeOptionParser; import com.oracle.svm.core.os.MemoryProtectionProvider; +import com.oracle.svm.core.os.VirtualMemoryProvider; import com.oracle.svm.core.snippets.SnippetRuntime; import com.oracle.svm.core.snippets.SnippetRuntime.SubstrateForeignCallDescriptor; import com.oracle.svm.core.snippets.SubstrateForeignCallTarget; @@ -103,6 +107,7 @@ import com.oracle.svm.core.thread.VMOperationControl; import com.oracle.svm.core.thread.VMThreads; import com.oracle.svm.core.thread.VMThreads.SafepointBehavior; +import com.oracle.svm.core.util.UnsignedUtils; import com.oracle.svm.core.util.VMError; import jdk.internal.misc.Unsafe; @@ -205,6 +210,14 @@ private static int createIsolate(CEntryPointCreateIsolateParameters parameters, if (cpuFeatureAccess.verifyHostSupportsArchitectureEarly() != 0) { return CEntryPointErrors.CPU_FEATURE_CHECK_FAILED; } + + UnsignedWord runtimePageSize = VirtualMemoryProvider.get().getGranularity(); + UnsignedWord imagePageSize = WordFactory.unsigned(SubstrateOptions.getPageSize()); + boolean validPageSize = runtimePageSize.equal(imagePageSize) || + (Heap.getHeap().allowPageSizeMismatch() && UnsignedUtils.isAMultiple(imagePageSize, runtimePageSize)); + if (!validPageSize) { + return CEntryPointErrors.PAGE_SIZE_CHECK_FAILED; + } CLongPointer parsedArgs = StackValue.get(IsolateArgumentParser.getStructSize()); IsolateArgumentParser.parse(parameters, parsedArgs); @@ -217,6 +230,12 @@ private static int createIsolate(CEntryPointCreateIsolateParameters parameters, setHeapBase(Isolates.getHeapBase(isolate.read())); } + return createIsolate0(parsedArgs, isolate, vmThreadSize); + } + + @Uninterruptible(reason = "Thread state not yet set up.") + @NeverInline(value = "Ensure this code cannot rise above where heap base is set.") + private static int createIsolate0(CLongPointer parsedArgs, WordPointer isolate, int vmThreadSize) { IsolateArgumentParser.singleton().persistOptions(parsedArgs); IsolateListenerSupport.singleton().afterCreateIsolate(isolate.read()); @@ -226,7 +245,7 @@ private static int createIsolate(CEntryPointCreateIsolateParameters parameters, return CEntryPointErrors.THREADING_INITIALIZATION_FAILED; } } - error = attachThread(isolate.read(), false, false, vmThreadSize, true); + int error = attachThread(isolate.read(), false, false, vmThreadSize, true); if (error != CEntryPointErrors.NO_ERROR) { return error; } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Heap.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Heap.java index 4902b9c13dd5..42e28322d963 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Heap.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/Heap.java @@ -37,6 +37,7 @@ import org.graalvm.word.Pointer; import org.graalvm.word.UnsignedWord; +import com.oracle.svm.core.SubstrateOptions; import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.hub.PredefinedClassesSupport; @@ -167,6 +168,14 @@ public List> getLoadedClasses() { @Fold public abstract int getImageHeapNullRegionSize(); + /** + * Returns whether the runtime page size doesn't have to match the page size set at image + * creation ({@link SubstrateOptions#getPageSize()}). If there is a mismatch, then the page size + * set at image creation must be a multiple of the runtime page size. + */ + @Fold + public abstract boolean allowPageSizeMismatch(); + /** * Returns true if the given object is located in the image heap. */ 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 5181bc089fec..968216505468 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 @@ -89,6 +89,7 @@ import org.graalvm.compiler.nodes.java.MethodCallTargetNode; import org.graalvm.compiler.options.OptionValues; import org.graalvm.compiler.phases.OptimisticOptimizations; +import org.graalvm.compiler.phases.Phase; import org.graalvm.compiler.phases.PhaseSuite; import org.graalvm.compiler.phases.common.CanonicalizerPhase; import org.graalvm.compiler.phases.tiers.HighTierContext; @@ -746,6 +747,27 @@ protected EncodedGraph lookupEncodedGraph(ResolvedJavaMethod method, BytecodePro } } + // Wrapper to clearly identify phase + class TrivialInlinePhase extends Phase { + final InliningGraphDecoder decoder; + final HostedMethod method; + + TrivialInlinePhase(InliningGraphDecoder decoder, HostedMethod method) { + this.decoder = decoder; + this.method = method; + } + + @Override + protected void run(StructuredGraph graph) { + decoder.decode(method); + } + + @Override + public CharSequence getName() { + return "TrivialInline"; + } + } + @SuppressWarnings("try") private void doInlineTrivial(DebugContext debug, HostedMethod method) { /* @@ -770,7 +792,7 @@ private void doInlineTrivial(DebugContext debug, HostedMethod method) { try (var s = debug.scope("InlineTrivial", graph, method, this)) { var inliningPlugin = new TrivialInliningPlugin(); var decoder = new InliningGraphDecoder(graph, providers, inliningPlugin); - decoder.decode(method); + new TrivialInlinePhase(decoder, method).apply(graph); if (inliningPlugin.inlinedDuringDecoding) { CanonicalizerPhase.create().apply(graph, providers);