summaryrefslogtreecommitdiff
path: root/src/jit/codegencommon.cpp
diff options
context:
space:
mode:
authorGleb Balykov <g.balykov@samsung.com>2018-06-29 17:25:17 +0300
committerGleb Balykov <g.balykov@samsung.com>2018-09-18 15:49:14 +0300
commitef670ab6e5db223d8b31738b02bb763d3e135ad2 (patch)
tree78bcdf1c6087c4fd04b333468c7be80b4111a5ac /src/jit/codegencommon.cpp
parentd424bb734ce61bc98d1cfab815c48c5ad1d01d5e (diff)
downloadcoreclr-ef670ab6e5db223d8b31738b02bb763d3e135ad2.tar.gz
coreclr-ef670ab6e5db223d8b31738b02bb763d3e135ad2.tar.bz2
coreclr-ef670ab6e5db223d8b31738b02bb763d3e135ad2.zip
Remove relocations for vtable chunks (#17147)
* Separate sections READONLY_VCHUNKS and READONLY_DICTIONARY * Remove relocations for second-level indirection of Vtable in case FEATURE_NGEN_RELOCS_OPTIMIZATIONS is enabled. Introduce FEATURE_NGEN_RELOCS_OPTIMIZATIONS, under which NGEN specific relocations optimizations are enabled * Replace push/pop of R11 in stubs with - str/ldr of R4 in space reserved in epilog for non-tail calls - usage of R4 with hybrid-tail calls (same as for EmitShuffleThunk) * Replace push/pop of R11 for function epilog with usage of LR as helper register right before its restore from stack
Diffstat (limited to 'src/jit/codegencommon.cpp')
-rw-r--r--src/jit/codegencommon.cpp72
1 files changed, 60 insertions, 12 deletions
diff --git a/src/jit/codegencommon.cpp b/src/jit/codegencommon.cpp
index 99902dc7bc..7c2869199e 100644
--- a/src/jit/codegencommon.cpp
+++ b/src/jit/codegencommon.cpp
@@ -9679,6 +9679,19 @@ void CodeGen::genFnEpilog(BasicBlock* block)
bool jmpEpilog = ((block->bbFlags & BBF_HAS_JMP) != 0);
+ GenTree* lastNode = block->lastNode();
+
+ // Method handle and address info used in case of jump epilog
+ CORINFO_METHOD_HANDLE methHnd = nullptr;
+ CORINFO_CONST_LOOKUP addrInfo;
+ addrInfo.addr = nullptr;
+
+ if (jmpEpilog && lastNode->gtOper == GT_JMP)
+ {
+ methHnd = (CORINFO_METHOD_HANDLE)lastNode->gtVal.gtVal1;
+ compiler->info.compCompHnd->getFunctionEntryPoint(methHnd, &addrInfo);
+ }
+
#ifdef _TARGET_ARM_
// We delay starting the unwind codes until we have an instruction which we know
// needs an unwind code. In particular, for large stack frames in methods without
@@ -9723,6 +9736,30 @@ void CodeGen::genFnEpilog(BasicBlock* block)
unwindStarted = true;
}
+ if (jmpEpilog && lastNode->gtOper == GT_JMP && addrInfo.accessType == IAT_RELPVALUE)
+ {
+ // IAT_RELPVALUE jump at the end is done using relative indirection, so,
+ // additional helper register is required.
+ // We use LR just before it is going to be restored from stack, i.e.
+ //
+ // movw r12, laddr
+ // movt r12, haddr
+ // mov lr, r12
+ // ldr r12, [r12]
+ // add r12, r12, lr
+ // pop {lr}
+ // ...
+ // bx r12
+
+ regNumber indCallReg = REG_R12;
+ regNumber vptrReg1 = REG_LR;
+
+ instGen_Set_Reg_To_Imm(EA_HANDLE_CNS_RELOC, indCallReg, (ssize_t)addrInfo.addr);
+ getEmitter()->emitIns_R_R(INS_mov, EA_PTRSIZE, vptrReg1, indCallReg);
+ getEmitter()->emitIns_R_R_I(INS_ldr, EA_PTRSIZE, indCallReg, indCallReg, 0);
+ getEmitter()->emitIns_R_R(INS_add, EA_PTRSIZE, indCallReg, vptrReg1);
+ }
+
genPopCalleeSavedRegisters(jmpEpilog);
if (regSet.rsMaskPreSpillRegs(true) != RBM_NONE)
@@ -9735,6 +9772,12 @@ void CodeGen::genFnEpilog(BasicBlock* block)
compiler->unwindAllocStack(preSpillRegArgSize);
}
+ if (jmpEpilog)
+ {
+ // We better not have used a pop PC to return otherwise this will be unreachable code
+ noway_assert(!genUsedPopToReturn);
+ }
+
#else // _TARGET_ARM64_
compiler->unwindBegEpilog();
@@ -9743,20 +9786,13 @@ void CodeGen::genFnEpilog(BasicBlock* block)
if (jmpEpilog)
{
-#ifdef _TARGET_ARMARCH_
hasTailCalls = true;
-#endif // _TARGET_ARMARCH_
noway_assert(block->bbJumpKind == BBJ_RETURN);
noway_assert(block->bbTreeList != nullptr);
-#ifdef _TARGET_ARM_
- // We better not have used a pop PC to return otherwise this will be unreachable code
- noway_assert(!genUsedPopToReturn);
-#endif // _TARGET_ARM_
-
/* figure out what jump we have */
- GenTree* jmpNode = block->lastNode();
+ GenTree* jmpNode = lastNode;
#if !FEATURE_FASTTAILCALL
noway_assert(jmpNode->gtOper == GT_JMP);
#else // FEATURE_FASTTAILCALL
@@ -9775,10 +9811,8 @@ void CodeGen::genFnEpilog(BasicBlock* block)
{
// Simply emit a jump to the methodHnd. This is similar to a call so we can use
// the same descriptor with some minor adjustments.
- CORINFO_METHOD_HANDLE methHnd = (CORINFO_METHOD_HANDLE)jmpNode->gtVal.gtVal1;
-
- CORINFO_CONST_LOOKUP addrInfo;
- compiler->info.compCompHnd->getFunctionEntryPoint(methHnd, &addrInfo);
+ assert(methHnd != nullptr);
+ assert(addrInfo.addr != nullptr);
#ifdef _TARGET_ARM_
emitter::EmitCallType callType;
@@ -9814,6 +9848,20 @@ void CodeGen::genFnEpilog(BasicBlock* block)
}
break;
+ case IAT_RELPVALUE:
+ {
+ // Load the address into a register, load relative indirect and call through a register
+ // We have to use R12 since we assume the argument registers are in use
+ // LR is used as helper register right before it is restored from stack, thus,
+ // all relative address calculations are performed before LR is restored.
+ callType = emitter::EC_INDIR_R;
+ indCallReg = REG_R12;
+ addr = NULL;
+
+ regTracker.rsTrackRegTrash(indCallReg);
+ break;
+ }
+
case IAT_PPVALUE:
default:
NO_WAY("Unsupported JMP indirection");