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