package com.oracle.svm.hosted;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.ForkJoinPool;
import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
import org.graalvm.compiler.core.common.CompressEncoding;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.nativeimage.ImageSingletons;
import com.oracle.graal.pointsto.BigBang;
import com.oracle.graal.pointsto.meta.AnalysisField;
import com.oracle.graal.pointsto.meta.AnalysisType;
import com.oracle.graal.pointsto.results.StaticAnalysisResultsBuilder;
import com.oracle.graal.pointsto.typestate.TypeState;
import com.oracle.svm.core.SubstrateOptions;
import com.oracle.svm.core.SubstrateTargetDescription;
import com.oracle.svm.core.config.ConfigurationValues;
import com.oracle.svm.core.config.ObjectLayout;
import com.oracle.svm.core.monitor.MultiThreadedMonitorSupport;
import com.oracle.svm.hosted.code.CompileQueue;
import com.oracle.svm.hosted.code.SharedRuntimeConfigurationBuilder;
import com.oracle.svm.hosted.config.HybridLayout;
import com.oracle.svm.hosted.config.HybridLayoutSupport;
import com.oracle.svm.hosted.meta.HostedField;
import com.oracle.svm.hosted.meta.HostedInstanceClass;
import com.oracle.svm.hosted.meta.HostedMetaAccess;
import com.oracle.svm.hosted.meta.HostedUniverse;
import jdk.vm.ci.meta.JavaKind;
public class HostedConfiguration {
public HostedConfiguration() {
}
public static HostedConfiguration instance() {
return ImageSingletons.lookup(HostedConfiguration.class);
}
static void setDefaultIfEmpty() {
if (!ImageSingletons.contains(HostedConfiguration.class)) {
ImageSingletons.add(HostedConfiguration.class, new HostedConfiguration());
CompressEncoding compressEncoding = new CompressEncoding(SubstrateOptions.SpawnIsolates.getValue() ? 1 : 0, 0);
ImageSingletons.add(CompressEncoding.class, compressEncoding);
ObjectLayout objectLayout = createObjectLayout();
ImageSingletons.add(ObjectLayout.class, objectLayout);
ImageSingletons.add(HybridLayoutSupport.class, new HybridLayoutSupport());
}
}
public static ObjectLayout createObjectLayout() {
return createObjectLayout(JavaKind.Object);
}
public static ObjectLayout createObjectLayout(JavaKind referenceKind) {
SubstrateTargetDescription target = ConfigurationValues.getTarget();
int referenceSize = target.arch.getPlatformKind(referenceKind).getSizeInBytes();
int objectAlignment = 8;
int hubOffset = 0;
int identityHashCodeOffset = hubOffset + referenceSize;
int firstFieldOffset = identityHashCodeOffset + target.arch.getPlatformKind(JavaKind.Int).getSizeInBytes();
int arrayLengthOffset = firstFieldOffset;
int arrayBaseOffset = arrayLengthOffset + target.arch.getPlatformKind(JavaKind.Int).getSizeInBytes();
return new ObjectLayout(target, referenceSize, objectAlignment, hubOffset, firstFieldOffset, arrayLengthOffset, arrayBaseOffset, identityHashCodeOffset);
}
public CompileQueue createCompileQueue(DebugContext debug, FeatureHandler featureHandler, HostedUniverse hostedUniverse,
SharedRuntimeConfigurationBuilder runtime, boolean deoptimizeAll, SnippetReflectionProvider aSnippetReflection, ForkJoinPool executor) {
return new CompileQueue(debug, featureHandler, hostedUniverse, runtime, deoptimizeAll, aSnippetReflection, executor);
}
public void findAllFieldsForLayout(HostedUniverse universe, @SuppressWarnings("unused") HostedMetaAccess metaAccess,
@SuppressWarnings("unused") Map<AnalysisField, HostedField> universeFields,
ArrayList<HostedField> rawFields,
ArrayList<HostedField> orderedFields, HostedInstanceClass clazz) {
for (AnalysisField aField : clazz.getWrapped().getInstanceFields(false)) {
HostedField hField = universe.lookup(aField);
if (hField.getDeclaringClass().equals(clazz)) {
if (HybridLayout.isHybridField(hField)) {
orderedFields.add(hField);
} else if (hField.isAccessed()) {
rawFields.add(hField);
}
}
}
}
public StaticAnalysisResultsBuilder createStaticAnalysisResultsBuilder(BigBang bigbang, HostedUniverse universe) {
return new StaticAnalysisResultsBuilder(bigbang, universe);
}
public void collectMonitorFieldInfo(BigBang bb, HostedUniverse hUniverse, Set<AnalysisType> immutableTypes) {
getForceMonitorSlotTypes(bb).forEach(type -> setMonitorField(hUniverse, type));
processedSynchronizedTypes(bb, hUniverse, immutableTypes);
}
private static Set<AnalysisType> getForceMonitorSlotTypes(BigBang bb) {
Set<AnalysisType> forceMonitorTypes = new HashSet<>();
for (Class<?> forceMonitorType : MultiThreadedMonitorSupport.FORCE_MONITOR_SLOT_TYPES) {
Optional<AnalysisType> aType = bb.getMetaAccess().optionalLookupJavaType(forceMonitorType);
aType.ifPresent(forceMonitorTypes::add);
}
return forceMonitorTypes;
}
protected void processedSynchronizedTypes(BigBang bb, HostedUniverse hUniverse, Set<AnalysisType> immutableTypes) {
TypeState allSynchronizedTypeState = bb.getAllSynchronizedTypeState();
for (AnalysisType type : allSynchronizedTypeState.types()) {
maybeSetMonitorField(hUniverse, immutableTypes, type);
}
}
protected static void maybeSetMonitorField(HostedUniverse hUniverse, Set<AnalysisType> immutableTypes, AnalysisType type) {
if (!type.isArray() && !immutableTypes.contains(type)) {
setMonitorField(hUniverse, type);
}
}
private static void setMonitorField(HostedUniverse hUniverse, AnalysisType type) {
final HostedInstanceClass hostedInstanceClass = (HostedInstanceClass) hUniverse.lookup(type);
hostedInstanceClass.setNeedMonitorField();
}
public boolean isUsingAOTProfiles() {
return false;
}
}