Fix module override for recursive generic signatures (#24707)
[platform/upstream/coreclr.git] / src / vm / zapsig.cpp
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: zapsig.cpp
6 //
7 // Signature encoding for zapper (ngen)
8 //
9
10 // ===========================================================================
11
12
13 #include "common.h"
14 #include "zapsig.h"
15 #include "typedesc.h"
16 #include "compile.h"
17 #include "sigbuilder.h"
18
19 #ifndef DACCESS_COMPILE
20
21 BOOL ZapSig::GetSignatureForTypeDesc(TypeDesc * desc, SigBuilder * pSigBuilder)
22 {
23     CONTRACTL
24     {
25         THROWS;
26         GC_TRIGGERS;
27     }
28     CONTRACTL_END
29
30     CorElementType elemType = desc->GetInternalCorElementType();
31
32     if (elemType == ELEMENT_TYPE_VALUETYPE)
33     {
34         // convert to ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG so that the right
35         // thing will happen in code:SigPointer.GetTypeHandleThrowing
36         elemType = (CorElementType) ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG;
37     }
38     else if (elemType == ELEMENT_TYPE_VAR || elemType == ELEMENT_TYPE_MVAR)
39     {
40         // Enable encoding of type variables for NGen signature only. IBC toolchain is not aware of them yet.
41         if (context.externalTokens == ZapSig::NormalTokens)
42             elemType = (CorElementType) ELEMENT_TYPE_VAR_ZAPSIG;
43     }
44
45     pSigBuilder->AppendElementType(elemType);
46
47     if (desc->HasTypeParam())
48     {
49         if (!this->GetSignatureForTypeHandle(desc->GetTypeParam(), pSigBuilder))
50             return FALSE;
51
52         if (elemType == ELEMENT_TYPE_ARRAY)
53         {
54             ArrayTypeDesc *pArrayDesc = dac_cast<PTR_ArrayTypeDesc>(desc);
55             _ASSERTE(pArrayDesc->GetRank() != 0);
56             pSigBuilder->AppendData(pArrayDesc->GetRank());
57             pSigBuilder->AppendData(0);
58             pSigBuilder->AppendData(0);
59         }
60     }
61     else
62     {
63         switch ((DWORD)elemType)
64         {
65         case ELEMENT_TYPE_FNPTR:
66             {
67                 FnPtrTypeDesc *pTD = dac_cast<PTR_FnPtrTypeDesc>(desc);
68
69                 // Emit calling convention
70                 pSigBuilder->AppendByte(pTD->GetCallConv());
71
72                 // number of args
73                 unsigned numArgs = pTD->GetNumArgs();
74                 pSigBuilder->AppendData(numArgs);
75
76                 // return type and args
77                 TypeHandle *retAndArgTypes = pTD->GetRetAndArgTypesPointer();
78                 for (DWORD i = 0; i <= numArgs; i++)
79                 {
80                     TypeHandle th = retAndArgTypes[i];
81                     // This should be a consequence of the type key being restored
82                     CONSISTENCY_CHECK(!th.IsNull() && !th.IsEncodedFixup());
83                     if (!this->GetSignatureForTypeHandle(th, pSigBuilder))
84                         return FALSE;
85                 }
86             }
87             break;
88
89         case ELEMENT_TYPE_MVAR:
90             //                    _ASSERTE(!"Cannot encode ET_MVAR in a ZapSig");
91             return FALSE;
92
93         case ELEMENT_TYPE_VAR:
94             //                    _ASSERTE(!"Cannot encode ET_VAR in a ZapSig");
95             return FALSE;
96
97         case ELEMENT_TYPE_VAR_ZAPSIG:
98             {
99                 TypeVarTypeDesc * pTypeVarDesc = dac_cast<PTR_TypeVarTypeDesc>(desc);
100                 Module * pVarTypeModule = pTypeVarDesc->GetModule();
101                 if (pVarTypeModule != this->context.pInfoModule)
102                 {
103                     DWORD index = (*this->pfnEncodeModule)(this->context.pModuleContext, pVarTypeModule);
104
105                     if (index == ENCODE_MODULE_FAILED)
106                         return FALSE;
107
108                     // emit the ET_MODULE_ZAPSIG escape
109                     pSigBuilder->AppendElementType((CorElementType) ELEMENT_TYPE_MODULE_ZAPSIG);
110                     // emit the module index
111                     pSigBuilder->AppendData(index);
112                 }
113                 pSigBuilder->AppendData(RidFromToken(pTypeVarDesc->GetToken()));
114                 break;
115             }
116
117         default:
118             _ASSERTE(!"Bad type");
119             return FALSE;
120         }
121     }
122
123     return TRUE;
124 }
125
126
127 // Create a signature for a typeHandle 
128 // It can be decoded using MetaSig::GetTypeHandleThrowing
129 // The tokens are espressed relative to this->pInfoModule
130 // When handle.GetModule() != this->pInfoModule), we escape the signature
131 // with an ELEMENT_TYPE_MODULE_ZAPSIG <id-num> <token> to encode 
132 // a temporary change of module 
133 //
134 // Returns the number of characters written into the buffer.  
135 // If buffer and bufferMax are NULL, it returns the number of
136 // characters that would have been written.
137 // If the buffer isn't big enough it doesn't write past bufferMax
138 // A return value of 0 indidates a failure to encode the signature
139 //
140 BOOL ZapSig::GetSignatureForTypeHandle(TypeHandle      handle,
141                                        SigBuilder *    pSigBuilder)
142 {
143     CONTRACTL
144     {
145         THROWS;
146         GC_TRIGGERS;
147
148         PRECONDITION(CheckPointer(handle));
149         PRECONDITION(CheckPointer(this->context.pInfoModule));
150         PRECONDITION(!handle.HasUnrestoredTypeKey());
151         MODE_ANY;
152     }
153     CONTRACTL_END
154
155     if (handle.IsTypeDesc())
156         return GetSignatureForTypeDesc(handle.AsTypeDesc(), pSigBuilder);
157
158     MethodTable *pMT = handle.AsMethodTable();
159
160     // Can we encode the type using a short ET encoding?
161     // 
162     CorElementType elemType = TryEncodeUsingShortcut(pMT);
163     if (elemType != ELEMENT_TYPE_END)
164     {
165         _ASSERTE(pMT->IsTypicalTypeDefinition());
166
167         // Check for an array type and encode that we are dealing with a MethodTable representation
168         if (elemType == ELEMENT_TYPE_SZARRAY || elemType == ELEMENT_TYPE_ARRAY)
169         {
170             pSigBuilder->AppendElementType((CorElementType)ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG);
171             pSigBuilder->AppendElementType(elemType);
172
173             TypeHandle elementType = pMT->GetApproxArrayElementTypeHandle();
174             if (!this->GetSignatureForTypeHandle(elementType, pSigBuilder))
175                 return FALSE;
176
177             if (elemType == ELEMENT_TYPE_ARRAY)
178             {
179                 pSigBuilder->AppendData(pMT->GetRank());
180                 pSigBuilder->AppendData(0);
181                 pSigBuilder->AppendData(0);
182             }
183         }
184         else
185         {
186             pSigBuilder->AppendElementType(elemType);
187         }
188         
189         return TRUE;
190     }
191
192     // We could not encode the type using a short encoding  
193     // and we have a handle that represents a Class or ValueType
194
195     // We may need to emit an out-of-module escape sequence
196     // 
197     Module *pTypeHandleModule = pMT->GetModule_NoLogging();
198
199     // If the type handle's module is different that the this->pInfoModule 
200     // we will need to add an out-of-module escape for the type
201     //
202     DWORD index = 0;
203     mdToken token = pMT->GetCl_NoLogging();
204 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
205     if (pTypeHandleModule != this->context.pInfoModule && !pTypeHandleModule->IsInCurrentVersionBubble())
206     {
207         pTypeHandleModule = GetAppDomain()->ToCompilationDomain()->GetTargetModule();
208         token = pTypeHandleModule->LookupTypeRefByMethodTable(pMT);
209     }
210 #endif
211     if (pTypeHandleModule != this->context.pInfoModule) 
212     {
213         // During IBC profiling this calls
214         //     code:Module.EncodeModuleHelper
215         // During ngen this calls
216         //     code:ZapImportTable.EncodeModuleHelper)
217         //
218         index = (*this->pfnEncodeModule)(this->context.pModuleContext, pTypeHandleModule); 
219
220         if (index == ENCODE_MODULE_FAILED)
221             return FALSE;
222
223         // emit the ET_MODULE_ZAPSIG escape
224         pSigBuilder->AppendElementType((CorElementType) ELEMENT_TYPE_MODULE_ZAPSIG);
225         // emit the module index
226         pSigBuilder->AppendData(index);
227     }
228
229     // Remember if we have an instantiated generic type 
230     bool fNeedsInstantiation = pMT->HasInstantiation() && !pMT->IsGenericTypeDefinition();
231
232     // We possibly have an instantiated generic type 
233     if (fNeedsInstantiation)
234     {
235         pSigBuilder->AppendElementType(ELEMENT_TYPE_GENERICINST);
236     }
237
238     // Beware of enums!  Can't use GetInternalCorElementType() here.
239     pSigBuilder->AppendElementType(pMT->IsValueType() ? ELEMENT_TYPE_VALUETYPE : ELEMENT_TYPE_CLASS);
240
241     _ASSERTE(!IsNilToken(token));
242     if (IsNilToken(token))
243         return FALSE;
244
245     if ((index != 0) && (this->pfnTokenDefinition != NULL))
246     {
247         //
248         // We do not want to log the metadata lookups that we perform here
249         // 
250         IBCLoggingDisabler   disableLogging;
251
252         // During IBC profiling this calls
253         //     code:Module::TokenDefinitionHelper
254         (*this->pfnTokenDefinition)(this->context.pModuleContext, pTypeHandleModule, index, &token);
255
256         // ibcExternalType tokens are actually encoded as mdtTypeDef tokens in the signature
257         _ASSERT(TypeFromToken(token) == ibcExternalType);
258         token = TokenFromRid(RidFromToken(token), mdtTypeDef);
259     }
260
261     pSigBuilder->AppendToken(token);
262
263     if (fNeedsInstantiation)
264     {
265         pSigBuilder->AppendData(pMT->GetNumGenericArgs());
266         Instantiation inst = pMT->GetInstantiation();
267         for (DWORD i = 0; i < inst.GetNumArgs(); i++)
268         {
269             TypeHandle t = inst[i];
270             CONSISTENCY_CHECK(!t.IsNull() && !t.IsEncodedFixup());
271             if (!this->GetSignatureForTypeHandle(t, pSigBuilder))
272                 return FALSE;
273         }
274     }
275     return TRUE;
276 }
277
278 #endif // #ifndef DACCESS_COMPILE
279
280 //
281 // Returns element type when the typeHandle can be encoded using
282 // using a single CorElementType value 
283 // This includes using ELEMENT_TYPE_CANON_ZAPSIG for the System.__Canon type
284 // 
285 /*static */ CorElementType ZapSig::TryEncodeUsingShortcut(/* in  */ MethodTable * pMT)
286 {
287    LIMITED_METHOD_CONTRACT;
288
289     CorElementType elemType = ELEMENT_TYPE_END;  // An illegal value that we check for later
290
291     // Set elemType to a shortcut encoding whenever possible
292     // 
293     if (pMT->IsTruePrimitive())
294         elemType = pMT->GetInternalCorElementType();
295     else if (pMT == g_pObjectClass)
296         elemType = ELEMENT_TYPE_OBJECT;
297     else if (pMT == g_pStringClass)
298         elemType = ELEMENT_TYPE_STRING;
299     else if (pMT == g_pCanonMethodTableClass)
300         elemType = (CorElementType) ELEMENT_TYPE_CANON_ZAPSIG;
301     else if (pMT->IsArray())
302         elemType = pMT->GetInternalCorElementType();  // either ELEMENT_TYPE_SZARRAY or ELEMENT_TYPE_ARRAY
303
304     return elemType;
305 }
306
307 //
308 // Compare a metadata signature element with a type handle
309 // The type handle must have a fully restored type key, which in turn means that modules for all of its
310 // components are loaded (e.g. type arguments to an instantiated type).
311 //
312 // Hence we can do the signature comparison without incurring any loads or restores.
313 //
314 /*static*/ BOOL ZapSig::CompareSignatureToTypeHandle(PCCOR_SIGNATURE          pSig,   
315                                                      Module*                  pModule, 
316                                                      TypeHandle               handle,
317                                                      const ZapSig::Context *  pZapSigContext)
318 {
319     CONTRACT(BOOL)
320     {
321         NOTHROW;
322         GC_NOTRIGGER;
323         MODE_ANY;
324         FORBID_FAULT;
325         PRECONDITION(CheckPointer(pModule));
326         PRECONDITION(CheckPointer(pZapSigContext));
327         PRECONDITION(CheckPointer(pZapSigContext->pModuleContext));
328         PRECONDITION(CheckPointer(pZapSigContext->pInfoModule));
329         PRECONDITION(CheckPointer(handle));
330         PRECONDITION(CheckPointer(pSig));
331         PRECONDITION(!handle.HasUnrestoredTypeKey());
332     }
333     CONTRACT_END
334
335     mdToken      tk;
336
337     //
338     // pOrigModule is the original module that contained this ZapSig
339     // 
340     Module *       pOrigModule = pZapSigContext->pInfoModule;
341     CorElementType sigType     = CorSigUncompressElementType(pSig);
342     CorElementType handleType  = handle.GetSignatureCorElementType();
343
344     switch ((DWORD)sigType)
345     {
346         default:
347         {
348             // Unknown type!
349             _ASSERTE(!"Unknown type in ZapSig::CompareSignatureToTypeHandle");
350             RETURN(FALSE);
351         }
352
353         case ELEMENT_TYPE_MODULE_ZAPSIG:
354         {
355             DWORD ix = CorSigUncompressData(pSig);
356             CONTRACT_VIOLATION(ThrowsViolation|GCViolation);
357             pModule = pZapSigContext->GetZapSigModule()->GetModuleFromIndexIfLoaded(ix);
358             if (pModule == NULL)
359                 RETURN FALSE;
360             else
361                 RETURN(CompareSignatureToTypeHandle(pSig, pModule, handle, pZapSigContext));
362         }
363     
364         case ELEMENT_TYPE_U:
365         case ELEMENT_TYPE_I:
366         case ELEMENT_TYPE_VOID:
367         case ELEMENT_TYPE_I1:
368         case ELEMENT_TYPE_U1:
369         case ELEMENT_TYPE_I2:
370         case ELEMENT_TYPE_U2:
371         case ELEMENT_TYPE_I4:
372         case ELEMENT_TYPE_U4:
373         case ELEMENT_TYPE_I8:
374         case ELEMENT_TYPE_U8:
375         case ELEMENT_TYPE_R4:
376         case ELEMENT_TYPE_R8:
377         case ELEMENT_TYPE_BOOLEAN:
378         case ELEMENT_TYPE_CHAR:
379         case ELEMENT_TYPE_TYPEDBYREF:
380             RETURN(sigType == handleType);
381
382         case ELEMENT_TYPE_STRING:   
383             RETURN(handle == TypeHandle(g_pStringClass));
384
385         case ELEMENT_TYPE_OBJECT:
386             RETURN(handle == TypeHandle(g_pObjectClass));
387
388         case ELEMENT_TYPE_CANON_ZAPSIG:
389             RETURN(handle == TypeHandle(g_pCanonMethodTableClass));
390
391         case ELEMENT_TYPE_VAR: 
392         case ELEMENT_TYPE_MVAR:
393         {
394             if (sigType != handleType)
395                 RETURN(FALSE);
396
397             unsigned varNum = CorSigUncompressData(pSig);
398             RETURN(varNum == (dac_cast<PTR_TypeVarTypeDesc>(handle.AsTypeDesc())->GetIndex()));
399         }
400
401         case ELEMENT_TYPE_VAR_ZAPSIG:
402         {
403             if (!handle.IsGenericVariable())
404                 RETURN(FALSE);
405
406             TypeVarTypeDesc *pTypeVarTypeDesc = handle.AsGenericVariable();
407
408             unsigned rid = CorSigUncompressData(pSig);
409             RETURN(TokenFromRid(rid, mdtGenericParam) == pTypeVarTypeDesc->GetToken() && pModule == pTypeVarTypeDesc->GetModule());
410         }
411
412         // These take an additional argument, which is the element type
413         case ELEMENT_TYPE_SZARRAY:
414         case ELEMENT_TYPE_PTR:
415         case ELEMENT_TYPE_BYREF:
416         {
417             if (sigType != handleType)
418                 RETURN(FALSE);
419
420             RETURN (CompareSignatureToTypeHandle(pSig, pModule, handle.GetTypeParam(), pZapSigContext));
421         }
422
423         case ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG:
424         {
425             if (handle.IsTypeDesc() || !handle.AsMethodTable()->IsArray())
426                 RETURN(FALSE);
427
428             RETURN (CompareSignatureToTypeHandle(pSig, pModule, handle, pZapSigContext));
429         }
430         
431         case ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG:
432         {
433             sigType = CorSigUncompressElementType(pSig);
434             _ASSERTE(sigType == ELEMENT_TYPE_VALUETYPE);
435
436             if (!handle.IsNativeValueType()) RETURN(FALSE);
437         } // fall-through
438
439         case ELEMENT_TYPE_VALUETYPE:
440         case ELEMENT_TYPE_CLASS:
441         {            
442             CorSigUncompressToken(pSig, &tk);
443             if (TypeFromToken(tk) == mdtTypeRef)
444             {
445                 BOOL resolved = FALSE;
446                 EX_TRY
447                 {
448                     ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
449                     resolved = ClassLoader::ResolveTokenToTypeDefThrowing(pModule, tk, &pModule, &tk, Loader::DontLoad);
450                 }
451                 EX_CATCH
452                 {
453                 }
454                 EX_END_CATCH(SwallowAllExceptions);
455                 if (!resolved)
456                     RETURN(FALSE);
457             }
458             _ASSERTE(TypeFromToken(tk) == mdtTypeDef);
459             RETURN (sigType == handleType && !handle.HasInstantiation() && pModule == handle.GetModule() && handle.GetCl() == tk);
460         }
461
462         case ELEMENT_TYPE_FNPTR: 
463         {
464             if (sigType != handleType)
465                 RETURN(FALSE);
466
467             FnPtrTypeDesc *pTD = handle.AsFnPtrType();
468             DWORD callConv = CorSigUncompressData(pSig);
469             if (callConv != pTD->GetCallConv())
470                 RETURN(FALSE);
471
472             DWORD numArgs = CorSigUncompressData(pSig);
473             if (numArgs != pTD->GetNumArgs())
474                 RETURN(FALSE);
475
476             {
477                 CONTRACT_VIOLATION(ThrowsViolation|GCViolation);
478
479                 for (DWORD i = 0; i <= numArgs; i++)
480                 {
481                     SigPointer sp(pSig);
482                     if (!CompareSignatureToTypeHandle(pSig, pOrigModule, pTD->GetRetAndArgTypes()[i], pZapSigContext))
483                         RETURN(FALSE);
484                     if (FAILED(sp.SkipExactlyOne()))
485                     {
486                         RETURN(FALSE);
487                     }
488                     pSig = sp.GetPtr();
489                 }
490             }    
491             break;
492         }
493
494         case ELEMENT_TYPE_GENERICINST:
495         {
496             if (!handle.HasInstantiation())
497                 RETURN(FALSE);
498
499             sigType = CorSigUncompressElementType(pSig);
500             if (sigType != handleType)
501                 RETURN(FALSE);
502
503             pSig += CorSigUncompressToken(pSig, &tk);
504             if (TypeFromToken(tk) == mdtTypeRef)
505             {
506                 BOOL resolved = FALSE;
507                 EX_TRY
508                 {
509                     ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE();
510                     resolved = ClassLoader::ResolveTokenToTypeDefThrowing(pModule, tk, &pModule, &tk, Loader::DontLoad);
511                 }
512                 EX_CATCH
513                 {
514                 }
515                 EX_END_CATCH(SwallowAllExceptions);
516                 if (!resolved)
517                     RETURN(FALSE);
518             }
519             _ASSERTE(TypeFromToken(tk) == mdtTypeDef);
520             if (pModule != handle.GetModule() || tk != handle.GetCl())
521                 RETURN(FALSE);
522
523             DWORD numGenericArgs = CorSigUncompressData(pSig);
524
525             if (numGenericArgs != handle.GetNumGenericArgs())
526                 RETURN(FALSE);
527
528             Instantiation inst = handle.GetInstantiation();
529             for (DWORD i = 0; i < inst.GetNumArgs(); i++)
530             {
531                 SigPointer sp(pSig);
532                 if (!CompareSignatureToTypeHandle(pSig, pOrigModule, inst[i], pZapSigContext))
533                     RETURN(FALSE);
534                 if (FAILED(sp.SkipExactlyOne()))
535                 {
536                     RETURN(FALSE);
537                 }
538                 pSig = sp.GetPtr();
539             }
540             break;
541         }
542
543         case ELEMENT_TYPE_ARRAY:
544         {
545             if (sigType != handleType)
546                 RETURN(FALSE);
547
548             if (!CompareSignatureToTypeHandle(pSig, pModule, handle.GetTypeParam(), pZapSigContext))
549                 RETURN(FALSE);
550             SigPointer sp(pSig);
551             if (FAILED(sp.SkipExactlyOne()))
552                 RETURN(FALSE);
553
554             DWORD rank;
555             if (FAILED(sp.GetData(&rank)))
556                 RETURN(FALSE);
557             
558             if (rank != handle.AsArray()->GetRank())
559                 RETURN(FALSE);
560
561             break;
562         }
563     }
564
565     RETURN(TRUE);
566 }
567
568 #ifdef FEATURE_PREJIT
569 /*static*/
570 BOOL ZapSig::CompareFixupToTypeHandle(Module * pModule, TADDR fixup, TypeHandle handle)
571 {
572     CONTRACTL
573     {
574         NOTHROW;
575         GC_NOTRIGGER;
576         MODE_ANY;
577         FORBID_FAULT;
578         PRECONDITION(CORCOMPILE_IS_POINTER_TAGGED(fixup));
579         PRECONDITION(CheckPointer(pModule));
580     }
581     CONTRACTL_END
582
583     Module *pDefiningModule;
584     PCCOR_SIGNATURE pSig = pModule->GetEncodedSigIfLoaded(CORCOMPILE_UNTAG_TOKEN(fixup), &pDefiningModule);
585     if (pDefiningModule == NULL)
586         return FALSE;
587         
588     ZapSig::Context zapSigContext(pDefiningModule, pModule);
589     return ZapSig::CompareSignatureToTypeHandle(pSig, pDefiningModule, handle, &zapSigContext);
590 }
591 #endif // FEATURE_PREJIT
592
593 /*static*/
594 BOOL ZapSig::CompareTypeHandleFieldToTypeHandle(TypeHandle *pTypeHnd, TypeHandle typeHnd2)
595 {
596     CONTRACTL
597     {
598         NOTHROW;
599         GC_NOTRIGGER;
600         MODE_ANY;
601         FORBID_FAULT;
602         PRECONDITION(CheckPointer(pTypeHnd));
603         PRECONDITION(CheckPointer(typeHnd2));
604         PRECONDITION(!CORCOMPILE_IS_POINTER_TAGGED((SIZE_T) typeHnd2.AsPtr()));
605     }
606     CONTRACTL_END
607
608     // Ensure that the compiler won't fetch the value twice
609     SIZE_T fixup = VolatileLoadWithoutBarrier((SIZE_T *)pTypeHnd);
610
611 #ifdef FEATURE_PREJIT
612     if (CORCOMPILE_IS_POINTER_TAGGED(fixup))
613     {
614         Module *pContainingModule = ExecutionManager::FindZapModule(dac_cast<TADDR>(pTypeHnd));
615         CONSISTENCY_CHECK(pContainingModule != NULL);
616         
617         Module *pDefiningModule;
618         PCCOR_SIGNATURE pSig = pContainingModule->GetEncodedSigIfLoaded(CORCOMPILE_UNTAG_TOKEN(fixup), &pDefiningModule);
619         if (pDefiningModule == NULL)
620             return FALSE;
621         else
622         {
623             ZapSig::Context    zapSigContext(pDefiningModule, pContainingModule);
624             ZapSig::Context *  pZapSigContext = &zapSigContext;
625             return CompareSignatureToTypeHandle(pSig, pDefiningModule, typeHnd2, pZapSigContext);
626         }
627     }
628     else
629 #endif // FEATURE_PREJIT
630         return TypeHandle::FromTAddr(fixup) == typeHnd2;
631 }
632
633 #ifndef DACCESS_COMPILE
634 Module *ZapSig::DecodeModuleFromIndex(Module *fromModule,
635                                       DWORD index)
636 {
637     CONTRACTL
638     {
639         THROWS;
640         GC_TRIGGERS;
641         MODE_ANY;
642     }
643     CONTRACTL_END;
644
645     Assembly *pAssembly = NULL;
646
647     if (index == 0)
648     {
649         pAssembly = fromModule->GetAssembly();
650     }
651     else
652     {
653         if (index < fromModule->GetAssemblyRefMax())
654         {
655             pAssembly = fromModule->LoadAssembly(RidToToken(index, mdtAssemblyRef))->GetAssembly();
656         }
657         else
658         {
659             index -= fromModule->GetAssemblyRefMax();
660
661             pAssembly = fromModule->GetNativeMetadataAssemblyRefFromCache(index);
662
663             if(pAssembly == NULL)
664             {
665                 AssemblySpec spec;
666                 spec.InitializeSpec(TokenFromRid(index, mdtAssemblyRef),
667                                     fromModule->GetNativeAssemblyImport(),
668                                     NULL);
669
670                 pAssembly = spec.LoadAssembly(FILE_LOADED);
671
672                 fromModule->SetNativeMetadataAssemblyRefInCache(index, pAssembly);            
673             }
674         }
675     }
676
677     return pAssembly->GetManifestModule();
678 }
679
680 Module *ZapSig::DecodeModuleFromIndexIfLoaded(Module *fromModule,
681                                               DWORD index)
682 {
683     CONTRACTL
684     {
685         NOTHROW;
686         GC_NOTRIGGER;
687         FORBID_FAULT;
688     }
689     CONTRACTL_END;
690
691     Assembly *pAssembly = NULL;
692     mdAssemblyRef tkAssemblyRef;
693
694     if (index == 0)
695         pAssembly = fromModule->GetAssembly();
696     else
697     {
698         if (index < fromModule->GetAssemblyRefMax())
699         {
700             tkAssemblyRef = RidToToken(index, mdtAssemblyRef);
701             pAssembly = fromModule->GetAssemblyIfLoaded(tkAssemblyRef);
702         }
703         else
704         {
705             index -= fromModule->GetAssemblyRefMax();
706             tkAssemblyRef = RidToToken(index, mdtAssemblyRef);
707             IMDInternalImport *  pMDImportOverride = fromModule->GetNativeAssemblyImport(FALSE);
708             if (pMDImportOverride != NULL)
709             {
710                 CHAR   szFullName[MAX_CLASS_NAME + 1];
711                 LPCSTR szWinRtNamespace = NULL;
712                 LPCSTR szWinRtClassName = NULL;
713                 
714                 BOOL fValidAssemblyRef = TRUE;
715                 LPCSTR pAssemblyName;
716                 DWORD  dwFlags;
717                 if (FAILED(pMDImportOverride->GetAssemblyRefProps(tkAssemblyRef, 
718                         NULL, 
719                         NULL, 
720                         &pAssemblyName, 
721                         NULL, 
722                         NULL, 
723                         NULL, 
724                         &dwFlags)))
725                 {   // Unexpected failure reading MetaData
726                     fValidAssemblyRef = FALSE;
727                 }
728                 
729                 if (fValidAssemblyRef && IsAfContentType_WindowsRuntime(dwFlags))
730                 {
731                     // Find the encoded type name
732                     LPCSTR pTypeName = NULL;
733                     if (pAssemblyName != NULL)
734                         pTypeName = strchr(pAssemblyName, '!');
735                     
736                     if (pTypeName != NULL)
737                     {
738                         pTypeName++;
739                         // pTypeName now contains the full type name (namespace + name)
740                     
741                         strcpy_s(szFullName, _countof(szFullName), pTypeName);
742                         LPSTR pszName = strrchr(szFullName, '.');
743                     
744                         // WinRT types must have a namespace
745                         if (pszName != NULL)
746                         {
747                             // Replace . between namespace and name with null terminator.
748                             // This breaks the string into a namespace and name pair.
749                             *pszName = '\0';
750                             pszName++;
751                             
752                             szWinRtNamespace = szFullName;
753                             szWinRtClassName = pszName;
754                         }
755                         else
756                         {   // Namespace '.' separator not found - invalid type name (namespace has to be always present)
757                             fValidAssemblyRef = FALSE;
758                         }
759                     }
760                     else
761                     {   // Type name separator in assembly name '!' not found
762                         fValidAssemblyRef = FALSE;
763                     }
764                 }
765
766                 if (fValidAssemblyRef)
767                 {
768                     pAssembly = fromModule->GetAssemblyIfLoaded(
769                             tkAssemblyRef, 
770                             szWinRtNamespace, 
771                             szWinRtClassName, 
772                             pMDImportOverride);
773                 }
774             }
775         }
776     }
777
778     if (pAssembly == NULL)
779         return NULL;
780
781     return pAssembly->GetManifestModule();
782 }
783
784
785 TypeHandle ZapSig::DecodeType(Module *pEncodeModuleContext,
786                               Module *pInfoModule,
787                               PCCOR_SIGNATURE pBuffer,
788                               ClassLoadLevel level)
789 {
790     CONTRACTL
791     {
792         THROWS;
793         GC_TRIGGERS;
794         MODE_ANY;
795     }
796     CONTRACTL_END;
797
798     SigPointer p(pBuffer);
799
800     ZapSig::Context    zapSigContext(pInfoModule, pEncodeModuleContext);
801     ZapSig::Context *  pZapSigContext = &zapSigContext;
802
803     SigTypeContext typeContext;    // empty context is OK: encoding should not contain type variables.
804
805     TypeHandle th = p.GetTypeHandleThrowing(pInfoModule,
806                                             &typeContext,
807                                             ClassLoader::LoadTypes,
808                                             level,
809                                             level < CLASS_LOADED, // For non-full loads, drop a level when loading generic arguments
810                                             NULL,
811                                             pZapSigContext);
812
813     return th;
814 }
815
816 MethodDesc *ZapSig::DecodeMethod(Module *pReferencingModule,
817                                  Module *pInfoModule,
818                                  PCCOR_SIGNATURE pBuffer,
819                                  TypeHandle * ppTH /*=NULL*/)
820 {
821     STANDARD_VM_CONTRACT;
822
823     SigTypeContext typeContext;    // empty context is OK: encoding should not contain type variables.
824
825     return DecodeMethod(pReferencingModule, pInfoModule, pBuffer, &typeContext, ppTH);
826 }
827
828 MethodDesc *ZapSig::DecodeMethod(Module *pReferencingModule,
829                                  Module *pInfoModule,
830                                  PCCOR_SIGNATURE pBuffer,
831                                  SigTypeContext *pContext,
832                                  TypeHandle *ppTH, /*=NULL*/
833                                  PCCOR_SIGNATURE *ppOwnerTypeSpecWithVars, /*=NULL*/
834                                  PCCOR_SIGNATURE *ppMethodSpecWithVars /*=NULL*/)
835 {
836     STANDARD_VM_CONTRACT;
837
838     MethodDesc *pMethod = NULL;
839
840     SigPointer sig(pBuffer);
841
842     ZapSig::Context    zapSigContext(pInfoModule, (void *)pReferencingModule, ZapSig::NormalTokens);
843     ZapSig::Context *  pZapSigContext = &zapSigContext;
844
845     // decode flags
846     DWORD methodFlags;
847     IfFailThrow(sig.GetData(&methodFlags));
848
849     TypeHandle thOwner = NULL;
850
851     if ( methodFlags & ENCODE_METHOD_SIG_OwnerType )
852     {
853         if (ppOwnerTypeSpecWithVars != NULL)
854             *ppOwnerTypeSpecWithVars = sig.GetPtr();
855
856         thOwner = sig.GetTypeHandleThrowing(pInfoModule,
857                                         pContext,
858                                         ClassLoader::LoadTypes,
859                                         CLASS_LOADED,
860                                         FALSE,
861                                         NULL,
862                                         pZapSigContext);
863
864         IfFailThrow(sig.SkipExactlyOne());
865     }
866
867     if ( methodFlags & ENCODE_METHOD_SIG_SlotInsteadOfToken )
868     {
869         // get the method desc using slot number
870         DWORD slot;
871         IfFailThrow(sig.GetData(&slot));
872
873         _ASSERTE(!thOwner.IsNull());
874
875         pMethod = thOwner.GetMethodTable()->GetMethodDescForSlot(slot);
876     }
877     else
878     {
879         //
880         // decode method token
881         //
882         RID rid;
883         IfFailThrow(sig.GetData(&rid));
884
885         if (methodFlags & ENCODE_METHOD_SIG_MemberRefToken)
886         {
887             if (thOwner.IsNull())
888             {
889                 TypeHandle th;
890                 MethodDesc * pMD = NULL;
891                 FieldDesc * pFD = NULL;
892
893                 MemberLoader::GetDescFromMemberRef(pInfoModule, TokenFromRid(rid, mdtMemberRef), &pMD, &pFD, NULL, FALSE, &th);
894                 _ASSERTE(pMD != NULL);
895
896                 thOwner = th;
897                 pMethod = pMD;
898             }
899             else
900             {
901                 pMethod = MemberLoader::GetMethodDescFromMemberRefAndType(pInfoModule, TokenFromRid(rid, mdtMemberRef), thOwner.GetMethodTable());
902             }
903         }
904         else
905         {
906             pMethod = MemberLoader::GetMethodDescFromMethodDef(pInfoModule, TokenFromRid(rid, mdtMethodDef), FALSE);
907         }
908     }
909
910     if (thOwner.IsNull())
911         thOwner = pMethod->GetMethodTable();
912
913     if (ppTH != NULL)
914         *ppTH = thOwner;
915
916     // Ensure that the methoddescs dependencies have been walked sufficiently for type forwarders to be resolved.
917     // This method is actually basically a nop for dependencies which are ngen'd, but is real work for jitted
918     // dependencies. (However, this shouldn't be meaningful work that wouldn't happen in any case very soon.)
919     pMethod->PrepareForUseAsADependencyOfANativeImage();
920
921     Instantiation inst;
922
923     // Instantiate the method if needed, or create a stub to a static method in a generic class.
924     if (methodFlags & ENCODE_METHOD_SIG_MethodInstantiation)
925     {
926         if (ppMethodSpecWithVars != NULL)
927             *ppMethodSpecWithVars = sig.GetPtr();
928
929         DWORD nargs;
930         IfFailThrow(sig.GetData(&nargs));
931         _ASSERTE(nargs > 0);
932
933         SIZE_T cbMem;
934
935         if (!ClrSafeInt<SIZE_T>::multiply(nargs, sizeof(TypeHandle), cbMem/* passed by ref */))
936             ThrowHR(COR_E_OVERFLOW);
937                         
938         TypeHandle * pInst = (TypeHandle*) _alloca(cbMem);
939
940         for (DWORD i = 0; i < nargs; i++)
941         {
942             pInst[i] = sig.GetTypeHandleThrowing(pInfoModule,
943                                                 pContext,
944                                                 ClassLoader::LoadTypes,
945                                                 CLASS_LOADED,
946                                                 FALSE,
947                                                 NULL,
948                                                 pZapSigContext);
949             IfFailThrow(sig.SkipExactlyOne());
950         }
951
952         inst = Instantiation(pInst, nargs);
953     }
954     else
955     {
956         inst = pMethod->GetMethodInstantiation();
957     }
958
959
960     // This must be called even if nargs == 0, in order to create an instantiating
961     // stub for static methods in generic classees if needed, also for BoxedEntryPointStubs
962     // in non-generic structs.
963     BOOL isInstantiatingStub = (methodFlags & ENCODE_METHOD_SIG_InstantiatingStub);
964     BOOL isUnboxingStub = (methodFlags & ENCODE_METHOD_SIG_UnboxingStub);
965
966     pMethod = MethodDesc::FindOrCreateAssociatedMethodDesc(pMethod, thOwner.GetMethodTable(),
967                                                             isUnboxingStub,
968                                                             inst,
969                                                             !(isInstantiatingStub || isUnboxingStub));
970
971     g_IBCLogger.LogMethodDescAccess(pMethod);
972
973     if (methodFlags & ENCODE_METHOD_SIG_Constrained)
974     {
975         TypeHandle constrainedType = sig.GetTypeHandleThrowing(pInfoModule,
976                                                 pContext,
977                                                 ClassLoader::LoadTypes,
978                                                 CLASS_LOADED,
979                                                 FALSE,
980                                                 NULL,
981                                                 pZapSigContext);
982
983         MethodDesc * directMethod = constrainedType.GetMethodTable()->TryResolveConstraintMethodApprox(thOwner.GetMethodTable(), pMethod);
984         if (directMethod == NULL)
985         {
986             // Method on value type was removed. Boxing stub would need to be generated to handle this case.
987             _ASSERTE(!"Constrained method resolution failed");
988
989             MemberLoader::ThrowMissingMethodException(constrainedType.GetMethodTable(), NULL, NULL, NULL, 0, NULL);
990         }
991
992         // Strip the instantiating stub if the signature did not ask for one
993         if (directMethod->IsInstantiatingStub() && !isInstantiatingStub)
994         {
995             pMethod = directMethod->GetWrappedMethodDesc();
996         }
997         else
998         {
999             pMethod = directMethod;
1000         }
1001     }
1002
1003     return pMethod;
1004 }
1005
1006 FieldDesc * ZapSig::DecodeField(Module *pReferencingModule,
1007                                 Module *pInfoModule,
1008                                 PCCOR_SIGNATURE pBuffer,
1009                                 TypeHandle *ppTH /*=NULL*/)
1010 {
1011     CONTRACTL
1012     {
1013         THROWS;
1014         GC_TRIGGERS;
1015         MODE_ANY;
1016     }
1017     CONTRACTL_END;
1018
1019     SigTypeContext typeContext;    // empty context is OK: encoding should not contain type variables.
1020
1021     return DecodeField(pReferencingModule, pInfoModule, pBuffer, &typeContext, ppTH);
1022 }
1023
1024 FieldDesc * ZapSig::DecodeField(Module *pReferencingModule,
1025                                 Module *pInfoModule,
1026                                 PCCOR_SIGNATURE pBuffer,
1027                                 SigTypeContext *pContext,
1028                                 TypeHandle *ppTH /*=NULL*/)
1029 {
1030     CONTRACTL
1031     {
1032         THROWS;
1033         GC_TRIGGERS;
1034         MODE_ANY;
1035     }
1036     CONTRACTL_END;
1037
1038     FieldDesc *pField = NULL;
1039
1040     SigPointer sig(pBuffer);
1041
1042     DWORD fieldFlags;
1043     IfFailThrow(sig.GetData(&fieldFlags));
1044
1045     MethodTable *pOwnerMT = NULL;
1046
1047     if (fieldFlags & ENCODE_FIELD_SIG_OwnerType)
1048     {
1049         ZapSig::Context    zapSigContext(pInfoModule, pReferencingModule);
1050         ZapSig::Context *  pZapSigContext = &zapSigContext;
1051
1052         pOwnerMT = sig.GetTypeHandleThrowing(pInfoModule,
1053                                         pContext,
1054                                         ClassLoader::LoadTypes,
1055                                         CLASS_LOADED,
1056                                         FALSE,
1057                                         NULL,
1058                                         pZapSigContext).GetMethodTable();
1059
1060         IfFailThrow(sig.SkipExactlyOne());
1061     }
1062
1063     if (fieldFlags & ENCODE_FIELD_SIG_IndexInsteadOfToken)
1064     {
1065         // get the field desc using index
1066         DWORD fieldIndex;
1067         IfFailThrow(sig.GetData(&fieldIndex));
1068
1069         _ASSERTE(pOwnerMT != NULL);
1070
1071         pField = pOwnerMT->GetFieldDescByIndex(fieldIndex);
1072         _ASSERTE(pOwnerMT == pField->GetApproxEnclosingMethodTable());
1073     }
1074     else
1075     {
1076         RID rid;
1077         IfFailThrow(sig.GetData(&rid));
1078
1079         if (fieldFlags & ENCODE_FIELD_SIG_MemberRefToken)
1080         {
1081             if (pOwnerMT == NULL)
1082             {
1083                 TypeHandle th;
1084                 MethodDesc * pMD = NULL;
1085                 FieldDesc * pFD = NULL;
1086
1087                 MemberLoader::GetDescFromMemberRef(pInfoModule, TokenFromRid(rid, mdtMemberRef), &pMD, &pFD, NULL, FALSE, &th);
1088                 _ASSERTE(pFD != NULL);
1089
1090                 pField = pFD;
1091             }
1092             else
1093             {
1094                 pField = MemberLoader::GetFieldDescFromMemberRefAndType(pInfoModule, TokenFromRid(rid, mdtMemberRef), pOwnerMT);
1095             }
1096         }
1097         else
1098         {
1099             pField = MemberLoader::GetFieldDescFromFieldDef(pInfoModule, TokenFromRid(rid, mdtFieldDef), FALSE);
1100         }
1101     }
1102
1103     if (ppTH != NULL)
1104         *ppTH = (pOwnerMT != NULL) ? pOwnerMT : pField->GetApproxEnclosingMethodTable();
1105
1106     return pField;
1107 }
1108
1109 // Copy single type signature, adding ELEMENT_TYPE_MODULE_ZAPSIG to types that are encoded using tokens.
1110 // The check for types that use token is conservative in the sense that it adds the override for types
1111 // it doesn't explicitly recognize.
1112 // The source signature originates from the module with index specified by the parameter moduleIndex.
1113 // Passing moduleIndex set to MODULE_INDEX_NONE results in pure copy of the signature.
1114 //
1115 // NOTE: This function is meant to process only generic signatures that occur as owner type,
1116 // constraint types and method instantiation in the EncodeMethod and EncodeField methods below.
1117 //
1118 void ZapSig::CopyTypeSignature(SigParser* pSigParser, SigBuilder* pSigBuilder, DWORD moduleIndex)
1119 {
1120     if (moduleIndex != MODULE_INDEX_NONE)
1121     {
1122         BYTE type;
1123         IfFailThrow(pSigParser->PeekByte(&type));
1124
1125         // Handle single and multidimensional arrays
1126         if (type == ELEMENT_TYPE_SZARRAY || type == ELEMENT_TYPE_ARRAY)
1127         {
1128             IfFailThrow(pSigParser->GetByte(&type));
1129             pSigBuilder->AppendElementType((CorElementType)type);
1130
1131             // Copy the element type signature
1132             CopyTypeSignature(pSigParser, pSigBuilder, moduleIndex);
1133
1134             if (type == ELEMENT_TYPE_ARRAY)
1135             {
1136                 // Copy rank
1137                 ULONG rank;
1138                 IfFailThrow(pSigParser->GetData(&rank));
1139                 pSigBuilder->AppendData(rank);
1140
1141                 if (rank)
1142                 {
1143                     // Copy # of sizes
1144                     ULONG nsizes;
1145                     IfFailThrow(pSigParser->GetData(&nsizes));
1146                     pSigBuilder->AppendData(nsizes);
1147
1148                     while (nsizes--)
1149                     {
1150                         // Copy size
1151                         ULONG size;
1152                         IfFailThrow(pSigParser->GetData(&size));
1153                         pSigBuilder->AppendData(size);
1154                     }
1155
1156                     // Copy # of lower bounds
1157                     ULONG nlbounds;
1158                     IfFailThrow(pSigParser->GetData(&nlbounds));
1159                     pSigBuilder->AppendData(nlbounds);
1160                     while (nlbounds--)
1161                     {
1162                         // Copy lower bound
1163                         ULONG lbound;
1164                         IfFailThrow(pSigParser->GetData(&lbound));
1165                         pSigBuilder->AppendData(lbound);
1166                     }
1167                 }
1168             }
1169
1170             return;
1171         }
1172
1173         // The following elements are not expected in the signatures this function processes. They are followed by
1174         if (type == ELEMENT_TYPE_BYREF || type == ELEMENT_TYPE_PTR || type == ELEMENT_TYPE_PINNED ||
1175             type == ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG || type == ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG)
1176         {
1177             _ASSERTE(FALSE);
1178         }
1179
1180         // Add the module zapsig only for types that use tokens.
1181         if (type >= ELEMENT_TYPE_PTR && type != ELEMENT_TYPE_I && type != ELEMENT_TYPE_U && type != ELEMENT_TYPE_OBJECT &&
1182             type != ELEMENT_TYPE_VAR && type != ELEMENT_TYPE_MVAR && type != ELEMENT_TYPE_TYPEDBYREF)
1183         {
1184             pSigBuilder->AppendElementType((CorElementType)ELEMENT_TYPE_MODULE_ZAPSIG);
1185             pSigBuilder->AppendData(moduleIndex);
1186         }
1187
1188         // Generic instantiation requires processing each nesting level separately
1189         if (type == ELEMENT_TYPE_GENERICINST)
1190         {
1191             IfFailThrow(pSigParser->GetByte(&type));
1192             _ASSERTE(type == ELEMENT_TYPE_GENERICINST);
1193             pSigBuilder->AppendElementType((CorElementType)type);
1194
1195             IfFailThrow(pSigParser->GetByte(&type));
1196             _ASSERTE((type == ELEMENT_TYPE_CLASS) || (type == ELEMENT_TYPE_VALUETYPE));
1197             pSigBuilder->AppendElementType((CorElementType)type);
1198
1199             mdToken token;
1200             IfFailThrow(pSigParser->GetToken(&token));
1201             pSigBuilder->AppendToken(token);
1202
1203             ULONG argCnt; // Get number of generic parameters
1204             IfFailThrow(pSigParser->GetData(&argCnt));
1205             pSigBuilder->AppendData(argCnt);
1206
1207             while (argCnt--)
1208             {
1209                 CopyTypeSignature(pSigParser, pSigBuilder, moduleIndex);
1210             }
1211
1212             return;
1213         }
1214     }
1215
1216     PCCOR_SIGNATURE typeSigStart = pSigParser->GetPtr();
1217     IfFailThrow(pSigParser->SkipExactlyOne());
1218     PCCOR_SIGNATURE typeSigEnd = pSigParser->GetPtr();
1219     pSigBuilder->AppendBlob((PVOID)typeSigStart, typeSigEnd - typeSigStart);
1220 }
1221
1222 /* static */
1223 BOOL ZapSig::EncodeMethod(
1224                     MethodDesc *          pMethod,
1225                     Module *              pInfoModule,
1226                     SigBuilder *          pSigBuilder,
1227                     LPVOID                pEncodeModuleContext,
1228                     ENCODEMODULE_CALLBACK pfnEncodeModule,
1229                     DEFINETOKEN_CALLBACK  pfnDefineToken,
1230                     CORINFO_RESOLVED_TOKEN * pResolvedToken,
1231                     CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken,
1232                     BOOL                  fEncodeUsingResolvedTokenSpecStreams)
1233 {
1234     CONTRACTL
1235     {
1236         THROWS;
1237         GC_TRIGGERS;
1238         MODE_ANY;
1239     }
1240     CONTRACTL_END;
1241
1242     TypeHandle ownerType;
1243
1244 #ifdef FEATURE_READYTORUN_COMPILER
1245
1246     // For methods encoded outside of the version bubble, we use pResolvedToken which describes the metadata token from which the method originated
1247     // For tokens inside the version bubble we are not constrained by the contents of pResolvedToken and as such we skip this codepath
1248     // Generic interfaces in canonical form are an exception, we need to get the real type from the pResolvedToken so that the lookup at runtime
1249     // can find the type in interface map.
1250     // FUTURE: This condition should likely be changed or reevaluated once support for smaller version bubbles is implemented.
1251     if (IsReadyToRunCompilation() && (!IsLargeVersionBubbleEnabled() || !pMethod->GetModule()->IsInCurrentVersionBubble() || (pMethod->IsSharedByGenericInstantiations() && pMethod->IsInterface())))
1252     {
1253         if (pMethod->IsNDirect())
1254         {
1255             ownerType = pMethod->GetMethodTable_NoLogging();
1256         }
1257         else
1258         {
1259             if (pResolvedToken == NULL)
1260             {
1261                 _ASSERTE(!"CORINFO_RESOLVED_TOKEN required to encode method!");
1262                 ThrowHR(E_FAIL);
1263             }
1264
1265             // Encode the referencing method type
1266             ownerType = TypeHandle(pResolvedToken->hClass);
1267         }
1268     }
1269     else
1270 #endif
1271     {
1272         ownerType = pMethod->GetMethodTable_NoLogging();
1273     }
1274
1275     ZapSig::ExternalTokens externalTokens = ZapSig::NormalTokens;
1276     if (pfnDefineToken != NULL)
1277     {
1278         externalTokens = ZapSig::IbcTokens;
1279     }
1280
1281     ZapSig zapSig(pInfoModule, pEncodeModuleContext, externalTokens,
1282                     (EncodeModuleCallback)    pfnEncodeModule, 
1283                     (TokenDefinitionCallback) pfnDefineToken);
1284
1285     //
1286     // output the sequence that represents the token for the method
1287     // 
1288     mdMethodDef methodToken               = pMethod->GetMemberDef_NoLogging();
1289     DWORD       methodFlags               = 0;
1290     BOOL        fMethodNeedsInstantiation = pMethod->HasMethodInstantiation() && !pMethod->IsGenericMethodDefinition();
1291
1292     if (pMethod->IsUnboxingStub())
1293         methodFlags |= ENCODE_METHOD_SIG_UnboxingStub;
1294     if (pMethod->IsInstantiatingStub())
1295         methodFlags |= ENCODE_METHOD_SIG_InstantiatingStub;
1296     if (fMethodNeedsInstantiation)
1297         methodFlags |= ENCODE_METHOD_SIG_MethodInstantiation;
1298
1299     //
1300     // For backward compatibility, IBC tokens use slightly different encoding:
1301     // - Owning type is uncoditionally encoded
1302     // - Number of method instantiation arguments is not encoded
1303     //
1304     if (externalTokens == ZapSig::IbcTokens)
1305     {
1306         // The type is always encoded before flags for IBC
1307         if (!zapSig.GetSignatureForTypeHandle(ownerType, pSigBuilder))
1308             return FALSE;
1309     }
1310     else
1311     {
1312         // Assume that the owner type is going to be needed
1313         methodFlags |= ENCODE_METHOD_SIG_OwnerType;
1314     }
1315
1316 #ifdef FEATURE_READYTORUN_COMPILER
1317     if (IsReadyToRunCompilation() && (pConstrainedResolvedToken != NULL))
1318     {
1319         methodFlags |= ENCODE_METHOD_SIG_Constrained;
1320     }
1321
1322     // FUTURE: This condition should likely be changed or reevaluated once support for smaller version bubbles is implemented.
1323     if (IsReadyToRunCompilation() && (!IsLargeVersionBubbleEnabled() || !pMethod->GetModule()->IsInCurrentVersionBubble()))
1324     {
1325         Module * pReferencingModule = pMethod->IsNDirect() ?
1326             pMethod->GetModule() :
1327             (Module *)pResolvedToken->tokenScope;
1328
1329         if (!pReferencingModule->IsInCurrentVersionBubble())
1330         {
1331             // FUTURE: Encoding of new cross-module references for ReadyToRun
1332             // This warning is hit for recursive cross-module inlining. It is commented out to avoid noise.
1333             // GetSvcLogger()->Printf(W("ReadyToRun: Method reference outside of current version bubble cannot be encoded\n"));
1334             ThrowHR(E_FAIL);
1335         }
1336
1337         methodToken = pMethod->IsNDirect() ?
1338             pMethod->GetMemberDef_NoLogging() :
1339             pResolvedToken->token;
1340
1341         if (TypeFromToken(methodToken) == mdtMethodSpec)
1342         {
1343             IfFailThrow(pReferencingModule->GetMDImport()->GetMethodSpecProps(methodToken, &methodToken, NULL, NULL));
1344         }
1345
1346         switch (TypeFromToken(methodToken))
1347         {
1348         case mdtMethodDef:
1349             _ASSERTE(pMethod->IsNDirect() || pResolvedToken->pTypeSpec == NULL);
1350             if (!ownerType.HasInstantiation() || ownerType.IsTypicalTypeDefinition())
1351             {
1352                 methodFlags &= ~ENCODE_METHOD_SIG_OwnerType;
1353             }
1354             break;
1355
1356         case mdtMemberRef:
1357             _ASSERTE(pResolvedToken != NULL);
1358             methodFlags |= ENCODE_METHOD_SIG_MemberRefToken;
1359
1360             if (pResolvedToken->pTypeSpec == NULL)
1361             {
1362                 methodFlags &= ~ENCODE_METHOD_SIG_OwnerType;
1363             }
1364             else
1365                 if (!(methodFlags & ENCODE_METHOD_SIG_InstantiatingStub))
1366                 {
1367                     if (SigPointer(pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec).IsPolyType(NULL) == hasNoVars)
1368                         methodFlags &= ~ENCODE_METHOD_SIG_OwnerType;
1369                 }
1370             break;
1371
1372         default:
1373             _ASSERTE(!"Unexpected method token type!");
1374             ThrowHR(E_NOTIMPL);
1375         }
1376     }
1377     else
1378 #endif
1379     if (IsNilToken(methodToken))
1380     {
1381         methodFlags |= ENCODE_METHOD_SIG_SlotInsteadOfToken;
1382     }
1383     else
1384     if (!pMethod->GetModule()->IsInCurrentVersionBubble())
1385     {
1386         // Using a method defined in another version bubble. We can assume the slot number is stable only for real interface methods.
1387         if (!ownerType.IsInterface() || pMethod->IsStatic() || pMethod->HasMethodInstantiation())
1388         {
1389             // FUTURE TODO: Version resilience
1390             _ASSERTE(!"References to non-interface methods not yet supported in version resilient images");
1391             IfFailThrow(E_FAIL);
1392         }
1393         methodFlags |= ENCODE_METHOD_SIG_SlotInsteadOfToken;
1394     }
1395     else
1396     {
1397         Module * pTypeHandleModule = pMethod->GetModule();
1398         
1399         if (pTypeHandleModule != pInfoModule) 
1400         {
1401             // During IBC profiling this calls
1402             //     code:Module.EncodeModuleHelper
1403             // During ngen this calls
1404             //     code:ZapImportTable.EncodeModuleHelper)
1405             //
1406             DWORD index = (*((EncodeModuleCallback) pfnEncodeModule))(pEncodeModuleContext, pTypeHandleModule);
1407             
1408             if (index == ENCODE_MODULE_FAILED)
1409             {
1410                 return FALSE;
1411             }
1412
1413             // If the method handle's module is different that the pInfoModule 
1414             // we need to call the TokenDefinitionCallback function
1415             // to record the names for the external module tokens
1416             //
1417             if ((index != 0) && (pfnDefineToken != NULL))
1418             {
1419                 //
1420                 // We do not want to log the metadata lookups that we perform here
1421                 // 
1422                 IBCLoggingDisabler   disableLogging;
1423                 
1424                 // During IBC profiling this calls
1425                 //     code:Module::TokenDefinitionHelper()
1426                 (*((TokenDefinitionCallback) pfnDefineToken))(pEncodeModuleContext, pTypeHandleModule, index, &methodToken);
1427             }
1428         }
1429         else
1430         {
1431             _ASSERTE(pInfoModule == pMethod->GetModule());
1432         }
1433
1434         if (!ownerType.HasInstantiation())
1435             methodFlags &= ~ENCODE_METHOD_SIG_OwnerType;
1436     }
1437
1438     //
1439     // output the flags
1440     // 
1441     pSigBuilder->AppendData(methodFlags);
1442
1443     if (methodFlags & ENCODE_METHOD_SIG_OwnerType)
1444     {
1445         if (fEncodeUsingResolvedTokenSpecStreams && pResolvedToken != NULL && pResolvedToken->pTypeSpec != NULL)
1446         {
1447             _ASSERTE(pResolvedToken->cbTypeSpec > 0);
1448
1449             DWORD moduleIndex = MODULE_INDEX_NONE;
1450             if ((IsReadyToRunCompilation() && pMethod->GetModule()->IsInCurrentVersionBubble() && pInfoModule != (Module *) pResolvedToken->tokenScope))
1451             {
1452                 moduleIndex = (*((EncodeModuleCallback)pfnEncodeModule))(pEncodeModuleContext, (Module *) pResolvedToken->tokenScope);
1453             }
1454
1455             SigParser sigParser(pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec);
1456             CopyTypeSignature(&sigParser, pSigBuilder, moduleIndex);
1457         }
1458         else
1459         {
1460             if (!zapSig.GetSignatureForTypeHandle(ownerType, pSigBuilder))
1461                 return FALSE;
1462         }
1463     }
1464
1465     if ((methodFlags & ENCODE_METHOD_SIG_SlotInsteadOfToken) == 0)
1466     {
1467         // emit the rid
1468         pSigBuilder->AppendData(RidFromToken(methodToken));
1469     }
1470     else
1471     {
1472         // have no token (e.g. it could be an array), encode slot number
1473         pSigBuilder->AppendData(pMethod->GetSlot());
1474     }
1475
1476     if ((methodFlags & ENCODE_METHOD_SIG_MethodInstantiation) != 0)
1477     {
1478         if (fEncodeUsingResolvedTokenSpecStreams && pResolvedToken != NULL && pResolvedToken->pMethodSpec != NULL)
1479         {
1480             _ASSERTE(pResolvedToken->cbMethodSpec > 1);
1481
1482             // Copy the pResolvedToken->pMethodSpec, inserting ELEMENT_TYPE_MODULE_ZAPSIG in front of each type parameter in needed
1483             SigParser sigParser(pResolvedToken->pMethodSpec, pResolvedToken->cbMethodSpec);
1484             BYTE callingConvention;
1485             IfFailThrow(sigParser.GetByte(&callingConvention));
1486             if (callingConvention != (BYTE)IMAGE_CEE_CS_CALLCONV_GENERICINST)
1487             {
1488                 ThrowHR(COR_E_BADIMAGEFORMAT);
1489             }
1490
1491             ULONG numGenArgs;
1492             IfFailThrow(sigParser.GetData(&numGenArgs));
1493             pSigBuilder->AppendData(numGenArgs);
1494
1495             DWORD moduleIndex = MODULE_INDEX_NONE;
1496             if ((IsReadyToRunCompilation() && pMethod->GetModule()->IsInCurrentVersionBubble() && pInfoModule != (Module *) pResolvedToken->tokenScope))
1497             {
1498                 moduleIndex = (*((EncodeModuleCallback)pfnEncodeModule))(pEncodeModuleContext, (Module *) pResolvedToken->tokenScope);
1499             }
1500
1501             while (numGenArgs != 0)
1502             {
1503                 CopyTypeSignature(&sigParser, pSigBuilder, moduleIndex);
1504                 numGenArgs--;
1505             }
1506         }
1507         else
1508         {
1509             Instantiation inst = pMethod->GetMethodInstantiation();
1510
1511             // Number of method instantiation arguments is not encoded in IBC tokens - see comment above
1512             if (externalTokens != ZapSig::IbcTokens)
1513                 pSigBuilder->AppendData(inst.GetNumArgs());
1514
1515             for (DWORD i = 0; i < inst.GetNumArgs(); i++)
1516             {
1517                 TypeHandle t = inst[i];
1518                 _ASSERTE(!t.IsNull());
1519
1520                 if (!zapSig.GetSignatureForTypeHandle(t, pSigBuilder))
1521                     return FALSE;
1522             }
1523         }
1524     }
1525
1526 #ifdef FEATURE_READYTORUN_COMPILER
1527     if ((methodFlags & ENCODE_METHOD_SIG_Constrained) != 0)
1528     {
1529         if (fEncodeUsingResolvedTokenSpecStreams && pConstrainedResolvedToken->pTypeSpec != NULL)
1530         {
1531             _ASSERTE(pConstrainedResolvedToken->cbTypeSpec > 0);
1532
1533             DWORD moduleIndex = (DWORD)-1;
1534             if (IsReadyToRunCompilation() && pMethod->GetModule()->IsInCurrentVersionBubble() && pInfoModule != (Module *) pConstrainedResolvedToken->tokenScope)
1535             {
1536                 moduleIndex = (*((EncodeModuleCallback)pfnEncodeModule))(pEncodeModuleContext, (Module *) pConstrainedResolvedToken->tokenScope);
1537             }
1538
1539             SigParser sigParser(pConstrainedResolvedToken->pTypeSpec, pConstrainedResolvedToken->cbTypeSpec);
1540             CopyTypeSignature(&sigParser, pSigBuilder, moduleIndex);
1541         }
1542         else
1543         {
1544             if (!zapSig.GetSignatureForTypeHandle(TypeHandle(pConstrainedResolvedToken->hClass), pSigBuilder))
1545                 return FALSE;
1546         }
1547     }
1548 #endif
1549
1550     return TRUE;
1551 }
1552
1553 void ZapSig::EncodeField(
1554         FieldDesc              *pField,
1555         Module                 *pInfoModule,
1556         SigBuilder             *pSigBuilder,
1557         LPVOID                 pEncodeModuleContext,
1558         ENCODEMODULE_CALLBACK  pfnEncodeModule,
1559         CORINFO_RESOLVED_TOKEN *pResolvedToken,
1560         BOOL                   fEncodeUsingResolvedTokenSpecStreams)
1561 {
1562     CONTRACTL
1563     {
1564         THROWS;
1565         GC_TRIGGERS;
1566         MODE_ANY;
1567     }
1568     CONTRACTL_END;
1569
1570     MethodTable * pMT;
1571
1572     mdMethodDef fieldToken = pField->GetMemberDef();
1573     DWORD fieldFlags = ENCODE_FIELD_SIG_OwnerType;
1574
1575 #ifdef FEATURE_READYTORUN_COMPILER
1576     if (IsReadyToRunCompilation() && (!IsLargeVersionBubbleEnabled() || !pField->GetModule()->IsInCurrentVersionBubble()))
1577     {
1578         if (pResolvedToken == NULL)
1579         {
1580             _ASSERTE(!"CORINFO_RESOLVED_TOKEN required to encode field!");
1581             ThrowHR(E_FAIL);
1582         }
1583
1584         // Encode the referencing field type
1585         pMT = (MethodTable *)(pResolvedToken->hClass);
1586
1587         Module * pReferencingModule = (Module *)pResolvedToken->tokenScope;
1588
1589         if (!pReferencingModule->IsInCurrentVersionBubble())
1590         {
1591             // FUTURE: Encoding of new cross-module references for ReadyToRun
1592             // This warning is hit for recursive cross-module inlining. It is commented out to avoid noise.
1593             // GetSvcLogger()->Printf(W("ReadyToRun: Field reference outside of current version bubble cannot be encoded\n"));
1594             ThrowHR(E_FAIL);
1595         }
1596         _ASSERTE(pReferencingModule == GetAppDomain()->ToCompilationDomain()->GetTargetModule());
1597
1598         fieldToken = pResolvedToken->token;
1599
1600         switch (TypeFromToken(fieldToken))
1601         {
1602         case mdtFieldDef:
1603             _ASSERTE(pResolvedToken->pTypeSpec == NULL);
1604             fieldFlags &= ~ENCODE_FIELD_SIG_OwnerType;
1605             break;
1606
1607         case mdtMemberRef:
1608             fieldFlags |= ENCODE_FIELD_SIG_MemberRefToken;
1609
1610             if (pResolvedToken->pTypeSpec == NULL)
1611             {
1612                 fieldFlags &= ~ENCODE_METHOD_SIG_OwnerType;
1613             }
1614             else
1615             {
1616                 if (SigPointer(pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec).IsPolyType(NULL) == hasNoVars)
1617                     fieldFlags &= ~ENCODE_METHOD_SIG_OwnerType;
1618             }
1619             break;
1620
1621         default:
1622             _ASSERTE(!"Unexpected field token type!");
1623             ThrowHR(E_NOTIMPL);
1624         }
1625     }
1626     else
1627 #endif
1628     {
1629         pMT = pField->GetApproxEnclosingMethodTable();
1630
1631         fieldFlags |= ENCODE_FIELD_SIG_IndexInsteadOfToken;
1632     }
1633
1634     //
1635     // output the flags
1636     // 
1637     pSigBuilder->AppendData(fieldFlags);
1638
1639     if (fieldFlags & ENCODE_FIELD_SIG_OwnerType)
1640     {
1641         if (fEncodeUsingResolvedTokenSpecStreams && pResolvedToken != NULL && pResolvedToken->pTypeSpec != NULL)
1642         {
1643             _ASSERTE(pResolvedToken->cbTypeSpec > 0);
1644
1645             DWORD moduleIndex = MODULE_INDEX_NONE;
1646             if ((IsReadyToRunCompilation() && pField->GetModule()->IsInCurrentVersionBubble() && pInfoModule != (Module *) pResolvedToken->tokenScope))
1647             {
1648                 moduleIndex = (*((EncodeModuleCallback)pfnEncodeModule))(pEncodeModuleContext, (Module *) pResolvedToken->tokenScope);
1649             }
1650
1651             SigParser sigParser(pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec);
1652             CopyTypeSignature(&sigParser, pSigBuilder, moduleIndex);
1653         }
1654         else
1655         {
1656             ZapSig zapSig(pInfoModule, pEncodeModuleContext, ZapSig::NormalTokens,
1657                 (EncodeModuleCallback)pfnEncodeModule, NULL);
1658
1659             //
1660             // Write class
1661             //
1662             BOOL fSuccess;
1663             fSuccess = zapSig.GetSignatureForTypeHandle(pMT, pSigBuilder);
1664             _ASSERTE(fSuccess);
1665         }
1666     }
1667
1668     if ((fieldFlags & ENCODE_FIELD_SIG_IndexInsteadOfToken) == 0)
1669     {
1670         // emit the rid
1671         pSigBuilder->AppendData(RidFromToken(fieldToken));
1672     }
1673     else
1674     {
1675         //
1676         // Write field index
1677         //
1678
1679         DWORD fieldIndex = pMT->GetIndexForFieldDesc(pField);
1680         _ASSERTE(fieldIndex < DWORD(pMT->GetNumStaticFields() + pMT->GetNumIntroducedInstanceFields()));
1681
1682         // have no token (e.g. it could be an array), encode slot number
1683         pSigBuilder->AppendData(fieldIndex);
1684     }
1685 }
1686
1687 #endif // DACCESS_COMPILE