diff options
Diffstat (limited to 'src/vm/readytoruninfo.cpp')
-rw-r--r-- | src/vm/readytoruninfo.cpp | 203 |
1 files changed, 134 insertions, 69 deletions
diff --git a/src/vm/readytoruninfo.cpp b/src/vm/readytoruninfo.cpp index ada502a417..3dd8fd3197 100644 --- a/src/vm/readytoruninfo.cpp +++ b/src/vm/readytoruninfo.cpp @@ -13,6 +13,8 @@ #include "dbginterface.h" #include "compile.h" +#include "versionresilienthashcode.h" +#include "typehashingalgorithms.h" using namespace NativeFormat; @@ -99,84 +101,62 @@ BOOL ReadyToRunInfo::TryLookupTypeTokenFromName(NameHandle *pName, mdToken * pFo // // Compute the hashcode of the type (hashcode based on type name and namespace name) // - DWORD dwHashCode = 0; - { - if (pName->GetTypeToken() == mdtBaseType) - { - // Name-based lookups (ex: Type.GetType()). - - pszName = pName->GetName(); - pszNameSpace = ""; - - if (pName->GetNameSpace() != NULL) - { - pszNameSpace = pName->GetNameSpace(); - } - else - { - LPCUTF8 p; - CQuickBytes szNamespace; - - if ((p = ns::FindSep(pszName)) != NULL) - { - SIZE_T d = p - pszName; + int dwHashCode = 0; - FAULT_NOT_FATAL(); - pszNameSpace = szNamespace.SetStringNoThrow(pszName, d); + if (pName->GetTypeToken() == mdtBaseType || pName->GetTypeModule() == NULL) + { + // Name-based lookups (ex: Type.GetType()). - if (pszNameSpace == NULL) - return FALSE; + pszName = pName->GetName(); + pszNameSpace = ""; - pszName = (p + 1); - } - } - - _ASSERT(pszNameSpace != NULL); - dwHashCode = ((dwHashCode << 5) + dwHashCode) ^ HashStringA(pszName); - dwHashCode = ((dwHashCode << 5) + dwHashCode) ^ HashStringA(pszNameSpace); + if (pName->GetNameSpace() != NULL) + { + pszNameSpace = pName->GetNameSpace(); + } + else + { + LPCUTF8 p; + CQuickBytes szNamespace; - // Bucket is not 'null' for a nested type, and it will have information about the nested type's encloser - if (!pName->GetBucket().IsNull()) + if ((p = ns::FindSep(pszName)) != NULL) { - // Must be a token based bucket that we found earlier in the R2R types hashtable - _ASSERT(pName->GetBucket().GetEntryType() == HashedTypeEntry::IsHashedTokenEntry); - - const HashedTypeEntry::TokenTypeEntry& tokenBasedEncloser = pName->GetBucket().GetTokenBasedEntryValue(); + SIZE_T d = p - pszName; - // Token must be a typedef token that we previously resolved (we shouldn't get here with an exported type token) - _ASSERT(TypeFromToken(tokenBasedEncloser.m_TypeToken) == mdtTypeDef); + FAULT_NOT_FATAL(); + pszNameSpace = szNamespace.SetStringNoThrow(pszName, d); - mdToken mdCurrentTypeToken = tokenBasedEncloser.m_TypeToken; - do - { - LPCUTF8 pszNameTemp; - LPCUTF8 pszNameSpaceTemp; - if (!GetTypeNameFromToken(tokenBasedEncloser.m_pModule->GetMDImport(), mdCurrentTypeToken, &pszNameTemp, &pszNameSpaceTemp)) - return FALSE; - - dwHashCode = ((dwHashCode << 5) + dwHashCode) ^ HashStringA(pszNameTemp); - dwHashCode = ((dwHashCode << 5) + dwHashCode) ^ HashStringA(pszNameSpaceTemp == NULL ? "" : pszNameSpaceTemp); - - } while (GetEnclosingToken(tokenBasedEncloser.m_pModule->GetMDImport(), mdCurrentTypeToken, &mdCurrentTypeToken)); + if (pszNameSpace == NULL) + return FALSE; + pszName = (p + 1); } } - else + + _ASSERT(pszNameSpace != NULL); + dwHashCode ^= ComputeNameHashCode(pszNameSpace, pszName); + + // Bucket is not 'null' for a nested type, and it will have information about the nested type's encloser + if (!pName->GetBucket().IsNull()) { - // Token based lookups (ex: tokens from IL code) + // Must be a token based bucket that we found earlier in the R2R types hashtable + _ASSERT(pName->GetBucket().GetEntryType() == HashedTypeEntry::IsHashedTokenEntry); - mdToken mdCurrentTypeToken = pName->GetTypeToken(); - do - { - if (!GetTypeNameFromToken(pName->GetTypeModule()->GetMDImport(), mdCurrentTypeToken, &pszName, &pszNameSpace)) - return FALSE; + const HashedTypeEntry::TokenTypeEntry& tokenBasedEncloser = pName->GetBucket().GetTokenBasedEntryValue(); - dwHashCode = ((dwHashCode << 5) + dwHashCode) ^ HashStringA(pszName); - dwHashCode = ((dwHashCode << 5) + dwHashCode) ^ HashStringA(pszNameSpace == NULL ? "" : pszNameSpace); + // Token must be a typedef token that we previously resolved (we shouldn't get here with an exported type token) + _ASSERT(TypeFromToken(tokenBasedEncloser.m_TypeToken) == mdtTypeDef); - } while (GetEnclosingToken(pName->GetTypeModule()->GetMDImport(), mdCurrentTypeToken, &mdCurrentTypeToken)); + mdToken mdCurrentTypeToken = tokenBasedEncloser.m_TypeToken; + dwHashCode ^= GetVersionResilientTypeHashCode(tokenBasedEncloser.m_pModule->GetMDImport(), mdCurrentTypeToken); } } + else + { + // Token based lookups (ex: tokens from IL code) + + dwHashCode = GetVersionResilientTypeHashCode(pName->GetTypeModule()->GetMDImport(), pName->GetTypeToken()); + } // @@ -191,7 +171,7 @@ BOOL ReadyToRunInfo::TryLookupTypeTokenFromName(NameHandle *pName, mdToken * pFo mdToken cl = ((ridAndFlag & 1) ? ((ridAndFlag >> 1) | mdtExportedType) : ((ridAndFlag >> 1) | mdtTypeDef)); _ASSERT(RidFromToken(cl) != 0); - if (pName->GetTypeToken() == mdtBaseType) + if (pName->GetTypeToken() == mdtBaseType || pName->GetTypeModule() == NULL) { // Compare type name and namespace name LPCUTF8 pszFoundName; @@ -456,6 +436,13 @@ ReadyToRunInfo::ReadyToRunInfo(Module * pModule, PEImageLayout * pLayout, READYT m_methodDefEntryPoints = NativeArray(&m_nativeReader, pEntryPointsDir->VirtualAddress); } + IMAGE_DATA_DIRECTORY * pinstMethodsDir = FindSection(READYTORUN_SECTION_INSTANCE_METHOD_ENTRYPOINTS); + if (pinstMethodsDir != NULL) + { + NativeParser parser = NativeParser(&m_nativeReader, pinstMethodsDir->VirtualAddress); + m_instMethodEntryPoints = NativeHashtable(parser); + } + IMAGE_DATA_DIRECTORY * pAvailableTypesDir = FindSection(READYTORUN_SECTION_AVAILABLE_TYPES); if (pAvailableTypesDir != NULL) { @@ -469,13 +456,61 @@ ReadyToRunInfo::ReadyToRunInfo(Module * pModule, PEImageLayout * pLayout, READYT } } -PCODE ReadyToRunInfo::GetEntryPoint(MethodDesc * pMD, BOOL fFixups /*=TRUE*/) +static bool SigMatchesMethodDesc(MethodDesc* pMD, SigPointer &sig, Module * pModule) { STANDARD_VM_CONTRACT; - // READYTORUN: FUTURE: Support for generics - if (pMD->HasClassOrMethodInstantiation()) - return NULL; + ZapSig::Context zapSigContext(pModule, (void *)pModule, ZapSig::NormalTokens); + ZapSig::Context * pZapSigContext = &zapSigContext; + + DWORD methodFlags; + IfFailThrow(sig.GetData(&methodFlags)); + + if (methodFlags & ENCODE_METHOD_SIG_OwnerType) + { + PCCOR_SIGNATURE pSigType; + DWORD cbSigType; + sig.GetSignature(&pSigType, &cbSigType); + if (!ZapSig::CompareSignatureToTypeHandle(pSigType, pModule, TypeHandle(pMD->GetMethodTable()), pZapSigContext)) + return false; + + IfFailThrow(sig.SkipExactlyOne()); + } + + _ASSERTE((methodFlags & ENCODE_METHOD_SIG_SlotInsteadOfToken) == 0); + _ASSERTE((methodFlags & ENCODE_METHOD_SIG_MemberRefToken) == 0); + + RID rid; + IfFailThrow(sig.GetData(&rid)); + if (RidFromToken(pMD->GetMemberDef()) != rid) + return false; + + if (methodFlags & ENCODE_METHOD_SIG_MethodInstantiation) + { + DWORD numGenericArgs; + IfFailThrow(sig.GetData(&numGenericArgs)); + Instantiation inst = pMD->GetMethodInstantiation(); + if (numGenericArgs != inst.GetNumArgs()) + return false; + + for (DWORD i = 0; i < numGenericArgs; i++) + { + PCCOR_SIGNATURE pSigArg; + DWORD cbSigArg; + sig.GetSignature(&pSigArg, &cbSigArg); + if (!ZapSig::CompareSignatureToTypeHandle(pSigArg, pModule, inst[i], pZapSigContext)) + return false; + + IfFailThrow(sig.SkipExactlyOne()); + } + } + + return true; +} + +PCODE ReadyToRunInfo::GetEntryPoint(MethodDesc * pMD, BOOL fFixups /*=TRUE*/) +{ + STANDARD_VM_CONTRACT; mdToken token = pMD->GetMemberDef(); int rid = RidFromToken(token); @@ -483,8 +518,38 @@ PCODE ReadyToRunInfo::GetEntryPoint(MethodDesc * pMD, BOOL fFixups /*=TRUE*/) return NULL; uint offset; - if (!m_methodDefEntryPoints.TryGetAt(rid - 1, &offset)) - return NULL; + if (pMD->HasClassOrMethodInstantiation()) + { + if (m_instMethodEntryPoints.IsNull()) + return NULL; + + NativeHashtable::Enumerator lookup = m_instMethodEntryPoints.Lookup(GetVersionResilientMethodHashCode(pMD)); + NativeParser entryParser; + offset = -1; + while (lookup.GetNext(entryParser)) + { + PCCOR_SIGNATURE pBlob = (PCCOR_SIGNATURE)entryParser.GetBlob(); + SigPointer sig(pBlob); + if (SigMatchesMethodDesc(pMD, sig, m_pModule)) + { + // Get the updated SigPointer location, so we can calculate the size of the blob, + // in order to skip the blob and find the entry point data. + PCCOR_SIGNATURE pSigNew; + DWORD cbSigNew; + sig.GetSignature(&pSigNew, &cbSigNew); + offset = entryParser.GetOffset() + (uint)(pSigNew - pBlob); + break; + } + } + + if (offset == -1) + return NULL; + } + else + { + if (!m_methodDefEntryPoints.TryGetAt(rid - 1, &offset)) + return NULL; + } uint id; offset = m_nativeReader.DecodeUnsigned(offset, &id); |