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: zapsig.cpp |
6 | // |
7 | // Signature encoding for zapper (ngen) |
8 | // |
9 | |
10 | // =========================================================================== |
11 | |
12 | |
13 | #include "common.h" |
14 | #ifdef FEATURE_PREJIT |
15 | #include "zapsig.h" |
16 | #include "typedesc.h" |
17 | #include "compile.h" |
18 | #include "sigbuilder.h" |
19 | |
20 | #ifndef DACCESS_COMPILE |
21 | |
22 | BOOL ZapSig::GetSignatureForTypeDesc(TypeDesc * desc, SigBuilder * pSigBuilder) |
23 | { |
24 | CONTRACTL |
25 | { |
26 | THROWS; |
27 | GC_TRIGGERS; |
28 | } |
29 | CONTRACTL_END |
30 | |
31 | CorElementType elemType = desc->GetInternalCorElementType(); |
32 | |
33 | if (elemType == ELEMENT_TYPE_VALUETYPE) |
34 | { |
35 | // convert to ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG so that the right |
36 | // thing will happen in code:SigPointer.GetTypeHandleThrowing |
37 | elemType = (CorElementType) ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG; |
38 | } |
39 | else if (elemType == ELEMENT_TYPE_VAR || elemType == ELEMENT_TYPE_MVAR) |
40 | { |
41 | // Enable encoding of type variables for NGen signature only. IBC toolchain is not aware of them yet. |
42 | if (context.externalTokens == ZapSig::NormalTokens) |
43 | elemType = (CorElementType) ELEMENT_TYPE_VAR_ZAPSIG; |
44 | } |
45 | |
46 | pSigBuilder->AppendElementType(elemType); |
47 | |
48 | if (desc->HasTypeParam()) |
49 | { |
50 | if (!this->GetSignatureForTypeHandle(desc->GetTypeParam(), pSigBuilder)) |
51 | return FALSE; |
52 | |
53 | if (elemType == ELEMENT_TYPE_ARRAY) |
54 | { |
55 | ArrayTypeDesc *pArrayDesc = dac_cast<PTR_ArrayTypeDesc>(desc); |
56 | _ASSERTE(pArrayDesc->GetRank() != 0); |
57 | pSigBuilder->AppendData(pArrayDesc->GetRank()); |
58 | pSigBuilder->AppendData(0); |
59 | pSigBuilder->AppendData(0); |
60 | } |
61 | } |
62 | else |
63 | { |
64 | switch ((DWORD)elemType) |
65 | { |
66 | case ELEMENT_TYPE_FNPTR: |
67 | { |
68 | FnPtrTypeDesc *pTD = dac_cast<PTR_FnPtrTypeDesc>(desc); |
69 | |
70 | // Emit calling convention |
71 | pSigBuilder->AppendByte(pTD->GetCallConv()); |
72 | |
73 | // number of args |
74 | unsigned numArgs = pTD->GetNumArgs(); |
75 | pSigBuilder->AppendData(numArgs); |
76 | |
77 | // return type and args |
78 | TypeHandle *retAndArgTypes = pTD->GetRetAndArgTypesPointer(); |
79 | for (DWORD i = 0; i <= numArgs; i++) |
80 | { |
81 | TypeHandle th = retAndArgTypes[i]; |
82 | // This should be a consequence of the type key being restored |
83 | CONSISTENCY_CHECK(!th.IsNull() && !th.IsEncodedFixup()); |
84 | if (!this->GetSignatureForTypeHandle(th, pSigBuilder)) |
85 | return FALSE; |
86 | } |
87 | } |
88 | break; |
89 | |
90 | case ELEMENT_TYPE_MVAR: |
91 | // _ASSERTE(!"Cannot encode ET_MVAR in a ZapSig"); |
92 | return FALSE; |
93 | |
94 | case ELEMENT_TYPE_VAR: |
95 | // _ASSERTE(!"Cannot encode ET_VAR in a ZapSig"); |
96 | return FALSE; |
97 | |
98 | case ELEMENT_TYPE_VAR_ZAPSIG: |
99 | { |
100 | TypeVarTypeDesc * pTypeVarDesc = dac_cast<PTR_TypeVarTypeDesc>(desc); |
101 | Module * pVarTypeModule = pTypeVarDesc->GetModule(); |
102 | if (pVarTypeModule != this->context.pInfoModule) |
103 | { |
104 | DWORD index = (*this->pfnEncodeModule)(this->context.pModuleContext, pVarTypeModule); |
105 | |
106 | if (index == ENCODE_MODULE_FAILED) |
107 | return FALSE; |
108 | |
109 | // emit the ET_MODULE_ZAPSIG escape |
110 | pSigBuilder->AppendElementType((CorElementType) ELEMENT_TYPE_MODULE_ZAPSIG); |
111 | // emit the module index |
112 | pSigBuilder->AppendData(index); |
113 | } |
114 | pSigBuilder->AppendData(RidFromToken(pTypeVarDesc->GetToken())); |
115 | break; |
116 | } |
117 | |
118 | default: |
119 | _ASSERTE(!"Bad type" ); |
120 | return FALSE; |
121 | } |
122 | } |
123 | |
124 | return TRUE; |
125 | } |
126 | |
127 | |
128 | // Create a signature for a typeHandle |
129 | // It can be decoded using MetaSig::GetTypeHandleThrowing |
130 | // The tokens are espressed relative to this->pInfoModule |
131 | // When handle.GetModule() != this->pInfoModule), we escape the signature |
132 | // with an ELEMENT_TYPE_MODULE_ZAPSIG <id-num> <token> to encode |
133 | // a temporary change of module |
134 | // |
135 | // Returns the number of characters written into the buffer. |
136 | // If buffer and bufferMax are NULL, it returns the number of |
137 | // characters that would have been written. |
138 | // If the buffer isn't big enough it doesn't write past bufferMax |
139 | // A return value of 0 indidates a failure to encode the signature |
140 | // |
141 | BOOL ZapSig::GetSignatureForTypeHandle(TypeHandle handle, |
142 | SigBuilder * pSigBuilder) |
143 | { |
144 | CONTRACTL |
145 | { |
146 | THROWS; |
147 | GC_TRIGGERS; |
148 | |
149 | PRECONDITION(CheckPointer(handle)); |
150 | PRECONDITION(CheckPointer(this->context.pInfoModule)); |
151 | PRECONDITION(!handle.HasUnrestoredTypeKey()); |
152 | MODE_ANY; |
153 | } |
154 | CONTRACTL_END |
155 | |
156 | if (handle.IsTypeDesc()) |
157 | return GetSignatureForTypeDesc(handle.AsTypeDesc(), pSigBuilder); |
158 | |
159 | MethodTable *pMT = handle.AsMethodTable(); |
160 | |
161 | // Can we encode the type using a short ET encoding? |
162 | // |
163 | CorElementType elemType = TryEncodeUsingShortcut(pMT); |
164 | if (elemType != ELEMENT_TYPE_END) |
165 | { |
166 | _ASSERTE(pMT->IsTypicalTypeDefinition()); |
167 | |
168 | // Check for an array type and encode that we are dealing with a MethodTable representation |
169 | if (elemType == ELEMENT_TYPE_SZARRAY || elemType == ELEMENT_TYPE_ARRAY) |
170 | { |
171 | pSigBuilder->AppendElementType((CorElementType)ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG); |
172 | pSigBuilder->AppendElementType(elemType); |
173 | |
174 | TypeHandle elementType = pMT->GetApproxArrayElementTypeHandle(); |
175 | if (!this->GetSignatureForTypeHandle(elementType, pSigBuilder)) |
176 | return FALSE; |
177 | |
178 | if (elemType == ELEMENT_TYPE_ARRAY) |
179 | { |
180 | pSigBuilder->AppendData(pMT->GetRank()); |
181 | pSigBuilder->AppendData(0); |
182 | pSigBuilder->AppendData(0); |
183 | } |
184 | } |
185 | else |
186 | { |
187 | pSigBuilder->AppendElementType(elemType); |
188 | } |
189 | |
190 | return TRUE; |
191 | } |
192 | |
193 | // We could not encode the type using a short encoding |
194 | // and we have a handle that represents a Class or ValueType |
195 | |
196 | // We may need to emit an out-of-module escape sequence |
197 | // |
198 | Module *pTypeHandleModule = pMT->GetModule_NoLogging(); |
199 | |
200 | // If the type handle's module is different that the this->pInfoModule |
201 | // we will need to add an out-of-module escape for the type |
202 | // |
203 | DWORD index = 0; |
204 | mdToken token = pMT->GetCl_NoLogging(); |
205 | #ifdef FEATURE_NATIVE_IMAGE_GENERATION |
206 | if (pTypeHandleModule != this->context.pInfoModule && !pTypeHandleModule->IsInCurrentVersionBubble()) |
207 | { |
208 | pTypeHandleModule = GetAppDomain()->ToCompilationDomain()->GetTargetModule(); |
209 | token = pTypeHandleModule->LookupTypeRefByMethodTable(pMT); |
210 | } |
211 | #endif |
212 | if (pTypeHandleModule != this->context.pInfoModule) |
213 | { |
214 | // During IBC profiling this calls |
215 | // code:Module.EncodeModuleHelper |
216 | // During ngen this calls |
217 | // code:ZapImportTable.EncodeModuleHelper) |
218 | // |
219 | index = (*this->pfnEncodeModule)(this->context.pModuleContext, pTypeHandleModule); |
220 | |
221 | if (index == ENCODE_MODULE_FAILED) |
222 | return FALSE; |
223 | |
224 | // emit the ET_MODULE_ZAPSIG escape |
225 | pSigBuilder->AppendElementType((CorElementType) ELEMENT_TYPE_MODULE_ZAPSIG); |
226 | // emit the module index |
227 | pSigBuilder->AppendData(index); |
228 | } |
229 | |
230 | // Remember if we have an instantiated generic type |
231 | bool fNeedsInstantiation = pMT->HasInstantiation() && !pMT->IsGenericTypeDefinition(); |
232 | |
233 | // We possibly have an instantiated generic type |
234 | if (fNeedsInstantiation) |
235 | { |
236 | pSigBuilder->AppendElementType(ELEMENT_TYPE_GENERICINST); |
237 | } |
238 | |
239 | // Beware of enums! Can't use GetInternalCorElementType() here. |
240 | pSigBuilder->AppendElementType(pMT->IsValueType() ? ELEMENT_TYPE_VALUETYPE : ELEMENT_TYPE_CLASS); |
241 | |
242 | _ASSERTE(!IsNilToken(token)); |
243 | if (IsNilToken(token)) |
244 | return FALSE; |
245 | |
246 | if ((index != 0) && (this->pfnTokenDefinition != NULL)) |
247 | { |
248 | // |
249 | // We do not want to log the metadata lookups that we perform here |
250 | // |
251 | IBCLoggingDisabler disableLogging; |
252 | |
253 | // During IBC profiling this calls |
254 | // code:Module::TokenDefinitionHelper |
255 | (*this->pfnTokenDefinition)(this->context.pModuleContext, pTypeHandleModule, index, &token); |
256 | |
257 | // ibcExternalType tokens are actually encoded as mdtTypeDef tokens in the signature |
258 | _ASSERT(TypeFromToken(token) == ibcExternalType); |
259 | token = TokenFromRid(RidFromToken(token), mdtTypeDef); |
260 | } |
261 | |
262 | pSigBuilder->AppendToken(token); |
263 | |
264 | if (fNeedsInstantiation) |
265 | { |
266 | pSigBuilder->AppendData(pMT->GetNumGenericArgs()); |
267 | Instantiation inst = pMT->GetInstantiation(); |
268 | for (DWORD i = 0; i < inst.GetNumArgs(); i++) |
269 | { |
270 | TypeHandle t = inst[i]; |
271 | CONSISTENCY_CHECK(!t.IsNull() && !t.IsEncodedFixup()); |
272 | if (!this->GetSignatureForTypeHandle(t, pSigBuilder)) |
273 | return FALSE; |
274 | } |
275 | } |
276 | return TRUE; |
277 | } |
278 | |
279 | #endif // #ifndef DACCESS_COMPILE |
280 | |
281 | // |
282 | // Returns element type when the typeHandle can be encoded using |
283 | // using a single CorElementType value |
284 | // This includes using ELEMENT_TYPE_CANON_ZAPSIG for the System.__Canon type |
285 | // |
286 | /*static */ CorElementType ZapSig::TryEncodeUsingShortcut(/* in */ MethodTable * pMT) |
287 | { |
288 | LIMITED_METHOD_CONTRACT; |
289 | |
290 | CorElementType elemType = ELEMENT_TYPE_END; // An illegal value that we check for later |
291 | |
292 | // Set elemType to a shortcut encoding whenever possible |
293 | // |
294 | if (pMT->IsTruePrimitive()) |
295 | elemType = pMT->GetInternalCorElementType(); |
296 | else if (pMT == g_pObjectClass) |
297 | elemType = ELEMENT_TYPE_OBJECT; |
298 | else if (pMT == g_pStringClass) |
299 | elemType = ELEMENT_TYPE_STRING; |
300 | else if (pMT == g_pCanonMethodTableClass) |
301 | elemType = (CorElementType) ELEMENT_TYPE_CANON_ZAPSIG; |
302 | else if (pMT->IsArray()) |
303 | elemType = pMT->GetInternalCorElementType(); // either ELEMENT_TYPE_SZARRAY or ELEMENT_TYPE_ARRAY |
304 | |
305 | return elemType; |
306 | } |
307 | |
308 | // |
309 | // Compare a metadata signature element with a type handle |
310 | // The type handle must have a fully restored type key, which in turn means that modules for all of its |
311 | // components are loaded (e.g. type arguments to an instantiated type). |
312 | // |
313 | // Hence we can do the signature comparison without incurring any loads or restores. |
314 | // |
315 | /*static*/ BOOL ZapSig::CompareSignatureToTypeHandle(PCCOR_SIGNATURE pSig, |
316 | Module* pModule, |
317 | TypeHandle handle, |
318 | const ZapSig::Context * pZapSigContext) |
319 | { |
320 | CONTRACT(BOOL) |
321 | { |
322 | NOTHROW; |
323 | GC_NOTRIGGER; |
324 | MODE_ANY; |
325 | FORBID_FAULT; |
326 | PRECONDITION(CheckPointer(pModule)); |
327 | PRECONDITION(CheckPointer(pZapSigContext)); |
328 | PRECONDITION(CheckPointer(pZapSigContext->pModuleContext)); |
329 | PRECONDITION(CheckPointer(pZapSigContext->pInfoModule)); |
330 | PRECONDITION(CheckPointer(handle)); |
331 | PRECONDITION(CheckPointer(pSig)); |
332 | PRECONDITION(!handle.HasUnrestoredTypeKey()); |
333 | } |
334 | CONTRACT_END |
335 | |
336 | mdToken tk; |
337 | |
338 | // |
339 | // pOrigModule is the original module that contained this ZapSig |
340 | // |
341 | Module * pOrigModule = pZapSigContext->pInfoModule; |
342 | CorElementType sigType = CorSigUncompressElementType(pSig); |
343 | CorElementType handleType = handle.GetSignatureCorElementType(); |
344 | |
345 | switch ((DWORD)sigType) |
346 | { |
347 | default: |
348 | { |
349 | // Unknown type! |
350 | _ASSERTE(!"Unknown type in ZapSig::CompareSignatureToTypeHandle" ); |
351 | RETURN(FALSE); |
352 | } |
353 | |
354 | case ELEMENT_TYPE_MODULE_ZAPSIG: |
355 | { |
356 | DWORD ix = CorSigUncompressData(pSig); |
357 | CONTRACT_VIOLATION(ThrowsViolation|GCViolation); |
358 | pModule = pZapSigContext->GetZapSigModule()->GetModuleFromIndexIfLoaded(ix); |
359 | if (pModule == NULL) |
360 | RETURN FALSE; |
361 | else |
362 | RETURN(CompareSignatureToTypeHandle(pSig, pModule, handle, pZapSigContext)); |
363 | } |
364 | |
365 | case ELEMENT_TYPE_U: |
366 | case ELEMENT_TYPE_I: |
367 | case ELEMENT_TYPE_VOID: |
368 | case ELEMENT_TYPE_I1: |
369 | case ELEMENT_TYPE_U1: |
370 | case ELEMENT_TYPE_I2: |
371 | case ELEMENT_TYPE_U2: |
372 | case ELEMENT_TYPE_I4: |
373 | case ELEMENT_TYPE_U4: |
374 | case ELEMENT_TYPE_I8: |
375 | case ELEMENT_TYPE_U8: |
376 | case ELEMENT_TYPE_R4: |
377 | case ELEMENT_TYPE_R8: |
378 | case ELEMENT_TYPE_BOOLEAN: |
379 | case ELEMENT_TYPE_CHAR: |
380 | case ELEMENT_TYPE_TYPEDBYREF: |
381 | RETURN(sigType == handleType); |
382 | |
383 | case ELEMENT_TYPE_STRING: |
384 | RETURN(handle == TypeHandle(g_pStringClass)); |
385 | |
386 | case ELEMENT_TYPE_OBJECT: |
387 | RETURN(handle == TypeHandle(g_pObjectClass)); |
388 | |
389 | case ELEMENT_TYPE_CANON_ZAPSIG: |
390 | RETURN(handle == TypeHandle(g_pCanonMethodTableClass)); |
391 | |
392 | case ELEMENT_TYPE_VAR: |
393 | case ELEMENT_TYPE_MVAR: |
394 | { |
395 | if (sigType != handleType) |
396 | RETURN(FALSE); |
397 | |
398 | unsigned varNum = CorSigUncompressData(pSig); |
399 | RETURN(varNum == (dac_cast<PTR_TypeVarTypeDesc>(handle.AsTypeDesc())->GetIndex())); |
400 | } |
401 | |
402 | case ELEMENT_TYPE_VAR_ZAPSIG: |
403 | { |
404 | if (!handle.IsGenericVariable()) |
405 | RETURN(FALSE); |
406 | |
407 | TypeVarTypeDesc *pTypeVarTypeDesc = handle.AsGenericVariable(); |
408 | |
409 | unsigned rid = CorSigUncompressData(pSig); |
410 | RETURN(TokenFromRid(rid, mdtGenericParam) == pTypeVarTypeDesc->GetToken() && pModule == pTypeVarTypeDesc->GetModule()); |
411 | } |
412 | |
413 | // These take an additional argument, which is the element type |
414 | case ELEMENT_TYPE_SZARRAY: |
415 | case ELEMENT_TYPE_PTR: |
416 | case ELEMENT_TYPE_BYREF: |
417 | { |
418 | if (sigType != handleType) |
419 | RETURN(FALSE); |
420 | |
421 | RETURN (CompareSignatureToTypeHandle(pSig, pModule, handle.GetTypeParam(), pZapSigContext)); |
422 | } |
423 | |
424 | case ELEMENT_TYPE_NATIVE_ARRAY_TEMPLATE_ZAPSIG: |
425 | { |
426 | if (handle.IsTypeDesc() || !handle.AsMethodTable()->IsArray()) |
427 | RETURN(FALSE); |
428 | |
429 | RETURN (CompareSignatureToTypeHandle(pSig, pModule, handle, pZapSigContext)); |
430 | } |
431 | |
432 | case ELEMENT_TYPE_NATIVE_VALUETYPE_ZAPSIG: |
433 | { |
434 | sigType = CorSigUncompressElementType(pSig); |
435 | _ASSERTE(sigType == ELEMENT_TYPE_VALUETYPE); |
436 | |
437 | if (!handle.IsNativeValueType()) RETURN(FALSE); |
438 | } // fall-through |
439 | |
440 | case ELEMENT_TYPE_VALUETYPE: |
441 | case ELEMENT_TYPE_CLASS: |
442 | { |
443 | CorSigUncompressToken(pSig, &tk); |
444 | if (TypeFromToken(tk) == mdtTypeRef) |
445 | { |
446 | BOOL resolved = FALSE; |
447 | EX_TRY |
448 | { |
449 | ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE(); |
450 | resolved = ClassLoader::ResolveTokenToTypeDefThrowing(pModule, tk, &pModule, &tk, Loader::DontLoad); |
451 | } |
452 | EX_CATCH |
453 | { |
454 | } |
455 | EX_END_CATCH(SwallowAllExceptions); |
456 | if (!resolved) |
457 | RETURN(FALSE); |
458 | } |
459 | _ASSERTE(TypeFromToken(tk) == mdtTypeDef); |
460 | RETURN (sigType == handleType && !handle.HasInstantiation() && pModule == handle.GetModule() && handle.GetCl() == tk); |
461 | } |
462 | |
463 | case ELEMENT_TYPE_FNPTR: |
464 | { |
465 | if (sigType != handleType) |
466 | RETURN(FALSE); |
467 | |
468 | FnPtrTypeDesc *pTD = handle.AsFnPtrType(); |
469 | DWORD callConv = CorSigUncompressData(pSig); |
470 | if (callConv != pTD->GetCallConv()) |
471 | RETURN(FALSE); |
472 | |
473 | DWORD numArgs = CorSigUncompressData(pSig); |
474 | if (numArgs != pTD->GetNumArgs()) |
475 | RETURN(FALSE); |
476 | |
477 | { |
478 | CONTRACT_VIOLATION(ThrowsViolation|GCViolation); |
479 | |
480 | for (DWORD i = 0; i <= numArgs; i++) |
481 | { |
482 | SigPointer sp(pSig); |
483 | if (!CompareSignatureToTypeHandle(pSig, pOrigModule, pTD->GetRetAndArgTypes()[i], pZapSigContext)) |
484 | RETURN(FALSE); |
485 | if (FAILED(sp.SkipExactlyOne())) |
486 | { |
487 | RETURN(FALSE); |
488 | } |
489 | pSig = sp.GetPtr(); |
490 | } |
491 | } |
492 | break; |
493 | } |
494 | |
495 | case ELEMENT_TYPE_GENERICINST: |
496 | { |
497 | if (!handle.HasInstantiation()) |
498 | RETURN(FALSE); |
499 | |
500 | sigType = CorSigUncompressElementType(pSig); |
501 | if (sigType != handleType) |
502 | RETURN(FALSE); |
503 | |
504 | pSig += CorSigUncompressToken(pSig, &tk); |
505 | if (TypeFromToken(tk) == mdtTypeRef) |
506 | { |
507 | BOOL resolved = FALSE; |
508 | EX_TRY |
509 | { |
510 | ENABLE_FORBID_GC_LOADER_USE_IN_THIS_SCOPE(); |
511 | resolved = ClassLoader::ResolveTokenToTypeDefThrowing(pModule, tk, &pModule, &tk, Loader::DontLoad); |
512 | } |
513 | EX_CATCH |
514 | { |
515 | } |
516 | EX_END_CATCH(SwallowAllExceptions); |
517 | if (!resolved) |
518 | RETURN(FALSE); |
519 | } |
520 | _ASSERTE(TypeFromToken(tk) == mdtTypeDef); |
521 | if (pModule != handle.GetModule() || tk != handle.GetCl()) |
522 | RETURN(FALSE); |
523 | |
524 | DWORD numGenericArgs = CorSigUncompressData(pSig); |
525 | |
526 | if (numGenericArgs != handle.GetNumGenericArgs()) |
527 | RETURN(FALSE); |
528 | |
529 | Instantiation inst = handle.GetInstantiation(); |
530 | for (DWORD i = 0; i < inst.GetNumArgs(); i++) |
531 | { |
532 | SigPointer sp(pSig); |
533 | if (!CompareSignatureToTypeHandle(pSig, pOrigModule, inst[i], pZapSigContext)) |
534 | RETURN(FALSE); |
535 | if (FAILED(sp.SkipExactlyOne())) |
536 | { |
537 | RETURN(FALSE); |
538 | } |
539 | pSig = sp.GetPtr(); |
540 | } |
541 | break; |
542 | } |
543 | |
544 | case ELEMENT_TYPE_ARRAY: |
545 | { |
546 | if (sigType != handleType) |
547 | RETURN(FALSE); |
548 | |
549 | if (!CompareSignatureToTypeHandle(pSig, pModule, handle.GetTypeParam(), pZapSigContext)) |
550 | RETURN(FALSE); |
551 | SigPointer sp(pSig); |
552 | if (FAILED(sp.SkipExactlyOne())) |
553 | RETURN(FALSE); |
554 | |
555 | DWORD rank; |
556 | if (FAILED(sp.GetData(&rank))) |
557 | RETURN(FALSE); |
558 | |
559 | if (rank != handle.AsArray()->GetRank()) |
560 | RETURN(FALSE); |
561 | |
562 | break; |
563 | } |
564 | } |
565 | |
566 | RETURN(TRUE); |
567 | } |
568 | |
569 | /*static*/ |
570 | BOOL ZapSig::CompareFixupToTypeHandle(Module * pModule, TADDR fixup, TypeHandle handle) |
571 | { |
572 | CONTRACTL |
573 | { |
574 | NOTHROW; |
575 | GC_NOTRIGGER; |
576 | MODE_ANY; |
577 | FORBID_FAULT; |
578 | PRECONDITION(CORCOMPILE_IS_POINTER_TAGGED(fixup)); |
579 | PRECONDITION(CheckPointer(pModule)); |
580 | } |
581 | CONTRACTL_END |
582 | |
583 | Module *pDefiningModule; |
584 | PCCOR_SIGNATURE pSig = pModule->GetEncodedSigIfLoaded(CORCOMPILE_UNTAG_TOKEN(fixup), &pDefiningModule); |
585 | if (pDefiningModule == NULL) |
586 | return FALSE; |
587 | |
588 | ZapSig::Context zapSigContext(pDefiningModule, pModule); |
589 | return ZapSig::CompareSignatureToTypeHandle(pSig, pDefiningModule, handle, &zapSigContext); |
590 | } |
591 | |
592 | /*static*/ |
593 | BOOL ZapSig::CompareTypeHandleFieldToTypeHandle(TypeHandle *pTypeHnd, TypeHandle typeHnd2) |
594 | { |
595 | CONTRACTL |
596 | { |
597 | NOTHROW; |
598 | GC_NOTRIGGER; |
599 | MODE_ANY; |
600 | FORBID_FAULT; |
601 | PRECONDITION(CheckPointer(pTypeHnd)); |
602 | PRECONDITION(CheckPointer(typeHnd2)); |
603 | PRECONDITION(!CORCOMPILE_IS_POINTER_TAGGED((SIZE_T) typeHnd2.AsPtr())); |
604 | } |
605 | CONTRACTL_END |
606 | |
607 | // Ensure that the compiler won't fetch the value twice |
608 | SIZE_T fixup = VolatileLoadWithoutBarrier((SIZE_T *)pTypeHnd); |
609 | |
610 | if (CORCOMPILE_IS_POINTER_TAGGED(fixup)) |
611 | { |
612 | Module *pContainingModule = ExecutionManager::FindZapModule(dac_cast<TADDR>(pTypeHnd)); |
613 | CONSISTENCY_CHECK(pContainingModule != NULL); |
614 | |
615 | Module *pDefiningModule; |
616 | PCCOR_SIGNATURE pSig = pContainingModule->GetEncodedSigIfLoaded(CORCOMPILE_UNTAG_TOKEN(fixup), &pDefiningModule); |
617 | if (pDefiningModule == NULL) |
618 | return FALSE; |
619 | else |
620 | { |
621 | ZapSig::Context zapSigContext(pDefiningModule, pContainingModule); |
622 | ZapSig::Context * pZapSigContext = &zapSigContext; |
623 | return CompareSignatureToTypeHandle(pSig, pDefiningModule, typeHnd2, pZapSigContext); |
624 | } |
625 | } |
626 | else |
627 | return TypeHandle::FromTAddr(fixup) == typeHnd2; |
628 | } |
629 | |
630 | #ifndef DACCESS_COMPILE |
631 | Module *ZapSig::DecodeModuleFromIndex(Module *fromModule, |
632 | DWORD index) |
633 | { |
634 | CONTRACTL |
635 | { |
636 | THROWS; |
637 | GC_TRIGGERS; |
638 | MODE_ANY; |
639 | } |
640 | CONTRACTL_END; |
641 | |
642 | Assembly *pAssembly = NULL; |
643 | |
644 | if (index == 0) |
645 | { |
646 | pAssembly = fromModule->GetAssembly(); |
647 | } |
648 | else |
649 | { |
650 | if (index < fromModule->GetAssemblyRefMax()) |
651 | { |
652 | pAssembly = fromModule->LoadAssembly(GetAppDomain(), RidToToken(index, mdtAssemblyRef))->GetAssembly(); |
653 | } |
654 | else |
655 | { |
656 | index -= fromModule->GetAssemblyRefMax(); |
657 | |
658 | pAssembly = fromModule->GetNativeMetadataAssemblyRefFromCache(index); |
659 | |
660 | if(pAssembly == NULL) |
661 | { |
662 | AssemblySpec spec; |
663 | spec.InitializeSpec(TokenFromRid(index, mdtAssemblyRef), |
664 | fromModule->GetNativeAssemblyImport(), |
665 | NULL); |
666 | |
667 | pAssembly = spec.LoadAssembly(FILE_LOADED); |
668 | |
669 | fromModule->SetNativeMetadataAssemblyRefInCache(index, pAssembly); |
670 | } |
671 | } |
672 | } |
673 | |
674 | return pAssembly->GetManifestModule(); |
675 | } |
676 | |
677 | Module *ZapSig::DecodeModuleFromIndexIfLoaded(Module *fromModule, |
678 | DWORD index) |
679 | { |
680 | CONTRACTL |
681 | { |
682 | NOTHROW; |
683 | GC_NOTRIGGER; |
684 | FORBID_FAULT; |
685 | SO_INTOLERANT; |
686 | } |
687 | CONTRACTL_END; |
688 | |
689 | Assembly *pAssembly = NULL; |
690 | mdAssemblyRef tkAssemblyRef; |
691 | |
692 | if (index == 0) |
693 | pAssembly = fromModule->GetAssembly(); |
694 | else |
695 | { |
696 | if (index < fromModule->GetAssemblyRefMax()) |
697 | { |
698 | tkAssemblyRef = RidToToken(index, mdtAssemblyRef); |
699 | pAssembly = fromModule->GetAssemblyIfLoaded(tkAssemblyRef); |
700 | } |
701 | else |
702 | { |
703 | index -= fromModule->GetAssemblyRefMax(); |
704 | tkAssemblyRef = RidToToken(index, mdtAssemblyRef); |
705 | IMDInternalImport * pMDImportOverride = fromModule->GetNativeAssemblyImport(FALSE); |
706 | if (pMDImportOverride != NULL) |
707 | { |
708 | CHAR szFullName[MAX_CLASS_NAME + 1]; |
709 | LPCSTR szWinRtNamespace = NULL; |
710 | LPCSTR szWinRtClassName = NULL; |
711 | |
712 | BOOL fValidAssemblyRef = TRUE; |
713 | LPCSTR pAssemblyName; |
714 | DWORD dwFlags; |
715 | if (FAILED(pMDImportOverride->GetAssemblyRefProps(tkAssemblyRef, |
716 | NULL, |
717 | NULL, |
718 | &pAssemblyName, |
719 | NULL, |
720 | NULL, |
721 | NULL, |
722 | &dwFlags))) |
723 | { // Unexpected failure reading MetaData |
724 | fValidAssemblyRef = FALSE; |
725 | } |
726 | |
727 | if (fValidAssemblyRef && IsAfContentType_WindowsRuntime(dwFlags)) |
728 | { |
729 | // Find the encoded type name |
730 | LPCSTR pTypeName = NULL; |
731 | if (pAssemblyName != NULL) |
732 | pTypeName = strchr(pAssemblyName, '!'); |
733 | |
734 | if (pTypeName != NULL) |
735 | { |
736 | pTypeName++; |
737 | // pTypeName now contains the full type name (namespace + name) |
738 | |
739 | strcpy_s(szFullName, _countof(szFullName), pTypeName); |
740 | LPSTR pszName = strrchr(szFullName, '.'); |
741 | |
742 | // WinRT types must have a namespace |
743 | if (pszName != NULL) |
744 | { |
745 | // Replace . between namespace and name with null terminator. |
746 | // This breaks the string into a namespace and name pair. |
747 | *pszName = '\0'; |
748 | pszName++; |
749 | |
750 | szWinRtNamespace = szFullName; |
751 | szWinRtClassName = pszName; |
752 | } |
753 | else |
754 | { // Namespace '.' separator not found - invalid type name (namespace has to be always present) |
755 | fValidAssemblyRef = FALSE; |
756 | } |
757 | } |
758 | else |
759 | { // Type name separator in assembly name '!' not found |
760 | fValidAssemblyRef = FALSE; |
761 | } |
762 | } |
763 | |
764 | if (fValidAssemblyRef) |
765 | { |
766 | pAssembly = fromModule->GetAssemblyIfLoaded( |
767 | tkAssemblyRef, |
768 | szWinRtNamespace, |
769 | szWinRtClassName, |
770 | pMDImportOverride); |
771 | } |
772 | } |
773 | } |
774 | } |
775 | |
776 | if (pAssembly == NULL) |
777 | return NULL; |
778 | |
779 | return pAssembly->GetManifestModule(); |
780 | } |
781 | |
782 | |
783 | TypeHandle ZapSig::DecodeType(Module *pEncodeModuleContext, |
784 | Module *pInfoModule, |
785 | PCCOR_SIGNATURE pBuffer, |
786 | ClassLoadLevel level) |
787 | { |
788 | CONTRACTL |
789 | { |
790 | THROWS; |
791 | GC_TRIGGERS; |
792 | MODE_ANY; |
793 | } |
794 | CONTRACTL_END; |
795 | |
796 | SigPointer p(pBuffer); |
797 | |
798 | ZapSig::Context zapSigContext(pInfoModule, pEncodeModuleContext); |
799 | ZapSig::Context * pZapSigContext = &zapSigContext; |
800 | |
801 | SigTypeContext typeContext; // empty context is OK: encoding should not contain type variables. |
802 | |
803 | TypeHandle th = p.GetTypeHandleThrowing(pInfoModule, |
804 | &typeContext, |
805 | ClassLoader::LoadTypes, |
806 | level, |
807 | level < CLASS_LOADED, // For non-full loads, drop a level when loading generic arguments |
808 | NULL, |
809 | pZapSigContext); |
810 | |
811 | return th; |
812 | } |
813 | |
814 | MethodDesc *ZapSig::DecodeMethod(Module *pReferencingModule, |
815 | Module *pInfoModule, |
816 | PCCOR_SIGNATURE pBuffer, |
817 | TypeHandle * ppTH /*=NULL*/) |
818 | { |
819 | STANDARD_VM_CONTRACT; |
820 | |
821 | SigTypeContext typeContext; // empty context is OK: encoding should not contain type variables. |
822 | |
823 | return DecodeMethod(pReferencingModule, pInfoModule, pBuffer, &typeContext, ppTH); |
824 | } |
825 | |
826 | MethodDesc *ZapSig::DecodeMethod(Module *pReferencingModule, |
827 | Module *pInfoModule, |
828 | PCCOR_SIGNATURE pBuffer, |
829 | SigTypeContext *pContext, |
830 | TypeHandle *ppTH, /*=NULL*/ |
831 | PCCOR_SIGNATURE *ppOwnerTypeSpecWithVars, /*=NULL*/ |
832 | PCCOR_SIGNATURE *ppMethodSpecWithVars /*=NULL*/) |
833 | { |
834 | STANDARD_VM_CONTRACT; |
835 | |
836 | MethodDesc *pMethod = NULL; |
837 | |
838 | SigPointer sig(pBuffer); |
839 | |
840 | ZapSig::Context zapSigContext(pInfoModule, (void *)pReferencingModule, ZapSig::NormalTokens); |
841 | ZapSig::Context * pZapSigContext = &zapSigContext; |
842 | |
843 | // decode flags |
844 | DWORD methodFlags; |
845 | IfFailThrow(sig.GetData(&methodFlags)); |
846 | |
847 | TypeHandle thOwner = NULL; |
848 | |
849 | if ( methodFlags & ENCODE_METHOD_SIG_OwnerType ) |
850 | { |
851 | if (ppOwnerTypeSpecWithVars != NULL) |
852 | *ppOwnerTypeSpecWithVars = sig.GetPtr(); |
853 | |
854 | thOwner = sig.GetTypeHandleThrowing(pInfoModule, |
855 | pContext, |
856 | ClassLoader::LoadTypes, |
857 | CLASS_LOADED, |
858 | FALSE, |
859 | NULL, |
860 | pZapSigContext); |
861 | |
862 | IfFailThrow(sig.SkipExactlyOne()); |
863 | } |
864 | |
865 | if ( methodFlags & ENCODE_METHOD_SIG_SlotInsteadOfToken ) |
866 | { |
867 | // get the method desc using slot number |
868 | DWORD slot; |
869 | IfFailThrow(sig.GetData(&slot)); |
870 | |
871 | _ASSERTE(!thOwner.IsNull()); |
872 | |
873 | pMethod = thOwner.GetMethodTable()->GetMethodDescForSlot(slot); |
874 | } |
875 | else |
876 | { |
877 | // |
878 | // decode method token |
879 | // |
880 | RID rid; |
881 | IfFailThrow(sig.GetData(&rid)); |
882 | |
883 | if (methodFlags & ENCODE_METHOD_SIG_MemberRefToken) |
884 | { |
885 | if (thOwner.IsNull()) |
886 | { |
887 | TypeHandle th; |
888 | MethodDesc * pMD = NULL; |
889 | FieldDesc * pFD = NULL; |
890 | |
891 | MemberLoader::GetDescFromMemberRef(pInfoModule, TokenFromRid(rid, mdtMemberRef), &pMD, &pFD, NULL, FALSE, &th); |
892 | _ASSERTE(pMD != NULL); |
893 | |
894 | thOwner = th; |
895 | pMethod = pMD; |
896 | } |
897 | else |
898 | { |
899 | pMethod = MemberLoader::GetMethodDescFromMemberRefAndType(pInfoModule, TokenFromRid(rid, mdtMemberRef), thOwner.GetMethodTable()); |
900 | } |
901 | } |
902 | else |
903 | { |
904 | pMethod = MemberLoader::GetMethodDescFromMethodDef(pInfoModule, TokenFromRid(rid, mdtMethodDef), FALSE); |
905 | } |
906 | } |
907 | |
908 | if (thOwner.IsNull()) |
909 | thOwner = pMethod->GetMethodTable(); |
910 | |
911 | if (ppTH != NULL) |
912 | *ppTH = thOwner; |
913 | |
914 | // Ensure that the methoddescs dependencies have been walked sufficiently for type forwarders to be resolved. |
915 | // This method is actually basically a nop for dependencies which are ngen'd, but is real work for jitted |
916 | // dependencies. (However, this shouldn't be meaningful work that wouldn't happen in any case very soon.) |
917 | pMethod->PrepareForUseAsADependencyOfANativeImage(); |
918 | |
919 | Instantiation inst; |
920 | |
921 | // Instantiate the method if needed, or create a stub to a static method in a generic class. |
922 | if (methodFlags & ENCODE_METHOD_SIG_MethodInstantiation) |
923 | { |
924 | if (ppMethodSpecWithVars != NULL) |
925 | *ppMethodSpecWithVars = sig.GetPtr(); |
926 | |
927 | DWORD nargs; |
928 | IfFailThrow(sig.GetData(&nargs)); |
929 | _ASSERTE(nargs > 0); |
930 | |
931 | SIZE_T cbMem; |
932 | |
933 | if (!ClrSafeInt<SIZE_T>::multiply(nargs, sizeof(TypeHandle), cbMem/* passed by ref */)) |
934 | ThrowHR(COR_E_OVERFLOW); |
935 | |
936 | TypeHandle * pInst = (TypeHandle*) _alloca(cbMem); |
937 | |
938 | for (DWORD i = 0; i < nargs; i++) |
939 | { |
940 | pInst[i] = sig.GetTypeHandleThrowing(pInfoModule, |
941 | pContext, |
942 | ClassLoader::LoadTypes, |
943 | CLASS_LOADED, |
944 | FALSE, |
945 | NULL, |
946 | pZapSigContext); |
947 | IfFailThrow(sig.SkipExactlyOne()); |
948 | } |
949 | |
950 | inst = Instantiation(pInst, nargs); |
951 | } |
952 | else |
953 | { |
954 | inst = pMethod->GetMethodInstantiation(); |
955 | } |
956 | |
957 | |
958 | // This must be called even if nargs == 0, in order to create an instantiating |
959 | // stub for static methods in generic classees if needed, also for BoxedEntryPointStubs |
960 | // in non-generic structs. |
961 | BOOL isInstantiatingStub = (methodFlags & ENCODE_METHOD_SIG_InstantiatingStub); |
962 | BOOL isUnboxingStub = (methodFlags & ENCODE_METHOD_SIG_UnboxingStub); |
963 | |
964 | pMethod = MethodDesc::FindOrCreateAssociatedMethodDesc(pMethod, thOwner.GetMethodTable(), |
965 | isUnboxingStub, |
966 | inst, |
967 | !(isInstantiatingStub || isUnboxingStub)); |
968 | |
969 | g_IBCLogger.LogMethodDescAccess(pMethod); |
970 | |
971 | if (methodFlags & ENCODE_METHOD_SIG_Constrained) |
972 | { |
973 | TypeHandle constrainedType = sig.GetTypeHandleThrowing(pInfoModule, |
974 | pContext, |
975 | ClassLoader::LoadTypes, |
976 | CLASS_LOADED, |
977 | FALSE, |
978 | NULL, |
979 | pZapSigContext); |
980 | |
981 | MethodDesc * directMethod = constrainedType.GetMethodTable()->TryResolveConstraintMethodApprox(thOwner.GetMethodTable(), pMethod); |
982 | if (directMethod == NULL) |
983 | { |
984 | // Method on value type was removed. Boxing stub would need to be generated to handle this case. |
985 | _ASSERTE(!"Constrained method resolution failed" ); |
986 | |
987 | MemberLoader::ThrowMissingMethodException(constrainedType.GetMethodTable(), NULL, NULL, NULL, 0, NULL); |
988 | } |
989 | |
990 | // Strip the instantiating stub if the signature did not ask for one |
991 | if (directMethod->IsInstantiatingStub() && !isInstantiatingStub) |
992 | { |
993 | pMethod = directMethod->GetWrappedMethodDesc(); |
994 | } |
995 | else |
996 | { |
997 | pMethod = directMethod; |
998 | } |
999 | } |
1000 | |
1001 | return pMethod; |
1002 | } |
1003 | |
1004 | FieldDesc * ZapSig::DecodeField(Module *pReferencingModule, |
1005 | Module *pInfoModule, |
1006 | PCCOR_SIGNATURE pBuffer, |
1007 | TypeHandle *ppTH /*=NULL*/) |
1008 | { |
1009 | CONTRACTL |
1010 | { |
1011 | THROWS; |
1012 | GC_TRIGGERS; |
1013 | MODE_ANY; |
1014 | } |
1015 | CONTRACTL_END; |
1016 | |
1017 | SigTypeContext typeContext; // empty context is OK: encoding should not contain type variables. |
1018 | |
1019 | return DecodeField(pReferencingModule, pInfoModule, pBuffer, &typeContext, ppTH); |
1020 | } |
1021 | |
1022 | FieldDesc * ZapSig::DecodeField(Module *pReferencingModule, |
1023 | Module *pInfoModule, |
1024 | PCCOR_SIGNATURE pBuffer, |
1025 | SigTypeContext *pContext, |
1026 | TypeHandle *ppTH /*=NULL*/) |
1027 | { |
1028 | CONTRACTL |
1029 | { |
1030 | THROWS; |
1031 | GC_TRIGGERS; |
1032 | MODE_ANY; |
1033 | } |
1034 | CONTRACTL_END; |
1035 | |
1036 | FieldDesc *pField = NULL; |
1037 | |
1038 | SigPointer sig(pBuffer); |
1039 | |
1040 | DWORD fieldFlags; |
1041 | IfFailThrow(sig.GetData(&fieldFlags)); |
1042 | |
1043 | MethodTable *pOwnerMT = NULL; |
1044 | |
1045 | if (fieldFlags & ENCODE_FIELD_SIG_OwnerType) |
1046 | { |
1047 | ZapSig::Context zapSigContext(pInfoModule, pReferencingModule); |
1048 | ZapSig::Context * pZapSigContext = &zapSigContext; |
1049 | |
1050 | pOwnerMT = sig.GetTypeHandleThrowing(pInfoModule, |
1051 | pContext, |
1052 | ClassLoader::LoadTypes, |
1053 | CLASS_LOADED, |
1054 | FALSE, |
1055 | NULL, |
1056 | pZapSigContext).GetMethodTable(); |
1057 | |
1058 | IfFailThrow(sig.SkipExactlyOne()); |
1059 | } |
1060 | |
1061 | if (fieldFlags & ENCODE_FIELD_SIG_IndexInsteadOfToken) |
1062 | { |
1063 | // get the field desc using index |
1064 | DWORD fieldIndex; |
1065 | IfFailThrow(sig.GetData(&fieldIndex)); |
1066 | |
1067 | _ASSERTE(pOwnerMT != NULL); |
1068 | |
1069 | pField = pOwnerMT->GetFieldDescByIndex(fieldIndex); |
1070 | _ASSERTE(pOwnerMT == pField->GetApproxEnclosingMethodTable()); |
1071 | } |
1072 | else |
1073 | { |
1074 | RID rid; |
1075 | IfFailThrow(sig.GetData(&rid)); |
1076 | |
1077 | if (fieldFlags & ENCODE_FIELD_SIG_MemberRefToken) |
1078 | { |
1079 | if (pOwnerMT == NULL) |
1080 | { |
1081 | TypeHandle th; |
1082 | MethodDesc * pMD = NULL; |
1083 | FieldDesc * pFD = NULL; |
1084 | |
1085 | MemberLoader::GetDescFromMemberRef(pInfoModule, TokenFromRid(rid, mdtMemberRef), &pMD, &pFD, NULL, FALSE, &th); |
1086 | _ASSERTE(pFD != NULL); |
1087 | |
1088 | pField = pFD; |
1089 | } |
1090 | else |
1091 | { |
1092 | pField = MemberLoader::GetFieldDescFromMemberRefAndType(pInfoModule, TokenFromRid(rid, mdtMemberRef), pOwnerMT); |
1093 | } |
1094 | } |
1095 | else |
1096 | { |
1097 | pField = MemberLoader::GetFieldDescFromFieldDef(pInfoModule, TokenFromRid(rid, mdtFieldDef), FALSE); |
1098 | } |
1099 | } |
1100 | |
1101 | if (ppTH != NULL) |
1102 | *ppTH = (pOwnerMT != NULL) ? pOwnerMT : pField->GetApproxEnclosingMethodTable(); |
1103 | |
1104 | return pField; |
1105 | } |
1106 | |
1107 | /* static */ |
1108 | BOOL ZapSig::EncodeMethod( |
1109 | MethodDesc * pMethod, |
1110 | Module * pInfoModule, |
1111 | SigBuilder * pSigBuilder, |
1112 | LPVOID pEncodeModuleContext, |
1113 | ENCODEMODULE_CALLBACK pfnEncodeModule, |
1114 | DEFINETOKEN_CALLBACK pfnDefineToken, |
1115 | CORINFO_RESOLVED_TOKEN * pResolvedToken, |
1116 | CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken, |
1117 | BOOL fEncodeUsingResolvedTokenSpecStreams) |
1118 | { |
1119 | CONTRACTL |
1120 | { |
1121 | THROWS; |
1122 | GC_TRIGGERS; |
1123 | MODE_ANY; |
1124 | } |
1125 | CONTRACTL_END; |
1126 | |
1127 | TypeHandle ownerType; |
1128 | |
1129 | #ifdef FEATURE_READYTORUN_COMPILER |
1130 | if (IsReadyToRunCompilation()) |
1131 | { |
1132 | if (pResolvedToken == NULL) |
1133 | { |
1134 | _ASSERTE(!"CORINFO_RESOLVED_TOKEN required to encode method!" ); |
1135 | ThrowHR(E_FAIL); |
1136 | } |
1137 | |
1138 | // Encode the referencing method type |
1139 | ownerType = TypeHandle(pResolvedToken->hClass); |
1140 | } |
1141 | else |
1142 | #endif |
1143 | { |
1144 | ownerType = pMethod->GetMethodTable_NoLogging(); |
1145 | } |
1146 | |
1147 | ZapSig::ExternalTokens externalTokens = ZapSig::NormalTokens; |
1148 | if (pfnDefineToken != NULL) |
1149 | { |
1150 | externalTokens = ZapSig::IbcTokens; |
1151 | } |
1152 | |
1153 | ZapSig zapSig(pInfoModule, pEncodeModuleContext, externalTokens, |
1154 | (EncodeModuleCallback) pfnEncodeModule, |
1155 | (TokenDefinitionCallback) pfnDefineToken); |
1156 | |
1157 | // |
1158 | // output the sequence that represents the token for the method |
1159 | // |
1160 | mdMethodDef methodToken = pMethod->GetMemberDef_NoLogging(); |
1161 | DWORD methodFlags = 0; |
1162 | BOOL fMethodNeedsInstantiation = pMethod->HasMethodInstantiation() && !pMethod->IsGenericMethodDefinition(); |
1163 | |
1164 | if (pMethod->IsUnboxingStub()) |
1165 | methodFlags |= ENCODE_METHOD_SIG_UnboxingStub; |
1166 | if (pMethod->IsInstantiatingStub()) |
1167 | methodFlags |= ENCODE_METHOD_SIG_InstantiatingStub; |
1168 | if (fMethodNeedsInstantiation) |
1169 | methodFlags |= ENCODE_METHOD_SIG_MethodInstantiation; |
1170 | |
1171 | // |
1172 | // For backward compatibility, IBC tokens use slightly different encoding: |
1173 | // - Owning type is uncoditionally encoded |
1174 | // - Number of method instantiation arguments is not encoded |
1175 | // |
1176 | if (externalTokens == ZapSig::IbcTokens) |
1177 | { |
1178 | // The type is always encoded before flags for IBC |
1179 | if (!zapSig.GetSignatureForTypeHandle(ownerType, pSigBuilder)) |
1180 | return FALSE; |
1181 | } |
1182 | else |
1183 | { |
1184 | // Assume that the owner type is going to be needed |
1185 | methodFlags |= ENCODE_METHOD_SIG_OwnerType; |
1186 | } |
1187 | |
1188 | #ifdef FEATURE_READYTORUN_COMPILER |
1189 | if (IsReadyToRunCompilation()) |
1190 | { |
1191 | if (pConstrainedResolvedToken != NULL) |
1192 | { |
1193 | methodFlags |= ENCODE_METHOD_SIG_Constrained; |
1194 | } |
1195 | |
1196 | Module * pReferencingModule = (Module *)pResolvedToken->tokenScope; |
1197 | |
1198 | if (!pReferencingModule->IsInCurrentVersionBubble()) |
1199 | { |
1200 | // FUTURE: Encoding of new cross-module references for ReadyToRun |
1201 | // This warning is hit for recursive cross-module inlining. It is commented out to avoid noise. |
1202 | // GetSvcLogger()->Printf(W("ReadyToRun: Method reference outside of current version bubble cannot be encoded\n")); |
1203 | ThrowHR(E_FAIL); |
1204 | } |
1205 | _ASSERTE(pReferencingModule == GetAppDomain()->ToCompilationDomain()->GetTargetModule()); |
1206 | |
1207 | methodToken = pResolvedToken->token; |
1208 | |
1209 | if (TypeFromToken(methodToken) == mdtMethodSpec) |
1210 | { |
1211 | IfFailThrow(pReferencingModule->GetMDImport()->GetMethodSpecProps(methodToken, &methodToken, NULL, NULL)); |
1212 | } |
1213 | |
1214 | switch (TypeFromToken(methodToken)) |
1215 | { |
1216 | case mdtMethodDef: |
1217 | _ASSERTE(pResolvedToken->pTypeSpec == NULL); |
1218 | if (!ownerType.HasInstantiation() || ownerType.IsTypicalTypeDefinition()) |
1219 | { |
1220 | methodFlags &= ~ENCODE_METHOD_SIG_OwnerType; |
1221 | } |
1222 | break; |
1223 | |
1224 | case mdtMemberRef: |
1225 | methodFlags |= ENCODE_METHOD_SIG_MemberRefToken; |
1226 | |
1227 | if (pResolvedToken->pTypeSpec == NULL) |
1228 | { |
1229 | methodFlags &= ~ENCODE_METHOD_SIG_OwnerType; |
1230 | } |
1231 | else |
1232 | if (!(methodFlags & ENCODE_METHOD_SIG_InstantiatingStub)) |
1233 | { |
1234 | if (SigPointer(pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec).IsPolyType(NULL) == hasNoVars) |
1235 | methodFlags &= ~ENCODE_METHOD_SIG_OwnerType; |
1236 | } |
1237 | break; |
1238 | |
1239 | default: |
1240 | _ASSERTE(!"Unexpected method token type!" ); |
1241 | ThrowHR(E_NOTIMPL); |
1242 | } |
1243 | } |
1244 | else |
1245 | #endif |
1246 | if (IsNilToken(methodToken)) |
1247 | { |
1248 | methodFlags |= ENCODE_METHOD_SIG_SlotInsteadOfToken; |
1249 | } |
1250 | else |
1251 | if (!pMethod->GetModule()->IsInCurrentVersionBubble()) |
1252 | { |
1253 | // Using a method defined in another version bubble. We can assume the slot number is stable only for real interface methods. |
1254 | if (!ownerType.IsInterface() || pMethod->IsStatic() || pMethod->HasMethodInstantiation()) |
1255 | { |
1256 | // FUTURE TODO: Version resilience |
1257 | _ASSERTE(!"References to non-interface methods not yet supported in version resilient images" ); |
1258 | IfFailThrow(E_FAIL); |
1259 | } |
1260 | methodFlags |= ENCODE_METHOD_SIG_SlotInsteadOfToken; |
1261 | } |
1262 | else |
1263 | { |
1264 | Module * pTypeHandleModule = pMethod->GetModule(); |
1265 | |
1266 | if (pTypeHandleModule != pInfoModule) |
1267 | { |
1268 | // During IBC profiling this calls |
1269 | // code:Module.EncodeModuleHelper |
1270 | // During ngen this calls |
1271 | // code:ZapImportTable.EncodeModuleHelper) |
1272 | // |
1273 | DWORD index = (*((EncodeModuleCallback) pfnEncodeModule))(pEncodeModuleContext, pTypeHandleModule); |
1274 | |
1275 | if (index == ENCODE_MODULE_FAILED) |
1276 | { |
1277 | return FALSE; |
1278 | } |
1279 | |
1280 | // If the method handle's module is different that the pInfoModule |
1281 | // we need to call the TokenDefinitionCallback function |
1282 | // to record the names for the external module tokens |
1283 | // |
1284 | if ((index != 0) && (pfnDefineToken != NULL)) |
1285 | { |
1286 | // |
1287 | // We do not want to log the metadata lookups that we perform here |
1288 | // |
1289 | IBCLoggingDisabler disableLogging; |
1290 | |
1291 | // During IBC profiling this calls |
1292 | // code:Module::TokenDefinitionHelper() |
1293 | (*((TokenDefinitionCallback) pfnDefineToken))(pEncodeModuleContext, pTypeHandleModule, index, &methodToken); |
1294 | } |
1295 | } |
1296 | else |
1297 | { |
1298 | _ASSERTE(pInfoModule = pMethod->GetModule()); |
1299 | } |
1300 | |
1301 | if (!ownerType.HasInstantiation()) |
1302 | methodFlags &= ~ENCODE_METHOD_SIG_OwnerType; |
1303 | } |
1304 | |
1305 | // |
1306 | // output the flags |
1307 | // |
1308 | pSigBuilder->AppendData(methodFlags); |
1309 | |
1310 | if (methodFlags & ENCODE_METHOD_SIG_OwnerType) |
1311 | { |
1312 | if (fEncodeUsingResolvedTokenSpecStreams && pResolvedToken != NULL && pResolvedToken->pTypeSpec != NULL) |
1313 | { |
1314 | _ASSERTE(pResolvedToken->cbTypeSpec > 0); |
1315 | pSigBuilder->AppendBlob((PVOID)pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec); |
1316 | } |
1317 | else |
1318 | { |
1319 | if (!zapSig.GetSignatureForTypeHandle(ownerType, pSigBuilder)) |
1320 | return FALSE; |
1321 | } |
1322 | } |
1323 | |
1324 | if ((methodFlags & ENCODE_METHOD_SIG_SlotInsteadOfToken) == 0) |
1325 | { |
1326 | // emit the rid |
1327 | pSigBuilder->AppendData(RidFromToken(methodToken)); |
1328 | } |
1329 | else |
1330 | { |
1331 | // have no token (e.g. it could be an array), encode slot number |
1332 | pSigBuilder->AppendData(pMethod->GetSlot()); |
1333 | } |
1334 | |
1335 | if ((methodFlags & ENCODE_METHOD_SIG_MethodInstantiation) != 0) |
1336 | { |
1337 | if (fEncodeUsingResolvedTokenSpecStreams && pResolvedToken != NULL && pResolvedToken->pMethodSpec != NULL) |
1338 | { |
1339 | _ASSERTE(pResolvedToken->cbMethodSpec > 1); |
1340 | |
1341 | if (*(BYTE*)pResolvedToken->pMethodSpec != (BYTE)IMAGE_CEE_CS_CALLCONV_GENERICINST) |
1342 | ThrowHR(COR_E_BADIMAGEFORMAT); |
1343 | |
1344 | pSigBuilder->AppendBlob((PVOID)(((BYTE*)pResolvedToken->pMethodSpec) + 1), pResolvedToken->cbMethodSpec - 1); |
1345 | } |
1346 | else |
1347 | { |
1348 | Instantiation inst = pMethod->GetMethodInstantiation(); |
1349 | |
1350 | // Number of method instantiation arguments is not encoded in IBC tokens - see comment above |
1351 | if (externalTokens != ZapSig::IbcTokens) |
1352 | pSigBuilder->AppendData(inst.GetNumArgs()); |
1353 | |
1354 | for (DWORD i = 0; i < inst.GetNumArgs(); i++) |
1355 | { |
1356 | TypeHandle t = inst[i]; |
1357 | _ASSERTE(!t.IsNull()); |
1358 | |
1359 | if (!zapSig.GetSignatureForTypeHandle(t, pSigBuilder)) |
1360 | return FALSE; |
1361 | } |
1362 | } |
1363 | } |
1364 | |
1365 | #ifdef FEATURE_READYTORUN_COMPILER |
1366 | if ((methodFlags & ENCODE_METHOD_SIG_Constrained) != 0) |
1367 | { |
1368 | if (fEncodeUsingResolvedTokenSpecStreams && pConstrainedResolvedToken->pTypeSpec != NULL) |
1369 | { |
1370 | _ASSERTE(pConstrainedResolvedToken->cbTypeSpec > 0); |
1371 | pSigBuilder->AppendBlob((PVOID)pConstrainedResolvedToken->pTypeSpec, pConstrainedResolvedToken->cbTypeSpec); |
1372 | } |
1373 | else |
1374 | { |
1375 | if (!zapSig.GetSignatureForTypeHandle(TypeHandle(pConstrainedResolvedToken->hClass), pSigBuilder)) |
1376 | return FALSE; |
1377 | } |
1378 | } |
1379 | #endif |
1380 | |
1381 | return TRUE; |
1382 | } |
1383 | |
1384 | void ZapSig::EncodeField( |
1385 | FieldDesc *pField, |
1386 | Module *pInfoModule, |
1387 | SigBuilder *pSigBuilder, |
1388 | LPVOID pEncodeModuleContext, |
1389 | ENCODEMODULE_CALLBACK pfnEncodeModule, |
1390 | CORINFO_RESOLVED_TOKEN *pResolvedToken, |
1391 | BOOL fEncodeUsingResolvedTokenSpecStreams) |
1392 | { |
1393 | CONTRACTL |
1394 | { |
1395 | THROWS; |
1396 | GC_TRIGGERS; |
1397 | MODE_ANY; |
1398 | } |
1399 | CONTRACTL_END; |
1400 | |
1401 | MethodTable * pMT; |
1402 | |
1403 | mdMethodDef fieldToken = pField->GetMemberDef(); |
1404 | DWORD fieldFlags = ENCODE_FIELD_SIG_OwnerType; |
1405 | |
1406 | #ifdef FEATURE_READYTORUN_COMPILER |
1407 | if (IsReadyToRunCompilation()) |
1408 | { |
1409 | if (pResolvedToken == NULL) |
1410 | { |
1411 | _ASSERTE(!"CORINFO_RESOLVED_TOKEN required to encode field!" ); |
1412 | ThrowHR(E_FAIL); |
1413 | } |
1414 | |
1415 | // Encode the referencing field type |
1416 | pMT = (MethodTable *)(pResolvedToken->hClass); |
1417 | |
1418 | Module * pReferencingModule = (Module *)pResolvedToken->tokenScope; |
1419 | |
1420 | if (!pReferencingModule->IsInCurrentVersionBubble()) |
1421 | { |
1422 | // FUTURE: Encoding of new cross-module references for ReadyToRun |
1423 | // This warning is hit for recursive cross-module inlining. It is commented out to avoid noise. |
1424 | // GetSvcLogger()->Printf(W("ReadyToRun: Field reference outside of current version bubble cannot be encoded\n")); |
1425 | ThrowHR(E_FAIL); |
1426 | } |
1427 | _ASSERTE(pReferencingModule == GetAppDomain()->ToCompilationDomain()->GetTargetModule()); |
1428 | |
1429 | fieldToken = pResolvedToken->token; |
1430 | |
1431 | switch (TypeFromToken(fieldToken)) |
1432 | { |
1433 | case mdtFieldDef: |
1434 | _ASSERTE(pResolvedToken->pTypeSpec == NULL); |
1435 | fieldFlags &= ~ENCODE_FIELD_SIG_OwnerType; |
1436 | break; |
1437 | |
1438 | case mdtMemberRef: |
1439 | fieldFlags |= ENCODE_FIELD_SIG_MemberRefToken; |
1440 | |
1441 | if (pResolvedToken->pTypeSpec == NULL) |
1442 | { |
1443 | fieldFlags &= ~ENCODE_METHOD_SIG_OwnerType; |
1444 | } |
1445 | else |
1446 | { |
1447 | if (SigPointer(pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec).IsPolyType(NULL) == hasNoVars) |
1448 | fieldFlags &= ~ENCODE_METHOD_SIG_OwnerType; |
1449 | } |
1450 | break; |
1451 | |
1452 | default: |
1453 | _ASSERTE(!"Unexpected field token type!" ); |
1454 | ThrowHR(E_NOTIMPL); |
1455 | } |
1456 | } |
1457 | else |
1458 | #endif |
1459 | { |
1460 | pMT = pField->GetApproxEnclosingMethodTable(); |
1461 | |
1462 | fieldFlags |= ENCODE_FIELD_SIG_IndexInsteadOfToken; |
1463 | } |
1464 | |
1465 | // |
1466 | // output the flags |
1467 | // |
1468 | pSigBuilder->AppendData(fieldFlags); |
1469 | |
1470 | if (fieldFlags & ENCODE_FIELD_SIG_OwnerType) |
1471 | { |
1472 | if (fEncodeUsingResolvedTokenSpecStreams && pResolvedToken != NULL && pResolvedToken->pTypeSpec != NULL) |
1473 | { |
1474 | _ASSERTE(pResolvedToken->cbTypeSpec > 0); |
1475 | pSigBuilder->AppendBlob((PVOID)pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec); |
1476 | } |
1477 | else |
1478 | { |
1479 | ZapSig zapSig(pInfoModule, pEncodeModuleContext, ZapSig::NormalTokens, |
1480 | (EncodeModuleCallback)pfnEncodeModule, NULL); |
1481 | |
1482 | // |
1483 | // Write class |
1484 | // |
1485 | BOOL fSuccess; |
1486 | fSuccess = zapSig.GetSignatureForTypeHandle(pMT, pSigBuilder); |
1487 | _ASSERTE(fSuccess); |
1488 | } |
1489 | } |
1490 | |
1491 | if ((fieldFlags & ENCODE_FIELD_SIG_IndexInsteadOfToken) == 0) |
1492 | { |
1493 | // emit the rid |
1494 | pSigBuilder->AppendData(RidFromToken(fieldToken)); |
1495 | } |
1496 | else |
1497 | { |
1498 | // |
1499 | // Write field index |
1500 | // |
1501 | |
1502 | DWORD fieldIndex = pMT->GetIndexForFieldDesc(pField); |
1503 | _ASSERTE(fieldIndex < DWORD(pMT->GetNumStaticFields() + pMT->GetNumIntroducedInstanceFields())); |
1504 | |
1505 | // have no token (e.g. it could be an array), encode slot number |
1506 | pSigBuilder->AppendData(fieldIndex); |
1507 | } |
1508 | } |
1509 | |
1510 | #endif // DACCESS_COMPILE |
1511 | |
1512 | #endif // FEATURE_PREJIT |
1513 | |