summaryrefslogtreecommitdiff
path: root/src/jit
diff options
context:
space:
mode:
authorAndy Ayers <andya@microsoft.com>2019-06-20 12:04:54 -0700
committerGitHub <noreply@github.com>2019-06-20 12:04:54 -0700
commitf163abbd16d35032e4450a09c548cb804cf36a85 (patch)
treef48a751f5ec82e7cf2992f3dc4797284bab0984e /src/jit
parentb1ea5ede9393be013477d270b3496e868b8bae20 (diff)
downloadcoreclr-f163abbd16d35032e4450a09c548cb804cf36a85.tar.gz
coreclr-f163abbd16d35032e4450a09c548cb804cf36a85.tar.bz2
coreclr-f163abbd16d35032e4450a09c548cb804cf36a85.zip
JIT: use register indirect for indirect jumps (#25251)
If we are jumping to another method via an indirection cell, the cell address may be too far from the jump to address via a RIP-relative indirection. So instead, load the target address into RAX and jump register indirect. Fixes #22342.
Diffstat (limited to 'src/jit')
-rw-r--r--src/jit/codegencommon.cpp28
-rw-r--r--src/jit/emitxarch.cpp8
2 files changed, 26 insertions, 10 deletions
diff --git a/src/jit/codegencommon.cpp b/src/jit/codegencommon.cpp
index bb81361d9b..34be5f7de7 100644
--- a/src/jit/codegencommon.cpp
+++ b/src/jit/codegencommon.cpp
@@ -8905,24 +8905,40 @@ void CodeGen::genFnEpilog(BasicBlock* block)
NO_WAY("Unsupported JMP indirection");
}
- const emitter::EmitCallType callType =
- (addrInfo.accessType == IAT_VALUE) ? emitter::EC_FUNC_TOKEN : emitter::EC_FUNC_TOKEN_INDIR;
+ // If we have IAT_PVALUE, jump via register indirect, as sometimes the
+ // indirection cell can't be reached by the jump.
- // Simply emit a jump to the methodHnd. This is similar to a call so we can use
- // the same descriptor with some minor adjustments.
+ emitter::EmitCallType callType;
+ void* addr;
+ regNumber indCallReg;
+
+ if (addrInfo.accessType == IAT_PVALUE)
+ {
+ callType = emitter::EC_INDIR_ARD;
+ indCallReg = REG_RAX;
+ addr = nullptr;
+ instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, indCallReg, (ssize_t)addrInfo.addr);
+ regSet.verifyRegUsed(indCallReg);
+ }
+ else
+ {
+ callType = emitter::EC_FUNC_TOKEN;
+ addr = addrInfo.addr;
+ indCallReg = REG_NA;
+ }
// clang-format off
getEmitter()->emitIns_Call(callType,
methHnd,
INDEBUG_LDISASM_COMMA(nullptr)
- addrInfo.addr,
+ addr,
0, // argSize
EA_UNKNOWN // retSize
MULTIREG_HAS_SECOND_GC_RET_ONLY_ARG(EA_UNKNOWN), // secondRetSize
gcInfo.gcVarPtrSetCur,
gcInfo.gcRegGCrefSetCur,
gcInfo.gcRegByrefSetCur,
- BAD_IL_OFFSET, REG_NA, REG_NA, 0, 0, /* iloffset, ireg, xreg, xmul, disp */
+ BAD_IL_OFFSET, indCallReg, REG_NA, 0, 0, /* iloffset, ireg, xreg, xmul, disp */
true /* isJump */
);
// clang-format on
diff --git a/src/jit/emitxarch.cpp b/src/jit/emitxarch.cpp
index 157a57e432..1f529ff694 100644
--- a/src/jit/emitxarch.cpp
+++ b/src/jit/emitxarch.cpp
@@ -7057,7 +7057,7 @@ void emitter::emitIns_Call(EmitCallType callType,
if (isJump)
{
- assert(callType == EC_FUNC_TOKEN || callType == EC_FUNC_TOKEN_INDIR);
+ assert(callType == EC_FUNC_TOKEN || callType == EC_INDIR_ARD);
if (callType == EC_FUNC_TOKEN)
{
ins = INS_l_jmp;
@@ -7853,9 +7853,9 @@ void emitter::emitDispAddrMode(instrDesc* id, bool noDetail)
printf("reloc ");
}
printf("J_M%03u_DS%02u", Compiler::s_compMethodsCount, id->idDebugOnlyInfo()->idMemCookie);
- }
- disp -= id->idDebugOnlyInfo()->idMemCookie;
+ disp -= id->idDebugOnlyInfo()->idMemCookie;
+ }
}
bool frameRef = false;
@@ -8351,7 +8351,7 @@ void emitter::emitDispIns(
emitDispAddrMode(id, isNew);
emitDispShift(ins);
- if (ins == INS_call)
+ if ((ins == INS_call) || (ins == INS_i_jmp))
{
assert(id->idInsFmt() == IF_ARD);