// vtable of it's owning class or interface.
void getMethodVTableOffset(CORINFO_METHOD_HANDLE method, /* IN */
unsigned* offsetOfIndirection, /* OUT */
- unsigned* offsetAfterIndirection /* OUT */
+ unsigned* offsetAfterIndirection,/* OUT */
+ unsigned* isRelative /* OUT */
);
// Find the virtual method in implementingClass that overrides virtualMethod.
LWM(GetMethodName, DLD, DD)
LWM(GetMethodSig, DLDL, Agnostic_CORINFO_SIG_INFO)
LWM(GetMethodSync, DWORDLONG, DLDL)
-LWM(GetMethodVTableOffset, DWORDLONG, DD)
+LWM(GetMethodVTableOffset, DWORDLONG, DDD)
LWM(GetNewArrHelper, DWORDLONG, DWORD)
LWM(GetNewHelper, Agnostic_GetNewHelper, DWORD)
LWM(GetParentType, DWORDLONG, DWORDLONG)
void MethodContext::recGetMethodVTableOffset(CORINFO_METHOD_HANDLE method,
unsigned* offsetOfIndirection,
- unsigned* offsetAfterIndirection)
+ unsigned* offsetAfterIndirection,
+ unsigned* isRelative)
{
if (GetMethodVTableOffset == nullptr)
- GetMethodVTableOffset = new LightWeightMap<DWORDLONG, DD>();
+ GetMethodVTableOffset = new LightWeightMap<DWORDLONG, DDD>();
- DD value;
+ DDD value;
value.A = (DWORD)*offsetOfIndirection;
value.B = (DWORD)*offsetAfterIndirection;
+ value.C = (DWORD)*isRelative;
GetMethodVTableOffset->Add((DWORDLONG)method, value);
DEBUG_REC(dmpGetMethodVTableOffset((DWORDLONG)method, value));
}
-void MethodContext::dmpGetMethodVTableOffset(DWORDLONG key, DD value)
+void MethodContext::dmpGetMethodVTableOffset(DWORDLONG key, DDD value)
{
printf("GetMethodVTableOffset key ftn-%016llX, value offi-%u, offa-%u", key, value.A, value.B);
}
void MethodContext::repGetMethodVTableOffset(CORINFO_METHOD_HANDLE method,
unsigned* offsetOfIndirection,
- unsigned* offsetAfterIndirection)
+ unsigned* offsetAfterIndirection,
+ unsigned* isRelative)
{
- DD value;
+ DDD value;
AssertCodeMsg(GetMethodVTableOffset != nullptr, EXCEPTIONCODE_MC, "Didn't find anything for %016llX",
(DWORDLONG)method);
*offsetOfIndirection = (unsigned)value.A;
*offsetAfterIndirection = (unsigned)value.B;
+ *isRelative = (unsigned)value.C;
DEBUG_REP(dmpGetMethodVTableOffset((DWORDLONG)method, value));
}
DWORD A;
DWORD B;
};
+ struct DDD
+ {
+ DWORD A;
+ DWORD B;
+ DWORD C;
+ };
struct Agnostic_CanTailCall
{
DWORDLONG callerHnd;
void recGetMethodVTableOffset(CORINFO_METHOD_HANDLE method,
unsigned* offsetOfIndirection,
- unsigned* offsetAfterIndirection);
- void dmpGetMethodVTableOffset(DWORDLONG key, DD value);
+ unsigned* offsetAfterIndirection,
+ unsigned* isRelative);
+ void dmpGetMethodVTableOffset(DWORDLONG key, DDD value);
void repGetMethodVTableOffset(CORINFO_METHOD_HANDLE method,
unsigned* offsetOfIndirection,
- unsigned* offsetAfterIndirection);
+ unsigned* offsetAfterIndirection,
+ unsigned* isRelative);
void recResolveVirtualMethod(CORINFO_METHOD_HANDLE virtMethod,
CORINFO_CLASS_HANDLE implClass,
// vtable of it's owning class or interface.
void interceptor_ICJI::getMethodVTableOffset(CORINFO_METHOD_HANDLE method, /* IN */
unsigned* offsetOfIndirection, /* OUT */
- unsigned* offsetAfterIndirection /* OUT */
+ unsigned* offsetAfterIndirection,/* OUT */
+ unsigned* isRelative /* OUT */
)
{
mc->cr->AddCall("getMethodVTableOffset");
- original_ICorJitInfo->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection);
- mc->recGetMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection);
+ original_ICorJitInfo->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection, isRelative);
+ mc->recGetMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection, isRelative);
}
// Find the virtual method in implementingClass that overrides virtualMethod.
// vtable of it's owning class or interface.
void interceptor_ICJI::getMethodVTableOffset(CORINFO_METHOD_HANDLE method, /* IN */
unsigned* offsetOfIndirection, /* OUT */
- unsigned* offsetAfterIndirection /* OUT */
+ unsigned* offsetAfterIndirection,/* OUT */
+ unsigned* isRelative /* OUT */
)
{
mcs->AddCall("getMethodVTableOffset");
- original_ICorJitInfo->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection);
+ original_ICorJitInfo->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection, isRelative);
}
// Find the virtual method in implementingClass that overrides virtualMethod.
// vtable of it's owning class or interface.
void interceptor_ICJI::getMethodVTableOffset(CORINFO_METHOD_HANDLE method, /* IN */
unsigned* offsetOfIndirection, /* OUT */
- unsigned* offsetAfterIndirection /* OUT */
+ unsigned* offsetAfterIndirection,/* OUT */
+ unsigned* isRelative /* OUT */
)
{
- original_ICorJitInfo->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection);
+ original_ICorJitInfo->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection, isRelative);
}
// Find the virtual method in implementingClass that overrides virtualMethod.
// vtable of it's owning class or interface.
void MyICJI::getMethodVTableOffset(CORINFO_METHOD_HANDLE method, /* IN */
unsigned* offsetOfIndirection, /* OUT */
- unsigned* offsetAfterIndirection /* OUT */
+ unsigned* offsetAfterIndirection,/* OUT */
+ unsigned* isRelative /* OUT */
)
{
jitInstance->mc->cr->AddCall("getMethodVTableOffset");
- jitInstance->mc->repGetMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection);
+ jitInstance->mc->repGetMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection, isRelative);
}
// Find the virtual method in implementingClass that overrides virtualMethod.
{
m_display->StartStructureWithOffset("Vtable",
mt->GetVtableOffset(),
- mt->GetNumVtableIndirections() * sizeof(PTR_PCODE),
+ mt->GetNumVtableIndirections() * sizeof(MethodTable::VTableIndir_t),
DataPtrToDisplay(PTR_TO_TADDR(mt) + mt->GetVtableOffset()),
- mt->GetNumVtableIndirections() * sizeof(PTR_PCODE));
+ mt->GetNumVtableIndirections() * sizeof(MethodTable::VTableIndir_t));
MethodTable::VtableIndirectionSlotIterator itIndirect = mt->IterateVtableIndirectionSlots();
{
DisplayStartElement( "Slot", ALWAYS );
DisplayWriteElementInt( "Index", i, ALWAYS );
- PTR_PCODE tgt = mt->GetVtableIndirections()[i];
+ TADDR base = dac_cast<TADDR>(&(mt->GetVtableIndirections()[i]));
+ PTR_PCODE tgt = MethodTable::VTableIndir_t::GetValueMaybeNullAtPtr(base);
DisplayWriteElementPointer( "Pointer",
DataPtrToDisplay(dac_cast<TADDR>(tgt)),
ALWAYS );
else
{
CoverageRead( PTR_TO_TADDR(mt) + mt->GetVtableOffset(),
- mt->GetNumVtableIndirections() * sizeof(PTR_PCODE) );
+ mt->GetNumVtableIndirections() * sizeof(MethodTable::VTableIndir_t) );
if (mt->HasNonVirtualSlotsArray())
{
virtual void getMethodVTableOffset (
CORINFO_METHOD_HANDLE method, /* IN */
unsigned* offsetOfIndirection, /* OUT */
- unsigned* offsetAfterIndirection /* OUT */
+ unsigned* offsetAfterIndirection, /* OUT */
+ unsigned* isRelative /* OUT */
) = 0;
// Find the virtual method in implementingClass that overrides virtualMethod,
void WrapICorJitInfo::getMethodVTableOffset(
CORINFO_METHOD_HANDLE method, /* IN */
unsigned* offsetOfIndirection, /* OUT */
- unsigned* offsetAfterIndirection /* OUT */)
+ unsigned* offsetAfterIndirection, /* OUT */
+ unsigned* isRelative /* OUT */)
{
API_ENTER(getMethodVTableOffset);
- wrapHnd->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection);
+ wrapHnd->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection, isRelative);
API_LEAVE(getMethodVTableOffset);
}
// stub dispatching is off or this is not a virtual call (could be a tailcall)
{
regNumber vptrReg;
+ regNumber vptrReg1;
+ regMaskTP vptrMask1;
unsigned vtabOffsOfIndirection;
unsigned vtabOffsAfterIndirection;
+ unsigned isRelative;
noway_assert(callType == CT_USER_FUNC);
+ /* Get hold of the vtable offset (note: this might be expensive) */
+
+ compiler->info.compCompHnd->getMethodVTableOffset(call->gtCallMethHnd, &vtabOffsOfIndirection,
+ &vtabOffsAfterIndirection, &isRelative);
+
vptrReg =
regSet.rsGrabReg(RBM_ALLINT); // Grab an available register to use for the CALL indirection
vptrMask = genRegMask(vptrReg);
+ if (isRelative)
+ {
+ vptrReg1 = regSet.rsGrabReg(RBM_ALLINT & ~vptrMask);
+ vptrMask1 = genRegMask(vptrReg1);
+ }
+
/* The register no longer holds a live pointer value */
gcInfo.gcMarkRegSetNpt(vptrMask);
+ if (isRelative)
+ {
+ gcInfo.gcMarkRegSetNpt(vptrMask1);
+ }
+
// MOV vptrReg, [REG_CALL_THIS + offs]
getEmitter()->emitIns_R_AR(ins_Load(TYP_I_IMPL), EA_PTRSIZE, vptrReg, genGetThisArgReg(call),
VPTR_OFFS);
regTracker.rsTrackRegTrash(vptrReg);
- noway_assert(vptrMask & ~call->gtCallRegUsedMask);
-
- /* Get hold of the vtable offset (note: this might be expensive) */
+ if (isRelative)
+ {
+ regTracker.rsTrackRegTrash(vptrReg1);
+ }
- compiler->info.compCompHnd->getMethodVTableOffset(call->gtCallMethHnd, &vtabOffsOfIndirection,
- &vtabOffsAfterIndirection);
+ noway_assert(vptrMask & ~call->gtCallRegUsedMask);
/* The register no longer holds a live pointer value */
gcInfo.gcMarkRegSetNpt(vptrMask);
if (vtabOffsOfIndirection != CORINFO_VIRTUALCALL_NO_CHUNK)
{
+ if (isRelative)
+ {
+#if defined(_TARGET_ARM_)
+ unsigned offset = vtabOffsOfIndirection + vtabOffsAfterIndirection;
+
+ // ADD vptrReg1, REG_CALL_IND_SCRATCH, vtabOffsOfIndirection + vtabOffsAfterIndirection
+ getEmitter()->emitIns_R_R_I(INS_add, EA_PTRSIZE, vptrReg1, vptrReg, offset);
+#else
+ _ASSERTE(false);
+#endif
+ }
+
// MOV vptrReg, [REG_CALL_IND_SCRATCH + vtabOffsOfIndirection]
getEmitter()->emitIns_R_AR(ins_Load(TYP_I_IMPL), EA_PTRSIZE, vptrReg, vptrReg,
vtabOffsOfIndirection);
}
+ else
+ {
+ _ASSERTE(!isRelative);
+ }
/* Call through the appropriate vtable slot */
if (fTailCall)
{
- /* Load the function address: "[vptrReg+vtabOffs] -> reg_intret" */
-
- getEmitter()->emitIns_R_AR(ins_Load(TYP_I_IMPL), EA_PTRSIZE, REG_TAILCALL_ADDR, vptrReg,
- vtabOffsAfterIndirection);
+ if (isRelative)
+ {
+#if defined(_TARGET_ARM_)
+ /* Load the function address: "[vptrReg1 + vptrReg] -> reg_intret" */
+ getEmitter()->emitIns_R_ARR(ins_Load(TYP_I_IMPL), EA_PTRSIZE, REG_TAILCALL_ADDR, vptrReg1,
+ vptrReg, 0);
+#else
+ _ASSERTE(false);
+#endif
+ }
+ else
+ {
+ /* Load the function address: "[vptrReg+vtabOffs] -> reg_intret" */
+ getEmitter()->emitIns_R_AR(ins_Load(TYP_I_IMPL), EA_PTRSIZE, REG_TAILCALL_ADDR, vptrReg,
+ vtabOffsAfterIndirection);
+ }
}
else
{
#if CPU_LOAD_STORE_ARCH
- getEmitter()->emitIns_R_AR(ins_Load(TYP_I_IMPL), EA_PTRSIZE, vptrReg, vptrReg,
- vtabOffsAfterIndirection);
+ if (isRelative)
+ {
+ getEmitter()->emitIns_R_ARR(ins_Load(TYP_I_IMPL), EA_PTRSIZE, vptrReg, vptrReg1, vptrReg,
+ 0);
+ }
+ else
+ {
+ getEmitter()->emitIns_R_AR(ins_Load(TYP_I_IMPL), EA_PTRSIZE, vptrReg, vptrReg,
+ vtabOffsAfterIndirection);
+ }
getEmitter()->emitIns_Call(emitter::EC_INDIR_R, call->gtCallMethHnd,
INDEBUG_LDISASM_COMMA(sigInfo) NULL, // addr
gcInfo.gcRegByrefSetCur, ilOffset,
vptrReg); // ireg
#else
+ _ASSERTE(!isRelative);
getEmitter()->emitIns_Call(emitter::EC_FUNC_VIRTUAL, call->gtCallMethHnd,
INDEBUG_LDISASM_COMMA(sigInfo) NULL, // addr
args, retSize, gcInfo.gcVarPtrSetCur, gcInfo.gcRegGCrefSetCur,
fmt = IF_T2_M0;
sf = INS_FLAGS_NOT_SET;
}
+ else if (insDoesNotSetFlags(flags) && reg1 != REG_SP && reg1 != REG_PC)
+ {
+ // movw,movt reg1, imm
+ codeGen->instGen_Set_Reg_To_Imm(attr, reg1, imm);
+
+ // ins reg1, reg2
+ emitIns_R_R(ins, attr, reg1, reg2);
+
+ return;
+ }
else
{
assert(!"Instruction cannot be encoded");
// We'll introduce another use of this local so increase its ref count.
comp->lvaTable[lclNum].incRefCnts(comp->compCurBB->getBBWeight(comp), comp);
+ // Get hold of the vtable offset (note: this might be expensive)
+ unsigned vtabOffsOfIndirection;
+ unsigned vtabOffsAfterIndirection;
+ unsigned isRelative;
+ comp->info.compCompHnd->getMethodVTableOffset(call->gtCallMethHnd, &vtabOffsOfIndirection,
+ &vtabOffsAfterIndirection, &isRelative);
+
// If the thisPtr is a local field, then construct a local field type node
GenTree* local;
if (thisPtr->isLclField())
// pointer to virtual table = [REG_CALL_THIS + offs]
GenTree* result = Ind(Offset(local, VPTR_OFFS));
- // Get hold of the vtable offset (note: this might be expensive)
- unsigned vtabOffsOfIndirection;
- unsigned vtabOffsAfterIndirection;
- comp->info.compCompHnd->getMethodVTableOffset(call->gtCallMethHnd, &vtabOffsOfIndirection,
- &vtabOffsAfterIndirection);
-
// Get the appropriate vtable chunk
if (vtabOffsOfIndirection != CORINFO_VIRTUALCALL_NO_CHUNK)
{
- // result = [REG_CALL_IND_SCRATCH + vtabOffsOfIndirection]
- result = Ind(Offset(result, vtabOffsOfIndirection));
+ if (isRelative)
+ {
+ unsigned lclNumTmp = comp->lvaGrabTemp(true DEBUGARG("lclNumTmp"));
+
+ comp->lvaTable[lclNumTmp].incRefCnts(comp->compCurBB->getBBWeight(comp), comp);
+ GenTree* lclvNodeStore = comp->gtNewTempAssign(lclNumTmp, result);
+
+ LIR::Range range = LIR::SeqTree(comp, lclvNodeStore);
+ JITDUMP("results of lowering call interm:\n");
+ DISPRANGE(range);
+ BlockRange().InsertBefore(call, std::move(range));
+
+ GenTree* tmpTree = comp->gtNewLclvNode(lclNumTmp, result->TypeGet());
+ tmpTree = Offset(tmpTree, vtabOffsOfIndirection);
+
+ tmpTree = comp->gtNewOperNode(GT_IND, TYP_I_IMPL, tmpTree, false);
+ GenTree* offs = comp->gtNewIconNode(vtabOffsOfIndirection + vtabOffsAfterIndirection, TYP_INT);
+ result = comp->gtNewOperNode(GT_ADD, TYP_I_IMPL, comp->gtNewLclvNode(lclNumTmp, result->TypeGet()), offs);
+
+ result = Ind(OffsetByIndex(result, tmpTree));
+ }
+ else
+ {
+ // result = [REG_CALL_IND_SCRATCH + vtabOffsOfIndirection]
+ result = Ind(Offset(result, vtabOffsOfIndirection));
+ }
+ }
+ else
+ {
+ _ASSERTE(!isRelative);
}
// Load the function address
// result = [reg+vtabOffs]
- result = Ind(Offset(result, vtabOffsAfterIndirection));
+ if (!isRelative)
+ {
+ result = Ind(Offset(result, vtabOffsAfterIndirection));
+ }
return result;
}
return new (comp, GT_LEA) GenTreeAddrMode(resultType, base, nullptr, 0, offset);
}
+ GenTree* OffsetByIndex(GenTree* base, GenTree* index)
+ {
+ var_types resultType = (base->TypeGet() == TYP_REF) ? TYP_BYREF : base->TypeGet();
+ return new (comp, GT_LEA) GenTreeAddrMode(resultType, base, index, 0, 0);
+ }
+
// returns true if the tree can use the read-modify-write memory instruction form
bool isRMWRegOper(GenTreePtr tree);
unsigned vtabOffsOfIndirection;
unsigned vtabOffsAfterIndirection;
- info.compCompHnd->getMethodVTableOffset(call->gtCallMethHnd, &vtabOffsOfIndirection, &vtabOffsAfterIndirection);
+ unsigned isRelative;
+ info.compCompHnd->getMethodVTableOffset(call->gtCallMethHnd, &vtabOffsOfIndirection, &vtabOffsAfterIndirection,
+ &isRelative);
/* Get the appropriate vtable chunk */
if (vtabOffsOfIndirection != CORINFO_VIRTUALCALL_NO_CHUNK)
{
- add = gtNewOperNode(GT_ADD, TYP_I_IMPL, vtbl, gtNewIconNode(vtabOffsOfIndirection, TYP_I_IMPL));
+ add = gtNewOperNode(GT_ADD, TYP_I_IMPL, vtbl, gtNewIconNode(vtabOffsOfIndirection, TYP_I_IMPL));
+
+ GenTreePtr indOffTree;
+
+ if (isRelative)
+ {
+ indOffTree = impCloneExpr(add, &add, NO_CLASS_HANDLE, (unsigned)CHECK_SPILL_ALL,
+ nullptr DEBUGARG("virtual table call"));
+ }
+
vtbl = gtNewOperNode(GT_IND, TYP_I_IMPL, add);
+
+ if (isRelative)
+ {
+ vtbl = gtNewOperNode(GT_ADD, TYP_I_IMPL, vtbl, indOffTree);
+ }
}
/* Now the appropriate vtable slot */
DWORD numNonVirtualSlots = numCtors + 3; // 3 for the proper rank Get, Set, Address
size_t cbMT = sizeof(MethodTable);
- cbMT += MethodTable::GetNumVtableIndirections(numVirtuals) * sizeof(PTR_PCODE);
+ cbMT += MethodTable::GetNumVtableIndirections(numVirtuals) * sizeof(MethodTable::VTableIndir_t);
// GC info
size_t cbCGCDescData = 0;
if (canShareVtableChunks)
{
// Share the parent chunk
- it.SetIndirectionSlot(pParentClass->GetVtableIndirections()[it.GetIndex()]);
+ it.SetIndirectionSlot(pParentClass->GetVtableIndirections()[it.GetIndex()].GetValueMaybeNull());
}
else
{
// Bytes are required for the vtable itself
S_SIZE_T safe_cbMT = S_SIZE_T( cbGC ) + S_SIZE_T( sizeof(MethodTable) );
- safe_cbMT += MethodTable::GetNumVtableIndirections(cSlots) * sizeof(PTR_PCODE);
+ safe_cbMT += MethodTable::GetNumVtableIndirections(cSlots) * sizeof(MethodTable::VTableIndir_t);
if (safe_cbMT.IsOverflow())
{
ThrowHR(COR_E_OVERFLOW);
if (canShareVtableChunks)
{
// Share the canonical chunk
- it.SetIndirectionSlot(pOldMT->GetVtableIndirections()[it.GetIndex()]);
+ it.SetIndirectionSlot(pOldMT->GetVtableIndirections()[it.GetIndex()].GetValueMaybeNull());
}
else
{
/*********************************************************************/
void CEEInfo::getMethodVTableOffset (CORINFO_METHOD_HANDLE methodHnd,
unsigned * pOffsetOfIndirection,
- unsigned * pOffsetAfterIndirection)
+ unsigned * pOffsetAfterIndirection,
+ unsigned * isRelative)
{
CONTRACTL {
SO_TOLERANT;
// better be in the vtable
_ASSERTE(method->GetSlot() < method->GetMethodTable()->GetNumVirtuals());
- *pOffsetOfIndirection = MethodTable::GetVtableOffset() + MethodTable::GetIndexOfVtableIndirection(method->GetSlot()) * sizeof(PTR_PCODE);
+ *pOffsetOfIndirection = MethodTable::GetVtableOffset() + MethodTable::GetIndexOfVtableIndirection(method->GetSlot()) * sizeof(MethodTable::VTableIndir_t);
*pOffsetAfterIndirection = MethodTable::GetIndexAfterVtableIndirection(method->GetSlot()) * sizeof(PCODE);
+ *isRelative = MethodTable::VTableIndir_t::isRelative ? 1 : 0;
EE_TO_JIT_TRANSITION_LEAF();
}
void getMethodVTableOffset (
CORINFO_METHOD_HANDLE methodHnd,
unsigned * pOffsetOfIndirection,
- unsigned * pOffsetAfterIndirection
- );
+ unsigned * pOffsetAfterIndirection,
+ unsigned * isRelative);
CORINFO_METHOD_HANDLE resolveVirtualMethod(
CORINFO_METHOD_HANDLE virtualMethod,
VtableIndirectionSlotIterator it = IterateVtableIndirectionSlots();
while (it.Next())
{
- image->FixupPointerField(this, it.GetOffsetFromMethodTable());
+ if (VTableIndir_t::isRelative)
+ {
+ image->FixupRelativePointerField(this, it.GetOffsetFromMethodTable());
+ }
+ else
+ {
+ image->FixupPointerField(this, it.GetOffsetFromMethodTable());
+ }
}
}
{
// Virtual slots live in chunks pointed to by vtable indirections
- slotBase = (PVOID) GetVtableIndirections()[GetIndexOfVtableIndirection(slotNumber)];
+ slotBase = (PVOID) GetVtableIndirections()[GetIndexOfVtableIndirection(slotNumber)].GetValueMaybeNull();
slotOffset = GetIndexAfterVtableIndirection(slotNumber) * sizeof(PCODE);
}
else if (HasSingleNonVirtualSlot())
if (!IsCanonicalMethodTable())
{
- if (GetVtableIndirections()[indirectionIndex] == GetCanonicalMethodTable()->GetVtableIndirections()[indirectionIndex])
+ if (GetVtableIndirections()[indirectionIndex].GetValueMaybeNull() == GetCanonicalMethodTable()->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull())
fSharedVtableChunk = TRUE;
}
if (slotNumber < GetNumParentVirtuals())
{
- if (GetVtableIndirections()[indirectionIndex] == GetParentMethodTable()->GetVtableIndirections()[indirectionIndex])
+ if (GetVtableIndirections()[indirectionIndex].GetValueMaybeNull() == GetParentMethodTable()->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull())
fSharedVtableChunk = TRUE;
}
CONSISTENCY_CHECK(slotNum < GetNumVirtuals());
// Virtual slots live in chunks pointed to by vtable indirections
- return *(GetVtableIndirections()[GetIndexOfVtableIndirection(slotNum)] + GetIndexAfterVtableIndirection(slotNum));
+
+ DWORD index = GetIndexOfVtableIndirection(slotNum);
+ TADDR base = dac_cast<TADDR>(&(GetVtableIndirections()[index]));
+ return *(VTableIndir_t::GetValueMaybeNullAtPtr(base) + GetIndexAfterVtableIndirection(slotNum));
}
PTR_PCODE GetSlotPtrRaw(UINT32 slotNum)
if (slotNum < GetNumVirtuals())
{
// Virtual slots live in chunks pointed to by vtable indirections
- return GetVtableIndirections()[GetIndexOfVtableIndirection(slotNum)] + GetIndexAfterVtableIndirection(slotNum);
+ DWORD index = GetIndexOfVtableIndirection(slotNum);
+ TADDR base = dac_cast<TADDR>(&(GetVtableIndirections()[index]));
+ return VTableIndir_t::GetValueMaybeNullAtPtr(base) + GetIndexAfterVtableIndirection(slotNum);
}
else if (HasSingleNonVirtualSlot())
{
#define VTABLE_SLOTS_PER_CHUNK 8
#define VTABLE_SLOTS_PER_CHUNK_LOG2 3
+#if defined(PLATFORM_UNIX) && defined(_TARGET_ARM_)
+ typedef RelativePointer<PTR_PCODE> VTableIndir_t;
+#else
+ typedef PlainPointer<PTR_PCODE> VTableIndir_t;
+#endif
+
static DWORD GetIndexOfVtableIndirection(DWORD slotNum);
static DWORD GetStartSlotForVtableIndirection(UINT32 indirectionIndex, DWORD wNumVirtuals);
static DWORD GetEndSlotForVtableIndirection(UINT32 indirectionIndex, DWORD wNumVirtuals);
static UINT32 GetIndexAfterVtableIndirection(UINT32 slotNum);
static DWORD GetNumVtableIndirections(DWORD wNumVirtuals);
- PTR_PTR_PCODE GetVtableIndirections();
+ DPTR(VTableIndir_t) GetVtableIndirections();
DWORD GetNumVtableIndirections();
class VtableIndirectionSlotIterator
friend class MethodTable;
private:
- PTR_PTR_PCODE m_pSlot;
+ DPTR(VTableIndir_t) m_pSlot;
DWORD m_i;
DWORD m_count;
PTR_MethodTable m_pMT;
}
//==========================================================================================
-inline PTR_PTR_PCODE MethodTable::GetVtableIndirections()
+inline DPTR(MethodTable::VTableIndir_t) MethodTable::GetVtableIndirections()
{
LIMITED_METHOD_DAC_CONTRACT;
- return dac_cast<PTR_PTR_PCODE>(dac_cast<TADDR>(this) + sizeof(MethodTable));
+ return dac_cast<DPTR(VTableIndir_t)>(dac_cast<TADDR>(this) + sizeof(MethodTable));
}
//==========================================================================================
WRAPPER_NO_CONTRACT;
PRECONDITION(m_i != (DWORD) -1 && m_i < m_count);
- return GetVtableOffset() + sizeof(PTR_PCODE) * m_i;
+ return GetVtableOffset() + sizeof(VTableIndir_t) * m_i;
}
//==========================================================================================
LIMITED_METHOD_DAC_CONTRACT;
PRECONDITION(m_i != (DWORD) -1 && m_i < m_count);
- return *m_pSlot;
+ return m_pSlot->GetValueMaybeNull(dac_cast<TADDR>(m_pSlot));
}
//==========================================================================================
inline void MethodTable::VtableIndirectionSlotIterator::SetIndirectionSlot(PTR_PCODE pChunk)
{
LIMITED_METHOD_CONTRACT;
- *m_pSlot = pChunk;
+ m_pSlot->SetValueMaybeNull(pChunk);
}
#endif
DWORD offset = offsets[GetFlag((WFLAGS2_ENUM)(flag - 1))];
if (offset >= sizeof(MethodTable)) {
- offset += GetNumVtableIndirections() * sizeof(PTR_PCODE);
+ offset += GetNumVtableIndirections() * sizeof(VTableIndir_t);
}
return dac_cast<TADDR>(this) + offset;
DWORD offset = c_OptionalMembersStartOffsets[GetFlag(enum_flag_MultipurposeSlotsMask)];
- offset += GetNumVtableIndirections() * sizeof(PTR_PCODE);
+ offset += GetNumVtableIndirections() * sizeof(VTableIndir_t);
#undef METHODTABLE_OPTIONAL_MEMBER
#define METHODTABLE_OPTIONAL_MEMBER(NAME, TYPE, GETTER) \
//
// Non-canonical method tables either share everything or nothing so it is sufficient to check
// just the first indirection to detect sharing.
- if (pMT->GetVtableIndirections()[0] != pCanonMT->GetVtableIndirections()[0])
+ if (pMT->GetVtableIndirections()[0].GetValueMaybeNull() != pCanonMT->GetVtableIndirections()[0].GetValueMaybeNull())
{
for (DWORD i = 0; i < nParentVirtuals; i++)
{
// We need to re-inherit this slot from the exact parent.
DWORD indirectionIndex = MethodTable::GetIndexOfVtableIndirection(i);
- if (pMT->GetVtableIndirections()[indirectionIndex] == pApproxParentMT->GetVtableIndirections()[indirectionIndex])
+ if (pMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull() == pApproxParentMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull())
{
// The slot lives in a chunk shared from the approximate parent MT
// If so, we need to change to share the chunk from the exact parent MT
_ASSERTE(MethodTable::CanShareVtableChunksFrom(pParentMT, pMT->GetLoaderModule()));
#endif
- pMT->GetVtableIndirections()[indirectionIndex] = pParentMT->GetVtableIndirections()[indirectionIndex];
+ pMT->GetVtableIndirections()[indirectionIndex].SetValueMaybeNull(pParentMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull());
i = MethodTable::GetEndSlotForVtableIndirection(indirectionIndex, nParentVirtuals) - 1;
continue;
S_SIZE_T cbTotalSize = S_SIZE_T(dwGCSize) + S_SIZE_T(sizeof(MethodTable));
// vtable
- cbTotalSize += MethodTable::GetNumVtableIndirections(dwVirtuals) * sizeof(PTR_PCODE);
+ cbTotalSize += MethodTable::GetNumVtableIndirections(dwVirtuals) * sizeof(MethodTable::VTableIndir_t);
DWORD dwMultipurposeSlotsMask = 0;
{
// Share the parent chunk
_ASSERTE(it.GetEndSlot() <= pMTParent->GetNumVirtuals());
- it.SetIndirectionSlot(pMTParent->GetVtableIndirections()[it.GetIndex()]);
+ it.SetIndirectionSlot(pMTParent->GetVtableIndirections()[it.GetIndex()].GetValueMaybeNull());
}
else
{
// with code:MethodDesc::SetStableEntryPointInterlocked.
//
DWORD indirectionIndex = MethodTable::GetIndexOfVtableIndirection(iCurSlot);
- if (GetParentMethodTable()->GetVtableIndirections()[indirectionIndex] != pMT->GetVtableIndirections()[indirectionIndex])
+ if (GetParentMethodTable()->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull() != pMT->GetVtableIndirections()[indirectionIndex].GetValueMaybeNull())
pMT->SetSlot(iCurSlot, pMD->GetMethodEntryPoint());
}
else
}
void ZapInfo::getMethodVTableOffset(CORINFO_METHOD_HANDLE method,
- unsigned * pOffsetOfIndirection,
- unsigned * pOffsetAfterIndirection)
+ unsigned * pOffsetOfIndirection,
+ unsigned * pOffsetAfterIndirection,
+ unsigned * isRelative)
{
- m_pEEJitInfo->getMethodVTableOffset(method, pOffsetOfIndirection, pOffsetAfterIndirection);
+ m_pEEJitInfo->getMethodVTableOffset(method, pOffsetOfIndirection, pOffsetAfterIndirection, isRelative);
}
CORINFO_METHOD_HANDLE ZapInfo::resolveVirtualMethod(
void getMethodVTableOffset(CORINFO_METHOD_HANDLE method,
unsigned * pOffsetOfIndirection,
- unsigned * pOffsetAfterIndirection);
+ unsigned * pOffsetAfterIndirection,
+ unsigned * isRelative);
CORINFO_METHOD_HANDLE resolveVirtualMethod(
CORINFO_METHOD_HANDLE virtualMethod,