From 9aa00c03f19ecfd0b2a2b603b928fa59fbe0ea5d Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Thu, 24 Aug 2023 19:11:04 +0200 Subject: [PATCH 01/19] improve stamps of deopt proxies --- .../compiler/graal/nodes/ValuePhiNode.java | 39 ++++++++++++++----- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/compiler/src/jdk.compiler.graal/src/jdk/compiler/graal/nodes/ValuePhiNode.java b/compiler/src/jdk.compiler.graal/src/jdk/compiler/graal/nodes/ValuePhiNode.java index d1b4d3e92801..739b02ebea71 100644 --- a/compiler/src/jdk.compiler.graal/src/jdk/compiler/graal/nodes/ValuePhiNode.java +++ b/compiler/src/jdk.compiler.graal/src/jdk/compiler/graal/nodes/ValuePhiNode.java @@ -34,6 +34,7 @@ import jdk.compiler.graal.graph.NodeInputList; import jdk.compiler.graal.nodeinfo.InputType; import jdk.compiler.graal.nodeinfo.NodeInfo; +import jdk.compiler.graal.nodes.spi.LimitedValueProxy; import jdk.compiler.graal.nodes.type.StampTool; import jdk.compiler.graal.util.CollectionsUtil; @@ -129,7 +130,7 @@ public boolean inferStamp() { */ private Stamp tryInferLoopPhiStamp(Stamp valuesStamp) { if (isAlive() && isLoopPhi() && valuesStamp.isPointerStamp()) { - Stamp firstValueStamp = firstValue().stamp(NodeView.DEFAULT); + Stamp firstValueStamp = stripProxies(firstValue()).stamp(NodeView.DEFAULT); if (firstValueStamp.meet(valuesStamp).equals(firstValueStamp)) { /* * Even the first value's stamp is not more precise than the current stamp, we won't @@ -137,14 +138,14 @@ private Stamp tryInferLoopPhiStamp(Stamp valuesStamp) { */ return valuesStamp; } - boolean hasDirectPhiOrProxyInput = false; + boolean hasDirectPhiInput = false; for (ValueNode value : values()) { - if (value instanceof ValuePhiNode || value instanceof ValueProxyNode) { - hasDirectPhiOrProxyInput = true; + if (stripProxies(value) instanceof ValuePhiNode) { + hasDirectPhiInput = true; break; } } - if (!hasDirectPhiOrProxyInput) { + if (!hasDirectPhiInput) { // Nothing to recurse over. return valuesStamp; } @@ -153,13 +154,12 @@ private Stamp tryInferLoopPhiStamp(Stamp valuesStamp) { NodeFlood flood = new NodeFlood(graph()); flood.addAll(values()); for (Node node : flood) { - if (node == this) { + Node unproxifiedNode = stripProxies(node); + if (unproxifiedNode == this) { // Don't use this value's stamp as that is what we are computing. - } else if (node instanceof ValuePhiNode phi) { + } else if (unproxifiedNode instanceof ValuePhiNode phi) { flood.addAll(phi.values()); - } else if (node instanceof ValueProxyNode proxy) { - flood.add(proxy.value()); - } else if (node instanceof ValueNode value) { + } else if (unproxifiedNode instanceof ValueNode value) { currentStamp = currentStamp.meet(value.stamp(NodeView.DEFAULT)); if (currentStamp.equals(valuesStamp)) { // We won't become more precise. @@ -175,6 +175,25 @@ private Stamp tryInferLoopPhiStamp(Stamp valuesStamp) { return valuesStamp; } + private static Node stripProxies(Node n) { + if (n instanceof ValueNode value) { + return stripProxies(value); + } + return n; + } + + /** + * Proxies with the same stamp as the original node should be ignored when trying to infer a + * loop stamp. + */ + private static ValueNode stripProxies(ValueNode v) { + ValueNode result = v; + while (result instanceof LimitedValueProxy proxy && proxy.getOriginalNode().stamp(NodeView.DEFAULT).equals(result.stamp(NodeView.DEFAULT))) { + result = proxy.getOriginalNode(); + } + return result; + } + @Override public boolean verify() { Stamp s = null; From 538a1bfdad8187594129a0bbff3f3c9d30213788 Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Mon, 28 Aug 2023 18:55:18 +0200 Subject: [PATCH 02/19] add custom providers for runtime compilation --- .../graal/pointsto/meta/HostedProviders.java | 6 +- .../ParseOnceRuntimeCompilationFeature.java | 70 ++++++++++++++++--- .../svm/hosted/NativeImageGenerator.java | 2 +- .../svm/hosted/RuntimeCompilationSupport.java | 3 +- .../AnalysisConstantReflectionProvider.java | 4 +- .../meta/HostedConstantFieldProvider.java | 8 ++- 6 files changed, 77 insertions(+), 16 deletions(-) diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/HostedProviders.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/HostedProviders.java index bf59d5ec56d9..4ec055a81f4e 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/HostedProviders.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/HostedProviders.java @@ -61,21 +61,21 @@ public void setGraphBuilderPlugins(GraphBuilderConfiguration.Plugins graphBuilde } @Override - public Providers copyWith(ConstantReflectionProvider substitution) { + public HostedProviders copyWith(ConstantReflectionProvider substitution) { assert this.getClass() == HostedProviders.class : "must override in " + getClass(); return new HostedProviders(getMetaAccess(), getCodeCache(), substitution, getConstantFieldProvider(), getForeignCalls(), getLowerer(), getReplacements(), getStampProvider(), getSnippetReflection(), getWordTypes(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), getLoopsDataProvider()); } @Override - public Providers copyWith(ConstantFieldProvider substitution) { + public HostedProviders copyWith(ConstantFieldProvider substitution) { assert this.getClass() == HostedProviders.class : "must override in " + getClass(); return new HostedProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), substitution, getForeignCalls(), getLowerer(), getReplacements(), getStampProvider(), getSnippetReflection(), getWordTypes(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), getLoopsDataProvider()); } @Override - public Providers copyWith(Replacements substitution) { + public HostedProviders copyWith(Replacements substitution) { assert this.getClass() == HostedProviders.class : "must override in " + getClass(); return new HostedProviders(getMetaAccess(), getCodeCache(), getConstantReflection(), getConstantFieldProvider(), getForeignCalls(), getLowerer(), substitution, getStampProvider(), getSnippetReflection(), getWordTypes(), getPlatformConfigurationProvider(), getMetaAccessExtensionProvider(), getLoopsDataProvider()); diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/ParseOnceRuntimeCompilationFeature.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/ParseOnceRuntimeCompilationFeature.java index 01d462b54313..fc641f70f289 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/ParseOnceRuntimeCompilationFeature.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/ParseOnceRuntimeCompilationFeature.java @@ -58,6 +58,7 @@ import com.oracle.graal.pointsto.flow.InvokeTypeFlow; import com.oracle.graal.pointsto.flow.MethodFlowsGraph; import com.oracle.graal.pointsto.infrastructure.GraphProvider; +import com.oracle.graal.pointsto.meta.AnalysisField; import com.oracle.graal.pointsto.meta.AnalysisMetaAccess; import com.oracle.graal.pointsto.meta.AnalysisMethod; import com.oracle.graal.pointsto.meta.AnalysisType; @@ -82,10 +83,15 @@ import com.oracle.svm.hosted.HeapBreakdownProvider; import com.oracle.svm.hosted.RuntimeCompilationSupport; import com.oracle.svm.hosted.SVMHost; +import com.oracle.svm.hosted.ameta.AnalysisConstantFieldProvider; +import com.oracle.svm.hosted.ameta.AnalysisConstantReflectionProvider; import com.oracle.svm.hosted.analysis.SVMParsingSupport; +import com.oracle.svm.hosted.classinitialization.ClassInitializationSupport; import com.oracle.svm.hosted.code.CompileQueue; import com.oracle.svm.hosted.code.DeoptimizationUtils; import com.oracle.svm.hosted.code.SubstrateCompilationDirectives; +import com.oracle.svm.hosted.meta.HostedConstantFieldProvider; +import com.oracle.svm.hosted.meta.HostedField; import com.oracle.svm.hosted.meta.HostedMethod; import com.oracle.svm.hosted.meta.HostedUniverse; import com.oracle.svm.hosted.nodes.DeoptProxyNode; @@ -132,7 +138,10 @@ import jdk.compiler.graal.word.WordTypes; import jdk.vm.ci.code.BytecodeFrame; import jdk.vm.ci.code.BytecodePosition; +import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; +import jdk.vm.ci.meta.MetaAccessProvider; +import jdk.vm.ci.meta.ResolvedJavaField; import jdk.vm.ci.meta.ResolvedJavaMethod; import jdk.vm.ci.meta.ResolvedJavaType; @@ -324,8 +333,10 @@ protected boolean shouldVerifyFrameStates() { private Map runtimeCandidateCallTree = null; private Map runtimeCompiledMethodCallTree = null; private HostedProviders analysisProviders = null; + private HostedProviders runtimeCompilationProviders = null; private AllowInliningPredicate allowInliningPredicate = (builder, target) -> AllowInliningPredicate.InlineDecision.INLINING_DISALLOWED; private boolean allowInliningPredicateUpdated = false; + private Function constantFieldProviderWrapper = Function.identity(); @Override public List> getRequiredFeatures() { @@ -360,7 +371,8 @@ public void registerAllowInliningPredicate(AllowInliningPredicate predicate) { @Override public void initializeAnalysisProviders(BigBang bb, Function generator) { HostedProviders defaultProviders = bb.getProviders(ORIGINAL_METHOD); - HostedProviders customHostedProviders = (HostedProviders) defaultProviders.copyWith(generator.apply(defaultProviders.getConstantFieldProvider())); + HostedProviders customHostedProviders = defaultProviders.copyWith(generator.apply(defaultProviders.getConstantFieldProvider())); + constantFieldProviderWrapper = generator; customHostedProviders.setGraphBuilderPlugins(hostedProviders.getGraphBuilderPlugins()); analysisProviders = customHostedProviders; } @@ -584,15 +596,15 @@ private void compileRuntimeCompiledMethod(DebugContext debug, HostedMethod metho ConvertDeoptimizeToGuardPhase convertDeoptimizeToGuard = new ConvertDeoptimizeToGuardPhase(canonicalizer); try (DebugContext.Scope s = debug.scope("RuntimeOptimize", graph, method, this)) { - canonicalizer.apply(graph, hostedProviders); + canonicalizer.apply(graph, runtimeCompilationProviders); - conditionalElimination.apply(graph, hostedProviders); + conditionalElimination.apply(graph, runtimeCompilationProviders); /* * ConvertDeoptimizeToGuardPhase was already executed after parsing, but optimizations * applied in between can provide new potential. */ - convertDeoptimizeToGuard.apply(graph, hostedProviders); + convertDeoptimizeToGuard.apply(graph, runtimeCompilationProviders); /* * More optimizations can be added here. @@ -634,7 +646,7 @@ private void encodeRuntimeCompiledMethods() { for (var runtimeInfo : runtimeGraphs.entrySet()) { var graph = runtimeInfo.getValue(); var method = runtimeInfo.getKey(); - DebugContext debug = new DebugContext.Builder(graph.getOptions(), new GraalDebugHandlersFactory(hostedProviders.getSnippetReflection())).build(); + DebugContext debug = new DebugContext.Builder(graph.getOptions(), new GraalDebugHandlersFactory(runtimeCompilationProviders.getSnippetReflection())).build(); graph.resetDebug(debug); try (DebugContext.Scope s = debug.scope("Graph Encoding", graph); DebugContext.Activation a = debug.activate()) { @@ -660,12 +672,16 @@ public void beforeCompilation(BeforeCompilationAccess c) { } @Override - public void onCompileQueueCreation(HostedUniverse universe, CompileQueue compileQueue) { + public void onCompileQueueCreation(BigBang bb, HostedUniverse hUniverse, CompileQueue compileQueue) { /* * Start fresh with a new GraphEncoder, since we are going to optimize all graphs now that * the static analysis results are available. */ graphEncoder = new GraphEncoder(ConfigurationValues.getTarget().arch); + assert runtimeCompilationProviders == null; + runtimeCompilationProviders = hostedProviders + .copyWith(constantFieldProviderWrapper.apply(new RuntimeCompilationFieldProvider(hostedProviders.getMetaAccess(), hUniverse))) + .copyWith(new RuntimeCompilationReflectionProvider(bb, hUniverse.hostVM().getClassInitializationSupport())); SubstrateCompilationDirectives.singleton().resetDeoptEntries(); /* @@ -674,7 +690,7 @@ public void onCompileQueueCreation(HostedUniverse universe, CompileQueue compile CompletionExecutor executor = compileQueue.getExecutor(); try { compileQueue.runOnExecutor(() -> { - universe.getMethods().stream().map(method -> method.getMultiMethod(RUNTIME_COMPILED_METHOD)).filter(method -> { + hUniverse.getMethods().stream().map(method -> method.getMultiMethod(RUNTIME_COMPILED_METHOD)).filter(method -> { if (method != null) { AnalysisMethod aMethod = method.getWrapped(); return aMethod.isImplementationInvoked() && !invalidForRuntimeCompilation.containsKey(aMethod); @@ -710,7 +726,7 @@ protected PhaseSuite getAfterParseSuite() { } }; - universe.getMethods().stream().map(method -> method.getMultiMethod(DEOPT_TARGET_METHOD)).filter(method -> { + hUniverse.getMethods().stream().map(method -> method.getMultiMethod(DEOPT_TARGET_METHOD)).filter(method -> { if (method != null) { return compileQueue.isRegisteredDeoptTarget(method); } @@ -1243,6 +1259,44 @@ public boolean insertPlaceholderParamAndReturnFlows(MultiMethod.MultiMethodKey m } } + /** + * Since we perform runtime compilation after universe creation, we can leverage components of + * the hosted universe provider for identifying final fields. + */ + private static class RuntimeCompilationFieldProvider extends AnalysisConstantFieldProvider { + final HostedUniverse hUniverse; + + RuntimeCompilationFieldProvider(MetaAccessProvider metaAccess, HostedUniverse hUniverse) { + super(metaAccess, hUniverse.hostVM()); + this.hUniverse = hUniverse; + } + + @Override + public boolean isFinalField(ResolvedJavaField f, ConstantFieldTool tool) { + HostedField hField = hUniverse.lookup(f); + if (HostedConstantFieldProvider.isFinalField(hField)) { + return true; + } + return super.isFinalField(f, tool); + } + } + + private static class RuntimeCompilationReflectionProvider extends AnalysisConstantReflectionProvider { + + RuntimeCompilationReflectionProvider(BigBang bb, ClassInitializationSupport classInitializationSupport) { + super(bb.getUniverse(), bb.getMetaAccess(), classInitializationSupport); + } + + @Override + public JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant receiver) { + /* + * We cannot fold simulated values during initial before-analysis graph creation; + * however, this runs after analysis has completed. + */ + return readValue(metaAccess, (AnalysisField) field, receiver, true); + } + } + /** * Removes {@link DeoptEntryNode}s, {@link DeoptProxyAnchorNode}s, and {@link DeoptProxyNode}s * which are determined to be unnecessary after the runtime compilation methods are optimized. 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 a1d2969b212e..a0b88fe4872c 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 @@ -674,7 +674,7 @@ protected void doRun(Map entryPoints, compileQueue = HostedConfiguration.instance().createCompileQueue(debug, featureHandler, hUniverse, runtimeConfiguration, DeoptTester.enabled(), bb.getSnippetReflectionProvider(), compilationExecutor); if (ImageSingletons.contains(RuntimeCompilationSupport.class)) { - ImageSingletons.lookup(RuntimeCompilationSupport.class).onCompileQueueCreation(hUniverse, compileQueue); + ImageSingletons.lookup(RuntimeCompilationSupport.class).onCompileQueueCreation(bb, hUniverse, compileQueue); } compileQueue.finish(debug); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/RuntimeCompilationSupport.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/RuntimeCompilationSupport.java index 1dd39a3deff4..a6530ef70880 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/RuntimeCompilationSupport.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/RuntimeCompilationSupport.java @@ -24,9 +24,10 @@ */ package com.oracle.svm.hosted; +import com.oracle.graal.pointsto.BigBang; import com.oracle.svm.hosted.code.CompileQueue; import com.oracle.svm.hosted.meta.HostedUniverse; public interface RuntimeCompilationSupport { - void onCompileQueueCreation(HostedUniverse universe, CompileQueue compileQueue); + void onCompileQueueCreation(BigBang bb, HostedUniverse hUniverse, CompileQueue compileQueue); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java index 9aaa6bc96f41..5ea8c09d98dc 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ameta/AnalysisConstantReflectionProvider.java @@ -72,7 +72,7 @@ @Platforms(Platform.HOSTED_ONLY.class) public class AnalysisConstantReflectionProvider extends SharedConstantReflectionProvider { private final AnalysisUniverse universe; - private final UniverseMetaAccess metaAccess; + protected final UniverseMetaAccess metaAccess; private HostedMetaAccess hMetaAccess; private final ClassInitializationSupport classInitializationSupport; private final AnalysisMethodHandleAccessProvider methodHandleAccess; @@ -186,7 +186,7 @@ public void forEachArrayElement(JavaConstant array, ObjIntConsumer } @Override - public final JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant receiver) { + public JavaConstant readFieldValue(ResolvedJavaField field, JavaConstant receiver) { return readValue(metaAccess, (AnalysisField) field, receiver, false); } diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedConstantFieldProvider.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedConstantFieldProvider.java index 481ad0176b39..a9a77fc8be66 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedConstantFieldProvider.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/meta/HostedConstantFieldProvider.java @@ -49,13 +49,19 @@ public HostedConstantFieldProvider(MetaAccessProvider metaAccess, SVMHost hostVM @Override public boolean isFinalField(ResolvedJavaField f, ConstantFieldTool tool) { HostedField field = (HostedField) f; + if (isFinalField(field)) { + return true; + } + return super.isFinalField(field, tool); + } + public static boolean isFinalField(HostedField field) { if (field.location == HostedField.LOC_UNMATERIALIZED_STATIC_CONSTANT) { return true; } else if (!field.isWritten() && field.isValueAvailable()) { return true; } - return super.isFinalField(field, tool); + return false; } @Override From c8fa4c3a3f1d3def8f1cfb05ef554d6a3daf92ea Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Mon, 28 Aug 2023 18:56:55 +0200 Subject: [PATCH 03/19] make runtime compilation implicit null checks explicit to analysis. --- .../com/oracle/graal/pointsto/api/HostVM.java | 5 + .../pointsto/flow/MethodTypeFlowBuilder.java | 129 +++++++++++------- .../src/com/oracle/svm/hosted/SVMHost.java | 5 + 3 files changed, 93 insertions(+), 46 deletions(-) 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 127d7412cee0..40cc2482c717 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 @@ -410,6 +410,11 @@ public boolean allowConstantFolding(AnalysisMethod method) { return method.isOriginalMethod(); } + @SuppressWarnings("unused") + public boolean addImplicitTypeflowNullChecks(AnalysisMethod method) { + return false; + } + public FieldValueComputer createFieldValueComputer(@SuppressWarnings("unused") AnalysisField field) { return null; } 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 9e1c718c4c4b..4667828efd2d 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 @@ -34,8 +34,42 @@ import java.util.Map; import java.util.Optional; +import org.graalvm.nativeimage.AnnotationAccess; + +import com.oracle.graal.pointsto.AbstractAnalysisEngine; +import com.oracle.graal.pointsto.ObjectScanner.EmbeddedRootScan; +import com.oracle.graal.pointsto.PointsToAnalysis; +import com.oracle.graal.pointsto.api.PointstoOptions; +import com.oracle.graal.pointsto.flow.LoadFieldTypeFlow.LoadInstanceFieldTypeFlow; +import com.oracle.graal.pointsto.flow.LoadFieldTypeFlow.LoadStaticFieldTypeFlow; +import com.oracle.graal.pointsto.flow.MethodFlowsGraph.GraphKind; +import com.oracle.graal.pointsto.flow.OffsetLoadTypeFlow.LoadIndexedTypeFlow; +import com.oracle.graal.pointsto.flow.OffsetLoadTypeFlow.UnsafeLoadTypeFlow; +import com.oracle.graal.pointsto.flow.OffsetLoadTypeFlow.UnsafePartitionLoadTypeFlow; +import com.oracle.graal.pointsto.flow.OffsetStoreTypeFlow.StoreIndexedTypeFlow; +import com.oracle.graal.pointsto.flow.OffsetStoreTypeFlow.UnsafePartitionStoreTypeFlow; +import com.oracle.graal.pointsto.flow.OffsetStoreTypeFlow.UnsafeStoreTypeFlow; +import com.oracle.graal.pointsto.flow.StoreFieldTypeFlow.StoreInstanceFieldTypeFlow; +import com.oracle.graal.pointsto.flow.StoreFieldTypeFlow.StoreStaticFieldTypeFlow; +import com.oracle.graal.pointsto.flow.builder.TypeFlowBuilder; +import com.oracle.graal.pointsto.flow.builder.TypeFlowGraphBuilder; +import com.oracle.graal.pointsto.meta.AnalysisField; +import com.oracle.graal.pointsto.meta.AnalysisMethod; +import com.oracle.graal.pointsto.meta.AnalysisType; +import com.oracle.graal.pointsto.meta.HostedProviders; +import com.oracle.graal.pointsto.meta.PointsToAnalysisMethod; +import com.oracle.graal.pointsto.nodes.UnsafePartitionLoadNode; +import com.oracle.graal.pointsto.nodes.UnsafePartitionStoreNode; +import com.oracle.graal.pointsto.phases.InlineBeforeAnalysis; +import com.oracle.graal.pointsto.results.StaticAnalysisResultsBuilder; +import com.oracle.graal.pointsto.results.StrengthenGraphs; +import com.oracle.graal.pointsto.typestate.TypeState; +import com.oracle.graal.pointsto.util.AnalysisError; +import com.oracle.svm.common.meta.MultiMethod; + import jdk.compiler.graal.core.common.spi.ForeignCallDescriptor; import jdk.compiler.graal.core.common.spi.ForeignCallsProvider; +import jdk.compiler.graal.core.common.type.AbstractObjectStamp; import jdk.compiler.graal.core.common.type.ObjectStamp; import jdk.compiler.graal.core.common.type.TypeReference; import jdk.compiler.graal.debug.DebugContext; @@ -110,39 +144,6 @@ import jdk.compiler.graal.replacements.nodes.ObjectClone; import jdk.compiler.graal.replacements.nodes.UnaryMathIntrinsicNode; import jdk.compiler.graal.virtual.phases.ea.PartialEscapePhase; -import org.graalvm.nativeimage.AnnotationAccess; - -import com.oracle.graal.pointsto.AbstractAnalysisEngine; -import com.oracle.graal.pointsto.ObjectScanner.EmbeddedRootScan; -import com.oracle.graal.pointsto.PointsToAnalysis; -import com.oracle.graal.pointsto.api.PointstoOptions; -import com.oracle.graal.pointsto.flow.LoadFieldTypeFlow.LoadInstanceFieldTypeFlow; -import com.oracle.graal.pointsto.flow.LoadFieldTypeFlow.LoadStaticFieldTypeFlow; -import com.oracle.graal.pointsto.flow.MethodFlowsGraph.GraphKind; -import com.oracle.graal.pointsto.flow.OffsetLoadTypeFlow.LoadIndexedTypeFlow; -import com.oracle.graal.pointsto.flow.OffsetLoadTypeFlow.UnsafeLoadTypeFlow; -import com.oracle.graal.pointsto.flow.OffsetLoadTypeFlow.UnsafePartitionLoadTypeFlow; -import com.oracle.graal.pointsto.flow.OffsetStoreTypeFlow.StoreIndexedTypeFlow; -import com.oracle.graal.pointsto.flow.OffsetStoreTypeFlow.UnsafePartitionStoreTypeFlow; -import com.oracle.graal.pointsto.flow.OffsetStoreTypeFlow.UnsafeStoreTypeFlow; -import com.oracle.graal.pointsto.flow.StoreFieldTypeFlow.StoreInstanceFieldTypeFlow; -import com.oracle.graal.pointsto.flow.StoreFieldTypeFlow.StoreStaticFieldTypeFlow; -import com.oracle.graal.pointsto.flow.builder.TypeFlowBuilder; -import com.oracle.graal.pointsto.flow.builder.TypeFlowGraphBuilder; -import com.oracle.graal.pointsto.meta.AnalysisField; -import com.oracle.graal.pointsto.meta.AnalysisMethod; -import com.oracle.graal.pointsto.meta.AnalysisType; -import com.oracle.graal.pointsto.meta.HostedProviders; -import com.oracle.graal.pointsto.meta.PointsToAnalysisMethod; -import com.oracle.graal.pointsto.nodes.UnsafePartitionLoadNode; -import com.oracle.graal.pointsto.nodes.UnsafePartitionStoreNode; -import com.oracle.graal.pointsto.phases.InlineBeforeAnalysis; -import com.oracle.graal.pointsto.results.StaticAnalysisResultsBuilder; -import com.oracle.graal.pointsto.results.StrengthenGraphs; -import com.oracle.graal.pointsto.typestate.TypeState; -import com.oracle.graal.pointsto.util.AnalysisError; -import com.oracle.svm.common.meta.MultiMethod; - import jdk.vm.ci.code.BytecodePosition; import jdk.vm.ci.meta.Constant; import jdk.vm.ci.meta.JavaConstant; @@ -162,6 +163,7 @@ public class MethodTypeFlowBuilder { private final MethodFlowsGraph.GraphKind graphKind; private boolean processed = false; private final boolean newFlowsGraph; + private final boolean addImplicitNullChecks; protected final TypeFlowGraphBuilder typeFlowGraphBuilder; protected List> postInitFlows = List.of(); @@ -170,6 +172,7 @@ public MethodTypeFlowBuilder(PointsToAnalysis bb, PointsToAnalysisMethod method, this.bb = bb; this.method = method; this.graphKind = graphKind; + addImplicitNullChecks = bb.getHostVM().addImplicitTypeflowNullChecks(method); if (flowsGraph == null) { this.flowsGraph = new MethodFlowsGraph(method, graphKind); newFlowsGraph = true; @@ -1041,8 +1044,7 @@ protected void node(FixedNode n) { state.add(node, newArrayBuilder); - } else if (n instanceof LoadFieldNode) { // value = object.field - LoadFieldNode node = (LoadFieldNode) n; + } else if (n instanceof LoadFieldNode node) { // value = object.field AnalysisField field = (AnalysisField) node.field(); assert field.isAccessed() : field; if (node.getStackKind() == JavaKind.Object) { @@ -1069,12 +1071,17 @@ protected void node(FixedNode n) { } state.add(node, loadFieldBuilder); } + if (addImplicitNullChecks && node.object() != null) { + processImplicitNonNull(node.object(), state); + } - } else if (n instanceof StoreFieldNode) { // object.field = value - processStoreField((StoreFieldNode) n, state); + } else if (n instanceof StoreFieldNode node) { // object.field = value + processStoreField(node, state); + if (addImplicitNullChecks && node.object() != null) { + processImplicitNonNull(node.object(), state); + } - } else if (n instanceof LoadIndexedNode) { - LoadIndexedNode node = (LoadIndexedNode) n; + } else if (n instanceof LoadIndexedNode node) { TypeFlowBuilder arrayBuilder = state.lookup(node.array()); if (node.getStackKind() == JavaKind.Object) { AnalysisType type = (AnalysisType) StampTool.typeOrNull(node.array(), bb.getMetaAccess()); @@ -1092,9 +1099,15 @@ protected void node(FixedNode n) { loadIndexedBuilder.addObserverDependency(arrayBuilder); state.add(node, loadIndexedBuilder); } + if (addImplicitNullChecks) { + processImplicitNonNull(node.array(), state); + } - } else if (n instanceof StoreIndexedNode) { - processStoreIndexed((StoreIndexedNode) n, state); + } else if (n instanceof StoreIndexedNode node) { + processStoreIndexed(node, state); + if (addImplicitNullChecks) { + processImplicitNonNull(node.array(), state); + } } else if (n instanceof UnsafePartitionLoadNode) { UnsafePartitionLoadNode node = (UnsafePartitionLoadNode) n; @@ -1309,13 +1322,17 @@ protected void node(FixedNode n) { } else if (n instanceof InvokeNode || n instanceof InvokeWithExceptionNode) { Invoke invoke = (Invoke) n; - if (invoke.callTarget() instanceof MethodCallTargetNode) { + if (invoke.callTarget() instanceof MethodCallTargetNode target) { guarantee(bb.strengthenGraalGraphs() || invoke.stateAfter().outerFrameState() == null, "Outer FrameState of %s must be null, but was %s. A non-null outer FrameState indicates that a method inlining has happened, but inlining should only happen after analysis.", invoke.stateAfter(), invoke.stateAfter().outerFrameState()); - MethodCallTargetNode target = (MethodCallTargetNode) invoke.callTarget(); - processMethodInvocation(state, invoke, target.invokeKind(), (PointsToAnalysisMethod) target.targetMethod(), target.arguments()); + var arguments = target.arguments(); + processMethodInvocation(state, invoke, target.invokeKind(), (PointsToAnalysisMethod) target.targetMethod(), arguments); + + if (addImplicitNullChecks && target.invokeKind().hasReceiver()) { + processImplicitNonNull(arguments.get(0), invoke.asNode(), state); + } } } else if (n instanceof ObjectClone) { @@ -1342,7 +1359,7 @@ protected void node(FixedNode n) { monitorEntryBuilder.addUseDependency(objectBuilder); /* Monitor enters must not be removed. */ typeFlowGraphBuilder.registerSinkBuilder(monitorEntryBuilder); - } else if (n instanceof MacroInvokable) { + } else if (n instanceof MacroInvokable node) { /* * Macro nodes can either be constant folded during compilation, or lowered back to * invocations if constant folding is not possible. So the static analysis needs to @@ -1351,8 +1368,10 @@ protected void node(FixedNode n) { * Note that some macro nodes, like for object cloning, are handled separately * above. */ - MacroInvokable node = (MacroInvokable) n; processMacroInvokable(state, node, true); + if (addImplicitNullChecks && node.getInvokeKind().hasReceiver()) { + processImplicitNonNull(node.getArgument(0), node.asNode(), state); + } } } @@ -1763,4 +1782,22 @@ private void processStoreIndexed(ValueNode node, ValueNode array, ValueNode valu /** Hook for unsafe offset value checks. */ protected void checkUnsafeOffset(@SuppressWarnings("unused") ValueNode base, @SuppressWarnings("unused") ValueNode offset) { } + + private void processImplicitNonNull(ValueNode node, TypeFlowsOfNodes state) { + processImplicitNonNull(node, node, state); + } + + private void processImplicitNonNull(ValueNode node, ValueNode source, TypeFlowsOfNodes state) { + assert addImplicitNullChecks && node.stamp(NodeView.DEFAULT) instanceof AbstractObjectStamp; + if (!StampTool.isPointerNonNull(node)) { + TypeFlowBuilder inputBuilder = state.lookup(node); + TypeFlowBuilder nullCheckBuilder = TypeFlowBuilder.create(bb, source, NullCheckTypeFlow.class, () -> { + NullCheckTypeFlow nullCheckFlow = new NullCheckTypeFlow(AbstractAnalysisEngine.sourcePosition(source), inputBuilder.get().getDeclaredType(), true); + flowsGraph.addMiscEntryFlow(nullCheckFlow); + return nullCheckFlow; + }); + nullCheckBuilder.addUseDependency(inputBuilder); + state.update(node, nullCheckBuilder); + } + } } 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 b273ee4a5818..3cd819124ceb 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 @@ -977,6 +977,11 @@ public boolean allowConstantFolding(AnalysisMethod method) { return method.isOriginalMethod() && !SubstrateCompilationDirectives.singleton().isRegisteredForDeoptTesting(method); } + @Override + public boolean addImplicitTypeflowNullChecks(AnalysisMethod method) { + return SubstrateCompilationDirectives.isRuntimeCompiledMethod(method); + } + @Override public FieldValueComputer createFieldValueComputer(AnalysisField field) { UnknownObjectField unknownObjectField = field.getAnnotation(UnknownObjectField.class); From acdf4c54c3c3a9b10281fa6445604a22824ab019 Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Tue, 10 Oct 2023 10:43:17 +0200 Subject: [PATCH 04/19] Change implicit nullcheck filter. --- .../com/oracle/graal/pointsto/api/HostVM.java | 5 ----- .../pointsto/flow/MethodTypeFlowBuilder.java | 22 +++++++------------ .../src/com/oracle/svm/hosted/SVMHost.java | 5 ----- .../flow/SVMMethodTypeFlowBuilder.java | 16 ++++++++++++++ 4 files changed, 24 insertions(+), 24 deletions(-) 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 40cc2482c717..127d7412cee0 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 @@ -410,11 +410,6 @@ public boolean allowConstantFolding(AnalysisMethod method) { return method.isOriginalMethod(); } - @SuppressWarnings("unused") - public boolean addImplicitTypeflowNullChecks(AnalysisMethod method) { - return false; - } - public FieldValueComputer createFieldValueComputer(@SuppressWarnings("unused") AnalysisField field) { return null; } 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 4667828efd2d..42aa72fec1ba 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 @@ -163,7 +163,6 @@ public class MethodTypeFlowBuilder { private final MethodFlowsGraph.GraphKind graphKind; private boolean processed = false; private final boolean newFlowsGraph; - private final boolean addImplicitNullChecks; protected final TypeFlowGraphBuilder typeFlowGraphBuilder; protected List> postInitFlows = List.of(); @@ -172,7 +171,6 @@ public MethodTypeFlowBuilder(PointsToAnalysis bb, PointsToAnalysisMethod method, this.bb = bb; this.method = method; this.graphKind = graphKind; - addImplicitNullChecks = bb.getHostVM().addImplicitTypeflowNullChecks(method); if (flowsGraph == null) { this.flowsGraph = new MethodFlowsGraph(method, graphKind); newFlowsGraph = true; @@ -1071,13 +1069,13 @@ protected void node(FixedNode n) { } state.add(node, loadFieldBuilder); } - if (addImplicitNullChecks && node.object() != null) { + if (node.object() != null) { processImplicitNonNull(node.object(), state); } } else if (n instanceof StoreFieldNode node) { // object.field = value processStoreField(node, state); - if (addImplicitNullChecks && node.object() != null) { + if (node.object() != null) { processImplicitNonNull(node.object(), state); } @@ -1099,15 +1097,11 @@ protected void node(FixedNode n) { loadIndexedBuilder.addObserverDependency(arrayBuilder); state.add(node, loadIndexedBuilder); } - if (addImplicitNullChecks) { - processImplicitNonNull(node.array(), state); - } + processImplicitNonNull(node.array(), state); } else if (n instanceof StoreIndexedNode node) { processStoreIndexed(node, state); - if (addImplicitNullChecks) { - processImplicitNonNull(node.array(), state); - } + processImplicitNonNull(node.array(), state); } else if (n instanceof UnsafePartitionLoadNode) { UnsafePartitionLoadNode node = (UnsafePartitionLoadNode) n; @@ -1330,7 +1324,7 @@ protected void node(FixedNode n) { var arguments = target.arguments(); processMethodInvocation(state, invoke, target.invokeKind(), (PointsToAnalysisMethod) target.targetMethod(), arguments); - if (addImplicitNullChecks && target.invokeKind().hasReceiver()) { + if (target.invokeKind().hasReceiver()) { processImplicitNonNull(arguments.get(0), invoke.asNode(), state); } } @@ -1369,7 +1363,7 @@ protected void node(FixedNode n) { * above. */ processMacroInvokable(state, node, true); - if (addImplicitNullChecks && node.getInvokeKind().hasReceiver()) { + if (node.getInvokeKind().hasReceiver()) { processImplicitNonNull(node.getArgument(0), node.asNode(), state); } } @@ -1787,8 +1781,8 @@ private void processImplicitNonNull(ValueNode node, TypeFlowsOfNodes state) { processImplicitNonNull(node, node, state); } - private void processImplicitNonNull(ValueNode node, ValueNode source, TypeFlowsOfNodes state) { - assert addImplicitNullChecks && node.stamp(NodeView.DEFAULT) instanceof AbstractObjectStamp; + protected void processImplicitNonNull(ValueNode node, ValueNode source, TypeFlowsOfNodes state) { + assert node.stamp(NodeView.DEFAULT) instanceof AbstractObjectStamp; if (!StampTool.isPointerNonNull(node)) { TypeFlowBuilder inputBuilder = state.lookup(node); TypeFlowBuilder nullCheckBuilder = TypeFlowBuilder.create(bb, source, NullCheckTypeFlow.class, () -> { 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 3cd819124ceb..b273ee4a5818 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 @@ -977,11 +977,6 @@ public boolean allowConstantFolding(AnalysisMethod method) { return method.isOriginalMethod() && !SubstrateCompilationDirectives.singleton().isRegisteredForDeoptTesting(method); } - @Override - public boolean addImplicitTypeflowNullChecks(AnalysisMethod method) { - return SubstrateCompilationDirectives.isRuntimeCompiledMethod(method); - } - @Override public FieldValueComputer createFieldValueComputer(AnalysisField field) { UnknownObjectField unknownObjectField = field.getAnnotation(UnknownObjectField.class); diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/flow/SVMMethodTypeFlowBuilder.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/flow/SVMMethodTypeFlowBuilder.java index 2d1d9a4027fc..b1f9b8058236 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/flow/SVMMethodTypeFlowBuilder.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/analysis/flow/SVMMethodTypeFlowBuilder.java @@ -53,6 +53,7 @@ import com.oracle.svm.core.util.UserError.UserException; import com.oracle.svm.hosted.NativeImageOptions; import com.oracle.svm.hosted.SVMHost; +import com.oracle.svm.hosted.code.SubstrateCompilationDirectives; import com.oracle.svm.hosted.substitute.ComputedValueField; import jdk.vm.ci.code.BytecodePosition; @@ -61,8 +62,15 @@ public class SVMMethodTypeFlowBuilder extends MethodTypeFlowBuilder { + private final boolean addImplicitNullCheckFilters; + public SVMMethodTypeFlowBuilder(PointsToAnalysis bb, PointsToAnalysisMethod method, MethodFlowsGraph flowsGraph, MethodFlowsGraph.GraphKind graphKind) { super(bb, method, flowsGraph, graphKind); + /* + * We only add these filters for runtime compiled methods, as other multi-method variants + * require explicit null checks. + */ + addImplicitNullCheckFilters = SubstrateCompilationDirectives.isRuntimeCompiledMethod(method); } protected SVMHost getHostVM() { @@ -217,4 +225,12 @@ private void processInlinedInvokeArgumentsNode(TypeFlowsOfNodes state, InlinedIn InvokeKind invokeKind = targetMethod.isStatic() ? InvokeKind.Static : InvokeKind.Special; processMethodInvocation(state, node, invokeKind, targetMethod, node.getArguments(), true, getInvokePosition(node), true); } + + @Override + protected void processImplicitNonNull(ValueNode node, ValueNode source, TypeFlowsOfNodes state) { + // GR-49362 - remove after improving non-runtime graphs + if (addImplicitNullCheckFilters) { + super.processImplicitNonNull(node, source, state); + } + } } From f32e527c2cabcc60e4afe6af5dc173b24f8cbc47 Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Thu, 5 Oct 2023 16:38:43 +0200 Subject: [PATCH 05/19] disable snippet counters in more scenarios --- .../isolated/DisableSnippetCountersFeature.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/DisableSnippetCountersFeature.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/DisableSnippetCountersFeature.java index 2c89628638f6..0faa2a46d9dc 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/DisableSnippetCountersFeature.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/isolated/DisableSnippetCountersFeature.java @@ -24,7 +24,14 @@ */ package com.oracle.svm.graal.isolated; +import com.oracle.svm.core.ParsingReason; +import com.oracle.svm.core.SubstrateOptions; +import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; +import com.oracle.svm.core.feature.InternalFeature; +import com.oracle.svm.core.option.HostedOptionValues; + import jdk.compiler.graal.api.replacements.SnippetReflectionProvider; +import jdk.compiler.graal.core.common.GraalOptions; import jdk.compiler.graal.hotspot.SymbolicSnippetEncoder; import jdk.compiler.graal.nodes.ConstantNode; import jdk.compiler.graal.nodes.ValueNode; @@ -34,12 +41,6 @@ import jdk.compiler.graal.phases.util.Providers; import jdk.compiler.graal.replacements.SnippetCounter; import jdk.compiler.graal.replacements.SnippetIntegerHistogram; - -import com.oracle.svm.core.ParsingReason; -import com.oracle.svm.core.SubstrateOptions; -import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature; -import com.oracle.svm.core.feature.InternalFeature; - import jdk.vm.ci.meta.JavaConstant; import jdk.vm.ci.meta.JavaKind; import jdk.vm.ci.meta.ResolvedJavaField; @@ -72,12 +73,14 @@ public boolean handleLoadField(GraphBuilderContext b, ValueNode object, Resolved /** * Disables snippet counters because they need a {@link SnippetReflectionProvider} which is not * fully supported for cross-isolate compilations. + * + * In general snippets counters should only enabled if the flag SnippetCounters is set. */ @AutomaticallyRegisteredFeature final class DisableSnippetCountersFeature implements InternalFeature { @Override public boolean isInConfiguration(IsInConfigurationAccess access) { - return SubstrateOptions.supportCompileInIsolates(); + return SubstrateOptions.supportCompileInIsolates() || !GraalOptions.SnippetCounters.getValue(HostedOptionValues.singleton()); } @Override From a720e5bd681a385960b333dbfdccc43c5e3dccf4 Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Tue, 10 Oct 2023 11:42:36 +0200 Subject: [PATCH 06/19] add back in dominator based global value numbering --- .../hosted/ParseOnceRuntimeCompilationFeature.java | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/ParseOnceRuntimeCompilationFeature.java b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/ParseOnceRuntimeCompilationFeature.java index fc641f70f289..46667863224a 100644 --- a/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/ParseOnceRuntimeCompilationFeature.java +++ b/substratevm/src/com.oracle.svm.graal/src/com/oracle/svm/graal/hosted/ParseOnceRuntimeCompilationFeature.java @@ -46,7 +46,6 @@ import java.util.function.Supplier; import java.util.stream.Collectors; -import jdk.compiler.graal.graph.NodeSourcePosition; import org.graalvm.collections.EconomicMap; import org.graalvm.nativeimage.ImageSingletons; import org.graalvm.nativeimage.hosted.Feature; @@ -108,6 +107,7 @@ import jdk.compiler.graal.debug.DebugHandlersFactory; import jdk.compiler.graal.debug.Indent; import jdk.compiler.graal.graph.NodeClass; +import jdk.compiler.graal.graph.NodeSourcePosition; import jdk.compiler.graal.java.BytecodeParser; import jdk.compiler.graal.java.GraphBuilderPhase; import jdk.compiler.graal.loop.phases.ConvertDeoptimizeToGuardPhase; @@ -130,6 +130,7 @@ import jdk.compiler.graal.phases.Phase; import jdk.compiler.graal.phases.PhaseSuite; import jdk.compiler.graal.phases.common.CanonicalizerPhase; +import jdk.compiler.graal.phases.common.DominatorBasedGlobalValueNumberingPhase; import jdk.compiler.graal.phases.common.IterativeConditionalEliminationPhase; import jdk.compiler.graal.phases.tiers.HighTierContext; import jdk.compiler.graal.phases.util.Providers; @@ -591,20 +592,19 @@ private void compileRuntimeCompiledMethod(DebugContext debug, HostedMethod metho */ aMethod.setAnalyzedGraph(null); - CanonicalizerPhase canonicalizer = CanonicalizerPhase.create(); - IterativeConditionalEliminationPhase conditionalElimination = new IterativeConditionalEliminationPhase(canonicalizer, true); - ConvertDeoptimizeToGuardPhase convertDeoptimizeToGuard = new ConvertDeoptimizeToGuardPhase(canonicalizer); - try (DebugContext.Scope s = debug.scope("RuntimeOptimize", graph, method, this)) { + CanonicalizerPhase canonicalizer = CanonicalizerPhase.create(); canonicalizer.apply(graph, runtimeCompilationProviders); - conditionalElimination.apply(graph, runtimeCompilationProviders); + new DominatorBasedGlobalValueNumberingPhase(canonicalizer).apply(graph, runtimeCompilationProviders); + + new IterativeConditionalEliminationPhase(canonicalizer, true).apply(graph, runtimeCompilationProviders); /* * ConvertDeoptimizeToGuardPhase was already executed after parsing, but optimizations * applied in between can provide new potential. */ - convertDeoptimizeToGuard.apply(graph, runtimeCompilationProviders); + new ConvertDeoptimizeToGuardPhase(canonicalizer).apply(graph, runtimeCompilationProviders); /* * More optimizations can be added here. From 6f9f78ae5c08e2f2fb97f622b271b6920e393346 Mon Sep 17 00:00:00 2001 From: mspasic Date: Wed, 27 Sep 2023 14:56:04 +0200 Subject: [PATCH 07/19] Extract method createIndirectCall --- .../svm/core/graal/snippets/NonSnippetLowerings.java | 8 ++++++-- .../com/oracle/svm/hosted/image/NativeImageCodeCache.java | 2 +- 2 files changed, 7 insertions(+), 3 deletions(-) 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 92f9ecb66bb6..fd21e9fc6637 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 @@ -410,8 +410,7 @@ public void lower(FixedNode node, LoweringTool tool) { hub = graph.unique(new LoadHubNode(runtimeConfig.getProviders().getStampProvider(), graph.addOrUnique(PiNode.create(receiver, nullCheck)))); AddressNode address = graph.unique(new OffsetAddressNode(hub, ConstantNode.forIntegerKind(FrameAccess.getWordKind(), vtableEntryOffset, graph))); ReadNode entry = graph.add(new ReadNode(address, SubstrateBackend.getVTableIdentity(), FrameAccess.getWordStamp(), BarrierType.NONE, MemoryOrderMode.PLAIN)); - loweredCallTarget = graph.add( - new IndirectCallTargetNode(entry, parameters.toArray(new ValueNode[parameters.size()]), callTarget.returnStamp(), signature, method, callType, invokeKind)); + loweredCallTarget = createIndirectCall(graph, callTarget, parameters, method, signature, callType, invokeKind, entry); graph.addBeforeFixed(node, entry); } @@ -435,6 +434,11 @@ protected LoweredCallTargetNode createDirectCall(StructuredGraph graph, MethodCa callTarget.returnStamp(), signature, targetMethod, callType, invokeKind)); } + protected IndirectCallTargetNode createIndirectCall(StructuredGraph graph, MethodCallTargetNode callTarget, NodeInputList parameters, SharedMethod method, JavaType[] signature, + CallingConvention.Type callType, InvokeKind invokeKind, ReadNode entry) { + return graph.add(new IndirectCallTargetNode(entry, parameters.toArray(new ValueNode[parameters.size()]), callTarget.returnStamp(), signature, method, callType, invokeKind)); + } + private static CallTargetNode createUnreachableCallTarget(LoweringTool tool, FixedNode node, NodeInputList parameters, StampPair returnStamp, JavaType[] signature, SharedMethod method, CallingConvention.Type callType, InvokeKind invokeKind) { 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 c675e30840cb..d9adb0517ace 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 @@ -264,7 +264,7 @@ public int getAlignedConstantsSize() { } public void buildRuntimeMetadata(SnippetReflectionProvider snippetReflectionProvider, ForkJoinPool threadPool) { - buildRuntimeMetadata(snippetReflectionProvider, threadPool, new MethodPointer(getFirstCompilation().getLeft()), WordFactory.signed(getCodeAreaSize())); + buildRuntimeMetadata(snippetReflectionProvider, threadPool, new MethodPointer(getFirstCompilation().getLeft(), true), WordFactory.signed(getCodeAreaSize())); } protected void buildRuntimeMetadata(SnippetReflectionProvider snippetReflection, ForkJoinPool threadPool, CFunctionPointer firstMethod, UnsignedWord codeSize) { From 753b95faf270651f1be2af0b75c38e0eed6c3286 Mon Sep 17 00:00:00 2001 From: Tom Shull Date: Fri, 20 Oct 2023 19:03:40 +0200 Subject: [PATCH 08/19] address reviewer feedback. --- .../graal/pointsto/flow/MethodTypeFlowBuilder.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) 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 42aa72fec1ba..e9dc80ad1065 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 @@ -1782,11 +1782,16 @@ private void processImplicitNonNull(ValueNode node, TypeFlowsOfNodes state) { } protected void processImplicitNonNull(ValueNode node, ValueNode source, TypeFlowsOfNodes state) { - assert node.stamp(NodeView.DEFAULT) instanceof AbstractObjectStamp; + assert node.stamp(NodeView.DEFAULT) instanceof AbstractObjectStamp : node; if (!StampTool.isPointerNonNull(node)) { TypeFlowBuilder inputBuilder = state.lookup(node); TypeFlowBuilder nullCheckBuilder = TypeFlowBuilder.create(bb, source, NullCheckTypeFlow.class, () -> { - NullCheckTypeFlow nullCheckFlow = new NullCheckTypeFlow(AbstractAnalysisEngine.sourcePosition(source), inputBuilder.get().getDeclaredType(), true); + var inputFlow = inputBuilder.get(); + if (inputFlow instanceof NullCheckTypeFlow nullCheck && nullCheck.isBlockingNull()) { + // unnecessary to create redundant null type check + return nullCheck; + } + NullCheckTypeFlow nullCheckFlow = new NullCheckTypeFlow(AbstractAnalysisEngine.sourcePosition(source), inputFlow.getDeclaredType(), true); flowsGraph.addMiscEntryFlow(nullCheckFlow); return nullCheckFlow; }); From b957ee40f302d54edf704b36120ef21fe977453a Mon Sep 17 00:00:00 2001 From: Peter Hofer Date: Thu, 5 Oct 2023 14:09:26 +0200 Subject: [PATCH 09/19] Remove virtual thread and continuation abstractions and code paths that have become unnecessary. --- .../genscavenge/ThreadLocalAllocation.java | 4 +- .../graal/GenScavengeAllocationSnippets.java | 5 +- .../graal/GenScavengeAllocationSupport.java | 13 +- .../ClassInitializationInfo.java | 11 +- .../snippets/SubstrateAllocationSnippets.java | 5 +- .../core/graal/stackvalue/StackValueNode.java | 3 +- .../core/heap/StoredContinuationAccess.java | 10 +- .../svm/core/hub/InteriorObjRefWalker.java | 4 +- .../image/DisallowedImageHeapObjects.java | 28 +-- .../core/jdk/ContinuationsNotSupported.java | 36 --- .../svm/core/jdk/ContinuationsSupported.java | 36 --- .../src/com/oracle/svm/core/jdk/LoomJDK.java | 36 --- .../com/oracle/svm/core/jdk/NotLoomJDK.java | 36 --- .../oracle/svm/core/jdk/StackTraceUtils.java | 10 +- .../jdk/Target_java_lang_StackWalker.java | 15 +- .../svm/core/jni/functions/JNIFunctions.java | 13 +- .../monitor/MultiThreadedMonitorSupport.java | 5 +- .../oracle/svm/core/thread/Continuation.java | 15 +- .../svm/core/thread/ContinuationSupport.java | 25 +- .../svm/core/thread/ContinuationsFeature.java | 64 ++--- .../oracle/svm/core/thread/JavaThreads.java | 155 +++++++----- .../oracle/svm/core/thread/LoomSupport.java | 52 ---- .../svm/core/thread/LoomVirtualThreads.java | 230 ------------------ .../svm/core/thread/PlatformThreads.java | 75 +++--- .../com/oracle/svm/core/thread/Safepoint.java | 2 +- .../core/thread/Target_java_lang_Thread.java | 101 ++------ .../Target_java_lang_VirtualThread.java | 9 +- ..._jdk_internal_misc_Unsafe_JavaThreads.java | 5 +- .../Target_jdk_internal_vm_Continuation.java | 37 +-- ..._jdk_internal_vm_ContinuationSupport.java} | 25 +- .../svm/core/thread/VirtualThreads.java | 76 ------ .../src/com/oracle/svm/hosted/SVMHost.java | 4 +- .../thread/HostedContinuationsFeature.java | 3 +- .../jfr/TestJavaLevelVirtualThreadEvents.java | 4 +- 34 files changed, 269 insertions(+), 883 deletions(-) delete mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ContinuationsNotSupported.java delete mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ContinuationsSupported.java delete mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/LoomJDK.java delete mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/NotLoomJDK.java delete mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/LoomSupport.java delete mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/LoomVirtualThreads.java rename substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/{Continuations.java => Target_jdk_internal_vm_ContinuationSupport.java} (57%) delete mode 100644 substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/thread/VirtualThreads.java diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java index 1c27f3931935..2c123a36acd3 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/ThreadLocalAllocation.java @@ -67,7 +67,7 @@ import com.oracle.svm.core.snippets.KnownIntrinsics; import com.oracle.svm.core.snippets.SubstrateForeignCallTarget; import com.oracle.svm.core.stack.StackOverflowCheck; -import com.oracle.svm.core.thread.Continuation; +import com.oracle.svm.core.thread.ContinuationSupport; import com.oracle.svm.core.thread.VMOperation; import com.oracle.svm.core.thread.VMThreads; import com.oracle.svm.core.threadlocal.FastThreadLocal; @@ -375,7 +375,7 @@ private static Object allocateLargeArrayLikeObjectInNewTlab(DynamicHub hub, int @Uninterruptible(reason = "Holds uninitialized memory") private static Object formatArrayLikeObject(Pointer memory, DynamicHub hub, int length, boolean unaligned, FillContent fillContent, byte[] podReferenceMap) { Class clazz = DynamicHub.toClass(hub); - if (Continuation.isSupported() && clazz == StoredContinuation.class) { + if (ContinuationSupport.isSupported() && clazz == StoredContinuation.class) { return FormatStoredContinuationNode.formatStoredContinuation(memory, clazz, length, false, unaligned, true); } else if (Pod.RuntimeSupport.isPresent() && podReferenceMap != null) { return FormatPodNode.formatPod(memory, clazz, length, podReferenceMap, false, unaligned, fillContent, true); diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeAllocationSnippets.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeAllocationSnippets.java index 247f6d6f6d3c..000c85080d58 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeAllocationSnippets.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeAllocationSnippets.java @@ -58,7 +58,6 @@ import com.oracle.svm.core.heap.Pod; import com.oracle.svm.core.hub.DynamicHub; import com.oracle.svm.core.hub.LayoutEncoding; -import com.oracle.svm.core.thread.Continuation; import com.oracle.svm.core.thread.ContinuationSupport; import jdk.vm.ci.meta.JavaKind; @@ -130,7 +129,7 @@ public Templates(OptionValues options, Providers providers, SubstrateAllocationS this.baseTemplates = baseTemplates; formatObject = snippet(providers, GenScavengeAllocationSnippets.class, "formatObjectSnippet"); formatArray = snippet(providers, GenScavengeAllocationSnippets.class, "formatArraySnippet"); - formatStoredContinuation = Continuation.isSupported() ? snippet(providers, GenScavengeAllocationSnippets.class, "formatStoredContinuation") : null; + formatStoredContinuation = ContinuationSupport.isSupported() ? snippet(providers, GenScavengeAllocationSnippets.class, "formatStoredContinuation") : null; formatPod = Pod.RuntimeSupport.isPresent() ? snippet(providers, GenScavengeAllocationSnippets.class, "formatPodSnippet", @@ -141,7 +140,7 @@ public Templates(OptionValues options, Providers providers, SubstrateAllocationS public void registerLowering(Map, NodeLoweringProvider> lowerings) { lowerings.put(FormatObjectNode.class, new FormatObjectLowering()); lowerings.put(FormatArrayNode.class, new FormatArrayLowering()); - if (Continuation.isSupported()) { + if (ContinuationSupport.isSupported()) { lowerings.put(FormatStoredContinuationNode.class, new FormatStoredContinuationLowering()); } if (Pod.RuntimeSupport.isPresent()) { diff --git a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeAllocationSupport.java b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeAllocationSupport.java index 5af97cbc22e5..f99a080c56a8 100644 --- a/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeAllocationSupport.java +++ b/substratevm/src/com.oracle.svm.core.genscavenge/src/com/oracle/svm/core/genscavenge/graal/GenScavengeAllocationSupport.java @@ -24,18 +24,19 @@ */ package com.oracle.svm.core.genscavenge.graal; -import com.oracle.svm.core.heap.Pod; -import com.oracle.svm.core.snippets.SnippetRuntime.SubstrateForeignCallDescriptor; -import com.oracle.svm.core.thread.Continuation; -import jdk.compiler.graal.core.common.spi.ForeignCallDescriptor; -import jdk.compiler.graal.word.Word; import org.graalvm.word.UnsignedWord; import com.oracle.svm.core.genscavenge.HeapParameters; import com.oracle.svm.core.genscavenge.ThreadLocalAllocation; import com.oracle.svm.core.graal.meta.SubstrateForeignCallsProvider; import com.oracle.svm.core.graal.snippets.GCAllocationSupport; +import com.oracle.svm.core.heap.Pod; import com.oracle.svm.core.snippets.SnippetRuntime; +import com.oracle.svm.core.snippets.SnippetRuntime.SubstrateForeignCallDescriptor; +import com.oracle.svm.core.thread.ContinuationSupport; + +import jdk.compiler.graal.core.common.spi.ForeignCallDescriptor; +import jdk.compiler.graal.word.Word; public class GenScavengeAllocationSupport implements GCAllocationSupport { private static final SubstrateForeignCallDescriptor SLOW_NEW_INSTANCE = SnippetRuntime.findForeignCall(ThreadLocalAllocation.class, "slowPathNewInstance", true); @@ -46,7 +47,7 @@ public class GenScavengeAllocationSupport implements GCAllocationSupport { public static void registerForeignCalls(SubstrateForeignCallsProvider foreignCalls) { foreignCalls.register(UNCONDITIONAL_FOREIGN_CALLS); - if (Continuation.isSupported()) { + if (ContinuationSupport.isSupported()) { foreignCalls.register(SLOW_NEW_STORED_CONTINUATION); } if (Pod.RuntimeSupport.isPresent()) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/classinitialization/ClassInitializationInfo.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/classinitialization/ClassInitializationInfo.java index c723a428a5cf..f13625d036df 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/classinitialization/ClassInitializationInfo.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/classinitialization/ClassInitializationInfo.java @@ -29,7 +29,6 @@ import org.graalvm.nativeimage.CurrentIsolate; import org.graalvm.nativeimage.IsolateThread; -import com.oracle.svm.core.hub.PredefinedClassesSupport; import org.graalvm.nativeimage.Platform; import org.graalvm.nativeimage.Platforms; import org.graalvm.nativeimage.c.function.CFunctionPointer; @@ -38,10 +37,12 @@ import com.oracle.svm.core.FunctionPointerHolder; import com.oracle.svm.core.c.InvokeJavaFunctionPointer; import com.oracle.svm.core.hub.DynamicHub; +import com.oracle.svm.core.hub.PredefinedClassesSupport; import com.oracle.svm.core.jdk.InternalVMMethod; import com.oracle.svm.core.snippets.SubstrateForeignCallTarget; +import com.oracle.svm.core.thread.ContinuationSupport; import com.oracle.svm.core.thread.JavaThreads; -import com.oracle.svm.core.thread.VirtualThreads; +import com.oracle.svm.core.thread.Target_jdk_internal_vm_Continuation; import com.oracle.svm.core.util.VMError; import jdk.internal.misc.Unsafe; @@ -263,16 +264,16 @@ private static void initialize(ClassInitializationInfo info, DynamicHub hub) { } boolean pinned = false; - if (VirtualThreads.isSupported() && JavaThreads.isCurrentThreadVirtual()) { + if (ContinuationSupport.isSupported() && JavaThreads.isCurrentThreadVirtual()) { // See comment on field `initThread` - VirtualThreads.singleton().pinCurrent(); + Target_jdk_internal_vm_Continuation.pin(); pinned = true; } try { doInitialize(info, hub); } finally { if (pinned) { - VirtualThreads.singleton().unpinCurrent(); + Target_jdk_internal_vm_Continuation.unpin(); } } } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateAllocationSnippets.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateAllocationSnippets.java index f3fa72e27dc1..1755d04ffd69 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateAllocationSnippets.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/snippets/SubstrateAllocationSnippets.java @@ -102,7 +102,6 @@ import com.oracle.svm.core.snippets.SnippetRuntime; import com.oracle.svm.core.snippets.SnippetRuntime.SubstrateForeignCallDescriptor; import com.oracle.svm.core.snippets.SubstrateForeignCallTarget; -import com.oracle.svm.core.thread.Continuation; import com.oracle.svm.core.thread.ContinuationSupport; import com.oracle.svm.core.util.VMError; @@ -600,7 +599,7 @@ public Templates(OptionValues options, Providers providers, SubstrateAllocationS ALLOCATION_LOCATIONS); SnippetInfo allocateStoredContinuationSnippet = null; - if (Continuation.isSupported()) { + if (ContinuationSupport.isSupported()) { allocateStoredContinuationSnippet = snippet(providers, SubstrateAllocationSnippets.class, "allocateStoredContinuation", @@ -634,7 +633,7 @@ public void registerLowering(Map, NodeLoweringProvider> lowerings.put(NewMultiArrayNode.class, new NewMultiArrayLowering()); lowerings.put(ValidateNewInstanceClassNode.class, new ValidateNewInstanceClassLowering()); - if (Continuation.isSupported()) { + if (ContinuationSupport.isSupported()) { lowerings.put(NewStoredContinuationNode.class, new NewStoredContinuationLowering()); } if (Pod.RuntimeSupport.isPresent()) { diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/stackvalue/StackValueNode.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/stackvalue/StackValueNode.java index f7d9c8454a4c..8c2785c164ed 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/stackvalue/StackValueNode.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/graal/stackvalue/StackValueNode.java @@ -46,7 +46,6 @@ import com.oracle.svm.core.FrameAccess; import com.oracle.svm.core.Uninterruptible; import com.oracle.svm.core.config.ConfigurationValues; -import com.oracle.svm.core.thread.VirtualThreads; import jdk.vm.ci.meta.ResolvedJavaMethod; @@ -153,7 +152,7 @@ public static StackValueNode create(int sizeInBytes, ResolvedJavaMethod method, * around in a caller, but these are difficult to ensure across multiple callers and * callees. */ - boolean checkVirtualThread = disallowVirtualThread && VirtualThreads.isSupported() && !Uninterruptible.Utils.isUninterruptible(method); + boolean checkVirtualThread = disallowVirtualThread && !Uninterruptible.Utils.isUninterruptible(method); return create(sizeInBytes, slotIdentity, checkVirtualThread); } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/StoredContinuationAccess.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/StoredContinuationAccess.java index e8da66702ef1..ca165013e1f1 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/StoredContinuationAccess.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/heap/StoredContinuationAccess.java @@ -39,9 +39,9 @@ import org.graalvm.word.UnsignedWord; import org.graalvm.word.WordFactory; -import com.oracle.svm.core.UnmanagedMemoryUtil; import com.oracle.svm.core.AlwaysInline; import com.oracle.svm.core.Uninterruptible; +import com.oracle.svm.core.UnmanagedMemoryUtil; import com.oracle.svm.core.c.NonmovableArray; import com.oracle.svm.core.code.CodeInfo; import com.oracle.svm.core.code.CodeInfoAccess; @@ -126,7 +126,7 @@ private static int allocateFromStack(Continuation cont, Pointer baseSp, Pointer if (!yield) { PreemptVisitor visitor = new PreemptVisitor(baseSp); JavaStackWalker.walkThread(targetThread, visitor); - if (visitor.preemptStatus != Continuation.FREEZE_OK) { + if (visitor.preemptStatus != ContinuationSupport.FREEZE_OK) { return visitor.preemptStatus; } startSp = visitor.leafSP; @@ -139,7 +139,7 @@ private static int allocateFromStack(Continuation cont, Pointer baseSp, Pointer StoredContinuation instance = allocate(framesSize); fillUninterruptibly(instance, startIp, startSp, framesSize); cont.stored = instance; - return Continuation.FREEZE_OK; + return ContinuationSupport.FREEZE_OK; } @Uninterruptible(reason = "Prevent modifications to the stack while initializing instance and copying frames.") @@ -300,7 +300,7 @@ private static final class PreemptVisitor extends StackFrameVisitor { Pointer leafSP; CodePointer leafIP; - int preemptStatus = Continuation.FREEZE_OK; + int preemptStatus = ContinuationSupport.FREEZE_OK; PreemptVisitor(Pointer endSP) { this.endSP = endSP; @@ -315,7 +315,7 @@ protected boolean visitFrame(Pointer sp, CodePointer ip, CodeInfo codeInfo, Deop FrameInfoQueryResult frameInfo = CodeInfoTable.lookupCodeInfoQueryResult(codeInfo, ip).getFrameInfo(); if (frameInfo.getSourceClass().equals(StoredContinuationAccess.class) && frameInfo.getSourceMethodName().equals("allocateToYield")) { // Continuation is already in the process of yielding, cancel preemption. - preemptStatus = Continuation.YIELDING; + preemptStatus = ContinuationSupport.FREEZE_YIELDING; return false; } diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/InteriorObjRefWalker.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/InteriorObjRefWalker.java index cc7a03916128..25c128eaf93a 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/InteriorObjRefWalker.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/hub/InteriorObjRefWalker.java @@ -43,7 +43,7 @@ import com.oracle.svm.core.heap.PodReferenceMapDecoder; import com.oracle.svm.core.heap.ReferenceAccess; import com.oracle.svm.core.heap.StoredContinuationAccess; -import com.oracle.svm.core.thread.Continuation; +import com.oracle.svm.core.thread.ContinuationSupport; import com.oracle.svm.core.util.VMError; /** @@ -130,7 +130,7 @@ private static boolean walkPod(Object obj, ObjectReferenceVisitor visitor, Dynam @AlwaysInline("Performance critical version") @Uninterruptible(reason = "Called from uninterruptible code.", mayBeInlined = true) private static boolean walkStoredContinuation(Object obj, ObjectReferenceVisitor visitor) { - if (!Continuation.isSupported()) { + if (!ContinuationSupport.isSupported()) { throw VMError.shouldNotReachHere("Stored continuation objects cannot be in the heap if the continuation support is disabled."); } return StoredContinuationAccess.walkReferences(obj, visitor); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/image/DisallowedImageHeapObjects.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/image/DisallowedImageHeapObjects.java index 125efc0dba22..b6ccc67d8976 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/image/DisallowedImageHeapObjects.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/image/DisallowedImageHeapObjects.java @@ -37,7 +37,6 @@ import java.util.concurrent.ThreadLocalRandom; import com.oracle.svm.core.SubstrateUtil; -import com.oracle.svm.core.thread.VirtualThreads; import com.oracle.svm.core.util.VMError; import com.oracle.svm.util.ReflectionUtil; @@ -52,20 +51,12 @@ public interface DisallowedObjectReporter { RuntimeException raise(String msg, Object obj, String initializerAction); } - private static final Class CANCELLABLE_CLASS; - private static final Class JDK_VIRTUAL_THREAD_CLASS; - private static final Class CONTINUATION_CLASS; - private static final Method CONTINUATION_IS_STARTED_METHOD; - private static final Class CLEANER_CLEANABLE_CLASS; - private static final Class LEGACY_CLEANER_CLASS; - static { - CANCELLABLE_CLASS = ReflectionUtil.lookupClass(false, "sun.nio.fs.Cancellable"); - JDK_VIRTUAL_THREAD_CLASS = ReflectionUtil.lookupClass(true, "java.lang.VirtualThread"); - CONTINUATION_CLASS = ReflectionUtil.lookupClass(true, "jdk.internal.vm.Continuation"); - CONTINUATION_IS_STARTED_METHOD = (CONTINUATION_CLASS == null) ? null : ReflectionUtil.lookupMethod(CONTINUATION_CLASS, "isStarted"); - CLEANER_CLEANABLE_CLASS = ReflectionUtil.lookupClass(false, "jdk.internal.ref.CleanerImpl$CleanerCleanable"); - LEGACY_CLEANER_CLASS = ReflectionUtil.lookupClass(false, "jdk.internal.ref.Cleaner"); - } + private static final Class CANCELLABLE_CLASS = ReflectionUtil.lookupClass(false, "sun.nio.fs.Cancellable"); + private static final Class VIRTUAL_THREAD_CLASS = ReflectionUtil.lookupClass(false, "java.lang.VirtualThread"); + private static final Class CONTINUATION_CLASS = ReflectionUtil.lookupClass(false, "jdk.internal.vm.Continuation"); + private static final Method CONTINUATION_IS_STARTED_METHOD = ReflectionUtil.lookupMethod(CONTINUATION_CLASS, "isStarted"); + private static final Class CLEANER_CLEANABLE_CLASS = ReflectionUtil.lookupClass(false, "jdk.internal.ref.CleanerImpl$CleanerCleanable"); + private static final Class LEGACY_CLEANER_CLASS = ReflectionUtil.lookupClass(false, "jdk.internal.ref.Cleaner"); public static void check(Object obj, DisallowedObjectReporter reporter) { if (((obj instanceof Random) && !(obj instanceof ThreadLocalRandom)) || obj instanceof SplittableRandom) { @@ -75,9 +66,8 @@ public static void check(Object obj, DisallowedObjectReporter reporter) { } /* Started platform threads */ - if (obj instanceof Thread) { - final Thread asThread = (Thread) obj; - if (VirtualThreads.isSupported() && (VirtualThreads.singleton().isVirtual(asThread) || (JDK_VIRTUAL_THREAD_CLASS != null && JDK_VIRTUAL_THREAD_CLASS.isInstance(asThread)))) { + if (obj instanceof Thread asThread) { + if (VIRTUAL_THREAD_CLASS.isInstance(asThread)) { // allowed unless the thread is mounted, in which case it references its carrier // thread and fails } else if (asThread.getState() != Thread.State.NEW && asThread.getState() != Thread.State.TERMINATED) { @@ -86,7 +76,7 @@ public static void check(Object obj, DisallowedObjectReporter reporter) { asThread, "Prevent threads from starting during image generation, or a started thread from being included in the image."); } } - if (SubstrateUtil.HOSTED && CONTINUATION_CLASS != null && CONTINUATION_CLASS.isInstance(obj)) { + if (SubstrateUtil.HOSTED && CONTINUATION_CLASS.isInstance(obj)) { boolean isStarted; try { isStarted = (Boolean) CONTINUATION_IS_STARTED_METHOD.invoke(obj); diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ContinuationsNotSupported.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ContinuationsNotSupported.java deleted file mode 100644 index 070f91430ff9..000000000000 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ContinuationsNotSupported.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2021, 2021, 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.jdk; - -import java.util.function.BooleanSupplier; - -import com.oracle.svm.core.thread.Continuation; - -public class ContinuationsNotSupported implements BooleanSupplier { - @Override - public boolean getAsBoolean() { - return !Continuation.isSupported(); - } -} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ContinuationsSupported.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ContinuationsSupported.java deleted file mode 100644 index 58e6fbf190ce..000000000000 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/ContinuationsSupported.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2021, 2021, 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.jdk; - -import java.util.function.BooleanSupplier; - -import com.oracle.svm.core.thread.Continuation; - -public class ContinuationsSupported implements BooleanSupplier { - @Override - public boolean getAsBoolean() { - return Continuation.isSupported(); - } -} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/LoomJDK.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/LoomJDK.java deleted file mode 100644 index 308577de3d72..000000000000 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/LoomJDK.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2020, 2020, 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.jdk; - -import java.util.function.BooleanSupplier; - -import com.oracle.svm.core.thread.LoomSupport; - -public class LoomJDK implements BooleanSupplier { - @Override - public boolean getAsBoolean() { - return LoomSupport.isEnabled(); - } -} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/NotLoomJDK.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/NotLoomJDK.java deleted file mode 100644 index 3107a626cad7..000000000000 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/NotLoomJDK.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright (c) 2020, 2020, 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.jdk; - -import java.util.function.BooleanSupplier; - -import com.oracle.svm.core.thread.LoomSupport; - -public class NotLoomJDK implements BooleanSupplier { - @Override - public boolean getAsBoolean() { - return !LoomSupport.isEnabled(); - } -} diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/StackTraceUtils.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/StackTraceUtils.java index 308f01da0ec7..38cc6bf04a62 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/StackTraceUtils.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/StackTraceUtils.java @@ -61,11 +61,8 @@ import com.oracle.svm.core.stack.StackFrameVisitor; import com.oracle.svm.core.thread.JavaThreads; import com.oracle.svm.core.thread.JavaVMOperation; -import com.oracle.svm.core.thread.LoomSupport; -import com.oracle.svm.core.thread.PlatformThreads; import com.oracle.svm.core.thread.Target_jdk_internal_vm_Continuation; import com.oracle.svm.core.thread.VMOperation; -import com.oracle.svm.core.thread.VirtualThreads; import com.oracle.svm.core.util.VMError; import jdk.vm.ci.meta.MetaAccessProvider; @@ -104,10 +101,7 @@ public static void visitCurrentThreadStackFrames(Pointer startSP, Pointer endSP, @NeverInline("Potentially starting a stack walk in the caller frame") public static StackTraceElement[] getStackTraceAtSafepoint(Thread thread) { assert VMOperation.isInProgressAtSafepoint(); - if (VirtualThreads.isSupported()) { // NOTE: also for platform threads! - return VirtualThreads.singleton().getVirtualOrPlatformThreadStackTraceAtSafepoint(thread, readCallerStackPointer()); - } - return PlatformThreads.getStackTraceAtSafepoint(thread, readCallerStackPointer()); + return JavaThreads.getStackTraceAtSafepoint(thread, readCallerStackPointer()); } public static StackTraceElement[] getThreadStackTraceAtSafepoint(IsolateThread isolateThread, Pointer endSP) { @@ -186,7 +180,7 @@ public static boolean shouldShowFrame(FrameInfoQueryResult frameInfo, boolean sh return false; } - if (LoomSupport.isEnabled() && clazz == Target_jdk_internal_vm_Continuation.class) { + if (clazz == Target_jdk_internal_vm_Continuation.class) { String name = frameInfo.getSourceMethodName(); if (name.startsWith("enter") || name.startsWith("yield")) { return false; diff --git a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_lang_StackWalker.java b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_lang_StackWalker.java index e6aed227bf14..4ab3bd5db3cc 100644 --- a/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_lang_StackWalker.java +++ b/substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/jdk/Target_java_lang_StackWalker.java @@ -48,7 +48,6 @@ import com.oracle.svm.core.annotate.Delete; import com.oracle.svm.core.annotate.Substitute; import com.oracle.svm.core.annotate.TargetClass; -import com.oracle.svm.core.annotate.TargetElement; import com.oracle.svm.core.code.CodeInfo; import com.oracle.svm.core.code.CodeInfoAccess; import com.oracle.svm.core.code.CodeInfoTable; @@ -65,8 +64,8 @@ import com.oracle.svm.core.stack.JavaStackWalk; import com.oracle.svm.core.stack.JavaStackWalker; import com.oracle.svm.core.thread.Continuation; +import com.oracle.svm.core.thread.ContinuationSupport; import com.oracle.svm.core.thread.JavaThreads; -import com.oracle.svm.core.thread.LoomSupport; import com.oracle.svm.core.thread.Target_java_lang_VirtualThread; import com.oracle.svm.core.thread.Target_jdk_internal_vm_Continuation; import com.oracle.svm.core.thread.Target_jdk_internal_vm_ContinuationScope; @@ -79,13 +78,13 @@ final class Target_java_lang_StackWalker { /** * Current continuation that the stack walker is on. */ - @Alias @TargetElement(onlyWith = LoomJDK.class)// + @Alias // Target_jdk_internal_vm_Continuation continuation; /** * Target continuation scope if we're iterating a {@link Target_jdk_internal_vm_Continuation}. */ - @Alias @TargetElement(onlyWith = LoomJDK.class)// + @Alias // Target_jdk_internal_vm_ContinuationScope contScope; @Alias Set