diff --git a/sdk/src/org.graalvm.collections.test/src/org/graalvm/collections/test/EmptyEconomicSetTest.java b/sdk/src/org.graalvm.collections.test/src/org/graalvm/collections/test/EmptyEconomicSetTest.java new file mode 100644 index 000000000000..cec13f29cab4 --- /dev/null +++ b/sdk/src/org.graalvm.collections.test/src/org/graalvm/collections/test/EmptyEconomicSetTest.java @@ -0,0 +1,90 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.graalvm.collections.test; + +import java.util.NoSuchElementException; + +import org.graalvm.collections.EconomicSet; +import org.junit.Assert; +import org.junit.Test; + +public class EmptyEconomicSetTest { + + @Test + public void testIsEmpty() { + Assert.assertTrue(EconomicSet.emptySet().isEmpty()); + } + + @Test + public void testSizeZero() { + Assert.assertEquals(0, EconomicSet.emptySet().size()); + } + + @Test(expected = IllegalArgumentException.class) + public void testAdd() { + EconomicSet.emptySet().add(1); + } + + @Test(expected = IllegalArgumentException.class) + public void testRemove() { + EconomicSet.emptySet().remove(1); + } + + @Test(expected = IllegalArgumentException.class) + public void testClear() { + EconomicSet.emptySet().clear(); + } + + @Test + public void testContains() { + Assert.assertFalse(EconomicSet.emptySet().contains(1)); + } + + @Test + public void testIteratorAlwaysEmpty() { + Assert.assertFalse(EconomicSet.emptySet().iterator().hasNext()); + } + + @Test(expected = NoSuchElementException.class) + public void testIteratorThrowsException() { + EconomicSet.emptySet().iterator().next(); + } +} diff --git a/sdk/src/org.graalvm.collections/snapshot.sigtest b/sdk/src/org.graalvm.collections/snapshot.sigtest index cb1cdd67cd5c..3ebf2e2a90e6 100644 --- a/sdk/src/org.graalvm.collections/snapshot.sigtest +++ b/sdk/src/org.graalvm.collections/snapshot.sigtest @@ -136,6 +136,7 @@ meth public static <%0 extends java.lang.Object> org.graalvm.collections.Economi meth public static <%0 extends java.lang.Object> org.graalvm.collections.EconomicSet<{%%0}> create(org.graalvm.collections.Equivalence,int) meth public static <%0 extends java.lang.Object> org.graalvm.collections.EconomicSet<{%%0}> create(org.graalvm.collections.Equivalence,org.graalvm.collections.UnmodifiableEconomicSet<{%%0}>) meth public static <%0 extends java.lang.Object> org.graalvm.collections.EconomicSet<{%%0}> create(org.graalvm.collections.UnmodifiableEconomicSet<{%%0}>) +meth public static org.graalvm.collections.EconomicSet emptySet() meth public void addAll(java.lang.Iterable<{org.graalvm.collections.EconomicSet%0}>) meth public void addAll(java.util.Iterator<{org.graalvm.collections.EconomicSet%0}>) meth public void addAll(org.graalvm.collections.EconomicSet<{org.graalvm.collections.EconomicSet%0}>) diff --git a/sdk/src/org.graalvm.collections/src/org/graalvm/collections/EconomicSet.java b/sdk/src/org.graalvm.collections/src/org/graalvm/collections/EconomicSet.java index 43077f947f7e..d247b3912ce1 100644 --- a/sdk/src/org.graalvm.collections/src/org/graalvm/collections/EconomicSet.java +++ b/sdk/src/org.graalvm.collections/src/org/graalvm/collections/EconomicSet.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017, 2019, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * The Universal Permissive License (UPL), Version 1.0 @@ -206,4 +206,14 @@ static EconomicSet create(Equivalence strategy, int initialCapacity) { static EconomicSet create(Equivalence strategy, UnmodifiableEconomicSet c) { return EconomicMapImpl.create(strategy, c, true); } + + /** + * Return an empty, unmodifiable {@link EconomicSet}. + * + * @since 25.0 + */ + @SuppressWarnings("unchecked") + static EconomicSet emptySet() { + return (EconomicSet) EmptySet.EMPTY_SET; + } } diff --git a/sdk/src/org.graalvm.collections/src/org/graalvm/collections/EmptySet.java b/sdk/src/org.graalvm.collections/src/org/graalvm/collections/EmptySet.java new file mode 100644 index 000000000000..a85ae47972c8 --- /dev/null +++ b/sdk/src/org.graalvm.collections/src/org/graalvm/collections/EmptySet.java @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * The Universal Permissive License (UPL), Version 1.0 + * + * Subject to the condition set forth below, permission is hereby granted to any + * person obtaining a copy of this software, associated documentation and/or + * data (collectively the "Software"), free of charge and under any and all + * copyright rights in the Software, and any and all patent rights owned or + * freely licensable by each licensor hereunder covering either (i) the + * unmodified Software as contributed to or provided by such licensor, or (ii) + * the Larger Works (as defined below), to deal in both + * + * (a) the Software, and + * + * (b) any piece of software and/or hardware listed in the lrgrwrks.txt file if + * one is included with the Software each a "Larger Work" to which the Software + * is contributed by such licensors), + * + * without restriction, including without limitation the rights to copy, create + * derivative works of, display, perform, and distribute the Software and make, + * use, sell, offer for sale, import, export, have made, and have sold the + * Software and the Larger Work(s), and to sublicense the foregoing rights on + * either these or other terms. + * + * This license is subject to the following condition: + * + * The above copyright notice and either this complete permission notice or at a + * minimum a reference to the UPL must be included in all copies or substantial + * portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +package org.graalvm.collections; + +import java.util.Iterator; + +/** + * Singleton instance for empty set. Reuses empty iterator from {@link EmptyMap}. + */ +class EmptySet { + static final EconomicSet EMPTY_SET = new EconomicSet<>() { + @Override + public boolean add(Object element) { + throw new IllegalArgumentException("Cannot modify the always-empty set"); + } + + @Override + public void remove(Object element) { + throw new IllegalArgumentException("Cannot modify the always-empty set"); + } + + @Override + public void clear() { + throw new IllegalArgumentException("Cannot modify the always-empty set"); + } + + @Override + public boolean contains(Object element) { + return false; + } + + @Override + public int size() { + return 0; + } + + @Override + public boolean isEmpty() { + return true; + } + + @Override + public Iterator iterator() { + return EmptyMap.EMPTY_ITERATOR; + } + }; +} diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java index c7dfc6d33e90..feaec2e3c99b 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/PointsToAnalysis.java @@ -45,6 +45,7 @@ import com.oracle.graal.pointsto.api.HostVM; import com.oracle.graal.pointsto.api.PointstoOptions; import com.oracle.graal.pointsto.constraints.UnsupportedFeatures; +import com.oracle.graal.pointsto.flow.AlwaysEnabledPredicateFlow; import com.oracle.graal.pointsto.flow.AnyPrimitiveSourceTypeFlow; import com.oracle.graal.pointsto.flow.FieldTypeFlow; import com.oracle.graal.pointsto.flow.FormalParamTypeFlow; @@ -103,9 +104,9 @@ public abstract class PointsToAnalysis extends AbstractAnalysisEngine { */ private final boolean trackPrimitiveValues; private final AnalysisType longType; - private final AnalysisType voidType; private final boolean usePredicates; private AnyPrimitiveSourceTypeFlow anyPrimitiveSourceTypeFlow; + private AlwaysEnabledPredicateFlow alwaysEnabledPredicateFlow; protected final boolean trackTypeFlowInputs; protected final boolean reportAnalysisStatistics; @@ -127,12 +128,13 @@ public PointsToAnalysis(OptionValues options, AnalysisUniverse universe, HostVM this.objectType = metaAccess.lookupJavaType(Object.class); this.longType = metaAccess.lookupJavaType(long.class); - this.voidType = metaAccess.lookupJavaType(void.class); this.trackPrimitiveValues = PointstoOptions.TrackPrimitiveValues.getValue(options); this.usePredicates = PointstoOptions.UsePredicates.getValue(options); this.anyPrimitiveSourceTypeFlow = new AnyPrimitiveSourceTypeFlow(null, longType); this.anyPrimitiveSourceTypeFlow.enableFlow(null); + this.alwaysEnabledPredicateFlow = new AlwaysEnabledPredicateFlow(); + /* * Make sure the all-instantiated type flow is created early. We do not have any * instantiated types yet, so the state is empty at first. @@ -292,6 +294,7 @@ public boolean trackConcreteAnalysisObjects(@SuppressWarnings("unused") Analysis public void cleanupAfterAnalysis() { super.cleanupAfterAnalysis(); anyPrimitiveSourceTypeFlow = null; + alwaysEnabledPredicateFlow = null; unsafeLoads = null; unsafeStores = null; @@ -310,10 +313,6 @@ public AnalysisType getLongType() { return longType; } - public AnalysisType getVoidType() { - return voidType; - } - public AnalysisType getObjectArrayType() { return metaAccess.lookupJavaType(Object[].class); } @@ -331,6 +330,10 @@ public AnyPrimitiveSourceTypeFlow getAnyPrimitiveSourceTypeFlow() { return anyPrimitiveSourceTypeFlow; } + public AlwaysEnabledPredicateFlow getAlwaysEnabledPredicateFlow() { + return alwaysEnabledPredicateFlow; + } + @Override public Iterable getAllSynchronizedTypes() { return getAllInstantiatedTypes(); 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 582be9b75e7e..9028ccedcf91 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 @@ -208,7 +208,7 @@ public MethodTypeFlowBuilder(PointsToAnalysis bb, PointsToAnalysisMethod method, this.graphKind = graphKind; if (bb.trackPrimitiveValues()) { this.alwaysEnabled = bb.usePredicates() - ? TypeFlowBuilder.create(bb, method, null, PointsToAnalysis.syntheticSourcePosition(method), AlwaysEnabledPredicateFlow.class, AlwaysEnabledPredicateFlow::new) + ? TypeFlowBuilder.create(bb, method, null, PointsToAnalysis.syntheticSourcePosition(method), AlwaysEnabledPredicateFlow.class, bb::getAlwaysEnabledPredicateFlow) : null; this.anyPrimitiveSourceTypeFlowBuilder = TypeFlowBuilder.create(bb, method, alwaysEnabled, null, AnyPrimitiveSourceTypeFlow.class, bb::getAnyPrimitiveSourceTypeFlow); } else { diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/TypeFlow.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/TypeFlow.java index f752f4d19db3..3d27398dcef5 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/TypeFlow.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/TypeFlow.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013, 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2013, 2025, 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 @@ -296,14 +296,14 @@ public void addPredicated(PointsToAnalysis bb, TypeFlow predicatedFlow) { } } - private void removePredicated(TypeFlow predicatedFlow) { - ConcurrentLightHashSet.removeElement(this, PREDICATED_FLOWS_UPDATER, predicatedFlow); - } - public Collection> getPredicatedFlows() { return ConcurrentLightHashSet.getElements(this, PREDICATED_FLOWS_UPDATER); } + public void clearPredicatedFlows() { + ConcurrentLightHashSet.clear(this, PREDICATED_FLOWS_UPDATER); + } + public boolean predicateAlreadyTriggered() { return AtomicUtils.isSet(this, PREDICATE_TRIGGERED_UPDATER); } @@ -945,31 +945,34 @@ protected void onSaturated() { private void notifySaturated(PointsToAnalysis bb) { for (TypeFlow use : getUses()) { notifyUseOfSaturation(bb, use); - removeUse(use); } + clearUses(); for (TypeFlow observer : getObservers()) { notifyObserverOfSaturation(bb, observer); - removeObserver(observer); } + clearObservers(); } /** This flow will swap itself out at all uses and observers. */ protected void swapOut(PointsToAnalysis bb, TypeFlow newFlow) { assert isSaturated() : "This operation should only be called on saturated flows:" + this; for (TypeFlow use : getUses()) { - swapAtUse(bb, newFlow, use); + newFlow.addUse(bb, use); } + clearUses(); for (TypeFlow observer : getObservers()) { - swapAtObserver(bb, newFlow, observer); + observer.replacedObservedWith(bb, newFlow); } + clearObservers(); /* * Before performing the swap, make sure addPredicated will immediately enable any newly * added predicated flows. */ AtomicUtils.atomicMark(this, PREDICATE_TRIGGERED_UPDATER); for (TypeFlow predicatedFlow : getPredicatedFlows()) { - swapAtPredicated(bb, newFlow, predicatedFlow); + newFlow.addPredicated(bb, predicatedFlow); } + clearPredicatedFlows(); } protected void swapAtUse(PointsToAnalysis bb, TypeFlow newFlow, TypeFlow use) { @@ -983,11 +986,6 @@ protected void swapAtObserver(PointsToAnalysis bb, TypeFlow newFlow, TypeFlow observer.replacedObservedWith(bb, newFlow); } - private void swapAtPredicated(PointsToAnalysis bb, TypeFlow newFlow, TypeFlow predicatedFlow) { - removePredicated(predicatedFlow); - newFlow.addPredicated(bb, predicatedFlow); - } - /** * Notifies this flow that its input has saturated, but only runs the * {@link TypeFlow#onInputSaturated}} if this flow is enabled. Otherwise, the execution of diff --git a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java index 6f0457d5f239..33bec09f8d62 100644 --- a/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java +++ b/substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/meta/AnalysisType.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2012, 2021, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2012, 2025, 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 @@ -59,6 +59,7 @@ import com.oracle.graal.pointsto.util.AnalysisError; import com.oracle.graal.pointsto.util.AnalysisFuture; import com.oracle.graal.pointsto.util.AtomicUtils; +import com.oracle.graal.pointsto.util.ConcurrentLightHashMap; import com.oracle.graal.pointsto.util.ConcurrentLightHashSet; import com.oracle.svm.util.LogUtils; @@ -110,6 +111,10 @@ public abstract class AnalysisType extends AnalysisElement implements WrappedJav static final AtomicReferenceFieldUpdater overrideableMethodsUpdater = AtomicReferenceFieldUpdater .newUpdater(AnalysisType.class, Object.class, "overrideableMethods"); + private static final AtomicReferenceFieldUpdater SUBTYPES_UPDATER = AtomicReferenceFieldUpdater.newUpdater(AnalysisType.class, Object.class, "subTypes"); + + private static final AtomicReferenceFieldUpdater RESOLVED_METHODS_UPDATER = AtomicReferenceFieldUpdater.newUpdater(AnalysisType.class, Object.class, "resolvedMethods"); + protected final AnalysisUniverse universe; private final ResolvedJavaType wrapped; private final String qualifiedName; @@ -126,7 +131,7 @@ public abstract class AnalysisType extends AnalysisElement implements WrappedJav @SuppressWarnings("unused") private volatile Object unsafeAccessedFields; /** Immediate subtypes and this type itself. */ - private final Set subTypes; + @SuppressWarnings("unused") private volatile Object subTypes; AnalysisType superClass; private final int id; @@ -153,7 +158,7 @@ public abstract class AnalysisType extends AnalysisElement implements WrappedJav * Map ResolvedJavaMethod to Object and not AnalysisMethod because when the type doesn't * implement the method the value stored is {@link AnalysisType#NULL_METHOD}. */ - private final ConcurrentHashMap resolvedMethods = new ConcurrentHashMap<>(); + @SuppressWarnings("unused") private volatile Object resolvedMethods; /** * Marker used in the {@link AnalysisType#resolvedMethods} map to signal that the type doesn't @@ -314,7 +319,6 @@ public AnalysisType(AnalysisUniverse universe, ResolvedJavaType javaType, JavaKi * Only after setting the id, the hashCode and compareTo methods work properly. So only now * it is allowed to put the type into a hashmap, e.g., invoke addSubType. */ - subTypes = ConcurrentHashMap.newKeySet(); addSubType(this); /* Build subtypes. */ @@ -686,12 +690,12 @@ public void registerSubtypeReachabilityNotification(SubtypeReachableNotification public void registerObjectReachableCallback(ObjectReachableCallback callback) { ConcurrentLightHashSet.addElement(this, objectReachableCallbacksUpdater, callback); /* Register the callback with already discovered subtypes too. */ - for (AnalysisType subType : subTypes) { + ConcurrentLightHashSet.forEach(this, SUBTYPES_UPDATER, (AnalysisType subType) -> { /* Subtypes include this type itself. */ if (!subType.equals(this)) { subType.registerObjectReachableCallback(callback); } - } + }); } public void notifyObjectReachable(DuringAnalysisAccess access, T object, ScanReason reason) { @@ -1051,12 +1055,12 @@ public ResolvedJavaType getSingleImplementor() { } /** Get the immediate subtypes, including this type itself. */ - public Set getSubTypes() { - return subTypes; + public Collection getSubTypes() { + return ConcurrentLightHashSet.getElements(this, SUBTYPES_UPDATER); } private void addSubType(AnalysisType subType) { - boolean result = this.subTypes.add(subType); + boolean result = ConcurrentLightHashSet.addElement(this, SUBTYPES_UPDATER, subType); /* Register the object reachability callbacks with the newly discovered subtype. */ if (!subType.equals(this)) { /* Subtypes include this type itself. */ @@ -1113,7 +1117,7 @@ public AnalysisType getElementalType() { public boolean hasSubTypes() { /* subTypes always includes this type itself. */ - return subTypes.size() > 1; + return ConcurrentLightHashSet.size(this, SUBTYPES_UPDATER) > 1; } @Override @@ -1128,7 +1132,7 @@ public AnalysisMethod resolveMethod(ResolvedJavaMethod method, ResolvedJavaType @Override public AnalysisMethod resolveConcreteMethod(ResolvedJavaMethod method, ResolvedJavaType callerType) { - Object resolvedMethod = resolvedMethods.get(method); + Object resolvedMethod = ConcurrentLightHashMap.get(this, RESOLVED_METHODS_UPDATER, method); if (resolvedMethod == null) { ResolvedJavaMethod originalMethod = OriginalMethodProvider.getOriginalMethod(method); Object newResolvedMethod = null; @@ -1155,7 +1159,7 @@ public AnalysisMethod resolveConcreteMethod(ResolvedJavaMethod method, ResolvedJ if (newResolvedMethod == null) { newResolvedMethod = NULL_METHOD; } - Object oldResolvedMethod = resolvedMethods.putIfAbsent(method, newResolvedMethod); + Object oldResolvedMethod = ConcurrentLightHashMap.putIfAbsent(this, RESOLVED_METHODS_UPDATER, method, newResolvedMethod); resolvedMethod = oldResolvedMethod != null ? oldResolvedMethod : newResolvedMethod; } return resolvedMethod == NULL_METHOD ? null : (AnalysisMethod) resolvedMethod; diff --git a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompilationGraph.java b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompilationGraph.java index 9077f39d738c..6fb6389c27e7 100644 --- a/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompilationGraph.java +++ b/substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompilationGraph.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2022, 2022, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2022, 2025, 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 @@ -24,9 +24,10 @@ */ package com.oracle.svm.hosted.code; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; +import org.graalvm.collections.EconomicSet; + +import com.oracle.graal.pointsto.flow.AnalysisParsedGraph; +import com.oracle.svm.hosted.meta.HostedMethod; import jdk.graal.compiler.graph.NodeSourcePosition; import jdk.graal.compiler.nodes.CallTargetNode.InvokeKind; @@ -35,9 +36,6 @@ import jdk.graal.compiler.nodes.StructuredGraph; import jdk.graal.compiler.nodes.java.MethodCallTargetNode; -import com.oracle.graal.pointsto.flow.AnalysisParsedGraph; -import com.oracle.svm.hosted.meta.HostedMethod; - /** * A holder for an {@link EncodedGraph} while doing the AOT compilation in {@link CompileQueue}. * Encoding the graph is important to reduce the memory footprint of the image generator. But a few @@ -93,10 +91,10 @@ public NodeSourcePosition getNodeSourcePosition() { private final EncodedGraph encodedGraph; private final int nodeCount; - private final Set invokeInfos; - private final Set allocationInfos; + private final EconomicSet invokeInfos; + private final EconomicSet allocationInfos; - private CompilationGraph(EncodedGraph encodedGraph, int nodeCount, Set invokeInfos, Set allocationInfos) { + private CompilationGraph(EncodedGraph encodedGraph, int nodeCount, EconomicSet invokeInfos, EconomicSet allocationInfos) { this.encodedGraph = encodedGraph; this.nodeCount = nodeCount; this.invokeInfos = invokeInfos; @@ -104,11 +102,10 @@ private CompilationGraph(EncodedGraph encodedGraph, int nodeCount, Set invokeInfos = new HashSet<>(); - Set allocationInfos = new HashSet<>(); + var invokeInfos = EconomicSet. create(); + var allocationInfos = EconomicSet. create(); for (var n : graph.getNodes()) { - if (n instanceof MethodCallTargetNode) { - MethodCallTargetNode node = (MethodCallTargetNode) n; + if (n instanceof MethodCallTargetNode node) { invokeInfos.add(new InvokeInfo( node.invokeKind(), (HostedMethod) node.targetMethod(), @@ -123,8 +120,8 @@ static CompilationGraph encode(StructuredGraph graph) { return new CompilationGraph( GraphEncoder.encodeSingleGraph(graph, AnalysisParsedGraph.HOST_ARCHITECTURE), graph.getNodeCount(), - invokeInfos.isEmpty() ? Collections.emptySet() : invokeInfos, - allocationInfos.isEmpty() ? Collections.emptySet() : allocationInfos); + invokeInfos.isEmpty() ? EconomicSet.emptySet() : invokeInfos, + allocationInfos.isEmpty() ? EconomicSet.emptySet() : allocationInfos); } public EncodedGraph getEncodedGraph() { @@ -135,11 +132,11 @@ public int getNodeCount() { return nodeCount; } - public Set getInvokeInfos() { + public EconomicSet getInvokeInfos() { return invokeInfos; } - public Set getAllocationInfos() { + public EconomicSet getAllocationInfos() { return allocationInfos; } }