summaryrefslogtreecommitdiff
path: root/src/vm/zapsig.h
blob: 4d2e98b593a9edfc11c301283b7e04020d116c06 (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
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
// 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.

// ---------------------------------------------------------------------------
// zapsig.h
// ---------------------------------------------------------------------------
//
// This module contains helper functions used to encode and manipulate
// signatures for the zapper (ngen).
//

// ---------------------------------------------------------------------------


#ifndef ZAPSIG_H
#define ZAPSIG_H

#include "common.h"

typedef DWORD(*ENCODEMODULE_CALLBACK)(LPVOID pModuleContext, CORINFO_MODULE_HANDLE moduleHandle);
typedef DWORD (*EncodeModuleCallback)(void* pModuleContext, Module *pReferencedModule);
enum {
    // return value when EncodeModule fails
    ENCODE_MODULE_FAILED         = 0xffffffff,
    // no module index override is needed 
    MODULE_INDEX_NONE            = 0xfffffffe
};

typedef void(*DEFINETOKEN_CALLBACK)(LPVOID pModuleContext, CORINFO_MODULE_HANDLE moduleHandle, DWORD index, mdTypeRef* token);
typedef void (*TokenDefinitionCallback)(void* pModuleContext, Module *pReferencedModule, DWORD index, mdToken* refToken);

class ZapSig
{
public:
    enum ExternalTokens
    {
        IllegalValue,
        NormalTokens,
        IbcTokens
    };
    
    struct Context
    {
        Module *        pInfoModule;              // The tokens in this ZapSig are expressed relative to context.pInfoModule         
        void *          pModuleContext;           // This is a code:Module* when we are resolving Ngen fixups or doing an Ibc Profiling run
                                                  // and is a code:ZapImportTable* when we are running ngen      
        ExternalTokens  externalTokens;           // When we see a ELEMENT_TYPE_MODULE_ZAPSIG this tells us what type of token follows.

        Module * GetZapSigModule() const        { return (Module*) pModuleContext; }
        
        Context(
                Module* _pInfoModule,
                void* _pModuleContext, ExternalTokens _externalTokens)
            : pInfoModule(_pInfoModule),
              pModuleContext(_pModuleContext),
              externalTokens(_externalTokens)
        { LIMITED_METHOD_CONTRACT; _ASSERTE(externalTokens != IllegalValue); }

        Context(
                Module* _pInfoModule,
                Module* _pZapSigModule)
            : pInfoModule(_pInfoModule),
              pModuleContext((void*) _pZapSigModule),
              externalTokens(NormalTokens)
        { }
    };

public:

    ZapSig(
           Module *                _pInfoModule, 
           void *                  _pModuleContext,
           ExternalTokens          _externalTokens,
           EncodeModuleCallback    _pfnEncodeModule,
           TokenDefinitionCallback _pfnTokenDefinition)

        : context(_pInfoModule, _pModuleContext, _externalTokens),
          pfnEncodeModule(_pfnEncodeModule),
          pfnTokenDefinition(_pfnTokenDefinition)
    {}

    // Static methods

    // Compare a type handle with a signature whose tokens are resolved with respect to pModule
    // pZapSigContext is used to resolve ELEMENT_TYPE_MODULE_ZAPSIG encodings
    static BOOL CompareSignatureToTypeHandle(PCCOR_SIGNATURE  pSig,
        Module*          pModule,
        TypeHandle       handle,
        const ZapSig::Context *  pZapSigContext);

    // Instance methods

    // Create a signature for a typeHandle 
    // It can be decoded using MetaSig::GetTypeHandleThrowing
    // The tokens are espressed relative to this->pInfoModule
    // When (handle.GetModule() != this->pInfoModule), we escape
    // the signature with ELEMENT_TYPE_MODULE_ZAPSIG <id-num>
    // followed by a <token> to encode a temporary change of module 
    // For Ibc Signatures the <token> is one of the ibc defined tokens
    // For Ngen Fixup signatures the <token> is for the external module
    //
    BOOL GetSignatureForTypeHandle(TypeHandle typeHandle,
                                   SigBuilder * pSigBuilder);

#ifdef FEATURE_PREJIT
    // Compare a type handle with a tagged pointer. Ensure that the common path is inlined into the caller.
    static FORCEINLINE BOOL CompareTaggedPointerToTypeHandle(Module * pModule, TADDR addr, TypeHandle handle)
    {
        WRAPPER_NO_CONTRACT;
        if (handle.AsTAddr() == addr)
            return TRUE;
        if (!CORCOMPILE_IS_POINTER_TAGGED(addr))
            return FALSE;
        return CompareFixupToTypeHandle(pModule, addr, handle);
    }

    static BOOL CompareFixupToTypeHandle(Module * pModule, TADDR fixup, TypeHandle handle);
#endif

    static BOOL CompareTypeHandleFieldToTypeHandle(TypeHandle *pTypeHnd, TypeHandle typeHnd2);

private:
    BOOL GetSignatureForTypeDesc(TypeDesc * desc, SigBuilder * pSigBuilder);

    // Returns element type when the typeHandle can be encoded using
    // using a single CorElementType value 
    // This includes using ELEMENT_TYPE_CANON_ZAPSIG for the System.__Canon type
    //
    static CorElementType TryEncodeUsingShortcut(/* in  */ MethodTable * pMT);

    // Copy single type signature, adding ELEMENT_TYPE_MODULE_ZAPSIG to types that are encoded using tokens.
    // The source signature originates from the module with index specified by the parameter moduleIndex.
    // Passing moduleIndex set to MODULE_INDEX_NONE results in pure copy of the signature.
    //
    static void CopyTypeSignature(SigParser* pSigParser, SigBuilder* pSigBuilder, DWORD moduleIndex);

private:

    ZapSig::Context           context;  
  
    EncodeModuleCallback      pfnEncodeModule;    // Function Pointer to the EncodeModuleHelper
    TokenDefinitionCallback   pfnTokenDefinition; // Function Pointer to the DefineTokenHelper

public:
    //--------------------------------------------------------------------
    // Static helper encode/decode helper methods

    static Module *DecodeModuleFromIndex(Module *fromModule,
        DWORD index);

    static Module *DecodeModuleFromIndexIfLoaded(Module *fromModule,
        DWORD index);

    // referencingModule is the module that references the type.
    // fromModule is the module in which the type is defined.
    // pBuffer contains the signature encoding for the type.
    // level is the class load level (see classloadlevel.h) to which the type should be loaded
    static TypeHandle DecodeType(
        Module              *referencingModule,
        Module              *fromModule,
        PCCOR_SIGNATURE     pBuffer,
        ClassLoadLevel      level = CLASS_LOADED);

    static MethodDesc *DecodeMethod(
        Module              *referencingModule,
        Module              *fromModule,
        PCCOR_SIGNATURE     pBuffer,
        TypeHandle          *ppTH = NULL);

    static MethodDesc *DecodeMethod(
        Module              *referencingModule,
        Module              *fromModule,
        PCCOR_SIGNATURE     pBuffer,
        SigTypeContext      *pContext,
        TypeHandle          *ppTH = NULL,
        PCCOR_SIGNATURE     *ppOwnerTypeSpecWithVars = NULL,
        PCCOR_SIGNATURE     *ppMethodSpecWithVars = NULL);

    static FieldDesc *DecodeField(
        Module              *referencingModule,
        Module              *fromModule,
        PCCOR_SIGNATURE     pBuffer,
        TypeHandle          *ppTH = NULL);

    static FieldDesc *DecodeField(
        Module              *pReferencingModule,
        Module              *pInfoModule,
        PCCOR_SIGNATURE     pBuffer,
        SigTypeContext      *pContext,
        TypeHandle          *ppTH = NULL);

    static BOOL EncodeMethod(
        MethodDesc             *pMethod,
        Module                 *pInfoModule,
        SigBuilder             *pSigBuilder,
        LPVOID                 pReferencingModule,
        ENCODEMODULE_CALLBACK  pfnEncodeModule,
        DEFINETOKEN_CALLBACK   pfnDefineToken,
        CORINFO_RESOLVED_TOKEN *pResolvedToken = NULL,
        CORINFO_RESOLVED_TOKEN *pConstrainedResolvedToken = NULL,
        BOOL                   fEncodeUsingResolvedTokenSpecStreams = FALSE);

    static void EncodeField(
        FieldDesc              *pField,
        Module                 *pInfoModule,
        SigBuilder             *pSigBuilder,
        LPVOID                 pReferencingModule,
        ENCODEMODULE_CALLBACK  pfnEncodeModule,
        CORINFO_RESOLVED_TOKEN *pResolvedToken = NULL,
        BOOL                   fEncodeUsingResolvedTokenSpecStreams = FALSE);

};

#endif // ZAPGSIG_H