1//
2// Copyright (c) Microsoft. All rights reserved.
3// Licensed under the MIT license. See LICENSE file in the project root for full license information.
4//
5
6#include "standardpch.h"
7#include "icorjitinfo.h"
8#include "superpmi-shim-collector.h"
9#include "ieememorymanager.h"
10#include "icorjitcompiler.h"
11#include "methodcontext.h"
12#include "errorhandling.h"
13#include "logging.h"
14
15#define fatMC // this is nice to have on so ildump works...
16
17// Stuff on ICorStaticInfo
18/**********************************************************************************/
19//
20// ICorMethodInfo
21//
22/**********************************************************************************/
23// return flags (defined above, CORINFO_FLG_PUBLIC ...)
24DWORD interceptor_ICJI::getMethodAttribs(CORINFO_METHOD_HANDLE ftn /* IN */)
25{
26 mc->cr->AddCall("getMethodAttribs");
27 DWORD temp = original_ICorJitInfo->getMethodAttribs(ftn);
28 mc->recGetMethodAttribs(ftn, temp);
29 return temp;
30}
31
32// sets private JIT flags, which can be, retrieved using getAttrib.
33void interceptor_ICJI::setMethodAttribs(CORINFO_METHOD_HANDLE ftn, /* IN */
34 CorInfoMethodRuntimeFlags attribs /* IN */)
35{
36 mc->cr->AddCall("setMethodAttribs");
37 original_ICorJitInfo->setMethodAttribs(ftn, attribs);
38 mc->cr->recSetMethodAttribs(ftn, attribs);
39}
40
41// Given a method descriptor ftnHnd, extract signature information into sigInfo
42//
43// 'memberParent' is typically only set when verifying. It should be the
44// result of calling getMemberParent.
45void interceptor_ICJI::getMethodSig(CORINFO_METHOD_HANDLE ftn, /* IN */
46 CORINFO_SIG_INFO* sig, /* OUT */
47 CORINFO_CLASS_HANDLE memberParent /* IN */
48 )
49{
50 mc->cr->AddCall("getMethodSig");
51 original_ICorJitInfo->getMethodSig(ftn, sig, memberParent);
52 mc->recGetMethodSig(ftn, sig, memberParent);
53}
54
55/*********************************************************************
56* Note the following methods can only be used on functions known
57* to be IL. This includes the method being compiled and any method
58* that 'getMethodInfo' returns true for
59*********************************************************************/
60// return information about a method private to the implementation
61// returns false if method is not IL, or is otherwise unavailable.
62// This method is used to fetch data needed to inline functions
63bool interceptor_ICJI::getMethodInfo(CORINFO_METHOD_HANDLE ftn, /* IN */
64 CORINFO_METHOD_INFO* info /* OUT */
65 )
66{
67 struct Param : FilterSuperPMIExceptionsParam_CaptureException
68 {
69 interceptor_ICJI* pThis;
70 CORINFO_METHOD_HANDLE ftn;
71 CORINFO_METHOD_INFO* info;
72 bool temp;
73 } param;
74 param.pThis = this;
75 param.ftn = ftn;
76 param.info = info;
77 param.temp = false;
78
79 PAL_TRY(Param*, pOuterParam, &param)
80 {
81 PAL_TRY(Param*, pParam, pOuterParam)
82 {
83 pParam->pThis->mc->cr->AddCall("getMethodInfo");
84 pParam->temp = pParam->pThis->original_ICorJitInfo->getMethodInfo(pParam->ftn, pParam->info);
85 }
86 PAL_EXCEPT_FILTER(FilterSuperPMIExceptions_CaptureExceptionAndContinue)
87 {
88 }
89 PAL_ENDTRY
90 }
91 PAL_FINALLY
92 {
93 this->mc->recGetMethodInfo(ftn, info, param.temp, param.exceptionCode);
94 }
95 PAL_ENDTRY
96
97 return param.temp;
98}
99
100// Decides if you have any limitations for inlining. If everything's OK, it will return
101// INLINE_PASS and will fill out pRestrictions with a mask of restrictions the caller of this
102// function must respect. If caller passes pRestrictions = nullptr, if there are any restrictions
103// INLINE_FAIL will be returned
104//
105// The callerHnd must be the immediate caller (i.e. when we have a chain of inlined calls)
106//
107// The inlined method need not be verified
108
109CorInfoInline interceptor_ICJI::canInline(CORINFO_METHOD_HANDLE callerHnd, /* IN */
110 CORINFO_METHOD_HANDLE calleeHnd, /* IN */
111 DWORD* pRestrictions /* OUT */
112 )
113{
114 struct Param : FilterSuperPMIExceptionsParam_CaptureException
115 {
116 interceptor_ICJI* pThis;
117 CORINFO_METHOD_HANDLE callerHnd;
118 CORINFO_METHOD_HANDLE calleeHnd;
119 DWORD* pRestrictions;
120 CorInfoInline temp;
121 } param;
122 param.pThis = this;
123 param.callerHnd = callerHnd;
124 param.calleeHnd = calleeHnd;
125 param.pRestrictions = pRestrictions;
126 param.temp = INLINE_NEVER;
127
128 PAL_TRY(Param*, pOuterParam, &param)
129 {
130 PAL_TRY(Param*, pParam, pOuterParam)
131 {
132 pParam->pThis->mc->cr->AddCall("canInline");
133 pParam->temp = pParam->pThis->original_ICorJitInfo->canInline(pParam->callerHnd, pParam->calleeHnd,
134 pParam->pRestrictions);
135 }
136 PAL_EXCEPT_FILTER(FilterSuperPMIExceptions_CaptureExceptionAndContinue)
137 {
138 }
139 PAL_ENDTRY
140 }
141 PAL_FINALLY
142 {
143 this->mc->recCanInline(callerHnd, calleeHnd, pRestrictions, param.temp, param.exceptionCode);
144 }
145 PAL_ENDTRY
146
147 return param.temp;
148}
149
150// Reports whether or not a method can be inlined, and why. canInline is responsible for reporting all
151// inlining results when it returns INLINE_FAIL and INLINE_NEVER. All other results are reported by the
152// JIT.
153void interceptor_ICJI::reportInliningDecision(CORINFO_METHOD_HANDLE inlinerHnd,
154 CORINFO_METHOD_HANDLE inlineeHnd,
155 CorInfoInline inlineResult,
156 const char* reason)
157{
158 mc->cr->AddCall("reportInliningDecision");
159 original_ICorJitInfo->reportInliningDecision(inlinerHnd, inlineeHnd, inlineResult, reason);
160 mc->cr->recReportInliningDecision(inlinerHnd, inlineeHnd, inlineResult, reason);
161}
162
163// Returns false if the call is across security boundaries thus we cannot tailcall
164//
165// The callerHnd must be the immediate caller (i.e. when we have a chain of inlined calls)
166bool interceptor_ICJI::canTailCall(CORINFO_METHOD_HANDLE callerHnd, /* IN */
167 CORINFO_METHOD_HANDLE declaredCalleeHnd, /* IN */
168 CORINFO_METHOD_HANDLE exactCalleeHnd, /* IN */
169 bool fIsTailPrefix /* IN */
170 )
171{
172 mc->cr->AddCall("canTailCall");
173 bool temp = original_ICorJitInfo->canTailCall(callerHnd, declaredCalleeHnd, exactCalleeHnd, fIsTailPrefix);
174 mc->recCanTailCall(callerHnd, declaredCalleeHnd, exactCalleeHnd, fIsTailPrefix, temp);
175 return temp;
176}
177
178// Reports whether or not a method can be tail called, and why.
179// canTailCall is responsible for reporting all results when it returns
180// false. All other results are reported by the JIT.
181void interceptor_ICJI::reportTailCallDecision(CORINFO_METHOD_HANDLE callerHnd,
182 CORINFO_METHOD_HANDLE calleeHnd,
183 bool fIsTailPrefix,
184 CorInfoTailCall tailCallResult,
185 const char* reason)
186{
187 mc->cr->AddCall("reportTailCallDecision");
188 original_ICorJitInfo->reportTailCallDecision(callerHnd, calleeHnd, fIsTailPrefix, tailCallResult, reason);
189 mc->cr->recReportTailCallDecision(callerHnd, calleeHnd, fIsTailPrefix, tailCallResult, reason);
190}
191
192// get individual exception handler
193void interceptor_ICJI::getEHinfo(CORINFO_METHOD_HANDLE ftn, /* IN */
194 unsigned EHnumber, /* IN */
195 CORINFO_EH_CLAUSE* clause /* OUT */
196 )
197{
198 mc->cr->AddCall("getEHinfo");
199 original_ICorJitInfo->getEHinfo(ftn, EHnumber, clause);
200 mc->recGetEHinfo(ftn, EHnumber, clause);
201}
202
203// return class it belongs to
204CORINFO_CLASS_HANDLE interceptor_ICJI::getMethodClass(CORINFO_METHOD_HANDLE method)
205{
206 mc->cr->AddCall("getMethodClass");
207 CORINFO_CLASS_HANDLE temp = original_ICorJitInfo->getMethodClass(method);
208 mc->recGetMethodClass(method, temp);
209 return temp;
210}
211
212// return module it belongs to
213CORINFO_MODULE_HANDLE interceptor_ICJI::getMethodModule(CORINFO_METHOD_HANDLE method)
214{
215 mc->cr->AddCall("getMethodModule");
216 return original_ICorJitInfo->getMethodModule(method);
217}
218
219// This function returns the offset of the specified method in the
220// vtable of it's owning class or interface.
221void interceptor_ICJI::getMethodVTableOffset(CORINFO_METHOD_HANDLE method, /* IN */
222 unsigned* offsetOfIndirection, /* OUT */
223 unsigned* offsetAfterIndirection, /* OUT */
224 bool* isRelative /* OUT */
225 )
226{
227 mc->cr->AddCall("getMethodVTableOffset");
228 original_ICorJitInfo->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection, isRelative);
229 mc->recGetMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection, isRelative);
230}
231
232// Find the virtual method in implementingClass that overrides virtualMethod.
233// Return null if devirtualization is not possible.
234CORINFO_METHOD_HANDLE interceptor_ICJI::resolveVirtualMethod(CORINFO_METHOD_HANDLE virtualMethod,
235 CORINFO_CLASS_HANDLE implementingClass,
236 CORINFO_CONTEXT_HANDLE ownerType)
237{
238 mc->cr->AddCall("resolveVirtualMethod");
239 CORINFO_METHOD_HANDLE result =
240 original_ICorJitInfo->resolveVirtualMethod(virtualMethod, implementingClass, ownerType);
241 mc->recResolveVirtualMethod(virtualMethod, implementingClass, ownerType, result);
242 return result;
243}
244
245// Get the unboxed entry point for a method, if possible.
246CORINFO_METHOD_HANDLE interceptor_ICJI::getUnboxedEntry(CORINFO_METHOD_HANDLE ftn, bool* requiresInstMethodTableArg)
247{
248 mc->cr->AddCall("getUnboxedEntry");
249 bool localRequiresInstMethodTableArg = false;
250 CORINFO_METHOD_HANDLE result = original_ICorJitInfo->getUnboxedEntry(ftn, &localRequiresInstMethodTableArg);
251 mc->recGetUnboxedEntry(ftn, &localRequiresInstMethodTableArg, result);
252 if (requiresInstMethodTableArg != nullptr)
253 {
254 *requiresInstMethodTableArg = localRequiresInstMethodTableArg;
255 }
256 return result;
257}
258
259// Given T, return the type of the default EqualityComparer<T>.
260// Returns null if the type can't be determined exactly.
261CORINFO_CLASS_HANDLE interceptor_ICJI::getDefaultEqualityComparerClass(CORINFO_CLASS_HANDLE cls)
262{
263 mc->cr->AddCall("getDefaultEqualityComparerClass");
264 CORINFO_CLASS_HANDLE result = original_ICorJitInfo->getDefaultEqualityComparerClass(cls);
265 mc->recGetDefaultEqualityComparerClass(cls, result);
266 return result;
267}
268
269void interceptor_ICJI::expandRawHandleIntrinsic(CORINFO_RESOLVED_TOKEN* pResolvedToken,
270 CORINFO_GENERICHANDLE_RESULT* pResult)
271{
272 mc->cr->AddCall("expandRawHandleIntrinsic");
273 original_ICorJitInfo->expandRawHandleIntrinsic(pResolvedToken, pResult);
274}
275
276// If a method's attributes have (getMethodAttribs) CORINFO_FLG_INTRINSIC set,
277// getIntrinsicID() returns the intrinsic ID.
278CorInfoIntrinsics interceptor_ICJI::getIntrinsicID(CORINFO_METHOD_HANDLE method, bool* pMustExpand /* OUT */
279 )
280{
281 mc->cr->AddCall("getIntrinsicID");
282 CorInfoIntrinsics temp = original_ICorJitInfo->getIntrinsicID(method, pMustExpand);
283 mc->recGetIntrinsicID(method, pMustExpand, temp);
284 return temp;
285}
286
287// Is the given module the System.Numerics.Vectors module?
288bool interceptor_ICJI::isInSIMDModule(CORINFO_CLASS_HANDLE classHnd)
289{
290 mc->cr->AddCall("isInSIMDModule");
291 bool temp = original_ICorJitInfo->isInSIMDModule(classHnd);
292 mc->recIsInSIMDModule(classHnd, temp);
293 return temp;
294}
295
296// return the unmanaged calling convention for a PInvoke
297CorInfoUnmanagedCallConv interceptor_ICJI::getUnmanagedCallConv(CORINFO_METHOD_HANDLE method)
298{
299 mc->cr->AddCall("getUnmanagedCallConv");
300 CorInfoUnmanagedCallConv temp = original_ICorJitInfo->getUnmanagedCallConv(method);
301 mc->recGetUnmanagedCallConv(method, temp);
302 return temp;
303}
304
305// return if any marshaling is required for PInvoke methods. Note that
306// method == 0 => calli. The call site sig is only needed for the varargs or calli case
307BOOL interceptor_ICJI::pInvokeMarshalingRequired(CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* callSiteSig)
308{
309 mc->cr->AddCall("pInvokeMarshalingRequired");
310 BOOL temp = original_ICorJitInfo->pInvokeMarshalingRequired(method, callSiteSig);
311 mc->recPInvokeMarshalingRequired(method, callSiteSig, temp);
312 return temp;
313}
314
315// Check constraints on method type arguments (only).
316// The parent class should be checked separately using satisfiesClassConstraints(parent).
317BOOL interceptor_ICJI::satisfiesMethodConstraints(CORINFO_CLASS_HANDLE parent, // the exact parent of the method
318 CORINFO_METHOD_HANDLE method)
319{
320 mc->cr->AddCall("satisfiesMethodConstraints");
321 BOOL temp = original_ICorJitInfo->satisfiesMethodConstraints(parent, method);
322 mc->recSatisfiesMethodConstraints(parent, method, temp);
323 return temp;
324}
325
326// Given a delegate target class, a target method parent class, a target method,
327// a delegate class, check if the method signature is compatible with the Invoke method of the delegate
328// (under the typical instantiation of any free type variables in the memberref signatures).
329BOOL interceptor_ICJI::isCompatibleDelegate(
330 CORINFO_CLASS_HANDLE objCls, /* type of the delegate target, if any */
331 CORINFO_CLASS_HANDLE methodParentCls, /* exact parent of the target method, if any */
332 CORINFO_METHOD_HANDLE method, /* (representative) target method, if any */
333 CORINFO_CLASS_HANDLE delegateCls, /* exact type of the delegate */
334 BOOL* pfIsOpenDelegate /* is the delegate open */
335 )
336{
337 mc->cr->AddCall("isCompatibleDelegate");
338 BOOL temp =
339 original_ICorJitInfo->isCompatibleDelegate(objCls, methodParentCls, method, delegateCls, pfIsOpenDelegate);
340 mc->recIsCompatibleDelegate(objCls, methodParentCls, method, delegateCls, pfIsOpenDelegate, temp);
341 return temp;
342}
343
344// Indicates if the method is an instance of the generic
345// method that passes (or has passed) verification
346CorInfoInstantiationVerification interceptor_ICJI::isInstantiationOfVerifiedGeneric(CORINFO_METHOD_HANDLE method /* IN
347 */
348 )
349{
350 mc->cr->AddCall("isInstantiationOfVerifiedGeneric");
351 CorInfoInstantiationVerification temp = original_ICorJitInfo->isInstantiationOfVerifiedGeneric(method);
352 mc->recIsInstantiationOfVerifiedGeneric(method, temp);
353 return temp;
354}
355
356// Loads the constraints on a typical method definition, detecting cycles;
357// for use in verification.
358void interceptor_ICJI::initConstraintsForVerification(CORINFO_METHOD_HANDLE method, /* IN */
359 BOOL* pfHasCircularClassConstraints, /* OUT */
360 BOOL* pfHasCircularMethodConstraint /* OUT */
361 )
362{
363 mc->cr->AddCall("initConstraintsForVerification");
364 original_ICorJitInfo->initConstraintsForVerification(method, pfHasCircularClassConstraints,
365 pfHasCircularMethodConstraint);
366 mc->recInitConstraintsForVerification(method, pfHasCircularClassConstraints, pfHasCircularMethodConstraint);
367}
368
369// Returns enum whether the method does not require verification
370// Also see ICorModuleInfo::canSkipVerification
371CorInfoCanSkipVerificationResult interceptor_ICJI::canSkipMethodVerification(CORINFO_METHOD_HANDLE ftnHandle)
372{
373 mc->cr->AddCall("canSkipMethodVerification");
374 CorInfoCanSkipVerificationResult temp = original_ICorJitInfo->canSkipMethodVerification(ftnHandle);
375 mc->recCanSkipMethodVerification(ftnHandle, FALSE, temp);
376 return temp;
377}
378
379// load and restore the method
380void interceptor_ICJI::methodMustBeLoadedBeforeCodeIsRun(CORINFO_METHOD_HANDLE method)
381{
382 mc->cr->AddCall("methodMustBeLoadedBeforeCodeIsRun");
383 original_ICorJitInfo->methodMustBeLoadedBeforeCodeIsRun(method);
384 mc->cr->recMethodMustBeLoadedBeforeCodeIsRun(method);
385}
386
387CORINFO_METHOD_HANDLE interceptor_ICJI::mapMethodDeclToMethodImpl(CORINFO_METHOD_HANDLE method)
388{
389 mc->cr->AddCall("mapMethodDeclToMethodImpl");
390 return original_ICorJitInfo->mapMethodDeclToMethodImpl(method);
391}
392
393// Returns the global cookie for the /GS unsafe buffer checks
394// The cookie might be a constant value (JIT), or a handle to memory location (Ngen)
395void interceptor_ICJI::getGSCookie(GSCookie* pCookieVal, // OUT
396 GSCookie** ppCookieVal // OUT
397 )
398{
399 mc->cr->AddCall("getGSCookie");
400 original_ICorJitInfo->getGSCookie(pCookieVal, ppCookieVal);
401 mc->recGetGSCookie(pCookieVal, ppCookieVal);
402}
403
404/**********************************************************************************/
405//
406// ICorModuleInfo
407//
408/**********************************************************************************/
409// Resolve metadata token into runtime method handles.
410void interceptor_ICJI::resolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN* pResolvedToken)
411{
412 struct Param : FilterSuperPMIExceptionsParam_CaptureException
413 {
414 interceptor_ICJI* pThis;
415 CORINFO_RESOLVED_TOKEN* pResolvedToken;
416 } param;
417 param.pThis = this;
418 param.pResolvedToken = pResolvedToken;
419
420 PAL_TRY(Param*, pOuterParam, &param)
421 {
422 PAL_TRY(Param*, pParam, pOuterParam)
423 {
424 pParam->pThis->mc->cr->AddCall("resolveToken");
425 pParam->pThis->original_ICorJitInfo->resolveToken(pParam->pResolvedToken);
426 }
427 PAL_EXCEPT_FILTER(FilterSuperPMIExceptions_CaptureExceptionAndContinue)
428 {
429 }
430 PAL_ENDTRY
431 }
432 PAL_FINALLY
433 {
434 this->mc->recResolveToken(param.pResolvedToken, param.exceptionCode);
435 }
436 PAL_ENDTRY
437}
438
439bool interceptor_ICJI::tryResolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN* pResolvedToken)
440{
441 mc->cr->AddCall("tryResolveToken");
442 bool success = original_ICorJitInfo->tryResolveToken(pResolvedToken);
443 mc->recResolveToken(pResolvedToken, success);
444 return success;
445}
446
447// Signature information about the call sig
448void interceptor_ICJI::findSig(CORINFO_MODULE_HANDLE module, /* IN */
449 unsigned sigTOK, /* IN */
450 CORINFO_CONTEXT_HANDLE context, /* IN */
451 CORINFO_SIG_INFO* sig /* OUT */
452 )
453{
454 mc->cr->AddCall("findSig");
455 original_ICorJitInfo->findSig(module, sigTOK, context, sig);
456 mc->recFindSig(module, sigTOK, context, sig);
457}
458
459// for Varargs, the signature at the call site may differ from
460// the signature at the definition. Thus we need a way of
461// fetching the call site information
462void interceptor_ICJI::findCallSiteSig(CORINFO_MODULE_HANDLE module, /* IN */
463 unsigned methTOK, /* IN */
464 CORINFO_CONTEXT_HANDLE context, /* IN */
465 CORINFO_SIG_INFO* sig /* OUT */
466 )
467{
468 mc->cr->AddCall("findCallSiteSig");
469 original_ICorJitInfo->findCallSiteSig(module, methTOK, context, sig);
470 mc->recFindCallSiteSig(module, methTOK, context, sig);
471}
472
473CORINFO_CLASS_HANDLE interceptor_ICJI::getTokenTypeAsHandle(CORINFO_RESOLVED_TOKEN* pResolvedToken /* IN */)
474{
475 mc->cr->AddCall("getTokenTypeAsHandle");
476 CORINFO_CLASS_HANDLE temp = original_ICorJitInfo->getTokenTypeAsHandle(pResolvedToken);
477 mc->recGetTokenTypeAsHandle(pResolvedToken, temp);
478 return temp;
479}
480
481// Returns true if the module does not require verification
482//
483// If fQuickCheckOnlyWithoutCommit=TRUE, the function only checks that the
484// module does not currently require verification in the current AppDomain.
485// This decision could change in the future, and so should not be cached.
486// If it is cached, it should only be used as a hint.
487// This is only used by ngen for calculating certain hints.
488//
489// Returns enum whether the module does not require verification
490// Also see ICorMethodInfo::canSkipMethodVerification();
491CorInfoCanSkipVerificationResult interceptor_ICJI::canSkipVerification(CORINFO_MODULE_HANDLE module /* IN */
492 )
493{
494 mc->cr->AddCall("canSkipVerification");
495 return original_ICorJitInfo->canSkipVerification(module);
496}
497
498// Checks if the given metadata token is valid
499BOOL interceptor_ICJI::isValidToken(CORINFO_MODULE_HANDLE module, /* IN */
500 unsigned metaTOK /* IN */
501 )
502{
503 mc->cr->AddCall("isValidToken");
504 BOOL result = original_ICorJitInfo->isValidToken(module, metaTOK);
505 mc->recIsValidToken(module, metaTOK, result);
506 return result;
507}
508
509// Checks if the given metadata token is valid StringRef
510BOOL interceptor_ICJI::isValidStringRef(CORINFO_MODULE_HANDLE module, /* IN */
511 unsigned metaTOK /* IN */
512 )
513{
514 mc->cr->AddCall("isValidStringRef");
515 BOOL temp = original_ICorJitInfo->isValidStringRef(module, metaTOK);
516 mc->recIsValidStringRef(module, metaTOK, temp);
517 return temp;
518}
519
520BOOL interceptor_ICJI::shouldEnforceCallvirtRestriction(CORINFO_MODULE_HANDLE scope)
521{
522 mc->cr->AddCall("shouldEnforceCallvirtRestriction");
523 BOOL temp = original_ICorJitInfo->shouldEnforceCallvirtRestriction(scope);
524 mc->recShouldEnforceCallvirtRestriction(scope, temp);
525 return temp;
526}
527
528/**********************************************************************************/
529//
530// ICorClassInfo
531//
532/**********************************************************************************/
533
534// If the value class 'cls' is isomorphic to a primitive type it will
535// return that type, otherwise it will return CORINFO_TYPE_VALUECLASS
536CorInfoType interceptor_ICJI::asCorInfoType(CORINFO_CLASS_HANDLE cls)
537{
538 mc->cr->AddCall("asCorInfoType");
539 CorInfoType temp = original_ICorJitInfo->asCorInfoType(cls);
540 mc->recAsCorInfoType(cls, temp);
541 return temp;
542}
543
544// for completeness
545const char* interceptor_ICJI::getClassName(CORINFO_CLASS_HANDLE cls)
546{
547 mc->cr->AddCall("getClassName");
548 const char* result = original_ICorJitInfo->getClassName(cls);
549 mc->recGetClassName(cls, result);
550 return result;
551}
552
553const char* interceptor_ICJI::getClassNameFromMetadata(CORINFO_CLASS_HANDLE cls, const char** namespaceName)
554{
555 mc->cr->AddCall("getClassNameFromMetadata");
556 const char* temp = original_ICorJitInfo->getClassNameFromMetadata(cls, namespaceName);
557 mc->recGetClassNameFromMetadata(cls, (char*)temp, namespaceName);
558 return temp;
559}
560
561CORINFO_CLASS_HANDLE interceptor_ICJI::getTypeInstantiationArgument(CORINFO_CLASS_HANDLE cls, unsigned index)
562{
563 mc->cr->AddCall("getTypeInstantiationArgument");
564 CORINFO_CLASS_HANDLE temp = original_ICorJitInfo->getTypeInstantiationArgument(cls, index);
565 mc->recGetTypeInstantiationArgument(cls, temp, index);
566 return temp;
567}
568
569// Append a (possibly truncated) representation of the type cls to the preallocated buffer ppBuf of length pnBufLen
570// If fNamespace=TRUE, include the namespace/enclosing classes
571// If fFullInst=TRUE (regardless of fNamespace and fAssembly), include namespace and assembly for any type parameters
572// If fAssembly=TRUE, suffix with a comma and the full assembly qualification
573// return size of representation
574int interceptor_ICJI::appendClassName(__deref_inout_ecount(*pnBufLen) WCHAR** ppBuf,
575 int* pnBufLen,
576 CORINFO_CLASS_HANDLE cls,
577 BOOL fNamespace,
578 BOOL fFullInst,
579 BOOL fAssembly)
580{
581 mc->cr->AddCall("appendClassName");
582 WCHAR* pBuf = *ppBuf;
583 int nLen = original_ICorJitInfo->appendClassName(ppBuf, pnBufLen, cls, fNamespace, fFullInst, fAssembly);
584 mc->recAppendClassName(cls, fNamespace, fFullInst, fAssembly, pBuf);
585 return nLen;
586}
587
588// Quick check whether the type is a value class. Returns the same value as getClassAttribs(cls) &
589// CORINFO_FLG_VALUECLASS, except faster.
590BOOL interceptor_ICJI::isValueClass(CORINFO_CLASS_HANDLE cls)
591{
592 mc->cr->AddCall("isValueClass");
593 BOOL temp = original_ICorJitInfo->isValueClass(cls);
594 mc->recIsValueClass(cls, temp);
595 return temp;
596}
597
598// Decides how the JIT should do the optimization to inline the check for
599// GetTypeFromHandle(handle) == obj.GetType() (for CORINFO_INLINE_TYPECHECK_SOURCE_VTABLE)
600// GetTypeFromHandle(X) == GetTypeFromHandle(Y) (for CORINFO_INLINE_TYPECHECK_SOURCE_TOKEN)
601CorInfoInlineTypeCheck interceptor_ICJI::canInlineTypeCheck(CORINFO_CLASS_HANDLE cls,
602 CorInfoInlineTypeCheckSource source)
603{
604 mc->cr->AddCall("canInlineTypeCheck");
605 CorInfoInlineTypeCheck temp = original_ICorJitInfo->canInlineTypeCheck(cls, source);
606 mc->recCanInlineTypeCheck(cls, source, temp);
607 return temp;
608}
609
610// If this method returns true, JIT will do optimization to inline the check for
611// GetTypeFromHandle(handle) == obj.GetType()
612BOOL interceptor_ICJI::canInlineTypeCheckWithObjectVTable(CORINFO_CLASS_HANDLE cls)
613{
614 mc->cr->AddCall("canInlineTypeCheckWithObjectVTable");
615 BOOL temp = original_ICorJitInfo->canInlineTypeCheckWithObjectVTable(cls);
616 mc->recCanInlineTypeCheckWithObjectVTable(cls, temp);
617 return temp;
618}
619
620// return flags (defined above, CORINFO_FLG_PUBLIC ...)
621DWORD interceptor_ICJI::getClassAttribs(CORINFO_CLASS_HANDLE cls)
622{
623 mc->cr->AddCall("getClassAttribs");
624 DWORD temp = original_ICorJitInfo->getClassAttribs(cls);
625 mc->recGetClassAttribs(cls, temp);
626 return temp;
627}
628
629// Returns "TRUE" iff "cls" is a struct type such that return buffers used for returning a value
630// of this type must be stack-allocated. This will generally be true only if the struct
631// contains GC pointers, and does not exceed some size limit. Maintaining this as an invariant allows
632// an optimization: the JIT may assume that return buffer pointers for return types for which this predicate
633// returns TRUE are always stack allocated, and thus, that stores to the GC-pointer fields of such return
634// buffers do not require GC write barriers.
635BOOL interceptor_ICJI::isStructRequiringStackAllocRetBuf(CORINFO_CLASS_HANDLE cls)
636{
637 mc->cr->AddCall("isStructRequiringStackAllocRetBuf");
638 BOOL temp = original_ICorJitInfo->isStructRequiringStackAllocRetBuf(cls);
639 mc->recIsStructRequiringStackAllocRetBuf(cls, temp);
640 return temp;
641}
642
643CORINFO_MODULE_HANDLE interceptor_ICJI::getClassModule(CORINFO_CLASS_HANDLE cls)
644{
645 mc->cr->AddCall("getClassModule");
646 return original_ICorJitInfo->getClassModule(cls);
647}
648
649// Returns the assembly that contains the module "mod".
650CORINFO_ASSEMBLY_HANDLE interceptor_ICJI::getModuleAssembly(CORINFO_MODULE_HANDLE mod)
651{
652 mc->cr->AddCall("getModuleAssembly");
653 return original_ICorJitInfo->getModuleAssembly(mod);
654}
655
656// Returns the name of the assembly "assem".
657const char* interceptor_ICJI::getAssemblyName(CORINFO_ASSEMBLY_HANDLE assem)
658{
659 mc->cr->AddCall("getAssemblyName");
660 return original_ICorJitInfo->getAssemblyName(assem);
661}
662
663// Allocate and delete process-lifetime objects. Should only be
664// referred to from static fields, lest a leak occur.
665// Note that "LongLifetimeFree" does not execute destructors, if "obj"
666// is an array of a struct type with a destructor.
667void* interceptor_ICJI::LongLifetimeMalloc(size_t sz)
668{
669 mc->cr->AddCall("LongLifetimeMalloc");
670 return original_ICorJitInfo->LongLifetimeMalloc(sz);
671}
672
673void interceptor_ICJI::LongLifetimeFree(void* obj)
674{
675 mc->cr->AddCall("LongLifetimeFree");
676 original_ICorJitInfo->LongLifetimeFree(obj);
677}
678
679size_t interceptor_ICJI::getClassModuleIdForStatics(CORINFO_CLASS_HANDLE cls,
680 CORINFO_MODULE_HANDLE* pModule,
681 void** ppIndirection)
682{
683 mc->cr->AddCall("getClassModuleIdForStatics");
684 size_t temp = original_ICorJitInfo->getClassModuleIdForStatics(cls, pModule, ppIndirection);
685 mc->recGetClassModuleIdForStatics(cls, pModule, ppIndirection, temp);
686 return temp;
687}
688
689// return the number of bytes needed by an instance of the class
690unsigned interceptor_ICJI::getClassSize(CORINFO_CLASS_HANDLE cls)
691{
692 mc->cr->AddCall("getClassSize");
693 unsigned temp = original_ICorJitInfo->getClassSize(cls);
694 mc->recGetClassSize(cls, temp);
695 return temp;
696}
697
698// return the number of bytes needed by an instance of the class allocated on the heap
699unsigned interceptor_ICJI::getHeapClassSize(CORINFO_CLASS_HANDLE cls)
700{
701 mc->cr->AddCall("getHeapClassSize");
702 unsigned temp = original_ICorJitInfo->getHeapClassSize(cls);
703 mc->recGetHeapClassSize(cls, temp);
704 return temp;
705}
706
707BOOL interceptor_ICJI::canAllocateOnStack(CORINFO_CLASS_HANDLE cls)
708{
709 mc->cr->AddCall("canAllocateOnStack");
710 BOOL temp = original_ICorJitInfo->canAllocateOnStack(cls);
711 mc->recCanAllocateOnStack(cls, temp);
712 return temp;
713}
714
715unsigned interceptor_ICJI::getClassAlignmentRequirement(CORINFO_CLASS_HANDLE cls, BOOL fDoubleAlignHint)
716{
717 mc->cr->AddCall("getClassAlignmentRequirement");
718 unsigned temp = original_ICorJitInfo->getClassAlignmentRequirement(cls, fDoubleAlignHint);
719 mc->recGetClassAlignmentRequirement(cls, fDoubleAlignHint, temp);
720 return temp;
721}
722
723// This is only called for Value classes. It returns a boolean array
724// in representing of 'cls' from a GC perspective. The class is
725// assumed to be an array of machine words
726// (of length // getClassSize(cls) / sizeof(void*)),
727// 'gcPtrs' is a pointer to an array of BYTEs of this length.
728// getClassGClayout fills in this array so that gcPtrs[i] is set
729// to one of the CorInfoGCType values which is the GC type of
730// the i-th machine word of an object of type 'cls'
731// returns the number of GC pointers in the array
732unsigned interceptor_ICJI::getClassGClayout(CORINFO_CLASS_HANDLE cls, /* IN */
733 BYTE* gcPtrs /* OUT */
734 )
735{
736 mc->cr->AddCall("getClassGClayout");
737 unsigned temp = original_ICorJitInfo->getClassGClayout(cls, gcPtrs);
738 unsigned len = (getClassSize(cls) + sizeof(void*) - 1) / sizeof(void*);
739 mc->recGetClassGClayout(cls, gcPtrs, len, temp);
740 return temp;
741}
742
743// returns the number of instance fields in a class
744unsigned interceptor_ICJI::getClassNumInstanceFields(CORINFO_CLASS_HANDLE cls /* IN */
745 )
746{
747 mc->cr->AddCall("getClassNumInstanceFields");
748 unsigned temp = original_ICorJitInfo->getClassNumInstanceFields(cls);
749 mc->recGetClassNumInstanceFields(cls, temp);
750 return temp;
751}
752
753CORINFO_FIELD_HANDLE interceptor_ICJI::getFieldInClass(CORINFO_CLASS_HANDLE clsHnd, INT num)
754{
755 mc->cr->AddCall("getFieldInClass");
756 CORINFO_FIELD_HANDLE temp = original_ICorJitInfo->getFieldInClass(clsHnd, num);
757 mc->recGetFieldInClass(clsHnd, num, temp);
758 return temp;
759}
760
761BOOL interceptor_ICJI::checkMethodModifier(CORINFO_METHOD_HANDLE hMethod, LPCSTR modifier, BOOL fOptional)
762{
763 mc->cr->AddCall("checkMethodModifier");
764 BOOL result = original_ICorJitInfo->checkMethodModifier(hMethod, modifier, fOptional);
765 mc->recCheckMethodModifier(hMethod, modifier, fOptional, result);
766 return result;
767}
768
769// returns the "NEW" helper optimized for "newCls."
770CorInfoHelpFunc interceptor_ICJI::getNewHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken,
771 CORINFO_METHOD_HANDLE callerHandle,
772 bool* pHasSideEffects)
773{
774 mc->cr->AddCall("getNewHelper");
775 CorInfoHelpFunc temp = original_ICorJitInfo->getNewHelper(pResolvedToken, callerHandle, pHasSideEffects);
776 mc->recGetNewHelper(pResolvedToken, callerHandle, pHasSideEffects, temp);
777 return temp;
778}
779
780// returns the newArr (1-Dim array) helper optimized for "arrayCls."
781CorInfoHelpFunc interceptor_ICJI::getNewArrHelper(CORINFO_CLASS_HANDLE arrayCls)
782{
783 mc->cr->AddCall("getNewArrHelper");
784 CorInfoHelpFunc temp = original_ICorJitInfo->getNewArrHelper(arrayCls);
785 mc->recGetNewArrHelper(arrayCls, temp);
786 return temp;
787}
788
789// returns the optimized "IsInstanceOf" or "ChkCast" helper
790CorInfoHelpFunc interceptor_ICJI::getCastingHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fThrowing)
791{
792 mc->cr->AddCall("getCastingHelper");
793 CorInfoHelpFunc temp = original_ICorJitInfo->getCastingHelper(pResolvedToken, fThrowing);
794 mc->recGetCastingHelper(pResolvedToken, fThrowing, temp);
795 return temp;
796}
797
798// returns helper to trigger static constructor
799CorInfoHelpFunc interceptor_ICJI::getSharedCCtorHelper(CORINFO_CLASS_HANDLE clsHnd)
800{
801 mc->cr->AddCall("getSharedCCtorHelper");
802 CorInfoHelpFunc temp = original_ICorJitInfo->getSharedCCtorHelper(clsHnd);
803 mc->recGetSharedCCtorHelper(clsHnd, temp);
804 return temp;
805}
806
807CorInfoHelpFunc interceptor_ICJI::getSecurityPrologHelper(CORINFO_METHOD_HANDLE ftn)
808{
809 mc->cr->AddCall("getSecurityPrologHelper");
810 CorInfoHelpFunc temp = original_ICorJitInfo->getSecurityPrologHelper(ftn);
811 mc->recGetSecurityPrologHelper(ftn, temp);
812 return temp;
813}
814
815// This is not pretty. Boxing nullable<T> actually returns
816// a boxed<T> not a boxed Nullable<T>. This call allows the verifier
817// to call back to the EE on the 'box' instruction and get the transformed
818// type to use for verification.
819CORINFO_CLASS_HANDLE interceptor_ICJI::getTypeForBox(CORINFO_CLASS_HANDLE cls)
820{
821 mc->cr->AddCall("getTypeForBox");
822 CORINFO_CLASS_HANDLE temp = original_ICorJitInfo->getTypeForBox(cls);
823 mc->recGetTypeForBox(cls, temp);
824 return temp;
825}
826
827// returns the correct box helper for a particular class. Note
828// that if this returns CORINFO_HELP_BOX, the JIT can assume
829// 'standard' boxing (allocate object and copy), and optimize
830CorInfoHelpFunc interceptor_ICJI::getBoxHelper(CORINFO_CLASS_HANDLE cls)
831{
832 mc->cr->AddCall("getBoxHelper");
833 CorInfoHelpFunc temp = original_ICorJitInfo->getBoxHelper(cls);
834 mc->recGetBoxHelper(cls, temp);
835 return temp;
836}
837
838// returns the unbox helper. If 'helperCopies' points to a true
839// value it means the JIT is requesting a helper that unboxes the
840// value into a particular location and thus has the signature
841// void unboxHelper(void* dest, CORINFO_CLASS_HANDLE cls, Object* obj)
842// Otherwise (it is null or points at a FALSE value) it is requesting
843// a helper that returns a pointer to the unboxed data
844// void* unboxHelper(CORINFO_CLASS_HANDLE cls, Object* obj)
845// The EE has the option of NOT returning the copy style helper
846// (But must be able to always honor the non-copy style helper)
847// The EE set 'helperCopies' on return to indicate what kind of
848// helper has been created.
849CorInfoHelpFunc interceptor_ICJI::getUnBoxHelper(CORINFO_CLASS_HANDLE cls)
850{
851 mc->cr->AddCall("getUnBoxHelper");
852 CorInfoHelpFunc temp = original_ICorJitInfo->getUnBoxHelper(cls);
853 mc->recGetUnBoxHelper(cls, temp);
854 return temp;
855}
856
857bool interceptor_ICJI::getReadyToRunHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken,
858 CORINFO_LOOKUP_KIND* pGenericLookupKind,
859 CorInfoHelpFunc id,
860 CORINFO_CONST_LOOKUP* pLookup)
861{
862 mc->cr->AddCall("getReadyToRunHelper");
863 bool result = original_ICorJitInfo->getReadyToRunHelper(pResolvedToken, pGenericLookupKind, id, pLookup);
864 mc->recGetReadyToRunHelper(pResolvedToken, pGenericLookupKind, id, pLookup, result);
865 return result;
866}
867
868void interceptor_ICJI::getReadyToRunDelegateCtorHelper(CORINFO_RESOLVED_TOKEN* pTargetMethod,
869 CORINFO_CLASS_HANDLE delegateType,
870 CORINFO_LOOKUP* pLookup)
871{
872 mc->cr->AddCall("getReadyToRunDelegateCtorHelper");
873 original_ICorJitInfo->getReadyToRunDelegateCtorHelper(pTargetMethod, delegateType, pLookup);
874 mc->recGetReadyToRunDelegateCtorHelper(pTargetMethod, delegateType, pLookup);
875}
876
877const char* interceptor_ICJI::getHelperName(CorInfoHelpFunc funcNum)
878{
879 mc->cr->AddCall("getHelperName");
880 const char* temp = original_ICorJitInfo->getHelperName(funcNum);
881 mc->recGetHelperName(funcNum, temp);
882 return temp;
883}
884
885// This function tries to initialize the class (run the class constructor).
886// this function returns whether the JIT must insert helper calls before
887// accessing static field or method.
888//
889// See code:ICorClassInfo#ClassConstruction.
890CorInfoInitClassResult interceptor_ICJI::initClass(
891 CORINFO_FIELD_HANDLE field, // Non-nullptr - inquire about cctor trigger before static field access
892 // nullptr - inquire about cctor trigger in method prolog
893 CORINFO_METHOD_HANDLE method, // Method referencing the field or prolog
894 CORINFO_CONTEXT_HANDLE context, // Exact context of method
895 BOOL speculative // TRUE means don't actually run it
896 )
897{
898 mc->cr->AddCall("initClass");
899 CorInfoInitClassResult temp = original_ICorJitInfo->initClass(field, method, context, speculative);
900 mc->recInitClass(field, method, context, speculative, temp);
901 return temp;
902}
903
904// This used to be called "loadClass". This records the fact
905// that the class must be loaded (including restored if necessary) before we execute the
906// code that we are currently generating. When jitting code
907// the function loads the class immediately. When zapping code
908// the zapper will if necessary use the call to record the fact that we have
909// to do a fixup/restore before running the method currently being generated.
910//
911// This is typically used to ensure value types are loaded before zapped
912// code that manipulates them is executed, so that the GC can access information
913// about those value types.
914void interceptor_ICJI::classMustBeLoadedBeforeCodeIsRun(CORINFO_CLASS_HANDLE cls)
915{
916 mc->cr->AddCall("classMustBeLoadedBeforeCodeIsRun");
917 original_ICorJitInfo->classMustBeLoadedBeforeCodeIsRun(cls);
918 mc->cr->recClassMustBeLoadedBeforeCodeIsRun(cls);
919}
920
921// returns the class handle for the special builtin classes
922CORINFO_CLASS_HANDLE interceptor_ICJI::getBuiltinClass(CorInfoClassId classId)
923{
924 mc->cr->AddCall("getBuiltinClass");
925 CORINFO_CLASS_HANDLE temp = original_ICorJitInfo->getBuiltinClass(classId);
926 mc->recGetBuiltinClass(classId, temp);
927 return temp;
928}
929
930// "System.Int32" ==> CORINFO_TYPE_INT..
931CorInfoType interceptor_ICJI::getTypeForPrimitiveValueClass(CORINFO_CLASS_HANDLE cls)
932{
933 mc->cr->AddCall("getTypeForPrimitiveValueClass");
934 CorInfoType temp = original_ICorJitInfo->getTypeForPrimitiveValueClass(cls);
935 mc->recGetTypeForPrimitiveValueClass(cls, temp);
936 return temp;
937}
938
939// "System.Int32" ==> CORINFO_TYPE_INT..
940// "System.UInt32" ==> CORINFO_TYPE_UINT..
941CorInfoType interceptor_ICJI::getTypeForPrimitiveNumericClass(CORINFO_CLASS_HANDLE cls)
942{
943 mc->cr->AddCall("getTypeForPrimitiveNumericClass");
944 CorInfoType temp = original_ICorJitInfo->getTypeForPrimitiveNumericClass(cls);
945 mc->recGetTypeForPrimitiveNumericClass(cls, temp);
946 return temp;
947}
948
949// TRUE if child is a subtype of parent
950// if parent is an interface, then does child implement / extend parent
951BOOL interceptor_ICJI::canCast(CORINFO_CLASS_HANDLE child, // subtype (extends parent)
952 CORINFO_CLASS_HANDLE parent // base type
953 )
954{
955 mc->cr->AddCall("canCast");
956 BOOL temp = original_ICorJitInfo->canCast(child, parent);
957 mc->recCanCast(child, parent, temp);
958 return temp;
959}
960
961// TRUE if cls1 and cls2 are considered equivalent types.
962BOOL interceptor_ICJI::areTypesEquivalent(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2)
963{
964 mc->cr->AddCall("areTypesEquivalent");
965 BOOL temp = original_ICorJitInfo->areTypesEquivalent(cls1, cls2);
966 mc->recAreTypesEquivalent(cls1, cls2, temp);
967 return temp;
968}
969
970// See if a cast from fromClass to toClass will succeed, fail, or needs
971// to be resolved at runtime.
972TypeCompareState interceptor_ICJI::compareTypesForCast(CORINFO_CLASS_HANDLE fromClass, CORINFO_CLASS_HANDLE toClass)
973{
974 mc->cr->AddCall("compareTypesForCast");
975 TypeCompareState temp = original_ICorJitInfo->compareTypesForCast(fromClass, toClass);
976 mc->recCompareTypesForCast(fromClass, toClass, temp);
977 return temp;
978}
979
980// See if types represented by cls1 and cls2 compare equal, not
981// equal, or the comparison needs to be resolved at runtime.
982TypeCompareState interceptor_ICJI::compareTypesForEquality(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2)
983{
984 mc->cr->AddCall("compareTypesForEquality");
985 TypeCompareState temp = original_ICorJitInfo->compareTypesForEquality(cls1, cls2);
986 mc->recCompareTypesForEquality(cls1, cls2, temp);
987 return temp;
988}
989
990// returns is the intersection of cls1 and cls2.
991CORINFO_CLASS_HANDLE interceptor_ICJI::mergeClasses(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2)
992{
993 mc->cr->AddCall("mergeClasses");
994 CORINFO_CLASS_HANDLE temp = original_ICorJitInfo->mergeClasses(cls1, cls2);
995 mc->recMergeClasses(cls1, cls2, temp);
996 return temp;
997}
998
999// Given a class handle, returns the Parent type.
1000// For COMObjectType, it returns Class Handle of System.Object.
1001// Returns 0 if System.Object is passed in.
1002CORINFO_CLASS_HANDLE interceptor_ICJI::getParentType(CORINFO_CLASS_HANDLE cls)
1003{
1004 mc->cr->AddCall("getParentType");
1005 CORINFO_CLASS_HANDLE temp = original_ICorJitInfo->getParentType(cls);
1006 mc->recGetParentType(cls, temp);
1007 return temp;
1008}
1009
1010// Returns the CorInfoType of the "child type". If the child type is
1011// not a primitive type, *clsRet will be set.
1012// Given an Array of Type Foo, returns Foo.
1013// Given BYREF Foo, returns Foo
1014CorInfoType interceptor_ICJI::getChildType(CORINFO_CLASS_HANDLE clsHnd, CORINFO_CLASS_HANDLE* clsRet)
1015{
1016 mc->cr->AddCall("getChildType");
1017 CorInfoType temp = original_ICorJitInfo->getChildType(clsHnd, clsRet);
1018 mc->recGetChildType(clsHnd, clsRet, temp);
1019 return temp;
1020}
1021
1022// Check constraints on type arguments of this class and parent classes
1023BOOL interceptor_ICJI::satisfiesClassConstraints(CORINFO_CLASS_HANDLE cls)
1024{
1025 mc->cr->AddCall("satisfiesClassConstraints");
1026 BOOL temp = original_ICorJitInfo->satisfiesClassConstraints(cls);
1027 mc->recSatisfiesClassConstraints(cls, temp);
1028 return temp;
1029}
1030
1031// Check if this is a single dimensional array type
1032BOOL interceptor_ICJI::isSDArray(CORINFO_CLASS_HANDLE cls)
1033{
1034 mc->cr->AddCall("isSDArray");
1035 BOOL temp = original_ICorJitInfo->isSDArray(cls);
1036 mc->recIsSDArray(cls, temp);
1037 return temp;
1038}
1039
1040// Get the numbmer of dimensions in an array
1041unsigned interceptor_ICJI::getArrayRank(CORINFO_CLASS_HANDLE cls)
1042{
1043 mc->cr->AddCall("getArrayRank");
1044 unsigned result = original_ICorJitInfo->getArrayRank(cls);
1045 mc->recGetArrayRank(cls, result);
1046 return result;
1047}
1048
1049// Get static field data for an array
1050void* interceptor_ICJI::getArrayInitializationData(CORINFO_FIELD_HANDLE field, DWORD size)
1051{
1052 mc->cr->AddCall("getArrayInitializationData");
1053 void* temp = original_ICorJitInfo->getArrayInitializationData(field, size);
1054 mc->recGetArrayInitializationData(field, size, temp);
1055 return temp;
1056}
1057
1058// Check Visibility rules.
1059CorInfoIsAccessAllowedResult interceptor_ICJI::canAccessClass(
1060 CORINFO_RESOLVED_TOKEN* pResolvedToken,
1061 CORINFO_METHOD_HANDLE callerHandle,
1062 CORINFO_HELPER_DESC* pAccessHelper /* If canAccessMethod returns something other
1063 than ALLOWED, then this is filled in. */
1064 )
1065{
1066 mc->cr->AddCall("canAccessClass");
1067 CorInfoIsAccessAllowedResult temp =
1068 original_ICorJitInfo->canAccessClass(pResolvedToken, callerHandle, pAccessHelper);
1069 mc->recCanAccessClass(pResolvedToken, callerHandle, pAccessHelper, temp);
1070 return temp;
1071}
1072
1073/**********************************************************************************/
1074//
1075// ICorFieldInfo
1076//
1077/**********************************************************************************/
1078// this function is for debugging only. It returns the field name
1079// and if 'moduleName' is non-null, it sets it to something that will
1080// says which method (a class name, or a module name)
1081const char* interceptor_ICJI::getFieldName(CORINFO_FIELD_HANDLE ftn, /* IN */
1082 const char** moduleName /* OUT */
1083 )
1084{
1085 mc->cr->AddCall("getFieldName");
1086 const char* temp = original_ICorJitInfo->getFieldName(ftn, moduleName);
1087 mc->recGetFieldName(ftn, moduleName, temp);
1088 return temp;
1089}
1090
1091// return class it belongs to
1092CORINFO_CLASS_HANDLE interceptor_ICJI::getFieldClass(CORINFO_FIELD_HANDLE field)
1093{
1094 mc->cr->AddCall("getFieldClass");
1095 CORINFO_CLASS_HANDLE temp = original_ICorJitInfo->getFieldClass(field);
1096 mc->recGetFieldClass(field, temp);
1097 return temp;
1098}
1099
1100// Return the field's type, if it is CORINFO_TYPE_VALUECLASS 'structType' is set
1101// the field's value class (if 'structType' == 0, then don't bother
1102// the structure info).
1103//
1104// 'memberParent' is typically only set when verifying. It should be the
1105// result of calling getMemberParent.
1106CorInfoType interceptor_ICJI::getFieldType(CORINFO_FIELD_HANDLE field,
1107 CORINFO_CLASS_HANDLE* structType,
1108 CORINFO_CLASS_HANDLE memberParent /* IN */
1109 )
1110{
1111 mc->cr->AddCall("getFieldType");
1112 CorInfoType temp = original_ICorJitInfo->getFieldType(field, structType, memberParent);
1113 mc->recGetFieldType(field, structType, memberParent, temp);
1114 return temp;
1115}
1116
1117// return the data member's instance offset
1118unsigned interceptor_ICJI::getFieldOffset(CORINFO_FIELD_HANDLE field)
1119{
1120 mc->cr->AddCall("getFieldOffset");
1121 unsigned temp = original_ICorJitInfo->getFieldOffset(field);
1122 mc->recGetFieldOffset(field, temp);
1123 return temp;
1124}
1125
1126// TODO: jit64 should be switched to the same plan as the i386 jits - use
1127// getClassGClayout to figure out the need for writebarrier helper, and inline the copying.
1128// The interpretted value class copy is slow. Once this happens, USE_WRITE_BARRIER_HELPERS
1129bool interceptor_ICJI::isWriteBarrierHelperRequired(CORINFO_FIELD_HANDLE field)
1130{
1131 mc->cr->AddCall("isWriteBarrierHelperRequired");
1132 bool result = original_ICorJitInfo->isWriteBarrierHelperRequired(field);
1133 mc->recIsWriteBarrierHelperRequired(field, result);
1134 return result;
1135}
1136
1137void interceptor_ICJI::getFieldInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken,
1138 CORINFO_METHOD_HANDLE callerHandle,
1139 CORINFO_ACCESS_FLAGS flags,
1140 CORINFO_FIELD_INFO* pResult)
1141{
1142 mc->cr->AddCall("getFieldInfo");
1143 original_ICorJitInfo->getFieldInfo(pResolvedToken, callerHandle, flags, pResult);
1144 mc->recGetFieldInfo(pResolvedToken, callerHandle, flags, pResult);
1145}
1146
1147// Returns true iff "fldHnd" represents a static field.
1148bool interceptor_ICJI::isFieldStatic(CORINFO_FIELD_HANDLE fldHnd)
1149{
1150 mc->cr->AddCall("isFieldStatic");
1151 bool result = original_ICorJitInfo->isFieldStatic(fldHnd);
1152 mc->recIsFieldStatic(fldHnd, result);
1153 return result;
1154}
1155
1156/*********************************************************************************/
1157//
1158// ICorDebugInfo
1159//
1160/*********************************************************************************/
1161// Query the EE to find out where interesting break points
1162// in the code are. The native compiler will ensure that these places
1163// have a corresponding break point in native code.
1164//
1165// Note that unless CORJIT_FLAG_DEBUG_CODE is specified, this function will
1166// be used only as a hint and the native compiler should not change its
1167// code generation.
1168void interceptor_ICJI::getBoundaries(CORINFO_METHOD_HANDLE ftn, // [IN] method of interest
1169 unsigned int* cILOffsets, // [OUT] size of pILOffsets
1170 DWORD** pILOffsets, // [OUT] IL offsets of interest
1171 // jit MUST free with freeArray!
1172 ICorDebugInfo::BoundaryTypes* implictBoundaries // [OUT] tell jit, all boundries of
1173 // this type
1174 )
1175{
1176 mc->cr->AddCall("getBoundaries");
1177 original_ICorJitInfo->getBoundaries(ftn, cILOffsets, pILOffsets, implictBoundaries);
1178 mc->recGetBoundaries(ftn, cILOffsets, pILOffsets, implictBoundaries);
1179}
1180
1181// Report back the mapping from IL to native code,
1182// this map should include all boundaries that 'getBoundaries'
1183// reported as interesting to the debugger.
1184
1185// Note that debugger (and profiler) is assuming that all of the
1186// offsets form a contiguous block of memory, and that the
1187// OffsetMapping is sorted in order of increasing native offset.
1188// Note - Ownership of pMap is transfered with this call. We need to record it before its passed on to the EE.
1189void interceptor_ICJI::setBoundaries(CORINFO_METHOD_HANDLE ftn, // [IN] method of interest
1190 ULONG32 cMap, // [IN] size of pMap
1191 ICorDebugInfo::OffsetMapping* pMap // [IN] map including all points of interest.
1192 // jit allocated with allocateArray, EE
1193 // frees
1194 )
1195{
1196 mc->cr->AddCall("setBoundaries");
1197 mc->cr->recSetBoundaries(ftn, cMap, pMap); // Since the EE frees, we've gotta record before its sent to the EE.
1198 original_ICorJitInfo->setBoundaries(ftn, cMap, pMap);
1199}
1200
1201// Query the EE to find out the scope of local varables.
1202// normally the JIT would trash variables after last use, but
1203// under debugging, the JIT needs to keep them live over their
1204// entire scope so that they can be inspected.
1205//
1206// Note that unless CORJIT_FLAG_DEBUG_CODE is specified, this function will
1207// be used only as a hint and the native compiler should not change its
1208// code generation.
1209void interceptor_ICJI::getVars(CORINFO_METHOD_HANDLE ftn, // [IN] method of interest
1210 ULONG32* cVars, // [OUT] size of 'vars'
1211 ICorDebugInfo::ILVarInfo** vars, // [OUT] scopes of variables of interest
1212 // jit MUST free with freeArray!
1213 bool* extendOthers // [OUT] it TRUE, then assume the scope
1214 // of unmentioned vars is entire method
1215 )
1216{
1217 mc->cr->AddCall("getVars");
1218 original_ICorJitInfo->getVars(ftn, cVars, vars, extendOthers);
1219 mc->recGetVars(ftn, cVars, vars, extendOthers);
1220}
1221
1222// Report back to the EE the location of every variable.
1223// note that the JIT might split lifetimes into different
1224// locations etc.
1225// Note - Ownership of vars is transfered with this call. We need to record it before its passed on to the EE.
1226void interceptor_ICJI::setVars(CORINFO_METHOD_HANDLE ftn, // [IN] method of interest
1227 ULONG32 cVars, // [IN] size of 'vars'
1228 ICorDebugInfo::NativeVarInfo* vars // [IN] map telling where local vars are stored at
1229 // what points
1230 // jit allocated with allocateArray, EE frees
1231 )
1232{
1233 mc->cr->AddCall("setVars");
1234 mc->cr->recSetVars(ftn, cVars, vars); // Since the EE frees, we've gotta record before its sent to the EE.
1235 original_ICorJitInfo->setVars(ftn, cVars, vars);
1236}
1237
1238/*-------------------------- Misc ---------------------------------------*/
1239// Used to allocate memory that needs to handed to the EE.
1240// For eg, use this to allocated memory for reporting debug info,
1241// which will be handed to the EE by setVars() and setBoundaries()
1242void* interceptor_ICJI::allocateArray(ULONG cBytes)
1243{
1244 mc->cr->AddCall("allocateArray");
1245 return original_ICorJitInfo->allocateArray(cBytes);
1246}
1247
1248// JitCompiler will free arrays passed by the EE using this
1249// For eg, The EE returns memory in getVars() and getBoundaries()
1250// to the JitCompiler, which the JitCompiler should release using
1251// freeArray()
1252void interceptor_ICJI::freeArray(void* array)
1253{
1254 mc->cr->AddCall("freeArray");
1255 original_ICorJitInfo->freeArray(array);
1256}
1257
1258/*********************************************************************************/
1259//
1260// ICorArgInfo
1261//
1262/*********************************************************************************/
1263// advance the pointer to the argument list.
1264// a ptr of 0, is special and always means the first argument
1265CORINFO_ARG_LIST_HANDLE interceptor_ICJI::getArgNext(CORINFO_ARG_LIST_HANDLE args /* IN */
1266 )
1267{
1268 mc->cr->AddCall("getArgNext");
1269 CORINFO_ARG_LIST_HANDLE temp = original_ICorJitInfo->getArgNext(args);
1270 mc->recGetArgNext(args, temp);
1271 return temp;
1272}
1273
1274// Get the type of a particular argument
1275// CORINFO_TYPE_UNDEF is returned when there are no more arguments
1276// If the type returned is a primitive type (or an enum) *vcTypeRet set to nullptr
1277// otherwise it is set to the TypeHandle associted with the type
1278// Enumerations will always look their underlying type (probably should fix this)
1279// Otherwise vcTypeRet is the type as would be seen by the IL,
1280// The return value is the type that is used for calling convention purposes
1281// (Thus if the EE wants a value class to be passed like an int, then it will
1282// return CORINFO_TYPE_INT
1283CorInfoTypeWithMod interceptor_ICJI::getArgType(CORINFO_SIG_INFO* sig, /* IN */
1284 CORINFO_ARG_LIST_HANDLE args, /* IN */
1285 CORINFO_CLASS_HANDLE* vcTypeRet /* OUT */
1286 )
1287{
1288 struct Param : FilterSuperPMIExceptionsParam_CaptureException
1289 {
1290 interceptor_ICJI* pThis;
1291 CORINFO_SIG_INFO* sig;
1292 CORINFO_ARG_LIST_HANDLE args;
1293 CORINFO_CLASS_HANDLE* vcTypeRet;
1294 CorInfoTypeWithMod temp;
1295 } param;
1296 param.pThis = this;
1297 param.sig = sig;
1298 param.args = args;
1299 param.vcTypeRet = vcTypeRet;
1300 param.temp = (CorInfoTypeWithMod)CORINFO_TYPE_UNDEF;
1301
1302 PAL_TRY(Param*, pOuterParam, &param)
1303 {
1304 PAL_TRY(Param*, pParam, pOuterParam)
1305 {
1306 pParam->pThis->mc->cr->AddCall("getArgType");
1307 pParam->temp =
1308 pParam->pThis->original_ICorJitInfo->getArgType(pParam->sig, pParam->args, pParam->vcTypeRet);
1309
1310#ifdef fatMC
1311 CORINFO_CLASS_HANDLE temp3 = pParam->pThis->getArgClass(pParam->sig, pParam->args);
1312#endif
1313 }
1314 PAL_EXCEPT_FILTER(FilterSuperPMIExceptions_CaptureExceptionAndContinue)
1315 {
1316 }
1317 PAL_ENDTRY
1318 }
1319 PAL_FINALLY
1320 {
1321 this->mc->recGetArgType(sig, args, vcTypeRet, param.temp, param.exceptionCode);
1322 }
1323 PAL_ENDTRY
1324
1325 return param.temp;
1326}
1327
1328// If the Arg is a CORINFO_TYPE_CLASS fetch the class handle associated with it
1329CORINFO_CLASS_HANDLE interceptor_ICJI::getArgClass(CORINFO_SIG_INFO* sig, /* IN */
1330 CORINFO_ARG_LIST_HANDLE args /* IN */
1331 )
1332{
1333 struct Param : FilterSuperPMIExceptionsParam_CaptureException
1334 {
1335 interceptor_ICJI* pThis;
1336 CORINFO_SIG_INFO* sig;
1337 CORINFO_ARG_LIST_HANDLE args;
1338 CORINFO_CLASS_HANDLE temp;
1339 } param;
1340 param.pThis = this;
1341 param.sig = sig;
1342 param.args = args;
1343 param.temp = 0;
1344
1345 PAL_TRY(Param*, pOuterParam, &param)
1346 {
1347 PAL_TRY(Param*, pParam, pOuterParam)
1348 {
1349 pParam->pThis->mc->cr->AddCall("getArgClass");
1350 pParam->temp = pParam->pThis->original_ICorJitInfo->getArgClass(pParam->sig, pParam->args);
1351 }
1352 PAL_EXCEPT_FILTER(FilterSuperPMIExceptions_CaptureExceptionAndContinue)
1353 {
1354 }
1355 PAL_ENDTRY
1356 }
1357 PAL_FINALLY
1358 {
1359 this->mc->recGetArgClass(sig, args, param.temp, param.exceptionCode);
1360
1361 // to build up a fat mc
1362 getClassName(param.temp);
1363 }
1364 PAL_ENDTRY
1365
1366 return param.temp;
1367}
1368
1369// Returns type of HFA for valuetype
1370CorInfoType interceptor_ICJI::getHFAType(CORINFO_CLASS_HANDLE hClass)
1371{
1372 mc->cr->AddCall("getHFAType");
1373 CorInfoType temp = original_ICorJitInfo->getHFAType(hClass);
1374 this->mc->recGetHFAType(hClass, temp);
1375 return temp;
1376}
1377
1378/*****************************************************************************
1379* ICorErrorInfo contains methods to deal with SEH exceptions being thrown
1380* from the corinfo interface. These methods may be called when an exception
1381* with code EXCEPTION_COMPLUS is caught.
1382*****************************************************************************/
1383// Returns the HRESULT of the current exception
1384HRESULT interceptor_ICJI::GetErrorHRESULT(struct _EXCEPTION_POINTERS* pExceptionPointers)
1385{
1386 mc->cr->AddCall("GetErrorHRESULT");
1387 return original_ICorJitInfo->GetErrorHRESULT(pExceptionPointers);
1388}
1389
1390// Fetches the message of the current exception
1391// Returns the size of the message (including terminating null). This can be
1392// greater than bufferLength if the buffer is insufficient.
1393ULONG interceptor_ICJI::GetErrorMessage(__inout_ecount(bufferLength) LPWSTR buffer, ULONG bufferLength)
1394{
1395 mc->cr->AddCall("GetErrorMessage");
1396 return original_ICorJitInfo->GetErrorMessage(buffer, bufferLength);
1397}
1398
1399// returns EXCEPTION_EXECUTE_HANDLER if it is OK for the compile to handle the
1400// exception, abort some work (like the inlining) and continue compilation
1401// returns EXCEPTION_CONTINUE_SEARCH if exception must always be handled by the EE
1402// things like ThreadStoppedException ...
1403// returns EXCEPTION_CONTINUE_EXECUTION if exception is fixed up by the EE
1404int interceptor_ICJI::FilterException(struct _EXCEPTION_POINTERS* pExceptionPointers)
1405{
1406 mc->cr->AddCall("FilterException");
1407 int temp = original_ICorJitInfo->FilterException(pExceptionPointers);
1408 mc->recFilterException(pExceptionPointers, temp);
1409 return temp;
1410}
1411
1412// Cleans up internal EE tracking when an exception is caught.
1413void interceptor_ICJI::HandleException(struct _EXCEPTION_POINTERS* pExceptionPointers)
1414{
1415 // bswHack?
1416 mc->cr->AddCall("HandleException");
1417 original_ICorJitInfo->HandleException(pExceptionPointers);
1418 mc->recHandleException(pExceptionPointers);
1419}
1420
1421void interceptor_ICJI::ThrowExceptionForJitResult(HRESULT result)
1422{
1423 mc->cr->AddCall("ThrowExceptionForJitResult");
1424 original_ICorJitInfo->ThrowExceptionForJitResult(result);
1425}
1426
1427// Throws an exception defined by the given throw helper.
1428void interceptor_ICJI::ThrowExceptionForHelper(const CORINFO_HELPER_DESC* throwHelper)
1429{
1430 mc->cr->AddCall("ThrowExceptionForHelper");
1431 original_ICorJitInfo->ThrowExceptionForHelper(throwHelper);
1432}
1433
1434/*****************************************************************************
1435 * ICorStaticInfo contains EE interface methods which return values that are
1436 * constant from invocation to invocation. Thus they may be embedded in
1437 * persisted information like statically generated code. (This is of course
1438 * assuming that all code versions are identical each time.)
1439 *****************************************************************************/
1440// Return details about EE internal data structures
1441void interceptor_ICJI::getEEInfo(CORINFO_EE_INFO* pEEInfoOut)
1442{
1443 mc->cr->AddCall("getEEInfo");
1444 original_ICorJitInfo->getEEInfo(pEEInfoOut);
1445 mc->recGetEEInfo(pEEInfoOut);
1446}
1447
1448// Returns name of the JIT timer log
1449LPCWSTR interceptor_ICJI::getJitTimeLogFilename()
1450{
1451 mc->cr->AddCall("getJitTimeLogFilename");
1452 LPCWSTR temp = original_ICorJitInfo->getJitTimeLogFilename();
1453 mc->recGetJitTimeLogFilename(temp);
1454 return temp;
1455}
1456
1457/*********************************************************************************/
1458//
1459// Diagnostic methods
1460//
1461/*********************************************************************************/
1462// this function is for debugging only. Returns method token.
1463// Returns mdMethodDefNil for dynamic methods.
1464mdMethodDef interceptor_ICJI::getMethodDefFromMethod(CORINFO_METHOD_HANDLE hMethod)
1465{
1466 mc->cr->AddCall("getMethodDefFromMethod");
1467 mdMethodDef result = original_ICorJitInfo->getMethodDefFromMethod(hMethod);
1468 mc->recGetMethodDefFromMethod(hMethod, result);
1469 return result;
1470}
1471
1472// this function is for debugging only. It returns the method name
1473// and if 'moduleName' is non-null, it sets it to something that will
1474// says which method (a class name, or a module name)
1475const char* interceptor_ICJI::getMethodName(CORINFO_METHOD_HANDLE ftn, /* IN */
1476 const char** moduleName /* OUT */
1477 )
1478{
1479 mc->cr->AddCall("getMethodName");
1480 const char* temp = original_ICorJitInfo->getMethodName(ftn, moduleName);
1481 mc->recGetMethodName(ftn, (char*)temp, moduleName);
1482 return temp;
1483}
1484
1485const char* interceptor_ICJI::getMethodNameFromMetadata(CORINFO_METHOD_HANDLE ftn, /* IN */
1486 const char** className, /* OUT */
1487 const char** namespaceName, /* OUT */
1488 const char** enclosingClassName /* OUT */
1489 )
1490{
1491 mc->cr->AddCall("getMethodNameFromMetadata");
1492 const char* temp = original_ICorJitInfo->getMethodNameFromMetadata(ftn, className, namespaceName, enclosingClassName);
1493 mc->recGetMethodNameFromMetadata(ftn, (char*)temp, className, namespaceName, enclosingClassName);
1494 return temp;
1495}
1496
1497// this function is for debugging only. It returns a value that
1498// is will always be the same for a given method. It is used
1499// to implement the 'jitRange' functionality
1500unsigned interceptor_ICJI::getMethodHash(CORINFO_METHOD_HANDLE ftn /* IN */
1501 )
1502{
1503 mc->cr->AddCall("getMethodHash");
1504 unsigned temp = original_ICorJitInfo->getMethodHash(ftn);
1505 mc->recGetMethodHash(ftn, temp);
1506 return temp;
1507}
1508
1509// this function is for debugging only.
1510size_t interceptor_ICJI::findNameOfToken(CORINFO_MODULE_HANDLE module, /* IN */
1511 mdToken metaTOK, /* IN */
1512 __out_ecount(FQNameCapacity) char* szFQName, /* OUT */
1513 size_t FQNameCapacity /* IN */
1514 )
1515{
1516 mc->cr->AddCall("findNameOfToken");
1517 size_t result = original_ICorJitInfo->findNameOfToken(module, metaTOK, szFQName, FQNameCapacity);
1518 mc->recFindNameOfToken(module, metaTOK, szFQName, FQNameCapacity, result);
1519 return result;
1520}
1521
1522bool interceptor_ICJI::getSystemVAmd64PassStructInRegisterDescriptor(
1523 /* IN */ CORINFO_CLASS_HANDLE structHnd,
1524 /* OUT */ SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr)
1525{
1526 mc->cr->AddCall("getSystemVAmd64PassStructInRegisterDescriptor");
1527 bool result =
1528 original_ICorJitInfo->getSystemVAmd64PassStructInRegisterDescriptor(structHnd, structPassInRegDescPtr);
1529 mc->recGetSystemVAmd64PassStructInRegisterDescriptor(structHnd, structPassInRegDescPtr, result);
1530 return result;
1531}
1532
1533// Stuff on ICorDynamicInfo
1534DWORD interceptor_ICJI::getThreadTLSIndex(void** ppIndirection)
1535{
1536 mc->cr->AddCall("getThreadTLSIndex");
1537 DWORD temp = original_ICorJitInfo->getThreadTLSIndex(ppIndirection);
1538 mc->recGetThreadTLSIndex(ppIndirection, temp);
1539 return temp;
1540}
1541
1542const void* interceptor_ICJI::getInlinedCallFrameVptr(void** ppIndirection)
1543{
1544 mc->cr->AddCall("getInlinedCallFrameVptr");
1545 const void* temp = original_ICorJitInfo->getInlinedCallFrameVptr(ppIndirection);
1546 mc->recGetInlinedCallFrameVptr(ppIndirection, temp);
1547 return temp;
1548}
1549
1550LONG* interceptor_ICJI::getAddrOfCaptureThreadGlobal(void** ppIndirection)
1551{
1552 mc->cr->AddCall("getAddrOfCaptureThreadGlobal");
1553 LONG* temp = original_ICorJitInfo->getAddrOfCaptureThreadGlobal(ppIndirection);
1554 mc->recGetAddrOfCaptureThreadGlobal(ppIndirection, temp);
1555 return temp;
1556}
1557
1558// return the native entry point to an EE helper (see CorInfoHelpFunc)
1559void* interceptor_ICJI::getHelperFtn(CorInfoHelpFunc ftnNum, void** ppIndirection)
1560{
1561 mc->cr->AddCall("getHelperFtn");
1562 void* temp = original_ICorJitInfo->getHelperFtn(ftnNum, ppIndirection);
1563 mc->recGetHelperFtn(ftnNum, ppIndirection, temp);
1564 return temp;
1565}
1566
1567// return a callable address of the function (native code). This function
1568// may return a different value (depending on whether the method has
1569// been JITed or not.
1570void interceptor_ICJI::getFunctionEntryPoint(CORINFO_METHOD_HANDLE ftn, /* IN */
1571 CORINFO_CONST_LOOKUP* pResult, /* OUT */
1572 CORINFO_ACCESS_FLAGS accessFlags)
1573{
1574 mc->cr->AddCall("getFunctionEntryPoint");
1575 original_ICorJitInfo->getFunctionEntryPoint(ftn, pResult, accessFlags);
1576 mc->recGetFunctionEntryPoint(ftn, pResult, accessFlags);
1577}
1578
1579// return a directly callable address. This can be used similarly to the
1580// value returned by getFunctionEntryPoint() except that it is
1581// guaranteed to be multi callable entrypoint.
1582void interceptor_ICJI::getFunctionFixedEntryPoint(CORINFO_METHOD_HANDLE ftn, CORINFO_CONST_LOOKUP* pResult)
1583{
1584 mc->cr->AddCall("getFunctionFixedEntryPoint");
1585 original_ICorJitInfo->getFunctionFixedEntryPoint(ftn, pResult);
1586 mc->recGetFunctionFixedEntryPoint(ftn, pResult);
1587}
1588
1589// get the synchronization handle that is passed to monXstatic function
1590void* interceptor_ICJI::getMethodSync(CORINFO_METHOD_HANDLE ftn, void** ppIndirection)
1591{
1592 mc->cr->AddCall("getMethodSync");
1593 void* temp = original_ICorJitInfo->getMethodSync(ftn, ppIndirection);
1594 mc->recGetMethodSync(ftn, ppIndirection, temp);
1595 return temp;
1596}
1597
1598// These entry points must be called if a handle is being embedded in
1599// the code to be passed to a JIT helper function. (as opposed to just
1600// being passed back into the ICorInfo interface.)
1601
1602// get slow lazy string literal helper to use (CORINFO_HELP_STRCNS*).
1603// Returns CORINFO_HELP_UNDEF if lazy string literal helper cannot be used.
1604CorInfoHelpFunc interceptor_ICJI::getLazyStringLiteralHelper(CORINFO_MODULE_HANDLE handle)
1605{
1606 mc->cr->AddCall("getLazyStringLiteralHelper");
1607 CorInfoHelpFunc temp = original_ICorJitInfo->getLazyStringLiteralHelper(handle);
1608 mc->recGetLazyStringLiteralHelper(handle, temp);
1609 return temp;
1610}
1611
1612CORINFO_MODULE_HANDLE interceptor_ICJI::embedModuleHandle(CORINFO_MODULE_HANDLE handle, void** ppIndirection)
1613{
1614 mc->cr->AddCall("embedModuleHandle");
1615 CORINFO_MODULE_HANDLE temp = original_ICorJitInfo->embedModuleHandle(handle, ppIndirection);
1616 mc->recEmbedModuleHandle(handle, ppIndirection, temp);
1617 return temp;
1618}
1619
1620CORINFO_CLASS_HANDLE interceptor_ICJI::embedClassHandle(CORINFO_CLASS_HANDLE handle, void** ppIndirection)
1621{
1622 mc->cr->AddCall("embedClassHandle");
1623 CORINFO_CLASS_HANDLE temp = original_ICorJitInfo->embedClassHandle(handle, ppIndirection);
1624 mc->recEmbedClassHandle(handle, ppIndirection, temp);
1625 return temp;
1626}
1627
1628CORINFO_METHOD_HANDLE interceptor_ICJI::embedMethodHandle(CORINFO_METHOD_HANDLE handle, void** ppIndirection)
1629{
1630 mc->cr->AddCall("embedMethodHandle");
1631 CORINFO_METHOD_HANDLE temp = original_ICorJitInfo->embedMethodHandle(handle, ppIndirection);
1632 mc->recEmbedMethodHandle(handle, ppIndirection, temp);
1633 return temp;
1634}
1635
1636CORINFO_FIELD_HANDLE interceptor_ICJI::embedFieldHandle(CORINFO_FIELD_HANDLE handle, void** ppIndirection)
1637{
1638 mc->cr->AddCall("embedFieldHandle");
1639 CORINFO_FIELD_HANDLE temp = original_ICorJitInfo->embedFieldHandle(handle, ppIndirection);
1640 mc->recEmbedFieldHandle(handle, ppIndirection, temp);
1641 return temp;
1642}
1643
1644// Given a module scope (module), a method handle (context) and
1645// a metadata token (metaTOK), fetch the handle
1646// (type, field or method) associated with the token.
1647// If this is not possible at compile-time (because the current method's
1648// code is shared and the token contains generic parameters)
1649// then indicate how the handle should be looked up at run-time.
1650//
1651void interceptor_ICJI::embedGenericHandle(CORINFO_RESOLVED_TOKEN* pResolvedToken,
1652 BOOL fEmbedParent, // TRUE - embeds parent type handle of the field/method
1653 // handle
1654 CORINFO_GENERICHANDLE_RESULT* pResult)
1655{
1656 mc->cr->AddCall("embedGenericHandle");
1657 original_ICorJitInfo->embedGenericHandle(pResolvedToken, fEmbedParent, pResult);
1658 mc->recEmbedGenericHandle(pResolvedToken, fEmbedParent, pResult);
1659}
1660
1661// Return information used to locate the exact enclosing type of the current method.
1662// Used only to invoke .cctor method from code shared across generic instantiations
1663// !needsRuntimeLookup statically known (enclosing type of method itself)
1664// needsRuntimeLookup:
1665// CORINFO_LOOKUP_THISOBJ use vtable pointer of 'this' param
1666// CORINFO_LOOKUP_CLASSPARAM use vtable hidden param
1667// CORINFO_LOOKUP_METHODPARAM use enclosing type of method-desc hidden param
1668CORINFO_LOOKUP_KIND interceptor_ICJI::getLocationOfThisType(CORINFO_METHOD_HANDLE context)
1669{
1670 mc->cr->AddCall("getLocationOfThisType");
1671 CORINFO_LOOKUP_KIND temp = original_ICorJitInfo->getLocationOfThisType(context);
1672 mc->recGetLocationOfThisType(context, &temp);
1673 return temp;
1674}
1675
1676// return the unmanaged target *if method has already been prelinked.*
1677void* interceptor_ICJI::getPInvokeUnmanagedTarget(CORINFO_METHOD_HANDLE method, void** ppIndirection)
1678{
1679 mc->cr->AddCall("getPInvokeUnmanagedTarget");
1680 void* result = original_ICorJitInfo->getPInvokeUnmanagedTarget(method, ppIndirection);
1681 mc->recGetPInvokeUnmanagedTarget(method, ppIndirection, result);
1682 return result;
1683}
1684
1685// return address of fixup area for late-bound PInvoke calls.
1686void* interceptor_ICJI::getAddressOfPInvokeFixup(CORINFO_METHOD_HANDLE method, void** ppIndirection)
1687{
1688 mc->cr->AddCall("getAddressOfPInvokeFixup");
1689 void* temp = original_ICorJitInfo->getAddressOfPInvokeFixup(method, ppIndirection);
1690 mc->recGetAddressOfPInvokeFixup(method, ppIndirection, temp);
1691 return temp;
1692}
1693
1694// return address of fixup area for late-bound PInvoke calls.
1695void interceptor_ICJI::getAddressOfPInvokeTarget(CORINFO_METHOD_HANDLE method, CORINFO_CONST_LOOKUP* pLookup)
1696{
1697 mc->cr->AddCall("getAddressOfPInvokeTarget");
1698 original_ICorJitInfo->getAddressOfPInvokeTarget(method, pLookup);
1699 mc->recGetAddressOfPInvokeTarget(method, pLookup);
1700}
1701
1702// Generate a cookie based on the signature that would needs to be passed
1703// to CORINFO_HELP_PINVOKE_CALLI
1704LPVOID interceptor_ICJI::GetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig, void** ppIndirection)
1705{
1706 mc->cr->AddCall("GetCookieForPInvokeCalliSig");
1707 LPVOID temp = original_ICorJitInfo->GetCookieForPInvokeCalliSig(szMetaSig, ppIndirection);
1708 mc->recGetCookieForPInvokeCalliSig(szMetaSig, ppIndirection, temp);
1709 return temp;
1710}
1711
1712// returns true if a VM cookie can be generated for it (might be false due to cross-module
1713// inlining, in which case the inlining should be aborted)
1714bool interceptor_ICJI::canGetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig)
1715{
1716 mc->cr->AddCall("canGetCookieForPInvokeCalliSig");
1717 bool temp = original_ICorJitInfo->canGetCookieForPInvokeCalliSig(szMetaSig);
1718 mc->recCanGetCookieForPInvokeCalliSig(szMetaSig, temp);
1719 return temp;
1720}
1721
1722// Gets a handle that is checked to see if the current method is
1723// included in "JustMyCode"
1724CORINFO_JUST_MY_CODE_HANDLE interceptor_ICJI::getJustMyCodeHandle(CORINFO_METHOD_HANDLE method,
1725 CORINFO_JUST_MY_CODE_HANDLE** ppIndirection)
1726{
1727 mc->cr->AddCall("getJustMyCodeHandle");
1728 CORINFO_JUST_MY_CODE_HANDLE temp = original_ICorJitInfo->getJustMyCodeHandle(method, ppIndirection);
1729 mc->recGetJustMyCodeHandle(method, ppIndirection, temp);
1730 return temp;
1731}
1732
1733// Gets a method handle that can be used to correlate profiling data.
1734// This is the IP of a native method, or the address of the descriptor struct
1735// for IL. Always guaranteed to be unique per process, and not to move. */
1736void interceptor_ICJI::GetProfilingHandle(BOOL* pbHookFunction, void** pProfilerHandle, BOOL* pbIndirectedHandles)
1737{
1738 mc->cr->AddCall("GetProfilingHandle");
1739 original_ICorJitInfo->GetProfilingHandle(pbHookFunction, pProfilerHandle, pbIndirectedHandles);
1740 mc->recGetProfilingHandle(pbHookFunction, pProfilerHandle, pbIndirectedHandles);
1741}
1742
1743// Returns instructions on how to make the call. See code:CORINFO_CALL_INFO for possible return values.
1744void interceptor_ICJI::getCallInfo(
1745 // Token info
1746 CORINFO_RESOLVED_TOKEN* pResolvedToken,
1747 // Generics info
1748 CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken,
1749 // Security info
1750 CORINFO_METHOD_HANDLE callerHandle,
1751 // Jit info
1752 CORINFO_CALLINFO_FLAGS flags,
1753 // out params
1754 CORINFO_CALL_INFO* pResult)
1755{
1756 struct Param : FilterSuperPMIExceptionsParam_CaptureException
1757 {
1758 interceptor_ICJI* pThis;
1759 CORINFO_RESOLVED_TOKEN* pResolvedToken;
1760 CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken;
1761 CORINFO_METHOD_HANDLE callerHandle;
1762 CORINFO_CALLINFO_FLAGS flags;
1763 CORINFO_CALL_INFO* pResult;
1764 } param;
1765 param.pThis = this;
1766 param.pResolvedToken = pResolvedToken;
1767 param.pConstrainedResolvedToken = pConstrainedResolvedToken;
1768 param.callerHandle = callerHandle;
1769 param.flags = flags;
1770 param.pResult = pResult;
1771
1772 PAL_TRY(Param*, pOuterParam, &param)
1773 {
1774 PAL_TRY(Param*, pParam, pOuterParam)
1775 {
1776 pParam->pThis->mc->cr->AddCall("getCallInfo");
1777 pParam->pThis->original_ICorJitInfo->getCallInfo(pParam->pResolvedToken, pParam->pConstrainedResolvedToken,
1778 pParam->callerHandle, pParam->flags, pParam->pResult);
1779 }
1780 PAL_EXCEPT_FILTER(FilterSuperPMIExceptions_CaptureExceptionAndContinue)
1781 {
1782 }
1783 PAL_ENDTRY
1784 }
1785 PAL_FINALLY
1786 {
1787 this->mc->recGetCallInfo(pResolvedToken, pConstrainedResolvedToken, callerHandle, flags, pResult,
1788 param.exceptionCode);
1789 }
1790 PAL_ENDTRY
1791}
1792
1793BOOL interceptor_ICJI::canAccessFamily(CORINFO_METHOD_HANDLE hCaller, CORINFO_CLASS_HANDLE hInstanceType)
1794{
1795 mc->cr->AddCall("canAccessFamily");
1796 BOOL temp = original_ICorJitInfo->canAccessFamily(hCaller, hInstanceType);
1797 mc->recCanAccessFamily(hCaller, hInstanceType, temp);
1798 return temp;
1799}
1800
1801// Returns TRUE if the Class Domain ID is the RID of the class (currently true for every class
1802// except reflection emitted classes and generics)
1803BOOL interceptor_ICJI::isRIDClassDomainID(CORINFO_CLASS_HANDLE cls)
1804{
1805 mc->cr->AddCall("isRIDClassDomainID");
1806 return original_ICorJitInfo->isRIDClassDomainID(cls);
1807}
1808
1809// returns the class's domain ID for accessing shared statics
1810unsigned interceptor_ICJI::getClassDomainID(CORINFO_CLASS_HANDLE cls, void** ppIndirection)
1811{
1812 mc->cr->AddCall("getClassDomainID");
1813 unsigned temp = original_ICorJitInfo->getClassDomainID(cls, ppIndirection);
1814 mc->recGetClassDomainID(cls, ppIndirection, temp);
1815 return temp;
1816}
1817
1818// return the data's address (for static fields only)
1819void* interceptor_ICJI::getFieldAddress(CORINFO_FIELD_HANDLE field, void** ppIndirection)
1820{
1821 mc->cr->AddCall("getFieldAddress");
1822 void* temp = original_ICorJitInfo->getFieldAddress(field, ppIndirection);
1823
1824 // Figure out the element type so we know how much we can load
1825 CORINFO_CLASS_HANDLE cch;
1826 CorInfoType cit = getFieldType(field, &cch, NULL);
1827 mc->recGetFieldAddress(field, ppIndirection, temp, cit);
1828 return temp;
1829}
1830
1831// return the class handle for the current value of a static field
1832CORINFO_CLASS_HANDLE interceptor_ICJI::getStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field, bool* pIsSpeculative)
1833{
1834 mc->cr->AddCall("getStaticFieldCurrentClass");
1835 bool localIsSpeculative = false;
1836 CORINFO_CLASS_HANDLE result = original_ICorJitInfo->getStaticFieldCurrentClass(field, &localIsSpeculative);
1837 mc->recGetStaticFieldCurrentClass(field, localIsSpeculative, result);
1838 if (pIsSpeculative != nullptr)
1839 {
1840 *pIsSpeculative = localIsSpeculative;
1841 }
1842 return result;
1843}
1844
1845// registers a vararg sig & returns a VM cookie for it (which can contain other stuff)
1846CORINFO_VARARGS_HANDLE interceptor_ICJI::getVarArgsHandle(CORINFO_SIG_INFO* pSig, void** ppIndirection)
1847{
1848 mc->cr->AddCall("getVarArgsHandle");
1849 CORINFO_VARARGS_HANDLE temp = original_ICorJitInfo->getVarArgsHandle(pSig, ppIndirection);
1850 mc->recGetVarArgsHandle(pSig, ppIndirection, temp);
1851 return temp;
1852}
1853
1854// returns true if a VM cookie can be generated for it (might be false due to cross-module
1855// inlining, in which case the inlining should be aborted)
1856bool interceptor_ICJI::canGetVarArgsHandle(CORINFO_SIG_INFO* pSig)
1857{
1858 mc->cr->AddCall("canGetVarArgsHandle");
1859 bool temp = original_ICorJitInfo->canGetVarArgsHandle(pSig);
1860 mc->recCanGetVarArgsHandle(pSig, temp);
1861 return temp;
1862}
1863
1864// Allocate a string literal on the heap and return a handle to it
1865InfoAccessType interceptor_ICJI::constructStringLiteral(CORINFO_MODULE_HANDLE module, mdToken metaTok, void** ppValue)
1866{
1867 mc->cr->AddCall("constructStringLiteral");
1868 InfoAccessType temp = original_ICorJitInfo->constructStringLiteral(module, metaTok, ppValue);
1869 mc->recConstructStringLiteral(module, metaTok, *ppValue, temp);
1870 return temp;
1871}
1872
1873bool interceptor_ICJI::convertPInvokeCalliToCall(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fMustConvert)
1874{
1875 mc->cr->AddCall("convertPInvokeCalliToCall");
1876 bool result = original_ICorJitInfo->convertPInvokeCalliToCall(pResolvedToken, fMustConvert);
1877 mc->recConvertPInvokeCalliToCall(pResolvedToken, fMustConvert, result);
1878 return result;
1879}
1880
1881InfoAccessType interceptor_ICJI::emptyStringLiteral(void** ppValue)
1882{
1883 mc->cr->AddCall("emptyStringLiteral");
1884 InfoAccessType temp = original_ICorJitInfo->emptyStringLiteral(ppValue);
1885 mc->recEmptyStringLiteral(ppValue, temp);
1886 return temp;
1887}
1888
1889// (static fields only) given that 'field' refers to thread local store,
1890// return the ID (TLS index), which is used to find the begining of the
1891// TLS data area for the particular DLL 'field' is associated with.
1892DWORD interceptor_ICJI::getFieldThreadLocalStoreID(CORINFO_FIELD_HANDLE field, void** ppIndirection)
1893{
1894 mc->cr->AddCall("getFieldThreadLocalStoreID");
1895 DWORD temp = original_ICorJitInfo->getFieldThreadLocalStoreID(field, ppIndirection);
1896 mc->recGetFieldThreadLocalStoreID(field, ppIndirection, temp);
1897 return temp;
1898}
1899
1900// Sets another object to intercept calls to "self" and current method being compiled
1901void interceptor_ICJI::setOverride(ICorDynamicInfo* pOverride, CORINFO_METHOD_HANDLE currentMethod)
1902{
1903 mc->cr->AddCall("setOverride");
1904 original_ICorJitInfo->setOverride(pOverride, currentMethod);
1905}
1906
1907// Adds an active dependency from the context method's module to the given module
1908// This is internal callback for the EE. JIT should not call it directly.
1909void interceptor_ICJI::addActiveDependency(CORINFO_MODULE_HANDLE moduleFrom, CORINFO_MODULE_HANDLE moduleTo)
1910{
1911 mc->cr->AddCall("addActiveDependency");
1912 original_ICorJitInfo->addActiveDependency(moduleFrom, moduleTo);
1913}
1914
1915CORINFO_METHOD_HANDLE interceptor_ICJI::GetDelegateCtor(CORINFO_METHOD_HANDLE methHnd,
1916 CORINFO_CLASS_HANDLE clsHnd,
1917 CORINFO_METHOD_HANDLE targetMethodHnd,
1918 DelegateCtorArgs* pCtorData)
1919{
1920 mc->cr->AddCall("GetDelegateCtor");
1921 CORINFO_METHOD_HANDLE temp = original_ICorJitInfo->GetDelegateCtor(methHnd, clsHnd, targetMethodHnd, pCtorData);
1922 mc->recGetDelegateCtor(methHnd, clsHnd, targetMethodHnd, pCtorData, temp);
1923 return temp;
1924}
1925
1926void interceptor_ICJI::MethodCompileComplete(CORINFO_METHOD_HANDLE methHnd)
1927{
1928 mc->cr->AddCall("MethodCompileComplete");
1929 original_ICorJitInfo->MethodCompileComplete(methHnd);
1930}
1931
1932// return a thunk that will copy the arguments for the given signature.
1933void* interceptor_ICJI::getTailCallCopyArgsThunk(CORINFO_SIG_INFO* pSig, CorInfoHelperTailCallSpecialHandling flags)
1934{
1935 mc->cr->AddCall("getTailCallCopyArgsThunk");
1936 void* result = original_ICorJitInfo->getTailCallCopyArgsThunk(pSig, flags);
1937 mc->recGetTailCallCopyArgsThunk(pSig, flags, result);
1938 return result;
1939}
1940
1941// Stuff directly on ICorJitInfo
1942
1943// Returns extended flags for a particular compilation instance.
1944DWORD interceptor_ICJI::getJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes)
1945{
1946 mc->cr->AddCall("getJitFlags");
1947 DWORD result = original_ICorJitInfo->getJitFlags(jitFlags, sizeInBytes);
1948 mc->recGetJitFlags(jitFlags, sizeInBytes, result);
1949 return result;
1950}
1951
1952// Runs the given function with the given parameter under an error trap
1953// and returns true if the function completes successfully. We don't
1954// record the results of the call: when this call gets played back,
1955// its result will depend on whether or not `function` calls something
1956// that throws at playback time rather than at capture time.
1957bool interceptor_ICJI::runWithErrorTrap(void (*function)(void*), void* param)
1958{
1959 mc->cr->AddCall("runWithErrorTrap");
1960 return original_ICorJitInfo->runWithErrorTrap(function, param);
1961}
1962
1963// return memory manager that the JIT can use to allocate a regular memory
1964IEEMemoryManager* interceptor_ICJI::getMemoryManager()
1965{
1966 mc->cr->AddCall("getMemoryManager");
1967 if (current_IEEMM->original_IEEMM == nullptr)
1968 current_IEEMM->original_IEEMM = original_ICorJitInfo->getMemoryManager();
1969 return current_IEEMM;
1970}
1971
1972// get a block of memory for the code, readonly data, and read-write data
1973void interceptor_ICJI::allocMem(ULONG hotCodeSize, /* IN */
1974 ULONG coldCodeSize, /* IN */
1975 ULONG roDataSize, /* IN */
1976 ULONG xcptnsCount, /* IN */
1977 CorJitAllocMemFlag flag, /* IN */
1978 void** hotCodeBlock, /* OUT */
1979 void** coldCodeBlock, /* OUT */
1980 void** roDataBlock /* OUT */
1981 )
1982{
1983 mc->cr->AddCall("allocMem");
1984 original_ICorJitInfo->allocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock,
1985 coldCodeBlock, roDataBlock);
1986 mc->cr->recAllocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, coldCodeBlock,
1987 roDataBlock);
1988}
1989
1990// Reserve memory for the method/funclet's unwind information.
1991// Note that this must be called before allocMem. It should be
1992// called once for the main method, once for every funclet, and
1993// once for every block of cold code for which allocUnwindInfo
1994// will be called.
1995//
1996// This is necessary because jitted code must allocate all the
1997// memory needed for the unwindInfo at the allocMem call.
1998// For prejitted code we split up the unwinding information into
1999// separate sections .rdata and .pdata.
2000//
2001void interceptor_ICJI::reserveUnwindInfo(BOOL isFunclet, /* IN */
2002 BOOL isColdCode, /* IN */
2003 ULONG unwindSize /* IN */
2004 )
2005{
2006 mc->cr->AddCall("reserveUnwindInfo");
2007 original_ICorJitInfo->reserveUnwindInfo(isFunclet, isColdCode, unwindSize);
2008 mc->cr->recReserveUnwindInfo(isFunclet, isColdCode, unwindSize);
2009}
2010
2011// Allocate and initialize the .rdata and .pdata for this method or
2012// funclet, and get the block of memory needed for the machine-specific
2013// unwind information (the info for crawling the stack frame).
2014// Note that allocMem must be called first.
2015//
2016// Parameters:
2017//
2018// pHotCode main method code buffer, always filled in
2019// pColdCode cold code buffer, only filled in if this is cold code,
2020// null otherwise
2021// startOffset start of code block, relative to appropriate code buffer
2022// (e.g. pColdCode if cold, pHotCode if hot).
2023// endOffset end of code block, relative to appropriate code buffer
2024// unwindSize size of unwind info pointed to by pUnwindBlock
2025// pUnwindBlock pointer to unwind info
2026// funcKind type of funclet (main method code, handler, filter)
2027//
2028void interceptor_ICJI::allocUnwindInfo(BYTE* pHotCode, /* IN */
2029 BYTE* pColdCode, /* IN */
2030 ULONG startOffset, /* IN */
2031 ULONG endOffset, /* IN */
2032 ULONG unwindSize, /* IN */
2033 BYTE* pUnwindBlock, /* IN */
2034 CorJitFuncKind funcKind /* IN */
2035 )
2036{
2037 mc->cr->AddCall("allocUnwindInfo");
2038 original_ICorJitInfo->allocUnwindInfo(pHotCode, pColdCode, startOffset, endOffset, unwindSize, pUnwindBlock,
2039 funcKind);
2040 mc->cr->recAllocUnwindInfo(pHotCode, pColdCode, startOffset, endOffset, unwindSize, pUnwindBlock, funcKind);
2041}
2042
2043// Get a block of memory needed for the code manager information,
2044// (the info for enumerating the GC pointers while crawling the
2045// stack frame).
2046// Note that allocMem must be called first
2047void* interceptor_ICJI::allocGCInfo(size_t size /* IN */)
2048{
2049 mc->cr->AddCall("allocGCInfo");
2050 void* temp = original_ICorJitInfo->allocGCInfo(size);
2051 mc->cr->recAllocGCInfo(size, temp);
2052 return temp;
2053}
2054
2055// only used on x64
2056void interceptor_ICJI::yieldExecution()
2057{
2058 mc->cr->AddCall("yieldExecution"); // Nothing to record
2059 original_ICorJitInfo->yieldExecution();
2060}
2061
2062// Indicate how many exception handler blocks are to be returned.
2063// This is guaranteed to be called before any 'setEHinfo' call.
2064// Note that allocMem must be called before this method can be called.
2065void interceptor_ICJI::setEHcount(unsigned cEH /* IN */)
2066{
2067 mc->cr->AddCall("setEHcount");
2068 original_ICorJitInfo->setEHcount(cEH);
2069 mc->cr->recSetEHcount(cEH);
2070}
2071
2072// Set the values for one particular exception handler block.
2073// Handler regions should be lexically contiguous.
2074// This is because FinallyIsUnwinding() uses lexicality to
2075// determine if a "finally" clause is executing.
2076void interceptor_ICJI::setEHinfo(unsigned EHnumber, /* IN */
2077 const CORINFO_EH_CLAUSE* clause /* IN */
2078 )
2079{
2080 mc->cr->AddCall("setEHinfo");
2081 original_ICorJitInfo->setEHinfo(EHnumber, clause);
2082 mc->cr->recSetEHinfo(EHnumber, clause);
2083}
2084
2085// Level 1 -> fatalError, Level 2 -> Error, Level 3 -> Warning
2086// Level 4 means happens 10 times in a run, level 5 means 100, level 6 means 1000 ...
2087// returns non-zero if the logging succeeded
2088BOOL interceptor_ICJI::logMsg(unsigned level, const char* fmt, va_list args)
2089{
2090 mc->cr->AddCall("logMsg");
2091 return original_ICorJitInfo->logMsg(level, fmt, args);
2092}
2093
2094// do an assert. will return true if the code should retry (DebugBreak)
2095// returns false, if the assert should be igored.
2096int interceptor_ICJI::doAssert(const char* szFile, int iLine, const char* szExpr)
2097{
2098 mc->cr->AddCall("doAssert");
2099 return original_ICorJitInfo->doAssert(szFile, iLine, szExpr);
2100}
2101
2102void interceptor_ICJI::reportFatalError(CorJitResult result)
2103{
2104 mc->cr->AddCall("reportFatalError");
2105 original_ICorJitInfo->reportFatalError(result);
2106 mc->cr->recReportFatalError(result);
2107}
2108
2109// allocate a basic block profile buffer where execution counts will be stored
2110// for jitted basic blocks.
2111HRESULT interceptor_ICJI::allocBBProfileBuffer(ULONG count, // The number of basic blocks that we have
2112 ProfileBuffer** profileBuffer)
2113{
2114 mc->cr->AddCall("allocBBProfileBuffer");
2115 HRESULT result = original_ICorJitInfo->allocBBProfileBuffer(count, profileBuffer);
2116 mc->cr->recAllocBBProfileBuffer(count, profileBuffer, result);
2117 return result;
2118}
2119
2120// get profile information to be used for optimizing the current method. The format
2121// of the buffer is the same as the format the JIT passes to allocBBProfileBuffer.
2122HRESULT interceptor_ICJI::getBBProfileData(CORINFO_METHOD_HANDLE ftnHnd,
2123 ULONG* count, // The number of basic blocks that we have
2124 ProfileBuffer** profileBuffer,
2125 ULONG* numRuns)
2126{
2127 mc->cr->AddCall("getBBProfileData");
2128 HRESULT temp = original_ICorJitInfo->getBBProfileData(ftnHnd, count, profileBuffer, numRuns);
2129 mc->recGetBBProfileData(ftnHnd, count, profileBuffer, numRuns, temp);
2130 return temp;
2131}
2132
2133// Associates a native call site, identified by its offset in the native code stream, with
2134// the signature information and method handle the JIT used to lay out the call site. If
2135// the call site has no signature information (e.g. a helper call) or has no method handle
2136// (e.g. a CALLI P/Invoke), then null should be passed instead.
2137void interceptor_ICJI::recordCallSite(ULONG instrOffset, /* IN */
2138 CORINFO_SIG_INFO* callSig, /* IN */
2139 CORINFO_METHOD_HANDLE methodHandle /* IN */
2140 )
2141{
2142 mc->cr->AddCall("recordCallSite");
2143 original_ICorJitInfo->recordCallSite(instrOffset, callSig, methodHandle);
2144 mc->cr->recRecordCallSite(instrOffset, callSig, methodHandle);
2145}
2146
2147// A relocation is recorded if we are pre-jitting.
2148// A jump thunk may be inserted if we are jitting
2149void interceptor_ICJI::recordRelocation(void* location, /* IN */
2150 void* target, /* IN */
2151 WORD fRelocType, /* IN */
2152 WORD slotNum, /* IN */
2153 INT32 addlDelta /* IN */
2154 )
2155{
2156 mc->cr->AddCall("recordRelocation");
2157 original_ICorJitInfo->recordRelocation(location, target, fRelocType, slotNum, addlDelta);
2158 mc->cr->recRecordRelocation(location, target, fRelocType, slotNum, addlDelta);
2159}
2160
2161WORD interceptor_ICJI::getRelocTypeHint(void* target)
2162{
2163 mc->cr->AddCall("getRelocTypeHint");
2164 WORD result = original_ICorJitInfo->getRelocTypeHint(target);
2165 mc->recGetRelocTypeHint(target, result);
2166 return result;
2167}
2168
2169// A callback to identify the range of address known to point to
2170// compiler-generated native entry points that call back into
2171// MSIL.
2172void interceptor_ICJI::getModuleNativeEntryPointRange(void** pStart, /* OUT */
2173 void** pEnd /* OUT */
2174 )
2175{
2176 mc->cr->AddCall("getModuleNativeEntryPointRange");
2177 original_ICorJitInfo->getModuleNativeEntryPointRange(pStart, pEnd);
2178}
2179
2180// For what machine does the VM expect the JIT to generate code? The VM
2181// returns one of the IMAGE_FILE_MACHINE_* values. Note that if the VM
2182// is cross-compiling (such as the case for crossgen), it will return a
2183// different value than if it was compiling for the host architecture.
2184//
2185DWORD interceptor_ICJI::getExpectedTargetArchitecture()
2186{
2187 return original_ICorJitInfo->getExpectedTargetArchitecture();
2188}
2189