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