pResult->stubLookup.runtimeLookup.testForNull = value.stubLookup.runtimeLookup.testForNull != 0;
pResult->stubLookup.runtimeLookup.testForFixup = value.stubLookup.runtimeLookup.testForFixup != 0;
pResult->stubLookup.runtimeLookup.indirectFirstOffset = value.stubLookup.runtimeLookup.indirectFirstOffset != 0;
+ pResult->stubLookup.runtimeLookup.indirectSecondOffset = value.stubLookup.runtimeLookup.indirectSecondOffset != 0;
for (int i = 0; i < CORINFO_MAXINDIRECTIONS; i++)
pResult->stubLookup.runtimeLookup.offsets[i] = (SIZE_T)value.stubLookup.runtimeLookup.offsets[i];
}
DWORD testForFixup;
DWORDLONG offsets[CORINFO_MAXINDIRECTIONS];
DWORD indirectFirstOffset;
+ DWORD indirectSecondOffset;
};
struct Agnostic_CORINFO_LOOKUP
{
runtimeLookup.testForNull = (DWORD)pLookup->testForNull;
runtimeLookup.testForFixup = (DWORD)pLookup->testForFixup;
runtimeLookup.indirectFirstOffset = (DWORD)pLookup->indirectFirstOffset;
+ runtimeLookup.indirectSecondOffset = (DWORD)pLookup->indirectSecondOffset;
for (int i = 0; i < CORINFO_MAXINDIRECTIONS; i++)
runtimeLookup.offsets[i] = (DWORDLONG)pLookup->offsets[i];
return runtimeLookup;
runtimeLookup.testForNull = lookup.testForNull != 0;
runtimeLookup.testForFixup = lookup.testForFixup != 0;
runtimeLookup.indirectFirstOffset = lookup.indirectFirstOffset != 0;
+ runtimeLookup.indirectSecondOffset = lookup.indirectSecondOffset != 0;
for (int i = 0; i < CORINFO_MAXINDIRECTIONS; i++)
runtimeLookup.offsets[i] = (size_t)lookup.offsets[i];
return CORINFO_RUNTIME_LOOKUP();
{
numDicts = (DWORD)CountDictionariesInClass(token, dependency->pImport);
}
- PTR_Dictionary dictionary( mt->GetPerInstInfo()[numDicts-1] );
+
+ TADDR base = dac_cast<TADDR>(&(mt->GetPerInstInfo()[numDicts-1]));
+
+ PTR_Dictionary dictionary( MethodTable::PerInstInfoElem_t::GetValueAtPtr(base) );
unsigned numArgs = mt->GetNumGenericArgs();
DictionaryToArgString( dictionary, numArgs, buf );
GenericsDictInfo, METHODTABLES);
DisplayEndStructure( METHODTABLES ); //GenericsDictInfo
-
- DPTR(PTR_Dictionary) perInstInfo = mt->GetPerInstInfo();
+ DPTR(MethodTable::PerInstInfoElem_t) perInstInfo = mt->GetPerInstInfo();
DisplayStartStructure( "PerInstInfo",
DPtrToPreferredAddr(perInstInfo),
// 1 means that value stored at first offset (offsets[0]) from pointer is offset1, and the next pointer is
// stored at pointer+offsets[0]+offset1.
bool indirectFirstOffset;
+
+ // If set, second offset is indirect.
+ // 0 means that value stored at second offset (offsets[1]) from pointer is next pointer, to which the next offset
+ // (offsets[2]) is added and so on.
+ // 1 means that value stored at second offset (offsets[1]) from pointer is offset2, and the next pointer is
+ // stored at pointer+offsets[1]+offset2.
+ bool indirectSecondOffset;
} ;
// Result of calling embedGenericHandle
// Applied repeated indirections
for (WORD i = 0; i < pRuntimeLookup->indirections; i++)
{
- if (i == 1 && pRuntimeLookup->indirectFirstOffset)
+ if ((i == 1 && pRuntimeLookup->indirectFirstOffset) || (i == 2 && pRuntimeLookup->indirectSecondOffset))
{
indOffTree = impCloneExpr(slotPtrTree, &slotPtrTree, NO_CLASS_HANDLE, (unsigned)CHECK_SPILL_ALL,
- nullptr DEBUGARG("impRuntimeLookup indirectFirstOffset"));
+ nullptr DEBUGARG("impRuntimeLookup indirectOffset"));
}
if (i != 0)
slotPtrTree->gtFlags |= GTF_IND_INVARIANT;
}
- if (i == 1 && pRuntimeLookup->indirectFirstOffset)
+ if ((i == 1 && pRuntimeLookup->indirectFirstOffset) || (i == 2 && pRuntimeLookup->indirectSecondOffset))
{
slotPtrTree = gtNewOperNode(GT_ADD, TYP_I_IMPL, indOffTree, slotPtrTree);
}
{
if (pMT->HasPerInstInfo())
{
- Dictionary ** pPerInstInfo = pMT->GetPerInstInfo();
+ DPTR(MethodTable::PerInstInfoElem_t) pPerInstInfo = pMT->GetPerInstInfo();
BOOL fIsEagerBound = pMT->CanEagerBindToParentDictionaries(image, NULL);
if (fIsEagerBound)
{
- image->PlaceInternedStructureForAddress(pPerInstInfo, CORCOMPILE_SECTION_READONLY_SHARED_HOT, CORCOMPILE_SECTION_READONLY_HOT);
+ if (MethodTable::PerInstInfoElem_t::isRelative)
+ {
+ image->PlaceStructureForAddress(pPerInstInfo, CORCOMPILE_SECTION_READONLY_HOT);
+ }
+ else
+ {
+ image->PlaceInternedStructureForAddress(pPerInstInfo, CORCOMPILE_SECTION_READONLY_SHARED_HOT, CORCOMPILE_SECTION_READONLY_HOT);
+ }
}
else
{
DWORD nDicts = pParentMT->GetNumDicts();
for (DWORD iDict = 0; iDict < nDicts; iDict++)
{
- if (pMT->GetPerInstInfo()[iDict] != pParentMT->GetPerInstInfo()[iDict])
- *EnsureWritablePages(&pMT->GetPerInstInfo()[iDict]) = pParentMT->GetPerInstInfo()[iDict];
+ if (pMT->GetPerInstInfo()[iDict].GetValueMaybeNull() != pParentMT->GetPerInstInfo()[iDict].GetValueMaybeNull())
+ {
+ EnsureWritablePages(&pMT->GetPerInstInfo()[iDict]);
+ pMT->GetPerInstInfo()[iDict].SetValueMaybeNull(pParentMT->GetPerInstInfo()[iDict].GetValueMaybeNull());
+ }
}
}
}
// MethodTable is expected to be normalized
- _ASSERTE(pDictionary == pMT->GetPerInstInfo()[dictionaryIndex]);
+ _ASSERTE(pDictionary == pMT->GetPerInstInfo()[dictionaryIndex].GetValueMaybeNull());
}
else
{
_ASSERTE(pOldMT->HasPerInstInfo());
// Fill in per-inst map pointer (which points to the array of generic dictionary pointers)
- pMT->SetPerInstInfo ((Dictionary**) (pMemory + cbMT + cbOptional + cbIMap + sizeof(GenericsDictInfo)));
+ pMT->SetPerInstInfo((MethodTable::PerInstInfoElem_t *) (pMemory + cbMT + cbOptional + cbIMap + sizeof(GenericsDictInfo)));
_ASSERTE(FitsIn<WORD>(pOldMT->GetNumDicts()));
_ASSERTE(FitsIn<WORD>(pOldMT->GetNumGenericArgs()));
pMT->SetDictInfo(static_cast<WORD>(pOldMT->GetNumDicts()), static_cast<WORD>(pOldMT->GetNumGenericArgs()));
// The others are filled in by LoadExactParents which copied down any inherited generic
// dictionary pointers.
Dictionary * pDict = (Dictionary*) (pMemory + cbMT + cbOptional + cbIMap + cbPerInst);
- *(pMT->GetPerInstInfo() + (pOldMT->GetNumDicts()-1)) = pDict;
+ MethodTable::PerInstInfoElem_t *pPInstInfo = (MethodTable::PerInstInfoElem_t *) (pMT->GetPerInstInfo() + (pOldMT->GetNumDicts()-1));
+ pPInstInfo->SetValueMaybeNull(pDict);
// Fill in the instantiation section of the generic dictionary. The remainder of the
// generic dictionary will be zeroed, which is the correct initial state.
pResult->signature = NULL;
pResult->indirectFirstOffset = 0;
+ pResult->indirectSecondOffset = 0;
// Unless we decide otherwise, just do the lookup via a helper function
pResult->indirections = CORINFO_USEHELPER;
IfFailThrow(sigptr.GetData(&data));
pResult->offsets[2] = sizeof(TypeHandle) * data;
+ if (MethodTable::IsPerInstInfoRelative())
+ {
+ pResult->indirectFirstOffset = 1;
+ pResult->indirectSecondOffset = 1;
+ }
+
return;
}
else if (type == ELEMENT_TYPE_GENERICINST &&
// Next indirect through the dictionary appropriate to this instantiated type
pResult->offsets[1] = sizeof(TypeHandle*) * (pContextMT->GetNumDicts() - 1);
+
+ if (MethodTable::IsPerInstInfoRelative())
+ {
+ pResult->indirectFirstOffset = 1;
+ pResult->indirectSecondOffset = 1;
+ }
}
}
}
ZapStoredStructure * pPerInstInfoNode;
if (CanEagerBindToParentDictionaries(image, NULL))
{
- pPerInstInfoNode = image->StoreInternedStructure((BYTE *)GetPerInstInfo() - sizeof(GenericsDictInfo), GetPerInstInfoSize() + sizeof(GenericsDictInfo), DataImage::ITEM_DICTIONARY);
+ if (PerInstInfoElem_t::isRelative)
+ {
+ pPerInstInfoNode = image->StoreStructure((BYTE *)GetPerInstInfo() - sizeof(GenericsDictInfo), GetPerInstInfoSize() + sizeof(GenericsDictInfo), DataImage::ITEM_DICTIONARY);
+ }
+ else
+ {
+ pPerInstInfoNode = image->StoreInternedStructure((BYTE *)GetPerInstInfo() - sizeof(GenericsDictInfo), GetPerInstInfoSize() + sizeof(GenericsDictInfo), DataImage::ITEM_DICTIONARY);
+ }
}
else
{
// target module. Thus we want to call CanEagerBindToMethodTable
// to check we can hardbind to the containing structure.
static
-void HardBindOrClearDictionaryPointer(DataImage *image, MethodTable *pMT, void * p, SSIZE_T offset)
+void HardBindOrClearDictionaryPointer(DataImage *image, MethodTable *pMT, void * p, SSIZE_T offset, bool isRelative)
{
WRAPPER_NO_CONTRACT;
if (image->CanEagerBindToMethodTable(pMT) &&
image->CanHardBindToZapModule(pMT->GetLoaderModule()))
{
- image->FixupPointerField(p, offset);
+ if (isRelative)
+ {
+ image->FixupRelativePointerField(p, offset);
+ }
+ else
+ {
+ image->FixupPointerField(p, offset);
+ }
}
else
{
if (HasPerInstInfo())
{
// Fixup the pointer to the per-inst table
- image->FixupPointerField(this, offsetof(MethodTable, m_pPerInstInfo));
+ image->FixupPlainOrRelativePointerField(this, &MethodTable::m_pPerInstInfo);
for (MethodTable *pChain = this; pChain != NULL; pChain = pChain->GetParentMethodTable())
{
// We special-case the dictionary for this method table because we must always
// hard bind to it even if it's not in its preferred zap module
+ size_t sizeDict = sizeof(PerInstInfoElem_t);
+
if (pChain == this)
- image->FixupPointerField(GetPerInstInfo(), dictNum * sizeof(Dictionary *));
+ {
+ if (PerInstInfoElem_t::isRelative)
+ {
+ image->FixupRelativePointerField(GetPerInstInfo(), dictNum * sizeDict);
+ }
+ else
+ {
+ image->FixupPointerField(GetPerInstInfo(), dictNum * sizeDict);
+ }
+ }
else
- HardBindOrClearDictionaryPointer(image, pChain, GetPerInstInfo(), dictNum * sizeof(Dictionary *));
+ {
+ HardBindOrClearDictionaryPointer(image, pChain, GetPerInstInfo(), dictNum * sizeDict, PerInstInfoElem_t::isRelative);
+ }
}
}
}
//==========================================================================================
// Return a pointer to the dictionary for an instantiated type
// Return NULL if not instantiated
-Dictionary* MethodTable::GetDictionary()
+PTR_Dictionary MethodTable::GetDictionary()
{
LIMITED_METHOD_DAC_CONTRACT;
{
// The instantiation for this class is stored in the type slots table
// *after* any inherited slots
- return GetPerInstInfo()[GetNumDicts()-1];
+ TADDR base = dac_cast<TADDR>(&(GetPerInstInfo()[GetNumDicts()-1]));
+ return PerInstInfoElem_t::GetValueMaybeNullAtPtr(base);
}
else
{
if (HasInstantiation())
{
PTR_GenericsDictInfo pDictInfo = GetGenericsDictInfo();
- return Instantiation(GetPerInstInfo()[pDictInfo->m_wNumDicts-1]->GetInstantiation(), pDictInfo->m_wNumTyPars);
+ TADDR base = dac_cast<TADDR>(&(GetPerInstInfo()[pDictInfo->m_wNumDicts-1]));
+ return Instantiation(PerInstInfoElem_t::GetValueMaybeNullAtPtr(base)->GetInstantiation(), pDictInfo->m_wNumTyPars);
}
else
{
// must have a dictionary entry. On the other hand, for instantiations shared with Dict<string,double> the opposite holds.
//
+#if defined(PLATFORM_UNIX) && defined(_TARGET_ARM_)
+ typedef RelativePointer<PTR_Dictionary> PerInstInfoElem_t;
+ typedef RelativePointer<DPTR(PerInstInfoElem_t)> PerInstInfo_t;
+#else
+ typedef PlainPointer<PTR_Dictionary> PerInstInfoElem_t;
+ typedef PlainPointer<DPTR(PerInstInfoElem_t)> PerInstInfo_t;
+#endif
+
// Return a pointer to the per-instantiation information. See field itself for comments.
- DPTR(PTR_Dictionary) GetPerInstInfo()
+ DPTR(PerInstInfoElem_t) GetPerInstInfo()
{
LIMITED_METHOD_DAC_CONTRACT;
_ASSERTE(HasPerInstInfo());
- return dac_cast<DPTR(PTR_Dictionary)>(m_pMultipurposeSlot1);
+ return ReadPointer(this, &MethodTable::m_pPerInstInfo);
}
BOOL HasPerInstInfo()
{
return GetFlag(enum_flag_HasPerInstInfo) && !IsArray();
}
#ifndef DACCESS_COMPILE
+ static inline bool IsPerInstInfoRelative()
+ {
+ LIMITED_METHOD_CONTRACT;
+ return decltype(m_pPerInstInfo)::isRelative;
+ }
static inline DWORD GetOffsetOfPerInstInfo()
{
LIMITED_METHOD_CONTRACT;
return offsetof(MethodTable, m_pPerInstInfo);
}
- void SetPerInstInfo(Dictionary** pPerInstInfo)
+ void SetPerInstInfo(PerInstInfoElem_t *pPerInstInfo)
{
LIMITED_METHOD_CONTRACT;
- m_pPerInstInfo = pPerInstInfo;
+ m_pPerInstInfo.SetValue(pPerInstInfo);
}
void SetDictInfo(WORD numDicts, WORD numTyPars)
{
// Get a pointer to the dictionary for this instantiated type
// (The instantiation is stored in the initial slots of the dictionary)
// If not instantiated, return NULL
- Dictionary* GetDictionary();
+ PTR_Dictionary GetDictionary();
#ifdef FEATURE_PREJIT
//
union
{
- PTR_Dictionary * m_pPerInstInfo;
- TADDR m_ElementTypeHnd;
- TADDR m_pMultipurposeSlot1;
+ PerInstInfo_t m_pPerInstInfo;
+ TADDR m_ElementTypeHnd;
+ TADDR m_pMultipurposeSlot1;
};
public:
union
inline DWORD MethodTable::GetPerInstInfoSize()
{
LIMITED_METHOD_DAC_CONTRACT;
- return GetNumDicts() * sizeof(TypeHandle*);
+ return GetNumDicts() * sizeof(PerInstInfoElem_t);
}
//==========================================================================================
if (dwNumDicts != 0)
{
cbTotalSize += sizeof(GenericsDictInfo);
- cbTotalSize += S_SIZE_T(dwNumDicts) * S_SIZE_T(sizeof(TypeHandle*));
+ cbTotalSize += S_SIZE_T(dwNumDicts) * S_SIZE_T(sizeof(MethodTable::PerInstInfoElem_t));
cbTotalSize += cbInstAndDict;
}
// the dictionary pointers follow the interface map
if (dwNumDicts)
{
- Dictionary** pPerInstInfo = (Dictionary**)(pData + offsetOfInstAndDict.Value() + sizeof(GenericsDictInfo));
+ MethodTable::PerInstInfoElem_t *pPerInstInfo = (MethodTable::PerInstInfoElem_t *)(pData + offsetOfInstAndDict.Value() + sizeof(GenericsDictInfo));
pMT->SetPerInstInfo ( pPerInstInfo);
// Fill in the dictionary for this type, if it's instantiated
if (cbInstAndDict)
{
- *(pPerInstInfo + (dwNumDicts-1)) = (Dictionary*) (pPerInstInfo + dwNumDicts);
+ MethodTable::PerInstInfoElem_t *pPInstInfo = (MethodTable::PerInstInfoElem_t *)(pPerInstInfo + (dwNumDicts-1));
+ pPInstInfo->SetValueMaybeNull((Dictionary*) (pPerInstInfo + dwNumDicts));
}
}
pResult->signature = NULL;
pResult->indirectFirstOffset = 0;
+ pResult->indirectSecondOffset = 0;
pResult->indirections = CORINFO_USEHELPER;
IfFailThrow(sigptr.GetData(&data));
pResult->offsets[2] = sizeof(TypeHandle) * data;
+ if (MethodTable::IsPerInstInfoRelative())
+ {
+ pResult->indirectFirstOffset = 1;
+ pResult->indirectSecondOffset = 1;
+ }
+
return;
}
}
// Next indirect through the dictionary appropriate to this instantiated type
pResult->offsets[1] = sizeof(TypeHandle*) * (pContextMT->GetNumDicts() - 1);
+ if (MethodTable::IsPerInstInfoRelative())
+ {
+ pResult->indirectFirstOffset = 1;
+ pResult->indirectSecondOffset = 1;
+ }
+
*pDictionaryIndexAndSlot |= dictionarySlot;
}
}