2 // Copyright (c) Microsoft. All rights reserved.
3 // Licensed under the MIT license. See LICENSE file in the project root for full license information.
6 #include "standardpch.h"
7 #include "icorjitinfo.h"
8 #include "superpmi-shim-counter.h"
9 #include "ieememorymanager.h"
10 #include "icorjitcompiler.h"
13 //Stuff on ICorStaticInfo
14 /**********************************************************************************/
18 /**********************************************************************************/
19 // return flags (defined above, CORINFO_FLG_PUBLIC ...)
20 DWORD interceptor_ICJI::getMethodAttribs (CORINFO_METHOD_HANDLE ftn /* IN */)
22 mcs->AddCall("getMethodAttribs");
23 return original_ICorJitInfo->getMethodAttribs(ftn);
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 */)
30 mcs->AddCall("setMethodAttribs");
31 original_ICorJitInfo->setMethodAttribs(ftn, attribs);
35 // Given a method descriptor ftnHnd, extract signature information into sigInfo
37 // 'memberParent' is typically only set when verifying. It should be the
38 // result of calling getMemberParent.
39 void interceptor_ICJI::getMethodSig (
40 CORINFO_METHOD_HANDLE ftn, /* IN */
41 CORINFO_SIG_INFO *sig, /* OUT */
42 CORINFO_CLASS_HANDLE memberParent/* IN */
45 mcs->AddCall("getMethodSig");
46 original_ICorJitInfo->getMethodSig(ftn, sig, memberParent);
50 /*********************************************************************
51 * Note the following methods can only be used on functions known
52 * to be IL. This includes the method being compiled and any method
53 * that 'getMethodInfo' returns true for
54 *********************************************************************/
56 // return information about a method private to the implementation
57 // returns false if method is not IL, or is otherwise unavailable.
58 // This method is used to fetch data needed to inline functions
59 bool interceptor_ICJI::getMethodInfo (
60 CORINFO_METHOD_HANDLE ftn, /* IN */
61 CORINFO_METHOD_INFO* info /* OUT */
64 mcs->AddCall("getMethodInfo");
65 return original_ICorJitInfo->getMethodInfo(ftn, info);
68 // Decides if you have any limitations for inlining. If everything's OK, it will return
69 // INLINE_PASS and will fill out pRestrictions with a mask of restrictions the caller of this
70 // function must respect. If caller passes pRestrictions = nullptr, if there are any restrictions
71 // INLINE_FAIL will be returned
73 // The callerHnd must be the immediate caller (i.e. when we have a chain of inlined calls)
75 // The inlined method need not be verified
77 CorInfoInline interceptor_ICJI::canInline (
78 CORINFO_METHOD_HANDLE callerHnd, /* IN */
79 CORINFO_METHOD_HANDLE calleeHnd, /* IN */
80 DWORD* pRestrictions /* OUT */
83 mcs->AddCall("canInline");
84 return original_ICorJitInfo->canInline(callerHnd, calleeHnd, pRestrictions);
87 // Reports whether or not a method can be inlined, and why. canInline is responsible for reporting all
88 // inlining results when it returns INLINE_FAIL and INLINE_NEVER. All other results are reported by the
90 void interceptor_ICJI::reportInliningDecision (CORINFO_METHOD_HANDLE inlinerHnd,
91 CORINFO_METHOD_HANDLE inlineeHnd,
92 CorInfoInline inlineResult,
95 mcs->AddCall("reportInliningDecision");
96 original_ICorJitInfo->reportInliningDecision(inlinerHnd, inlineeHnd, inlineResult, reason);
100 // Returns false if the call is across security boundaries thus we cannot tailcall
102 // The callerHnd must be the immediate caller (i.e. when we have a chain of inlined calls)
103 bool interceptor_ICJI::canTailCall (
104 CORINFO_METHOD_HANDLE callerHnd, /* IN */
105 CORINFO_METHOD_HANDLE declaredCalleeHnd, /* IN */
106 CORINFO_METHOD_HANDLE exactCalleeHnd, /* IN */
107 bool fIsTailPrefix /* IN */
110 mcs->AddCall("canTailCall");
111 return original_ICorJitInfo->canTailCall(callerHnd, declaredCalleeHnd, exactCalleeHnd, fIsTailPrefix);
114 // Reports whether or not a method can be tail called, and why.
115 // canTailCall is responsible for reporting all results when it returns
116 // false. All other results are reported by the JIT.
117 void interceptor_ICJI::reportTailCallDecision (CORINFO_METHOD_HANDLE callerHnd,
118 CORINFO_METHOD_HANDLE calleeHnd,
120 CorInfoTailCall tailCallResult,
123 mcs->AddCall("reportTailCallDecision");
124 original_ICorJitInfo->reportTailCallDecision(callerHnd, calleeHnd, fIsTailPrefix, tailCallResult, reason);
127 // get individual exception handler
128 void interceptor_ICJI::getEHinfo(
129 CORINFO_METHOD_HANDLE ftn, /* IN */
130 unsigned EHnumber, /* IN */
131 CORINFO_EH_CLAUSE* clause /* OUT */
134 mcs->AddCall("getEHinfo");
135 original_ICorJitInfo->getEHinfo(ftn, EHnumber, clause);
138 // return class it belongs to
139 CORINFO_CLASS_HANDLE interceptor_ICJI::getMethodClass (
140 CORINFO_METHOD_HANDLE method
143 mcs->AddCall("getMethodClass");
144 return original_ICorJitInfo->getMethodClass(method);
147 // return module it belongs to
148 CORINFO_MODULE_HANDLE interceptor_ICJI::getMethodModule (
149 CORINFO_METHOD_HANDLE method
152 mcs->AddCall("getMethodModule");
153 return original_ICorJitInfo->getMethodModule(method);
156 // This function returns the offset of the specified method in the
157 // vtable of it's owning class or interface.
158 void interceptor_ICJI::getMethodVTableOffset (
159 CORINFO_METHOD_HANDLE method, /* IN */
160 unsigned* offsetOfIndirection, /* OUT */
161 unsigned* offsetAfterIndirection /* OUT */
164 mcs->AddCall("getMethodVTableOffset");
165 original_ICorJitInfo->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection);
168 // Find the virtual method in implementingClass that overrides virtualMethod.
169 // Return null if devirtualization is not possible.
170 CORINFO_METHOD_HANDLE interceptor_ICJI::resolveVirtualMethod(
171 CORINFO_METHOD_HANDLE virtualMethod,
172 CORINFO_CLASS_HANDLE implementingClass,
173 CORINFO_CONTEXT_HANDLE ownerType
176 mcs->AddCall("resolveVirtualMethod");
177 return original_ICorJitInfo->resolveVirtualMethod(virtualMethod, implementingClass, ownerType);
180 // If a method's attributes have (getMethodAttribs) CORINFO_FLG_INTRINSIC set,
181 // getIntrinsicID() returns the intrinsic ID.
182 CorInfoIntrinsics interceptor_ICJI::getIntrinsicID(
183 CORINFO_METHOD_HANDLE method,
184 bool* pMustExpand /* OUT */
187 mcs->AddCall("getIntrinsicID");
188 return original_ICorJitInfo->getIntrinsicID(method, pMustExpand);
191 // Is the given module the System.Numerics.Vectors module?
192 bool interceptor_ICJI::isInSIMDModule(
193 CORINFO_CLASS_HANDLE classHnd
196 mcs->AddCall("isInSIMDModule");
197 return original_ICorJitInfo->isInSIMDModule(classHnd);
200 // return the unmanaged calling convention for a PInvoke
201 CorInfoUnmanagedCallConv interceptor_ICJI::getUnmanagedCallConv(
202 CORINFO_METHOD_HANDLE method
205 mcs->AddCall("getUnmanagedCallConv");
206 return original_ICorJitInfo->getUnmanagedCallConv(method);
209 // return if any marshaling is required for PInvoke methods. Note that
210 // method == 0 => calli. The call site sig is only needed for the varargs or calli case
211 BOOL interceptor_ICJI::pInvokeMarshalingRequired(
212 CORINFO_METHOD_HANDLE method,
213 CORINFO_SIG_INFO* callSiteSig
216 mcs->AddCall("pInvokeMarshalingRequired");
217 return original_ICorJitInfo->pInvokeMarshalingRequired(method, callSiteSig);
220 // Check constraints on method type arguments (only).
221 // The parent class should be checked separately using satisfiesClassConstraints(parent).
222 BOOL interceptor_ICJI::satisfiesMethodConstraints(
223 CORINFO_CLASS_HANDLE parent, // the exact parent of the method
224 CORINFO_METHOD_HANDLE method
227 mcs->AddCall("satisfiesMethodConstraints");
228 return original_ICorJitInfo->satisfiesMethodConstraints(parent, method);
231 // Given a delegate target class, a target method parent class, a target method,
232 // a delegate class, check if the method signature is compatible with the Invoke method of the delegate
233 // (under the typical instantiation of any free type variables in the memberref signatures).
234 BOOL interceptor_ICJI::isCompatibleDelegate(
235 CORINFO_CLASS_HANDLE objCls, /* type of the delegate target, if any */
236 CORINFO_CLASS_HANDLE methodParentCls, /* exact parent of the target method, if any */
237 CORINFO_METHOD_HANDLE method, /* (representative) target method, if any */
238 CORINFO_CLASS_HANDLE delegateCls, /* exact type of the delegate */
239 BOOL *pfIsOpenDelegate /* is the delegate open */
242 mcs->AddCall("isCompatibleDelegate");
243 return original_ICorJitInfo->isCompatibleDelegate(objCls, methodParentCls, method, delegateCls, pfIsOpenDelegate);
246 // Determines whether the delegate creation obeys security transparency rules
247 BOOL interceptor_ICJI::isDelegateCreationAllowed (
248 CORINFO_CLASS_HANDLE delegateHnd,
249 CORINFO_METHOD_HANDLE calleeHnd
252 mcs->AddCall("isDelegateCreationAllowed");
253 return original_ICorJitInfo->isDelegateCreationAllowed(delegateHnd, calleeHnd);
257 // Indicates if the method is an instance of the generic
258 // method that passes (or has passed) verification
259 CorInfoInstantiationVerification interceptor_ICJI::isInstantiationOfVerifiedGeneric (
260 CORINFO_METHOD_HANDLE method /* IN */
263 mcs->AddCall("isInstantiationOfVerifiedGeneric");
264 return original_ICorJitInfo->isInstantiationOfVerifiedGeneric(method);
267 // Loads the constraints on a typical method definition, detecting cycles;
268 // for use in verification.
269 void interceptor_ICJI::initConstraintsForVerification(
270 CORINFO_METHOD_HANDLE method, /* IN */
271 BOOL *pfHasCircularClassConstraints, /* OUT */
272 BOOL *pfHasCircularMethodConstraint /* OUT */
275 mcs->AddCall("initConstraintsForVerification");
276 original_ICorJitInfo->initConstraintsForVerification(method, pfHasCircularClassConstraints, pfHasCircularMethodConstraint);
279 // Returns enum whether the method does not require verification
280 // Also see ICorModuleInfo::canSkipVerification
281 CorInfoCanSkipVerificationResult interceptor_ICJI::canSkipMethodVerification (
282 CORINFO_METHOD_HANDLE ftnHandle
285 mcs->AddCall("canSkipMethodVerification");
286 return original_ICorJitInfo->canSkipMethodVerification(ftnHandle);
289 // load and restore the method
290 void interceptor_ICJI::methodMustBeLoadedBeforeCodeIsRun(
291 CORINFO_METHOD_HANDLE method
294 mcs->AddCall("methodMustBeLoadedBeforeCodeIsRun");
295 original_ICorJitInfo->methodMustBeLoadedBeforeCodeIsRun(method);
298 CORINFO_METHOD_HANDLE interceptor_ICJI::mapMethodDeclToMethodImpl(
299 CORINFO_METHOD_HANDLE method
302 mcs->AddCall("mapMethodDeclToMethodImpl");
303 return original_ICorJitInfo->mapMethodDeclToMethodImpl(method);
306 // Returns the global cookie for the /GS unsafe buffer checks
307 // The cookie might be a constant value (JIT), or a handle to memory location (Ngen)
308 void interceptor_ICJI::getGSCookie(
309 GSCookie * pCookieVal, // OUT
310 GSCookie ** ppCookieVal // OUT
313 mcs->AddCall("getGSCookie");
314 original_ICorJitInfo->getGSCookie(pCookieVal, ppCookieVal);
317 /**********************************************************************************/
321 /**********************************************************************************/
323 // Resolve metadata token into runtime method handles.
324 void interceptor_ICJI::resolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken)
326 mcs->AddCall("resolveToken");
327 original_ICorJitInfo->resolveToken(pResolvedToken);
330 bool interceptor_ICJI::tryResolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken)
332 mcs->AddCall("tryResolveToken");
333 return original_ICorJitInfo->tryResolveToken(pResolvedToken);
336 // Signature information about the call sig
337 void interceptor_ICJI::findSig (
338 CORINFO_MODULE_HANDLE module, /* IN */
339 unsigned sigTOK, /* IN */
340 CORINFO_CONTEXT_HANDLE context, /* IN */
341 CORINFO_SIG_INFO *sig /* OUT */
344 mcs->AddCall("findSig");
345 original_ICorJitInfo->findSig(module, sigTOK, context, sig);
348 // for Varargs, the signature at the call site may differ from
349 // the signature at the definition. Thus we need a way of
350 // fetching the call site information
351 void interceptor_ICJI::findCallSiteSig (
352 CORINFO_MODULE_HANDLE module, /* IN */
353 unsigned methTOK, /* IN */
354 CORINFO_CONTEXT_HANDLE context, /* IN */
355 CORINFO_SIG_INFO *sig /* OUT */
358 mcs->AddCall("findCallSiteSig");
359 original_ICorJitInfo->findCallSiteSig(module, methTOK, context, sig);
362 CORINFO_CLASS_HANDLE interceptor_ICJI::getTokenTypeAsHandle (
363 CORINFO_RESOLVED_TOKEN * pResolvedToken /* IN */)
365 mcs->AddCall("getTokenTypeAsHandle");
366 return original_ICorJitInfo->getTokenTypeAsHandle(pResolvedToken);
369 // Returns true if the module does not require verification
371 // If fQuickCheckOnlyWithoutCommit=TRUE, the function only checks that the
372 // module does not currently require verification in the current AppDomain.
373 // This decision could change in the future, and so should not be cached.
374 // If it is cached, it should only be used as a hint.
375 // This is only used by ngen for calculating certain hints.
378 // Returns enum whether the module does not require verification
379 // Also see ICorMethodInfo::canSkipMethodVerification();
380 CorInfoCanSkipVerificationResult interceptor_ICJI::canSkipVerification (
381 CORINFO_MODULE_HANDLE module /* IN */
384 mcs->AddCall("canSkipVerification");
385 return original_ICorJitInfo->canSkipVerification(module);
388 // Checks if the given metadata token is valid
389 BOOL interceptor_ICJI::isValidToken (
390 CORINFO_MODULE_HANDLE module, /* IN */
391 unsigned metaTOK /* IN */
394 mcs->AddCall("isValidToken");
395 return original_ICorJitInfo->isValidToken(module, metaTOK);
398 // Checks if the given metadata token is valid StringRef
399 BOOL interceptor_ICJI::isValidStringRef (
400 CORINFO_MODULE_HANDLE module, /* IN */
401 unsigned metaTOK /* IN */
404 mcs->AddCall("isValidStringRef");
405 return original_ICorJitInfo->isValidStringRef(module, metaTOK);
408 BOOL interceptor_ICJI::shouldEnforceCallvirtRestriction(
409 CORINFO_MODULE_HANDLE scope
412 mcs->AddCall("shouldEnforceCallvirtRestriction");
413 return original_ICorJitInfo->shouldEnforceCallvirtRestriction(scope);
416 /**********************************************************************************/
420 /**********************************************************************************/
422 // If the value class 'cls' is isomorphic to a primitive type it will
423 // return that type, otherwise it will return CORINFO_TYPE_VALUECLASS
424 CorInfoType interceptor_ICJI::asCorInfoType (
425 CORINFO_CLASS_HANDLE cls
428 mcs->AddCall("asCorInfoType");
429 return original_ICorJitInfo->asCorInfoType(cls);
433 const char* interceptor_ICJI::getClassName (
434 CORINFO_CLASS_HANDLE cls
437 mcs->AddCall("getClassName");
438 return original_ICorJitInfo->getClassName(cls);
442 // Append a (possibly truncated) representation of the type cls to the preallocated buffer ppBuf of length pnBufLen
443 // If fNamespace=TRUE, include the namespace/enclosing classes
444 // If fFullInst=TRUE (regardless of fNamespace and fAssembly), include namespace and assembly for any type parameters
445 // If fAssembly=TRUE, suffix with a comma and the full assembly qualification
446 // return size of representation
447 int interceptor_ICJI::appendClassName(
448 __deref_inout_ecount(*pnBufLen) WCHAR** ppBuf,
450 CORINFO_CLASS_HANDLE cls,
456 mcs->AddCall("appendClassName");
457 return original_ICorJitInfo->appendClassName(ppBuf, pnBufLen, cls, fNamespace, fFullInst, fAssembly);
460 // Quick check whether the type is a value class. Returns the same value as getClassAttribs(cls) & CORINFO_FLG_VALUECLASS, except faster.
461 BOOL interceptor_ICJI::isValueClass(CORINFO_CLASS_HANDLE cls)
463 mcs->AddCall("isValueClass");
464 return original_ICorJitInfo->isValueClass(cls);
467 // If this method returns true, JIT will do optimization to inline the check for
468 // GetTypeFromHandle(handle) == obj.GetType()
469 BOOL interceptor_ICJI::canInlineTypeCheckWithObjectVTable(CORINFO_CLASS_HANDLE cls)
471 mcs->AddCall("canInlineTypeCheckWithObjectVTable");
472 return original_ICorJitInfo->canInlineTypeCheckWithObjectVTable(cls);
475 // return flags (defined above, CORINFO_FLG_PUBLIC ...)
476 DWORD interceptor_ICJI::getClassAttribs (
477 CORINFO_CLASS_HANDLE cls
480 mcs->AddCall("getClassAttribs");
481 return original_ICorJitInfo->getClassAttribs(cls);
484 // Returns "TRUE" iff "cls" is a struct type such that return buffers used for returning a value
485 // of this type must be stack-allocated. This will generally be true only if the struct
486 // contains GC pointers, and does not exceed some size limit. Maintaining this as an invariant allows
487 // an optimization: the JIT may assume that return buffer pointers for return types for which this predicate
488 // returns TRUE are always stack allocated, and thus, that stores to the GC-pointer fields of such return
489 // buffers do not require GC write barriers.
490 BOOL interceptor_ICJI::isStructRequiringStackAllocRetBuf(CORINFO_CLASS_HANDLE cls)
492 mcs->AddCall("isStructRequiringStackAllocRetBuf");
493 return original_ICorJitInfo->isStructRequiringStackAllocRetBuf(cls);
496 CORINFO_MODULE_HANDLE interceptor_ICJI::getClassModule (
497 CORINFO_CLASS_HANDLE cls
500 mcs->AddCall("getClassModule");
501 return original_ICorJitInfo->getClassModule(cls);
504 // Returns the assembly that contains the module "mod".
505 CORINFO_ASSEMBLY_HANDLE interceptor_ICJI::getModuleAssembly (
506 CORINFO_MODULE_HANDLE mod
509 mcs->AddCall("getModuleAssembly");
510 return original_ICorJitInfo->getModuleAssembly(mod);
513 // Returns the name of the assembly "assem".
514 const char* interceptor_ICJI::getAssemblyName (
515 CORINFO_ASSEMBLY_HANDLE assem
518 mcs->AddCall("getAssemblyName");
519 return original_ICorJitInfo->getAssemblyName(assem);
522 // Allocate and delete process-lifetime objects. Should only be
523 // referred to from static fields, lest a leak occur.
524 // Note that "LongLifetimeFree" does not execute destructors, if "obj"
525 // is an array of a struct type with a destructor.
526 void* interceptor_ICJI::LongLifetimeMalloc(size_t sz)
528 mcs->AddCall("LongLifetimeMalloc");
529 return original_ICorJitInfo->LongLifetimeMalloc(sz);
532 void interceptor_ICJI::LongLifetimeFree(void* obj)
534 mcs->AddCall("LongLifetimeFree");
535 original_ICorJitInfo->LongLifetimeFree(obj);
538 size_t interceptor_ICJI::getClassModuleIdForStatics (
539 CORINFO_CLASS_HANDLE cls,
540 CORINFO_MODULE_HANDLE *pModule,
544 mcs->AddCall("getClassModuleIdForStatics");
545 return original_ICorJitInfo->getClassModuleIdForStatics(cls, pModule, ppIndirection);
548 // return the number of bytes needed by an instance of the class
549 unsigned interceptor_ICJI::getClassSize (
550 CORINFO_CLASS_HANDLE cls
553 mcs->AddCall("getClassSize");
554 return original_ICorJitInfo->getClassSize(cls);
557 unsigned interceptor_ICJI::getClassAlignmentRequirement (
558 CORINFO_CLASS_HANDLE cls,
559 BOOL fDoubleAlignHint
562 mcs->AddCall("getClassAlignmentRequirement");
563 return original_ICorJitInfo->getClassAlignmentRequirement(cls, fDoubleAlignHint);
566 // This is only called for Value classes. It returns a boolean array
567 // in representing of 'cls' from a GC perspective. The class is
568 // assumed to be an array of machine words
569 // (of length // getClassSize(cls) / sizeof(void*)),
570 // 'gcPtrs' is a pointer to an array of BYTEs of this length.
571 // getClassGClayout fills in this array so that gcPtrs[i] is set
572 // to one of the CorInfoGCType values which is the GC type of
573 // the i-th machine word of an object of type 'cls'
574 // returns the number of GC pointers in the array
575 unsigned interceptor_ICJI::getClassGClayout (
576 CORINFO_CLASS_HANDLE cls, /* IN */
577 BYTE *gcPtrs /* OUT */
580 mcs->AddCall("getClassGClayout");
581 return original_ICorJitInfo->getClassGClayout(cls, gcPtrs);
584 // returns the number of instance fields in a class
585 unsigned interceptor_ICJI::getClassNumInstanceFields (
586 CORINFO_CLASS_HANDLE cls /* IN */
589 mcs->AddCall("getClassNumInstanceFields");
590 return original_ICorJitInfo->getClassNumInstanceFields(cls);
593 CORINFO_FIELD_HANDLE interceptor_ICJI::getFieldInClass(
594 CORINFO_CLASS_HANDLE clsHnd,
598 mcs->AddCall("getFieldInClass");
599 return original_ICorJitInfo->getFieldInClass(clsHnd, num);
602 BOOL interceptor_ICJI::checkMethodModifier(
603 CORINFO_METHOD_HANDLE hMethod,
608 mcs->AddCall("checkMethodModifier");
609 return original_ICorJitInfo->checkMethodModifier(hMethod, modifier, fOptional);
612 // returns the "NEW" helper optimized for "newCls."
613 CorInfoHelpFunc interceptor_ICJI::getNewHelper(
614 CORINFO_RESOLVED_TOKEN * pResolvedToken,
615 CORINFO_METHOD_HANDLE callerHandle
618 mcs->AddCall("getNewHelper");
619 return original_ICorJitInfo->getNewHelper(pResolvedToken, callerHandle);
622 // returns the newArr (1-Dim array) helper optimized for "arrayCls."
623 CorInfoHelpFunc interceptor_ICJI::getNewArrHelper(
624 CORINFO_CLASS_HANDLE arrayCls
627 mcs->AddCall("getNewArrHelper");
628 return original_ICorJitInfo->getNewArrHelper(arrayCls);
631 // returns the optimized "IsInstanceOf" or "ChkCast" helper
632 CorInfoHelpFunc interceptor_ICJI::getCastingHelper(
633 CORINFO_RESOLVED_TOKEN * pResolvedToken,
637 mcs->AddCall("getCastingHelper");
638 return original_ICorJitInfo->getCastingHelper(pResolvedToken, fThrowing);
641 // returns helper to trigger static constructor
642 CorInfoHelpFunc interceptor_ICJI::getSharedCCtorHelper(
643 CORINFO_CLASS_HANDLE clsHnd
646 mcs->AddCall("getSharedCCtorHelper");
647 return original_ICorJitInfo->getSharedCCtorHelper(clsHnd);
650 CorInfoHelpFunc interceptor_ICJI::getSecurityPrologHelper(
651 CORINFO_METHOD_HANDLE ftn
654 mcs->AddCall("getSecurityPrologHelper");
655 return original_ICorJitInfo->getSecurityPrologHelper(ftn);
658 // This is not pretty. Boxing nullable<T> actually returns
659 // a boxed<T> not a boxed Nullable<T>. This call allows the verifier
660 // to call back to the EE on the 'box' instruction and get the transformed
661 // type to use for verification.
662 CORINFO_CLASS_HANDLE interceptor_ICJI::getTypeForBox(
663 CORINFO_CLASS_HANDLE cls
666 mcs->AddCall("getTypeForBox");
667 return original_ICorJitInfo->getTypeForBox(cls);
670 // returns the correct box helper for a particular class. Note
671 // that if this returns CORINFO_HELP_BOX, the JIT can assume
672 // 'standard' boxing (allocate object and copy), and optimize
673 CorInfoHelpFunc interceptor_ICJI::getBoxHelper(
674 CORINFO_CLASS_HANDLE cls
677 mcs->AddCall("getBoxHelper");
678 return original_ICorJitInfo->getBoxHelper(cls);
681 // returns the unbox helper. If 'helperCopies' points to a true
682 // value it means the JIT is requesting a helper that unboxes the
683 // value into a particular location and thus has the signature
684 // void unboxHelper(void* dest, CORINFO_CLASS_HANDLE cls, Object* obj)
685 // Otherwise (it is null or points at a FALSE value) it is requesting
686 // a helper that returns a pointer to the unboxed data
687 // void* unboxHelper(CORINFO_CLASS_HANDLE cls, Object* obj)
688 // The EE has the option of NOT returning the copy style helper
689 // (But must be able to always honor the non-copy style helper)
690 // The EE set 'helperCopies' on return to indicate what kind of
691 // helper has been created.
693 CorInfoHelpFunc interceptor_ICJI::getUnBoxHelper(
694 CORINFO_CLASS_HANDLE cls
697 mcs->AddCall("getUnBoxHelper");
698 return original_ICorJitInfo->getUnBoxHelper(cls);
701 bool interceptor_ICJI::getReadyToRunHelper(
702 CORINFO_RESOLVED_TOKEN * pResolvedToken,
703 CORINFO_LOOKUP_KIND * pGenericLookupKind,
705 CORINFO_CONST_LOOKUP * pLookup
708 mcs->AddCall("getReadyToRunHelper");
709 return original_ICorJitInfo->getReadyToRunHelper(pResolvedToken, pGenericLookupKind, id, pLookup);
712 void interceptor_ICJI::getReadyToRunDelegateCtorHelper(
713 CORINFO_RESOLVED_TOKEN * pTargetMethod,
714 CORINFO_CLASS_HANDLE delegateType,
715 CORINFO_LOOKUP * pLookup
718 mcs->AddCall("getReadyToRunDelegateCtorHelper");
719 original_ICorJitInfo->getReadyToRunDelegateCtorHelper(pTargetMethod, delegateType, pLookup);
722 const char* interceptor_ICJI::getHelperName(
723 CorInfoHelpFunc funcNum
726 mcs->AddCall("getHelperName");
727 return original_ICorJitInfo->getHelperName(funcNum);
730 // This function tries to initialize the class (run the class constructor).
731 // this function returns whether the JIT must insert helper calls before
732 // accessing static field or method.
734 // See code:ICorClassInfo#ClassConstruction.
735 CorInfoInitClassResult interceptor_ICJI::initClass(
736 CORINFO_FIELD_HANDLE field, // Non-nullptr - inquire about cctor trigger before static field access
737 // nullptr - inquire about cctor trigger in method prolog
738 CORINFO_METHOD_HANDLE method, // Method referencing the field or prolog
739 CORINFO_CONTEXT_HANDLE context, // Exact context of method
740 BOOL speculative // TRUE means don't actually run it
743 mcs->AddCall("initClass");
744 return original_ICorJitInfo->initClass(field, method, context, speculative);
747 // This used to be called "loadClass". This records the fact
748 // that the class must be loaded (including restored if necessary) before we execute the
749 // code that we are currently generating. When jitting code
750 // the function loads the class immediately. When zapping code
751 // the zapper will if necessary use the call to record the fact that we have
752 // to do a fixup/restore before running the method currently being generated.
754 // This is typically used to ensure value types are loaded before zapped
755 // code that manipulates them is executed, so that the GC can access information
756 // about those value types.
757 void interceptor_ICJI::classMustBeLoadedBeforeCodeIsRun(
758 CORINFO_CLASS_HANDLE cls
761 mcs->AddCall("classMustBeLoadedBeforeCodeIsRun");
762 original_ICorJitInfo->classMustBeLoadedBeforeCodeIsRun(cls);
765 // returns the class handle for the special builtin classes
766 CORINFO_CLASS_HANDLE interceptor_ICJI::getBuiltinClass (
767 CorInfoClassId classId
770 mcs->AddCall("getBuiltinClass");
771 return original_ICorJitInfo->getBuiltinClass(classId);
774 // "System.Int32" ==> CORINFO_TYPE_INT..
775 CorInfoType interceptor_ICJI::getTypeForPrimitiveValueClass(
776 CORINFO_CLASS_HANDLE cls
779 mcs->AddCall("getTypeForPrimitiveValueClass");
780 return original_ICorJitInfo->getTypeForPrimitiveValueClass(cls);
783 // TRUE if child is a subtype of parent
784 // if parent is an interface, then does child implement / extend parent
785 BOOL interceptor_ICJI::canCast(
786 CORINFO_CLASS_HANDLE child, // subtype (extends parent)
787 CORINFO_CLASS_HANDLE parent // base type
790 mcs->AddCall("canCast");
791 return original_ICorJitInfo->canCast(child, parent);
794 // TRUE if cls1 and cls2 are considered equivalent types.
795 BOOL interceptor_ICJI::areTypesEquivalent(
796 CORINFO_CLASS_HANDLE cls1,
797 CORINFO_CLASS_HANDLE cls2
800 mcs->AddCall("areTypesEquivalent");
801 return original_ICorJitInfo->areTypesEquivalent(cls1, cls2);
804 // returns is the intersection of cls1 and cls2.
805 CORINFO_CLASS_HANDLE interceptor_ICJI::mergeClasses(
806 CORINFO_CLASS_HANDLE cls1,
807 CORINFO_CLASS_HANDLE cls2
810 mcs->AddCall("mergeClasses");
811 return original_ICorJitInfo->mergeClasses(cls1, cls2);
814 // Given a class handle, returns the Parent type.
815 // For COMObjectType, it returns Class Handle of System.Object.
816 // Returns 0 if System.Object is passed in.
817 CORINFO_CLASS_HANDLE interceptor_ICJI::getParentType (
818 CORINFO_CLASS_HANDLE cls
821 mcs->AddCall("getParentType");
822 return original_ICorJitInfo->getParentType(cls);
825 // Returns the CorInfoType of the "child type". If the child type is
826 // not a primitive type, *clsRet will be set.
827 // Given an Array of Type Foo, returns Foo.
828 // Given BYREF Foo, returns Foo
829 CorInfoType interceptor_ICJI::getChildType (
830 CORINFO_CLASS_HANDLE clsHnd,
831 CORINFO_CLASS_HANDLE *clsRet
834 mcs->AddCall("getChildType");
835 return original_ICorJitInfo->getChildType(clsHnd, clsRet);
838 // Check constraints on type arguments of this class and parent classes
839 BOOL interceptor_ICJI::satisfiesClassConstraints(
840 CORINFO_CLASS_HANDLE cls
843 mcs->AddCall("satisfiesClassConstraints");
844 return original_ICorJitInfo->satisfiesClassConstraints(cls);
847 // Check if this is a single dimensional array type
848 BOOL interceptor_ICJI::isSDArray(
849 CORINFO_CLASS_HANDLE cls
852 mcs->AddCall("isSDArray");
853 return original_ICorJitInfo->isSDArray(cls);
856 // Get the numbmer of dimensions in an array
857 unsigned interceptor_ICJI::getArrayRank(
858 CORINFO_CLASS_HANDLE cls
861 mcs->AddCall("getArrayRank");
862 return original_ICorJitInfo->getArrayRank(cls);
865 // Get static field data for an array
866 void * interceptor_ICJI::getArrayInitializationData(
867 CORINFO_FIELD_HANDLE field,
871 mcs->AddCall("getArrayInitializationData");
872 return original_ICorJitInfo->getArrayInitializationData(field, size);
875 // Check Visibility rules.
876 CorInfoIsAccessAllowedResult interceptor_ICJI::canAccessClass(
877 CORINFO_RESOLVED_TOKEN * pResolvedToken,
878 CORINFO_METHOD_HANDLE callerHandle,
879 CORINFO_HELPER_DESC *pAccessHelper /* If canAccessMethod returns something other
880 than ALLOWED, then this is filled in. */
883 mcs->AddCall("canAccessClass");
884 return original_ICorJitInfo->canAccessClass(pResolvedToken, callerHandle, pAccessHelper);
887 /**********************************************************************************/
891 /**********************************************************************************/
893 // this function is for debugging only. It returns the field name
894 // and if 'moduleName' is non-null, it sets it to something that will
895 // says which method (a class name, or a module name)
896 const char* interceptor_ICJI::getFieldName (
897 CORINFO_FIELD_HANDLE ftn, /* IN */
898 const char **moduleName /* OUT */
901 mcs->AddCall("getFieldName");
902 return original_ICorJitInfo->getFieldName(ftn, moduleName);
905 // return class it belongs to
906 CORINFO_CLASS_HANDLE interceptor_ICJI::getFieldClass (
907 CORINFO_FIELD_HANDLE field
910 mcs->AddCall("getFieldClass");
911 return original_ICorJitInfo->getFieldClass(field);
914 // Return the field's type, if it is CORINFO_TYPE_VALUECLASS 'structType' is set
915 // the field's value class (if 'structType' == 0, then don't bother
916 // the structure info).
918 // 'memberParent' is typically only set when verifying. It should be the
919 // result of calling getMemberParent.
920 CorInfoType interceptor_ICJI::getFieldType(
921 CORINFO_FIELD_HANDLE field,
922 CORINFO_CLASS_HANDLE *structType,
923 CORINFO_CLASS_HANDLE memberParent/* IN */
926 mcs->AddCall("getFieldType");
927 return original_ICorJitInfo->getFieldType(field, structType, memberParent);
930 // return the data member's instance offset
931 unsigned interceptor_ICJI::getFieldOffset(
932 CORINFO_FIELD_HANDLE field
935 mcs->AddCall("getFieldOffset");
936 return original_ICorJitInfo->getFieldOffset(field);
939 // TODO: jit64 should be switched to the same plan as the i386 jits - use
940 // getClassGClayout to figure out the need for writebarrier helper, and inline the copying.
941 // The interpretted value class copy is slow. Once this happens, USE_WRITE_BARRIER_HELPERS
942 bool interceptor_ICJI::isWriteBarrierHelperRequired(
943 CORINFO_FIELD_HANDLE field)
945 mcs->AddCall("isWriteBarrierHelperRequired");
946 return original_ICorJitInfo->isWriteBarrierHelperRequired(field);
949 void interceptor_ICJI::getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken,
950 CORINFO_METHOD_HANDLE callerHandle,
951 CORINFO_ACCESS_FLAGS flags,
952 CORINFO_FIELD_INFO *pResult
955 mcs->AddCall("getFieldInfo");
956 original_ICorJitInfo->getFieldInfo(pResolvedToken, callerHandle, flags, pResult);
959 // Returns true iff "fldHnd" represents a static field.
960 bool interceptor_ICJI::isFieldStatic(CORINFO_FIELD_HANDLE fldHnd)
962 mcs->AddCall("isFieldStatic");
963 return original_ICorJitInfo->isFieldStatic(fldHnd);
966 /*********************************************************************************/
970 /*********************************************************************************/
972 // Query the EE to find out where interesting break points
973 // in the code are. The native compiler will ensure that these places
974 // have a corresponding break point in native code.
976 // Note that unless CORJIT_FLAG_DEBUG_CODE is specified, this function will
977 // be used only as a hint and the native compiler should not change its
979 void interceptor_ICJI::getBoundaries(
980 CORINFO_METHOD_HANDLE ftn, // [IN] method of interest
981 unsigned int *cILOffsets, // [OUT] size of pILOffsets
982 DWORD **pILOffsets, // [OUT] IL offsets of interest
983 // jit MUST free with freeArray!
984 ICorDebugInfo::BoundaryTypes *implictBoundaries // [OUT] tell jit, all boundries of this type
987 mcs->AddCall("getBoundaries");
988 original_ICorJitInfo->getBoundaries(ftn, cILOffsets, pILOffsets, implictBoundaries);
991 // Report back the mapping from IL to native code,
992 // this map should include all boundaries that 'getBoundaries'
993 // reported as interesting to the debugger.
995 // Note that debugger (and profiler) is assuming that all of the
996 // offsets form a contiguous block of memory, and that the
997 // OffsetMapping is sorted in order of increasing native offset.
998 void interceptor_ICJI::setBoundaries(
999 CORINFO_METHOD_HANDLE ftn, // [IN] method of interest
1000 ULONG32 cMap, // [IN] size of pMap
1001 ICorDebugInfo::OffsetMapping *pMap // [IN] map including all points of interest.
1002 // jit allocated with allocateArray, EE frees
1005 mcs->AddCall("setBoundaries");
1006 original_ICorJitInfo->setBoundaries(ftn, cMap, pMap);
1009 // Query the EE to find out the scope of local varables.
1010 // normally the JIT would trash variables after last use, but
1011 // under debugging, the JIT needs to keep them live over their
1012 // entire scope so that they can be inspected.
1014 // Note that unless CORJIT_FLAG_DEBUG_CODE is specified, this function will
1015 // be used only as a hint and the native compiler should not change its
1017 void interceptor_ICJI::getVars(
1018 CORINFO_METHOD_HANDLE ftn, // [IN] method of interest
1019 ULONG32 *cVars, // [OUT] size of 'vars'
1020 ICorDebugInfo::ILVarInfo **vars, // [OUT] scopes of variables of interest
1021 // jit MUST free with freeArray!
1022 bool *extendOthers // [OUT] it TRUE, then assume the scope
1023 // of unmentioned vars is entire method
1026 mcs->AddCall("getVars");
1027 original_ICorJitInfo->getVars(ftn, cVars, vars, extendOthers);
1030 // Report back to the EE the location of every variable.
1031 // note that the JIT might split lifetimes into different
1034 void interceptor_ICJI::setVars(
1035 CORINFO_METHOD_HANDLE ftn, // [IN] method of interest
1036 ULONG32 cVars, // [IN] size of 'vars'
1037 ICorDebugInfo::NativeVarInfo *vars // [IN] map telling where local vars are stored at what points
1038 // jit allocated with allocateArray, EE frees
1041 mcs->AddCall("setVars");
1042 original_ICorJitInfo->setVars(ftn, cVars, vars);
1045 /*-------------------------- Misc ---------------------------------------*/
1047 // Used to allocate memory that needs to handed to the EE.
1048 // For eg, use this to allocated memory for reporting debug info,
1049 // which will be handed to the EE by setVars() and setBoundaries()
1050 void * interceptor_ICJI::allocateArray(
1054 mcs->AddCall("allocateArray");
1055 return original_ICorJitInfo->allocateArray(cBytes);
1058 // JitCompiler will free arrays passed by the EE using this
1059 // For eg, The EE returns memory in getVars() and getBoundaries()
1060 // to the JitCompiler, which the JitCompiler should release using
1062 void interceptor_ICJI::freeArray(
1066 mcs->AddCall("freeArray");
1067 original_ICorJitInfo->freeArray(array);
1070 /*********************************************************************************/
1074 /*********************************************************************************/
1076 // advance the pointer to the argument list.
1077 // a ptr of 0, is special and always means the first argument
1078 CORINFO_ARG_LIST_HANDLE interceptor_ICJI::getArgNext (
1079 CORINFO_ARG_LIST_HANDLE args /* IN */
1082 mcs->AddCall("getArgNext");
1083 return original_ICorJitInfo->getArgNext(args);
1086 // Get the type of a particular argument
1087 // CORINFO_TYPE_UNDEF is returned when there are no more arguments
1088 // If the type returned is a primitive type (or an enum) *vcTypeRet set to nullptr
1089 // otherwise it is set to the TypeHandle associted with the type
1090 // Enumerations will always look their underlying type (probably should fix this)
1091 // Otherwise vcTypeRet is the type as would be seen by the IL,
1092 // The return value is the type that is used for calling convention purposes
1093 // (Thus if the EE wants a value class to be passed like an int, then it will
1094 // return CORINFO_TYPE_INT
1095 CorInfoTypeWithMod interceptor_ICJI::getArgType (
1096 CORINFO_SIG_INFO* sig, /* IN */
1097 CORINFO_ARG_LIST_HANDLE args, /* IN */
1098 CORINFO_CLASS_HANDLE *vcTypeRet /* OUT */
1101 mcs->AddCall("getArgType");
1102 return original_ICorJitInfo->getArgType(sig, args, vcTypeRet);
1105 // If the Arg is a CORINFO_TYPE_CLASS fetch the class handle associated with it
1106 CORINFO_CLASS_HANDLE interceptor_ICJI::getArgClass (
1107 CORINFO_SIG_INFO* sig, /* IN */
1108 CORINFO_ARG_LIST_HANDLE args /* IN */
1111 mcs->AddCall("getArgClass");
1112 return original_ICorJitInfo->getArgClass(sig, args);
1115 // Returns type of HFA for valuetype
1116 CorInfoType interceptor_ICJI::getHFAType (
1117 CORINFO_CLASS_HANDLE hClass
1120 mcs->AddCall("getHFAType");
1121 return original_ICorJitInfo->getHFAType(hClass);
1124 /*****************************************************************************
1125 * ICorErrorInfo contains methods to deal with SEH exceptions being thrown
1126 * from the corinfo interface. These methods may be called when an exception
1127 * with code EXCEPTION_COMPLUS is caught.
1128 *****************************************************************************/
1130 // Returns the HRESULT of the current exception
1131 HRESULT interceptor_ICJI::GetErrorHRESULT(
1132 struct _EXCEPTION_POINTERS *pExceptionPointers
1135 mcs->AddCall("GetErrorHRESULT");
1136 return original_ICorJitInfo->GetErrorHRESULT(pExceptionPointers);
1139 // Fetches the message of the current exception
1140 // Returns the size of the message (including terminating null). This can be
1141 // greater than bufferLength if the buffer is insufficient.
1142 ULONG interceptor_ICJI::GetErrorMessage(
1143 __inout_ecount(bufferLength) LPWSTR buffer,
1147 mcs->AddCall("GetErrorMessage");
1148 return original_ICorJitInfo->GetErrorMessage(buffer, bufferLength);
1151 // returns EXCEPTION_EXECUTE_HANDLER if it is OK for the compile to handle the
1152 // exception, abort some work (like the inlining) and continue compilation
1153 // returns EXCEPTION_CONTINUE_SEARCH if exception must always be handled by the EE
1154 // things like ThreadStoppedException ...
1155 // returns EXCEPTION_CONTINUE_EXECUTION if exception is fixed up by the EE
1157 int interceptor_ICJI::FilterException(
1158 struct _EXCEPTION_POINTERS *pExceptionPointers
1161 mcs->AddCall("FilterException");
1162 return original_ICorJitInfo->FilterException(pExceptionPointers);
1165 // Cleans up internal EE tracking when an exception is caught.
1166 void interceptor_ICJI::HandleException(
1167 struct _EXCEPTION_POINTERS *pExceptionPointers
1170 mcs->AddCall("HandleException");
1171 original_ICorJitInfo->HandleException(pExceptionPointers);
1174 void interceptor_ICJI::ThrowExceptionForJitResult(
1177 mcs->AddCall("ThrowExceptionForJitResult");
1178 original_ICorJitInfo->ThrowExceptionForJitResult(result);
1181 //Throws an exception defined by the given throw helper.
1182 void interceptor_ICJI::ThrowExceptionForHelper(
1183 const CORINFO_HELPER_DESC * throwHelper)
1185 mcs->AddCall("ThrowExceptionForHelper");
1186 original_ICorJitInfo->ThrowExceptionForHelper(throwHelper);
1189 /*****************************************************************************
1190 * ICorStaticInfo contains EE interface methods which return values that are
1191 * constant from invocation to invocation. Thus they may be embedded in
1192 * persisted information like statically generated code. (This is of course
1193 * assuming that all code versions are identical each time.)
1194 *****************************************************************************/
1196 // Return details about EE internal data structures
1197 void interceptor_ICJI::getEEInfo(
1198 CORINFO_EE_INFO *pEEInfoOut
1201 mcs->AddCall("getEEInfo");
1202 original_ICorJitInfo->getEEInfo(pEEInfoOut);
1205 // Returns name of the JIT timer log
1206 LPCWSTR interceptor_ICJI::getJitTimeLogFilename()
1208 mcs->AddCall("getJitTimeLogFilename");
1209 return original_ICorJitInfo->getJitTimeLogFilename();
1212 /*********************************************************************************/
1214 // Diagnostic methods
1216 /*********************************************************************************/
1218 // this function is for debugging only. Returns method token.
1219 // Returns mdMethodDefNil for dynamic methods.
1220 mdMethodDef interceptor_ICJI::getMethodDefFromMethod(
1221 CORINFO_METHOD_HANDLE hMethod
1224 mcs->AddCall("getMethodDefFromMethod");
1225 return original_ICorJitInfo->getMethodDefFromMethod(hMethod);
1228 // this function is for debugging only. It returns the method name
1229 // and if 'moduleName' is non-null, it sets it to something that will
1230 // says which method (a class name, or a module name)
1231 const char* interceptor_ICJI::getMethodName (
1232 CORINFO_METHOD_HANDLE ftn, /* IN */
1233 const char **moduleName /* OUT */
1236 mcs->AddCall("getMethodName");
1237 return original_ICorJitInfo->getMethodName(ftn, moduleName);
1240 // this function is for debugging only. It returns a value that
1241 // is will always be the same for a given method. It is used
1242 // to implement the 'jitRange' functionality
1243 unsigned interceptor_ICJI::getMethodHash (
1244 CORINFO_METHOD_HANDLE ftn /* IN */
1247 mcs->AddCall("getMethodHash");
1248 return original_ICorJitInfo->getMethodHash(ftn);
1251 // this function is for debugging only.
1252 size_t interceptor_ICJI::findNameOfToken (
1253 CORINFO_MODULE_HANDLE module, /* IN */
1254 mdToken metaTOK, /* IN */
1255 __out_ecount (FQNameCapacity) char * szFQName, /* OUT */
1256 size_t FQNameCapacity /* IN */
1259 mcs->AddCall("findNameOfToken");
1260 return original_ICorJitInfo->findNameOfToken(module, metaTOK, szFQName, FQNameCapacity);
1263 bool interceptor_ICJI::getSystemVAmd64PassStructInRegisterDescriptor(
1264 /* IN */ CORINFO_CLASS_HANDLE structHnd,
1265 /* OUT */ SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr
1268 mcs->AddCall("getSystemVAmd64PassStructInRegisterDescriptor");
1269 return original_ICorJitInfo->getSystemVAmd64PassStructInRegisterDescriptor(structHnd, structPassInRegDescPtr);
1272 //Stuff on ICorDynamicInfo
1273 DWORD interceptor_ICJI::getThreadTLSIndex(
1274 void **ppIndirection
1277 mcs->AddCall("getThreadTLSIndex");
1278 return original_ICorJitInfo->getThreadTLSIndex(ppIndirection);
1281 const void * interceptor_ICJI::getInlinedCallFrameVptr(
1282 void **ppIndirection
1285 mcs->AddCall("getInlinedCallFrameVptr");
1286 return original_ICorJitInfo->getInlinedCallFrameVptr(ppIndirection);
1289 LONG * interceptor_ICJI::getAddrOfCaptureThreadGlobal(
1290 void **ppIndirection
1293 mcs->AddCall("getAddrOfCaptureThreadGlobal");
1294 return original_ICorJitInfo->getAddrOfCaptureThreadGlobal(ppIndirection);
1297 SIZE_T* interceptor_ICJI::getAddrModuleDomainID(CORINFO_MODULE_HANDLE module)
1299 mcs->AddCall("getAddrModuleDomainID");
1300 return original_ICorJitInfo->getAddrModuleDomainID(module);
1303 // return the native entry point to an EE helper (see CorInfoHelpFunc)
1304 void* interceptor_ICJI::getHelperFtn (
1305 CorInfoHelpFunc ftnNum,
1306 void **ppIndirection
1309 mcs->AddCall("getHelperFtn");
1310 return original_ICorJitInfo->getHelperFtn(ftnNum, ppIndirection);
1313 // return a callable address of the function (native code). This function
1314 // may return a different value (depending on whether the method has
1315 // been JITed or not.
1316 void interceptor_ICJI::getFunctionEntryPoint(
1317 CORINFO_METHOD_HANDLE ftn, /* IN */
1318 CORINFO_CONST_LOOKUP * pResult, /* OUT */
1319 CORINFO_ACCESS_FLAGS accessFlags)
1321 mcs->AddCall("getFunctionEntryPoint");
1322 original_ICorJitInfo->getFunctionEntryPoint(ftn, pResult, accessFlags);
1325 // return a directly callable address. This can be used similarly to the
1326 // value returned by getFunctionEntryPoint() except that it is
1327 // guaranteed to be multi callable entrypoint.
1328 void interceptor_ICJI::getFunctionFixedEntryPoint(
1329 CORINFO_METHOD_HANDLE ftn,
1330 CORINFO_CONST_LOOKUP * pResult)
1332 mcs->AddCall("getFunctionFixedEntryPoint");
1333 original_ICorJitInfo->getFunctionFixedEntryPoint(ftn, pResult);
1336 // get the synchronization handle that is passed to monXstatic function
1337 void* interceptor_ICJI::getMethodSync(
1338 CORINFO_METHOD_HANDLE ftn,
1339 void **ppIndirection
1342 mcs->AddCall("getMethodSync");
1343 return original_ICorJitInfo->getMethodSync(ftn, ppIndirection);
1346 // These entry points must be called if a handle is being embedded in
1347 // the code to be passed to a JIT helper function. (as opposed to just
1348 // being passed back into the ICorInfo interface.)
1350 // get slow lazy string literal helper to use (CORINFO_HELP_STRCNS*).
1351 // Returns CORINFO_HELP_UNDEF if lazy string literal helper cannot be used.
1352 CorInfoHelpFunc interceptor_ICJI::getLazyStringLiteralHelper(
1353 CORINFO_MODULE_HANDLE handle
1356 mcs->AddCall("getLazyStringLiteralHelper");
1357 return original_ICorJitInfo->getLazyStringLiteralHelper(handle);
1360 CORINFO_MODULE_HANDLE interceptor_ICJI::embedModuleHandle(
1361 CORINFO_MODULE_HANDLE handle,
1362 void **ppIndirection
1365 mcs->AddCall("embedModuleHandle");
1366 return original_ICorJitInfo->embedModuleHandle(handle, ppIndirection);
1369 CORINFO_CLASS_HANDLE interceptor_ICJI::embedClassHandle(
1370 CORINFO_CLASS_HANDLE handle,
1371 void **ppIndirection
1374 mcs->AddCall("embedClassHandle");
1375 return original_ICorJitInfo->embedClassHandle(handle, ppIndirection);
1378 CORINFO_METHOD_HANDLE interceptor_ICJI::embedMethodHandle(
1379 CORINFO_METHOD_HANDLE handle,
1380 void **ppIndirection
1383 mcs->AddCall("embedMethodHandle");
1384 return original_ICorJitInfo->embedMethodHandle(handle, ppIndirection);
1387 CORINFO_FIELD_HANDLE interceptor_ICJI::embedFieldHandle(
1388 CORINFO_FIELD_HANDLE handle,
1389 void **ppIndirection
1392 mcs->AddCall("embedFieldHandle");
1393 return original_ICorJitInfo->embedFieldHandle(handle, ppIndirection);
1396 // Given a module scope (module), a method handle (context) and
1397 // a metadata token (metaTOK), fetch the handle
1398 // (type, field or method) associated with the token.
1399 // If this is not possible at compile-time (because the current method's
1400 // code is shared and the token contains generic parameters)
1401 // then indicate how the handle should be looked up at run-time.
1403 void interceptor_ICJI::embedGenericHandle(
1404 CORINFO_RESOLVED_TOKEN * pResolvedToken,
1405 BOOL fEmbedParent, // TRUE - embeds parent type handle of the field/method handle
1406 CORINFO_GENERICHANDLE_RESULT * pResult)
1408 mcs->AddCall("embedGenericHandle");
1409 original_ICorJitInfo->embedGenericHandle(pResolvedToken, fEmbedParent, pResult);
1412 // Return information used to locate the exact enclosing type of the current method.
1413 // Used only to invoke .cctor method from code shared across generic instantiations
1414 // !needsRuntimeLookup statically known (enclosing type of method itself)
1415 // needsRuntimeLookup:
1416 // CORINFO_LOOKUP_THISOBJ use vtable pointer of 'this' param
1417 // CORINFO_LOOKUP_CLASSPARAM use vtable hidden param
1418 // CORINFO_LOOKUP_METHODPARAM use enclosing type of method-desc hidden param
1419 CORINFO_LOOKUP_KIND interceptor_ICJI::getLocationOfThisType(
1420 CORINFO_METHOD_HANDLE context
1423 mcs->AddCall("getLocationOfThisType");
1424 return original_ICorJitInfo->getLocationOfThisType(context);
1427 // return the unmanaged target *if method has already been prelinked.*
1428 void* interceptor_ICJI::getPInvokeUnmanagedTarget(
1429 CORINFO_METHOD_HANDLE method,
1430 void **ppIndirection
1433 mcs->AddCall("getPInvokeUnmanagedTarget");
1434 return original_ICorJitInfo->getPInvokeUnmanagedTarget(method, ppIndirection);
1437 // return address of fixup area for late-bound PInvoke calls.
1438 void* interceptor_ICJI::getAddressOfPInvokeFixup(
1439 CORINFO_METHOD_HANDLE method,
1440 void **ppIndirection
1443 mcs->AddCall("getAddressOfPInvokeFixup");
1444 return original_ICorJitInfo->getAddressOfPInvokeFixup(method, ppIndirection);
1447 // return address of fixup area for late-bound PInvoke calls.
1448 void interceptor_ICJI::getAddressOfPInvokeTarget(
1449 CORINFO_METHOD_HANDLE method,
1450 CORINFO_CONST_LOOKUP *pLookup
1453 mcs->AddCall("getAddressOfPInvokeTarget");
1454 original_ICorJitInfo->getAddressOfPInvokeTarget(method, pLookup);
1457 // Generate a cookie based on the signature that would needs to be passed
1458 // to CORINFO_HELP_PINVOKE_CALLI
1459 LPVOID interceptor_ICJI::GetCookieForPInvokeCalliSig(
1460 CORINFO_SIG_INFO* szMetaSig,
1461 void ** ppIndirection
1464 mcs->AddCall("GetCookieForPInvokeCalliSig");
1465 return original_ICorJitInfo->GetCookieForPInvokeCalliSig(szMetaSig, ppIndirection);
1468 // returns true if a VM cookie can be generated for it (might be false due to cross-module
1469 // inlining, in which case the inlining should be aborted)
1470 bool interceptor_ICJI::canGetCookieForPInvokeCalliSig(
1471 CORINFO_SIG_INFO* szMetaSig
1474 mcs->AddCall("canGetCookieForPInvokeCalliSig");
1475 return original_ICorJitInfo->canGetCookieForPInvokeCalliSig(szMetaSig);
1478 // Gets a handle that is checked to see if the current method is
1479 // included in "JustMyCode"
1480 CORINFO_JUST_MY_CODE_HANDLE interceptor_ICJI::getJustMyCodeHandle(
1481 CORINFO_METHOD_HANDLE method,
1482 CORINFO_JUST_MY_CODE_HANDLE**ppIndirection
1485 mcs->AddCall("getJustMyCodeHandle");
1486 return original_ICorJitInfo->getJustMyCodeHandle(method, ppIndirection);
1489 // Gets a method handle that can be used to correlate profiling data.
1490 // This is the IP of a native method, or the address of the descriptor struct
1491 // for IL. Always guaranteed to be unique per process, and not to move. */
1492 void interceptor_ICJI::GetProfilingHandle(
1493 BOOL *pbHookFunction,
1494 void **pProfilerHandle,
1495 BOOL *pbIndirectedHandles
1498 mcs->AddCall("GetProfilingHandle");
1499 original_ICorJitInfo->GetProfilingHandle(pbHookFunction, pProfilerHandle, pbIndirectedHandles);
1502 // Returns instructions on how to make the call. See code:CORINFO_CALL_INFO for possible return values.
1503 void interceptor_ICJI::getCallInfo(
1505 CORINFO_RESOLVED_TOKEN * pResolvedToken,
1508 CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken,
1511 CORINFO_METHOD_HANDLE callerHandle,
1514 CORINFO_CALLINFO_FLAGS flags,
1517 CORINFO_CALL_INFO *pResult
1520 mcs->AddCall("getCallInfo");
1521 original_ICorJitInfo->getCallInfo(pResolvedToken, pConstrainedResolvedToken, callerHandle, flags, pResult);
1524 BOOL interceptor_ICJI::canAccessFamily(CORINFO_METHOD_HANDLE hCaller,
1525 CORINFO_CLASS_HANDLE hInstanceType)
1528 mcs->AddCall("canAccessFamily");
1529 return original_ICorJitInfo->canAccessFamily(hCaller, hInstanceType);
1531 // Returns TRUE if the Class Domain ID is the RID of the class (currently true for every class
1532 // except reflection emitted classes and generics)
1533 BOOL interceptor_ICJI::isRIDClassDomainID(CORINFO_CLASS_HANDLE cls)
1535 mcs->AddCall("isRIDClassDomainID");
1536 return original_ICorJitInfo->isRIDClassDomainID(cls);
1539 // returns the class's domain ID for accessing shared statics
1540 unsigned interceptor_ICJI::getClassDomainID (
1541 CORINFO_CLASS_HANDLE cls,
1542 void **ppIndirection
1545 mcs->AddCall("getClassDomainID");
1546 return original_ICorJitInfo->getClassDomainID(cls, ppIndirection);
1550 // return the data's address (for static fields only)
1551 void* interceptor_ICJI::getFieldAddress(
1552 CORINFO_FIELD_HANDLE field,
1553 void **ppIndirection
1556 mcs->AddCall("getFieldAddress");
1557 return original_ICorJitInfo->getFieldAddress(field, ppIndirection);
1560 // registers a vararg sig & returns a VM cookie for it (which can contain other stuff)
1561 CORINFO_VARARGS_HANDLE interceptor_ICJI::getVarArgsHandle(
1562 CORINFO_SIG_INFO *pSig,
1563 void **ppIndirection
1566 mcs->AddCall("getVarArgsHandle");
1567 return original_ICorJitInfo->getVarArgsHandle(pSig, ppIndirection);
1570 // returns true if a VM cookie can be generated for it (might be false due to cross-module
1571 // inlining, in which case the inlining should be aborted)
1572 bool interceptor_ICJI::canGetVarArgsHandle(
1573 CORINFO_SIG_INFO *pSig
1576 mcs->AddCall("canGetVarArgsHandle");
1577 return original_ICorJitInfo->canGetVarArgsHandle(pSig);
1580 // Allocate a string literal on the heap and return a handle to it
1581 InfoAccessType interceptor_ICJI::constructStringLiteral(
1582 CORINFO_MODULE_HANDLE module,
1587 mcs->AddCall("constructStringLiteral");
1588 return original_ICorJitInfo->constructStringLiteral(module, metaTok, ppValue);
1591 InfoAccessType interceptor_ICJI::emptyStringLiteral(
1595 mcs->AddCall("emptyStringLiteral");
1596 return original_ICorJitInfo->emptyStringLiteral(ppValue);
1599 // (static fields only) given that 'field' refers to thread local store,
1600 // return the ID (TLS index), which is used to find the begining of the
1601 // TLS data area for the particular DLL 'field' is associated with.
1602 DWORD interceptor_ICJI::getFieldThreadLocalStoreID (
1603 CORINFO_FIELD_HANDLE field,
1604 void **ppIndirection
1607 mcs->AddCall("getFieldThreadLocalStoreID");
1608 return original_ICorJitInfo->getFieldThreadLocalStoreID(field, ppIndirection);
1611 // Sets another object to intercept calls to "self" and current method being compiled
1612 void interceptor_ICJI::setOverride(
1613 ICorDynamicInfo *pOverride,
1614 CORINFO_METHOD_HANDLE currentMethod
1617 mcs->AddCall("setOverride");
1618 original_ICorJitInfo->setOverride(pOverride, currentMethod);
1621 // Adds an active dependency from the context method's module to the given module
1622 // This is internal callback for the EE. JIT should not call it directly.
1623 void interceptor_ICJI::addActiveDependency(
1624 CORINFO_MODULE_HANDLE moduleFrom,
1625 CORINFO_MODULE_HANDLE moduleTo
1628 mcs->AddCall("addActiveDependency");
1629 original_ICorJitInfo->addActiveDependency(moduleFrom, moduleTo);
1632 CORINFO_METHOD_HANDLE interceptor_ICJI::GetDelegateCtor(
1633 CORINFO_METHOD_HANDLE methHnd,
1634 CORINFO_CLASS_HANDLE clsHnd,
1635 CORINFO_METHOD_HANDLE targetMethodHnd,
1636 DelegateCtorArgs * pCtorData
1639 mcs->AddCall("GetDelegateCtor");
1640 return original_ICorJitInfo->GetDelegateCtor(methHnd, clsHnd, targetMethodHnd, pCtorData);
1643 void interceptor_ICJI::MethodCompileComplete(
1644 CORINFO_METHOD_HANDLE methHnd
1647 mcs->AddCall("MethodCompileComplete");
1648 original_ICorJitInfo->MethodCompileComplete(methHnd);
1651 // return a thunk that will copy the arguments for the given signature.
1652 void* interceptor_ICJI::getTailCallCopyArgsThunk (
1653 CORINFO_SIG_INFO *pSig,
1654 CorInfoHelperTailCallSpecialHandling flags
1657 mcs->AddCall("getTailCallCopyArgsThunk");
1658 return original_ICorJitInfo->getTailCallCopyArgsThunk(pSig, flags);
1661 //Stuff directly on ICorJitInfo
1663 // Returns extended flags for a particular compilation instance.
1664 DWORD interceptor_ICJI::getJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes)
1666 mcs->AddCall("getJitFlags");
1667 return original_ICorJitInfo->getJitFlags(jitFlags, sizeInBytes);
1670 // Runs the given function with the given parameter under an error trap
1671 // and returns true if the function completes successfully. We don't
1672 // record the results of the call: when this call gets played back,
1673 // its result will depend on whether or not `function` calls something
1674 // that throws at playback time rather than at capture time.
1675 bool interceptor_ICJI::runWithErrorTrap(void (*function)(void*), void *param)
1677 mcs->AddCall("runWithErrorTrap");
1678 return original_ICorJitInfo->runWithErrorTrap(function, param);
1681 // return memory manager that the JIT can use to allocate a regular memory
1682 IEEMemoryManager* interceptor_ICJI::getMemoryManager()
1684 mcs->AddCall("getMemoryManager");
1685 if(current_IEEMM->original_IEEMM == nullptr)
1686 current_IEEMM->original_IEEMM = original_ICorJitInfo->getMemoryManager();
1688 return current_IEEMM;
1691 // get a block of memory for the code, readonly data, and read-write data
1692 void interceptor_ICJI::allocMem (
1693 ULONG hotCodeSize, /* IN */
1694 ULONG coldCodeSize, /* IN */
1695 ULONG roDataSize, /* IN */
1696 ULONG xcptnsCount, /* IN */
1697 CorJitAllocMemFlag flag, /* IN */
1698 void ** hotCodeBlock, /* OUT */
1699 void ** coldCodeBlock, /* OUT */
1700 void ** roDataBlock /* OUT */
1703 mcs->AddCall("allocMem");
1704 return original_ICorJitInfo->allocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, coldCodeBlock, roDataBlock);
1707 // Reserve memory for the method/funclet's unwind information.
1708 // Note that this must be called before allocMem. It should be
1709 // called once for the main method, once for every funclet, and
1710 // once for every block of cold code for which allocUnwindInfo
1713 // This is necessary because jitted code must allocate all the
1714 // memory needed for the unwindInfo at the allocMem call.
1715 // For prejitted code we split up the unwinding information into
1716 // separate sections .rdata and .pdata.
1718 void interceptor_ICJI::reserveUnwindInfo (
1719 BOOL isFunclet, /* IN */
1720 BOOL isColdCode, /* IN */
1721 ULONG unwindSize /* IN */
1724 mcs->AddCall("reserveUnwindInfo");
1725 original_ICorJitInfo->reserveUnwindInfo(isFunclet, isColdCode, unwindSize);
1728 // Allocate and initialize the .rdata and .pdata for this method or
1729 // funclet, and get the block of memory needed for the machine-specific
1730 // unwind information (the info for crawling the stack frame).
1731 // Note that allocMem must be called first.
1735 // pHotCode main method code buffer, always filled in
1736 // pColdCode cold code buffer, only filled in if this is cold code,
1738 // startOffset start of code block, relative to appropriate code buffer
1739 // (e.g. pColdCode if cold, pHotCode if hot).
1740 // endOffset end of code block, relative to appropriate code buffer
1741 // unwindSize size of unwind info pointed to by pUnwindBlock
1742 // pUnwindBlock pointer to unwind info
1743 // funcKind type of funclet (main method code, handler, filter)
1745 void interceptor_ICJI::allocUnwindInfo (
1746 BYTE * pHotCode, /* IN */
1747 BYTE * pColdCode, /* IN */
1748 ULONG startOffset, /* IN */
1749 ULONG endOffset, /* IN */
1750 ULONG unwindSize, /* IN */
1751 BYTE * pUnwindBlock, /* IN */
1752 CorJitFuncKind funcKind /* IN */
1755 mcs->AddCall("allocUnwindInfo");
1756 original_ICorJitInfo->allocUnwindInfo(pHotCode, pColdCode, startOffset, endOffset, unwindSize, pUnwindBlock, funcKind);
1759 // Get a block of memory needed for the code manager information,
1760 // (the info for enumerating the GC pointers while crawling the
1762 // Note that allocMem must be called first
1763 void * interceptor_ICJI::allocGCInfo (
1764 size_t size /* IN */
1767 mcs->AddCall("allocGCInfo");
1768 return original_ICorJitInfo->allocGCInfo(size);
1772 void interceptor_ICJI::yieldExecution()
1774 mcs->AddCall("yieldExecution");
1775 original_ICorJitInfo->yieldExecution();
1778 // Indicate how many exception handler blocks are to be returned.
1779 // This is guaranteed to be called before any 'setEHinfo' call.
1780 // Note that allocMem must be called before this method can be called.
1781 void interceptor_ICJI::setEHcount (
1782 unsigned cEH /* IN */
1785 mcs->AddCall("setEHcount");
1786 original_ICorJitInfo->setEHcount(cEH);
1789 // Set the values for one particular exception handler block.
1791 // Handler regions should be lexically contiguous.
1792 // This is because FinallyIsUnwinding() uses lexicality to
1793 // determine if a "finally" clause is executing.
1794 void interceptor_ICJI::setEHinfo (
1795 unsigned EHnumber, /* IN */
1796 const CORINFO_EH_CLAUSE *clause /* IN */
1799 mcs->AddCall("setEHinfo");
1800 original_ICorJitInfo->setEHinfo(EHnumber, clause);
1803 // Level 1 -> fatalError, Level 2 -> Error, Level 3 -> Warning
1804 // Level 4 means happens 10 times in a run, level 5 means 100, level 6 means 1000 ...
1805 // returns non-zero if the logging succeeded
1806 BOOL interceptor_ICJI::logMsg(unsigned level, const char* fmt, va_list args)
1808 mcs->AddCall("logMsg");
1809 return original_ICorJitInfo->logMsg(level, fmt, args);
1812 // do an assert. will return true if the code should retry (DebugBreak)
1813 // returns false, if the assert should be igored.
1814 int interceptor_ICJI::doAssert(const char* szFile, int iLine, const char* szExpr)
1816 mcs->AddCall("doAssert");
1817 return original_ICorJitInfo->doAssert(szFile, iLine, szExpr);
1820 void interceptor_ICJI::reportFatalError(CorJitResult result)
1822 mcs->AddCall("reportFatalError");
1823 original_ICorJitInfo->reportFatalError(result);
1827 struct ProfileBuffer // Also defined here: code:CORBBTPROF_BLOCK_DATA
1830 ULONG ExecutionCount;
1834 // allocate a basic block profile buffer where execution counts will be stored
1835 // for jitted basic blocks.
1836 HRESULT interceptor_ICJI::allocBBProfileBuffer (
1837 ULONG count, // The number of basic blocks that we have
1838 ProfileBuffer ** profileBuffer
1841 mcs->AddCall("allocBBProfileBuffer");
1842 return original_ICorJitInfo->allocBBProfileBuffer(count, profileBuffer);
1845 // get profile information to be used for optimizing the current method. The format
1846 // of the buffer is the same as the format the JIT passes to allocBBProfileBuffer.
1847 HRESULT interceptor_ICJI::getBBProfileData(
1848 CORINFO_METHOD_HANDLE ftnHnd,
1849 ULONG * count, // The number of basic blocks that we have
1850 ProfileBuffer ** profileBuffer,
1854 mcs->AddCall("getBBProfileData");
1855 return original_ICorJitInfo->getBBProfileData(ftnHnd, count, profileBuffer, numRuns);
1858 // Associates a native call site, identified by its offset in the native code stream, with
1859 // the signature information and method handle the JIT used to lay out the call site. If
1860 // the call site has no signature information (e.g. a helper call) or has no method handle
1861 // (e.g. a CALLI P/Invoke), then null should be passed instead.
1862 void interceptor_ICJI::recordCallSite(
1863 ULONG instrOffset, /* IN */
1864 CORINFO_SIG_INFO * callSig, /* IN */
1865 CORINFO_METHOD_HANDLE methodHandle /* IN */
1868 mcs->AddCall("recordCallSite");
1869 return original_ICorJitInfo->recordCallSite(instrOffset, callSig, methodHandle);
1872 // A relocation is recorded if we are pre-jitting.
1873 // A jump thunk may be inserted if we are jitting
1874 void interceptor_ICJI::recordRelocation(
1875 void * location, /* IN */
1876 void * target, /* IN */
1877 WORD fRelocType, /* IN */
1878 WORD slotNum, /* IN */
1879 INT32 addlDelta /* IN */
1882 mcs->AddCall("recordRelocation");
1883 original_ICorJitInfo->recordRelocation(location, target, fRelocType, slotNum, addlDelta);
1886 WORD interceptor_ICJI::getRelocTypeHint(void * target)
1888 mcs->AddCall("getRelocTypeHint");
1889 return original_ICorJitInfo->getRelocTypeHint(target);
1892 // A callback to identify the range of address known to point to
1893 // compiler-generated native entry points that call back into
1895 void interceptor_ICJI::getModuleNativeEntryPointRange(
1896 void ** pStart, /* OUT */
1897 void ** pEnd /* OUT */
1900 mcs->AddCall("getModuleNativeEntryPointRange");
1901 original_ICorJitInfo->getModuleNativeEntryPointRange(pStart, pEnd);
1904 // For what machine does the VM expect the JIT to generate code? The VM
1905 // returns one of the IMAGE_FILE_MACHINE_* values. Note that if the VM
1906 // is cross-compiling (such as the case for crossgen), it will return a
1907 // different value than if it was compiling for the host architecture.
1909 DWORD interceptor_ICJI::getExpectedTargetArchitecture()
1911 mcs->AddCall("getExpectedTargetArchitecture");
1912 return original_ICorJitInfo->getExpectedTargetArchitecture();