Merge remote-tracking branch 'dotnet/master' into NullableFeature
[platform/upstream/coreclr.git] / src / vm / ilstubresolver.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 // File: ILStubResolver.cpp
6 // 
7
8 //
9
10
11 #include "common.h"
12
13 #include "field.h"
14
15 // returns pointer to IL code
16 BYTE* ILStubResolver::GetCodeInfo(unsigned* pCodeSize, unsigned* pStackSize, CorInfoOptions* pOptions, unsigned* pEHSize)
17 {
18     CONTRACT(BYTE*)
19     {
20         STANDARD_VM_CHECK;
21         PRECONDITION(CheckPointer(pCodeSize));
22         PRECONDITION(CheckPointer(pStackSize));
23         PRECONDITION(CheckPointer(pOptions));
24         PRECONDITION(CheckPointer(pEHSize));
25         PRECONDITION(CheckPointer(m_pCompileTimeState));
26         POSTCONDITION(CheckPointer(RETVAL));
27     }
28     CONTRACT_END;
29
30 #ifndef DACCESS_COMPILE
31     CORINFO_METHOD_INFO methodInfo;    
32     getMethodInfoILMethodHeaderHelper(&m_pCompileTimeState->m_ILHeader, &methodInfo);
33
34     *pCodeSize = methodInfo.ILCodeSize;
35     *pStackSize = methodInfo.maxStack;
36     *pOptions = methodInfo.options;
37     *pEHSize = methodInfo.EHcount;
38     
39     RETURN methodInfo.ILCode;
40 #else // DACCESS_COMPILE
41     DacNotImpl();
42     RETURN NULL;
43 #endif // DACCESS_COMPILE
44 }
45
46 // static
47 LPCUTF8 ILStubResolver::GetStubClassName(MethodDesc* pMD)
48 {
49     CONTRACTL
50     {
51         MODE_ANY;
52         GC_NOTRIGGER;
53         NOTHROW;
54         SUPPORTS_DAC;
55         PRECONDITION(pMD->IsILStub());
56     }
57     CONTRACTL_END;
58
59     return "ILStubClass";
60 }
61
62 LPCUTF8 ILStubResolver::GetStubMethodName()
63 {
64     CONTRACTL
65     {
66         MODE_ANY;
67         GC_NOTRIGGER;
68         NOTHROW;
69     }
70     CONTRACTL_END;
71
72     switch (m_type)
73     {
74         case CLRToNativeInteropStub: return "IL_STUB_PInvoke";
75         case CLRToCOMInteropStub:    return "IL_STUB_CLRtoCOM";
76         case CLRToWinRTInteropStub:  return "IL_STUB_CLRtoWinRT";
77         case NativeToCLRInteropStub: return "IL_STUB_ReversePInvoke";
78         case COMToCLRInteropStub:    return "IL_STUB_COMtoCLR";
79         case WinRTToCLRInteropStub:  return "IL_STUB_WinRTtoCLR";
80 #ifdef FEATURE_ARRAYSTUB_AS_IL
81         case ArrayOpStub:            return "IL_STUB_Array";
82 #endif
83 #ifdef FEATURE_MULTICASTSTUB_AS_IL
84         case MulticastDelegateStub:  return "IL_STUB_MulticastDelegate_Invoke";
85 #endif
86 #ifdef FEATURE_STUBS_AS_IL
87         case UnboxingILStub:         return "IL_STUB_UnboxingStub";
88         case InstantiatingStub:      return "IL_STUB_InstantiatingStub";
89         case SecureDelegateStub:     return "IL_STUB_SecureDelegate_Invoke";
90 #endif
91         default:
92             UNREACHABLE_MSG("Unknown stub type");
93     }
94 }
95
96 void ILStubResolver::GetJitContext(SecurityControlFlags* pSecurityControlFlags,
97                                    TypeHandle* pTypeOwner)
98 {
99     CONTRACTL
100     {
101         STANDARD_VM_CHECK;
102         PRECONDITION(CheckPointer(pSecurityControlFlags));
103         PRECONDITION(CheckPointer(pTypeOwner));
104     }
105     CONTRACTL_END;
106
107     *pSecurityControlFlags = DynamicResolver::SkipVisibilityChecks;
108     *pTypeOwner = TypeHandle();
109 }
110
111 ChunkAllocator* ILStubResolver::GetJitMetaHeap()
112 {
113     LIMITED_METHOD_CONTRACT;
114     _ASSERTE(FALSE);
115     return NULL;
116 }
117
118 SigPointer 
119 ILStubResolver::GetLocalSig()
120 {
121     STANDARD_VM_CONTRACT;
122
123     return SigPointer(
124         m_pCompileTimeState->m_ILHeader.LocalVarSig, 
125         m_pCompileTimeState->m_ILHeader.cbLocalVarSig);
126 }
127
128 OBJECTHANDLE ILStubResolver::ConstructStringLiteral(mdToken token)
129 {
130     STANDARD_VM_CONTRACT;
131     _ASSERTE(FALSE);
132     return NULL;
133 }
134
135 BOOL ILStubResolver::IsValidStringRef(mdToken metaTok)
136 {
137     STANDARD_VM_CONTRACT;
138     _ASSERTE(FALSE);
139     return FALSE;
140 }
141
142 void ILStubResolver::ResolveToken(mdToken token, TypeHandle * pTH, MethodDesc ** ppMD, FieldDesc ** ppFD)
143 {        
144     STANDARD_VM_CONTRACT;
145
146     *pTH = NULL;
147     *ppMD = NULL;
148     *ppFD = NULL;
149
150     switch (TypeFromToken(token))
151     {
152     case mdtMethodDef:
153         {
154             MethodDesc* pMD = m_pCompileTimeState->m_tokenLookupMap.LookupMethodDef(token);
155             _ASSERTE(pMD);
156             *ppMD = pMD;
157             *pTH = TypeHandle(pMD->GetMethodTable());
158         }
159         break;
160
161     case mdtTypeDef:
162         {
163             TypeHandle typeHnd = m_pCompileTimeState->m_tokenLookupMap.LookupTypeDef(token);
164             _ASSERTE(!typeHnd.IsNull());
165             *pTH = typeHnd;
166         }
167         break;
168
169     case mdtFieldDef:
170         {
171             FieldDesc* pFD = m_pCompileTimeState->m_tokenLookupMap.LookupFieldDef(token);
172             _ASSERTE(pFD);
173             *ppFD = pFD;
174             *pTH = TypeHandle(pFD->GetEnclosingMethodTable());
175         }
176         break;
177
178     default:
179         UNREACHABLE_MSG("unexpected metadata token type");
180     }
181 }
182
183 //---------------------------------------------------------------------------------------
184 // 
185 SigPointer 
186 ILStubResolver::ResolveSignature(
187     mdToken token)
188 {
189     STANDARD_VM_CONTRACT;
190     CONSISTENCY_CHECK_MSG(token == TOKEN_ILSTUB_TARGET_SIG, "IL stubs do not support any other signature tokens!");
191
192     return m_pCompileTimeState->m_StubTargetMethodSig;
193 }
194
195 //---------------------------------------------------------------------------------------
196 // 
197 SigPointer 
198 ILStubResolver::ResolveSignatureForVarArg(
199     mdToken token)
200 {
201     STANDARD_VM_CONTRACT;
202     _ASSERTE(FALSE);
203     return SigPointer();
204 }
205
206 //---------------------------------------------------------------------------------------
207 // 
208 void ILStubResolver::GetEHInfo(unsigned EHnumber, CORINFO_EH_CLAUSE* clause)
209 {
210     CONTRACTL
211     {
212         STANDARD_VM_CHECK;
213         PRECONDITION(CheckPointer(m_pCompileTimeState));
214         PRECONDITION(CheckPointer(m_pCompileTimeState->m_ILHeader.EH));
215         PRECONDITION(EHnumber < m_pCompileTimeState->m_ILHeader.EH->EHCount());
216     }
217     CONTRACTL_END;
218    
219     COR_ILMETHOD_SECT_EH_CLAUSE_FAT ehClause;
220     const COR_ILMETHOD_SECT_EH_CLAUSE_FAT* ehInfo;
221     ehInfo = (COR_ILMETHOD_SECT_EH_CLAUSE_FAT*)m_pCompileTimeState->m_ILHeader.EH->EHClause(EHnumber, &ehClause);
222     clause->Flags = (CORINFO_EH_CLAUSE_FLAGS)ehInfo->GetFlags();
223     clause->TryOffset = ehInfo->GetTryOffset();
224     clause->TryLength = ehInfo->GetTryLength();
225     clause->HandlerOffset = ehInfo->GetHandlerOffset();
226     clause->HandlerLength = ehInfo->GetHandlerLength();
227     clause->ClassToken = ehInfo->GetClassToken();
228     clause->FilterOffset = ehInfo->GetFilterOffset();
229 }
230
231 bool ILStubResolver::IsNativeToCLRInteropStub()
232 {
233     return (m_type == NativeToCLRInteropStub);
234 }
235
236 void ILStubResolver::SetStubType(ILStubType stubType)
237 {
238     LIMITED_METHOD_CONTRACT;
239     m_type = stubType;
240 }
241
242 void ILStubResolver::SetStubMethodDesc(MethodDesc* pStubMD)
243 {
244     LIMITED_METHOD_CONTRACT;
245     m_pStubMD = PTR_MethodDesc(pStubMD);
246 }
247
248 void ILStubResolver::SetStubTargetMethodDesc(MethodDesc* pStubTargetMD)
249 {
250     LIMITED_METHOD_CONTRACT;
251     m_pStubTargetMD = PTR_MethodDesc(pStubTargetMD);
252 }
253
254
255 //---------------------------------------------------------------------------------------
256 // 
257 void 
258 ILStubResolver::SetStubTargetMethodSig(
259     PCCOR_SIGNATURE pStubTargetMethodSig, 
260     DWORD           cbStubTargetSigLength)
261 {
262     CONTRACTL
263     {
264         STANDARD_VM_CHECK;
265         PRECONDITION(CheckPointer(m_pCompileTimeState));
266     }
267     CONTRACTL_END;
268
269     NewArrayHolder<BYTE> pNewSig = new BYTE[cbStubTargetSigLength];
270     
271     memcpyNoGCRefs((void *)pNewSig, pStubTargetMethodSig, cbStubTargetSigLength);
272     
273     m_pCompileTimeState->m_StubTargetMethodSig = SigPointer(pNewSig, cbStubTargetSigLength);
274     pNewSig.SuppressRelease();
275 }
276
277 //---------------------------------------------------------------------------------------
278 // 
279 MethodDesc * 
280 ILStubResolver::GetStubTargetMethodDesc()
281 {
282     LIMITED_METHOD_CONTRACT;
283     return m_pStubTargetMD;
284 }
285
286 MethodDesc* ILStubResolver::GetStubMethodDesc()
287 {
288     LIMITED_METHOD_CONTRACT;
289     return m_pStubMD;
290 }
291
292 ILStubResolver::ILStubResolver() : 
293     m_pCompileTimeState(dac_cast<PTR_CompileTimeState>(ILNotYetGenerated)),
294     m_pStubMD(dac_cast<PTR_MethodDesc>(nullptr)),
295     m_pStubTargetMD(dac_cast<PTR_MethodDesc>(nullptr)),
296     m_type(Unassigned),
297     m_jitFlags()
298 {
299     LIMITED_METHOD_CONTRACT;
300     
301 }
302
303 //---------------------------------------------------------------------------------------
304 // 
305 COR_ILMETHOD_DECODER * 
306 ILStubResolver::AllocGeneratedIL(
307     size_t cbCode, 
308     DWORD  cbLocalSig, 
309     UINT   maxStack)
310 {
311     STANDARD_VM_CONTRACT;
312
313 #if !defined(DACCESS_COMPILE)
314     _ASSERTE(0 != cbCode);
315
316     NewArrayHolder<BYTE>             pNewILCodeBuffer        = NULL;
317     NewArrayHolder<BYTE>             pNewLocalSig            = NULL;
318     NewArrayHolder<CompileTimeState> pNewCompileTimeState    = NULL;
319
320     pNewCompileTimeState = (CompileTimeState *)new BYTE[sizeof(CompileTimeState)];
321     memset(pNewCompileTimeState, 0, sizeof(CompileTimeState));
322
323     pNewILCodeBuffer = new BYTE[cbCode];
324
325     if (0 != cbLocalSig)
326     {
327         pNewLocalSig = new BYTE[cbLocalSig];
328     }
329
330     COR_ILMETHOD_DECODER* pILHeader = &pNewCompileTimeState->m_ILHeader;    
331
332     pILHeader->Flags         = 0;
333     pILHeader->CodeSize      = (DWORD)cbCode;
334     pILHeader->MaxStack      = maxStack;
335     pILHeader->EH            = 0;
336     pILHeader->Sect          = 0;
337     pILHeader->Code          = pNewILCodeBuffer;
338     pILHeader->LocalVarSig   = pNewLocalSig;
339     pILHeader->cbLocalVarSig = cbLocalSig;
340
341 #ifdef _DEBUG
342     LPVOID pPrevCompileTimeState =
343 #endif // _DEBUG
344     FastInterlockExchangePointer(&m_pCompileTimeState, pNewCompileTimeState.GetValue());
345     CONSISTENCY_CHECK(ILNotYetGenerated == (UINT_PTR)pPrevCompileTimeState);
346
347     pNewLocalSig.SuppressRelease();
348     pNewILCodeBuffer.SuppressRelease();
349     pNewCompileTimeState.SuppressRelease();
350
351     return pILHeader;
352
353 #else  // DACCESS_COMPILE
354     DacNotImpl();
355     return NULL;
356
357 #endif // DACCESS_COMPILE
358 } // ILStubResolver::AllocGeneratedIL
359
360 //---------------------------------------------------------------------------------------
361 // 
362 COR_ILMETHOD_DECODER* ILStubResolver::GetILHeader()
363 {
364     CONTRACTL
365     {
366         MODE_ANY;
367         THROWS;
368         GC_NOTRIGGER;
369         PRECONDITION(CheckPointer(m_pCompileTimeState));
370     }
371     CONTRACTL_END;
372
373     return &m_pCompileTimeState->m_ILHeader;
374 }
375
376 COR_ILMETHOD_SECT_EH* ILStubResolver::AllocEHSect(size_t nClauses)
377 {
378     STANDARD_VM_CONTRACT;
379
380     if (nClauses >= 1)
381     {
382         size_t cbSize = sizeof(COR_ILMETHOD_SECT_EH)
383                         - sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT)
384                         + (nClauses * sizeof(IMAGE_COR_ILMETHOD_SECT_EH_CLAUSE_FAT));
385         m_pCompileTimeState->m_pEHSect = (COR_ILMETHOD_SECT_EH*) new BYTE[cbSize];
386         CONSISTENCY_CHECK(NULL == m_pCompileTimeState->m_ILHeader.EH);
387         m_pCompileTimeState->m_ILHeader.EH = m_pCompileTimeState->m_pEHSect;
388         return m_pCompileTimeState->m_pEHSect;
389     }
390     else
391     {
392         return NULL;
393     }
394 }
395
396
397 void ILStubResolver::FreeCompileTimeState()
398 {
399     CONTRACTL
400     {
401         NOTHROW;
402         GC_NOTRIGGER;
403         MODE_ANY;
404     }
405     CONTRACTL_END;
406
407     if ((ILNotYetGenerated == dac_cast<TADDR>(m_pCompileTimeState)) || 
408         (ILGeneratedAndFreed == dac_cast<TADDR>(m_pCompileTimeState)))
409     {
410         return;
411     }
412
413     ClearCompileTimeState(ILGeneratedAndFreed);
414 }
415
416 //---------------------------------------------------------------------------------------
417 // 
418 void 
419 ILStubResolver::ClearCompileTimeState(CompileTimeStatePtrSpecialValues newState)
420 {
421     CONTRACTL
422     {
423         NOTHROW;
424         GC_NOTRIGGER;
425         MODE_ANY;
426     }
427     CONTRACTL_END;
428
429     //
430     // See allocations in AllocGeneratedIL and SetStubTargetMethodSig
431     //
432     
433     COR_ILMETHOD_DECODER * pILHeader = &m_pCompileTimeState->m_ILHeader;    
434
435     CONSISTENCY_CHECK(NULL != pILHeader->Code);
436     delete[] pILHeader->Code;
437
438     if (NULL != pILHeader->LocalVarSig)
439     {
440         delete[] pILHeader->LocalVarSig;
441     }
442
443     if (!m_pCompileTimeState->m_StubTargetMethodSig.IsNull())
444     {
445         delete[] m_pCompileTimeState->m_StubTargetMethodSig.GetPtr();
446     }
447
448     if (NULL != m_pCompileTimeState->m_pEHSect)
449     {
450         delete[] m_pCompileTimeState->m_pEHSect;
451     }
452
453     delete m_pCompileTimeState;
454
455     FastInterlockExchangePointer(&m_pCompileTimeState, dac_cast<PTR_CompileTimeState>((TADDR)newState));
456 } // ILStubResolver::ClearCompileTimeState
457
458 //---------------------------------------------------------------------------------------
459 // 
460 void 
461 ILStubResolver::SetTokenLookupMap(
462     TokenLookupMap * pMap)
463 {
464     CONTRACTL
465     {
466         STANDARD_VM_CHECK;
467         PRECONDITION(CheckPointer(m_pCompileTimeState));
468     }
469     CONTRACTL_END;
470
471     // run copy ctor
472     new (&m_pCompileTimeState->m_tokenLookupMap) TokenLookupMap(pMap);
473 }
474
475 bool ILStubResolver::IsCompiled()
476 {
477     LIMITED_METHOD_CONTRACT;
478     return (dac_cast<TADDR>(m_pCompileTimeState) == ILGeneratedAndFreed);
479 }
480
481 bool ILStubResolver::IsILGenerated()
482 {
483     return (dac_cast<TADDR>(m_pCompileTimeState) != ILNotYetGenerated);
484 }
485
486 void ILStubResolver::SetJitFlags(CORJIT_FLAGS jitFlags)
487 {
488     LIMITED_METHOD_CONTRACT;
489     m_jitFlags = jitFlags;
490 }
491
492 CORJIT_FLAGS ILStubResolver::GetJitFlags()
493 {
494     LIMITED_METHOD_CONTRACT;
495     return m_jitFlags;
496 }
497
498 // static
499 void ILStubResolver::StubGenFailed(ILStubResolver* pResolver)
500 {
501     CONTRACTL
502     {
503         NOTHROW;
504         GC_NOTRIGGER;
505         MODE_ANY;
506     }
507     CONTRACTL_END;
508
509     if ((ILNotYetGenerated == dac_cast<TADDR>(pResolver->m_pCompileTimeState)) || 
510         (ILGeneratedAndFreed == dac_cast<TADDR>(pResolver->m_pCompileTimeState)))
511     {
512         return;
513     }
514
515     pResolver->ClearCompileTimeState(ILNotYetGenerated);
516 }