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