Skip to content

Commit 28d0406

Browse files
committed
[GR-65022] Economic collections.
PullRequest: graal/20991
2 parents 381d229 + 8debd00 commit 28d0406

File tree

17 files changed

+101
-80
lines changed

17 files changed

+101
-80
lines changed

sdk/src/org.graalvm.collections/snapshot.sigtest

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ meth public static <%0 extends java.lang.Object, %1 extends java.lang.Object> or
128128
meth public static <%0 extends java.lang.Object, %1 extends java.lang.Object> org.graalvm.collections.MapCursor<{%%0},{%%1}> emptyCursor()
129129
meth public void putAll(org.graalvm.collections.EconomicMap<{org.graalvm.collections.EconomicMap%0},{org.graalvm.collections.EconomicMap%1}>)
130130
meth public void putAll(org.graalvm.collections.UnmodifiableEconomicMap<? extends {org.graalvm.collections.EconomicMap%0},? extends {org.graalvm.collections.EconomicMap%1}>)
131+
meth public {org.graalvm.collections.EconomicMap%1} computeIfAbsent({org.graalvm.collections.EconomicMap%0},java.util.function.Function<? super {org.graalvm.collections.EconomicMap%0},? extends {org.graalvm.collections.EconomicMap%1}>)
131132
meth public {org.graalvm.collections.EconomicMap%1} putIfAbsent({org.graalvm.collections.EconomicMap%0},{org.graalvm.collections.EconomicMap%1})
132133

133134
CLSS public final org.graalvm.collections.EconomicMapUtil
@@ -163,6 +164,7 @@ meth public abstract void clear()
163164
meth public abstract void remove({org.graalvm.collections.EconomicSet%0})
164165
meth public static <%0 extends java.lang.Object> org.graalvm.collections.EconomicSet<{%%0}> create()
165166
meth public static <%0 extends java.lang.Object> org.graalvm.collections.EconomicSet<{%%0}> create(int)
167+
meth public static <%0 extends java.lang.Object> org.graalvm.collections.EconomicSet<{%%0}> create(java.lang.Iterable<{%%0}>)
166168
meth public static <%0 extends java.lang.Object> org.graalvm.collections.EconomicSet<{%%0}> create(org.graalvm.collections.Equivalence)
167169
meth public static <%0 extends java.lang.Object> org.graalvm.collections.EconomicSet<{%%0}> create(org.graalvm.collections.Equivalence,int)
168170
meth public static <%0 extends java.lang.Object> org.graalvm.collections.EconomicSet<{%%0}> create(org.graalvm.collections.Equivalence,org.graalvm.collections.UnmodifiableEconomicSet<{%%0}>)

sdk/src/org.graalvm.collections/src/org/graalvm/collections/EconomicMap.java

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2017, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2017, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -42,6 +42,7 @@
4242

4343
import java.util.Map;
4444
import java.util.function.BiFunction;
45+
import java.util.function.Function;
4546

4647
/**
4748
* Memory efficient map data structure that dynamically changes its representation depending on the
@@ -281,4 +282,21 @@ static <K, V> EconomicMap<K, V> of(K key1, V value1, K key2, V value2) {
281282
map.put(key2, value2);
282283
return map;
283284
}
285+
286+
/**
287+
* If the specified key is not already associated with a value (or is mapped to {@code null}),
288+
* attempts to compute its value using the given mapping function and enters it into this map
289+
* unless {@code null}.
290+
*
291+
* @since 25.1
292+
*/
293+
default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
294+
V value = get(key);
295+
if (value == null) {
296+
value = mappingFunction.apply(key);
297+
put(key, value);
298+
}
299+
return value;
300+
}
301+
284302
}

sdk/src/org.graalvm.collections/src/org/graalvm/collections/EconomicSet.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -167,8 +167,7 @@ static <E> EconomicSet<E> create(Equivalence strategy) {
167167

168168
/**
169169
* Creates a new set guaranteeing insertion order when iterating over its elements with the
170-
* default {@link Equivalence#DEFAULT} comparison strategy and inserts all elements of the
171-
* specified collection.
170+
* default {@link Equivalence#DEFAULT} comparison strategy.
172171
*
173172
* @since 19.0
174173
*/
@@ -207,6 +206,19 @@ static <E> EconomicSet<E> create(Equivalence strategy, UnmodifiableEconomicSet<E
207206
return EconomicMapImpl.create(strategy, c, true);
208207
}
209208

209+
/**
210+
* Creates a new set guaranteeing insertion order when iterating over its elements with the
211+
* default {@link Equivalence#DEFAULT} comparison strategy and inserts all elements of the
212+
* specified iterable.
213+
*
214+
* @since 25.1
215+
*/
216+
static <E> EconomicSet<E> create(Iterable<E> c) {
217+
EconomicSet<E> set = create();
218+
set.addAll(c);
219+
return set;
220+
}
221+
210222
/**
211223
* Return an empty, unmodifiable {@link EconomicSet}.
212224
*

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/MethodFlowsGraph.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ public final Iterable<TypeFlow<?>> flows() {
178178
private Iterator<TypeFlow<?>> flowsIterator() {
179179
return new Iterator<>() {
180180
final Deque<TypeFlow<?>> worklist = new ArrayDeque<>();
181-
final Set<TypeFlow<?>> seen = new HashSet<>();
181+
final Set<TypeFlow<?>> seen = new HashSet<>(); // no EconomicSet, null key is used
182182
TypeFlow<?> next;
183183

184184
{

substratevm/src/com.oracle.graal.pointsto/src/com/oracle/graal/pointsto/flow/builder/TypeFlowBuilder.java

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,7 @@
2424
*/
2525
package com.oracle.graal.pointsto.flow.builder;
2626

27-
import java.util.Collection;
28-
import java.util.HashSet;
2927
import java.util.List;
30-
import java.util.Set;
3128
import java.util.function.Supplier;
3229

3330
import com.oracle.graal.pointsto.PointsToAnalysis;
@@ -39,6 +36,7 @@
3936
import com.oracle.graal.pointsto.typestate.PointsToStats;
4037

4138
import jdk.graal.compiler.phases.common.LazyValue;
39+
import org.graalvm.collections.EconomicSet;
4240

4341
/**
4442
* The type flow builder is a node in the type flow builder graph. The {@link #useDependencies} and
@@ -90,9 +88,9 @@ private static boolean checkPredicate(PointsToAnalysis bb, Class<?> clazz, Objec
9088
private final Class<T> flowClass;
9189
private final LazyValue<T> lazyTypeFlowCreator;
9290
/** Input dependency, i.e., builders that have this builder as an use. */
93-
private final Set<TypeFlowBuilder<?>> useDependencies;
91+
private final EconomicSet<TypeFlowBuilder<?>> useDependencies;
9492
/** Input dependency, i.e., builders that have this builder as an observer. */
95-
private final Set<TypeFlowBuilder<?>> observerDependencies;
93+
private final EconomicSet<TypeFlowBuilder<?>> observerDependencies;
9694
private boolean buildingAnActualParameter;
9795
private boolean isMaterialized;
9896

@@ -107,8 +105,8 @@ private TypeFlowBuilder(Object source, Object predicate, Class<T> flowClass, Laz
107105
this.flowClass = flowClass;
108106
this.source = source;
109107
this.lazyTypeFlowCreator = creator;
110-
this.useDependencies = new HashSet<>();
111-
this.observerDependencies = new HashSet<>();
108+
this.useDependencies = EconomicSet.create();
109+
this.observerDependencies = EconomicSet.create();
112110
this.buildingAnActualParameter = false;
113111
this.isMaterialized = false;
114112
this.predicate = predicate;
@@ -138,15 +136,15 @@ public void addUseDependency(TypeFlowBuilder<?> dependency) {
138136
this.useDependencies.add(dependency);
139137
}
140138

141-
Collection<TypeFlowBuilder<?>> getUseDependencies() {
139+
Iterable<TypeFlowBuilder<?>> getUseDependencies() {
142140
return useDependencies;
143141
}
144142

145143
public void addObserverDependency(TypeFlowBuilder<?> dependency) {
146144
this.observerDependencies.add(dependency);
147145
}
148146

149-
Collection<TypeFlowBuilder<?>> getObserverDependencies() {
147+
Iterable<TypeFlowBuilder<?>> getObserverDependencies() {
150148
return observerDependencies;
151149
}
152150

substratevm/src/com.oracle.svm.agent/src/com/oracle/svm/agent/NativeImageAgent.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -47,16 +47,15 @@
4747
import java.util.Arrays;
4848
import java.util.ConcurrentModificationException;
4949
import java.util.Date;
50-
import java.util.HashSet;
5150
import java.util.List;
52-
import java.util.Set;
5351
import java.util.TimeZone;
5452
import java.util.concurrent.ScheduledThreadPoolExecutor;
5553
import java.util.concurrent.TimeUnit;
5654
import java.util.function.Function;
5755
import java.util.function.Predicate;
5856
import java.util.function.Supplier;
5957

58+
import org.graalvm.collections.EconomicSet;
6059
import org.graalvm.nativeimage.Platform;
6160
import org.graalvm.nativeimage.ProcessProperties;
6261
import org.graalvm.nativeimage.hosted.Feature;
@@ -109,7 +108,7 @@ public final class NativeImageAgent extends JvmtiAgentBase<NativeImageAgentJNIHa
109108
private Path configOutputDirPath;
110109
private Path configOutputLockFilePath;
111110
private FileTime expectedConfigModifiedBefore;
112-
Set<String> classPathEntries;
111+
EconomicSet<String> classPathEntries;
113112

114113
private static String getTokenValue(String token) {
115114
return token.substring(token.indexOf('=') + 1);
@@ -287,7 +286,7 @@ protected int onLoadCallback(JNIJavaVM vm, JvmtiEnv jvmti, JvmtiEventCallbacks c
287286
return error(USAGE_ERROR, "The agent can generate conditional configuration either for the current run or in the partial mode but not both at the same time.");
288287
}
289288

290-
classPathEntries = new HashSet<>(Arrays.asList(getClasspathEntries(jvmti)));
289+
classPathEntries = EconomicSet.create(Arrays.asList(getClasspathEntries(jvmti)));
291290

292291
boolean isConditionalConfigurationRun = !conditionalConfigUserPackageFilterFiles.isEmpty() || conditionalConfigPartialRun;
293292
boolean shouldTraceOriginInformation = configurationWithOrigins || isConditionalConfigurationRun;

substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/CommonOptionParser.java

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,7 @@
3232
import java.util.Arrays;
3333
import java.util.Comparator;
3434
import java.util.EnumSet;
35-
import java.util.HashSet;
3635
import java.util.List;
37-
import java.util.Set;
3836
import java.util.function.Consumer;
3937
import java.util.function.Predicate;
4038

@@ -70,13 +68,13 @@ public class CommonOptionParser {
7068
*/
7169
public static final class OptionParseResult {
7270
private final EnumSet<OptionType> printFlags;
73-
private final Set<String> optionNameFilter;
71+
private final EconomicSet<String> optionNameFilter;
7472
private final String error;
7573
private final OptionKey<?> optionKey;
7674
private final boolean optionUnrecognized;
7775
private static final String EXTRA_HELP_OPTIONS_WILDCARD = "*";
7876

79-
OptionParseResult(EnumSet<OptionType> printFlags, String error, Set<String> optionNameFilter, OptionKey<?> optionKey, boolean optionUnrecognized) {
77+
OptionParseResult(EnumSet<OptionType> printFlags, String error, EconomicSet<String> optionNameFilter, OptionKey<?> optionKey, boolean optionUnrecognized) {
8078
this.printFlags = printFlags;
8179
this.error = error;
8280
this.optionNameFilter = optionNameFilter;
@@ -85,15 +83,15 @@ public static final class OptionParseResult {
8583
}
8684

8785
private OptionParseResult(EnumSet<OptionType> printFlags, String error, OptionKey<?> optionKey) {
88-
this(printFlags, error, new HashSet<>(), optionKey, false);
86+
this(printFlags, error, EconomicSet.create(), optionKey, false);
8987
}
9088

9189
static OptionParseResult error(String message) {
9290
return new OptionParseResult(EnumSet.noneOf(OptionType.class), message, null);
9391
}
9492

9593
static OptionParseResult optionUnrecognizedError(String message) {
96-
return new OptionParseResult(EnumSet.noneOf(OptionType.class), message, new HashSet<>(), null, true);
94+
return new OptionParseResult(EnumSet.noneOf(OptionType.class), message, EconomicSet.create(), null, true);
9795
}
9896

9997
static OptionParseResult correct(OptionKey<?> optionKey) {
@@ -104,10 +102,10 @@ static OptionParseResult printFlags(EnumSet<OptionType> selectedOptionTypes) {
104102
return new OptionParseResult(selectedOptionTypes, null, null);
105103
}
106104

107-
static OptionParseResult printFlagsWithExtraHelp(Set<String> optionNameFilter) {
108-
Set<String> optionNames = optionNameFilter;
105+
static OptionParseResult printFlagsWithExtraHelp(EconomicSet<String> optionNameFilter) {
106+
EconomicSet<String> optionNames = optionNameFilter;
109107
if (optionNames.contains(EXTRA_HELP_OPTIONS_WILDCARD)) {
110-
optionNames = new HashSet<>();
108+
optionNames = EconomicSet.create();
111109
optionNames.add(EXTRA_HELP_OPTIONS_WILDCARD);
112110
}
113111
return new OptionParseResult(EnumSet.noneOf(OptionType.class), null, optionNames, null, false);
@@ -292,7 +290,8 @@ public static OptionParseResult parseOption(EconomicMap<String, OptionDescriptor
292290
if (CommonOptions.PrintFlagsWithExtraHelp.getName().equals(optionName)) {
293291
String optionValue = (String) value;
294292
String[] optionNames = StringUtil.split(optionValue, ",");
295-
HashSet<String> selectedOptionNames = new HashSet<>(Arrays.asList(optionNames));
293+
EconomicSet<String> selectedOptionNames = EconomicSet.create();
294+
selectedOptionNames.addAll(Arrays.asList(optionNames));
296295
return OptionParseResult.printFlagsWithExtraHelp(selectedOptionNames);
297296
}
298297
return OptionParseResult.correct(optionKey);

substratevm/src/com.oracle.svm.common/src/com/oracle/svm/common/option/IntentionallyUnsupportedOptions.java

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,10 @@
2424
*/
2525
package com.oracle.svm.common.option;
2626

27-
import java.util.HashSet;
28-
import java.util.Set;
29-
3027
import jdk.graal.compiler.core.common.util.CompilationAlarm;
3128
import jdk.graal.compiler.hotspot.CompilerConfigurationFactory;
3229
import jdk.graal.compiler.options.OptionKey;
30+
import org.graalvm.collections.EconomicSet;
3331

3432
/**
3533
* Native image uses its own mechanisms to handle certain options, resulting in some Graal options
@@ -39,7 +37,7 @@
3937
*/
4038
public final class IntentionallyUnsupportedOptions {
4139

42-
private static final Set<OptionKey<?>> unsupportedOptions = new HashSet<>();
40+
private static final EconomicSet<OptionKey<?>> unsupportedOptions = EconomicSet.create();
4341

4442
static {
4543
unsupportedOptions.add(CompilerConfigurationFactory.Options.CompilerConfiguration);

substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/ConfigurationParser.java

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,12 @@
3737
import java.util.Collections;
3838
import java.util.Comparator;
3939
import java.util.EnumSet;
40-
import java.util.HashMap;
41-
import java.util.HashSet;
4240
import java.util.List;
43-
import java.util.Map;
4441
import java.util.Optional;
4542
import java.util.Set;
4643

4744
import org.graalvm.collections.EconomicMap;
45+
import org.graalvm.collections.EconomicSet;
4846
import org.graalvm.nativeimage.ImageInfo;
4947

5048
import com.oracle.svm.util.LogUtils;
@@ -83,7 +81,7 @@ public static InputStream openStream(URI uri) throws IOException {
8381
public static final String MODULE_KEY = "module";
8482
public static final String GLOB_KEY = "glob";
8583
public static final String BUNDLE_KEY = "bundle";
86-
private final Map<String, Set<String>> seenUnknownAttributesByType = new HashMap<>();
84+
private final EconomicMap<String, EconomicSet<String>> seenUnknownAttributesByType = EconomicMap.create();
8785
private final EnumSet<ConfigurationParserOption> parserOptions;
8886

8987
protected ConfigurationParser(EnumSet<ConfigurationParserOption> parserOptions) {
@@ -149,14 +147,15 @@ public static EconomicMap<String, Object> asMap(Object data, String errorMessage
149147
}
150148

151149
protected void checkAttributes(EconomicMap<String, Object> map, String type, Collection<String> requiredAttrs, Collection<String> optionalAttrs) {
152-
Set<String> unseenRequired = new HashSet<>(requiredAttrs);
150+
EconomicSet<String> unseenRequired = EconomicSet.create();
151+
unseenRequired.addAll(requiredAttrs);
153152
for (String key : map.getKeys()) {
154153
unseenRequired.remove(key);
155154
}
156155
if (!unseenRequired.isEmpty()) {
157156
throw new JsonParserException("Missing attribute(s) [" + String.join(", ", unseenRequired) + "] in " + type);
158157
}
159-
Set<String> unknownAttributes = new HashSet<>();
158+
EconomicSet<String> unknownAttributes = EconomicSet.create();
160159
for (String key : map.getKeys()) {
161160
unknownAttributes.add(key);
162161
}
@@ -170,7 +169,8 @@ protected void checkAttributes(EconomicMap<String, Object> map, String type, Col
170169
if (unknownAttributes.size() > 0) {
171170
String message = "Unknown attribute(s) [" + String.join(", ", unknownAttributes) + "] in " + type;
172171
warnOrFailOnSchemaError(message);
173-
Set<String> unknownAttributesForType = seenUnknownAttributesByType.computeIfAbsent(type, key -> new HashSet<>());
172+
173+
EconomicSet<String> unknownAttributesForType = seenUnknownAttributesByType.computeIfAbsent(type, key -> EconomicSet.create());
174174
unknownAttributesForType.addAll(unknownAttributes);
175175
}
176176
}

substratevm/src/com.oracle.svm.configure/src/com/oracle/svm/configure/command/ConfigurationGenerateCommand.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,10 +32,8 @@
3232
import java.nio.file.Path;
3333
import java.nio.file.Paths;
3434
import java.util.ArrayList;
35-
import java.util.HashSet;
3635
import java.util.Iterator;
3736
import java.util.List;
38-
import java.util.Set;
3937
import java.util.function.Predicate;
4038

4139
import com.oracle.svm.configure.ConfigurationUsageException;
@@ -50,6 +48,7 @@
5048
import com.oracle.svm.util.LogUtils;
5149

5250
import jdk.graal.compiler.phases.common.LazyValue;
51+
import org.graalvm.collections.EconomicSet;
5352

5453
public class ConfigurationGenerateCommand extends ConfigurationCommand {
5554
@Override
@@ -310,11 +309,11 @@ private static void parseFilterFiles(ComplexFilter filter, List<URI> filterFiles
310309

311310
@SuppressWarnings("fallthrough")
312311
private static void failIfAgentLockFilesPresent(ConfigurationFileCollection... collections) {
313-
Set<String> paths = null;
312+
EconomicSet<String> paths = null;
314313
for (ConfigurationFileCollection coll : collections) {
315314
for (URI path : coll.getDetectedAgentLockPaths()) {
316315
if (paths == null) {
317-
paths = new HashSet<>();
316+
paths = EconomicSet.create();
318317
}
319318
paths.add(path.toString());
320319
}

0 commit comments

Comments
 (0)