Remove relocations for MethodTable's vtable-1st-level-indirection
[platform/upstream/dotnet/runtime.git] / src / coreclr / src / vm / jitinterface.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: JITinterface.CPP
6 //
7
8 // ===========================================================================
9
10
11 #include "common.h"
12 #include "jitinterface.h"
13 #include "codeman.h"
14 #include "method.hpp"
15 #include "class.h"
16 #include "object.h"
17 #include "field.h"
18 #include "stublink.h"
19 #include "virtualcallstub.h"
20 #include "corjit.h"
21 #include "eeconfig.h"
22 #include "excep.h"
23 #include "log.h"
24 #include "excep.h"
25 #include "float.h"      // for isnan
26 #include "dbginterface.h"
27 #include "security.h"
28 #include "dllimport.h"
29 #include "gcheaputilities.h"
30 #include "comdelegate.h"
31 #include "jitperf.h" // to track jit perf
32 #include "corprof.h"
33 #include "eeprofinterfaces.h"
34 #include "perfcounters.h"
35 #ifdef PROFILING_SUPPORTED
36 #include "proftoeeinterfaceimpl.h"
37 #include "eetoprofinterfaceimpl.h"
38 #include "eetoprofinterfaceimpl.inl"
39 #include "profilepriv.h"
40 #endif
41 #include "tls.h"
42 #include "ecall.h"
43 #include "generics.h"
44 #include "typestring.h"
45 #include "stackprobe.h"
46 #include "typedesc.h"
47 #include "genericdict.h"
48 #include "array.h"
49 #include "debuginfostore.h"
50 #include "security.h"
51 #include "safemath.h"
52 #include "runtimehandles.h"
53 #include "sigbuilder.h"
54 #include "openum.h"
55 #ifdef HAVE_GCCOVER
56 #include "gccover.h"
57 #endif // HAVE_GCCOVER
58
59 #include "mdaassistants.h"
60
61 #ifdef FEATURE_PREJIT
62 #include "compile.h"
63 #include "corcompile.h"
64 #endif // FEATURE_PREJIT
65
66
67 #ifdef FEATURE_INTERPRETER
68 #include "interpreter.h"
69 #endif // FEATURE_INTERPRETER
70
71 // The Stack Overflow probe takes place in the COOPERATIVE_TRANSITION_BEGIN() macro
72 //
73
74 #define JIT_TO_EE_TRANSITION()          MAKE_CURRENT_THREAD_AVAILABLE_EX(m_pThread);                \
75                                         _ASSERTE(CURRENT_THREAD == GetThread());                    \
76                                         INSTALL_UNWIND_AND_CONTINUE_HANDLER_NO_PROBE;               \
77                                         COOPERATIVE_TRANSITION_BEGIN();                             \
78                                         START_NON_JIT_PERF();
79
80 #define EE_TO_JIT_TRANSITION()          STOP_NON_JIT_PERF();                                        \
81                                         COOPERATIVE_TRANSITION_END();                               \
82                                         UNINSTALL_UNWIND_AND_CONTINUE_HANDLER_NO_PROBE;
83
84 #define JIT_TO_EE_TRANSITION_LEAF()
85 #define EE_TO_JIT_TRANSITION_LEAF()
86
87
88 #if defined(CROSSGEN_COMPILE)
89 static const char *const hlpNameTable[CORINFO_HELP_COUNT] = {
90 #define JITHELPER(code, pfnHelper, sig) #code,
91 #include "jithelpers.h"
92 };
93 #endif
94
95 #ifdef DACCESS_COMPILE
96
97 // The real definitions are in jithelpers.cpp. However, those files are not included in the DAC build.
98 // Hence, we add them here.
99 GARY_IMPL(VMHELPDEF, hlpFuncTable, CORINFO_HELP_COUNT);
100 GARY_IMPL(VMHELPDEF, hlpDynamicFuncTable, DYNAMIC_CORINFO_HELP_COUNT);
101
102 #else // DACCESS_COMPILE
103
104 /*********************************************************************/
105
106 #if defined(ENABLE_PERF_COUNTERS)
107 LARGE_INTEGER g_lastTimeInJitCompilation;
108 #endif
109
110 /*********************************************************************/
111
112 inline CORINFO_MODULE_HANDLE GetScopeHandle(MethodDesc* method) 
113 {
114     LIMITED_METHOD_CONTRACT;
115     if (method->IsDynamicMethod())
116     {
117         return MakeDynamicScope(method->AsDynamicMethodDesc()->GetResolver());
118     }
119     else
120     {
121         return GetScopeHandle(method->GetModule());
122     }
123 }
124
125 //This is common refactored code from within several of the access check functions.
126 BOOL ModifyCheckForDynamicMethod(DynamicResolver *pResolver,
127                                  TypeHandle *pOwnerTypeForSecurity,
128                                  AccessCheckOptions::AccessCheckType *pAccessCheckType,
129                                  DynamicResolver** ppAccessContext)
130 {
131     CONTRACTL {
132         STANDARD_VM_CHECK;
133         PRECONDITION(CheckPointer(pResolver));
134         PRECONDITION(CheckPointer(pOwnerTypeForSecurity));
135         PRECONDITION(CheckPointer(pAccessCheckType));
136         PRECONDITION(CheckPointer(ppAccessContext));
137         PRECONDITION(*pAccessCheckType == AccessCheckOptions::kNormalAccessibilityChecks);
138     } CONTRACTL_END;
139
140     BOOL doAccessCheck = TRUE;
141
142     //Do not blindly initialize fields, since they've already got important values.
143     DynamicResolver::SecurityControlFlags dwSecurityFlags = DynamicResolver::Default;
144         
145     TypeHandle dynamicOwner;
146     pResolver->GetJitContext(&dwSecurityFlags, &dynamicOwner);
147     if (!dynamicOwner.IsNull())
148         *pOwnerTypeForSecurity = dynamicOwner;
149
150     if (dwSecurityFlags & DynamicResolver::SkipVisibilityChecks)
151     {
152         doAccessCheck = FALSE;
153     }
154     else if (dwSecurityFlags & DynamicResolver::RestrictedSkipVisibilityChecks)
155     {
156         *pAccessCheckType = AccessCheckOptions::kRestrictedMemberAccessNoTransparency;
157     }
158     else
159     {
160         *pAccessCheckType = AccessCheckOptions::kNormalAccessNoTransparency;
161     }
162
163     return doAccessCheck;
164 }
165
166 /*****************************************************************************/
167
168 // Initialize from data we passed across to the JIT
169 inline static void GetTypeContext(const CORINFO_SIG_INST *info, SigTypeContext *pTypeContext)
170 {
171     LIMITED_METHOD_CONTRACT;
172     SigTypeContext::InitTypeContext(
173         Instantiation((TypeHandle *) info->classInst, info->classInstCount), 
174         Instantiation((TypeHandle *) info->methInst, info->methInstCount), 
175         pTypeContext);
176 }
177
178 static MethodDesc* GetMethodFromContext(CORINFO_CONTEXT_HANDLE context)
179 {
180     LIMITED_METHOD_CONTRACT;
181     if (((size_t) context & CORINFO_CONTEXTFLAGS_MASK) == CORINFO_CONTEXTFLAGS_CLASS)
182     {
183         return NULL;
184     }
185     else
186     {
187         return GetMethod((CORINFO_METHOD_HANDLE)((size_t) context & ~CORINFO_CONTEXTFLAGS_MASK));
188     }
189 }
190
191 static TypeHandle GetTypeFromContext(CORINFO_CONTEXT_HANDLE context)
192 {
193     LIMITED_METHOD_CONTRACT;
194     if (((size_t) context & CORINFO_CONTEXTFLAGS_MASK) == CORINFO_CONTEXTFLAGS_CLASS)
195     {
196         return TypeHandle((CORINFO_CLASS_HANDLE) ((size_t) context & ~CORINFO_CONTEXTFLAGS_MASK));
197     }
198     else
199     {
200         MethodTable * pMT = GetMethodFromContext(context)->GetMethodTable();
201         return TypeHandle(pMT);
202     }
203 }
204
205 // Initialize from a context parameter passed to the JIT and back.  This is a parameter
206 // that indicates which method is being jitted.
207
208 inline static void GetTypeContext(CORINFO_CONTEXT_HANDLE context, SigTypeContext *pTypeContext)
209 {
210     CONTRACTL
211     {
212         NOTHROW;
213         GC_NOTRIGGER;
214         SO_TOLERANT;
215         MODE_ANY;
216         PRECONDITION(context != NULL);
217     }
218     CONTRACTL_END;
219     if (GetMethodFromContext(context))
220     {
221         SigTypeContext::InitTypeContext(GetMethodFromContext(context), pTypeContext);
222     }
223     else
224     {
225         SigTypeContext::InitTypeContext(GetTypeFromContext(context), pTypeContext);
226     }
227 }
228
229 static BOOL ContextIsShared(CORINFO_CONTEXT_HANDLE context)
230 {
231     LIMITED_METHOD_CONTRACT;
232     MethodDesc *pContextMD = GetMethodFromContext(context);
233     if (pContextMD != NULL)
234     {
235         return pContextMD->IsSharedByGenericInstantiations();
236     }
237     else
238     {
239         // Type handle contexts are non-shared and are used for inlining of
240         // non-generic methods in generic classes
241         return FALSE;
242     }
243 }
244
245 // Returns true if context is providing any generic variables
246 static BOOL ContextIsInstantiated(CORINFO_CONTEXT_HANDLE context)
247 {
248     LIMITED_METHOD_CONTRACT;
249     if (GetMethodFromContext(context))
250     {
251         return GetMethodFromContext(context)->HasClassOrMethodInstantiation();
252     }
253     else
254     {
255         return GetTypeFromContext(context).HasInstantiation();
256     }
257 }
258
259 /*********************************************************************/
260 // This normalizes EE type information into the form expected by the JIT.
261 //
262 // If typeHnd contains exact type information, then *clsRet will contain
263 // the normalized CORINFO_CLASS_HANDLE information on return.
264
265 // Static
266 CorInfoType CEEInfo::asCorInfoType(CorElementType eeType,
267                                    TypeHandle typeHnd, /* optional in */
268                                    CORINFO_CLASS_HANDLE *clsRet/* optional out */ ) {
269     CONTRACT(CorInfoType) {
270         THROWS;
271         GC_TRIGGERS;
272         PRECONDITION((CorTypeInfo::IsGenericVariable(eeType)) == 
273                      (!typeHnd.IsNull() && typeHnd.IsGenericVariable()));
274         PRECONDITION(eeType != ELEMENT_TYPE_GENERICINST);
275     } CONTRACT_END;
276
277     TypeHandle typeHndUpdated = typeHnd;
278
279     if (!typeHnd.IsNull())
280     {
281         CorElementType normType = typeHnd.GetInternalCorElementType();
282         // If we have a type handle, then it has the better type
283         // in some cases
284         if (eeType == ELEMENT_TYPE_VALUETYPE && !CorTypeInfo::IsObjRef(normType))
285             eeType = normType;
286
287         // Zap the typeHnd when the type _really_ is a primitive
288         // as far as verification is concerned. Returning a null class
289         // handle means it is is a primitive.
290         //
291         // Enums are exactly like primitives, even from a verification standpoint,
292         // so we zap the type handle in this case.
293         //
294         // However RuntimeTypeHandle etc. are reported as E_T_INT (or something like that)
295         // but don't count as primitives as far as verification is concerned...
296         //
297         // To make things stranger, TypedReference returns true for "IsTruePrimitive".
298         // However the JIT likes us to report the type handle in that case.
299         if (!typeHnd.IsTypeDesc() && (
300                 (typeHnd.AsMethodTable()->IsTruePrimitive() && typeHnd != TypeHandle(g_TypedReferenceMT))
301                     || typeHnd.AsMethodTable()->IsEnum()) )
302         {
303             typeHndUpdated = TypeHandle();
304         }
305
306     }
307
308     static const BYTE map[] = {
309         CORINFO_TYPE_UNDEF,
310         CORINFO_TYPE_VOID,
311         CORINFO_TYPE_BOOL,
312         CORINFO_TYPE_CHAR,
313         CORINFO_TYPE_BYTE,
314         CORINFO_TYPE_UBYTE,
315         CORINFO_TYPE_SHORT,
316         CORINFO_TYPE_USHORT,
317         CORINFO_TYPE_INT,
318         CORINFO_TYPE_UINT,
319         CORINFO_TYPE_LONG,
320         CORINFO_TYPE_ULONG,
321         CORINFO_TYPE_FLOAT,
322         CORINFO_TYPE_DOUBLE,
323         CORINFO_TYPE_STRING,
324         CORINFO_TYPE_PTR,            // PTR
325         CORINFO_TYPE_BYREF,
326         CORINFO_TYPE_VALUECLASS,
327         CORINFO_TYPE_CLASS,
328         CORINFO_TYPE_VAR,            // VAR (type variable)
329         CORINFO_TYPE_CLASS,          // ARRAY
330         CORINFO_TYPE_CLASS,          // WITH
331         CORINFO_TYPE_REFANY,
332         CORINFO_TYPE_UNDEF,          // VALUEARRAY_UNSUPPORTED
333         CORINFO_TYPE_NATIVEINT,      // I
334         CORINFO_TYPE_NATIVEUINT,     // U
335         CORINFO_TYPE_UNDEF,          // R_UNSUPPORTED
336
337         // put the correct type when we know our implementation
338         CORINFO_TYPE_PTR,            // FNPTR
339         CORINFO_TYPE_CLASS,          // OBJECT
340         CORINFO_TYPE_CLASS,          // SZARRAY
341         CORINFO_TYPE_VAR,            // MVAR
342
343         CORINFO_TYPE_UNDEF,          // CMOD_REQD
344         CORINFO_TYPE_UNDEF,          // CMOD_OPT
345         CORINFO_TYPE_UNDEF,          // INTERNAL
346         };
347
348     _ASSERTE(sizeof(map) == ELEMENT_TYPE_MAX);
349     _ASSERTE(eeType < (CorElementType) sizeof(map));
350         // spot check of the map
351     _ASSERTE((CorInfoType) map[ELEMENT_TYPE_I4] == CORINFO_TYPE_INT);
352     _ASSERTE((CorInfoType) map[ELEMENT_TYPE_PTR] == CORINFO_TYPE_PTR);
353     _ASSERTE((CorInfoType) map[ELEMENT_TYPE_TYPEDBYREF] == CORINFO_TYPE_REFANY);
354
355     CorInfoType res = ((unsigned)eeType < ELEMENT_TYPE_MAX) ? ((CorInfoType) map[(unsigned)eeType]) : CORINFO_TYPE_UNDEF;
356
357     if (clsRet)
358         *clsRet = CORINFO_CLASS_HANDLE(typeHndUpdated.AsPtr());
359
360     RETURN res;
361 }
362
363
364 inline static CorInfoType toJitType(TypeHandle typeHnd, CORINFO_CLASS_HANDLE *clsRet = NULL)
365 {
366     WRAPPER_NO_CONTRACT;
367     return CEEInfo::asCorInfoType(typeHnd.GetInternalCorElementType(), typeHnd, clsRet);
368 }
369
370 #ifdef _DEBUG
371 void DebugSecurityCalloutStress(CORINFO_METHOD_HANDLE methodBeingCompiledHnd,
372                                 CorInfoIsAccessAllowedResult& currentAnswer,
373                                 CorInfoSecurityRuntimeChecks& currentRuntimeChecks)
374 {
375     WRAPPER_NO_CONTRACT;
376     if (currentAnswer != CORINFO_ACCESS_ALLOWED)
377     {
378         return;
379     }
380     static ConfigDWORD AlwaysInsertCallout;
381     switch (AlwaysInsertCallout.val(CLRConfig::INTERNAL_Security_AlwaysInsertCallout))
382     {
383     case 0: //No stress
384         return;
385     case 1: //Always
386         break;
387     default: //2 (or anything else), do so half the time
388         if (((size_t(methodBeingCompiledHnd) / sizeof(void*)) % 64) < 32)
389             return;
390     }
391     //Do the stress
392     currentAnswer = CORINFO_ACCESS_RUNTIME_CHECK;
393     currentRuntimeChecks = CORINFO_ACCESS_SECURITY_NONE;
394 }
395 #else
396 #define DebugSecurityCalloutStress(a, b, c) do {} while(0)
397 #endif //_DEBUG
398
399 void CheckForEquivalenceAndLoadTypeBeforeCodeIsRun(Module *pModule, mdToken token, Module *pDefModule, mdToken defToken, const SigParser *ptr, SigTypeContext *pTypeContext, void *pData)
400 {
401     CONTRACTL
402     {
403         THROWS;
404         GC_TRIGGERS;
405         SO_INTOLERANT;
406     }
407     CONTRACTL_END;
408
409     if (IsTypeDefEquivalent(defToken, pDefModule))
410     {
411         SigPointer sigPtr(*ptr);
412         TypeHandle th = sigPtr.GetTypeHandleThrowing(pModule, pTypeContext);
413         ((ICorDynamicInfo *)pData)->classMustBeLoadedBeforeCodeIsRun(CORINFO_CLASS_HANDLE(th.AsPtr()));
414     }
415 }
416
417 inline static void TypeEquivalenceFixupSpecificationHelper(ICorDynamicInfo * pCorInfo, MethodDesc *pMD)
418 {
419     STANDARD_VM_CONTRACT;
420
421     // A fixup is necessary to ensure that the parameters to the method are loaded before the method
422     // is called. In these cases we will not perform the appropriate loading when we load parameter
423     // types because with type equivalence, the parameter types at the call site do not necessarily
424     // match that those in the actual function. (They must be equivalent, but not necessarily the same.)
425     // In non-ngen scenarios this code here will force the types to be loaded directly by the call to
426     // HasTypeEquivalentStructParameters.
427     if (!pMD->IsVirtual())
428     {
429         if (pMD->HasTypeEquivalentStructParameters())
430         {
431             if (IsCompilationProcess())
432                 pMD->WalkValueTypeParameters(pMD->GetMethodTable(), CheckForEquivalenceAndLoadTypeBeforeCodeIsRun, pCorInfo);
433         }
434     }
435     else
436     {
437         if (pMD->GetMethodTable()->DependsOnEquivalentOrForwardedStructs())
438         {
439             if (pMD->HasTypeEquivalentStructParameters())
440                 pCorInfo->classMustBeLoadedBeforeCodeIsRun((CORINFO_CLASS_HANDLE)pMD->GetMethodTable());
441         }
442     }
443 }
444
445 //---------------------------------------------------------------------------------------
446 // 
447 //@GENERICS:
448 // The method handle is used to instantiate method and class type parameters
449 // It's also used to determine whether an extra dictionary parameter is required
450 //
451 // sig          - Input metadata signature
452 // scopeHnd     - The signature is to be interpreted in the context of this scope (module)
453 // token        - Metadata token used to refer to the signature (may be mdTokenNil for dynamic methods)
454 // sigRet       - Resulting output signature in a format that is understood by native compilers
455 // pContextMD   - The method with any instantiation information (may be NULL)
456 // localSig     - Is it a local variables declaration, or a method signature (with return type, etc).
457 // contextType  - The type with any instantiaton information
458 // 
459 //static
460 void 
461 CEEInfo::ConvToJitSig(
462     PCCOR_SIGNATURE       pSig, 
463     DWORD                 cbSig, 
464     CORINFO_MODULE_HANDLE scopeHnd, 
465     mdToken               token, 
466     CORINFO_SIG_INFO *    sigRet,
467     MethodDesc *          pContextMD,
468     bool                  localSig,
469     TypeHandle            contextType)
470 {
471     CONTRACTL {
472         THROWS;
473         GC_TRIGGERS;
474     } CONTRACTL_END;
475
476     SigTypeContext typeContext;
477
478     if (pContextMD)
479     {
480         SigTypeContext::InitTypeContext(pContextMD, contextType, &typeContext);
481     }
482     else
483     {
484         SigTypeContext::InitTypeContext(contextType, &typeContext);
485     }
486
487     _ASSERTE(CORINFO_CALLCONV_DEFAULT == (CorInfoCallConv) IMAGE_CEE_CS_CALLCONV_DEFAULT);
488     _ASSERTE(CORINFO_CALLCONV_VARARG == (CorInfoCallConv) IMAGE_CEE_CS_CALLCONV_VARARG);
489     _ASSERTE(CORINFO_CALLCONV_MASK == (CorInfoCallConv) IMAGE_CEE_CS_CALLCONV_MASK);
490     _ASSERTE(CORINFO_CALLCONV_HASTHIS == (CorInfoCallConv) IMAGE_CEE_CS_CALLCONV_HASTHIS);
491
492     TypeHandle typeHnd = TypeHandle();
493
494     sigRet->pSig = pSig;
495     sigRet->cbSig = cbSig;
496     sigRet->retTypeClass = 0;
497     sigRet->retTypeSigClass = 0;
498     sigRet->scope = scopeHnd;
499     sigRet->token = token;
500     sigRet->sigInst.classInst = (CORINFO_CLASS_HANDLE *) typeContext.m_classInst.GetRawArgs();
501     sigRet->sigInst.classInstCount = (unsigned) typeContext.m_classInst.GetNumArgs();
502     sigRet->sigInst.methInst = (CORINFO_CLASS_HANDLE *) typeContext.m_methodInst.GetRawArgs();
503     sigRet->sigInst.methInstCount = (unsigned) typeContext.m_methodInst.GetNumArgs();
504
505     SigPointer sig(pSig, cbSig);
506
507     if (!localSig)
508     {
509         // This is a method signature which includes calling convention, return type, 
510         // arguments, etc
511
512         _ASSERTE(!sig.IsNull());
513         Module * module = GetModule(scopeHnd);
514         sigRet->flags = 0;
515
516         ULONG data;
517         IfFailThrow(sig.GetCallingConvInfo(&data));
518         sigRet->callConv = (CorInfoCallConv) data;
519
520         if ((isCallConv(sigRet->callConv, IMAGE_CEE_CS_CALLCONV_VARARG)) ||
521             (isCallConv(sigRet->callConv, IMAGE_CEE_CS_CALLCONV_NATIVEVARARG)))
522         {
523             // This signature corresponds to a method that uses varargs, which are not supported.
524              COMPlusThrow(kInvalidProgramException, IDS_EE_VARARG_NOT_SUPPORTED);
525         }
526
527         // Skip number of type arguments
528         if (sigRet->callConv & IMAGE_CEE_CS_CALLCONV_GENERIC)
529           IfFailThrow(sig.GetData(NULL));
530
531         ULONG numArgs;
532         IfFailThrow(sig.GetData(&numArgs));
533         if (numArgs != (unsigned short) numArgs)
534             COMPlusThrowHR(COR_E_INVALIDPROGRAM);
535
536         sigRet->numArgs = (unsigned short) numArgs;
537
538         CorElementType type = sig.PeekElemTypeClosed(module, &typeContext);
539
540         if (!CorTypeInfo::IsPrimitiveType(type))
541         {
542             typeHnd = sig.GetTypeHandleThrowing(module, &typeContext);
543             _ASSERTE(!typeHnd.IsNull());
544
545             // I believe it doesn't make any diff. if this is
546             // GetInternalCorElementType or GetSignatureCorElementType
547             type = typeHnd.GetSignatureCorElementType();
548
549         }
550         sigRet->retType = CEEInfo::asCorInfoType(type, typeHnd, &sigRet->retTypeClass);
551         sigRet->retTypeSigClass = CORINFO_CLASS_HANDLE(typeHnd.AsPtr());
552
553         IfFailThrow(sig.SkipExactlyOne());  // must to a skip so we skip any class tokens associated with the return type
554         _ASSERTE(sigRet->retType < CORINFO_TYPE_COUNT);
555
556         sigRet->args = (CORINFO_ARG_LIST_HANDLE)sig.GetPtr();
557     } 
558     else
559     {
560         // This is local variables declaration
561
562         sigRet->callConv = CORINFO_CALLCONV_DEFAULT;
563         sigRet->retType = CORINFO_TYPE_VOID;
564         sigRet->flags   = CORINFO_SIGFLAG_IS_LOCAL_SIG;
565         sigRet->numArgs = 0;
566         if (!sig.IsNull())
567         {
568             ULONG callConv;
569             IfFailThrow(sig.GetCallingConvInfo(&callConv));
570             if (callConv != IMAGE_CEE_CS_CALLCONV_LOCAL_SIG)
571             {
572                 COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_CALLCONV_NOT_LOCAL_SIG);
573             }
574
575             ULONG numArgs;
576             IfFailThrow(sig.GetData(&numArgs));
577             
578             if (numArgs != (unsigned short) numArgs)
579                 COMPlusThrowHR(COR_E_INVALIDPROGRAM);
580
581             sigRet->numArgs = (unsigned short) numArgs;
582         }
583
584         sigRet->args = (CORINFO_ARG_LIST_HANDLE)sig.GetPtr();
585     }
586
587     _ASSERTE(SigInfoFlagsAreValid(sigRet));
588 } // CEEInfo::ConvToJitSig
589
590 //---------------------------------------------------------------------------------------
591 // 
592 CORINFO_CLASS_HANDLE CEEInfo::getTokenTypeAsHandle (CORINFO_RESOLVED_TOKEN * pResolvedToken)
593 {
594     CONTRACTL {
595         SO_TOLERANT;
596         THROWS;
597         GC_TRIGGERS;
598         MODE_PREEMPTIVE;
599     } CONTRACTL_END;
600
601     CORINFO_CLASS_HANDLE tokenType = NULL;
602
603     JIT_TO_EE_TRANSITION();
604
605     _ASSERTE((pResolvedToken->hMethod == NULL) || (pResolvedToken->hField == NULL));
606
607     BinderClassID classID = CLASS__TYPE_HANDLE;
608
609     if (pResolvedToken->hMethod != NULL)
610     {
611         classID = CLASS__METHOD_HANDLE;
612     }
613     else
614     if (pResolvedToken->hField != NULL)
615     {
616         classID = CLASS__FIELD_HANDLE;
617     }
618
619     tokenType = CORINFO_CLASS_HANDLE(MscorlibBinder::GetClass(classID));
620
621     EE_TO_JIT_TRANSITION();
622
623     return tokenType;
624 }
625
626 /*********************************************************************/
627 size_t CEEInfo::findNameOfToken (
628             CORINFO_MODULE_HANDLE       scopeHnd,
629             mdToken                     metaTOK,
630             __out_ecount (FQNameCapacity)  char * szFQName,
631             size_t FQNameCapacity)
632 {
633     CONTRACTL {
634         SO_TOLERANT;
635         THROWS;
636         GC_TRIGGERS;
637         MODE_PREEMPTIVE;
638     } CONTRACTL_END;
639
640     size_t NameLen = 0;
641
642     JIT_TO_EE_TRANSITION();
643
644     if (IsDynamicScope(scopeHnd))
645     {
646         strncpy_s (szFQName, FQNameCapacity, "DynamicToken", FQNameCapacity - 1);
647         NameLen = strlen (szFQName);
648     }
649     else
650     {
651         Module* module = (Module *)scopeHnd;
652         NameLen = findNameOfToken(module, metaTOK, szFQName, FQNameCapacity);
653     }
654         
655     EE_TO_JIT_TRANSITION();
656
657     return NameLen;
658 }
659
660 CorInfoCanSkipVerificationResult CEEInfo::canSkipMethodVerification(CORINFO_METHOD_HANDLE ftnHnd)
661 {
662     CONTRACTL {
663         SO_TOLERANT;
664         THROWS;
665         GC_TRIGGERS;
666         MODE_PREEMPTIVE;
667     } CONTRACTL_END;
668
669     return CORINFO_VERIFICATION_CAN_SKIP;
670 }
671
672 /*********************************************************************/
673 BOOL CEEInfo::shouldEnforceCallvirtRestriction(
674         CORINFO_MODULE_HANDLE scopeHnd)
675 {
676     LIMITED_METHOD_CONTRACT;
677     // see vsw 599197
678     // verification rule added in whidbey requiring virtual methods
679     // to be called via callvirt except if certain other rules are
680     // obeyed.
681
682     if (g_pConfig->LegacyVirtualMethodCallVerification())
683         return false;
684     else 
685         return true;
686        
687 }
688
689 #ifdef FEATURE_READYTORUN_COMPILER
690
691 // Returns true if assemblies are in the same version bubble
692 // Right now each assembly is in its own version bubble.
693 // If the need arises (i.e. performance issues) we will define sets of assemblies (e.g. all app assemblies)
694 // The main point is that all this logic is concentrated in one place.
695
696 // NOTICE: If you change this logic to allow multi-assembly version bubbles you
697 // need to consider the impact on diagnostic tools. Currently there is an inlining
698 // table which tracks inliner/inlinee relationships in R2R images but it is not
699 // yet capable of encoding cross-assembly inlines. The scenario where this
700 // may show are instrumenting profilers that want to instrument a given method A
701 // using the ReJit APIs. If method A happens to inlined within method B in another 
702 // assembly then the profiler needs to know that so it can rejit B too.
703 // The recommended approach is to upgrade the inlining table (vm\inlinetracking.h\.cpp)
704 // now that presumably R2R images have some way to refer to methods in other
705 // assemblies in their version bubble. Chat with the diagnostics team if you need more 
706 // details.
707 //
708 // There already is a case where cross-assembly inlining occurs in an
709 // unreported fashion for methods marked NonVersionable. There is a specific 
710 // exemption called out for this on ICorProfilerInfo6::EnumNgenModuleMethodsInliningThisMethod
711 // and the impact of the cut was vetted with partners. It would not be appropriate 
712 // to increase that unreported set without additional review.
713
714
715 bool IsInSameVersionBubble(Assembly * current, Assembly * target)
716 {
717     LIMITED_METHOD_CONTRACT;
718
719     // trivial case: current and target are identical
720     // DO NOT change this without reading the notice above
721     if (current == target)
722         return true;
723
724     return false;
725 }
726
727 // Returns true if the assemblies defining current and target are in the same version bubble
728 static bool IsInSameVersionBubble(MethodDesc* pCurMD, MethodDesc *pTargetMD)
729 {
730     LIMITED_METHOD_CONTRACT;
731     // DO NOT change this without reading the notice above
732     if (IsInSameVersionBubble(pCurMD->GetModule()->GetAssembly(),
733                               pTargetMD->GetModule()->GetAssembly()))
734     {
735         return true;
736     }
737     if (IsReadyToRunCompilation())
738     {
739         if (pTargetMD->GetModule()->GetMDImport()->GetCustomAttributeByName(pTargetMD->GetMemberDef(),
740                 NONVERSIONABLE_TYPE, NULL, NULL) == S_OK)
741         {
742             return true;
743         }
744     }
745     return false;
746
747 }
748
749 #endif // FEATURE_READYTORUN_COMPILER
750
751
752 /*********************************************************************/
753 CorInfoCanSkipVerificationResult CEEInfo::canSkipVerification(
754         CORINFO_MODULE_HANDLE moduleHnd)
755 {
756     CONTRACTL {
757         SO_TOLERANT;
758         THROWS;
759         GC_TRIGGERS;
760         MODE_PREEMPTIVE;
761     } CONTRACTL_END;
762
763     return CORINFO_VERIFICATION_CAN_SKIP;
764 }
765
766 /*********************************************************************/
767 // Checks if the given metadata token is valid
768 BOOL CEEInfo::isValidToken (
769         CORINFO_MODULE_HANDLE       module,
770         mdToken                     metaTOK)
771 {
772     CONTRACTL {
773         SO_TOLERANT;
774         NOTHROW;
775         GC_NOTRIGGER;
776         MODE_ANY;
777     } CONTRACTL_END;
778
779     BOOL result = FALSE;
780
781     JIT_TO_EE_TRANSITION_LEAF();
782
783     if (IsDynamicScope(module))
784     {
785         // No explicit token validation for dynamic code. Validation is
786         // side-effect of token resolution.
787         result = TRUE;
788     }
789     else
790     {
791         result = ((Module *)module)->GetMDImport()->IsValidToken(metaTOK);
792     }
793
794     EE_TO_JIT_TRANSITION_LEAF();
795
796     return result;
797 }
798
799 /*********************************************************************/
800 // Checks if the given metadata token is valid StringRef
801 BOOL CEEInfo::isValidStringRef (
802         CORINFO_MODULE_HANDLE       module,
803         mdToken                     metaTOK)
804 {
805     CONTRACTL {
806         SO_TOLERANT;
807         THROWS;
808         GC_TRIGGERS;
809         MODE_PREEMPTIVE;
810     } CONTRACTL_END;
811
812     BOOL result = FALSE;
813
814     JIT_TO_EE_TRANSITION();
815
816     if (IsDynamicScope(module))
817     {
818         result = GetDynamicResolver(module)->IsValidStringRef(metaTOK);
819     }
820     else
821     {
822         result = ((Module *)module)->CheckStringRef(metaTOK);
823         if (result)
824         {
825             DWORD dwCharCount;    
826             LPCWSTR pString;
827             result = (!FAILED(((Module *)module)->GetMDImport()->GetUserString(metaTOK, &dwCharCount, NULL, &pString)) &&
828                      pString != NULL);
829         }
830     }
831
832     EE_TO_JIT_TRANSITION();
833
834     return result;
835 }
836
837 /* static */
838 size_t CEEInfo::findNameOfToken (Module* module,
839                                                  mdToken metaTOK,
840                                                  __out_ecount (FQNameCapacity) char * szFQName,
841                                                  size_t FQNameCapacity)
842 {
843     CONTRACTL {
844         NOTHROW;
845         GC_TRIGGERS;
846     } CONTRACTL_END;
847
848 #ifdef _DEBUG
849     PCCOR_SIGNATURE sig = NULL;
850     DWORD           cSig;
851     LPCUTF8         pszNamespace = NULL;
852     LPCUTF8         pszClassName = NULL;
853     
854     mdToken tokType = TypeFromToken(metaTOK);
855     switch(tokType)
856     {
857         case mdtTypeRef:
858             {
859                 if (FAILED(module->GetMDImport()->GetNameOfTypeRef(metaTOK, &pszNamespace, &pszClassName)))
860                 {
861                     pszNamespace = pszClassName = "Invalid TypeRef record";
862                 }
863                 ns::MakePath(szFQName, (int)FQNameCapacity, pszNamespace, pszClassName);
864                 break;
865             }
866         case mdtTypeDef:
867             {
868                 if (FAILED(module->GetMDImport()->GetNameOfTypeDef(metaTOK, &pszClassName, &pszNamespace)))
869                 {
870                     pszClassName = pszNamespace = "Invalid TypeDef record";
871                 }
872                 ns::MakePath(szFQName, (int)FQNameCapacity, pszNamespace, pszClassName);
873                 break;
874             }
875         case mdtFieldDef:
876             {
877                 LPCSTR szFieldName;
878                 if (FAILED(module->GetMDImport()->GetNameOfFieldDef(metaTOK, &szFieldName)))
879                 {
880                     szFieldName = "Invalid FieldDef record";
881                 }
882                 strncpy_s(szFQName,  FQNameCapacity,  (char*)szFieldName, FQNameCapacity - 1);
883                 break;
884             }
885         case mdtMethodDef:
886             {
887                 LPCSTR szMethodName;
888                 if (FAILED(module->GetMDImport()->GetNameOfMethodDef(metaTOK, &szMethodName)))
889                 {
890                     szMethodName = "Invalid MethodDef record";
891                 }
892                 strncpy_s(szFQName, FQNameCapacity, (char*)szMethodName, FQNameCapacity - 1);
893                 break;
894             }
895         case mdtMemberRef:
896             {
897                 LPCSTR szName;
898                 if (FAILED(module->GetMDImport()->GetNameAndSigOfMemberRef((mdMemberRef)metaTOK, &sig, &cSig, &szName)))
899                 {
900                     szName = "Invalid MemberRef record";
901                 }
902                 strncpy_s(szFQName, FQNameCapacity, (char *)szName, FQNameCapacity - 1);
903                 break;
904             }
905         default:
906             sprintf_s(szFQName, FQNameCapacity, "!TK_%x", metaTOK);
907             break;
908     }
909
910 #else // !_DEBUG
911     strncpy_s (szFQName, FQNameCapacity, "<UNKNOWN>", FQNameCapacity - 1);
912 #endif // _DEBUG
913
914
915     return strlen (szFQName);
916 }
917
918 CorInfoHelpFunc CEEInfo::getLazyStringLiteralHelper(CORINFO_MODULE_HANDLE handle)
919
920     CONTRACTL {
921         SO_TOLERANT;
922         NOTHROW;
923         GC_NOTRIGGER;
924         MODE_PREEMPTIVE;
925     } CONTRACTL_END;
926
927     CorInfoHelpFunc result = CORINFO_HELP_UNDEF;
928
929     JIT_TO_EE_TRANSITION_LEAF();
930
931     result = IsDynamicScope(handle) ? CORINFO_HELP_UNDEF : CORINFO_HELP_STRCNS;
932
933     EE_TO_JIT_TRANSITION_LEAF();
934
935     return result;
936 }
937
938
939 CHECK CheckContext(CORINFO_MODULE_HANDLE scopeHnd, CORINFO_CONTEXT_HANDLE context)
940 {
941     CHECK_MSG(scopeHnd != NULL, "Illegal null scope");
942     CHECK_MSG(((size_t) context & ~CORINFO_CONTEXTFLAGS_MASK) != NULL, "Illegal null context");
943     if (((size_t) context & CORINFO_CONTEXTFLAGS_MASK) == CORINFO_CONTEXTFLAGS_CLASS)
944     {
945         TypeHandle handle((CORINFO_CLASS_HANDLE) ((size_t) context & ~CORINFO_CONTEXTFLAGS_MASK));
946         CHECK_MSG(handle.GetModule() == GetModule(scopeHnd), "Inconsistent scope and context");
947     }
948     else
949     {
950         MethodDesc* handle = (MethodDesc*) ((size_t) context & ~CORINFO_CONTEXTFLAGS_MASK);
951         CHECK_MSG(handle->GetModule() == GetModule(scopeHnd), "Inconsistent scope and context");
952     }
953
954     CHECK_OK;
955 }
956
957
958 static DECLSPEC_NORETURN void ThrowBadTokenException(CORINFO_RESOLVED_TOKEN * pResolvedToken)
959 {
960     switch (pResolvedToken->tokenType & CORINFO_TOKENKIND_Mask)
961     {
962     case CORINFO_TOKENKIND_Class:
963         COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_CLASS_TOKEN);
964     case CORINFO_TOKENKIND_Method:
965         COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_INVALID_METHOD_TOKEN);
966     case CORINFO_TOKENKIND_Field:
967         COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_FIELD_TOKEN);
968     default:
969         COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
970     }
971 }
972
973 /*********************************************************************/
974 void CEEInfo::resolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken)
975 {
976     CONTRACTL {
977         SO_TOLERANT;
978         THROWS;
979         GC_TRIGGERS;
980         MODE_PREEMPTIVE;
981     } CONTRACTL_END;
982
983     JIT_TO_EE_TRANSITION();
984
985     _ASSERTE(CheckContext(pResolvedToken->tokenScope, pResolvedToken->tokenContext));
986
987     pResolvedToken->pTypeSpec = NULL;
988     pResolvedToken->cbTypeSpec = NULL;
989     pResolvedToken->pMethodSpec = NULL;
990     pResolvedToken->cbMethodSpec = NULL;
991
992     TypeHandle th;
993     MethodDesc * pMD = NULL;
994     FieldDesc * pFD = NULL;
995
996     CorInfoTokenKind tokenType = pResolvedToken->tokenType;
997
998     if (IsDynamicScope(pResolvedToken->tokenScope))
999     {
1000         GetDynamicResolver(pResolvedToken->tokenScope)->ResolveToken(pResolvedToken->token, &th, &pMD, &pFD);
1001
1002         //
1003         // Check that we got the expected handles and fill in missing data if necessary
1004         //
1005
1006         CorTokenType tkType = (CorTokenType)TypeFromToken(pResolvedToken->token);
1007
1008         if (pMD != NULL)
1009         {
1010             if ((tkType != mdtMethodDef) && (tkType != mdtMemberRef))
1011                 ThrowBadTokenException(pResolvedToken);
1012             if ((tokenType & CORINFO_TOKENKIND_Method) == 0)
1013                 ThrowBadTokenException(pResolvedToken);
1014             if (th.IsNull())
1015                 th = pMD->GetMethodTable();
1016
1017             // "PermitUninstDefOrRef" check
1018             if ((tokenType != CORINFO_TOKENKIND_Ldtoken) && pMD->ContainsGenericVariables())
1019             {
1020                 COMPlusThrow(kInvalidProgramException);
1021             }
1022
1023             // if this is a BoxedEntryPointStub get the UnboxedEntryPoint one
1024             if (pMD->IsUnboxingStub())
1025             {
1026                 pMD = pMD->GetMethodTable()->GetUnboxedEntryPointMD(pMD);
1027             }
1028
1029             // Activate target if required
1030             if (tokenType != CORINFO_TOKENKIND_Ldtoken)
1031             {
1032                 ScanTokenForDynamicScope(pResolvedToken, th, pMD);
1033             }
1034         }
1035         else
1036         if (pFD != NULL)
1037         {
1038             if ((tkType != mdtFieldDef) && (tkType != mdtMemberRef))
1039                 ThrowBadTokenException(pResolvedToken);
1040             if ((tokenType & CORINFO_TOKENKIND_Field) == 0)
1041                 ThrowBadTokenException(pResolvedToken);
1042             if (th.IsNull())
1043                 th = pFD->GetApproxEnclosingMethodTable();
1044
1045             if (pFD->IsStatic() && (tokenType != CORINFO_TOKENKIND_Ldtoken))
1046             {
1047                 ScanTokenForDynamicScope(pResolvedToken, th);
1048             }
1049         }
1050         else
1051         {
1052             if ((tkType != mdtTypeDef) && (tkType != mdtTypeRef))
1053                 ThrowBadTokenException(pResolvedToken);
1054             if ((tokenType & CORINFO_TOKENKIND_Class) == 0)
1055                 ThrowBadTokenException(pResolvedToken);
1056             if (th.IsNull())
1057                 ThrowBadTokenException(pResolvedToken);
1058
1059             if (tokenType == CORINFO_TOKENKIND_Box || tokenType == CORINFO_TOKENKIND_Constrained)
1060             {
1061                 ScanTokenForDynamicScope(pResolvedToken, th);
1062             }
1063         }
1064
1065         _ASSERTE((pMD == NULL) || (pFD == NULL));
1066         _ASSERTE(!th.IsNull());
1067
1068         // "PermitUninstDefOrRef" check
1069         if ((tokenType != CORINFO_TOKENKIND_Ldtoken) && th.ContainsGenericVariables())
1070         {
1071             COMPlusThrow(kInvalidProgramException);
1072         }
1073
1074         // The JIT always wants to see normalized typedescs for arrays
1075         if (!th.IsTypeDesc() && th.AsMethodTable()->IsArray())
1076         {
1077             MethodTable * pMT = th.AsMethodTable();
1078         
1079             // Load the TypeDesc for the array type.
1080             DWORD rank = pMT->GetRank();
1081             TypeHandle elemType = pMT->GetApproxArrayElementTypeHandle();
1082             th = ClassLoader::LoadArrayTypeThrowing(elemType, pMT->GetInternalCorElementType(), rank);
1083         }
1084     }
1085     else
1086     {
1087         unsigned metaTOK = pResolvedToken->token;
1088         Module * pModule = (Module *)pResolvedToken->tokenScope;
1089
1090         switch (TypeFromToken(metaTOK))
1091         {
1092         case mdtModuleRef:
1093             if ((tokenType & CORINFO_TOKENKIND_Class) == 0)
1094                 ThrowBadTokenException(pResolvedToken);
1095         
1096             {
1097                 DomainFile *pTargetModule = pModule->LoadModule(GetAppDomain(), metaTOK, FALSE /* loadResources */);
1098                 if (pTargetModule == NULL)
1099                     COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
1100                 th = TypeHandle(pTargetModule->GetModule()->GetGlobalMethodTable());
1101                 if (th.IsNull())
1102                     COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
1103             }
1104             break;
1105
1106         case mdtTypeDef:
1107         case mdtTypeRef:
1108             if ((tokenType & CORINFO_TOKENKIND_Class) == 0)
1109                 ThrowBadTokenException(pResolvedToken);
1110
1111             th = ClassLoader::LoadTypeDefOrRefThrowing(pModule, metaTOK, 
1112                                          ClassLoader::ThrowIfNotFound, 
1113                                          (tokenType == CORINFO_TOKENKIND_Ldtoken) ? 
1114                                             ClassLoader::PermitUninstDefOrRef : ClassLoader::FailIfUninstDefOrRef);
1115             break;
1116
1117         case mdtTypeSpec:
1118             {
1119                 if ((tokenType & CORINFO_TOKENKIND_Class) == 0)
1120                     ThrowBadTokenException(pResolvedToken);
1121
1122                 IfFailThrow(pModule->GetMDImport()->GetTypeSpecFromToken(metaTOK, &pResolvedToken->pTypeSpec, &pResolvedToken->cbTypeSpec));
1123                 
1124                 SigTypeContext typeContext;
1125                 GetTypeContext(pResolvedToken->tokenContext, &typeContext);
1126
1127                 SigPointer sigptr(pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec);
1128                 th = sigptr.GetTypeHandleThrowing(pModule, &typeContext);
1129             }
1130             break;
1131
1132         case mdtMethodDef:
1133             if ((tokenType & CORINFO_TOKENKIND_Method) == 0)
1134                 ThrowBadTokenException(pResolvedToken);
1135
1136             pMD = MemberLoader::GetMethodDescFromMethodDef(pModule, metaTOK, (tokenType != CORINFO_TOKENKIND_Ldtoken));
1137
1138             th = pMD->GetMethodTable();
1139             break;
1140
1141         case mdtFieldDef:
1142             if ((tokenType & CORINFO_TOKENKIND_Field) == 0)
1143                 ThrowBadTokenException(pResolvedToken);
1144
1145             pFD = MemberLoader::GetFieldDescFromFieldDef(pModule, metaTOK, (tokenType != CORINFO_TOKENKIND_Ldtoken));
1146
1147             th = pFD->GetEnclosingMethodTable();
1148             break;
1149
1150         case mdtMemberRef:
1151             {
1152                 SigTypeContext typeContext;
1153                 GetTypeContext(pResolvedToken->tokenContext, &typeContext);
1154
1155                 MemberLoader::GetDescFromMemberRef(pModule, metaTOK, &pMD, &pFD, &typeContext, (tokenType != CORINFO_TOKENKIND_Ldtoken),
1156                     &th, TRUE, &pResolvedToken->pTypeSpec, &pResolvedToken->cbTypeSpec);
1157
1158                 _ASSERTE((pMD != NULL) ^ (pFD != NULL));
1159                 _ASSERTE(!th.IsNull());
1160
1161                 if (pMD != NULL)
1162                 {
1163                     if ((tokenType & CORINFO_TOKENKIND_Method) == 0)
1164                         ThrowBadTokenException(pResolvedToken);
1165                 }
1166                 else
1167                 {
1168                     if ((tokenType & CORINFO_TOKENKIND_Field) == 0)
1169                         ThrowBadTokenException(pResolvedToken);
1170                 }
1171             }
1172             break;
1173
1174         case mdtMethodSpec:
1175             {
1176                 if ((tokenType & CORINFO_TOKENKIND_Method) == 0)
1177                     ThrowBadTokenException(pResolvedToken);
1178
1179                 SigTypeContext typeContext;
1180                 GetTypeContext(pResolvedToken->tokenContext, &typeContext);
1181
1182                 // We need the method desc to carry exact instantiation, thus allowInstParam == FALSE.
1183                 pMD = MemberLoader::GetMethodDescFromMethodSpec(pModule, metaTOK, &typeContext, (tokenType != CORINFO_TOKENKIND_Ldtoken), FALSE /* allowInstParam */,
1184                     &th, TRUE, &pResolvedToken->pTypeSpec, &pResolvedToken->cbTypeSpec, &pResolvedToken->pMethodSpec, &pResolvedToken->cbMethodSpec);
1185             }
1186             break;
1187
1188         default:
1189             ThrowBadTokenException(pResolvedToken);
1190         }
1191
1192         //
1193         // Module dependency tracking
1194         //
1195         if (pMD != NULL)
1196         {
1197             ScanToken(pModule, pResolvedToken, th, pMD);
1198         }
1199         else
1200         if (pFD != NULL)
1201         {
1202             if (pFD->IsStatic())
1203                 ScanToken(pModule, pResolvedToken, th);
1204         }
1205         else
1206         {
1207             // It should not be required to trigger the modules cctors for ldtoken, it is done for backward compatibility only.
1208             if (tokenType == CORINFO_TOKENKIND_Box || tokenType == CORINFO_TOKENKIND_Constrained || tokenType == CORINFO_TOKENKIND_Ldtoken)
1209                 ScanToken(pModule, pResolvedToken, th);
1210         }
1211     }
1212
1213     //
1214     // tokenType specific verification and transformations
1215     //
1216     CorElementType et = th.GetInternalCorElementType();
1217     switch (tokenType)
1218     {            
1219         case CORINFO_TOKENKIND_Ldtoken:
1220             // Allow everything.
1221             break;
1222
1223         case CORINFO_TOKENKIND_Newarr:
1224             // Disallow ELEMENT_TYPE_BYREF and ELEMENT_TYPE_VOID
1225             if (et == ELEMENT_TYPE_BYREF || et == ELEMENT_TYPE_VOID)
1226                 COMPlusThrow(kInvalidProgramException);
1227
1228             th = ClassLoader::LoadArrayTypeThrowing(th);
1229             break;
1230             
1231         default:
1232             // Disallow ELEMENT_TYPE_BYREF and ELEMENT_TYPE_VOID
1233             if (et == ELEMENT_TYPE_BYREF || et == ELEMENT_TYPE_VOID)
1234                 COMPlusThrow(kInvalidProgramException);
1235             break;
1236     }
1237
1238     // The JIT interface should always return fully loaded types
1239     _ASSERTE(th.IsFullyLoaded());
1240
1241     pResolvedToken->hClass = CORINFO_CLASS_HANDLE(th.AsPtr());
1242     pResolvedToken->hMethod = CORINFO_METHOD_HANDLE(pMD);
1243     pResolvedToken->hField = CORINFO_FIELD_HANDLE(pFD);
1244
1245     EE_TO_JIT_TRANSITION();
1246 }
1247
1248 /*********************************************************************/
1249 struct TryResolveTokenFilterParam
1250 {
1251     CEEInfo* m_this;
1252     CORINFO_RESOLVED_TOKEN* m_resolvedToken;
1253     EXCEPTION_POINTERS m_exceptionPointers;
1254     bool m_success;
1255 };
1256
1257 bool isValidTokenForTryResolveToken(CEEInfo* info, CORINFO_RESOLVED_TOKEN* resolvedToken)
1258 {
1259     CONTRACTL {
1260         NOTHROW;
1261         GC_NOTRIGGER;
1262         SO_TOLERANT;
1263         MODE_ANY;
1264     } CONTRACTL_END;
1265
1266     if (!info->isValidToken(resolvedToken->tokenScope, resolvedToken->token))
1267     {
1268         return false;
1269     }
1270
1271     CorInfoTokenKind tokenType = resolvedToken->tokenType;
1272     switch (TypeFromToken(resolvedToken->token))
1273     {
1274     case mdtModuleRef:
1275     case mdtTypeDef:
1276     case mdtTypeRef:
1277     case mdtTypeSpec:
1278         if ((tokenType & CORINFO_TOKENKIND_Class) == 0)
1279             return false;
1280         break;
1281
1282     case mdtMethodDef:
1283     case mdtMethodSpec:
1284         if ((tokenType & CORINFO_TOKENKIND_Method) == 0)
1285             return false;
1286         break;
1287
1288     case mdtFieldDef:
1289         if ((tokenType & CORINFO_TOKENKIND_Field) == 0)
1290             return false;
1291         break;
1292
1293     case mdtMemberRef:
1294         if ((tokenType & (CORINFO_TOKENKIND_Method | CORINFO_TOKENKIND_Field)) == 0)
1295             return false;
1296         break;
1297
1298     default:
1299         return false;
1300     }
1301
1302     return true;
1303 }
1304
1305 LONG EEFilterException(struct _EXCEPTION_POINTERS* exceptionPointers, void* unused);
1306
1307 LONG TryResolveTokenFilter(struct _EXCEPTION_POINTERS* exceptionPointers, void* theParam)
1308 {
1309     CONTRACTL {
1310         NOTHROW;
1311         GC_NOTRIGGER;
1312         SO_TOLERANT;
1313         MODE_ANY;
1314     } CONTRACTL_END;
1315
1316     // Backward compatibility: Convert bad image format exceptions thrown while resolving tokens
1317     // to simple true/false successes. This is done for backward compatibility only. Ideally,
1318     // we would always treat bad tokens in the IL  stream as fatal errors.
1319     if (exceptionPointers->ExceptionRecord->ExceptionCode == EXCEPTION_COMPLUS)
1320     {
1321         auto* param = reinterpret_cast<TryResolveTokenFilterParam*>(theParam);
1322         if (!isValidTokenForTryResolveToken(param->m_this, param->m_resolvedToken))
1323         {
1324             param->m_exceptionPointers = *exceptionPointers;
1325             return EEFilterException(exceptionPointers, nullptr);
1326         }
1327     }
1328
1329     return EXCEPTION_CONTINUE_SEARCH;
1330 }
1331
1332 bool CEEInfo::tryResolveToken(CORINFO_RESOLVED_TOKEN* resolvedToken)
1333 {
1334     // No dynamic contract here because SEH is used
1335     STATIC_CONTRACT_SO_TOLERANT;
1336     STATIC_CONTRACT_THROWS;
1337     STATIC_CONTRACT_GC_TRIGGERS;
1338     STATIC_CONTRACT_MODE_PREEMPTIVE;
1339
1340     TryResolveTokenFilterParam param;
1341     param.m_this = this;
1342     param.m_resolvedToken = resolvedToken;
1343     param.m_success = true;
1344
1345     PAL_TRY(TryResolveTokenFilterParam*, pParam, &param)
1346     {
1347         pParam->m_this->resolveToken(pParam->m_resolvedToken);
1348     }
1349     PAL_EXCEPT_FILTER(TryResolveTokenFilter)
1350     {
1351         if (param.m_exceptionPointers.ExceptionRecord->ExceptionCode == EXCEPTION_COMPLUS)
1352         {
1353             HandleException(&param.m_exceptionPointers);
1354         }
1355
1356         param.m_success = false;
1357     }
1358     PAL_ENDTRY
1359
1360     return param.m_success;
1361 }
1362
1363 /*********************************************************************/
1364 // We have a few frequently used constants in mscorlib that are defined as 
1365 // readonly static fields for historic reasons. Check for them here and 
1366 // allow them to be treated as actual constants by the JIT.
1367 static CORINFO_FIELD_ACCESSOR getFieldIntrinsic(FieldDesc * field)
1368 {
1369     STANDARD_VM_CONTRACT;
1370
1371     if (MscorlibBinder::GetField(FIELD__STRING__EMPTY) == field)
1372     {
1373         return CORINFO_FIELD_INTRINSIC_EMPTY_STRING;
1374     }
1375     else
1376     if ((MscorlibBinder::GetField(FIELD__INTPTR__ZERO) == field) ||
1377         (MscorlibBinder::GetField(FIELD__UINTPTR__ZERO) == field))
1378     {
1379         return CORINFO_FIELD_INTRINSIC_ZERO;
1380     }
1381     else
1382     if (MscorlibBinder::GetField(FIELD__BITCONVERTER__ISLITTLEENDIAN) == field)
1383     {
1384         return CORINFO_FIELD_INTRINSIC_ISLITTLEENDIAN;
1385     }
1386
1387     return (CORINFO_FIELD_ACCESSOR)-1;
1388 }
1389
1390 static CorInfoHelpFunc getGenericStaticsHelper(FieldDesc * pField)
1391 {
1392     STANDARD_VM_CONTRACT;
1393
1394     int helper = CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE;
1395
1396     if (pField->GetFieldType() == ELEMENT_TYPE_CLASS ||
1397         pField->GetFieldType() == ELEMENT_TYPE_VALUETYPE)
1398     {
1399         helper = CORINFO_HELP_GETGENERICS_GCSTATIC_BASE;
1400     }
1401
1402     if (pField->IsThreadStatic())
1403     {
1404         const int delta = CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE - CORINFO_HELP_GETGENERICS_GCSTATIC_BASE;
1405
1406         static_assert_no_msg(CORINFO_HELP_GETGENERICS_NONGCTHREADSTATIC_BASE 
1407             == CORINFO_HELP_GETGENERICS_NONGCSTATIC_BASE + delta);
1408
1409         helper += (CORINFO_HELP_GETGENERICS_GCTHREADSTATIC_BASE - CORINFO_HELP_GETGENERICS_GCSTATIC_BASE);
1410     }
1411
1412     return (CorInfoHelpFunc)helper;
1413 }
1414
1415 CorInfoHelpFunc CEEInfo::getSharedStaticsHelper(FieldDesc * pField, MethodTable * pFieldMT)
1416 {
1417     STANDARD_VM_CONTRACT;
1418
1419     int helper = CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE;
1420
1421     if (pField->GetFieldType() == ELEMENT_TYPE_CLASS ||
1422         pField->GetFieldType() == ELEMENT_TYPE_VALUETYPE)
1423     {
1424         helper = CORINFO_HELP_GETSHARED_GCSTATIC_BASE;
1425     }
1426
1427     if (pFieldMT->IsDynamicStatics())
1428     {
1429         const int delta = CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS - CORINFO_HELP_GETSHARED_GCSTATIC_BASE;
1430
1431         static_assert_no_msg(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS 
1432             == CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE + delta);
1433
1434         helper += delta;
1435     }
1436     else
1437     if (!pFieldMT->HasClassConstructor() && !pFieldMT->HasBoxedRegularStatics())
1438     {
1439         const int delta = CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR - CORINFO_HELP_GETSHARED_GCSTATIC_BASE;
1440
1441         static_assert_no_msg(CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR 
1442             == CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE + delta);
1443
1444         helper += delta;
1445     }
1446
1447     if (pField->IsThreadStatic())
1448     {
1449         const int delta = CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE - CORINFO_HELP_GETSHARED_GCSTATIC_BASE;
1450
1451         static_assert_no_msg(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE 
1452             == CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE + delta);
1453         static_assert_no_msg(CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR 
1454             == CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR + delta);
1455         static_assert_no_msg(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR 
1456             == CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR + delta);
1457         static_assert_no_msg(CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS 
1458             == CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS + delta);
1459         static_assert_no_msg(CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS 
1460             == CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS + delta);
1461
1462         helper += delta;
1463     }
1464
1465     return (CorInfoHelpFunc)helper;
1466 }
1467
1468 static CorInfoHelpFunc getInstanceFieldHelper(FieldDesc * pField, CORINFO_ACCESS_FLAGS flags)
1469 {
1470     STANDARD_VM_CONTRACT;
1471
1472     int helper;
1473
1474     CorElementType type = pField->GetFieldType();
1475
1476     if (CorTypeInfo::IsObjRef(type))
1477         helper = CORINFO_HELP_GETFIELDOBJ;
1478     else
1479     switch (type)
1480     {
1481     case ELEMENT_TYPE_VALUETYPE:
1482         helper = CORINFO_HELP_GETFIELDSTRUCT;
1483         break;
1484     case ELEMENT_TYPE_I1:
1485     case ELEMENT_TYPE_BOOLEAN:
1486     case ELEMENT_TYPE_U1:
1487         helper = CORINFO_HELP_GETFIELD8;
1488         break;
1489     case ELEMENT_TYPE_I2:
1490     case ELEMENT_TYPE_CHAR:
1491     case ELEMENT_TYPE_U2:
1492         helper = CORINFO_HELP_GETFIELD16;
1493         break;
1494     case ELEMENT_TYPE_I4:
1495     case ELEMENT_TYPE_U4:
1496     IN_WIN32(default:)
1497         helper = CORINFO_HELP_GETFIELD32;
1498         break;
1499     case ELEMENT_TYPE_I8:
1500     case ELEMENT_TYPE_U8:
1501     IN_WIN64(default:)
1502         helper = CORINFO_HELP_GETFIELD64;
1503         break;
1504     case ELEMENT_TYPE_R4:
1505         helper = CORINFO_HELP_GETFIELDFLOAT;
1506         break;
1507     case ELEMENT_TYPE_R8:
1508         helper = CORINFO_HELP_GETFIELDDOUBLE;
1509         break;
1510     }
1511
1512     if (flags & CORINFO_ACCESS_SET)
1513     {
1514         const int delta = CORINFO_HELP_SETFIELDOBJ - CORINFO_HELP_GETFIELDOBJ;
1515
1516         static_assert_no_msg(CORINFO_HELP_SETFIELD8 == CORINFO_HELP_GETFIELD8 + delta);
1517         static_assert_no_msg(CORINFO_HELP_SETFIELD16 == CORINFO_HELP_GETFIELD16 + delta);
1518         static_assert_no_msg(CORINFO_HELP_SETFIELD32 == CORINFO_HELP_GETFIELD32 + delta);
1519         static_assert_no_msg(CORINFO_HELP_SETFIELD64 == CORINFO_HELP_GETFIELD64 + delta);
1520         static_assert_no_msg(CORINFO_HELP_SETFIELDSTRUCT == CORINFO_HELP_GETFIELDSTRUCT + delta);
1521         static_assert_no_msg(CORINFO_HELP_SETFIELDFLOAT == CORINFO_HELP_GETFIELDFLOAT + delta);
1522         static_assert_no_msg(CORINFO_HELP_SETFIELDDOUBLE == CORINFO_HELP_GETFIELDDOUBLE + delta);
1523
1524         helper += delta;
1525     }
1526
1527     return (CorInfoHelpFunc)helper;
1528 }
1529
1530 /*********************************************************************/
1531 void CEEInfo::getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken,
1532                             CORINFO_METHOD_HANDLE  callerHandle,
1533                             CORINFO_ACCESS_FLAGS   flags, 
1534                             CORINFO_FIELD_INFO    *pResult
1535                            )
1536 {
1537     CONTRACTL {
1538         SO_TOLERANT;
1539         THROWS;
1540         GC_TRIGGERS;
1541         MODE_PREEMPTIVE;
1542     } CONTRACTL_END;
1543
1544     JIT_TO_EE_TRANSITION();
1545
1546     _ASSERTE((flags & (CORINFO_ACCESS_GET | CORINFO_ACCESS_SET | CORINFO_ACCESS_ADDRESS | CORINFO_ACCESS_INIT_ARRAY)) != 0);
1547
1548     INDEBUG(memset(pResult, 0xCC, sizeof(*pResult)));
1549
1550     FieldDesc * pField = (FieldDesc*)pResolvedToken->hField;
1551     MethodTable * pFieldMT = pField->GetApproxEnclosingMethodTable();
1552
1553     // Helper to use if the field access requires it
1554     CORINFO_FIELD_ACCESSOR fieldAccessor = (CORINFO_FIELD_ACCESSOR)-1;
1555     DWORD fieldFlags = 0;
1556
1557     pResult->offset = pField->GetOffset();
1558     if (pField->IsStatic())
1559     {
1560         fieldFlags |= CORINFO_FLG_FIELD_STATIC;
1561
1562         if (pField->IsRVA())
1563         {
1564             fieldFlags |= CORINFO_FLG_FIELD_UNMANAGED;
1565
1566             Module* module = pFieldMT->GetModule();
1567             if (module->IsRvaFieldTls(pResult->offset))
1568             {
1569                 fieldAccessor = CORINFO_FIELD_STATIC_TLS;
1570
1571                 // Provide helper to use if the JIT is not able to emit the TLS access
1572                 // as intrinsic
1573                 pResult->helper = CORINFO_HELP_GETSTATICFIELDADDR_TLS;
1574
1575                 pResult->offset = module->GetFieldTlsOffset(pResult->offset);
1576             }
1577             else
1578             {
1579                 fieldAccessor = CORINFO_FIELD_STATIC_RVA_ADDRESS;
1580             }
1581
1582             // We are not going through a helper. The constructor has to be triggered explicitly.
1583             if (!pFieldMT->IsClassPreInited())
1584                 fieldFlags |= CORINFO_FLG_FIELD_INITCLASS;
1585         }
1586         else
1587         if (pField->IsContextStatic())
1588         {
1589             fieldAccessor = CORINFO_FIELD_STATIC_ADDR_HELPER;
1590
1591             pResult->helper = CORINFO_HELP_GETSTATICFIELDADDR_CONTEXT;
1592         }
1593         else
1594         {
1595             // Regular or thread static
1596             CORINFO_FIELD_ACCESSOR intrinsicAccessor;
1597
1598             if (pField->GetFieldType() == ELEMENT_TYPE_VALUETYPE)
1599                 fieldFlags |= CORINFO_FLG_FIELD_STATIC_IN_HEAP;
1600
1601             if (pFieldMT->IsSharedByGenericInstantiations())
1602             {
1603                 fieldAccessor = CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER;
1604
1605                 pResult->helper = getGenericStaticsHelper(pField);
1606             }
1607             else
1608             if (pFieldMT->GetModule()->IsSystem() && (flags & CORINFO_ACCESS_GET) &&
1609                 (intrinsicAccessor = getFieldIntrinsic(pField)) != (CORINFO_FIELD_ACCESSOR)-1)
1610             {
1611                 // Intrinsics
1612                 fieldAccessor = intrinsicAccessor;
1613             }
1614             else
1615             if (// Domain neutral access.
1616                 m_pMethodBeingCompiled->IsDomainNeutral() || m_pMethodBeingCompiled->IsZapped() || IsCompilingForNGen() ||
1617                 // Static fields are not pinned in collectible types. We will always access 
1618                 // them using a helper since the address cannot be embeded into the code.
1619                 pFieldMT->Collectible() ||
1620                 // We always treat accessing thread statics as if we are in domain neutral code.
1621                 pField->IsThreadStatic()
1622                 )
1623             {
1624                 fieldAccessor = CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER;
1625
1626                 pResult->helper = getSharedStaticsHelper(pField, pFieldMT);
1627             }
1628             else
1629             {
1630                 fieldAccessor = CORINFO_FIELD_STATIC_ADDRESS;
1631
1632                 // We are not going through a helper. The constructor has to be triggered explicitly.
1633                 if (!pFieldMT->IsClassPreInited())
1634                     fieldFlags |= CORINFO_FLG_FIELD_INITCLASS;
1635             }
1636         }
1637
1638         //
1639         // Currently, we only this optimization for regular statics, but it
1640         // looks like it may be permissible to do this optimization for
1641         // thread statics as well.
1642         //
1643         if ((flags & CORINFO_ACCESS_ADDRESS) &&
1644             !pField->IsThreadStatic() &&
1645             !pField->IsContextStatic() &&
1646             (fieldAccessor != CORINFO_FIELD_STATIC_TLS))
1647         {
1648             fieldFlags |= CORINFO_FLG_FIELD_SAFESTATIC_BYREF_RETURN;
1649         }
1650     }
1651     else
1652     {
1653         BOOL fInstanceHelper = FALSE;
1654
1655 #if CHECK_APP_DOMAIN_LEAKS
1656         if (g_pConfig->EnableFullDebug()
1657             && pField->IsDangerousAppDomainAgileField()
1658             && CorTypeInfo::IsObjRef(pField->GetFieldType()))
1659         {
1660             //
1661             // In a checked field with all checks turned on, we use a helper to enforce the app domain
1662             // agile invariant.
1663             //
1664             // <REVISIT_TODO>@todo: we'd like to check this for value type fields as well - we
1665             // just need to add some code to iterate through the fields for
1666             // references during the assignment.
1667             // </REVISIT_TODO>
1668             fInstanceHelper = TRUE;
1669         }
1670         else
1671 #endif // CHECK_APP_DOMAIN_LEAKS
1672
1673         if (fInstanceHelper)
1674         {
1675             if (flags & CORINFO_ACCESS_ADDRESS)
1676             {
1677                 fieldAccessor = CORINFO_FIELD_INSTANCE_ADDR_HELPER;
1678
1679                 pResult->helper = CORINFO_HELP_GETFIELDADDR;
1680             }
1681             else
1682             {
1683                 fieldAccessor = CORINFO_FIELD_INSTANCE_HELPER;
1684
1685                 pResult->helper = getInstanceFieldHelper(pField, flags);
1686             }
1687         }
1688         else
1689         if (pField->IsEnCNew())
1690         {
1691             fieldAccessor = CORINFO_FIELD_INSTANCE_ADDR_HELPER;
1692
1693             pResult->helper = CORINFO_HELP_GETFIELDADDR;
1694         }
1695         else
1696         {
1697             fieldAccessor = CORINFO_FIELD_INSTANCE;
1698         }
1699
1700         // FieldDesc::GetOffset() does not include the size of Object
1701         if (!pFieldMT->IsValueType())
1702         {
1703             pResult->offset += sizeof(Object);
1704         }
1705     }
1706
1707     // TODO: This is touching metadata. Can we avoid it?
1708     DWORD fieldAttribs = pField->GetAttributes();
1709
1710     if (IsFdFamily(fieldAttribs))
1711         fieldFlags |= CORINFO_FLG_FIELD_PROTECTED;
1712
1713     if (IsFdInitOnly(fieldAttribs))
1714         fieldFlags |= CORINFO_FLG_FIELD_FINAL;
1715
1716     pResult->fieldAccessor = fieldAccessor;
1717     pResult->fieldFlags = fieldFlags;
1718
1719     if (!(flags & CORINFO_ACCESS_INLINECHECK))
1720     {
1721         //get the field's type.  Grab the class for structs.
1722         pResult->fieldType = getFieldTypeInternal(pResolvedToken->hField, &pResult->structType, pResolvedToken->hClass);
1723
1724
1725         MethodDesc * pCallerForSecurity = GetMethodForSecurity(callerHandle);
1726
1727         //
1728         //Since we can't get the special verify-only instantiated FD like we can with MDs, go back to the parent
1729         //of the memberRef and load that one.  That should give us the open instantiation.
1730         //
1731         //If the field we found is owned by a generic type, you have to go back to the signature and reload.
1732         //Otherwise we filled in !0.
1733         TypeHandle fieldTypeForSecurity = TypeHandle(pResolvedToken->hClass);
1734         if (pResolvedToken->pTypeSpec != NULL)
1735         {
1736             SigTypeContext typeContext;
1737             SigTypeContext::InitTypeContext(pCallerForSecurity, &typeContext);
1738
1739             SigPointer sigptr(pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec);
1740             fieldTypeForSecurity = sigptr.GetTypeHandleThrowing((Module *)pResolvedToken->tokenScope, &typeContext);
1741
1742             // typeHnd can be a variable type
1743             if (fieldTypeForSecurity.GetMethodTable() == NULL)
1744             {
1745                 COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_METHODDEF_PARENT_NO_MEMBERS);
1746             }
1747         }
1748
1749         BOOL doAccessCheck = TRUE;
1750         AccessCheckOptions::AccessCheckType accessCheckType = AccessCheckOptions::kNormalAccessibilityChecks;
1751
1752         DynamicResolver * pAccessContext = NULL;
1753
1754         //More in code:CEEInfo::getCallInfo, but the short version is that the caller and callee Descs do
1755         //not completely describe the type.
1756         TypeHandle callerTypeForSecurity = TypeHandle(pCallerForSecurity->GetMethodTable());
1757         if (IsDynamicScope(pResolvedToken->tokenScope))
1758         {
1759             doAccessCheck = ModifyCheckForDynamicMethod(GetDynamicResolver(pResolvedToken->tokenScope), &callerTypeForSecurity,
1760                 &accessCheckType, &pAccessContext);
1761         }
1762
1763         //Now for some link time checks.
1764         //Um... where are the field link demands?
1765
1766         pResult->accessAllowed = CORINFO_ACCESS_ALLOWED;
1767
1768         if (doAccessCheck)
1769         {
1770             //Well, let's check some visibility at least.
1771             AccessCheckOptions accessCheckOptions(accessCheckType,
1772                 pAccessContext,
1773                 FALSE,
1774                 pField);
1775
1776             _ASSERTE(pCallerForSecurity != NULL && callerTypeForSecurity != NULL);
1777             StaticAccessCheckContext accessContext(pCallerForSecurity, callerTypeForSecurity.GetMethodTable());
1778
1779             BOOL canAccess = ClassLoader::CanAccess(
1780                 &accessContext,
1781                 fieldTypeForSecurity.GetMethodTable(),
1782                 fieldTypeForSecurity.GetAssembly(),
1783                 fieldAttribs,
1784                 NULL,
1785                 (flags & CORINFO_ACCESS_INIT_ARRAY) ? NULL : pField, // For InitializeArray, we don't need tocheck the type of the field.
1786                 accessCheckOptions,
1787                 FALSE /*checkTargetMethodTransparency*/,
1788                 TRUE  /*checkTargetTypeTransparency*/);
1789
1790             if (!canAccess)
1791             {
1792                 //Set up the throw helper
1793                 pResult->accessAllowed = CORINFO_ACCESS_ILLEGAL;
1794
1795                 pResult->accessCalloutHelper.helperNum = CORINFO_HELP_FIELD_ACCESS_EXCEPTION;
1796                 pResult->accessCalloutHelper.numArgs = 2;
1797
1798                 pResult->accessCalloutHelper.args[0].Set(CORINFO_METHOD_HANDLE(pCallerForSecurity));
1799                 pResult->accessCalloutHelper.args[1].Set(CORINFO_FIELD_HANDLE(pField));
1800
1801                 if (IsCompilingForNGen())
1802                 {
1803                     //see code:CEEInfo::getCallInfo for more information.
1804                     if (pCallerForSecurity->ContainsGenericVariables())
1805                         COMPlusThrowNonLocalized(kNotSupportedException, W("Cannot embed generic MethodDesc"));
1806                 }
1807             }
1808             else
1809             {
1810                 CorInfoIsAccessAllowedResult isAccessAllowed = CORINFO_ACCESS_ALLOWED;
1811                 CorInfoSecurityRuntimeChecks runtimeChecks = CORINFO_ACCESS_SECURITY_NONE;
1812
1813                 DebugSecurityCalloutStress(getMethodBeingCompiled(), isAccessAllowed, runtimeChecks);
1814                 if (isAccessAllowed == CORINFO_ACCESS_RUNTIME_CHECK)
1815                 {
1816                     pResult->accessAllowed = isAccessAllowed;
1817                     //Explain the callback to the JIT.
1818                     pResult->accessCalloutHelper.helperNum = CORINFO_HELP_FIELD_ACCESS_CHECK;
1819                     pResult->accessCalloutHelper.numArgs = 3;
1820
1821                     pResult->accessCalloutHelper.args[0].Set(CORINFO_METHOD_HANDLE(pCallerForSecurity));
1822
1823                     /* REVISIT_TODO Wed 4/8/2009
1824                      * This field handle is not useful on its own.  We also need to embed the enclosing class
1825                      * handle.
1826                      */
1827                     pResult->accessCalloutHelper.args[1].Set(CORINFO_FIELD_HANDLE(pField));
1828
1829                     pResult->accessCalloutHelper.args[2].Set(runtimeChecks);
1830
1831                     if (IsCompilingForNGen())
1832                     {
1833                         //see code:CEEInfo::getCallInfo for more information.
1834                         if (pCallerForSecurity->ContainsGenericVariables())
1835                             COMPlusThrowNonLocalized(kNotSupportedException, W("Cannot embed generic MethodDesc"));
1836                     }
1837                 }
1838             }
1839         }
1840     }
1841
1842     EE_TO_JIT_TRANSITION();
1843 }
1844
1845 //---------------------------------------------------------------------------------------
1846 // 
1847 bool CEEInfo::isFieldStatic(CORINFO_FIELD_HANDLE fldHnd)
1848 {
1849     CONTRACTL {
1850         SO_TOLERANT;
1851         THROWS;
1852         GC_TRIGGERS;
1853         MODE_PREEMPTIVE;
1854     } CONTRACTL_END;
1855
1856     bool res = false;
1857     JIT_TO_EE_TRANSITION_LEAF();
1858     FieldDesc* field = (FieldDesc*)fldHnd;
1859     res = (field->IsStatic() != 0);
1860     EE_TO_JIT_TRANSITION_LEAF();
1861     return res;
1862 }
1863
1864 //---------------------------------------------------------------------------------------
1865 // 
1866 void 
1867 CEEInfo::findCallSiteSig(
1868     CORINFO_MODULE_HANDLE  scopeHnd, 
1869     unsigned               sigMethTok, 
1870     CORINFO_CONTEXT_HANDLE context, 
1871     CORINFO_SIG_INFO *     sigRet)
1872 {
1873     CONTRACTL {
1874         SO_TOLERANT;
1875         THROWS;
1876         GC_TRIGGERS;
1877         MODE_PREEMPTIVE;
1878     } CONTRACTL_END;
1879
1880     JIT_TO_EE_TRANSITION();
1881
1882     PCCOR_SIGNATURE       pSig = NULL;
1883     DWORD                 cbSig = 0;
1884
1885     if (IsDynamicScope(scopeHnd))
1886     {
1887         DynamicResolver * pResolver = GetDynamicResolver(scopeHnd);
1888         SigPointer sig;
1889
1890         if (TypeFromToken(sigMethTok) == mdtMemberRef)
1891         {
1892             sig = pResolver->ResolveSignatureForVarArg(sigMethTok);
1893         }
1894         else
1895         {
1896             _ASSERTE(TypeFromToken(sigMethTok) == mdtMethodDef);
1897
1898             TypeHandle classHandle;
1899             MethodDesc * pMD = NULL;
1900             FieldDesc * pFD = NULL;
1901
1902             // in this case a method is asked for its sig. Resolve the method token and get the sig
1903             pResolver->ResolveToken(sigMethTok, &classHandle, &pMD, &pFD);
1904             if (pMD == NULL)
1905                 COMPlusThrow(kInvalidProgramException);
1906
1907             PCCOR_SIGNATURE pSig = NULL;
1908             DWORD           cbSig;
1909             pMD->GetSig(&pSig, &cbSig);
1910             sig = SigPointer(pSig, cbSig);
1911
1912             context = MAKE_METHODCONTEXT(pMD);
1913             scopeHnd = GetScopeHandle(pMD->GetModule());
1914         }
1915
1916         sig.GetSignature(&pSig, &cbSig);
1917         sigMethTok = mdTokenNil;
1918     }
1919     else
1920     {
1921         Module * module = (Module *)scopeHnd;
1922         LPCUTF8  szName;
1923
1924         if (TypeFromToken(sigMethTok) == mdtMemberRef)
1925         {
1926             IfFailThrow(module->GetMDImport()->GetNameAndSigOfMemberRef(sigMethTok, &pSig, &cbSig, &szName));
1927             
1928             // Defs have already been checked by the loader for validity
1929             // However refs need to be checked.
1930             if (!Security::CanSkipVerification(module->GetDomainAssembly()))
1931             {
1932                 // Can pass 0 for the flags, since it is only used for defs.
1933                 IfFailThrow(validateTokenSig(sigMethTok, pSig, cbSig, 0, module->GetMDImport()));
1934             }
1935         }
1936         else if (TypeFromToken(sigMethTok) == mdtMethodDef)
1937         {
1938             IfFailThrow(module->GetMDImport()->GetSigOfMethodDef(sigMethTok, &cbSig, &pSig));
1939         }
1940     }
1941
1942     CEEInfo::ConvToJitSig(
1943         pSig, 
1944         cbSig, 
1945         scopeHnd, 
1946         sigMethTok, 
1947         sigRet, 
1948         GetMethodFromContext(context), 
1949         false,
1950         GetTypeFromContext(context));
1951     EE_TO_JIT_TRANSITION();
1952 } // CEEInfo::findCallSiteSig
1953
1954 //---------------------------------------------------------------------------------------
1955 // 
1956 void 
1957 CEEInfo::findSig(
1958     CORINFO_MODULE_HANDLE  scopeHnd, 
1959     unsigned               sigTok, 
1960     CORINFO_CONTEXT_HANDLE context, 
1961     CORINFO_SIG_INFO *     sigRet)
1962 {
1963     CONTRACTL {
1964         SO_TOLERANT;
1965         THROWS;
1966         GC_TRIGGERS;
1967         MODE_PREEMPTIVE;
1968     } CONTRACTL_END;
1969
1970     JIT_TO_EE_TRANSITION();
1971
1972     PCCOR_SIGNATURE       pSig = NULL;
1973     DWORD                 cbSig = 0;
1974
1975     if (IsDynamicScope(scopeHnd))
1976     {
1977         SigPointer sig = GetDynamicResolver(scopeHnd)->ResolveSignature(sigTok);
1978         sig.GetSignature(&pSig, &cbSig);
1979         sigTok = mdTokenNil;
1980     }
1981     else
1982     {
1983         Module * module = (Module *)scopeHnd;
1984         
1985         // We need to resolve this stand alone sig
1986         IfFailThrow(module->GetMDImport()->GetSigFromToken(
1987             (mdSignature)sigTok, 
1988             &cbSig, 
1989             &pSig));
1990     }
1991
1992     CEEInfo::ConvToJitSig(
1993         pSig, 
1994         cbSig, 
1995         scopeHnd, 
1996         sigTok, 
1997         sigRet, 
1998         GetMethodFromContext(context), 
1999         false,
2000         GetTypeFromContext(context));
2001     
2002     EE_TO_JIT_TRANSITION();
2003 } // CEEInfo::findSig
2004
2005 //---------------------------------------------------------------------------------------
2006 // 
2007 unsigned 
2008 CEEInfo::getClassSize(
2009     CORINFO_CLASS_HANDLE clsHnd)
2010 {
2011     CONTRACTL {
2012         SO_TOLERANT;
2013         NOTHROW;
2014         GC_NOTRIGGER;
2015         MODE_PREEMPTIVE;
2016     } CONTRACTL_END;
2017
2018     unsigned result = 0;
2019
2020     JIT_TO_EE_TRANSITION_LEAF();
2021
2022     TypeHandle VMClsHnd(clsHnd);
2023     result = VMClsHnd.GetSize();
2024
2025     EE_TO_JIT_TRANSITION_LEAF();
2026
2027     return result;
2028 }
2029
2030 unsigned CEEInfo::getClassAlignmentRequirement(CORINFO_CLASS_HANDLE type, BOOL fDoubleAlignHint)
2031 {
2032     CONTRACTL {
2033         SO_TOLERANT;
2034         NOTHROW;
2035         GC_NOTRIGGER;
2036         MODE_PREEMPTIVE;
2037     } CONTRACTL_END;
2038
2039     // Default alignment is sizeof(void*)
2040     unsigned result = sizeof(void*);
2041
2042     JIT_TO_EE_TRANSITION_LEAF();
2043
2044     TypeHandle clsHnd(type);
2045
2046 #ifdef FEATURE_DOUBLE_ALIGNMENT_HINT
2047     if (fDoubleAlignHint)
2048     {
2049         MethodTable* pMT = clsHnd.GetMethodTable();
2050         if (pMT != NULL)
2051         {
2052             // Return the size of the double align hint. Ignore the actual alignment info account
2053             // so that structs with 64-bit integer fields do not trigger double aligned frames on x86.
2054             if (pMT->GetClass()->IsAlign8Candidate())
2055                 result = 8;
2056         }
2057     }
2058     else
2059 #endif
2060     {
2061         result = getClassAlignmentRequirementStatic(clsHnd);
2062     }
2063
2064     EE_TO_JIT_TRANSITION_LEAF();
2065
2066     return result;
2067 }
2068
2069 unsigned CEEInfo::getClassAlignmentRequirementStatic(TypeHandle clsHnd)
2070 {
2071     LIMITED_METHOD_CONTRACT;
2072
2073     // Default alignment is sizeof(void*)
2074     unsigned result = sizeof(void*);
2075
2076     MethodTable * pMT = clsHnd.GetMethodTable();
2077     if (pMT == NULL)
2078         return result;
2079
2080     if (pMT->HasLayout())
2081     {
2082         EEClassLayoutInfo* pInfo = pMT->GetLayoutInfo();
2083
2084         if (clsHnd.IsNativeValueType())
2085         {
2086             // if it's the unmanaged view of the managed type, we always use the unmanaged alignment requirement
2087             result = pInfo->m_LargestAlignmentRequirementOfAllMembers;
2088         }
2089         else
2090         if (pInfo->IsManagedSequential())
2091         {
2092             _ASSERTE(!pMT->ContainsPointers());
2093
2094             // if it's managed sequential, we use the managed alignment requirement
2095             result = pInfo->m_ManagedLargestAlignmentRequirementOfAllMembers;
2096         }
2097         else if (pInfo->IsBlittable())
2098         {
2099             _ASSERTE(!pMT->ContainsPointers());
2100
2101             // if it's blittable, we use the unmanaged alignment requirement
2102             result = pInfo->m_LargestAlignmentRequirementOfAllMembers;
2103         }
2104     }
2105
2106 #ifdef FEATURE_64BIT_ALIGNMENT
2107     if (result < 8 && pMT->RequiresAlign8())
2108     {
2109         // If the structure contains 64-bit primitive fields and the platform requires 8-byte alignment for
2110         // such fields then make sure we return at least 8-byte alignment. Note that it's technically possible
2111         // to create unmanaged APIs that take unaligned structures containing such fields and this
2112         // unconditional alignment bump would cause us to get the calling convention wrong on platforms such
2113         // as ARM. If we see such cases in the future we'd need to add another control (such as an alignment
2114         // property for the StructLayout attribute or a marshaling directive attribute for p/invoke arguments)
2115         // that allows more precise control. For now we'll go with the likely scenario.
2116         result = 8;
2117     }
2118 #endif // FEATURE_64BIT_ALIGNMENT
2119
2120     return result;
2121 }
2122
2123 CORINFO_FIELD_HANDLE
2124 CEEInfo::getFieldInClass(CORINFO_CLASS_HANDLE clsHnd, INT num)
2125 {
2126     CONTRACTL {
2127         SO_TOLERANT;
2128         NOTHROW;
2129         GC_NOTRIGGER;
2130         MODE_PREEMPTIVE;
2131     } CONTRACTL_END;
2132
2133     CORINFO_FIELD_HANDLE result = NULL;
2134
2135     JIT_TO_EE_TRANSITION_LEAF();
2136
2137     TypeHandle VMClsHnd(clsHnd);
2138
2139     MethodTable* pMT= VMClsHnd.AsMethodTable();
2140
2141     result = (CORINFO_FIELD_HANDLE) ((pMT->GetApproxFieldDescListRaw()) + num);
2142
2143     EE_TO_JIT_TRANSITION_LEAF();
2144
2145     return result;
2146 }
2147
2148 mdMethodDef
2149 CEEInfo::getMethodDefFromMethod(CORINFO_METHOD_HANDLE hMethod)
2150 {
2151     CONTRACTL {
2152         SO_TOLERANT;
2153         NOTHROW;
2154         GC_NOTRIGGER;
2155         MODE_PREEMPTIVE;
2156     } CONTRACTL_END;
2157
2158     mdMethodDef result = 0;
2159
2160     JIT_TO_EE_TRANSITION_LEAF();
2161
2162     MethodDesc* pMD = GetMethod(hMethod);
2163
2164     if (pMD->IsDynamicMethod())
2165     {
2166         // Dynamic methods do not have tokens
2167         result = mdMethodDefNil;
2168     }
2169     else
2170     {
2171         result = pMD->GetMemberDef();
2172     }
2173
2174     EE_TO_JIT_TRANSITION_LEAF();
2175
2176     return result;
2177 }
2178
2179 BOOL CEEInfo::checkMethodModifier(CORINFO_METHOD_HANDLE hMethod,
2180                                   LPCSTR modifier,
2181                                   BOOL fOptional)
2182 {
2183     CONTRACTL {
2184         SO_TOLERANT;
2185         THROWS;
2186         GC_TRIGGERS;
2187         MODE_PREEMPTIVE;
2188     } CONTRACTL_END;
2189
2190     BOOL result = FALSE;
2191
2192     JIT_TO_EE_TRANSITION();
2193
2194     MethodDesc* pMD = GetMethod(hMethod);
2195     Module* pModule = pMD->GetModule();
2196     MetaSig sig(pMD);
2197     CorElementType eeType = fOptional ? ELEMENT_TYPE_CMOD_OPT : ELEMENT_TYPE_CMOD_REQD;
2198
2199     // modopts/modreqs for the method are by convention stored on the return type
2200     result = sig.GetReturnProps().HasCustomModifier(pModule, modifier, eeType);
2201
2202     EE_TO_JIT_TRANSITION();
2203
2204     return result;
2205 }
2206
2207 /*********************************************************************/
2208 static unsigned ComputeGCLayout(MethodTable * pMT, BYTE* gcPtrs)
2209 {
2210     STANDARD_VM_CONTRACT;
2211
2212     unsigned result = 0;
2213
2214     _ASSERTE(pMT->IsValueType());
2215
2216     // TODO: TypedReference should ideally be implemented as a by-ref-like struct containing a ByReference<T> field, in which
2217     // case the check for g_TypedReferenceMT below would not be necessary
2218     if (pMT == g_TypedReferenceMT || pMT->HasSameTypeDefAs(g_pByReferenceClass))
2219     {
2220         if (gcPtrs[0] == TYPE_GC_NONE)
2221         {
2222             gcPtrs[0] = TYPE_GC_BYREF;
2223             result++;
2224         }
2225         else if (gcPtrs[0] != TYPE_GC_BYREF)
2226         {
2227             COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
2228         }
2229         return result;
2230     }
2231
2232     ApproxFieldDescIterator fieldIterator(pMT, ApproxFieldDescIterator::INSTANCE_FIELDS);
2233     for (FieldDesc *pFD = fieldIterator.Next(); pFD != NULL; pFD = fieldIterator.Next())
2234     {
2235         int fieldStartIndex = pFD->GetOffset() / sizeof(void*);
2236
2237         if (pFD->GetFieldType() != ELEMENT_TYPE_VALUETYPE)
2238         {
2239             if (pFD->IsObjRef())
2240             {
2241                 if (gcPtrs[fieldStartIndex] == TYPE_GC_NONE)
2242                 {
2243                     gcPtrs[fieldStartIndex] = TYPE_GC_REF;
2244                     result++;
2245                 }
2246                 else if (gcPtrs[fieldStartIndex] != TYPE_GC_REF)
2247                 {
2248                     COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
2249                 }
2250             }
2251         }
2252         else
2253         {
2254             MethodTable * pFieldMT = pFD->GetApproxFieldTypeHandleThrowing().AsMethodTable();
2255             result += ComputeGCLayout(pFieldMT, gcPtrs + fieldStartIndex);
2256         }
2257     }
2258     return result;
2259 }
2260
2261 unsigned CEEInfo::getClassGClayout (CORINFO_CLASS_HANDLE clsHnd, BYTE* gcPtrs)
2262 {
2263     CONTRACTL {
2264         SO_TOLERANT;
2265         THROWS;
2266         GC_TRIGGERS;
2267         MODE_PREEMPTIVE;
2268     } CONTRACTL_END;
2269
2270     unsigned result = 0;
2271
2272     JIT_TO_EE_TRANSITION();
2273
2274     TypeHandle VMClsHnd(clsHnd);
2275
2276     MethodTable* pMT = VMClsHnd.GetMethodTable();
2277
2278     if (pMT->IsByRefLike())
2279     {
2280         // TODO: TypedReference should ideally be implemented as a by-ref-like struct containing a ByReference<T> field, in
2281         // which case the check for g_TypedReferenceMT below would not be necessary
2282         if (pMT == g_TypedReferenceMT)
2283         {
2284             gcPtrs[0] = TYPE_GC_BYREF;
2285             gcPtrs[1] = TYPE_GC_NONE;
2286             result = 1;
2287         }
2288         else
2289         {
2290             memset(gcPtrs, TYPE_GC_NONE,
2291                 (VMClsHnd.GetSize() + sizeof(void*) - 1) / sizeof(void*));
2292             // Note: This case is more complicated than the TypedReference case
2293             // due to ByRefLike structs being included as fields in other value 
2294             // types (TypedReference can not be.)
2295             result = ComputeGCLayout(VMClsHnd.AsMethodTable(), gcPtrs);
2296         }
2297     }
2298     else if (VMClsHnd.IsNativeValueType())
2299     {
2300         // native value types have no GC pointers
2301         result = 0;
2302         memset(gcPtrs, TYPE_GC_NONE,
2303                (VMClsHnd.GetSize() + sizeof(void*) -1)/ sizeof(void*));
2304     }
2305     else
2306     {
2307         _ASSERTE(pMT->IsValueType());
2308         _ASSERTE(sizeof(BYTE) == 1);
2309
2310         // assume no GC pointers at first
2311         result = 0;
2312         memset(gcPtrs, TYPE_GC_NONE,
2313                (VMClsHnd.GetSize() + sizeof(void*) -1)/ sizeof(void*));
2314
2315         // walk the GC descriptors, turning on the correct bits
2316         if (pMT->ContainsPointers())
2317         {
2318             CGCDesc* map = CGCDesc::GetCGCDescFromMT(pMT);
2319             CGCDescSeries * pByValueSeries = map->GetLowestSeries();
2320
2321             for (SIZE_T i = 0; i < map->GetNumSeries(); i++)
2322             {
2323                 // Get offset into the value class of the first pointer field (includes a +Object)
2324                 size_t cbSeriesSize = pByValueSeries->GetSeriesSize() + pMT->GetBaseSize();
2325                 size_t cbOffset = pByValueSeries->GetSeriesOffset() - sizeof(Object);
2326
2327                 _ASSERTE (cbOffset % sizeof(void*) == 0);
2328                 _ASSERTE (cbSeriesSize % sizeof(void*) == 0);
2329
2330                 result += (unsigned) (cbSeriesSize / sizeof(void*));
2331                 memset(&gcPtrs[cbOffset/sizeof(void*)], TYPE_GC_REF, cbSeriesSize / sizeof(void*));
2332
2333                 pByValueSeries++;
2334             }
2335         }
2336     }
2337
2338     EE_TO_JIT_TRANSITION();
2339
2340     return result;
2341 }
2342
2343 // returns the enregister info for a struct based on type of fields, alignment, etc.
2344 bool CEEInfo::getSystemVAmd64PassStructInRegisterDescriptor(
2345                                                 /*IN*/  CORINFO_CLASS_HANDLE structHnd,
2346                                                 /*OUT*/ SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr)
2347 {
2348     CONTRACTL {
2349         SO_TOLERANT;
2350         THROWS;
2351         GC_TRIGGERS;
2352         MODE_PREEMPTIVE;
2353     } CONTRACTL_END;
2354
2355 #if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF)
2356     JIT_TO_EE_TRANSITION();
2357
2358     _ASSERTE(structPassInRegDescPtr != nullptr);
2359     TypeHandle th(structHnd);
2360
2361     structPassInRegDescPtr->passedInRegisters = false;
2362     
2363     // Make sure this is a value type.
2364     if (th.IsValueType())
2365     {
2366         _ASSERTE((CorInfoType2UnixAmd64Classification(th.GetInternalCorElementType()) == SystemVClassificationTypeStruct) ||
2367                  (CorInfoType2UnixAmd64Classification(th.GetInternalCorElementType()) == SystemVClassificationTypeTypedReference));
2368
2369         // The useNativeLayout in this case tracks whether the classification
2370         // is for a native layout of the struct or not.
2371         // If the struct has special marshaling it has a native layout. 
2372         // In such cases the classifier needs to use the native layout.
2373         // For structs with no native layout, the managed layout should be used
2374         // even if classified for the purposes of marshaling/PInvoke passing.
2375         bool useNativeLayout = false;
2376         MethodTable* methodTablePtr = nullptr;
2377         if (!th.IsTypeDesc())
2378         {
2379             methodTablePtr = th.AsMethodTable();
2380         }
2381         else
2382         {
2383             _ASSERTE(th.IsNativeValueType());
2384
2385             useNativeLayout = true;
2386             methodTablePtr = th.AsNativeValueType();
2387         }
2388         _ASSERTE(methodTablePtr != nullptr);
2389
2390         // If we have full support for FEATURE_UNIX_AMD64_STRUCT_PASSING, and not just the interface,
2391         // then we've cached whether this is a reg passed struct in the MethodTable, computed during
2392         // MethodTable construction. Otherwise, we are just building in the interface, and we haven't
2393         // computed or cached anything, so we need to compute it now.
2394 #if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
2395         bool canPassInRegisters = useNativeLayout ? methodTablePtr->GetLayoutInfo()->IsNativeStructPassedInRegisters()
2396                                                   : methodTablePtr->IsRegPassedStruct();
2397 #else // !defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
2398         SystemVStructRegisterPassingHelper helper((unsigned int)th.GetSize());
2399         bool canPassInRegisters = methodTablePtr->ClassifyEightBytes(&helper, 0, 0, useNativeLayout);
2400 #endif // !defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
2401
2402         if (canPassInRegisters)
2403         {
2404 #if defined(FEATURE_UNIX_AMD64_STRUCT_PASSING)
2405             SystemVStructRegisterPassingHelper helper((unsigned int)th.GetSize());
2406             bool result = methodTablePtr->ClassifyEightBytes(&helper, 0, 0, useNativeLayout);
2407
2408             // The answer must be true at this point.
2409             _ASSERTE(result);
2410 #endif // FEATURE_UNIX_AMD64_STRUCT_PASSING
2411
2412             structPassInRegDescPtr->passedInRegisters = true;
2413
2414             structPassInRegDescPtr->eightByteCount = helper.eightByteCount;
2415             _ASSERTE(structPassInRegDescPtr->eightByteCount <= CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS);
2416
2417             for (unsigned int i = 0; i < CLR_SYSTEMV_MAX_EIGHTBYTES_COUNT_TO_PASS_IN_REGISTERS; i++)
2418             {
2419                 structPassInRegDescPtr->eightByteClassifications[i] = helper.eightByteClassifications[i];
2420                 structPassInRegDescPtr->eightByteSizes[i] = helper.eightByteSizes[i];
2421                 structPassInRegDescPtr->eightByteOffsets[i] = helper.eightByteOffsets[i];
2422             }
2423         }
2424
2425         _ASSERTE(structPassInRegDescPtr->passedInRegisters == canPassInRegisters);
2426     }
2427
2428     EE_TO_JIT_TRANSITION();
2429
2430     return true;
2431 #else // !defined(FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF)
2432     return false;
2433 #endif // !defined(FEATURE_UNIX_AMD64_STRUCT_PASSING_ITF)
2434 }
2435
2436 /*********************************************************************/
2437 unsigned CEEInfo::getClassNumInstanceFields (CORINFO_CLASS_HANDLE clsHnd)
2438 {
2439     CONTRACTL {
2440         SO_TOLERANT;
2441         NOTHROW;
2442         GC_NOTRIGGER;
2443         MODE_PREEMPTIVE;
2444     } CONTRACTL_END;
2445
2446     unsigned result = 0;
2447
2448     JIT_TO_EE_TRANSITION_LEAF();
2449
2450     TypeHandle th(clsHnd);
2451
2452     if (!th.IsTypeDesc())
2453     {
2454         result = th.AsMethodTable()->GetNumInstanceFields();
2455     }
2456     else
2457     {
2458         // native value types are opaque aggregates with explicit size
2459         result = 0;
2460     }
2461
2462     EE_TO_JIT_TRANSITION_LEAF();
2463
2464     return result;
2465 }
2466
2467
2468 CorInfoType CEEInfo::asCorInfoType (CORINFO_CLASS_HANDLE clsHnd)
2469 {
2470     CONTRACTL {
2471         SO_TOLERANT;
2472         THROWS;
2473         GC_TRIGGERS;
2474         MODE_PREEMPTIVE;
2475     } CONTRACTL_END;
2476
2477     CorInfoType result = CORINFO_TYPE_UNDEF;
2478
2479     JIT_TO_EE_TRANSITION();
2480
2481     TypeHandle VMClsHnd(clsHnd);
2482     result = toJitType(VMClsHnd);
2483
2484     EE_TO_JIT_TRANSITION();
2485
2486     return result;
2487 }
2488
2489
2490 CORINFO_LOOKUP_KIND CEEInfo::getLocationOfThisType(CORINFO_METHOD_HANDLE context)
2491 {
2492     CONTRACTL {
2493         SO_TOLERANT;
2494         THROWS;
2495         GC_TRIGGERS;
2496         MODE_PREEMPTIVE;
2497     } CONTRACTL_END;
2498
2499     CORINFO_LOOKUP_KIND result;
2500
2501     /* Initialize fields of result for debug build warning */
2502     result.needsRuntimeLookup = false;
2503     result.runtimeLookupKind  = CORINFO_LOOKUP_THISOBJ;
2504
2505     JIT_TO_EE_TRANSITION();
2506
2507     MethodDesc *pContextMD = GetMethod(context);
2508
2509     // If the method table is not shared, then return CONST
2510     if (!pContextMD->GetMethodTable()->IsSharedByGenericInstantiations())
2511     {
2512         result.needsRuntimeLookup = false;
2513     }
2514     else
2515     {
2516         result.needsRuntimeLookup = true;
2517
2518         // If we've got a vtable extra argument, go through that
2519         if (pContextMD->RequiresInstMethodTableArg())
2520         {
2521             result.runtimeLookupKind = CORINFO_LOOKUP_CLASSPARAM;
2522         }
2523         // If we've got an object, go through its vtable
2524         else if (pContextMD->AcquiresInstMethodTableFromThis())
2525         {
2526             result.runtimeLookupKind = CORINFO_LOOKUP_THISOBJ;
2527         }
2528         // Otherwise go through the method-desc argument
2529         else
2530         {
2531             _ASSERTE(pContextMD->RequiresInstMethodDescArg());
2532             result.runtimeLookupKind = CORINFO_LOOKUP_METHODPARAM;
2533         }
2534     }
2535
2536     EE_TO_JIT_TRANSITION();
2537
2538     return result;
2539 }
2540
2541 CORINFO_METHOD_HANDLE CEEInfo::GetDelegateCtor(
2542                                         CORINFO_METHOD_HANDLE methHnd,
2543                                         CORINFO_CLASS_HANDLE clsHnd,
2544                                         CORINFO_METHOD_HANDLE targetMethodHnd,
2545                                         DelegateCtorArgs *pCtorData)
2546 {
2547     CONTRACTL {
2548         SO_TOLERANT;
2549         THROWS;
2550         GC_TRIGGERS;
2551         MODE_PREEMPTIVE;
2552     } CONTRACTL_END;
2553
2554     if (isVerifyOnly())
2555     {
2556         // No sense going through the optimized case just for verification and it can cause issues parsing
2557         // uninstantiated generic signatures.
2558         return methHnd;
2559     }
2560
2561     CORINFO_METHOD_HANDLE result = NULL;
2562
2563     JIT_TO_EE_TRANSITION();
2564
2565     MethodDesc *pCurrentCtor = (MethodDesc*)methHnd;
2566     if (!pCurrentCtor->IsFCall())
2567     {
2568         result =  methHnd;
2569     }
2570     else
2571     {
2572         MethodDesc *pTargetMethod = (MethodDesc*)targetMethodHnd;
2573         TypeHandle delegateType = (TypeHandle)clsHnd;
2574
2575         MethodDesc *pDelegateCtor = COMDelegate::GetDelegateCtor(delegateType, pTargetMethod, pCtorData);
2576         if (!pDelegateCtor)
2577             pDelegateCtor = pCurrentCtor;
2578         result = (CORINFO_METHOD_HANDLE)pDelegateCtor;
2579     }
2580
2581     EE_TO_JIT_TRANSITION();
2582
2583     return result;
2584 }
2585
2586 void CEEInfo::MethodCompileComplete(CORINFO_METHOD_HANDLE methHnd)
2587 {
2588     CONTRACTL {
2589         SO_TOLERANT;
2590         THROWS;
2591         GC_TRIGGERS;
2592         MODE_PREEMPTIVE;
2593     } CONTRACTL_END;
2594
2595     JIT_TO_EE_TRANSITION();
2596
2597     MethodDesc* pMD = GetMethod(methHnd);
2598
2599     if (pMD->IsDynamicMethod())
2600     {
2601         pMD->AsDynamicMethodDesc()->GetResolver()->FreeCompileTimeState();
2602     }
2603
2604     EE_TO_JIT_TRANSITION();
2605 }
2606
2607 // Given a module scope (scopeHnd), a method handle (context) and an metadata token,
2608 // attempt to load the handle (type, field or method) associated with the token.
2609 // If this is not possible at compile-time (because the method code is shared and the token contains type parameters)
2610 // then indicate how the handle should be looked up at run-time.
2611 //
2612 // See corinfo.h for more details
2613 //
2614 void CEEInfo::embedGenericHandle(
2615             CORINFO_RESOLVED_TOKEN * pResolvedToken,
2616             BOOL                     fEmbedParent,
2617             CORINFO_GENERICHANDLE_RESULT *pResult)
2618 {
2619     CONTRACTL {
2620         SO_TOLERANT;
2621         THROWS;
2622         GC_TRIGGERS;
2623         MODE_PREEMPTIVE;
2624     } CONTRACTL_END;
2625
2626     INDEBUG(memset(pResult, 0xCC, sizeof(*pResult)));
2627
2628     JIT_TO_EE_TRANSITION();
2629
2630     BOOL fRuntimeLookup;
2631     MethodDesc * pTemplateMD = NULL;    
2632
2633     if (!fEmbedParent && pResolvedToken->hMethod != NULL)
2634     {
2635         MethodDesc * pMD = (MethodDesc *)pResolvedToken->hMethod;
2636         TypeHandle th(pResolvedToken->hClass);
2637
2638         pResult->handleType = CORINFO_HANDLETYPE_METHOD;
2639
2640         Instantiation methodInst = pMD->GetMethodInstantiation();
2641
2642         pMD = MethodDesc::FindOrCreateAssociatedMethodDesc(pMD, th.GetMethodTable(), FALSE, methodInst, FALSE);
2643
2644         // Normalize the method handle for reflection
2645         if (pResolvedToken->tokenType == CORINFO_TOKENKIND_Ldtoken)
2646             pMD = MethodDesc::FindOrCreateAssociatedMethodDescForReflection(pMD, th, methodInst);
2647
2648         pResult->compileTimeHandle = (CORINFO_GENERIC_HANDLE)pMD;
2649         pTemplateMD = pMD;
2650
2651         // Runtime lookup is only required for stubs. Regular entrypoints are always the same shared MethodDescs.
2652         fRuntimeLookup = pMD->IsWrapperStub() &&
2653             (pMD->GetMethodTable()->IsSharedByGenericInstantiations() || TypeHandle::IsCanonicalSubtypeInstantiation(methodInst));
2654     }
2655     else
2656     if (!fEmbedParent && pResolvedToken->hField != NULL)
2657     {
2658         FieldDesc * pFD = (FieldDesc *)pResolvedToken->hField;
2659         TypeHandle th(pResolvedToken->hClass);
2660
2661         pResult->handleType = CORINFO_HANDLETYPE_FIELD;
2662
2663         pResult->compileTimeHandle = (CORINFO_GENERIC_HANDLE)pFD;
2664
2665         fRuntimeLookup = th.IsSharedByGenericInstantiations() && pFD->IsStatic();
2666     }
2667     else
2668     {
2669         TypeHandle th(pResolvedToken->hClass);
2670
2671         pResult->handleType = CORINFO_HANDLETYPE_CLASS;
2672
2673         if (pResolvedToken->tokenType == CORINFO_TOKENKIND_Newarr)
2674         {
2675             pResult->compileTimeHandle = (CORINFO_GENERIC_HANDLE)th.AsArray()->GetTemplateMethodTable();
2676         }
2677         else
2678         {
2679             pResult->compileTimeHandle = (CORINFO_GENERIC_HANDLE)th.AsPtr();
2680         }
2681
2682         if (fEmbedParent && pResolvedToken->hMethod != NULL)
2683         {
2684             MethodDesc * pDeclaringMD = (MethodDesc *)pResolvedToken->hMethod;
2685
2686             if (!pDeclaringMD->GetMethodTable()->HasSameTypeDefAs(th.GetMethodTable()))
2687             {
2688                 //
2689                 // The method type may point to a sub-class of the actual class that declares the method.
2690                 // It is important to embed the declaring type in this case.
2691                 //
2692
2693                 pTemplateMD = pDeclaringMD;
2694
2695                 pResult->compileTimeHandle = (CORINFO_GENERIC_HANDLE)pDeclaringMD->GetMethodTable();
2696             }
2697         }
2698
2699         // IsSharedByGenericInstantiations would not work here. The runtime lookup is required
2700         // even for standalone generic variables that show up as __Canon here.
2701         fRuntimeLookup = th.IsCanonicalSubtype();
2702     }
2703
2704     _ASSERTE(pResult->compileTimeHandle);
2705
2706     if (fRuntimeLookup 
2707             // Handle invalid IL - see comment in code:CEEInfo::ComputeRuntimeLookupForSharedGenericToken
2708             && ContextIsShared(pResolvedToken->tokenContext))
2709     {
2710         DictionaryEntryKind entryKind = EmptySlot;
2711         switch (pResult->handleType)
2712         {
2713         case CORINFO_HANDLETYPE_CLASS:
2714             entryKind = (pTemplateMD != NULL) ? DeclaringTypeHandleSlot : TypeHandleSlot;
2715             break;
2716         case CORINFO_HANDLETYPE_METHOD:
2717             entryKind = MethodDescSlot;
2718             break;
2719         case CORINFO_HANDLETYPE_FIELD:
2720             entryKind = FieldDescSlot;
2721             break;
2722         default:
2723             _ASSERTE(false);
2724         }
2725
2726         ComputeRuntimeLookupForSharedGenericToken(entryKind,
2727                                                   pResolvedToken,
2728                                                   NULL,
2729                                                   pTemplateMD,
2730                                                   &pResult->lookup);
2731     }
2732     else
2733     {
2734         // If the target is not shared then we've already got our result and
2735         // can simply do a static look up
2736         pResult->lookup.lookupKind.needsRuntimeLookup = false;
2737
2738         pResult->lookup.constLookup.handle = pResult->compileTimeHandle;
2739         pResult->lookup.constLookup.accessType = IAT_VALUE;
2740     }
2741     
2742     EE_TO_JIT_TRANSITION();
2743 }
2744
2745 void CEEInfo::ScanForModuleDependencies(Module* pModule, SigPointer psig)
2746 {
2747     STANDARD_VM_CONTRACT;
2748
2749     _ASSERTE(pModule && !pModule->IsSystem());
2750
2751     CorElementType eType;
2752     IfFailThrow(psig.GetElemType(&eType));
2753     
2754     switch (eType)
2755     {
2756         case ELEMENT_TYPE_GENERICINST:
2757         {
2758             ScanForModuleDependencies(pModule,psig);
2759             IfFailThrow(psig.SkipExactlyOne());
2760
2761             ULONG ntypars;
2762             IfFailThrow(psig.GetData(&ntypars));
2763             for (ULONG i = 0; i < ntypars; i++)
2764             {
2765               ScanForModuleDependencies(pModule,psig);
2766               IfFailThrow(psig.SkipExactlyOne());
2767             }
2768             break;
2769         }
2770
2771         case ELEMENT_TYPE_VALUETYPE:
2772         case ELEMENT_TYPE_CLASS:
2773         {
2774             mdToken tk;
2775             IfFailThrow(psig.GetToken(&tk));
2776             if (TypeFromToken(tk) ==  mdtTypeRef)
2777             {
2778                 Module * pTypeDefModule;
2779                 mdToken tkTypeDef;
2780
2781                 if  (ClassLoader::ResolveTokenToTypeDefThrowing(pModule, tk, &pTypeDefModule, &tkTypeDef))
2782                     break;
2783
2784                 if (!pTypeDefModule->IsSystem() && (pModule != pTypeDefModule))
2785                 {
2786                     m_pOverride->addActiveDependency((CORINFO_MODULE_HANDLE)pModule, (CORINFO_MODULE_HANDLE)pTypeDefModule);
2787                 }
2788             }
2789             break;
2790         }
2791
2792         default:
2793             break;
2794     }
2795 }
2796
2797 void CEEInfo::ScanMethodSpec(Module * pModule, PCCOR_SIGNATURE pMethodSpec, ULONG cbMethodSpec)
2798 {
2799     STANDARD_VM_CONTRACT;
2800
2801     SigPointer sp(pMethodSpec, cbMethodSpec);
2802
2803     BYTE etype;
2804     IfFailThrow(sp.GetByte(&etype));
2805
2806     _ASSERT(etype == (BYTE)IMAGE_CEE_CS_CALLCONV_GENERICINST);
2807
2808     ULONG nGenericMethodArgs;
2809     IfFailThrow(sp.GetData(&nGenericMethodArgs));
2810
2811     for (ULONG i = 0; i < nGenericMethodArgs; i++)
2812     {
2813         ScanForModuleDependencies(pModule,sp);
2814         IfFailThrow(sp.SkipExactlyOne());
2815     }
2816 }
2817
2818 BOOL CEEInfo::ScanTypeSpec(Module * pModule, PCCOR_SIGNATURE pTypeSpec, ULONG cbTypeSpec)
2819 {
2820     STANDARD_VM_CONTRACT;
2821
2822     SigPointer sp(pTypeSpec, cbTypeSpec);
2823
2824     CorElementType eType;
2825     IfFailThrow(sp.GetElemType(&eType));
2826
2827     // Filter out non-instantiated types and typedescs (typevars, arrays, ...)
2828     if (eType != ELEMENT_TYPE_GENERICINST)
2829     {
2830         // Scanning of the parent chain is required for reference types only.
2831         // Note that the parent chain MUST NOT be scanned for instantiated 
2832         // generic variables because of they are not a real dependencies.
2833         return (eType == ELEMENT_TYPE_CLASS);
2834     }
2835
2836     IfFailThrow(sp.SkipExactlyOne());
2837
2838     ULONG ntypars;
2839     IfFailThrow(sp.GetData(&ntypars));
2840
2841     for (ULONG i = 0; i < ntypars; i++)
2842     {
2843         ScanForModuleDependencies(pModule,sp);
2844         IfFailThrow(sp.SkipExactlyOne());
2845     }
2846
2847     return TRUE;
2848 }
2849
2850 void CEEInfo::ScanInstantiation(Module * pModule, Instantiation inst)
2851 {
2852     STANDARD_VM_CONTRACT;
2853
2854     for (DWORD i = 0; i < inst.GetNumArgs(); i++)
2855     {
2856         TypeHandle th = inst[i];
2857         if (th.IsTypeDesc())
2858             continue;
2859
2860         MethodTable * pMT = th.AsMethodTable();
2861
2862         Module * pDefModule = pMT->GetModule();
2863
2864         if (!pDefModule->IsSystem() && (pModule != pDefModule))
2865         {
2866             m_pOverride->addActiveDependency((CORINFO_MODULE_HANDLE)pModule, (CORINFO_MODULE_HANDLE)pDefModule);
2867         }
2868
2869         if (pMT->HasInstantiation())
2870         {
2871             ScanInstantiation(pModule, pMT->GetInstantiation());
2872         }
2873     }
2874 }
2875
2876 //
2877 // ScanToken is used to track triggers for creation of per-AppDomain state instead, including allocations required for statics and
2878 // triggering of module cctors.
2879 //
2880 // The basic rule is: There should be no possibility of a shared module that is "active" to have a direct call into a  module that 
2881 // is not "active". And we don't want to intercept every call during runtime, so during compile time we track static calls and 
2882 // everything that can result in new virtual calls.
2883 //
2884 // The current algoritm (scan the parent type chain and instantiation variables) is more than enough to maintain this invariant.
2885 // One could come up with a more efficient algorithm that still maintains the invariant, but it may introduce backward compatibility
2886 // issues.
2887 //
2888 // For efficiency, the implementation leverages the loaded types as much as possible. Unfortunately, we still have to go back to
2889 // metadata when the generic variables could have been substituted via generic context.
2890 //
2891 void CEEInfo::ScanToken(Module * pModule, CORINFO_RESOLVED_TOKEN * pResolvedToken, TypeHandle th, MethodDesc * pMD)
2892 {
2893     STANDARD_VM_CONTRACT;
2894
2895     if (pModule->IsSystem())
2896         return;
2897
2898     if (isVerifyOnly())
2899         return;
2900
2901     //
2902     // Scan method instantiation
2903     //
2904     if (pMD != NULL && pResolvedToken->pMethodSpec != NULL)
2905     {
2906         if (ContextIsInstantiated(pResolvedToken->tokenContext))
2907         {
2908             ScanMethodSpec(pModule, pResolvedToken->pMethodSpec, pResolvedToken->cbMethodSpec);
2909         }
2910         else
2911         {
2912             ScanInstantiation(pModule, pMD->GetMethodInstantiation());
2913         }
2914     }
2915
2916     if (th.IsTypeDesc())
2917         return;
2918
2919     MethodTable * pMT = th.AsMethodTable();
2920
2921     //
2922     // Scan type instantiation
2923     //
2924     if (pResolvedToken->pTypeSpec != NULL)
2925     {
2926         if (ContextIsInstantiated(pResolvedToken->tokenContext))
2927         {
2928             if (!ScanTypeSpec(pModule, pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec))
2929                 return;
2930         }
2931         else
2932         {
2933             ScanInstantiation(pModule, pMT->GetInstantiation());
2934         }
2935     }
2936
2937     //
2938     // Scan chain of parent types
2939     //
2940     for (;;)
2941     {
2942         Module * pDefModule = pMT->GetModule();
2943         if (pDefModule->IsSystem())
2944             break;
2945
2946         if (pModule != pDefModule)
2947         {
2948             m_pOverride->addActiveDependency((CORINFO_MODULE_HANDLE)pModule, (CORINFO_MODULE_HANDLE)pDefModule);
2949         }
2950
2951         MethodTable * pParentMT = pMT->GetParentMethodTable();
2952         if (pParentMT == NULL)
2953             break;
2954
2955         if (pParentMT->HasInstantiation())
2956         {
2957             IMDInternalImport* pInternalImport = pDefModule->GetMDImport();
2958
2959             mdToken tkParent;
2960             IfFailThrow(pInternalImport->GetTypeDefProps(pMT->GetCl(), NULL, &tkParent));
2961
2962             if (TypeFromToken(tkParent) == mdtTypeSpec)
2963             {
2964                 PCCOR_SIGNATURE pTypeSpec;
2965                 ULONG           cbTypeSpec;
2966                 IfFailThrow(pInternalImport->GetTypeSpecFromToken(tkParent, &pTypeSpec, &cbTypeSpec));
2967
2968                 ScanTypeSpec(pDefModule, pTypeSpec, cbTypeSpec);
2969             }
2970         }
2971
2972         pMT = pParentMT;
2973     }
2974 }
2975
2976 void CEEInfo::ScanTokenForDynamicScope(CORINFO_RESOLVED_TOKEN * pResolvedToken, TypeHandle th, MethodDesc * pMD)
2977 {
2978     STANDARD_VM_CONTRACT;
2979
2980     if (m_pMethodBeingCompiled->IsLCGMethod())
2981     {
2982         // The dependency tracking for LCG is irrelevant. Perform immediate activation.
2983         if (pMD != NULL && pMD->HasMethodInstantiation())
2984             pMD->EnsureActive();
2985         if (!th.IsTypeDesc())
2986             th.AsMethodTable()->EnsureInstanceActive();
2987         return;
2988     }
2989
2990     // Stubs-as-IL have to do regular dependency tracking because they can be shared cross-domain.
2991     Module * pModule = GetDynamicResolver(pResolvedToken->tokenScope)->GetDynamicMethod()->GetModule();
2992     ScanToken(pModule, pResolvedToken, th, pMD);
2993 }
2994
2995 MethodDesc * CEEInfo::GetMethodForSecurity(CORINFO_METHOD_HANDLE callerHandle)
2996 {
2997     STANDARD_VM_CONTRACT;
2998
2999     // Cache the cast lookup
3000     if (callerHandle == m_hMethodForSecurity_Key)
3001     {
3002         return m_pMethodForSecurity_Value;
3003     }
3004
3005     MethodDesc * pCallerMethod = (MethodDesc *)callerHandle;
3006
3007     //If the caller is generic, load the open type and then load the field again,  This allows us to
3008     //differentiate between BadGeneric<T> containing a memberRef for a field of type InaccessibleClass and
3009     //GoodGeneric<T> containing a memberRef for a field of type T instantiated over InaccessibleClass.
3010     MethodDesc * pMethodForSecurity = pCallerMethod->IsILStub() ? 
3011         pCallerMethod : pCallerMethod->LoadTypicalMethodDefinition();
3012
3013     m_hMethodForSecurity_Key = callerHandle;
3014     m_pMethodForSecurity_Value = pMethodForSecurity;
3015
3016     return pMethodForSecurity;
3017 }
3018
3019 // Check that the instantation is <!/!!0, ..., !/!!(n-1)>
3020 static BOOL IsSignatureForTypicalInstantiation(SigPointer sigptr, CorElementType varType, ULONG ntypars)
3021 {
3022     STANDARD_VM_CONTRACT;
3023
3024     for (ULONG i = 0; i < ntypars; i++)
3025     {
3026         CorElementType type;
3027         IfFailThrow(sigptr.GetElemType(&type));
3028         if (type != varType)
3029             return FALSE;
3030
3031         ULONG data;
3032         IfFailThrow(sigptr.GetData(&data));
3033                     
3034         if (data != i)
3035              return FALSE;
3036     }
3037
3038     return TRUE;
3039 }
3040
3041 // Check that methodSpec instantiation is <!!0, ..., !!(n-1)>
3042 static BOOL IsMethodSpecForTypicalInstantation(SigPointer sigptr)
3043 {
3044     STANDARD_VM_CONTRACT;
3045
3046     BYTE etype;
3047     IfFailThrow(sigptr.GetByte(&etype));
3048     _ASSERTE(etype == (BYTE)IMAGE_CEE_CS_CALLCONV_GENERICINST);
3049
3050     ULONG ntypars;
3051     IfFailThrow(sigptr.GetData(&ntypars));
3052
3053     return IsSignatureForTypicalInstantiation(sigptr, ELEMENT_TYPE_MVAR, ntypars);
3054 }
3055
3056 // Check that typeSpec instantiation is <!0, ..., !(n-1)>
3057 static BOOL IsTypeSpecForTypicalInstantiation(SigPointer sigptr)
3058 {
3059     STANDARD_VM_CONTRACT;
3060
3061     CorElementType type;
3062     IfFailThrow(sigptr.GetElemType(&type));
3063     if (type != ELEMENT_TYPE_GENERICINST)
3064         return FALSE;
3065
3066     IfFailThrow(sigptr.SkipExactlyOne());
3067
3068     ULONG ntypars;
3069     IfFailThrow(sigptr.GetData(&ntypars));
3070
3071     return IsSignatureForTypicalInstantiation(sigptr, ELEMENT_TYPE_VAR, ntypars);
3072 }
3073
3074 void CEEInfo::ComputeRuntimeLookupForSharedGenericToken(DictionaryEntryKind entryKind,
3075                                                         CORINFO_RESOLVED_TOKEN * pResolvedToken,
3076                                                         CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken,
3077                                                         MethodDesc * pTemplateMD /* for method-based slots */,
3078                                                         CORINFO_LOOKUP *pResultLookup)
3079 {
3080     CONTRACTL{
3081         STANDARD_VM_CHECK;
3082         PRECONDITION(CheckPointer(pResultLookup));
3083     } CONTRACTL_END;
3084
3085
3086     // We should never get here when we are only verifying
3087     _ASSERTE(!isVerifyOnly());
3088
3089     pResultLookup->lookupKind.needsRuntimeLookup = true;
3090     pResultLookup->lookupKind.runtimeLookupFlags = 0;
3091
3092     CORINFO_RUNTIME_LOOKUP *pResult = &pResultLookup->runtimeLookup;
3093     pResult->signature = NULL;
3094
3095     pResult->indirectFirstOffset = 0;
3096     pResult->indirectSecondOffset = 0;
3097
3098     // Unless we decide otherwise, just do the lookup via a helper function
3099     pResult->indirections = CORINFO_USEHELPER;
3100
3101     MethodDesc *pContextMD = GetMethodFromContext(pResolvedToken->tokenContext);
3102     MethodTable *pContextMT = pContextMD->GetMethodTable();
3103
3104     // Do not bother computing the runtime lookup if we are inlining. The JIT is going
3105     // to abort the inlining attempt anyway.
3106     if (pContextMD != m_pMethodBeingCompiled)
3107     {
3108         return;
3109     }
3110
3111     // There is a pathological case where invalid IL refereces __Canon type directly, but there is no dictionary availabled to store the lookup. 
3112     // All callers of ComputeRuntimeLookupForSharedGenericToken have to filter out this case. We can't do much about it here.
3113     _ASSERTE(pContextMD->IsSharedByGenericInstantiations());
3114
3115     BOOL fInstrument = FALSE;
3116
3117 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
3118     // This will make sure that when IBC logging is turned on we will go through a version
3119     // of JIT_GenericHandle which logs the access. Note that we still want the dictionaries
3120     // to be populated to prepopulate the types at NGen time.
3121     if (IsCompilingForNGen() &&
3122         GetAppDomain()->ToCompilationDomain()->m_fForceInstrument)
3123     {
3124         fInstrument = TRUE;
3125     }
3126 #endif // FEATURE_NATIVE_IMAGE_GENERATION
3127
3128     if (pContextMD->RequiresInstMethodDescArg())
3129     {
3130         pResultLookup->lookupKind.runtimeLookupKind = CORINFO_LOOKUP_METHODPARAM;
3131     }
3132     else
3133     {
3134         if (pContextMD->RequiresInstMethodTableArg())
3135             pResultLookup->lookupKind.runtimeLookupKind = CORINFO_LOOKUP_CLASSPARAM;
3136         else
3137             pResultLookup->lookupKind.runtimeLookupKind = CORINFO_LOOKUP_THISOBJ;
3138     }
3139
3140 #ifdef FEATURE_READYTORUN_COMPILER
3141     if (IsReadyToRunCompilation())
3142     {
3143 #if defined(_TARGET_ARM_)
3144         ThrowHR(E_NOTIMPL); /* TODO - NYI */
3145 #endif
3146         pResultLookup->lookupKind.runtimeLookupArgs = NULL;
3147
3148         switch (entryKind)
3149         {
3150         case DeclaringTypeHandleSlot:
3151             _ASSERTE(pTemplateMD != NULL);
3152             pResultLookup->lookupKind.runtimeLookupArgs = pTemplateMD->GetMethodTable();
3153             pResultLookup->lookupKind.runtimeLookupFlags = READYTORUN_FIXUP_DeclaringTypeHandle;
3154             break;
3155
3156         case TypeHandleSlot:
3157             pResultLookup->lookupKind.runtimeLookupFlags = READYTORUN_FIXUP_TypeHandle;
3158             break;
3159
3160         case MethodDescSlot:
3161         case MethodEntrySlot:
3162         case ConstrainedMethodEntrySlot:
3163         case DispatchStubAddrSlot:
3164         {
3165             if (pTemplateMD != (MethodDesc*)pResolvedToken->hMethod)
3166                 ThrowHR(E_NOTIMPL);
3167
3168             if (entryKind == MethodDescSlot)
3169                 pResultLookup->lookupKind.runtimeLookupFlags = READYTORUN_FIXUP_MethodHandle;
3170             else if (entryKind == MethodEntrySlot || entryKind == ConstrainedMethodEntrySlot)
3171                 pResultLookup->lookupKind.runtimeLookupFlags = READYTORUN_FIXUP_MethodEntry;
3172             else
3173                 pResultLookup->lookupKind.runtimeLookupFlags = READYTORUN_FIXUP_VirtualEntry;
3174
3175             pResultLookup->lookupKind.runtimeLookupArgs = pConstrainedResolvedToken;
3176
3177             break;
3178         }
3179
3180         case FieldDescSlot:
3181             pResultLookup->lookupKind.runtimeLookupFlags = READYTORUN_FIXUP_FieldHandle;
3182             break;
3183
3184         default:
3185             _ASSERTE(!"Unknown dictionary entry kind!");
3186             IfFailThrow(E_FAIL);
3187         }
3188
3189         // For R2R compilations, we don't generate the dictionary lookup signatures (dictionary lookups are done in a 
3190         // different way that is more version resilient... plus we can't have pointers to existing MTs/MDs in the sigs)
3191         return;
3192     }
3193 #endif
3194     // If we've got a  method type parameter of any kind then we must look in the method desc arg
3195     if (pContextMD->RequiresInstMethodDescArg())
3196     {
3197         pResult->helper = fInstrument ? CORINFO_HELP_RUNTIMEHANDLE_METHOD_LOG : CORINFO_HELP_RUNTIMEHANDLE_METHOD;
3198
3199         if (fInstrument)
3200             goto NoSpecialCase;
3201
3202         // Special cases:
3203         // (1) Naked method type variable: look up directly in instantiation hanging off runtime md
3204         // (2) Reference to method-spec of current method (e.g. a recursive call) i.e. currentmeth<!0,...,!(n-1)>
3205         if ((entryKind == TypeHandleSlot) && (pResolvedToken->tokenType != CORINFO_TOKENKIND_Newarr))
3206         {
3207             SigPointer sigptr(pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec);
3208             CorElementType type;
3209             IfFailThrow(sigptr.GetElemType(&type));
3210             if (type == ELEMENT_TYPE_MVAR)
3211             {
3212                 pResult->indirections = 2;
3213                 pResult->testForNull = 0;
3214 #ifdef FEATURE_PREJIT
3215                 pResult->testForFixup = 1;
3216 #else
3217                 pResult->testForFixup = 0;
3218 #endif
3219                 pResult->offsets[0] = offsetof(InstantiatedMethodDesc, m_pPerInstInfo);
3220
3221                 if (decltype(InstantiatedMethodDesc::m_pPerInstInfo)::isRelative)
3222                 {
3223                     pResult->indirectFirstOffset = 1;
3224                 }
3225
3226                 ULONG data;
3227                 IfFailThrow(sigptr.GetData(&data));
3228                 pResult->offsets[1] = sizeof(TypeHandle) * data;
3229
3230                 return;
3231             }
3232         }
3233         else if (entryKind == MethodDescSlot)
3234         {
3235             // It's the context itself (i.e. a recursive call)
3236             if (!pTemplateMD->HasSameMethodDefAs(pContextMD))
3237                 goto NoSpecialCase;
3238
3239             // Now just check that the instantiation is (!!0, ..., !!(n-1))
3240             if (!IsMethodSpecForTypicalInstantation(SigPointer(pResolvedToken->pMethodSpec, pResolvedToken->cbMethodSpec)))
3241                 goto NoSpecialCase;
3242
3243             // Type instantiation has to match too if there is one
3244             if (pContextMT->HasInstantiation())
3245             {
3246                 TypeHandle thTemplate(pResolvedToken->hClass);
3247
3248                 if (thTemplate.IsTypeDesc() || !thTemplate.AsMethodTable()->HasSameTypeDefAs(pContextMT))
3249                     goto NoSpecialCase;
3250
3251                 // This check filters out method instantiation on generic type definition, like G::M<!!0>()
3252                 // We may not ever get it here. Filter it out just to be sure...
3253                 if (pResolvedToken->pTypeSpec == NULL)
3254                     goto NoSpecialCase;
3255
3256                 if (!IsTypeSpecForTypicalInstantiation(SigPointer(pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec)))
3257                     goto NoSpecialCase;
3258             }
3259
3260             // Just use the method descriptor that was passed in!
3261             pResult->indirections = 0;
3262             pResult->testForNull = 0;
3263             pResult->testForFixup = 0;
3264
3265             return;
3266         }
3267     }
3268     // Otherwise we must just have class type variables
3269     else
3270     {
3271         _ASSERTE(pContextMT->GetNumGenericArgs() > 0);
3272
3273         if (pContextMD->RequiresInstMethodTableArg())
3274         {
3275             // If we've got a vtable extra argument, go through that
3276             pResult->helper = fInstrument ? CORINFO_HELP_RUNTIMEHANDLE_CLASS_LOG : CORINFO_HELP_RUNTIMEHANDLE_CLASS;
3277         }
3278         // If we've got an object, go through its vtable
3279         else
3280         {
3281             _ASSERTE(pContextMD->AcquiresInstMethodTableFromThis());
3282             pResult->helper = fInstrument ? CORINFO_HELP_RUNTIMEHANDLE_CLASS_LOG : CORINFO_HELP_RUNTIMEHANDLE_CLASS;
3283         }
3284
3285         if (fInstrument)
3286             goto NoSpecialCase;
3287
3288         // Special cases:
3289         // (1) Naked class type variable: look up directly in instantiation hanging off vtable
3290         // (2) C<!0,...,!(n-1)> where C is the context's class and C is sealed: just return vtable ptr
3291         if ((entryKind == TypeHandleSlot) && (pResolvedToken->tokenType != CORINFO_TOKENKIND_Newarr))
3292         {
3293             SigPointer sigptr(pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec);
3294             CorElementType type;
3295             IfFailThrow(sigptr.GetElemType(&type));
3296             if (type == ELEMENT_TYPE_VAR)
3297             {
3298                 pResult->indirections = 3;
3299                 pResult->testForNull = 0;
3300 #ifdef FEATURE_PREJIT
3301                 pResult->testForFixup = 1;
3302 #else
3303                 pResult->testForFixup = 0;
3304 #endif
3305                 pResult->offsets[0] = MethodTable::GetOffsetOfPerInstInfo();
3306                 pResult->offsets[1] = sizeof(TypeHandle*) * (pContextMT->GetNumDicts() - 1);
3307                 ULONG data;
3308                 IfFailThrow(sigptr.GetData(&data));
3309                 pResult->offsets[2] = sizeof(TypeHandle) * data;
3310
3311                 if (MethodTable::IsPerInstInfoRelative())
3312                 {
3313                     pResult->indirectFirstOffset = 1;
3314                     pResult->indirectSecondOffset = 1;
3315                 }
3316
3317                 return;
3318             }
3319             else if (type == ELEMENT_TYPE_GENERICINST &&
3320                 (pContextMT->IsSealed() || pResultLookup->lookupKind.runtimeLookupKind == CORINFO_LOOKUP_CLASSPARAM))
3321             {
3322                 TypeHandle thTemplate(pResolvedToken->hClass);
3323
3324                 if (thTemplate.IsTypeDesc() || !thTemplate.AsMethodTable()->HasSameTypeDefAs(pContextMT))
3325                     goto NoSpecialCase;
3326
3327                 if (!IsTypeSpecForTypicalInstantiation(SigPointer(pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec)))
3328                     goto NoSpecialCase;
3329
3330                 // Just use the vtable pointer itself!
3331                 pResult->indirections = 0;
3332                 pResult->testForNull = 0;
3333                 pResult->testForFixup = 0;
3334
3335                 return;
3336             }
3337         }
3338     }
3339
3340 NoSpecialCase:
3341
3342     SigBuilder sigBuilder;
3343
3344     sigBuilder.AppendData(entryKind);
3345
3346     if (pResultLookup->lookupKind.runtimeLookupKind != CORINFO_LOOKUP_METHODPARAM)
3347     {
3348         _ASSERTE(pContextMT->GetNumDicts() > 0);
3349         sigBuilder.AppendData(pContextMT->GetNumDicts() - 1);
3350     }
3351
3352     Module * pModule = (Module *)pResolvedToken->tokenScope;
3353
3354     switch (entryKind)
3355     {
3356     case DeclaringTypeHandleSlot:
3357         _ASSERTE(pTemplateMD != NULL);
3358         sigBuilder.AppendElementType(ELEMENT_TYPE_INTERNAL);
3359         sigBuilder.AppendPointer(pTemplateMD->GetMethodTable());
3360         // fall through
3361
3362     case TypeHandleSlot:
3363         {
3364             if (pResolvedToken->tokenType == CORINFO_TOKENKIND_Newarr)
3365             {
3366                 if (!IsReadyToRunCompilation())
3367                 {
3368                     sigBuilder.AppendElementType((CorElementType)ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG);
3369                 }
3370
3371                 sigBuilder.AppendElementType(ELEMENT_TYPE_SZARRAY);
3372             }
3373
3374             // Note that we can come here with pResolvedToken->pTypeSpec == NULL for invalid IL that 
3375             // directly references __Canon
3376             if (pResolvedToken->pTypeSpec != NULL)
3377             {
3378                 SigPointer sigptr(pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec);
3379                 sigptr.ConvertToInternalExactlyOne(pModule, NULL, &sigBuilder);
3380             }
3381             else
3382             {
3383                 sigBuilder.AppendElementType(ELEMENT_TYPE_INTERNAL);
3384                 sigBuilder.AppendPointer(pResolvedToken->hClass);
3385             }
3386         }
3387         break;
3388
3389     case ConstrainedMethodEntrySlot:
3390         // Encode constrained type token
3391         if (pConstrainedResolvedToken->pTypeSpec != NULL)
3392         {
3393             SigPointer sigptr(pConstrainedResolvedToken->pTypeSpec, pConstrainedResolvedToken->cbTypeSpec);
3394             sigptr.ConvertToInternalExactlyOne(pModule, NULL, &sigBuilder);
3395         }
3396         else
3397         {
3398             sigBuilder.AppendElementType(ELEMENT_TYPE_INTERNAL);
3399             sigBuilder.AppendPointer(pConstrainedResolvedToken->hClass);
3400         }
3401         // fall through
3402
3403     case MethodDescSlot:
3404     case MethodEntrySlot:
3405     case DispatchStubAddrSlot:
3406         {
3407             // Encode containing type
3408             if (pResolvedToken->pTypeSpec != NULL)
3409             {
3410                 SigPointer sigptr(pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec);
3411                 sigptr.ConvertToInternalExactlyOne(pModule, NULL, &sigBuilder);
3412             }
3413             else
3414             {
3415                 sigBuilder.AppendElementType(ELEMENT_TYPE_INTERNAL);
3416                 sigBuilder.AppendPointer(pResolvedToken->hClass);
3417             }
3418
3419             // Encode method
3420             _ASSERTE(pTemplateMD != NULL);
3421
3422             mdMethodDef methodToken               = pTemplateMD->GetMemberDef_NoLogging();
3423             DWORD       methodFlags               = 0;
3424
3425             // Check for non-NULL method spec first. We can encode the method instantiation only if we have one in method spec to start with. Note that there are weird cases 
3426             // like instantiating stub for generic method definition that do not have method spec but that won't be caught by the later conditions either.
3427             BOOL fMethodNeedsInstantiation = (pResolvedToken->pMethodSpec != NULL) && pTemplateMD->HasMethodInstantiation() && !pTemplateMD->IsGenericMethodDefinition();
3428
3429             if (pTemplateMD->IsUnboxingStub())
3430                 methodFlags |= ENCODE_METHOD_SIG_UnboxingStub;
3431             // Always create instantiating stub for method entry points even if the template does not ask for it. It saves caller 
3432             // from creating throw-away instantiating stub.
3433             if (pTemplateMD->IsInstantiatingStub() || (entryKind == MethodEntrySlot))
3434                 methodFlags |= ENCODE_METHOD_SIG_InstantiatingStub;
3435             if (fMethodNeedsInstantiation)
3436                 methodFlags |= ENCODE_METHOD_SIG_MethodInstantiation;
3437             if (IsNilToken(methodToken))
3438             {
3439                 methodFlags |= ENCODE_METHOD_SIG_SlotInsteadOfToken;
3440             }
3441             else
3442             if (entryKind == DispatchStubAddrSlot && pTemplateMD->IsVtableMethod())
3443             {
3444                 // Encode the method for dispatch stub using slot to avoid touching the interface method MethodDesc at runtime
3445
3446                 // There should be no other flags set if we are encoding the method using slot for virtual stub dispatch
3447                 _ASSERTE(methodFlags == 0);
3448
3449                 methodFlags |= ENCODE_METHOD_SIG_SlotInsteadOfToken;
3450             }
3451             else
3452             if (!pTemplateMD->GetModule()->IsInCurrentVersionBubble())
3453             {
3454                 // Using a method defined in another version bubble. We can assume the slot number is stable only for real interface methods.
3455                 if (!pTemplateMD->GetMethodTable()->IsInterface() || pTemplateMD->IsStatic() || pTemplateMD->HasMethodInstantiation())
3456                 {
3457                     _ASSERTE(!"References to non-interface methods not yet supported in version resilient images");
3458                     IfFailThrow(E_FAIL);
3459                 }
3460                 methodFlags |= ENCODE_METHOD_SIG_SlotInsteadOfToken;
3461             }
3462
3463             sigBuilder.AppendData(methodFlags);
3464
3465             if ((methodFlags & ENCODE_METHOD_SIG_SlotInsteadOfToken) == 0)
3466             {
3467                 // Encode method token and its module context (as method's type)
3468                 sigBuilder.AppendElementType(ELEMENT_TYPE_INTERNAL);
3469                 sigBuilder.AppendPointer(pTemplateMD->GetMethodTable());
3470                 
3471                 sigBuilder.AppendData(RidFromToken(methodToken));
3472             }
3473             else
3474             {
3475                 sigBuilder.AppendData(pTemplateMD->GetSlot());
3476             }
3477
3478             if (fMethodNeedsInstantiation)
3479             {
3480                 SigPointer sigptr(pResolvedToken->pMethodSpec, pResolvedToken->cbMethodSpec);
3481                 
3482                 BYTE etype;
3483                 IfFailThrow(sigptr.GetByte(&etype));
3484
3485                 // Load the generic method instantiation
3486                 THROW_BAD_FORMAT_MAYBE(etype == (BYTE)IMAGE_CEE_CS_CALLCONV_GENERICINST, 0, pModule);
3487                 
3488                 DWORD nGenericMethodArgs;
3489                 IfFailThrow(sigptr.GetData(&nGenericMethodArgs));
3490                 sigBuilder.AppendData(nGenericMethodArgs);
3491                 
3492                 _ASSERTE(nGenericMethodArgs == pTemplateMD->GetNumGenericMethodArgs());
3493                 
3494                 for (DWORD i = 0; i < nGenericMethodArgs; i++)
3495                 {
3496                     sigptr.ConvertToInternalExactlyOne(pModule, NULL, &sigBuilder);
3497                 }
3498             }
3499         }
3500         break;
3501         
3502     case FieldDescSlot:
3503         {
3504             if (pResolvedToken->pTypeSpec != NULL)
3505             {
3506                  // Encode containing type
3507                 SigPointer sigptr(pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec);
3508                 sigptr.ConvertToInternalExactlyOne(pModule, NULL, &sigBuilder);
3509             }
3510             else
3511             {
3512                 sigBuilder.AppendElementType(ELEMENT_TYPE_INTERNAL);
3513                 sigBuilder.AppendPointer(pResolvedToken->hClass);
3514             }
3515
3516             FieldDesc * pField = (FieldDesc *)pResolvedToken->hField;
3517             _ASSERTE(pField != NULL);
3518
3519             DWORD fieldIndex = pField->GetApproxEnclosingMethodTable()->GetIndexForFieldDesc(pField);
3520             sigBuilder.AppendData(fieldIndex);
3521         }
3522         break;
3523         
3524     default:
3525         _ASSERTE(false);
3526     }
3527
3528     DictionaryEntrySignatureSource signatureSource = (IsCompilationProcess() ? FromZapImage : FromJIT);
3529
3530     // It's a method dictionary lookup
3531     if (pResultLookup->lookupKind.runtimeLookupKind == CORINFO_LOOKUP_METHODPARAM)
3532     {
3533         _ASSERTE(pContextMD != NULL);
3534         _ASSERTE(pContextMD->HasMethodInstantiation());
3535
3536         if (DictionaryLayout::FindToken(pContextMD->GetLoaderAllocator(), pContextMD->GetNumGenericMethodArgs(), pContextMD->GetDictionaryLayout(), pResult, &sigBuilder, 1, signatureSource))
3537         {
3538             pResult->testForNull = 1;
3539             pResult->testForFixup = 0;
3540
3541             // Indirect through dictionary table pointer in InstantiatedMethodDesc
3542             pResult->offsets[0] = offsetof(InstantiatedMethodDesc, m_pPerInstInfo);
3543
3544             if (decltype(InstantiatedMethodDesc::m_pPerInstInfo)::isRelative)
3545             {
3546                 pResult->indirectFirstOffset = 1;
3547             }
3548         }
3549     }
3550
3551     // It's a class dictionary lookup (CORINFO_LOOKUP_CLASSPARAM or CORINFO_LOOKUP_THISOBJ)
3552     else
3553     {
3554         if (DictionaryLayout::FindToken(pContextMT->GetLoaderAllocator(), pContextMT->GetNumGenericArgs(), pContextMT->GetClass()->GetDictionaryLayout(), pResult, &sigBuilder, 2, signatureSource))
3555         {
3556             pResult->testForNull = 1;
3557             pResult->testForFixup = 0;
3558
3559             // Indirect through dictionary table pointer in vtable
3560             pResult->offsets[0] = MethodTable::GetOffsetOfPerInstInfo();
3561
3562             // Next indirect through the dictionary appropriate to this instantiated type
3563             pResult->offsets[1] = sizeof(TypeHandle*) * (pContextMT->GetNumDicts() - 1);
3564
3565             if (MethodTable::IsPerInstInfoRelative())
3566             {
3567                 pResult->indirectFirstOffset = 1;
3568                 pResult->indirectSecondOffset = 1;
3569             }
3570         }
3571     }
3572 }
3573
3574
3575
3576 /*********************************************************************/
3577 const char* CEEInfo::getClassName (CORINFO_CLASS_HANDLE clsHnd)
3578 {
3579     CONTRACTL {
3580         SO_TOLERANT;
3581         THROWS;
3582         GC_TRIGGERS;
3583         MODE_PREEMPTIVE;
3584     } CONTRACTL_END;
3585
3586     const char* result = NULL;
3587
3588     JIT_TO_EE_TRANSITION();
3589
3590     TypeHandle VMClsHnd(clsHnd);
3591     MethodTable* pMT = VMClsHnd.GetMethodTable();
3592     if (pMT == NULL)
3593     {
3594         result = "";
3595     }
3596     else
3597     {
3598 #ifdef _DEBUG
3599         result = pMT->GetDebugClassName();
3600 #else // !_DEBUG
3601         // since this is for diagnostic purposes only,
3602         // give up on the namespace, as we don't have a buffer to concat it
3603         // also note this won't show array class names.
3604         LPCUTF8 nameSpace;
3605         result = pMT->GetFullyQualifiedNameInfo(&nameSpace);
3606 #endif
3607     }
3608
3609     EE_TO_JIT_TRANSITION();
3610
3611     return result;
3612 }
3613
3614 /***********************************************************************/
3615 const char* CEEInfo::getHelperName (CorInfoHelpFunc ftnNum)
3616 {
3617     CONTRACTL {
3618         SO_TOLERANT;
3619         NOTHROW;
3620         GC_NOTRIGGER;
3621         MODE_PREEMPTIVE;
3622         PRECONDITION(ftnNum >= 0 && ftnNum < CORINFO_HELP_COUNT);
3623     } CONTRACTL_END;
3624
3625     const char* result = NULL;
3626
3627     JIT_TO_EE_TRANSITION_LEAF();
3628
3629 #ifdef CROSSGEN_COMPILE
3630     result = hlpNameTable[ftnNum];
3631 #else
3632 #ifdef _DEBUG
3633     result = hlpFuncTable[ftnNum].name;
3634 #else
3635     result = "AnyJITHelper";
3636 #endif
3637 #endif
3638
3639     EE_TO_JIT_TRANSITION_LEAF();
3640
3641     return result;
3642 }
3643
3644
3645 /*********************************************************************/
3646 int CEEInfo::appendClassName(__deref_inout_ecount(*pnBufLen) WCHAR** ppBuf,
3647                              int* pnBufLen,
3648                              CORINFO_CLASS_HANDLE    clsHnd,
3649                              BOOL fNamespace,
3650                              BOOL fFullInst,
3651                              BOOL fAssembly)
3652 {
3653     CONTRACTL {
3654         SO_TOLERANT;
3655         MODE_PREEMPTIVE;
3656         THROWS;
3657         GC_TRIGGERS;
3658     } CONTRACTL_END;
3659
3660     int nLen = 0;
3661
3662     JIT_TO_EE_TRANSITION();
3663
3664     TypeHandle th(clsHnd);
3665     StackSString ss;
3666     TypeString::AppendType(ss,th,
3667                            (fNamespace ? TypeString::FormatNamespace : 0) |
3668                            (fFullInst ? TypeString::FormatFullInst : 0) |
3669                            (fAssembly ? TypeString::FormatAssembly : 0));
3670     const WCHAR* szString = ss.GetUnicode();
3671     nLen = (int)wcslen(szString);
3672     if (*pnBufLen > 0)
3673     {
3674     wcscpy_s(*ppBuf, *pnBufLen, szString );
3675     (*ppBuf)[(*pnBufLen) - 1] = W('\0');
3676     (*ppBuf) += nLen;
3677     (*pnBufLen) -= nLen;
3678     }
3679
3680     EE_TO_JIT_TRANSITION();
3681
3682     return nLen;
3683 }
3684
3685 /*********************************************************************/
3686 CORINFO_MODULE_HANDLE CEEInfo::getClassModule(CORINFO_CLASS_HANDLE clsHnd)
3687 {
3688     CONTRACTL {
3689         SO_TOLERANT;
3690         NOTHROW;
3691         GC_NOTRIGGER;
3692         MODE_PREEMPTIVE;
3693     } CONTRACTL_END;
3694
3695     CORINFO_MODULE_HANDLE result = NULL;
3696
3697     JIT_TO_EE_TRANSITION_LEAF();
3698
3699     TypeHandle     VMClsHnd(clsHnd);
3700
3701     result = CORINFO_MODULE_HANDLE(VMClsHnd.GetModule());
3702
3703     EE_TO_JIT_TRANSITION_LEAF();
3704
3705     return result;
3706 }
3707
3708 /*********************************************************************/
3709 CORINFO_ASSEMBLY_HANDLE CEEInfo::getModuleAssembly(CORINFO_MODULE_HANDLE modHnd)
3710 {
3711     CONTRACTL {
3712         SO_TOLERANT;
3713         NOTHROW;
3714         GC_NOTRIGGER;
3715         MODE_PREEMPTIVE;
3716     } CONTRACTL_END;
3717
3718     CORINFO_ASSEMBLY_HANDLE result = NULL;
3719
3720     JIT_TO_EE_TRANSITION_LEAF();
3721
3722     result = CORINFO_ASSEMBLY_HANDLE(GetModule(modHnd)->GetAssembly());
3723
3724     EE_TO_JIT_TRANSITION_LEAF();
3725
3726     return result;
3727 }
3728
3729 /*********************************************************************/
3730 const char* CEEInfo::getAssemblyName(CORINFO_ASSEMBLY_HANDLE asmHnd)
3731 {
3732     CONTRACTL {
3733         SO_TOLERANT;
3734         THROWS;
3735         GC_TRIGGERS;
3736         MODE_PREEMPTIVE;
3737     } CONTRACTL_END;
3738
3739     const char*  result = NULL;
3740
3741     JIT_TO_EE_TRANSITION();
3742     result = ((Assembly*)asmHnd)->GetSimpleName();
3743     EE_TO_JIT_TRANSITION();
3744
3745     return result;
3746 }
3747
3748 /*********************************************************************/
3749 void* CEEInfo::LongLifetimeMalloc(size_t sz)
3750 {
3751     CONTRACTL {
3752         SO_TOLERANT;
3753         NOTHROW;
3754         GC_NOTRIGGER;
3755         MODE_PREEMPTIVE;
3756     } CONTRACTL_END;
3757
3758     void*  result = NULL;
3759
3760     JIT_TO_EE_TRANSITION_LEAF();
3761     result = new (nothrow) char[sz];
3762     EE_TO_JIT_TRANSITION_LEAF();
3763
3764     return result;
3765 }
3766
3767 /*********************************************************************/
3768 void CEEInfo::LongLifetimeFree(void* obj)
3769 {
3770     CONTRACTL {
3771         SO_TOLERANT;
3772         NOTHROW;
3773         GC_NOTRIGGER;
3774         MODE_PREEMPTIVE;
3775     } CONTRACTL_END;
3776
3777     JIT_TO_EE_TRANSITION_LEAF();
3778     (operator delete)(obj);
3779     EE_TO_JIT_TRANSITION_LEAF();
3780 }
3781
3782 /*********************************************************************/
3783 size_t CEEInfo::getClassModuleIdForStatics(CORINFO_CLASS_HANDLE clsHnd, CORINFO_MODULE_HANDLE *pModuleHandle, void **ppIndirection)
3784 {
3785     CONTRACTL {
3786         SO_TOLERANT;
3787         NOTHROW;
3788         GC_NOTRIGGER;
3789         MODE_PREEMPTIVE;
3790     } CONTRACTL_END;
3791
3792     size_t result = 0;
3793
3794     JIT_TO_EE_TRANSITION_LEAF();
3795
3796     TypeHandle     VMClsHnd(clsHnd);
3797     Module *pModule = VMClsHnd.AsMethodTable()->GetModuleForStatics();
3798
3799     if (ppIndirection != NULL)
3800         *ppIndirection = NULL;
3801
3802     // The zapper needs the module handle. The jit should not use it at all.
3803     if (pModuleHandle)
3804         *pModuleHandle = CORINFO_MODULE_HANDLE(pModule);
3805
3806     result = pModule->GetModuleID();
3807
3808     _ASSERTE(result);
3809
3810     EE_TO_JIT_TRANSITION_LEAF();
3811
3812     return result;
3813 }
3814
3815 /*********************************************************************/
3816 BOOL CEEInfo::isValueClass(CORINFO_CLASS_HANDLE clsHnd)
3817 {
3818     CONTRACTL {
3819         SO_TOLERANT;
3820         NOTHROW;
3821         GC_NOTRIGGER;
3822         MODE_PREEMPTIVE;
3823     } CONTRACTL_END;
3824
3825     BOOL ret = FALSE;
3826
3827     JIT_TO_EE_TRANSITION_LEAF();
3828
3829     _ASSERTE(clsHnd);
3830
3831     // Note that clsHnd.IsValueType() would not return what the JIT expects
3832     // for corner cases like ELEMENT_TYPE_FNPTR
3833     TypeHandle VMClsHnd(clsHnd);
3834     MethodTable * pMT = VMClsHnd.GetMethodTable();
3835     ret = (pMT != NULL) ? pMT->IsValueType() : 0;
3836
3837     EE_TO_JIT_TRANSITION_LEAF();
3838
3839     return ret;
3840 }
3841
3842 /*********************************************************************/
3843 // If this method returns true, JIT will do optimization to inline the check for
3844 //     GetClassFromHandle(handle) == obj.GetType()
3845 //
3846 // This will enable to use directly the typehandle instead of going through getClassByHandle
3847 BOOL CEEInfo::canInlineTypeCheckWithObjectVTable (CORINFO_CLASS_HANDLE clsHnd)
3848 {
3849     CONTRACTL {
3850         SO_TOLERANT;
3851         NOTHROW;
3852         GC_NOTRIGGER;
3853         MODE_PREEMPTIVE;
3854     } CONTRACTL_END;
3855
3856     BOOL ret = FALSE;
3857
3858     JIT_TO_EE_TRANSITION_LEAF();
3859
3860     _ASSERTE(clsHnd);
3861
3862     TypeHandle VMClsHnd(clsHnd);
3863
3864     if (VMClsHnd.IsTypeDesc())
3865     {
3866         // We can't do this optimization for arrays because of the object methodtable is template methodtable
3867         ret = FALSE;
3868     }
3869     else
3870     if (VMClsHnd.AsMethodTable()->IsMarshaledByRef())
3871     {
3872         // We can't do this optimization for marshalbyrefs because of the object methodtable can be transparent proxy
3873         ret = FALSE;
3874     }
3875     else
3876     if (VMClsHnd.AsMethodTable()->IsInterface())
3877     {
3878         // Object.GetType() should not ever return interface. However, WCF custom remoting proxy does it. Disable this
3879         // optimization for interfaces so that (autogenerated) code that compares Object.GetType() with interface type works 
3880         // as expected for WCF custom remoting proxy. Note that this optimization is still not going to work well for custom
3881         // remoting proxies that are even more broken than the WCF one, e.g. returning random non-marshalbyref types 
3882         // from Object.GetType().
3883         ret = FALSE;
3884     }
3885     else
3886     if (VMClsHnd == TypeHandle(g_pCanonMethodTableClass))   
3887     {
3888         // We can't do this optimization in shared generics code because of we do not know what the actual type is going to be.
3889         // (It can be array, marshalbyref, etc.)
3890         ret = FALSE;
3891     }
3892     else
3893     {
3894         // It is safe to perform this optimization
3895         ret = TRUE;
3896     }
3897
3898     EE_TO_JIT_TRANSITION_LEAF();
3899
3900     return(ret);
3901 }
3902
3903 /*********************************************************************/
3904 DWORD CEEInfo::getClassAttribs (CORINFO_CLASS_HANDLE clsHnd)
3905 {
3906     CONTRACTL {
3907         SO_TOLERANT;
3908         THROWS;
3909         GC_TRIGGERS;
3910         MODE_PREEMPTIVE;
3911     } CONTRACTL_END;
3912
3913     // <REVISIT_TODO>@todo FIX need to really fetch the class atributes.  at present
3914     // we don't need to because the JIT only cares in the case of COM classes</REVISIT_TODO>
3915     DWORD ret = 0;
3916
3917     JIT_TO_EE_TRANSITION();
3918
3919     ret = getClassAttribsInternal(clsHnd);
3920
3921     EE_TO_JIT_TRANSITION();
3922
3923     return ret;
3924 }
3925
3926
3927 /*********************************************************************/
3928 BOOL CEEInfo::isStructRequiringStackAllocRetBuf(CORINFO_CLASS_HANDLE clsHnd)
3929 {
3930     CONTRACTL {
3931         SO_TOLERANT;
3932         THROWS;
3933         GC_TRIGGERS;
3934         MODE_PREEMPTIVE;
3935     } CONTRACTL_END;
3936
3937     BOOL ret = 0;
3938
3939     JIT_TO_EE_TRANSITION_LEAF();
3940
3941     TypeHandle     VMClsHnd(clsHnd);
3942     MethodTable * pMT = VMClsHnd.GetMethodTable();
3943     ret = (pMT != NULL && pMT->IsStructRequiringStackAllocRetBuf());
3944
3945     EE_TO_JIT_TRANSITION_LEAF();
3946
3947     return ret;
3948 }
3949
3950 /*********************************************************************/
3951 DWORD CEEInfo::getClassAttribsInternal (CORINFO_CLASS_HANDLE clsHnd)
3952 {
3953     STANDARD_VM_CONTRACT;
3954
3955     DWORD ret = 0;
3956
3957     _ASSERTE(clsHnd);
3958
3959     TypeHandle     VMClsHnd(clsHnd);
3960
3961     // Byrefs should only occur in method and local signatures, which are accessed
3962     // using ICorClassInfo and ICorClassInfo.getChildType.
3963     // So getClassAttribs() should not be called for byrefs
3964
3965     if (VMClsHnd.IsByRef())
3966     {
3967         _ASSERTE(!"Did findClass() return a Byref?");
3968         COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
3969     }
3970     else if (VMClsHnd.IsGenericVariable())
3971     {
3972         //@GENERICSVER: for now, type variables simply report "variable".
3973         ret |= CORINFO_FLG_GENERIC_TYPE_VARIABLE;
3974     }
3975     else
3976     {
3977         MethodTable *pMT = VMClsHnd.GetMethodTable();
3978
3979         if (!pMT)
3980         {
3981             _ASSERTE(!"Did findClass() return a Byref?");
3982             COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
3983         }
3984
3985         EEClass * pClass = pMT->GetClass();
3986
3987         // The array flag is used to identify the faked-up methods on
3988         // array types, i.e. .ctor, Get, Set and Address
3989         if (pMT->IsArray())
3990             ret |= CORINFO_FLG_ARRAY;
3991
3992         if (pMT->IsInterface())
3993             ret |= CORINFO_FLG_INTERFACE;
3994
3995         if (pMT->HasComponentSize())
3996             ret |= CORINFO_FLG_VAROBJSIZE;
3997
3998         if (pMT->IsValueType())
3999         {
4000             ret |= CORINFO_FLG_VALUECLASS;
4001
4002             if (pMT->IsByRefLike())
4003                 ret |= CORINFO_FLG_CONTAINS_STACK_PTR;
4004
4005             if ((pClass->IsNotTightlyPacked() && (!pClass->IsManagedSequential() || pClass->HasExplicitSize())) ||
4006                 pMT == g_TypedReferenceMT ||
4007                 VMClsHnd.IsNativeValueType())
4008             {
4009                 ret |= CORINFO_FLG_CUSTOMLAYOUT;
4010             }
4011
4012             if (pClass->IsUnsafeValueClass())
4013                 ret |= CORINFO_FLG_UNSAFE_VALUECLASS;
4014         }
4015         if (pClass->HasExplicitFieldOffsetLayout() && pClass->HasOverLayedField())
4016             ret |= CORINFO_FLG_OVERLAPPING_FIELDS;
4017         if (VMClsHnd.IsCanonicalSubtype())
4018             ret |= CORINFO_FLG_SHAREDINST;
4019
4020         if (pMT->HasVariance())
4021             ret |= CORINFO_FLG_VARIANCE;
4022
4023         if (pMT->IsContextful())
4024             ret |= CORINFO_FLG_CONTEXTFUL;
4025
4026         if (pMT->IsMarshaledByRef())
4027             ret |= CORINFO_FLG_MARSHAL_BYREF;
4028
4029         if (pMT->ContainsPointers() || pMT == g_TypedReferenceMT)
4030             ret |= CORINFO_FLG_CONTAINS_GC_PTR;
4031
4032         if (pMT->IsDelegate())
4033             ret |= CORINFO_FLG_DELEGATE;
4034
4035         if (pClass->IsBeforeFieldInit())
4036         {
4037             if (IsReadyToRunCompilation() && !pMT->GetModule()->IsInCurrentVersionBubble())
4038             {
4039                 // For version resiliency do not allow hoisting static constructors out of loops
4040             }
4041             else
4042             {
4043                 ret |= CORINFO_FLG_BEFOREFIELDINIT;
4044             }
4045         }
4046
4047         if (pClass->IsAbstract())
4048             ret |= CORINFO_FLG_ABSTRACT;
4049
4050         if (pClass->IsSealed())
4051             ret |= CORINFO_FLG_FINAL;
4052     }
4053
4054     return ret;
4055 }
4056
4057 /*********************************************************************/
4058 //
4059 // See code:CorInfoFlag#ClassConstructionFlags  for details.
4060 //
4061 CorInfoInitClassResult CEEInfo::initClass(
4062             CORINFO_FIELD_HANDLE    field,
4063             CORINFO_METHOD_HANDLE   method,
4064             CORINFO_CONTEXT_HANDLE  context,
4065             BOOL                    speculative)
4066 {
4067     CONTRACTL {
4068         SO_TOLERANT;
4069         THROWS;
4070         GC_TRIGGERS;
4071         MODE_PREEMPTIVE;
4072     } CONTRACTL_END;
4073
4074     DWORD result = CORINFO_INITCLASS_NOT_REQUIRED;
4075
4076     JIT_TO_EE_TRANSITION();
4077     {
4078
4079     // Do not bother figuring out the initialization if we are only verifying the method.
4080     if (isVerifyOnly())
4081     {
4082         result = CORINFO_INITCLASS_NOT_REQUIRED;
4083         goto exit;
4084     }
4085
4086     FieldDesc * pFD = (FieldDesc *)field;
4087     _ASSERTE(pFD == NULL || pFD->IsStatic());
4088
4089     MethodDesc * pMD = (MethodDesc *)method;
4090
4091     TypeHandle typeToInitTH = (pFD != NULL) ? pFD->GetEnclosingMethodTable() : GetTypeFromContext(context);
4092
4093     MethodDesc *methodBeingCompiled = m_pMethodBeingCompiled;
4094
4095     BOOL fMethodDomainNeutral = methodBeingCompiled->IsDomainNeutral() || methodBeingCompiled->IsZapped() || IsCompilingForNGen();
4096
4097     MethodTable *pTypeToInitMT = typeToInitTH.AsMethodTable();
4098
4099     // This should be the most common early-out case.
4100     if (fMethodDomainNeutral)
4101     {
4102         if (pTypeToInitMT->IsClassPreInited())
4103         {
4104             result = CORINFO_INITCLASS_NOT_REQUIRED;
4105             goto exit;
4106         }
4107     }
4108     else
4109     {
4110 #ifdef CROSSGEN_COMPILE
4111         _ASSERTE(FALSE);
4112 #else // CROSSGEN_COMPILE
4113         if (pTypeToInitMT->IsClassInited())
4114         {
4115             // If the type is initialized there really is nothing to do.
4116             result = CORINFO_INITCLASS_INITIALIZED;
4117             goto exit;
4118         }
4119 #endif // CROSSGEN_COMPILE
4120     }
4121
4122     if (pTypeToInitMT->IsGlobalClass())
4123     {
4124         // For both jitted and ngen code the global class is always considered initialized
4125         result = CORINFO_INITCLASS_NOT_REQUIRED;
4126         goto exit;
4127     }
4128
4129     bool fIgnoreBeforeFieldInit = false;
4130
4131     if (pFD == NULL)
4132     {
4133         if (!fIgnoreBeforeFieldInit && pTypeToInitMT->GetClass()->IsBeforeFieldInit())
4134         {
4135             // We can wait for field accesses to run .cctor
4136             result = CORINFO_INITCLASS_NOT_REQUIRED;
4137             goto exit;
4138         }
4139
4140         // Run .cctor on statics & constructors
4141         if (pMD->IsStatic())
4142         {
4143             // Except don't class construct on .cctor - it would be circular
4144             if (pMD->IsClassConstructor())
4145             {
4146                 result = CORINFO_INITCLASS_NOT_REQUIRED;
4147                 goto exit;
4148             }
4149         }
4150         else
4151         // According to the spec, we should be able to do this optimization for both reference and valuetypes.
4152         // To maintain backward compatibility, we are doing it for reference types only.
4153         if (!pMD->IsCtor() && !pTypeToInitMT->IsValueType())
4154         {
4155             // For instance methods of types with precise-initialization
4156             // semantics, we can assume that the .ctor triggerred the
4157             // type initialization.
4158             // This does not hold for NULL "this" object. However, the spec does
4159             // not require that case to work.
4160             result = CORINFO_INITCLASS_NOT_REQUIRED;
4161             goto exit;
4162         }
4163     }
4164
4165     if (pTypeToInitMT->IsSharedByGenericInstantiations())
4166     {
4167         // Shared generic code has to use helper. Moreover, tell JIT not to inline since
4168         // inlining of generic dictionary lookups is not supported.
4169         result = CORINFO_INITCLASS_USE_HELPER | CORINFO_INITCLASS_DONT_INLINE;
4170         goto exit;
4171     }
4172
4173     //
4174     // Try to prove that the initialization is not necessary because of nesting
4175     //
4176
4177     if (pFD == NULL)
4178     {
4179         // Handled above
4180         _ASSERTE(fIgnoreBeforeFieldInit || !pTypeToInitMT->GetClass()->IsBeforeFieldInit());
4181
4182         // Note that jit has both methods the same if asking whether to emit cctor
4183         // for a given method's code (as opposed to inlining codegen).
4184         if (context != MAKE_METHODCONTEXT(methodBeingCompiled) && pTypeToInitMT == methodBeingCompiled->GetMethodTable())
4185         {
4186             // If we're inling a call to a method in our own type, then we should already
4187             // have triggered the .cctor when caller was itself called.
4188             result = CORINFO_INITCLASS_NOT_REQUIRED;
4189             goto exit;
4190         }
4191     }
4192     else
4193     {
4194         // This optimization may cause static fields in reference types to be accessed without cctor being triggered
4195         // for NULL "this" object. It does not conform with what the spec says. However, we have been historically 
4196         // doing it for perf reasons.
4197         if (!pTypeToInitMT->IsValueType() && !pTypeToInitMT->GetClass()->IsBeforeFieldInit())
4198         {
4199             if (pTypeToInitMT == GetTypeFromContext(context).AsMethodTable() || pTypeToInitMT == methodBeingCompiled->GetMethodTable())
4200             {
4201                 // The class will be initialized by the time we access the field.
4202                 result = CORINFO_INITCLASS_NOT_REQUIRED;
4203                 goto exit;
4204             }
4205         }
4206
4207         // If we are currently compiling the class constructor for this static field access then we can skip the initClass 
4208         if (methodBeingCompiled->GetMethodTable() == pTypeToInitMT && methodBeingCompiled->IsStatic() && methodBeingCompiled->IsClassConstructor())
4209         {
4210             // The class will be initialized by the time we access the field.
4211             result = CORINFO_INITCLASS_NOT_REQUIRED;
4212             goto exit;
4213         }
4214     }
4215
4216     if (fMethodDomainNeutral)
4217     {
4218         // Well, because of code sharing we can't do anything at coge generation time.
4219         // We have to do it at runtime.
4220         result = CORINFO_INITCLASS_USE_HELPER;
4221         goto exit;
4222     }
4223
4224 #ifndef CROSSGEN_COMPILE
4225     //
4226     // Optimizations for domain specific code
4227     //
4228
4229     // Allocate space for the local class if necessary, but don't trigger
4230     // class construction.
4231     DomainLocalModule *pModule = pTypeToInitMT->GetDomainLocalModule();
4232     pModule->PopulateClass(pTypeToInitMT);
4233
4234     if (pTypeToInitMT->IsClassInited())
4235     {
4236         result = CORINFO_INITCLASS_INITIALIZED;
4237         goto exit;
4238     }
4239
4240 #ifdef FEATURE_MULTICOREJIT
4241     // Once multicore JIT is enabled in an AppDomain by calling SetProfileRoot, always use helper function to call class init, for consistency
4242     if (! GetAppDomain()->GetMulticoreJitManager().AllowCCtorsToRunDuringJITing())
4243     {
4244         result = CORINFO_INITCLASS_USE_HELPER;
4245
4246         goto exit;
4247     }
4248 #endif
4249
4250     // To preserve consistent behavior between ngen and not-ngenned states, do not eagerly
4251     // run class constructors for autongennable code.
4252     if (pTypeToInitMT->RunCCTorAsIfNGenImageExists())
4253     {
4254         result = CORINFO_INITCLASS_USE_HELPER;
4255         goto exit;
4256     }
4257
4258     if (!pTypeToInitMT->GetClass()->IsBeforeFieldInit())
4259     {
4260         // Do not inline the access if we cannot initialize the class. Chances are that the class will get
4261         // initialized by the time the access is jitted.
4262         result = CORINFO_INITCLASS_USE_HELPER | CORINFO_INITCLASS_DONT_INLINE;
4263         goto exit;
4264     }
4265
4266     if (speculative)
4267     {
4268         // Tell the JIT that we may be able to initialize the class when asked to.
4269         result = CORINFO_INITCLASS_SPECULATIVE;
4270         goto exit;
4271     }
4272
4273     //
4274     // We cannot run the class constructor without first activating the
4275     // module containing the class.  However, since the current module
4276     // we are compiling inside is not active, we don't want to do this.
4277     //
4278     // This should be an unusal case since normally the method's module should
4279     // be active during jitting.
4280     //
4281     // @TODO: We should check IsActivating() instead of IsActive() since we may
4282     // be running the Module::.cctor(). The assembly is not marked as active
4283     // until then.
4284     if (!methodBeingCompiled->GetLoaderModule()->GetDomainFile()->IsActive())
4285     {
4286         result = CORINFO_INITCLASS_USE_HELPER;
4287         goto exit;
4288     }
4289
4290     //
4291     // Run the .cctor
4292     //
4293
4294     EX_TRY
4295     {
4296         pTypeToInitMT->CheckRunClassInitThrowing();
4297     }
4298     EX_CATCH
4299     {
4300     } EX_END_CATCH(SwallowAllExceptions);
4301
4302     if (pTypeToInitMT->IsClassInited())
4303     {
4304         result = CORINFO_INITCLASS_INITIALIZED;
4305         goto exit;
4306     }
4307 #endif // CROSSGEN_COMPILE
4308
4309     // Do not inline the access if we were unable to initialize the class. Chances are that the class will get
4310     // initialized by the time the access is jitted.
4311     result = (CORINFO_INITCLASS_USE_HELPER | CORINFO_INITCLASS_DONT_INLINE);
4312
4313     }
4314 exit: ;
4315     EE_TO_JIT_TRANSITION();
4316
4317     return (CorInfoInitClassResult)result;
4318 }
4319
4320
4321
4322 void CEEInfo::classMustBeLoadedBeforeCodeIsRun (CORINFO_CLASS_HANDLE typeToLoadHnd)
4323 {
4324     CONTRACTL {
4325         SO_TOLERANT;
4326         NOTHROW;
4327         GC_NOTRIGGER;
4328         MODE_PREEMPTIVE;
4329     } CONTRACTL_END;
4330
4331     JIT_TO_EE_TRANSITION_LEAF();
4332
4333     TypeHandle th = TypeHandle(typeToLoadHnd);
4334
4335     // Type handles returned to JIT at runtime are always fully loaded. Verify that it is the case.
4336     _ASSERTE(th.IsFullyLoaded());
4337
4338     EE_TO_JIT_TRANSITION_LEAF();
4339 }
4340
4341 /*********************************************************************/
4342 void CEEInfo::methodMustBeLoadedBeforeCodeIsRun (CORINFO_METHOD_HANDLE methHnd)
4343 {
4344     CONTRACTL {
4345         SO_TOLERANT;
4346         NOTHROW;
4347         GC_NOTRIGGER;
4348         MODE_PREEMPTIVE;
4349     } CONTRACTL_END;
4350
4351     JIT_TO_EE_TRANSITION_LEAF();
4352
4353     MethodDesc *pMD = (MethodDesc*) methHnd;
4354
4355     // MethodDescs returned to JIT at runtime are always fully loaded. Verify that it is the case.
4356     _ASSERTE(pMD->IsRestored() && pMD->GetMethodTable()->IsFullyLoaded());
4357
4358     EE_TO_JIT_TRANSITION_LEAF();
4359 }
4360
4361 /*********************************************************************/
4362 CORINFO_METHOD_HANDLE CEEInfo::mapMethodDeclToMethodImpl(CORINFO_METHOD_HANDLE methHnd)
4363 {
4364     CONTRACTL {
4365         SO_TOLERANT;
4366         THROWS;
4367         GC_TRIGGERS;
4368         MODE_PREEMPTIVE;
4369     } CONTRACTL_END;
4370
4371     CORINFO_METHOD_HANDLE result = NULL;
4372
4373     JIT_TO_EE_TRANSITION();
4374
4375     MethodDesc *pMD = GetMethod(methHnd);
4376     pMD = MethodTable::MapMethodDeclToMethodImpl(pMD);
4377     result = (CORINFO_METHOD_HANDLE) pMD;
4378
4379     EE_TO_JIT_TRANSITION();
4380
4381     return result;
4382 }
4383
4384 /*********************************************************************/
4385 CORINFO_CLASS_HANDLE CEEInfo::getBuiltinClass(CorInfoClassId classId)
4386 {
4387     CONTRACTL {
4388         SO_TOLERANT;
4389         THROWS;
4390         GC_TRIGGERS;
4391         MODE_PREEMPTIVE;
4392     } CONTRACTL_END;
4393
4394     CORINFO_CLASS_HANDLE result = (CORINFO_CLASS_HANDLE) 0;
4395
4396     JIT_TO_EE_TRANSITION();
4397
4398     switch (classId)
4399     {
4400     case CLASSID_SYSTEM_OBJECT:
4401         result = CORINFO_CLASS_HANDLE(g_pObjectClass);
4402         break;
4403     case CLASSID_TYPED_BYREF:
4404         result = CORINFO_CLASS_HANDLE(g_TypedReferenceMT);
4405         break;
4406     case CLASSID_TYPE_HANDLE:
4407         result = CORINFO_CLASS_HANDLE(MscorlibBinder::GetClass(CLASS__TYPE_HANDLE));
4408         break;
4409     case CLASSID_FIELD_HANDLE:
4410         result = CORINFO_CLASS_HANDLE(MscorlibBinder::GetClass(CLASS__FIELD_HANDLE));
4411         break;
4412     case CLASSID_METHOD_HANDLE:
4413         result = CORINFO_CLASS_HANDLE(MscorlibBinder::GetClass(CLASS__METHOD_HANDLE));
4414         break;
4415     case CLASSID_ARGUMENT_HANDLE:
4416         result = CORINFO_CLASS_HANDLE(MscorlibBinder::GetClass(CLASS__ARGUMENT_HANDLE));
4417         break;
4418     case CLASSID_STRING:
4419         result = CORINFO_CLASS_HANDLE(g_pStringClass);
4420         break;
4421     case CLASSID_RUNTIME_TYPE:
4422         result = CORINFO_CLASS_HANDLE(g_pRuntimeTypeClass);
4423         break;
4424     default:
4425         _ASSERTE(!"NYI: unknown classId");
4426         break;
4427     }
4428
4429     EE_TO_JIT_TRANSITION();
4430
4431     return result;
4432 }
4433
4434
4435
4436 /*********************************************************************/
4437 CorInfoType CEEInfo::getTypeForPrimitiveValueClass(
4438         CORINFO_CLASS_HANDLE clsHnd)
4439 {
4440     CONTRACTL {
4441         SO_TOLERANT;
4442         THROWS;
4443         GC_TRIGGERS;
4444         MODE_PREEMPTIVE;
4445     } CONTRACTL_END;
4446
4447     CorInfoType result = CORINFO_TYPE_UNDEF;
4448
4449     JIT_TO_EE_TRANSITION();
4450
4451     TypeHandle th(clsHnd);
4452     _ASSERTE (!th.IsGenericVariable());
4453
4454     MethodTable    *pMT = th.GetMethodTable();
4455     PREFIX_ASSUME(pMT != NULL);
4456
4457     // Is it a non primitive struct such as
4458     // RuntimeTypeHandle, RuntimeMethodHandle, RuntimeArgHandle?
4459     if (pMT->IsValueType() &&
4460         !pMT->IsTruePrimitive()  &&
4461         !pMT->IsEnum())
4462     {
4463         // default value CORINFO_TYPE_UNDEF is what we want
4464     }
4465     else
4466     {
4467         switch (th.GetInternalCorElementType())
4468         {
4469         case ELEMENT_TYPE_I1:
4470         case ELEMENT_TYPE_U1:
4471         case ELEMENT_TYPE_BOOLEAN:
4472             result = asCorInfoType(ELEMENT_TYPE_I1);
4473             break;
4474
4475         case ELEMENT_TYPE_I2:
4476         case ELEMENT_TYPE_U2:
4477         case ELEMENT_TYPE_CHAR:
4478             result = asCorInfoType(ELEMENT_TYPE_I2);
4479             break;
4480
4481         case ELEMENT_TYPE_I4:
4482         case ELEMENT_TYPE_U4:
4483             result = asCorInfoType(ELEMENT_TYPE_I4);
4484             break;
4485
4486         case ELEMENT_TYPE_I8:
4487         case ELEMENT_TYPE_U8:
4488             result = asCorInfoType(ELEMENT_TYPE_I8);
4489             break;
4490
4491         case ELEMENT_TYPE_I:
4492         case ELEMENT_TYPE_U:
4493             result = asCorInfoType(ELEMENT_TYPE_I);
4494             break;
4495
4496         case ELEMENT_TYPE_R4:
4497             result = asCorInfoType(ELEMENT_TYPE_R4);
4498             break;
4499
4500         case ELEMENT_TYPE_R8:
4501             result = asCorInfoType(ELEMENT_TYPE_R8);
4502             break;
4503
4504         case ELEMENT_TYPE_VOID:
4505             result = asCorInfoType(ELEMENT_TYPE_VOID);
4506             break;
4507
4508         case ELEMENT_TYPE_PTR:
4509         case ELEMENT_TYPE_FNPTR:
4510             result = asCorInfoType(ELEMENT_TYPE_PTR);
4511             break;
4512
4513         default:
4514             break;
4515         }
4516     }
4517
4518     EE_TO_JIT_TRANSITION();
4519
4520     return result;
4521 }
4522
4523
4524 void CEEInfo::getGSCookie(GSCookie * pCookieVal, GSCookie ** ppCookieVal)
4525 {
4526     CONTRACTL {
4527         SO_TOLERANT;
4528         THROWS;
4529         GC_TRIGGERS;
4530         MODE_PREEMPTIVE;
4531     } CONTRACTL_END;
4532
4533     JIT_TO_EE_TRANSITION();
4534
4535     if (pCookieVal)
4536     {
4537         *pCookieVal = GetProcessGSCookie();
4538         *ppCookieVal = NULL;
4539     }
4540     else
4541     {
4542         *ppCookieVal = GetProcessGSCookiePtr();
4543     }
4544
4545     EE_TO_JIT_TRANSITION();
4546 }
4547
4548
4549 /*********************************************************************/
4550 // TRUE if child is a subtype of parent
4551 // if parent is an interface, then does child implement / extend parent
4552 BOOL CEEInfo::canCast(
4553         CORINFO_CLASS_HANDLE        child,
4554         CORINFO_CLASS_HANDLE        parent)
4555 {
4556     CONTRACTL {
4557         SO_TOLERANT;
4558         THROWS;
4559         GC_TRIGGERS;
4560         MODE_PREEMPTIVE;
4561     } CONTRACTL_END;
4562
4563     BOOL result = FALSE;
4564
4565     JIT_TO_EE_TRANSITION();
4566
4567     result = ((TypeHandle)child).CanCastTo((TypeHandle)parent);
4568
4569     EE_TO_JIT_TRANSITION();
4570
4571     return result;
4572 }
4573
4574 /*********************************************************************/
4575 // TRUE if cls1 and cls2 are considered equivalent types.
4576 BOOL CEEInfo::areTypesEquivalent(
4577         CORINFO_CLASS_HANDLE        cls1,
4578         CORINFO_CLASS_HANDLE        cls2)
4579 {
4580     CONTRACTL {
4581         SO_TOLERANT;
4582         THROWS;
4583         GC_TRIGGERS;
4584         MODE_PREEMPTIVE;
4585     } CONTRACTL_END;
4586
4587     BOOL result = FALSE;
4588
4589     JIT_TO_EE_TRANSITION();
4590
4591     result = ((TypeHandle)cls1).IsEquivalentTo((TypeHandle)cls2);
4592
4593     EE_TO_JIT_TRANSITION();
4594
4595     return result;
4596 }
4597
4598 /*********************************************************************/
4599 // returns is the intersection of cls1 and cls2.
4600 CORINFO_CLASS_HANDLE CEEInfo::mergeClasses(
4601         CORINFO_CLASS_HANDLE        cls1,
4602         CORINFO_CLASS_HANDLE        cls2)
4603 {
4604     CONTRACTL {
4605         SO_TOLERANT;
4606         THROWS;
4607         GC_TRIGGERS;
4608         MODE_PREEMPTIVE;
4609     } CONTRACTL_END;
4610
4611     CORINFO_CLASS_HANDLE result = NULL;
4612
4613     JIT_TO_EE_TRANSITION();
4614
4615     TypeHandle merged = TypeHandle::MergeTypeHandlesToCommonParent(TypeHandle(cls1), TypeHandle(cls2));
4616 #ifdef _DEBUG
4617     {
4618         //Make sure the merge is reflexive in the cases we "support".
4619         TypeHandle hnd1 = TypeHandle(cls1);
4620         TypeHandle hnd2 = TypeHandle(cls2);
4621         TypeHandle reflexive = TypeHandle::MergeTypeHandlesToCommonParent(hnd2, hnd1);
4622
4623         //If both sides are classes than either they have a common non-interface parent (in which case it is
4624         //reflexive)
4625         //OR they share a common interface, and it can be order dependent (if they share multiple interfaces
4626         //in common)
4627         if (!hnd1.IsInterface() && !hnd2.IsInterface())
4628         {
4629             if (merged.IsInterface())
4630             {
4631                 _ASSERTE(reflexive.IsInterface());
4632             }
4633             else
4634             {
4635                 _ASSERTE(merged == reflexive);
4636             }
4637         }
4638         //Both results must either be interfaces or classes.  They cannot be mixed.
4639         _ASSERTE((!!merged.IsInterface()) == (!!reflexive.IsInterface()));
4640
4641         //If the result of the merge was a class, then the result of the reflexive merge was the same class.
4642         if (!merged.IsInterface())
4643         {
4644             _ASSERTE(merged == reflexive);
4645         }
4646
4647         //If both sides are arrays, then the result is either an array or g_pArrayClass.  The above is
4648         //actually true about the element type for references types, but I think that that is a little
4649         //excessive for sanity.
4650         if (hnd1.IsArray() && hnd2.IsArray())
4651         {
4652             _ASSERTE((merged.IsArray() && reflexive.IsArray())
4653                      || ((merged == g_pArrayClass) && (reflexive == g_pArrayClass)));
4654         }
4655
4656         //Can I assert anything about generic variables?
4657
4658         //The results must always be assignable
4659         _ASSERTE(hnd1.CanCastTo(merged) && hnd2.CanCastTo(merged) && hnd1.CanCastTo(reflexive)
4660                  && hnd2.CanCastTo(reflexive));
4661     }
4662 #endif
4663     result = CORINFO_CLASS_HANDLE(merged.AsPtr());
4664
4665     EE_TO_JIT_TRANSITION();
4666     return result;
4667 }
4668
4669 /*********************************************************************/
4670 // Given a class handle, returns the Parent type.
4671 // For COMObjectType, it returns Class Handle of System.Object.
4672 // Returns 0 if System.Object is passed in.
4673 CORINFO_CLASS_HANDLE CEEInfo::getParentType(
4674             CORINFO_CLASS_HANDLE    cls)
4675 {
4676     CONTRACTL {
4677         SO_TOLERANT;
4678         THROWS;
4679         GC_TRIGGERS;
4680         MODE_PREEMPTIVE;
4681     } CONTRACTL_END;
4682
4683     CORINFO_CLASS_HANDLE result = NULL;
4684
4685     JIT_TO_EE_TRANSITION();
4686
4687     TypeHandle th(cls);
4688
4689     _ASSERTE(!th.IsNull());
4690     _ASSERTE(!th.IsGenericVariable());
4691
4692     TypeHandle thParent = th.GetParent();
4693
4694 #ifdef FEATURE_COMINTEROP
4695     // If we encounter __ComObject in the hierarchy, we need to skip it
4696     // since this hierarchy is introduced by the EE, but won't be present
4697     // in the metadata.
4698     if (!thParent.IsNull() && IsComObjectClass(thParent))
4699     {
4700         result = (CORINFO_CLASS_HANDLE) g_pObjectClass;
4701     }
4702     else
4703 #endif // FEATURE_COMINTEROP
4704     {
4705         result = CORINFO_CLASS_HANDLE(thParent.AsPtr());
4706     }
4707
4708     EE_TO_JIT_TRANSITION();
4709
4710     return result;
4711 }
4712
4713
4714 /*********************************************************************/
4715 // Returns the CorInfoType of the "child type". If the child type is
4716 // not a primitive type, *clsRet will be set.
4717 // Given an Array of Type Foo, returns Foo.
4718 // Given BYREF Foo, returns Foo
4719 CorInfoType CEEInfo::getChildType (
4720         CORINFO_CLASS_HANDLE       clsHnd,
4721         CORINFO_CLASS_HANDLE       *clsRet
4722         )
4723 {
4724     CONTRACTL {
4725         SO_TOLERANT;
4726         THROWS;
4727         GC_TRIGGERS;
4728         MODE_PREEMPTIVE;
4729     } CONTRACTL_END;
4730
4731     CorInfoType ret = CORINFO_TYPE_UNDEF;
4732     *clsRet = 0;
4733     TypeHandle  retType = TypeHandle();
4734
4735     JIT_TO_EE_TRANSITION();
4736
4737     TypeHandle th(clsHnd);
4738
4739     _ASSERTE(!th.IsNull());
4740
4741     // BYREF, ARRAY types
4742     if (th.IsTypeDesc())
4743     {
4744         retType = th.AsTypeDesc()->GetTypeParam();
4745     }
4746     else
4747     {
4748         // <REVISIT_TODO> we really should not have this case.  arrays type handles
4749         // used in the JIT interface should never be ordinary method tables,
4750         // indeed array type handles should really never be ordinary MTs
4751         // at all.  Perhaps we should assert !th.IsTypeDesc() && th.AsMethodTable().IsArray()? </REVISIT_TODO>
4752         MethodTable* pMT= th.AsMethodTable();
4753         if (pMT->IsArray())
4754             retType = pMT->GetApproxArrayElementTypeHandle();
4755     }
4756
4757     if (!retType.IsNull()) {
4758         CorElementType type = retType.GetInternalCorElementType();
4759         ret = CEEInfo::asCorInfoType(type,retType, clsRet);
4760
4761         // <REVISIT_TODO>What if this one is a value array ?</REVISIT_TODO>
4762     }
4763
4764     EE_TO_JIT_TRANSITION();
4765
4766     return ret;
4767 }
4768
4769 /*********************************************************************/
4770 // Check any constraints on class type arguments
4771 BOOL CEEInfo::satisfiesClassConstraints(CORINFO_CLASS_HANDLE cls)
4772 {
4773     CONTRACTL {
4774         SO_TOLERANT;
4775         THROWS;
4776         GC_TRIGGERS;
4777         MODE_PREEMPTIVE;
4778     } CONTRACTL_END;
4779
4780     BOOL result = FALSE;
4781
4782     JIT_TO_EE_TRANSITION();
4783
4784     _ASSERTE(cls != NULL);
4785     result = TypeHandle(cls).SatisfiesClassConstraints();
4786
4787     EE_TO_JIT_TRANSITION();
4788
4789     return result;
4790 }
4791
4792 /*********************************************************************/
4793 // Check if this is a single dimensional array type
4794 BOOL CEEInfo::isSDArray(CORINFO_CLASS_HANDLE  cls)
4795 {
4796     CONTRACTL {
4797         SO_TOLERANT;
4798         THROWS;
4799         GC_TRIGGERS;
4800         MODE_PREEMPTIVE;
4801     } CONTRACTL_END;
4802
4803     BOOL result = FALSE;
4804
4805     JIT_TO_EE_TRANSITION();
4806
4807     TypeHandle th(cls);
4808
4809     _ASSERTE(!th.IsNull());
4810
4811     if (th.IsArrayType())
4812     {
4813         // Lots of code used to think that System.Array's methodtable returns TRUE for IsArray(). It doesn't.
4814         _ASSERTE(th != TypeHandle(g_pArrayClass));
4815
4816         result = (th.GetInternalCorElementType() == ELEMENT_TYPE_SZARRAY);
4817     }
4818
4819     EE_TO_JIT_TRANSITION();
4820
4821     return result;
4822 }
4823
4824 /*********************************************************************/
4825 // Get the number of dimensions in an array
4826 unsigned CEEInfo::getArrayRank(CORINFO_CLASS_HANDLE  cls)
4827 {
4828     CONTRACTL {
4829         SO_TOLERANT;
4830         THROWS;
4831         GC_TRIGGERS;
4832         MODE_PREEMPTIVE;
4833     } CONTRACTL_END;
4834
4835     unsigned result = 0;
4836
4837     JIT_TO_EE_TRANSITION();
4838
4839     TypeHandle th(cls);
4840
4841     _ASSERTE(!th.IsNull());
4842
4843     if (th.IsArrayType())
4844     {
4845         // Lots of code used to think that System.Array's methodtable returns TRUE for IsArray(). It doesn't.
4846         _ASSERTE(th != TypeHandle(g_pArrayClass));
4847
4848         result = th.GetPossiblySharedArrayMethodTable()->GetRank();
4849     }
4850
4851     EE_TO_JIT_TRANSITION();
4852
4853     return result;
4854 }
4855
4856 /*********************************************************************/
4857 // Get static field data for an array
4858 // Note that it's OK to return NULL from this method.  This will cause
4859 // the JIT to make a runtime call to InitializeArray instead of doing
4860 // the inline optimization (thus preserving the original behavior).
4861 void * CEEInfo::getArrayInitializationData(
4862             CORINFO_FIELD_HANDLE        field,
4863             DWORD                       size
4864             )
4865 {
4866     CONTRACTL {
4867         SO_TOLERANT;
4868         THROWS;
4869         GC_TRIGGERS;
4870         MODE_PREEMPTIVE;
4871     } CONTRACTL_END;
4872
4873     void * result = NULL;
4874
4875     JIT_TO_EE_TRANSITION();
4876
4877     FieldDesc* pField = (FieldDesc*) field;
4878
4879     if (!pField                    ||
4880         !pField->IsRVA()           ||
4881         (pField->LoadSize() < size)
4882 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
4883         // This will make sure that when IBC logging is on, the array initialization happens thru 
4884         // COMArrayInfo::InitializeArray. This gives a place to put the IBC probe that can help
4885         // separate hold and cold RVA blobs.
4886         || (IsCompilingForNGen() &&
4887             GetAppDomain()->ToCompilationDomain()->m_fForceInstrument)
4888 #endif // FEATURE_NATIVE_IMAGE_GENERATION
4889         )
4890     {
4891         result = NULL;
4892     }
4893     else
4894     {
4895         result = pField->GetStaticAddressHandle(NULL);
4896     }
4897
4898     EE_TO_JIT_TRANSITION();
4899
4900     return result;
4901 }
4902
4903 CorInfoIsAccessAllowedResult CEEInfo::canAccessClass(
4904             CORINFO_RESOLVED_TOKEN * pResolvedToken,
4905             CORINFO_METHOD_HANDLE   callerHandle,
4906             CORINFO_HELPER_DESC    *pAccessHelper
4907             )
4908 {
4909     CONTRACTL {
4910         SO_TOLERANT;
4911         THROWS;
4912         GC_TRIGGERS;
4913         MODE_PREEMPTIVE;
4914     } CONTRACTL_END;
4915
4916     CorInfoIsAccessAllowedResult isAccessAllowed = CORINFO_ACCESS_ALLOWED;
4917
4918     JIT_TO_EE_TRANSITION();
4919
4920     INDEBUG(memset(pAccessHelper, 0xCC, sizeof(*pAccessHelper)));
4921
4922     BOOL doAccessCheck = TRUE;
4923     AccessCheckOptions::AccessCheckType accessCheckType = AccessCheckOptions::kNormalAccessibilityChecks;
4924     DynamicResolver * pAccessContext = NULL;
4925
4926     //All access checks must be done on the open instantiation.
4927     MethodDesc * pCallerForSecurity = GetMethodForSecurity(callerHandle);
4928     TypeHandle callerTypeForSecurity = TypeHandle(pCallerForSecurity->GetMethodTable());
4929
4930     TypeHandle pCalleeForSecurity = TypeHandle(pResolvedToken->hClass);
4931     if (pResolvedToken->pTypeSpec != NULL)
4932     {
4933         SigTypeContext typeContext;
4934         SigTypeContext::InitTypeContext(pCallerForSecurity, &typeContext);
4935
4936         SigPointer sigptr(pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec);
4937         pCalleeForSecurity = sigptr.GetTypeHandleThrowing((Module *)pResolvedToken->tokenScope, &typeContext);
4938     }
4939
4940     while (pCalleeForSecurity.HasTypeParam())
4941     {
4942         pCalleeForSecurity = pCalleeForSecurity.GetTypeParam();
4943     }
4944
4945     if (IsDynamicScope(pResolvedToken->tokenScope))
4946     {
4947         doAccessCheck = ModifyCheckForDynamicMethod(GetDynamicResolver(pResolvedToken->tokenScope),
4948                                                     &callerTypeForSecurity, &accessCheckType,
4949                                                     &pAccessContext);
4950     }
4951
4952     //Since this is a check against a TypeHandle, there are some things we can stick in a TypeHandle that
4953     //don't require access checks.
4954     if (pCalleeForSecurity.IsGenericVariable())
4955     {
4956         //I don't need to check for access against !!0.
4957         doAccessCheck = FALSE;
4958     }
4959
4960     //Now do the visibility checks
4961     if (doAccessCheck)
4962     {
4963         AccessCheckOptions accessCheckOptions(accessCheckType,
4964                                               pAccessContext,
4965                                               FALSE /*throw on error*/,
4966                                               pCalleeForSecurity.GetMethodTable());
4967
4968         _ASSERTE(pCallerForSecurity != NULL && callerTypeForSecurity != NULL);
4969         StaticAccessCheckContext accessContext(pCallerForSecurity, callerTypeForSecurity.GetMethodTable());
4970
4971         BOOL canAccessType = ClassLoader::CanAccessClass(&accessContext,
4972                                                          pCalleeForSecurity.GetMethodTable(),
4973                                                          pCalleeForSecurity.GetAssembly(),
4974                                                          accessCheckOptions);
4975
4976         isAccessAllowed = canAccessType ? CORINFO_ACCESS_ALLOWED : CORINFO_ACCESS_ILLEGAL;
4977     }
4978
4979
4980     if (isAccessAllowed != CORINFO_ACCESS_ALLOWED)
4981     {
4982         //These all get the throw helper
4983         pAccessHelper->helperNum = CORINFO_HELP_CLASS_ACCESS_EXCEPTION;
4984         pAccessHelper->numArgs = 2;
4985
4986         pAccessHelper->args[0].Set(CORINFO_METHOD_HANDLE(pCallerForSecurity));
4987         pAccessHelper->args[1].Set(CORINFO_CLASS_HANDLE(pCalleeForSecurity.AsPtr()));
4988
4989         if (IsCompilingForNGen())
4990         {
4991             //see code:CEEInfo::getCallInfo for more information.
4992             if (pCallerForSecurity->ContainsGenericVariables() || pCalleeForSecurity.ContainsGenericVariables())
4993                 COMPlusThrowNonLocalized(kNotSupportedException, W("Cannot embed generic TypeHandle"));
4994         }
4995     }
4996
4997     if (isAccessAllowed == CORINFO_ACCESS_ALLOWED)
4998     {
4999         //Finally let's get me some transparency checks.
5000         CorInfoSecurityRuntimeChecks runtimeChecks = CORINFO_ACCESS_SECURITY_NONE; 
5001
5002
5003         DebugSecurityCalloutStress(getMethodBeingCompiled(), isAccessAllowed,
5004                                    runtimeChecks);
5005
5006         if (isAccessAllowed != CORINFO_ACCESS_ALLOWED)
5007         {
5008             _ASSERTE(isAccessAllowed == CORINFO_ACCESS_RUNTIME_CHECK);
5009             //Well, time for the runtime helper
5010             pAccessHelper->helperNum = CORINFO_HELP_CLASS_ACCESS_CHECK;
5011             pAccessHelper->numArgs = 3;
5012
5013             pAccessHelper->args[0].Set(CORINFO_METHOD_HANDLE(pCallerForSecurity));
5014             pAccessHelper->args[1].Set(CORINFO_CLASS_HANDLE(pCalleeForSecurity.AsPtr()));
5015             pAccessHelper->args[2].Set(runtimeChecks);
5016
5017             if (IsCompilingForNGen())
5018             {
5019                 //see code:CEEInfo::getCallInfo for more information.
5020                 if (pCallerForSecurity->ContainsGenericVariables() || pCalleeForSecurity.ContainsGenericVariables())
5021                     COMPlusThrowNonLocalized(kNotSupportedException, W("Cannot embed generic TypeHandle"));
5022             }
5023         }
5024     }
5025
5026     EE_TO_JIT_TRANSITION();
5027     return isAccessAllowed;
5028 }
5029
5030 /***********************************************************************/
5031 // return the address of a pointer to a callable stub that will do the
5032 // virtual or interface call
5033 void CEEInfo::getCallInfo(
5034             CORINFO_RESOLVED_TOKEN * pResolvedToken,
5035             CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken,
5036             CORINFO_METHOD_HANDLE   callerHandle,
5037             CORINFO_CALLINFO_FLAGS  flags,
5038             CORINFO_CALL_INFO      *pResult /*out */)
5039 {
5040     CONTRACTL {
5041         SO_TOLERANT;
5042         THROWS;
5043         GC_TRIGGERS;
5044         MODE_PREEMPTIVE;
5045     } CONTRACTL_END;
5046
5047     JIT_TO_EE_TRANSITION();
5048
5049     _ASSERTE(CheckPointer(pResult));
5050
5051     INDEBUG(memset(pResult, 0xCC, sizeof(*pResult)));
5052
5053     MethodDesc* pMD = (MethodDesc *)pResolvedToken->hMethod;
5054     TypeHandle th(pResolvedToken->hClass);
5055
5056     _ASSERTE(pMD);
5057     _ASSERTE((size_t(pMD) & 0x1) == 0);
5058
5059     // Spec says that a callvirt lookup ignores static methods. Since static methods
5060     // can't have the exact same signature as instance methods, a lookup that found
5061     // a static method would have never found an instance method.
5062     if (pMD->IsStatic() && (flags & CORINFO_CALLINFO_CALLVIRT))
5063     {
5064         EX_THROW(EEMessageException, (kMissingMethodException, IDS_EE_MISSING_METHOD, W("?")));
5065     }
5066
5067
5068
5069     TypeHandle exactType = TypeHandle(pResolvedToken->hClass);
5070
5071     TypeHandle constrainedType;
5072     if ((flags & CORINFO_CALLINFO_CALLVIRT) && (pConstrainedResolvedToken != NULL))
5073     {
5074         constrainedType = TypeHandle(pConstrainedResolvedToken->hClass);
5075     }
5076
5077     BOOL fResolvedConstraint = FALSE;
5078     BOOL fForceUseRuntimeLookup = FALSE;
5079
5080     MethodDesc * pMDAfterConstraintResolution = pMD;
5081     if (constrainedType.IsNull())
5082     {
5083         pResult->thisTransform = CORINFO_NO_THIS_TRANSFORM;
5084     }
5085     // <NICE> Things go wrong when this code path is used when verifying generic code.
5086     // It would be nice if we didn't go down this sort of code path when verifying but
5087     // not generating code. </NICE>
5088     else if (constrainedType.ContainsGenericVariables() || exactType.ContainsGenericVariables())
5089     {
5090         // <NICE> It shouldn't really matter what we do here - but the x86 JIT is annoyingly sensitive
5091         // about what we do, since it pretend generic variables are reference types and generates
5092         // an internal JIT tree even when just verifying generic code. </NICE>
5093         if (constrainedType.IsGenericVariable())
5094         {
5095             pResult->thisTransform = CORINFO_DEREF_THIS; // convert 'this' of type &T --> T
5096         }
5097         else if (constrainedType.IsValueType())
5098         {
5099             pResult->thisTransform = CORINFO_BOX_THIS; // convert 'this' of type &VC<T> --> boxed(VC<T>)
5100         }
5101         else
5102         {
5103             pResult->thisTransform = CORINFO_DEREF_THIS; // convert 'this' of type &C<T> --> C<T>
5104         }
5105     }
5106     else
5107     {
5108         // We have a "constrained." call.  Try a partial resolve of the constraint call.  Note that this
5109         // will not necessarily resolve the call exactly, since we might be compiling
5110         // shared generic code - it may just resolve it to a candidate suitable for
5111         // JIT compilation, and require a runtime lookup for the actual code pointer
5112         // to call.
5113         if (constrainedType.IsEnum())
5114         {
5115             // Optimize constrained calls to enum's GetHashCode method. TryResolveConstraintMethodApprox would return
5116             // null since the virtual method resolves to System.Enum's implementation and that's a reference type.
5117             // We can't do this for any other method since ToString and Equals have different semantics for enums
5118             // and their underlying type.
5119             if (pMD->GetSlot() == MscorlibBinder::GetMethod(METHOD__OBJECT__GET_HASH_CODE)->GetSlot())
5120             {
5121                 // Pretend this was a "constrained. UnderlyingType" instruction prefix
5122                 constrainedType = TypeHandle(MscorlibBinder::GetElementType(constrainedType.GetVerifierCorElementType()));
5123
5124                 // Native image signature encoder will use this field. It needs to match that pretended type, a bogus signature
5125                 // would be produced otherwise.
5126                 pConstrainedResolvedToken->hClass = (CORINFO_CLASS_HANDLE)constrainedType.AsPtr();
5127
5128                 // Clear the token and typespec because of they do not match hClass anymore.
5129                 pConstrainedResolvedToken->token = mdTokenNil;
5130                 pConstrainedResolvedToken->pTypeSpec = NULL;
5131             }
5132         }
5133
5134         MethodDesc * directMethod = constrainedType.GetMethodTable()->TryResolveConstraintMethodApprox(
5135             exactType, 
5136             pMD, 
5137             &fForceUseRuntimeLookup);
5138         if (directMethod)
5139         {
5140             // Either
5141             //    1. no constraint resolution at compile time (!directMethod)
5142             // OR 2. no code sharing lookup in call
5143             // OR 3. we have have resolved to an instantiating stub
5144
5145             pMDAfterConstraintResolution = directMethod;
5146             _ASSERTE(!pMDAfterConstraintResolution->IsInterface());
5147             fResolvedConstraint = TRUE;
5148             pResult->thisTransform = CORINFO_NO_THIS_TRANSFORM;
5149
5150             exactType = constrainedType;
5151         }
5152         else  if (constrainedType.IsValueType())
5153         {
5154             pResult->thisTransform = CORINFO_BOX_THIS;
5155         }
5156         else
5157         {
5158             pResult->thisTransform = CORINFO_DEREF_THIS;
5159         }
5160     }
5161
5162     //
5163     // Initialize callee context used for inlining and instantiation arguments
5164     //
5165
5166     MethodDesc * pTargetMD = pMDAfterConstraintResolution;
5167
5168     if (pTargetMD->HasMethodInstantiation())
5169     {
5170         pResult->contextHandle = MAKE_METHODCONTEXT(pTargetMD);
5171         pResult->exactContextNeedsRuntimeLookup = pTargetMD->GetMethodTable()->IsSharedByGenericInstantiations() || TypeHandle::IsCanonicalSubtypeInstantiation(pTargetMD->GetMethodInstantiation());
5172     }
5173     else
5174     {
5175         if (!exactType.IsTypeDesc())
5176         {
5177             // Because of .NET's notion of base calls, exactType may point to a sub-class
5178             // of the actual class that defines pTargetMD.  If the JIT decides to inline, it is
5179             // important that they 'match', so we fix exactType here.
5180 #ifdef FEATURE_READYTORUN_COMPILER
5181             if (IsReadyToRunCompilation() &&
5182                 !isVerifyOnly() && 
5183                 !IsInSameVersionBubble((MethodDesc*)callerHandle, pTargetMD))
5184             {
5185                 // For version resilient code we can only inline within the same version bubble;
5186                 // we "repair" the precise types only for those callees.
5187                 // The above condition needs to stay in sync with CEEInfo::canInline
5188             }
5189             else
5190 #endif
5191             {
5192          
5193                 exactType = pTargetMD->GetExactDeclaringType(exactType.AsMethodTable());
5194                 _ASSERTE(!exactType.IsNull());
5195             }
5196         }
5197
5198         pResult->contextHandle = MAKE_CLASSCONTEXT(exactType.AsPtr());
5199         pResult->exactContextNeedsRuntimeLookup = exactType.IsSharedByGenericInstantiations();
5200     }
5201
5202     //
5203     // Determine whether to perform direct call
5204     //
5205
5206     bool directCall = false;
5207     bool resolvedCallVirt = false;
5208     bool callVirtCrossingVersionBubble = false;
5209
5210     // Delegate targets are always treated as direct calls here. (It would be nice to clean it up...).
5211     if (flags & CORINFO_CALLINFO_LDFTN)
5212     {
5213         if (m_pOverride != NULL)
5214             TypeEquivalenceFixupSpecificationHelper(m_pOverride, pTargetMD);
5215         directCall = true;
5216     }
5217     else
5218     // Static methods are always direct calls
5219     if (pTargetMD->IsStatic())
5220     {
5221         directCall = true;
5222     }
5223     else
5224     // Force all interface calls to be interpreted as if they are virtual.
5225     if (pTargetMD->GetMethodTable()->IsInterface())
5226     {
5227         directCall = false;
5228     }
5229     else
5230     if (!(flags & CORINFO_CALLINFO_CALLVIRT) || fResolvedConstraint)
5231     {
5232         directCall = true;
5233     }
5234     else
5235     {
5236         bool devirt;
5237
5238 #ifdef FEATURE_READYTORUN_COMPILER
5239
5240         // if we are generating version resilient code
5241         // AND
5242         //    caller/callee are in different version bubbles
5243         // we have to apply more restrictive rules
5244         // These rules are related to the "inlining rules" as far as the
5245         // boundaries of a version bubble are concerned.
5246
5247         if (IsReadyToRunCompilation() &&
5248             !isVerifyOnly() &&
5249             !IsInSameVersionBubble((MethodDesc*)callerHandle, pTargetMD)
5250            )
5251         {
5252             // For version resiliency we won't de-virtualize all final/sealed method calls.  Because during a 
5253             // servicing event it is legal to unseal a method or type.
5254             //
5255             // Note that it is safe to devirtualize in the following cases, since a servicing event cannot later modify it
5256             //  1) Callvirt on a virtual final method of a value type - since value types are sealed types as per ECMA spec
5257             //  2) Delegate.Invoke() - since a Delegate is a sealed class as per ECMA spec
5258             //  3) JIT intrinsics - since they have pre-defined behavior
5259             devirt = pTargetMD->GetMethodTable()->IsValueType() ||
5260                      (pTargetMD->GetMethodTable()->IsDelegate() && ((DelegateEEClass*)(pTargetMD->GetMethodTable()->GetClass()))->GetInvokeMethod() == pMD) ||
5261                      (pTargetMD->IsFCall() && ECall::GetIntrinsicID(pTargetMD) != CORINFO_INTRINSIC_Illegal);
5262
5263             callVirtCrossingVersionBubble = true;
5264         }
5265         else
5266 #endif
5267         {
5268             DWORD dwMethodAttrs = pTargetMD->GetAttrs();
5269             devirt = !IsMdVirtual(dwMethodAttrs) || IsMdFinal(dwMethodAttrs) || pTargetMD->GetMethodTable()->IsSealed();
5270         }
5271
5272         if (devirt)
5273         {
5274             // We can't allow generic remotable methods to be considered resolved, it leads to a non-instantiating method desc being
5275             // passed to the remoting stub. The easiest way to deal with these is to force them through the virtual code path.
5276             // It is actually good to do this deoptimization for all remotable methods since remoting interception via vtable dispatch 
5277             // is faster then remoting interception via thunk
5278             if (!pTargetMD->IsRemotingInterceptedViaVirtualDispatch() /* || !pTargetMD->HasMethodInstantiation() */)
5279             {
5280                 resolvedCallVirt = true;
5281                 directCall = true;
5282             }
5283         }
5284     }
5285
5286     if (directCall)
5287     {
5288         bool allowInstParam = (flags & CORINFO_CALLINFO_ALLOWINSTPARAM)
5289             // See code:IsRemotingInterceptedViaPrestub on why we need need to disallow inst param for remoting.
5290             && !( pTargetMD->MayBeRemotingIntercepted() && !pTargetMD->IsVtableMethod() );
5291
5292         // Create instantiating stub if necesary
5293         if (!allowInstParam && pTargetMD->RequiresInstArg())
5294         {
5295             pTargetMD = MethodDesc::FindOrCreateAssociatedMethodDesc(pTargetMD, 
5296                 exactType.AsMethodTable(), 
5297                 FALSE /* forceBoxedEntryPoint */, 
5298                 pTargetMD->GetMethodInstantiation(),
5299                 FALSE /* allowInstParam */);
5300         }
5301
5302         // We don't allow a JIT to call the code directly if a runtime lookup is
5303         // needed. This is the case if
5304         //     1. the scan of the call token indicated that it involves code sharing
5305         // AND 2. the method is an instantiating stub
5306         //
5307         // In these cases the correct instantiating stub is only found via a runtime lookup.
5308         //
5309         // Note that most JITs don't call instantiating stubs directly if they can help it -
5310         // they call the underlying shared code and provide the type context parameter
5311         // explicitly. However
5312         //    (a) some JITs may call instantiating stubs (it makes the JIT simpler) and
5313         //    (b) if the method is a remote stub then the EE will force the
5314         //        call through an instantiating stub and
5315         //    (c) constraint calls that require runtime context lookup are never resolved 
5316         //        to underlying shared generic code
5317
5318         if (((pResult->exactContextNeedsRuntimeLookup && pTargetMD->IsInstantiatingStub() && (!allowInstParam || fResolvedConstraint)) || fForceUseRuntimeLookup)
5319                 // Handle invalid IL - see comment in code:CEEInfo::ComputeRuntimeLookupForSharedGenericToken
5320                 && ContextIsShared(pResolvedToken->tokenContext))
5321         {
5322             _ASSERTE(!m_pMethodBeingCompiled->IsDynamicMethod());
5323             pResult->kind = CORINFO_CALL_CODE_POINTER;
5324
5325             // For reference types, the constrained type does not affect method resolution
5326             DictionaryEntryKind entryKind = (!constrainedType.IsNull() && constrainedType.IsValueType()) ? ConstrainedMethodEntrySlot : MethodEntrySlot;
5327
5328             ComputeRuntimeLookupForSharedGenericToken(entryKind,
5329                                                       pResolvedToken,
5330                                                       pConstrainedResolvedToken,
5331                                                       pMD,
5332                                                       &pResult->codePointerLookup);
5333         }
5334         else
5335         {
5336             if (allowInstParam && pTargetMD->IsInstantiatingStub())
5337             {
5338                 pTargetMD = pTargetMD->GetWrappedMethodDesc();
5339             }
5340
5341             pResult->kind = CORINFO_CALL;
5342
5343             if (IsReadyToRunCompilation())
5344             {
5345                 // Compensate for always treating delegates as direct calls above
5346                 if ((flags & CORINFO_CALLINFO_LDFTN) && (flags & CORINFO_CALLINFO_CALLVIRT) && !resolvedCallVirt)
5347                 {
5348                    pResult->kind = CORINFO_VIRTUALCALL_LDVIRTFTN;
5349                 }
5350             }
5351         }
5352         pResult->nullInstanceCheck = resolvedCallVirt;
5353     }
5354     // All virtual calls which take method instantiations must
5355     // currently be implemented by an indirect call via a runtime-lookup
5356     // function pointer
5357     else if (pTargetMD->HasMethodInstantiation())
5358     {
5359         pResult->kind = CORINFO_VIRTUALCALL_LDVIRTFTN;  // stub dispatch can't handle generic method calls yet
5360         pResult->nullInstanceCheck = TRUE;
5361     }
5362     // Non-interface dispatches go through the vtable
5363     else if (!pTargetMD->IsInterface() && !IsReadyToRunCompilation())
5364     {
5365         pResult->kind = CORINFO_VIRTUALCALL_VTABLE;
5366         pResult->nullInstanceCheck = TRUE;
5367     }
5368     else
5369     {
5370         if (IsReadyToRunCompilation())
5371         {
5372             // Insert explicit null checks for cross-version bubble non-interface calls. 
5373             // It is required to handle null checks properly for non-virtual <-> virtual change between versions
5374             pResult->nullInstanceCheck = !!(callVirtCrossingVersionBubble && !pTargetMD->IsInterface());
5375         }
5376         else
5377         {
5378             // No need to null check - the dispatch code will deal with null this.
5379             pResult->nullInstanceCheck = FALSE;
5380         }
5381 #ifdef STUB_DISPATCH_PORTABLE
5382         pResult->kind = CORINFO_VIRTUALCALL_LDVIRTFTN;
5383 #else // STUB_DISPATCH_PORTABLE
5384         pResult->kind = CORINFO_VIRTUALCALL_STUB;
5385
5386         // We can't make stub calls when we need exact information
5387         // for interface calls from shared code.
5388
5389         if (// If the token is not shared then we don't need a runtime lookup
5390             pResult->exactContextNeedsRuntimeLookup
5391             // Handle invalid IL - see comment in code:CEEInfo::ComputeRuntimeLookupForSharedGenericToken
5392             && ContextIsShared(pResolvedToken->tokenContext))
5393         {
5394             _ASSERTE(!m_pMethodBeingCompiled->IsDynamicMethod());
5395             
5396             ComputeRuntimeLookupForSharedGenericToken(DispatchStubAddrSlot,
5397                                                         pResolvedToken,
5398                                                         NULL,
5399                                                         pMD,
5400                                                         &pResult->stubLookup);
5401         }
5402         else
5403         {
5404             pResult->stubLookup.lookupKind.needsRuntimeLookup = false;
5405
5406             BYTE * indcell = NULL;
5407
5408             if (!(flags & CORINFO_CALLINFO_KINDONLY) && !isVerifyOnly())
5409             {
5410 #ifndef CROSSGEN_COMPILE
5411                 // We shouldn't be using GetLoaderAllocator here because for LCG, we need to get the 
5412                 // VirtualCallStubManager from where the stub will be used. 
5413                 // For normal methods there is no difference.
5414                 LoaderAllocator *pLoaderAllocator = m_pMethodBeingCompiled->GetLoaderAllocatorForCode();
5415                 VirtualCallStubManager *pMgr = pLoaderAllocator->GetVirtualCallStubManager();
5416
5417                 PCODE addr = pMgr->GetCallStub(exactType, pTargetMD);
5418                 _ASSERTE(pMgr->isStub(addr));
5419                 
5420                 // Now we want to indirect through a cell so that updates can take place atomically.
5421                 if (m_pMethodBeingCompiled->IsLCGMethod())
5422                 {
5423                     // LCG methods should use recycled indcells to prevent leaks.
5424                     indcell = pMgr->GenerateStubIndirection(addr, TRUE);
5425
5426                     // Add it to the per DM list so that we can recycle them when the resolver is finalized
5427                     LCGMethodResolver *pResolver = m_pMethodBeingCompiled->AsDynamicMethodDesc()->GetLCGMethodResolver();
5428                     pResolver->AddToUsedIndCellList(indcell);
5429                 }
5430                 else
5431                 {
5432                     // Normal methods should avoid recycled cells to preserve the locality of all indcells
5433                     // used by one method.
5434                     indcell = pMgr->GenerateStubIndirection(addr, FALSE);
5435                 }
5436 #else // CROSSGEN_COMPILE
5437                 // This path should be unreachable during crossgen
5438                 _ASSERTE(false);
5439 #endif // CROSSGEN_COMPILE
5440             }
5441
5442             // We use an indirect call
5443             pResult->stubLookup.constLookup.accessType = IAT_PVALUE;
5444             pResult->stubLookup.constLookup.addr = indcell;
5445         }
5446 #endif // STUB_DISPATCH_PORTABLE
5447     }
5448
5449     pResult->hMethod = CORINFO_METHOD_HANDLE(pTargetMD);
5450
5451     pResult->accessAllowed = CORINFO_ACCESS_ALLOWED;
5452     if ((flags & CORINFO_CALLINFO_SECURITYCHECKS) &&
5453         !((MethodDesc *)callerHandle)->IsILStub()) // IL stubs can access everything, don't bother doing access checks
5454     {
5455         //Our type system doesn't always represent the target exactly with the MethodDesc.  In all cases,
5456         //carry around the parent MethodTable for both Caller and Callee.
5457         TypeHandle calleeTypeForSecurity = TypeHandle(pResolvedToken->hClass);
5458         MethodDesc * pCalleeForSecurity = pMD;
5459
5460         MethodDesc * pCallerForSecurity = GetMethodForSecurity(callerHandle); //Should this be the open MD?
5461
5462         if (pCallerForSecurity->HasClassOrMethodInstantiation())
5463         {
5464             _ASSERTE(!IsDynamicScope(pResolvedToken->tokenScope));
5465
5466             SigTypeContext typeContext;
5467             SigTypeContext::InitTypeContext(pCallerForSecurity, &typeContext);
5468             _ASSERTE(!typeContext.IsEmpty());
5469
5470             //If the caller is generic, load the open type and resolve the token again.  Use that for the access
5471             //checks.  If we don't do this then we can't tell the difference between:
5472             //
5473             //BadGeneric<T> containing a methodspec for InaccessibleType::member (illegal)
5474             //and
5475             //BadGeneric<T> containing a methodspec for !!0::member instantiated over InaccessibleType (legal)
5476
5477             if (pResolvedToken->pTypeSpec != NULL)
5478             {
5479                 SigPointer sigptr(pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec);
5480                 calleeTypeForSecurity = sigptr.GetTypeHandleThrowing((Module *)pResolvedToken->tokenScope, &typeContext);
5481
5482                 // typeHnd can be a variable type
5483                 if (calleeTypeForSecurity.GetMethodTable() == NULL)
5484                 {
5485                     COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_METHODDEF_PARENT_NO_MEMBERS);
5486                 }
5487             }
5488
5489             if (pCalleeForSecurity->IsArray())
5490             {
5491                 // FindOrCreateAssociatedMethodDesc won't remap array method desc because of array base type 
5492                 // is not part of instantiation. We have to special case it.
5493                 pCalleeForSecurity = calleeTypeForSecurity.GetMethodTable()->GetParallelMethodDesc(pCalleeForSecurity);
5494             }
5495             else
5496             if (pResolvedToken->pMethodSpec != NULL)
5497             {
5498                 DWORD nGenericMethodArgs = 0;
5499                 CQuickBytes qbGenericMethodArgs;
5500                 TypeHandle *genericMethodArgs = NULL;
5501
5502                 SigPointer sp(pResolvedToken->pMethodSpec, pResolvedToken->cbMethodSpec);
5503
5504                 BYTE etype;
5505                 IfFailThrow(sp.GetByte(&etype));
5506
5507                 // Load the generic method instantiation
5508                 THROW_BAD_FORMAT_MAYBE(etype == (BYTE)IMAGE_CEE_CS_CALLCONV_GENERICINST, 0, (Module *)pResolvedToken->tokenScope);
5509
5510                 IfFailThrow(sp.GetData(&nGenericMethodArgs));
5511
5512                 DWORD cbAllocSize = 0;
5513                 if (!ClrSafeInt<DWORD>::multiply(nGenericMethodArgs, sizeof(TypeHandle), cbAllocSize))
5514                 {
5515                     COMPlusThrowHR(COR_E_OVERFLOW);
5516                 }
5517
5518                 genericMethodArgs = reinterpret_cast<TypeHandle *>(qbGenericMethodArgs.AllocThrows(cbAllocSize));
5519
5520                 for (DWORD i = 0; i < nGenericMethodArgs; i++)
5521                 {
5522                     genericMethodArgs[i] = sp.GetTypeHandleThrowing((Module *)pResolvedToken->tokenScope, &typeContext);
5523                     _ASSERTE (!genericMethodArgs[i].IsNull());
5524                     IfFailThrow(sp.SkipExactlyOne());
5525                 }
5526
5527                 pCalleeForSecurity = MethodDesc::FindOrCreateAssociatedMethodDesc(pMD, calleeTypeForSecurity.GetMethodTable(), FALSE, Instantiation(genericMethodArgs, nGenericMethodArgs), FALSE);
5528             }
5529             else
5530             if (pResolvedToken->pTypeSpec != NULL)
5531             {
5532                 pCalleeForSecurity = MethodDesc::FindOrCreateAssociatedMethodDesc(pMD, calleeTypeForSecurity.GetMethodTable(), FALSE, Instantiation(), TRUE);
5533             }
5534         }
5535
5536         TypeHandle callerTypeForSecurity = TypeHandle(pCallerForSecurity->GetMethodTable());
5537
5538         //Passed various link-time checks.  Now do access checks.
5539
5540         BOOL doAccessCheck = TRUE;
5541         BOOL canAccessMethod = TRUE;
5542         AccessCheckOptions::AccessCheckType accessCheckType = AccessCheckOptions::kNormalAccessibilityChecks;
5543         DynamicResolver * pAccessContext = NULL;
5544
5545         callerTypeForSecurity = TypeHandle(pCallerForSecurity->GetMethodTable());
5546         if (pCallerForSecurity->IsDynamicMethod())
5547         {
5548             doAccessCheck = ModifyCheckForDynamicMethod(pCallerForSecurity->AsDynamicMethodDesc()->GetResolver(),
5549                                                         &callerTypeForSecurity,
5550                                                         &accessCheckType, &pAccessContext);
5551         }
5552     
5553         pResult->accessAllowed = CORINFO_ACCESS_ALLOWED;
5554
5555         if (doAccessCheck)
5556         {
5557             AccessCheckOptions accessCheckOptions(accessCheckType,
5558                                                   pAccessContext,
5559                                                   FALSE,
5560                                                   pCalleeForSecurity);
5561
5562             _ASSERTE(pCallerForSecurity != NULL && callerTypeForSecurity != NULL);
5563             StaticAccessCheckContext accessContext(pCallerForSecurity, callerTypeForSecurity.GetMethodTable());
5564
5565             canAccessMethod = ClassLoader::CanAccess(&accessContext,
5566                                                      calleeTypeForSecurity.GetMethodTable(),
5567                                                      calleeTypeForSecurity.GetAssembly(),
5568                                                      pCalleeForSecurity->GetAttrs(),
5569                                                      pCalleeForSecurity,
5570                                                      NULL,
5571                                                      accessCheckOptions,
5572                                                      FALSE,
5573                                                      TRUE
5574                                                     );
5575
5576             // If we were allowed access to the exact method, but it is on a type that has a type parameter
5577             // (for instance an array), we need to ensure that we also have access to the type parameter.
5578             if (canAccessMethod && calleeTypeForSecurity.HasTypeParam())
5579             {
5580                 TypeHandle typeParam = calleeTypeForSecurity.GetTypeParam();
5581                 while (typeParam.HasTypeParam())
5582                 {
5583                     typeParam = typeParam.GetTypeParam();
5584                 }
5585
5586                 _ASSERTE(pCallerForSecurity != NULL && callerTypeForSecurity != NULL);
5587                 StaticAccessCheckContext accessContext(pCallerForSecurity, callerTypeForSecurity.GetMethodTable());
5588
5589                 MethodTable* pTypeParamMT = typeParam.GetMethodTable();
5590
5591                 // No accees check is need for Var, MVar, or FnPtr.
5592                 if (pTypeParamMT != NULL)
5593                     canAccessMethod = ClassLoader::CanAccessClassForExtraChecks(&accessContext,
5594                                                                                 pTypeParamMT,
5595                                                                                 typeParam.GetAssembly(),
5596                                                                                 accessCheckOptions,
5597                                                                                 TRUE);
5598             }
5599
5600             pResult->accessAllowed = canAccessMethod ? CORINFO_ACCESS_ALLOWED : CORINFO_ACCESS_ILLEGAL;
5601             if (!canAccessMethod)
5602             {
5603                 //Check failed, fill in the throw exception helper.
5604                 pResult->callsiteCalloutHelper.helperNum = CORINFO_HELP_METHOD_ACCESS_EXCEPTION;
5605                 pResult->callsiteCalloutHelper.numArgs = 2;
5606
5607                 pResult->callsiteCalloutHelper.args[0].Set(CORINFO_METHOD_HANDLE(pCallerForSecurity));
5608                 pResult->callsiteCalloutHelper.args[1].Set(CORINFO_METHOD_HANDLE(pCalleeForSecurity));
5609
5610                 //We now embed open instantiations in a few places for security callouts (since you can only
5611                 //do the security check on the open instantiation).  We throw these methods out in
5612                 //TriageMethodForZap.  In addition, NGen has problems referencing them properly.  Just throw out the whole
5613                 //method and rejit at runtime.
5614                 if (IsCompilingForNGen())
5615                 {
5616                     if (pCallerForSecurity->ContainsGenericVariables()
5617                         || pCalleeForSecurity->ContainsGenericVariables())
5618                     {
5619                         COMPlusThrowNonLocalized(kNotSupportedException, W("Cannot embed generic MethodDesc"));
5620                     }
5621                 }
5622             }
5623         }
5624     }
5625
5626     //We're pretty much done at this point.  Let's grab the rest of the information that the jit is going to
5627     //need.
5628     pResult->classFlags = getClassAttribsInternal(pResolvedToken->hClass);
5629
5630     pResult->methodFlags = getMethodAttribsInternal(pResult->hMethod);
5631     getMethodSigInternal(pResult->hMethod, &pResult->sig, (pResult->hMethod == pResolvedToken->hMethod) ? pResolvedToken->hClass : NULL);
5632
5633     if (flags & CORINFO_CALLINFO_VERIFICATION)
5634     {
5635         if (pResult->hMethod != pResolvedToken->hMethod)
5636         {
5637             pResult->verMethodFlags = getMethodAttribsInternal(pResolvedToken->hMethod);
5638             getMethodSigInternal(pResolvedToken->hMethod, &pResult->verSig, pResolvedToken->hClass);
5639         }
5640         else
5641         {
5642             pResult->verMethodFlags = pResult->methodFlags;
5643             pResult->verSig = pResult->sig;
5644         }
5645     }
5646
5647     pResult->secureDelegateInvoke = FALSE;
5648
5649 #ifdef FEATURE_STUBS_AS_IL
5650     if (m_pMethodBeingCompiled->IsDynamicMethod())
5651     {
5652         auto pMD = m_pMethodBeingCompiled->AsDynamicMethodDesc();
5653         if (pMD->IsILStub() && pMD->IsSecureDelegateStub())
5654         {
5655             pResult->secureDelegateInvoke = TRUE;
5656         }
5657     }
5658 #endif
5659
5660     EE_TO_JIT_TRANSITION();
5661 }
5662
5663 BOOL CEEInfo::canAccessFamily(CORINFO_METHOD_HANDLE hCaller,
5664                               CORINFO_CLASS_HANDLE hInstanceType)
5665 {
5666     WRAPPER_NO_CONTRACT;
5667
5668     BOOL ret = FALSE;
5669
5670     //Since this is only for verification, I don't need to do the demand.
5671     JIT_TO_EE_TRANSITION();
5672
5673     TypeHandle targetType = TypeHandle(hInstanceType);
5674     TypeHandle accessingType = TypeHandle(GetMethod(hCaller)->GetMethodTable());
5675     AccessCheckOptions::AccessCheckType accessCheckOptions = AccessCheckOptions::kNormalAccessibilityChecks;
5676     DynamicResolver* pIgnored;
5677     BOOL doCheck = TRUE;
5678     if (GetMethod(hCaller)->IsDynamicMethod())
5679     {
5680         //If this is a DynamicMethod, perform the check from the type to which the DynamicMethod was
5681         //attached.
5682         //
5683         //If this is a dynamic method, don't do this check.  If they specified SkipVisibilityChecks
5684         //(ModifyCheckForDynamicMethod returned false), we should obviously skip the check for the C++
5685         //protected rule (since we skipped all the other visibility checks).  If they specified
5686         //RestrictedSkipVisibilityChecks, then they're a "free" DynamicMethod.  This check is meaningless
5687         //(i.e.  it would always fail).  We've already done a demand for access to the member.  Let that be
5688         //enough.
5689         doCheck = ModifyCheckForDynamicMethod(GetMethod(hCaller)->AsDynamicMethodDesc()->GetResolver(),
5690                                               &accessingType, &accessCheckOptions, &pIgnored);
5691         if (accessCheckOptions == AccessCheckOptions::kRestrictedMemberAccess 
5692             || accessCheckOptions == AccessCheckOptions::kRestrictedMemberAccessNoTransparency
5693             )
5694             doCheck = FALSE;
5695     }
5696
5697     if (doCheck)
5698     {
5699         ret = ClassLoader::CanAccessFamilyVerification(accessingType, targetType);
5700     }
5701     else
5702     {
5703         ret = TRUE;
5704     }
5705
5706     EE_TO_JIT_TRANSITION();
5707     return ret;
5708 }
5709 void CEEInfo::ThrowExceptionForHelper(const CORINFO_HELPER_DESC * throwHelper)
5710 {
5711     CONTRACTL {
5712         SO_TOLERANT;
5713         THROWS;
5714         GC_TRIGGERS;
5715         MODE_PREEMPTIVE;
5716     } CONTRACTL_END;
5717
5718     JIT_TO_EE_TRANSITION();
5719
5720     _ASSERTE(throwHelper->args[0].argType == CORINFO_HELPER_ARG_TYPE_Method);
5721     MethodDesc *pCallerMD = GetMethod(throwHelper->args[0].methodHandle);
5722
5723     StaticAccessCheckContext accessContext(pCallerMD);
5724
5725     switch (throwHelper->helperNum)
5726     {
5727     case CORINFO_HELP_METHOD_ACCESS_EXCEPTION:
5728         {
5729             _ASSERTE(throwHelper->args[1].argType == CORINFO_HELPER_ARG_TYPE_Method);
5730             ThrowMethodAccessException(&accessContext, GetMethod(throwHelper->args[1].methodHandle));
5731         }
5732         break;
5733     case CORINFO_HELP_FIELD_ACCESS_EXCEPTION:
5734         {
5735             _ASSERTE(throwHelper->args[1].argType == CORINFO_HELPER_ARG_TYPE_Field);
5736             ThrowFieldAccessException(&accessContext, reinterpret_cast<FieldDesc *>(throwHelper->args[1].fieldHandle));
5737         }
5738         break;
5739     case CORINFO_HELP_CLASS_ACCESS_EXCEPTION:
5740         {
5741             _ASSERTE(throwHelper->args[1].argType == CORINFO_HELPER_ARG_TYPE_Class);
5742             TypeHandle typeHnd(throwHelper->args[1].classHandle);
5743             ThrowTypeAccessException(&accessContext, typeHnd.GetMethodTable());
5744         }
5745         break;
5746
5747     default:
5748         _ASSERTE(!"Unknown access exception type");
5749     }
5750     EE_TO_JIT_TRANSITION();
5751 }
5752
5753
5754 BOOL CEEInfo::isRIDClassDomainID(CORINFO_CLASS_HANDLE cls)
5755 {
5756     CONTRACTL {
5757         SO_TOLERANT;
5758         THROWS;
5759         GC_TRIGGERS;
5760         MODE_PREEMPTIVE;
5761     } CONTRACTL_END;
5762
5763     BOOL result = FALSE;
5764
5765     JIT_TO_EE_TRANSITION();
5766
5767     TypeHandle  VMClsHnd(cls);
5768
5769     result = !VMClsHnd.AsMethodTable()->IsDynamicStatics();
5770
5771     EE_TO_JIT_TRANSITION();
5772
5773     return result;
5774 }
5775
5776
5777 /***********************************************************************/
5778 unsigned CEEInfo::getClassDomainID (CORINFO_CLASS_HANDLE clsHnd,
5779                                     void **ppIndirection)
5780 {
5781     CONTRACTL {
5782         SO_TOLERANT;
5783         THROWS;
5784         GC_TRIGGERS;
5785         MODE_PREEMPTIVE;
5786     } CONTRACTL_END;
5787
5788     unsigned result = 0;
5789
5790     if (ppIndirection != NULL)
5791         *ppIndirection = NULL;
5792
5793     JIT_TO_EE_TRANSITION();
5794
5795     TypeHandle  VMClsHnd(clsHnd);
5796
5797     if (VMClsHnd.AsMethodTable()->IsDynamicStatics())
5798     {
5799         result = (unsigned)VMClsHnd.AsMethodTable()->GetModuleDynamicEntryID();
5800     }
5801     else
5802     {
5803         result = (unsigned)VMClsHnd.AsMethodTable()->GetClassIndex();
5804     }
5805
5806     EE_TO_JIT_TRANSITION();
5807
5808     return result;
5809 }
5810
5811 //---------------------------------------------------------------------------------------
5812 //
5813 // Used by the JIT to determine whether the profiler or IBC is tracking object
5814 // allocations
5815 //
5816 // Return Value:
5817 //    bool indicating whether the profiler or IBC is tracking object allocations
5818 //
5819 // Notes:
5820 //    Normally, a profiler would just directly call the inline helper to determine
5821 //    whether the profiler set the relevant event flag (e.g.,
5822 //    CORProfilerTrackAllocationsEnabled). However, this wrapper also asks whether we're
5823 //    running for IBC instrumentation or enabling the object allocated ETW event. If so,
5824 //    we treat that the same as if the profiler requested allocation information, so that
5825 //    the JIT will still use the profiling-friendly object allocation jit helper, so the
5826 //    allocations can be tracked.
5827 //
5828
5829 bool __stdcall TrackAllocationsEnabled()
5830 {
5831     CONTRACTL 
5832     {
5833         NOTHROW;
5834         GC_NOTRIGGER;
5835         MODE_ANY;      
5836     } 
5837     CONTRACTL_END;
5838
5839     return (
5840         (g_IBCLogger.InstrEnabled() != FALSE)
5841 #ifdef PROFILING_SUPPORTED
5842         || CORProfilerTrackAllocationsEnabled()
5843 #endif // PROFILING_SUPPORTED
5844 #ifdef FEATURE_EVENT_TRACE
5845         || ETW::TypeSystemLog::IsHeapAllocEventEnabled()
5846 #endif // FEATURE_EVENT_TRACE
5847         );
5848 }
5849
5850 /***********************************************************************/
5851 CorInfoHelpFunc CEEInfo::getNewHelper(CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_METHOD_HANDLE callerHandle)
5852 {
5853     CONTRACTL {
5854         SO_TOLERANT;
5855         THROWS;
5856         GC_TRIGGERS;
5857         MODE_PREEMPTIVE;
5858     } CONTRACTL_END;
5859
5860     CorInfoHelpFunc result = CORINFO_HELP_UNDEF;
5861
5862     JIT_TO_EE_TRANSITION();
5863
5864     TypeHandle  VMClsHnd(pResolvedToken->hClass);
5865
5866     if(VMClsHnd.IsTypeDesc())
5867     {
5868         COMPlusThrow(kInvalidOperationException,W("InvalidOperation_CantInstantiateFunctionPointer"));
5869     }
5870
5871     if(VMClsHnd.IsAbstract())
5872     {
5873         COMPlusThrow(kInvalidOperationException,W("InvalidOperation_CantInstantiateAbstractClass"));
5874     }
5875
5876     MethodTable* pMT = VMClsHnd.AsMethodTable();
5877     result = getNewHelperStatic(pMT);
5878
5879     _ASSERTE(result != CORINFO_HELP_UNDEF);
5880         
5881     EE_TO_JIT_TRANSITION();
5882
5883     return result;
5884 }
5885
5886 /***********************************************************************/
5887 CorInfoHelpFunc CEEInfo::getNewHelperStatic(MethodTable * pMT)
5888 {
5889     STANDARD_VM_CONTRACT;
5890
5891
5892     // Slow helper is the default
5893     CorInfoHelpFunc helper = CORINFO_HELP_NEWFAST;
5894
5895
5896     if (pMT->IsComObjectType())
5897     {
5898         // Use slow helper
5899         _ASSERTE(helper == CORINFO_HELP_NEWFAST);
5900     }
5901     else
5902     if ((pMT->GetBaseSize() >= LARGE_OBJECT_SIZE) || 
5903         pMT->HasFinalizer())
5904     {
5905         // Use slow helper
5906         _ASSERTE(helper == CORINFO_HELP_NEWFAST);
5907     }
5908     else
5909     // don't call the super-optimized one since that does not check
5910     // for GCStress
5911     if (GCStress<cfg_alloc>::IsEnabled())
5912     {
5913         // Use slow helper
5914         _ASSERTE(helper == CORINFO_HELP_NEWFAST);
5915     }
5916     else
5917 #ifdef _LOGALLOC
5918 #ifdef LOGGING
5919     // Super fast version doesn't do logging
5920     if (LoggingOn(LF_GCALLOC, LL_INFO10))
5921     {
5922         // Use slow helper
5923         _ASSERTE(helper == CORINFO_HELP_NEWFAST);
5924     }
5925     else
5926 #endif // LOGGING
5927 #endif // _LOGALLOC
5928     // Don't use the SFAST allocator when tracking object allocations,
5929     // so we don't have to instrument it.
5930     if (TrackAllocationsEnabled())
5931     {
5932         // Use slow helper
5933         _ASSERTE(helper == CORINFO_HELP_NEWFAST);
5934     }
5935     else
5936 #ifdef FEATURE_64BIT_ALIGNMENT
5937     // @ARMTODO: Force all 8-byte alignment requiring allocations down one slow path. As performance
5938     // measurements dictate we can spread these out to faster, more specialized helpers later.
5939     if (pMT->RequiresAlign8())
5940     {
5941         // Use slow helper
5942         _ASSERTE(helper == CORINFO_HELP_NEWFAST);
5943     }
5944     else
5945 #endif
5946     {
5947         // Use the fast helper when all conditions are met
5948         helper = CORINFO_HELP_NEWSFAST;
5949     }
5950
5951 #ifdef FEATURE_DOUBLE_ALIGNMENT_HINT
5952     // If we are use the the fast allocator we also may need the 
5953     // specialized varion for align8
5954     if (pMT->GetClass()->IsAlign8Candidate() &&
5955         (helper == CORINFO_HELP_NEWSFAST))
5956     {
5957         helper = CORINFO_HELP_NEWSFAST_ALIGN8;
5958     }
5959 #endif // FEATURE_DOUBLE_ALIGNMENT_HINT
5960
5961     return helper;
5962 }
5963
5964 /***********************************************************************/
5965 // <REVIEW> this only works for shared generic code because all the
5966 // helpers are actually the same. If they were different then things might
5967 // break because the same helper would end up getting used for different but
5968 // representation-compatible arrays (e.g. one with a default constructor
5969 // and one without) </REVIEW>
5970 CorInfoHelpFunc CEEInfo::getNewArrHelper (CORINFO_CLASS_HANDLE arrayClsHnd)
5971 {
5972     CONTRACTL {
5973         SO_TOLERANT;
5974         THROWS;
5975         GC_TRIGGERS;
5976         MODE_PREEMPTIVE;
5977     } CONTRACTL_END;
5978
5979     CorInfoHelpFunc result = CORINFO_HELP_UNDEF;
5980
5981     JIT_TO_EE_TRANSITION();
5982
5983     TypeHandle arrayType(arrayClsHnd);
5984
5985     result = getNewArrHelperStatic(arrayType);
5986
5987     _ASSERTE(result != CORINFO_HELP_UNDEF);
5988
5989     EE_TO_JIT_TRANSITION();
5990
5991     return result;
5992 }
5993
5994 /***********************************************************************/
5995 CorInfoHelpFunc CEEInfo::getNewArrHelperStatic(TypeHandle clsHnd)
5996 {
5997     STANDARD_VM_CONTRACT;
5998
5999     ArrayTypeDesc* arrayTypeDesc = clsHnd.AsArray();
6000     _ASSERTE(arrayTypeDesc->GetInternalCorElementType() == ELEMENT_TYPE_SZARRAY);
6001
6002     if (GCStress<cfg_alloc>::IsEnabled())
6003     {
6004         return CORINFO_HELP_NEWARR_1_DIRECT;
6005     }
6006
6007     CorInfoHelpFunc result = CORINFO_HELP_UNDEF;
6008
6009     TypeHandle thElemType = arrayTypeDesc->GetTypeParam();
6010     CorElementType elemType = thElemType.GetInternalCorElementType();
6011
6012     // This is if we're asked for newarr !0 when verifying generic code
6013     // Of course ideally you wouldn't even be generating code when
6014     // simply doing verification (we run the JIT importer in import-only
6015     // mode), but importing does more than one would like so we try to be
6016     // tolerant when asked for non-sensical helpers.
6017     if (CorTypeInfo::IsGenericVariable(elemType))
6018     {
6019         result = CORINFO_HELP_NEWARR_1_OBJ;
6020     }
6021     else if (CorTypeInfo::IsObjRef(elemType))
6022     {
6023         // It is an array of object refs
6024         result = CORINFO_HELP_NEWARR_1_OBJ;
6025     }
6026     else
6027     {
6028         // These cases always must use the slow helper
6029         if (
6030 #ifdef FEATURE_64BIT_ALIGNMENT
6031             thElemType.RequiresAlign8() ||
6032 #endif
6033             (elemType == ELEMENT_TYPE_VOID) ||
6034             LoggingOn(LF_GCALLOC, LL_INFO10) ||
6035             TrackAllocationsEnabled())
6036         {
6037             // Use the slow helper
6038             result = CORINFO_HELP_NEWARR_1_DIRECT;
6039         }
6040 #ifdef FEATURE_DOUBLE_ALIGNMENT_HINT
6041         else if (elemType == ELEMENT_TYPE_R8)
6042         {
6043             // Use the Align8 fast helper
6044             result = CORINFO_HELP_NEWARR_1_ALIGN8;
6045         }
6046 #endif
6047         else
6048         {
6049             // Yea, we can do it the fast way!
6050             result = CORINFO_HELP_NEWARR_1_VC;
6051         }
6052     }
6053
6054     return result;
6055 }
6056
6057 /***********************************************************************/
6058 CorInfoHelpFunc CEEInfo::getCastingHelper(CORINFO_RESOLVED_TOKEN * pResolvedToken, bool fThrowing)
6059 {
6060     CONTRACTL {
6061         SO_TOLERANT;
6062         THROWS;
6063         GC_TRIGGERS;
6064         MODE_PREEMPTIVE;
6065     } CONTRACTL_END;
6066
6067     if (isVerifyOnly())
6068         return fThrowing ? CORINFO_HELP_CHKCASTANY : CORINFO_HELP_ISINSTANCEOFANY;
6069
6070     CorInfoHelpFunc result = CORINFO_HELP_UNDEF;
6071
6072     JIT_TO_EE_TRANSITION();
6073
6074     bool fClassMustBeRestored;
6075     result = getCastingHelperStatic(TypeHandle(pResolvedToken->hClass), fThrowing, &fClassMustBeRestored);
6076     if (fClassMustBeRestored && m_pOverride != NULL)
6077         m_pOverride->classMustBeLoadedBeforeCodeIsRun(pResolvedToken->hClass);
6078
6079     EE_TO_JIT_TRANSITION();
6080
6081     return result;
6082 }
6083
6084 /***********************************************************************/
6085 CorInfoHelpFunc CEEInfo::getCastingHelperStatic(TypeHandle clsHnd, bool fThrowing, bool * pfClassMustBeRestored)
6086 {
6087     STANDARD_VM_CONTRACT;
6088
6089     // Slow helper is the default
6090     int helper = CORINFO_HELP_ISINSTANCEOFANY;
6091
6092     *pfClassMustBeRestored = false;
6093
6094     if (clsHnd == TypeHandle(g_pCanonMethodTableClass))
6095     {
6096         // In shared code just use the catch-all helper for type variables, as the same
6097         // code may be used for interface/array/class instantiations
6098         //
6099         // We may be able to take advantage of constraints to select a specialized helper.
6100         // This optimizations does not seem to be warranted at the moment.
6101         _ASSERTE(helper == CORINFO_HELP_ISINSTANCEOFANY);
6102     }
6103     else
6104     if (!clsHnd.IsTypeDesc() && clsHnd.AsMethodTable()->HasVariance())
6105     {
6106         // Casting to variant type requires the type to be fully loaded
6107         *pfClassMustBeRestored = true;
6108
6109         _ASSERTE(helper == CORINFO_HELP_ISINSTANCEOFANY);
6110     }
6111     else
6112     if (!clsHnd.IsTypeDesc() && clsHnd.AsMethodTable()->HasTypeEquivalence())
6113     {
6114         // If the type can be equivalent with something, use the slow helper
6115         // Note: if the type of the instance is the one marked as equivalent, it will be
6116         // caught by the fast helpers in the same way as they catch transparent proxies.
6117         _ASSERTE(helper == CORINFO_HELP_ISINSTANCEOFANY);
6118     }
6119     else
6120     if (clsHnd.IsInterface())
6121     {
6122         // If it is a non-variant interface, use the fast interface helper
6123         helper = CORINFO_HELP_ISINSTANCEOFINTERFACE;
6124     }
6125     else
6126     if (clsHnd.IsArray())
6127     {           
6128         if (clsHnd.AsArray()->GetInternalCorElementType() != ELEMENT_TYPE_SZARRAY)
6129         {
6130             // Casting to multidimensional array type requires restored pointer to EEClass to fetch rank
6131             *pfClassMustBeRestored = true;
6132         }
6133
6134         // If it is an array, use the fast array helper
6135         helper = CORINFO_HELP_ISINSTANCEOFARRAY;
6136     }
6137     else
6138     if (!clsHnd.IsTypeDesc() && !Nullable::IsNullableType(clsHnd))
6139     {
6140         // If it is a non-variant class, use the fast class helper
6141         helper = CORINFO_HELP_ISINSTANCEOFCLASS;
6142     }
6143     else
6144     {
6145         // Otherwise, use the slow helper
6146         _ASSERTE(helper == CORINFO_HELP_ISINSTANCEOFANY);
6147     }
6148
6149 #ifdef FEATURE_PREJIT
6150     BOOL t1, t2, forceInstr;
6151     SystemDomain::GetCompilationOverrides(&t1, &t2, &forceInstr);
6152     if (forceInstr)
6153     {
6154         // If we're compiling for instrumentation, use the slowest but instrumented cast helper
6155         helper = CORINFO_HELP_ISINSTANCEOFANY;
6156     }
6157 #endif
6158
6159     if (fThrowing)
6160     {
6161         const int delta = CORINFO_HELP_CHKCASTANY - CORINFO_HELP_ISINSTANCEOFANY;
6162
6163         static_assert_no_msg(CORINFO_HELP_CHKCASTINTERFACE 
6164             == CORINFO_HELP_ISINSTANCEOFINTERFACE + delta);
6165         static_assert_no_msg(CORINFO_HELP_CHKCASTARRAY 
6166             == CORINFO_HELP_ISINSTANCEOFARRAY + delta);
6167         static_assert_no_msg(CORINFO_HELP_CHKCASTCLASS 
6168             == CORINFO_HELP_ISINSTANCEOFCLASS + delta);
6169
6170         helper += delta;
6171     }
6172
6173     return (CorInfoHelpFunc)helper;
6174 }
6175
6176 /***********************************************************************/
6177 CorInfoHelpFunc CEEInfo::getSharedCCtorHelper(CORINFO_CLASS_HANDLE clsHnd)
6178 {
6179     CONTRACTL {
6180         SO_TOLERANT;
6181         NOTHROW;
6182         GC_NOTRIGGER;
6183         MODE_PREEMPTIVE;
6184     } CONTRACTL_END;
6185
6186     CorInfoHelpFunc result = CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE;
6187
6188     JIT_TO_EE_TRANSITION_LEAF();
6189
6190     TypeHandle cls(clsHnd);
6191     MethodTable* pMT = cls.AsMethodTable();
6192
6193     if (pMT->IsDynamicStatics())
6194     {
6195         _ASSERTE(!cls.ContainsGenericVariables());
6196         _ASSERTE(pMT->GetModuleDynamicEntryID() != (unsigned) -1);
6197
6198         result = CORINFO_HELP_CLASSINIT_SHARED_DYNAMICCLASS;
6199     }
6200
6201     EE_TO_JIT_TRANSITION_LEAF();
6202
6203     return result;
6204 }
6205
6206 /***********************************************************************/
6207 CorInfoHelpFunc CEEInfo::getUnBoxHelper(CORINFO_CLASS_HANDLE clsHnd)
6208 {
6209     LIMITED_METHOD_CONTRACT;
6210
6211     if (m_pOverride != NULL)
6212         m_pOverride->classMustBeLoadedBeforeCodeIsRun(clsHnd);
6213
6214     TypeHandle VMClsHnd(clsHnd);
6215     if (Nullable::IsNullableType(VMClsHnd))
6216         return CORINFO_HELP_UNBOX_NULLABLE;
6217     
6218     return CORINFO_HELP_UNBOX;
6219 }
6220
6221 /***********************************************************************/
6222 bool CEEInfo::getReadyToRunHelper(
6223         CORINFO_RESOLVED_TOKEN *        pResolvedToken,
6224         CORINFO_LOOKUP_KIND *           pGenericLookupKind,
6225         CorInfoHelpFunc                 id,
6226         CORINFO_CONST_LOOKUP *          pLookup
6227         )
6228 {
6229     LIMITED_METHOD_CONTRACT;
6230     UNREACHABLE();      // only called during NGen
6231 }
6232
6233 /***********************************************************************/
6234 void CEEInfo::getReadyToRunDelegateCtorHelper(
6235         CORINFO_RESOLVED_TOKEN * pTargetMethod,
6236         CORINFO_CLASS_HANDLE     delegateType,
6237         CORINFO_LOOKUP *   pLookup
6238         )
6239 {
6240     LIMITED_METHOD_CONTRACT;
6241     UNREACHABLE();      // only called during NGen
6242 }
6243
6244 /***********************************************************************/
6245 // see code:Nullable#NullableVerification
6246
6247 CORINFO_CLASS_HANDLE  CEEInfo::getTypeForBox(CORINFO_CLASS_HANDLE  cls)
6248 {
6249     LIMITED_METHOD_CONTRACT;
6250
6251     TypeHandle VMClsHnd(cls);
6252     if (Nullable::IsNullableType(VMClsHnd)) {
6253         VMClsHnd = VMClsHnd.AsMethodTable()->GetInstantiation()[0];
6254     }    
6255     return static_cast<CORINFO_CLASS_HANDLE>(VMClsHnd.AsPtr());
6256 }
6257
6258 /***********************************************************************/
6259 // see code:Nullable#NullableVerification
6260 CorInfoHelpFunc CEEInfo::getBoxHelper(CORINFO_CLASS_HANDLE clsHnd)
6261 {
6262     CONTRACTL {
6263         SO_TOLERANT;
6264         THROWS;
6265         GC_TRIGGERS;
6266         MODE_PREEMPTIVE;
6267     } CONTRACTL_END;
6268
6269     CorInfoHelpFunc result = CORINFO_HELP_UNDEF;
6270
6271     JIT_TO_EE_TRANSITION();
6272
6273     TypeHandle VMClsHnd(clsHnd);
6274     if (Nullable::IsNullableType(VMClsHnd))
6275     {
6276         result = CORINFO_HELP_BOX_NULLABLE;
6277     }
6278     else 
6279     {
6280         // Dev10 718281 - This has been functionally broken fora very long time (at least 2.0).
6281         // The recent addition of the check for stack pointers has caused it to now AV instead
6282         // of gracefully failing with an InvalidOperationException. Since nobody has noticed
6283         // it being broken, we are choosing not to invest to fix it, and instead explicitly
6284         // breaking it and failing early and consistently.
6285         if(VMClsHnd.IsTypeDesc())
6286         {
6287             COMPlusThrow(kInvalidOperationException,W("InvalidOperation_TypeCannotBeBoxed"));
6288         }
6289
6290         // we shouldn't allow boxing of types that contains stack pointers
6291         // csc and vbc already disallow it.
6292         if (VMClsHnd.AsMethodTable()->IsByRefLike())
6293             COMPlusThrow(kInvalidProgramException);
6294
6295         result = CORINFO_HELP_BOX;
6296     }
6297     
6298     EE_TO_JIT_TRANSITION();
6299
6300     return result;
6301 }
6302
6303 /***********************************************************************/
6304 CorInfoHelpFunc CEEInfo::getSecurityPrologHelper(CORINFO_METHOD_HANDLE ftn)
6305 {
6306     CONTRACTL {
6307         SO_TOLERANT;
6308         THROWS;
6309         GC_TRIGGERS;
6310         MODE_PREEMPTIVE;
6311     } CONTRACTL_END;
6312
6313     CorInfoHelpFunc result = CORINFO_HELP_UNDEF;
6314
6315     JIT_TO_EE_TRANSITION();
6316
6317 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
6318     // This will make sure that when IBC logging is on, we call the slow helper with IBC probe
6319     if (IsCompilingForNGen() &&
6320         GetAppDomain()->ToCompilationDomain()->m_fForceInstrument)
6321     {
6322         result = CORINFO_HELP_SECURITY_PROLOG_FRAMED;
6323     }
6324 #endif // FEATURE_NATIVE_IMAGE_GENERATION
6325
6326     if (result == CORINFO_HELP_UNDEF)
6327     {
6328         result = CORINFO_HELP_SECURITY_PROLOG;
6329     }
6330
6331     EE_TO_JIT_TRANSITION();
6332
6333     return result;
6334 }
6335
6336 /***********************************************************************/
6337 // registers a vararg sig & returns a class-specific cookie for it.
6338
6339 CORINFO_VARARGS_HANDLE CEEInfo::getVarArgsHandle(CORINFO_SIG_INFO *sig,
6340                                                  void **ppIndirection)
6341 {
6342     CONTRACTL {
6343         SO_TOLERANT;
6344         THROWS;
6345         GC_TRIGGERS;
6346         MODE_PREEMPTIVE;
6347     } CONTRACTL_END;
6348
6349     CORINFO_VARARGS_HANDLE result = NULL;
6350
6351     if (ppIndirection != NULL)
6352         *ppIndirection = NULL;
6353
6354     JIT_TO_EE_TRANSITION();
6355
6356     Module* module = GetModule(sig->scope);
6357
6358     result = CORINFO_VARARGS_HANDLE(module->GetVASigCookie(Signature(sig->pSig, sig->cbSig)));
6359
6360     EE_TO_JIT_TRANSITION();
6361
6362     return result;
6363 }
6364
6365 bool CEEInfo::canGetVarArgsHandle(CORINFO_SIG_INFO *sig)
6366 {
6367     LIMITED_METHOD_CONTRACT;
6368     return true;
6369 }
6370
6371 /***********************************************************************/
6372 unsigned CEEInfo::getMethodHash (CORINFO_METHOD_HANDLE ftnHnd)
6373 {
6374     CONTRACTL {
6375         SO_TOLERANT;
6376         THROWS;
6377         GC_TRIGGERS;
6378         MODE_PREEMPTIVE;
6379     } CONTRACTL_END;
6380
6381     unsigned result = 0;
6382
6383     JIT_TO_EE_TRANSITION();
6384
6385     MethodDesc* ftn = GetMethod(ftnHnd);
6386
6387     result = (unsigned) ftn->GetStableHash();
6388
6389     EE_TO_JIT_TRANSITION();
6390
6391     return result;
6392 }
6393
6394 /***********************************************************************/
6395 const char* CEEInfo::getMethodName (CORINFO_METHOD_HANDLE ftnHnd, const char** scopeName)
6396 {
6397     CONTRACTL {
6398         SO_TOLERANT;
6399         THROWS;
6400         GC_TRIGGERS;
6401         MODE_PREEMPTIVE;
6402     } CONTRACTL_END;
6403
6404     const char* result = NULL;
6405
6406     JIT_TO_EE_TRANSITION();
6407
6408     MethodDesc *ftn;
6409
6410     ftn = GetMethod(ftnHnd);
6411
6412     if (scopeName != 0)
6413     {
6414         if (ftn->IsLCGMethod())
6415         {
6416             *scopeName = "DynamicClass";
6417         }
6418         else if (ftn->IsILStub())
6419         {
6420             *scopeName = ILStubResolver::GetStubClassName(ftn);
6421         }
6422         else
6423         {
6424             MethodTable * pMT = ftn->GetMethodTable();
6425 #if defined(_DEBUG) 
6426 #ifdef FEATURE_SYMDIFF
6427             if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_SymDiffDump))
6428             {
6429                 if (pMT->IsArray())
6430                 {
6431                     ssClsNameBuff.Clear();
6432                     ssClsNameBuff.SetUTF8(pMT->GetDebugClassName());
6433                 }
6434                 else
6435                     pMT->_GetFullyQualifiedNameForClassNestedAware(ssClsNameBuff);
6436             }
6437             else
6438             {
6439 #endif
6440                 // Calling _GetFullyQualifiedNameForClass in chk build is very expensive
6441                 // since it construct the class name everytime we call this method. In chk
6442                 // builds we already have a cheaper way to get the class name -
6443                 // GetDebugClassName - which doesn't calculate the class name everytime.
6444                 // This results in huge saving in Ngen time for checked builds. 
6445                 ssClsNameBuff.Clear();
6446                 ssClsNameBuff.SetUTF8(pMT->GetDebugClassName());
6447
6448 #ifdef FEATURE_SYMDIFF
6449             }
6450 #endif            
6451             // Append generic instantiation at the end
6452             Instantiation inst = pMT->GetInstantiation();
6453             if (!inst.IsEmpty())
6454                 TypeString::AppendInst(ssClsNameBuff, inst);
6455                 
6456             *scopeName = ssClsNameBuff.GetUTF8(ssClsNameBuffScratch);
6457 #else // !_DEBUG
6458             // since this is for diagnostic purposes only,
6459             // give up on the namespace, as we don't have a buffer to concat it
6460             // also note this won't show array class names.
6461             LPCUTF8 nameSpace;
6462             *scopeName= pMT->GetFullyQualifiedNameInfo(&nameSpace);
6463 #endif // !_DEBUG
6464         }
6465     }
6466
6467     result = ftn->GetName();
6468
6469     EE_TO_JIT_TRANSITION();
6470     
6471     return result;
6472 }
6473
6474 /*********************************************************************/
6475 DWORD CEEInfo::getMethodAttribs (CORINFO_METHOD_HANDLE ftn)
6476 {
6477     CONTRACTL {
6478         SO_TOLERANT;
6479         THROWS;
6480         GC_TRIGGERS;
6481         MODE_PREEMPTIVE;
6482     } CONTRACTL_END;
6483
6484     DWORD result = 0;
6485
6486     JIT_TO_EE_TRANSITION();
6487
6488     result = getMethodAttribsInternal(ftn);
6489
6490     EE_TO_JIT_TRANSITION();
6491
6492     return result;
6493 }
6494
6495 /*********************************************************************/
6496 DWORD CEEInfo::getMethodAttribsInternal (CORINFO_METHOD_HANDLE ftn)
6497 {
6498     STANDARD_VM_CONTRACT;
6499
6500 /*
6501     returns method attribute flags (defined in corhdr.h)
6502
6503     NOTE: This doesn't return certain method flags
6504     (mdAssem, mdFamANDAssem, mdFamORAssem, mdPrivateScope)
6505 */
6506
6507     MethodDesc* pMD = GetMethod(ftn);
6508
6509     if (pMD->IsLCGMethod()) 
6510     {
6511 #ifndef CROSSGEN_COMPILE
6512 #endif // !CROSSGEN_COMPILE
6513
6514         return CORINFO_FLG_STATIC | CORINFO_FLG_DONT_INLINE | CORINFO_FLG_NOSECURITYWRAP;
6515     }
6516
6517     DWORD result = 0;
6518
6519     // <REVISIT_TODO>@todo: can we git rid of CORINFO_FLG_ stuff and just include cor.h?</REVISIT_TODO>
6520
6521     DWORD attribs = pMD->GetAttrs();
6522
6523     if (IsMdFamily(attribs))
6524         result |= CORINFO_FLG_PROTECTED;
6525     if (IsMdStatic(attribs))
6526         result |= CORINFO_FLG_STATIC;
6527     if (pMD->IsSynchronized())
6528         result |= CORINFO_FLG_SYNCH;
6529     if (pMD->IsFCallOrIntrinsic())
6530         result |= CORINFO_FLG_NOGCCHECK | CORINFO_FLG_INTRINSIC;
6531     if (IsMdVirtual(attribs))
6532         result |= CORINFO_FLG_VIRTUAL;
6533     if (IsMdAbstract(attribs))
6534         result |= CORINFO_FLG_ABSTRACT;
6535     if (IsMdRTSpecialName(attribs))
6536     {
6537         LPCUTF8 pName = pMD->GetName();
6538         if (IsMdInstanceInitializer(attribs, pName) ||
6539             IsMdClassConstructor(attribs, pName))
6540             result |= CORINFO_FLG_CONSTRUCTOR;
6541     }
6542
6543     //
6544     // See if we need to embed a .cctor call at the head of the
6545     // method body.
6546     //
6547
6548     MethodTable* pMT = pMD->GetMethodTable();
6549
6550     // method or class might have the final bit
6551     if (IsMdFinal(attribs) || pMT->IsSealed())
6552     {
6553         result |= CORINFO_FLG_FINAL;
6554     }
6555
6556     if (pMD->IsEnCAddedMethod())
6557     {
6558         result |= CORINFO_FLG_EnC;
6559     }
6560
6561     if (pMD->IsSharedByGenericInstantiations())
6562     {
6563         result |= CORINFO_FLG_SHAREDINST;
6564     }
6565
6566     if (pMD->IsNDirect())
6567     {
6568         result |= CORINFO_FLG_PINVOKE;
6569     }
6570
6571     if (!pMD->IsInterceptedForDeclSecurity())
6572     {
6573         result |= CORINFO_FLG_NOSECURITYWRAP;
6574     }
6575
6576     if (IsMdRequireSecObject(attribs))
6577     {
6578         // Assume all methods marked as DynamicSecurity are
6579         // marked that way because they use StackCrawlMark to identify
6580         // the caller.
6581         // See comments in canInline or canTailCall
6582         result |= CORINFO_FLG_DONT_INLINE_CALLER;
6583     }
6584
6585     // Check for an inlining directive.
6586     if (pMD->IsNotInline())
6587     {
6588         /* Function marked as not inlineable */
6589         result |= CORINFO_FLG_DONT_INLINE;
6590     }
6591     // AggressiveInlining only makes sense for IL methods.
6592     else if (pMD->IsIL() && IsMiAggressiveInlining(pMD->GetImplAttrs()))
6593     {
6594         result |= CORINFO_FLG_FORCEINLINE;
6595     }
6596
6597     if (pMT->IsDelegate() && ((DelegateEEClass*)(pMT->GetClass()))->GetInvokeMethod() == pMD)
6598     {
6599         // This is now used to emit efficient invoke code for any delegate invoke,
6600         // including multicast.
6601         result |= CORINFO_FLG_DELEGATE_INVOKE;
6602     }
6603
6604     return result;
6605 }
6606
6607 /*********************************************************************/
6608 void CEEInfo::setMethodAttribs (
6609         CORINFO_METHOD_HANDLE ftnHnd,
6610         CorInfoMethodRuntimeFlags attribs)
6611 {
6612     CONTRACTL {
6613         SO_TOLERANT;
6614         THROWS;
6615         GC_TRIGGERS;
6616         MODE_PREEMPTIVE;
6617     } CONTRACTL_END;
6618
6619     JIT_TO_EE_TRANSITION();
6620
6621     MethodDesc* ftn = GetMethod(ftnHnd);
6622
6623     if (attribs & CORINFO_FLG_BAD_INLINEE)
6624     {
6625         BOOL fCacheInliningHint = TRUE;
6626
6627 #ifdef FEATURE_NATIVE_IMAGE_GENERATION
6628         if (IsCompilationProcess())
6629         {
6630             // Since we are running managed code during NGen the inlining hint may be 
6631             // changing underneeth us as the code is JITed. We need to prevent the inlining
6632             // hints from changing once we start to use them to place IL in the image.
6633             if (!g_pCEECompileInfo->IsCachingOfInliningHintsEnabled())
6634             {
6635                 fCacheInliningHint = FALSE;
6636             }
6637             else
6638             {
6639                 // Don't cache inlining hints inside mscorlib during NGen of other assemblies,
6640                 // since mscorlib is loaded domain neutral and will survive worker process recycling,
6641                 // causing determinism problems.
6642                 Module * pModule = ftn->GetModule();
6643                 if (pModule->IsSystem() && pModule->HasNativeImage())
6644                 {
6645                     fCacheInliningHint = FALSE;
6646                 }
6647             }
6648         }
6649 #endif
6650
6651         if (fCacheInliningHint)
6652         {
6653             ftn->SetNotInline(true);
6654         }
6655     }
6656
6657     // Both CORINFO_FLG_UNVERIFIABLE and CORINFO_FLG_VERIFIABLE cannot be set
6658     _ASSERTE(!(attribs & CORINFO_FLG_UNVERIFIABLE) || 
6659              !(attribs & CORINFO_FLG_VERIFIABLE  ));
6660
6661     if (attribs & CORINFO_FLG_VERIFIABLE)
6662         ftn->SetIsVerified(TRUE);
6663     else if (attribs & CORINFO_FLG_UNVERIFIABLE)
6664         ftn->SetIsVerified(FALSE);
6665
6666     EE_TO_JIT_TRANSITION();
6667 }
6668
6669 /*********************************************************************/
6670
6671 void getMethodInfoILMethodHeaderHelper(
6672     COR_ILMETHOD_DECODER* header,
6673     CORINFO_METHOD_INFO* methInfo
6674     )
6675 {
6676     LIMITED_METHOD_CONTRACT;
6677     
6678     methInfo->ILCode          = const_cast<BYTE*>(header->Code);
6679     methInfo->ILCodeSize      = header->GetCodeSize();
6680     methInfo->maxStack        = static_cast<unsigned short>(header->GetMaxStack());
6681     methInfo->EHcount         = static_cast<unsigned short>(header->EHCount());
6682
6683     methInfo->options         =
6684         (CorInfoOptions)((header->GetFlags() & CorILMethod_InitLocals) ? CORINFO_OPT_INIT_LOCALS : 0) ;
6685 }
6686
6687 mdToken FindGenericMethodArgTypeSpec(IMDInternalImport* pInternalImport)
6688 {
6689     STANDARD_VM_CONTRACT;
6690
6691     HENUMInternalHolder hEnumTypeSpecs(pInternalImport);
6692     mdToken token;
6693
6694     static const BYTE signature[] = { ELEMENT_TYPE_MVAR, 0 };
6695
6696     hEnumTypeSpecs.EnumAllInit(mdtTypeSpec);
6697     while (hEnumTypeSpecs.EnumNext(&token))
6698     {
6699         PCCOR_SIGNATURE pSig;
6700         ULONG cbSig;
6701         IfFailThrow(pInternalImport->GetTypeSpecFromToken(token, &pSig, &cbSig));
6702         if (cbSig == sizeof(signature) && memcmp(pSig, signature, cbSig) == 0)
6703             return token;
6704     }
6705
6706     COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
6707 }
6708
6709 /*********************************************************************
6710
6711 IL is the most efficient and portable way to implement certain low level methods 
6712 in mscorlib.dll. Unfortunately, there is no good way to link IL into mscorlib.dll today.
6713 Until we find a good way to link IL into mscorlib.dll, we will provide the IL implementation here.
6714
6715 - All IL intrinsincs are members of System.Runtime.CompilerServices.JitHelpers class
6716 - All IL intrinsincs should be kept very simple. Implement the minimal reusable version of 
6717 unsafe construct and depend on inlining to do the rest.
6718 - The C# implementation of the IL intrinsic should be good enough for functionalily. Everything should work 
6719 correctly (but slower) if the IL intrinsics are removed.
6720
6721 *********************************************************************/
6722
6723 bool getILIntrinsicImplementation(MethodDesc * ftn,
6724                                   CORINFO_METHOD_INFO * methInfo)
6725 {
6726     STANDARD_VM_CONTRACT;
6727
6728     // Precondition: ftn is a method in mscorlib 
6729     _ASSERTE(ftn->GetModule()->IsSystem());
6730
6731     mdMethodDef tk = ftn->GetMemberDef();
6732
6733     // Compare tokens to cover all generic instantiations
6734     // The body of the first method is simply ret Arg0. The second one first casts the arg to I4.
6735
6736     if (tk == MscorlibBinder::GetMethod(METHOD__JIT_HELPERS__UNSAFE_CAST)->GetMemberDef())
6737     {
6738         // Return the argument that was passed in.
6739         static const BYTE ilcode[] = { CEE_LDARG_0, CEE_RET };
6740         methInfo->ILCode = const_cast<BYTE*>(ilcode);
6741         methInfo->ILCodeSize = sizeof(ilcode);
6742         methInfo->maxStack = 1;
6743         methInfo->EHcount = 0;
6744         methInfo->options = (CorInfoOptions)0;
6745         return true;
6746     }
6747     else if (tk == MscorlibBinder::GetMethod(METHOD__JIT_HELPERS__UNSAFE_CAST_TO_STACKPTR)->GetMemberDef())
6748     {
6749         // Return the argument that was passed in converted to IntPtr
6750         static const BYTE ilcode[] = { CEE_LDARG_0, CEE_CONV_I, CEE_RET };
6751         methInfo->ILCode = const_cast<BYTE*>(ilcode);
6752         methInfo->ILCodeSize = sizeof(ilcode);
6753         methInfo->maxStack = 1;
6754         methInfo->EHcount = 0;
6755         methInfo->options = (CorInfoOptions)0;
6756         return true;
6757     }
6758     else if (tk == MscorlibBinder::GetMethod(METHOD__JIT_HELPERS__UNSAFE_ENUM_CAST)->GetMemberDef()) 
6759     {
6760         // Normally we would follow the above pattern and unconditionally replace the IL,
6761         // relying on generic type constraints to guarantee that it will only ever be instantiated
6762         // on the type/size of argument we expect.
6763         //
6764         // However C#/CLR does not support restricting a generic type to be an Enum, so the best
6765         // we can do is constrain it to be a value type.  This is fine for run time, since we only
6766         // ever create instantiations on 4 byte or less Enums. But during NGen we may compile instantiations
6767         // on other value types (to be specific, every value type instatiation of EqualityComparer
6768         // because of its TypeDependencyAttribute; here again we would like to restrict this to
6769         // 4 byte or less Enums but cannot).
6770         //
6771         // This IL is invalid for those instantiations, and replacing it would lead to all sorts of
6772         // errors at NGen time.  So we only replace it for instantiations where it would be valid, 
6773         // leaving the others, which we should never execute, with the C# implementation of throwing.
6774
6775         _ASSERTE(ftn->HasMethodInstantiation());
6776         Instantiation inst = ftn->GetMethodInstantiation();
6777
6778         _ASSERTE(inst.GetNumArgs() == 1);
6779         CorElementType et = inst[0].GetVerifierCorElementType();
6780         if (et == ELEMENT_TYPE_I4 ||
6781             et == ELEMENT_TYPE_U4 ||
6782             et == ELEMENT_TYPE_I2 ||
6783             et == ELEMENT_TYPE_U2 ||
6784             et == ELEMENT_TYPE_I1 ||
6785             et == ELEMENT_TYPE_U1)
6786         {
6787             // Cast to I4 and return the argument that was passed in.
6788             static const BYTE ilcode[] = { CEE_LDARG_0, CEE_CONV_I4, CEE_RET };
6789             methInfo->ILCode = const_cast<BYTE*>(ilcode);
6790             methInfo->ILCodeSize = sizeof(ilcode);
6791             methInfo->maxStack = 1;
6792             methInfo->EHcount = 0;
6793             methInfo->options = (CorInfoOptions)0;
6794             return true;
6795         }
6796     }
6797     else if (tk == MscorlibBinder::GetMethod(METHOD__JIT_HELPERS__UNSAFE_ENUM_CAST_LONG)->GetMemberDef()) 
6798     {
6799         // The the comment above on why this is is not an unconditional replacement.  This case handles
6800         // Enums backed by 8 byte values.
6801
6802         _ASSERTE(ftn->HasMethodInstantiation());
6803         Instantiation inst = ftn->GetMethodInstantiation();
6804
6805         _ASSERTE(inst.GetNumArgs() == 1);
6806         CorElementType et = inst[0].GetVerifierCorElementType();
6807         if (et == ELEMENT_TYPE_I8 ||
6808             et == ELEMENT_TYPE_U8)
6809         {
6810             // Cast to I8 and return the argument that was passed in.
6811             static const BYTE ilcode[] = { CEE_LDARG_0, CEE_CONV_I8, CEE_RET };
6812             methInfo->ILCode = const_cast<BYTE*>(ilcode);
6813             methInfo->ILCodeSize = sizeof(ilcode);
6814             methInfo->maxStack = 1;
6815             methInfo->EHcount = 0;
6816             methInfo->options = (CorInfoOptions)0;
6817             return true;
6818         }
6819     }
6820     else if (tk == MscorlibBinder::GetMethod(METHOD__JIT_HELPERS__GET_RAW_SZ_ARRAY_DATA)->GetMemberDef())
6821     {
6822         mdToken tokArrayPinningHelper = MscorlibBinder::GetField(FIELD__ARRAY_PINNING_HELPER__M_ARRAY_DATA)->GetMemberDef();
6823
6824         static BYTE ilcode[] = { CEE_LDARG_0,
6825                                  CEE_LDFLDA,0,0,0,0,
6826                                  CEE_RET };
6827
6828         ilcode[2] = (BYTE)(tokArrayPinningHelper);
6829         ilcode[3] = (BYTE)(tokArrayPinningHelper >> 8);
6830         ilcode[4] = (BYTE)(tokArrayPinningHelper >> 16);
6831         ilcode[5] = (BYTE)(tokArrayPinningHelper >> 24);
6832
6833         methInfo->ILCode = const_cast<BYTE*>(ilcode);
6834         methInfo->ILCodeSize = sizeof(ilcode);
6835         methInfo->maxStack = 1;
6836         methInfo->EHcount = 0;
6837         methInfo->options = (CorInfoOptions)0;
6838         return true;
6839     }
6840
6841     return false;
6842 }
6843
6844 bool getILIntrinsicImplementationForUnsafe(MethodDesc * ftn,
6845                                            CORINFO_METHOD_INFO * methInfo)
6846 {
6847     STANDARD_VM_CONTRACT;
6848
6849     // Precondition: ftn is a method in mscorlib 
6850     _ASSERTE(ftn->GetModule()->IsSystem());
6851
6852     mdMethodDef tk = ftn->GetMemberDef();
6853
6854     if (tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__AS_POINTER)->GetMemberDef())
6855     {
6856         // Return the argument that was passed in.
6857         static const BYTE ilcode[] = { CEE_LDARG_0, CEE_CONV_U, CEE_RET };
6858         methInfo->ILCode = const_cast<BYTE*>(ilcode);
6859         methInfo->ILCodeSize = sizeof(ilcode);
6860         methInfo->maxStack = 1;
6861         methInfo->EHcount = 0;
6862         methInfo->options = (CorInfoOptions)0;
6863         return true;
6864     }
6865     if (tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__SIZEOF)->GetMemberDef())
6866     {
6867         _ASSERTE(ftn->HasMethodInstantiation());
6868         Instantiation inst = ftn->GetMethodInstantiation();
6869
6870         _ASSERTE(ftn->GetNumGenericMethodArgs() == 1);
6871         mdToken tokGenericArg = FindGenericMethodArgTypeSpec(MscorlibBinder::GetModule()->GetMDImport());
6872
6873         static BYTE ilcode[] = { CEE_PREFIX1, (CEE_SIZEOF & 0xFF), 0,0,0,0, CEE_RET };
6874
6875         ilcode[2] = (BYTE)(tokGenericArg);
6876         ilcode[3] = (BYTE)(tokGenericArg >> 8);
6877         ilcode[4] = (BYTE)(tokGenericArg >> 16);
6878         ilcode[5] = (BYTE)(tokGenericArg >> 24);
6879
6880         methInfo->ILCode = const_cast<BYTE*>(ilcode);
6881         methInfo->ILCodeSize = sizeof(ilcode);
6882         methInfo->maxStack = 1;
6883         methInfo->EHcount = 0;
6884         methInfo->options = (CorInfoOptions)0;
6885         return true;
6886     }
6887     else if (tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__BYREF_AS)->GetMemberDef())
6888     {
6889         // Return the argument that was passed in.
6890         static const BYTE ilcode[] = { CEE_LDARG_0, CEE_RET };
6891         methInfo->ILCode = const_cast<BYTE*>(ilcode);
6892         methInfo->ILCodeSize = sizeof(ilcode);
6893         methInfo->maxStack = 1;
6894         methInfo->EHcount = 0;
6895         methInfo->options = (CorInfoOptions)0;
6896         return true;
6897     }
6898     else if (tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__BYREF_ADD)->GetMemberDef())
6899     {
6900         mdToken tokGenericArg = FindGenericMethodArgTypeSpec(MscorlibBinder::GetModule()->GetMDImport());
6901
6902         static BYTE ilcode[] = { CEE_LDARG_1,
6903             CEE_PREFIX1, (CEE_SIZEOF & 0xFF), 0,0,0,0,
6904             CEE_CONV_I,
6905             CEE_MUL,
6906             CEE_LDARG_0,
6907             CEE_ADD,
6908             CEE_RET };
6909
6910         ilcode[3] = (BYTE)(tokGenericArg);
6911         ilcode[4] = (BYTE)(tokGenericArg >> 8);
6912         ilcode[5] = (BYTE)(tokGenericArg >> 16);
6913         ilcode[6] = (BYTE)(tokGenericArg >> 24);
6914
6915         methInfo->ILCode = const_cast<BYTE*>(ilcode);
6916         methInfo->ILCodeSize = sizeof(ilcode);
6917         methInfo->maxStack = 2;
6918         methInfo->EHcount = 0;
6919         methInfo->options = (CorInfoOptions)0;
6920         return true;
6921     }
6922     else if (tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__BYREF_ADD_BYTE_OFFSET)->GetMemberDef())
6923     {
6924         static BYTE ilcode[] = { CEE_LDARG_0, CEE_LDARG_1, CEE_ADD, CEE_RET };
6925
6926         methInfo->ILCode = const_cast<BYTE*>(ilcode);
6927         methInfo->ILCodeSize = sizeof(ilcode);
6928         methInfo->maxStack = 2;
6929         methInfo->EHcount = 0;
6930         methInfo->options = (CorInfoOptions)0;
6931         return true;
6932     }
6933     else if (tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__BYREF_ARE_SAME)->GetMemberDef())
6934     {
6935         // Compare the two arguments
6936         static const BYTE ilcode[] = { CEE_LDARG_0, CEE_LDARG_1, CEE_PREFIX1, (CEE_CEQ & 0xFF), CEE_RET };
6937         methInfo->ILCode = const_cast<BYTE*>(ilcode);
6938         methInfo->ILCodeSize = sizeof(ilcode);
6939         methInfo->maxStack = 2;
6940         methInfo->EHcount = 0;
6941         methInfo->options = (CorInfoOptions)0;
6942         return true;
6943     }
6944     else if (tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__BYREF_INIT_BLOCK_UNALIGNED)->GetMemberDef())
6945     {
6946         static const BYTE ilcode[] = { CEE_LDARG_0, CEE_LDARG_1, CEE_LDARG_2, CEE_PREFIX1, (CEE_UNALIGNED & 0xFF), 0x01, CEE_PREFIX1, (CEE_INITBLK & 0xFF), CEE_RET };
6947         methInfo->ILCode = const_cast<BYTE*>(ilcode);
6948         methInfo->ILCodeSize = sizeof(ilcode);
6949         methInfo->maxStack = 3;
6950         methInfo->EHcount = 0;
6951         methInfo->options = (CorInfoOptions)0;
6952         return true;
6953     }
6954     else if (tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__BYREF_READ_UNALIGNED)->GetMemberDef() ||
6955              tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__PTR_READ_UNALIGNED)->GetMemberDef())
6956     {
6957         _ASSERTE(ftn->HasMethodInstantiation());
6958         Instantiation inst = ftn->GetMethodInstantiation();
6959         _ASSERTE(ftn->GetNumGenericMethodArgs() == 1);
6960         mdToken tokGenericArg = FindGenericMethodArgTypeSpec(MscorlibBinder::GetModule()->GetMDImport());
6961
6962         static const BYTE ilcode[]
6963         { 
6964             CEE_LDARG_0,
6965             CEE_PREFIX1, (CEE_UNALIGNED & 0xFF), 1,
6966             CEE_LDOBJ, (BYTE)(tokGenericArg), (BYTE)(tokGenericArg >> 8), (BYTE)(tokGenericArg >> 16), (BYTE)(tokGenericArg >> 24),
6967             CEE_RET
6968         };
6969
6970         methInfo->ILCode = const_cast<BYTE*>(ilcode);
6971         methInfo->ILCodeSize = sizeof(ilcode);
6972         methInfo->maxStack = 2;
6973         methInfo->EHcount = 0;
6974         methInfo->options = (CorInfoOptions)0;
6975         return true;
6976     }
6977     else if (tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__BYREF_WRITE_UNALIGNED)->GetMemberDef() ||
6978              tk == MscorlibBinder::GetMethod(METHOD__UNSAFE__PTR_WRITE_UNALIGNED)->GetMemberDef())
6979     {
6980         _ASSERTE(ftn->HasMethodInstantiation());
6981         Instantiation inst = ftn->GetMethodInstantiation();
6982         _ASSERTE(ftn->GetNumGenericMethodArgs() == 1);
6983         mdToken tokGenericArg = FindGenericMethodArgTypeSpec(MscorlibBinder::GetModule()->GetMDImport());
6984
6985         static const BYTE ilcode[]
6986         {
6987             CEE_LDARG_0,
6988             CEE_LDARG_1,
6989             CEE_PREFIX1, (CEE_UNALIGNED & 0xFF), 1,
6990             CEE_STOBJ, (BYTE)(tokGenericArg), (BYTE)(tokGenericArg >> 8), (BYTE)(tokGenericArg >> 16), (BYTE)(tokGenericArg >> 24),
6991             CEE_RET
6992         };
6993
6994         methInfo->ILCode = const_cast<BYTE*>(ilcode);
6995         methInfo->ILCodeSize = sizeof(ilcode);
6996         methInfo->maxStack = 2;
6997         methInfo->EHcount = 0;
6998         methInfo->options = (CorInfoOptions)0;
6999         return true;
7000     }
7001
7002     return false;
7003 }
7004
7005 bool getILIntrinsicImplementationForVolatile(MethodDesc * ftn,
7006                                              CORINFO_METHOD_INFO * methInfo)
7007 {
7008     STANDARD_VM_CONTRACT;
7009
7010     //
7011     // This replaces the implementations of Volatile.* in mscorlib with more efficient ones.
7012     // We do this because we cannot otherwise express these in C#.  What we *want* to do is
7013     // to treat the byref args to these methods as "volatile."  In pseudo-C#, this would look
7014     // like:
7015     //
7016     //   int Read(ref volatile int location)
7017     //   {
7018     //       return location;
7019     //   }
7020     //
7021     // However, C# does not yet provide a way to declare a byref as "volatile."  So instead,
7022     // we substitute raw IL bodies for these methods that use the correct volatile instructions.
7023     //
7024
7025     // Precondition: ftn is a method in mscorlib in the System.Threading.Volatile class
7026     _ASSERTE(ftn->GetModule()->IsSystem());
7027     _ASSERTE(MscorlibBinder::IsClass(ftn->GetMethodTable(), CLASS__VOLATILE));
7028     _ASSERTE(strcmp(ftn->GetMethodTable()->GetClass()->GetDebugClassName(), "System.Threading.Volatile") == 0);
7029
7030     const size_t VolatileMethodBodySize = 6;
7031
7032     struct VolatileMethodImpl
7033     {
7034         BinderMethodID methodId;
7035         BYTE body[VolatileMethodBodySize];
7036     };
7037
7038 #define VOLATILE_IMPL(type, loadinst, storeinst) \
7039     { \
7040         METHOD__VOLATILE__READ_##type, \
7041         { \
7042             CEE_LDARG_0, \
7043             CEE_PREFIX1, (CEE_VOLATILE & 0xFF), \
7044             loadinst, \
7045             CEE_NOP, /*pad to VolatileMethodBodySize bytes*/ \
7046             CEE_RET \
7047         } \
7048     }, \
7049     { \
7050         METHOD__VOLATILE__WRITE_##type, \
7051         { \
7052             CEE_LDARG_0, \
7053             CEE_LDARG_1, \
7054             CEE_PREFIX1, (CEE_VOLATILE & 0xFF), \
7055             storeinst, \
7056             CEE_RET \
7057         } \
7058     },
7059
7060     static const VolatileMethodImpl volatileImpls[] =
7061     {
7062         VOLATILE_IMPL(T,       CEE_LDIND_REF, CEE_STIND_REF)
7063         VOLATILE_IMPL(Bool,    CEE_LDIND_I1,  CEE_STIND_I1)
7064         VOLATILE_IMPL(Int,     CEE_LDIND_I4,  CEE_STIND_I4)
7065         VOLATILE_IMPL(IntPtr,  CEE_LDIND_I,   CEE_STIND_I)
7066         VOLATILE_IMPL(UInt,    CEE_LDIND_U4,  CEE_STIND_I4)
7067         VOLATILE_IMPL(UIntPtr, CEE_LDIND_I,   CEE_STIND_I)
7068         VOLATILE_IMPL(SByt,    CEE_LDIND_I1,  CEE_STIND_I1)
7069         VOLATILE_IMPL(Byte,    CEE_LDIND_U1,  CEE_STIND_I1)
7070         VOLATILE_IMPL(Shrt,    CEE_LDIND_I2,  CEE_STIND_I2)
7071         VOLATILE_IMPL(UShrt,   CEE_LDIND_U2,  CEE_STIND_I2)
7072         VOLATILE_IMPL(Flt,     CEE_LDIND_R4,  CEE_STIND_R4)
7073
7074         //
7075         // Ordinary volatile loads and stores only guarantee atomicity for pointer-sized (or smaller) data.
7076         // So, on 32-bit platforms we must use Interlocked operations instead for the 64-bit types.
7077         // The implementation in mscorlib already does this, so we will only substitute a new
7078         // IL body if we're running on a 64-bit platform.
7079         //
7080         IN_WIN64(VOLATILE_IMPL(Long,  CEE_LDIND_I8, CEE_STIND_I8))
7081         IN_WIN64(VOLATILE_IMPL(ULong, CEE_LDIND_I8, CEE_STIND_I8))
7082         IN_WIN64(VOLATILE_IMPL(Dbl,   CEE_LDIND_R8, CEE_STIND_R8))
7083     };
7084
7085     mdMethodDef md = ftn->GetMemberDef();
7086     for (unsigned i = 0; i < NumItems(volatileImpls); i++)
7087     {
7088         if (md == MscorlibBinder::GetMethod(volatileImpls[i].methodId)->GetMemberDef())
7089         {
7090             methInfo->ILCode = const_cast<BYTE*>(volatileImpls[i].body);
7091             methInfo->ILCodeSize = VolatileMethodBodySize;
7092             methInfo->maxStack = 2;
7093             methInfo->EHcount = 0;
7094             methInfo->options = (CorInfoOptions)0;
7095             return true;
7096         }
7097     }
7098
7099     return false;
7100 }
7101
7102 bool getILIntrinsicImplementationForInterlocked(MethodDesc * ftn,
7103                                                 CORINFO_METHOD_INFO * methInfo)
7104 {
7105     STANDARD_VM_CONTRACT;
7106
7107     // Precondition: ftn is a method in mscorlib in the System.Threading.Interlocked class
7108     _ASSERTE(ftn->GetModule()->IsSystem());
7109     _ASSERTE(MscorlibBinder::IsClass(ftn->GetMethodTable(), CLASS__INTERLOCKED));
7110
7111     // We are only interested if ftn's token and CompareExchange<T> token match
7112     if (ftn->GetMemberDef() != MscorlibBinder::GetMethod(METHOD__INTERLOCKED__COMPARE_EXCHANGE_T)->GetMemberDef())
7113         return false;       
7114
7115     // Get MethodDesc for System.Threading.Interlocked.CompareExchangeFast()
7116     MethodDesc* cmpxchgFast = MscorlibBinder::GetMethod(METHOD__INTERLOCKED__COMPARE_EXCHANGE_OBJECT);
7117
7118     // The MethodDesc lookup must not fail, and it should have the name "CompareExchangeFast"
7119     _ASSERTE(cmpxchgFast != NULL);
7120     _ASSERTE(strcmp(cmpxchgFast->GetName(), "CompareExchange") == 0);
7121
7122     // Setup up the body of the method
7123     static BYTE il[] = {
7124                           CEE_LDARG_0,
7125                           CEE_LDARG_1,
7126                           CEE_LDARG_2,
7127                           CEE_CALL,0,0,0,0, 
7128                           CEE_RET
7129                         };
7130
7131     // Get the token for System.Threading.Interlocked.CompareExchangeFast(), and patch [target]
7132     mdMethodDef cmpxchgFastToken = cmpxchgFast->GetMemberDef();
7133     il[4] = (BYTE)((int)cmpxchgFastToken >> 0);
7134     il[5] = (BYTE)((int)cmpxchgFastToken >> 8);
7135     il[6] = (BYTE)((int)cmpxchgFastToken >> 16);
7136     il[7] = (BYTE)((int)cmpxchgFastToken >> 24);
7137
7138     // Initialize methInfo
7139     methInfo->ILCode = const_cast<BYTE*>(il);
7140     methInfo->ILCodeSize = sizeof(il);
7141     methInfo->maxStack = 3;
7142     methInfo->EHcount = 0;
7143     methInfo->options = (CorInfoOptions)0;
7144
7145     return true;
7146 }
7147
7148 bool getILIntrinsicImplementationForRuntimeHelpers(MethodDesc * ftn,
7149     CORINFO_METHOD_INFO * methInfo)
7150 {
7151     STANDARD_VM_CONTRACT;
7152
7153     // Precondition: ftn is a method in mscorlib 
7154     _ASSERTE(ftn->GetModule()->IsSystem());
7155
7156     mdMethodDef tk = ftn->GetMemberDef();
7157
7158     if (tk == MscorlibBinder::GetMethod(METHOD__RUNTIME_HELPERS__IS_REFERENCE_OR_CONTAINS_REFERENCES)->GetMemberDef())
7159     {
7160         _ASSERTE(ftn->HasMethodInstantiation());
7161         Instantiation inst = ftn->GetMethodInstantiation();
7162
7163         _ASSERTE(ftn->GetNumGenericMethodArgs() == 1);
7164         TypeHandle typeHandle = inst[0];
7165         MethodTable * methodTable = typeHandle.GetMethodTable();
7166
7167         static const BYTE returnTrue[] = { CEE_LDC_I4_1, CEE_RET };
7168         static const BYTE returnFalse[] = { CEE_LDC_I4_0, CEE_RET };
7169
7170         if (!methodTable->IsValueType() || methodTable->ContainsPointers())
7171         {
7172             methInfo->ILCode = const_cast<BYTE*>(returnTrue);
7173         }
7174         else
7175         {
7176             methInfo->ILCode = const_cast<BYTE*>(returnFalse);
7177         }
7178
7179         methInfo->ILCodeSize = sizeof(returnTrue);
7180         methInfo->maxStack = 1;
7181         methInfo->EHcount = 0;
7182         methInfo->options = (CorInfoOptions)0;
7183         return true;
7184     }
7185
7186     return false;
7187 }
7188
7189 //---------------------------------------------------------------------------------------
7190 // 
7191 //static
7192 void 
7193 getMethodInfoHelper(
7194     MethodDesc *           ftn, 
7195     CORINFO_METHOD_HANDLE  ftnHnd, 
7196     COR_ILMETHOD_DECODER * header, 
7197     CORINFO_METHOD_INFO *  methInfo)
7198 {
7199     STANDARD_VM_CONTRACT;
7200
7201     _ASSERTE(ftn == GetMethod(ftnHnd));
7202
7203     methInfo->ftn             = ftnHnd;
7204     methInfo->scope           = GetScopeHandle(ftn);
7205     methInfo->regionKind      = CORINFO_REGION_JIT;
7206     //
7207     // For Jitted code the regionKind is JIT;
7208     // For Ngen-ed code the zapper will set this to HOT or COLD, if we  
7209     // are using IBC data to partition methods into Hot/Cold regions
7210
7211     /* Grab information from the IL header */
7212
7213     PCCOR_SIGNATURE pLocalSig = NULL;
7214     DWORD           cbLocalSig = 0;
7215
7216     if (NULL != header)
7217     {
7218         bool fILIntrinsic = false;
7219
7220         MethodTable * pMT  = ftn->GetMethodTable();
7221       
7222         if (MscorlibBinder::IsClass(pMT, CLASS__JIT_HELPERS))
7223         {
7224             fILIntrinsic = getILIntrinsicImplementation(ftn, methInfo);
7225         }
7226         else if (MscorlibBinder::IsClass(pMT, CLASS__UNSAFE))
7227         {
7228             fILIntrinsic = getILIntrinsicImplementationForUnsafe(ftn, methInfo);
7229         }
7230         else if (MscorlibBinder::IsClass(pMT, CLASS__INTERLOCKED))
7231         {
7232             fILIntrinsic = getILIntrinsicImplementationForInterlocked(ftn, methInfo);
7233         }
7234         else if (MscorlibBinder::IsClass(pMT, CLASS__VOLATILE))
7235         {
7236             fILIntrinsic = getILIntrinsicImplementationForVolatile(ftn, methInfo);
7237         }
7238         else if (MscorlibBinder::IsClass(pMT, CLASS__RUNTIME_HELPERS))
7239         {
7240             fILIntrinsic = getILIntrinsicImplementationForRuntimeHelpers(ftn, methInfo);
7241         }
7242
7243         if (!fILIntrinsic)
7244         {
7245             getMethodInfoILMethodHeaderHelper(header, methInfo);
7246             pLocalSig = header->LocalVarSig;
7247             cbLocalSig = header->cbLocalVarSig;
7248         }
7249     }
7250     else
7251     {
7252         _ASSERTE(ftn->IsDynamicMethod());
7253
7254         DynamicResolver * pResolver = ftn->AsDynamicMethodDesc()->GetResolver();        
7255         unsigned int EHCount;
7256         methInfo->ILCode = pResolver->GetCodeInfo(&methInfo->ILCodeSize,
7257                                                   &methInfo->maxStack,
7258                                                   &methInfo->options,
7259                                                   &EHCount);
7260         methInfo->EHcount = (unsigned short)EHCount;
7261         SigPointer localSig = pResolver->GetLocalSig();
7262         localSig.GetSignature(&pLocalSig, &cbLocalSig);
7263     }
7264
7265     methInfo->options = (CorInfoOptions)(((UINT32)methInfo->options) | 
7266                             ((ftn->AcquiresInstMethodTableFromThis() ? CORINFO_GENERICS_CTXT_FROM_THIS : 0) |
7267                              (ftn->RequiresInstMethodTableArg() ? CORINFO_GENERICS_CTXT_FROM_METHODTABLE : 0) |
7268                              (ftn->RequiresInstMethodDescArg() ? CORINFO_GENERICS_CTXT_FROM_METHODDESC : 0)));
7269
7270     // EEJitManager::ResolveEHClause and CrawlFrame::GetExactGenericInstantiations
7271     // need to be able to get to CORINFO_GENERICS_CTXT_MASK if there are any
7272     // catch clauses like "try {} catch(MyException<T> e) {}".
7273     // Such constructs are rare, and having to extend the lifetime of variable
7274     // for such cases is reasonable
7275
7276     if (methInfo->options & CORINFO_GENERICS_CTXT_MASK)
7277     {
7278 #if defined(PROFILING_SUPPORTED)
7279         BOOL fProfilerRequiresGenericsContextForEnterLeave = FALSE;
7280         {
7281             BEGIN_PIN_PROFILER(CORProfilerPresent());
7282             if (g_profControlBlock.pProfInterface->RequiresGenericsContextForEnterLeave())
7283             {
7284                 fProfilerRequiresGenericsContextForEnterLeave = TRUE;
7285             }
7286             END_PIN_PROFILER();
7287         }
7288         if (fProfilerRequiresGenericsContextForEnterLeave)
7289         {
7290             methInfo->options = CorInfoOptions(methInfo->options|CORINFO_GENERICS_CTXT_KEEP_ALIVE);
7291         }
7292         else
7293 #endif // defined(PROFILING_SUPPORTED)
7294         {
7295             // Check all the exception clauses
7296
7297             if (ftn->IsDynamicMethod())
7298             {
7299                 // @TODO: how do we detect the need to mark this flag?
7300             }
7301             else
7302             {
7303                 COR_ILMETHOD_SECT_EH_CLAUSE_FAT ehClause;
7304
7305                 for (unsigned i = 0; i < methInfo->EHcount; i++)
7306                 {
7307                     const COR_ILMETHOD_SECT_EH_CLAUSE_FAT* ehInfo =
7308                             (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)header->EH->EHClause(i, &ehClause);
7309
7310                     // Is it a typed catch clause?
7311                     if (ehInfo->GetFlags() != COR_ILEXCEPTION_CLAUSE_NONE)
7312                         continue;
7313
7314                     // Check if we catch "C<T>" ?
7315
7316                     DWORD catchTypeToken = ehInfo->GetClassToken();
7317                     if (TypeFromToken(catchTypeToken) != mdtTypeSpec)
7318                         continue;
7319
7320                     PCCOR_SIGNATURE pSig;
7321                     ULONG cSig;
7322                     IfFailThrow(ftn->GetMDImport()->GetTypeSpecFromToken(catchTypeToken, &pSig, &cSig));
7323                     
7324                     SigPointer psig(pSig, cSig);
7325
7326                     SigTypeContext sigTypeContext(ftn);
7327                     if (psig.IsPolyType(&sigTypeContext) & hasSharableVarsMask)
7328                     {
7329                         methInfo->options = CorInfoOptions(methInfo->options|CORINFO_GENERICS_CTXT_KEEP_ALIVE);
7330                         break;
7331                     }
7332                 }
7333             }
7334         }
7335     }
7336
7337     PCCOR_SIGNATURE pSig = NULL;
7338     DWORD           cbSig = 0;
7339     ftn->GetSig(&pSig, &cbSig);
7340     
7341     /* Fetch the method signature */
7342     // Type parameters in the signature should be instantiated according to the
7343     // class/method/array instantiation of ftnHnd
7344     CEEInfo::ConvToJitSig(
7345         pSig, 
7346         cbSig, 
7347         GetScopeHandle(ftn), 
7348         mdTokenNil, 
7349         &methInfo->args, 
7350         ftn, 
7351         false);
7352
7353     // Shared generic or static per-inst methods and shared methods on generic structs
7354     // take an extra argument representing their instantiation
7355     if (ftn->RequiresInstArg())
7356         methInfo->args.callConv = (CorInfoCallConv)(methInfo->args.callConv | CORINFO_CALLCONV_PARAMTYPE);
7357
7358     _ASSERTE((IsMdStatic(ftn->GetAttrs()) == 0) == ((methInfo->args.callConv & CORINFO_CALLCONV_HASTHIS) != 0));
7359
7360     /* And its local variables */
7361     // Type parameters in the signature should be instantiated according to the
7362     // class/method/array instantiation of ftnHnd
7363     CEEInfo::ConvToJitSig(
7364         pLocalSig, 
7365         cbLocalSig, 
7366         GetScopeHandle(ftn), 
7367         mdTokenNil, 
7368         &methInfo->locals, 
7369         ftn, 
7370         true);
7371 } // getMethodInfoHelper
7372
7373 //---------------------------------------------------------------------------------------
7374 // 
7375 bool 
7376 CEEInfo::getMethodInfo(
7377     CORINFO_METHOD_HANDLE ftnHnd, 
7378     CORINFO_METHOD_INFO * methInfo)
7379 {
7380     CONTRACTL {
7381         SO_TOLERANT;
7382         THROWS;
7383         GC_TRIGGERS;
7384         MODE_PREEMPTIVE;
7385     } CONTRACTL_END;
7386
7387     bool result = false;
7388
7389     JIT_TO_EE_TRANSITION();
7390
7391     MethodDesc * ftn = GetMethod(ftnHnd);
7392
7393     if (!ftn->IsDynamicMethod() && (!ftn->IsIL() || !ftn->GetRVA() || ftn->IsWrapperStub()))
7394     {
7395     /* Return false if not IL or has no code */
7396         result = false;
7397     }
7398     else
7399     {
7400         /* Get the IL header */
7401         /* <REVISIT_TODO>TODO: canInline already did validation, however, we do it again
7402            here because NGEN uses this function without calling canInline
7403            It would be nice to avoid this redundancy </REVISIT_TODO>*/
7404         Module* pModule = ftn->GetModule();
7405
7406         bool    verify = !Security::CanSkipVerification(ftn);
7407
7408         if (ftn->IsDynamicMethod())
7409         {
7410             getMethodInfoHelper(ftn, ftnHnd, NULL, methInfo);
7411         }
7412         else
7413         {
7414             COR_ILMETHOD_DECODER::DecoderStatus status = COR_ILMETHOD_DECODER::SUCCESS;
7415             COR_ILMETHOD_DECODER header(ftn->GetILHeader(TRUE), ftn->GetMDImport(), verify ? &status : NULL);
7416
7417             // If we get a verification error then we try to demand SkipVerification for the module
7418             if (status == COR_ILMETHOD_DECODER::VERIFICATION_ERROR &&
7419                 Security::CanSkipVerification(pModule->GetDomainAssembly()))
7420             {
7421                 status = COR_ILMETHOD_DECODER::SUCCESS;
7422             }
7423
7424             if (status != COR_ILMETHOD_DECODER::SUCCESS)
7425             {
7426                 if (status == COR_ILMETHOD_DECODER::VERIFICATION_ERROR)
7427                 {
7428                     // Throw a verification HR
7429                     COMPlusThrowHR(COR_E_VERIFICATION);
7430                 }
7431                 else
7432                 {
7433                     COMPlusThrowHR(COR_E_BADIMAGEFORMAT, BFA_BAD_IL);
7434                 }
7435             }
7436
7437             getMethodInfoHelper(ftn, ftnHnd, &header, methInfo);
7438         }
7439
7440         LOG((LF_JIT, LL_INFO100000, "Getting method info (possible inline) %s::%s%s\n",
7441             ftn->m_pszDebugClassName, ftn->m_pszDebugMethodName, ftn->m_pszDebugMethodSignature));
7442
7443         result = true;
7444     }
7445
7446     EE_TO_JIT_TRANSITION();
7447
7448     return result;
7449 }
7450
7451 #ifdef _DEBUG
7452
7453 /************************************************************************
7454     Return true when ftn contains a local of type CLASS__STACKCRAWMARK
7455 */
7456
7457 bool containsStackCrawlMarkLocal(MethodDesc* ftn)
7458 {
7459     STANDARD_VM_CONTRACT;
7460     
7461     COR_ILMETHOD* ilHeader = ftn->GetILHeader();
7462     _ASSERTE(ilHeader);
7463
7464     COR_ILMETHOD_DECODER header(ilHeader, ftn->GetMDImport(), NULL);
7465
7466     if (header.LocalVarSig == NULL)
7467         return NULL;
7468
7469     SigPointer ptr(header.LocalVarSig, header.cbLocalVarSig);
7470
7471     IfFailThrow(ptr.GetData(NULL)); // IMAGE_CEE_CS_CALLCONV_LOCAL_SIG
7472
7473     ULONG numLocals;
7474     IfFailThrow(ptr.GetData(&numLocals));
7475
7476     for(ULONG i = 0; i < numLocals; i++)
7477     {
7478         CorElementType eType;
7479         IfFailThrow(ptr.PeekElemType(&eType));
7480         if (eType != ELEMENT_TYPE_VALUETYPE)
7481         {
7482             IfFailThrow(ptr.SkipExactlyOne());
7483             continue;
7484         }
7485
7486         IfFailThrow(ptr.GetElemType(NULL));
7487
7488         mdToken token;
7489         IfFailThrow(ptr.GetToken(&token));
7490
7491         // We are inside mscorlib - simple token match is sufficient
7492         if (token == MscorlibBinder::GetClass(CLASS__STACKCRAWMARK)->GetCl())
7493             return TRUE;
7494     }
7495
7496     return FALSE;
7497 }
7498
7499 #endif
7500
7501 /*************************************************************
7502  * Check if the caller and calle are in the same assembly
7503  * i.e. do not inline across assemblies
7504  *************************************************************/
7505
7506 CorInfoInline CEEInfo::canInline (CORINFO_METHOD_HANDLE hCaller,
7507                                   CORINFO_METHOD_HANDLE hCallee,
7508                                   DWORD*                pRestrictions)
7509 {
7510     CONTRACTL {
7511         SO_TOLERANT;
7512         THROWS;
7513         GC_TRIGGERS;
7514         MODE_PREEMPTIVE;
7515     } CONTRACTL_END;
7516
7517     CorInfoInline result = INLINE_PASS;  // By default we pass.  
7518                                          // Do not set pass in the rest of the method.
7519     DWORD         dwRestrictions = 0;    // By default, no restrictions
7520     const char *  szFailReason = NULL;   // for reportInlineDecision
7521
7522     JIT_TO_EE_TRANSITION();
7523
7524     // This does not work in the multi-threaded case
7525 #if 0
7526     // Caller should check this condition first
7527     _ASSERTE(!(CORINFO_FLG_DONT_INLINE & getMethodAttribsInternal(hCallee)));
7528 #endif
7529
7530     MethodDesc* pCaller = GetMethod(hCaller);
7531     MethodDesc* pCallee = GetMethod(hCallee);
7532
7533     if (pCallee->IsNoMetadata())
7534     {
7535         result = INLINE_FAIL;
7536         szFailReason = "Inlinee is NoMetadata";
7537         goto exit;
7538     }
7539
7540 #ifdef DEBUGGING_SUPPORTED
7541
7542     // If the callee wants debuggable code, don't allow it to be inlined
7543
7544     {
7545         // Combining the next two lines, and eliminating jitDebuggerFlags, leads to bad codegen in x86 Release builds using Visual C++ 19.00.24215.1.
7546         CORJIT_FLAGS jitDebuggerFlags = GetDebuggerCompileFlags(pCallee->GetModule(), CORJIT_FLAGS());
7547         if (jitDebuggerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE))
7548         {
7549             result = INLINE_NEVER;
7550             szFailReason = "Inlinee is debuggable";
7551             goto exit;
7552         }
7553     }
7554 #endif
7555
7556     // The orginal caller is the current method
7557     MethodDesc *  pOrigCaller;
7558     pOrigCaller = m_pMethodBeingCompiled;
7559     Module *      pOrigCallerModule;
7560     pOrigCallerModule = pOrigCaller->GetLoaderModule();
7561
7562     // Prevent recursive compiling/inlining/verifying
7563     if (pOrigCaller != pCallee)
7564     {
7565         //  The Inliner may not do code verification.
7566         //  So never inline anything that is unverifiable / bad code.
7567         if (!Security::CanSkipVerification(pCallee))
7568         {
7569             // Inlinee needs to be verifiable
7570             if (!pCallee->IsVerifiable())
7571             {
7572                 result = INLINE_NEVER;
7573                 szFailReason = "Inlinee is not verifiable";
7574                 goto exit;
7575             }
7576         }
7577     }
7578
7579     // We check this here as the call to MethodDesc::IsVerifiable()
7580     // may set CORINFO_FLG_DONT_INLINE.
7581     if (pCallee->IsNotInline()) 
7582     {
7583         result = INLINE_NEVER;
7584         szFailReason = "Inlinee is marked as no inline";
7585         goto exit;
7586     }
7587
7588     // Also check to see if the method requires a security object.  This means they call demand and
7589     // shouldn't be inlined.
7590     if (IsMdRequireSecObject(pCallee->GetAttrs())) 
7591     {
7592         result = INLINE_NEVER;
7593         szFailReason = "Inlinee requires a security object (or contains StackCrawlMark)";
7594         goto exit;
7595     }
7596
7597     // If the method is MethodImpl'd by another method within the same type, then we have
7598     // an issue that the importer will import the wrong body. In this case, we'll just
7599     // disallow inlining because getFunctionEntryPoint will do the right thing.
7600     {
7601         MethodDesc  *pMDDecl = pCallee;
7602         MethodTable *pMT     = pMDDecl->GetMethodTable();
7603         MethodDesc  *pMDImpl = pMT->MapMethodDeclToMethodImpl(pMDDecl);
7604
7605         if (pMDDecl != pMDImpl)
7606         {
7607             result = INLINE_NEVER;
7608             szFailReason = "Inlinee is MethodImpl'd by another method within the same type";
7609             goto exit;
7610         }
7611     }
7612
7613     //
7614     // Perform the Cross-Assembly inlining checks
7615     // 
7616     {
7617         Module *    pCalleeModule   = pCallee->GetModule();
7618
7619 #ifdef FEATURE_PREJIT
7620         Assembly *  pCalleeAssembly = pCalleeModule->GetAssembly();
7621
7622 #ifdef _DEBUG
7623         //
7624         // Make sure that all methods with StackCrawlMark are marked as IsMdRequireSecObject
7625         //
7626         if (pCalleeAssembly->IsSystem())
7627         {
7628             _ASSERTE(!containsStackCrawlMarkLocal(pCallee));
7629         }
7630 #endif
7631
7632         // To allow for servicing of Ngen images we want to disable most 
7633         // Cross-Assembly inlining except for the cases that we explicitly allow.
7634         // 
7635         if (IsCompilingForNGen())
7636         {
7637             // This is an canInline call at Ngen time 
7638             //
7639             //
7640             Assembly *  pOrigCallerAssembly = pOrigCallerModule->GetAssembly();
7641
7642             if (pCalleeAssembly == pOrigCallerAssembly)
7643             {
7644                 // Within the same assembly
7645                 // we can freely inline with no restrictions
7646             }
7647             else
7648             {
7649 #ifdef FEATURE_READYTORUN_COMPILER
7650                 // No inlinining for version resilient code except if in the same version bubble
7651                 // If this condition changes, please make the corresponding change
7652                 // in getCallInfo, too.
7653                 if (IsReadyToRunCompilation() &&
7654                     !isVerifyOnly() &&
7655                     !IsInSameVersionBubble(pCaller, pCallee)
7656                    )
7657                 {
7658                     result = INLINE_NEVER;
7659                     szFailReason = "Cross-module inlining in version resilient code";
7660                     goto exit;
7661                 }
7662 #endif
7663             }
7664         }
7665 #endif  // FEATURE_PREJIT
7666
7667         // TODO: We can probably be smarter here if the caller is jitted, as we will
7668         // know for sure if the inlinee has really no string interning active (currently
7669         // it's only on in the ngen case (besides requiring the attribute)), but this is getting
7670         // too subtle. Will only do if somebody screams about it, as bugs here are going to
7671         // be tough to find
7672         if ((pOrigCallerModule != pCalleeModule) &&  pCalleeModule->IsNoStringInterning())
7673         {
7674             dwRestrictions |= INLINE_NO_CALLEE_LDSTR;
7675         }
7676
7677         // The remoting interception can be skipped only if the call is on same this pointer
7678         if (pCallee->MayBeRemotingIntercepted())
7679         {
7680             dwRestrictions |= INLINE_SAME_THIS;
7681         }
7682     }
7683
7684 #ifdef PROFILING_SUPPORTED
7685     if (CORProfilerPresent())
7686     {
7687         // #rejit
7688         // 
7689         // See if rejit-specific flags for the caller disable inlining
7690         if ((ReJitManager::GetCurrentReJitFlags(pCaller) &
7691             COR_PRF_CODEGEN_DISABLE_INLINING) != 0)
7692         {
7693             result = INLINE_FAIL;
7694             szFailReason = "ReJIT request disabled inlining from caller";
7695             goto exit;
7696         }
7697
7698         // If the profiler has set a mask preventing inlining, always return
7699         // false to the jit.
7700         if (CORProfilerDisableInlining())
7701         {
7702             result = INLINE_FAIL;
7703             szFailReason = "Profiler disabled inlining globally";
7704             goto exit;
7705         }
7706
7707         // If the profiler wishes to be notified of JIT events and the result from
7708         // the above tests will cause a function to be inlined, we need to tell the
7709         // profiler that this inlining is going to take place, and give them a
7710         // chance to prevent it.
7711         {
7712             BEGIN_PIN_PROFILER(CORProfilerTrackJITInfo());
7713             if (pCaller->IsILStub() || pCallee->IsILStub())
7714             {
7715                 // do nothing
7716             }
7717             else
7718             {
7719                 BOOL fShouldInline;
7720
7721                 HRESULT hr = g_profControlBlock.pProfInterface->JITInlining(
7722                     (FunctionID)pCaller,
7723                     (FunctionID)pCallee,
7724                     &fShouldInline);
7725
7726                 if (SUCCEEDED(hr) && !fShouldInline)
7727                 {
7728                     result = INLINE_FAIL;
7729                     szFailReason = "Profiler disabled inlining locally";
7730                     goto exit;
7731                 }
7732             }
7733             END_PIN_PROFILER();
7734         }
7735     }
7736 #endif // PROFILING_SUPPORTED
7737
7738
7739 #ifdef PROFILING_SUPPORTED
7740     if (CORProfilerPresent())
7741     {
7742         // #rejit
7743         // 
7744         // See if rejit-specific flags for the caller disable inlining
7745         if ((ReJitManager::GetCurrentReJitFlags(pCaller) &
7746             COR_PRF_CODEGEN_DISABLE_INLINING) != 0)
7747         {
7748             result = INLINE_FAIL;
7749             szFailReason = "ReJIT request disabled inlining from caller";
7750             goto exit;
7751         }
7752
7753         // If the profiler has set a mask preventing inlining, always return
7754         // false to the jit.
7755         if (CORProfilerDisableInlining())
7756         {
7757             result = INLINE_FAIL;
7758             szFailReason = "Profiler disabled inlining globally";
7759             goto exit;
7760         }
7761
7762         // If the profiler wishes to be notified of JIT events and the result from
7763         // the above tests will cause a function to be inlined, we need to tell the
7764         // profiler that this inlining is going to take place, and give them a
7765         // chance to prevent it.
7766         {
7767             BEGIN_PIN_PROFILER(CORProfilerTrackJITInfo());
7768             if (pCaller->IsILStub() || pCallee->IsILStub())
7769             {
7770                 // do nothing
7771             }
7772             else
7773             {
7774                 BOOL fShouldInline;
7775
7776                 HRESULT hr = g_profControlBlock.pProfInterface->JITInlining(
7777                     (FunctionID)pCaller,
7778                     (FunctionID)pCallee,
7779                     &fShouldInline);
7780
7781                 if (SUCCEEDED(hr) && !fShouldInline)
7782                 {
7783                     result = INLINE_FAIL;
7784                     szFailReason = "Profiler disabled inlining locally";
7785                     goto exit;
7786                 }
7787             }
7788             END_PIN_PROFILER();
7789         }
7790     }
7791 #endif // PROFILING_SUPPORTED
7792
7793 exit: ;
7794
7795     EE_TO_JIT_TRANSITION();
7796
7797     if (result == INLINE_PASS && dwRestrictions)
7798     {
7799         if (pRestrictions)
7800         {
7801             *pRestrictions = dwRestrictions;
7802         }
7803         else
7804         {
7805             // If the jitter didn't want to know about restrictions, it shouldn't be inlining
7806             result = INLINE_FAIL;
7807             szFailReason = "Inlinee has restrictions the JIT doesn't want";
7808         }
7809     }
7810     else
7811     {
7812         if (pRestrictions)
7813         {
7814             // Denied inlining, makes no sense to pass out restrictions,
7815             *pRestrictions = 0;
7816         }
7817     }
7818
7819     if (dontInline(result))
7820     {
7821         // If you hit this assert, it means you added a new way to prevent inlining
7822         // without documenting it for ETW!
7823         _ASSERTE(szFailReason != NULL);
7824         reportInliningDecision(hCaller, hCallee, result, szFailReason);
7825     }
7826
7827     return result;
7828 }
7829
7830 void CEEInfo::reportInliningDecision (CORINFO_METHOD_HANDLE inlinerHnd,
7831                                       CORINFO_METHOD_HANDLE inlineeHnd,
7832                                       CorInfoInline inlineResult,
7833                                       const char * reason)
7834 {
7835     STATIC_CONTRACT_THROWS;
7836     STATIC_CONTRACT_GC_TRIGGERS;
7837     STATIC_CONTRACT_SO_TOLERANT;
7838
7839     JIT_TO_EE_TRANSITION();
7840
7841 #ifdef _DEBUG
7842     if (LoggingOn(LF_JIT, LL_INFO100000))
7843     {
7844         SString currentMethodName;
7845         currentMethodName.AppendUTF8(m_pMethodBeingCompiled->GetModule_NoLogging()->GetFile()->GetSimpleName());
7846         currentMethodName.Append(L'/');
7847         TypeString::AppendMethodInternal(currentMethodName, m_pMethodBeingCompiled, TypeString::FormatBasic);
7848
7849         SString inlineeMethodName;
7850         if (GetMethod(inlineeHnd))
7851         {
7852             inlineeMethodName.AppendUTF8(GetMethod(inlineeHnd)->GetModule_NoLogging()->GetFile()->GetSimpleName());
7853             inlineeMethodName.Append(L'/');
7854             TypeString::AppendMethodInternal(inlineeMethodName, GetMethod(inlineeHnd), TypeString::FormatBasic);
7855         }
7856         else
7857         {
7858             inlineeMethodName.AppendASCII( "<null>" );
7859         }
7860
7861         SString inlinerMethodName;
7862         if (GetMethod(inlinerHnd))
7863         {
7864             inlinerMethodName.AppendUTF8(GetMethod(inlinerHnd)->GetModule_NoLogging()->GetFile()->GetSimpleName());
7865             inlinerMethodName.Append(L'/');
7866             TypeString::AppendMethodInternal(inlinerMethodName, GetMethod(inlinerHnd), TypeString::FormatBasic);
7867         }
7868         else
7869         {
7870             inlinerMethodName.AppendASCII("<null>");
7871         }
7872
7873         if (dontInline(inlineResult))
7874         {
7875             LOG((LF_JIT, LL_INFO100000,
7876                  "While compiling '%S', inline of '%S' into '%S' failed because: '%s'.\n",
7877                  currentMethodName.GetUnicode(), inlineeMethodName.GetUnicode(),
7878                  inlinerMethodName.GetUnicode(), reason));
7879         }
7880         else
7881         {
7882             LOG((LF_JIT, LL_INFO100000, "While compiling '%S', inline of '%S' into '%S' succeeded.\n",
7883                  currentMethodName.GetUnicode(), inlineeMethodName.GetUnicode(),
7884                  inlinerMethodName.GetUnicode()));
7885
7886         }
7887     }
7888 #endif //_DEBUG
7889
7890     //I'm gonna duplicate this code because the format is slightly different.  And LoggingOn is debug only.
7891     if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, 
7892                                      TRACE_LEVEL_VERBOSE,
7893                                      CLR_JITTRACING_KEYWORD))
7894     {
7895         SString methodBeingCompiledNames[3];
7896         SString inlinerNames[3];
7897         SString inlineeNames[3];
7898         MethodDesc * methodBeingCompiled = m_pMethodBeingCompiled;
7899 #define GMI(pMD, strArray) \
7900         do { \
7901             if (pMD) { \
7902                 (pMD)->GetMethodInfo((strArray)[0], (strArray)[1], (strArray)[2]); \
7903             } else {  \
7904                 (strArray)[0].Set(W("<null>")); \
7905                 (strArray)[1].Set(W("<null>")); \
7906                 (strArray)[2].Set(W("<null>")); \
7907             } } while (0)
7908
7909         GMI(methodBeingCompiled, methodBeingCompiledNames);
7910         GMI(GetMethod(inlinerHnd), inlinerNames);
7911         GMI(GetMethod(inlineeHnd), inlineeNames);
7912 #undef GMI
7913         if (dontInline(inlineResult))
7914         {
7915             const char * str = (reason ? reason : "");
7916
7917             FireEtwMethodJitInliningFailed(methodBeingCompiledNames[0].GetUnicode(),
7918                                            methodBeingCompiledNames[1].GetUnicode(),
7919                                            methodBeingCompiledNames[2].GetUnicode(),
7920                                            inlinerNames[0].GetUnicode(),
7921                                            inlinerNames[1].GetUnicode(),
7922                                            inlinerNames[2].GetUnicode(),
7923                                            inlineeNames[0].GetUnicode(),
7924                                            inlineeNames[1].GetUnicode(),
7925                                            inlineeNames[2].GetUnicode(),
7926                                            inlineResult == INLINE_NEVER,
7927                                            str,
7928                                            GetClrInstanceId());
7929         }
7930         else
7931         {
7932             FireEtwMethodJitInliningSucceeded(methodBeingCompiledNames[0].GetUnicode(),
7933                                               methodBeingCompiledNames[1].GetUnicode(),
7934                                               methodBeingCompiledNames[2].GetUnicode(),
7935                                               inlinerNames[0].GetUnicode(),
7936                                               inlinerNames[1].GetUnicode(),
7937                                               inlinerNames[2].GetUnicode(),
7938                                               inlineeNames[0].GetUnicode(),
7939                                               inlineeNames[1].GetUnicode(),
7940                                               inlineeNames[2].GetUnicode(),
7941                                               GetClrInstanceId());
7942         }
7943
7944     }
7945
7946     EE_TO_JIT_TRANSITION();
7947 }
7948
7949
7950 /*************************************************************
7951 This loads the (formal) declared constraints on the class and method type parameters, 
7952 and detects (but does not itself reject) circularities among the class type parameters 
7953 and (separately) method type parameters. 
7954
7955 It must be called whenever we verify a typical method, ie any method (generic or
7956 nongeneric) in a typical class. It must be called for non-generic methods too, 
7957 because their bodies may still mention class type parameters which will need to
7958 have their formal constraints loaded in order to perform type compatibility tests.
7959
7960 We have to rule out cycles like "C<U,T> where T:U, U:T" only to avoid looping 
7961 in the verifier (ie the T.CanCast(A) would loop calling U.CanCast(A) then 
7962 T.CanCastTo(A) etc.). Since the JIT only tries to walk the hierarchy from a type
7963 a parameter when verifying, it should be safe to JIT unverified, but trusted, 
7964 instantiations even in the presence of cycle constraints.
7965 @TODO: It should be possible (and easy) to detect cycles much earlier on by
7966 directly inspecting the metadata. All you have to do is check that, for each
7967 of the n type parameters to a class or method there is no path of length n 
7968 obtained by following naked type parameter constraints of the same kind. 
7969 This can be detected by looking directly at metadata, without actually loading
7970 the typehandles for the naked type parameters.
7971  *************************************************************/
7972
7973 void CEEInfo::initConstraintsForVerification(CORINFO_METHOD_HANDLE hMethod,
7974                                              BOOL *pfHasCircularClassConstraints,
7975                                              BOOL *pfHasCircularMethodConstraints)
7976 {
7977     CONTRACTL {
7978         SO_TOLERANT;
7979         THROWS;
7980         GC_TRIGGERS;
7981         MODE_PREEMPTIVE;
7982         PRECONDITION(CheckPointer(pfHasCircularClassConstraints));
7983         PRECONDITION(CheckPointer(pfHasCircularMethodConstraints));
7984     } CONTRACTL_END;
7985
7986     *pfHasCircularClassConstraints  = FALSE;
7987     *pfHasCircularMethodConstraints = FALSE;
7988
7989     JIT_TO_EE_TRANSITION();
7990
7991     MethodDesc* pMethod = GetMethod(hMethod);
7992     if (pMethod->IsTypicalMethodDefinition())
7993     {
7994         // Force a load of the constraints on the type parameters, detecting cyclic bounds
7995         pMethod->LoadConstraintsForTypicalMethodDefinition(pfHasCircularClassConstraints,pfHasCircularMethodConstraints);
7996     }
7997
7998     EE_TO_JIT_TRANSITION();
7999 }
8000
8001 /*************************************************************
8002  * Check if a method to be compiled is an instantiation
8003  * of generic code that has already been verified.
8004  * Three possible return values (see corinfo.h)
8005  *************************************************************/
8006
8007 CorInfoInstantiationVerification  
8008     CEEInfo::isInstantiationOfVerifiedGeneric(CORINFO_METHOD_HANDLE hMethod)
8009 {
8010     CONTRACTL {
8011         SO_TOLERANT;
8012         THROWS;
8013         GC_TRIGGERS;
8014         MODE_PREEMPTIVE;
8015     } CONTRACTL_END;
8016
8017     CorInfoInstantiationVerification result = INSTVER_NOT_INSTANTIATION;
8018
8019     JIT_TO_EE_TRANSITION();
8020
8021     MethodDesc * pMethod = GetMethod(hMethod);
8022
8023     if (!(pMethod->HasClassOrMethodInstantiation()))
8024     {
8025         result = INSTVER_NOT_INSTANTIATION;
8026         goto exit;
8027     }
8028
8029     if (pMethod->IsTypicalMethodDefinition())
8030     {
8031         result = INSTVER_NOT_INSTANTIATION;
8032         goto exit;
8033     }
8034
8035     result = pMethod->IsVerifiable() ? INSTVER_GENERIC_PASSED_VERIFICATION
8036                                      : INSTVER_GENERIC_FAILED_VERIFICATION;
8037
8038  exit: ;
8039
8040     EE_TO_JIT_TRANSITION();
8041
8042     return result;
8043 }
8044
8045 /*************************************************************
8046  * Similar to above, but perform check for tail call
8047  * eligibility. The callee can be passed as NULL if not known
8048  * (calli and callvirt).
8049  *************************************************************/
8050
8051 bool CEEInfo::canTailCall (CORINFO_METHOD_HANDLE hCaller,
8052                            CORINFO_METHOD_HANDLE hDeclaredCallee,
8053                            CORINFO_METHOD_HANDLE hExactCallee,
8054                            bool fIsTailPrefix)
8055 {
8056     CONTRACTL {
8057         SO_TOLERANT;
8058         THROWS;
8059         GC_TRIGGERS;
8060         MODE_PREEMPTIVE;
8061     } CONTRACTL_END;
8062
8063     bool result = false;
8064     const char * szFailReason = NULL;
8065
8066     JIT_TO_EE_TRANSITION();
8067
8068     // See comments in canInline above.
8069
8070     MethodDesc* pCaller = GetMethod(hCaller);
8071     MethodDesc* pDeclaredCallee = GetMethod(hDeclaredCallee);
8072     MethodDesc* pExactCallee = GetMethod(hExactCallee);
8073
8074     _ASSERTE(pCaller->GetModule());
8075     _ASSERTE(pCaller->GetModule()->GetClassLoader());
8076
8077     _ASSERTE((pExactCallee == NULL) || pExactCallee->GetModule());
8078     _ASSERTE((pExactCallee == NULL) || pExactCallee->GetModule()->GetClassLoader());
8079
8080     // If the caller is the static constructor (.cctor) of a class which has a ComImport base class
8081     // somewhere up the class hierarchy, then we cannot make the call into a tailcall.  See
8082     // RegisterObjectCreationCallback() in ExtensibleClassFactory.cpp for more information.
8083     if (pCaller->IsClassConstructor() &&
8084         pCaller->GetMethodTable()->IsComObjectType())
8085     {
8086         result = false;
8087         szFailReason = "Caller is  ComImport .cctor";
8088         goto exit;
8089     }
8090
8091     // TailCalls will throw off security stackwalking logic when there is a declarative Assert
8092     // Note that this check will also include declarative demands.  It's OK to do a tailcall in
8093     // those cases, but we currently don't have a way to check only for declarative Asserts.
8094     if (pCaller->IsInterceptedForDeclSecurity())
8095     {
8096         result = false;
8097         szFailReason = "Caller has declarative security";
8098         goto exit;
8099     }
8100
8101     if (!fIsTailPrefix)        
8102     {
8103         mdMethodDef callerToken = pCaller->GetMemberDef();
8104
8105         // We don't want to tailcall the entrypoint for an application; JIT64 will sometimes
8106         // do this for simple entrypoints and it results in a rather confusing debugging 
8107         // experience.
8108         if (callerToken == pCaller->GetModule()->GetEntryPointToken())
8109         {
8110             result = false;
8111             szFailReason = "Caller is the entry point";
8112             goto exit;
8113         }
8114
8115         if (!pCaller->IsNoMetadata())
8116         {
8117             // Do not tailcall from methods that are marked as noinline (people often use no-inline
8118             // to mean "I want to always see this method in stacktrace")
8119             DWORD dwImplFlags = 0;
8120             IfFailThrow(pCaller->GetMDImport()->GetMethodImplProps(callerToken, NULL, &dwImplFlags));
8121             
8122             if (IsMiNoInlining(dwImplFlags))
8123             {
8124                 result = false;
8125                 szFailReason = "Caller is marked as no inline";
8126                 goto exit;
8127             }
8128         }
8129
8130         // Methods with StackCrawlMark depend on finding their caller on the stack.
8131         // If we tail call one of these guys, they get confused.  For lack of
8132         // a better way of identifying them, we use DynamicSecurity attribute to identify
8133         // them. We have an assert in canInline that ensures all StackCrawlMark
8134         // methods are appropriately marked.
8135         //
8136         if ((pExactCallee != NULL) && IsMdRequireSecObject(pExactCallee->GetAttrs()))
8137         {
8138             result = false;
8139             szFailReason = "Callee might have a StackCrawlMark.LookForMyCaller";
8140             goto exit;
8141         }
8142     }
8143
8144
8145     result = true;
8146
8147 exit: ;
8148
8149     EE_TO_JIT_TRANSITION();
8150
8151     if (!result)
8152     {
8153         // If you hit this assert, it means you added a new way to prevent tail calls
8154         // without documenting it for ETW!
8155         _ASSERTE(szFailReason != NULL);
8156         reportTailCallDecision(hCaller, hExactCallee, fIsTailPrefix, TAILCALL_FAIL, szFailReason);
8157     }
8158
8159     return result;
8160 }
8161
8162 void CEEInfo::reportTailCallDecision (CORINFO_METHOD_HANDLE callerHnd,
8163                                      CORINFO_METHOD_HANDLE calleeHnd,
8164                                      bool fIsTailPrefix,
8165                                      CorInfoTailCall tailCallResult,
8166                                      const char * reason)
8167 {
8168     STATIC_CONTRACT_THROWS;
8169     STATIC_CONTRACT_GC_TRIGGERS;
8170     STATIC_CONTRACT_SO_TOLERANT;
8171
8172     JIT_TO_EE_TRANSITION();
8173
8174     //put code here.  Make sure to report the method being compiled in addition to inliner and inlinee.
8175 #ifdef _DEBUG
8176     if (LoggingOn(LF_JIT, LL_INFO100000))
8177     {
8178         SString currentMethodName;
8179         TypeString::AppendMethodInternal(currentMethodName, m_pMethodBeingCompiled,
8180                                          TypeString::FormatBasic);
8181
8182         SString calleeMethodName;
8183         if (GetMethod(calleeHnd))
8184         {
8185             TypeString::AppendMethodInternal(calleeMethodName, GetMethod(calleeHnd),
8186                                              TypeString::FormatBasic);
8187         }
8188         else
8189         {
8190             calleeMethodName.AppendASCII( "<null>" );
8191         }
8192
8193         SString callerMethodName;
8194         if (GetMethod(callerHnd))
8195         {
8196             TypeString::AppendMethodInternal(callerMethodName, GetMethod(callerHnd),
8197                                              TypeString::FormatBasic);
8198         }
8199         else
8200         {
8201             callerMethodName.AppendASCII( "<null>" );
8202         }
8203         if (tailCallResult == TAILCALL_FAIL)
8204         {
8205             LOG((LF_JIT, LL_INFO100000,
8206                  "While compiling '%S', %Splicit tail call from '%S' to '%S' failed because: '%s'.\n",
8207                  currentMethodName.GetUnicode(), fIsTailPrefix ? W("ex") : W("im"),
8208                  callerMethodName.GetUnicode(), calleeMethodName.GetUnicode(), reason));
8209         }
8210         else
8211         {
8212             static const char * const tailCallType[] = {
8213                 "optimized tail call", "recursive loop", "helper assisted tailcall"
8214             };
8215             _ASSERTE(tailCallResult >= 0 && (size_t)tailCallResult < sizeof(tailCallType) / sizeof(tailCallType[0]));
8216             LOG((LF_JIT, LL_INFO100000,
8217                  "While compiling '%S', %Splicit tail call from '%S' to '%S' generated as a %s.\n",
8218                  currentMethodName.GetUnicode(), fIsTailPrefix ? W("ex") : W("im"),
8219                  callerMethodName.GetUnicode(), calleeMethodName.GetUnicode(), tailCallType[tailCallResult]));
8220
8221         }
8222     }
8223 #endif //_DEBUG
8224
8225     // I'm gonna duplicate this code because the format is slightly different.  And LoggingOn is debug only.
8226     if (ETW_TRACING_CATEGORY_ENABLED(MICROSOFT_WINDOWS_DOTNETRUNTIME_PROVIDER_Context, 
8227                                      TRACE_LEVEL_VERBOSE,
8228                                      CLR_JITTRACING_KEYWORD))
8229     {
8230         SString methodBeingCompiledNames[3];
8231         SString callerNames[3];
8232         SString calleeNames[3];
8233         MethodDesc * methodBeingCompiled = m_pMethodBeingCompiled;
8234 #define GMI(pMD, strArray) \
8235         do { \
8236             if (pMD) { \
8237                 (pMD)->GetMethodInfo((strArray)[0], (strArray)[1], (strArray)[2]); \
8238             } else {  \
8239                 (strArray)[0].Set(W("<null>")); \
8240                 (strArray)[1].Set(W("<null>")); \
8241                 (strArray)[2].Set(W("<null>")); \
8242             } } while (0)
8243
8244         GMI(methodBeingCompiled, methodBeingCompiledNames);
8245         GMI(GetMethod(callerHnd), callerNames);
8246         GMI(GetMethod(calleeHnd), calleeNames);
8247 #undef GMI
8248         if (tailCallResult == TAILCALL_FAIL)
8249         {
8250             const char * str = (reason ? reason : "");
8251
8252             FireEtwMethodJitTailCallFailed(methodBeingCompiledNames[0].GetUnicode(),
8253                                            methodBeingCompiledNames[1].GetUnicode(),
8254                                            methodBeingCompiledNames[2].GetUnicode(),
8255                                            callerNames[0].GetUnicode(),
8256                                            callerNames[1].GetUnicode(),
8257                                            callerNames[2].GetUnicode(),
8258                                            calleeNames[0].GetUnicode(),
8259                                            calleeNames[1].GetUnicode(),
8260                                            calleeNames[2].GetUnicode(),
8261                                            fIsTailPrefix,
8262                                            str,
8263                                            GetClrInstanceId());
8264         }
8265         else
8266         {
8267             FireEtwMethodJitTailCallSucceeded(methodBeingCompiledNames[0].GetUnicode(),
8268                                               methodBeingCompiledNames[1].GetUnicode(),
8269                                               methodBeingCompiledNames[2].GetUnicode(),
8270                                               callerNames[0].GetUnicode(),
8271                                               callerNames[1].GetUnicode(),
8272                                               callerNames[2].GetUnicode(),
8273                                               calleeNames[0].GetUnicode(),
8274                                               calleeNames[1].GetUnicode(),
8275                                               calleeNames[2].GetUnicode(),
8276                                               fIsTailPrefix,
8277                                               tailCallResult,
8278                                               GetClrInstanceId());
8279         }
8280
8281     }
8282
8283
8284     EE_TO_JIT_TRANSITION();
8285 }
8286
8287 void CEEInfo::getEHinfoHelper(
8288     CORINFO_METHOD_HANDLE   ftnHnd,
8289     unsigned                EHnumber,
8290     CORINFO_EH_CLAUSE*      clause,
8291     COR_ILMETHOD_DECODER*   pILHeader)
8292 {
8293     STANDARD_VM_CONTRACT;
8294
8295     _ASSERTE(CheckPointer(pILHeader->EH));
8296     _ASSERTE(EHnumber < pILHeader->EH->EHCount());
8297
8298     COR_ILMETHOD_SECT_EH_CLAUSE_FAT ehClause;
8299     const COR_ILMETHOD_SECT_EH_CLAUSE_FAT* ehInfo;
8300     ehInfo = (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)pILHeader->EH->EHClause(EHnumber, &ehClause);
8301
8302     clause->Flags = (CORINFO_EH_CLAUSE_FLAGS)ehInfo->GetFlags();
8303     clause->TryOffset = ehInfo->GetTryOffset();
8304     clause->TryLength = ehInfo->GetTryLength();
8305     clause->HandlerOffset = ehInfo->GetHandlerOffset();
8306     clause->HandlerLength = ehInfo->GetHandlerLength();
8307     if ((clause->Flags & CORINFO_EH_CLAUSE_FILTER) == 0)
8308         clause->ClassToken = ehInfo->GetClassToken();
8309     else
8310         clause->FilterOffset = ehInfo->GetFilterOffset();
8311 }
8312
8313 /*********************************************************************/
8314 // get individual exception handler
8315 void CEEInfo::getEHinfo(
8316             CORINFO_METHOD_HANDLE ftnHnd,
8317             unsigned      EHnumber,
8318             CORINFO_EH_CLAUSE* clause)
8319 {
8320     CONTRACTL {
8321         SO_TOLERANT;
8322         THROWS;
8323         GC_TRIGGERS;
8324         MODE_PREEMPTIVE;
8325     } CONTRACTL_END;
8326
8327     JIT_TO_EE_TRANSITION();
8328
8329     MethodDesc * ftn          = GetMethod(ftnHnd);
8330
8331     if (IsDynamicMethodHandle(ftnHnd))
8332     {
8333         GetMethod(ftnHnd)->AsDynamicMethodDesc()->GetResolver()->GetEHInfo(EHnumber, clause);
8334     }
8335     else
8336     {
8337         COR_ILMETHOD_DECODER header(ftn->GetILHeader(TRUE), ftn->GetMDImport(), NULL);
8338         getEHinfoHelper(ftnHnd, EHnumber, clause, &header);
8339     }
8340
8341     EE_TO_JIT_TRANSITION();
8342 }
8343
8344 //---------------------------------------------------------------------------------------
8345 // 
8346 void 
8347 CEEInfo::getMethodSig(
8348     CORINFO_METHOD_HANDLE ftnHnd, 
8349     CORINFO_SIG_INFO *    sigRet, 
8350     CORINFO_CLASS_HANDLE  owner)
8351 {
8352     CONTRACTL {
8353         SO_TOLERANT;
8354         THROWS;
8355         GC_TRIGGERS;
8356         MODE_PREEMPTIVE;
8357     } CONTRACTL_END;
8358
8359     JIT_TO_EE_TRANSITION();
8360
8361     getMethodSigInternal(ftnHnd, sigRet, owner);
8362
8363     EE_TO_JIT_TRANSITION();
8364 }
8365
8366 //---------------------------------------------------------------------------------------
8367 // 
8368 void 
8369 CEEInfo::getMethodSigInternal(
8370     CORINFO_METHOD_HANDLE ftnHnd, 
8371     CORINFO_SIG_INFO *    sigRet, 
8372     CORINFO_CLASS_HANDLE  owner)
8373 {
8374     STANDARD_VM_CONTRACT;
8375
8376     MethodDesc * ftn = GetMethod(ftnHnd);
8377     
8378     PCCOR_SIGNATURE pSig = NULL;
8379     DWORD           cbSig = 0;
8380     ftn->GetSig(&pSig, &cbSig);
8381
8382     // Type parameters in the signature are instantiated
8383     // according to the class/method/array instantiation of ftnHnd and owner
8384     CEEInfo::ConvToJitSig(
8385         pSig, 
8386         cbSig, 
8387         GetScopeHandle(ftn), 
8388         mdTokenNil, 
8389         sigRet, 
8390         ftn, 
8391         false, 
8392         (TypeHandle)owner);
8393
8394     //@GENERICS:
8395     // Shared generic methods and shared methods on generic structs take an extra argument representing their instantiation
8396     if (ftn->RequiresInstArg())
8397     {
8398         sigRet->callConv = (CorInfoCallConv) (sigRet->callConv | CORINFO_CALLCONV_PARAMTYPE);
8399     }
8400
8401     // We want the calling convention bit to be consistant with the method attribute bit
8402     _ASSERTE( (IsMdStatic(ftn->GetAttrs()) == 0) == ((sigRet->callConv & CORINFO_CALLCONV_HASTHIS) != 0) );
8403 }
8404
8405 //---------------------------------------------------------------------------------------
8406 // 
8407 //@GENERICSVER: for a method desc in a typical instantiation of a generic class,
8408 // this will return the typical instantiation of the generic class,
8409 // but only provided type variables are never shared.
8410 // The JIT verifier relies on this behaviour to extract the typical class from an instantiated method's typical method handle.
8411 // 
8412 CORINFO_CLASS_HANDLE 
8413 CEEInfo::getMethodClass(
8414     CORINFO_METHOD_HANDLE methodHnd)
8415 {
8416     CONTRACTL {
8417         SO_TOLERANT;
8418         THROWS;
8419         GC_TRIGGERS;
8420         MODE_PREEMPTIVE;
8421     } CONTRACTL_END;
8422
8423     CORINFO_CLASS_HANDLE result = NULL;
8424
8425     JIT_TO_EE_TRANSITION();
8426
8427     MethodDesc* method = GetMethod(methodHnd);
8428
8429     if (method->IsDynamicMethod())
8430     {
8431         DynamicResolver::SecurityControlFlags securityControlFlags = DynamicResolver::Default;
8432         TypeHandle typeOwner;
8433
8434         DynamicResolver* pResolver = method->AsDynamicMethodDesc()->GetResolver();
8435         pResolver->GetJitContext(&securityControlFlags, &typeOwner);
8436             
8437         if (!typeOwner.IsNull() && (method == pResolver->GetDynamicMethod())) 
8438         {
8439             result = CORINFO_CLASS_HANDLE(typeOwner.AsPtr());
8440         }
8441     }
8442
8443     if (result == NULL)
8444     {
8445         TypeHandle th = TypeHandle(method->GetMethodTable());
8446
8447         result = CORINFO_CLASS_HANDLE(th.AsPtr());
8448     }
8449
8450     EE_TO_JIT_TRANSITION();
8451
8452     return result;
8453 }
8454
8455 /***********************************************************************/
8456 CORINFO_MODULE_HANDLE CEEInfo::getMethodModule (CORINFO_METHOD_HANDLE methodHnd)
8457 {
8458     CONTRACTL {
8459         SO_TOLERANT;
8460         NOTHROW;
8461         GC_NOTRIGGER;
8462         MODE_PREEMPTIVE;
8463     } CONTRACTL_END;
8464
8465     CORINFO_MODULE_HANDLE result = NULL;
8466
8467     JIT_TO_EE_TRANSITION_LEAF();
8468
8469     MethodDesc* method = GetMethod(methodHnd);
8470
8471     if (method->IsDynamicMethod())
8472     {
8473         // this should never be called, thus the assert, I don't know if the (non existent) caller
8474         // expects the Module or the scope
8475         UNREACHABLE();
8476     }
8477     else
8478     {
8479         result = (CORINFO_MODULE_HANDLE) method->GetModule();
8480     }
8481     
8482     EE_TO_JIT_TRANSITION_LEAF();
8483
8484     return result;
8485 }
8486
8487 /*********************************************************************/
8488 CorInfoIntrinsics CEEInfo::getIntrinsicID(CORINFO_METHOD_HANDLE methodHnd,
8489                                           bool * pMustExpand)
8490 {
8491     CONTRACTL {
8492         SO_TOLERANT;
8493         THROWS;
8494         GC_TRIGGERS;
8495         MODE_PREEMPTIVE;
8496     } CONTRACTL_END;
8497
8498     CorInfoIntrinsics result = CORINFO_INTRINSIC_Illegal;
8499
8500     JIT_TO_EE_TRANSITION();
8501
8502     if (pMustExpand != NULL)
8503     {
8504         *pMustExpand = false;
8505     }
8506
8507     MethodDesc* method = GetMethod(methodHnd);
8508
8509     if (method->IsArray())
8510     {
8511         ArrayMethodDesc * arrMethod = (ArrayMethodDesc *)method;
8512         result = arrMethod->GetIntrinsicID();
8513     }
8514     else
8515     if (method->IsFCall())
8516     {
8517         result = ECall::GetIntrinsicID(method);
8518     }
8519     else
8520     {
8521         MethodTable * pMT = method->GetMethodTable();
8522         if (pMT->GetModule()->IsSystem() && pMT->IsByRefLike())
8523         {
8524             if (pMT->HasSameTypeDefAs(g_pByReferenceClass))
8525             {
8526                 // ByReference<T> has just two methods: constructor and Value property
8527                 if (method->IsCtor())
8528                 {
8529                     result = CORINFO_INTRINSIC_ByReference_Ctor;
8530                 }
8531                 else
8532                 {
8533                     _ASSERTE(strcmp(method->GetName(), "get_Value") == 0);
8534                     result = CORINFO_INTRINSIC_ByReference_Value;
8535                 }
8536                 if (pMustExpand != nullptr)
8537                 {
8538                     *pMustExpand = true;
8539                 }
8540             }
8541             else if (pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__SPAN)))
8542             {
8543                 if (method->HasSameMethodDefAs(MscorlibBinder::GetMethod(METHOD__SPAN__GET_ITEM)))
8544                 {
8545                     result = CORINFO_INTRINSIC_Span_GetItem;
8546                 }
8547             }
8548             else if (pMT->HasSameTypeDefAs(MscorlibBinder::GetClass(CLASS__READONLY_SPAN)))
8549             {
8550                 if (method->HasSameMethodDefAs(MscorlibBinder::GetMethod(METHOD__READONLY_SPAN__GET_ITEM)))
8551                 {
8552                     result = CORINFO_INTRINSIC_ReadOnlySpan_GetItem;
8553                 }
8554             }
8555         }
8556     }
8557
8558     EE_TO_JIT_TRANSITION();
8559
8560     return result;
8561 }
8562
8563 /*********************************************************************/
8564 bool CEEInfo::isInSIMDModule(CORINFO_CLASS_HANDLE classHnd)
8565 {
8566 CONTRACTL {
8567         SO_TOLERANT;
8568         NOTHROW;
8569         GC_NOTRIGGER;
8570         MODE_PREEMPTIVE;
8571     } CONTRACTL_END;
8572
8573     bool result = false;
8574     JIT_TO_EE_TRANSITION_LEAF();
8575
8576     TypeHandle VMClsHnd(classHnd);
8577     if (VMClsHnd.GetMethodTable()->GetAssembly()->IsSIMDVectorAssembly())
8578     {
8579         result = true;
8580     }
8581     EE_TO_JIT_TRANSITION_LEAF();
8582
8583     return result;
8584 }
8585
8586 /*********************************************************************/
8587 void CEEInfo::getMethodVTableOffset (CORINFO_METHOD_HANDLE methodHnd,
8588                                      unsigned * pOffsetOfIndirection,
8589                                      unsigned * pOffsetAfterIndirection,
8590                                      unsigned * isRelative)
8591 {
8592     CONTRACTL {
8593         SO_TOLERANT;
8594         NOTHROW;
8595         GC_NOTRIGGER;
8596         MODE_PREEMPTIVE;
8597     } CONTRACTL_END;
8598
8599     JIT_TO_EE_TRANSITION_LEAF();
8600
8601     MethodDesc* method = GetMethod(methodHnd);
8602
8603     //@GENERICS: shouldn't be doing this for instantiated methods as they live elsewhere
8604     _ASSERTE(!method->HasMethodInstantiation());
8605
8606     _ASSERTE(MethodTable::GetVtableOffset() < 256);  // a rough sanity check
8607
8608     // better be in the vtable
8609     _ASSERTE(method->GetSlot() < method->GetMethodTable()->GetNumVirtuals());
8610
8611     *pOffsetOfIndirection = MethodTable::GetVtableOffset() + MethodTable::GetIndexOfVtableIndirection(method->GetSlot()) * sizeof(MethodTable::VTableIndir_t);
8612     *pOffsetAfterIndirection = MethodTable::GetIndexAfterVtableIndirection(method->GetSlot()) * sizeof(PCODE);
8613     *isRelative = MethodTable::VTableIndir_t::isRelative ? 1 : 0;
8614
8615     EE_TO_JIT_TRANSITION_LEAF();
8616 }
8617
8618 /*********************************************************************/
8619 CORINFO_METHOD_HANDLE CEEInfo::resolveVirtualMethodHelper(CORINFO_METHOD_HANDLE baseMethod,
8620                                                           CORINFO_CLASS_HANDLE derivedClass,
8621                                                           CORINFO_CONTEXT_HANDLE ownerType)
8622 {
8623     CONTRACTL {
8624         THROWS;
8625         GC_TRIGGERS;
8626         MODE_PREEMPTIVE;
8627     } CONTRACTL_END;
8628
8629     MethodDesc* pBaseMD = GetMethod(baseMethod);
8630     MethodTable* pBaseMT = pBaseMD->GetMethodTable();
8631
8632     // Method better be from a fully loaded class
8633     _ASSERTE(pBaseMD->IsRestored() && pBaseMT->IsFullyLoaded());
8634
8635     //@GENERICS: shouldn't be doing this for instantiated methods as they live elsewhere
8636     _ASSERTE(!pBaseMD->HasMethodInstantiation());
8637
8638     // Method better be virtual
8639     _ASSERTE(pBaseMD->IsVirtual());
8640
8641     MethodDesc* pDevirtMD = nullptr;
8642
8643     TypeHandle DerivedClsHnd(derivedClass);
8644     MethodTable* pDerivedMT = DerivedClsHnd.GetMethodTable();
8645     _ASSERTE(pDerivedMT->IsRestored() && pDerivedMT->IsFullyLoaded());
8646
8647     // Can't devirtualize from __Canon.
8648     if (DerivedClsHnd == TypeHandle(g_pCanonMethodTableClass))
8649     {
8650         return nullptr;
8651     }
8652
8653     if (pBaseMT->IsInterface())
8654     {
8655
8656 #ifdef FEATURE_COMINTEROP
8657         // Don't try and devirtualize com interface calls.
8658         if (pDerivedMT->IsComObjectType())
8659         {
8660             return nullptr;
8661         }
8662 #endif // FEATURE_COMINTEROP
8663
8664         // Interface call devirtualization.
8665         //
8666         // We must ensure that pDerivedMT actually implements the
8667         // interface corresponding to pBaseMD.
8668         if (!pDerivedMT->CanCastToInterface(pBaseMT))
8669         {
8670             return nullptr;
8671         }
8672
8673         // For generic interface methods we must have an ownerType to
8674         // safely devirtualize.
8675         if (ownerType != nullptr)
8676         {
8677             TypeHandle OwnerClsHnd = GetTypeFromContext(ownerType);
8678             MethodTable* pOwnerMT = OwnerClsHnd.GetMethodTable();
8679
8680             // If the derived class is a shared class, make sure the
8681             // owner class is too.
8682             if (pDerivedMT->IsSharedByGenericInstantiations())
8683             {
8684                 pOwnerMT = pOwnerMT->GetCanonicalMethodTable();
8685             }
8686
8687             pDevirtMD = pDerivedMT->GetMethodDescForInterfaceMethod(TypeHandle(pOwnerMT), pBaseMD);
8688         }
8689         else if (!pBaseMD->HasClassOrMethodInstantiation())
8690         {
8691             pDevirtMD = pDerivedMT->GetMethodDescForInterfaceMethod(pBaseMD);
8692         }
8693         else
8694         {
8695             return nullptr;
8696         }
8697     }
8698     else
8699     {
8700         // Virtual call devirtualization.
8701         // 
8702         // The derived class should be a subclass of the the base class.
8703         MethodTable* pCheckMT = pDerivedMT;
8704         
8705         while (pCheckMT != nullptr)
8706         {
8707             if (pCheckMT->HasSameTypeDefAs(pBaseMT))
8708             {
8709                 break;
8710             }
8711             
8712             pCheckMT = pCheckMT->GetParentMethodTable();
8713         }
8714         
8715         if (pCheckMT == nullptr)
8716         {
8717             return nullptr;
8718         }
8719         
8720         // The base method should be in the base vtable
8721         WORD slot = pBaseMD->GetSlot();
8722         _ASSERTE(slot < pBaseMT->GetNumVirtuals());
8723         
8724         // Fetch the method that would be invoked if the class were
8725         // exactly derived class. It is up to the jit to determine whether
8726         // directly calling this method is correct.
8727         pDevirtMD = pDerivedMT->GetMethodDescForSlot(slot);
8728     }
8729
8730     _ASSERTE(pDevirtMD->IsRestored());
8731
8732 #ifdef FEATURE_READYTORUN_COMPILER
8733     // Check if devirtualization is dependent upon cross-version
8734     // bubble information and if so, disallow it.
8735     if (IsReadyToRunCompilation())
8736     {
8737         MethodDesc* callerMethod = m_pMethodBeingCompiled;
8738         Assembly* pCallerAssembly = callerMethod->GetModule()->GetAssembly();
8739         bool allowDevirt =
8740             IsInSameVersionBubble(pCallerAssembly , pDevirtMD->GetModule()->GetAssembly())
8741             && IsInSameVersionBubble(pCallerAssembly , pDerivedMT->GetAssembly());
8742
8743         if (!allowDevirt)
8744         {
8745             return nullptr;
8746         }
8747     }
8748 #endif
8749
8750     return (CORINFO_METHOD_HANDLE) pDevirtMD;
8751 }
8752
8753 CORINFO_METHOD_HANDLE CEEInfo::resolveVirtualMethod(CORINFO_METHOD_HANDLE methodHnd,
8754                                                     CORINFO_CLASS_HANDLE derivedClass,
8755                                                     CORINFO_CONTEXT_HANDLE ownerType)
8756 {
8757     CONTRACTL {
8758         SO_TOLERANT;
8759         THROWS;
8760         GC_TRIGGERS;
8761         MODE_PREEMPTIVE;
8762     } CONTRACTL_END;
8763
8764     CORINFO_METHOD_HANDLE result = nullptr;
8765
8766     JIT_TO_EE_TRANSITION();
8767
8768     result = resolveVirtualMethodHelper(methodHnd, derivedClass, ownerType);
8769
8770     EE_TO_JIT_TRANSITION();
8771
8772     return result;
8773 }
8774
8775 void CEEInfo::expandRawHandleIntrinsic(
8776     CORINFO_RESOLVED_TOKEN *        pResolvedToken,
8777     CORINFO_GENERICHANDLE_RESULT *  pResult)
8778 {
8779     LIMITED_METHOD_CONTRACT;
8780     UNREACHABLE();      // only called with CoreRT.
8781 }
8782
8783 /*********************************************************************/
8784 void CEEInfo::getFunctionEntryPoint(CORINFO_METHOD_HANDLE  ftnHnd,
8785                                     CORINFO_CONST_LOOKUP * pResult,
8786                                     CORINFO_ACCESS_FLAGS   accessFlags)
8787 {
8788     CONTRACTL {
8789         SO_TOLERANT;
8790         THROWS;
8791         GC_TRIGGERS;
8792         MODE_PREEMPTIVE;
8793     } CONTRACTL_END;
8794
8795     void* ret = NULL;
8796     InfoAccessType accessType = IAT_VALUE;
8797
8798     JIT_TO_EE_TRANSITION();
8799
8800     MethodDesc * ftn = GetMethod(ftnHnd);
8801 #if defined(FEATURE_GDBJIT)
8802     MethodDesc * orig_ftn = ftn;
8803 #endif
8804
8805     // Resolve methodImpl.
8806     ftn = ftn->GetMethodTable()->MapMethodDeclToMethodImpl(ftn);
8807
8808     ret = (void *)ftn->TryGetMultiCallableAddrOfCode(accessFlags);
8809
8810     // TryGetMultiCallableAddrOfCode returns NULL if indirect access is desired
8811     if (ret == NULL)
8812     {
8813         // should never get here for EnC methods or if interception via remoting stub is required
8814         _ASSERTE(!ftn->IsEnCMethod());
8815
8816         _ASSERTE((accessFlags & CORINFO_ACCESS_THIS) || !ftn->IsRemotingInterceptedViaVirtualDispatch());
8817
8818         ret = ftn->GetAddrOfSlot();
8819         accessType = IAT_PVALUE;
8820     }
8821
8822
8823 #if defined(FEATURE_GDBJIT)
8824     CalledMethod * pCM = new CalledMethod(orig_ftn, ret, m_pCalledMethods);
8825     m_pCalledMethods = pCM;
8826 #endif
8827
8828     EE_TO_JIT_TRANSITION();
8829
8830     _ASSERTE(ret != NULL);
8831
8832     pResult->accessType = accessType;
8833     pResult->addr = ret;
8834 }
8835
8836 /*********************************************************************/
8837 void CEEInfo::getFunctionFixedEntryPoint(CORINFO_METHOD_HANDLE   ftn,
8838                                          CORINFO_CONST_LOOKUP *  pResult)
8839 {
8840     CONTRACTL {
8841         SO_TOLERANT;
8842         THROWS;
8843         GC_TRIGGERS;
8844         MODE_PREEMPTIVE;
8845     } CONTRACTL_END;
8846
8847     JIT_TO_EE_TRANSITION();
8848
8849     MethodDesc * pMD = GetMethod(ftn);
8850
8851     pResult->accessType = IAT_VALUE;
8852
8853
8854 #ifndef CROSSGEN_COMPILE
8855     // If LDFTN target has [NativeCallable] attribute , then create a UMEntryThunk.
8856     if (pMD->HasNativeCallableAttribute())
8857     {
8858         pResult->addr = (void*)COMDelegate::ConvertToCallback(pMD);
8859     }
8860     else
8861 #endif //CROSSGEN_COMPILE
8862     {
8863         pResult->addr = (void *)pMD->GetMultiCallableAddrOfCode();
8864     }
8865     EE_TO_JIT_TRANSITION();
8866 }
8867
8868 /*********************************************************************/
8869 const char* CEEInfo::getFieldName (CORINFO_FIELD_HANDLE fieldHnd, const char** scopeName)
8870 {
8871     CONTRACTL {
8872         SO_TOLERANT;
8873         THROWS;
8874         GC_TRIGGERS;
8875         MODE_PREEMPTIVE;
8876     } CONTRACTL_END;
8877
8878     const char* result = NULL;
8879
8880     JIT_TO_EE_TRANSITION();
8881
8882     FieldDesc* field = (FieldDesc*) fieldHnd;
8883     if (scopeName != 0)
8884     {
8885         TypeHandle t = TypeHandle(field->GetApproxEnclosingMethodTable());
8886         *scopeName = "";
8887         if (!t.IsNull())
8888         {
8889 #ifdef _DEBUG
8890             t.GetName(ssClsNameBuff);
8891             *scopeName = ssClsNameBuff.GetUTF8(ssClsNameBuffScratch);
8892 #else // !_DEBUG
8893             // since this is for diagnostic purposes only,
8894             // give up on the namespace, as we don't have a buffer to concat it
8895             // also note this won't show array class names.
8896             LPCUTF8 nameSpace;
8897             *scopeName= t.GetMethodTable()->GetFullyQualifiedNameInfo(&nameSpace);
8898 #endif // !_DEBUG
8899         }
8900     }
8901
8902     result = field->GetName();
8903
8904     EE_TO_JIT_TRANSITION();
8905
8906     return result;
8907 }
8908
8909 /*********************************************************************/
8910 // Get the type that declares the field
8911 CORINFO_CLASS_HANDLE CEEInfo::getFieldClass (CORINFO_FIELD_HANDLE fieldHnd)
8912 {
8913     CONTRACTL {
8914         SO_TOLERANT;
8915         NOTHROW;
8916         GC_NOTRIGGER;
8917         MODE_PREEMPTIVE;
8918     } CONTRACTL_END;
8919
8920     CORINFO_CLASS_HANDLE result = NULL;
8921
8922     JIT_TO_EE_TRANSITION_LEAF();
8923
8924     FieldDesc* field = (FieldDesc*) fieldHnd;
8925     result = CORINFO_CLASS_HANDLE(field->GetApproxEnclosingMethodTable());
8926
8927     EE_TO_JIT_TRANSITION_LEAF();
8928
8929     return result;
8930 }
8931
8932 /*********************************************************************/
8933 // Returns the basic type of the field (not the the type that declares the field)
8934 //
8935 // pTypeHnd - On return, for reference and value types, *pTypeHnd will contain 
8936 //            the normalized type of the field.
8937 // owner - Optional. For resolving in a generic context
8938
8939 CorInfoType CEEInfo::getFieldType (CORINFO_FIELD_HANDLE fieldHnd, 
8940                                    CORINFO_CLASS_HANDLE* pTypeHnd, 
8941                                    CORINFO_CLASS_HANDLE owner)
8942 {
8943     CONTRACTL {
8944         SO_TOLERANT;
8945         THROWS;
8946         GC_TRIGGERS;
8947         MODE_PREEMPTIVE;
8948     } CONTRACTL_END;
8949
8950     CorInfoType result = CORINFO_TYPE_UNDEF;
8951
8952     JIT_TO_EE_TRANSITION();
8953
8954     result = getFieldTypeInternal(fieldHnd, pTypeHnd, owner);
8955
8956     EE_TO_JIT_TRANSITION();
8957
8958     return result;
8959 }
8960
8961 /*********************************************************************/
8962 CorInfoType CEEInfo::getFieldTypeInternal (CORINFO_FIELD_HANDLE fieldHnd, 
8963                                            CORINFO_CLASS_HANDLE* pTypeHnd, 
8964                                            CORINFO_CLASS_HANDLE owner)
8965 {
8966     STANDARD_VM_CONTRACT;
8967
8968     *pTypeHnd = 0;
8969
8970     TypeHandle clsHnd = TypeHandle();
8971     FieldDesc* field = (FieldDesc*) fieldHnd;
8972     CorElementType type   = field->GetFieldType();
8973
8974     // <REVISIT_TODO>TODO should not burn the time to do this for anything but Value Classes</REVISIT_TODO>
8975     _ASSERTE(type != ELEMENT_TYPE_BYREF);
8976
8977     if (type == ELEMENT_TYPE_I)
8978     {
8979         PTR_MethodTable enclosingMethodTable = field->GetApproxEnclosingMethodTable();
8980         if (enclosingMethodTable->IsByRefLike() && enclosingMethodTable->HasSameTypeDefAs(g_pByReferenceClass))
8981         {
8982             _ASSERTE(field->GetOffset() == 0);
8983             return CORINFO_TYPE_BYREF;
8984         }
8985     }
8986
8987     if (!CorTypeInfo::IsPrimitiveType(type))
8988     {
8989         PCCOR_SIGNATURE sig;
8990         DWORD sigCount;
8991         CorCallingConvention conv;
8992
8993         field->GetSig(&sig, &sigCount);
8994
8995         conv = (CorCallingConvention)CorSigUncompressCallingConv(sig);
8996         _ASSERTE(isCallConv(conv, IMAGE_CEE_CS_CALLCONV_FIELD));
8997
8998         SigPointer ptr(sig, sigCount);
8999
9000         // For verifying code involving generics, use the class instantiation
9001         // of the optional owner (to provide exact, not representative,
9002         // type information)
9003         SigTypeContext typeContext(field, (TypeHandle)owner);
9004
9005         clsHnd = ptr.GetTypeHandleThrowing(field->GetModule(), &typeContext);
9006         _ASSERTE(!clsHnd.IsNull());
9007
9008         // I believe it doesn't make any diff. if this is GetInternalCorElementType 
9009         // or GetSignatureCorElementType.
9010         type = clsHnd.GetSignatureCorElementType();
9011     }
9012
9013     return CEEInfo::asCorInfoType(type, clsHnd, pTypeHnd);
9014 }
9015
9016 /*********************************************************************/
9017 unsigned CEEInfo::getFieldOffset (CORINFO_FIELD_HANDLE fieldHnd)
9018 {
9019     CONTRACTL {
9020         SO_TOLERANT;
9021         THROWS;
9022         GC_TRIGGERS;
9023         MODE_PREEMPTIVE;
9024     } CONTRACTL_END;
9025
9026     unsigned result = (unsigned) -1;
9027
9028     JIT_TO_EE_TRANSITION();
9029
9030     FieldDesc* field = (FieldDesc*) fieldHnd;
9031
9032     // GetOffset() does not include the size of Object
9033     result = field->GetOffset();
9034
9035     // So if it is not a value class, add the Object into it
9036     if (field->IsStatic())
9037     {
9038         Module* pModule = field->GetModule();
9039         if (field->IsRVA() && pModule->IsRvaFieldTls(field->GetOffset()))
9040         {
9041             result = pModule->GetFieldTlsOffset(field->GetOffset());
9042         }
9043     }
9044     else if (!field->GetApproxEnclosingMethodTable()->IsValueType())
9045     {
9046         result += sizeof(Object);
9047     }
9048
9049     EE_TO_JIT_TRANSITION();
9050
9051     return result;
9052 }
9053
9054 /*********************************************************************/
9055 bool CEEInfo::isWriteBarrierHelperRequired(CORINFO_FIELD_HANDLE field)
9056 {
9057     CONTRACTL {
9058         SO_TOLERANT;
9059         THROWS;
9060         GC_TRIGGERS;
9061         MODE_PREEMPTIVE;
9062     } CONTRACTL_END;
9063
9064     bool fHelperRequired = false;
9065
9066     JIT_TO_EE_TRANSITION();
9067
9068     FieldDesc * pField = (FieldDesc *)field;
9069
9070     // TODO: jit64 should be switched to the same plan as the i386 jits - use
9071     // getClassGClayout to figure out the need for writebarrier helper, and inline the copying.
9072     // Once this happens, USE_WRITE_BARRIER_HELPERS and CORINFO_FLG_WRITE_BARRIER_HELPER can be removed.
9073     CorElementType type = pField->GetFieldType();
9074
9075     if(CorTypeInfo::IsObjRef(type))
9076         fHelperRequired = true;
9077     else if (type == ELEMENT_TYPE_VALUETYPE)
9078     {
9079         TypeHandle th = pField->GetFieldTypeHandleThrowing();
9080         _ASSERTE(!th.IsNull());
9081         if(th.GetMethodTable()->ContainsPointers())
9082             fHelperRequired = true;
9083     }
9084
9085     EE_TO_JIT_TRANSITION();
9086
9087     return fHelperRequired;
9088 }
9089
9090 /*********************************************************************/
9091 DWORD CEEInfo::getFieldThreadLocalStoreID(CORINFO_FIELD_HANDLE fieldHnd, void **ppIndirection)
9092 {
9093     CONTRACTL {
9094         SO_TOLERANT;
9095         THROWS;
9096         GC_TRIGGERS;
9097         MODE_PREEMPTIVE;
9098     } CONTRACTL_END;
9099
9100     DWORD result = 0;
9101
9102     if (ppIndirection != NULL)
9103         *ppIndirection = NULL;
9104
9105     JIT_TO_EE_TRANSITION();
9106
9107     FieldDesc* field = (FieldDesc*) fieldHnd;
9108     Module* module = field->GetModule();
9109
9110     _ASSERTE(field->IsRVA());       // Only RVA statics can be thread local
9111     _ASSERTE(module->IsRvaFieldTls(field->GetOffset()));
9112
9113     result = module->GetTlsIndex();
9114
9115     EE_TO_JIT_TRANSITION();
9116
9117     return result;
9118 }
9119
9120 void *CEEInfo::allocateArray(ULONG cBytes)
9121 {
9122     CONTRACTL {
9123         SO_TOLERANT;
9124         THROWS;
9125         GC_TRIGGERS;
9126         MODE_PREEMPTIVE;
9127     } CONTRACTL_END;
9128
9129     void * result = NULL;
9130
9131     JIT_TO_EE_TRANSITION();
9132
9133     result = new BYTE [cBytes];
9134
9135     EE_TO_JIT_TRANSITION();
9136
9137     return result;
9138 }
9139
9140 void CEEInfo::freeArray(void *array)
9141 {
9142     CONTRACTL {
9143         SO_TOLERANT;
9144         THROWS;
9145         GC_TRIGGERS;
9146         MODE_PREEMPTIVE;
9147     } CONTRACTL_END;
9148
9149     JIT_TO_EE_TRANSITION();
9150
9151     delete [] ((BYTE*) array);
9152
9153     EE_TO_JIT_TRANSITION();
9154 }
9155
9156 void CEEInfo::getBoundaries(CORINFO_METHOD_HANDLE ftn,
9157                                unsigned int *cILOffsets, DWORD **pILOffsets,
9158                                ICorDebugInfo::BoundaryTypes *implicitBoundaries)
9159 {
9160     CONTRACTL {
9161         SO_TOLERANT;
9162         THROWS;
9163         GC_TRIGGERS;
9164         MODE_PREEMPTIVE;
9165     } CONTRACTL_END;
9166
9167     JIT_TO_EE_TRANSITION();
9168
9169 #ifdef DEBUGGING_SUPPORTED
9170     if (g_pDebugInterface && !IsCompilationProcess())
9171     {
9172         g_pDebugInterface->getBoundaries(GetMethod(ftn), cILOffsets, pILOffsets,
9173                                      implicitBoundaries);
9174     }
9175     else
9176     {
9177         *cILOffsets = 0;
9178         *pILOffsets = NULL;
9179         *implicitBoundaries = ICorDebugInfo::DEFAULT_BOUNDARIES;
9180     }
9181 #endif // DEBUGGING_SUPPORTED
9182
9183     EE_TO_JIT_TRANSITION();
9184 }
9185
9186 void CEEInfo::getVars(CORINFO_METHOD_HANDLE ftn, ULONG32 *cVars, ICorDebugInfo::ILVarInfo **vars,
9187                          bool *extendOthers)
9188 {
9189     CONTRACTL {
9190         SO_TOLERANT;
9191         THROWS;
9192         GC_TRIGGERS;
9193         MODE_PREEMPTIVE;
9194     } CONTRACTL_END;
9195
9196     JIT_TO_EE_TRANSITION();
9197
9198 #ifdef DEBUGGING_SUPPORTED
9199     if (g_pDebugInterface && !IsCompilationProcess())
9200     {
9201         g_pDebugInterface->getVars(GetMethod(ftn), cVars, vars, extendOthers);
9202     }
9203     else
9204     {
9205         *cVars = 0;
9206         *vars = NULL;
9207
9208         // Just tell the JIT to extend everything.
9209         *extendOthers = true;
9210     }
9211 #endif // DEBUGGING_SUPPORTED
9212
9213     EE_TO_JIT_TRANSITION();
9214 }
9215
9216 /*********************************************************************/
9217 CORINFO_ARG_LIST_HANDLE CEEInfo::getArgNext(CORINFO_ARG_LIST_HANDLE args)
9218 {
9219     CONTRACTL {
9220         SO_TOLERANT;
9221         THROWS;
9222         GC_TRIGGERS;
9223         MODE_PREEMPTIVE;
9224     } CONTRACTL_END;
9225
9226     CORINFO_ARG_LIST_HANDLE result = NULL;
9227
9228     JIT_TO_EE_TRANSITION();
9229
9230     SigPointer ptr((unsigned __int8*) args);
9231     IfFailThrow(ptr.SkipExactlyOne());
9232
9233     result = (CORINFO_ARG_LIST_HANDLE) ptr.GetPtr();
9234
9235     EE_TO_JIT_TRANSITION();
9236     
9237     return result;
9238 }
9239
9240
9241 /*********************************************************************/
9242
9243 CorInfoTypeWithMod CEEInfo::getArgType (
9244         CORINFO_SIG_INFO*       sig,
9245         CORINFO_ARG_LIST_HANDLE args,
9246         CORINFO_CLASS_HANDLE*   vcTypeRet
9247         )
9248 {
9249     CONTRACTL {
9250         SO_TOLERANT;
9251         THROWS;
9252         GC_TRIGGERS;
9253         MODE_PREEMPTIVE;
9254     } CONTRACTL_END;
9255
9256     CorInfoTypeWithMod result = CorInfoTypeWithMod(CORINFO_TYPE_UNDEF);
9257
9258     JIT_TO_EE_TRANSITION();
9259
9260    _ASSERTE((BYTE*) sig->pSig <= (BYTE*) sig->args && (BYTE*) args < (BYTE*) sig->pSig + sig->cbSig);
9261    _ASSERTE((BYTE*) sig->args <= (BYTE*) args);
9262     INDEBUG(*vcTypeRet = CORINFO_CLASS_HANDLE((size_t)INVALID_POINTER_CC));
9263
9264     SigPointer ptr((unsigned __int8*) args);
9265     CorElementType eType;
9266     IfFailThrow(ptr.PeekElemType(&eType));
9267     while (eType == ELEMENT_TYPE_PINNED)
9268     {
9269         result = CORINFO_TYPE_MOD_PINNED;
9270         IfFailThrow(ptr.GetElemType(NULL));
9271         IfFailThrow(ptr.PeekElemType(&eType));
9272     }
9273
9274     // Now read off the "real" element type after taking any instantiations into consideration
9275     SigTypeContext typeContext;
9276     GetTypeContext(&sig->sigInst,&typeContext);
9277
9278     Module* pModule = GetModule(sig->scope);
9279
9280     CorElementType type = ptr.PeekElemTypeClosed(pModule, &typeContext);
9281
9282     TypeHandle typeHnd = TypeHandle();
9283     switch (type) {
9284       case ELEMENT_TYPE_VAR :
9285       case ELEMENT_TYPE_MVAR :
9286       case ELEMENT_TYPE_VALUETYPE :
9287       case ELEMENT_TYPE_TYPEDBYREF :
9288       case ELEMENT_TYPE_INTERNAL :
9289       {
9290             typeHnd = ptr.GetTypeHandleThrowing(pModule, &typeContext);
9291             _ASSERTE(!typeHnd.IsNull());
9292
9293             CorElementType normType = typeHnd.GetInternalCorElementType();
9294
9295             // if we are looking up a value class, don't morph it to a refernece type
9296             // (This can only happen in illegal IL)
9297             if (!CorTypeInfo::IsObjRef(normType) || type != ELEMENT_TYPE_VALUETYPE)
9298             {
9299                 type = normType;
9300             }
9301         }
9302         break;
9303
9304     case ELEMENT_TYPE_PTR:
9305         // Load the type eagerly under debugger to make the eval work
9306         if (!isVerifyOnly() && CORDisableJITOptimizations(pModule->GetDebuggerInfoBits()))
9307         {
9308             // NOTE: in some IJW cases, when the type pointed at is unmanaged,
9309             // the GetTypeHandle may fail, because there is no TypeDef for such type.
9310             // Usage of GetTypeHandleThrowing would lead to class load exception
9311             TypeHandle thPtr = ptr.GetTypeHandleNT(pModule, &typeContext);
9312             if(!thPtr.IsNull())
9313             {
9314                 m_pOverride->classMustBeLoadedBeforeCodeIsRun(CORINFO_CLASS_HANDLE(thPtr.AsPtr()));
9315             }
9316         }
9317         break;
9318
9319     case ELEMENT_TYPE_VOID:
9320         // void is not valid in local sigs
9321         if (sig->flags & CORINFO_SIGFLAG_IS_LOCAL_SIG)
9322             COMPlusThrowHR(COR_E_INVALIDPROGRAM);
9323         break;
9324
9325     case ELEMENT_TYPE_END:
9326            COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
9327         break;
9328
9329     default:
9330         break;
9331     }
9332
9333     result = CorInfoTypeWithMod(result | CEEInfo::asCorInfoType(type, typeHnd, vcTypeRet));
9334     EE_TO_JIT_TRANSITION();
9335     
9336     return result;
9337 }
9338
9339 /*********************************************************************/
9340
9341 CORINFO_CLASS_HANDLE CEEInfo::getArgClass (
9342     CORINFO_SIG_INFO*       sig,
9343     CORINFO_ARG_LIST_HANDLE args
9344     )
9345 {
9346     CONTRACTL {
9347         SO_TOLERANT;
9348         THROWS;
9349         GC_TRIGGERS;
9350         MODE_PREEMPTIVE;
9351     } CONTRACTL_END;
9352
9353     CORINFO_CLASS_HANDLE result = NULL;
9354
9355     JIT_TO_EE_TRANSITION();
9356
9357     // make certain we dont have a completely wacked out sig pointer
9358     _ASSERTE((BYTE*) sig->pSig <= (BYTE*) sig->args);
9359     _ASSERTE((BYTE*) sig->args <= (BYTE*) args && (BYTE*) args < &((BYTE*) sig->args)[0x10000*5]);
9360
9361     Module* pModule = GetModule(sig->scope);
9362
9363     SigPointer ptr((unsigned __int8*) args);
9364
9365     CorElementType eType;
9366     IfFailThrow(ptr.PeekElemType(&eType));
9367
9368     while (eType == ELEMENT_TYPE_PINNED)
9369     {
9370         IfFailThrow(ptr.GetElemType(NULL));
9371         IfFailThrow(ptr.PeekElemType(&eType));
9372     }
9373     // Now read off the "real" element type after taking any instantiations into consideration
9374     SigTypeContext typeContext;
9375     GetTypeContext(&sig->sigInst, &typeContext);
9376     CorElementType type = ptr.PeekElemTypeClosed(pModule, &typeContext);
9377
9378     if (!CorTypeInfo::IsPrimitiveType(type)) {
9379         TypeHandle th = ptr.GetTypeHandleThrowing(pModule, &typeContext);
9380         result = CORINFO_CLASS_HANDLE(th.AsPtr());
9381     }
9382
9383     EE_TO_JIT_TRANSITION();
9384     
9385     return result;
9386 }
9387
9388 /*********************************************************************/
9389
9390 CorInfoType CEEInfo::getHFAType(CORINFO_CLASS_HANDLE hClass)
9391 {
9392     CONTRACTL {
9393         SO_TOLERANT;
9394         THROWS;
9395         GC_TRIGGERS;
9396         MODE_PREEMPTIVE;
9397     } CONTRACTL_END;
9398
9399     CorInfoType result = CORINFO_TYPE_UNDEF;
9400
9401 #ifdef FEATURE_HFA
9402     JIT_TO_EE_TRANSITION();
9403
9404     TypeHandle VMClsHnd(hClass);
9405
9406     result = asCorInfoType(VMClsHnd.GetHFAType());
9407     
9408     EE_TO_JIT_TRANSITION();
9409 #endif
9410
9411     return result;
9412 }
9413
9414 /*********************************************************************/
9415
9416     // return the unmanaged calling convention for a PInvoke
9417 CorInfoUnmanagedCallConv CEEInfo::getUnmanagedCallConv(CORINFO_METHOD_HANDLE method)
9418 {
9419     CONTRACTL {
9420         SO_TOLERANT;
9421         THROWS;
9422         GC_TRIGGERS;
9423         MODE_PREEMPTIVE;
9424     } CONTRACTL_END;
9425
9426     CorInfoUnmanagedCallConv result = CORINFO_UNMANAGED_CALLCONV_UNKNOWN;
9427
9428     JIT_TO_EE_TRANSITION();
9429
9430     MethodDesc* pMD = NULL;
9431     pMD = GetMethod(method);
9432     _ASSERTE(pMD->IsNDirect());
9433
9434 #ifdef _TARGET_X86_
9435     EX_TRY
9436     {
9437         PInvokeStaticSigInfo sigInfo(pMD, PInvokeStaticSigInfo::NO_THROW_ON_ERROR);
9438
9439         switch (sigInfo.GetCallConv()) {
9440             case pmCallConvCdecl:
9441                 result = CORINFO_UNMANAGED_CALLCONV_C;
9442                 break;
9443             case pmCallConvStdcall:
9444                 result = CORINFO_UNMANAGED_CALLCONV_STDCALL;
9445                 break;
9446             case pmCallConvThiscall:
9447                 result = CORINFO_UNMANAGED_CALLCONV_THISCALL;
9448                 break;
9449             default:
9450                 result = CORINFO_UNMANAGED_CALLCONV_UNKNOWN;
9451         }
9452     }
9453     EX_CATCH
9454     {
9455         result = CORINFO_UNMANAGED_CALLCONV_UNKNOWN;
9456     }
9457     EX_END_CATCH(SwallowAllExceptions)
9458 #else // !_TARGET_X86_
9459     //
9460     // we have only one calling convention
9461     //
9462     result = CORINFO_UNMANAGED_CALLCONV_STDCALL;
9463 #endif // !_TARGET_X86_
9464
9465     EE_TO_JIT_TRANSITION();
9466     
9467     return result;
9468 }
9469
9470 /*********************************************************************/
9471 BOOL NDirectMethodDesc::ComputeMarshalingRequired()
9472 {
9473     WRAPPER_NO_CONTRACT;
9474
9475     return NDirect::MarshalingRequired(this);
9476 }
9477
9478 /*********************************************************************/
9479 BOOL CEEInfo::pInvokeMarshalingRequired(CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* callSiteSig)
9480 {
9481     CONTRACTL {
9482         SO_TOLERANT;
9483         THROWS;
9484         GC_TRIGGERS;
9485         MODE_PREEMPTIVE;
9486     } CONTRACTL_END;
9487
9488     BOOL result = FALSE;
9489
9490     JIT_TO_EE_TRANSITION();
9491
9492     if (method != 0)
9493     {
9494         MethodDesc* ftn = GetMethod(method);
9495         _ASSERTE(ftn->IsNDirect());
9496         NDirectMethodDesc *pMD = (NDirectMethodDesc*)ftn;
9497
9498 #if defined(HAS_NDIRECT_IMPORT_PRECODE)
9499         if (pMD->IsVarArg())
9500         {
9501             // Varag P/Invoke must not be inlined because its NDirectMethodDesc
9502             // does not contain a meaningful stack size (it is call site specific).
9503             // See code:InlinedCallFrame.UpdateRegDisplay where this is needed.
9504             result = TRUE;
9505         }
9506         else if (pMD->MarshalingRequired())
9507         {
9508             // This is not a no-marshal signature.
9509             result = TRUE;
9510         }
9511         else
9512         {
9513             // This is a no-marshal non-vararg signature.
9514             result = FALSE;
9515         }
9516 #else
9517         // Marshalling is required to lazy initialize the indirection cell 
9518         // without NDirectImportPrecode.
9519         result = TRUE;
9520 #endif
9521     }
9522     else
9523     {
9524         // check the call site signature
9525         result = NDirect::MarshalingRequired(
9526                     GetMethod(method),
9527                     callSiteSig->pSig,
9528                     GetModule(callSiteSig->scope));
9529     }
9530
9531     EE_TO_JIT_TRANSITION();
9532
9533     return result;
9534 }
9535
9536 /*********************************************************************/
9537 // Generate a cookie based on the signature that would needs to be passed
9538 // to CORINFO_HELP_PINVOKE_CALLI
9539 LPVOID CEEInfo::GetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig,
9540                                             void **ppIndirection)
9541 {
9542     WRAPPER_NO_CONTRACT;
9543
9544     return getVarArgsHandle(szMetaSig, ppIndirection);
9545 }
9546
9547 bool CEEInfo::canGetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig)
9548 {
9549     LIMITED_METHOD_CONTRACT;
9550     return true;
9551 }
9552
9553
9554 // Check any constraints on method type arguments
9555 BOOL CEEInfo::satisfiesMethodConstraints(
9556     CORINFO_CLASS_HANDLE        parent,
9557     CORINFO_METHOD_HANDLE       method)
9558 {
9559     CONTRACTL {
9560         SO_TOLERANT;
9561         THROWS;
9562         GC_TRIGGERS;
9563         MODE_PREEMPTIVE;
9564     } CONTRACTL_END;
9565
9566     BOOL result = FALSE;
9567
9568     JIT_TO_EE_TRANSITION();
9569
9570     _ASSERTE(parent != NULL);
9571     _ASSERTE(method != NULL);
9572     result = GetMethod(method)->SatisfiesMethodConstraints(TypeHandle(parent));
9573
9574     EE_TO_JIT_TRANSITION();
9575
9576     return result;
9577 }
9578
9579
9580
9581 /*********************************************************************/
9582 // Given a delegate target class, a target method parent class,  a  target method,
9583 // a delegate class, check if the method signature is compatible with the Invoke method of the delegate
9584 // (under the typical instantiation of any free type variables in the memberref signatures).
9585 //
9586 // objCls should be NULL if the target object is NULL
9587 //@GENERICSVER: new (suitable for generics)
9588 BOOL CEEInfo::isCompatibleDelegate(
9589             CORINFO_CLASS_HANDLE        objCls,
9590             CORINFO_CLASS_HANDLE        methodParentCls,
9591             CORINFO_METHOD_HANDLE       method,
9592             CORINFO_CLASS_HANDLE        delegateCls,
9593             BOOL*                       pfIsOpenDelegate)
9594 {
9595     CONTRACTL {
9596         SO_TOLERANT;
9597         THROWS;
9598         GC_TRIGGERS;
9599         MODE_PREEMPTIVE;
9600     } CONTRACTL_END;
9601
9602     BOOL result = FALSE;
9603
9604     JIT_TO_EE_TRANSITION();
9605
9606     _ASSERTE(method != NULL);
9607     _ASSERTE(delegateCls != NULL);
9608
9609     TypeHandle delegateClsHnd = (TypeHandle) delegateCls;
9610
9611     _ASSERTE(delegateClsHnd.GetMethodTable()->IsDelegate());
9612
9613     TypeHandle methodParentHnd = (TypeHandle) (methodParentCls);
9614     MethodDesc* pMDFtn = GetMethod(method);
9615     TypeHandle objClsHnd(objCls);
9616
9617     EX_TRY
9618     {
9619       result = COMDelegate::ValidateCtor(objClsHnd, methodParentHnd, pMDFtn, delegateClsHnd, pfIsOpenDelegate);
9620     }
9621     EX_CATCH
9622     {
9623     }
9624     EX_END_CATCH(SwallowAllExceptions)
9625
9626     EE_TO_JIT_TRANSITION();
9627
9628     return result;
9629 }
9630
9631 /*********************************************************************/
9632     // return the unmanaged target *if method has already been prelinked.*
9633 void* CEEInfo::getPInvokeUnmanagedTarget(CORINFO_METHOD_HANDLE method,
9634                                                     void **ppIndirection)
9635 {
9636     CONTRACTL {
9637         SO_TOLERANT;
9638         THROWS;
9639         GC_TRIGGERS;
9640         MODE_PREEMPTIVE;
9641     } CONTRACTL_END;
9642
9643     void* result = NULL;
9644
9645     if (ppIndirection != NULL)
9646         *ppIndirection = NULL;
9647
9648 #ifndef CROSSGEN_COMPILE
9649     JIT_TO_EE_TRANSITION();
9650
9651     MethodDesc* ftn = GetMethod(method);
9652     _ASSERTE(ftn->IsNDirect());
9653     NDirectMethodDesc *pMD = (NDirectMethodDesc*)ftn;
9654
9655     if (pMD->NDirectTargetIsImportThunk())
9656     {
9657     }
9658     else
9659     {
9660         result = pMD->GetNDirectTarget();
9661     }
9662
9663     EE_TO_JIT_TRANSITION();
9664 #endif // CROSSGEN_COMPILE
9665
9666     return result;
9667 }
9668
9669 /*********************************************************************/
9670     // return address of fixup area for late-bound N/Direct calls.
9671 void* CEEInfo::getAddressOfPInvokeFixup(CORINFO_METHOD_HANDLE method,
9672                                         void **ppIndirection)
9673 {
9674     CONTRACTL {
9675         SO_TOLERANT;
9676         NOTHROW;
9677         GC_NOTRIGGER;
9678         MODE_PREEMPTIVE;
9679     } CONTRACTL_END;
9680
9681     void * result = NULL;
9682
9683     if (ppIndirection != NULL)
9684         *ppIndirection = NULL;
9685
9686     JIT_TO_EE_TRANSITION_LEAF();
9687
9688     MethodDesc* ftn = GetMethod(method);
9689     _ASSERTE(ftn->IsNDirect());
9690     NDirectMethodDesc *pMD = (NDirectMethodDesc*)ftn;
9691
9692     result = (LPVOID)&(pMD->GetWriteableData()->m_pNDirectTarget);
9693
9694     EE_TO_JIT_TRANSITION_LEAF();
9695
9696     return result;
9697 }
9698
9699 /*********************************************************************/
9700     // return address of fixup area for late-bound N/Direct calls.
9701 void CEEInfo::getAddressOfPInvokeTarget(CORINFO_METHOD_HANDLE method,
9702                                         CORINFO_CONST_LOOKUP *pLookup)
9703 {
9704     WRAPPER_NO_CONTRACT;
9705
9706     void *pIndirection;
9707     pLookup->accessType = IAT_PVALUE;
9708     pLookup->addr = getAddressOfPInvokeFixup(method, &pIndirection);
9709     _ASSERTE(pIndirection == NULL);
9710 }
9711
9712 /*********************************************************************/
9713 CORINFO_JUST_MY_CODE_HANDLE CEEInfo::getJustMyCodeHandle(
9714                 CORINFO_METHOD_HANDLE       method,
9715                 CORINFO_JUST_MY_CODE_HANDLE**ppIndirection)
9716 {
9717     CONTRACTL {
9718         SO_TOLERANT;
9719         NOTHROW;
9720         GC_NOTRIGGER;
9721         MODE_PREEMPTIVE;
9722     } CONTRACTL_END;
9723
9724     CORINFO_JUST_MY_CODE_HANDLE result = NULL;
9725
9726     if (ppIndirection)
9727         *ppIndirection = NULL;
9728
9729     JIT_TO_EE_TRANSITION_LEAF();
9730
9731     // Get the flag from the debugger.
9732     MethodDesc* ftn = GetMethod(method);
9733     DWORD * pFlagAddr = NULL;
9734     
9735     if (g_pDebugInterface)
9736     {
9737         pFlagAddr = g_pDebugInterface->GetJMCFlagAddr(ftn->GetModule());
9738     }
9739
9740     result = (CORINFO_JUST_MY_CODE_HANDLE) pFlagAddr;
9741
9742     EE_TO_JIT_TRANSITION_LEAF();
9743
9744     return result;
9745 }
9746
9747 /*********************************************************************/
9748 void InlinedCallFrame::GetEEInfo(CORINFO_EE_INFO::InlinedCallFrameInfo *pInfo)
9749 {
9750     LIMITED_METHOD_CONTRACT;
9751
9752     pInfo->size                          = sizeof(GSCookie) + sizeof(InlinedCallFrame);
9753
9754     pInfo->offsetOfGSCookie              = 0;
9755     pInfo->offsetOfFrameVptr             = sizeof(GSCookie);
9756     pInfo->offsetOfFrameLink             = sizeof(GSCookie) + Frame::GetOffsetOfNextLink();
9757     pInfo->offsetOfCallSiteSP            = sizeof(GSCookie) + offsetof(InlinedCallFrame, m_pCallSiteSP);
9758     pInfo->offsetOfCalleeSavedFP         = sizeof(GSCookie) + offsetof(InlinedCallFrame, m_pCalleeSavedFP);
9759     pInfo->offsetOfCallTarget            = sizeof(GSCookie) + offsetof(InlinedCallFrame, m_Datum);
9760     pInfo->offsetOfReturnAddress         = sizeof(GSCookie) + offsetof(InlinedCallFrame, m_pCallerReturnAddress);
9761 }
9762
9763 /*********************************************************************/
9764 // Return details about EE internal data structures 
9765 void CEEInfo::getEEInfo(CORINFO_EE_INFO *pEEInfoOut)
9766 {
9767     CONTRACTL {
9768         SO_TOLERANT;
9769         THROWS;
9770         GC_TRIGGERS;
9771         MODE_PREEMPTIVE;
9772     } CONTRACTL_END;
9773
9774     INDEBUG(memset(pEEInfoOut, 0xCC, sizeof(*pEEInfoOut)));
9775
9776     JIT_TO_EE_TRANSITION();
9777
9778     InlinedCallFrame::GetEEInfo(&pEEInfoOut->inlinedCallFrameInfo);
9779
9780     // Offsets into the Thread structure
9781     pEEInfoOut->offsetOfThreadFrame = Thread::GetOffsetOfCurrentFrame();
9782     pEEInfoOut->offsetOfGCState     = Thread::GetOffsetOfGCFlag();
9783
9784     // Delegate offsets
9785     pEEInfoOut->offsetOfDelegateInstance    = DelegateObject::GetOffsetOfTarget();
9786     pEEInfoOut->offsetOfDelegateFirstTarget = DelegateObject::GetOffsetOfMethodPtr();
9787
9788     // Secure delegate offsets
9789     pEEInfoOut->offsetOfSecureDelegateIndirectCell = DelegateObject::GetOffsetOfMethodPtrAux();
9790
9791     // Remoting offsets
9792     pEEInfoOut->offsetOfTransparentProxyRP = TransparentProxyObject::GetOffsetOfRP();
9793     pEEInfoOut->offsetOfRealProxyServer    = RealProxyObject::GetOffsetOfServerObject();
9794
9795     pEEInfoOut->offsetOfObjArrayData       = (DWORD)PtrArray::GetDataOffset();
9796
9797     pEEInfoOut->sizeOfReversePInvokeFrame  = (DWORD)-1;
9798
9799     pEEInfoOut->osPageSize = GetOsPageSize();
9800     pEEInfoOut->maxUncheckedOffsetForNullObject = MAX_UNCHECKED_OFFSET_FOR_NULL_OBJECT;
9801     pEEInfoOut->targetAbi = CORINFO_CORECLR_ABI;
9802
9803     pEEInfoOut->osType = CORINFO_WINNT;
9804
9805     // hardcode OS version to 0.0.0. These fields can be removed from JITEE interface
9806     pEEInfoOut->osMajor = 0;
9807     pEEInfoOut->osMinor = 0;
9808     pEEInfoOut->osBuild = 0;
9809
9810     EE_TO_JIT_TRANSITION();
9811 }
9812
9813 LPCWSTR CEEInfo::getJitTimeLogFilename()
9814 {
9815     CONTRACTL {
9816         SO_TOLERANT;
9817         THROWS;
9818         GC_TRIGGERS;
9819         MODE_PREEMPTIVE;
9820     } CONTRACTL_END;
9821
9822     LPCWSTR result = NULL;
9823
9824     JIT_TO_EE_TRANSITION();
9825     result = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_JitTimeLogFile);
9826     EE_TO_JIT_TRANSITION();
9827
9828     return result;
9829 }
9830
9831
9832
9833     // Return details about EE internal data structures
9834 DWORD CEEInfo::getThreadTLSIndex(void **ppIndirection)
9835 {
9836     CONTRACTL {
9837         SO_TOLERANT;
9838         THROWS;
9839         GC_TRIGGERS;
9840         MODE_PREEMPTIVE;
9841     } CONTRACTL_END;
9842
9843     DWORD result = (DWORD)-1;
9844
9845     if (ppIndirection != NULL)
9846         *ppIndirection = NULL;
9847
9848     JIT_TO_EE_TRANSITION();
9849
9850 #if !defined(CROSSGEN_COMPILE) && !defined(FEATURE_IMPLICIT_TLS)
9851     result = GetThreadTLSIndex();
9852
9853     // The JIT can use the optimized TLS access only if the runtime is using it as well.
9854     //  (This is necessaryto make managed code work well under appverifier.)
9855     if (GetTLSAccessMode(result) == TLSACCESS_GENERIC)
9856         result = (DWORD)-1;
9857 #endif
9858
9859     EE_TO_JIT_TRANSITION();
9860
9861     return result;
9862 }
9863
9864 const void * CEEInfo::getInlinedCallFrameVptr(void **ppIndirection)
9865 {
9866     CONTRACTL {
9867         SO_TOLERANT;
9868         NOTHROW;
9869         GC_NOTRIGGER;
9870         MODE_PREEMPTIVE;
9871     } CONTRACTL_END;
9872
9873     void * result = NULL;
9874
9875     if (ppIndirection != NULL)
9876         *ppIndirection = NULL;
9877
9878     JIT_TO_EE_TRANSITION_LEAF();
9879
9880 #ifndef CROSSGEN_COMPILE
9881     result = (void*)InlinedCallFrame::GetMethodFrameVPtr();
9882 #else
9883     result = (void*)0x43210;
9884 #endif
9885
9886     EE_TO_JIT_TRANSITION_LEAF();
9887
9888     return result;
9889 }
9890
9891 LONG * CEEInfo::getAddrOfCaptureThreadGlobal(void **ppIndirection)
9892 {
9893     CONTRACTL {
9894         SO_TOLERANT;
9895         NOTHROW;
9896         GC_NOTRIGGER;
9897         MODE_PREEMPTIVE;
9898     } CONTRACTL_END;
9899
9900     LONG * result = NULL;
9901
9902     if (ppIndirection != NULL)
9903         *ppIndirection = NULL;
9904
9905     JIT_TO_EE_TRANSITION_LEAF();
9906
9907     result = (LONG *)&g_TrapReturningThreads;
9908
9909     EE_TO_JIT_TRANSITION_LEAF();
9910
9911     return result;
9912 }
9913
9914
9915
9916 HRESULT CEEInfo::GetErrorHRESULT(struct _EXCEPTION_POINTERS *pExceptionPointers)
9917 {
9918     CONTRACTL {
9919         SO_TOLERANT;
9920         NOTHROW;
9921         GC_TRIGGERS;
9922         MODE_ANY;
9923     } CONTRACTL_END;
9924
9925     HRESULT hr = S_OK;
9926
9927     //This function is called from the JIT64 exception filter during PEVerify.  Because it is a filter, it
9928     //can be "called" from a NOTHROW region in the case of StackOverflow.  Security::MapToHR throws
9929     //internally, but it catches all exceptions.  Therefore, none of the children can cause an exception to
9930     //percolate out of this function (except for Stack Overflow).  Obviously I can't explain most of this to
9931     //the Contracts system, and I can't add this CONTRACT_VIOLATION to the filter in Jit64.
9932     CONTRACT_VIOLATION(ThrowsViolation);
9933
9934     JIT_TO_EE_TRANSITION();
9935
9936     GCX_COOP();
9937
9938     OBJECTREF throwable = GetThread()->LastThrownObject();
9939     hr = GetExceptionHResult(throwable);
9940
9941     EE_TO_JIT_TRANSITION();
9942
9943     return hr;
9944 }
9945
9946
9947 ULONG CEEInfo::GetErrorMessage(__inout_ecount(bufferLength) LPWSTR buffer, ULONG bufferLength)
9948 {
9949     CONTRACTL {
9950         SO_TOLERANT;
9951         THROWS;
9952         GC_TRIGGERS;
9953         MODE_PREEMPTIVE;
9954     } CONTRACTL_END;
9955
9956     ULONG result = 0;
9957
9958 #ifndef CROSSGEN_COMPILE
9959     JIT_TO_EE_TRANSITION();
9960
9961     GCX_COOP();
9962
9963     OBJECTREF throwable = GetThread()->LastThrownObject();
9964
9965     if (throwable != NULL)
9966     {
9967         EX_TRY
9968         {
9969             result = GetExceptionMessage(throwable, buffer, bufferLength);
9970         }
9971         EX_CATCH
9972         {
9973         }
9974         EX_END_CATCH(SwallowAllExceptions)
9975     }
9976
9977     EE_TO_JIT_TRANSITION();
9978 #endif
9979
9980     return result;
9981 }
9982
9983 // This method is called from CEEInfo::FilterException which
9984 // is run as part of the SEH filter clause for the JIT.
9985 // It is fatal to throw an exception while running a SEH filter clause
9986 // so our contract is NOTHROW, NOTRIGGER.
9987 //
9988 LONG EEFilterException(struct _EXCEPTION_POINTERS *pExceptionPointers, void *unused)
9989 {
9990     CONTRACTL {
9991         SO_TOLERANT;
9992         NOTHROW;
9993         GC_NOTRIGGER;
9994     } CONTRACTL_END;
9995
9996     int result = 0;
9997
9998     JIT_TO_EE_TRANSITION_LEAF();
9999
10000     VALIDATE_BACKOUT_STACK_CONSUMPTION;
10001
10002     unsigned code = pExceptionPointers->ExceptionRecord->ExceptionCode;
10003
10004 #ifdef _DEBUG
10005     if (code == EXCEPTION_ACCESS_VIOLATION)
10006     {
10007         static int hit = 0;
10008         if (hit++ == 0)
10009         {
10010             _ASSERTE(!"Access violation while Jitting!");
10011             // If you set the debugger to catch access violations and 'go'
10012             // you will get back to the point at which the access violation occurred
10013             result = EXCEPTION_CONTINUE_EXECUTION;
10014         }
10015         else
10016         {
10017             result = EXCEPTION_CONTINUE_SEARCH;
10018         }
10019     }
10020     else
10021 #endif // _DEBUG
10022     // No one should be catching breakpoint
10023     // Similarly the JIT doesn't know how to reset the guard page, so it shouldn't
10024     // be catching a hard stack overflow
10025     if (code == EXCEPTION_BREAKPOINT || code == EXCEPTION_SINGLE_STEP || code == EXCEPTION_STACK_OVERFLOW)
10026     {
10027         result = EXCEPTION_CONTINUE_SEARCH;
10028     }
10029 #ifdef CROSSGEN_COMPILE
10030     else
10031     {
10032         result = EXCEPTION_EXECUTE_HANDLER;
10033     }
10034 #else
10035     else if (!IsComPlusException(pExceptionPointers->ExceptionRecord))
10036     {
10037         result = EXCEPTION_EXECUTE_HANDLER;
10038     }
10039     else
10040     {
10041         GCX_COOP();
10042
10043         // This is actually the LastThrown exception object.
10044         OBJECTREF throwable = CLRException::GetThrowableFromExceptionRecord(pExceptionPointers->ExceptionRecord);
10045
10046         if (throwable != NULL)
10047         {
10048             struct 
10049             {
10050                 OBJECTREF oLastThrownObject;
10051             } _gc;
10052
10053             ZeroMemory(&_gc, sizeof(_gc));
10054             
10055             // Setup the throwables
10056             _gc.oLastThrownObject = throwable;
10057
10058             GCPROTECT_BEGIN(_gc);
10059
10060             // Don't catch ThreadAbort and other uncatchable exceptions
10061             if (IsUncatchable(&_gc.oLastThrownObject))
10062                 result = EXCEPTION_CONTINUE_SEARCH;
10063             else
10064                 result = EXCEPTION_EXECUTE_HANDLER;
10065             
10066             GCPROTECT_END();
10067         }
10068     }
10069 #endif
10070
10071     EE_TO_JIT_TRANSITION_LEAF();
10072
10073     return result;
10074 }
10075
10076 int CEEInfo::FilterException(struct _EXCEPTION_POINTERS *pExceptionPointers)
10077 {
10078     WRAPPER_NO_CONTRACT;
10079     return EEFilterException(pExceptionPointers, nullptr);
10080 }
10081
10082 // This code is called if FilterException chose to handle the exception.
10083 void CEEInfo::HandleException(struct _EXCEPTION_POINTERS *pExceptionPointers)
10084 {
10085     CONTRACTL {
10086         SO_TOLERANT;
10087         NOTHROW;
10088         GC_NOTRIGGER;
10089     } CONTRACTL_END;
10090
10091     JIT_TO_EE_TRANSITION_LEAF();
10092
10093 #ifndef CROSSGEN_COMPILE
10094     if (IsComPlusException(pExceptionPointers->ExceptionRecord))
10095     {
10096         GCX_COOP();
10097
10098         // This is actually the LastThrown exception object.
10099         OBJECTREF throwable = CLRException::GetThrowableFromExceptionRecord(pExceptionPointers->ExceptionRecord);
10100
10101         if (throwable != NULL)
10102         {
10103             struct 
10104             {
10105                 OBJECTREF oLastThrownObject;
10106                 OBJECTREF oCurrentThrowable;
10107             } _gc;
10108
10109             ZeroMemory(&_gc, sizeof(_gc));
10110             
10111             PTR_Thread pCurThread = GetThread();
10112
10113             // Setup the throwables
10114             _gc.oLastThrownObject = throwable;
10115
10116             // This will be NULL if no managed exception is active. Otherwise,
10117             // it will reference the active throwable.
10118             _gc.oCurrentThrowable = pCurThread->GetThrowable(); 
10119
10120             GCPROTECT_BEGIN(_gc);
10121
10122             // JIT does not use or reference managed exceptions at all and simply swallows them,
10123             // or lets them fly through so that they will either get caught in managed code, the VM
10124             // or will go unhandled. 
10125             //
10126             // Blind swallowing of managed exceptions can break the semantic of "which exception handler"
10127             // gets to process the managed exception first. The expected handler is managed code exception 
10128             // handler (e.g. COMPlusFrameHandler on x86 and ProcessCLRException on 64bit) which will setup 
10129             // the exception tracker for the exception that will enable the expected sync between the 
10130             // LastThrownObject (LTO), setup in RaiseTheExceptionInternalOnly, and the exception tracker.
10131             // 
10132             // However, JIT can break this by swallowing the managed exception before managed code exception
10133             // handler gets a chance to setup an exception tracker for it. Since there is no cleanup
10134             // done for the swallowed exception as part of the unwind (because no exception tracker may have been setup), 
10135             // we need to reset the LTO, if it is out of sync from the active throwable.
10136             //
10137             // Hence, check if the LastThrownObject and active-exception throwable are in sync or not.
10138             // If not, bring them in sync.
10139             //
10140             // Example
10141             // -------
10142             // It is possible that an exception was already in progress and while processing it (e.g.
10143             // invoking finally block), we invoked JIT that had another managed exception @ JIT-EE transition boundary
10144             // that is swallowed by the JIT before managed code exception handler sees it. This breaks the sync between
10145             // LTO and the active exception in the exception tracker.
10146             if (_gc.oCurrentThrowable != _gc.oLastThrownObject)
10147             {
10148                 // Update the LTO. 
10149                 //
10150                 // Note: Incase of OOM, this will get set to OOM instance.
10151                 pCurThread->SafeSetLastThrownObject(_gc.oCurrentThrowable);
10152             }
10153  
10154             GCPROTECT_END();
10155         }
10156     }
10157 #endif
10158
10159     EE_TO_JIT_TRANSITION_LEAF();
10160 }
10161
10162 void ThrowExceptionForJit(HRESULT res);
10163
10164 void CEEInfo::ThrowExceptionForJitResult(
10165         HRESULT result)
10166 {
10167     CONTRACTL {
10168         SO_TOLERANT;
10169         THROWS;
10170         GC_TRIGGERS;
10171         MODE_PREEMPTIVE;
10172     } CONTRACTL_END;
10173
10174     JIT_TO_EE_TRANSITION();
10175
10176     if (!SUCCEEDED(result))
10177         ThrowExceptionForJit(result);
10178
10179     EE_TO_JIT_TRANSITION();
10180 }
10181
10182
10183 CORINFO_MODULE_HANDLE CEEInfo::embedModuleHandle(CORINFO_MODULE_HANDLE handle,
10184                                                  void **ppIndirection)
10185 {
10186     CONTRACTL {
10187         SO_TOLERANT;
10188         NOTHROW;
10189         GC_NOTRIGGER;
10190         MODE_PREEMPTIVE;
10191         PRECONDITION(!IsDynamicScope(handle));
10192     }
10193     CONTRACTL_END;
10194
10195     if (ppIndirection != NULL)
10196         *ppIndirection = NULL;
10197
10198     JIT_TO_EE_TRANSITION_LEAF();
10199
10200     EE_TO_JIT_TRANSITION_LEAF();
10201
10202     return handle;
10203 }
10204
10205 CORINFO_CLASS_HANDLE CEEInfo::embedClassHandle(CORINFO_CLASS_HANDLE handle,
10206                                                void **ppIndirection)
10207 {
10208     CONTRACTL {
10209         SO_TOLERANT;
10210         NOTHROW;
10211         GC_NOTRIGGER;
10212         MODE_PREEMPTIVE;
10213     }
10214     CONTRACTL_END;
10215
10216     if (ppIndirection != NULL)
10217         *ppIndirection = NULL;
10218
10219     JIT_TO_EE_TRANSITION_LEAF();
10220
10221     EE_TO_JIT_TRANSITION_LEAF();
10222
10223     return handle;
10224 }
10225
10226 CORINFO_FIELD_HANDLE CEEInfo::embedFieldHandle(CORINFO_FIELD_HANDLE handle,
10227                                                void **ppIndirection)
10228 {
10229     CONTRACTL {
10230         SO_TOLERANT;
10231         NOTHROW;
10232         GC_NOTRIGGER;
10233         MODE_PREEMPTIVE;
10234     }
10235     CONTRACTL_END;
10236
10237     if (ppIndirection != NULL)
10238         *ppIndirection = NULL;
10239
10240     JIT_TO_EE_TRANSITION_LEAF();
10241
10242     EE_TO_JIT_TRANSITION_LEAF();
10243
10244     return handle;
10245 }
10246
10247 CORINFO_METHOD_HANDLE CEEInfo::embedMethodHandle(CORINFO_METHOD_HANDLE handle,
10248                                                  void **ppIndirection)
10249 {
10250     CONTRACTL {
10251         SO_TOLERANT;
10252         NOTHROW;
10253         GC_NOTRIGGER;
10254         MODE_PREEMPTIVE;
10255     }
10256     CONTRACTL_END;
10257
10258     if (ppIndirection != NULL)
10259         *ppIndirection = NULL;
10260
10261     JIT_TO_EE_TRANSITION_LEAF();
10262
10263     EE_TO_JIT_TRANSITION_LEAF();
10264
10265     return handle;
10266 }
10267
10268 /*********************************************************************/
10269 void CEEInfo::setJitFlags(const CORJIT_FLAGS& jitFlags)
10270 {
10271     LIMITED_METHOD_CONTRACT;
10272
10273     m_jitFlags = jitFlags;
10274 }
10275
10276 /*********************************************************************/
10277 DWORD CEEInfo::getJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes)
10278 {
10279     CONTRACTL {
10280         SO_TOLERANT;
10281         NOTHROW;
10282         GC_NOTRIGGER;
10283         MODE_PREEMPTIVE;
10284     } CONTRACTL_END;
10285
10286     JIT_TO_EE_TRANSITION_LEAF();
10287
10288     _ASSERTE(sizeInBytes >= sizeof(m_jitFlags));
10289     *jitFlags = m_jitFlags;
10290
10291     EE_TO_JIT_TRANSITION_LEAF();
10292
10293     return sizeof(m_jitFlags);
10294 }
10295
10296 /*********************************************************************/
10297 #if !defined(PLATFORM_UNIX)
10298
10299 struct RunWithErrorTrapFilterParam
10300 {
10301     ICorDynamicInfo* m_corInfo;
10302     void (*m_function)(void*);
10303     void* m_param;
10304     EXCEPTION_POINTERS m_exceptionPointers;
10305 };
10306
10307 static LONG RunWithErrorTrapFilter(struct _EXCEPTION_POINTERS* exceptionPointers, void* theParam)
10308 {
10309     WRAPPER_NO_CONTRACT;
10310
10311     auto* param = reinterpret_cast<RunWithErrorTrapFilterParam*>(theParam);
10312     param->m_exceptionPointers = *exceptionPointers;
10313     return param->m_corInfo->FilterException(exceptionPointers);
10314 }
10315
10316 #endif // !defined(PLATFORM_UNIX)
10317
10318 bool CEEInfo::runWithErrorTrap(void (*function)(void*), void* param)
10319 {
10320     // No dynamic contract here because SEH is used
10321     STATIC_CONTRACT_THROWS;
10322     STATIC_CONTRACT_GC_TRIGGERS;
10323     STATIC_CONTRACT_SO_TOLERANT;
10324     STATIC_CONTRACT_MODE_PREEMPTIVE;
10325
10326     // NOTE: the lack of JIT/EE transition markers in this method is intentional. Any
10327     //       transitions into the EE proper should occur either via the call to
10328     //       `EEFilterException` (which is appropraitely marked) or via JIT/EE
10329     //       interface calls made by `function`.
10330
10331     bool success = true;
10332
10333 #if !defined(PLATFORM_UNIX)
10334
10335     RunWithErrorTrapFilterParam trapParam;
10336     trapParam.m_corInfo = m_pOverride == nullptr ? this : m_pOverride;
10337     trapParam.m_function = function;
10338     trapParam.m_param = param;
10339
10340     PAL_TRY(RunWithErrorTrapFilterParam*, pTrapParam, &trapParam)
10341     {
10342         pTrapParam->m_function(pTrapParam->m_param);
10343     }
10344     PAL_EXCEPT_FILTER(RunWithErrorTrapFilter)
10345     {
10346         HandleException(&trapParam.m_exceptionPointers);
10347         success = false;
10348     }
10349     PAL_ENDTRY
10350
10351 #else // !defined(PLATFORM_UNIX)
10352
10353     // We shouldn't need PAL_TRY on *nix: any exceptions that we are able to catch
10354     // ought to originate from the runtime itself and should be catchable inside of
10355     // EX_TRY/EX_CATCH, including emulated SEH exceptions.
10356     EX_TRY
10357     {
10358         function(param);
10359     }
10360     EX_CATCH
10361     {
10362         success = false;
10363     }
10364     EX_END_CATCH(RethrowTerminalExceptions);
10365
10366 #endif
10367
10368     return success;
10369 }
10370
10371 /*********************************************************************/
10372 IEEMemoryManager* CEEInfo::getMemoryManager()
10373 {
10374     CONTRACTL {
10375         SO_TOLERANT;
10376         NOTHROW;
10377         GC_NOTRIGGER;
10378         MODE_PREEMPTIVE;
10379     } CONTRACTL_END;
10380
10381     IEEMemoryManager* result = NULL;
10382
10383     JIT_TO_EE_TRANSITION_LEAF();
10384
10385     result = GetEEMemoryManager();
10386
10387     EE_TO_JIT_TRANSITION_LEAF();
10388
10389     return result;
10390 }
10391
10392 /*********************************************************************/
10393 int CEEInfo::doAssert(const char* szFile, int iLine, const char* szExpr)
10394 {
10395     STATIC_CONTRACT_SO_TOLERANT;
10396     STATIC_CONTRACT_THROWS;
10397     STATIC_CONTRACT_GC_TRIGGERS;
10398     STATIC_CONTRACT_MODE_PREEMPTIVE;
10399     STATIC_CONTRACT_DEBUG_ONLY;
10400
10401     int result = 0;
10402
10403     JIT_TO_EE_TRANSITION();
10404
10405 #ifdef CROSSGEN_COMPILE
10406     ThrowHR(COR_E_INVALIDPROGRAM);
10407 #else
10408
10409 #ifdef _DEBUG
10410     BEGIN_DEBUG_ONLY_CODE;
10411     result = _DbgBreakCheck(szFile, iLine, szExpr);
10412     END_DEBUG_ONLY_CODE;
10413 #else // !_DEBUG
10414     result = 1;   // break into debugger
10415 #endif // !_DEBUG
10416
10417 #endif
10418
10419     EE_TO_JIT_TRANSITION();
10420
10421     return result;
10422 }
10423
10424 void CEEInfo::reportFatalError(CorJitResult result)
10425 {
10426     STATIC_CONTRACT_SO_TOLERANT;
10427     STATIC_CONTRACT_THROWS;
10428     STATIC_CONTRACT_GC_TRIGGERS;
10429     STATIC_CONTRACT_MODE_PREEMPTIVE;
10430
10431     JIT_TO_EE_TRANSITION_LEAF();
10432
10433     STRESS_LOG2(LF_JIT,LL_ERROR, "Jit reported error 0x%x while compiling 0x%p\n",
10434                 (int)result, (INT_PTR)getMethodBeingCompiled());
10435
10436     EE_TO_JIT_TRANSITION_LEAF();
10437 }
10438
10439 BOOL CEEInfo::logMsg(unsigned level, const char* fmt, va_list args)
10440 {
10441     STATIC_CONTRACT_SO_TOLERANT;
10442     STATIC_CONTRACT_THROWS;
10443     STATIC_CONTRACT_GC_TRIGGERS;
10444     STATIC_CONTRACT_MODE_PREEMPTIVE;
10445     STATIC_CONTRACT_DEBUG_ONLY;
10446
10447     BOOL result = FALSE;
10448
10449     JIT_TO_EE_TRANSITION_LEAF();
10450
10451 #ifdef LOGGING
10452     if (LoggingOn(LF_JIT, level))
10453     {
10454         LogSpewValist(LF_JIT, level, (char*) fmt, args);
10455         result = TRUE;
10456     }
10457 #endif // LOGGING
10458
10459     EE_TO_JIT_TRANSITION_LEAF();
10460
10461     return result;
10462 }
10463
10464 void CEEInfo::yieldExecution()
10465 {
10466     WRAPPER_NO_CONTRACT;
10467 }
10468
10469
10470 #ifndef CROSSGEN_COMPILE
10471
10472 /*********************************************************************/
10473
10474 void* CEEJitInfo::getHelperFtn(CorInfoHelpFunc    ftnNum,         /* IN  */
10475                                void **            ppIndirection)  /* OUT */
10476 {
10477     CONTRACTL {
10478         SO_TOLERANT;
10479         NOTHROW;
10480         GC_NOTRIGGER;
10481         MODE_PREEMPTIVE;
10482     } CONTRACTL_END;
10483
10484     void* result = NULL;
10485
10486     if (ppIndirection != NULL)
10487         *ppIndirection = NULL;
10488
10489     JIT_TO_EE_TRANSITION_LEAF();
10490
10491     _ASSERTE(ftnNum < CORINFO_HELP_COUNT);
10492
10493     void* pfnHelper = hlpFuncTable[ftnNum].pfnHelper;
10494
10495     size_t dynamicFtnNum = ((size_t)pfnHelper - 1);
10496     if (dynamicFtnNum < DYNAMIC_CORINFO_HELP_COUNT)
10497     {
10498 #ifdef _PREFAST_
10499 #pragma warning(push)
10500 #pragma warning(disable:26001) // "Bounds checked above using the underflow trick"
10501 #endif /*_PREFAST_ */
10502
10503 #if defined(_TARGET_AMD64_)
10504         // To avoid using a jump stub we always call certain helpers using an indirect call.
10505         // Because when using a direct call and the target is father away than 2^31 bytes,
10506         // the direct call instead goes to a jump stub which jumps to the jit helper.
10507         // However in this process the jump stub will corrupt RAX.
10508         //
10509         // The set of helpers for which RAX must be preserved are the profiler probes
10510         // and the STOP_FOR_GC helper which maps to JIT_RareDisableHelper.
10511         // In the case of the STOP_FOR_GC helper RAX can be holding a function return value.
10512         //
10513         if (dynamicFtnNum == DYNAMIC_CORINFO_HELP_STOP_FOR_GC    ||
10514             dynamicFtnNum == DYNAMIC_CORINFO_HELP_PROF_FCN_ENTER ||
10515             dynamicFtnNum == DYNAMIC_CORINFO_HELP_PROF_FCN_LEAVE ||
10516             dynamicFtnNum == DYNAMIC_CORINFO_HELP_PROF_FCN_TAILCALL)
10517         {
10518             _ASSERTE(ppIndirection != NULL);
10519             *ppIndirection = &hlpDynamicFuncTable[dynamicFtnNum].pfnHelper;
10520             return NULL;
10521         }
10522 #endif
10523
10524 #if defined(ENABLE_FAST_GCPOLL_HELPER)
10525         //always call this indirectly so that we can swap GC Poll helpers.
10526         if (dynamicFtnNum == DYNAMIC_CORINFO_HELP_POLL_GC)
10527         {
10528             _ASSERTE(ppIndirection != NULL);
10529             *ppIndirection = &hlpDynamicFuncTable[dynamicFtnNum].pfnHelper;
10530             return NULL;
10531         }
10532 #endif
10533
10534         pfnHelper = hlpDynamicFuncTable[dynamicFtnNum].pfnHelper;
10535
10536 #ifdef _PREFAST_
10537 #pragma warning(pop)
10538 #endif /*_PREFAST_*/
10539     }
10540
10541     _ASSERTE(pfnHelper);
10542
10543     result = (LPVOID)GetEEFuncEntryPoint(pfnHelper);
10544
10545     EE_TO_JIT_TRANSITION_LEAF();
10546
10547     return result;
10548 }
10549
10550 PCODE CEEJitInfo::getHelperFtnStatic(CorInfoHelpFunc ftnNum)
10551 {
10552     LIMITED_METHOD_CONTRACT;
10553
10554     void* pfnHelper = hlpFuncTable[ftnNum].pfnHelper;
10555
10556     // If pfnHelper is an index into the dynamic helper table, it should be less 
10557     // than DYNAMIC_CORINFO_HELP_COUNT.  In this case we need to find the actual pfnHelper 
10558     // using an extra indirection.  Note the special case
10559     // where pfnHelper==0 where pfnHelper-1 will underflow and we will avoid the indirection.
10560     if (((size_t)pfnHelper - 1) < DYNAMIC_CORINFO_HELP_COUNT)
10561     {
10562         pfnHelper = hlpDynamicFuncTable[((size_t)pfnHelper - 1)].pfnHelper;
10563     }
10564
10565     _ASSERTE(pfnHelper != NULL);
10566
10567     return GetEEFuncEntryPoint(pfnHelper);
10568 }
10569
10570 void CEEJitInfo::addActiveDependency(CORINFO_MODULE_HANDLE moduleFrom,CORINFO_MODULE_HANDLE moduleTo)
10571 {
10572     CONTRACTL
10573     {
10574         STANDARD_VM_CHECK;
10575         PRECONDITION(CheckPointer(moduleFrom));
10576         PRECONDITION(!IsDynamicScope(moduleFrom));
10577         PRECONDITION(CheckPointer(moduleTo));
10578         PRECONDITION(!IsDynamicScope(moduleTo));
10579         PRECONDITION(moduleFrom != moduleTo);
10580     }
10581     CONTRACTL_END;
10582
10583     // This is only called internaly. JIT-EE transition is not needed.
10584     // JIT_TO_EE_TRANSITION();
10585
10586     Module *dependency = (Module *)moduleTo;
10587     _ASSERTE(!dependency->IsSystem());
10588
10589     if (m_pMethodBeingCompiled->IsLCGMethod())
10590     {
10591         // The context module of the m_pMethodBeingCompiled is irrelevant.  Rather than tracking
10592         // the dependency, we just do immediate activation.
10593         dependency->EnsureActive();
10594     }
10595     else
10596     {
10597 #ifdef FEATURE_LOADER_OPTIMIZATION
10598         Module *context = (Module *)moduleFrom;
10599
10600         // Record active dependency for loader.
10601         context->AddActiveDependency(dependency, FALSE);
10602 #else
10603         dependency->EnsureActive();
10604 #endif
10605     }
10606
10607     // EE_TO_JIT_TRANSITION();
10608 }
10609
10610
10611 // Wrapper around CEEInfo::GetProfilingHandle.  The first time this is called for a
10612 // method desc, it calls through to EEToProfInterfaceImpl::EEFunctionIDMappe and caches the
10613 // result in CEEJitInfo::GetProfilingHandleCache.  Thereafter, this wrapper regurgitates the cached values
10614 // rather than calling into CEEInfo::GetProfilingHandle each time.  This avoids
10615 // making duplicate calls into the profiler's FunctionIDMapper callback.
10616 void CEEJitInfo::GetProfilingHandle(BOOL                      *pbHookFunction,
10617                                     void                     **pProfilerHandle,
10618                                     BOOL                      *pbIndirectedHandles)
10619 {
10620     CONTRACTL {
10621         SO_TOLERANT;
10622         THROWS;
10623         GC_TRIGGERS;
10624         MODE_PREEMPTIVE;
10625     } CONTRACTL_END;
10626     
10627     _ASSERTE(pbHookFunction != NULL);
10628     _ASSERTE(pProfilerHandle != NULL);
10629     _ASSERTE(pbIndirectedHandles != NULL);
10630     
10631     if (!m_gphCache.m_bGphIsCacheValid)
10632     {
10633 #ifdef PROFILING_SUPPORTED
10634         JIT_TO_EE_TRANSITION();
10635
10636         // Cache not filled in, so make our first and only call to CEEInfo::GetProfilingHandle here        
10637
10638         // methods with no metadata behind cannot be exposed to tools expecting metadata (profiler, debugger...)
10639         // they shouldnever come here as they are called out in GetCompileFlag
10640         _ASSERTE(!m_pMethodBeingCompiled->IsNoMetadata());
10641
10642         // We pass in the typical method definition to the function mapper because in
10643         // Whidbey all the profiling API transactions are done in terms of typical
10644         // method definitions not instantiations.
10645         BOOL bHookFunction = TRUE;
10646         void * profilerHandle = m_pMethodBeingCompiled;
10647
10648         {
10649             BEGIN_PIN_PROFILER(CORProfilerFunctionIDMapperEnabled());
10650             profilerHandle = (void *)g_profControlBlock.pProfInterface->EEFunctionIDMapper((FunctionID) m_pMethodBeingCompiled, &bHookFunction);
10651             END_PIN_PROFILER();
10652         }
10653
10654         m_gphCache.m_pvGphProfilerHandle = profilerHandle;
10655         m_gphCache.m_bGphHookFunction = (bHookFunction != FALSE);
10656         m_gphCache.m_bGphIsCacheValid = true;
10657
10658         EE_TO_JIT_TRANSITION();
10659 #endif //PROFILING_SUPPORTED
10660     }
10661         
10662     // Our cache of these values are bitfield bools, but the interface requires
10663     // BOOL.  So to avoid setting aside a staging area on the stack for these
10664     // values, we filled them in directly in the if (not cached yet) case.
10665     *pbHookFunction = (m_gphCache.m_bGphHookFunction != false);
10666
10667     // At this point, the remaining values must be in the cache by now, so use them  
10668     *pProfilerHandle = m_gphCache.m_pvGphProfilerHandle;
10669
10670     //
10671     // This is the JIT case, which is never indirected.
10672     //
10673     *pbIndirectedHandles = FALSE;
10674 }
10675
10676 /*********************************************************************/
10677 void CEEJitInfo::BackoutJitData(EEJitManager * jitMgr)
10678 {
10679     CONTRACTL {
10680         NOTHROW;
10681         GC_TRIGGERS;
10682     } CONTRACTL_END;
10683
10684     CodeHeader* pCodeHeader = GetCodeHeader();
10685     if (pCodeHeader)
10686         jitMgr->RemoveJitData(pCodeHeader, m_GCinfo_len, m_EHinfo_len);
10687 }
10688
10689 /*********************************************************************/
10690 // Route jit information to the Jit Debug store.
10691 void CEEJitInfo::setBoundaries(CORINFO_METHOD_HANDLE ftn, ULONG32 cMap,
10692                                ICorDebugInfo::OffsetMapping *pMap)
10693 {
10694     CONTRACTL {
10695         SO_TOLERANT;
10696         THROWS;
10697         GC_TRIGGERS;
10698         MODE_PREEMPTIVE;
10699     } CONTRACTL_END;
10700
10701     JIT_TO_EE_TRANSITION();
10702
10703     // We receive ownership of the array
10704     _ASSERTE(m_pOffsetMapping == NULL && m_iOffsetMapping == 0);
10705     m_iOffsetMapping = cMap;
10706     m_pOffsetMapping = pMap;
10707
10708     EE_TO_JIT_TRANSITION();
10709 }
10710
10711 void CEEJitInfo::setVars(CORINFO_METHOD_HANDLE ftn, ULONG32 cVars, ICorDebugInfo::NativeVarInfo *vars)
10712 {
10713     CONTRACTL {
10714         SO_TOLERANT;
10715         THROWS;
10716         GC_TRIGGERS;
10717         MODE_PREEMPTIVE;
10718     } CONTRACTL_END;
10719
10720     JIT_TO_EE_TRANSITION();
10721
10722     // We receive ownership of the array
10723     _ASSERTE(m_pNativeVarInfo == NULL && m_iNativeVarInfo == 0);
10724     m_iNativeVarInfo = cVars;
10725     m_pNativeVarInfo = vars;
10726
10727     EE_TO_JIT_TRANSITION();
10728 }
10729
10730 void CEEJitInfo::CompressDebugInfo()
10731 {
10732     CONTRACTL {
10733         SO_TOLERANT;
10734         THROWS;
10735         GC_TRIGGERS;
10736         MODE_PREEMPTIVE;
10737     } CONTRACTL_END;
10738
10739     // Don't track JIT info for DynamicMethods.
10740     if (m_pMethodBeingCompiled->IsDynamicMethod())
10741         return;
10742
10743     if (m_iOffsetMapping == 0 && m_iNativeVarInfo == 0)
10744         return;
10745
10746     JIT_TO_EE_TRANSITION();
10747
10748     EX_TRY
10749     {
10750         PTR_BYTE pDebugInfo = CompressDebugInfo::CompressBoundariesAndVars(
10751             m_pOffsetMapping, m_iOffsetMapping,
10752             m_pNativeVarInfo, m_iNativeVarInfo,
10753             NULL, 
10754             m_pMethodBeingCompiled->GetLoaderAllocator()->GetLowFrequencyHeap());
10755
10756         GetCodeHeader()->SetDebugInfo(pDebugInfo);
10757     }
10758     EX_CATCH
10759     {
10760         // Just ignore exceptions here. The debugger's structures will still be in a consistent state.
10761     }
10762     EX_END_CATCH(SwallowAllExceptions)
10763
10764     EE_TO_JIT_TRANSITION();
10765 }
10766
10767 void reservePersonalityRoutineSpace(ULONG &unwindSize)
10768 {
10769 #if defined(_TARGET_X86_)
10770     // Do nothing
10771 #elif defined(_TARGET_AMD64_)
10772     // Add space for personality routine, it must be 4-byte aligned.
10773     // Everything in the UNWIND_INFO up to the variable-sized UnwindCodes
10774     // array has already had its size included in unwindSize by the caller.
10775     unwindSize += sizeof(ULONG);
10776
10777     // Note that the count of unwind codes (2 bytes each) is stored as a UBYTE
10778     // So the largest size could be 510 bytes, plus the header and language
10779     // specific stuff.  This can't overflow.
10780
10781     _ASSERTE(FitsInU4(unwindSize + sizeof(ULONG)));
10782     unwindSize = (ULONG)(ALIGN_UP(unwindSize, sizeof(ULONG)));
10783 #elif defined(_TARGET_ARM_) || defined(_TARGET_ARM64_)
10784     // The JIT passes in a 4-byte aligned block of unwind data.
10785     _ASSERTE(IS_ALIGNED(unwindSize, sizeof(ULONG)));
10786
10787     // Add space for personality routine, it must be 4-byte aligned.
10788     unwindSize += sizeof(ULONG);
10789 #else
10790     PORTABILITY_ASSERT("reservePersonalityRoutineSpace");
10791 #endif // !defined(_TARGET_AMD64_)
10792
10793 }
10794 // Reserve memory for the method/funclet's unwind information.
10795 // Note that this must be called before allocMem. It should be
10796 // called once for the main method, once for every funclet, and
10797 // once for every block of cold code for which allocUnwindInfo
10798 // will be called.
10799 //
10800 // This is necessary because jitted code must allocate all the
10801 // memory needed for the unwindInfo at the allocMem call.
10802 // For prejitted code we split up the unwinding information into
10803 // separate sections .rdata and .pdata.
10804 //
10805 void CEEJitInfo::reserveUnwindInfo(BOOL isFunclet, BOOL isColdCode, ULONG unwindSize)
10806 {
10807 #ifdef WIN64EXCEPTIONS
10808     CONTRACTL {
10809         SO_TOLERANT;
10810         NOTHROW;
10811         GC_NOTRIGGER;
10812         MODE_PREEMPTIVE;
10813     }
10814     CONTRACTL_END;
10815
10816     JIT_TO_EE_TRANSITION_LEAF();
10817
10818     CONSISTENCY_CHECK_MSG(!isColdCode, "Hot/Cold splitting is not supported in jitted code");
10819     _ASSERTE_MSG(m_theUnwindBlock == NULL,
10820         "reserveUnwindInfo() can only be called before allocMem(), but allocMem() has already been called. "
10821         "This may indicate the JIT has hit a NO_WAY assert after calling allocMem(), and is re-JITting. "
10822         "Set COMPlus_JitBreakOnBadCode=1 and rerun to get the real error.");
10823
10824     ULONG currentSize  = unwindSize;
10825
10826     reservePersonalityRoutineSpace(currentSize);
10827
10828     m_totalUnwindSize += currentSize;
10829
10830     m_totalUnwindInfos++;
10831
10832     EE_TO_JIT_TRANSITION_LEAF();
10833 #else // WIN64EXCEPTIONS
10834     LIMITED_METHOD_CONTRACT;
10835     // Dummy implementation to make cross-platform altjit work
10836 #endif // WIN64EXCEPTIONS
10837 }
10838
10839 // Allocate and initialize the .rdata and .pdata for this method or
10840 // funclet and get the block of memory needed for the machine specific
10841 // unwind information (the info for crawling the stack frame).
10842 // Note that allocMem must be called first.
10843 //
10844 // The pHotCode parameter points at the first byte of the code of the method
10845 // The startOffset and endOffset are the region (main or funclet) that
10846 // we are to allocate and create .rdata and .pdata for.
10847 // The pUnwindBlock is copied and contains the .pdata unwind area
10848 //
10849 // Parameters:
10850 //
10851 //    pHotCode        main method code buffer, always filled in
10852 //    pColdCode       always NULL for jitted code
10853 //    startOffset     start of code block, relative to pHotCode
10854 //    endOffset       end of code block, relative to pHotCode
10855 //    unwindSize      size of unwind info pointed to by pUnwindBlock
10856 //    pUnwindBlock    pointer to unwind info
10857 //    funcKind        type of funclet (main method code, handler, filter)
10858 //
10859 void CEEJitInfo::allocUnwindInfo (
10860         BYTE *              pHotCode,              /* IN */
10861         BYTE *              pColdCode,             /* IN */
10862         ULONG               startOffset,           /* IN */
10863         ULONG               endOffset,             /* IN */
10864         ULONG               unwindSize,            /* IN */
10865         BYTE *              pUnwindBlock,          /* IN */
10866         CorJitFuncKind      funcKind               /* IN */
10867         )
10868 {
10869 #ifdef WIN64EXCEPTIONS
10870     CONTRACTL {
10871         SO_TOLERANT;
10872         THROWS;
10873         GC_TRIGGERS;
10874         MODE_PREEMPTIVE;
10875         PRECONDITION(m_theUnwindBlock != NULL);
10876         PRECONDITION(m_usedUnwindSize < m_totalUnwindSize);
10877         PRECONDITION(m_usedUnwindInfos < m_totalUnwindInfos);
10878         PRECONDITION(endOffset <= m_codeSize);
10879     } CONTRACTL_END;
10880
10881     CONSISTENCY_CHECK_MSG(pColdCode == NULL, "Hot/Cold code splitting not supported for jitted code");
10882
10883     JIT_TO_EE_TRANSITION();
10884
10885     //
10886     // We add one callback-type dynamic function table per range section.
10887     // Therefore, the RUNTIME_FUNCTION info is always relative to the
10888     // image base contained in the dynamic function table, which happens
10889     // to be the LowAddress of the range section.  The JIT has no
10890     // knowledge of the range section, so it gives us offsets that are
10891     // relative to the beginning of the method (pHotCode) and we allocate
10892     // and initialize the RUNTIME_FUNCTION data and record its location
10893     // in this function.
10894     //
10895
10896     if (funcKind != CORJIT_FUNC_ROOT)
10897     {
10898         // The main method should be emitted before funclets
10899         _ASSERTE(m_usedUnwindInfos > 0);
10900     }
10901
10902     PT_RUNTIME_FUNCTION pRuntimeFunction = m_CodeHeader->GetUnwindInfo(m_usedUnwindInfos);
10903     m_usedUnwindInfos++;
10904
10905     // Make sure that the RUNTIME_FUNCTION is aligned on a DWORD sized boundary
10906     _ASSERTE(IS_ALIGNED(pRuntimeFunction, sizeof(DWORD)));
10907
10908     UNWIND_INFO * pUnwindInfo = (UNWIND_INFO *) &(m_theUnwindBlock[m_usedUnwindSize]);
10909     m_usedUnwindSize += unwindSize;
10910
10911     reservePersonalityRoutineSpace(m_usedUnwindSize);
10912
10913     _ASSERTE(m_usedUnwindSize <= m_totalUnwindSize);
10914
10915     // Make sure that the UnwindInfo is aligned
10916     _ASSERTE(IS_ALIGNED(pUnwindInfo, sizeof(ULONG)));
10917
10918     /* Calculate Image Relative offset to add to the jit generated unwind offsets */     
10919
10920     TADDR baseAddress = m_moduleBase;
10921
10922     size_t currentCodeSizeT = (size_t)pHotCode - baseAddress;
10923
10924     /* Check if currentCodeSizeT offset fits in 32-bits */
10925     if (!FitsInU4(currentCodeSizeT))
10926     {
10927         _ASSERTE(!"Bad currentCodeSizeT");
10928         COMPlusThrowHR(E_FAIL);
10929     }
10930
10931     /* Check if EndAddress offset fits in 32-bit */
10932     if (!FitsInU4(currentCodeSizeT + endOffset))
10933     {
10934         _ASSERTE(!"Bad currentCodeSizeT");
10935         COMPlusThrowHR(E_FAIL);
10936     }
10937
10938     unsigned currentCodeOffset = (unsigned) currentCodeSizeT;
10939
10940     /* Calculate Unwind Info delta */
10941     size_t unwindInfoDeltaT = (size_t) pUnwindInfo - baseAddress;
10942
10943     /* Check if unwindDeltaT offset fits in 32-bits */
10944     if (!FitsInU4(unwindInfoDeltaT))
10945     {
10946         _ASSERTE(!"Bad unwindInfoDeltaT");
10947         COMPlusThrowHR(E_FAIL);
10948     }
10949
10950     unsigned unwindInfoDelta = (unsigned) unwindInfoDeltaT;
10951
10952     RUNTIME_FUNCTION__SetBeginAddress(pRuntimeFunction, currentCodeOffset + startOffset);
10953
10954 #ifdef _TARGET_AMD64_
10955     pRuntimeFunction->EndAddress        = currentCodeOffset + endOffset;
10956 #endif
10957
10958     RUNTIME_FUNCTION__SetUnwindInfoAddress(pRuntimeFunction, unwindInfoDelta);
10959
10960 #ifdef _DEBUG
10961     if (funcKind != CORJIT_FUNC_ROOT)
10962     {
10963         // Check the the new funclet doesn't overlap any existing funclet.
10964
10965         for (ULONG iUnwindInfo = 0; iUnwindInfo < m_usedUnwindInfos - 1; iUnwindInfo++)
10966         {
10967             PT_RUNTIME_FUNCTION pOtherFunction = m_CodeHeader->GetUnwindInfo(iUnwindInfo);
10968             _ASSERTE((   RUNTIME_FUNCTION__BeginAddress(pOtherFunction) >= RUNTIME_FUNCTION__EndAddress(pRuntimeFunction, baseAddress)
10969                      || RUNTIME_FUNCTION__EndAddress(pOtherFunction, baseAddress) <= RUNTIME_FUNCTION__BeginAddress(pRuntimeFunction)));
10970         }
10971     }
10972 #endif // _DEBUG
10973
10974     /* Copy the UnwindBlock */
10975     memcpy(pUnwindInfo, pUnwindBlock, unwindSize);
10976
10977 #if defined(_TARGET_X86_)
10978
10979     // Do NOTHING
10980
10981 #elif defined(_TARGET_AMD64_)
10982
10983     pUnwindInfo->Flags = UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER;
10984
10985     ULONG * pPersonalityRoutine = (ULONG*)ALIGN_UP(&(pUnwindInfo->UnwindCode[pUnwindInfo->CountOfUnwindCodes]), sizeof(ULONG));
10986     *pPersonalityRoutine = ExecutionManager::GetCLRPersonalityRoutineValue();
10987
10988 #elif defined(_TARGET_ARM64_)
10989
10990     *(LONG *)pUnwindInfo |= (1 << 20); // X bit
10991
10992     ULONG * pPersonalityRoutine = (ULONG*)((BYTE *)pUnwindInfo + ALIGN_UP(unwindSize, sizeof(ULONG)));
10993     *pPersonalityRoutine = ExecutionManager::GetCLRPersonalityRoutineValue();
10994
10995 #elif defined(_TARGET_ARM_)
10996
10997     *(LONG *)pUnwindInfo |= (1 << 20); // X bit
10998
10999     ULONG * pPersonalityRoutine = (ULONG*)((BYTE *)pUnwindInfo + ALIGN_UP(unwindSize, sizeof(ULONG)));
11000     *pPersonalityRoutine = (TADDR)ProcessCLRException - baseAddress;
11001
11002 #endif
11003
11004 #if defined(_TARGET_AMD64_)
11005     // Publish the new unwind information in a way that the ETW stack crawler can find
11006     if (m_usedUnwindInfos == m_totalUnwindInfos)
11007         UnwindInfoTable::PublishUnwindInfoForMethod(baseAddress, m_CodeHeader->GetUnwindInfo(0), m_totalUnwindInfos);
11008 #endif // defined(_TARGET_AMD64_)
11009
11010     EE_TO_JIT_TRANSITION();
11011 #else // WIN64EXCEPTIONS
11012     LIMITED_METHOD_CONTRACT;
11013     // Dummy implementation to make cross-platform altjit work
11014 #endif // WIN64EXCEPTIONS
11015 }
11016
11017 void CEEJitInfo::recordCallSite(ULONG                 instrOffset,
11018                                 CORINFO_SIG_INFO *    callSig,
11019                                 CORINFO_METHOD_HANDLE methodHandle)
11020 {
11021     // Currently, only testing tools use this method. The EE itself doesn't need record this information.
11022     // N.B. The memory that callSig points to is managed by the JIT and isn't guaranteed to be around after
11023     // this function returns, so future implementations should copy the sig info if they want it to persist.
11024     LIMITED_METHOD_CONTRACT;
11025 }
11026
11027 // This is a variant for AMD64 or other machines that
11028 // cannot always hold the destination address in a 32-bit location
11029 // A relocation is recorded if we are pre-jitting.
11030 // A jump thunk may be inserted if we are jitting
11031
11032 void CEEJitInfo::recordRelocation(void * location,
11033                                   void * target,
11034                                   WORD   fRelocType,
11035                                   WORD   slot,
11036                                   INT32  addlDelta)
11037 {
11038     CONTRACTL {
11039         SO_TOLERANT;
11040         THROWS;
11041         GC_TRIGGERS;
11042         MODE_PREEMPTIVE;
11043     } CONTRACTL_END;
11044
11045 #ifdef _WIN64
11046     JIT_TO_EE_TRANSITION();
11047
11048     INT64 delta;
11049
11050     switch (fRelocType)
11051     {
11052     case IMAGE_REL_BASED_DIR64:
11053         // Write 64-bits into location
11054         *((UINT64 *) ((BYTE *) location + slot)) = (UINT64) target;
11055         break;
11056
11057 #ifdef _TARGET_AMD64_
11058     case IMAGE_REL_BASED_REL32:
11059         {
11060             target = (BYTE *)target + addlDelta;
11061
11062             INT32 * fixupLocation = (INT32 *) ((BYTE *) location + slot);
11063             BYTE * baseAddr = (BYTE *)fixupLocation + sizeof(INT32);
11064
11065             delta  = (INT64)((BYTE *)target - baseAddr);
11066
11067             //
11068             // Do we need to insert a jump stub to make the source reach the target?
11069             //
11070             // Note that we cannot stress insertion of jump stub by inserting it unconditionally. JIT records the relocations 
11071             // for intra-module jumps and calls. It does not expect the register used by the jump stub to be trashed.
11072             //
11073             if (!FitsInI4(delta))
11074             {
11075                 if (m_fAllowRel32)
11076                 {
11077                     //
11078                     // When m_fAllowRel32 == TRUE, the JIT will use REL32s for both data addresses and direct code targets.
11079                     // Since we cannot tell what the relocation is for, we have to defensively retry.
11080                     //
11081                     m_fRel32Overflow = TRUE;
11082                     delta = 0;
11083                 }
11084                 else
11085                 {
11086                     //
11087                     // When m_fAllowRel32 == FALSE, the JIT will use a REL32s for direct code targets only.
11088                     // Use jump stub.
11089                     // 
11090                     delta = rel32UsingJumpStub(fixupLocation, (PCODE)target, m_pMethodBeingCompiled);
11091                 }
11092             }
11093
11094             LOG((LF_JIT, LL_INFO100000, "Encoded a PCREL32 at" FMT_ADDR "to" FMT_ADDR "+%d,  delta is 0x%04x\n",
11095                  DBG_ADDR(fixupLocation), DBG_ADDR(target), addlDelta, delta));
11096
11097             // Write the 32-bits pc-relative delta into location
11098             *fixupLocation = (INT32) delta;
11099         }
11100         break;
11101 #endif // _TARGET_AMD64_
11102
11103 #ifdef _TARGET_ARM64_
11104     case IMAGE_REL_ARM64_BRANCH26:   // 26 bit offset << 2 & sign ext, for B and BL
11105         {
11106             _ASSERTE(slot == 0);
11107             _ASSERTE(addlDelta == 0);
11108
11109             PCODE branchTarget  = (PCODE) target;
11110             _ASSERTE((branchTarget & 0x3) == 0);   // the low two bits must be zero
11111
11112             PCODE fixupLocation = (PCODE) location;
11113             _ASSERTE((fixupLocation & 0x3) == 0);  // the low two bits must be zero
11114
11115             delta = (INT64)(branchTarget - fixupLocation);
11116             _ASSERTE((delta & 0x3) == 0);          // the low two bits must be zero
11117
11118             UINT32 branchInstr = *((UINT32*) fixupLocation);
11119             branchInstr &= 0xFC000000;  // keep bits 31-26
11120             _ASSERTE((branchInstr & 0x7FFFFFFF) == 0x14000000);  // Must be B or BL
11121
11122             //
11123             // Do we need to insert a jump stub to make the source reach the target?
11124             //
11125             //
11126             if (!FitsInRel28(delta))
11127             {
11128                 // Use jump stub.
11129                 // 
11130                 TADDR baseAddr = (TADDR)fixupLocation;
11131                 TADDR loAddr   = baseAddr - 0x08000000;   // -2^27
11132                 TADDR hiAddr   = baseAddr + 0x07FFFFFF;   // +2^27-1
11133
11134                 // Check for the wrap around cases  
11135                 if (loAddr > baseAddr)
11136                     loAddr = UINT64_MIN; // overflow
11137                 if (hiAddr < baseAddr)
11138                     hiAddr = UINT64_MAX; // overflow
11139
11140                 PCODE jumpStubAddr = ExecutionManager::jumpStub(m_pMethodBeingCompiled,
11141                                                                 (PCODE)  target,
11142                                                                 (BYTE *) loAddr,
11143                                                                 (BYTE *) hiAddr);
11144
11145                 delta = (INT64)(jumpStubAddr - fixupLocation);
11146
11147                 if (!FitsInRel28(delta))
11148                 {
11149                     _ASSERTE(!"jump stub was not in expected range");
11150                     EEPOLICY_HANDLE_FATAL_ERROR(COR_E_EXECUTIONENGINE);
11151                 }
11152
11153                 LOG((LF_JIT, LL_INFO100000, "Using JumpStub at" FMT_ADDR "that jumps to" FMT_ADDR "\n",
11154                      DBG_ADDR(jumpStubAddr), DBG_ADDR(target)));
11155             }
11156
11157             LOG((LF_JIT, LL_INFO100000, "Encoded a BRANCH26 at" FMT_ADDR "to" FMT_ADDR ",  delta is 0x%04x\n",
11158                  DBG_ADDR(fixupLocation), DBG_ADDR(target), delta));
11159
11160             _ASSERTE(FitsInRel28(delta));
11161
11162             PutArm64Rel28((UINT32*) fixupLocation, (INT32)delta);
11163         }
11164         break;
11165
11166     case IMAGE_REL_ARM64_PAGEBASE_REL21:
11167         {
11168             _ASSERTE(slot == 0);
11169             _ASSERTE(addlDelta == 0);
11170
11171             // Write the 21 bits pc-relative page address into location.
11172             INT64 targetPage = (INT64)target & 0xFFFFFFFFFFFFF000LL;
11173             INT64 lcoationPage = (INT64)location & 0xFFFFFFFFFFFFF000LL;
11174             INT64 relPage = (INT64)(targetPage - lcoationPage);
11175             INT32 imm21 = (INT32)(relPage >> 12) & 0x1FFFFF;
11176             PutArm64Rel21((UINT32 *)location, imm21);
11177         }
11178         break;
11179
11180     case IMAGE_REL_ARM64_PAGEOFFSET_12A:
11181         {
11182             _ASSERTE(slot == 0);
11183             _ASSERTE(addlDelta == 0);
11184
11185             // Write the 12 bits page offset into location.
11186             INT32 imm12 = (INT32)target & 0xFFFLL;
11187             PutArm64Rel12((UINT32 *)location, imm12);
11188         }
11189         break;
11190
11191 #endif // _TARGET_ARM64_
11192
11193     default:
11194         _ASSERTE(!"Unknown reloc type");
11195         break;
11196     }
11197
11198     EE_TO_JIT_TRANSITION();
11199 #else // _WIN64
11200     JIT_TO_EE_TRANSITION_LEAF();
11201
11202     // Nothing to do on 32-bit
11203
11204     EE_TO_JIT_TRANSITION_LEAF();
11205 #endif // _WIN64
11206 }
11207
11208 WORD CEEJitInfo::getRelocTypeHint(void * target)
11209 {
11210     CONTRACTL {
11211         SO_TOLERANT;
11212         THROWS;
11213         GC_TRIGGERS;
11214         MODE_PREEMPTIVE;
11215     } CONTRACTL_END;
11216
11217 #ifdef _TARGET_AMD64_
11218     if (m_fAllowRel32)
11219     {
11220         // The JIT calls this method for data addresses only. It always uses REL32s for direct code targets.
11221         if (IsPreferredExecutableRange(target))
11222             return IMAGE_REL_BASED_REL32;
11223     }
11224 #endif // _TARGET_AMD64_
11225
11226     // No hints
11227     return (WORD)-1;
11228 }
11229
11230 void CEEJitInfo::getModuleNativeEntryPointRange(void** pStart, void** pEnd)
11231 {
11232     CONTRACTL {
11233         SO_TOLERANT;
11234         NOTHROW;
11235         GC_NOTRIGGER;
11236         MODE_PREEMPTIVE;
11237     }
11238     CONTRACTL_END;
11239
11240     JIT_TO_EE_TRANSITION_LEAF();
11241
11242     *pStart = *pEnd = 0;
11243
11244     EE_TO_JIT_TRANSITION_LEAF();
11245 }
11246
11247 DWORD CEEJitInfo::getExpectedTargetArchitecture()
11248 {
11249     LIMITED_METHOD_CONTRACT;
11250
11251     return IMAGE_FILE_MACHINE_NATIVE;
11252 }
11253
11254 void CEEInfo::JitProcessShutdownWork()
11255 {
11256     LIMITED_METHOD_CONTRACT;
11257
11258     EEJitManager* jitMgr = ExecutionManager::GetEEJitManager();
11259
11260     // If we didn't load the JIT, there is no work to do.
11261     if (jitMgr->m_jit != NULL)
11262     {
11263         // Do the shutdown work.
11264         jitMgr->m_jit->ProcessShutdownWork(this);
11265     }
11266
11267 #ifdef ALLOW_SXS_JIT
11268     if (jitMgr->m_alternateJit != NULL)
11269     {
11270         jitMgr->m_alternateJit->ProcessShutdownWork(this);
11271     }
11272 #endif // ALLOW_SXS_JIT
11273 }
11274
11275 /*********************************************************************/
11276 InfoAccessType CEEJitInfo::constructStringLiteral(CORINFO_MODULE_HANDLE scopeHnd,
11277                                                   mdToken metaTok,
11278                                                   void **ppValue)
11279 {
11280     CONTRACTL {
11281         SO_TOLERANT;
11282         THROWS;
11283         GC_TRIGGERS;
11284         MODE_PREEMPTIVE;
11285     } CONTRACTL_END;
11286
11287     InfoAccessType result = IAT_PVALUE;
11288
11289     JIT_TO_EE_TRANSITION();
11290
11291     _ASSERTE(ppValue != NULL);
11292
11293     if (IsDynamicScope(scopeHnd))
11294     {
11295         *ppValue = (LPVOID)GetDynamicResolver(scopeHnd)->ConstructStringLiteral(metaTok);
11296     }
11297     else
11298     {
11299         *ppValue = (LPVOID)ConstructStringLiteral(scopeHnd, metaTok); // throws
11300     }
11301
11302     EE_TO_JIT_TRANSITION();
11303
11304     return result;
11305 }
11306
11307 /*********************************************************************/
11308 InfoAccessType CEEJitInfo::emptyStringLiteral(void ** ppValue)
11309 {
11310     CONTRACTL {
11311         SO_TOLERANT;
11312         THROWS;
11313         GC_TRIGGERS;
11314         MODE_PREEMPTIVE;
11315     } CONTRACTL_END;
11316
11317     InfoAccessType result = IAT_PVALUE;
11318
11319     if(NingenEnabled())
11320     {
11321         *ppValue = NULL;
11322         return result;
11323     }
11324
11325     JIT_TO_EE_TRANSITION();
11326     *ppValue = StringObject::GetEmptyStringRefPtr();
11327     EE_TO_JIT_TRANSITION();
11328
11329     return result;
11330 }
11331
11332 /*********************************************************************/
11333 void* CEEJitInfo::getFieldAddress(CORINFO_FIELD_HANDLE fieldHnd,
11334                                   void **ppIndirection)
11335 {
11336     CONTRACTL {
11337         SO_TOLERANT;
11338         THROWS;
11339         GC_TRIGGERS;
11340         MODE_PREEMPTIVE;
11341     } CONTRACTL_END;
11342
11343     void *result = NULL;
11344
11345     if (ppIndirection != NULL)
11346         *ppIndirection = NULL;
11347
11348     // Do not bother with initialization if we are only verifying the method.
11349     if (isVerifyOnly())
11350     {
11351         return (void *)0x10;
11352     }
11353
11354     JIT_TO_EE_TRANSITION();
11355
11356     FieldDesc* field = (FieldDesc*) fieldHnd;
11357
11358     MethodTable* pMT = field->GetEnclosingMethodTable();
11359
11360     _ASSERTE(!pMT->ContainsGenericVariables());
11361
11362     // We must not call here for statics of collectible types.
11363     _ASSERTE(!pMT->Collectible());
11364
11365     void *base = NULL;
11366
11367     if (!field->IsRVA())
11368     {
11369         // <REVISIT_TODO>@todo: assert that the current method being compiled is unshared</REVISIT_TODO>
11370
11371         // Allocate space for the local class if necessary, but don't trigger
11372         // class construction.
11373         DomainLocalModule *pLocalModule = pMT->GetDomainLocalModule();
11374         pLocalModule->PopulateClass(pMT);
11375
11376         GCX_COOP();
11377
11378         base = (void *) field->GetBase();
11379     }
11380
11381     result = field->GetStaticAddressHandle(base);
11382
11383     EE_TO_JIT_TRANSITION();
11384
11385     return result;
11386 }
11387
11388 static void *GetClassSync(MethodTable *pMT)
11389 {
11390     STANDARD_VM_CONTRACT;
11391
11392     GCX_COOP();
11393
11394     OBJECTREF ref = pMT->GetManagedClassObject();
11395     return (void*)ref->GetSyncBlock()->GetMonitor();
11396 }
11397
11398 /*********************************************************************/
11399 void* CEEJitInfo::getMethodSync(CORINFO_METHOD_HANDLE ftnHnd,
11400                                 void **ppIndirection)
11401 {
11402     CONTRACTL {
11403         SO_TOLERANT;
11404         THROWS;
11405         GC_TRIGGERS;
11406         MODE_PREEMPTIVE;
11407     } CONTRACTL_END;
11408
11409     void * result = NULL;
11410
11411     if (ppIndirection != NULL)
11412         *ppIndirection = NULL;
11413
11414     JIT_TO_EE_TRANSITION();
11415
11416     result = GetClassSync((GetMethod(ftnHnd))->GetMethodTable());
11417
11418     EE_TO_JIT_TRANSITION();
11419
11420     return result;
11421 }
11422
11423 /*********************************************************************/
11424 HRESULT CEEJitInfo::allocBBProfileBuffer (
11425     ULONG                         count,
11426     ICorJitInfo::ProfileBuffer ** profileBuffer
11427     )
11428 {
11429     CONTRACTL {
11430         SO_TOLERANT;
11431         THROWS;
11432         GC_TRIGGERS;
11433         MODE_PREEMPTIVE;
11434     } CONTRACTL_END;
11435
11436     HRESULT hr = E_FAIL;
11437
11438     JIT_TO_EE_TRANSITION();
11439
11440 #ifdef FEATURE_PREJIT
11441
11442     // We need to know the code size. Typically we can get the code size
11443     // from m_ILHeader. For dynamic methods, m_ILHeader will be NULL, so
11444     // for that case we need to use DynamicResolver to get the code size.
11445
11446     unsigned codeSize = 0; 
11447     if (m_pMethodBeingCompiled->IsDynamicMethod())
11448     {
11449         unsigned stackSize, ehSize;
11450         CorInfoOptions options;
11451         DynamicResolver * pResolver = m_pMethodBeingCompiled->AsDynamicMethodDesc()->GetResolver();        
11452         pResolver->GetCodeInfo(&codeSize, &stackSize, &options, &ehSize);
11453     }
11454     else
11455     {
11456         codeSize = m_ILHeader->GetCodeSize();    
11457     }
11458     
11459     *profileBuffer = m_pMethodBeingCompiled->GetLoaderModule()->AllocateProfileBuffer(m_pMethodBeingCompiled->GetMemberDef(), count, codeSize);
11460     hr = (*profileBuffer ? S_OK : E_OUTOFMEMORY);
11461 #else // FEATURE_PREJIT
11462     _ASSERTE(!"allocBBProfileBuffer not implemented on CEEJitInfo!");
11463     hr = E_NOTIMPL;
11464 #endif // !FEATURE_PREJIT
11465
11466     EE_TO_JIT_TRANSITION();
11467     
11468     return hr;
11469 }
11470
11471 // Consider implementing getBBProfileData on CEEJitInfo.  This will allow us
11472 // to use profile info in codegen for non zapped images.
11473 HRESULT CEEJitInfo::getBBProfileData (
11474     CORINFO_METHOD_HANDLE         ftnHnd,
11475     ULONG *                       size,
11476     ICorJitInfo::ProfileBuffer ** profileBuffer,
11477     ULONG *                       numRuns
11478     )
11479 {
11480     LIMITED_METHOD_CONTRACT;
11481     _ASSERTE(!"getBBProfileData not implemented on CEEJitInfo!");
11482     return E_NOTIMPL;
11483 }
11484
11485 void CEEJitInfo::allocMem (
11486     ULONG               hotCodeSize,    /* IN */
11487     ULONG               coldCodeSize,   /* IN */
11488     ULONG               roDataSize,     /* IN */
11489     ULONG               xcptnsCount,    /* IN */
11490     CorJitAllocMemFlag  flag,           /* IN */
11491     void **             hotCodeBlock,   /* OUT */
11492     void **             coldCodeBlock,  /* OUT */
11493     void **             roDataBlock     /* OUT */
11494             )
11495 {
11496     CONTRACTL {
11497         SO_TOLERANT;
11498         THROWS;
11499         GC_TRIGGERS;
11500         MODE_PREEMPTIVE;
11501     } CONTRACTL_END;
11502
11503     JIT_TO_EE_TRANSITION();
11504
11505     _ASSERTE(coldCodeSize == 0);
11506     if (coldCodeBlock)
11507     {
11508         *coldCodeBlock = NULL;
11509     }
11510
11511     ULONG codeSize      = hotCodeSize;
11512     void **codeBlock    = hotCodeBlock;
11513
11514     S_SIZE_T totalSize = S_SIZE_T(codeSize);
11515
11516     size_t roDataAlignment = sizeof(void*);
11517     if ((flag & CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN)!= 0)
11518     {
11519         roDataAlignment = 16;
11520     }
11521     else if (roDataSize >= 8)
11522     {
11523         roDataAlignment = 8;
11524     }
11525     if (roDataSize > 0)
11526     {
11527         size_t codeAlignment = ((flag & CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN)!= 0)
11528                                ? 16 : sizeof(void*);
11529         totalSize.AlignUp(codeAlignment);
11530         if (roDataAlignment > codeAlignment) {
11531             // Add padding to align read-only data.
11532             totalSize += (roDataAlignment - codeAlignment);
11533         }
11534         totalSize += roDataSize;
11535     }
11536
11537 #ifdef WIN64EXCEPTIONS
11538     totalSize.AlignUp(sizeof(DWORD));
11539     totalSize += m_totalUnwindSize;
11540 #endif
11541
11542     _ASSERTE(m_CodeHeader == 0 &&
11543             // The jit-compiler sometimes tries to compile a method a second time
11544             // if it failed the first time. In such a situation, m_CodeHeader may
11545             // have already been assigned. Its OK to ignore this assert in such a
11546             // situation - we will leak some memory, but that is acceptable
11547             // since this should happen very rarely.
11548             "Note that this may fire if the JITCompiler tries to recompile a method");
11549
11550     if( totalSize.IsOverflow() )
11551     {
11552         COMPlusThrowHR(CORJIT_OUTOFMEM);
11553     }
11554
11555     m_CodeHeader = m_jitManager->allocCode(m_pMethodBeingCompiled, totalSize.Value(), flag
11556 #ifdef WIN64EXCEPTIONS
11557                                            , m_totalUnwindInfos
11558                                            , &m_moduleBase
11559 #endif
11560                                            );
11561
11562     BYTE* current = (BYTE *)m_CodeHeader->GetCodeStartAddress();
11563
11564     *codeBlock = current;
11565     current += codeSize;
11566
11567     if (roDataSize > 0)
11568     {
11569         current = (BYTE *)ALIGN_UP(current, roDataAlignment);
11570         *roDataBlock = current;
11571         current += roDataSize;
11572     }
11573     else
11574     {
11575         *roDataBlock = NULL;
11576     }
11577
11578 #ifdef WIN64EXCEPTIONS
11579     current = (BYTE *)ALIGN_UP(current, sizeof(DWORD));
11580
11581     m_theUnwindBlock = current;
11582     current += m_totalUnwindSize;
11583 #endif
11584
11585     _ASSERTE((SIZE_T)(current - (BYTE *)m_CodeHeader->GetCodeStartAddress()) <= totalSize.Value());
11586
11587 #ifdef _DEBUG
11588     m_codeSize = codeSize;
11589 #endif  // _DEBUG
11590
11591     EE_TO_JIT_TRANSITION();
11592 }
11593
11594 /*********************************************************************/
11595 void * CEEJitInfo::allocGCInfo (size_t size)
11596 {
11597     CONTRACTL {
11598         SO_TOLERANT;
11599         THROWS;
11600         GC_TRIGGERS;
11601         MODE_PREEMPTIVE;
11602     } CONTRACTL_END;
11603
11604     void * block = NULL;
11605
11606     JIT_TO_EE_TRANSITION();
11607
11608     _ASSERTE(m_CodeHeader != 0);
11609     _ASSERTE(m_CodeHeader->GetGCInfo() == 0);
11610
11611 #ifdef _WIN64
11612     if (size & 0xFFFFFFFF80000000LL)
11613     {
11614         COMPlusThrowHR(CORJIT_OUTOFMEM);
11615     }
11616 #endif // _WIN64
11617
11618     block = m_jitManager->allocGCInfo(m_CodeHeader,(DWORD)size, &m_GCinfo_len);
11619     if (!block)
11620     {
11621         COMPlusThrowHR(CORJIT_OUTOFMEM);
11622     }
11623
11624     _ASSERTE(m_CodeHeader->GetGCInfo() != 0 && block == m_CodeHeader->GetGCInfo());
11625
11626     EE_TO_JIT_TRANSITION();
11627
11628     return block;
11629 }
11630
11631 /*********************************************************************/
11632 void CEEJitInfo::setEHcount (
11633         unsigned      cEH)
11634 {
11635     CONTRACTL {
11636         SO_TOLERANT;
11637         THROWS;
11638         GC_TRIGGERS;
11639         MODE_PREEMPTIVE;
11640     } CONTRACTL_END;
11641
11642     JIT_TO_EE_TRANSITION();
11643
11644     _ASSERTE(cEH != 0);
11645     _ASSERTE(m_CodeHeader != 0);
11646     _ASSERTE(m_CodeHeader->GetEHInfo() == 0);
11647
11648     EE_ILEXCEPTION* ret;
11649     ret = m_jitManager->allocEHInfo(m_CodeHeader,cEH, &m_EHinfo_len);
11650     _ASSERTE(ret);      // allocEHInfo throws if there's not enough memory
11651
11652     _ASSERTE(m_CodeHeader->GetEHInfo() != 0 && m_CodeHeader->GetEHInfo()->EHCount() == cEH);
11653
11654     EE_TO_JIT_TRANSITION();
11655 }
11656
11657 /*********************************************************************/
11658 void CEEJitInfo::setEHinfo (
11659         unsigned      EHnumber,
11660         const CORINFO_EH_CLAUSE* clause)
11661 {
11662     CONTRACTL {
11663         SO_TOLERANT;
11664         THROWS;
11665         GC_TRIGGERS;
11666         MODE_PREEMPTIVE;
11667     } CONTRACTL_END;
11668
11669     JIT_TO_EE_TRANSITION();
11670
11671     // <REVISIT_TODO> Fix make the Code Manager EH clauses EH_INFO+</REVISIT_TODO>
11672     _ASSERTE(m_CodeHeader->GetEHInfo() != 0 && EHnumber < m_CodeHeader->GetEHInfo()->EHCount());
11673
11674     EE_ILEXCEPTION_CLAUSE* pEHClause = m_CodeHeader->GetEHInfo()->EHClause(EHnumber);
11675
11676     pEHClause->TryStartPC     = clause->TryOffset;
11677     pEHClause->TryEndPC       = clause->TryLength;
11678     pEHClause->HandlerStartPC = clause->HandlerOffset;
11679     pEHClause->HandlerEndPC   = clause->HandlerLength;
11680     pEHClause->ClassToken     = clause->ClassToken;
11681     pEHClause->Flags          = (CorExceptionFlag)clause->Flags;
11682
11683     LOG((LF_EH, LL_INFO1000000, "Setting EH clause #%d for %s::%s\n", EHnumber, m_pMethodBeingCompiled->m_pszDebugClassName, m_pMethodBeingCompiled->m_pszDebugMethodName));
11684     LOG((LF_EH, LL_INFO1000000, "    Flags         : 0x%08lx  ->  0x%08lx\n",            clause->Flags,         pEHClause->Flags));
11685     LOG((LF_EH, LL_INFO1000000, "    TryOffset     : 0x%08lx  ->  0x%08lx (startpc)\n",  clause->TryOffset,     pEHClause->TryStartPC));
11686     LOG((LF_EH, LL_INFO1000000, "    TryLength     : 0x%08lx  ->  0x%08lx (endpc)\n",    clause->TryLength,     pEHClause->TryEndPC));
11687     LOG((LF_EH, LL_INFO1000000, "    HandlerOffset : 0x%08lx  ->  0x%08lx\n",            clause->HandlerOffset, pEHClause->HandlerStartPC));
11688     LOG((LF_EH, LL_INFO1000000, "    HandlerLength : 0x%08lx  ->  0x%08lx\n",            clause->HandlerLength, pEHClause->HandlerEndPC));
11689     LOG((LF_EH, LL_INFO1000000, "    ClassToken    : 0x%08lx  ->  0x%08lx\n",            clause->ClassToken,    pEHClause->ClassToken));
11690     LOG((LF_EH, LL_INFO1000000, "    FilterOffset  : 0x%08lx  ->  0x%08lx\n",            clause->FilterOffset,  pEHClause->FilterOffset));
11691
11692     if (m_pMethodBeingCompiled->IsDynamicMethod() &&
11693         ((pEHClause->Flags & COR_ILEXCEPTION_CLAUSE_FILTER) == 0) &&
11694         (clause->ClassToken != NULL))
11695     {
11696         MethodDesc * pMD; FieldDesc * pFD;
11697         m_pMethodBeingCompiled->AsDynamicMethodDesc()->GetResolver()->ResolveToken(clause->ClassToken, (TypeHandle *)&pEHClause->TypeHandle, &pMD, &pFD);
11698         SetHasCachedTypeHandle(pEHClause);
11699         LOG((LF_EH, LL_INFO1000000, "  CachedTypeHandle: 0x%08lx  ->  0x%08lx\n",        clause->ClassToken,    pEHClause->TypeHandle));
11700     }
11701
11702     EE_TO_JIT_TRANSITION();
11703 }
11704
11705 /*********************************************************************/
11706 // get individual exception handler
11707 void CEEJitInfo::getEHinfo(
11708                               CORINFO_METHOD_HANDLE  ftn,      /* IN  */
11709                               unsigned               EHnumber, /* IN  */
11710                               CORINFO_EH_CLAUSE*     clause)   /* OUT */
11711 {
11712     CONTRACTL {
11713         SO_TOLERANT;
11714         THROWS;
11715         GC_TRIGGERS;
11716         MODE_PREEMPTIVE;
11717     } CONTRACTL_END;
11718
11719     JIT_TO_EE_TRANSITION();
11720
11721     if (IsDynamicMethodHandle(ftn))
11722     {
11723         GetMethod(ftn)->AsDynamicMethodDesc()->GetResolver()->GetEHInfo(EHnumber, clause);
11724     }
11725     else
11726     {
11727         _ASSERTE(ftn == CORINFO_METHOD_HANDLE(m_pMethodBeingCompiled));  // For now only support if the method being jitted
11728         getEHinfoHelper(ftn, EHnumber, clause, m_ILHeader);
11729     }
11730
11731     EE_TO_JIT_TRANSITION();
11732 }
11733 #endif // CROSSGEN_COMPILE
11734
11735 #if defined(CROSSGEN_COMPILE)
11736 EXTERN_C ICorJitCompiler* __stdcall getJit();
11737 #endif // defined(CROSSGEN_COMPILE)
11738
11739 #ifdef FEATURE_INTERPRETER
11740 static CorJitResult CompileMethodWithEtwWrapper(EEJitManager *jitMgr,
11741                                                       CEEInfo *comp,
11742                                                       struct CORINFO_METHOD_INFO *info,
11743                                                       unsigned flags,
11744                                                       BYTE **nativeEntry,
11745                                                       ULONG *nativeSizeOfCode)
11746 {
11747     STATIC_CONTRACT_THROWS;
11748     STATIC_CONTRACT_GC_TRIGGERS;
11749     STATIC_CONTRACT_MODE_PREEMPTIVE;
11750     STATIC_CONTRACT_SO_INTOLERANT;
11751
11752     SString namespaceOrClassName, methodName, methodSignature;
11753     // Fire an ETW event to mark the beginning of JIT'ing
11754     ETW::MethodLog::MethodJitting(reinterpret_cast<MethodDesc*>(info->ftn), &namespaceOrClassName, &methodName, &methodSignature);
11755
11756     CorJitResult ret = jitMgr->m_jit->compileMethod(comp, info, flags, nativeEntry, nativeSizeOfCode);
11757
11758     // Logically, it would seem that the end-of-JITting ETW even should go here, but it must come after the native code has been
11759     // set for the given method desc, which happens in a caller.
11760
11761     return ret;
11762 }
11763 #endif // FEATURE_INTERPRETER
11764
11765 //
11766 // Helper function because can't have dtors in BEGIN_SO_TOLERANT_CODE.
11767 //
11768 CorJitResult invokeCompileMethodHelper(EEJitManager *jitMgr,
11769                                  CEEInfo *comp,
11770                                  struct CORINFO_METHOD_INFO *info,
11771                                  CORJIT_FLAGS jitFlags,
11772                                  BYTE **nativeEntry,
11773                                  ULONG *nativeSizeOfCode)
11774 {
11775     STATIC_CONTRACT_THROWS;
11776     STATIC_CONTRACT_GC_TRIGGERS;
11777     STATIC_CONTRACT_MODE_PREEMPTIVE;
11778     STATIC_CONTRACT_SO_INTOLERANT;
11779
11780     CorJitResult ret = CORJIT_SKIPPED;   // Note that CORJIT_SKIPPED is an error exit status code
11781
11782
11783     comp->setJitFlags(jitFlags);
11784
11785 #ifdef FEATURE_STACK_SAMPLING
11786     // SO_INTOLERANT due to init affecting global state.
11787     static ConfigDWORD s_stackSamplingEnabled;
11788     bool samplingEnabled = (s_stackSamplingEnabled.val(CLRConfig::UNSUPPORTED_StackSamplingEnabled) != 0);
11789 #endif
11790
11791     BEGIN_SO_TOLERANT_CODE(GetThread());
11792
11793
11794 #if defined(ALLOW_SXS_JIT) && !defined(CROSSGEN_COMPILE)
11795     if (FAILED(ret) && jitMgr->m_alternateJit
11796 #ifdef FEATURE_STACK_SAMPLING
11797         && (!samplingEnabled || (jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SAMPLING_JIT_BACKGROUND)))
11798 #endif
11799        )
11800     {
11801         ret = jitMgr->m_alternateJit->compileMethod( comp,
11802                                                      info,
11803                                                      CORJIT_FLAGS::CORJIT_FLAG_CALL_GETJITFLAGS,
11804                                                      nativeEntry,
11805                                                      nativeSizeOfCode );
11806
11807 #ifdef FEATURE_STACK_SAMPLING
11808         if (jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SAMPLING_JIT_BACKGROUND))
11809         {
11810             // Don't bother with failures if we couldn't collect a trace.
11811             ret = CORJIT_OK;
11812         }
11813 #endif // FEATURE_STACK_SAMPLING
11814
11815         // If we failed to jit, then fall back to the primary Jit.
11816         if (FAILED(ret))
11817         {
11818             // Consider adding this call:
11819             //      ((CEEJitInfo*)comp)->BackoutJitData(jitMgr);
11820             ((CEEJitInfo*)comp)->ResetForJitRetry();
11821             ret = CORJIT_SKIPPED;
11822         }
11823     }
11824 #endif // defined(ALLOW_SXS_JIT) && !defined(CROSSGEN_COMPILE)
11825
11826 #ifdef FEATURE_INTERPRETER
11827     static ConfigDWORD s_InterpreterFallback;
11828
11829     bool interpreterFallback = (s_InterpreterFallback.val(CLRConfig::INTERNAL_InterpreterFallback) != 0);
11830
11831     if (interpreterFallback == false)
11832     {
11833         // If we're doing an "import_only" compilation, it's for verification, so don't interpret.
11834         // (We assume that importation is completely architecture-independent, or at least nearly so.)
11835         if (FAILED(ret) && !jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY) && !jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_MAKEFINALCODE))
11836         {
11837             ret = Interpreter::GenerateInterpreterStub(comp, info, nativeEntry, nativeSizeOfCode);
11838         }
11839     }
11840     
11841     if (FAILED(ret) && jitMgr->m_jit)
11842     {
11843         ret = CompileMethodWithEtwWrapper(jitMgr, 
11844                                           comp,
11845                                           info,
11846                                           CORJIT_FLAGS::CORJIT_FLAG_CALL_GETJITFLAGS,
11847                                           nativeEntry,
11848                                           nativeSizeOfCode);
11849     }
11850
11851     if (interpreterFallback == true)
11852     {
11853         // If we're doing an "import_only" compilation, it's for verification, so don't interpret.
11854         // (We assume that importation is completely architecture-independent, or at least nearly so.)
11855         if (FAILED(ret) && !jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY) && !jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_MAKEFINALCODE))
11856         {
11857             ret = Interpreter::GenerateInterpreterStub(comp, info, nativeEntry, nativeSizeOfCode);
11858         }
11859     }
11860 #else
11861     if (FAILED(ret))
11862     {
11863         ret = jitMgr->m_jit->compileMethod( comp,
11864                                             info,
11865                                             CORJIT_FLAGS::CORJIT_FLAG_CALL_GETJITFLAGS,
11866                                             nativeEntry,
11867                                             nativeSizeOfCode);
11868     }
11869 #endif // FEATURE_INTERPRETER
11870
11871 #if !defined(CROSSGEN_COMPILE)
11872     // Cleanup any internal data structures allocated 
11873     // such as IL code after a successfull JIT compile
11874     // If the JIT fails we keep the IL around and will
11875     // try reJIT the same IL.  VSW 525059
11876     //
11877     if (SUCCEEDED(ret) && !jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY) && !((CEEJitInfo*)comp)->JitAgain())
11878     {
11879         ((CEEJitInfo*)comp)->CompressDebugInfo();
11880
11881 #ifdef FEATURE_INTERPRETER
11882         // We do this cleanup in the prestub, where we know whether the method
11883         // has been interpreted.
11884 #else
11885         comp->MethodCompileComplete(info->ftn);
11886 #endif // FEATURE_INTERPRETER
11887     }
11888 #endif // !defined(CROSSGEN_COMPILE)
11889     
11890
11891 #if defined(FEATURE_GDBJIT)
11892     if (SUCCEEDED(ret) && *nativeEntry != NULL)
11893     {
11894         CodeHeader* pCH = ((CodeHeader*)((PCODE)*nativeEntry & ~1)) - 1;
11895         pCH->SetCalledMethods((PTR_VOID)comp->GetCalledMethods());
11896     }
11897 #endif
11898
11899     END_SO_TOLERANT_CODE;
11900
11901     return ret;
11902 }
11903
11904
11905 /*********************************************************************/
11906 CorJitResult invokeCompileMethod(EEJitManager *jitMgr,
11907                                  CEEInfo *comp,
11908                                  struct CORINFO_METHOD_INFO *info,
11909                                  CORJIT_FLAGS jitFlags,
11910                                  BYTE **nativeEntry,
11911                                  ULONG *nativeSizeOfCode)
11912 {
11913     CONTRACTL {
11914         THROWS;
11915         GC_TRIGGERS;
11916         MODE_COOPERATIVE;
11917     } CONTRACTL_END;
11918     //
11919     // The JIT runs in preemptive mode
11920     //
11921
11922     GCX_PREEMP();
11923
11924     CorJitResult ret = invokeCompileMethodHelper(jitMgr, comp, info, jitFlags, nativeEntry, nativeSizeOfCode);
11925
11926     //
11927     // Verify that we are still in preemptive mode when we return
11928     // from the JIT
11929     //
11930
11931     _ASSERTE(GetThread()->PreemptiveGCDisabled() == FALSE);
11932
11933     return ret;
11934 }
11935
11936 CORJIT_FLAGS GetCompileFlagsIfGenericInstantiation(
11937         CORINFO_METHOD_HANDLE method,
11938         CORJIT_FLAGS compileFlags,
11939         ICorJitInfo * pCorJitInfo,
11940         BOOL * raiseVerificationException,
11941         BOOL * unverifiableGenericCode);
11942
11943 CorJitResult CallCompileMethodWithSEHWrapper(EEJitManager *jitMgr,
11944                                 CEEInfo *comp,
11945                                 struct CORINFO_METHOD_INFO *info,
11946                                 CORJIT_FLAGS flags,
11947                                 BYTE **nativeEntry,
11948                                 ULONG *nativeSizeOfCode,
11949                                 MethodDesc *ftn)
11950 {
11951     // no dynamic contract here because SEH is used, with a finally clause
11952     STATIC_CONTRACT_NOTHROW;
11953     STATIC_CONTRACT_GC_TRIGGERS;
11954
11955     LOG((LF_CORDB, LL_EVERYTHING, "CallCompileMethodWithSEHWrapper called...\n"));
11956
11957     struct Param
11958     {
11959         EEJitManager *jitMgr;
11960         CEEInfo *comp;
11961         struct CORINFO_METHOD_INFO *info;
11962         CORJIT_FLAGS flags;
11963         BYTE **nativeEntry;
11964         ULONG *nativeSizeOfCode;
11965         MethodDesc *ftn;
11966         CorJitResult res;
11967     }; Param param;
11968     param.jitMgr = jitMgr;
11969     param.comp = comp;
11970     param.info = info;
11971     param.flags = flags;
11972     param.nativeEntry = nativeEntry;
11973     param.nativeSizeOfCode = nativeSizeOfCode;
11974     param.ftn = ftn;
11975     param.res = CORJIT_INTERNALERROR;
11976
11977     PAL_TRY(Param *, pParam, &param)
11978     {
11979         //
11980         // Call out to the JIT-compiler
11981         //
11982
11983         pParam->res = invokeCompileMethod( pParam->jitMgr,
11984                                            pParam->comp,
11985                                            pParam->info,
11986                                            pParam->flags,
11987                                            pParam->nativeEntry,
11988                                            pParam->nativeSizeOfCode);
11989     }
11990     PAL_FINALLY
11991     {
11992 #if defined(DEBUGGING_SUPPORTED) && !defined(CROSSGEN_COMPILE)
11993         if (!flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY) &&
11994             !flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_MCJIT_BACKGROUND)
11995 #ifdef FEATURE_STACK_SAMPLING
11996             && !flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SAMPLING_JIT_BACKGROUND)
11997 #endif // FEATURE_STACK_SAMPLING
11998            )
11999         {
12000             //
12001             // Notify the debugger that we have successfully jitted the function
12002             //
12003             if (ftn->HasNativeCode())
12004             {
12005                 //
12006                 // Nothing to do here (don't need to notify the debugger
12007                 // because the function has already been successfully jitted)
12008                 //
12009                 // This is the case where we aborted the jit because of a deadlock cycle
12010                 // in initClass.  
12011                 //
12012             }
12013             else
12014             {
12015                 if (g_pDebugInterface)
12016                 {
12017                     if (param.res == CORJIT_OK && !((CEEJitInfo*)param.comp)->JitAgain())
12018                     {
12019                         g_pDebugInterface->JITComplete(ftn, (TADDR) *nativeEntry);
12020                     }
12021                 }
12022             }
12023         }
12024 #endif // DEBUGGING_SUPPORTED && !CROSSGEN_COMPILE
12025     }
12026     PAL_ENDTRY
12027
12028     return param.res;
12029 }
12030
12031 /*********************************************************************/
12032 // Figures out the compile flags that are used by both JIT and NGen
12033
12034 /* static */ CORJIT_FLAGS CEEInfo::GetBaseCompileFlags(MethodDesc * ftn)
12035 {
12036      CONTRACTL {
12037         THROWS;
12038         GC_TRIGGERS;
12039     } CONTRACTL_END;
12040
12041     //
12042     // Figure out the code quality flags
12043     //
12044
12045     CORJIT_FLAGS flags;
12046     if (g_pConfig->JitFramed())
12047         flags.Set(CORJIT_FLAGS::CORJIT_FLAG_FRAMED);
12048     if (g_pConfig->JitAlignLoops())
12049         flags.Set(CORJIT_FLAGS::CORJIT_FLAG_ALIGN_LOOPS);
12050     if (ReJitManager::IsReJITEnabled() || g_pConfig->AddRejitNops())
12051         flags.Set(CORJIT_FLAGS::CORJIT_FLAG_PROF_REJIT_NOPS);
12052 #ifdef _TARGET_X86_
12053     if (g_pConfig->PInvokeRestoreEsp(ftn->GetModule()->IsPreV4Assembly()))
12054         flags.Set(CORJIT_FLAGS::CORJIT_FLAG_PINVOKE_RESTORE_ESP);
12055 #endif // _TARGET_X86_
12056
12057     //See if we should instruct the JIT to emit calls to JIT_PollGC for thread suspension.  If we have a
12058     //non-default value in the EE Config, then use that.  Otherwise select the platform specific default.
12059 #ifdef FEATURE_ENABLE_GCPOLL
12060     EEConfig::GCPollType pollType = g_pConfig->GetGCPollType();
12061     if (EEConfig::GCPOLL_TYPE_POLL == pollType)
12062         flags.Set(CORJIT_FLAGS::CORJIT_FLAG_GCPOLL_CALLS);
12063     else if (EEConfig::GCPOLL_TYPE_INLINE == pollType)
12064         flags.Set(CORJIT_FLAGS::CORJIT_FLAG_GCPOLL_INLINE);
12065 #endif //FEATURE_ENABLE_GCPOLL
12066
12067     // Set flags based on method's ImplFlags.
12068     if (!ftn->IsNoMetadata())
12069     {
12070          DWORD dwImplFlags = 0;
12071          IfFailThrow(ftn->GetMDImport()->GetMethodImplProps(ftn->GetMemberDef(), NULL, &dwImplFlags));
12072         
12073          if (IsMiNoOptimization(dwImplFlags))
12074          {
12075              flags.Set(CORJIT_FLAGS::CORJIT_FLAG_MIN_OPT);
12076          }
12077
12078          // Always emit frames for methods marked no-inline (see #define ETW_EBP_FRAMED in the JIT)
12079          if (IsMiNoInlining(dwImplFlags))
12080          {
12081              flags.Set(CORJIT_FLAGS::CORJIT_FLAG_FRAMED);
12082          }
12083     }
12084
12085     return flags;
12086 }
12087
12088 /*********************************************************************/
12089 // Figures out (some of) the flags to use to compile the method
12090 // Returns the new set to use
12091
12092 CORJIT_FLAGS GetDebuggerCompileFlags(Module* pModule, CORJIT_FLAGS flags)
12093 {
12094     STANDARD_VM_CONTRACT;
12095
12096     //Right now if we don't have a debug interface on CoreCLR, we can't generate debug info.  So, in those
12097     //cases don't attempt it.
12098     if (!g_pDebugInterface)
12099         return flags;
12100
12101 #ifdef DEBUGGING_SUPPORTED
12102
12103 #ifdef _DEBUG
12104     if (g_pConfig->GenDebuggableCode())
12105         flags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE);
12106 #endif // _DEBUG
12107
12108 #ifdef EnC_SUPPORTED
12109     if (pModule->IsEditAndContinueEnabled())
12110     {
12111         flags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_EnC);
12112     }
12113 #endif // EnC_SUPPORTED
12114
12115     // Debug info is always tracked
12116     flags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO);
12117 #endif // DEBUGGING_SUPPORTED
12118
12119     if (CORDisableJITOptimizations(pModule->GetDebuggerInfoBits()))
12120     {
12121         flags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE);
12122     }
12123
12124     if (flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY))
12125     {
12126         // If we are only verifying the method, dont need any debug info and this
12127         // prevents getVars()/getBoundaries() from being called unnecessarily.
12128         flags.Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO);
12129         flags.Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE);
12130     }
12131
12132     return flags;
12133 }
12134
12135 CORJIT_FLAGS GetCompileFlags(MethodDesc * ftn, CORJIT_FLAGS flags, CORINFO_METHOD_INFO * methodInfo)
12136 {
12137     STANDARD_VM_CONTRACT;
12138
12139     _ASSERTE(methodInfo->regionKind ==  CORINFO_REGION_JIT);
12140
12141     //
12142     // Get the compile flags that are shared between JIT and NGen
12143     //
12144     flags.Add(CEEInfo::GetBaseCompileFlags(ftn));
12145
12146     //
12147     // Get CPU specific flags
12148     //
12149     if (!flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY))
12150     {
12151         flags.Add(ExecutionManager::GetEEJitManager()->GetCPUCompileFlags());
12152     }
12153
12154     //
12155     // Find the debugger and profiler related flags
12156     //
12157
12158 #ifdef DEBUGGING_SUPPORTED
12159     flags.Add(GetDebuggerCompileFlags(ftn->GetModule(), flags));
12160 #endif
12161
12162 #ifdef PROFILING_SUPPORTED
12163     if (CORProfilerTrackEnterLeave() && !ftn->IsNoMetadata())
12164         flags.Set(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE);
12165
12166     if (CORProfilerTrackTransitions())
12167         flags.Set(CORJIT_FLAGS::CORJIT_FLAG_PROF_NO_PINVOKE_INLINE);
12168 #endif // PROFILING_SUPPORTED
12169
12170     // Set optimization flags
12171     if (!flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_MIN_OPT))
12172     {
12173         unsigned optType = g_pConfig->GenOptimizeType();
12174         _ASSERTE(optType <= OPT_RANDOM);
12175
12176         if (optType == OPT_RANDOM)
12177             optType = methodInfo->ILCodeSize % OPT_RANDOM;
12178
12179         if (g_pConfig->JitMinOpts())
12180             flags.Set(CORJIT_FLAGS::CORJIT_FLAG_MIN_OPT);
12181
12182         if (optType == OPT_SIZE)
12183         {
12184             flags.Set(CORJIT_FLAGS::CORJIT_FLAG_SIZE_OPT);
12185         }
12186         else if (optType == OPT_SPEED)
12187         {
12188             flags.Set(CORJIT_FLAGS::CORJIT_FLAG_SPEED_OPT);
12189         }
12190     }
12191
12192     //
12193     // Verification flags
12194     //
12195
12196 #ifdef _DEBUG
12197     if (g_pConfig->IsJitVerificationDisabled())
12198         flags.Set(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION);
12199 #endif // _DEBUG
12200
12201     if (!flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY) && Security::CanSkipVerification(ftn))
12202         flags.Set(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION);
12203
12204     if (ftn->IsILStub())
12205     {
12206         flags.Set(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION);
12207
12208         // no debug info available for IL stubs
12209         flags.Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO);
12210     }
12211
12212     return flags;
12213 }
12214
12215 #if defined(_WIN64)
12216 //The implementation of Jit64 prevents it from both inlining and verifying at the same time.  This causes a
12217 //perf problem for code that adopts Transparency.  This code attempts to enable inlining in spite of that
12218 //limitation in that scenario.
12219 //
12220 //This only works for real methods.  If the method isn't IsIL, then IsVerifiable will AV.  That would be a
12221 //bad thing (TM).
12222 BOOL IsTransparentMethodSafeToSkipVerification(CORJIT_FLAGS flags, MethodDesc * ftn)
12223 {
12224     STANDARD_VM_CONTRACT;
12225
12226     BOOL ret = FALSE;
12227     if (!flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY) && !flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION)
12228            && Security::IsMethodTransparent(ftn) &&
12229                ((ftn->IsIL() && !ftn->IsUnboxingStub()) ||
12230                    (ftn->IsDynamicMethod() && !ftn->IsILStub())))
12231     {
12232         EX_TRY
12233         {
12234             //Verify the method
12235             ret = ftn->IsVerifiable();
12236         }
12237         EX_CATCH
12238         {
12239             //If the jit throws an exception, do not let it leak out of here.  For example, we can sometimes
12240             //get an IPE that we could recover from in the Jit (i.e. invalid local in a method with skip
12241             //verification).
12242         }
12243         EX_END_CATCH(RethrowTerminalExceptions)
12244     }
12245     return ret;
12246 }
12247 #else
12248 #define IsTransparentMethodSafeToSkipVerification(flags,ftn) (FALSE)
12249 #endif //_WIN64
12250
12251 /*********************************************************************/
12252 // We verify generic code once and for all using the typical open type,
12253 // and then no instantiations need to be verified.  If verification
12254 // failed, then we need to throw an exception whenever we try
12255 // to compile a real instantiation
12256
12257 CORJIT_FLAGS GetCompileFlagsIfGenericInstantiation(
12258         CORINFO_METHOD_HANDLE method,
12259         CORJIT_FLAGS compileFlags,
12260         ICorJitInfo * pCorJitInfo,
12261         BOOL * raiseVerificationException,
12262         BOOL * unverifiableGenericCode)
12263 {
12264     STANDARD_VM_CONTRACT;
12265
12266     *raiseVerificationException = FALSE;
12267     *unverifiableGenericCode = FALSE;
12268
12269     // If we have already decided to skip verification, keep on going.
12270     if (compileFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION))
12271         return compileFlags;
12272
12273     CorInfoInstantiationVerification ver = pCorJitInfo->isInstantiationOfVerifiedGeneric(method);
12274
12275     switch(ver)
12276     {
12277     case INSTVER_NOT_INSTANTIATION:
12278         // Non-generic, or open instantiation of a generic type/method
12279         if (IsTransparentMethodSafeToSkipVerification(compileFlags, (MethodDesc*)method))
12280             compileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION);
12281         return compileFlags;
12282
12283     case INSTVER_GENERIC_PASSED_VERIFICATION:
12284         // If the typical instantiation is verifiable, there is no need
12285         // to verify the concrete instantiations
12286         compileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION);
12287         return compileFlags;
12288
12289     case INSTVER_GENERIC_FAILED_VERIFICATION:
12290
12291         *unverifiableGenericCode = TRUE;
12292
12293         // The generic method is not verifiable.
12294         // Check if it has SkipVerification permission
12295         MethodDesc * pGenMethod = GetMethod(method)->LoadTypicalMethodDefinition();
12296
12297         CORINFO_METHOD_HANDLE genMethodHandle = CORINFO_METHOD_HANDLE(pGenMethod);
12298
12299         CorInfoCanSkipVerificationResult canSkipVer;
12300         canSkipVer = pCorJitInfo->canSkipMethodVerification(genMethodHandle);
12301         
12302         switch(canSkipVer)
12303         {
12304
12305 #ifdef FEATURE_PREJIT
12306             case CORINFO_VERIFICATION_DONT_JIT:
12307             {
12308                 // Transparent code could be partial trust, but we don't know at NGEN time.
12309                 // This is the flag that NGEN passes to the JIT to tell it to give-up if it
12310                 // hits unverifiable code.  Since we've already hit unverifiable code,
12311                 // there's no point in starting the JIT, just to have it give up, so we
12312                 // give up here.
12313                 _ASSERTE(compileFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_PREJIT));
12314                 *raiseVerificationException = TRUE;
12315                 return CORJIT_FLAGS(); // This value will not be used
12316             }
12317 #else // FEATURE_PREJIT
12318             // Need to have this case here to keep the MAC build happy
12319             case CORINFO_VERIFICATION_DONT_JIT:
12320             {
12321                 _ASSERTE(!"We should never get here");
12322                 return compileFlags;
12323             }
12324 #endif // FEATURE_PREJIT
12325
12326             case CORINFO_VERIFICATION_CANNOT_SKIP:
12327             {
12328                 // For unverifiable generic code without SkipVerification permission,
12329                 // we cannot ask the compiler to emit CORINFO_HELP_VERIFICATION in
12330                 // unverifiable branches as the compiler cannot determine the unverifiable
12331                 // branches while compiling the concrete instantiation. Instead,
12332                 // just throw a VerificationException right away.
12333                 *raiseVerificationException = TRUE;
12334                 return CORJIT_FLAGS(); // This value will not be used
12335             }
12336
12337             case CORINFO_VERIFICATION_CAN_SKIP:
12338             {
12339                 compileFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION);
12340                 return compileFlags;
12341             }
12342
12343             case CORINFO_VERIFICATION_RUNTIME_CHECK:
12344             {
12345                 // Compile the method without CORJIT_FLAG_SKIP_VERIFICATION.
12346                 // The compiler will know to add a call to
12347                 // CORINFO_HELP_VERIFICATION_RUNTIME_CHECK, and then to skip verification.
12348                 return compileFlags;
12349             }
12350         }
12351     }
12352
12353     _ASSERTE(!"We should never get here");
12354     return compileFlags;
12355 }
12356
12357 // ********************************************************************
12358
12359 // Throw the right type of exception for the given JIT result
12360
12361 void ThrowExceptionForJit(HRESULT res)
12362 {
12363     CONTRACTL
12364     {
12365         THROWS;
12366         GC_NOTRIGGER;
12367         SO_INTOLERANT;
12368         MODE_ANY;
12369     }
12370     CONTRACTL_END;
12371     switch (res)
12372     {
12373         case CORJIT_OUTOFMEM:
12374             COMPlusThrowOM();              
12375             break; 
12376             
12377 #ifdef _TARGET_X86_
12378         // Currently, only x86 JIT returns adequate error codes. The x86 JIT is also the
12379         // JIT that has more limitations and given that to get this message for 64 bit
12380         // is going to require some code churn (either changing their EH handlers or
12381         // fixing the 3 or 4 code sites they have that return CORJIT_INTERNALERROR independently
12382         // of the error, the least risk fix is making this x86 only.
12383         case CORJIT_INTERNALERROR:
12384             COMPlusThrow(kInvalidProgramException, (UINT) IDS_EE_JIT_COMPILER_ERROR);
12385             break;   
12386 #endif
12387
12388         case CORJIT_BADCODE:
12389         default:                    
12390             COMPlusThrow(kInvalidProgramException);                                            
12391             break;
12392     }
12393  }
12394
12395 // ********************************************************************
12396 #ifdef _DEBUG
12397 LONG g_JitCount = 0;
12398 #endif
12399
12400 //#define PERF_TRACK_METHOD_JITTIMES
12401 #ifdef _TARGET_AMD64_
12402 BOOL g_fAllowRel32 = TRUE;
12403 #endif
12404
12405
12406 // ********************************************************************
12407 //                  README!!
12408 // ********************************************************************
12409
12410 // The reason that this is named UnsafeJitFunction is that this helper
12411 // method is not thread safe!  When multiple threads get in here for
12412 // the same pMD, ALL of them MUST return the SAME value.
12413 // To insure that this happens you must call MakeJitWorker.
12414 // It creates a DeadlockAware list of methods being jitted and prevents us
12415 // from trying to jit the same method more that once.
12416 //
12417 // Calls to this method that occur to check if inlining can occur on x86,
12418 // are OK since they discard the return value of this method.
12419
12420 PCODE UnsafeJitFunction(MethodDesc* ftn, COR_ILMETHOD_DECODER* ILHeader, CORJIT_FLAGS flags,
12421                         ULONG * pSizeOfCode)
12422 {
12423     STANDARD_VM_CONTRACT;
12424
12425     PCODE ret = NULL;
12426
12427     COOPERATIVE_TRANSITION_BEGIN();
12428
12429 #ifdef FEATURE_PREJIT
12430
12431     if (g_pConfig->RequireZaps() == EEConfig::REQUIRE_ZAPS_ALL &&
12432         ftn->GetModule()->GetDomainFile()->IsZapRequired() &&
12433         PartialNGenStressPercentage() == 0 && 
12434 #ifdef FEATURE_STACK_SAMPLING
12435         !flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SAMPLING_JIT_BACKGROUND) &&
12436 #endif
12437         !flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY))
12438     {
12439         StackSString ss(SString::Ascii, "ZapRequire: JIT compiler invoked for ");
12440         TypeString::AppendMethodInternal(ss, ftn);
12441
12442 #ifdef _DEBUG
12443         // Assert as some test may not check their error codes well. So throwing an
12444         // exception may not cause a test failure (as it should).
12445         StackScratchBuffer scratch;
12446         DbgAssertDialog(__FILE__, __LINE__, (char*)ss.GetUTF8(scratch));
12447 #endif // _DEBUG
12448
12449         COMPlusThrowNonLocalized(kFileNotFoundException, ss.GetUnicode());
12450     }
12451
12452 #endif // FEATURE_PREJIT
12453
12454 #ifndef CROSSGEN_COMPILE
12455     EEJitManager *jitMgr = ExecutionManager::GetEEJitManager();
12456     if (!jitMgr->LoadJIT())
12457     {
12458 #ifdef ALLOW_SXS_JIT
12459         if (!jitMgr->IsMainJitLoaded())
12460         {
12461             // Don't want to throw InvalidProgram from here.
12462             EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_EXECUTIONENGINE, W("Failed to load JIT compiler"));
12463         }
12464         if (!jitMgr->IsAltJitLoaded())
12465         {
12466             // Don't want to throw InvalidProgram from here.
12467             EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_EXECUTIONENGINE, W("Failed to load alternative JIT compiler"));
12468         }
12469 #else // ALLOW_SXS_JIT
12470         // Don't want to throw InvalidProgram from here.
12471         EEPOLICY_HANDLE_FATAL_ERROR_WITH_MESSAGE(COR_E_EXECUTIONENGINE, W("Failed to load JIT compiler"));
12472 #endif // ALLOW_SXS_JIT
12473     }
12474 #endif // CROSSGEN_COMPILE
12475
12476 #ifdef _DEBUG
12477     // This is here so we can see the name and class easily in the debugger
12478
12479     LPCUTF8 cls  = ftn->GetMethodTable()->GetDebugClassName();
12480     LPCUTF8 name = ftn->GetName();
12481
12482     if (ftn->IsNoMetadata())
12483     {
12484         if (ftn->IsILStub())
12485         {
12486             LOG((LF_JIT, LL_INFO10000, "{ Jitting IL Stub }\n"));
12487         }
12488         else
12489         {
12490             LOG((LF_JIT, LL_INFO10000, "{ Jitting dynamic method }\n"));
12491         }
12492     }
12493     else
12494     {
12495         SString methodString;
12496         if (LoggingOn(LF_JIT, LL_INFO10000))
12497             TypeString::AppendMethodDebug(methodString, ftn);
12498
12499         LOG((LF_JIT, LL_INFO10000, "{ Jitting method (%p) %S %s\n", ftn, methodString.GetUnicode(), ftn->m_pszDebugMethodSignature));
12500     }
12501
12502 #if 0
12503     if (!SString::_stricmp(cls,"ENC") &&
12504        (!SString::_stricmp(name,"G")))
12505     {
12506        static count = 0;
12507        count++;
12508        if (count > 0)
12509             DebugBreak();
12510     }
12511 #endif // 0
12512 #endif // _DEBUG
12513
12514     CORINFO_METHOD_HANDLE ftnHnd = (CORINFO_METHOD_HANDLE)ftn;
12515     CORINFO_METHOD_INFO methodInfo;
12516
12517     getMethodInfoHelper(ftn, ftnHnd, ILHeader, &methodInfo);
12518
12519     // If it's generic then we can only enter through an instantiated md (unless we're just verifying it)
12520     _ASSERTE(flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY) || !ftn->IsGenericMethodDefinition());
12521
12522     // If it's an instance method then it must not be entered from a generic class
12523     _ASSERTE(flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY) || ftn->IsStatic() ||
12524              ftn->GetNumGenericClassArgs() == 0 || ftn->HasClassInstantiation());
12525
12526     // method attributes and signature are consistant
12527     _ASSERTE(!!ftn->IsStatic() == ((methodInfo.args.callConv & CORINFO_CALLCONV_HASTHIS) == 0));
12528
12529     flags = GetCompileFlags(ftn, flags, &methodInfo);
12530
12531 #ifdef _DEBUG
12532     if (!flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION))
12533     {
12534         SString methodString;
12535         if (LoggingOn(LF_VERIFIER, LL_INFO100))
12536             TypeString::AppendMethodDebug(methodString, ftn);
12537
12538         LOG((LF_VERIFIER, LL_INFO100, "{ Will verify method (%p) %S %s\n", ftn, methodString.GetUnicode(), ftn->m_pszDebugMethodSignature));
12539     }
12540 #endif //_DEBUG
12541
12542 #ifdef _TARGET_AMD64_
12543     BOOL fForceRel32Overflow = FALSE;
12544
12545 #ifdef _DEBUG
12546     // Always exercise the overflow codepath with force relocs
12547     if (PEDecoder::GetForceRelocs())
12548         fForceRel32Overflow = TRUE;
12549 #endif
12550
12551     BOOL fAllowRel32 = g_fAllowRel32 | fForceRel32Overflow;
12552
12553     // For determinism, never try to use the REL32 in compilation process
12554     if (IsCompilationProcess())
12555     {
12556         fForceRel32Overflow = FALSE;
12557         fAllowRel32 = FALSE;
12558     }
12559 #endif // _TARGET_AMD64_
12560
12561     for (;;)
12562     {
12563 #ifndef CROSSGEN_COMPILE
12564         CEEJitInfo jitInfo(ftn, ILHeader, jitMgr, flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY));
12565 #else
12566         // This path should be only ever used for verification in crossgen and so we should not need EEJitManager
12567         _ASSERTE(flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY));
12568         CEEInfo jitInfo(ftn, true);
12569         EEJitManager *jitMgr = NULL;
12570 #endif
12571
12572 #if defined(_TARGET_AMD64_) && !defined(CROSSGEN_COMPILE)
12573         if (fForceRel32Overflow)
12574             jitInfo.SetRel32Overflow(fAllowRel32);
12575         jitInfo.SetAllowRel32(fAllowRel32);
12576 #endif
12577
12578         MethodDesc * pMethodForSecurity = jitInfo.GetMethodForSecurity(ftnHnd);
12579
12580         //Since the check could trigger a demand, we have to do this every time.
12581         //This is actually an overly complicated way to make sure that a method can access all its arguments
12582         //and its return type.
12583         AccessCheckOptions::AccessCheckType accessCheckType = AccessCheckOptions::kNormalAccessibilityChecks;
12584         TypeHandle ownerTypeForSecurity = TypeHandle(pMethodForSecurity->GetMethodTable());
12585         DynamicResolver *pAccessContext = NULL;
12586         BOOL doAccessCheck = TRUE;
12587         if (pMethodForSecurity->IsDynamicMethod())
12588         {
12589             doAccessCheck = ModifyCheckForDynamicMethod(pMethodForSecurity->AsDynamicMethodDesc()->GetResolver(),
12590                                                         &ownerTypeForSecurity,
12591                                                         &accessCheckType, &pAccessContext);
12592         }
12593         if (doAccessCheck)
12594         {
12595             AccessCheckOptions accessCheckOptions(accessCheckType,
12596                                                   pAccessContext,
12597                                                   TRUE /*Throw on error*/,
12598                                                   pMethodForSecurity);
12599
12600             StaticAccessCheckContext accessContext(pMethodForSecurity, ownerTypeForSecurity.GetMethodTable());
12601
12602             // We now do an access check from pMethodForSecurity to pMethodForSecurity, its sole purpose is to
12603             // verify that pMethodForSecurity/ownerTypeForSecurity has access to all its parameters.
12604
12605             // ownerTypeForSecurity.GetMethodTable() can be null if the pMethodForSecurity is a DynamicMethod
12606             // associated with a TypeDesc (Array, Ptr, Ref, or FnPtr). That doesn't make any sense, but we will
12607             // just do an access check from a NULL context which means only public types are accessible.
12608             if (!ClassLoader::CanAccess(&accessContext,
12609                                         ownerTypeForSecurity.GetMethodTable(),
12610                                         ownerTypeForSecurity.GetAssembly(),
12611                                         pMethodForSecurity->GetAttrs(),
12612                                         pMethodForSecurity,
12613                                         NULL,
12614                                         accessCheckOptions,
12615                                         TRUE /*Check method transparency*/,
12616                                         TRUE /*Check type transparency*/))
12617             {
12618                 EX_THROW(EEMethodException, (pMethodForSecurity));
12619             }
12620         }
12621
12622         BOOL raiseVerificationException, unverifiableGenericCode;
12623
12624         flags = GetCompileFlagsIfGenericInstantiation(
12625                     ftnHnd,
12626                     flags,
12627                     &jitInfo,
12628                     &raiseVerificationException, 
12629                     &unverifiableGenericCode);
12630
12631         if (raiseVerificationException)
12632             COMPlusThrow(kVerificationException);
12633
12634         CorJitResult res;
12635         PBYTE nativeEntry;
12636         ULONG sizeOfCode;
12637
12638         {
12639             GCX_COOP();
12640
12641             /* There is a double indirection to call compileMethod  - can we
12642                improve this with the new structure? */
12643
12644 #ifdef PERF_TRACK_METHOD_JITTIMES
12645             //Because we're not calling QPC enough.  I'm not going to track times if we're just importing.
12646             LARGE_INTEGER methodJitTimeStart = {0};
12647             if (!flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY))
12648                 QueryPerformanceCounter (&methodJitTimeStart);
12649
12650 #endif
12651 #if defined(ENABLE_PERF_COUNTERS)
12652             START_JIT_PERF();
12653 #endif
12654
12655 #if defined(ENABLE_PERF_COUNTERS)
12656             LARGE_INTEGER CycleStart;
12657             QueryPerformanceCounter (&CycleStart);
12658 #endif // defined(ENABLE_PERF_COUNTERS)
12659
12660             // Note on debuggerTrackInfo arg: if we're only importing (ie, verifying/
12661             // checking to make sure we could JIT, but not actually generating code (
12662             // eg, for inlining), then DON'T TELL THE DEBUGGER about this.
12663             res = CallCompileMethodWithSEHWrapper(jitMgr,
12664                                                   &jitInfo,
12665                                                   &methodInfo,
12666                                                   flags,
12667                                                   &nativeEntry,
12668                                                   &sizeOfCode,
12669                                                   (MethodDesc*)ftn);
12670             LOG((LF_CORDB, LL_EVERYTHING, "Got through CallCompile MethodWithSEHWrapper\n"));
12671
12672 #if FEATURE_PERFMAP
12673             // Save the code size so that it can be reported to the perfmap.
12674             if (pSizeOfCode != NULL)
12675             {
12676                 *pSizeOfCode = sizeOfCode;
12677             }
12678 #endif
12679
12680 #if defined(ENABLE_PERF_COUNTERS)
12681             LARGE_INTEGER CycleStop;
12682             QueryPerformanceCounter(&CycleStop);
12683             GetPerfCounters().m_Jit.timeInJitBase = GetPerfCounters().m_Jit.timeInJit;
12684             GetPerfCounters().m_Jit.timeInJit += static_cast<DWORD>(CycleStop.QuadPart - CycleStart.QuadPart);
12685             GetPerfCounters().m_Jit.cMethodsJitted++;
12686             GetPerfCounters().m_Jit.cbILJitted+=methodInfo.ILCodeSize;
12687
12688 #endif // defined(ENABLE_PERF_COUNTERS)
12689
12690 #if defined(ENABLE_PERF_COUNTERS)
12691             STOP_JIT_PERF();
12692 #endif
12693
12694 #ifdef PERF_TRACK_METHOD_JITTIMES
12695             //store the time in the string buffer.  Module name and token are unique enough.  Also, do not
12696             //capture importing time, just actual compilation time.
12697             if (!flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY))
12698             {
12699                 LARGE_INTEGER methodJitTimeStop;
12700                 QueryPerformanceCounter(&methodJitTimeStop);
12701                 SString codeBase;
12702                 ftn->GetModule()->GetDomainFile()->GetFile()->GetCodeBaseOrName(codeBase);
12703                 codeBase.AppendPrintf(W(",0x%x,%d,%d\n"),
12704                                  //(const WCHAR *)codeBase, //module name
12705                                  ftn->GetMemberDef(), //method token
12706                                  (unsigned)(methodJitTimeStop.QuadPart - methodJitTimeStart.QuadPart), //cycle count
12707                                  methodInfo.ILCodeSize //il size
12708                                 );
12709                 WszOutputDebugString((const WCHAR*)codeBase);
12710             }
12711 #endif // PERF_TRACK_METHOD_JITTIMES
12712
12713         }
12714
12715         LOG((LF_JIT, LL_INFO10000, "Done Jitting method %s::%s  %s }\n",cls,name, ftn->m_pszDebugMethodSignature));
12716
12717         if (!SUCCEEDED(res))
12718         {
12719             COUNTER_ONLY(GetPerfCounters().m_Jit.cJitFailures++);
12720
12721 #ifndef CROSSGEN_COMPILE
12722             jitInfo.BackoutJitData(jitMgr);
12723 #endif
12724
12725             ThrowExceptionForJit(res);
12726         }
12727
12728         if (flags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IMPORT_ONLY))
12729         {
12730             // The method must been processed by the verifier. Note that it may
12731             // either have been marked as verifiable or unverifiable.
12732             // ie. IsVerified() does not imply IsVerifiable()
12733             _ASSERTE(ftn->IsVerified());
12734
12735             // We are done
12736             break;
12737         }
12738
12739         if (!nativeEntry)
12740             COMPlusThrow(kInvalidProgramException);
12741
12742 #if defined(_TARGET_AMD64_) && !defined(CROSSGEN_COMPILE)
12743         if (jitInfo.IsRel32Overflow())
12744         {
12745             // Backout and try again with fAllowRel32 == FALSE.
12746             jitInfo.BackoutJitData(jitMgr);
12747
12748             // Disallow rel32 relocs in future.
12749             g_fAllowRel32 = FALSE;
12750
12751             _ASSERTE(fAllowRel32 != FALSE);
12752             fAllowRel32 = FALSE;
12753             continue;
12754         }
12755 #endif // _TARGET_AMD64_ && !CROSSGEN_COMPILE
12756
12757         LOG((LF_JIT, LL_INFO10000,
12758             "Jitted Entry at" FMT_ADDR "method %s::%s %s\n", DBG_ADDR(nativeEntry),
12759              ftn->m_pszDebugClassName, ftn->m_pszDebugMethodName, ftn->m_pszDebugMethodSignature));
12760
12761 #if defined(FEATURE_CORESYSTEM)
12762
12763 #ifdef _DEBUG
12764         LPCUTF8 pszDebugClassName = ftn->m_pszDebugClassName;
12765         LPCUTF8 pszDebugMethodName = ftn->m_pszDebugMethodName;
12766         LPCUTF8 pszDebugMethodSignature = ftn->m_pszDebugMethodSignature;
12767 #else
12768         LPCUTF8 pszNamespace;
12769         LPCUTF8 pszDebugClassName = ftn->GetMethodTable()->GetFullyQualifiedNameInfo(&pszNamespace);
12770         LPCUTF8 pszDebugMethodName = ftn->GetName();
12771         LPCUTF8 pszDebugMethodSignature = "";
12772 #endif
12773
12774         //DbgPrintf("Jitted Entry at" FMT_ADDR "method %s::%s %s size %08x\n", DBG_ADDR(nativeEntry),
12775         //          pszDebugClassName, pszDebugMethodName, pszDebugMethodSignature, sizeOfCode);
12776 #endif
12777
12778         ClrFlushInstructionCache(nativeEntry, sizeOfCode); 
12779         ret = (PCODE)nativeEntry;
12780
12781 #ifdef _TARGET_ARM_
12782         ret |= THUMB_CODE;
12783 #endif
12784
12785         // We are done
12786         break;
12787     }
12788
12789 #ifdef _DEBUG
12790     FastInterlockIncrement(&g_JitCount);
12791     static BOOL fHeartbeat = -1;
12792
12793     if (fHeartbeat == -1)
12794         fHeartbeat = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_JitHeartbeat);
12795
12796     if (fHeartbeat)
12797         printf(".");
12798 #endif // _DEBUG
12799
12800     COOPERATIVE_TRANSITION_END();
12801     return ret;
12802 }
12803
12804 extern "C" unsigned __stdcall PartialNGenStressPercentage()
12805 {
12806     LIMITED_METHOD_CONTRACT;
12807 #ifndef _DEBUG 
12808     return 0;
12809 #else // _DEBUG
12810     static ConfigDWORD partialNGenStress;
12811     DWORD partialNGenStressVal = partialNGenStress.val(CLRConfig::INTERNAL_partialNGenStress);
12812     _ASSERTE(partialNGenStressVal <= 100);
12813     return partialNGenStressVal;
12814 #endif // _DEBUG
12815 }
12816
12817 #ifdef FEATURE_PREJIT
12818 /*********************************************************************/
12819
12820 //
12821 // Table loading functions
12822 //
12823 void Module::LoadHelperTable()
12824 {
12825     STANDARD_VM_CONTRACT;
12826
12827 #ifndef CROSSGEN_COMPILE
12828     COUNT_T tableSize;
12829     BYTE * table = (BYTE *) GetNativeImage()->GetNativeHelperTable(&tableSize);
12830
12831     if (tableSize == 0)
12832         return;
12833
12834     EnsureWritableExecutablePages(table, tableSize);
12835
12836     BYTE * curEntry   = table;
12837     BYTE * tableEnd   = table + tableSize;
12838
12839 #ifdef LOGGING
12840     int iEntryNumber = 0;
12841 #endif // LOGGING
12842
12843     //
12844     // Fill in helpers
12845     //
12846
12847     while (curEntry < tableEnd)
12848     {
12849         DWORD dwHelper = *(DWORD *)curEntry;
12850
12851         int iHelper = (USHORT)dwHelper;
12852         _ASSERTE(iHelper < CORINFO_HELP_COUNT);
12853
12854         LOG((LF_JIT, LL_INFO1000000, "JIT helper %3d (%-40s: table @ %p, size 0x%x, entry %3d @ %p, pfnHelper %p)\n",
12855             iHelper, hlpFuncTable[iHelper].name, table, tableSize, iEntryNumber, curEntry, hlpFuncTable[iHelper].pfnHelper));
12856
12857 #if defined(ENABLE_FAST_GCPOLL_HELPER)
12858         // The fast GC poll helper works by calling indirect through a pointer that points to either
12859         // JIT_PollGC or JIT_PollGC_Nop, based on whether we need to poll or not. The JIT_PollGC_Nop
12860         // version is just a "ret". The pointer is stored in hlpDynamicFuncTable[DYNAMIC_CORINFO_HELP_POLL_GC].
12861         // See EnableJitGCPoll() and DisableJitGCPoll().
12862         // In NGEN images, we generate a direct call to the helper table. Here, we replace that with
12863         // an indirect jump through the pointer in hlpDynamicFuncTable[DYNAMIC_CORINFO_HELP_POLL_GC].
12864         if (iHelper == CORINFO_HELP_POLL_GC)
12865         {
12866             LOG((LF_JIT, LL_INFO1000000, "JIT helper CORINFO_HELP_POLL_GC (%d); emitting indirect jump to 0x%x\n",
12867                 CORINFO_HELP_POLL_GC, &hlpDynamicFuncTable[DYNAMIC_CORINFO_HELP_POLL_GC].pfnHelper));
12868
12869             emitJumpInd(curEntry, &hlpDynamicFuncTable[DYNAMIC_CORINFO_HELP_POLL_GC].pfnHelper);
12870             curEntry = curEntry + HELPER_TABLE_ENTRY_LEN;
12871         }
12872         else
12873 #endif // ENABLE_FAST_GCPOLL_HELPER
12874         {
12875             PCODE pfnHelper = CEEJitInfo::getHelperFtnStatic((CorInfoHelpFunc)iHelper);
12876
12877             if (dwHelper & CORCOMPILE_HELPER_PTR)
12878             {
12879                 //
12880                 // Indirection cell
12881                 //
12882
12883                 *(TADDR *)curEntry = pfnHelper;
12884
12885                 curEntry = curEntry + sizeof(TADDR);
12886             }
12887             else
12888             {
12889                 //
12890                 // Jump thunk
12891                 //
12892
12893 #if defined(_TARGET_AMD64_)
12894                 *curEntry = X86_INSTR_JMP_REL32;
12895                 *(INT32 *)(curEntry + 1) = rel32UsingJumpStub((INT32 *)(curEntry + 1), pfnHelper, NULL, GetLoaderAllocator());   
12896 #else // all other platforms
12897                 emitJump(curEntry, (LPVOID)pfnHelper);
12898                 _ASSERTE(HELPER_TABLE_ENTRY_LEN >= JUMP_ALLOCATE_SIZE);
12899 #endif
12900
12901                 curEntry = curEntry + HELPER_TABLE_ENTRY_LEN;
12902             }
12903         }
12904 #ifdef LOGGING
12905         // Note that some table entries are sizeof(TADDR) in length, and some are HELPER_TABLE_ENTRY_LEN in length
12906         ++iEntryNumber;
12907 #endif // LOGGING
12908     }
12909
12910     ClrFlushInstructionCache(table, tableSize);
12911 #endif // CROSSGEN_COMPILE
12912 }
12913
12914 #ifdef FEATURE_READYTORUN
12915 CorInfoHelpFunc MapReadyToRunHelper(ReadyToRunHelper helperNum)
12916 {
12917     LIMITED_METHOD_CONTRACT;
12918
12919     switch (helperNum)
12920     {
12921 #define HELPER(readyToRunHelper, corInfoHelpFunc, flags) \
12922     case readyToRunHelper:                                  return corInfoHelpFunc;
12923 #include "readytorunhelpers.h"
12924
12925     case READYTORUN_HELPER_GetString:                       return CORINFO_HELP_STRCNS;
12926
12927     default:                                                return CORINFO_HELP_UNDEF;
12928     }
12929 }
12930
12931 void ComputeGCRefMap(MethodTable * pMT, BYTE * pGCRefMap, size_t cbGCRefMap)
12932 {
12933     STANDARD_VM_CONTRACT;
12934
12935     ZeroMemory(pGCRefMap, cbGCRefMap);
12936
12937     if (!pMT->ContainsPointers())
12938         return;
12939     
12940     CGCDesc* map = CGCDesc::GetCGCDescFromMT(pMT);
12941     CGCDescSeries* cur = map->GetHighestSeries();
12942     CGCDescSeries* last = map->GetLowestSeries();
12943     DWORD size = pMT->GetBaseSize();
12944     _ASSERTE(cur >= last);
12945
12946     do
12947     {
12948         // offset to embedded references in this series must be
12949         // adjusted by the VTable pointer, when in the unboxed state.
12950         size_t offset = cur->GetSeriesOffset() - sizeof(void*);
12951         size_t offsetStop = offset + cur->GetSeriesSize() + size;
12952         while (offset < offsetStop)
12953         {
12954             size_t bit = offset / sizeof(void *);
12955
12956             size_t index = bit / 8;
12957             _ASSERTE(index < cbGCRefMap);
12958             pGCRefMap[index] |= (1 << (bit & 7));
12959
12960             offset += sizeof(void *);
12961         }
12962         cur--;
12963     } while (cur >= last);
12964 }
12965
12966 //
12967 // Type layout check verifies that there was no incompatible change in the value type layout. 
12968 // If there was one, we will fall back to JIT instead of using the pre-generated code from the ready to run image.
12969 // This should be rare situation. Changes in value type layout not common.
12970 //
12971 // The following properties of the value type layout are checked:
12972 // - Size
12973 // - HFA-ness (on platform that support HFAs)
12974 // - Alignment
12975 // - Position of GC references
12976 //
12977 BOOL TypeLayoutCheck(MethodTable * pMT, PCCOR_SIGNATURE pBlob)
12978 {
12979     STANDARD_VM_CONTRACT;
12980
12981     SigPointer p(pBlob);
12982     IfFailThrow(p.SkipExactlyOne());
12983
12984     DWORD dwFlags;
12985     IfFailThrow(p.GetData(&dwFlags));
12986
12987     // Size is checked unconditionally
12988     DWORD dwExpectedSize;
12989     IfFailThrow(p.GetData(&dwExpectedSize));
12990
12991     DWORD dwActualSize = pMT->GetNumInstanceFieldBytes();
12992     if (dwExpectedSize != dwActualSize)
12993         return FALSE;
12994
12995 #ifdef FEATURE_HFA
12996     if (dwFlags & READYTORUN_LAYOUT_HFA)
12997     {
12998         DWORD dwExpectedHFAType;
12999         IfFailThrow(p.GetData(&dwExpectedHFAType));
13000
13001         DWORD dwActualHFAType = pMT->GetHFAType();
13002         if (dwExpectedHFAType != dwActualHFAType)
13003             return FALSE;
13004     }
13005     else
13006     {
13007         if (pMT->IsHFA())
13008             return FALSE;
13009     }
13010 #else
13011     _ASSERTE(!(dwFlags & READYTORUN_LAYOUT_HFA));
13012 #endif
13013
13014     if (dwFlags & READYTORUN_LAYOUT_Alignment)
13015     {
13016         DWORD dwExpectedAlignment = sizeof(void *);
13017         if (!(dwFlags & READYTORUN_LAYOUT_Alignment_Native))
13018         {
13019             IfFailThrow(p.GetData(&dwExpectedAlignment));
13020         }
13021
13022         DWORD dwActualAlignment = CEEInfo::getClassAlignmentRequirementStatic(pMT);
13023         if (dwExpectedAlignment != dwActualAlignment)
13024             return FALSE;
13025
13026     }
13027
13028     if (dwFlags & READYTORUN_LAYOUT_GCLayout)
13029     {
13030         if (dwFlags & READYTORUN_LAYOUT_GCLayout_Empty)
13031         {
13032             if (pMT->ContainsPointers())
13033                 return FALSE;
13034         }
13035         else
13036         {
13037             size_t cbGCRefMap = (dwActualSize / sizeof(TADDR) + 7) / 8;
13038             _ASSERTE(cbGCRefMap > 0);
13039
13040             BYTE * pGCRefMap = (BYTE *)_alloca(cbGCRefMap);
13041
13042             ComputeGCRefMap(pMT, pGCRefMap, cbGCRefMap);
13043
13044             if (memcmp(pGCRefMap, p.GetPtr(), cbGCRefMap) != 0)
13045                 return FALSE;
13046         }
13047     }
13048
13049     return TRUE;
13050 }
13051
13052 #endif // FEATURE_READYTORUN
13053
13054 BOOL LoadDynamicInfoEntry(Module *currentModule,
13055                           RVA fixupRva,
13056                           SIZE_T *entry)
13057 {
13058     STANDARD_VM_CONTRACT;
13059
13060     PCCOR_SIGNATURE pBlob = currentModule->GetNativeFixupBlobData(fixupRva);
13061
13062     BYTE kind = *pBlob++;
13063
13064     Module * pInfoModule = currentModule;
13065
13066     if (kind & ENCODE_MODULE_OVERRIDE)
13067     {
13068         pInfoModule = currentModule->GetModuleFromIndex(CorSigUncompressData(pBlob));
13069         kind &= ~ENCODE_MODULE_OVERRIDE;
13070     }
13071
13072     MethodDesc * pMD = NULL;
13073
13074     PCCOR_SIGNATURE pSig;
13075     DWORD cSig;
13076
13077     mdSignature token;
13078
13079     size_t result = 0;
13080     
13081     switch (kind)
13082     {
13083     case ENCODE_MODULE_HANDLE:
13084         result = (size_t)pInfoModule;
13085         break;
13086
13087     case ENCODE_TYPE_HANDLE:
13088     case ENCODE_TYPE_DICTIONARY:
13089         {
13090             TypeHandle th = ZapSig::DecodeType(currentModule, pInfoModule, pBlob);
13091
13092             if (!th.IsTypeDesc())
13093             {
13094                 if (currentModule->IsReadyToRun())
13095                 {
13096                     // We do not emit activation fixups for version resilient references. Activate the target explicitly.
13097                     th.AsMethodTable()->EnsureInstanceActive();
13098                 }
13099                 else
13100                 {
13101 #ifdef FEATURE_WINMD_RESILIENT
13102                     // We do not emit activation fixups for version resilient references. Activate the target explicitly.
13103                     th.AsMethodTable()->EnsureInstanceActive();
13104 #endif
13105                 }
13106             }
13107
13108             result = (size_t)th.AsPtr();
13109         }
13110         break;
13111
13112     case ENCODE_METHOD_HANDLE:
13113     case ENCODE_METHOD_DICTIONARY:
13114         {
13115             MethodDesc * pMD = ZapSig::DecodeMethod(currentModule, pInfoModule, pBlob);
13116
13117             if (currentModule->IsReadyToRun())
13118             {
13119                 // We do not emit activation fixups for version resilient references. Activate the target explicitly.
13120                 pMD->EnsureActive();
13121             }
13122
13123             result = (size_t)pMD;
13124         }
13125         break;
13126
13127     case ENCODE_FIELD_HANDLE:
13128         result = (size_t) ZapSig::DecodeField(currentModule, pInfoModule, pBlob);
13129         break;
13130
13131 #ifndef CROSSGEN_COMPILE
13132     case ENCODE_STRING_HANDLE:
13133         {
13134             // We need to update strings atomically (due to NoStringInterning attribute). Note
13135             // that modules with string interning dont really need this, as the hash tables have
13136             // their own locking, but dont add more complexity for what will be the non common
13137             // case.
13138
13139             // We will have to lock and update the entry. (this is really a double check, where
13140             // the first check is done in the caller of this function)
13141             DWORD rid = CorSigUncompressData(pBlob);
13142             if (rid == 0)
13143             {
13144                 // Empty string
13145                 result = (size_t)StringObject::GetEmptyStringRefPtr();
13146             }
13147             else
13148             {
13149                 CrstHolder ch(pInfoModule->GetFixupCrst());
13150
13151                 if (!CORCOMPILE_IS_POINTER_TAGGED(*entry) && (*entry != NULL))
13152                 {
13153                     // We lost the race, just return
13154                     return TRUE;
13155                 }
13156
13157                 // For generic instantiations compiled into the ngen image of some other
13158                 // client assembly, we need to ensure that we intern the string
13159                 // in the defining assembly.
13160                 bool mayNeedToSyncWithFixups = pInfoModule != currentModule;
13161
13162                 result = (size_t) pInfoModule->ResolveStringRef(TokenFromRid(rid, mdtString), currentModule->GetDomain(), mayNeedToSyncWithFixups);
13163             }
13164         }
13165         break;
13166
13167     case ENCODE_VARARGS_SIG:
13168         {
13169             mdSignature token = TokenFromRid(
13170                                     CorSigUncompressData(pBlob),
13171                                     mdtSignature);
13172
13173             IfFailThrow(pInfoModule->GetMDImport()->GetSigFromToken(token, &cSig, &pSig));
13174
13175             goto VarArgs;
13176         }
13177         break;
13178
13179     case ENCODE_VARARGS_METHODREF:
13180         {
13181             mdSignature token = TokenFromRid(
13182                                     CorSigUncompressData(pBlob),
13183                                     mdtMemberRef);
13184
13185             LPCSTR szName_Ignore;
13186             IfFailThrow(pInfoModule->GetMDImport()->GetNameAndSigOfMemberRef(token, &pSig, &cSig, &szName_Ignore));
13187
13188             goto VarArgs;
13189         }
13190         break;
13191
13192     case ENCODE_VARARGS_METHODDEF:
13193         {
13194             token = TokenFromRid(
13195                         CorSigUncompressData(pBlob),
13196                         mdtMethodDef);
13197
13198             IfFailThrow(pInfoModule->GetMDImport()->GetSigOfMethodDef(token, &cSig, &pSig));
13199
13200         VarArgs:
13201             result = (size_t) CORINFO_VARARGS_HANDLE(currentModule->GetVASigCookie(Signature(pSig, cSig)));
13202         }
13203         break;
13204
13205         // ENCODE_METHOD_NATIVECALLABLE_HANDLE is same as ENCODE_METHOD_ENTRY_DEF_TOKEN 
13206         // except for AddrOfCode
13207     case ENCODE_METHOD_NATIVE_ENTRY:
13208     case ENCODE_METHOD_ENTRY_DEF_TOKEN:
13209         {
13210             mdToken MethodDef = TokenFromRid(CorSigUncompressData(pBlob), mdtMethodDef);
13211             pMD = MemberLoader::GetMethodDescFromMethodDef(pInfoModule, MethodDef, FALSE);
13212
13213             pMD->PrepareForUseAsADependencyOfANativeImage();
13214
13215             if (currentModule->IsReadyToRun())
13216             {
13217                 // We do not emit activation fixups for version resilient references. Activate the target explicitly.
13218                 pMD->EnsureActive();
13219             }
13220
13221             goto MethodEntry;
13222         }
13223
13224     case ENCODE_METHOD_ENTRY_REF_TOKEN:
13225         {
13226             SigTypeContext typeContext;
13227             mdToken MemberRef = TokenFromRid(CorSigUncompressData(pBlob), mdtMemberRef);
13228             FieldDesc * pFD = NULL;
13229             TypeHandle th;
13230
13231             MemberLoader::GetDescFromMemberRef(pInfoModule, MemberRef, &pMD, &pFD, &typeContext, FALSE /* strict metadata checks */, &th);
13232             _ASSERTE(pMD != NULL);
13233
13234             pMD->PrepareForUseAsADependencyOfANativeImage();
13235
13236             if (currentModule->IsReadyToRun())
13237             {
13238                 // We do not emit activation fixups for version resilient references. Activate the target explicitly.
13239                 pMD->EnsureActive();
13240             }
13241             else
13242             {
13243 #ifdef FEATURE_WINMD_RESILIENT
13244                 // We do not emit activation fixups for version resilient references. Activate the target explicitly.
13245                 pMD->EnsureActive();
13246 #endif
13247             }
13248
13249             goto MethodEntry;
13250         }
13251
13252     case ENCODE_METHOD_ENTRY:
13253         {
13254             pMD = ZapSig::DecodeMethod(currentModule, pInfoModule, pBlob);
13255
13256             if (currentModule->IsReadyToRun())
13257             {
13258                 // We do not emit activation fixups for version resilient references. Activate the target explicitly.
13259                 pMD->EnsureActive();
13260             }
13261
13262         MethodEntry:
13263             if (kind == ENCODE_METHOD_NATIVE_ENTRY)
13264             {
13265                 result = COMDelegate::ConvertToCallback(pMD);
13266             }
13267             else
13268             {
13269                 result = pMD->GetMultiCallableAddrOfCode(CORINFO_ACCESS_ANY);
13270             }
13271
13272         #ifndef _TARGET_ARM_
13273             if (CORCOMPILE_IS_PCODE_TAGGED(result))
13274             {
13275                 // There is a rare case where the function entrypoint may not be aligned. This could happen only for FCalls, 
13276                 // only on x86 and only if we failed to hardbind the fcall (e.g. ngen image for mscorlib.dll does not exist 
13277                 // and /nodependencies flag for ngen was used). The function entrypoints should be aligned in all other cases.
13278                 //
13279                 // We will wrap the unaligned method entrypoint by funcptr stub with aligned entrypoint.
13280                 _ASSERTE(pMD->IsFCall());
13281                 result = pMD->GetLoaderAllocator()->GetFuncPtrStubs()->GetFuncPtrStub(pMD);
13282             }
13283         #endif
13284         }
13285         break;
13286
13287     case ENCODE_SYNC_LOCK:
13288         {
13289             TypeHandle th = ZapSig::DecodeType(currentModule, pInfoModule, pBlob);
13290
13291             result = (size_t) GetClassSync(th.AsMethodTable());
13292         }
13293         break;
13294
13295     case ENCODE_INDIRECT_PINVOKE_TARGET:
13296         {
13297             MethodDesc *pMethod = ZapSig::DecodeMethod(currentModule, pInfoModule, pBlob);
13298
13299             _ASSERTE(pMethod->IsNDirect());
13300             NDirectMethodDesc *pMD = (NDirectMethodDesc*)pMethod;
13301             result = (size_t)(LPVOID)&(pMD->GetWriteableData()->m_pNDirectTarget);
13302         }
13303         break;
13304
13305 #if defined(PROFILING_SUPPORTED)
13306     case ENCODE_PROFILING_HANDLE:
13307         {
13308             MethodDesc *pMethod = ZapSig::DecodeMethod(currentModule, pInfoModule, pBlob);
13309
13310             // methods with no metadata behind cannot be exposed to tools expecting metadata (profiler, debugger...)
13311             // they shouldnever come here as they are called out in GetCompileFlag
13312             _ASSERTE(!pMethod->IsNoMetadata());
13313
13314             FunctionID funId = (FunctionID)pMethod;
13315
13316             BOOL bHookFunction = TRUE;
13317             CORINFO_PROFILING_HANDLE profilerHandle = (CORINFO_PROFILING_HANDLE)funId;
13318
13319             {
13320                 BEGIN_PIN_PROFILER(CORProfilerFunctionIDMapperEnabled());
13321                 profilerHandle = (CORINFO_PROFILING_HANDLE) g_profControlBlock.pProfInterface->EEFunctionIDMapper(funId, &bHookFunction);
13322                 END_PIN_PROFILER();
13323             }
13324
13325             // Profiling handle is opaque token. It does not have to be aligned thus we can not store it in the same location as token.
13326             *EnsureWritablePages(entry+kZapProfilingHandleImportValueIndexClientData) = (SIZE_T)profilerHandle;
13327
13328             if (bHookFunction)
13329             {
13330                 *EnsureWritablePages(entry+kZapProfilingHandleImportValueIndexEnterAddr) = (SIZE_T)(void *)hlpDynamicFuncTable[DYNAMIC_CORINFO_HELP_PROF_FCN_ENTER].pfnHelper;
13331                 *EnsureWritablePages(entry+kZapProfilingHandleImportValueIndexLeaveAddr) = (SIZE_T)(void *)hlpDynamicFuncTable[DYNAMIC_CORINFO_HELP_PROF_FCN_LEAVE].pfnHelper;
13332                 *EnsureWritablePages(entry+kZapProfilingHandleImportValueIndexTailcallAddr) = (SIZE_T)(void *)hlpDynamicFuncTable[DYNAMIC_CORINFO_HELP_PROF_FCN_TAILCALL].pfnHelper;
13333             }
13334             else
13335             {
13336                 *EnsureWritablePages(entry+kZapProfilingHandleImportValueIndexEnterAddr) = (SIZE_T)(void *)JIT_ProfilerEnterLeaveTailcallStub;
13337                 *EnsureWritablePages(entry+kZapProfilingHandleImportValueIndexLeaveAddr) = (SIZE_T)(void *)JIT_ProfilerEnterLeaveTailcallStub;
13338                 *EnsureWritablePages(entry+kZapProfilingHandleImportValueIndexTailcallAddr) = (SIZE_T)(void *)JIT_ProfilerEnterLeaveTailcallStub;
13339             }
13340         }
13341         break;
13342 #endif // PROFILING_SUPPORTED
13343
13344     case ENCODE_STATIC_FIELD_ADDRESS:
13345         {
13346             FieldDesc *pField = ZapSig::DecodeField(currentModule, pInfoModule, pBlob);
13347
13348             pField->GetEnclosingMethodTable()->CheckRestore();
13349
13350             // We can take address of RVA field only since ngened code is domain neutral
13351             _ASSERTE(pField->IsRVA());
13352
13353             // Field address is not aligned thus we can not store it in the same location as token.
13354             *EnsureWritablePages(entry+1) = (size_t)pField->GetStaticAddressHandle(NULL);
13355         }
13356         break;
13357
13358     case ENCODE_VIRTUAL_ENTRY_SLOT:
13359         {
13360             DWORD slot = CorSigUncompressData(pBlob);
13361
13362             TypeHandle ownerType = ZapSig::DecodeType(currentModule, pInfoModule, pBlob);
13363
13364             LOG((LF_ZAP, LL_INFO100000, "     Fixup stub dispatch\n"));
13365
13366             VirtualCallStubManager * pMgr = currentModule->GetLoaderAllocator()->GetVirtualCallStubManager();
13367
13368             // <REVISIT_TODO>
13369             // We should be generating a stub indirection here, but the zapper already uses one level
13370             // of indirection, i.e. we would have to return IAT_PPVALUE to the JIT, and on the whole the JITs
13371             // aren't quite set up to accept that. Furthermore the call sequences would be different - at
13372             // the moment an indirection cell uses "call [cell-addr]" on x86, and instead we would want the
13373             // euqivalent of "call [[call-addr]]".  This could perhaps be implemented as "call [eax]" </REVISIT_TODO>
13374             result = pMgr->GetCallStub(ownerType, slot);
13375         }
13376         break;
13377
13378     case ENCODE_CLASS_ID_FOR_STATICS:
13379         {
13380             TypeHandle th = ZapSig::DecodeType(currentModule, pInfoModule, pBlob);
13381
13382             MethodTable * pMT = th.AsMethodTable();
13383             if (pMT->IsDynamicStatics())
13384             {
13385                 result = pMT->GetModuleDynamicEntryID();
13386             }
13387             else
13388             {
13389                 result = pMT->GetClassIndex();
13390             }
13391         }
13392         break;
13393
13394     case ENCODE_MODULE_ID_FOR_STATICS:
13395         {
13396             result = pInfoModule->GetModuleID();
13397         }
13398         break;
13399
13400     case ENCODE_MODULE_ID_FOR_GENERIC_STATICS:
13401         {
13402             TypeHandle th = ZapSig::DecodeType(currentModule, pInfoModule, pBlob);
13403
13404             MethodTable * pMT = th.AsMethodTable();
13405
13406             result = pMT->GetModuleForStatics()->GetModuleID();
13407         }
13408         break;
13409
13410     case ENCODE_ACTIVE_DEPENDENCY:
13411         {
13412             Module* pModule = currentModule->GetModuleFromIndex(CorSigUncompressData(pBlob));
13413
13414             STRESS_LOG3(LF_ZAP,LL_INFO10000,"Modules are: %08x,%08x,%08x",currentModule,pInfoModule,pModule);
13415             pInfoModule->AddActiveDependency(pModule, FALSE);
13416         }
13417         break;
13418
13419 #ifdef FEATURE_READYTORUN
13420     case ENCODE_READYTORUN_HELPER:
13421         {
13422             DWORD helperNum = CorSigUncompressData(pBlob);
13423
13424             CorInfoHelpFunc corInfoHelpFunc = MapReadyToRunHelper((ReadyToRunHelper)helperNum);
13425             if (corInfoHelpFunc != CORINFO_HELP_UNDEF)
13426             {
13427                 result = (size_t)CEEJitInfo::getHelperFtnStatic(corInfoHelpFunc);
13428             }
13429             else
13430             {
13431                 switch (helperNum)
13432                 {
13433                 case READYTORUN_HELPER_Module:
13434                     {
13435                         Module * pPrevious = InterlockedCompareExchangeT(EnsureWritablePages((Module **)entry), pInfoModule, NULL);
13436                         if (pPrevious != pInfoModule && pPrevious != NULL)
13437                             COMPlusThrowHR(COR_E_FILELOAD, IDS_NATIVE_IMAGE_CANNOT_BE_LOADED_MULTIPLE_TIMES, pInfoModule->GetPath());
13438                         return TRUE;
13439                     }
13440                     break;
13441
13442                 case READYTORUN_HELPER_GSCookie:
13443                     result = (size_t)GetProcessGSCookie();
13444                     break;
13445
13446                 case READYTORUN_HELPER_DelayLoad_MethodCall:
13447                     result = (size_t)GetEEFuncEntryPoint(DelayLoad_MethodCall);
13448                     break;
13449
13450                 case READYTORUN_HELPER_DelayLoad_Helper:
13451                     result = (size_t)GetEEFuncEntryPoint(DelayLoad_Helper);
13452                     break;
13453
13454                 case READYTORUN_HELPER_DelayLoad_Helper_Obj:
13455                     result = (size_t)GetEEFuncEntryPoint(DelayLoad_Helper_Obj);
13456                     break;
13457
13458                 case READYTORUN_HELPER_DelayLoad_Helper_ObjObj:
13459                     result = (size_t)GetEEFuncEntryPoint(DelayLoad_Helper_ObjObj);
13460                     break;
13461
13462                 default:
13463                     STRESS_LOG1(LF_ZAP, LL_WARNING, "Unknown READYTORUN_HELPER %d\n", helperNum);
13464                     _ASSERTE(!"Unknown READYTORUN_HELPER");
13465                     return FALSE;
13466                 }
13467             }
13468         }
13469         break;
13470
13471     case ENCODE_FIELD_OFFSET:
13472         {
13473             FieldDesc * pFD = ZapSig::DecodeField(currentModule, pInfoModule, pBlob);
13474             _ASSERTE(!pFD->IsStatic());
13475             _ASSERTE(!pFD->IsFieldOfValueType());
13476
13477             DWORD dwOffset = (DWORD)sizeof(Object) + pFD->GetOffset();
13478
13479             if (dwOffset > MAX_UNCHECKED_OFFSET_FOR_NULL_OBJECT)
13480                 return FALSE;
13481             result = dwOffset;
13482         }
13483         break;
13484
13485     case ENCODE_FIELD_BASE_OFFSET:
13486         {
13487             TypeHandle th = ZapSig::DecodeType(currentModule, pInfoModule, pBlob);
13488
13489             MethodTable * pMT = th.AsMethodTable();
13490             _ASSERTE(!pMT->IsValueType());
13491
13492             DWORD dwOffsetBase = ReadyToRunInfo::GetFieldBaseOffset(pMT);
13493             if (dwOffsetBase > MAX_UNCHECKED_OFFSET_FOR_NULL_OBJECT)
13494                 return FALSE;
13495             result = dwOffsetBase;
13496         }
13497         break;
13498
13499     case ENCODE_CHECK_TYPE_LAYOUT:
13500         {
13501             TypeHandle th = ZapSig::DecodeType(currentModule, pInfoModule, pBlob);
13502             MethodTable * pMT = th.AsMethodTable();
13503             _ASSERTE(pMT->IsValueType());
13504
13505             if (!TypeLayoutCheck(pMT, pBlob))
13506                 return FALSE;
13507
13508             result = 1;
13509         }
13510         break;
13511
13512     case ENCODE_CHECK_FIELD_OFFSET:
13513         {
13514             DWORD dwExpectedOffset = CorSigUncompressData(pBlob);
13515
13516             FieldDesc * pFD = ZapSig::DecodeField(currentModule, pInfoModule, pBlob);
13517             _ASSERTE(!pFD->IsStatic());
13518
13519             DWORD dwOffset = pFD->GetOffset();
13520             if (!pFD->IsFieldOfValueType())
13521                 dwOffset += sizeof(Object);
13522
13523             if (dwExpectedOffset != dwOffset)
13524                 return FALSE;
13525
13526             result = 1;
13527         }
13528         break;
13529 #endif // FEATURE_READYTORUN
13530
13531 #endif // CROSSGEN_COMPILE
13532
13533     default:
13534         STRESS_LOG1(LF_ZAP, LL_WARNING, "Unknown FIXUP_BLOB_KIND %d\n", kind);
13535         _ASSERTE(!"Unknown FIXUP_BLOB_KIND");
13536         return FALSE;
13537     }
13538
13539     MemoryBarrier();
13540     *EnsureWritablePages(entry) = result;
13541
13542     return TRUE;
13543 }
13544 #endif // FEATURE_PREJIT
13545
13546 void* CEEInfo::getTailCallCopyArgsThunk(CORINFO_SIG_INFO       *pSig,
13547                                         CorInfoHelperTailCallSpecialHandling flags)
13548 {
13549     CONTRACTL {
13550         SO_TOLERANT;
13551         THROWS;
13552         GC_TRIGGERS;
13553         MODE_PREEMPTIVE;
13554     } CONTRACTL_END;
13555
13556     void * ftn = NULL;
13557
13558 #if defined(_TARGET_AMD64_) || defined(_TARGET_ARM_)
13559
13560     JIT_TO_EE_TRANSITION();
13561
13562     Stub* pStub = CPUSTUBLINKER::CreateTailCallCopyArgsThunk(pSig, flags);
13563         
13564     ftn = (void*)pStub->GetEntryPoint();
13565
13566     EE_TO_JIT_TRANSITION();
13567
13568 #endif // _TARGET_AMD64_ || _TARGET_ARM_
13569
13570     return ftn;
13571 }
13572
13573 void CEEInfo::allocMem (
13574         ULONG               hotCodeSize,    /* IN */
13575         ULONG               coldCodeSize,   /* IN */
13576         ULONG               roDataSize,     /* IN */
13577         ULONG               xcptnsCount,    /* IN */
13578         CorJitAllocMemFlag  flag,           /* IN */
13579         void **             hotCodeBlock,   /* OUT */
13580         void **             coldCodeBlock,  /* OUT */
13581         void **             roDataBlock     /* OUT */
13582         )
13583 {
13584     LIMITED_METHOD_CONTRACT;
13585     UNREACHABLE();      // only called on derived class.
13586 }
13587
13588 void CEEInfo::reserveUnwindInfo (
13589         BOOL                isFunclet,             /* IN */
13590         BOOL                isColdCode,            /* IN */
13591         ULONG               unwindSize             /* IN */
13592         )
13593 {
13594     LIMITED_METHOD_CONTRACT;
13595     UNREACHABLE();      // only called on derived class.
13596 }
13597
13598 void CEEInfo::allocUnwindInfo (
13599         BYTE *              pHotCode,              /* IN */
13600         BYTE *              pColdCode,             /* IN */
13601         ULONG               startOffset,           /* IN */
13602         ULONG               endOffset,             /* IN */
13603         ULONG               unwindSize,            /* IN */
13604         BYTE *              pUnwindBlock,          /* IN */
13605         CorJitFuncKind      funcKind               /* IN */
13606         )
13607 {
13608     LIMITED_METHOD_CONTRACT;
13609     UNREACHABLE();      // only called on derived class.
13610 }
13611
13612 void * CEEInfo::allocGCInfo (
13613         size_t                  size        /* IN */
13614         )
13615 {
13616     LIMITED_METHOD_CONTRACT;
13617     UNREACHABLE_RET();      // only called on derived class.
13618 }
13619
13620 void CEEInfo::setEHcount (
13621         unsigned             cEH    /* IN */
13622         )
13623 {
13624     LIMITED_METHOD_CONTRACT;
13625     UNREACHABLE();      // only called on derived class.
13626 }
13627
13628 void CEEInfo::setEHinfo (
13629         unsigned             EHnumber,   /* IN  */
13630         const CORINFO_EH_CLAUSE *clause      /* IN */
13631         )
13632 {
13633     LIMITED_METHOD_CONTRACT;
13634     UNREACHABLE();      // only called on derived class.
13635 }
13636
13637 InfoAccessType CEEInfo::constructStringLiteral(CORINFO_MODULE_HANDLE scopeHnd,
13638                                                mdToken metaTok,
13639                                                void **ppValue)
13640 {
13641     LIMITED_METHOD_CONTRACT;
13642     UNREACHABLE();      // only called on derived class.
13643 }
13644
13645 InfoAccessType CEEInfo::emptyStringLiteral(void ** ppValue)
13646 {
13647     LIMITED_METHOD_CONTRACT;
13648     _ASSERTE(isVerifyOnly());
13649     *ppValue = (void *)0x10;
13650     return IAT_PVALUE;
13651 }
13652
13653 void* CEEInfo::getFieldAddress(CORINFO_FIELD_HANDLE fieldHnd,
13654                                   void **ppIndirection)
13655 {
13656     LIMITED_METHOD_CONTRACT;
13657     _ASSERTE(isVerifyOnly());
13658     if (ppIndirection != NULL)
13659         *ppIndirection = NULL;
13660     return (void *)0x10;
13661 }
13662
13663 void* CEEInfo::getMethodSync(CORINFO_METHOD_HANDLE ftnHnd,
13664                              void **ppIndirection)
13665 {
13666     LIMITED_METHOD_CONTRACT;
13667     UNREACHABLE();      // only called on derived class.
13668 }
13669
13670 HRESULT CEEInfo::allocBBProfileBuffer (
13671         ULONG                 count,           // The number of basic blocks that we have
13672         ProfileBuffer **      profileBuffer
13673         )
13674 {
13675     LIMITED_METHOD_CONTRACT;
13676     UNREACHABLE_RET();      // only called on derived class.
13677 }
13678
13679 HRESULT CEEInfo::getBBProfileData(
13680         CORINFO_METHOD_HANDLE ftnHnd,
13681         ULONG *               count,           // The number of basic blocks that we have
13682         ProfileBuffer **      profileBuffer,
13683         ULONG *               numRuns
13684         )
13685 {
13686     LIMITED_METHOD_CONTRACT;
13687     UNREACHABLE_RET();      // only called on derived class.
13688 }
13689
13690
13691 void CEEInfo::recordCallSite(
13692         ULONG                 instrOffset,  /* IN */
13693         CORINFO_SIG_INFO *    callSig,      /* IN */
13694         CORINFO_METHOD_HANDLE methodHandle  /* IN */
13695         )
13696 {
13697     LIMITED_METHOD_CONTRACT;
13698     UNREACHABLE();      // only called on derived class.
13699 }
13700
13701 void CEEInfo::recordRelocation(
13702         void *                 location,   /* IN  */
13703         void *                 target,     /* IN  */
13704         WORD                   fRelocType, /* IN  */
13705         WORD                   slotNum,  /* IN  */
13706         INT32                  addlDelta /* IN  */
13707         )
13708 {
13709     LIMITED_METHOD_CONTRACT;
13710     UNREACHABLE();      // only called on derived class.
13711 }
13712
13713 WORD CEEInfo::getRelocTypeHint(void * target)
13714 {
13715     LIMITED_METHOD_CONTRACT;
13716     UNREACHABLE_RET();      // only called on derived class.
13717 }
13718
13719 void CEEInfo::getModuleNativeEntryPointRange(
13720         void ** pStart, /* OUT */
13721         void ** pEnd    /* OUT */
13722         )
13723 {
13724     LIMITED_METHOD_CONTRACT;
13725     UNREACHABLE();      // only called on derived class.
13726 }
13727
13728 DWORD CEEInfo::getExpectedTargetArchitecture()
13729 {
13730     LIMITED_METHOD_CONTRACT;
13731
13732     return IMAGE_FILE_MACHINE_NATIVE;
13733 }
13734
13735 void CEEInfo::setBoundaries(CORINFO_METHOD_HANDLE ftn, ULONG32 cMap,
13736                                ICorDebugInfo::OffsetMapping *pMap)
13737 {
13738     LIMITED_METHOD_CONTRACT;
13739     UNREACHABLE();      // only called on derived class.
13740 }
13741
13742 void CEEInfo::setVars(CORINFO_METHOD_HANDLE ftn, ULONG32 cVars, ICorDebugInfo::NativeVarInfo *vars)
13743 {
13744     LIMITED_METHOD_CONTRACT;
13745     UNREACHABLE();      // only called on derived class.
13746 }
13747
13748 void* CEEInfo::getHelperFtn(CorInfoHelpFunc    ftnNum,         /* IN  */
13749                             void **            ppIndirection)  /* OUT */
13750 {
13751     LIMITED_METHOD_CONTRACT;
13752     UNREACHABLE();      // only called on derived class.
13753 }
13754
13755 // Active dependency helpers
13756 void CEEInfo::addActiveDependency(CORINFO_MODULE_HANDLE moduleFrom,CORINFO_MODULE_HANDLE moduleTo)
13757 {
13758     LIMITED_METHOD_CONTRACT;
13759     UNREACHABLE();      // only called on derived class.
13760 }
13761
13762 void CEEInfo::GetProfilingHandle(BOOL                      *pbHookFunction,
13763                                  void                     **pProfilerHandle,
13764                                  BOOL                      *pbIndirectedHandles)
13765 {
13766     LIMITED_METHOD_CONTRACT;
13767     UNREACHABLE();      // only called on derived class.
13768 }
13769
13770 #endif // !DACCESS_COMPILE
13771
13772 EECodeInfo::EECodeInfo()
13773 {
13774     WRAPPER_NO_CONTRACT;
13775
13776     m_codeAddress = NULL;
13777
13778     m_pJM = NULL;
13779     m_pMD = NULL;
13780     m_relOffset = 0;
13781
13782 #ifdef WIN64EXCEPTIONS
13783     m_pFunctionEntry = NULL;
13784 #endif
13785 }
13786
13787 void EECodeInfo::Init(PCODE codeAddress)
13788 {
13789     CONTRACTL {
13790         NOTHROW;
13791         GC_NOTRIGGER;
13792         SO_TOLERANT;
13793     } CONTRACTL_END;
13794
13795     Init(codeAddress, ExecutionManager::GetScanFlags());
13796 }
13797
13798 void EECodeInfo::Init(PCODE codeAddress, ExecutionManager::ScanFlag scanFlag)
13799 {
13800     CONTRACTL {
13801         NOTHROW;
13802         GC_NOTRIGGER;
13803         SO_TOLERANT;
13804     } CONTRACTL_END;
13805
13806     m_codeAddress = codeAddress;
13807
13808     RangeSection * pRS = ExecutionManager::FindCodeRange(codeAddress, scanFlag);
13809     if (pRS == NULL)
13810         goto Invalid;
13811
13812     if (!pRS->pjit->JitCodeToMethodInfo(pRS, codeAddress, &m_pMD, this))
13813         goto Invalid;
13814
13815     m_pJM = pRS->pjit;
13816     return;
13817
13818 Invalid:
13819     m_pJM = NULL;
13820     m_pMD = NULL;
13821     m_relOffset = 0;
13822
13823 #ifdef WIN64EXCEPTIONS
13824     m_pFunctionEntry = NULL;
13825 #endif
13826 }
13827
13828 TADDR EECodeInfo::GetSavedMethodCode()
13829 {
13830     CONTRACTL {
13831         // All EECodeInfo methods must be NOTHROW/GC_NOTRIGGER since they can
13832         // be used during GC.
13833         NOTHROW;
13834         GC_NOTRIGGER;
13835         HOST_NOCALLS;
13836         SUPPORTS_DAC;
13837     } CONTRACTL_END;
13838 #ifndef _WIN64
13839 #if defined(HAVE_GCCOVER)
13840     _ASSERTE (!m_pMD->m_GcCover || GCStress<cfg_instr>::IsEnabled());
13841     if (GCStress<cfg_instr>::IsEnabled()
13842         && m_pMD->m_GcCover)
13843     {
13844         _ASSERTE(m_pMD->m_GcCover->savedCode);
13845
13846         // Make sure we return the TADDR of savedCode here.  The byte array is not marshaled automatically.
13847         // The caller is responsible for any necessary marshaling.
13848         return PTR_TO_MEMBER_TADDR(GCCoverageInfo, m_pMD->m_GcCover, savedCode);
13849     }
13850 #endif //defined(HAVE_GCCOVER)
13851 #endif
13852
13853     return GetStartAddress();
13854 }
13855
13856 TADDR EECodeInfo::GetStartAddress()
13857 {
13858     CONTRACTL {
13859         NOTHROW;
13860         GC_NOTRIGGER;
13861         HOST_NOCALLS;
13862         SUPPORTS_DAC;
13863     } CONTRACTL_END;
13864
13865     return m_pJM->JitTokenToStartAddress(m_methodToken);
13866 }
13867
13868 #if defined(WIN64EXCEPTIONS)
13869
13870 // ----------------------------------------------------------------------------
13871 // EECodeInfo::GetMainFunctionInfo
13872 //
13873 // Description: 
13874 //    Simple helper to transform a funclet's EECodeInfo into a parent function EECodeInfo.
13875 //
13876 // Return Value:
13877 //    An EECodeInfo for the start of the main function body (offset 0).
13878 //
13879
13880 EECodeInfo EECodeInfo::GetMainFunctionInfo()
13881 {
13882     LIMITED_METHOD_CONTRACT;
13883     SUPPORTS_DAC;
13884
13885     EECodeInfo result = *this;
13886     result.m_relOffset = 0;
13887     result.m_codeAddress = this->GetStartAddress();
13888     result.m_pFunctionEntry = NULL;
13889
13890     return result;
13891 }
13892
13893 PTR_RUNTIME_FUNCTION EECodeInfo::GetFunctionEntry()
13894 {
13895     LIMITED_METHOD_CONTRACT;
13896     SUPPORTS_DAC;
13897
13898     if (m_pFunctionEntry == NULL)
13899         m_pFunctionEntry = m_pJM->LazyGetFunctionEntry(this);
13900     return m_pFunctionEntry;
13901 }
13902
13903 #if defined(_TARGET_AMD64_)
13904
13905 BOOL EECodeInfo::HasFrameRegister()
13906 {
13907     LIMITED_METHOD_CONTRACT;
13908
13909     PTR_RUNTIME_FUNCTION pFuncEntry = GetFunctionEntry();
13910     _ASSERTE(pFuncEntry != NULL);
13911
13912     BOOL fHasFrameRegister = FALSE;
13913     PUNWIND_INFO pUnwindInfo = (PUNWIND_INFO)(GetModuleBase() + pFuncEntry->UnwindData);
13914     if (pUnwindInfo->FrameRegister != 0)
13915     {
13916         fHasFrameRegister = TRUE;
13917         _ASSERTE(pUnwindInfo->FrameRegister == kRBP);
13918     }
13919
13920     return fHasFrameRegister;
13921 }
13922 #endif // defined(_TARGET_AMD64_)
13923
13924 #endif // defined(WIN64EXCEPTIONS)
13925
13926
13927 #if defined(_TARGET_AMD64_)
13928 // ----------------------------------------------------------------------------
13929 // EECodeInfo::GetUnwindInfoHelper
13930 //
13931 // Description: 
13932 //    Simple helper to return a pointer to the UNWIND_INFO given the offset to the unwind info.
13933 //    On DAC builds, this function will read the memory from the target process and create a host copy.
13934 //
13935 // Arguments:
13936 //    * unwindInfoOffset - This is the offset to the unwind info, relative to the beginning of the code heap
13937 //        for jitted code or to the module base for ngned code. this->GetModuleBase() will return the correct
13938 //        module base.
13939 //
13940 // Return Value:
13941 //    Return a pointer to the UNWIND_INFO.  On DAC builds, this function will create a host copy of the
13942 //    UNWIND_INFO and return a host pointer.  It will correctly read all of the memory for the variable-sized 
13943 //    unwind info.
13944 //
13945
13946 UNWIND_INFO * EECodeInfo::GetUnwindInfoHelper(ULONG unwindInfoOffset)
13947 {
13948 #if defined(DACCESS_COMPILE)
13949     return DacGetUnwindInfo(static_cast<TADDR>(this->GetModuleBase() + unwindInfoOffset));
13950 #else  // !DACCESS_COMPILE
13951     return reinterpret_cast<UNWIND_INFO *>(this->GetModuleBase() + unwindInfoOffset);
13952 #endif // !DACCESS_COMPILE
13953 }
13954
13955 // ----------------------------------------------------------------------------
13956 // EECodeInfo::GetFixedStackSize
13957 //
13958 // Description: 
13959 //    Return the fixed stack size of a specified managed method.  This function DOES NOT take current control
13960 //    PC into account.  So the fixed stack size returned by this function is not valid in the prolog or
13961 //    the epilog.
13962 //    
13963 // Return Value:
13964 //    Return the fixed stack size.
13965 //    
13966 // Notes:
13967 //    * For method with dynamic stack allocations, this function will return the fixed stack size on X64 (the
13968 //        stack size immediately after the prolog), and it will return 0 on IA64. This difference is due to
13969 //        the different unwind info encoding.
13970 //        
13971
13972 ULONG EECodeInfo::GetFixedStackSize()
13973 {
13974     WRAPPER_NO_CONTRACT;
13975     SUPPORTS_DAC;
13976
13977     ULONG uFixedStackSize = 0;
13978
13979     ULONG uDummy = 0;
13980     GetOffsetsFromUnwindInfo(&uFixedStackSize, &uDummy);
13981     
13982     return uFixedStackSize;
13983 }
13984
13985 #define kRBP    5
13986 // The information returned by this method is only valid if we are not in a prolog or an epilog.
13987 // Since this method is only used for the security stackwalk cache, this assumption is valid, since
13988 // we cannot make a call in a prolog or an epilog.
13989 //
13990 // The next assumption is that only rbp is used as a frame register in jitted code.  There is an 
13991 // assert below to guard this assumption.
13992 void EECodeInfo::GetOffsetsFromUnwindInfo(ULONG* pRSPOffset, ULONG* pRBPOffset)
13993 {
13994     LIMITED_METHOD_CONTRACT;
13995     SUPPORTS_DAC;
13996
13997     _ASSERTE((pRSPOffset != NULL) && (pRBPOffset != NULL));
13998
13999     // moduleBase is a target address.
14000     TADDR moduleBase = GetModuleBase();
14001
14002     DWORD unwindInfo = RUNTIME_FUNCTION__GetUnwindInfoAddress(GetFunctionEntry());
14003
14004     if ((unwindInfo & RUNTIME_FUNCTION_INDIRECT) != 0)
14005     {
14006         unwindInfo = RUNTIME_FUNCTION__GetUnwindInfoAddress(PTR_RUNTIME_FUNCTION(moduleBase + (unwindInfo & ~RUNTIME_FUNCTION_INDIRECT)));
14007     }
14008
14009     UNWIND_INFO * pInfo = GetUnwindInfoHelper(unwindInfo);
14010     if (pInfo->Flags & UNW_FLAG_CHAININFO)
14011     {
14012         _ASSERTE(!"GetRbpOffset() - chained unwind info used, violating assumptions of the security stackwalk cache");
14013         DebugBreak();
14014     }
14015
14016     // Either we are not using a frame pointer, or we are using rbp as the frame pointer.
14017     if ( (pInfo->FrameRegister != 0) && (pInfo->FrameRegister != kRBP) )
14018     {
14019         _ASSERTE(!"GetRbpOffset() - non-RBP frame pointer used, violating assumptions of the security stackwalk cache");
14020         DebugBreak();
14021     }
14022
14023     // Walk the unwind info.
14024     ULONG StackOffset     = 0;
14025     ULONG StackSize       = 0;
14026     for (int i = 0; i < pInfo->CountOfUnwindCodes; i++)
14027     {
14028         ULONG UnwindOp = pInfo->UnwindCode[i].UnwindOp;
14029         ULONG OpInfo   = pInfo->UnwindCode[i].OpInfo;
14030
14031         if (UnwindOp == UWOP_SAVE_NONVOL)
14032         {
14033             if (OpInfo == kRBP)
14034             {
14035                 StackOffset = pInfo->UnwindCode[i+1].FrameOffset * 8;
14036             }
14037         }
14038         else if (UnwindOp == UWOP_SAVE_NONVOL_FAR)
14039         {
14040             if (OpInfo == kRBP)
14041             {
14042                 StackOffset  =  pInfo->UnwindCode[i + 1].FrameOffset;
14043                 StackOffset += (pInfo->UnwindCode[i + 2].FrameOffset << 16);
14044             }
14045         }
14046         else if (UnwindOp == UWOP_ALLOC_SMALL)
14047         {
14048             StackSize += (OpInfo * 8) + 8;
14049         }
14050         else if (UnwindOp == UWOP_ALLOC_LARGE)
14051         {
14052             ULONG IncrementalStackSize = pInfo->UnwindCode[i + 1].FrameOffset;
14053             if (OpInfo == 0)
14054             {
14055                 IncrementalStackSize *= 8;
14056             }
14057             else
14058             {
14059                 IncrementalStackSize += (pInfo->UnwindCode[i + 2].FrameOffset << 16);
14060  
14061                 // This is a special opcode.  We need to increment the index by 1 in addition to the normal adjustments.
14062                 i += 1;        
14063             }
14064             StackSize += IncrementalStackSize;
14065         }
14066         else if (UnwindOp == UWOP_PUSH_NONVOL)
14067         {
14068             // Because of constraints on epilogs, this unwind opcode is always last in the unwind code array.
14069             // This means that StackSize has been initialized already when we first see this unwind opcode.  
14070             // Note that the intial value of StackSize does not include the stack space used for pushes.
14071             // Thus, here we only need to increment StackSize 8 bytes at a time until we see the unwind code for "push rbp".
14072             if (OpInfo == kRBP)
14073             {
14074                 StackOffset = StackSize;
14075             }
14076
14077             StackSize += 8;
14078         }
14079
14080         // Adjust the index into the unwind code array.
14081         i += UnwindOpExtraSlotTable[UnwindOp];
14082     }
14083
14084     *pRSPOffset = StackSize + 8;        // add 8 for the return address
14085     *pRBPOffset = StackOffset;
14086 }
14087 #undef kRBP
14088
14089
14090 #if defined(_DEBUG) && defined(HAVE_GCCOVER)
14091
14092 LPVOID                EECodeInfo::findNextFunclet (LPVOID pvFuncletStart, SIZE_T cbCode, LPVOID *ppvFuncletEnd)
14093 {
14094     CONTRACTL {
14095         NOTHROW;
14096         GC_NOTRIGGER;
14097     } CONTRACTL_END;
14098
14099     while (cbCode > 0)
14100     {
14101         PT_RUNTIME_FUNCTION   pFunctionEntry;
14102         ULONGLONG           uImageBase;
14103 #ifdef FEATURE_PAL
14104         EECodeInfo codeInfo;
14105         codeInfo.Init((PCODE)pvFuncletStart);
14106         pFunctionEntry = codeInfo.GetFunctionEntry();
14107         uImageBase = (ULONGLONG)codeInfo.GetModuleBase();
14108 #else // !FEATURE_PAL
14109         //
14110         // This is GCStress debug only - use the slow OS APIs to enumerate funclets
14111         //
14112
14113         pFunctionEntry = (PT_RUNTIME_FUNCTION) RtlLookupFunctionEntry((ULONGLONG)pvFuncletStart,
14114                               &uImageBase
14115                               AMD64_ARG(NULL)
14116                               );
14117 #endif
14118
14119         if (pFunctionEntry != NULL)
14120         {
14121 #ifdef FEATURE_PREJIT
14122             // workaround: Check for indirect entry that is generated for cold part of main method body.
14123             if ((TADDR)pvFuncletStart < (TADDR)uImageBase + pFunctionEntry->BeginAddress ||
14124                 (TADDR)uImageBase + pFunctionEntry->EndAddress <= (TADDR)pvFuncletStart)
14125             {
14126                 Module * pZapModule = ExecutionManager::FindZapModule((TADDR)pvFuncletStart);
14127                 NGenLayoutInfo * pLayoutInfo = pZapModule->GetNGenLayoutInfo();
14128
14129                 int ColdFunctionIndex = NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod((DWORD)((TADDR)pvFuncletStart - uImageBase),
14130                                                                                pLayoutInfo->m_pRuntimeFunctions[2],
14131                                                                                0, pLayoutInfo->m_nRuntimeFunctions[2] - 1);
14132
14133                 pFunctionEntry = pLayoutInfo->m_pRuntimeFunctions[2] + ColdFunctionIndex;
14134             }
14135 #endif
14136
14137             _ASSERTE((TADDR)pvFuncletStart == (TADDR)uImageBase + pFunctionEntry->BeginAddress);
14138             _ASSERTE((TADDR)uImageBase + pFunctionEntry->EndAddress <= (TADDR)pvFuncletStart + cbCode);
14139             *ppvFuncletEnd = (LPVOID)(uImageBase + pFunctionEntry->EndAddress);
14140             return (LPVOID)(uImageBase + pFunctionEntry->BeginAddress);
14141         }
14142
14143         pvFuncletStart = (LPVOID)((TADDR)pvFuncletStart + 1);
14144         cbCode--;
14145     }
14146
14147     return NULL;
14148 }
14149 #endif // defined(_DEBUG) && !defined(HAVE_GCCOVER)
14150 #endif // defined(_TARGET_AMD64_)