Skip to content

Commit 91b53d3

Browse files
committed
[GR-64325] Migrate more layered image metadata to schema.
PullRequest: graal/20574
2 parents e03b661 + 5d31475 commit 91b53d3

16 files changed

+934
-607
lines changed

substratevm/src/com.oracle.svm.hosted/resources/SharedLayerSnapshotCapnProtoSchema.capnp

Lines changed: 50 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ using MethodId = Int32;
88
using FieldId = Int32;
99
using ConstantId = Int32;
1010
using SingletonObjId = Int32;
11+
using HostedMethodIndex = Int32;
1112

1213
struct PersistedAnalysisType {
1314
id @0 :TypeId;
@@ -75,8 +76,8 @@ struct PersistedAnalysisMethod {
7576
argumentTypeIds @6 :List(TypeId);
7677
returnTypeId @7 :TypeId;
7778
modifiers @8 :Int32;
78-
code @9 :Data;
79-
codeSize @10 :Int32;
79+
bytecode @9 :Data;
80+
bytecodeSize @10 :Int32;
8081
isConstructor @11 :Bool;
8182
isSynthetic @12 :Bool;
8283
canBeStaticallyBound @13 :Bool;
@@ -92,32 +93,33 @@ struct PersistedAnalysisMethod {
9293
analysisGraphLocation @23 :Text;
9394
analysisGraphIsIntrinsic @24 :Bool;
9495
strengthenedGraphLocation @25 :Text;
96+
hostedMethodIndex @26 :HostedMethodIndex;
9597
wrappedMethod :union {
96-
none @26 :Void; # default
98+
none @27 :Void; # default
9799
factoryMethod :group {
98-
targetConstructorId @27 :MethodId;
99-
throwAllocatedObject @28 :Bool;
100-
instantiatedTypeId @29 :TypeId;
100+
targetConstructorId @28 :MethodId;
101+
throwAllocatedObject @29 :Bool;
102+
instantiatedTypeId @30 :TypeId;
101103
}
102104
outlinedSB :group {
103-
methodTypeReturn @30 :Text;
104-
methodTypeParameters @31 :List(Text);
105+
methodTypeReturn @31 :Text;
106+
methodTypeParameters @32 :List(Text);
105107
}
106108
cEntryPointCallStub :group {
107-
originalMethodId @32 :MethodId;
108-
notPublished @33 :Bool;
109+
originalMethodId @33 :MethodId;
110+
notPublished @34 :Bool;
109111
}
110112
wrappedMember :group {
111113
union {
112-
reflectionExpandSignature @34 :Void;
113-
javaCallVariantWrapper @35 :Void;
114+
reflectionExpandSignature @35 :Void;
115+
javaCallVariantWrapper @36 :Void;
114116
}
115-
name @36 :Text;
116-
declaringClassName @37 :Text;
117-
argumentTypeNames @38 :List(Text);
117+
name @37 :Text;
118+
declaringClassName @38 :Text;
119+
argumentTypeNames @39 :List(Text);
118120
}
119121
polymorphicSignature :group {
120-
callers @39 :List(MethodId);
122+
callers @40 :List(MethodId);
121123
}
122124
}
123125
}
@@ -273,6 +275,8 @@ struct SharedLayerSnapshot {
273275
staticFinalFieldFoldingSingleton @15 :StaticFinalFieldFoldingSingleton;
274276
registeredJNILibraries @16 :List(Text);
275277
layeredRuntimeMetadataSingleton @17 :LayeredRuntimeMetadataSingleton;
278+
dynamicHubInfos @18 :List(DynamicHubInfo);
279+
hostedMethods @19 :List(PersistedHostedMethod);
276280
}
277281

278282
struct StaticFinalFieldFoldingSingleton {
@@ -305,3 +309,33 @@ struct PrimitiveArray {
305309
d @7 :List(Float64);
306310
}
307311
}
312+
313+
struct DispatchSlotInfo {
314+
declaredHostedMethodIndex @0 :HostedMethodIndex;
315+
resolvedHostedMethodIndex @1 :HostedMethodIndex;
316+
slotIndex @2 :Int32;
317+
resolutionStatus @3 :Int32;
318+
slotSymbolName @4 :Text;
319+
}
320+
321+
struct PersistedHostedMethod {
322+
index @0 :Int32;
323+
methodId @1 :MethodId;
324+
vTableIndex @2 :Int32;
325+
installedOffset @3 :Int32;
326+
isVirtualCallTarget @4 :Bool;
327+
symbolName @5 :Text;
328+
hostedMethodName @6 :Text;
329+
hostedMethodUniqueName @7 :Text;
330+
}
331+
332+
struct DynamicHubInfo {
333+
typeId @0 :TypeId;
334+
installed @1 :Bool;
335+
typecheckId @2 :Int32;
336+
numClassTypes @3 :Int32;
337+
numInterfaceTypes @4 :Int32;
338+
typecheckSlotValues @5 :List(Int32);
339+
locallyDeclaredSlotsHostedMethodIndexes @6 :List(HostedMethodIndex);
340+
dispatchTableSlotValues @7 :List(DispatchSlotInfo);
341+
}

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

Lines changed: 49 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -24,15 +24,10 @@
2424
*/
2525
package com.oracle.svm.hosted;
2626

27-
import java.util.ArrayList;
2827
import java.util.Arrays;
2928
import java.util.Collection;
3029
import java.util.EnumSet;
31-
import java.util.HashMap;
3230
import java.util.HashSet;
33-
import java.util.List;
34-
import java.util.Map;
35-
import java.util.Objects;
3631
import java.util.Set;
3732

3833
import org.graalvm.nativeimage.ImageSingletons;
@@ -50,6 +45,8 @@
5045
import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter;
5146
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton;
5247
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags;
48+
import com.oracle.svm.hosted.imagelayer.HostedImageLayerBuildingSupport;
49+
import com.oracle.svm.hosted.imagelayer.SVMImageLayerLoader;
5350
import com.oracle.svm.hosted.meta.HostedType;
5451

5552
import jdk.graal.compiler.debug.Assertions;
@@ -65,7 +62,7 @@ public boolean isInConfiguration(Feature.IsInConfigurationAccess access) {
6562
@Override
6663
public void beforeUniverseBuilding(BeforeUniverseBuildingAccess access) {
6764
if (ImageLayerBuildingSupport.buildingInitialLayer()) {
68-
ImageSingletons.add(LayerTypeCheckInfo.class, new LayerTypeCheckInfo());
65+
ImageSingletons.add(LayerTypeCheckInfo.class, new LayerTypeCheckInfo(0));
6966
}
7067
}
7168

@@ -112,136 +109,86 @@ public static int loadTypeInfo(Collection<HostedType> types) {
112109
}
113110
}
114111

115-
public static void persistTypeInfo(Collection<HostedType> types) {
116-
if (ImageLayerBuildingSupport.buildingImageLayer()) {
117-
ImageSingletons.lookup(LayerTypeCheckInfo.class).persistTypeInfo(types);
118-
}
119-
}
120-
121-
record TypeCheckInfo(int typeID, int numClassTypes, int numInterfaceTypes, int[] typecheckSlots) {
122-
private List<Integer> toIntList() {
123-
ArrayList<Integer> list = new ArrayList<>();
124-
list.add(typeID);
125-
list.add(numClassTypes);
126-
list.add(numInterfaceTypes);
127-
Arrays.stream(typecheckSlots).forEach(list::add);
128-
129-
return list;
130-
}
112+
@SuppressWarnings("unused")
113+
public static boolean validateTypeInfo(Collection<HostedType> types) {
114+
if (ImageLayerBuildingSupport.buildingExtensionLayer()) {
115+
var loader = HostedImageLayerBuildingSupport.singleton().getLoader();
116+
for (HostedType type : types) {
117+
if (type.getWrapped().isInBaseLayer()) {
118+
var priorInfo = getTypecheckInfo(loader, type);
119+
if (!priorInfo.installed()) {
120+
// no need to validate this hub, as it was not installed
121+
continue;
122+
}
123+
int typeID = type.getTypeID();
124+
int numClassTypes = type.getNumClassTypes();
125+
int numInterfaceTypes = type.getNumInterfaceTypes();
126+
int[] typecheckSlots = type.getOpenTypeWorldTypeCheckSlots();
127+
boolean matches = typeID == priorInfo.typeID && numClassTypes == priorInfo.numClassTypes && numInterfaceTypes == priorInfo.numInterfaceTypes &&
128+
Arrays.equals(typecheckSlots, priorInfo.typecheckSlots);
129+
if (!matches) {
130+
var typeInfo = new TypeCheckInfo(true, typeID, numClassTypes, numInterfaceTypes, typecheckSlots);
131+
assert false : Assertions.errorMessage("Mismatch for ", type, priorInfo, typeInfo, Arrays.toString(priorInfo.typecheckSlots),
132+
Arrays.toString(typeInfo.typecheckSlots));
131133

132-
private static TypeCheckInfo fromIntList(List<Integer> list) {
133-
int typeID = list.get(0);
134-
int numClassTypes = list.get(1);
135-
int numInterfaceTypes = list.get(2);
136-
int[] typecheckSlots = list.subList(3, list.size()).stream().mapToInt(i -> i).toArray();
137-
return new TypeCheckInfo(typeID, numClassTypes, numInterfaceTypes, typecheckSlots);
134+
}
135+
}
136+
}
138137
}
138+
return true;
139+
}
139140

140-
@Override
141-
public boolean equals(Object o) {
142-
if (this == o) {
143-
return true;
144-
}
145-
if (o == null || getClass() != o.getClass()) {
146-
return false;
141+
static TypeCheckInfo getTypecheckInfo(SVMImageLayerLoader loader, HostedType hType) {
142+
if (hType.getWrapped().isInBaseLayer()) {
143+
var hubInfo = loader.getDynamicHubInfo(hType.getWrapped());
144+
var valuesReader = hubInfo.getTypecheckSlotValues();
145+
int[] typecheckSlots = new int[valuesReader.size()];
146+
for (int i = 0; i < typecheckSlots.length; i++) {
147+
typecheckSlots[i] = valuesReader.get(i);
147148
}
148-
TypeCheckInfo typeCheckInfo = (TypeCheckInfo) o;
149-
return typeID == typeCheckInfo.typeID && numClassTypes == typeCheckInfo.numClassTypes && numInterfaceTypes == typeCheckInfo.numInterfaceTypes &&
150-
Arrays.equals(typecheckSlots, typeCheckInfo.typecheckSlots);
149+
return new TypeCheckInfo(hubInfo.getInstalled(), hubInfo.getTypecheckId(), hubInfo.getNumClassTypes(), hubInfo.getNumInterfaceTypes(), typecheckSlots);
150+
} else {
151+
return null;
151152
}
153+
}
152154

153-
@Override
154-
public int hashCode() {
155-
int result = Objects.hash(typeID, numClassTypes, numInterfaceTypes);
156-
result = 31 * result + Arrays.hashCode(typecheckSlots);
157-
return result;
158-
}
155+
record TypeCheckInfo(boolean installed, int typeID, int numClassTypes, int numInterfaceTypes, int[] typecheckSlots) {
159156
}
160157

161158
private static final class LayerTypeCheckInfo implements LayeredImageSingleton {
162-
Map<Integer, TypeCheckInfo> identifierToTypeInfo = new HashMap<>();
163-
int maxTypeID = 0;
159+
final int maxTypeID;
160+
161+
LayerTypeCheckInfo(int maxTypeID) {
162+
this.maxTypeID = maxTypeID;
163+
}
164164

165165
public int loadTypeID(Collection<HostedType> types) {
166-
ArrayList<Integer> usedIDs = new ArrayList<>();
166+
var loader = HostedImageLayerBuildingSupport.singleton().getLoader();
167167
for (HostedType type : types) {
168-
int identifierID = type.getWrapped().getId();
169-
TypeCheckInfo info = identifierToTypeInfo.get(identifierID);
168+
TypeCheckInfo info = getTypecheckInfo(loader, type);
170169
if (info != null) {
171-
usedIDs.add(info.typeID);
172170
type.loadTypeID(info.typeID);
173171
}
174172
}
175173

176174
return maxTypeID;
177175
}
178176

179-
public void persistTypeInfo(Collection<HostedType> types) {
180-
for (HostedType type : types) {
181-
/*
182-
* Currently we are calculating type id information for all types. However, for
183-
* types not tracked across layers, the type ID may not be the same in different
184-
* layers.
185-
*/
186-
assert type.getTypeID() != -1 : type;
187-
if (type.getWrapped().isTrackedAcrossLayers()) {
188-
int identifierID = type.getWrapped().getId();
189-
int typeID = type.getTypeID();
190-
int numClassTypes = type.getNumClassTypes();
191-
int numInterfaceTypes = type.getNumInterfaceTypes();
192-
int[] typecheckSlots = type.getOpenTypeWorldTypeCheckSlots();
193-
var priorInfo = identifierToTypeInfo.get(identifierID);
194-
var newTypeInfo = new TypeCheckInfo(typeID, numClassTypes, numInterfaceTypes, typecheckSlots);
195-
if (priorInfo == null) {
196-
identifierToTypeInfo.put(identifierID, newTypeInfo);
197-
} else {
198-
assert newTypeInfo.equals(priorInfo) : Assertions.errorMessage("Mismatch for ", type, priorInfo, newTypeInfo, Arrays.toString(priorInfo.typecheckSlots),
199-
Arrays.toString(newTypeInfo.typecheckSlots));
200-
}
201-
}
202-
}
203-
}
204-
205177
@Override
206178
public EnumSet<LayeredImageSingletonBuilderFlags> getImageBuilderFlags() {
207179
return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY;
208180
}
209181

210-
private static String getTypeInfoKey(int id) {
211-
return String.format("TypeInfo-%s", id);
212-
}
213-
214182
@Override
215183
public PersistFlags preparePersist(ImageSingletonWriter writer) {
216-
/*
217-
* Note all that is strictly needed to restore the typecheck information is the
218-
* (identifierID -> typeID) mappings. In the future we can compact the amount of
219-
* information we store.
220-
*/
221-
var typeIdentifierIds = identifierToTypeInfo.keySet().stream().sorted().toList();
222-
writer.writeIntList("typeIdentifierIds", typeIdentifierIds);
223184
writer.writeInt("maxTypeID", DynamicHubSupport.currentLayer().getMaxTypeId());
224185

225-
for (int identifierID : typeIdentifierIds) {
226-
var typeInfo = identifierToTypeInfo.get(identifierID);
227-
assert typeInfo != null;
228-
writer.writeIntList(getTypeInfoKey(identifierID), typeInfo.toIntList());
229-
}
230-
231186
return PersistFlags.CREATE;
232187
}
233188

234189
@SuppressWarnings("unused")
235190
public static Object createFromLoader(ImageSingletonLoader loader) {
236-
var info = new LayerTypeCheckInfo();
237-
info.maxTypeID = loader.readInt("maxTypeID");
238-
List<Integer> typeIdentifierIds = loader.readIntList("typeIdentifierIds");
239-
for (var identifierID : typeIdentifierIds) {
240-
Object previous = info.identifierToTypeInfo.put(identifierID, TypeCheckInfo.fromIntList(loader.readIntList(getTypeInfoKey(identifierID))));
241-
assert previous == null : previous;
242-
}
243-
244-
return info;
191+
return new LayerTypeCheckInfo(loader.readInt("maxTypeID"));
245192
}
246193
}
247194
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/code/CompileQueue.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@
7171
import com.oracle.svm.hosted.ProgressReporter;
7272
import com.oracle.svm.hosted.diagnostic.HostedHeapDumpFeature;
7373
import com.oracle.svm.hosted.imagelayer.HostedImageLayerBuildingSupport;
74-
import com.oracle.svm.hosted.imagelayer.LayeredDispatchTableSupport;
74+
import com.oracle.svm.hosted.imagelayer.LayeredDispatchTableFeature;
7575
import com.oracle.svm.hosted.imagelayer.SVMImageLayerLoader;
7676
import com.oracle.svm.hosted.meta.HostedMethod;
7777
import com.oracle.svm.hosted.meta.HostedUniverse;
@@ -188,7 +188,7 @@ public record UnpublishedTrivialMethods(CompilationGraph unpublishedGraph, boole
188188

189189
private final ConcurrentMap<HostedMethod, UnpublishedTrivialMethods> unpublishedTrivialMethods = new ConcurrentHashMap<>();
190190

191-
private final LayeredDispatchTableSupport layeredDispatchTableSupport = ImageLayerBuildingSupport.buildingSharedLayer() ? LayeredDispatchTableSupport.singleton() : null;
191+
private final LayeredDispatchTableFeature layeredDispatchTableSupport = ImageLayerBuildingSupport.buildingSharedLayer() ? LayeredDispatchTableFeature.singleton() : null;
192192

193193
public abstract static class CompileReason {
194194
/**

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/MethodPointerRelocationProvider.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
import com.oracle.svm.core.feature.InternalFeature;
3232
import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
3333
import com.oracle.svm.core.meta.MethodPointer;
34-
import com.oracle.svm.hosted.imagelayer.LayeredDispatchTableSupport;
34+
import com.oracle.svm.hosted.imagelayer.LayeredDispatchTableFeature;
3535
import com.oracle.svm.hosted.meta.HostedMethod;
3636

3737
public class MethodPointerRelocationProvider {
@@ -46,7 +46,7 @@ public void markMethodPointerRelocation(ObjectFile.ProgbitsSectionImpl section,
4646
long addend, MethodPointer methodPointer, boolean isInjectedNotCompiled) {
4747
String symbolName;
4848
if (imageLayer) {
49-
symbolName = LayeredDispatchTableSupport.singleton().getSymbolName(methodPointer, target, isInjectedNotCompiled);
49+
symbolName = LayeredDispatchTableFeature.singleton().getSymbolName(methodPointer, target, isInjectedNotCompiled);
5050
} else {
5151
symbolName = NativeImage.localSymbolNameForMethod(target);
5252
}

substratevm/src/com.oracle.svm.hosted/src/com/oracle/svm/hosted/image/NativeImage.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@
111111
import com.oracle.svm.hosted.image.RelocatableBuffer.Info;
112112
import com.oracle.svm.hosted.imagelayer.HostedDynamicLayerInfo;
113113
import com.oracle.svm.hosted.imagelayer.HostedImageLayerBuildingSupport;
114-
import com.oracle.svm.hosted.imagelayer.LayeredDispatchTableSupport;
114+
import com.oracle.svm.hosted.imagelayer.LayeredDispatchTableFeature;
115115
import com.oracle.svm.hosted.meta.HostedMetaAccess;
116116
import com.oracle.svm.hosted.meta.HostedMethod;
117117
import com.oracle.svm.hosted.meta.HostedType;
@@ -545,7 +545,7 @@ public void build(String imageName, DebugContext debug) {
545545
HostedDynamicLayerInfo.singleton().defineSymbolsForPriorLayerMethods(objectFile);
546546
}
547547
if (ImageLayerBuildingSupport.buildingImageLayer()) {
548-
LayeredDispatchTableSupport.singleton().defineDispatchTableSlotSymbols(objectFile, textSection, codeCache, metaAccess);
548+
LayeredDispatchTableFeature.singleton().defineDispatchTableSlotSymbols(objectFile, textSection, codeCache, metaAccess);
549549
}
550550

551551
// Mark the sections with the relocations from the maps.
@@ -787,7 +787,7 @@ private static String getUniqueShortName(ResolvedJavaMethod sm) {
787787
if (sm instanceof HostedMethod hMethod) {
788788
if (hMethod.isCompiledInPriorLayer()) {
789789
// ensure we use a consistent symbol name across layers
790-
name = HostedDynamicLayerInfo.singleton().loadMethodNameInfo(hMethod.getWrapped()).uniqueShortName();
790+
name = HostedDynamicLayerInfo.loadMethodNameInfo(hMethod.getWrapped()).uniqueShortName();
791791
} else {
792792
name = hMethod.getUniqueShortName();
793793
}

0 commit comments

Comments
 (0)