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