Skip to content

Commit 099f57b

Browse files
committed
[JDK-8354443] Match C2's code generation for the deopt handler
PullRequest: graal/20659
2 parents 9da64df + 69bd3af commit 099f57b

File tree

2 files changed

+46
-5
lines changed

2 files changed

+46
-5
lines changed

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/asm/amd64/AMD64MacroAssembler.java

+11
Original file line numberDiff line numberDiff line change
@@ -482,8 +482,19 @@ public int directJmp(long address, Register scratch) {
482482
return beforeJmp;
483483
}
484484

485+
/** Emits a jmp instruction with an immediate to be patched. Includes JCC erratum mitigation. */
485486
public void jmp() {
486487
mitigateJCCErratum(5);
488+
rawJmpNoJCCErratumMitigation();
489+
}
490+
491+
/**
492+
* Emits a jmp instruction with an immediate to be patched. Does <em>not</em> include JCC
493+
* erratum mitigation. Most use cases should use {@link #jmp()} instead. This method should only
494+
* be used directly when predictable code size is more important than the performance penalty of
495+
* a possibly misaligned jump.
496+
*/
497+
public void rawJmpNoJCCErratumMitigation() {
487498
annotatePatchingImmediate(1, 4);
488499
emitByte(0xE9);
489500
emitInt(0);

compiler/src/jdk.graal.compiler/src/jdk/graal/compiler/hotspot/amd64/AMD64HotSpotBackend.java

+35-5
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2012, 2024, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2012, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -58,6 +58,7 @@
5858
import jdk.graal.compiler.hotspot.meta.HotSpotProviders;
5959
import jdk.graal.compiler.hotspot.stubs.Stub;
6060
import jdk.graal.compiler.lir.LIR;
61+
import jdk.graal.compiler.lir.SyncPort;
6162
import jdk.graal.compiler.lir.amd64.AMD64Call;
6263
import jdk.graal.compiler.lir.amd64.AMD64FrameMap;
6364
import jdk.graal.compiler.lir.asm.CompilationResultBuilder;
@@ -459,20 +460,49 @@ public void emitCodeSuffix(CompilationResultBuilder crb, AMD64MacroAssembler asm
459460
crb.recordImplicitException(pendingImplicitException.codeOffset, pos, pendingImplicitException.state);
460461
}
461462
}
462-
trampolineCall(crb, asm, foreignCalls.lookupForeignCall(EXCEPTION_HANDLER), HotSpotMarkId.EXCEPTION_HANDLER_ENTRY);
463-
trampolineCall(crb, asm, foreignCalls.lookupForeignCall(DEOPT_BLOB_UNPACK), HotSpotMarkId.DEOPT_HANDLER_ENTRY);
463+
emitExceptionHandler(crb, asm, foreignCalls.lookupForeignCall(EXCEPTION_HANDLER), HotSpotMarkId.EXCEPTION_HANDLER_ENTRY);
464+
emitDeoptHandler(crb, asm, foreignCalls.lookupForeignCall(DEOPT_BLOB_UNPACK), HotSpotMarkId.DEOPT_HANDLER_ENTRY);
464465
if (config.supportsMethodHandleDeoptimizationEntry() && crb.needsMHDeoptHandler()) {
465-
trampolineCall(crb, asm, foreignCalls.lookupForeignCall(DEOPT_BLOB_UNPACK), HotSpotMarkId.DEOPT_MH_HANDLER_ENTRY);
466+
emitDeoptHandler(crb, asm, foreignCalls.lookupForeignCall(DEOPT_BLOB_UNPACK), HotSpotMarkId.DEOPT_MH_HANDLER_ENTRY);
466467
}
467468
}
468469
}
469470

470-
private static void trampolineCall(CompilationResultBuilder crb, AMD64MacroAssembler asm, ForeignCallLinkage callTarget, HotSpotMarkId exceptionHandlerEntry) {
471+
private static void emitExceptionHandler(CompilationResultBuilder crb, AMD64MacroAssembler asm, ForeignCallLinkage callTarget, HotSpotMarkId exceptionHandlerEntry) {
471472
crb.recordMark(AMD64Call.directCall(crb, asm, callTarget, null, false, null), exceptionHandlerEntry);
472473
// Ensure the return location is a unique pc and that control flow doesn't return here
473474
asm.halt();
474475
}
475476

477+
// @formatter:off
478+
@SyncPort(from = "https://github.com/openjdk/jdk/blob/74a2c831a2af55c66317ca8aead53fde2a2a6900/src/hotspot/cpu/x86/x86.ad#L1261-L1288",
479+
sha1 = "1326c5aa33296807cd6fb271150c3fcc0bfb9388")
480+
// @formatter:on
481+
private static void emitDeoptHandler(CompilationResultBuilder crb, AMD64MacroAssembler asm, ForeignCallLinkage callTarget, HotSpotMarkId deoptHandlerEntry) {
482+
/* Line comments preserved from JDK code. */
483+
crb.recordMark(asm.position(), deoptHandlerEntry);
484+
int position = asm.position();
485+
Label next = new Label();
486+
// push a "the_pc" on the stack without destroying any registers
487+
// as they all may be live.
488+
489+
// push address of "next"
490+
asm.call(next);
491+
asm.bind(next);
492+
// adjust it so it matches "the_pc"
493+
asm.subq(new AMD64Address(rsp, 0), asm.position() - position);
494+
495+
int jmpSize = 1 + 4; // 1 byte opcode + 4 bytes displacement
496+
crb.recordDirectCall(asm.position(), asm.position() + jmpSize, callTarget, null);
497+
asm.rawJmpNoJCCErratumMitigation();
498+
499+
/*
500+
* Ensure that control flow doesn't return here. The synthetic return location PC is the
501+
* address of the call instruction above.
502+
*/
503+
asm.halt();
504+
}
505+
476506
@Override
477507
public RegisterAllocationConfig newRegisterAllocationConfig(RegisterConfig registerConfig, String[] allocationRestrictedTo, Object stub) {
478508
RegisterConfig registerConfigNonNull = registerConfig == null ? getCodeCache().getRegisterConfig() : registerConfig;

0 commit comments

Comments
 (0)