Merge pull request #24232 from janvorli/fix-large-version-bubble-2
[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 /* static */
1110 BOOL ZapSig::EncodeMethod(
1111                     MethodDesc *          pMethod,
1112                     Module *              pInfoModule,
1113                     SigBuilder *          pSigBuilder,
1114                     LPVOID                pEncodeModuleContext,
1115                     ENCODEMODULE_CALLBACK pfnEncodeModule,
1116                     DEFINETOKEN_CALLBACK  pfnDefineToken,
1117                     CORINFO_RESOLVED_TOKEN * pResolvedToken,
1118                     CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken,
1119                     BOOL                  fEncodeUsingResolvedTokenSpecStreams)
1120 {
1121     CONTRACTL
1122     {
1123         THROWS;
1124         GC_TRIGGERS;
1125         MODE_ANY;
1126     }
1127     CONTRACTL_END;
1128
1129     TypeHandle ownerType;
1130
1131 #ifdef FEATURE_READYTORUN_COMPILER
1132
1133     // For methods encoded outside of the version bubble, we use pResolvedToken which describes the metadata token from which the method originated
1134     // For tokens inside the version bubble we are not constrained by the contents of pResolvedToken and as such we skip this codepath
1135     // Generic interfaces in canonical form are an exception, we need to get the real type from the pResolvedToken so that the lookup at runtime
1136     // can find the type in interface map.
1137     // FUTURE: This condition should likely be changed or reevaluated once support for smaller version bubbles is implemented.
1138     if (IsReadyToRunCompilation() && (!IsLargeVersionBubbleEnabled() || !pMethod->GetModule()->IsInCurrentVersionBubble() || (pMethod->IsSharedByGenericInstantiations() && pMethod->IsInterface())))
1139     {
1140         if (pMethod->IsNDirect())
1141         {
1142             ownerType = pMethod->GetMethodTable_NoLogging();
1143         }
1144         else
1145         {
1146             if (pResolvedToken == NULL)
1147             {
1148                 _ASSERTE(!"CORINFO_RESOLVED_TOKEN required to encode method!");
1149                 ThrowHR(E_FAIL);
1150             }
1151
1152             // Encode the referencing method type
1153             ownerType = TypeHandle(pResolvedToken->hClass);
1154         }
1155     }
1156     else
1157 #endif
1158     {
1159         ownerType = pMethod->GetMethodTable_NoLogging();
1160     }
1161
1162     ZapSig::ExternalTokens externalTokens = ZapSig::NormalTokens;
1163     if (pfnDefineToken != NULL)
1164     {
1165         externalTokens = ZapSig::IbcTokens;
1166     }
1167
1168     ZapSig zapSig(pInfoModule, pEncodeModuleContext, externalTokens,
1169                     (EncodeModuleCallback)    pfnEncodeModule, 
1170                     (TokenDefinitionCallback) pfnDefineToken);
1171
1172     //
1173     // output the sequence that represents the token for the method
1174     // 
1175     mdMethodDef methodToken               = pMethod->GetMemberDef_NoLogging();
1176     DWORD       methodFlags               = 0;
1177     BOOL        fMethodNeedsInstantiation = pMethod->HasMethodInstantiation() && !pMethod->IsGenericMethodDefinition();
1178
1179     if (pMethod->IsUnboxingStub())
1180         methodFlags |= ENCODE_METHOD_SIG_UnboxingStub;
1181     if (pMethod->IsInstantiatingStub())
1182         methodFlags |= ENCODE_METHOD_SIG_InstantiatingStub;
1183     if (fMethodNeedsInstantiation)
1184         methodFlags |= ENCODE_METHOD_SIG_MethodInstantiation;
1185
1186     //
1187     // For backward compatibility, IBC tokens use slightly different encoding:
1188     // - Owning type is uncoditionally encoded
1189     // - Number of method instantiation arguments is not encoded
1190     //
1191     if (externalTokens == ZapSig::IbcTokens)
1192     {
1193         // The type is always encoded before flags for IBC
1194         if (!zapSig.GetSignatureForTypeHandle(ownerType, pSigBuilder))
1195             return FALSE;
1196     }
1197     else
1198     {
1199         // Assume that the owner type is going to be needed
1200         methodFlags |= ENCODE_METHOD_SIG_OwnerType;
1201     }
1202
1203 #ifdef FEATURE_READYTORUN_COMPILER
1204     if (IsReadyToRunCompilation() && (pConstrainedResolvedToken != NULL))
1205     {
1206         methodFlags |= ENCODE_METHOD_SIG_Constrained;
1207     }
1208
1209     // FUTURE: This condition should likely be changed or reevaluated once support for smaller version bubbles is implemented.
1210     if (IsReadyToRunCompilation() && (!IsLargeVersionBubbleEnabled() || !pMethod->GetModule()->IsInCurrentVersionBubble()))
1211     {
1212         Module * pReferencingModule = pMethod->IsNDirect() ?
1213             pMethod->GetModule() :
1214             (Module *)pResolvedToken->tokenScope;
1215
1216         if (!pReferencingModule->IsInCurrentVersionBubble())
1217         {
1218             // FUTURE: Encoding of new cross-module references for ReadyToRun
1219             // This warning is hit for recursive cross-module inlining. It is commented out to avoid noise.
1220             // GetSvcLogger()->Printf(W("ReadyToRun: Method reference outside of current version bubble cannot be encoded\n"));
1221             ThrowHR(E_FAIL);
1222         }
1223
1224         methodToken = pMethod->IsNDirect() ?
1225             pMethod->GetMemberDef_NoLogging() :
1226             pResolvedToken->token;
1227
1228         if (TypeFromToken(methodToken) == mdtMethodSpec)
1229         {
1230             IfFailThrow(pReferencingModule->GetMDImport()->GetMethodSpecProps(methodToken, &methodToken, NULL, NULL));
1231         }
1232
1233         switch (TypeFromToken(methodToken))
1234         {
1235         case mdtMethodDef:
1236             _ASSERTE(pMethod->IsNDirect() || pResolvedToken->pTypeSpec == NULL);
1237             if (!ownerType.HasInstantiation() || ownerType.IsTypicalTypeDefinition())
1238             {
1239                 methodFlags &= ~ENCODE_METHOD_SIG_OwnerType;
1240             }
1241             break;
1242
1243         case mdtMemberRef:
1244             _ASSERTE(pResolvedToken != NULL);
1245             methodFlags |= ENCODE_METHOD_SIG_MemberRefToken;
1246
1247             if (pResolvedToken->pTypeSpec == NULL)
1248             {
1249                 methodFlags &= ~ENCODE_METHOD_SIG_OwnerType;
1250             }
1251             else
1252                 if (!(methodFlags & ENCODE_METHOD_SIG_InstantiatingStub))
1253                 {
1254                     if (SigPointer(pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec).IsPolyType(NULL) == hasNoVars)
1255                         methodFlags &= ~ENCODE_METHOD_SIG_OwnerType;
1256                 }
1257             break;
1258
1259         default:
1260             _ASSERTE(!"Unexpected method token type!");
1261             ThrowHR(E_NOTIMPL);
1262         }
1263     }
1264     else
1265 #endif
1266     if (IsNilToken(methodToken))
1267     {
1268         methodFlags |= ENCODE_METHOD_SIG_SlotInsteadOfToken;
1269     }
1270     else
1271     if (!pMethod->GetModule()->IsInCurrentVersionBubble())
1272     {
1273         // Using a method defined in another version bubble. We can assume the slot number is stable only for real interface methods.
1274         if (!ownerType.IsInterface() || pMethod->IsStatic() || pMethod->HasMethodInstantiation())
1275         {
1276             // FUTURE TODO: Version resilience
1277             _ASSERTE(!"References to non-interface methods not yet supported in version resilient images");
1278             IfFailThrow(E_FAIL);
1279         }
1280         methodFlags |= ENCODE_METHOD_SIG_SlotInsteadOfToken;
1281     }
1282     else
1283     {
1284         Module * pTypeHandleModule = pMethod->GetModule();
1285         
1286         if (pTypeHandleModule != pInfoModule) 
1287         {
1288             // During IBC profiling this calls
1289             //     code:Module.EncodeModuleHelper
1290             // During ngen this calls
1291             //     code:ZapImportTable.EncodeModuleHelper)
1292             //
1293             DWORD index = (*((EncodeModuleCallback) pfnEncodeModule))(pEncodeModuleContext, pTypeHandleModule);
1294             
1295             if (index == ENCODE_MODULE_FAILED)
1296             {
1297                 return FALSE;
1298             }
1299
1300             // If the method handle's module is different that the pInfoModule 
1301             // we need to call the TokenDefinitionCallback function
1302             // to record the names for the external module tokens
1303             //
1304             if ((index != 0) && (pfnDefineToken != NULL))
1305             {
1306                 //
1307                 // We do not want to log the metadata lookups that we perform here
1308                 // 
1309                 IBCLoggingDisabler   disableLogging;
1310                 
1311                 // During IBC profiling this calls
1312                 //     code:Module::TokenDefinitionHelper()
1313                 (*((TokenDefinitionCallback) pfnDefineToken))(pEncodeModuleContext, pTypeHandleModule, index, &methodToken);
1314             }
1315         }
1316         else
1317         {
1318             _ASSERTE(pInfoModule = pMethod->GetModule());
1319         }
1320
1321         if (!ownerType.HasInstantiation())
1322             methodFlags &= ~ENCODE_METHOD_SIG_OwnerType;
1323     }
1324
1325     //
1326     // output the flags
1327     // 
1328     pSigBuilder->AppendData(methodFlags);
1329
1330     if (methodFlags & ENCODE_METHOD_SIG_OwnerType)
1331     {
1332         if (fEncodeUsingResolvedTokenSpecStreams && pResolvedToken != NULL && pResolvedToken->pTypeSpec != NULL)
1333         {
1334             _ASSERTE(pResolvedToken->cbTypeSpec > 0);
1335
1336             if (IsReadyToRunCompilation() && pMethod->GetModule()->IsInCurrentVersionBubble() && pInfoModule != (Module *) pResolvedToken->tokenScope)
1337             {
1338                 pSigBuilder->AppendElementType((CorElementType)ELEMENT_TYPE_MODULE_ZAPSIG);
1339                 DWORD index = (*((EncodeModuleCallback)pfnEncodeModule))(pEncodeModuleContext, (Module *) pResolvedToken->tokenScope);
1340                 pSigBuilder->AppendData(index);
1341             }
1342
1343             pSigBuilder->AppendBlob((PVOID)pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec);
1344         }
1345         else
1346         {
1347             if (!zapSig.GetSignatureForTypeHandle(ownerType, pSigBuilder))
1348                 return FALSE;
1349         }
1350     }
1351
1352     if ((methodFlags & ENCODE_METHOD_SIG_SlotInsteadOfToken) == 0)
1353     {
1354         // emit the rid
1355         pSigBuilder->AppendData(RidFromToken(methodToken));
1356     }
1357     else
1358     {
1359         // have no token (e.g. it could be an array), encode slot number
1360         pSigBuilder->AppendData(pMethod->GetSlot());
1361     }
1362
1363     if ((methodFlags & ENCODE_METHOD_SIG_MethodInstantiation) != 0)
1364     {
1365         if (fEncodeUsingResolvedTokenSpecStreams && pResolvedToken != NULL && pResolvedToken->pMethodSpec != NULL)
1366         {
1367             _ASSERTE(pResolvedToken->cbMethodSpec > 1);
1368
1369             if (*(BYTE*)pResolvedToken->pMethodSpec != (BYTE)IMAGE_CEE_CS_CALLCONV_GENERICINST)
1370                 ThrowHR(COR_E_BADIMAGEFORMAT);
1371
1372             pSigBuilder->AppendBlob((PVOID)(((BYTE*)pResolvedToken->pMethodSpec) + 1), pResolvedToken->cbMethodSpec - 1);
1373         }
1374         else
1375         {
1376             Instantiation inst = pMethod->GetMethodInstantiation();
1377
1378             // Number of method instantiation arguments is not encoded in IBC tokens - see comment above
1379             if (externalTokens != ZapSig::IbcTokens)
1380                 pSigBuilder->AppendData(inst.GetNumArgs());
1381
1382             for (DWORD i = 0; i < inst.GetNumArgs(); i++)
1383             {
1384                 TypeHandle t = inst[i];
1385                 _ASSERTE(!t.IsNull());
1386
1387                 if (!zapSig.GetSignatureForTypeHandle(t, pSigBuilder))
1388                     return FALSE;
1389             }
1390         }
1391     }
1392
1393 #ifdef FEATURE_READYTORUN_COMPILER
1394     if ((methodFlags & ENCODE_METHOD_SIG_Constrained) != 0)
1395     {
1396         if (fEncodeUsingResolvedTokenSpecStreams && pConstrainedResolvedToken->pTypeSpec != NULL)
1397         {
1398             _ASSERTE(pConstrainedResolvedToken->cbTypeSpec > 0);
1399             pSigBuilder->AppendBlob((PVOID)pConstrainedResolvedToken->pTypeSpec, pConstrainedResolvedToken->cbTypeSpec);
1400         }
1401         else
1402         {
1403             if (!zapSig.GetSignatureForTypeHandle(TypeHandle(pConstrainedResolvedToken->hClass), pSigBuilder))
1404                 return FALSE;
1405         }
1406     }
1407 #endif
1408
1409     return TRUE;
1410 }
1411
1412 void ZapSig::EncodeField(
1413         FieldDesc              *pField,
1414         Module                 *pInfoModule,
1415         SigBuilder             *pSigBuilder,
1416         LPVOID                 pEncodeModuleContext,
1417         ENCODEMODULE_CALLBACK  pfnEncodeModule,
1418         CORINFO_RESOLVED_TOKEN *pResolvedToken,
1419         BOOL                   fEncodeUsingResolvedTokenSpecStreams)
1420 {
1421     CONTRACTL
1422     {
1423         THROWS;
1424         GC_TRIGGERS;
1425         MODE_ANY;
1426     }
1427     CONTRACTL_END;
1428
1429     MethodTable * pMT;
1430
1431     mdMethodDef fieldToken = pField->GetMemberDef();
1432     DWORD fieldFlags = ENCODE_FIELD_SIG_OwnerType;
1433
1434 #ifdef FEATURE_READYTORUN_COMPILER
1435     if (IsReadyToRunCompilation())
1436     {
1437         if (pResolvedToken == NULL)
1438         {
1439             _ASSERTE(!"CORINFO_RESOLVED_TOKEN required to encode field!");
1440             ThrowHR(E_FAIL);
1441         }
1442
1443         // Encode the referencing field type
1444         pMT = (MethodTable *)(pResolvedToken->hClass);
1445
1446         Module * pReferencingModule = (Module *)pResolvedToken->tokenScope;
1447
1448         if (!pReferencingModule->IsInCurrentVersionBubble())
1449         {
1450             // FUTURE: Encoding of new cross-module references for ReadyToRun
1451             // This warning is hit for recursive cross-module inlining. It is commented out to avoid noise.
1452             // GetSvcLogger()->Printf(W("ReadyToRun: Field reference outside of current version bubble cannot be encoded\n"));
1453             ThrowHR(E_FAIL);
1454         }
1455         _ASSERTE(pReferencingModule == GetAppDomain()->ToCompilationDomain()->GetTargetModule());
1456
1457         fieldToken = pResolvedToken->token;
1458
1459         switch (TypeFromToken(fieldToken))
1460         {
1461         case mdtFieldDef:
1462             _ASSERTE(pResolvedToken->pTypeSpec == NULL);
1463             fieldFlags &= ~ENCODE_FIELD_SIG_OwnerType;
1464             break;
1465
1466         case mdtMemberRef:
1467             fieldFlags |= ENCODE_FIELD_SIG_MemberRefToken;
1468
1469             if (pResolvedToken->pTypeSpec == NULL)
1470             {
1471                 fieldFlags &= ~ENCODE_METHOD_SIG_OwnerType;
1472             }
1473             else
1474             {
1475                 if (SigPointer(pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec).IsPolyType(NULL) == hasNoVars)
1476                     fieldFlags &= ~ENCODE_METHOD_SIG_OwnerType;
1477             }
1478             break;
1479
1480         default:
1481             _ASSERTE(!"Unexpected field token type!");
1482             ThrowHR(E_NOTIMPL);
1483         }
1484     }
1485     else
1486 #endif
1487     {
1488         pMT = pField->GetApproxEnclosingMethodTable();
1489
1490         fieldFlags |= ENCODE_FIELD_SIG_IndexInsteadOfToken;
1491     }
1492
1493     //
1494     // output the flags
1495     // 
1496     pSigBuilder->AppendData(fieldFlags);
1497
1498     if (fieldFlags & ENCODE_FIELD_SIG_OwnerType)
1499     {
1500         if (fEncodeUsingResolvedTokenSpecStreams && pResolvedToken != NULL && pResolvedToken->pTypeSpec != NULL)
1501         {
1502             _ASSERTE(pResolvedToken->cbTypeSpec > 0);
1503             pSigBuilder->AppendBlob((PVOID)pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec);
1504         }
1505         else
1506         {
1507             ZapSig zapSig(pInfoModule, pEncodeModuleContext, ZapSig::NormalTokens,
1508                 (EncodeModuleCallback)pfnEncodeModule, NULL);
1509
1510             //
1511             // Write class
1512             //
1513             BOOL fSuccess;
1514             fSuccess = zapSig.GetSignatureForTypeHandle(pMT, pSigBuilder);
1515             _ASSERTE(fSuccess);
1516         }
1517     }
1518
1519     if ((fieldFlags & ENCODE_FIELD_SIG_IndexInsteadOfToken) == 0)
1520     {
1521         // emit the rid
1522         pSigBuilder->AppendData(RidFromToken(fieldToken));
1523     }
1524     else
1525     {
1526         //
1527         // Write field index
1528         //
1529
1530         DWORD fieldIndex = pMT->GetIndexForFieldDesc(pField);
1531         _ASSERTE(fieldIndex < DWORD(pMT->GetNumStaticFields() + pMT->GetNumIntroducedInstanceFields()));
1532
1533         // have no token (e.g. it could be an array), encode slot number
1534         pSigBuilder->AppendData(fieldIndex);
1535     }
1536 }
1537
1538 #endif // DACCESS_COMPILE