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);
34 // Given a method descriptor ftnHnd, extract signature information into sigInfo
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 */
43 mcs->AddCall("getMethodSig");
44 original_ICorJitInfo->getMethodSig(ftn, sig, memberParent);
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 *********************************************************************/
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 */
60 mcs->AddCall("getMethodInfo");
61 return original_ICorJitInfo->getMethodInfo(ftn, info);
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
69 // The callerHnd must be the immediate caller (i.e. when we have a chain of inlined calls)
71 // The inlined method need not be verified
73 CorInfoInline interceptor_ICJI::canInline(CORINFO_METHOD_HANDLE callerHnd, /* IN */
74 CORINFO_METHOD_HANDLE calleeHnd, /* IN */
75 DWORD* pRestrictions /* OUT */
78 mcs->AddCall("canInline");
79 return original_ICorJitInfo->canInline(callerHnd, calleeHnd, pRestrictions);
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
85 void interceptor_ICJI::reportInliningDecision(CORINFO_METHOD_HANDLE inlinerHnd,
86 CORINFO_METHOD_HANDLE inlineeHnd,
87 CorInfoInline inlineResult,
90 mcs->AddCall("reportInliningDecision");
91 original_ICorJitInfo->reportInliningDecision(inlinerHnd, inlineeHnd, inlineResult, reason);
94 // Returns false if the call is across security boundaries thus we cannot tailcall
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 */
103 mcs->AddCall("canTailCall");
104 return original_ICorJitInfo->canTailCall(callerHnd, declaredCalleeHnd, exactCalleeHnd, fIsTailPrefix);
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,
113 CorInfoTailCall tailCallResult,
116 mcs->AddCall("reportTailCallDecision");
117 original_ICorJitInfo->reportTailCallDecision(callerHnd, calleeHnd, fIsTailPrefix, tailCallResult, reason);
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 */
126 mcs->AddCall("getEHinfo");
127 original_ICorJitInfo->getEHinfo(ftn, EHnumber, clause);
130 // return class it belongs to
131 CORINFO_CLASS_HANDLE interceptor_ICJI::getMethodClass(CORINFO_METHOD_HANDLE method)
133 mcs->AddCall("getMethodClass");
134 return original_ICorJitInfo->getMethodClass(method);
137 // return module it belongs to
138 CORINFO_MODULE_HANDLE interceptor_ICJI::getMethodModule(CORINFO_METHOD_HANDLE method)
140 mcs->AddCall("getMethodModule");
141 return original_ICorJitInfo->getMethodModule(method);
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 bool* isRelative /* OUT */
152 mcs->AddCall("getMethodVTableOffset");
153 original_ICorJitInfo->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection, isRelative);
156 // Find the virtual method in implementingClass that overrides virtualMethod.
157 // Return null if devirtualization is not possible.
158 CORINFO_METHOD_HANDLE interceptor_ICJI::resolveVirtualMethod(CORINFO_METHOD_HANDLE virtualMethod,
159 CORINFO_CLASS_HANDLE implementingClass,
160 CORINFO_CONTEXT_HANDLE ownerType)
162 mcs->AddCall("resolveVirtualMethod");
163 return original_ICorJitInfo->resolveVirtualMethod(virtualMethod, implementingClass, ownerType);
166 void interceptor_ICJI::expandRawHandleIntrinsic(
167 CORINFO_RESOLVED_TOKEN * pResolvedToken,
168 CORINFO_GENERICHANDLE_RESULT * pResult)
170 mcs->AddCall("expandRawHandleIntrinsic");
171 original_ICorJitInfo->expandRawHandleIntrinsic(pResolvedToken, pResult);
174 // If a method's attributes have (getMethodAttribs) CORINFO_FLG_INTRINSIC set,
175 // getIntrinsicID() returns the intrinsic ID.
176 CorInfoIntrinsics interceptor_ICJI::getIntrinsicID(CORINFO_METHOD_HANDLE method, bool* pMustExpand /* OUT */
179 mcs->AddCall("getIntrinsicID");
180 return original_ICorJitInfo->getIntrinsicID(method, pMustExpand);
183 // Is the given module the System.Numerics.Vectors module?
184 bool interceptor_ICJI::isInSIMDModule(CORINFO_CLASS_HANDLE classHnd)
186 mcs->AddCall("isInSIMDModule");
187 return original_ICorJitInfo->isInSIMDModule(classHnd);
190 // return the unmanaged calling convention for a PInvoke
191 CorInfoUnmanagedCallConv interceptor_ICJI::getUnmanagedCallConv(CORINFO_METHOD_HANDLE method)
193 mcs->AddCall("getUnmanagedCallConv");
194 return original_ICorJitInfo->getUnmanagedCallConv(method);
197 // return if any marshaling is required for PInvoke methods. Note that
198 // method == 0 => calli. The call site sig is only needed for the varargs or calli case
199 BOOL interceptor_ICJI::pInvokeMarshalingRequired(CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* callSiteSig)
201 mcs->AddCall("pInvokeMarshalingRequired");
202 return original_ICorJitInfo->pInvokeMarshalingRequired(method, callSiteSig);
205 // Check constraints on method type arguments (only).
206 // The parent class should be checked separately using satisfiesClassConstraints(parent).
207 BOOL interceptor_ICJI::satisfiesMethodConstraints(CORINFO_CLASS_HANDLE parent, // the exact parent of the method
208 CORINFO_METHOD_HANDLE method)
210 mcs->AddCall("satisfiesMethodConstraints");
211 return original_ICorJitInfo->satisfiesMethodConstraints(parent, method);
214 // Given a delegate target class, a target method parent class, a target method,
215 // a delegate class, check if the method signature is compatible with the Invoke method of the delegate
216 // (under the typical instantiation of any free type variables in the memberref signatures).
217 BOOL interceptor_ICJI::isCompatibleDelegate(
218 CORINFO_CLASS_HANDLE objCls, /* type of the delegate target, if any */
219 CORINFO_CLASS_HANDLE methodParentCls, /* exact parent of the target method, if any */
220 CORINFO_METHOD_HANDLE method, /* (representative) target method, if any */
221 CORINFO_CLASS_HANDLE delegateCls, /* exact type of the delegate */
222 BOOL* pfIsOpenDelegate /* is the delegate open */
225 mcs->AddCall("isCompatibleDelegate");
226 return original_ICorJitInfo->isCompatibleDelegate(objCls, methodParentCls, method, delegateCls, pfIsOpenDelegate);
229 // Indicates if the method is an instance of the generic
230 // method that passes (or has passed) verification
231 CorInfoInstantiationVerification interceptor_ICJI::isInstantiationOfVerifiedGeneric(CORINFO_METHOD_HANDLE method /* IN
235 mcs->AddCall("isInstantiationOfVerifiedGeneric");
236 return original_ICorJitInfo->isInstantiationOfVerifiedGeneric(method);
239 // Loads the constraints on a typical method definition, detecting cycles;
240 // for use in verification.
241 void interceptor_ICJI::initConstraintsForVerification(CORINFO_METHOD_HANDLE method, /* IN */
242 BOOL* pfHasCircularClassConstraints, /* OUT */
243 BOOL* pfHasCircularMethodConstraint /* OUT */
246 mcs->AddCall("initConstraintsForVerification");
247 original_ICorJitInfo->initConstraintsForVerification(method, pfHasCircularClassConstraints,
248 pfHasCircularMethodConstraint);
251 // Returns enum whether the method does not require verification
252 // Also see ICorModuleInfo::canSkipVerification
253 CorInfoCanSkipVerificationResult interceptor_ICJI::canSkipMethodVerification(CORINFO_METHOD_HANDLE ftnHandle)
255 mcs->AddCall("canSkipMethodVerification");
256 return original_ICorJitInfo->canSkipMethodVerification(ftnHandle);
259 // load and restore the method
260 void interceptor_ICJI::methodMustBeLoadedBeforeCodeIsRun(CORINFO_METHOD_HANDLE method)
262 mcs->AddCall("methodMustBeLoadedBeforeCodeIsRun");
263 original_ICorJitInfo->methodMustBeLoadedBeforeCodeIsRun(method);
266 CORINFO_METHOD_HANDLE interceptor_ICJI::mapMethodDeclToMethodImpl(CORINFO_METHOD_HANDLE method)
268 mcs->AddCall("mapMethodDeclToMethodImpl");
269 return original_ICorJitInfo->mapMethodDeclToMethodImpl(method);
272 // Returns the global cookie for the /GS unsafe buffer checks
273 // The cookie might be a constant value (JIT), or a handle to memory location (Ngen)
274 void interceptor_ICJI::getGSCookie(GSCookie* pCookieVal, // OUT
275 GSCookie** ppCookieVal // OUT
278 mcs->AddCall("getGSCookie");
279 original_ICorJitInfo->getGSCookie(pCookieVal, ppCookieVal);
282 /**********************************************************************************/
286 /**********************************************************************************/
288 // Resolve metadata token into runtime method handles.
289 void interceptor_ICJI::resolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN* pResolvedToken)
291 mcs->AddCall("resolveToken");
292 original_ICorJitInfo->resolveToken(pResolvedToken);
295 bool interceptor_ICJI::tryResolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN* pResolvedToken)
297 mcs->AddCall("tryResolveToken");
298 return original_ICorJitInfo->tryResolveToken(pResolvedToken);
301 // Signature information about the call sig
302 void interceptor_ICJI::findSig(CORINFO_MODULE_HANDLE module, /* IN */
303 unsigned sigTOK, /* IN */
304 CORINFO_CONTEXT_HANDLE context, /* IN */
305 CORINFO_SIG_INFO* sig /* OUT */
308 mcs->AddCall("findSig");
309 original_ICorJitInfo->findSig(module, sigTOK, context, sig);
312 // for Varargs, the signature at the call site may differ from
313 // the signature at the definition. Thus we need a way of
314 // fetching the call site information
315 void interceptor_ICJI::findCallSiteSig(CORINFO_MODULE_HANDLE module, /* IN */
316 unsigned methTOK, /* IN */
317 CORINFO_CONTEXT_HANDLE context, /* IN */
318 CORINFO_SIG_INFO* sig /* OUT */
321 mcs->AddCall("findCallSiteSig");
322 original_ICorJitInfo->findCallSiteSig(module, methTOK, context, sig);
325 CORINFO_CLASS_HANDLE interceptor_ICJI::getTokenTypeAsHandle(CORINFO_RESOLVED_TOKEN* pResolvedToken /* IN */)
327 mcs->AddCall("getTokenTypeAsHandle");
328 return original_ICorJitInfo->getTokenTypeAsHandle(pResolvedToken);
331 // Returns true if the module does not require verification
333 // If fQuickCheckOnlyWithoutCommit=TRUE, the function only checks that the
334 // module does not currently require verification in the current AppDomain.
335 // This decision could change in the future, and so should not be cached.
336 // If it is cached, it should only be used as a hint.
337 // This is only used by ngen for calculating certain hints.
340 // Returns enum whether the module does not require verification
341 // Also see ICorMethodInfo::canSkipMethodVerification();
342 CorInfoCanSkipVerificationResult interceptor_ICJI::canSkipVerification(CORINFO_MODULE_HANDLE module /* IN */
345 mcs->AddCall("canSkipVerification");
346 return original_ICorJitInfo->canSkipVerification(module);
349 // Checks if the given metadata token is valid
350 BOOL interceptor_ICJI::isValidToken(CORINFO_MODULE_HANDLE module, /* IN */
351 unsigned metaTOK /* IN */
354 mcs->AddCall("isValidToken");
355 return original_ICorJitInfo->isValidToken(module, metaTOK);
358 // Checks if the given metadata token is valid StringRef
359 BOOL interceptor_ICJI::isValidStringRef(CORINFO_MODULE_HANDLE module, /* IN */
360 unsigned metaTOK /* IN */
363 mcs->AddCall("isValidStringRef");
364 return original_ICorJitInfo->isValidStringRef(module, metaTOK);
367 BOOL interceptor_ICJI::shouldEnforceCallvirtRestriction(CORINFO_MODULE_HANDLE scope)
369 mcs->AddCall("shouldEnforceCallvirtRestriction");
370 return original_ICorJitInfo->shouldEnforceCallvirtRestriction(scope);
373 /**********************************************************************************/
377 /**********************************************************************************/
379 // If the value class 'cls' is isomorphic to a primitive type it will
380 // return that type, otherwise it will return CORINFO_TYPE_VALUECLASS
381 CorInfoType interceptor_ICJI::asCorInfoType(CORINFO_CLASS_HANDLE cls)
383 mcs->AddCall("asCorInfoType");
384 return original_ICorJitInfo->asCorInfoType(cls);
388 const char* interceptor_ICJI::getClassName(CORINFO_CLASS_HANDLE cls)
390 mcs->AddCall("getClassName");
391 return original_ICorJitInfo->getClassName(cls);
394 // Append a (possibly truncated) representation of the type cls to the preallocated buffer ppBuf of length pnBufLen
395 // If fNamespace=TRUE, include the namespace/enclosing classes
396 // If fFullInst=TRUE (regardless of fNamespace and fAssembly), include namespace and assembly for any type parameters
397 // If fAssembly=TRUE, suffix with a comma and the full assembly qualification
398 // return size of representation
399 int interceptor_ICJI::appendClassName(__deref_inout_ecount(*pnBufLen) WCHAR** ppBuf,
401 CORINFO_CLASS_HANDLE cls,
406 mcs->AddCall("appendClassName");
407 return original_ICorJitInfo->appendClassName(ppBuf, pnBufLen, cls, fNamespace, fFullInst, fAssembly);
410 // Quick check whether the type is a value class. Returns the same value as getClassAttribs(cls) &
411 // CORINFO_FLG_VALUECLASS, except faster.
412 BOOL interceptor_ICJI::isValueClass(CORINFO_CLASS_HANDLE cls)
414 mcs->AddCall("isValueClass");
415 return original_ICorJitInfo->isValueClass(cls);
418 // If this method returns true, JIT will do optimization to inline the check for
419 // GetTypeFromHandle(handle) == obj.GetType()
420 BOOL interceptor_ICJI::canInlineTypeCheckWithObjectVTable(CORINFO_CLASS_HANDLE cls)
422 mcs->AddCall("canInlineTypeCheckWithObjectVTable");
423 return original_ICorJitInfo->canInlineTypeCheckWithObjectVTable(cls);
426 // return flags (defined above, CORINFO_FLG_PUBLIC ...)
427 DWORD interceptor_ICJI::getClassAttribs(CORINFO_CLASS_HANDLE cls)
429 mcs->AddCall("getClassAttribs");
430 return original_ICorJitInfo->getClassAttribs(cls);
433 // Returns "TRUE" iff "cls" is a struct type such that return buffers used for returning a value
434 // of this type must be stack-allocated. This will generally be true only if the struct
435 // contains GC pointers, and does not exceed some size limit. Maintaining this as an invariant allows
436 // an optimization: the JIT may assume that return buffer pointers for return types for which this predicate
437 // returns TRUE are always stack allocated, and thus, that stores to the GC-pointer fields of such return
438 // buffers do not require GC write barriers.
439 BOOL interceptor_ICJI::isStructRequiringStackAllocRetBuf(CORINFO_CLASS_HANDLE cls)
441 mcs->AddCall("isStructRequiringStackAllocRetBuf");
442 return original_ICorJitInfo->isStructRequiringStackAllocRetBuf(cls);
445 CORINFO_MODULE_HANDLE interceptor_ICJI::getClassModule(CORINFO_CLASS_HANDLE cls)
447 mcs->AddCall("getClassModule");
448 return original_ICorJitInfo->getClassModule(cls);
451 // Returns the assembly that contains the module "mod".
452 CORINFO_ASSEMBLY_HANDLE interceptor_ICJI::getModuleAssembly(CORINFO_MODULE_HANDLE mod)
454 mcs->AddCall("getModuleAssembly");
455 return original_ICorJitInfo->getModuleAssembly(mod);
458 // Returns the name of the assembly "assem".
459 const char* interceptor_ICJI::getAssemblyName(CORINFO_ASSEMBLY_HANDLE assem)
461 mcs->AddCall("getAssemblyName");
462 return original_ICorJitInfo->getAssemblyName(assem);
465 // Allocate and delete process-lifetime objects. Should only be
466 // referred to from static fields, lest a leak occur.
467 // Note that "LongLifetimeFree" does not execute destructors, if "obj"
468 // is an array of a struct type with a destructor.
469 void* interceptor_ICJI::LongLifetimeMalloc(size_t sz)
471 mcs->AddCall("LongLifetimeMalloc");
472 return original_ICorJitInfo->LongLifetimeMalloc(sz);
475 void interceptor_ICJI::LongLifetimeFree(void* obj)
477 mcs->AddCall("LongLifetimeFree");
478 original_ICorJitInfo->LongLifetimeFree(obj);
481 size_t interceptor_ICJI::getClassModuleIdForStatics(CORINFO_CLASS_HANDLE cls,
482 CORINFO_MODULE_HANDLE* pModule,
483 void** ppIndirection)
485 mcs->AddCall("getClassModuleIdForStatics");
486 return original_ICorJitInfo->getClassModuleIdForStatics(cls, pModule, ppIndirection);
489 // return the number of bytes needed by an instance of the class
490 unsigned interceptor_ICJI::getClassSize(CORINFO_CLASS_HANDLE cls)
492 mcs->AddCall("getClassSize");
493 return original_ICorJitInfo->getClassSize(cls);
496 unsigned interceptor_ICJI::getClassAlignmentRequirement(CORINFO_CLASS_HANDLE cls, BOOL fDoubleAlignHint)
498 mcs->AddCall("getClassAlignmentRequirement");
499 return original_ICorJitInfo->getClassAlignmentRequirement(cls, fDoubleAlignHint);
502 // This is only called for Value classes. It returns a boolean array
503 // in representing of 'cls' from a GC perspective. The class is
504 // assumed to be an array of machine words
505 // (of length // getClassSize(cls) / sizeof(void*)),
506 // 'gcPtrs' is a pointer to an array of BYTEs of this length.
507 // getClassGClayout fills in this array so that gcPtrs[i] is set
508 // to one of the CorInfoGCType values which is the GC type of
509 // the i-th machine word of an object of type 'cls'
510 // returns the number of GC pointers in the array
511 unsigned interceptor_ICJI::getClassGClayout(CORINFO_CLASS_HANDLE cls, /* IN */
512 BYTE* gcPtrs /* OUT */
515 mcs->AddCall("getClassGClayout");
516 return original_ICorJitInfo->getClassGClayout(cls, gcPtrs);
519 // returns the number of instance fields in a class
520 unsigned interceptor_ICJI::getClassNumInstanceFields(CORINFO_CLASS_HANDLE cls /* IN */
523 mcs->AddCall("getClassNumInstanceFields");
524 return original_ICorJitInfo->getClassNumInstanceFields(cls);
527 CORINFO_FIELD_HANDLE interceptor_ICJI::getFieldInClass(CORINFO_CLASS_HANDLE clsHnd, INT num)
529 mcs->AddCall("getFieldInClass");
530 return original_ICorJitInfo->getFieldInClass(clsHnd, num);
533 BOOL interceptor_ICJI::checkMethodModifier(CORINFO_METHOD_HANDLE hMethod, LPCSTR modifier, BOOL fOptional)
535 mcs->AddCall("checkMethodModifier");
536 return original_ICorJitInfo->checkMethodModifier(hMethod, modifier, fOptional);
539 // returns the "NEW" helper optimized for "newCls."
540 CorInfoHelpFunc interceptor_ICJI::getNewHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken,
541 CORINFO_METHOD_HANDLE callerHandle)
543 mcs->AddCall("getNewHelper");
544 return original_ICorJitInfo->getNewHelper(pResolvedToken, callerHandle);
547 // returns the newArr (1-Dim array) helper optimized for "arrayCls."
548 CorInfoHelpFunc interceptor_ICJI::getNewArrHelper(CORINFO_CLASS_HANDLE arrayCls)
550 mcs->AddCall("getNewArrHelper");
551 return original_ICorJitInfo->getNewArrHelper(arrayCls);
554 // returns the optimized "IsInstanceOf" or "ChkCast" helper
555 CorInfoHelpFunc interceptor_ICJI::getCastingHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken, bool fThrowing)
557 mcs->AddCall("getCastingHelper");
558 return original_ICorJitInfo->getCastingHelper(pResolvedToken, fThrowing);
561 // returns helper to trigger static constructor
562 CorInfoHelpFunc interceptor_ICJI::getSharedCCtorHelper(CORINFO_CLASS_HANDLE clsHnd)
564 mcs->AddCall("getSharedCCtorHelper");
565 return original_ICorJitInfo->getSharedCCtorHelper(clsHnd);
568 CorInfoHelpFunc interceptor_ICJI::getSecurityPrologHelper(CORINFO_METHOD_HANDLE ftn)
570 mcs->AddCall("getSecurityPrologHelper");
571 return original_ICorJitInfo->getSecurityPrologHelper(ftn);
574 // This is not pretty. Boxing nullable<T> actually returns
575 // a boxed<T> not a boxed Nullable<T>. This call allows the verifier
576 // to call back to the EE on the 'box' instruction and get the transformed
577 // type to use for verification.
578 CORINFO_CLASS_HANDLE interceptor_ICJI::getTypeForBox(CORINFO_CLASS_HANDLE cls)
580 mcs->AddCall("getTypeForBox");
581 return original_ICorJitInfo->getTypeForBox(cls);
584 // returns the correct box helper for a particular class. Note
585 // that if this returns CORINFO_HELP_BOX, the JIT can assume
586 // 'standard' boxing (allocate object and copy), and optimize
587 CorInfoHelpFunc interceptor_ICJI::getBoxHelper(CORINFO_CLASS_HANDLE cls)
589 mcs->AddCall("getBoxHelper");
590 return original_ICorJitInfo->getBoxHelper(cls);
593 // returns the unbox helper. If 'helperCopies' points to a true
594 // value it means the JIT is requesting a helper that unboxes the
595 // value into a particular location and thus has the signature
596 // void unboxHelper(void* dest, CORINFO_CLASS_HANDLE cls, Object* obj)
597 // Otherwise (it is null or points at a FALSE value) it is requesting
598 // a helper that returns a pointer to the unboxed data
599 // void* unboxHelper(CORINFO_CLASS_HANDLE cls, Object* obj)
600 // The EE has the option of NOT returning the copy style helper
601 // (But must be able to always honor the non-copy style helper)
602 // The EE set 'helperCopies' on return to indicate what kind of
603 // helper has been created.
605 CorInfoHelpFunc interceptor_ICJI::getUnBoxHelper(CORINFO_CLASS_HANDLE cls)
607 mcs->AddCall("getUnBoxHelper");
608 return original_ICorJitInfo->getUnBoxHelper(cls);
611 bool interceptor_ICJI::getReadyToRunHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken,
612 CORINFO_LOOKUP_KIND* pGenericLookupKind,
614 CORINFO_CONST_LOOKUP* pLookup)
616 mcs->AddCall("getReadyToRunHelper");
617 return original_ICorJitInfo->getReadyToRunHelper(pResolvedToken, pGenericLookupKind, id, pLookup);
620 void interceptor_ICJI::getReadyToRunDelegateCtorHelper(CORINFO_RESOLVED_TOKEN* pTargetMethod,
621 CORINFO_CLASS_HANDLE delegateType,
622 CORINFO_LOOKUP* pLookup)
624 mcs->AddCall("getReadyToRunDelegateCtorHelper");
625 original_ICorJitInfo->getReadyToRunDelegateCtorHelper(pTargetMethod, delegateType, pLookup);
628 const char* interceptor_ICJI::getHelperName(CorInfoHelpFunc funcNum)
630 mcs->AddCall("getHelperName");
631 return original_ICorJitInfo->getHelperName(funcNum);
634 // This function tries to initialize the class (run the class constructor).
635 // this function returns whether the JIT must insert helper calls before
636 // accessing static field or method.
638 // See code:ICorClassInfo#ClassConstruction.
639 CorInfoInitClassResult interceptor_ICJI::initClass(
640 CORINFO_FIELD_HANDLE field, // Non-nullptr - inquire about cctor trigger before static field access
641 // nullptr - inquire about cctor trigger in method prolog
642 CORINFO_METHOD_HANDLE method, // Method referencing the field or prolog
643 CORINFO_CONTEXT_HANDLE context, // Exact context of method
644 BOOL speculative // TRUE means don't actually run it
647 mcs->AddCall("initClass");
648 return original_ICorJitInfo->initClass(field, method, context, speculative);
651 // This used to be called "loadClass". This records the fact
652 // that the class must be loaded (including restored if necessary) before we execute the
653 // code that we are currently generating. When jitting code
654 // the function loads the class immediately. When zapping code
655 // the zapper will if necessary use the call to record the fact that we have
656 // to do a fixup/restore before running the method currently being generated.
658 // This is typically used to ensure value types are loaded before zapped
659 // code that manipulates them is executed, so that the GC can access information
660 // about those value types.
661 void interceptor_ICJI::classMustBeLoadedBeforeCodeIsRun(CORINFO_CLASS_HANDLE cls)
663 mcs->AddCall("classMustBeLoadedBeforeCodeIsRun");
664 original_ICorJitInfo->classMustBeLoadedBeforeCodeIsRun(cls);
667 // returns the class handle for the special builtin classes
668 CORINFO_CLASS_HANDLE interceptor_ICJI::getBuiltinClass(CorInfoClassId classId)
670 mcs->AddCall("getBuiltinClass");
671 return original_ICorJitInfo->getBuiltinClass(classId);
674 // "System.Int32" ==> CORINFO_TYPE_INT..
675 CorInfoType interceptor_ICJI::getTypeForPrimitiveValueClass(CORINFO_CLASS_HANDLE cls)
677 mcs->AddCall("getTypeForPrimitiveValueClass");
678 return original_ICorJitInfo->getTypeForPrimitiveValueClass(cls);
681 // TRUE if child is a subtype of parent
682 // if parent is an interface, then does child implement / extend parent
683 BOOL interceptor_ICJI::canCast(CORINFO_CLASS_HANDLE child, // subtype (extends parent)
684 CORINFO_CLASS_HANDLE parent // base type
687 mcs->AddCall("canCast");
688 return original_ICorJitInfo->canCast(child, parent);
691 // TRUE if cls1 and cls2 are considered equivalent types.
692 BOOL interceptor_ICJI::areTypesEquivalent(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2)
694 mcs->AddCall("areTypesEquivalent");
695 return original_ICorJitInfo->areTypesEquivalent(cls1, cls2);
698 // returns is the intersection of cls1 and cls2.
699 CORINFO_CLASS_HANDLE interceptor_ICJI::mergeClasses(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2)
701 mcs->AddCall("mergeClasses");
702 return original_ICorJitInfo->mergeClasses(cls1, cls2);
705 // Given a class handle, returns the Parent type.
706 // For COMObjectType, it returns Class Handle of System.Object.
707 // Returns 0 if System.Object is passed in.
708 CORINFO_CLASS_HANDLE interceptor_ICJI::getParentType(CORINFO_CLASS_HANDLE cls)
710 mcs->AddCall("getParentType");
711 return original_ICorJitInfo->getParentType(cls);
714 // Returns the CorInfoType of the "child type". If the child type is
715 // not a primitive type, *clsRet will be set.
716 // Given an Array of Type Foo, returns Foo.
717 // Given BYREF Foo, returns Foo
718 CorInfoType interceptor_ICJI::getChildType(CORINFO_CLASS_HANDLE clsHnd, CORINFO_CLASS_HANDLE* clsRet)
720 mcs->AddCall("getChildType");
721 return original_ICorJitInfo->getChildType(clsHnd, clsRet);
724 // Check constraints on type arguments of this class and parent classes
725 BOOL interceptor_ICJI::satisfiesClassConstraints(CORINFO_CLASS_HANDLE cls)
727 mcs->AddCall("satisfiesClassConstraints");
728 return original_ICorJitInfo->satisfiesClassConstraints(cls);
731 // Check if this is a single dimensional array type
732 BOOL interceptor_ICJI::isSDArray(CORINFO_CLASS_HANDLE cls)
734 mcs->AddCall("isSDArray");
735 return original_ICorJitInfo->isSDArray(cls);
738 // Get the numbmer of dimensions in an array
739 unsigned interceptor_ICJI::getArrayRank(CORINFO_CLASS_HANDLE cls)
741 mcs->AddCall("getArrayRank");
742 return original_ICorJitInfo->getArrayRank(cls);
745 // Get static field data for an array
746 void* interceptor_ICJI::getArrayInitializationData(CORINFO_FIELD_HANDLE field, DWORD size)
748 mcs->AddCall("getArrayInitializationData");
749 return original_ICorJitInfo->getArrayInitializationData(field, size);
752 // Check Visibility rules.
753 CorInfoIsAccessAllowedResult interceptor_ICJI::canAccessClass(
754 CORINFO_RESOLVED_TOKEN* pResolvedToken,
755 CORINFO_METHOD_HANDLE callerHandle,
756 CORINFO_HELPER_DESC* pAccessHelper /* If canAccessMethod returns something other
757 than ALLOWED, then this is filled in. */
760 mcs->AddCall("canAccessClass");
761 return original_ICorJitInfo->canAccessClass(pResolvedToken, callerHandle, pAccessHelper);
764 /**********************************************************************************/
768 /**********************************************************************************/
770 // this function is for debugging only. It returns the field name
771 // and if 'moduleName' is non-null, it sets it to something that will
772 // says which method (a class name, or a module name)
773 const char* interceptor_ICJI::getFieldName(CORINFO_FIELD_HANDLE ftn, /* IN */
774 const char** moduleName /* OUT */
777 mcs->AddCall("getFieldName");
778 return original_ICorJitInfo->getFieldName(ftn, moduleName);
781 // return class it belongs to
782 CORINFO_CLASS_HANDLE interceptor_ICJI::getFieldClass(CORINFO_FIELD_HANDLE field)
784 mcs->AddCall("getFieldClass");
785 return original_ICorJitInfo->getFieldClass(field);
788 // Return the field's type, if it is CORINFO_TYPE_VALUECLASS 'structType' is set
789 // the field's value class (if 'structType' == 0, then don't bother
790 // the structure info).
792 // 'memberParent' is typically only set when verifying. It should be the
793 // result of calling getMemberParent.
794 CorInfoType interceptor_ICJI::getFieldType(CORINFO_FIELD_HANDLE field,
795 CORINFO_CLASS_HANDLE* structType,
796 CORINFO_CLASS_HANDLE memberParent /* IN */
799 mcs->AddCall("getFieldType");
800 return original_ICorJitInfo->getFieldType(field, structType, memberParent);
803 // return the data member's instance offset
804 unsigned interceptor_ICJI::getFieldOffset(CORINFO_FIELD_HANDLE field)
806 mcs->AddCall("getFieldOffset");
807 return original_ICorJitInfo->getFieldOffset(field);
810 // TODO: jit64 should be switched to the same plan as the i386 jits - use
811 // getClassGClayout to figure out the need for writebarrier helper, and inline the copying.
812 // The interpretted value class copy is slow. Once this happens, USE_WRITE_BARRIER_HELPERS
813 bool interceptor_ICJI::isWriteBarrierHelperRequired(CORINFO_FIELD_HANDLE field)
815 mcs->AddCall("isWriteBarrierHelperRequired");
816 return original_ICorJitInfo->isWriteBarrierHelperRequired(field);
819 void interceptor_ICJI::getFieldInfo(CORINFO_RESOLVED_TOKEN* pResolvedToken,
820 CORINFO_METHOD_HANDLE callerHandle,
821 CORINFO_ACCESS_FLAGS flags,
822 CORINFO_FIELD_INFO* pResult)
824 mcs->AddCall("getFieldInfo");
825 original_ICorJitInfo->getFieldInfo(pResolvedToken, callerHandle, flags, pResult);
828 // Returns true iff "fldHnd" represents a static field.
829 bool interceptor_ICJI::isFieldStatic(CORINFO_FIELD_HANDLE fldHnd)
831 mcs->AddCall("isFieldStatic");
832 return original_ICorJitInfo->isFieldStatic(fldHnd);
835 /*********************************************************************************/
839 /*********************************************************************************/
841 // Query the EE to find out where interesting break points
842 // in the code are. The native compiler will ensure that these places
843 // have a corresponding break point in native code.
845 // Note that unless CORJIT_FLAG_DEBUG_CODE is specified, this function will
846 // be used only as a hint and the native compiler should not change its
848 void interceptor_ICJI::getBoundaries(CORINFO_METHOD_HANDLE ftn, // [IN] method of interest
849 unsigned int* cILOffsets, // [OUT] size of pILOffsets
850 DWORD** pILOffsets, // [OUT] IL offsets of interest
851 // jit MUST free with freeArray!
852 ICorDebugInfo::BoundaryTypes* implictBoundaries // [OUT] tell jit, all boundries of
856 mcs->AddCall("getBoundaries");
857 original_ICorJitInfo->getBoundaries(ftn, cILOffsets, pILOffsets, implictBoundaries);
860 // Report back the mapping from IL to native code,
861 // this map should include all boundaries that 'getBoundaries'
862 // reported as interesting to the debugger.
864 // Note that debugger (and profiler) is assuming that all of the
865 // offsets form a contiguous block of memory, and that the
866 // OffsetMapping is sorted in order of increasing native offset.
867 void interceptor_ICJI::setBoundaries(CORINFO_METHOD_HANDLE ftn, // [IN] method of interest
868 ULONG32 cMap, // [IN] size of pMap
869 ICorDebugInfo::OffsetMapping* pMap // [IN] map including all points of interest.
870 // jit allocated with allocateArray, EE
874 mcs->AddCall("setBoundaries");
875 original_ICorJitInfo->setBoundaries(ftn, cMap, pMap);
878 // Query the EE to find out the scope of local varables.
879 // normally the JIT would trash variables after last use, but
880 // under debugging, the JIT needs to keep them live over their
881 // entire scope so that they can be inspected.
883 // Note that unless CORJIT_FLAG_DEBUG_CODE is specified, this function will
884 // be used only as a hint and the native compiler should not change its
886 void interceptor_ICJI::getVars(CORINFO_METHOD_HANDLE ftn, // [IN] method of interest
887 ULONG32* cVars, // [OUT] size of 'vars'
888 ICorDebugInfo::ILVarInfo** vars, // [OUT] scopes of variables of interest
889 // jit MUST free with freeArray!
890 bool* extendOthers // [OUT] it TRUE, then assume the scope
891 // of unmentioned vars is entire method
894 mcs->AddCall("getVars");
895 original_ICorJitInfo->getVars(ftn, cVars, vars, extendOthers);
898 // Report back to the EE the location of every variable.
899 // note that the JIT might split lifetimes into different
902 void interceptor_ICJI::setVars(CORINFO_METHOD_HANDLE ftn, // [IN] method of interest
903 ULONG32 cVars, // [IN] size of 'vars'
904 ICorDebugInfo::NativeVarInfo* vars // [IN] map telling where local vars are stored at
906 // jit allocated with allocateArray, EE frees
909 mcs->AddCall("setVars");
910 original_ICorJitInfo->setVars(ftn, cVars, vars);
913 /*-------------------------- Misc ---------------------------------------*/
915 // Used to allocate memory that needs to handed to the EE.
916 // For eg, use this to allocated memory for reporting debug info,
917 // which will be handed to the EE by setVars() and setBoundaries()
918 void* interceptor_ICJI::allocateArray(ULONG cBytes)
920 mcs->AddCall("allocateArray");
921 return original_ICorJitInfo->allocateArray(cBytes);
924 // JitCompiler will free arrays passed by the EE using this
925 // For eg, The EE returns memory in getVars() and getBoundaries()
926 // to the JitCompiler, which the JitCompiler should release using
928 void interceptor_ICJI::freeArray(void* array)
930 mcs->AddCall("freeArray");
931 original_ICorJitInfo->freeArray(array);
934 /*********************************************************************************/
938 /*********************************************************************************/
940 // advance the pointer to the argument list.
941 // a ptr of 0, is special and always means the first argument
942 CORINFO_ARG_LIST_HANDLE interceptor_ICJI::getArgNext(CORINFO_ARG_LIST_HANDLE args /* IN */
945 mcs->AddCall("getArgNext");
946 return original_ICorJitInfo->getArgNext(args);
949 // Get the type of a particular argument
950 // CORINFO_TYPE_UNDEF is returned when there are no more arguments
951 // If the type returned is a primitive type (or an enum) *vcTypeRet set to nullptr
952 // otherwise it is set to the TypeHandle associted with the type
953 // Enumerations will always look their underlying type (probably should fix this)
954 // Otherwise vcTypeRet is the type as would be seen by the IL,
955 // The return value is the type that is used for calling convention purposes
956 // (Thus if the EE wants a value class to be passed like an int, then it will
957 // return CORINFO_TYPE_INT
958 CorInfoTypeWithMod interceptor_ICJI::getArgType(CORINFO_SIG_INFO* sig, /* IN */
959 CORINFO_ARG_LIST_HANDLE args, /* IN */
960 CORINFO_CLASS_HANDLE* vcTypeRet /* OUT */
963 mcs->AddCall("getArgType");
964 return original_ICorJitInfo->getArgType(sig, args, vcTypeRet);
967 // If the Arg is a CORINFO_TYPE_CLASS fetch the class handle associated with it
968 CORINFO_CLASS_HANDLE interceptor_ICJI::getArgClass(CORINFO_SIG_INFO* sig, /* IN */
969 CORINFO_ARG_LIST_HANDLE args /* IN */
972 mcs->AddCall("getArgClass");
973 return original_ICorJitInfo->getArgClass(sig, args);
976 // Returns type of HFA for valuetype
977 CorInfoType interceptor_ICJI::getHFAType(CORINFO_CLASS_HANDLE hClass)
979 mcs->AddCall("getHFAType");
980 return original_ICorJitInfo->getHFAType(hClass);
983 /*****************************************************************************
984 * ICorErrorInfo contains methods to deal with SEH exceptions being thrown
985 * from the corinfo interface. These methods may be called when an exception
986 * with code EXCEPTION_COMPLUS is caught.
987 *****************************************************************************/
989 // Returns the HRESULT of the current exception
990 HRESULT interceptor_ICJI::GetErrorHRESULT(struct _EXCEPTION_POINTERS* pExceptionPointers)
992 mcs->AddCall("GetErrorHRESULT");
993 return original_ICorJitInfo->GetErrorHRESULT(pExceptionPointers);
996 // Fetches the message of the current exception
997 // Returns the size of the message (including terminating null). This can be
998 // greater than bufferLength if the buffer is insufficient.
999 ULONG interceptor_ICJI::GetErrorMessage(__inout_ecount(bufferLength) LPWSTR buffer, ULONG bufferLength)
1001 mcs->AddCall("GetErrorMessage");
1002 return original_ICorJitInfo->GetErrorMessage(buffer, bufferLength);
1005 // returns EXCEPTION_EXECUTE_HANDLER if it is OK for the compile to handle the
1006 // exception, abort some work (like the inlining) and continue compilation
1007 // returns EXCEPTION_CONTINUE_SEARCH if exception must always be handled by the EE
1008 // things like ThreadStoppedException ...
1009 // returns EXCEPTION_CONTINUE_EXECUTION if exception is fixed up by the EE
1011 int interceptor_ICJI::FilterException(struct _EXCEPTION_POINTERS* pExceptionPointers)
1013 mcs->AddCall("FilterException");
1014 return original_ICorJitInfo->FilterException(pExceptionPointers);
1017 // Cleans up internal EE tracking when an exception is caught.
1018 void interceptor_ICJI::HandleException(struct _EXCEPTION_POINTERS* pExceptionPointers)
1020 mcs->AddCall("HandleException");
1021 original_ICorJitInfo->HandleException(pExceptionPointers);
1024 void interceptor_ICJI::ThrowExceptionForJitResult(HRESULT result)
1026 mcs->AddCall("ThrowExceptionForJitResult");
1027 original_ICorJitInfo->ThrowExceptionForJitResult(result);
1030 // Throws an exception defined by the given throw helper.
1031 void interceptor_ICJI::ThrowExceptionForHelper(const CORINFO_HELPER_DESC* throwHelper)
1033 mcs->AddCall("ThrowExceptionForHelper");
1034 original_ICorJitInfo->ThrowExceptionForHelper(throwHelper);
1037 /*****************************************************************************
1038 * ICorStaticInfo contains EE interface methods which return values that are
1039 * constant from invocation to invocation. Thus they may be embedded in
1040 * persisted information like statically generated code. (This is of course
1041 * assuming that all code versions are identical each time.)
1042 *****************************************************************************/
1044 // Return details about EE internal data structures
1045 void interceptor_ICJI::getEEInfo(CORINFO_EE_INFO* pEEInfoOut)
1047 mcs->AddCall("getEEInfo");
1048 original_ICorJitInfo->getEEInfo(pEEInfoOut);
1051 // Returns name of the JIT timer log
1052 LPCWSTR interceptor_ICJI::getJitTimeLogFilename()
1054 mcs->AddCall("getJitTimeLogFilename");
1055 return original_ICorJitInfo->getJitTimeLogFilename();
1058 /*********************************************************************************/
1060 // Diagnostic methods
1062 /*********************************************************************************/
1064 // this function is for debugging only. Returns method token.
1065 // Returns mdMethodDefNil for dynamic methods.
1066 mdMethodDef interceptor_ICJI::getMethodDefFromMethod(CORINFO_METHOD_HANDLE hMethod)
1068 mcs->AddCall("getMethodDefFromMethod");
1069 return original_ICorJitInfo->getMethodDefFromMethod(hMethod);
1072 // this function is for debugging only. It returns the method name
1073 // and if 'moduleName' is non-null, it sets it to something that will
1074 // says which method (a class name, or a module name)
1075 const char* interceptor_ICJI::getMethodName(CORINFO_METHOD_HANDLE ftn, /* IN */
1076 const char** moduleName /* OUT */
1079 mcs->AddCall("getMethodName");
1080 return original_ICorJitInfo->getMethodName(ftn, moduleName);
1083 // this function is for debugging only. It returns a value that
1084 // is will always be the same for a given method. It is used
1085 // to implement the 'jitRange' functionality
1086 unsigned interceptor_ICJI::getMethodHash(CORINFO_METHOD_HANDLE ftn /* IN */
1089 mcs->AddCall("getMethodHash");
1090 return original_ICorJitInfo->getMethodHash(ftn);
1093 // this function is for debugging only.
1094 size_t interceptor_ICJI::findNameOfToken(CORINFO_MODULE_HANDLE module, /* IN */
1095 mdToken metaTOK, /* IN */
1096 __out_ecount(FQNameCapacity) char* szFQName, /* OUT */
1097 size_t FQNameCapacity /* IN */
1100 mcs->AddCall("findNameOfToken");
1101 return original_ICorJitInfo->findNameOfToken(module, metaTOK, szFQName, FQNameCapacity);
1104 bool interceptor_ICJI::getSystemVAmd64PassStructInRegisterDescriptor(
1105 /* IN */ CORINFO_CLASS_HANDLE structHnd,
1106 /* OUT */ SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr)
1108 mcs->AddCall("getSystemVAmd64PassStructInRegisterDescriptor");
1109 return original_ICorJitInfo->getSystemVAmd64PassStructInRegisterDescriptor(structHnd, structPassInRegDescPtr);
1112 // Stuff on ICorDynamicInfo
1113 DWORD interceptor_ICJI::getThreadTLSIndex(void** ppIndirection)
1115 mcs->AddCall("getThreadTLSIndex");
1116 return original_ICorJitInfo->getThreadTLSIndex(ppIndirection);
1119 const void* interceptor_ICJI::getInlinedCallFrameVptr(void** ppIndirection)
1121 mcs->AddCall("getInlinedCallFrameVptr");
1122 return original_ICorJitInfo->getInlinedCallFrameVptr(ppIndirection);
1125 LONG* interceptor_ICJI::getAddrOfCaptureThreadGlobal(void** ppIndirection)
1127 mcs->AddCall("getAddrOfCaptureThreadGlobal");
1128 return original_ICorJitInfo->getAddrOfCaptureThreadGlobal(ppIndirection);
1131 // return the native entry point to an EE helper (see CorInfoHelpFunc)
1132 void* interceptor_ICJI::getHelperFtn(CorInfoHelpFunc ftnNum, void** ppIndirection)
1134 mcs->AddCall("getHelperFtn");
1135 return original_ICorJitInfo->getHelperFtn(ftnNum, ppIndirection);
1138 // return a callable address of the function (native code). This function
1139 // may return a different value (depending on whether the method has
1140 // been JITed or not.
1141 void interceptor_ICJI::getFunctionEntryPoint(CORINFO_METHOD_HANDLE ftn, /* IN */
1142 CORINFO_CONST_LOOKUP* pResult, /* OUT */
1143 CORINFO_ACCESS_FLAGS accessFlags)
1145 mcs->AddCall("getFunctionEntryPoint");
1146 original_ICorJitInfo->getFunctionEntryPoint(ftn, pResult, accessFlags);
1149 // return a directly callable address. This can be used similarly to the
1150 // value returned by getFunctionEntryPoint() except that it is
1151 // guaranteed to be multi callable entrypoint.
1152 void interceptor_ICJI::getFunctionFixedEntryPoint(CORINFO_METHOD_HANDLE ftn, CORINFO_CONST_LOOKUP* pResult)
1154 mcs->AddCall("getFunctionFixedEntryPoint");
1155 original_ICorJitInfo->getFunctionFixedEntryPoint(ftn, pResult);
1158 // get the synchronization handle that is passed to monXstatic function
1159 void* interceptor_ICJI::getMethodSync(CORINFO_METHOD_HANDLE ftn, void** ppIndirection)
1161 mcs->AddCall("getMethodSync");
1162 return original_ICorJitInfo->getMethodSync(ftn, ppIndirection);
1165 // These entry points must be called if a handle is being embedded in
1166 // the code to be passed to a JIT helper function. (as opposed to just
1167 // being passed back into the ICorInfo interface.)
1169 // get slow lazy string literal helper to use (CORINFO_HELP_STRCNS*).
1170 // Returns CORINFO_HELP_UNDEF if lazy string literal helper cannot be used.
1171 CorInfoHelpFunc interceptor_ICJI::getLazyStringLiteralHelper(CORINFO_MODULE_HANDLE handle)
1173 mcs->AddCall("getLazyStringLiteralHelper");
1174 return original_ICorJitInfo->getLazyStringLiteralHelper(handle);
1177 CORINFO_MODULE_HANDLE interceptor_ICJI::embedModuleHandle(CORINFO_MODULE_HANDLE handle, void** ppIndirection)
1179 mcs->AddCall("embedModuleHandle");
1180 return original_ICorJitInfo->embedModuleHandle(handle, ppIndirection);
1183 CORINFO_CLASS_HANDLE interceptor_ICJI::embedClassHandle(CORINFO_CLASS_HANDLE handle, void** ppIndirection)
1185 mcs->AddCall("embedClassHandle");
1186 return original_ICorJitInfo->embedClassHandle(handle, ppIndirection);
1189 CORINFO_METHOD_HANDLE interceptor_ICJI::embedMethodHandle(CORINFO_METHOD_HANDLE handle, void** ppIndirection)
1191 mcs->AddCall("embedMethodHandle");
1192 return original_ICorJitInfo->embedMethodHandle(handle, ppIndirection);
1195 CORINFO_FIELD_HANDLE interceptor_ICJI::embedFieldHandle(CORINFO_FIELD_HANDLE handle, void** ppIndirection)
1197 mcs->AddCall("embedFieldHandle");
1198 return original_ICorJitInfo->embedFieldHandle(handle, ppIndirection);
1201 // Given a module scope (module), a method handle (context) and
1202 // a metadata token (metaTOK), fetch the handle
1203 // (type, field or method) associated with the token.
1204 // If this is not possible at compile-time (because the current method's
1205 // code is shared and the token contains generic parameters)
1206 // then indicate how the handle should be looked up at run-time.
1208 void interceptor_ICJI::embedGenericHandle(CORINFO_RESOLVED_TOKEN* pResolvedToken,
1209 BOOL fEmbedParent, // TRUE - embeds parent type handle of the field/method
1211 CORINFO_GENERICHANDLE_RESULT* pResult)
1213 mcs->AddCall("embedGenericHandle");
1214 original_ICorJitInfo->embedGenericHandle(pResolvedToken, fEmbedParent, pResult);
1217 // Return information used to locate the exact enclosing type of the current method.
1218 // Used only to invoke .cctor method from code shared across generic instantiations
1219 // !needsRuntimeLookup statically known (enclosing type of method itself)
1220 // needsRuntimeLookup:
1221 // CORINFO_LOOKUP_THISOBJ use vtable pointer of 'this' param
1222 // CORINFO_LOOKUP_CLASSPARAM use vtable hidden param
1223 // CORINFO_LOOKUP_METHODPARAM use enclosing type of method-desc hidden param
1224 CORINFO_LOOKUP_KIND interceptor_ICJI::getLocationOfThisType(CORINFO_METHOD_HANDLE context)
1226 mcs->AddCall("getLocationOfThisType");
1227 return original_ICorJitInfo->getLocationOfThisType(context);
1230 // return the unmanaged target *if method has already been prelinked.*
1231 void* interceptor_ICJI::getPInvokeUnmanagedTarget(CORINFO_METHOD_HANDLE method, void** ppIndirection)
1233 mcs->AddCall("getPInvokeUnmanagedTarget");
1234 return original_ICorJitInfo->getPInvokeUnmanagedTarget(method, ppIndirection);
1237 // return address of fixup area for late-bound PInvoke calls.
1238 void* interceptor_ICJI::getAddressOfPInvokeFixup(CORINFO_METHOD_HANDLE method, void** ppIndirection)
1240 mcs->AddCall("getAddressOfPInvokeFixup");
1241 return original_ICorJitInfo->getAddressOfPInvokeFixup(method, ppIndirection);
1244 // return address of fixup area for late-bound PInvoke calls.
1245 void interceptor_ICJI::getAddressOfPInvokeTarget(CORINFO_METHOD_HANDLE method, CORINFO_CONST_LOOKUP* pLookup)
1247 mcs->AddCall("getAddressOfPInvokeTarget");
1248 original_ICorJitInfo->getAddressOfPInvokeTarget(method, pLookup);
1251 // Generate a cookie based on the signature that would needs to be passed
1252 // to CORINFO_HELP_PINVOKE_CALLI
1253 LPVOID interceptor_ICJI::GetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig, void** ppIndirection)
1255 mcs->AddCall("GetCookieForPInvokeCalliSig");
1256 return original_ICorJitInfo->GetCookieForPInvokeCalliSig(szMetaSig, ppIndirection);
1259 // returns true if a VM cookie can be generated for it (might be false due to cross-module
1260 // inlining, in which case the inlining should be aborted)
1261 bool interceptor_ICJI::canGetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig)
1263 mcs->AddCall("canGetCookieForPInvokeCalliSig");
1264 return original_ICorJitInfo->canGetCookieForPInvokeCalliSig(szMetaSig);
1267 // Gets a handle that is checked to see if the current method is
1268 // included in "JustMyCode"
1269 CORINFO_JUST_MY_CODE_HANDLE interceptor_ICJI::getJustMyCodeHandle(CORINFO_METHOD_HANDLE method,
1270 CORINFO_JUST_MY_CODE_HANDLE** ppIndirection)
1272 mcs->AddCall("getJustMyCodeHandle");
1273 return original_ICorJitInfo->getJustMyCodeHandle(method, ppIndirection);
1276 // Gets a method handle that can be used to correlate profiling data.
1277 // This is the IP of a native method, or the address of the descriptor struct
1278 // for IL. Always guaranteed to be unique per process, and not to move. */
1279 void interceptor_ICJI::GetProfilingHandle(BOOL* pbHookFunction, void** pProfilerHandle, BOOL* pbIndirectedHandles)
1281 mcs->AddCall("GetProfilingHandle");
1282 original_ICorJitInfo->GetProfilingHandle(pbHookFunction, pProfilerHandle, pbIndirectedHandles);
1285 // Returns instructions on how to make the call. See code:CORINFO_CALL_INFO for possible return values.
1286 void interceptor_ICJI::getCallInfo(
1288 CORINFO_RESOLVED_TOKEN* pResolvedToken,
1291 CORINFO_RESOLVED_TOKEN* pConstrainedResolvedToken,
1294 CORINFO_METHOD_HANDLE callerHandle,
1297 CORINFO_CALLINFO_FLAGS flags,
1300 CORINFO_CALL_INFO* pResult)
1302 mcs->AddCall("getCallInfo");
1303 original_ICorJitInfo->getCallInfo(pResolvedToken, pConstrainedResolvedToken, callerHandle, flags, pResult);
1306 BOOL interceptor_ICJI::canAccessFamily(CORINFO_METHOD_HANDLE hCaller, CORINFO_CLASS_HANDLE hInstanceType)
1309 mcs->AddCall("canAccessFamily");
1310 return original_ICorJitInfo->canAccessFamily(hCaller, hInstanceType);
1312 // Returns TRUE if the Class Domain ID is the RID of the class (currently true for every class
1313 // except reflection emitted classes and generics)
1314 BOOL interceptor_ICJI::isRIDClassDomainID(CORINFO_CLASS_HANDLE cls)
1316 mcs->AddCall("isRIDClassDomainID");
1317 return original_ICorJitInfo->isRIDClassDomainID(cls);
1320 // returns the class's domain ID for accessing shared statics
1321 unsigned interceptor_ICJI::getClassDomainID(CORINFO_CLASS_HANDLE cls, void** ppIndirection)
1323 mcs->AddCall("getClassDomainID");
1324 return original_ICorJitInfo->getClassDomainID(cls, ppIndirection);
1327 // return the data's address (for static fields only)
1328 void* interceptor_ICJI::getFieldAddress(CORINFO_FIELD_HANDLE field, void** ppIndirection)
1330 mcs->AddCall("getFieldAddress");
1331 return original_ICorJitInfo->getFieldAddress(field, ppIndirection);
1334 // registers a vararg sig & returns a VM cookie for it (which can contain other stuff)
1335 CORINFO_VARARGS_HANDLE interceptor_ICJI::getVarArgsHandle(CORINFO_SIG_INFO* pSig, void** ppIndirection)
1337 mcs->AddCall("getVarArgsHandle");
1338 return original_ICorJitInfo->getVarArgsHandle(pSig, ppIndirection);
1341 // returns true if a VM cookie can be generated for it (might be false due to cross-module
1342 // inlining, in which case the inlining should be aborted)
1343 bool interceptor_ICJI::canGetVarArgsHandle(CORINFO_SIG_INFO* pSig)
1345 mcs->AddCall("canGetVarArgsHandle");
1346 return original_ICorJitInfo->canGetVarArgsHandle(pSig);
1349 // Allocate a string literal on the heap and return a handle to it
1350 InfoAccessType interceptor_ICJI::constructStringLiteral(CORINFO_MODULE_HANDLE module, mdToken metaTok, void** ppValue)
1352 mcs->AddCall("constructStringLiteral");
1353 return original_ICorJitInfo->constructStringLiteral(module, metaTok, ppValue);
1356 InfoAccessType interceptor_ICJI::emptyStringLiteral(void** ppValue)
1358 mcs->AddCall("emptyStringLiteral");
1359 return original_ICorJitInfo->emptyStringLiteral(ppValue);
1362 // (static fields only) given that 'field' refers to thread local store,
1363 // return the ID (TLS index), which is used to find the begining of the
1364 // TLS data area for the particular DLL 'field' is associated with.
1365 DWORD interceptor_ICJI::getFieldThreadLocalStoreID(CORINFO_FIELD_HANDLE field, void** ppIndirection)
1367 mcs->AddCall("getFieldThreadLocalStoreID");
1368 return original_ICorJitInfo->getFieldThreadLocalStoreID(field, ppIndirection);
1371 // Sets another object to intercept calls to "self" and current method being compiled
1372 void interceptor_ICJI::setOverride(ICorDynamicInfo* pOverride, CORINFO_METHOD_HANDLE currentMethod)
1374 mcs->AddCall("setOverride");
1375 original_ICorJitInfo->setOverride(pOverride, currentMethod);
1378 // Adds an active dependency from the context method's module to the given module
1379 // This is internal callback for the EE. JIT should not call it directly.
1380 void interceptor_ICJI::addActiveDependency(CORINFO_MODULE_HANDLE moduleFrom, CORINFO_MODULE_HANDLE moduleTo)
1382 mcs->AddCall("addActiveDependency");
1383 original_ICorJitInfo->addActiveDependency(moduleFrom, moduleTo);
1386 CORINFO_METHOD_HANDLE interceptor_ICJI::GetDelegateCtor(CORINFO_METHOD_HANDLE methHnd,
1387 CORINFO_CLASS_HANDLE clsHnd,
1388 CORINFO_METHOD_HANDLE targetMethodHnd,
1389 DelegateCtorArgs* pCtorData)
1391 mcs->AddCall("GetDelegateCtor");
1392 return original_ICorJitInfo->GetDelegateCtor(methHnd, clsHnd, targetMethodHnd, pCtorData);
1395 void interceptor_ICJI::MethodCompileComplete(CORINFO_METHOD_HANDLE methHnd)
1397 mcs->AddCall("MethodCompileComplete");
1398 original_ICorJitInfo->MethodCompileComplete(methHnd);
1401 // return a thunk that will copy the arguments for the given signature.
1402 void* interceptor_ICJI::getTailCallCopyArgsThunk(CORINFO_SIG_INFO* pSig, CorInfoHelperTailCallSpecialHandling flags)
1404 mcs->AddCall("getTailCallCopyArgsThunk");
1405 return original_ICorJitInfo->getTailCallCopyArgsThunk(pSig, flags);
1408 // Stuff directly on ICorJitInfo
1410 // Returns extended flags for a particular compilation instance.
1411 DWORD interceptor_ICJI::getJitFlags(CORJIT_FLAGS* jitFlags, DWORD sizeInBytes)
1413 mcs->AddCall("getJitFlags");
1414 return original_ICorJitInfo->getJitFlags(jitFlags, sizeInBytes);
1417 // Runs the given function with the given parameter under an error trap
1418 // and returns true if the function completes successfully. We don't
1419 // record the results of the call: when this call gets played back,
1420 // its result will depend on whether or not `function` calls something
1421 // that throws at playback time rather than at capture time.
1422 bool interceptor_ICJI::runWithErrorTrap(void (*function)(void*), void* param)
1424 mcs->AddCall("runWithErrorTrap");
1425 return original_ICorJitInfo->runWithErrorTrap(function, param);
1428 // return memory manager that the JIT can use to allocate a regular memory
1429 IEEMemoryManager* interceptor_ICJI::getMemoryManager()
1431 mcs->AddCall("getMemoryManager");
1432 if (current_IEEMM->original_IEEMM == nullptr)
1433 current_IEEMM->original_IEEMM = original_ICorJitInfo->getMemoryManager();
1435 return current_IEEMM;
1438 // get a block of memory for the code, readonly data, and read-write data
1439 void interceptor_ICJI::allocMem(ULONG hotCodeSize, /* IN */
1440 ULONG coldCodeSize, /* IN */
1441 ULONG roDataSize, /* IN */
1442 ULONG xcptnsCount, /* IN */
1443 CorJitAllocMemFlag flag, /* IN */
1444 void** hotCodeBlock, /* OUT */
1445 void** coldCodeBlock, /* OUT */
1446 void** roDataBlock /* OUT */
1449 mcs->AddCall("allocMem");
1450 return original_ICorJitInfo->allocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock,
1451 coldCodeBlock, roDataBlock);
1454 // Reserve memory for the method/funclet's unwind information.
1455 // Note that this must be called before allocMem. It should be
1456 // called once for the main method, once for every funclet, and
1457 // once for every block of cold code for which allocUnwindInfo
1460 // This is necessary because jitted code must allocate all the
1461 // memory needed for the unwindInfo at the allocMem call.
1462 // For prejitted code we split up the unwinding information into
1463 // separate sections .rdata and .pdata.
1465 void interceptor_ICJI::reserveUnwindInfo(BOOL isFunclet, /* IN */
1466 BOOL isColdCode, /* IN */
1467 ULONG unwindSize /* IN */
1470 mcs->AddCall("reserveUnwindInfo");
1471 original_ICorJitInfo->reserveUnwindInfo(isFunclet, isColdCode, unwindSize);
1474 // Allocate and initialize the .rdata and .pdata for this method or
1475 // funclet, and get the block of memory needed for the machine-specific
1476 // unwind information (the info for crawling the stack frame).
1477 // Note that allocMem must be called first.
1481 // pHotCode main method code buffer, always filled in
1482 // pColdCode cold code buffer, only filled in if this is cold code,
1484 // startOffset start of code block, relative to appropriate code buffer
1485 // (e.g. pColdCode if cold, pHotCode if hot).
1486 // endOffset end of code block, relative to appropriate code buffer
1487 // unwindSize size of unwind info pointed to by pUnwindBlock
1488 // pUnwindBlock pointer to unwind info
1489 // funcKind type of funclet (main method code, handler, filter)
1491 void interceptor_ICJI::allocUnwindInfo(BYTE* pHotCode, /* IN */
1492 BYTE* pColdCode, /* IN */
1493 ULONG startOffset, /* IN */
1494 ULONG endOffset, /* IN */
1495 ULONG unwindSize, /* IN */
1496 BYTE* pUnwindBlock, /* IN */
1497 CorJitFuncKind funcKind /* IN */
1500 mcs->AddCall("allocUnwindInfo");
1501 original_ICorJitInfo->allocUnwindInfo(pHotCode, pColdCode, startOffset, endOffset, unwindSize, pUnwindBlock,
1505 // Get a block of memory needed for the code manager information,
1506 // (the info for enumerating the GC pointers while crawling the
1508 // Note that allocMem must be called first
1509 void* interceptor_ICJI::allocGCInfo(size_t size /* IN */
1512 mcs->AddCall("allocGCInfo");
1513 return original_ICorJitInfo->allocGCInfo(size);
1517 void interceptor_ICJI::yieldExecution()
1519 mcs->AddCall("yieldExecution");
1520 original_ICorJitInfo->yieldExecution();
1523 // Indicate how many exception handler blocks are to be returned.
1524 // This is guaranteed to be called before any 'setEHinfo' call.
1525 // Note that allocMem must be called before this method can be called.
1526 void interceptor_ICJI::setEHcount(unsigned cEH /* IN */
1529 mcs->AddCall("setEHcount");
1530 original_ICorJitInfo->setEHcount(cEH);
1533 // Set the values for one particular exception handler block.
1535 // Handler regions should be lexically contiguous.
1536 // This is because FinallyIsUnwinding() uses lexicality to
1537 // determine if a "finally" clause is executing.
1538 void interceptor_ICJI::setEHinfo(unsigned EHnumber, /* IN */
1539 const CORINFO_EH_CLAUSE* clause /* IN */
1542 mcs->AddCall("setEHinfo");
1543 original_ICorJitInfo->setEHinfo(EHnumber, clause);
1546 // Level 1 -> fatalError, Level 2 -> Error, Level 3 -> Warning
1547 // Level 4 means happens 10 times in a run, level 5 means 100, level 6 means 1000 ...
1548 // returns non-zero if the logging succeeded
1549 BOOL interceptor_ICJI::logMsg(unsigned level, const char* fmt, va_list args)
1551 mcs->AddCall("logMsg");
1552 return original_ICorJitInfo->logMsg(level, fmt, args);
1555 // do an assert. will return true if the code should retry (DebugBreak)
1556 // returns false, if the assert should be igored.
1557 int interceptor_ICJI::doAssert(const char* szFile, int iLine, const char* szExpr)
1559 mcs->AddCall("doAssert");
1560 return original_ICorJitInfo->doAssert(szFile, iLine, szExpr);
1563 void interceptor_ICJI::reportFatalError(CorJitResult result)
1565 mcs->AddCall("reportFatalError");
1566 original_ICorJitInfo->reportFatalError(result);
1570 struct ProfileBuffer // Also defined here: code:CORBBTPROF_BLOCK_DATA
1573 ULONG ExecutionCount;
1577 // allocate a basic block profile buffer where execution counts will be stored
1578 // for jitted basic blocks.
1579 HRESULT interceptor_ICJI::allocBBProfileBuffer(ULONG count, // The number of basic blocks that we have
1580 ProfileBuffer** profileBuffer)
1582 mcs->AddCall("allocBBProfileBuffer");
1583 return original_ICorJitInfo->allocBBProfileBuffer(count, profileBuffer);
1586 // get profile information to be used for optimizing the current method. The format
1587 // of the buffer is the same as the format the JIT passes to allocBBProfileBuffer.
1588 HRESULT interceptor_ICJI::getBBProfileData(CORINFO_METHOD_HANDLE ftnHnd,
1589 ULONG* count, // The number of basic blocks that we have
1590 ProfileBuffer** profileBuffer,
1593 mcs->AddCall("getBBProfileData");
1594 return original_ICorJitInfo->getBBProfileData(ftnHnd, count, profileBuffer, numRuns);
1597 // Associates a native call site, identified by its offset in the native code stream, with
1598 // the signature information and method handle the JIT used to lay out the call site. If
1599 // the call site has no signature information (e.g. a helper call) or has no method handle
1600 // (e.g. a CALLI P/Invoke), then null should be passed instead.
1601 void interceptor_ICJI::recordCallSite(ULONG instrOffset, /* IN */
1602 CORINFO_SIG_INFO* callSig, /* IN */
1603 CORINFO_METHOD_HANDLE methodHandle /* IN */
1606 mcs->AddCall("recordCallSite");
1607 return original_ICorJitInfo->recordCallSite(instrOffset, callSig, methodHandle);
1610 // A relocation is recorded if we are pre-jitting.
1611 // A jump thunk may be inserted if we are jitting
1612 void interceptor_ICJI::recordRelocation(void* location, /* IN */
1613 void* target, /* IN */
1614 WORD fRelocType, /* IN */
1615 WORD slotNum, /* IN */
1616 INT32 addlDelta /* IN */
1619 mcs->AddCall("recordRelocation");
1620 original_ICorJitInfo->recordRelocation(location, target, fRelocType, slotNum, addlDelta);
1623 WORD interceptor_ICJI::getRelocTypeHint(void* target)
1625 mcs->AddCall("getRelocTypeHint");
1626 return original_ICorJitInfo->getRelocTypeHint(target);
1629 // A callback to identify the range of address known to point to
1630 // compiler-generated native entry points that call back into
1632 void interceptor_ICJI::getModuleNativeEntryPointRange(void** pStart, /* OUT */
1633 void** pEnd /* OUT */
1636 mcs->AddCall("getModuleNativeEntryPointRange");
1637 original_ICorJitInfo->getModuleNativeEntryPointRange(pStart, pEnd);
1640 // For what machine does the VM expect the JIT to generate code? The VM
1641 // returns one of the IMAGE_FILE_MACHINE_* values. Note that if the VM
1642 // is cross-compiling (such as the case for crossgen), it will return a
1643 // different value than if it was compiling for the host architecture.
1645 DWORD interceptor_ICJI::getExpectedTargetArchitecture()
1647 mcs->AddCall("getExpectedTargetArchitecture");
1648 return original_ICorJitInfo->getExpectedTargetArchitecture();