Skip to content

Commit 1306542

Browse files
committed
Allow future constants to be null
1 parent 5ddfcb9 commit 1306542

File tree

6 files changed

+49
-26
lines changed

6 files changed

+49
-26
lines changed

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/ClassLoaderFeature.java

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,21 +27,22 @@
2727
import java.util.concurrent.ConcurrentHashMap;
2828
import java.util.function.Function;
2929

30+
import org.graalvm.nativeimage.libgraal.hosted.LibGraalLoader;
31+
3032
import com.oracle.graal.pointsto.heap.ImageHeapConstant;
3133
import com.oracle.svm.core.BuildPhaseProvider;
3234
import com.oracle.svm.core.feature.AutomaticallyRegisteredFeature;
3335
import com.oracle.svm.core.feature.InternalFeature;
3436
import com.oracle.svm.core.fieldvaluetransformer.FieldValueTransformerWithAvailability;
37+
import com.oracle.svm.core.fieldvaluetransformer.ObjectToConstantFieldValueTransformer;
3538
import com.oracle.svm.core.hub.ClassForNameSupport;
3639
import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
3740
import com.oracle.svm.core.util.VMError;
3841
import com.oracle.svm.hosted.FeatureImpl.DuringSetupAccessImpl;
3942
import com.oracle.svm.hosted.imagelayer.CrossLayerConstantRegistry;
40-
import com.oracle.svm.core.fieldvaluetransformer.ObjectToConstantFieldValueTransformer;
4143
import com.oracle.svm.hosted.jdk.HostedClassLoaderPackageManagement;
4244
import com.oracle.svm.util.ReflectionUtil;
4345

44-
import org.graalvm.nativeimage.libgraal.hosted.LibGraalLoader;
4546
import jdk.internal.loader.ClassLoaders;
4647
import jdk.vm.ci.meta.JavaConstant;
4748
import jdk.vm.ci.meta.ResolvedJavaField;
@@ -94,7 +95,7 @@ private Object runtimeClassLoaderObjectReplacer(Object replaceCandidate) {
9495
return replaceCandidate;
9596
}
9697

97-
ImageHeapConstant replaceClassLoadersWithLayerConstant(CrossLayerConstantRegistry registry, Object object) {
98+
JavaConstant replaceClassLoadersWithLayerConstant(CrossLayerConstantRegistry registry, Object object) {
9899
if (object instanceof ClassLoader loader) {
99100
if (replaceWithAppClassLoader(loader) || loader == nativeImageSystemClassLoader.defaultSystemClassLoader) {
100101
return registry.getConstant(APP_KEY_NAME);
@@ -136,7 +137,7 @@ public void duringSetup(DuringSetupAccess access) {
136137
});
137138
}
138139
} else {
139-
config.registerObjectToConstantReplacer(obj -> replaceClassLoadersWithLayerConstant(registry, obj));
140+
config.registerObjectToConstantReplacer(obj -> (ImageHeapConstant) replaceClassLoadersWithLayerConstant(registry, obj));
140141
// relink packages defined in the prior layers
141142
config.registerObjectToConstantReplacer(packageManager::replaceWithPriorLayerPackage);
142143
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/SystemInOutErrFeature.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import com.oracle.svm.hosted.imagelayer.CrossLayerConstantRegistry;
4242

4343
import jdk.internal.access.SharedSecrets;
44+
import jdk.vm.ci.meta.JavaConstant;
4445

4546
/**
4647
* We use an {@link Feature.DuringSetupAccess#registerObjectReplacer object replacer} because the
@@ -96,7 +97,7 @@ public void duringSetup(DuringSetupAccess access) {
9697
access.registerObjectReplacer(this::replaceStreamsWithRuntimeObject);
9798
} else {
9899
var registry = CrossLayerConstantRegistry.singletonOrNull();
99-
((FeatureImpl.DuringSetupAccessImpl) access).registerObjectToConstantReplacer(obj -> replaceStreamsWithLayerConstant(registry, obj));
100+
((FeatureImpl.DuringSetupAccessImpl) access).registerObjectToConstantReplacer(obj -> (ImageHeapConstant) replaceStreamsWithLayerConstant(registry, obj));
100101
}
101102
}
102103

@@ -121,7 +122,7 @@ Object replaceStreamsWithRuntimeObject(Object object) {
121122
}
122123
}
123124

124-
ImageHeapConstant replaceStreamsWithLayerConstant(CrossLayerConstantRegistry registry, Object object) {
125+
JavaConstant replaceStreamsWithLayerConstant(CrossLayerConstantRegistry registry, Object object) {
125126
if (object == hostedIn) {
126127
return registry.getConstant(SYSTEM_IN_KEY_NAME);
127128
} else if (object == hostedOut) {

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/CrossLayerConstantRegistry.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,8 @@
2929
import com.oracle.graal.pointsto.heap.ImageHeapConstant;
3030
import com.oracle.graal.pointsto.meta.AnalysisType;
3131

32+
import jdk.vm.ci.meta.JavaConstant;
33+
3234
/**
3335
* Registry to manage cross-layer constant references.
3436
*/
@@ -46,7 +48,7 @@ static CrossLayerConstantRegistry singletonOrNull() {
4648
* Retrieves the constant associated with {@code keyName}. If a constant does not exist then an
4749
* error is thrown.
4850
*/
49-
ImageHeapConstant getConstant(String keyName);
51+
JavaConstant getConstant(String keyName);
5052

5153
/**
5254
* Checks whether a constant for {@code keyName} was registered in a prior layer.

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/imagelayer/CrossLayerConstantRegistryFeature.java

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@
2424
*/
2525
package com.oracle.svm.hosted.imagelayer;
2626

27+
import static com.oracle.svm.hosted.imagelayer.CrossLayerConstantRegistryFeature.INVALID;
28+
2729
import java.util.ArrayList;
2830
import java.util.EnumSet;
2931
import java.util.HashMap;
@@ -56,9 +58,12 @@
5658
import jdk.graal.compiler.core.common.CompressEncoding;
5759
import jdk.graal.compiler.core.common.NumUtil;
5860
import jdk.graal.compiler.debug.Assertions;
61+
import jdk.vm.ci.meta.JavaConstant;
5962

6063
@AutomaticallyRegisteredFeature
6164
public class CrossLayerConstantRegistryFeature implements InternalFeature, FeatureSingleton, CrossLayerConstantRegistry {
65+
static final int INVALID = -1;
66+
private static final Object NULL_CONSTANT_MARKER = new Object();
6267

6368
private record FutureConstantCandidateInfo(ImageHeapRelocatableConstant constant) {
6469
}
@@ -122,7 +127,7 @@ public void duringSetup(DuringSetupAccess access) {
122127
*/
123128
ImageHeapConstant replacePriorMarkersWithConstant(CrossLayerConstantRegistry registry, Object object) {
124129
if (object instanceof PriorLayerMarker priorLayerMarker) {
125-
return registry.getConstant(priorLayerMarker.getKey());
130+
return (ImageHeapConstant) registry.getConstant(priorLayerMarker.getKey());
126131
}
127132

128133
return null;
@@ -142,7 +147,7 @@ private void addInitialObjects(NativeImageHeap heap, HostedUniverse hUniverse) {
142147
* used by a prior layer. However, currently it is not worth introducing this
143148
* complication to the code.
144149
*/
145-
ImageHeapConstant singletonConstant = (ImageHeapConstant) hUniverse.getSnippetReflection().forObject(futureConstant);
150+
JavaConstant singletonConstant = futureConstant == NULL_CONSTANT_MARKER ? JavaConstant.NULL_POINTER : (ImageHeapConstant) hUniverse.getSnippetReflection().forObject(futureConstant);
146151
heap.addConstant(singletonConstant, false, addReason);
147152
}
148153
}
@@ -159,7 +164,7 @@ public void afterCompilation(AfterCompilationAccess access) {
159164
FutureConstantCandidateInfo futureConstant = (FutureConstantCandidateInfo) entry.getValue();
160165
var constant = futureConstant.constant();
161166
AnalysisType type = constant.getType();
162-
tracker.registerFutureTrackingInfo(new FutureTrackingInfo(key, FutureTrackingInfo.State.Type, type.getId(), -1));
167+
tracker.registerFutureTrackingInfo(new FutureTrackingInfo(key, FutureTrackingInfo.State.Type, type.getId(), INVALID));
163168

164169
});
165170
}
@@ -194,11 +199,17 @@ public void beforeImageWrite(BeforeImageWriteAccess access) {
194199
*/
195200
for (var entry : finalizedFutureConstants.entrySet()) {
196201
// We know these constants have been installed via addInitialObjects
197-
var futureConstant = (ImageHeapConstant) snippetReflection.forObject(entry.getValue());
198-
var objectInfo = heap.getConstantInfo(futureConstant);
199-
int id = ImageHeapConstant.getConstantID(futureConstant);
200-
FutureTrackingInfo info = (FutureTrackingInfo) tracker.getTrackingInfo(entry.getKey());
201-
tracker.updateFutureTrackingInfo(new FutureTrackingInfo(info.key(), FutureTrackingInfo.State.Final, id, NumUtil.safeToInt(objectInfo.getOffset())));
202+
Object value = entry.getValue();
203+
if (value == NULL_CONSTANT_MARKER) {
204+
FutureTrackingInfo info = (FutureTrackingInfo) tracker.getTrackingInfo(entry.getKey());
205+
tracker.updateFutureTrackingInfo(new FutureTrackingInfo(info.key(), FutureTrackingInfo.State.Final, INVALID, INVALID));
206+
} else {
207+
var futureConstant = (ImageHeapConstant) snippetReflection.forObject(value);
208+
var objectInfo = heap.getConstantInfo(futureConstant);
209+
int id = ImageHeapConstant.getConstantID(futureConstant);
210+
FutureTrackingInfo info = (FutureTrackingInfo) tracker.getTrackingInfo(entry.getKey());
211+
tracker.updateFutureTrackingInfo(new FutureTrackingInfo(info.key(), FutureTrackingInfo.State.Final, id, NumUtil.safeToInt(objectInfo.getOffset())));
212+
}
202213
}
203214

204215
if (ImageLayerBuildingSupport.buildingApplicationLayer()) {
@@ -241,7 +252,8 @@ private void generateRelocationPatchArray() {
241252
FutureTrackingInfo info = (FutureTrackingInfo) tracker.getTrackingInfo(entry.getKey());
242253
VMError.guarantee(info.state() == FutureTrackingInfo.State.Final, "Invalid future %s", info);
243254

244-
int referenceEncoding = info.offset() >>> shift;
255+
int offset = info.offset();
256+
int referenceEncoding = offset == INVALID ? 0 : offset >>> shift;
245257
for (int heapOffset : offsetsToPatch) {
246258
patchArray.add(heapOffset - heapBeginOffset);
247259
patchArray.add(referenceEncoding);
@@ -271,7 +283,7 @@ public boolean constantExists(String keyName) {
271283
}
272284

273285
@Override
274-
public ImageHeapConstant getConstant(String keyName) {
286+
public JavaConstant getConstant(String keyName) {
275287
TrackingInfo idInfo = tracker.getTrackingInfo(keyName);
276288
if (idInfo instanceof PriorTrackingInfo prior) {
277289
return loader.getOrCreateConstant(prior.constantId());
@@ -287,6 +299,10 @@ public ImageHeapConstant getConstant(String keyName) {
287299
if (idInfo instanceof FutureTrackingInfo future) {
288300
VMError.guarantee(!finalizedFutureConstants.containsKey(keyName), "Future was finalized in this layer: %s", future);
289301

302+
if (future.loaderId() == INVALID) {
303+
return JavaConstant.NULL_POINTER;
304+
}
305+
290306
if (future.state() != FutureTrackingInfo.State.Type) {
291307
return loader.getOrCreateConstant(future.loaderId());
292308
}
@@ -339,7 +355,8 @@ public void finalizeFutureHeapConstant(String keyName, Object obj) {
339355
checkCandidateRegistry();
340356
VMError.guarantee(tracker.getTrackingInfo(keyName) instanceof FutureTrackingInfo, "This key was not registered as a future constant %s", keyName);
341357

342-
var previous = finalizedFutureConstants.putIfAbsent(keyName, obj);
358+
Object object = obj == null ? NULL_CONSTANT_MARKER : obj;
359+
var previous = finalizedFutureConstants.putIfAbsent(keyName, object);
343360
VMError.guarantee(previous == null, "This key has been registered before: %s", keyName);
344361
}
345362

@@ -351,7 +368,7 @@ public void markFutureHeapConstantPatchSite(ImageHeapRelocatableConstant constan
351368
VMError.guarantee(!patchingSealed, "Cross layer patching is sealed");
352369
var data = constant.getConstantData();
353370
tracker.registerPatchSite(data.key, heapOffset);
354-
tracker.updateFutureTrackingInfo(new FutureTrackingInfo(data.key, FutureTrackingInfo.State.Relocatable, ImageHeapConstant.getConstantID(constant), -1));
371+
tracker.updateFutureTrackingInfo(new FutureTrackingInfo(data.key, FutureTrackingInfo.State.Relocatable, ImageHeapConstant.getConstantID(constant), INVALID));
355372
}
356373

357374
/**
@@ -506,7 +523,7 @@ public static Object createFromLoader(ImageSingletonLoader loader) {
506523
String key = futureKeys.next();
507524
FutureTrackingInfo.State state = FutureTrackingInfo.State.values()[futureStates.next()];
508525
int loaderId = futureLoaderIds.next();
509-
int offset = state == FutureTrackingInfo.State.Final ? futureOffsets.next() : -1;
526+
int offset = state == FutureTrackingInfo.State.Final ? futureOffsets.next() : INVALID;
510527
tracker.registerFutureTrackingInfo(new FutureTrackingInfo(key, state, loaderId, offset));
511528

512529
List<Integer> offsetsToPatch = loader.readIntList(futureKeyPatchKey(key));
@@ -531,14 +548,14 @@ enum State {
531548
}
532549

533550
public FutureTrackingInfo {
534-
assert key != null && loaderId >= 0 : Assertions.errorMessage(key, loaderId);
551+
assert key != null && loaderId >= INVALID : Assertions.errorMessage(key, loaderId);
535552
switch (state) {
536553
case Type:
537554
case Relocatable:
538-
assert offset == -1 : Assertions.errorMessage(state, offset);
555+
assert offset == INVALID : Assertions.errorMessage(state, offset);
539556
break;
540557
case Final:
541-
assert offset > 0 : Assertions.errorMessage(state, offset);
558+
assert offset > 0 || (offset == INVALID && loaderId == INVALID) : Assertions.errorMessage(state, offset);
542559
}
543560
}
544561
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/ForkJoinPoolFeature.java

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
import com.oracle.svm.hosted.FeatureImpl;
3636
import com.oracle.svm.hosted.imagelayer.CrossLayerConstantRegistry;
3737

38+
import jdk.vm.ci.meta.JavaConstant;
39+
3840
@AutomaticallyRegisteredFeature
3941
class ForkJoinPoolFeature implements InternalFeature, FeatureSingleton {
4042

@@ -44,7 +46,7 @@ class ForkJoinPoolFeature implements InternalFeature, FeatureSingleton {
4446
public void duringSetup(DuringSetupAccess access) {
4547
CrossLayerConstantRegistry registry = CrossLayerConstantRegistry.singletonOrNull();
4648
if (ImageLayerBuildingSupport.buildingExtensionLayer() && registry.constantExists(KEY_NAME)) {
47-
((FeatureImpl.DuringSetupAccessImpl) access).registerObjectToConstantReplacer(obj -> replaceCommonPoolWithLayerConstant(registry, obj));
49+
((FeatureImpl.DuringSetupAccessImpl) access).registerObjectToConstantReplacer(obj -> (ImageHeapConstant) replaceCommonPoolWithLayerConstant(registry, obj));
4850
} else {
4951
var commonPool = new DeferredCommonPool();
5052
access.registerObjectReplacer(obj -> replaceCommonPoolWithRuntimeObject(obj, commonPool));
@@ -62,7 +64,7 @@ private static Object replaceCommonPoolWithRuntimeObject(Object original, Deferr
6264
return original;
6365
}
6466

65-
private static ImageHeapConstant replaceCommonPoolWithLayerConstant(CrossLayerConstantRegistry registry, Object original) {
67+
private static JavaConstant replaceCommonPoolWithLayerConstant(CrossLayerConstantRegistry registry, Object original) {
6668
if (original == ForkJoinPool.commonPool()) {
6769
return registry.getConstant(KEY_NAME);
6870
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/jdk/HostedClassLoaderPackageManagement.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -236,7 +236,7 @@ public ImageHeapConstant replaceWithPriorLayerPackage(Object obj) {
236236

237237
var keyName = generateKeyName(hostedPackage.getName());
238238
if (registry.constantExists(keyName)) {
239-
return registry.getConstant(keyName);
239+
return (ImageHeapConstant) registry.getConstant(keyName);
240240
}
241241
}
242242

0 commit comments

Comments
 (0)