Skip to content
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions src/coreclr/vm/methodtable.h
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,11 @@ struct MethodTableAuxiliaryData
};
};

// Lazily initialized cache for the version-resilient hash code of this MethodTable.
// A stored value of 0 indicates the field hasn't been set yet.
// Placed here to fill the 4-byte alignment padding between m_dwFlags and m_pLoaderModule,
// so this field adds no extra size to the struct on 64-bit platforms.
int m_cachedVersionResilientHashCode;

PTR_Module m_pLoaderModule;
Comment thread
jkotas marked this conversation as resolved.

Expand Down
52 changes: 33 additions & 19 deletions src/coreclr/vm/versionresilienthashcode.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -110,38 +110,52 @@ int GetVersionResilientTypeHashCode(TypeHandle type)
{
STANDARD_VM_CONTRACT;

if (type.IsArray())
{
return ComputeArrayTypeHashCode(GetVersionResilientTypeHashCode(type.GetArrayElementTypeHandle()), type.GetRank());
}
else
if (!type.IsTypeDesc())
{
MethodTable *pMT = type.AsMethodTable();

_ASSERTE(!pMT->IsArray());
_ASSERTE(!IsNilToken(pMT->GetCl()));

LPCUTF8 szNamespace;
LPCUTF8 szName;
IfFailThrow(pMT->GetMDImport()->GetNameOfTypeDef(pMT->GetCl(), &szName, &szNamespace));
int hashcode = ComputeNameHashCode(szNamespace, szName);
_ASSERTE(pMT->IsArray() || !IsNilToken(pMT->GetCl()));

MethodTable *pMTEnclosing = pMT->LoadEnclosingMethodTable(CLASS_LOAD_APPROXPARENTS);
if (pMTEnclosing != NULL)
int cachedHashCode = VolatileLoadWithoutBarrier(&pMT->GetAuxiliaryData()->m_cachedVersionResilientHashCode);
if (cachedHashCode != 0)
{
hashcode = ComputeNestedTypeHashCode(GetVersionResilientTypeHashCode(TypeHandle(pMTEnclosing)), hashcode);
return cachedHashCode;
}

if (!pMT->IsGenericTypeDefinition() && pMT->HasInstantiation())
int hashcode;
if (pMT->IsArray())
{
return ComputeGenericInstanceHashCode(hashcode,
pMT->GetInstantiation().GetNumArgs(), pMT->GetInstantiation(), GetVersionResilientTypeHashCode);
hashcode = ComputeArrayTypeHashCode(GetVersionResilientTypeHashCode(type.GetArrayElementTypeHandle()), type.GetRank());
}
else
{
return hashcode;
LPCUTF8 szNamespace;
LPCUTF8 szName;
IfFailThrow(pMT->GetMDImport()->GetNameOfTypeDef(pMT->GetCl(), &szName, &szNamespace));
hashcode = ComputeNameHashCode(szNamespace, szName);

MethodTable *pMTEnclosing = pMT->LoadEnclosingMethodTable(CLASS_LOAD_APPROXPARENTS);
if (pMTEnclosing != NULL)
{
hashcode = ComputeNestedTypeHashCode(GetVersionResilientTypeHashCode(TypeHandle(pMTEnclosing)), hashcode);
}

if (!pMT->IsGenericTypeDefinition() && pMT->HasInstantiation())
{
hashcode = ComputeGenericInstanceHashCode(hashcode,
pMT->GetInstantiation().GetNumArgs(), pMT->GetInstantiation(), GetVersionResilientTypeHashCode);
}
}

// 0 is used as the sentinel "not yet cached" value, so only cache if non-zero.
// Types with a hash code of exactly 0 are extremely rare in practice; they will simply
// have their hash code recomputed on every call, which is still correct behavior.
if (hashcode != 0)
Comment thread
jkotas marked this conversation as resolved.
{
VolatileStore(&pMT->GetAuxiliaryDataForWrite()->m_cachedVersionResilientHashCode, hashcode);
}
Comment thread
jkotas marked this conversation as resolved.

return hashcode;
}
else
if (type.IsPointer())
Expand Down
Loading