Merge pull request #9610 from sdmaclea/PR-ARM64-CALLSITE
[platform/upstream/coreclr.git] / src / vm / runtimehandles.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
6 #include "common.h"
7 #include "corhdr.h"
8 #include "runtimehandles.h"
9 #include "object.h"
10 #include "class.h"
11 #include "method.hpp"
12 #include "typehandle.h"
13 #include "field.h"
14 #include "siginfo.hpp"
15 #include "clsload.hpp"
16 #include "typestring.h"
17 #include "typeparse.h"
18 #include "holder.h"
19 #include "codeman.h"
20 #include "corhlpr.h"
21 #include "jitinterface.h"
22 #include "stackprobe.h"
23 #include "eeconfig.h"
24 #include "eehash.h"
25 #include "objecthandle.h"
26 #include "interoputil.h"
27 #include "typedesc.h"
28 #include "virtualcallstub.h"
29 #include "contractimpl.h"
30 #include "dynamicmethod.h"
31 #include "peimagelayout.inl"
32 #include "security.h"
33 #include "eventtrace.h"
34 #include "invokeutil.h"
35
36
37 FCIMPL3(FC_BOOL_RET, Utf8String::EqualsCaseSensitive, LPCUTF8 szLhs, LPCUTF8 szRhs, INT32 stringNumBytes)
38 {
39     CONTRACTL {
40         FCALL_CHECK;
41         PRECONDITION(CheckPointer(szLhs));
42         PRECONDITION(CheckPointer(szRhs));
43     }
44     CONTRACTL_END;
45
46     // Important: the string in pSsz isn't null terminated so the length must be used
47     // when performing operations on the string.
48
49     // At this point, both the left and right strings are guaranteed to have the
50     // same length.
51     FC_RETURN_BOOL(strncmp(szLhs, szRhs, stringNumBytes) == 0);
52 }
53 FCIMPLEND
54
55 BOOL QCALLTYPE Utf8String::EqualsCaseInsensitive(LPCUTF8 szLhs, LPCUTF8 szRhs, INT32 stringNumBytes)
56 {
57     QCALL_CONTRACT;
58
59     // Important: the string in pSsz isn't null terminated so the length must be used
60     // when performing operations on the string.
61     
62     BOOL fStringsEqual = FALSE;
63     
64     BEGIN_QCALL;
65
66     _ASSERTE(CheckPointer(szLhs));
67     _ASSERTE(CheckPointer(szRhs));
68
69     // At this point, both the left and right strings are guaranteed to have the
70     // same length. 
71     StackSString lhs(SString::Utf8, szLhs, stringNumBytes);
72     StackSString rhs(SString::Utf8, szRhs, stringNumBytes);
73
74     // We can use SString for simple case insensitive compares
75     fStringsEqual = lhs.EqualsCaseInsensitive(rhs);
76
77     END_QCALL;
78
79     return fStringsEqual;
80 }
81
82 ULONG QCALLTYPE Utf8String::HashCaseInsensitive(LPCUTF8 sz, INT32 stringNumBytes)
83 {
84     QCALL_CONTRACT;
85
86     // Important: the string in pSsz isn't null terminated so the length must be used
87     // when performing operations on the string.
88
89     ULONG hashValue = 0;
90     
91     BEGIN_QCALL;
92
93     StackSString str(SString::Utf8, sz, stringNumBytes);
94     hashValue = str.HashCaseInsensitive();
95
96     END_QCALL;
97
98     return hashValue;
99 }
100
101 static BOOL CheckCAVisibilityFromDecoratedType(MethodTable* pCAMT, MethodDesc* pCACtor, MethodTable* pDecoratedMT, Module* pDecoratedModule)
102 {
103     CONTRACTL
104     {
105         THROWS;
106         GC_TRIGGERS;
107         MODE_ANY;
108         PRECONDITION(CheckPointer(pCAMT));
109         PRECONDITION(CheckPointer(pCACtor, NULL_OK));
110         PRECONDITION(CheckPointer(pDecoratedMT, NULL_OK));
111         PRECONDITION(CheckPointer(pDecoratedModule));
112     }
113     CONTRACTL_END;
114
115     DWORD dwAttr = mdPublic;
116
117     if (pCACtor != NULL)
118     {
119         // Allowing a dangerous method to be called in custom attribute instantiation is, well, dangerous.
120         // E.g. a malicious user can craft a custom attribute record that fools us into creating a DynamicMethod
121         // object attached to typeof(System.Reflection.CustomAttribute) and thus gain access to mscorlib internals.
122         if (InvokeUtil::IsDangerousMethod(pCACtor))
123             return FALSE;
124
125         _ASSERTE(pCACtor->IsCtor());
126
127         dwAttr = pCACtor->GetAttrs();
128     }
129     
130     StaticAccessCheckContext accessContext(NULL, pDecoratedMT, pDecoratedModule->GetAssembly());
131
132     // Don't do transparency check here. Custom attributes have different transparency rules. 
133     // The checks are done by AllowCriticalCustomAttributes and CheckLinktimeDemands in CustomAttribute.cs.
134     return ClassLoader::CanAccess(
135         &accessContext, 
136         pCAMT,
137         pCAMT->GetAssembly(), 
138         dwAttr,
139         pCACtor,
140         NULL,
141         *AccessCheckOptions::s_pNormalAccessChecks,
142         FALSE,
143         FALSE);
144 }
145
146 BOOL QCALLTYPE RuntimeMethodHandle::IsCAVisibleFromDecoratedType(
147     EnregisteredTypeHandle  targetTypeHandle,
148     MethodDesc *            pTargetCtor,
149     EnregisteredTypeHandle  sourceTypeHandle,
150     QCall::ModuleHandle     sourceModuleHandle)
151 {
152     QCALL_CONTRACT;
153
154     BOOL bResult = TRUE;
155
156     BEGIN_QCALL;
157     TypeHandle sourceHandle = TypeHandle::FromPtr(sourceTypeHandle);
158     TypeHandle targetHandle = TypeHandle::FromPtr(targetTypeHandle);
159
160     _ASSERTE((sourceHandle.IsNull() || !sourceHandle.IsTypeDesc()) &&
161              !targetHandle.IsNull() &&
162              !targetHandle.IsTypeDesc());
163
164     if (sourceHandle.IsTypeDesc() ||
165         targetHandle.IsNull() || 
166         targetHandle.IsTypeDesc())
167         COMPlusThrowArgumentNull(NULL, W("Arg_InvalidHandle"));
168
169     bResult = CheckCAVisibilityFromDecoratedType(targetHandle.AsMethodTable(), pTargetCtor, sourceHandle.AsMethodTable(), sourceModuleHandle);
170     END_QCALL;
171
172     return bResult;
173 }
174
175 // static
176 BOOL QCALLTYPE RuntimeMethodHandle::IsSecurityCritical(MethodDesc *pMD)
177 {
178     CONTRACTL
179     {
180         QCALL_CHECK;
181         PRECONDITION(CheckPointer(pMD));
182     }
183     CONTRACTL_END;
184
185     BOOL fIsCritical = TRUE;
186
187     BEGIN_QCALL;
188
189     if (pMD == NULL)
190         COMPlusThrowArgumentNull(NULL, W("Arg_InvalidHandle"));
191
192     fIsCritical = Security::IsMethodCritical(pMD);
193
194     END_QCALL;
195
196     return fIsCritical;
197 }
198
199 // static
200 BOOL QCALLTYPE RuntimeMethodHandle::IsSecuritySafeCritical(MethodDesc *pMD)
201 {
202     CONTRACTL
203     {
204         QCALL_CHECK;
205         PRECONDITION(CheckPointer(pMD));
206     }
207     CONTRACTL_END;
208
209     BOOL fIsSafeCritical = TRUE;
210
211     BEGIN_QCALL;
212
213     if (pMD == NULL)
214         COMPlusThrowArgumentNull(NULL, W("Arg_InvalidHandle"));
215
216     fIsSafeCritical = Security::IsMethodSafeCritical(pMD);
217
218     END_QCALL;
219
220     return fIsSafeCritical;
221 }
222
223 // static
224 BOOL QCALLTYPE RuntimeMethodHandle::IsSecurityTransparent(MethodDesc *pMD)
225 {
226     CONTRACTL
227     {
228         QCALL_CHECK;
229         PRECONDITION(CheckPointer(pMD));
230     }
231     CONTRACTL_END;
232
233     BOOL fIsTransparent = TRUE;
234
235     BEGIN_QCALL;
236
237     if (pMD == NULL)
238         COMPlusThrowArgumentNull(NULL, W("Arg_InvalidHandle"));
239
240     fIsTransparent = Security::IsMethodTransparent(pMD);
241
242     END_QCALL;
243
244     return fIsTransparent;
245 }
246
247 FCIMPL2(FC_BOOL_RET, RuntimeMethodHandle::IsTokenSecurityTransparent, ReflectModuleBaseObject *pModuleUNSAFE, INT32 tkToken) {
248     CONTRACTL {
249         FCALL_CHECK;
250     }
251     CONTRACTL_END;
252
253     REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE);
254
255     if(refModule == NULL)
256         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
257
258     Module *pModule = refModule->GetModule();
259
260     BOOL bIsSecurityTransparent = TRUE;
261     
262     HELPER_METHOD_FRAME_BEGIN_RET_1(refModule);
263     {
264         bIsSecurityTransparent = Security::IsTokenTransparent(pModule, tkToken);
265     }
266     HELPER_METHOD_FRAME_END();
267
268     FC_RETURN_BOOL(bIsSecurityTransparent );
269
270 }
271 FCIMPLEND
272
273 static bool DoAttributeTransparencyChecks(Assembly *pAttributeAssembly, Assembly *pDecoratedAssembly)
274 {
275     CONTRACTL
276     {
277         THROWS;
278         MODE_COOPERATIVE;
279         GC_TRIGGERS;
280         PRECONDITION(CheckPointer(pAttributeAssembly));
281         PRECONDITION(CheckPointer(pDecoratedAssembly));
282     }
283     CONTRACTL_END;
284
285     // Do transparency checks - if both the decorated assembly and attribute use the v4 security model,
286     // then we can do a direct transparency check.  However, if the decorated assembly uses the v2
287     // security model, then we need to convert the security critical attribute to looking as though it
288     // has a LinkDemand for full trust.
289     const SecurityTransparencyBehavior *pTargetTransparency = pDecoratedAssembly->GetSecurityTransparencyBehavior();
290     const SecurityTransparencyBehavior *pAttributeTransparency = pAttributeAssembly->GetSecurityTransparencyBehavior();
291
292     // v2 transparency did not impose checks for using its custom attributes, so if the attribute is
293     // defined in an assembly using the v2 transparency model then we don't need to do any
294     // additional checks.
295     if (pAttributeTransparency->DoAttributesRequireTransparencyChecks())
296     {
297         if (pTargetTransparency->CanTransparentCodeCallLinkDemandMethods() &&
298             pAttributeTransparency->CanCriticalMembersBeConvertedToLinkDemand())
299         {
300             // We have a v4 critical attribute being applied to a v2 transparent target. Since v2
301             // transparency doesn't understand externally visible critical attributes, we convert the
302             // attribute to a LinkDemand for full trust.  v2 transparency did not convert
303             // LinkDemands on its attributes into full demands so we do not do that second level of
304             // conversion here either.
305             Security::FullTrustLinkDemand(pDecoratedAssembly);
306             return true;
307         }
308         else
309         {
310             // If we are here either the target of the attribute uses the v4 security model, or the
311             // attribute itself uses the v2 model.  In these cases, we cannot perform a conversion of
312             // the critical attribute into a LinkDemand, and we have an error condition.
313             return false;
314         }
315     }
316
317     return true;
318 }
319
320 FCIMPL3(void, RuntimeMethodHandle::CheckLinktimeDemands, ReflectMethodObject *pMethodUNSAFE, ReflectModuleBaseObject *pModuleUNSAFE, CLR_BOOL isDecoratedTargetSecurityTransparent) 
321 {
322     CONTRACTL 
323     {
324         FCALL_CHECK;
325         PRECONDITION(CheckPointer(pModuleUNSAFE));
326         PRECONDITION(CheckPointer(pMethodUNSAFE));
327     }
328     CONTRACTL_END;
329
330     if(!Security::IsTransparencyEnforcementEnabled())
331     {
332         FCUnique(0xb0);
333         return;
334     }
335
336     REFLECTMETHODREF refMethod = (REFLECTMETHODREF)ObjectToOBJECTREF(pMethodUNSAFE);
337     REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE);
338
339     HELPER_METHOD_FRAME_BEGIN_2(refMethod, refModule);
340     {
341         MethodDesc *pCallee = refMethod->GetMethod(); // pCallee is the CA ctor or CA setter method
342         Module *pDecoratedModule = refModule->GetModule();
343
344         bool isAttributeSecurityCritical = Security::IsMethodCritical(pCallee) &&
345                                            !Security::IsMethodSafeCritical(pCallee);
346
347         if (isDecoratedTargetSecurityTransparent && isAttributeSecurityCritical)
348         {
349             if (!DoAttributeTransparencyChecks(pCallee->GetAssembly(), pDecoratedModule->GetAssembly()))
350             {
351                 SecurityTransparent::ThrowMethodAccessException(pCallee);
352             }
353         }
354
355     }
356     HELPER_METHOD_FRAME_END();
357 }
358 FCIMPLEND
359
360 NOINLINE static ReflectClassBaseObject* GetRuntimeTypeHelper(LPVOID __me, TypeHandle typeHandle, OBJECTREF keepAlive)
361 {
362     FC_INNER_PROLOG_NO_ME_SETUP();
363     if (typeHandle.AsPtr() == NULL)
364         return NULL;
365     
366     // RuntimeTypeHandle::GetRuntimeType has picked off the most common case, but does not cover array types.
367     // Before we do the really heavy weight option of setting up a helper method frame, check if we have to. 
368     OBJECTREF refType = typeHandle.GetManagedClassObjectFast();
369     if (refType != NULL)
370         return (ReflectClassBaseObject*)OBJECTREFToObject(refType);
371
372     HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_1(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, keepAlive);
373     refType = typeHandle.GetManagedClassObject();
374     HELPER_METHOD_FRAME_END();
375
376     FC_INNER_EPILOG();
377     return (ReflectClassBaseObject*)OBJECTREFToObject(refType);
378 }
379
380 #define RETURN_CLASS_OBJECT(typeHandle, keepAlive) FC_INNER_RETURN(ReflectClassBaseObject*, GetRuntimeTypeHelper(__me, typeHandle, keepAlive))
381
382 NOINLINE ReflectModuleBaseObject* GetRuntimeModuleHelper(LPVOID __me, Module *pModule, OBJECTREF keepAlive)
383 {
384     FC_INNER_PROLOG_NO_ME_SETUP();
385     if (pModule == NULL)
386         return NULL;
387     
388     DomainFile * pDomainFile = pModule->FindDomainFile(GetAppDomain());
389
390     OBJECTREF refModule = (pDomainFile != NULL) ? pDomainFile->GetExposedModuleObjectIfExists() : NULL;
391
392     if(refModule != NULL)
393         return (ReflectModuleBaseObject*)OBJECTREFToObject(refModule);
394
395     HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_1(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, keepAlive);
396     refModule = pModule->GetExposedObject();
397     HELPER_METHOD_FRAME_END();
398
399     FC_INNER_EPILOG();
400     return (ReflectModuleBaseObject*)OBJECTREFToObject(refModule);
401 }
402
403 NOINLINE AssemblyBaseObject* GetRuntimeAssemblyHelper(LPVOID __me, DomainAssembly *pAssembly, OBJECTREF keepAlive)
404 {
405     FC_INNER_PROLOG_NO_ME_SETUP();
406     if (pAssembly == NULL)
407         return NULL;
408     
409     OBJECTREF refAssembly = (pAssembly != NULL) ? pAssembly->GetExposedAssemblyObjectIfExists() : NULL;
410
411     if(refAssembly != NULL)
412         return (AssemblyBaseObject*)OBJECTREFToObject(refAssembly);
413
414     HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_1(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, keepAlive);
415     refAssembly = pAssembly->GetExposedAssemblyObject();
416     HELPER_METHOD_FRAME_END();
417
418     FC_INNER_EPILOG();
419     return (AssemblyBaseObject*)OBJECTREFToObject(refAssembly);
420 }
421
422
423 // This is the routine that is called by the 'typeof()' operator in C#.  It is one of the most commonly used
424 // reflection operations. This call should be optimized away in nearly all situations
425 FCIMPL1_V(ReflectClassBaseObject*, RuntimeTypeHandle::GetTypeFromHandle, FCALLRuntimeTypeHandle th)
426 {
427     FCALL_CONTRACT;
428     
429     FCUnique(0x31);
430     return FCALL_RTH_TO_REFLECTCLASS(th);
431 }
432 FCIMPLEND
433
434 FCIMPL1(ReflectClassBaseObject*, RuntimeTypeHandle::GetRuntimeType, EnregisteredTypeHandle th)
435 {
436     FCALL_CONTRACT;
437     
438     TypeHandle typeHandle = TypeHandle::FromPtr(th);
439     _ASSERTE(CheckPointer(typeHandle.AsPtr(), NULL_OK));
440     if (typeHandle.AsPtr()!= NULL)
441     {
442         if (!typeHandle.IsTypeDesc())
443         {
444             OBJECTREF typePtr = typeHandle.AsMethodTable()->GetManagedClassObjectIfExists();
445             if (typePtr != NULL)
446             {
447                 return (ReflectClassBaseObject*)OBJECTREFToObject(typePtr);
448             }
449         }
450     }
451     else 
452         return NULL;
453
454     RETURN_CLASS_OBJECT(typeHandle, NULL);
455 }
456 FCIMPLEND
457
458 FCIMPL1_V(EnregisteredTypeHandle, RuntimeTypeHandle::GetValueInternal, FCALLRuntimeTypeHandle RTH)
459 {
460     FCALL_CONTRACT;
461
462     if (FCALL_RTH_TO_REFLECTCLASS(RTH) == NULL)
463         return 0;
464
465     return FCALL_RTH_TO_REFLECTCLASS(RTH) ->GetType().AsPtr();
466 }
467 FCIMPLEND
468
469 // TypeEqualsHelper and TypeNotEqualsHelper are almost identical.
470 // Unfortunately we cannot combime them because they need to hardcode the caller's name
471 NOINLINE static BOOL TypeEqualSlow(OBJECTREF refL, OBJECTREF refR, LPVOID __me)
472 {
473     BOOL ret = FALSE;
474
475     FC_INNER_PROLOG_NO_ME_SETUP();
476
477     _ASSERTE(refL != NULL && refR != NULL);
478
479     HELPER_METHOD_FRAME_BEGIN_RET_ATTRIB_2(Frame::FRAME_ATTR_EXACT_DEPTH|Frame::FRAME_ATTR_CAPTURE_DEPTH_2, refL, refR);
480
481     MethodDescCallSite TypeEqualsMethod(METHOD__OBJECT__EQUALS, &refL);
482
483     ARG_SLOT args[] = 
484     {
485         ObjToArgSlot(refL),
486         ObjToArgSlot(refR)
487     };
488
489     ret = TypeEqualsMethod.Call_RetBool(args);
490
491     HELPER_METHOD_FRAME_END();
492
493     FC_INNER_EPILOG();
494
495     return ret;
496 }
497
498
499
500 #include <optsmallperfcritical.h>
501
502 FCIMPL2(FC_BOOL_RET, RuntimeTypeHandle::TypeEQ, Object* left, Object* right)
503 {
504     FCALL_CONTRACT;
505
506     OBJECTREF refL = (OBJECTREF)left;
507     OBJECTREF refR = (OBJECTREF)right;
508
509     if (refL == refR)
510     {
511         FC_RETURN_BOOL(TRUE);
512     }
513
514     if (!refL || !refR)
515     {
516         FC_RETURN_BOOL(FALSE);
517     }
518
519     if ((refL->GetMethodTable() == g_pRuntimeTypeClass || refR->GetMethodTable() == g_pRuntimeTypeClass))
520     {
521         // Quick path for negative common case
522         FC_RETURN_BOOL(FALSE);
523     }
524
525     // The fast path didn't get us the result
526     // Let's try the slow path: refL.Equals(refR);
527     FC_INNER_RETURN(FC_BOOL_RET, (FC_BOOL_RET)(!!TypeEqualSlow(refL, refR, __me)));
528 }
529 FCIMPLEND
530
531 FCIMPL2(FC_BOOL_RET, RuntimeTypeHandle::TypeNEQ, Object* left, Object* right)
532 {
533     FCALL_CONTRACT;
534
535     OBJECTREF refL = (OBJECTREF)left;
536     OBJECTREF refR = (OBJECTREF)right;
537
538     if (refL == refR)
539     {
540         FC_RETURN_BOOL(FALSE);
541     }
542
543     if (!refL || !refR)
544     {
545         FC_RETURN_BOOL(TRUE);
546     }
547
548     if ((refL->GetMethodTable() == g_pRuntimeTypeClass || refR->GetMethodTable() == g_pRuntimeTypeClass))
549     {
550         // Quick path for negative common case
551         FC_RETURN_BOOL(TRUE);
552     }
553
554     // The fast path didn't get us the result
555     // Let's try the slow path: refL.Equals(refR);
556     FC_INNER_RETURN(FC_BOOL_RET, (FC_BOOL_RET)(!TypeEqualSlow(refL, refR, __me)));
557 }
558 FCIMPLEND
559
560 #include <optdefault.h>
561
562
563
564
565 #ifdef FEATURE_COMINTEROP
566 FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::IsWindowsRuntimeObjectType, ReflectClassBaseObject *rtTypeUNSAFE)
567 {
568     FCALL_CONTRACT;
569
570     BOOL isWindowsRuntimeType = FALSE;
571
572     TypeHandle typeHandle = rtTypeUNSAFE->GetType();
573     MethodTable *pMT = typeHandle.GetMethodTable();
574
575     if (pMT != NULL)
576     {
577         isWindowsRuntimeType = pMT->IsWinRTObjectType();
578     }
579
580     FC_RETURN_BOOL(isWindowsRuntimeType);
581 }
582 FCIMPLEND
583
584 FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::IsTypeExportedToWindowsRuntime, ReflectClassBaseObject *rtTypeUNSAFE)
585 {
586     FCALL_CONTRACT;
587
588     BOOL isExportedToWinRT = FALSE;
589
590     TypeHandle typeHandle = rtTypeUNSAFE->GetType();
591     MethodTable *pMT = typeHandle.GetMethodTable();
592
593     if (pMT != NULL)
594     {
595         isExportedToWinRT = pMT->IsExportedToWinRT();
596     }
597
598     FC_RETURN_BOOL(isExportedToWinRT);
599 }
600 FCIMPLEND
601 #endif // FEATURE_COMINTEROP
602
603 NOINLINE static MethodDesc * RestoreMethodHelper(MethodDesc * pMethod, LPVOID __me)
604 {
605     FC_INNER_PROLOG_NO_ME_SETUP();
606
607     HELPER_METHOD_FRAME_BEGIN_RET_0();
608     pMethod->CheckRestore();
609     HELPER_METHOD_FRAME_END();
610
611     FC_INNER_EPILOG();
612
613     return pMethod;
614 }
615
616 FCIMPL1(MethodDesc *, RuntimeTypeHandle::GetFirstIntroducedMethod, ReflectClassBaseObject *pTypeUNSAFE) {
617     CONTRACTL {
618         FCALL_CHECK;
619         PRECONDITION(CheckPointer(pTypeUNSAFE));
620     }
621     CONTRACTL_END;
622
623     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
624     TypeHandle typeHandle = refType->GetType();
625     
626     if (typeHandle.IsGenericVariable())
627         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
628         
629     if (typeHandle.IsTypeDesc()) {
630         if (!typeHandle.IsArray()) 
631             return NULL;
632     }
633
634     MethodTable* pMT = typeHandle.GetMethodTable();
635     if (pMT == NULL)
636         return NULL;
637
638     MethodDesc* pMethod = MethodTable::IntroducedMethodIterator::GetFirst(pMT);
639
640     // The only method that can show up here unrestored is instantiated methods. Check for it before performing the expensive IsRestored() check.
641     if (pMethod != NULL && pMethod->GetClassification() == mcInstantiated && !pMethod->IsRestored()) {
642         FC_INNER_RETURN(MethodDesc *, RestoreMethodHelper(pMethod, __me));
643     }
644
645     _ASSERTE(pMethod == NULL || pMethod->IsRestored());
646     return pMethod;
647 }
648 FCIMPLEND
649
650 #include <optsmallperfcritical.h>
651 FCIMPL1(void, RuntimeTypeHandle::GetNextIntroducedMethod, MethodDesc ** ppMethod) {
652     CONTRACTL {
653         FCALL_CHECK;
654         PRECONDITION(CheckPointer(ppMethod));
655         PRECONDITION(CheckPointer(*ppMethod));
656     }
657     CONTRACTL_END;
658
659     MethodDesc *pMethod = MethodTable::IntroducedMethodIterator::GetNext(*ppMethod);
660
661     *ppMethod = pMethod;
662
663     if (pMethod != NULL && pMethod->GetClassification() == mcInstantiated && !pMethod->IsRestored()) {
664         FC_INNER_RETURN_VOID(RestoreMethodHelper(pMethod, __me));
665     }
666
667     _ASSERTE(pMethod == NULL || pMethod->IsRestored());
668 }
669 FCIMPLEND
670 #include <optdefault.h>
671
672 FCIMPL1(INT32, RuntimeTypeHandle::GetCorElementType, ReflectClassBaseObject *pTypeUNSAFE) {
673     CONTRACTL {
674         FCALL_CHECK;
675     }
676     CONTRACTL_END;
677
678     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
679
680     if (refType == NULL)
681         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
682
683     return refType->GetType().GetSignatureCorElementType();
684 }
685 FCIMPLEND
686
687 FCIMPL1(AssemblyBaseObject*, RuntimeTypeHandle::GetAssembly, ReflectClassBaseObject *pTypeUNSAFE) {
688     CONTRACTL {
689         FCALL_CHECK;
690     }
691     CONTRACTL_END;
692
693     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
694
695     if (refType == NULL)
696         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
697
698     DomainFile *pDomainFile = NULL;
699     
700         Module *pModule = refType->GetType().GetAssembly()->GetManifestModule();
701
702             pDomainFile = pModule->FindDomainFile(GetAppDomain());
703 #ifdef FEATURE_LOADER_OPTIMIZATION        
704         if (pDomainFile == NULL)
705         {
706             HELPER_METHOD_FRAME_BEGIN_RET_1(refType);
707             
708             pDomainFile = GetAppDomain()->LoadDomainNeutralModuleDependency(pModule, FILE_LOADED);
709
710             HELPER_METHOD_FRAME_END();
711         }
712 #endif // FEATURE_LOADER_OPTIMIZATION        
713
714
715     FC_RETURN_ASSEMBLY_OBJECT((DomainAssembly *)pDomainFile, refType);
716 }
717 FCIMPLEND
718
719
720 FCIMPL1(FC_BOOL_RET, RuntimeFieldHandle::AcquiresContextFromThis, FieldDesc *pField)
721 {
722     CONTRACTL {
723         FCALL_CHECK;
724         PRECONDITION(CheckPointer(pField));
725     }
726     CONTRACTL_END;
727
728     FC_RETURN_BOOL(pField->IsSharedByGenericInstantiations());
729
730 }
731 FCIMPLEND
732
733 // static
734 BOOL QCALLTYPE RuntimeFieldHandle::IsSecurityCritical(FieldDesc *pFD)
735 {
736     CONTRACTL
737     {
738         QCALL_CHECK;
739         PRECONDITION(CheckPointer(pFD));
740     }
741     CONTRACTL_END;
742
743     BOOL fIsCritical = FALSE;
744
745     BEGIN_QCALL;
746
747     fIsCritical = Security::IsFieldCritical(pFD);
748
749     END_QCALL;
750
751     return fIsCritical;
752 }
753
754 // static
755 BOOL QCALLTYPE RuntimeFieldHandle::IsSecuritySafeCritical(FieldDesc *pFD)
756 {
757     CONTRACTL
758     {
759         QCALL_CHECK;
760         PRECONDITION(CheckPointer(pFD));
761     }
762     CONTRACTL_END;
763
764     BOOL fIsSafeCritical = FALSE;
765
766     BEGIN_QCALL;
767
768     fIsSafeCritical = Security::IsFieldSafeCritical(pFD);
769
770     END_QCALL;
771
772     return fIsSafeCritical;
773 }
774
775 // static
776 BOOL QCALLTYPE RuntimeFieldHandle::IsSecurityTransparent(FieldDesc *pFD)
777 {
778     CONTRACTL
779     {
780         QCALL_CHECK;
781         PRECONDITION(CheckPointer(pFD));
782     }
783     CONTRACTL_END;
784
785     BOOL fIsTransparent = FALSE;
786
787     BEGIN_QCALL;
788
789     fIsTransparent = Security::IsFieldTransparent(pFD);
790
791     END_QCALL;
792
793     return fIsTransparent;
794 }
795
796 // static
797 void QCALLTYPE RuntimeFieldHandle::CheckAttributeAccess(FieldDesc *pFD, QCall::ModuleHandle pModule)
798 {
799     CONTRACTL
800     {
801         QCALL_CHECK;
802         PRECONDITION(CheckPointer(pFD));
803         PRECONDITION(CheckPointer(pModule.m_pModule));
804     }
805     CONTRACTL_END;
806     
807     if(!Security::IsTransparencyEnforcementEnabled())
808     {
809         FCUnique(0xb1);
810         return;
811     }
812
813     BEGIN_QCALL;
814
815     if (Security::IsFieldCritical(pFD) && !Security::IsFieldSafeCritical(pFD))
816     {
817         GCX_COOP();
818
819         if (!DoAttributeTransparencyChecks(pFD->GetModule()->GetAssembly(), pModule->GetAssembly()))
820         {
821             ThrowFieldAccessException(NULL, pFD, TRUE, IDS_E_CRITICAL_FIELD_ACCESS_DENIED);
822         }
823     }
824
825     END_QCALL;
826 }
827
828 FCIMPL1(ReflectModuleBaseObject*, RuntimeTypeHandle::GetModule, ReflectClassBaseObject *pTypeUNSAFE) {
829     CONTRACTL {
830         FCALL_CHECK;
831     }
832     CONTRACTL_END;
833     
834     Module *result;
835
836     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
837
838     if (refType == NULL)
839         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
840
841     BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), FCThrow(kStackOverflowException));
842
843     result = refType->GetType().GetModule();
844
845     END_SO_INTOLERANT_CODE;
846
847     FC_RETURN_MODULE_OBJECT(result, refType);
848 }
849 FCIMPLEND
850
851 FCIMPL1(ReflectClassBaseObject *, RuntimeTypeHandle::GetBaseType, ReflectClassBaseObject *pTypeUNSAFE) {
852     CONTRACTL {
853         FCALL_CHECK;
854     }
855     CONTRACTL_END;
856
857     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
858
859     if (refType == NULL)
860         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
861
862     TypeHandle typeHandle = refType->GetType();
863     
864     if (typeHandle.IsGenericVariable())
865         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
866         
867     if (typeHandle.IsTypeDesc()) {
868         if (!typeHandle.IsArray()) 
869             return NULL;
870     }
871     
872     RETURN_CLASS_OBJECT(typeHandle.GetParent(), refType);
873 }
874 FCIMPLEND
875      
876 FCIMPL1(ReflectClassBaseObject *, RuntimeTypeHandle::GetElementType, ReflectClassBaseObject *pTypeUNSAFE) {
877     CONTRACTL {
878         FCALL_CHECK;
879     }
880     CONTRACTL_END;
881     
882     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
883
884     if (refType == NULL)
885         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
886
887     TypeHandle typeHandle = refType->GetType();
888
889     if (!typeHandle.IsTypeDesc())
890         return 0;   
891
892     if (typeHandle.IsGenericVariable())
893         return 0;
894
895     TypeHandle typeReturn;
896
897     if (typeHandle.IsArray()) 
898         typeReturn = typeHandle.AsArray()->GetArrayElementTypeHandle();
899     else
900         typeReturn = typeHandle.AsTypeDesc()->GetTypeParam();
901
902     RETURN_CLASS_OBJECT(typeReturn, refType);
903 }
904 FCIMPLEND
905             
906 FCIMPL1(INT32, RuntimeTypeHandle::GetArrayRank, ReflectClassBaseObject *pTypeUNSAFE) {
907     CONTRACTL {
908         FCALL_CHECK;
909         PRECONDITION(CheckPointer(pTypeUNSAFE));
910         PRECONDITION(pTypeUNSAFE->GetType().IsArray());
911     }
912     CONTRACTL_END;
913
914     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
915
916     return (INT32)refType->GetType().AsArray()->GetRank();   
917 }
918 FCIMPLEND
919
920 FCIMPL1(INT32, RuntimeTypeHandle::GetNumVirtuals, ReflectClassBaseObject *pTypeUNSAFE) {
921     CONTRACTL {
922         FCALL_CHECK;
923     }
924     CONTRACTL_END;
925     
926     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
927
928     if (refType == NULL)
929         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
930
931     TypeHandle typeHandle = refType->GetType();
932
933     if (typeHandle.IsGenericVariable())
934         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
935     
936     MethodTable *pMT = typeHandle.GetMethodTable();
937
938     if (pMT) 
939         return (INT32)pMT->GetNumVirtuals();
940     else
941         return 0; //REVIEW: should this return the number of methods in Object?
942 }
943 FCIMPLEND
944
945 FCIMPL2(MethodDesc *, RuntimeTypeHandle::GetMethodAt, ReflectClassBaseObject *pTypeUNSAFE, INT32 slot) {
946     CONTRACTL {
947         FCALL_CHECK;
948     }
949     CONTRACTL_END;
950     
951     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
952
953     if (refType == NULL)
954         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
955
956     TypeHandle typeHandle = refType->GetType();
957
958     MethodDesc* pRetMethod = NULL;
959
960     if (typeHandle.IsGenericVariable())
961         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
962
963     if (slot < 0 || slot >= (INT32)typeHandle.GetMethodTable()->GetNumVirtuals())
964         FCThrowRes(kArgumentException, W("Arg_ArgumentOutOfRangeException"));      
965
966     HELPER_METHOD_FRAME_BEGIN_RET_1(refType);
967     pRetMethod = typeHandle.GetMethodTable()->GetMethodDescForSlot((DWORD)slot);
968     HELPER_METHOD_FRAME_END();
969
970     return pRetMethod;
971 }
972
973 FCIMPLEND
974
975 FCIMPL3(FC_BOOL_RET, RuntimeTypeHandle::GetFields, ReflectClassBaseObject *pTypeUNSAFE, INT32 **result, INT32 *pCount) {
976     CONTRACTL {
977         FCALL_CHECK;
978     }
979     CONTRACTL_END;
980     
981     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
982     if (refType == NULL)
983         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
984
985     TypeHandle typeHandle = refType->GetType();
986     
987     if (!pCount || !result)
988         FCThrow(kArgumentNullException);
989
990     if (typeHandle.IsGenericVariable())
991         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
992     
993     if (typeHandle.IsTypeDesc()) {
994         *pCount = 0;
995         FC_RETURN_BOOL(TRUE);
996     }
997
998     MethodTable *pMT= typeHandle.GetMethodTable();
999     if (!pMT)
1000         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
1001
1002     BOOL retVal = FALSE;
1003     HELPER_METHOD_FRAME_BEGIN_RET_1(refType);
1004     // <TODO>Check this approximation - we may be losing exact type information </TODO>
1005     ApproxFieldDescIterator fdIterator(pMT, ApproxFieldDescIterator::ALL_FIELDS);
1006     INT32 count = (INT32)fdIterator.Count();
1007
1008     if (count > *pCount) 
1009     {
1010         *pCount = count;
1011     } 
1012     else 
1013     {
1014         for(INT32 i = 0; i < count; i ++)
1015             result[i] = (INT32*)fdIterator.Next();
1016         
1017         *pCount = count;
1018         retVal = TRUE;
1019     }
1020     HELPER_METHOD_FRAME_END();
1021     FC_RETURN_BOOL(retVal);
1022 }
1023 FCIMPLEND
1024
1025 void QCALLTYPE RuntimeMethodHandle::ConstructInstantiation(MethodDesc * pMethod, DWORD format, QCall::StringHandleOnStack retString)
1026 {
1027     QCALL_CONTRACT;
1028
1029     BEGIN_QCALL;
1030
1031     StackSString ss;
1032     TypeString::AppendInst(ss, pMethod->LoadMethodInstantiation(), format);
1033     retString.Set(ss);
1034     
1035     END_QCALL;
1036 }
1037
1038 void QCALLTYPE RuntimeTypeHandle::ConstructName(EnregisteredTypeHandle pTypeHandle, DWORD format, QCall::StringHandleOnStack retString)
1039 {
1040     QCALL_CONTRACT;
1041       
1042     BEGIN_QCALL;
1043
1044     StackSString ss;    
1045     TypeString::AppendType(ss, TypeHandle::FromPtr(pTypeHandle), format);
1046     retString.Set(ss);
1047
1048     END_QCALL;
1049 }
1050
1051 PTRARRAYREF CopyRuntimeTypeHandles(TypeHandle * prgTH, FixupPointer<TypeHandle> * prgTH2, INT32 numTypeHandles, BinderClassID arrayElemType)
1052 {
1053     CONTRACTL {
1054         THROWS;
1055         GC_TRIGGERS;
1056         MODE_COOPERATIVE;
1057     }
1058     CONTRACTL_END;
1059
1060     PTRARRAYREF refReturn = NULL;
1061     PTRARRAYREF refArray  = NULL;
1062
1063     if (numTypeHandles == 0)
1064         return NULL;
1065
1066     _ASSERTE((prgTH != NULL) || (prgTH2 != NULL));
1067     if (prgTH != NULL)
1068     {
1069         _ASSERTE(prgTH2 == NULL);
1070     }
1071
1072     GCPROTECT_BEGIN(refArray);
1073     TypeHandle thRuntimeType = TypeHandle(MscorlibBinder::GetClass(arrayElemType));
1074     TypeHandle arrayHandle = ClassLoader::LoadArrayTypeThrowing(thRuntimeType, ELEMENT_TYPE_SZARRAY);
1075     refArray = (PTRARRAYREF)AllocateArrayEx(arrayHandle, &numTypeHandles, 1);
1076
1077     for (INT32 i = 0; i < numTypeHandles; i++)
1078     {
1079         TypeHandle th;
1080
1081         if (prgTH != NULL)
1082             th = prgTH[i];
1083         else
1084             th = prgTH2[i].GetValue();
1085
1086         OBJECTREF refType = th.GetManagedClassObject();
1087         refArray->SetAt(i, refType);
1088     }
1089
1090     refReturn = refArray;
1091     GCPROTECT_END();
1092
1093     return refReturn;
1094 }
1095
1096 void QCALLTYPE RuntimeTypeHandle::GetConstraints(EnregisteredTypeHandle pTypeHandle, QCall::ObjectHandleOnStack retTypeArray)
1097 {
1098     QCALL_CONTRACT;
1099
1100     TypeHandle* constraints = NULL;
1101     
1102     BEGIN_QCALL;
1103     
1104     TypeHandle typeHandle = TypeHandle::FromPtr(pTypeHandle);
1105     
1106     if (!typeHandle.IsGenericVariable())
1107         COMPlusThrow(kArgumentException, W("Arg_InvalidHandle"));
1108
1109         TypeVarTypeDesc* pGenericVariable = typeHandle.AsGenericVariable();              
1110     
1111     DWORD dwCount;
1112     constraints = pGenericVariable->GetConstraints(&dwCount);
1113
1114     GCX_COOP();
1115     retTypeArray.Set(CopyRuntimeTypeHandles(constraints, NULL, dwCount, CLASS__TYPE));
1116
1117     END_QCALL;
1118
1119     return;
1120 }
1121
1122 FCIMPL1(PtrArray*, RuntimeTypeHandle::GetInterfaces, ReflectClassBaseObject *pTypeUNSAFE) {
1123     CONTRACTL {
1124         FCALL_CHECK;
1125     }
1126     CONTRACTL_END;
1127     
1128     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
1129
1130     if (refType == NULL)
1131         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1132
1133     TypeHandle typeHandle = refType->GetType();
1134     
1135   if (typeHandle.IsGenericVariable())
1136         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1137     
1138     INT32 ifaceCount = 0; 
1139   
1140     PTRARRAYREF refRetVal  = NULL;
1141     HELPER_METHOD_FRAME_BEGIN_RET_2(refRetVal, refType);
1142     {
1143         if (typeHandle.IsTypeDesc())
1144         {
1145             if (typeHandle.IsArray())
1146             {
1147                 ifaceCount = typeHandle.GetMethodTable()->GetNumInterfaces();            
1148             }
1149             else
1150             {
1151                 ifaceCount = 0;
1152             }
1153         }
1154         else
1155         {
1156             ifaceCount = typeHandle.GetMethodTable()->GetNumInterfaces();
1157         }
1158
1159         // Allocate the array
1160         if (ifaceCount > 0)
1161         {            
1162             TypeHandle arrayHandle = ClassLoader::LoadArrayTypeThrowing(TypeHandle(g_pRuntimeTypeClass), ELEMENT_TYPE_SZARRAY);
1163             refRetVal = (PTRARRAYREF)AllocateArrayEx(arrayHandle, &ifaceCount, 1);
1164         
1165             // populate type array
1166             UINT i = 0;
1167             
1168             MethodTable::InterfaceMapIterator it = typeHandle.GetMethodTable()->IterateInterfaceMap();
1169             while (it.Next())
1170             {
1171                 OBJECTREF refInterface = it.GetInterface()->GetManagedClassObject();
1172                 refRetVal->SetAt(i, refInterface);
1173                 _ASSERTE(refRetVal->GetAt(i) != NULL);
1174                 i++;
1175             }
1176         }
1177     }
1178     HELPER_METHOD_FRAME_END();
1179
1180     return (PtrArray*)OBJECTREFToObject(refRetVal);
1181 }
1182 FCIMPLEND
1183
1184 FCIMPL1(INT32, RuntimeTypeHandle::GetAttributes, ReflectClassBaseObject *pTypeUNSAFE) {
1185     CONTRACTL {
1186         FCALL_CHECK;
1187     }
1188     CONTRACTL_END;
1189     
1190     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
1191
1192     if (refType == NULL)
1193         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1194
1195     TypeHandle typeHandle = refType->GetType();
1196       
1197     if (typeHandle.IsTypeDesc()) {
1198
1199         if (typeHandle.IsGenericVariable()) {
1200             return tdPublic;        
1201         }
1202     
1203         if (!typeHandle.IsArray()) 
1204             return 0;
1205     }
1206
1207 #ifdef FEATURE_COMINTEROP
1208     // __ComObject types are always public.
1209     if (IsComObjectClass(typeHandle))
1210         return (typeHandle.GetMethodTable()->GetAttrClass() & tdVisibilityMask) | tdPublic;
1211 #endif // FEATURE_COMINTEROP
1212
1213     INT32 ret = 0;
1214     
1215     ret = (INT32)typeHandle.GetMethodTable()->GetAttrClass();
1216     return ret;
1217 }
1218 FCIMPLEND
1219
1220
1221 FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::IsValueType, ReflectClassBaseObject *pTypeUNSAFE)
1222 {
1223     CONTRACTL {
1224         FCALL_CHECK;
1225     }
1226     CONTRACTL_END;
1227     
1228     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
1229
1230     _ASSERTE(refType != NULL);
1231
1232     TypeHandle typeHandle = refType->GetType();
1233
1234     FC_RETURN_BOOL(typeHandle.IsValueType());
1235 }
1236 FCIMPLEND;
1237
1238 FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::IsInterface, ReflectClassBaseObject *pTypeUNSAFE)
1239 {
1240     CONTRACTL {
1241         FCALL_CHECK;
1242     }
1243     CONTRACTL_END;
1244     
1245     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
1246
1247     _ASSERTE(refType != NULL);
1248
1249     TypeHandle typeHandle = refType->GetType();
1250
1251     FC_RETURN_BOOL(typeHandle.IsInterface());
1252 }
1253 FCIMPLEND;
1254
1255 BOOL 
1256 QCALLTYPE 
1257 RuntimeTypeHandle::IsVisible(
1258     EnregisteredTypeHandle pTypeHandle)
1259 {
1260     CONTRACTL
1261     {
1262         QCALL_CHECK;
1263     }
1264     CONTRACTL_END;
1265     
1266     BOOL fIsExternallyVisible = FALSE;
1267     
1268     BEGIN_QCALL;
1269     
1270     TypeHandle typeHandle = TypeHandle::FromPtr(pTypeHandle);
1271
1272     _ASSERTE(!typeHandle.IsNull());
1273     
1274     fIsExternallyVisible = typeHandle.IsExternallyVisible();
1275     
1276     END_QCALL;
1277     
1278     return fIsExternallyVisible;
1279 } // RuntimeTypeHandle::IsVisible
1280
1281 // static
1282 BOOL QCALLTYPE RuntimeTypeHandle::IsSecurityCritical(EnregisteredTypeHandle pTypeHandle)
1283 {
1284     CONTRACTL
1285     {
1286         QCALL_CHECK;
1287         PRECONDITION(CheckPointer(pTypeHandle));
1288     }
1289     CONTRACTL_END;
1290
1291     BOOL fIsCritical = FALSE;
1292
1293     BEGIN_QCALL;
1294
1295     MethodTable *pMT = TypeHandle::FromPtr(pTypeHandle).GetMethodTable();
1296     if (pMT != NULL)
1297     {
1298         fIsCritical = Security::IsTypeCritical(pMT);
1299     }
1300
1301     END_QCALL;
1302
1303     return fIsCritical;
1304 }
1305
1306 // static
1307 BOOL QCALLTYPE RuntimeTypeHandle::IsSecuritySafeCritical(EnregisteredTypeHandle pTypeHandle)
1308 {
1309     CONTRACTL
1310     {
1311         QCALL_CHECK;
1312         PRECONDITION(CheckPointer(pTypeHandle));
1313     }
1314     CONTRACTL_END;
1315
1316     BOOL fIsSafeCritical = FALSE;
1317
1318     BEGIN_QCALL;
1319
1320     MethodTable *pMT = TypeHandle::FromPtr(pTypeHandle).GetMethodTable();
1321     if (pMT != NULL)
1322     {
1323         fIsSafeCritical = Security::IsTypeSafeCritical(pMT);
1324     }
1325
1326     END_QCALL;
1327
1328     return fIsSafeCritical;
1329 }
1330
1331 // static
1332 BOOL QCALLTYPE RuntimeTypeHandle::IsSecurityTransparent(EnregisteredTypeHandle pTypeHandle)
1333 {
1334     CONTRACTL
1335     {
1336         QCALL_CHECK;
1337         PRECONDITION(CheckPointer(pTypeHandle));
1338     }
1339     CONTRACTL_END;
1340
1341     BOOL fIsTransparent = TRUE;
1342
1343     BEGIN_QCALL;
1344
1345     MethodTable * pMT = TypeHandle::FromPtr(pTypeHandle).GetMethodTable();
1346     if (pMT != NULL)
1347     {
1348         fIsTransparent = Security::IsTypeTransparent(pMT);
1349     }
1350     
1351     END_QCALL;
1352
1353     return fIsTransparent;
1354 }
1355     
1356 FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::HasProxyAttribute, ReflectClassBaseObject *pTypeUNSAFE) {
1357     CONTRACTL {
1358         FCALL_CHECK;
1359     }
1360     CONTRACTL_END;
1361
1362     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
1363
1364     if (refType == NULL)
1365         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1366
1367     TypeHandle typeHandle = refType->GetType();
1368     
1369     // TODO: Justify this
1370     if (typeHandle.IsGenericVariable())
1371         FC_RETURN_BOOL(FALSE);
1372         
1373     if (typeHandle.IsTypeDesc()) {
1374         if (!typeHandle.IsArray()) 
1375             FC_RETURN_BOOL(FALSE);
1376     }  
1377     
1378     MethodTable* pMT= typeHandle.GetMethodTable();
1379     
1380     if (!pMT) 
1381         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
1382
1383     FC_RETURN_BOOL(pMT->GetClass()->HasRemotingProxyAttribute());
1384 }
1385 FCIMPLEND
1386
1387 FCIMPL2(FC_BOOL_RET, RuntimeTypeHandle::IsComObject, ReflectClassBaseObject *pTypeUNSAFE, CLR_BOOL isGenericCOM) {
1388 #ifdef FEATURE_COMINTEROP
1389     CONTRACTL {
1390         FCALL_CHECK;
1391     }
1392     CONTRACTL_END;
1393     
1394     BOOL ret = FALSE;
1395
1396     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
1397
1398     if (refType == NULL)
1399         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1400
1401     TypeHandle typeHandle = refType->GetType();
1402
1403     HELPER_METHOD_FRAME_BEGIN_RET_1(refType);
1404     {
1405         if (isGenericCOM) 
1406             ret = IsComObjectClass(typeHandle);
1407         else
1408             ret = IsComWrapperClass(typeHandle);
1409     }
1410     HELPER_METHOD_FRAME_END();
1411
1412     FC_RETURN_BOOL(ret);
1413 #else
1414     CONTRACTL {
1415         DISABLED(NOTHROW);
1416         GC_NOTRIGGER;
1417         MODE_COOPERATIVE;
1418         PRECONDITION(CheckPointer(pTypeUNSAFE));
1419     }
1420     CONTRACTL_END;
1421     FCUnique(0x37);
1422     FC_RETURN_BOOL(FALSE);
1423 #endif
1424 }
1425 FCIMPLEND
1426
1427 FCIMPL1(LPCUTF8, RuntimeTypeHandle::GetUtf8Name, ReflectClassBaseObject* pTypeUNSAFE) {
1428     CONTRACTL {
1429         FCALL_CHECK;
1430     }
1431     CONTRACTL_END;
1432     
1433     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
1434
1435     if (refType == NULL)
1436         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1437
1438     TypeHandle typeHandle = refType->GetType();
1439     INT32 tkTypeDef = mdTypeDefNil;
1440     LPCUTF8 szName = NULL;
1441
1442     if (typeHandle.IsGenericVariable())
1443         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
1444         
1445     if (typeHandle.IsTypeDesc()) 
1446         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
1447
1448     MethodTable* pMT= typeHandle.GetMethodTable();
1449     
1450     if (pMT == NULL)
1451         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
1452
1453     tkTypeDef = (INT32)pMT->GetCl();
1454     
1455     if (IsNilToken(tkTypeDef))
1456         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
1457     
1458     if (FAILED(pMT->GetMDImport()->GetNameOfTypeDef(tkTypeDef, &szName, NULL)))
1459     {
1460         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
1461     }
1462     
1463     _ASSERTE(CheckPointer(szName, NULL_OK));
1464     
1465     return szName;
1466 }
1467 FCIMPLEND
1468
1469 FCIMPL1(INT32, RuntimeTypeHandle::GetToken, ReflectClassBaseObject *pTypeUNSAFE) {
1470     CONTRACTL {
1471         FCALL_CHECK;
1472     }
1473     CONTRACTL_END;
1474
1475     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
1476
1477     if (refType == NULL)
1478         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1479
1480     TypeHandle typeHandle = refType->GetType();
1481
1482     if (typeHandle.IsTypeDesc()) 
1483     {
1484         if (typeHandle.IsGenericVariable())
1485         {
1486             INT32 tkTypeDef = typeHandle.AsGenericVariable()->GetToken();
1487         
1488             _ASSERTE(!IsNilToken(tkTypeDef) && TypeFromToken(tkTypeDef) == mdtGenericParam);
1489
1490             return tkTypeDef;
1491         }
1492         
1493         return mdTypeDefNil;
1494     }
1495
1496     return  (INT32)typeHandle.AsMethodTable()->GetCl();
1497 }
1498 FCIMPLEND
1499
1500 PVOID QCALLTYPE RuntimeTypeHandle::GetGCHandle(EnregisteredTypeHandle pTypeHandle, INT32 handleType)
1501 {
1502     QCALL_CONTRACT;
1503     
1504     OBJECTHANDLE objHandle = NULL;
1505
1506     BEGIN_QCALL;
1507     
1508     GCX_COOP();
1509
1510     TypeHandle th = TypeHandle::FromPtr(pTypeHandle);
1511     objHandle = th.GetDomain()->CreateTypedHandle(NULL, handleType);
1512     th.GetLoaderAllocator()->RegisterHandleForCleanup(objHandle);
1513
1514     END_QCALL;
1515
1516     return objHandle;
1517 }
1518
1519 void QCALLTYPE RuntimeTypeHandle::VerifyInterfaceIsImplemented(EnregisteredTypeHandle pTypeHandle, EnregisteredTypeHandle pIFaceHandle)
1520 {
1521     QCALL_CONTRACT;
1522
1523     BEGIN_QCALL;
1524
1525     TypeHandle typeHandle = TypeHandle::FromPtr(pTypeHandle);
1526     TypeHandle ifaceHandle = TypeHandle::FromPtr(pIFaceHandle);
1527
1528     if (typeHandle.IsGenericVariable())
1529         COMPlusThrow(kArgumentException, W("Arg_InvalidHandle"));
1530     
1531     if (typeHandle.IsTypeDesc()) {
1532         if (!typeHandle.IsArray())
1533             COMPlusThrow(kArgumentException, W("Arg_NotFoundIFace"));
1534     }
1535
1536     if (typeHandle.IsInterface())
1537         COMPlusThrow(kArgumentException, W("Argument_InterfaceMap"));
1538
1539     if (!ifaceHandle.IsInterface())
1540         COMPlusThrow(kArgumentException, W("Arg_MustBeInterface"));
1541
1542     // First try the cheap check, which amounts to iterating the interface map looking for
1543     // the ifaceHandle MethodTable.
1544     if (!typeHandle.GetMethodTable()->ImplementsInterface(ifaceHandle.AsMethodTable()))
1545     {   // If the cheap check fails, try the more expensive but complete check.
1546         if (!typeHandle.CanCastTo(ifaceHandle))
1547         {   // If the complete check fails, we're certain that this type
1548             // does not implement the interface specified.
1549         COMPlusThrow(kArgumentException, W("Arg_NotFoundIFace"));
1550         }
1551     }
1552
1553     END_QCALL;
1554 }
1555
1556 INT32 QCALLTYPE RuntimeTypeHandle::GetInterfaceMethodImplementationSlot(EnregisteredTypeHandle pTypeHandle, EnregisteredTypeHandle pOwner, MethodDesc * pMD)
1557 {
1558     QCALL_CONTRACT;
1559
1560     INT32 slotNumber = -1;
1561
1562     BEGIN_QCALL;
1563
1564     TypeHandle typeHandle = TypeHandle::FromPtr(pTypeHandle);
1565     TypeHandle thOwnerOfMD = TypeHandle::FromPtr(pOwner);
1566
1567         // Ok to have INVALID_SLOT in the case where abstract class does not implement an interface method.
1568         // This case can not be reproed using C# "implements" all interface methods
1569         // with at least an abstract method. b19897_GetInterfaceMap_Abstract.exe tests this case.
1570         //@TODO:STUBDISPATCH: Don't need to track down the implementation, just the declaration, and this can
1571         //@TODO:              be done faster - just need to make a function FindDispatchDecl.
1572         DispatchSlot slot(typeHandle.GetMethodTable()->FindDispatchSlotForInterfaceMD(thOwnerOfMD, pMD));
1573     if (!slot.IsNull())
1574             slotNumber = slot.GetMethodDesc()->GetSlot();
1575
1576     END_QCALL;
1577     
1578     return slotNumber;
1579     }
1580     
1581 void QCALLTYPE RuntimeTypeHandle::GetDefaultConstructor(EnregisteredTypeHandle pTypeHandle, QCall::ObjectHandleOnStack retMethod)
1582 {
1583     QCALL_CONTRACT;
1584
1585     BEGIN_QCALL;
1586     
1587     MethodDesc* pCtor = NULL;
1588     
1589     TypeHandle typeHandle = TypeHandle::FromPtr(pTypeHandle);
1590
1591     if (!typeHandle.IsTypeDesc())
1592     {
1593         MethodTable* pMethodTable = typeHandle.AsMethodTable();
1594         if (pMethodTable->HasDefaultConstructor())
1595             pCtor = pMethodTable->GetDefaultConstructor();
1596     }
1597
1598     if (pCtor != NULL)
1599     {
1600         GCX_COOP();
1601         retMethod.Set(pCtor->GetStubMethodInfo());
1602     }
1603     END_QCALL;
1604
1605     return;
1606 }
1607
1608 FCIMPL1(ReflectMethodObject*, RuntimeTypeHandle::GetDeclaringMethod, ReflectClassBaseObject *pTypeUNSAFE) {
1609     CONTRACTL {
1610         FCALL_CHECK;
1611     }
1612     CONTRACTL_END;
1613     
1614     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
1615
1616     if (refType == NULL)
1617         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1618
1619     TypeHandle typeHandle = refType->GetType();;
1620
1621     if (!typeHandle.IsTypeDesc())
1622         return NULL;
1623     
1624     TypeVarTypeDesc* pGenericVariable = typeHandle.AsGenericVariable();
1625     mdToken defToken = pGenericVariable->GetTypeOrMethodDef();
1626     if (TypeFromToken(defToken) != mdtMethodDef)
1627         return NULL;
1628
1629     REFLECTMETHODREF pRet = NULL;
1630     HELPER_METHOD_FRAME_BEGIN_RET_0();
1631     MethodDesc * pMD = pGenericVariable->LoadOwnerMethod();
1632     pMD->CheckRestore();
1633     pRet = pMD->GetStubMethodInfo();
1634     HELPER_METHOD_FRAME_END();
1635
1636     return (ReflectMethodObject*)OBJECTREFToObject(pRet);
1637 }
1638 FCIMPLEND
1639
1640 FCIMPL1(ReflectClassBaseObject*, RuntimeTypeHandle::GetDeclaringType, ReflectClassBaseObject *pTypeUNSAFE) {
1641     CONTRACTL {
1642         FCALL_CHECK;
1643     }
1644     CONTRACTL_END;
1645     
1646     TypeHandle retTypeHandle;
1647
1648     BOOL fThrowException = FALSE;
1649     LPCWSTR argName = W("Arg_InvalidHandle");
1650     RuntimeExceptionKind reKind = kArgumentNullException;
1651
1652     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
1653
1654     if (refType == NULL)
1655         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1656
1657     TypeHandle typeHandle = refType->GetType();
1658
1659     MethodTable* pMT = NULL;
1660     mdTypeDef tkTypeDef = mdTokenNil;
1661
1662     BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), FCThrow(kStackOverflowException));
1663     if (typeHandle.IsTypeDesc()) {
1664
1665         if (typeHandle.IsGenericVariable()) {
1666             TypeVarTypeDesc* pGenericVariable = typeHandle.AsGenericVariable();
1667             mdToken defToken = pGenericVariable->GetTypeOrMethodDef();
1668             
1669             // Try the fast way first (if the declaring type has been loaded already).
1670             if (TypeFromToken(defToken) == mdtMethodDef)
1671             {
1672                 MethodDesc * retMethod = pGenericVariable->GetModule()->LookupMethodDef(defToken);
1673                 if (retMethod != NULL)
1674                     retTypeHandle = retMethod->GetMethodTable();
1675             }
1676             else
1677             {
1678                 retTypeHandle = pGenericVariable->GetModule()->LookupTypeDef(defToken);
1679             }
1680
1681             if (!retTypeHandle.IsNull() && retTypeHandle.IsFullyLoaded())
1682                 goto Exit;
1683
1684             // OK, need to go the slow way and load the type first.
1685             HELPER_METHOD_FRAME_BEGIN_RET_1(refType);
1686             {
1687                 if (TypeFromToken(defToken) == mdtMethodDef)
1688                 {
1689                     retTypeHandle = pGenericVariable->LoadOwnerMethod()->GetMethodTable();
1690                 }
1691                 else
1692                 {
1693                     retTypeHandle = pGenericVariable->LoadOwnerType();
1694                 }
1695                 retTypeHandle.CheckRestore();
1696             }
1697             HELPER_METHOD_FRAME_END();
1698             goto Exit;
1699         }
1700         if (!typeHandle.IsArray())
1701         {
1702             retTypeHandle = TypeHandle();
1703             goto Exit;
1704         }
1705     }
1706     
1707     pMT = typeHandle.GetMethodTable();
1708
1709     if (pMT == NULL) 
1710     {
1711         fThrowException = TRUE;
1712         goto Exit;
1713     }
1714
1715     if(!pMT->GetClass()->IsNested())
1716     {
1717         retTypeHandle = TypeHandle();
1718         goto Exit;
1719     }
1720
1721     tkTypeDef = pMT->GetCl();
1722     
1723     if (FAILED(typeHandle.GetModule()->GetMDImport()->GetNestedClassProps(tkTypeDef, &tkTypeDef)))
1724     {
1725         fThrowException = TRUE;
1726         reKind = kBadImageFormatException;
1727         argName = NULL;
1728         goto Exit;
1729     }
1730     
1731     // Try the fast way first (if the declaring type has been loaded already).
1732     retTypeHandle = typeHandle.GetModule()->LookupTypeDef(tkTypeDef);
1733     if (retTypeHandle.IsNull())
1734     { 
1735          // OK, need to go the slow way and load the type first.
1736         HELPER_METHOD_FRAME_BEGIN_RET_1(refType);
1737         {
1738             retTypeHandle = ClassLoader::LoadTypeDefThrowing(typeHandle.GetModule(), tkTypeDef, 
1739                                                              ClassLoader::ThrowIfNotFound, 
1740                                                              ClassLoader::PermitUninstDefOrRef);
1741         }
1742         HELPER_METHOD_FRAME_END();
1743     }
1744 Exit:
1745
1746     END_SO_INTOLERANT_CODE;
1747
1748     if (fThrowException)
1749     {
1750         FCThrowRes(reKind, argName);
1751     }
1752
1753     RETURN_CLASS_OBJECT(retTypeHandle, refType);
1754   }
1755 FCIMPLEND
1756
1757 FCIMPL2(FC_BOOL_RET, RuntimeTypeHandle::CanCastTo, ReflectClassBaseObject *pTypeUNSAFE, ReflectClassBaseObject *pTargetUNSAFE) {
1758     CONTRACTL {
1759         FCALL_CHECK;
1760     }
1761     CONTRACTL_END;
1762     
1763     
1764     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
1765     REFLECTCLASSBASEREF refTarget = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTargetUNSAFE);
1766
1767     if ((refType == NULL) || (refTarget == NULL)) 
1768         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
1769
1770     TypeHandle fromHandle = refType->GetType();
1771     TypeHandle toHandle = refTarget->GetType();
1772
1773     BOOL iRetVal = 0;
1774
1775     TypeHandle::CastResult r = fromHandle.CanCastToNoGC(toHandle);
1776     if (r == TypeHandle::MaybeCast)
1777     {
1778         HELPER_METHOD_FRAME_BEGIN_RET_2(refType, refTarget);
1779         iRetVal = fromHandle.CanCastTo(toHandle);
1780         HELPER_METHOD_FRAME_END();
1781     }
1782     else
1783     {
1784         iRetVal = (r == TypeHandle::CanCast);
1785     }
1786
1787     // We allow T to be cast to Nullable<T>
1788     if (!iRetVal && Nullable::IsNullableType(toHandle) && !fromHandle.IsTypeDesc())
1789     {
1790         HELPER_METHOD_FRAME_BEGIN_RET_2(refType, refTarget);
1791         if (Nullable::IsNullableForType(toHandle, fromHandle.AsMethodTable())) 
1792         {
1793             iRetVal = TRUE;
1794         }
1795         HELPER_METHOD_FRAME_END();
1796     }
1797         
1798     FC_RETURN_BOOL(iRetVal);
1799 }
1800 FCIMPLEND
1801
1802 void QCALLTYPE RuntimeTypeHandle::GetTypeByNameUsingCARules(LPCWSTR pwzClassName, QCall::ModuleHandle pModule, QCall::ObjectHandleOnStack retType)
1803 {
1804     QCALL_CONTRACT;
1805     
1806     TypeHandle typeHandle;
1807
1808     BEGIN_QCALL;
1809         
1810     if (!pwzClassName)
1811         COMPlusThrowArgumentNull(W("className"),W("ArgumentNull_String"));
1812
1813     typeHandle = TypeName::GetTypeUsingCASearchRules(pwzClassName, pModule->GetAssembly());
1814
1815     GCX_COOP();
1816     retType.Set(typeHandle.GetManagedClassObject());
1817
1818     END_QCALL;
1819
1820     return;
1821 }
1822
1823 void QCALLTYPE RuntimeTypeHandle::GetTypeByName(LPCWSTR pwzClassName, BOOL bThrowOnError, BOOL bIgnoreCase, BOOL bReflectionOnly,
1824                                                 QCall::StackCrawlMarkHandle pStackMark, 
1825                                                 ICLRPrivBinder * pPrivHostBinder,
1826                                                 BOOL bLoadTypeFromPartialNameHack, QCall::ObjectHandleOnStack retType,
1827                                                 QCall::ObjectHandleOnStack keepAlive)
1828 {
1829     QCALL_CONTRACT;
1830     
1831     TypeHandle typeHandle;
1832     
1833     BEGIN_QCALL;
1834
1835     if (!pwzClassName)
1836             COMPlusThrowArgumentNull(W("className"),W("ArgumentNull_String"));
1837
1838     {
1839         typeHandle = TypeName::GetTypeManaged(pwzClassName, NULL, bThrowOnError, bIgnoreCase, bReflectionOnly, /*bProhibitAsmQualifiedName =*/ FALSE, pStackMark,
1840                                               bLoadTypeFromPartialNameHack, (OBJECTREF*)keepAlive.m_ppObject,
1841                                               pPrivHostBinder);
1842     }
1843
1844     if (!typeHandle.IsNull())
1845     {
1846         GCX_COOP();
1847         retType.Set(typeHandle.GetManagedClassObject());
1848     }
1849
1850     END_QCALL;
1851
1852     return;
1853 }
1854
1855 FCIMPL6(FC_BOOL_RET, RuntimeTypeHandle::SatisfiesConstraints, PTR_ReflectClassBaseObject pParamTypeUNSAFE, TypeHandle *typeContextArgs, INT32 typeContextCount, TypeHandle *methodContextArgs, INT32 methodContextCount, PTR_ReflectClassBaseObject pArgumentTypeUNSAFE);
1856 {
1857     CONTRACTL {
1858         FCALL_CHECK;
1859         PRECONDITION(CheckPointer(typeContextArgs, NULL_OK));
1860         PRECONDITION(CheckPointer(methodContextArgs, NULL_OK));
1861     }
1862     CONTRACTL_END;
1863     
1864     REFLECTCLASSBASEREF refParamType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pParamTypeUNSAFE);
1865     REFLECTCLASSBASEREF refArgumentType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pArgumentTypeUNSAFE);
1866
1867     TypeHandle thGenericParameter = refParamType->GetType();
1868     TypeHandle thGenericArgument = refArgumentType->GetType();
1869     BOOL bResult = FALSE; 
1870     SigTypeContext typeContext;
1871
1872     Instantiation classInst;
1873     Instantiation methodInst;
1874
1875     if (typeContextArgs != NULL)
1876     {
1877         classInst = Instantiation(typeContextArgs, typeContextCount);
1878     }
1879     
1880     if (methodContextArgs != NULL)
1881     {
1882         methodInst = Instantiation(methodContextArgs, methodContextCount);
1883     }
1884
1885     SigTypeContext::InitTypeContext(classInst, methodInst, &typeContext);
1886
1887     HELPER_METHOD_FRAME_BEGIN_RET_2(refParamType, refArgumentType);
1888     {
1889         bResult = thGenericParameter.AsGenericVariable()->SatisfiesConstraints(&typeContext, thGenericArgument);
1890     }
1891     HELPER_METHOD_FRAME_END();
1892
1893     FC_RETURN_BOOL(bResult);      
1894 }
1895 FCIMPLEND
1896
1897 void QCALLTYPE RuntimeTypeHandle::GetInstantiation(EnregisteredTypeHandle pType, QCall::ObjectHandleOnStack retTypes, BOOL fAsRuntimeTypeArray)
1898 {
1899     QCALL_CONTRACT;
1900
1901     BEGIN_QCALL;
1902
1903     TypeHandle typeHandle = TypeHandle::FromPtr(pType);
1904     Instantiation inst = typeHandle.GetInstantiation();
1905     GCX_COOP();
1906     retTypes.Set(CopyRuntimeTypeHandles(NULL, inst.GetRawArgs(), inst.GetNumArgs(), fAsRuntimeTypeArray ? CLASS__CLASS : CLASS__TYPE));
1907     END_QCALL;
1908
1909     return;
1910 }
1911
1912 void QCALLTYPE RuntimeTypeHandle::MakeArray(EnregisteredTypeHandle pTypeHandle, INT32 rank, QCall::ObjectHandleOnStack retType)
1913 {
1914     QCALL_CONTRACT;
1915
1916     TypeHandle arrayHandle;
1917     
1918     BEGIN_QCALL;
1919     arrayHandle = TypeHandle::FromPtr(pTypeHandle).MakeArray(rank);
1920     GCX_COOP();
1921     retType.Set(arrayHandle.GetManagedClassObject());
1922     END_QCALL;
1923     
1924     return;
1925 }
1926
1927 void QCALLTYPE RuntimeTypeHandle::MakeSZArray(EnregisteredTypeHandle pTypeHandle, QCall::ObjectHandleOnStack retType)
1928 {
1929     QCALL_CONTRACT;
1930     
1931     TypeHandle arrayHandle;
1932     
1933     BEGIN_QCALL;
1934     arrayHandle = TypeHandle::FromPtr(pTypeHandle).MakeSZArray();
1935     GCX_COOP();
1936     retType.Set(arrayHandle.GetManagedClassObject());
1937     END_QCALL;
1938
1939     return;
1940 }
1941
1942 void QCALLTYPE RuntimeTypeHandle::MakePointer(EnregisteredTypeHandle pTypeHandle, QCall::ObjectHandleOnStack retType)
1943 {
1944     QCALL_CONTRACT;
1945     
1946     TypeHandle pointerHandle;
1947     
1948     BEGIN_QCALL;
1949     pointerHandle = TypeHandle::FromPtr(pTypeHandle).MakePointer();
1950     GCX_COOP();
1951     retType.Set(pointerHandle.GetManagedClassObject());
1952     END_QCALL;
1953     
1954     return;
1955 }
1956
1957 void QCALLTYPE RuntimeTypeHandle::MakeByRef(EnregisteredTypeHandle pTypeHandle, QCall::ObjectHandleOnStack retType)
1958 {
1959     QCALL_CONTRACT;
1960     
1961     TypeHandle byRefHandle;
1962     
1963     BEGIN_QCALL;
1964     byRefHandle = TypeHandle::FromPtr(pTypeHandle).MakeByRef();
1965     GCX_COOP();
1966     retType.Set(byRefHandle.GetManagedClassObject());
1967     END_QCALL;
1968     
1969     return;
1970 }
1971
1972 BOOL QCALLTYPE RuntimeTypeHandle::IsCollectible(EnregisteredTypeHandle pTypeHandle)
1973 {
1974     QCALL_CONTRACT;
1975
1976     BOOL retVal = FALSE;
1977
1978     BEGIN_QCALL;
1979     retVal = TypeHandle::FromPtr(pTypeHandle).GetLoaderAllocator()->IsCollectible();
1980     END_QCALL;
1981
1982     return retVal;
1983 }
1984     
1985 void QCALLTYPE RuntimeTypeHandle::Instantiate(EnregisteredTypeHandle pTypeHandle, TypeHandle * pInstArray, INT32 cInstArray, QCall::ObjectHandleOnStack retType)
1986 {
1987     QCALL_CONTRACT;
1988     
1989     TypeHandle type;
1990
1991     BEGIN_QCALL;
1992     type = TypeHandle::FromPtr(pTypeHandle).Instantiate(Instantiation(pInstArray, cInstArray));
1993     GCX_COOP();
1994     retType.Set(type.GetManagedClassObject());
1995     END_QCALL;
1996
1997     return;
1998 }
1999
2000 void QCALLTYPE RuntimeTypeHandle::GetGenericTypeDefinition(EnregisteredTypeHandle pTypeHandle, QCall::ObjectHandleOnStack retType)
2001 {
2002     QCALL_CONTRACT;
2003     
2004     TypeHandle typeDef;
2005     
2006     BEGIN_QCALL;
2007     
2008     TypeHandle genericType = TypeHandle::FromPtr(pTypeHandle);
2009
2010     typeDef = ClassLoader::LoadTypeDefThrowing(genericType.GetModule(), 
2011                                                        genericType.GetMethodTable()->GetCl(),
2012                                                        ClassLoader::ThrowIfNotFound,
2013                                                        ClassLoader::PermitUninstDefOrRef);
2014
2015     GCX_COOP();
2016     retType.Set(typeDef.GetManagedClassObject());
2017
2018     END_QCALL;
2019     
2020     return;
2021 }
2022
2023 FCIMPL2(FC_BOOL_RET, RuntimeTypeHandle::CompareCanonicalHandles, ReflectClassBaseObject *pLeftUNSAFE, ReflectClassBaseObject *pRightUNSAFE)
2024 {
2025     FCALL_CONTRACT;
2026     
2027     REFLECTCLASSBASEREF refLeft = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pLeftUNSAFE);
2028     REFLECTCLASSBASEREF refRight = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pRightUNSAFE);
2029
2030     if ((refLeft == NULL) || (refRight == NULL))
2031         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2032
2033     FC_RETURN_BOOL(refLeft->GetType().GetCanonicalMethodTable() == refRight->GetType().GetCanonicalMethodTable());
2034 }
2035 FCIMPLEND
2036
2037 FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::HasInstantiation, PTR_ReflectClassBaseObject pTypeUNSAFE)
2038 {
2039     FCALL_CONTRACT;       
2040     
2041     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
2042
2043     if (refType == NULL)
2044         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2045
2046     FC_RETURN_BOOL(refType->GetType().HasInstantiation());
2047 }
2048 FCIMPLEND
2049
2050 FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::IsGenericTypeDefinition, PTR_ReflectClassBaseObject pTypeUNSAFE)
2051 {
2052     FCALL_CONTRACT;
2053     
2054     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
2055
2056     if (refType == NULL)
2057         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2058
2059     FC_RETURN_BOOL(refType->GetType().IsGenericTypeDefinition());
2060 }
2061 FCIMPLEND
2062
2063 FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::IsGenericVariable, PTR_ReflectClassBaseObject pTypeUNSAFE)
2064 {
2065     FCALL_CONTRACT;
2066     
2067     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
2068
2069     if (refType == NULL)
2070         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2071
2072     FC_RETURN_BOOL(refType->GetType().IsGenericVariable());
2073 }
2074 FCIMPLEND
2075
2076 FCIMPL1(INT32, RuntimeTypeHandle::GetGenericVariableIndex, PTR_ReflectClassBaseObject pTypeUNSAFE)
2077 {
2078     FCALL_CONTRACT;
2079     
2080     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
2081
2082     if (refType == NULL)
2083         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2084
2085     return (INT32)refType->GetType().AsGenericVariable()->GetIndex();
2086 }
2087 FCIMPLEND
2088
2089 FCIMPL1(FC_BOOL_RET, RuntimeTypeHandle::ContainsGenericVariables, PTR_ReflectClassBaseObject pTypeUNSAFE)
2090 {
2091     FCALL_CONTRACT;
2092
2093     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
2094
2095     if (refType == NULL)
2096         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2097
2098     FC_RETURN_BOOL(refType->GetType().ContainsGenericVariables());
2099 }
2100 FCIMPLEND
2101
2102 FCIMPL1(IMDInternalImport*, RuntimeTypeHandle::GetMetadataImport, ReflectClassBaseObject * pTypeUNSAFE)
2103 {
2104     FCALL_CONTRACT;
2105
2106     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
2107
2108     if (refType == NULL)
2109         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2110
2111     Module *pModule = refType->GetType().GetModule();
2112
2113     return pModule->GetMDImport();
2114 }
2115 FCIMPLEND
2116
2117
2118 //***********************************************************************************
2119 //***********************************************************************************
2120 //***********************************************************************************
2121
2122 void * QCALLTYPE RuntimeMethodHandle::GetFunctionPointer(MethodDesc * pMethod)
2123 {
2124     QCALL_CONTRACT;
2125         
2126     void* funcPtr = 0;
2127     
2128     BEGIN_QCALL;
2129
2130     funcPtr = (void*)pMethod->GetMultiCallableAddrOfCode();
2131
2132     END_QCALL;
2133
2134     return funcPtr;
2135 }
2136     
2137 FCIMPL1(LPCUTF8, RuntimeMethodHandle::GetUtf8Name, MethodDesc *pMethod) {
2138     CONTRACTL {
2139         FCALL_CHECK;
2140     }
2141     CONTRACTL_END;
2142     
2143     LPCUTF8 szName = NULL;
2144     
2145     if (!pMethod)
2146         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2147            
2148     szName = pMethod->GetName();
2149
2150     _ASSERTE(CheckPointer(szName, NULL_OK));
2151     
2152     return szName;
2153 }
2154 FCIMPLEND
2155
2156 FCIMPL2(FC_BOOL_RET, RuntimeMethodHandle::MatchesNameHash, MethodDesc * pMethod, ULONG hash)
2157 {
2158     FCALL_CONTRACT;
2159
2160     FC_RETURN_BOOL(pMethod->MightHaveName(hash));
2161 }
2162 FCIMPLEND
2163
2164 FCIMPL1(StringObject*, RuntimeMethodHandle::GetName, MethodDesc *pMethod) {
2165     CONTRACTL {
2166         FCALL_CHECK;
2167     }
2168     CONTRACTL_END;
2169         
2170     if (!pMethod)
2171         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2172         
2173     STRINGREF refName = NULL;
2174
2175     HELPER_METHOD_FRAME_BEGIN_RET_0();
2176     refName = StringObject::NewString(pMethod->GetName());
2177     HELPER_METHOD_FRAME_END();            
2178     
2179     return (StringObject*)OBJECTREFToObject(refName);
2180 }
2181 FCIMPLEND
2182
2183 FCIMPL1(INT32, RuntimeMethodHandle::GetAttributes, MethodDesc *pMethod) {
2184     CONTRACTL {
2185         FCALL_CHECK;
2186     }
2187     CONTRACTL_END;
2188     
2189     if (!pMethod)
2190         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2191
2192     INT32 retVal = 0;        
2193     BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), FCThrow(kStackOverflowException));
2194     retVal = (INT32)pMethod->GetAttrs();
2195     END_SO_INTOLERANT_CODE;
2196     return retVal;
2197 }
2198 FCIMPLEND
2199
2200 FCIMPL1(INT32, RuntimeMethodHandle::GetImplAttributes, ReflectMethodObject *pMethodUNSAFE) {
2201     CONTRACTL {
2202         FCALL_CHECK;
2203     }
2204     CONTRACTL_END;
2205     
2206     if (!pMethodUNSAFE)
2207         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2208
2209     MethodDesc* pMethod = pMethodUNSAFE->GetMethod();
2210     INT32 attributes = 0;
2211
2212     if (IsNilToken(pMethod->GetMemberDef()))
2213         return attributes;
2214     
2215     BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), FCThrow(kStackOverflowException));
2216     {
2217         attributes = (INT32)pMethod->GetImplAttrs();
2218     }
2219     END_SO_INTOLERANT_CODE;
2220
2221     return attributes;
2222 }
2223 FCIMPLEND
2224     
2225
2226 FCIMPL1(ReflectClassBaseObject*, RuntimeMethodHandle::GetDeclaringType, MethodDesc *pMethod) {
2227     CONTRACTL {
2228         FCALL_CHECK;
2229         PRECONDITION(CheckPointer(pMethod));
2230     }
2231     CONTRACTL_END;
2232     
2233     if (!pMethod)
2234         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2235         
2236     MethodTable *pMT = pMethod->GetMethodTable();
2237     TypeHandle declType(pMT);
2238     if (pMT->IsArray()) 
2239     {
2240         HELPER_METHOD_FRAME_BEGIN_RET_0();   
2241         
2242         // Load the TypeDesc for the array type.  Note the returned type is approximate, i.e.
2243         // if shared between reference array types then we will get object[] back.
2244         DWORD rank = pMT->GetRank();
2245         TypeHandle elemType = pMT->GetApproxArrayElementTypeHandle();
2246         declType = ClassLoader::LoadArrayTypeThrowing(elemType, pMT->GetInternalCorElementType(), rank);
2247         HELPER_METHOD_FRAME_END();            
2248     }
2249     RETURN_CLASS_OBJECT(declType, NULL);
2250 }
2251 FCIMPLEND
2252
2253 FCIMPL1(INT32, RuntimeMethodHandle::GetSlot, MethodDesc *pMethod) {
2254     CONTRACTL {
2255         FCALL_CHECK;
2256     }
2257     CONTRACTL_END;
2258     
2259     if (!pMethod)
2260         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2261         
2262     return (INT32)pMethod->GetSlot();
2263 }
2264 FCIMPLEND
2265
2266 FCIMPL3(Object *, SignatureNative::GetCustomModifiers, SignatureNative* pSignatureUNSAFE, 
2267     INT32 parameter, CLR_BOOL fRequired)
2268 {   
2269     CONTRACTL {
2270         FCALL_CHECK;
2271     }
2272     CONTRACTL_END;
2273
2274     struct 
2275     {
2276         SIGNATURENATIVEREF pSig;
2277         PTRARRAYREF retVal;
2278     } gc;
2279
2280     gc.pSig = (SIGNATURENATIVEREF)pSignatureUNSAFE;
2281     gc.retVal = NULL;
2282
2283     HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
2284     {
2285         
2286         BYTE callConv = *(BYTE*)gc.pSig->GetCorSig();
2287         SigTypeContext typeContext;
2288         gc.pSig->GetTypeContext(&typeContext);
2289         MetaSig sig(gc.pSig->GetCorSig(), 
2290                     gc.pSig->GetCorSigSize(),
2291                     gc.pSig->GetModule(), 
2292                     &typeContext,
2293                     (callConv & IMAGE_CEE_CS_CALLCONV_MASK) == IMAGE_CEE_CS_CALLCONV_FIELD ? MetaSig::sigField : MetaSig::sigMember);
2294         _ASSERTE(callConv == sig.GetCallingConventionInfo());                 
2295
2296         SigPointer argument(NULL, 0);
2297
2298         PRECONDITION(sig.GetCallingConvention() != IMAGE_CEE_CS_CALLCONV_FIELD || parameter == 1);
2299
2300         if (parameter == 0) 
2301         {
2302             argument = sig.GetReturnProps();
2303         }
2304         else
2305         {
2306             for(INT32 i = 0; i < parameter; i++)
2307                 sig.NextArg();
2308
2309             argument = sig.GetArgProps();
2310         }
2311         
2312         //if (parameter < 0 || parameter > (INT32)sig.NumFixedArgs())
2313         //    FCThrowResVoid(kArgumentNullException, W("Arg_ArgumentOutOfRangeException")); 
2314         
2315         SigPointer sp = argument;
2316         Module* pModule = sig.GetModule();
2317         INT32 cMods = 0;
2318         CorElementType cmodType;
2319
2320         CorElementType cmodTypeExpected = fRequired ? ELEMENT_TYPE_CMOD_REQD : ELEMENT_TYPE_CMOD_OPT;
2321         
2322         // Discover the number of required and optional custom modifiers.   
2323         while(TRUE)
2324         {
2325             BYTE data;
2326             IfFailThrow(sp.GetByte(&data));
2327             cmodType = (CorElementType)data;
2328             
2329             if (cmodType == ELEMENT_TYPE_CMOD_REQD || cmodType == ELEMENT_TYPE_CMOD_OPT)
2330             {
2331                 if (cmodType == cmodTypeExpected)
2332                 {
2333                     cMods ++;
2334                 }
2335             }        
2336             else if (cmodType != ELEMENT_TYPE_SENTINEL) 
2337             {
2338                 break;        
2339             }
2340             
2341             IfFailThrow(sp.GetToken(NULL));
2342         }
2343
2344         // Reset sp and populate the arrays for the required and optional custom 
2345         // modifiers now that we know how long they should be. 
2346         sp = argument;
2347
2348         MethodTable *pMT = MscorlibBinder::GetClass(CLASS__TYPE);
2349         TypeHandle arrayHandle = ClassLoader::LoadArrayTypeThrowing(TypeHandle(pMT), ELEMENT_TYPE_SZARRAY);
2350
2351         gc.retVal = (PTRARRAYREF) AllocateArrayEx(arrayHandle, &cMods, 1);
2352
2353         while(cMods != 0)
2354         {
2355             BYTE data;
2356             IfFailThrow(sp.GetByte(&data));
2357             cmodType = (CorElementType)data;
2358
2359             mdToken token;
2360             IfFailThrow(sp.GetToken(&token));
2361
2362             if (cmodType == cmodTypeExpected)
2363             {
2364                 TypeHandle th = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(pModule, token, 
2365                                                                             &typeContext,
2366                                                                             ClassLoader::ThrowIfNotFound, 
2367                                                                             ClassLoader::FailIfUninstDefOrRef);        
2368         
2369                 OBJECTREF refType = th.GetManagedClassObject();
2370                 gc.retVal->SetAt(--cMods, refType);
2371             }
2372         }    
2373     }  
2374     HELPER_METHOD_FRAME_END();
2375
2376     return OBJECTREFToObject(gc.retVal);
2377 }
2378 FCIMPLEND
2379
2380 FCIMPL1(INT32, RuntimeMethodHandle::GetMethodDef, ReflectMethodObject *pMethodUNSAFE) {
2381     CONTRACTL {
2382         FCALL_CHECK;
2383     }
2384     CONTRACTL_END;
2385     
2386     if (!pMethodUNSAFE)
2387         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2388
2389     MethodDesc* pMethod = pMethodUNSAFE->GetMethod();
2390
2391     if (pMethod->HasMethodInstantiation())
2392     {
2393         HELPER_METHOD_FRAME_BEGIN_RET_1(pMethodUNSAFE);
2394         {         
2395             pMethod = pMethod->StripMethodInstantiation();
2396         }
2397         HELPER_METHOD_FRAME_END();
2398     }
2399
2400     INT32 tkMethodDef = (INT32)pMethod->GetMemberDef();
2401     _ASSERTE(TypeFromToken(tkMethodDef) == mdtMethodDef);
2402     
2403     if (IsNilToken(tkMethodDef) || TypeFromToken(tkMethodDef) != mdtMethodDef)
2404         return mdMethodDefNil;
2405     
2406     return tkMethodDef;
2407 }
2408 FCIMPLEND
2409
2410 FCIMPL6(void, SignatureNative::GetSignature,
2411     SignatureNative* pSignatureNativeUNSAFE, 
2412     PCCOR_SIGNATURE pCorSig, DWORD cCorSig,
2413     FieldDesc *pFieldDesc, ReflectMethodObject *pMethodUNSAFE, ReflectClassBaseObject *pDeclaringTypeUNSAFE) {
2414     CONTRACTL {
2415         FCALL_CHECK;
2416         PRECONDITION(pDeclaringTypeUNSAFE || pMethodUNSAFE->GetMethod()->IsDynamicMethod());
2417         PRECONDITION(CheckPointer(pCorSig, NULL_OK));
2418         PRECONDITION(CheckPointer(pMethodUNSAFE, NULL_OK));
2419         PRECONDITION(CheckPointer(pFieldDesc, NULL_OK));
2420     }
2421     CONTRACTL_END;
2422
2423     struct
2424     {
2425         REFLECTCLASSBASEREF refDeclaringType;
2426         REFLECTMETHODREF refMethod;
2427         SIGNATURENATIVEREF pSig;
2428     } gc;
2429
2430     gc.refDeclaringType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pDeclaringTypeUNSAFE);
2431     gc.refMethod = (REFLECTMETHODREF)ObjectToOBJECTREF(pMethodUNSAFE);
2432     gc.pSig = (SIGNATURENATIVEREF)pSignatureNativeUNSAFE;
2433
2434     MethodDesc *pMethod;
2435     TypeHandle declType;
2436
2437     if (gc.refDeclaringType == NULL)
2438     {
2439         // for dynamic method, see precondition
2440         pMethod = gc.refMethod->GetMethod();
2441         declType = pMethod->GetMethodTable();
2442     }
2443     else
2444     {
2445         pMethod = gc.refMethod != NULL ? gc.refMethod->GetMethod() : NULL;
2446         declType = gc.refDeclaringType->GetType();
2447     }
2448
2449     HELPER_METHOD_FRAME_BEGIN_PROTECT(gc);
2450     {        
2451         Module* pModule = declType.GetModule();
2452         
2453         if (pMethod)
2454         {
2455             pMethod->GetSig(&pCorSig, &cCorSig);
2456             if (pMethod->GetClassification() == mcInstantiated)
2457             {
2458                 LoaderAllocator *pLoaderAllocator = pMethod->GetLoaderAllocator();
2459                 if (pLoaderAllocator->IsCollectible())
2460                     gc.pSig->SetKeepAlive(pLoaderAllocator->GetExposedObject());
2461             }
2462         }
2463         else if (pFieldDesc)
2464             pFieldDesc->GetSig(&pCorSig, &cCorSig);
2465         
2466         gc.pSig->m_sig = pCorSig;    
2467         gc.pSig->m_cSig = cCorSig;    
2468         gc.pSig->m_pMethod = pMethod;    
2469
2470         REFLECTCLASSBASEREF refDeclType = (REFLECTCLASSBASEREF)declType.GetManagedClassObject();
2471         gc.pSig->SetDeclaringType(refDeclType);
2472
2473         PREFIX_ASSUME(pCorSig!= NULL);
2474         BYTE callConv = *(BYTE*)pCorSig;
2475         SigTypeContext typeContext;
2476         if (pMethod)
2477             SigTypeContext::InitTypeContext(
2478                 pMethod, declType.GetClassOrArrayInstantiation(), pMethod->LoadMethodInstantiation(), &typeContext);
2479         else
2480             SigTypeContext::InitTypeContext(declType, &typeContext);
2481         MetaSig msig(pCorSig, cCorSig, pModule, &typeContext,
2482             (callConv & IMAGE_CEE_CS_CALLCONV_MASK) == IMAGE_CEE_CS_CALLCONV_FIELD ? MetaSig::sigField : MetaSig::sigMember);
2483
2484         if (callConv == IMAGE_CEE_CS_CALLCONV_FIELD)
2485         {            
2486             msig.NextArgNormalized();
2487
2488             OBJECTREF refRetType = msig.GetLastTypeHandleThrowing().GetManagedClassObject();
2489             gc.pSig->SetReturnType(refRetType);
2490         }
2491         else
2492         {
2493             gc.pSig->SetCallingConvention(msig.GetCallingConventionInfo());
2494
2495             OBJECTREF refRetType = msig.GetRetTypeHandleThrowing().GetManagedClassObject();
2496             gc.pSig->SetReturnType(refRetType);
2497
2498             INT32 nArgs = msig.NumFixedArgs();
2499             TypeHandle arrayHandle = ClassLoader::LoadArrayTypeThrowing(TypeHandle(g_pRuntimeTypeClass), ELEMENT_TYPE_SZARRAY);
2500
2501             PTRARRAYREF ptrArrayarguments = (PTRARRAYREF) AllocateArrayEx(arrayHandle, &nArgs, 1);
2502             gc.pSig->SetArgumentArray(ptrArrayarguments);
2503
2504             for (INT32 i = 0; i < nArgs; i++) 
2505             {
2506                 msig.NextArg();
2507
2508                 OBJECTREF refArgType = msig.GetLastTypeHandleThrowing().GetManagedClassObject();
2509                 gc.pSig->SetArgument(i, refArgType);
2510             }
2511
2512             _ASSERTE(gc.pSig->m_returnType != NULL);
2513         }
2514     }
2515     HELPER_METHOD_FRAME_END();
2516 }
2517 FCIMPLEND
2518
2519 FCIMPL2(FC_BOOL_RET, SignatureNative::CompareSig, SignatureNative* pLhsUNSAFE, SignatureNative* pRhsUNSAFE)
2520 {
2521     FCALL_CONTRACT;
2522     
2523     INT32 ret = 0;
2524
2525     struct
2526     {
2527         SIGNATURENATIVEREF pLhs;
2528         SIGNATURENATIVEREF pRhs;
2529     } gc;
2530
2531     gc.pLhs = (SIGNATURENATIVEREF)pLhsUNSAFE;
2532     gc.pRhs = (SIGNATURENATIVEREF)pRhsUNSAFE;
2533
2534     HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
2535     {
2536         ret = MetaSig::CompareMethodSigs(
2537             gc.pLhs->GetCorSig(), gc.pLhs->GetCorSigSize(), gc.pLhs->GetModule(), NULL, 
2538             gc.pRhs->GetCorSig(), gc.pRhs->GetCorSigSize(), gc.pRhs->GetModule(), NULL);    
2539     }
2540     HELPER_METHOD_FRAME_END();
2541     FC_RETURN_BOOL(ret);
2542 }
2543 FCIMPLEND
2544
2545 void QCALLTYPE RuntimeMethodHandle::GetMethodInstantiation(MethodDesc * pMethod, QCall::ObjectHandleOnStack retTypes, BOOL fAsRuntimeTypeArray)
2546 {
2547     QCALL_CONTRACT;
2548             
2549     BEGIN_QCALL;
2550     Instantiation inst = pMethod->LoadMethodInstantiation();
2551
2552     GCX_COOP();
2553     retTypes.Set(CopyRuntimeTypeHandles(NULL, inst.GetRawArgs(), inst.GetNumArgs(), fAsRuntimeTypeArray ? CLASS__CLASS : CLASS__TYPE));
2554     END_QCALL;
2555
2556     return;
2557 }
2558     
2559 FCIMPL1(FC_BOOL_RET, RuntimeMethodHandle::HasMethodInstantiation, MethodDesc * pMethod)
2560 {
2561     FCALL_CONTRACT;
2562
2563     FC_RETURN_BOOL(pMethod->HasMethodInstantiation());
2564 }
2565 FCIMPLEND
2566
2567 FCIMPL1(FC_BOOL_RET, RuntimeMethodHandle::IsGenericMethodDefinition, MethodDesc * pMethod)
2568 {
2569     FCALL_CONTRACT;
2570
2571     FC_RETURN_BOOL(pMethod->IsGenericMethodDefinition());
2572 }
2573 FCIMPLEND
2574
2575 FCIMPL1(FC_BOOL_RET, RuntimeMethodHandle::IsDynamicMethod, MethodDesc * pMethod)
2576 {
2577     FCALL_CONTRACT;
2578
2579     FC_RETURN_BOOL(pMethod->IsNoMetadata());
2580 }
2581 FCIMPLEND
2582
2583 FCIMPL1(Object*, RuntimeMethodHandle::GetResolver, MethodDesc * pMethod)
2584 {
2585     FCALL_CONTRACT;
2586
2587     if (!pMethod)
2588         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2589
2590     OBJECTREF resolver = NULL;
2591     if (pMethod->IsLCGMethod())
2592     {
2593         resolver = pMethod->AsDynamicMethodDesc()->GetLCGMethodResolver()->GetManagedResolver();
2594     }
2595     return OBJECTREFToObject(resolver);
2596 }
2597 FCIMPLEND
2598
2599 void QCALLTYPE RuntimeMethodHandle::Destroy(MethodDesc * pMethod)
2600 {
2601     QCALL_CONTRACT;
2602
2603     BEGIN_QCALL;
2604
2605     if (pMethod == NULL)
2606         COMPlusThrowArgumentNull(NULL, W("Arg_InvalidHandle"));
2607     
2608     DynamicMethodDesc* pDynamicMethodDesc = pMethod->AsDynamicMethodDesc();
2609
2610     GCX_COOP();
2611
2612     // Destroy should be called only if the managed part is gone.
2613     _ASSERTE(OBJECTREFToObject(pDynamicMethodDesc->GetLCGMethodResolver()->GetManagedResolver()) == NULL);
2614
2615     // Fire Unload Dynamic Method Event here
2616     ETW::MethodLog::DynamicMethodDestroyed(pMethod);
2617
2618     pDynamicMethodDesc->Destroy();
2619
2620     END_QCALL;
2621     }
2622     
2623 FCIMPL1(FC_BOOL_RET, RuntimeMethodHandle::IsTypicalMethodDefinition, ReflectMethodObject *pMethodUNSAFE)
2624 {
2625     FCALL_CONTRACT;
2626
2627     if (!pMethodUNSAFE)
2628         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2629
2630     MethodDesc* pMethod = pMethodUNSAFE->GetMethod();
2631
2632     FC_RETURN_BOOL(pMethod->IsTypicalMethodDefinition());
2633 }
2634 FCIMPLEND
2635     
2636 void QCALLTYPE RuntimeMethodHandle::GetTypicalMethodDefinition(MethodDesc * pMethod, QCall::ObjectHandleOnStack refMethod)
2637     {            
2638     QCALL_CONTRACT;
2639
2640     BEGIN_QCALL;
2641 #ifdef _DEBUG
2642     {
2643         GCX_COOP();
2644         _ASSERTE(((ReflectMethodObject *)(*refMethod.m_ppObject))->GetMethod() == pMethod);
2645     }
2646 #endif
2647     MethodDesc *pMethodTypical = pMethod->LoadTypicalMethodDefinition();
2648     if (pMethodTypical != pMethod)
2649     {
2650         GCX_COOP();
2651         refMethod.Set(pMethodTypical->GetStubMethodInfo());
2652     }
2653     END_QCALL;
2654     
2655     return;
2656 }
2657
2658 void QCALLTYPE RuntimeMethodHandle::StripMethodInstantiation(MethodDesc * pMethod, QCall::ObjectHandleOnStack refMethod)
2659     {            
2660     QCALL_CONTRACT;
2661
2662     BEGIN_QCALL;
2663
2664     if (!pMethod)
2665         COMPlusThrowArgumentNull(NULL, W("Arg_InvalidHandle"));
2666
2667 #ifdef _DEBUG
2668     {
2669         GCX_COOP();
2670         _ASSERTE(((ReflectMethodObject *)(*refMethod.m_ppObject))->GetMethod() == pMethod);
2671     }
2672 #endif
2673     MethodDesc *pMethodStripped = pMethod->StripMethodInstantiation();
2674     if (pMethodStripped != pMethod)
2675     {
2676         GCX_COOP();
2677         refMethod.Set(pMethodStripped->GetStubMethodInfo());
2678     }
2679     END_QCALL;
2680
2681     return;
2682 }
2683
2684 // In the VM there might be more than one MethodDescs for a "method"
2685 // examples are methods on generic types which may have additional instantiating stubs
2686 //          and methods on value types which may have additional unboxing stubs.
2687 //
2688 // For generic methods we always hand out an instantiating stub except for a generic method definition
2689 // For non-generic methods on generic types we need an instantiating stub if it's one of the following
2690 //  - static method on a generic class
2691 //  - static or instance method on a generic interface
2692 //  - static or instance method on a generic value type
2693 // The Reflection policy is to always hand out instantiating stubs in these cases
2694 //
2695 // For methods on non-generic value types we can use either the cannonical method or the unboxing stub
2696 // The Reflection policy is to always hand out unboxing stubs if the methods are virtual methods
2697 // The reason for this is that in the current implementation of the class loader, the v-table slots for 
2698 // those methods point to unboxing stubs already. Note that this is just a implementation choice
2699 // that might change in the future. But we should always keep this Reflection policy an invariant.
2700 // 
2701 // For virtual methods on generic value types (intersection of the two cases), reflection will hand
2702 // out an unboxing instantiating stub
2703 // 
2704 // GetInstantiatingStub is called to: 
2705 // 1. create an InstantiatedMethodDesc for a generic method when calling BindGenericArguments() on a generic
2706 //    method. In this case instArray will not be null.
2707 // 2. create an InstantiatedMethodDesc for a method in a generic class. In this case instArray will be null.
2708 // 3. create an UnboxingStub for a method in a value type. In this case instArray will be null.
2709 // For case 2 and 3, an instantiating stub or unboxing stub might not be needed in which case the original 
2710 // MethodDesc is returned.
2711 FCIMPL3(MethodDesc*, RuntimeMethodHandle::GetStubIfNeeded,
2712     MethodDesc *pMethod,
2713     ReflectClassBaseObject *pTypeUNSAFE,
2714     PtrArray* instArrayUNSAFE)
2715 {
2716     CONTRACTL {
2717         FCALL_CHECK;
2718     }
2719     CONTRACTL_END;
2720
2721     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
2722     PTRARRAYREF instArray = (PTRARRAYREF)ObjectToOBJECTREF(instArrayUNSAFE);
2723
2724     if (refType == NULL)
2725         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2726
2727     TypeHandle instType = refType->GetType();
2728     MethodDesc *pNewMethod = pMethod;
2729
2730     // error conditions
2731     if (!pMethod)
2732         FCThrowRes(kArgumentException, W("Arg_InvalidHandle"));
2733
2734     if (instType.IsNull())
2735         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2736     
2737     // Perf optimization: this logic is actually duplicated in FindOrCreateAssociatedMethodDescForReflection, but since it
2738     // is the more common case it's worth the duplicate check here to avoid the helper method frame
2739     if ( instArray == NULL &&
2740          ( pMethod->HasMethodInstantiation() || 
2741            ( !instType.IsValueType() && 
2742              ( !instType.HasInstantiation() || instType.IsGenericTypeDefinition() ) ) ) )
2743     {
2744         return pNewMethod;
2745     }
2746
2747     HELPER_METHOD_FRAME_BEGIN_RET_2(refType, instArray);
2748     {
2749         TypeHandle *inst = NULL;
2750         DWORD ntypars = 0;
2751
2752         if (instArray != NULL) 
2753         {
2754             ntypars = instArray->GetNumComponents();    
2755
2756             size_t size = ntypars * sizeof(TypeHandle);
2757             if ((size / sizeof(TypeHandle)) != ntypars) // uint over/underflow
2758                 COMPlusThrow(kArgumentException);
2759             inst = (TypeHandle*) _alloca(size);        
2760
2761             for (DWORD i = 0; i < ntypars; i++) 
2762             {
2763                 REFLECTCLASSBASEREF instRef = (REFLECTCLASSBASEREF)instArray->GetAt(i);
2764
2765                 if (instRef == NULL)
2766                     COMPlusThrowArgumentNull(W("inst"), W("ArgumentNull_ArrayElement"));
2767
2768                 inst[i] = instRef->GetType();
2769             }
2770         }
2771
2772         pNewMethod = MethodDesc::FindOrCreateAssociatedMethodDescForReflection(pMethod, instType, Instantiation(inst, ntypars));
2773     }
2774     HELPER_METHOD_FRAME_END();
2775
2776     return pNewMethod;
2777 }
2778 FCIMPLEND
2779
2780         
2781 FCIMPL2(MethodDesc*, RuntimeMethodHandle::GetMethodFromCanonical, MethodDesc *pMethod, ReflectClassBaseObject *pTypeUNSAFE)
2782 {
2783     CONTRACTL {
2784         FCALL_CHECK;
2785         PRECONDITION(CheckPointer(pMethod));
2786     }
2787     CONTRACTL_END;
2788     
2789     REFLECTCLASSBASEREF refType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pTypeUNSAFE);
2790
2791     TypeHandle instType = refType->GetType();
2792     MethodDesc* pMDescInCanonMT = instType.GetMethodTable()->GetParallelMethodDesc(pMethod);
2793
2794     return pMDescInCanonMT;
2795 }
2796 FCIMPLEND
2797
2798
2799 FCIMPL2(MethodBody *, RuntimeMethodHandle::GetMethodBody, ReflectMethodObject *pMethodUNSAFE, ReflectClassBaseObject *pDeclaringTypeUNSAFE)
2800 {      
2801     CONTRACTL 
2802     {
2803         FCALL_CHECK;
2804     }
2805     CONTRACTL_END;
2806
2807     struct _gc
2808     {
2809         METHODBODYREF MethodBodyObj;
2810         EXCEPTIONHANDLINGCLAUSEREF EHClauseObj;
2811         LOCALVARIABLEINFOREF LocalVariableInfoObj;
2812         U1ARRAYREF                  U1Array;
2813         BASEARRAYREF                TempArray;
2814         REFLECTCLASSBASEREF         declaringType;
2815         REFLECTMETHODREF            refMethod;
2816     } gc;
2817
2818     gc.MethodBodyObj = NULL;
2819     gc.EHClauseObj = NULL;
2820     gc.LocalVariableInfoObj = NULL;
2821     gc.U1Array              = NULL;
2822     gc.TempArray            = NULL;
2823     gc.declaringType        = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pDeclaringTypeUNSAFE);
2824     gc.refMethod = (REFLECTMETHODREF)ObjectToOBJECTREF(pMethodUNSAFE);
2825
2826
2827     if (!gc.refMethod)
2828         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2829
2830     MethodDesc* pMethod = gc.refMethod->GetMethod();
2831
2832     TypeHandle declaringType = gc.declaringType == NULL ? TypeHandle() : gc.declaringType->GetType();
2833
2834     if (!pMethod->IsIL())
2835         return NULL;
2836
2837     HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
2838     {
2839         MethodDesc *pMethodIL = pMethod;
2840         if (pMethod->IsWrapperStub())
2841             pMethodIL = pMethod->GetWrappedMethodDesc();
2842         
2843         COR_ILMETHOD* pILHeader = pMethodIL->GetILHeader();
2844         
2845         if (pILHeader)
2846         {
2847             MethodTable * pExceptionHandlingClauseMT = MscorlibBinder::GetClass(CLASS__EH_CLAUSE);
2848             TypeHandle thEHClauseArray = ClassLoader::LoadArrayTypeThrowing(TypeHandle(pExceptionHandlingClauseMT), ELEMENT_TYPE_SZARRAY);
2849
2850             MethodTable * pLocalVariableMT = MscorlibBinder::GetClass(CLASS__LOCAL_VARIABLE_INFO);
2851             TypeHandle thLocalVariableArray = ClassLoader::LoadArrayTypeThrowing(TypeHandle(pLocalVariableMT), ELEMENT_TYPE_SZARRAY);
2852
2853             Module* pModule = pMethod->GetModule();
2854             COR_ILMETHOD_DECODER::DecoderStatus status;
2855             COR_ILMETHOD_DECODER header(pILHeader, pModule->GetMDImport(), &status);
2856
2857             if (status != COR_ILMETHOD_DECODER::SUCCESS)
2858             {
2859                 if (status == COR_ILMETHOD_DECODER::VERIFICATION_ERROR)
2860                 {
2861                     // Throw a verification HR
2862                     COMPlusThrowHR(COR_E_VERIFICATION);
2863                 }
2864                 else
2865                 {
2866                     COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
2867                 }
2868             }
2869
2870             gc.MethodBodyObj = (METHODBODYREF)AllocateObject(MscorlibBinder::GetClass(CLASS__METHOD_BODY));
2871             
2872             gc.MethodBodyObj->m_maxStackSize = header.GetMaxStack();
2873             gc.MethodBodyObj->m_initLocals = !!(header.GetFlags() & CorILMethod_InitLocals);
2874
2875             if (header.IsFat())
2876                 gc.MethodBodyObj->m_localVarSigToken = header.GetLocalVarSigTok();
2877             else
2878                 gc.MethodBodyObj->m_localVarSigToken = 0;
2879
2880             // Allocate the array of IL and fill it in from the method header.
2881             BYTE* pIL = const_cast<BYTE*>(header.Code);
2882             COUNT_T cIL = header.GetCodeSize();
2883             gc.U1Array  = (U1ARRAYREF) AllocatePrimitiveArray(ELEMENT_TYPE_U1, cIL);
2884
2885             SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->m_IL, gc.U1Array, GetAppDomain());
2886             memcpyNoGCRefs(gc.MethodBodyObj->m_IL->GetDataPtr(), pIL, cIL);
2887
2888             // Allocate the array of exception clauses.
2889             INT32 cEh = (INT32)header.EHCount();
2890             const COR_ILMETHOD_SECT_EH* ehInfo = header.EH;
2891             gc.TempArray = (BASEARRAYREF) AllocateArrayEx(thEHClauseArray, &cEh, 1);
2892
2893             SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->m_exceptionClauses, gc.TempArray, GetAppDomain());
2894             
2895             for (INT32 i = 0; i < cEh; i++)
2896             {                    
2897                 COR_ILMETHOD_SECT_EH_CLAUSE_FAT ehBuff; 
2898                 const COR_ILMETHOD_SECT_EH_CLAUSE_FAT* ehClause = 
2899                     (const COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)ehInfo->EHClause(i, &ehBuff); 
2900
2901                 gc.EHClauseObj = (EXCEPTIONHANDLINGCLAUSEREF) AllocateObject(pExceptionHandlingClauseMT);
2902
2903                 gc.EHClauseObj->m_flags = ehClause->GetFlags();  
2904                 gc.EHClauseObj->m_tryOffset = ehClause->GetTryOffset();
2905                 gc.EHClauseObj->m_tryLength = ehClause->GetTryLength();
2906                 gc.EHClauseObj->m_handlerOffset = ehClause->GetHandlerOffset();
2907                 gc.EHClauseObj->m_handlerLength = ehClause->GetHandlerLength();
2908                 
2909                 if ((ehClause->GetFlags() & COR_ILEXCEPTION_CLAUSE_FILTER) == 0)
2910                     gc.EHClauseObj->m_catchToken = ehClause->GetClassToken();
2911                 else
2912                     gc.EHClauseObj->m_filterOffset = ehClause->GetFilterOffset();
2913                 
2914                 gc.MethodBodyObj->m_exceptionClauses->SetAt(i, (OBJECTREF) gc.EHClauseObj);
2915                 SetObjectReference((OBJECTREF*)&(gc.EHClauseObj->m_methodBody), (OBJECTREF)gc.MethodBodyObj, GetAppDomain());
2916             }     
2917            
2918             if (header.LocalVarSig != NULL)
2919             {
2920                 SigTypeContext sigTypeContext(pMethod, declaringType, pMethod->LoadMethodInstantiation());
2921                 MetaSig metaSig(header.LocalVarSig, 
2922                                 header.cbLocalVarSig, 
2923                                 pModule, 
2924                                 &sigTypeContext, 
2925                                 MetaSig::sigLocalVars);
2926                 INT32 cLocals = metaSig.NumFixedArgs();
2927                 gc.TempArray  = (BASEARRAYREF) AllocateArrayEx(thLocalVariableArray, &cLocals, 1);
2928                 SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->m_localVariables, gc.TempArray, GetAppDomain());
2929
2930                 for (INT32 i = 0; i < cLocals; i ++)
2931                 {
2932                     gc.LocalVariableInfoObj = (LOCALVARIABLEINFOREF)AllocateObject(pLocalVariableMT);
2933
2934                     gc.LocalVariableInfoObj->m_localIndex = i;
2935                     
2936                     metaSig.NextArg();
2937
2938                     CorElementType eType;
2939                     IfFailThrow(metaSig.GetArgProps().PeekElemType(&eType));
2940                     if (ELEMENT_TYPE_PINNED == eType)
2941                         gc.LocalVariableInfoObj->m_bIsPinned = TRUE;
2942
2943                     TypeHandle  tempType= metaSig.GetArgProps().GetTypeHandleThrowing(pModule, &sigTypeContext);       
2944                     OBJECTREF refLocalType = tempType.GetManagedClassObject();
2945                     gc.LocalVariableInfoObj->SetType(refLocalType);
2946                     gc.MethodBodyObj->m_localVariables->SetAt(i, (OBJECTREF) gc.LocalVariableInfoObj);
2947                 }        
2948             }
2949             else
2950             {
2951                 INT32 cLocals = 0;
2952                 gc.TempArray  = (BASEARRAYREF) AllocateArrayEx(thLocalVariableArray, &cLocals, 1);
2953                 SetObjectReference((OBJECTREF*)&gc.MethodBodyObj->m_localVariables, gc.TempArray, GetAppDomain());
2954             }
2955         }
2956     }
2957     HELPER_METHOD_FRAME_END();
2958
2959     return (MethodBody*)OBJECTREFToObject(gc.MethodBodyObj);
2960 }
2961 FCIMPLEND
2962
2963 FCIMPL1(FC_BOOL_RET, RuntimeMethodHandle::IsConstructor, MethodDesc *pMethod)
2964 {
2965     CONTRACTL {
2966         FCALL_CHECK;
2967         PRECONDITION(CheckPointer(pMethod));
2968     }
2969     CONTRACTL_END;
2970
2971     BOOL ret = FALSE;
2972     BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), FCThrow(kStackOverflowException));
2973     ret = (BOOL)pMethod->IsClassConstructorOrCtor();
2974     END_SO_INTOLERANT_CODE;
2975     FC_RETURN_BOOL(ret);
2976 }
2977 FCIMPLEND
2978
2979 FCIMPL1(Object*, RuntimeMethodHandle::GetLoaderAllocator, MethodDesc *pMethod)
2980 {
2981     CONTRACTL {
2982         FCALL_CHECK;
2983     }
2984     CONTRACTL_END;
2985
2986     OBJECTREF loaderAllocator = NULL;
2987
2988     if (!pMethod)
2989         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
2990
2991     HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(loaderAllocator);
2992
2993     LoaderAllocator *pLoaderAllocator = pMethod->GetLoaderAllocator();
2994     loaderAllocator = pLoaderAllocator->GetExposedObject();
2995
2996     HELPER_METHOD_FRAME_END();
2997
2998     return OBJECTREFToObject(loaderAllocator);
2999 }
3000 FCIMPLEND
3001
3002 //*********************************************************************************************
3003 //*********************************************************************************************
3004 //*********************************************************************************************
3005
3006 FCIMPL1(StringObject*, RuntimeFieldHandle::GetName, ReflectFieldObject *pFieldUNSAFE) {
3007     CONTRACTL {
3008         FCALL_CHECK;
3009     }
3010     CONTRACTL_END;
3011     
3012     REFLECTFIELDREF refField = (REFLECTFIELDREF)ObjectToOBJECTREF(pFieldUNSAFE);
3013     if (!refField)
3014         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3015         
3016     FieldDesc *pField = refField->GetField();
3017     
3018     STRINGREF refString = NULL;
3019     HELPER_METHOD_FRAME_BEGIN_RET_1(refField);
3020     {
3021         refString = StringObject::NewString(pField->GetName());
3022     }
3023     HELPER_METHOD_FRAME_END();
3024     return (StringObject*)OBJECTREFToObject(refString);
3025 }
3026 FCIMPLEND
3027     
3028 FCIMPL1(LPCUTF8, RuntimeFieldHandle::GetUtf8Name, FieldDesc *pField) {
3029     CONTRACTL {
3030         FCALL_CHECK;
3031         PRECONDITION(CheckPointer(pField));
3032     }
3033     CONTRACTL_END;
3034     
3035     LPCUTF8    szFieldName;
3036     
3037     if (FAILED(pField->GetName_NoThrow(&szFieldName)))
3038     {
3039         FCThrow(kBadImageFormatException);
3040     }
3041     return szFieldName;
3042 }
3043 FCIMPLEND
3044
3045 FCIMPL2(FC_BOOL_RET, RuntimeFieldHandle::MatchesNameHash, FieldDesc * pField, ULONG hash)
3046 {
3047     FCALL_CONTRACT;
3048
3049     FC_RETURN_BOOL(pField->MightHaveName(hash));
3050 }
3051 FCIMPLEND
3052
3053 FCIMPL1(INT32, RuntimeFieldHandle::GetAttributes, FieldDesc *pField) {
3054     CONTRACTL {
3055         FCALL_CHECK;
3056     }
3057     CONTRACTL_END;
3058     
3059     if (!pField)
3060         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3061
3062     INT32 ret = 0;
3063     BEGIN_SO_INTOLERANT_CODE_NOTHROW(GetThread(), FCThrow(kStackOverflowException));
3064     ret = (INT32)pField->GetAttributes();
3065     END_SO_INTOLERANT_CODE;
3066     return ret;
3067 }
3068 FCIMPLEND
3069     
3070 FCIMPL1(ReflectClassBaseObject*, RuntimeFieldHandle::GetApproxDeclaringType, FieldDesc *pField) {
3071     CONTRACTL {
3072         FCALL_CHECK;
3073     }
3074     CONTRACTL_END;
3075     
3076     if (!pField)
3077         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3078         
3079     TypeHandle th = TypeHandle(pField->GetApproxEnclosingMethodTable());  // <REVISIT_TODO> this needs to be checked - see bug 184355 </REVISIT_TODO>
3080     RETURN_CLASS_OBJECT(th, NULL);
3081 }
3082 FCIMPLEND
3083
3084 FCIMPL1(INT32, RuntimeFieldHandle::GetToken, ReflectFieldObject *pFieldUNSAFE) {
3085     CONTRACTL {
3086         FCALL_CHECK;
3087     }
3088     CONTRACTL_END;
3089
3090     REFLECTFIELDREF refField = (REFLECTFIELDREF)ObjectToOBJECTREF(pFieldUNSAFE);
3091     if (!refField)
3092         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3093         
3094     FieldDesc *pField = refField->GetField();
3095
3096     INT32 tkFieldDef = (INT32)pField->GetMemberDef();
3097     _ASSERTE(!IsNilToken(tkFieldDef) || tkFieldDef == mdFieldDefNil);
3098     return tkFieldDef;
3099 }
3100 FCIMPLEND
3101
3102 FCIMPL2(FieldDesc*, RuntimeFieldHandle::GetStaticFieldForGenericType, FieldDesc *pField, ReflectClassBaseObject *pDeclaringTypeUNSAFE)
3103 {
3104     CONTRACTL {
3105         FCALL_CHECK;
3106     }
3107     CONTRACTL_END;
3108
3109     REFLECTCLASSBASEREF refDeclaringType = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(pDeclaringTypeUNSAFE);
3110
3111     if ((refDeclaringType == NULL) || (pField == NULL))
3112         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3113
3114     TypeHandle declaringType = refDeclaringType->GetType();
3115     
3116     if (!pField)
3117         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3118     if (declaringType.IsTypeDesc())
3119         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3120     MethodTable *pMT = declaringType.AsMethodTable();
3121
3122     _ASSERTE(pField->IsStatic());
3123     if (pMT->HasGenericsStaticsInfo())
3124         pField = pMT->GetFieldDescByIndex(pField->GetApproxEnclosingMethodTable()->GetIndexForFieldDesc(pField));
3125     _ASSERTE(!pField->IsSharedByGenericInstantiations());
3126     _ASSERTE(pField->GetEnclosingMethodTable() == pMT);
3127
3128     return pField;
3129 }
3130 FCIMPLEND
3131
3132 FCIMPL1(ReflectModuleBaseObject*, AssemblyHandle::GetManifestModule, AssemblyBaseObject* pAssemblyUNSAFE) {
3133     FCALL_CONTRACT;
3134
3135     ASSEMBLYREF refAssembly = (ASSEMBLYREF)ObjectToOBJECTREF(pAssemblyUNSAFE);
3136     
3137     if (refAssembly == NULL)
3138         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3139
3140     DomainAssembly *pAssembly = refAssembly->GetDomainAssembly();
3141     Assembly* currentAssembly = pAssembly->GetCurrentAssembly();
3142
3143     if (currentAssembly == NULL)
3144         return NULL;
3145
3146     Module *pModule = currentAssembly->GetManifestModule();
3147     DomainFile * pDomainFile = pModule->FindDomainFile(GetAppDomain());
3148
3149 #ifdef _DEBUG
3150     OBJECTREF orModule;
3151     
3152     HELPER_METHOD_FRAME_BEGIN_RET_1(refAssembly);
3153     orModule = (pDomainFile != NULL) ? pDomainFile->GetExposedModuleObjectIfExists() : NULL;
3154     if (orModule == NULL)
3155         orModule = pModule->GetExposedObject();
3156 #else
3157     OBJECTREF orModule = (pDomainFile != NULL) ? pDomainFile->GetExposedModuleObjectIfExists() : NULL;
3158     if (orModule != NULL)
3159         return (ReflectModuleBaseObject*)OBJECTREFToObject(orModule);
3160
3161     HELPER_METHOD_FRAME_BEGIN_RET_1(refAssembly);
3162     orModule = pModule->GetExposedObject();
3163 #endif
3164
3165     HELPER_METHOD_FRAME_END();
3166     return (ReflectModuleBaseObject*)OBJECTREFToObject(orModule);
3167
3168 }
3169 FCIMPLEND
3170
3171 FCIMPL1(INT32, AssemblyHandle::GetToken, AssemblyBaseObject* pAssemblyUNSAFE) {
3172     FCALL_CONTRACT;
3173     
3174     ASSEMBLYREF refAssembly = (ASSEMBLYREF)ObjectToOBJECTREF(pAssemblyUNSAFE);
3175     
3176     if (refAssembly == NULL)
3177         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3178
3179     DomainAssembly *pAssembly = refAssembly->GetDomainAssembly();
3180     mdAssembly token = mdAssemblyNil;
3181     
3182     IMDInternalImport *mdImport = pAssembly->GetCurrentAssembly()->GetManifestImport();
3183     
3184     if (mdImport != 0)
3185     {
3186         if (FAILED(mdImport->GetAssemblyFromScope(&token)))
3187         {
3188             FCThrow(kBadImageFormatException);
3189         }
3190     }
3191     
3192     return token;
3193 }
3194 FCIMPLEND
3195
3196     
3197 void QCALLTYPE ModuleHandle::GetPEKind(QCall::ModuleHandle pModule, DWORD* pdwPEKind, DWORD* pdwMachine)
3198 {
3199     QCALL_CONTRACT;
3200
3201     BEGIN_QCALL;
3202     pModule->GetFile()->GetPEKindAndMachine(pdwPEKind, pdwMachine);
3203     END_QCALL;
3204 }
3205
3206 FCIMPL1(INT32, ModuleHandle::GetMDStreamVersion, ReflectModuleBaseObject * pModuleUNSAFE)
3207 {
3208     FCALL_CONTRACT;
3209
3210     REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE);
3211
3212     if (refModule == NULL)
3213         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3214
3215     Module *pModule = refModule->GetModule();
3216     
3217     if (pModule->IsResource())
3218         return 0;
3219     
3220     return pModule->GetMDImport()->GetMetadataStreamVersion();   
3221 }
3222 FCIMPLEND
3223
3224 void QCALLTYPE ModuleHandle::GetModuleType(QCall::ModuleHandle pModule, QCall::ObjectHandleOnStack retType)
3225 {
3226     QCALL_CONTRACT;
3227
3228     TypeHandle globalTypeHandle = TypeHandle();
3229     
3230     BEGIN_QCALL;
3231     
3232         EX_TRY
3233         {          
3234             globalTypeHandle = TypeHandle(pModule->GetGlobalMethodTable());
3235         }
3236         EX_SWALLOW_NONTRANSIENT;
3237
3238         if (!globalTypeHandle.IsNull())
3239         {
3240             GCX_COOP();
3241             retType.Set(globalTypeHandle.GetManagedClassObject());
3242         }
3243
3244     END_QCALL;
3245
3246     return;
3247 }
3248
3249 FCIMPL1(INT32, ModuleHandle::GetToken, ReflectModuleBaseObject * pModuleUNSAFE) {
3250     CONTRACTL {
3251         FCALL_CHECK;
3252     }
3253     CONTRACTL_END;
3254
3255     REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE);
3256
3257     if (refModule == NULL)
3258         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3259
3260     Module *pModule = refModule->GetModule();
3261     
3262     if (pModule->IsResource())
3263         return mdModuleNil;
3264     
3265     return pModule->GetMDImport()->GetModuleFromScope();
3266 }
3267 FCIMPLEND
3268
3269 FCIMPL1(IMDInternalImport*, ModuleHandle::GetMetadataImport, ReflectModuleBaseObject * pModuleUNSAFE)
3270 {
3271     FCALL_CONTRACT;
3272
3273     REFLECTMODULEBASEREF refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE);
3274
3275     if (refModule == NULL)
3276         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3277
3278     Module *pModule = refModule->GetModule();
3279
3280     if (pModule->IsResource())
3281         return NULL;
3282
3283     return pModule->GetMDImport();
3284 }
3285 FCIMPLEND
3286
3287 BOOL QCALLTYPE ModuleHandle::ContainsPropertyMatchingHash(QCall::ModuleHandle pModule, INT32 tkProperty, ULONG hash)
3288 {
3289     QCALL_CONTRACT;
3290
3291     BOOL fContains = TRUE;
3292
3293     BEGIN_QCALL;
3294
3295     fContains = pModule->MightContainMatchingProperty(tkProperty, hash);
3296
3297     END_QCALL;
3298
3299     return fContains;
3300 }
3301
3302 void QCALLTYPE ModuleHandle::ResolveType(QCall::ModuleHandle pModule, INT32 tkType, TypeHandle *typeArgs, INT32 typeArgsCount, TypeHandle *methodArgs, INT32 methodArgsCount, QCall::ObjectHandleOnStack retType)
3303 {
3304     QCALL_CONTRACT;
3305
3306     TypeHandle typeHandle;
3307     
3308     BEGIN_QCALL;
3309     
3310     _ASSERTE(!IsNilToken(tkType));
3311
3312     SigTypeContext typeContext(Instantiation(typeArgs, typeArgsCount), Instantiation(methodArgs, methodArgsCount));
3313         typeHandle = ClassLoader::LoadTypeDefOrRefOrSpecThrowing(pModule, tkType, &typeContext, 
3314                                                           ClassLoader::ThrowIfNotFound, 
3315                                                           ClassLoader::PermitUninstDefOrRef);
3316
3317     GCX_COOP();
3318     retType.Set(typeHandle.GetManagedClassObject());
3319
3320     END_QCALL;
3321
3322     return;
3323 }
3324
3325 MethodDesc *QCALLTYPE ModuleHandle::ResolveMethod(QCall::ModuleHandle pModule, INT32 tkMemberRef, TypeHandle *typeArgs, INT32 typeArgsCount, TypeHandle *methodArgs, INT32 methodArgsCount)
3326 {
3327     QCALL_CONTRACT;
3328
3329     MethodDesc* pMD = NULL;
3330     
3331     BEGIN_QCALL;
3332
3333     _ASSERTE(!IsNilToken(tkMemberRef));
3334
3335     BOOL strictMetadataChecks = (TypeFromToken(tkMemberRef) == mdtMethodSpec);
3336
3337     SigTypeContext typeContext(Instantiation(typeArgs, typeArgsCount), Instantiation(methodArgs, methodArgsCount));
3338     pMD = MemberLoader::GetMethodDescFromMemberDefOrRefOrSpec(pModule, tkMemberRef, &typeContext, strictMetadataChecks, FALSE);
3339
3340     // This will get us the instantiating or unboxing stub if needed
3341     pMD = MethodDesc::FindOrCreateAssociatedMethodDescForReflection(pMD, pMD->GetMethodTable(), pMD->GetMethodInstantiation());
3342
3343     END_QCALL;
3344
3345     return pMD;
3346 }
3347
3348 void QCALLTYPE ModuleHandle::ResolveField(QCall::ModuleHandle pModule, INT32 tkMemberRef, TypeHandle *typeArgs, INT32 typeArgsCount, TypeHandle *methodArgs, INT32 methodArgsCount, QCall::ObjectHandleOnStack retField)
3349 {
3350     QCALL_CONTRACT;
3351
3352     FieldDesc* pField = NULL;
3353     
3354     BEGIN_QCALL;
3355
3356     _ASSERTE(!IsNilToken(tkMemberRef));
3357
3358     SigTypeContext typeContext(Instantiation(typeArgs, typeArgsCount), Instantiation(methodArgs, methodArgsCount));
3359     pField = MemberLoader::GetFieldDescFromMemberDefOrRef(pModule, tkMemberRef, &typeContext, FALSE);
3360     GCX_COOP();
3361     retField.Set(pField->GetStubFieldInfo());
3362
3363     END_QCALL;
3364
3365     return;
3366 }
3367
3368 void QCALLTYPE ModuleHandle::GetAssembly(QCall::ModuleHandle pModule, QCall::ObjectHandleOnStack retAssembly)
3369 {
3370     QCALL_CONTRACT;
3371
3372     DomainAssembly *pAssembly = NULL;
3373
3374     BEGIN_QCALL;
3375     pAssembly = pModule->GetDomainAssembly();
3376
3377     GCX_COOP();
3378     retAssembly.Set(pAssembly->GetExposedAssemblyObject());
3379     END_QCALL;
3380
3381     return;
3382 }
3383
3384 FCIMPL5(ReflectMethodObject*, ModuleHandle::GetDynamicMethod, ReflectMethodObject *pMethodUNSAFE, ReflectModuleBaseObject *pModuleUNSAFE, StringObject *name, U1Array *sig,  Object *resolver) {
3385     CONTRACTL {
3386         FCALL_CHECK;
3387         PRECONDITION(CheckPointer(name));
3388         PRECONDITION(CheckPointer(sig));
3389     }
3390     CONTRACTL_END;
3391     
3392     DynamicMethodDesc *pNewMD = NULL;
3393
3394     struct
3395     {
3396         STRINGREF nameRef;
3397         OBJECTREF resolverRef;
3398         OBJECTREF methodRef;
3399         REFLECTMETHODREF retMethod;
3400         REFLECTMODULEBASEREF refModule;
3401     } gc;
3402     gc.nameRef = (STRINGREF)name;
3403     gc.resolverRef = (OBJECTREF)resolver;
3404     gc.methodRef = ObjectToOBJECTREF(pMethodUNSAFE);
3405     gc.retMethod = NULL;
3406     gc.refModule = (REFLECTMODULEBASEREF)ObjectToOBJECTREF(pModuleUNSAFE);
3407
3408     if (gc.refModule == NULL)
3409         FCThrowRes(kArgumentNullException, W("Arg_InvalidHandle"));
3410
3411     Module *pModule = gc.refModule->GetModule();
3412
3413     HELPER_METHOD_FRAME_BEGIN_RET_PROTECT(gc);
3414     
3415     DomainFile *pDomainModule = pModule->GetDomainFile();
3416
3417     U1ARRAYREF dataArray = (U1ARRAYREF)sig;
3418     DWORD sigSize = dataArray->GetNumComponents();
3419     NewHolder<BYTE> pSig(new BYTE[sigSize]);
3420     memcpy(pSig, dataArray->GetDataPtr(), sigSize);
3421
3422     DWORD length = gc.nameRef->GetStringLength();
3423     NewArrayHolder<char> pName(new char[(length + 1) * 2]);
3424     pName[0] = '\0';
3425     length = WszWideCharToMultiByte(CP_UTF8, 0, gc.nameRef->GetBuffer(), length, pName, (length + 1) * 2 - sizeof(char), NULL, NULL);
3426     if (length)
3427         pName[length / sizeof(char)] = '\0';
3428
3429     DynamicMethodTable *pMTForDynamicMethods = pDomainModule->GetDynamicMethodTable();
3430     pNewMD = pMTForDynamicMethods->GetDynamicMethod(pSig, sigSize, pName);
3431     _ASSERTE(pNewMD != NULL);
3432     // pNewMD now owns pSig and pName.
3433     pSig.SuppressRelease();
3434     pName.SuppressRelease();
3435
3436     // create a handle to hold the resolver objectref
3437     OBJECTHANDLE resolverHandle = pDomainModule->GetAppDomain()->CreateLongWeakHandle(gc.resolverRef);
3438     pNewMD->GetLCGMethodResolver()->SetManagedResolver(resolverHandle);
3439     gc.retMethod = pNewMD->GetStubMethodInfo();
3440     gc.retMethod->SetKeepAlive(gc.resolverRef);
3441
3442     LoaderAllocator *pLoaderAllocator = pModule->GetLoaderAllocator();
3443
3444     if (pLoaderAllocator->IsCollectible())
3445         pLoaderAllocator->AddReference();
3446    
3447     HELPER_METHOD_FRAME_END();
3448
3449     return (ReflectMethodObject*)OBJECTREFToObject(gc.retMethod);
3450 }
3451 FCIMPLEND
3452
3453 void QCALLTYPE RuntimeMethodHandle::GetCallerType(QCall::StackCrawlMarkHandle pStackMark, QCall::ObjectHandleOnStack retType)
3454
3455     QCALL_CONTRACT;
3456
3457     BEGIN_QCALL;
3458     GCX_COOP();
3459     MethodTable *pMT = NULL;
3460
3461     pMT = SystemDomain::GetCallersType(pStackMark);
3462
3463     if (pMT != NULL)
3464         retType.Set(pMT->GetManagedClassObject());
3465
3466     END_QCALL;
3467
3468     return;
3469 }