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