Skip to content

Commit 7e85991

Browse files
committed
Remove abstractions over different conditions
1 parent 4ebb6ce commit 7e85991

18 files changed

+108
-233
lines changed

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/code/RuntimeMetadataDecoderImpl.java

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,6 @@
3333
import java.lang.reflect.Parameter;
3434
import java.lang.reflect.RecordComponent;
3535
import java.util.Arrays;
36-
import java.util.HashSet;
37-
import java.util.Set;
3836
import java.util.function.Function;
3937

4038
import org.graalvm.nativeimage.ImageSingletons;
@@ -43,7 +41,6 @@
4341

4442
import com.oracle.svm.core.SubstrateUtil;
4543
import com.oracle.svm.core.c.NonmovableArrays;
46-
import com.oracle.svm.core.configure.RuntimeCondition;
4744
import com.oracle.svm.core.configure.RuntimeConditionSet;
4845
import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton;
4946
import com.oracle.svm.core.hub.DynamicHub;
@@ -381,11 +378,7 @@ private static Object decodeField(UnsafeArrayTypeReader buf, Class<?> declaringC
381378

382379
private static RuntimeConditionSet decodeConditions(UnsafeArrayTypeReader buf) {
383380
var conditionTypes = decodeArray(buf, Class.class, i -> decodeType(buf));
384-
Set<RuntimeCondition> runtimeConditions = new HashSet<>(conditionTypes.length);
385-
for (Class<?> conditionType : conditionTypes) {
386-
runtimeConditions.add(RuntimeCondition.createTypeReachedCondition(conditionType));
387-
}
388-
return RuntimeConditionSet.createRuntime(runtimeConditions);
381+
return RuntimeConditionSet.createDecoded(conditionTypes);
389382
}
390383

391384
/**

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ConfigurationFiles.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,10 +128,13 @@ public static final class Options {
128128
@Option(help = "Testing flag: the typeReachable condition is treated as typeReached so the semantics of programs can change.")//
129129
public static final HostedOptionKey<Boolean> TreatAllTypeReachableConditionsAsTypeReached = new HostedOptionKey<>(false);
130130

131-
@Option(help = "Testing flag: the typeReached condition is always satisfied however it prints the stack traces where it would not be satisfied.")//
131+
@Option(help = "Testing flag: the 'name' is treated as 'type' reflection configuration.")//
132+
public static final HostedOptionKey<Boolean> TreatAllNameEntriesAsType = new HostedOptionKey<>(false);
133+
134+
@Option(help = "Testing flag: the 'typeReached' condition is always satisfied however it prints the stack trace where it would not be satisfied.")//
132135
public static final HostedOptionKey<Boolean> TrackUnsatisfiedTypeReachedConditions = new HostedOptionKey<>(false);
133136

134-
@Option(help = "Testing flag: print typeReached conditions that are used on interfaces.")//
137+
@Option(help = "Testing flag: print 'typeReached' conditions that are used on interfaces at build time.")//
135138
public static final HostedOptionKey<Boolean> TrackTypeReachedOnInterfaces = new HostedOptionKey<>(false);
136139

137140
@Option(help = "Testing flag: every type is considered as it participates in a typeReachable condition.")//

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
*/
2525
package com.oracle.svm.core.configure;
2626

27+
import static com.oracle.svm.core.configure.ConfigurationFiles.Options.TreatAllNameEntriesAsType;
2728
import static com.oracle.svm.core.configure.ConfigurationFiles.Options.TreatAllTypeReachableConditionsAsTypeReached;
2829
import static org.graalvm.nativeimage.impl.UnresolvedConfigurationCondition.TYPE_REACHABLE_KEY;
2930
import static org.graalvm.nativeimage.impl.UnresolvedConfigurationCondition.TYPE_REACHED_KEY;
@@ -215,7 +216,7 @@ protected UnresolvedConfigurationCondition parseCondition(EconomicMap<String, Ob
215216

216217
if (conditionObject.containsKey(TYPE_REACHED_KEY)) {
217218
if (!runtimeCondition) {
218-
failOnSchemaError("'" + TYPE_REACHED_KEY + "' condition can not be used in older schemas. Please migrate to the latest schema.");
219+
failOnSchemaError("'" + TYPE_REACHED_KEY + "' condition cannot be used in older schemas. Please migrate the file to the latest schema.");
219220
}
220221
Object object = conditionObject.get(TYPE_REACHED_KEY);
221222
var condition = parseTypeContents(object);
@@ -224,7 +225,7 @@ protected UnresolvedConfigurationCondition parseCondition(EconomicMap<String, Ob
224225
return UnresolvedConfigurationCondition.create(className, true);
225226
}
226227
} else if (conditionObject.containsKey(TYPE_REACHABLE_KEY)) {
227-
if (runtimeCondition) {
228+
if (runtimeCondition && !TreatAllTypeReachableConditionsAsTypeReached.getValue()) {
228229
failOnSchemaError("'" + TYPE_REACHABLE_KEY + "' condition can not be used with the latest schema. Please use '" + TYPE_REACHED_KEY + "'.");
229230
}
230231
Object object = conditionObject.get(TYPE_REACHABLE_KEY);
@@ -248,7 +249,7 @@ protected static Optional<ConfigurationTypeDescriptor> parseTypeOrName(EconomicM
248249
if (typeObject != null) {
249250
return parseTypeContents(typeObject);
250251
} else if (name != null) {
251-
return Optional.of(new NamedConfigurationTypeDescriptor(asString(name)));
252+
return Optional.of(new NamedConfigurationTypeDescriptor(asString(name), TreatAllNameEntriesAsType.getValue()));
252253
} else {
253254
throw failOnSchemaError("must have type or name specified for an element");
254255
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ConfigurationTypeDescriptor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,5 @@ static String checkQualifiedJavaName(String javaName) {
7373
return canonicalizeTypeName(javaName);
7474
}
7575

76-
boolean isType();
76+
boolean definedAsType();
7777
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/NamedConfigurationTypeDescriptor.java

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,20 +30,20 @@
3030

3131
import com.oracle.svm.core.util.json.JsonWriter;
3232

33-
public record NamedConfigurationTypeDescriptor(String name, boolean type) implements ConfigurationTypeDescriptor {
33+
public record NamedConfigurationTypeDescriptor(String name, boolean definedAsType) implements ConfigurationTypeDescriptor {
3434

3535
public NamedConfigurationTypeDescriptor(String name) {
3636
this(name, false);
3737
}
3838

39-
public NamedConfigurationTypeDescriptor(String name, boolean type) {
39+
public NamedConfigurationTypeDescriptor(String name, boolean definedAsType) {
4040
this.name = ConfigurationTypeDescriptor.checkQualifiedJavaName(name);
41-
this.type = type;
41+
this.definedAsType = definedAsType;
4242
}
4343

4444
@Override
45-
public boolean isType() {
46-
return type;
45+
public boolean definedAsType() {
46+
return definedAsType;
4747
}
4848

4949
@Override
@@ -74,5 +74,4 @@ public int compareTo(ConfigurationTypeDescriptor other) {
7474
public void printJson(JsonWriter writer) throws IOException {
7575
writer.quote(name);
7676
}
77-
7877
}

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ProxyConfigurationTypeDescriptor.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ public int compareTo(ConfigurationTypeDescriptor other) {
6565
}
6666

6767
@Override
68-
public boolean isType() {
68+
public boolean definedAsType() {
6969
return true;
7070
}
7171

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/ReflectionConfigurationParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ private void parseClass(EconomicMap<String, Object> data) {
8484
if (type.isEmpty()) {
8585
return;
8686
}
87-
boolean isType = type.get().isType();
87+
boolean isType = type.get().definedAsType();
8888

8989
UnresolvedConfigurationCondition unresolvedCondition = parseCondition(data, isType);
9090
TypeResult<C> conditionResult = conditionResolver.resolveCondition(unresolvedCondition);

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/RuntimeCondition.java

Lines changed: 0 additions & 76 deletions
This file was deleted.

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/RuntimeConditionSet.java

Lines changed: 63 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -30,43 +30,40 @@
3030
import java.util.Arrays;
3131
import java.util.HashSet;
3232
import java.util.Set;
33-
import java.util.stream.Collectors;
34-
import java.util.stream.Stream;
3533

3634
import org.graalvm.nativeimage.Platform;
3735
import org.graalvm.nativeimage.Platforms;
3836
import org.graalvm.nativeimage.impl.ConfigurationCondition;
3937

38+
import com.oracle.svm.core.hub.DynamicHub;
4039
import com.oracle.svm.core.util.VMError;
4140
import com.oracle.svm.util.LogUtils;
4241

4342
/**
44-
* Represents a group of {@link RuntimeCondition}s that guard a value.
43+
* Represents a group of {@link #conditions} that guard a value. The conditions are encoded
4544
* <p>
4645
* If any of the {@link #conditions} is satisfied then the whole set becomes also
4746
* {@link #satisfied}. {@link RuntimeConditionSet}s can be created at build time
48-
* {@link #createHosted(ConfigurationCondition...)} and stored to the image heap, or it can be
49-
* encoded ({@link #getTypesForEncoding()} and later decoded at run time
50-
* ({@link #createRuntime(Set)}. The current implementation does not cache {@link #conditions},
51-
* although this will be implemented in the future (GR-49526)
47+
* {@link #createHosted(ConfigurationCondition)} and stored to the image heap, or it can be encoded
48+
* ({@link #getTypesForEncoding()} and later decoded at run time ({@link #createDecoded(Object[])}.
49+
* The current implementation does not cache {@link #conditions}, although this will be implemented
50+
* in the future (GR-49526)
5251
*/
5352
public class RuntimeConditionSet {
5453

55-
private RuntimeCondition[] conditions;
54+
private Object[] conditions;
5655
private boolean satisfied;
5756

5857
@Platforms(Platform.HOSTED_ONLY.class)
59-
public static RuntimeConditionSet createHosted(ConfigurationCondition... conditions) {
60-
var conditionSet = new RuntimeConditionSet(Set.of());
61-
for (ConfigurationCondition condition : conditions) {
62-
conditionSet.addCondition(condition);
63-
}
64-
return conditionSet;
58+
public static RuntimeConditionSet emptySet() {
59+
return new RuntimeConditionSet(new Object[0]);
6560
}
6661

6762
@Platforms(Platform.HOSTED_ONLY.class)
68-
public static RuntimeConditionSet unmodifiableEmptySet() {
69-
return UnmodifiableRuntimeConditionSet.UNMODIFIABLE_EMPTY_SET;
63+
public static RuntimeConditionSet createHosted(ConfigurationCondition condition) {
64+
var conditionSet = new RuntimeConditionSet(new Object[0]);
65+
conditionSet.addCondition(condition);
66+
return conditionSet;
7067
}
7168

7269
@Platforms(Platform.HOSTED_ONLY.class)
@@ -80,10 +77,10 @@ public synchronized void addCondition(ConfigurationCondition cnd) {
8077
return;
8178
}
8279

83-
RuntimeCondition newRuntimeCondition = RuntimeCondition.create(cnd);
84-
Stream<RuntimeCondition> existingConditions = conditions == null ? Stream.empty() : Arrays.stream(conditions);
85-
setConditions(Stream.concat(existingConditions, Stream.of(newRuntimeCondition))
86-
.collect(Collectors.toSet()));
80+
Object newRuntimeCondition = createRuntimeCondition(cnd);
81+
Set<Object> existingConditions = conditions == null ? new HashSet<>() : new HashSet<>(Arrays.asList(conditions));
82+
existingConditions.add(newRuntimeCondition);
83+
setConditions(existingConditions.toArray());
8784
}
8885

8986
@Platforms(Platform.HOSTED_ONLY.class)
@@ -92,28 +89,19 @@ public Set<Class<?>> getTypesForEncoding() {
9289
return Set.of();
9390
} else {
9491
Set<Class<?>> types = new HashSet<>();
95-
for (RuntimeCondition condition : conditions) {
96-
types.addAll(condition.getTypesForEncoding());
92+
for (Object condition : conditions) {
93+
types.addAll(getTypesForEncoding(condition));
9794
}
9895
return types;
9996
}
10097
}
10198

102-
public static RuntimeConditionSet createRuntime(Set<RuntimeCondition> conditions) {
103-
return new RuntimeConditionSet(conditions);
104-
}
105-
106-
private RuntimeConditionSet(Set<RuntimeCondition> conditions) {
107-
setConditions(conditions);
99+
public static RuntimeConditionSet unmodifiableEmptySet() {
100+
return UnmodifiableRuntimeConditionSet.UNMODIFIABLE_EMPTY_SET;
108101
}
109102

110-
private void setConditions(Set<RuntimeCondition> conditions) {
111-
if (conditions.isEmpty()) {
112-
this.conditions = null;
113-
} else {
114-
this.conditions = conditions.toArray(RuntimeCondition[]::new);
115-
}
116-
satisfied = false;
103+
public static RuntimeConditionSet createDecoded(Object[] conditions) {
104+
return new RuntimeConditionSet(conditions);
117105
}
118106

119107
/**
@@ -133,8 +121,8 @@ public boolean satisfied() {
133121
if (localConditions == null) {
134122
result = true;
135123
} else {
136-
for (RuntimeCondition condition : localConditions) {
137-
if (condition.isSatisfied()) {
124+
for (Object condition : localConditions) {
125+
if (isSatisfied(condition)) {
138126
conditions = null;
139127
satisfied = result = true;
140128
break;
@@ -158,10 +146,46 @@ public String toString() {
158146
return conditionsString + " = " + satisfied;
159147
}
160148

149+
private RuntimeConditionSet(Object[] conditions) {
150+
setConditions(conditions);
151+
}
152+
153+
private void setConditions(Object[] conditions) {
154+
if (conditions.length == 0) {
155+
this.conditions = null;
156+
} else {
157+
this.conditions = conditions;
158+
}
159+
satisfied = false;
160+
}
161+
162+
private static Object createRuntimeCondition(ConfigurationCondition cnd) {
163+
if (cnd.isAlwaysTrue() || !cnd.isRuntimeChecked()) {
164+
throw VMError.shouldNotReachHere("We should never create run-time conditions from conditions that are always true at build time. Condition: " + cnd);
165+
}
166+
return cnd.getType();
167+
}
168+
169+
private static boolean isSatisfied(Object condition) {
170+
if (condition instanceof Class<?> typeReachedCondition) {
171+
return DynamicHub.fromClass(typeReachedCondition).isReached();
172+
} else {
173+
throw VMError.shouldNotReachHere("Only typeReached condition is supported.");
174+
}
175+
}
176+
177+
private static Set<Class<?>> getTypesForEncoding(Object condition) {
178+
if (condition instanceof Class<?> res) {
179+
return Set.of(res);
180+
} else {
181+
throw VMError.shouldNotReachHere("Only typeReached condition is supported.");
182+
}
183+
}
184+
161185
public static final class UnmodifiableRuntimeConditionSet extends RuntimeConditionSet {
162-
private static final RuntimeConditionSet UNMODIFIABLE_EMPTY_SET = new UnmodifiableRuntimeConditionSet(Set.of());
186+
private static final RuntimeConditionSet UNMODIFIABLE_EMPTY_SET = new UnmodifiableRuntimeConditionSet(new Object[0]);
163187

164-
private UnmodifiableRuntimeConditionSet(Set<RuntimeCondition> conditions) {
188+
private UnmodifiableRuntimeConditionSet(Object[] conditions) {
165189
super(conditions);
166190
}
167191

substratevm/src/com.oracle.svm.core/src/com/oracle/svm/core/configure/SerializationConfigurationParser.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ private void parseSerializationDescriptorObject(EconomicMap<String, Object> data
105105
return;
106106
}
107107

108-
UnresolvedConfigurationCondition unresolvedCondition = parseCondition(data, targetSerializationClass.get().isType());
108+
UnresolvedConfigurationCondition unresolvedCondition = parseCondition(data, targetSerializationClass.get().definedAsType());
109109
var condition = conditionResolver.resolveCondition(unresolvedCondition);
110110
if (!condition.isPresent()) {
111111
return;

0 commit comments

Comments
 (0)