Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ using MethodId = Int32;
using FieldId = Int32;
using ConstantId = Int32;
using SingletonObjId = Int32;
using HostedMethodIndex = Int32;

struct PersistedAnalysisType {
id @0 :TypeId;
Expand Down Expand Up @@ -75,8 +76,8 @@ struct PersistedAnalysisMethod {
argumentTypeIds @6 :List(TypeId);
returnTypeId @7 :TypeId;
modifiers @8 :Int32;
code @9 :Data;
codeSize @10 :Int32;
bytecode @9 :Data;
bytecodeSize @10 :Int32;
isConstructor @11 :Bool;
isSynthetic @12 :Bool;
canBeStaticallyBound @13 :Bool;
Expand All @@ -92,32 +93,33 @@ struct PersistedAnalysisMethod {
analysisGraphLocation @23 :Text;
analysisGraphIsIntrinsic @24 :Bool;
strengthenedGraphLocation @25 :Text;
hostedMethodIndex @26 :HostedMethodIndex;
wrappedMethod :union {
none @26 :Void; # default
none @27 :Void; # default
factoryMethod :group {
targetConstructorId @27 :MethodId;
throwAllocatedObject @28 :Bool;
instantiatedTypeId @29 :TypeId;
targetConstructorId @28 :MethodId;
throwAllocatedObject @29 :Bool;
instantiatedTypeId @30 :TypeId;
}
outlinedSB :group {
methodTypeReturn @30 :Text;
methodTypeParameters @31 :List(Text);
methodTypeReturn @31 :Text;
methodTypeParameters @32 :List(Text);
}
cEntryPointCallStub :group {
originalMethodId @32 :MethodId;
notPublished @33 :Bool;
originalMethodId @33 :MethodId;
notPublished @34 :Bool;
}
wrappedMember :group {
union {
reflectionExpandSignature @34 :Void;
javaCallVariantWrapper @35 :Void;
reflectionExpandSignature @35 :Void;
javaCallVariantWrapper @36 :Void;
}
name @36 :Text;
declaringClassName @37 :Text;
argumentTypeNames @38 :List(Text);
name @37 :Text;
declaringClassName @38 :Text;
argumentTypeNames @39 :List(Text);
}
polymorphicSignature :group {
callers @39 :List(MethodId);
callers @40 :List(MethodId);
}
}
}
Expand Down Expand Up @@ -273,6 +275,8 @@ struct SharedLayerSnapshot {
staticFinalFieldFoldingSingleton @15 :StaticFinalFieldFoldingSingleton;
registeredJNILibraries @16 :List(Text);
layeredRuntimeMetadataSingleton @17 :LayeredRuntimeMetadataSingleton;
dynamicHubInfos @18 :List(DynamicHubInfo);
hostedMethods @19 :List(PersistedHostedMethod);
}

struct StaticFinalFieldFoldingSingleton {
Expand Down Expand Up @@ -305,3 +309,33 @@ struct PrimitiveArray {
d @7 :List(Float64);
}
}

struct DispatchSlotInfo {
declaredHostedMethodIndex @0 :HostedMethodIndex;
resolvedHostedMethodIndex @1 :HostedMethodIndex;
slotIndex @2 :Int32;
resolutionStatus @3 :Int32;
slotSymbolName @4 :Text;
}

struct PersistedHostedMethod {
index @0 :Int32;
methodId @1 :MethodId;
vTableIndex @2 :Int32;
installedOffset @3 :Int32;
isVirtualCallTarget @4 :Bool;
symbolName @5 :Text;
hostedMethodName @6 :Text;
hostedMethodUniqueName @7 :Text;
}

struct DynamicHubInfo {
typeId @0 :TypeId;
installed @1 :Bool;
typecheckId @2 :Int32;
numClassTypes @3 :Int32;
numInterfaceTypes @4 :Int32;
typecheckSlotValues @5 :List(Int32);
locallyDeclaredSlotsHostedMethodIndexes @6 :List(HostedMethodIndex);
dispatchTableSlotValues @7 :List(DispatchSlotInfo);
}
Original file line number Diff line number Diff line change
Expand Up @@ -24,15 +24,10 @@
*/
package com.oracle.svm.hosted;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;

import org.graalvm.nativeimage.ImageSingletons;
Expand All @@ -50,6 +45,8 @@
import com.oracle.svm.core.layeredimagesingleton.ImageSingletonWriter;
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingleton;
import com.oracle.svm.core.layeredimagesingleton.LayeredImageSingletonBuilderFlags;
import com.oracle.svm.hosted.imagelayer.HostedImageLayerBuildingSupport;
import com.oracle.svm.hosted.imagelayer.SVMImageLayerLoader;
import com.oracle.svm.hosted.meta.HostedType;

import jdk.graal.compiler.debug.Assertions;
Expand All @@ -65,7 +62,7 @@ public boolean isInConfiguration(Feature.IsInConfigurationAccess access) {
@Override
public void beforeUniverseBuilding(BeforeUniverseBuildingAccess access) {
if (ImageLayerBuildingSupport.buildingInitialLayer()) {
ImageSingletons.add(LayerTypeCheckInfo.class, new LayerTypeCheckInfo());
ImageSingletons.add(LayerTypeCheckInfo.class, new LayerTypeCheckInfo(0));
}
}

Expand Down Expand Up @@ -112,136 +109,86 @@ public static int loadTypeInfo(Collection<HostedType> types) {
}
}

public static void persistTypeInfo(Collection<HostedType> types) {
if (ImageLayerBuildingSupport.buildingImageLayer()) {
ImageSingletons.lookup(LayerTypeCheckInfo.class).persistTypeInfo(types);
}
}

record TypeCheckInfo(int typeID, int numClassTypes, int numInterfaceTypes, int[] typecheckSlots) {
private List<Integer> toIntList() {
ArrayList<Integer> list = new ArrayList<>();
list.add(typeID);
list.add(numClassTypes);
list.add(numInterfaceTypes);
Arrays.stream(typecheckSlots).forEach(list::add);

return list;
}
@SuppressWarnings("unused")
public static boolean validateTypeInfo(Collection<HostedType> types) {
if (ImageLayerBuildingSupport.buildingExtensionLayer()) {
var loader = HostedImageLayerBuildingSupport.singleton().getLoader();
for (HostedType type : types) {
if (type.getWrapped().isInBaseLayer()) {
var priorInfo = getTypecheckInfo(loader, type);
if (!priorInfo.installed()) {
// no need to validate this hub, as it was not installed
continue;
}
int typeID = type.getTypeID();
int numClassTypes = type.getNumClassTypes();
int numInterfaceTypes = type.getNumInterfaceTypes();
int[] typecheckSlots = type.getOpenTypeWorldTypeCheckSlots();
boolean matches = typeID == priorInfo.typeID && numClassTypes == priorInfo.numClassTypes && numInterfaceTypes == priorInfo.numInterfaceTypes &&
Arrays.equals(typecheckSlots, priorInfo.typecheckSlots);
if (!matches) {
var typeInfo = new TypeCheckInfo(true, typeID, numClassTypes, numInterfaceTypes, typecheckSlots);
assert false : Assertions.errorMessage("Mismatch for ", type, priorInfo, typeInfo, Arrays.toString(priorInfo.typecheckSlots),
Arrays.toString(typeInfo.typecheckSlots));

private static TypeCheckInfo fromIntList(List<Integer> list) {
int typeID = list.get(0);
int numClassTypes = list.get(1);
int numInterfaceTypes = list.get(2);
int[] typecheckSlots = list.subList(3, list.size()).stream().mapToInt(i -> i).toArray();
return new TypeCheckInfo(typeID, numClassTypes, numInterfaceTypes, typecheckSlots);
}
}
}
}
return true;
}

@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
static TypeCheckInfo getTypecheckInfo(SVMImageLayerLoader loader, HostedType hType) {
if (hType.getWrapped().isInBaseLayer()) {
var hubInfo = loader.getDynamicHubInfo(hType.getWrapped());
var valuesReader = hubInfo.getTypecheckSlotValues();
int[] typecheckSlots = new int[valuesReader.size()];
for (int i = 0; i < typecheckSlots.length; i++) {
typecheckSlots[i] = valuesReader.get(i);
}
TypeCheckInfo typeCheckInfo = (TypeCheckInfo) o;
return typeID == typeCheckInfo.typeID && numClassTypes == typeCheckInfo.numClassTypes && numInterfaceTypes == typeCheckInfo.numInterfaceTypes &&
Arrays.equals(typecheckSlots, typeCheckInfo.typecheckSlots);
return new TypeCheckInfo(hubInfo.getInstalled(), hubInfo.getTypecheckId(), hubInfo.getNumClassTypes(), hubInfo.getNumInterfaceTypes(), typecheckSlots);
} else {
return null;
}
}

@Override
public int hashCode() {
int result = Objects.hash(typeID, numClassTypes, numInterfaceTypes);
result = 31 * result + Arrays.hashCode(typecheckSlots);
return result;
}
record TypeCheckInfo(boolean installed, int typeID, int numClassTypes, int numInterfaceTypes, int[] typecheckSlots) {
}

private static final class LayerTypeCheckInfo implements LayeredImageSingleton {
Map<Integer, TypeCheckInfo> identifierToTypeInfo = new HashMap<>();
int maxTypeID = 0;
final int maxTypeID;

LayerTypeCheckInfo(int maxTypeID) {
this.maxTypeID = maxTypeID;
}

public int loadTypeID(Collection<HostedType> types) {
ArrayList<Integer> usedIDs = new ArrayList<>();
var loader = HostedImageLayerBuildingSupport.singleton().getLoader();
for (HostedType type : types) {
int identifierID = type.getWrapped().getId();
TypeCheckInfo info = identifierToTypeInfo.get(identifierID);
TypeCheckInfo info = getTypecheckInfo(loader, type);
if (info != null) {
usedIDs.add(info.typeID);
type.loadTypeID(info.typeID);
}
}

return maxTypeID;
}

public void persistTypeInfo(Collection<HostedType> types) {
for (HostedType type : types) {
/*
* Currently we are calculating type id information for all types. However, for
* types not tracked across layers, the type ID may not be the same in different
* layers.
*/
assert type.getTypeID() != -1 : type;
if (type.getWrapped().isTrackedAcrossLayers()) {
int identifierID = type.getWrapped().getId();
int typeID = type.getTypeID();
int numClassTypes = type.getNumClassTypes();
int numInterfaceTypes = type.getNumInterfaceTypes();
int[] typecheckSlots = type.getOpenTypeWorldTypeCheckSlots();
var priorInfo = identifierToTypeInfo.get(identifierID);
var newTypeInfo = new TypeCheckInfo(typeID, numClassTypes, numInterfaceTypes, typecheckSlots);
if (priorInfo == null) {
identifierToTypeInfo.put(identifierID, newTypeInfo);
} else {
assert newTypeInfo.equals(priorInfo) : Assertions.errorMessage("Mismatch for ", type, priorInfo, newTypeInfo, Arrays.toString(priorInfo.typecheckSlots),
Arrays.toString(newTypeInfo.typecheckSlots));
}
}
}
}

@Override
public EnumSet<LayeredImageSingletonBuilderFlags> getImageBuilderFlags() {
return LayeredImageSingletonBuilderFlags.BUILDTIME_ACCESS_ONLY;
}

private static String getTypeInfoKey(int id) {
return String.format("TypeInfo-%s", id);
}

@Override
public PersistFlags preparePersist(ImageSingletonWriter writer) {
/*
* Note all that is strictly needed to restore the typecheck information is the
* (identifierID -> typeID) mappings. In the future we can compact the amount of
* information we store.
*/
var typeIdentifierIds = identifierToTypeInfo.keySet().stream().sorted().toList();
writer.writeIntList("typeIdentifierIds", typeIdentifierIds);
writer.writeInt("maxTypeID", DynamicHubSupport.currentLayer().getMaxTypeId());

for (int identifierID : typeIdentifierIds) {
var typeInfo = identifierToTypeInfo.get(identifierID);
assert typeInfo != null;
writer.writeIntList(getTypeInfoKey(identifierID), typeInfo.toIntList());
}

return PersistFlags.CREATE;
}

@SuppressWarnings("unused")
public static Object createFromLoader(ImageSingletonLoader loader) {
var info = new LayerTypeCheckInfo();
info.maxTypeID = loader.readInt("maxTypeID");
List<Integer> typeIdentifierIds = loader.readIntList("typeIdentifierIds");
for (var identifierID : typeIdentifierIds) {
Object previous = info.identifierToTypeInfo.put(identifierID, TypeCheckInfo.fromIntList(loader.readIntList(getTypeInfoKey(identifierID))));
assert previous == null : previous;
}

return info;
return new LayerTypeCheckInfo(loader.readInt("maxTypeID"));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
import com.oracle.svm.hosted.ProgressReporter;
import com.oracle.svm.hosted.diagnostic.HostedHeapDumpFeature;
import com.oracle.svm.hosted.imagelayer.HostedImageLayerBuildingSupport;
import com.oracle.svm.hosted.imagelayer.LayeredDispatchTableSupport;
import com.oracle.svm.hosted.imagelayer.LayeredDispatchTableFeature;
import com.oracle.svm.hosted.imagelayer.SVMImageLayerLoader;
import com.oracle.svm.hosted.meta.HostedMethod;
import com.oracle.svm.hosted.meta.HostedUniverse;
Expand Down Expand Up @@ -188,7 +188,7 @@ public record UnpublishedTrivialMethods(CompilationGraph unpublishedGraph, boole

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

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

public abstract static class CompileReason {
/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
import com.oracle.svm.core.feature.InternalFeature;
import com.oracle.svm.core.imagelayer.ImageLayerBuildingSupport;
import com.oracle.svm.core.meta.MethodPointer;
import com.oracle.svm.hosted.imagelayer.LayeredDispatchTableSupport;
import com.oracle.svm.hosted.imagelayer.LayeredDispatchTableFeature;
import com.oracle.svm.hosted.meta.HostedMethod;

public class MethodPointerRelocationProvider {
Expand All @@ -46,7 +46,7 @@ public void markMethodPointerRelocation(ObjectFile.ProgbitsSectionImpl section,
long addend, MethodPointer methodPointer, boolean isInjectedNotCompiled) {
String symbolName;
if (imageLayer) {
symbolName = LayeredDispatchTableSupport.singleton().getSymbolName(methodPointer, target, isInjectedNotCompiled);
symbolName = LayeredDispatchTableFeature.singleton().getSymbolName(methodPointer, target, isInjectedNotCompiled);
} else {
symbolName = NativeImage.localSymbolNameForMethod(target);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@
import com.oracle.svm.hosted.image.RelocatableBuffer.Info;
import com.oracle.svm.hosted.imagelayer.HostedDynamicLayerInfo;
import com.oracle.svm.hosted.imagelayer.HostedImageLayerBuildingSupport;
import com.oracle.svm.hosted.imagelayer.LayeredDispatchTableSupport;
import com.oracle.svm.hosted.imagelayer.LayeredDispatchTableFeature;
import com.oracle.svm.hosted.meta.HostedMetaAccess;
import com.oracle.svm.hosted.meta.HostedMethod;
import com.oracle.svm.hosted.meta.HostedType;
Expand Down Expand Up @@ -545,7 +545,7 @@ public void build(String imageName, DebugContext debug) {
HostedDynamicLayerInfo.singleton().defineSymbolsForPriorLayerMethods(objectFile);
}
if (ImageLayerBuildingSupport.buildingImageLayer()) {
LayeredDispatchTableSupport.singleton().defineDispatchTableSlotSymbols(objectFile, textSection, codeCache, metaAccess);
LayeredDispatchTableFeature.singleton().defineDispatchTableSlotSymbols(objectFile, textSection, codeCache, metaAccess);
}

// Mark the sections with the relocations from the maps.
Expand Down Expand Up @@ -787,7 +787,7 @@ private static String getUniqueShortName(ResolvedJavaMethod sm) {
if (sm instanceof HostedMethod hMethod) {
if (hMethod.isCompiledInPriorLayer()) {
// ensure we use a consistent symbol name across layers
name = HostedDynamicLayerInfo.singleton().loadMethodNameInfo(hMethod.getWrapped()).uniqueShortName();
name = HostedDynamicLayerInfo.loadMethodNameInfo(hMethod.getWrapped()).uniqueShortName();
} else {
name = hMethod.getUniqueShortName();
}
Expand Down
Loading