summaryrefslogtreecommitdiff
path: root/src/vm/generics.inl
blob: df60ff951ecc82c5a7c20b38167179d6964df208 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
//
// File: generics.inl
//

//
// Helper functions for generics implementation
//

//
// ============================================================================

#ifndef GENERICS_INL
#define GENERICS_INL

#ifdef FEATURE_COMINTEROP
#include "winrttypenameconverter.h"
#endif

// Generics helper functions
namespace Generics
{
#ifndef DACCESS_COMPILE
    inline void DetermineCCWTemplateAndGUIDPresenceOnNonCanonicalMethodTable(
        // Input
        MethodTable *pOldMT, BOOL fNewMTContainsGenericVariables,
        // Output
        BOOL *pfHasGuidInfo, BOOL *pfHasCCWTemplate)
    {
        STANDARD_VM_CONTRACT;

#ifdef FEATURE_COMINTEROP 
        WORD wNumInterfaces = static_cast<WORD>(pOldMT->GetNumInterfaces());

        InterfaceInfo_t * pOldIMap = (InterfaceInfo_t *)pOldMT->GetInterfaceMap();

        BOOL fHasGuidInfo = FALSE;

        // Generic WinRT delegates expose a class interface and need the CCW template
        BOOL fHasCCWTemplate = FALSE;
    
        if (!fNewMTContainsGenericVariables)
        {
            if (pOldMT->IsInterface())
            {
                fHasGuidInfo = (pOldMT->IsProjectedFromWinRT() || WinRTTypeNameConverter::IsRedirectedType(pOldMT, WinMDAdapter::WinMDTypeKind_PInterface));
            }
            else if (pOldMT->IsDelegate())
            {
                fHasGuidInfo = (pOldMT->IsProjectedFromWinRT() || WinRTTypeNameConverter::IsRedirectedType(pOldMT, WinMDAdapter::WinMDTypeKind_PDelegate));
                
                // Generic WinRT delegates expose a class interface and need a CCW template
                fHasCCWTemplate = fHasGuidInfo;
            }
            
            if (!fHasCCWTemplate)
            {
                if (pOldMT->IsInterface())
                {
                    // Interfaces need the CCW template if they are redirected and need variance
                    if (pOldMT->HasVariance() &&
                        (pOldMT->IsProjectedFromWinRT() || WinRTTypeNameConverter::IsRedirectedType(pOldMT, WinMDAdapter::WinMDTypeKind_PInterface)))
                        {
                            fHasCCWTemplate = TRUE;
                        }
                }
                else
                {
                    // Other types may need the CCW template if they implement generic interfaces
                    for (WORD iItf = 0; iItf < wNumInterfaces; iItf++)
                    {
                        // If the class implements a generic WinRT interface, it needs its own (per-instantiation)
                        // CCW template as the one on EEClass would be shared and hence useless.
                        OVERRIDE_TYPE_LOAD_LEVEL_LIMIT(CLASS_LOAD_APPROXPARENTS);
                        MethodTable *pItfMT = pOldIMap[iItf].GetApproxMethodTable(pOldMT->GetLoaderModule());
                        if (pItfMT->HasInstantiation() && 
                            (pItfMT->IsProjectedFromWinRT() || WinRTTypeNameConverter::IsRedirectedType(pItfMT, WinMDAdapter::WinMDTypeKind_PInterface)))
                        {
                            fHasCCWTemplate = TRUE;
                            break;
                        }
                    }
                }
            }
        }
#else // FEATURE_COMINTEROP
        BOOL fHasGuidInfo = FALSE;
        BOOL fHasCCWTemplate = FALSE;
#endif // FEATURE_COMINTEROP
        *pfHasGuidInfo = fHasGuidInfo;
        *pfHasCCWTemplate = fHasCCWTemplate;
    }
#endif // DACCESS_COMPILE
}

#endif // GENERICS_INL