| 1 | // Licensed to the .NET Foundation under one or more agreements. | 
|---|
| 2 | // The .NET Foundation licenses this file to you under the MIT license. | 
|---|
| 3 | // See the LICENSE file in the project root for more information. | 
|---|
| 4 | //***************************************************************************** | 
|---|
| 5 | // File: MethodIter.cpp | 
|---|
| 6 |  | 
|---|
| 7 | // Iterate through jitted instances of a method. | 
|---|
| 8 | //***************************************************************************** | 
|---|
| 9 |  | 
|---|
| 10 |  | 
|---|
| 11 | #include "common.h" | 
|---|
| 12 | #include "methoditer.h" | 
|---|
| 13 |  | 
|---|
| 14 |  | 
|---|
| 15 | //--------------------------------------------------------------------------------------- | 
|---|
| 16 | // | 
|---|
| 17 | // Iterates next MethodDesc. Updates the holder only if the assembly differs from the previous one. | 
|---|
| 18 | // Caller should not release (i.e. change) the holder explicitly between calls, otherwise collectible | 
|---|
| 19 | // assembly might be without a reference and get deallocated (even the native part). | 
|---|
| 20 | // | 
|---|
| 21 | BOOL LoadedMethodDescIterator::Next( | 
|---|
| 22 | CollectibleAssemblyHolder<DomainAssembly *> * pDomainAssemblyHolder) | 
|---|
| 23 | { | 
|---|
| 24 | CONTRACTL | 
|---|
| 25 | { | 
|---|
| 26 | NOTHROW; | 
|---|
| 27 | GC_NOTRIGGER; | 
|---|
| 28 | MODE_PREEMPTIVE; | 
|---|
| 29 | } | 
|---|
| 30 | CONTRACTL_END | 
|---|
| 31 |  | 
|---|
| 32 | if (!m_fFirstTime) | 
|---|
| 33 | { | 
|---|
| 34 | // This is the 2nd or more time we called Next(). | 
|---|
| 35 |  | 
|---|
| 36 | // If the method + type is not generic, then nothing more to iterate. | 
|---|
| 37 | if (!m_mainMD->HasClassOrMethodInstantiation()) | 
|---|
| 38 | { | 
|---|
| 39 | *pDomainAssemblyHolder = NULL; | 
|---|
| 40 | return FALSE; | 
|---|
| 41 | } | 
|---|
| 42 | goto ADVANCE_METHOD; | 
|---|
| 43 | } | 
|---|
| 44 |  | 
|---|
| 45 | m_fFirstTime = FALSE; | 
|---|
| 46 |  | 
|---|
| 47 | // This is the 1st time we've called Next(). must Initialize iterator | 
|---|
| 48 | if (m_mainMD == NULL) | 
|---|
| 49 | { | 
|---|
| 50 | m_mainMD = m_module->LookupMethodDef(m_md); | 
|---|
| 51 | } | 
|---|
| 52 |  | 
|---|
| 53 | // note m_mainMD should be sufficiently restored to allow us to get | 
|---|
| 54 | // at the method table, flags and token etc. | 
|---|
| 55 | if (m_mainMD == NULL) | 
|---|
| 56 | { | 
|---|
| 57 | *pDomainAssemblyHolder = NULL; | 
|---|
| 58 | return FALSE; | 
|---|
| 59 | } | 
|---|
| 60 |  | 
|---|
| 61 | // Needs to work w/ non-generic methods too. | 
|---|
| 62 | if (!m_mainMD->HasClassOrMethodInstantiation()) | 
|---|
| 63 | { | 
|---|
| 64 | *pDomainAssemblyHolder = NULL; | 
|---|
| 65 | return TRUE; | 
|---|
| 66 | } | 
|---|
| 67 |  | 
|---|
| 68 | m_assemIterator = m_pAppDomain->IterateAssembliesEx(m_assemIterationFlags); | 
|---|
| 69 |  | 
|---|
| 70 | ADVANCE_ASSEMBLY: | 
|---|
| 71 | if  (!m_assemIterator.Next(pDomainAssemblyHolder)) | 
|---|
| 72 | { | 
|---|
| 73 | _ASSERTE(*pDomainAssemblyHolder == NULL); | 
|---|
| 74 | return FALSE; | 
|---|
| 75 | } | 
|---|
| 76 |  | 
|---|
| 77 | #ifdef _DEBUG | 
|---|
| 78 | dbg_m_pDomainAssembly = *pDomainAssemblyHolder; | 
|---|
| 79 | #endif //_DEBUG | 
|---|
| 80 |  | 
|---|
| 81 | m_moduleIterator = (*pDomainAssemblyHolder)->IterateModules(m_moduleIterationFlags); | 
|---|
| 82 |  | 
|---|
| 83 | ADVANCE_MODULE: | 
|---|
| 84 | if  (!m_moduleIterator.Next()) | 
|---|
| 85 | goto ADVANCE_ASSEMBLY; | 
|---|
| 86 |  | 
|---|
| 87 | if (GetCurrentModule()->IsResource()) | 
|---|
| 88 | goto ADVANCE_MODULE; | 
|---|
| 89 |  | 
|---|
| 90 | if (m_mainMD->HasClassInstantiation()) | 
|---|
| 91 | { | 
|---|
| 92 | m_typeIterator.Reset(); | 
|---|
| 93 | } | 
|---|
| 94 | else | 
|---|
| 95 | { | 
|---|
| 96 | m_startedNonGenericType = FALSE; | 
|---|
| 97 | } | 
|---|
| 98 |  | 
|---|
| 99 | ADVANCE_TYPE: | 
|---|
| 100 | if (m_mainMD->HasClassInstantiation()) | 
|---|
| 101 | { | 
|---|
| 102 | if (!GetCurrentModule()->GetAvailableParamTypes()->FindNext(&m_typeIterator, &m_typeIteratorEntry)) | 
|---|
| 103 | goto ADVANCE_MODULE; | 
|---|
| 104 | if (CORCOMPILE_IS_POINTER_TAGGED(m_typeIteratorEntry->GetTypeHandle().AsTAddr())) | 
|---|
| 105 | goto ADVANCE_TYPE; | 
|---|
| 106 |  | 
|---|
| 107 | //if (m_typeIteratorEntry->data != TypeHandle(m_mainMD->GetMethodTable())) | 
|---|
| 108 | //    goto ADVANCE_TYPE; | 
|---|
| 109 |  | 
|---|
| 110 | // When looking up the AvailableParamTypes table we have to be really careful since | 
|---|
| 111 | // the entries may be unrestored, and may have all sorts of encoded tokens in them. | 
|---|
| 112 | // Similar logic occurs in the Lookup function for that table.  We will clean this | 
|---|
| 113 | // up in Whidbey Beta2. | 
|---|
| 114 | TypeHandle th = m_typeIteratorEntry->GetTypeHandle(); | 
|---|
| 115 |  | 
|---|
| 116 | if (th.IsEncodedFixup()) | 
|---|
| 117 | goto ADVANCE_TYPE; | 
|---|
| 118 |  | 
|---|
| 119 | if (th.IsTypeDesc()) | 
|---|
| 120 | goto ADVANCE_TYPE; | 
|---|
| 121 |  | 
|---|
| 122 | MethodTable *pMT = th.AsMethodTable(); | 
|---|
| 123 |  | 
|---|
| 124 | if (!pMT->IsRestored()) | 
|---|
| 125 | goto ADVANCE_TYPE; | 
|---|
| 126 |  | 
|---|
| 127 | // Check the class token | 
|---|
| 128 | if (pMT->GetTypeDefRid() != m_mainMD->GetMethodTable()->GetTypeDefRid()) | 
|---|
| 129 | goto ADVANCE_TYPE; | 
|---|
| 130 |  | 
|---|
| 131 | // Check the module is correct | 
|---|
| 132 | if (pMT->GetModule() != m_module) | 
|---|
| 133 | goto ADVANCE_TYPE; | 
|---|
| 134 | } | 
|---|
| 135 | else if (m_startedNonGenericType) | 
|---|
| 136 | { | 
|---|
| 137 | goto ADVANCE_MODULE; | 
|---|
| 138 | } | 
|---|
| 139 | else | 
|---|
| 140 | { | 
|---|
| 141 | m_startedNonGenericType = TRUE; | 
|---|
| 142 | } | 
|---|
| 143 |  | 
|---|
| 144 | if (m_mainMD->HasMethodInstantiation()) | 
|---|
| 145 | { | 
|---|
| 146 | m_methodIterator.Reset(); | 
|---|
| 147 | } | 
|---|
| 148 | else | 
|---|
| 149 | { | 
|---|
| 150 | m_startedNonGenericMethod = FALSE; | 
|---|
| 151 | } | 
|---|
| 152 |  | 
|---|
| 153 | ADVANCE_METHOD: | 
|---|
| 154 | if (m_mainMD->HasMethodInstantiation()) | 
|---|
| 155 | { | 
|---|
| 156 | if (!GetCurrentModule()->GetInstMethodHashTable()->FindNext(&m_methodIterator, &m_methodIteratorEntry)) | 
|---|
| 157 | goto ADVANCE_TYPE; | 
|---|
| 158 | if (CORCOMPILE_IS_POINTER_TAGGED(dac_cast<TADDR>(m_methodIteratorEntry->GetMethod()))) | 
|---|
| 159 | goto ADVANCE_METHOD; | 
|---|
| 160 | if (!m_methodIteratorEntry->GetMethod()->IsRestored()) | 
|---|
| 161 | goto ADVANCE_METHOD; | 
|---|
| 162 | if (m_methodIteratorEntry->GetMethod()->GetModule() != m_module) | 
|---|
| 163 | goto ADVANCE_METHOD; | 
|---|
| 164 | if (m_methodIteratorEntry->GetMethod()->GetMemberDef() != m_md) | 
|---|
| 165 | goto ADVANCE_METHOD; | 
|---|
| 166 | } | 
|---|
| 167 | else if (m_startedNonGenericMethod) | 
|---|
| 168 | { | 
|---|
| 169 | goto ADVANCE_TYPE; | 
|---|
| 170 | } | 
|---|
| 171 | else | 
|---|
| 172 | { | 
|---|
| 173 | m_startedNonGenericMethod = TRUE; | 
|---|
| 174 | } | 
|---|
| 175 |  | 
|---|
| 176 | // Note: We don't need to keep the assembly alive in DAC - see code:CollectibleAssemblyHolder#CAH_DAC | 
|---|
| 177 | #ifndef DACCESS_COMPILE | 
|---|
| 178 | _ASSERTE_MSG( | 
|---|
| 179 | *pDomainAssemblyHolder == dbg_m_pDomainAssembly, | 
|---|
| 180 | "Caller probably modified the assembly holder, which he shouldn't - see method comment."); | 
|---|
| 181 | #endif //DACCESS_COMPILE | 
|---|
| 182 |  | 
|---|
| 183 | return TRUE; | 
|---|
| 184 | } // LoadedMethodDescIterator::Next | 
|---|
| 185 |  | 
|---|
| 186 |  | 
|---|
| 187 | Module * LoadedMethodDescIterator::GetCurrentModule() | 
|---|
| 188 | { | 
|---|
| 189 | CONTRACTL | 
|---|
| 190 | { | 
|---|
| 191 | NOTHROW; | 
|---|
| 192 | GC_NOTRIGGER; | 
|---|
| 193 | MODE_ANY; | 
|---|
| 194 | } | 
|---|
| 195 | CONTRACTL_END | 
|---|
| 196 |  | 
|---|
| 197 | return m_moduleIterator.GetLoadedModule(); | 
|---|
| 198 | } | 
|---|
| 199 |  | 
|---|
| 200 | MethodDesc *LoadedMethodDescIterator::Current() | 
|---|
| 201 | { | 
|---|
| 202 | CONTRACTL | 
|---|
| 203 | { | 
|---|
| 204 | NOTHROW; | 
|---|
| 205 | GC_NOTRIGGER; | 
|---|
| 206 | PRECONDITION(CheckPointer(m_mainMD)); | 
|---|
| 207 | } | 
|---|
| 208 | CONTRACTL_END | 
|---|
| 209 |  | 
|---|
| 210 |  | 
|---|
| 211 | if (m_mainMD->HasMethodInstantiation()) | 
|---|
| 212 | { | 
|---|
| 213 | _ASSERTE(m_methodIteratorEntry); | 
|---|
| 214 | return m_methodIteratorEntry->GetMethod(); | 
|---|
| 215 | } | 
|---|
| 216 |  | 
|---|
| 217 | if (!m_mainMD->HasClassInstantiation()) | 
|---|
| 218 | { | 
|---|
| 219 | // No Method or Class instantiation,then it's not generic. | 
|---|
| 220 | return m_mainMD; | 
|---|
| 221 | } | 
|---|
| 222 |  | 
|---|
| 223 | MethodTable *pMT = m_typeIteratorEntry->GetTypeHandle().GetMethodTable(); | 
|---|
| 224 | PREFIX_ASSUME(pMT != NULL); | 
|---|
| 225 | _ASSERTE(pMT); | 
|---|
| 226 |  | 
|---|
| 227 | return pMT->GetMethodDescForSlot(m_mainMD->GetSlot()); | 
|---|
| 228 | } | 
|---|
| 229 |  | 
|---|
| 230 | // Initialize the iterator. It will cover generics + prejitted; | 
|---|
| 231 | // but it is not EnC aware. | 
|---|
| 232 | void | 
|---|
| 233 | LoadedMethodDescIterator::Start( | 
|---|
| 234 | AppDomain * pAppDomain, | 
|---|
| 235 | Module *pModule, | 
|---|
| 236 | mdMethodDef md, | 
|---|
| 237 | AssemblyIterationFlags assemblyIterationFlags, | 
|---|
| 238 | ModuleIterationOption moduleIterationFlags) | 
|---|
| 239 | { | 
|---|
| 240 | CONTRACTL | 
|---|
| 241 | { | 
|---|
| 242 | NOTHROW; | 
|---|
| 243 | GC_NOTRIGGER; | 
|---|
| 244 | PRECONDITION(CheckPointer(pModule)); | 
|---|
| 245 | PRECONDITION(CheckPointer(pAppDomain, NULL_OK)); | 
|---|
| 246 | } | 
|---|
| 247 | CONTRACTL_END; | 
|---|
| 248 |  | 
|---|
| 249 | m_assemIterationFlags = assemblyIterationFlags; | 
|---|
| 250 | m_moduleIterationFlags = moduleIterationFlags; | 
|---|
| 251 | m_mainMD = NULL; | 
|---|
| 252 | m_module = pModule; | 
|---|
| 253 | m_md = md; | 
|---|
| 254 | m_pAppDomain = pAppDomain; | 
|---|
| 255 | m_fFirstTime = TRUE; | 
|---|
| 256 |  | 
|---|
| 257 | _ASSERTE(pAppDomain != NULL); | 
|---|
| 258 | _ASSERTE(TypeFromToken(m_md) == mdtMethodDef); | 
|---|
| 259 | } | 
|---|
| 260 |  | 
|---|
| 261 | // This is special init for DAC only | 
|---|
| 262 | // @TODO:: change it to dac compile only. | 
|---|
| 263 | void | 
|---|
| 264 | LoadedMethodDescIterator::Start( | 
|---|
| 265 | AppDomain     *pAppDomain, | 
|---|
| 266 | Module          *pModule, | 
|---|
| 267 | mdMethodDef     md, | 
|---|
| 268 | MethodDesc      *pMethodDesc) | 
|---|
| 269 | { | 
|---|
| 270 | Start(pAppDomain, pModule, md); | 
|---|
| 271 | m_mainMD = pMethodDesc; | 
|---|
| 272 | } | 
|---|
| 273 |  | 
|---|
| 274 | LoadedMethodDescIterator::LoadedMethodDescIterator(void) | 
|---|
| 275 | { | 
|---|
| 276 | LIMITED_METHOD_CONTRACT; | 
|---|
| 277 | m_mainMD = NULL; | 
|---|
| 278 | m_module = NULL; | 
|---|
| 279 | m_md = mdTokenNil; | 
|---|
| 280 | m_pAppDomain = NULL; | 
|---|
| 281 | } | 
|---|
| 282 |  | 
|---|