|
24 | 24 | */ |
25 | 25 | package com.oracle.svm.core; |
26 | 26 |
|
| 27 | +import java.util.ArrayList; |
27 | 28 | import java.util.HashMap; |
| 29 | +import java.util.List; |
28 | 30 | import java.util.Map; |
29 | 31 | import java.util.StringJoiner; |
30 | 32 | import java.util.function.Function; |
31 | 33 |
|
32 | | -import jdk.graal.compiler.api.replacements.Fold; |
33 | | -import jdk.graal.compiler.options.Option; |
34 | 34 | import org.graalvm.nativeimage.ImageSingletons; |
35 | 35 | import org.graalvm.nativeimage.Platform; |
36 | 36 | import org.graalvm.nativeimage.Platforms; |
37 | 37 |
|
| 38 | +import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; |
| 39 | +import com.oracle.svm.core.layeredimagesingleton.ImageSingletonLoader; |
| 40 | +import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter; |
| 41 | +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton; |
| 42 | +import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton.PersistFlags; |
38 | 43 | import com.oracle.svm.core.option.APIOption; |
39 | | -import com.oracle.svm.core.option.HostedOptionKey; |
40 | 44 | import com.oracle.svm.core.option.AccumulatingLocatableMultiOptionValue; |
41 | | -import com.oracle.svm.core.feature.AutomaticallyRegisteredImageSingleton; |
| 45 | +import com.oracle.svm.core.option.HostedOptionKey; |
| 46 | +import com.oracle.svm.core.traits.BuiltinTraits.BuildtimeAccessOnly; |
| 47 | +import com.oracle.svm.core.traits.SingletonLayeredCallbacks; |
| 48 | +import com.oracle.svm.core.traits.SingletonLayeredCallbacksSupplier; |
| 49 | +import com.oracle.svm.core.traits.SingletonLayeredInstallationKind.Independent; |
| 50 | +import com.oracle.svm.core.traits.SingletonTrait; |
| 51 | +import com.oracle.svm.core.traits.SingletonTraitKind; |
| 52 | +import com.oracle.svm.core.traits.SingletonTraits; |
42 | 53 | import com.oracle.svm.core.util.VMError; |
43 | 54 |
|
| 55 | +import jdk.graal.compiler.api.replacements.Fold; |
| 56 | +import jdk.graal.compiler.options.Option; |
| 57 | + |
44 | 58 | class RuntimeAssertionsOptionTransformer implements Function<Object, Object> { |
45 | 59 |
|
46 | 60 | private static final String SEPARATOR = ","; |
@@ -77,9 +91,19 @@ static class Disable extends RuntimeAssertionsOptionTransformer { |
77 | 91 | } |
78 | 92 |
|
79 | 93 | @AutomaticallyRegisteredImageSingleton |
| 94 | +@SingletonTraits(access = BuildtimeAccessOnly.class, layeredCallbacks = RuntimeAssertionsSupport.LayeredCallbacks.class, layeredInstallationKind = Independent.class) |
80 | 95 | @Platforms(Platform.HOSTED_ONLY.class) |
81 | 96 | public final class RuntimeAssertionsSupport { |
82 | 97 |
|
| 98 | + private static final String PACKAGE = "package"; |
| 99 | + private static final String CLASS = "class"; |
| 100 | + |
| 101 | + private static final String ASSERTION_STATUS_KEYS = "AssertionStatusKeys"; |
| 102 | + private static final String ASSERTION_STATUS_VALUES = "AssertionStatusValues"; |
| 103 | + |
| 104 | + private static final String DEFAULT_ASSERTION_STATUS = "defaultAssertionStatus"; |
| 105 | + private static final String SYSTEM_ASSERTION_STATUS = "systemAssertionStatus"; |
| 106 | + |
83 | 107 | public static final char ENABLE_PREFIX = '+'; |
84 | 108 | public static final char DISABLE_PREFIX = '-'; |
85 | 109 | public static final String PACKAGE_SUFFIX = "..."; |
@@ -201,4 +225,64 @@ public boolean getDefaultAssertionStatus() { |
201 | 225 | public boolean getDefaultSystemAssertionStatus() { |
202 | 226 | return systemAssertionStatus; |
203 | 227 | } |
| 228 | + |
| 229 | + static class LayeredCallbacks extends SingletonLayeredCallbacksSupplier { |
| 230 | + @Override |
| 231 | + public SingletonTrait getLayeredCallbacksTrait() { |
| 232 | + SingletonLayeredCallbacks action = new SingletonLayeredCallbacks() { |
| 233 | + @Override |
| 234 | + public LayeredImageSingleton.PersistFlags doPersist(ImageSingletonWriter writer, Object singleton) { |
| 235 | + RuntimeAssertionsSupport runtimeAssertionsSupport = (RuntimeAssertionsSupport) singleton; |
| 236 | + persistAssertionStatus(writer, PACKAGE, runtimeAssertionsSupport.packageAssertionStatus); |
| 237 | + persistAssertionStatus(writer, CLASS, runtimeAssertionsSupport.classAssertionStatus); |
| 238 | + writer.writeInt(DEFAULT_ASSERTION_STATUS, runtimeAssertionsSupport.defaultAssertionStatus ? 1 : 0); |
| 239 | + writer.writeInt(SYSTEM_ASSERTION_STATUS, runtimeAssertionsSupport.systemAssertionStatus ? 1 : 0); |
| 240 | + return PersistFlags.CALLBACK_ON_REGISTRATION; |
| 241 | + } |
| 242 | + |
| 243 | + private void persistAssertionStatus(ImageSingletonWriter writer, String type, Map<String, Boolean> assertionStatus) { |
| 244 | + List<String> keys = new ArrayList<>(); |
| 245 | + List<Boolean> values = new ArrayList<>(); |
| 246 | + for (var entry : assertionStatus.entrySet()) { |
| 247 | + keys.add(entry.getKey()); |
| 248 | + values.add(entry.getValue()); |
| 249 | + } |
| 250 | + writer.writeStringList(type + ASSERTION_STATUS_KEYS, keys); |
| 251 | + writer.writeBoolList(type + ASSERTION_STATUS_VALUES, values); |
| 252 | + } |
| 253 | + |
| 254 | + @Override |
| 255 | + public void onSingletonRegistration(ImageSingletonLoader loader, Object singleton) { |
| 256 | + RuntimeAssertionsSupport runtimeAssertionsSupport = (RuntimeAssertionsSupport) singleton; |
| 257 | + checkMaps(loadAssertionStatus(loader, PACKAGE), runtimeAssertionsSupport.packageAssertionStatus); |
| 258 | + checkMaps(loadAssertionStatus(loader, CLASS), runtimeAssertionsSupport.classAssertionStatus); |
| 259 | + checkBoolean(runtimeAssertionsSupport.defaultAssertionStatus, loader, DEFAULT_ASSERTION_STATUS); |
| 260 | + checkBoolean(runtimeAssertionsSupport.systemAssertionStatus, loader, SYSTEM_ASSERTION_STATUS); |
| 261 | + } |
| 262 | + |
| 263 | + private void checkBoolean(boolean currentLayerAssertionStatus, ImageSingletonLoader loader, String assertionStatusKey) { |
| 264 | + boolean previousLayerStatus = loader.readInt(assertionStatusKey) == 1; |
| 265 | + VMError.guarantee(currentLayerAssertionStatus == previousLayerStatus, "The assertion status is the previous layer was %s, but the assertion status in the current layer is %s", |
| 266 | + currentLayerAssertionStatus, previousLayerStatus); |
| 267 | + } |
| 268 | + |
| 269 | + private Map<String, Boolean> loadAssertionStatus(ImageSingletonLoader loader, String type) { |
| 270 | + HashMap<String, Boolean> result = new HashMap<>(); |
| 271 | + var keys = loader.readStringList(type + ASSERTION_STATUS_KEYS); |
| 272 | + var values = loader.readBoolList(type + ASSERTION_STATUS_VALUES); |
| 273 | + for (int i = 0; i < keys.size(); ++i) { |
| 274 | + result.put(keys.get(i), values.get(i)); |
| 275 | + } |
| 276 | + return result; |
| 277 | + } |
| 278 | + |
| 279 | + public static <T, U> void checkMaps(Map<T, U> previousLayerMap, Map<T, U> currentLayerMap) { |
| 280 | + VMError.guarantee(previousLayerMap.equals(currentLayerMap), |
| 281 | + "The assertion status maps should be the same across layers, but the map in previous layers is %s and the map in the current layer is %s", |
| 282 | + previousLayerMap, currentLayerMap); |
| 283 | + } |
| 284 | + }; |
| 285 | + return new SingletonTrait(SingletonTraitKind.LAYERED_CALLBACKS, action); |
| 286 | + } |
| 287 | + } |
204 | 288 | } |
0 commit comments