package org.graalvm.compiler.hotspot;
import static jdk.vm.ci.code.CodeUtil.K;
import static jdk.vm.ci.code.CodeUtil.getCallingConvention;
import static jdk.vm.ci.common.InitTimer.timer;
import java.util.Collections;
import org.graalvm.compiler.core.common.NumUtil;
import org.graalvm.compiler.core.common.spi.ForeignCallDescriptor;
import org.graalvm.compiler.debug.DebugHandlersFactory;
import org.graalvm.compiler.hotspot.meta.HotSpotHostForeignCallsProvider;
import org.graalvm.compiler.hotspot.meta.HotSpotLoweringProvider;
import org.graalvm.compiler.hotspot.meta.HotSpotProviders;
import org.graalvm.compiler.hotspot.stubs.Stub;
import org.graalvm.compiler.lir.asm.CompilationResultBuilder;
import org.graalvm.compiler.lir.framemap.ReferenceMapBuilder;
import org.graalvm.compiler.nodes.StructuredGraph;
import org.graalvm.compiler.options.OptionValues;
import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
import jdk.vm.ci.code.CallingConvention;
import jdk.vm.ci.common.InitTimer;
import jdk.vm.ci.hotspot.HotSpotCallingConventionType;
import jdk.vm.ci.hotspot.HotSpotJVMCIRuntime;
import jdk.vm.ci.meta.JavaKind;
import jdk.vm.ci.meta.JavaType;
import jdk.vm.ci.runtime.JVMCICompiler;
import org.graalvm.compiler.word.Word;
public abstract class HotSpotHostBackend extends HotSpotBackend {
public static final ForeignCallDescriptor DEOPTIMIZATION_HANDLER = new ForeignCallDescriptor("deoptHandler", void.class);
public static final ForeignCallDescriptor UNCOMMON_TRAP_HANDLER = new ForeignCallDescriptor("uncommonTrapHandler", void.class);
public static final ForeignCallDescriptor ENABLE_STACK_RESERVED_ZONE = new ForeignCallDescriptor("enableStackReservedZoneEntry", void.class, Word.class);
public static final ForeignCallDescriptor THROW_DELAYED_STACKOVERFLOW_ERROR = new ForeignCallDescriptor("throwDelayedStackoverflowError", void.class);
protected final GraalHotSpotVMConfig config;
public HotSpotHostBackend(GraalHotSpotVMConfig config, HotSpotGraalRuntimeProvider runtime, HotSpotProviders providers) {
super(runtime, providers);
this.config = config;
}
@Override
@SuppressWarnings("try")
public void completeInitialization(HotSpotJVMCIRuntime jvmciRuntime, OptionValues options) {
final HotSpotProviders providers = getProviders();
HotSpotHostForeignCallsProvider foreignCalls = (HotSpotHostForeignCallsProvider) providers.getForeignCalls();
final HotSpotLoweringProvider lowerer = (HotSpotLoweringProvider) providers.getLowerer();
try (InitTimer st = timer("foreignCalls.initialize")) {
foreignCalls.initialize(providers, options);
}
try (InitTimer st = timer("lowerer.initialize")) {
Iterable<DebugHandlersFactory> factories = Collections.singletonList(new GraalDebugHandlersFactory(providers.getSnippetReflection()));
lowerer.initialize(options, factories, providers, config);
}
}
protected CallingConvention makeCallingConvention(StructuredGraph graph, Stub stub) {
if (stub != null) {
return stub.getLinkage().getIncomingCallingConvention();
}
CallingConvention cc = getCallingConvention(getCodeCache(), HotSpotCallingConventionType.JavaCallee, graph.method(), this);
if (graph.getEntryBCI() != JVMCICompiler.INVOCATION_ENTRY_BCI) {
JavaType[] parameterTypes = new JavaType[]{getMetaAccess().lookupJavaType(long.class)};
CallingConvention tmp = getCodeCache().getRegisterConfig().getCallingConvention(HotSpotCallingConventionType.JavaCallee, getMetaAccess().lookupJavaType(void.class), parameterTypes, this);
cc = new CallingConvention(cc.getStackSize(), cc.getReturn(), tmp.getArgument(0));
}
return cc;
}
public void emitStackOverflowCheck(CompilationResultBuilder crb) {
if (config.useStackBanging) {
int pageSize = config.vmPageSize;
int bangEnd = NumUtil.roundUp(config.stackShadowPages * 4 * K, pageSize);
int bangEndSafe = bangEnd;
int frameSize = Math.max(crb.frameMap.frameSize(), crb.compilationResult.getMaxInterpreterFrameSize());
if (frameSize > pageSize) {
bangEnd += frameSize;
}
int bangOffset = bangEndSafe;
if (bangOffset <= bangEnd) {
crb.blockComment("[stack overflow check]");
}
while (bangOffset <= bangEnd) {
bangStackWithOffset(crb, bangOffset);
bangOffset += pageSize;
}
}
}
protected abstract void bangStackWithOffset(CompilationResultBuilder crb, int bangOffset);
@Override
public ReferenceMapBuilder newReferenceMapBuilder(int totalFrameSize) {
int uncompressedReferenceSize = getTarget().arch.getPlatformKind(JavaKind.Object).getSizeInBytes();
return new HotSpotReferenceMapBuilder(totalFrameSize, config.maxOopMapStackOffset, uncompressedReferenceSize);
}
}