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