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 @@ -713,7 +713,7 @@ public void emitMembar(int barriers) {

@Override
protected void emitForeignCallOp(ForeignCallLinkage linkage, Value targetAddress, Value result, Value[] arguments, Value[] temps, LIRFrameState info) {
long maxOffset = linkage.getMaxCallTargetOffset();
long maxOffset = linkage.getMaxCallTargetOffset(getCodeCache());
if (maxOffset != (int) maxOffset) {
append(new AMD64Call.DirectFarForeignCallOp(linkage, result, arguments, temps, info));
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
package jdk.graal.compiler.core.common.spi;

import jdk.vm.ci.code.CallingConvention;
import jdk.vm.ci.code.CodeCacheProvider;
import jdk.vm.ci.meta.InvokeTarget;
import jdk.vm.ci.meta.Value;

Expand All @@ -50,7 +51,7 @@ public interface ForeignCallLinkage extends InvokeTarget {
* the code cache or -1 when not applicable. Intended for determining the required size of
* address/offset fields.
*/
long getMaxCallTargetOffset();
long getMaxCallTargetOffset(CodeCacheProvider codeCache);

ForeignCallDescriptor getDescriptor();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,6 @@
*/
package jdk.graal.compiler.hotspot;

import static jdk.vm.ci.hotspot.HotSpotJVMCIRuntime.runtime;

import java.util.Arrays;

import org.graalvm.collections.EconomicSet;
Expand Down Expand Up @@ -263,8 +261,8 @@ public Value[] getTemporaries() {
}

@Override
public long getMaxCallTargetOffset() {
return runtime().getHostJVMCIBackend().getCodeCache().getMaxCallTargetOffset(address);
public long getMaxCallTargetOffset(CodeCacheProvider codeCache) {
return codeCache.getMaxCallTargetOffset(address);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,7 @@ private void emitNmethodEntryBarrier(CompilationResultBuilder crb, AArch64MacroA
crb.getLIR().addSlowPath(null, () -> {
masm.bind(entryPoint);
int beforeCall = masm.position();
if (AArch64Call.isNearCall(callTarget)) {
if (AArch64Call.isNearCall(callTarget, getCodeCache())) {
// Address is fixed up by the runtime.
masm.bl();
} else {
Expand Down Expand Up @@ -471,7 +471,7 @@ private void emitCodePrefix(CompilationResultBuilder crb, ResolvedJavaMethod ins
ForeignCallLinkage icMissHandler = getForeignCalls().lookupForeignCall(IC_MISS_HANDLER);

// Size of IC check sequence checked with a guarantee below.
int inlineCacheCheckSize = AArch64Call.isNearCall(icMissHandler) ? 20 : 32;
int inlineCacheCheckSize = AArch64Call.isNearCall(icMissHandler, getCodeCache()) ? 20 : 32;
if (config.useCompactObjectHeaders) {
// Extra instruction for shifting
inlineCacheCheckSize += 4;
Expand Down Expand Up @@ -560,7 +560,7 @@ private void emitCodeSuffix(CompilationResultBuilder crb, AArch64MacroAssembler
}

ForeignCallLinkage uncommonTrapBlob = foreignCalls.lookupForeignCall(DEOPT_BLOB_UNCOMMON_TRAP);
Register helper = AArch64Call.isNearCall(uncommonTrapBlob) ? null : scratch;
Register helper = AArch64Call.isNearCall(uncommonTrapBlob, getCodeCache()) ? null : scratch;
AArch64Call.directCall(crb, masm, uncommonTrapBlob, helper, pendingImplicitException.state());
crb.recordImplicitException(pendingImplicitException.codeOffset(), pos, pendingImplicitException.state());
}
Expand All @@ -570,7 +570,7 @@ private void emitCodeSuffix(CompilationResultBuilder crb, AArch64MacroAssembler
Register scratch = sc.getRegister();
crb.recordMark(HotSpotMarkId.EXCEPTION_HANDLER_ENTRY);
ForeignCallLinkage linkage = foreignCalls.lookupForeignCall(EXCEPTION_HANDLER);
Register helper = AArch64Call.isNearCall(linkage) ? null : scratch;
Register helper = AArch64Call.isNearCall(linkage, getCodeCache()) ? null : scratch;
AArch64Call.directCall(crb, masm, linkage, helper, null);
// Ensure the return location is a unique pc and that control flow doesn't return
// here
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,7 @@ protected Value getCompareValueForConstantPointer(Value v) {
@Override
protected void emitForeignCallOp(ForeignCallLinkage linkage, Value targetAddress, Value result, Value[] arguments, Value[] temps, LIRFrameState info) {
currentRuntimeCallInfo = info;
if (AArch64Call.isNearCall(linkage)) {
if (AArch64Call.isNearCall(linkage, getCodeCache())) {
append(new AArch64Call.DirectNearForeignCallOp(linkage, result, arguments, temps, info, label));
} else {
append(new AArch64Call.DirectFarForeignCallOp(linkage, result, arguments, temps, info, label));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ public static void emitCode(GraalHotSpotVMConfig config, CompilationResultBuilde
masm.str(64, addressReg, cArg1);

// Make the call
AArch64Call.directCall(crb, masm, callTarget, AArch64Call.isNearCall(callTarget) ? null : rtmp2, null);
AArch64Call.directCall(crb, masm, callTarget, AArch64Call.isNearCall(callTarget, crb.getCodeCache()) ? null : rtmp2, null);

// Retrieve result and move to the result register.
AArch64Address cRet = (AArch64Address) crb.asAddress(cc.getReturn());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,7 @@ protected void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm
CallingConvention cc = callTarget.getOutgoingCallingConvention();
AArch64Address cArg0 = (AArch64Address) crb.asAddress(cc.getArgument(0));
masm.str(64, previousValue, cArg0);
AArch64Call.directCall(crb, masm, callTarget, AArch64Call.isNearCall(callTarget) ? null : scratch1, null);
AArch64Call.directCall(crb, masm, callTarget, AArch64Call.isNearCall(callTarget, crb.getCodeCache()) ? null : scratch1, null);
masm.jmp(done);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ static void emitStoreBarrier(CompilationResultBuilder crb,
masm.loadAddress(rscratch1, address);
masm.str(64, rscratch1, cArg0);

AArch64Call.directCall(crb, masm, callTarget, AArch64Call.isNearCall(callTarget) ? null : rscratch1, null);
AArch64Call.directCall(crb, masm, callTarget, AArch64Call.isNearCall(callTarget, crb.getCodeCache()) ? null : rscratch1, null);
assert cc.getReturn().equals(Value.ILLEGAL) : cc + " " + callTarget;

masm.jmp(slowContinuation);
Expand Down Expand Up @@ -383,7 +383,7 @@ public static void emitLoadBarrier(CompilationResultBuilder crb,
masm.loadAddress(ref, address);
}
masm.str(64, addressReg, cArg1);
AArch64Call.directCall(crb, masm, callTarget, AArch64Call.isNearCall(callTarget) ? null : scratch1, null);
AArch64Call.directCall(crb, masm, callTarget, AArch64Call.isNearCall(callTarget, crb.getCodeCache()) ? null : scratch1, null);
masm.ldr(64, ref, cArg0);

masm.jmp(continuation);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -312,6 +312,8 @@ public record MethodCallToRecord(Object receiver, CompilationProxy.SymbolicMetho
* @param clazz the class
* @param singleton {@code true} iff the class should be treated as a singleton (e.g., a
* provider)
* @param useLocalMirrorFallback {@code true} iff the methods of this class can be invoked with
* local mirrors on the replaying VM as a fallback
* @param mirrorLocator a method that can find the local mirror of a proxy during replay or
* {@code null}
* @param methods the recording/replay behavior the methods - only needed for non-default
Expand All @@ -320,7 +322,7 @@ public record MethodCallToRecord(Object receiver, CompilationProxy.SymbolicMetho
* @param methodCallsToRecordProvider provides the methods calls that should be recorded in the
* serialized compilation unit
*/
public record Registration(Class<?> clazz, boolean singleton, LocalMirrorLocator mirrorLocator,
public record Registration(Class<?> clazz, boolean singleton, boolean useLocalMirrorFallback, LocalMirrorLocator mirrorLocator,
UnmodifiableEconomicMap<CompilationProxy.SymbolicMethod, MethodRegistration> methods, Class<?>[] extraInterfaces,
MethodCallsToRecordProvider methodCallsToRecordProvider) {
/**
Expand Down Expand Up @@ -451,6 +453,8 @@ private static class RegistrationBuilder<T> {

private boolean singleton;

private boolean localMirrorFallback;

private LocalMirrorLocator mirrorLocator;

private final EconomicMap<CompilationProxy.SymbolicMethod, MethodRegistrationBuilder> methods;
Expand All @@ -461,6 +465,7 @@ private static class RegistrationBuilder<T> {

RegistrationBuilder(Class<T> clazz, Class<?>... extraInterfaces) {
this.clazz = clazz;
this.localMirrorFallback = true;
this.methods = EconomicMap.create();
this.extraInterfaces = extraInterfaces;
this.methods.put(CompilationProxyBase.toStringMethod, MethodRegistrationBuilder.createDefault(CompilationProxyBase.toStringMethod));
Expand All @@ -476,6 +481,11 @@ public RegistrationBuilder<T> setSingleton(boolean newSingleton) {
return this;
}

public RegistrationBuilder<T> useLocalMirrorFallback(boolean enabled) {
localMirrorFallback = enabled;
return this;
}

private MethodRegistrationBuilder findRegistrationBuilder(CompilationProxy.SymbolicMethod symbolicMethod) {
MethodRegistrationBuilder builder = methods.get(symbolicMethod);
if (builder == null) {
Expand Down Expand Up @@ -532,7 +542,7 @@ private void register(CompilerInterfaceDeclarations declarations) {
while (cursor.advance()) {
registrations.put(cursor.getKey(), cursor.getValue().build());
}
declarations.addRegistration(new Registration(clazz, singleton, mirrorLocator, registrations, extraInterfaces, methodCallsToRecordProvider));
declarations.addRegistration(new Registration(clazz, singleton, localMirrorFallback, mirrorLocator, registrations, extraInterfaces, methodCallsToRecordProvider));
}
}

Expand Down Expand Up @@ -663,6 +673,9 @@ public static CompilerInterfaceDeclarations build() {
constantReflection.getMemoryAccessProvider())
.register(declarations);
new RegistrationBuilder<>(HotSpotCodeCacheProvider.class).setSingleton(true)
// Avoid using the code cache of the replaying VM due to non-determinism (e.g., max call target offset).
.useLocalMirrorFallback(false)
.setDefaultValue(HotSpotCodeCacheProviderProxy.getMaxCallTargetOffsetMethod, -1L)
.setDefaultValueStrategy(HotSpotCodeCacheProviderProxy.installCodeMethod, null)
.setDefaultValueSupplier(HotSpotCodeCacheProviderProxy.installCodeMethod, CompilerInterfaceDeclarations::installCodeReplacement)
// Interpreter frame size is not tracked since the arguments are not serializable.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -503,20 +503,22 @@ public CompilationProxy createProxy(CompilerInterfaceDeclarations.Registration r
return proxyMapper.proxifyRecursive(result);
}
}
try {
Object[] unproxifiedArgs = (Object[]) proxyMapper.unproxifyRecursive(args);
if (registration.singleton()) {
return proxyMapper.proxifyRecursive(callback.invoke(input, unproxifiedArgs));
}
Object localMirror = proxyInfo.localMirror;
if (localMirror != null) {
return proxyMapper.proxifyRecursive(callback.invoke(localMirror, unproxifiedArgs));
if (registration.useLocalMirrorFallback()) {
try {
Object[] unproxifiedArgs = (Object[]) proxyMapper.unproxifyRecursive(args);
if (registration.singleton()) {
return proxyMapper.proxifyRecursive(callback.invoke(input, unproxifiedArgs));
}
Object localMirror = proxyInfo.localMirror;
if (localMirror != null) {
return proxyMapper.proxifyRecursive(callback.invoke(localMirror, unproxifiedArgs));
}
} catch (NotUnproxifiableException ignored2) {
// Cannot unproxify the arguments: continue.
} catch (InvocationTargetException exception) {
// The result of the invocation is a thrown exception.
throw exception.getTargetException();
}
} catch (NotUnproxifiableException ignored2) {
// Cannot unproxify the arguments: continue.
} catch (InvocationTargetException exception) {
// The result of the invocation is a thrown exception.
throw exception.getTargetException();
}
CompilerInterfaceDeclarations.OperationResultSupplier handler = registration.findFallbackHandler(method);
if (handler != null) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ public SpeculationLog createSpeculationLog() {
return (SpeculationLog) handle(createSpeculationLogMethod, createSpeculationLogInvokable);
}

private static final SymbolicMethod getMaxCallTargetOffsetMethod = method("getMaxCallTargetOffset", long.class);
public static final SymbolicMethod getMaxCallTargetOffsetMethod = method("getMaxCallTargetOffset", long.class);
private static final InvokableMethod getMaxCallTargetOffsetInvokable = (receiver, args) -> ((HotSpotCodeCacheProvider) receiver).getMaxCallTargetOffset((long) args[0]);

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@
import jdk.graal.compiler.lir.StandardOp.LabelHoldingOp;
import jdk.graal.compiler.lir.gen.DiagnosticLIRGeneratorTool.ZapRegistersAfterInstruction;

import jdk.vm.ci.code.CodeCacheProvider;
import jdk.vm.ci.code.Register;
import jdk.vm.ci.code.site.Call;
import jdk.vm.ci.meta.InvokeTarget;
Expand Down Expand Up @@ -195,8 +196,8 @@ protected void emitCall(CompilationResultBuilder crb, AArch64MacroAssembler masm
* @return true if foreign call can be called directly and does not need a scratch register to
* load the address into.
*/
public static boolean isNearCall(ForeignCallLinkage linkage) {
long maxOffset = linkage.getMaxCallTargetOffset();
public static boolean isNearCall(ForeignCallLinkage linkage, CodeCacheProvider codeCache) {
long maxOffset = linkage.getMaxCallTargetOffset(codeCache);
return maxOffset != -1 && AArch64MacroAssembler.isBranchImmediateOffset(maxOffset);
}

Expand Down Expand Up @@ -247,7 +248,7 @@ public static int indirectCall(CompilationResultBuilder crb, AArch64MacroAssembl
public static void directJmp(CompilationResultBuilder crb, AArch64MacroAssembler masm, ForeignCallLinkage callTarget) {
try (AArch64MacroAssembler.ScratchRegister scratch = masm.getScratchRegister()) {
int before = masm.position();
if (AArch64Call.isNearCall(callTarget)) {
if (AArch64Call.isNearCall(callTarget, crb.getCodeCache())) {
masm.jmp();
} else {
masm.movNativeAddress(scratch.getRegister(), 0L, true);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
CallingConvention cc = callTarget.getOutgoingCallingConvention();
AArch64Address cArg0 = (AArch64Address) crb.asAddress(cc.getArgument(0));
masm.str(64, cardPointer, cArg0);
AArch64Call.directCall(crb, masm, callTarget, AArch64Call.isNearCall(callTarget) ? null : scratch1, null);
AArch64Call.directCall(crb, masm, callTarget, AArch64Call.isNearCall(callTarget, crb.getCodeCache()) ? null : scratch1, null);
masm.jmp(done);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,7 @@ public void emitCode(CompilationResultBuilder crb, AArch64MacroAssembler masm) {
CallingConvention cc = callTarget.getOutgoingCallingConvention();
AArch64Address cArg0 = (AArch64Address) crb.asAddress(cc.getArgument(0));
masm.str(64, previousValue, cArg0);
AArch64Call.directCall(crb, masm, callTarget, AArch64Call.isNearCall(callTarget) ? null : scratch1, null);
AArch64Call.directCall(crb, masm, callTarget, AArch64Call.isNearCall(callTarget, crb.getCodeCache()) ? null : scratch1, null);
masm.jmp(done);
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
package com.oracle.svm.core.graal.meta;

import jdk.graal.compiler.core.common.spi.ForeignCallLinkage;
import jdk.vm.ci.code.CodeCacheProvider;
import org.graalvm.nativeimage.Platform;
import org.graalvm.nativeimage.Platforms;

Expand Down Expand Up @@ -72,7 +73,7 @@ public CallingConvention getIncomingCallingConvention() {
}

@Override
public long getMaxCallTargetOffset() {
public long getMaxCallTargetOffset(CodeCacheProvider codeCache) {
return -1;
}

Expand Down