* Add option to measure time spent inside calls to the CLR (off by default).
#ifndef __GCENV_EE_H__
#define __GCENV_EE_H__
-#include "gcinterface.h"
+struct ScanContext;
+class CrawlFrame;
+struct gc_alloc_context;
+
+typedef void promote_func(PTR_PTR_Object, ScanContext*, uint32_t);
+
+typedef void enum_alloc_context_func(gc_alloc_context*, void*);
+
+typedef struct
+{
+ promote_func* f;
+ ScanContext* sc;
+ CrawlFrame * cf;
+} GCCONTEXT;
+
+// GC background thread function prototype
+typedef uint32_t (__stdcall *GCBackgroundThreadFunction)(void* param);
class GCToEEInterface
{
public:
+ //
+ // Suspend/Resume callbacks
+ //
+ typedef enum
+ {
+ SUSPEND_FOR_GC = 1,
+ SUSPEND_FOR_GC_PREP = 6
+ } SUSPEND_REASON;
+
static void SuspendEE(SUSPEND_REASON reason);
static void RestartEE(bool bFinishedGC); //resume threads.
gc_heap::ee_suspend_event.Wait(INFINITE, FALSE);
BEGIN_TIMING(suspend_ee_during_log);
- GCToEEInterface::SuspendEE(SUSPEND_FOR_GC);
+ GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_FOR_GC);
END_TIMING(suspend_ee_during_log);
proceed_with_gc_p = TRUE;
dprintf (2, ("suspend_EE"));
#ifdef MULTIPLE_HEAPS
gc_heap* hp = gc_heap::g_heaps[0];
- GCToEEInterface::SuspendEE(SUSPEND_FOR_GC_PREP);
+ GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_FOR_GC_PREP);
#else
- GCToEEInterface::SuspendEE(SUSPEND_FOR_GC_PREP);
+ GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_FOR_GC_PREP);
#endif //MULTIPLE_HEAPS
}
}
gc_started = TRUE;
dprintf (2, ("bgc_suspend_EE"));
- GCToEEInterface::SuspendEE(SUSPEND_FOR_GC_PREP);
+ GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_FOR_GC_PREP);
gc_started = FALSE;
for (int i = 0; i < n_heaps; i++)
reset_gc_done();
gc_started = TRUE;
dprintf (2, ("bgc_suspend_EE"));
- GCToEEInterface::SuspendEE(SUSPEND_FOR_GC_PREP);
+ GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_FOR_GC_PREP);
gc_started = FALSE;
set_gc_done();
}
dprintf (2, ("Suspending EE"));
BEGIN_TIMING(suspend_ee_during_log);
- GCToEEInterface::SuspendEE(SUSPEND_FOR_GC);
+ GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_FOR_GC);
END_TIMING(suspend_ee_during_log);
gc_heap::proceed_with_gc_p = gc_heap::should_proceed_with_gc();
gc_heap::disable_preemptive (current_thread, cooperative_mode);
#define __GC_H
#include "gcinterface.h"
-#include "env/gcenv.ee.h"
-#ifdef FEATURE_STANDALONE_GC
-#include "gcenv.ee.standalone.inl"
-#endif // FEATURE_STANDALONE_GC
/*
* Promotion Function Prototypes
IGCHeapInternal* g_theGCHeap;
-#ifdef FEATURE_STANDALONE_GC
-IGCToCLR* g_theGCToCLR;
-#endif // FEATURE_STANDALONE_GC
-
/* global versions of the card table and brick table */
GPTR_IMPL(uint32_t,g_card_table);
IGCHeap* InitializeGarbageCollector(IGCToCLR* clrToGC)
{
LIMITED_METHOD_CONTRACT;
+ UNREFERENCED_PARAMETER(clrToGC);
IGCHeapInternal* heap;
#ifdef FEATURE_SVR_GC
#endif
g_theGCHeap = heap;
-
-#ifdef FEATURE_STANDALONE_GC
- assert(clrToGC != nullptr);
- g_theGCToCLR = clrToGC;
-#else
- assert(clrToGC == nullptr);
-#endif
-
return heap;
}
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-#ifndef __GCTOENV_EE_STANDALONE_INL__
-#define __GCTOENV_EE_STANDALONE_INL__
-
-#include "env/gcenv.ee.h"
-
-// The singular interface instance. All calls in GCToEEInterface
-// will be fowarded to this interface instance.
-extern IGCToCLR* g_theGCToCLR;
-
-// When we are building the GC in a standalone environment, we
-// will be dispatching virtually against g_theGCToCLR to call
-// into the EE. This class provides an identical API to the existing
-// GCToEEInterface, but only forwards the call onto the global
-// g_theGCToCLR instance.
-inline void GCToEEInterface::SuspendEE(SUSPEND_REASON reason)
-{
- assert(g_theGCToCLR != nullptr);
- g_theGCToCLR->SuspendEE(reason);
-}
-
-inline void GCToEEInterface::RestartEE(bool bFinishedGC)
-{
- assert(g_theGCToCLR != nullptr);
- g_theGCToCLR->RestartEE(bFinishedGC);
-}
-
-inline void GCToEEInterface::GcScanRoots(promote_func* fn, int condemned, int max_gen, ScanContext* sc)
-{
- assert(g_theGCToCLR != nullptr);
- g_theGCToCLR->GcScanRoots(fn, condemned, max_gen, sc);
-}
-
-inline void GCToEEInterface::GcStartWork(int condemned, int max_gen)
-{
- assert(g_theGCToCLR != nullptr);
- g_theGCToCLR->GcStartWork(condemned, max_gen);
-}
-
-inline void GCToEEInterface::AfterGcScanRoots(int condemned, int max_gen, ScanContext* sc)
-{
- assert(g_theGCToCLR != nullptr);
- g_theGCToCLR->AfterGcScanRoots(condemned, max_gen, sc);
-}
-
-inline void GCToEEInterface::GcBeforeBGCSweepWork()
-{
- assert(g_theGCToCLR != nullptr);
- g_theGCToCLR->GcBeforeBGCSweepWork();
-}
-
-inline void GCToEEInterface::GcDone(int condemned)
-{
- assert(g_theGCToCLR != nullptr);
- g_theGCToCLR->GcDone(condemned);
-}
-
-inline bool GCToEEInterface::RefCountedHandleCallbacks(Object * pObject)
-{
- assert(g_theGCToCLR != nullptr);
- return g_theGCToCLR->RefCountedHandleCallbacks(pObject);
-}
-
-inline void GCToEEInterface::SyncBlockCacheWeakPtrScan(HANDLESCANPROC scanProc, uintptr_t lp1, uintptr_t lp2)
-{
- assert(g_theGCToCLR != nullptr);
- g_theGCToCLR->SyncBlockCacheWeakPtrScan(scanProc, lp1, lp2);
-}
-
-inline void GCToEEInterface::SyncBlockCacheDemote(int max_gen)
-{
- assert(g_theGCToCLR != nullptr);
- g_theGCToCLR->SyncBlockCacheDemote(max_gen);
-}
-
-inline void GCToEEInterface::SyncBlockCachePromotionsGranted(int max_gen)
-{
- assert(g_theGCToCLR != nullptr);
- g_theGCToCLR->SyncBlockCachePromotionsGranted(max_gen);
-}
-
-inline bool GCToEEInterface::IsPreemptiveGCDisabled(Thread * pThread)
-{
- assert(g_theGCToCLR != nullptr);
- return g_theGCToCLR->IsPreemptiveGCDisabled(pThread);
-}
-
-
-inline void GCToEEInterface::EnablePreemptiveGC(Thread * pThread)
-{
- assert(g_theGCToCLR != nullptr);
- g_theGCToCLR->EnablePreemptiveGC(pThread);
-}
-
-inline void GCToEEInterface::DisablePreemptiveGC(Thread * pThread)
-{
- assert(g_theGCToCLR != nullptr);
- g_theGCToCLR->DisablePreemptiveGC(pThread);
-}
-
-inline gc_alloc_context * GCToEEInterface::GetAllocContext(Thread * pThread)
-{
- assert(g_theGCToCLR != nullptr);
- return g_theGCToCLR->GetAllocContext(pThread);
-}
-
-inline bool GCToEEInterface::CatchAtSafePoint(Thread * pThread)
-{
- assert(g_theGCToCLR != nullptr);
- return g_theGCToCLR->CatchAtSafePoint(pThread);
-}
-
-inline void GCToEEInterface::GcEnumAllocContexts(enum_alloc_context_func* fn, void* param)
-{
- assert(g_theGCToCLR != nullptr);
- g_theGCToCLR->GcEnumAllocContexts(fn, param);
-}
-
-inline Thread* GCToEEInterface::CreateBackgroundThread(GCBackgroundThreadFunction threadStart, void* arg)
-{
- assert(g_theGCToCLR != nullptr);
- return g_theGCToCLR->CreateBackgroundThread(threadStart, arg);
-}
-
-#endif // __GCTOENV_EE_STANDALONE_INL__
+++ /dev/null
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-// See the LICENSE file in the project root for more information.
-
-#ifndef _GCINTERFACE_EE_H_
-#define _GCINTERFACE_EE_H_
-
-// This interface provides the interface that the GC will use to speak to the rest
-// of the execution engine. Everything that the GC does that requires the EE
-// to be informed or that requires EE action must go through this interface.
-//
-// When FEATURE_STANDALONE_GC is defined, this class is named IGCToCLR and is
-// an abstract class. The EE will provide a class that fulfills this interface,
-// and the GC will dispatch virtually on it to call into the EE. When FEATURE_STANDALONE_GC
-// is not defined, this class is named GCToEEInterface and the GC will dispatch statically on it.
-class IGCToCLR {
-public:
- // Suspends the EE for the given reason.
- virtual
- void SuspendEE(SUSPEND_REASON reason) = 0;
-
- // Resumes all paused threads, with a boolean indicating
- // if the EE is being restarted because a GC is complete.
- virtual
- void RestartEE(bool bFinishedGC) = 0;
-
- // Performs a stack walk of all managed threads and invokes the given promote_func
- // on all GC roots encountered on the stack. Depending on the condemned generation,
- // this function may also enumerate all static GC refs if necessary.
- virtual
- void GcScanRoots(promote_func* fn, int condemned, int max_gen, ScanContext* sc) = 0;
-
- // Callback from the GC informing the EE that it is preparing to start working.
- virtual
- void GcStartWork(int condemned, int max_gen) = 0;
-
- // Callback from the GC informing the EE that it has completed the managed stack
- // scan. User threads are still suspended at this point.
- virtual
- void AfterGcScanRoots(int condemned, int max_gen, ScanContext* sc) = 0;
-
- // Callback from the GC informing the EE that the background sweep phase of a BGC is
- // about to begin.
- virtual
- void GcBeforeBGCSweepWork() = 0;
-
- // Callback from the GC informing the EE that a GC has completed.
- virtual
- void GcDone(int condemned) = 0;
-
- // Predicate for the GC to query whether or not a given refcounted handle should
- // be promoted.
- virtual
- bool RefCountedHandleCallbacks(Object * pObject) = 0;
-
- // Performs a weak pointer scan of the sync block cache.
- virtual
- void SyncBlockCacheWeakPtrScan(HANDLESCANPROC scanProc, uintptr_t lp1, uintptr_t lp2) = 0;
-
- // Indicates to the EE that the GC intends to demote objects in the sync block cache.
- virtual
- void SyncBlockCacheDemote(int max_gen) = 0;
-
- // Indicates to the EE that the GC has granted promotion to objects in the sync block cache.
- virtual
- void SyncBlockCachePromotionsGranted(int max_gen) = 0;
-
- // Queries whether or not the given thread has preemptive GC disabled.
- virtual
- bool IsPreemptiveGCDisabled(Thread * pThread) = 0;
-
- // Enables preemptive GC on the given thread.
- virtual
- void EnablePreemptiveGC(Thread * pThread) = 0;
-
- // Disables preemptive GC on the given thread.
- virtual
- void DisablePreemptiveGC(Thread * pThread) = 0;
-
- // Retrieves the alloc context associated with a given thread.
- virtual
- gc_alloc_context * GetAllocContext(Thread * pThread) = 0;
-
- // Returns true if this thread is waiting to reach a safe point.
- virtual
- bool CatchAtSafePoint(Thread * pThread) = 0;
-
- // Calls the given enum_alloc_context_func with every active alloc context.
- virtual
- void GcEnumAllocContexts(enum_alloc_context_func* fn, void* param) = 0;
-
- // Creates and returns a new background thread.
- virtual
- Thread* CreateBackgroundThread(GCBackgroundThreadFunction threadStart, void* arg) = 0;
-};
-
-#endif // _GCINTERFACE_EE_H_
#ifndef _GC_INTERFACE_H_
#define _GC_INTERFACE_H_
-struct ScanContext;
-struct gc_alloc_context;
-class CrawlFrame;
-
-// Callback passed to GcScanRoots.
-typedef void promote_func(PTR_PTR_Object, ScanContext*, uint32_t);
-
-// Callback passed to GcEnumAllocContexts.
-typedef void enum_alloc_context_func(gc_alloc_context*, void*);
-
-// Callback passed to CreateBackgroundThread.
-typedef uint32_t (__stdcall *GCBackgroundThreadFunction)(void* param);
-
-// Struct often used as a parameter to callbacks.
-typedef struct
-{
- promote_func* f;
- ScanContext* sc;
- CrawlFrame * cf;
-} GCCONTEXT;
-
-// SUSPEND_REASON is the reason why the GC wishes to suspend the EE,
-// used as an argument to IGCToCLR::SuspendEE.
-typedef enum
-{
- SUSPEND_FOR_GC = 1,
- SUSPEND_FOR_GC_PREP = 6
-} SUSPEND_REASON;
-
-#include "gcinterface.ee.h"
-
// The allocation context must be known to the VM for use in the allocation
// fast path and known to the GC for performing the allocation. Every Thread
// has its own allocation context that it hands to the GC when allocating.
class Object;
class IGCHeap;
+class IGCToCLR;
// Initializes the garbage collector. Should only be called
// once, during EE startup.
g_pThreadList = pThread;
}
-void GCToEEInterface::SuspendEE(SUSPEND_REASON reason)
+void GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_REASON reason)
{
g_theGCHeap->SetGCInProgress(TRUE);
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-// The sample is to be kept simple, so building the sample
-// in tandem with a standalone GC is currently not supported.
-#ifdef FEATURE_STANDALONE_GC
-#undef FEATURE_STANDALONE_GC
-#endif // FEATURE_STANDALONE_GC
-
#if defined(_DEBUG)
#ifndef _DEBUG_IMPL
#define _DEBUG_IMPL 1
#include "gcenv.structs.h"
#include "gcenv.base.h"
+#include "gcenv.ee.h"
#include "gcenv.os.h"
#include "gcenv.interlocked.h"
#include "gcenv.interlocked.inl"
#include "gcenv.object.h"
#include "gcenv.sync.h"
-#include "gcenv.ee.h"
#define MAX_LONGPATH 1024
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+DEF_CLR_API(getMethodAttribs)
+DEF_CLR_API(setMethodAttribs)
+DEF_CLR_API(getMethodSig)
+DEF_CLR_API(getMethodInfo)
+DEF_CLR_API(canInline)
+DEF_CLR_API(reportInliningDecision)
+DEF_CLR_API(canTailCall)
+DEF_CLR_API(reportTailCallDecision)
+DEF_CLR_API(getEHinfo)
+DEF_CLR_API(getMethodClass)
+DEF_CLR_API(getMethodModule)
+DEF_CLR_API(getMethodVTableOffset)
+DEF_CLR_API(getIntrinsicID)
+DEF_CLR_API(isInSIMDModule)
+DEF_CLR_API(getUnmanagedCallConv)
+DEF_CLR_API(pInvokeMarshalingRequired)
+DEF_CLR_API(satisfiesMethodConstraints)
+DEF_CLR_API(isCompatibleDelegate)
+DEF_CLR_API(isDelegateCreationAllowed)
+DEF_CLR_API(isInstantiationOfVerifiedGeneric)
+DEF_CLR_API(initConstraintsForVerification)
+DEF_CLR_API(canSkipMethodVerification)
+DEF_CLR_API(methodMustBeLoadedBeforeCodeIsRun)
+DEF_CLR_API(mapMethodDeclToMethodImpl)
+DEF_CLR_API(getGSCookie)
+DEF_CLR_API(resolveToken)
+DEF_CLR_API(tryResolveToken)
+DEF_CLR_API(findSig)
+DEF_CLR_API(findCallSiteSig)
+DEF_CLR_API(getTokenTypeAsHandle)
+DEF_CLR_API(canSkipVerification)
+DEF_CLR_API(isValidToken)
+DEF_CLR_API(isValidStringRef)
+DEF_CLR_API(shouldEnforceCallvirtRestriction)
+DEF_CLR_API(asCorInfoType)
+DEF_CLR_API(getClassName)
+DEF_CLR_API(appendClassName)
+DEF_CLR_API(isValueClass)
+DEF_CLR_API(canInlineTypeCheckWithObjectVTable)
+DEF_CLR_API(getClassAttribs)
+DEF_CLR_API(isStructRequiringStackAllocRetBuf)
+DEF_CLR_API(getClassModule)
+DEF_CLR_API(getModuleAssembly)
+DEF_CLR_API(getAssemblyName)
+DEF_CLR_API(LongLifetimeMalloc)
+DEF_CLR_API(LongLifetimeFree)
+DEF_CLR_API(getClassModuleIdForStatics)
+DEF_CLR_API(getClassSize)
+DEF_CLR_API(getClassAlignmentRequirement)
+DEF_CLR_API(getClassGClayout)
+DEF_CLR_API(getClassNumInstanceFields)
+DEF_CLR_API(getFieldInClass)
+DEF_CLR_API(checkMethodModifier)
+DEF_CLR_API(getNewHelper)
+DEF_CLR_API(getNewArrHelper)
+DEF_CLR_API(getCastingHelper)
+DEF_CLR_API(getSharedCCtorHelper)
+DEF_CLR_API(getSecurityPrologHelper)
+DEF_CLR_API(getTypeForBox)
+DEF_CLR_API(getBoxHelper)
+DEF_CLR_API(getUnBoxHelper)
+DEF_CLR_API(getReadyToRunHelper)
+DEF_CLR_API(getReadyToRunDelegateCtorHelper)
+DEF_CLR_API(getHelperName)
+DEF_CLR_API(initClass)
+DEF_CLR_API(classMustBeLoadedBeforeCodeIsRun)
+DEF_CLR_API(getBuiltinClass)
+DEF_CLR_API(getTypeForPrimitiveValueClass)
+DEF_CLR_API(canCast)
+DEF_CLR_API(areTypesEquivalent)
+DEF_CLR_API(mergeClasses)
+DEF_CLR_API(getParentType)
+DEF_CLR_API(getChildType)
+DEF_CLR_API(satisfiesClassConstraints)
+DEF_CLR_API(isSDArray)
+DEF_CLR_API(getArrayRank)
+DEF_CLR_API(getArrayInitializationData)
+DEF_CLR_API(canAccessClass)
+DEF_CLR_API(getFieldName)
+DEF_CLR_API(getFieldClass)
+DEF_CLR_API(getFieldType)
+DEF_CLR_API(getFieldOffset)
+DEF_CLR_API(isWriteBarrierHelperRequired)
+DEF_CLR_API(getFieldInfo)
+DEF_CLR_API(isFieldStatic)
+DEF_CLR_API(getBoundaries)
+DEF_CLR_API(setBoundaries)
+DEF_CLR_API(getVars)
+DEF_CLR_API(setVars)
+DEF_CLR_API(allocateArray)
+DEF_CLR_API(freeArray)
+DEF_CLR_API(getArgNext)
+DEF_CLR_API(getArgType)
+DEF_CLR_API(getArgClass)
+DEF_CLR_API(getHFAType)
+DEF_CLR_API(GetErrorHRESULT)
+DEF_CLR_API(GetErrorMessage)
+DEF_CLR_API(FilterException)
+DEF_CLR_API(HandleException)
+DEF_CLR_API(ThrowExceptionForJitResult)
+DEF_CLR_API(ThrowExceptionForHelper)
+DEF_CLR_API(getEEInfo)
+DEF_CLR_API(getJitTimeLogFilename)
+DEF_CLR_API(getMethodDefFromMethod)
+DEF_CLR_API(getMethodName)
+DEF_CLR_API(getMethodHash)
+DEF_CLR_API(findNameOfToken)
+DEF_CLR_API(getSystemVAmd64PassStructInRegisterDescriptor)
+DEF_CLR_API(getThreadTLSIndex)
+DEF_CLR_API(getInlinedCallFrameVptr)
+DEF_CLR_API(getAddrOfCaptureThreadGlobal)
+DEF_CLR_API(getAddrModuleDomainID)
+DEF_CLR_API(getHelperFtn)
+DEF_CLR_API(getFunctionEntryPoint)
+DEF_CLR_API(getFunctionFixedEntryPoint)
+DEF_CLR_API(getMethodSync)
+DEF_CLR_API(getLazyStringLiteralHelper)
+DEF_CLR_API(embedModuleHandle)
+DEF_CLR_API(embedClassHandle)
+DEF_CLR_API(embedMethodHandle)
+DEF_CLR_API(embedFieldHandle)
+DEF_CLR_API(embedGenericHandle)
+DEF_CLR_API(getLocationOfThisType)
+DEF_CLR_API(getPInvokeUnmanagedTarget)
+DEF_CLR_API(getAddressOfPInvokeFixup)
+DEF_CLR_API(getAddressOfPInvokeTarget)
+DEF_CLR_API(GetCookieForPInvokeCalliSig)
+DEF_CLR_API(canGetCookieForPInvokeCalliSig)
+DEF_CLR_API(getJustMyCodeHandle)
+DEF_CLR_API(GetProfilingHandle)
+DEF_CLR_API(getCallInfo)
+DEF_CLR_API(canAccessFamily)
+DEF_CLR_API(isRIDClassDomainID)
+DEF_CLR_API(getClassDomainID)
+DEF_CLR_API(getFieldAddress)
+DEF_CLR_API(getVarArgsHandle)
+DEF_CLR_API(canGetVarArgsHandle)
+DEF_CLR_API(constructStringLiteral)
+DEF_CLR_API(emptyStringLiteral)
+DEF_CLR_API(getFieldThreadLocalStoreID)
+DEF_CLR_API(setOverride)
+DEF_CLR_API(addActiveDependency)
+DEF_CLR_API(GetDelegateCtor)
+DEF_CLR_API(MethodCompileComplete)
+DEF_CLR_API(getTailCallCopyArgsThunk)
+DEF_CLR_API(getJitFlags)
+DEF_CLR_API(runWithErrorTrap)
+DEF_CLR_API(getMemoryManager)
+DEF_CLR_API(allocMem)
+DEF_CLR_API(reserveUnwindInfo)
+DEF_CLR_API(allocUnwindInfo)
+DEF_CLR_API(allocGCInfo)
+DEF_CLR_API(yieldExecution)
+DEF_CLR_API(setEHcount)
+DEF_CLR_API(setEHinfo)
+DEF_CLR_API(logMsg)
+DEF_CLR_API(doAssert)
+DEF_CLR_API(reportFatalError)
+DEF_CLR_API(allocBBProfileBuffer)
+DEF_CLR_API(getBBProfileData)
+DEF_CLR_API(recordCallSite)
+DEF_CLR_API(recordRelocation)
+DEF_CLR_API(getRelocTypeHint)
+DEF_CLR_API(getModuleNativeEntryPointRange)
+DEF_CLR_API(getExpectedTargetArchitecture)
+
+#undef DEF_CLR_API
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+#define API_ENTER(name) wrapComp->CLR_API_Enter(API_##name);
+#define API_LEAVE(name) wrapComp->CLR_API_Leave(API_##name);
+
+/**********************************************************************************/
+// clang-format off
+/**********************************************************************************/
+//
+// ICorMethodInfo
+//
+
+DWORD WrapICorJitInfo::getMethodAttribs(CORINFO_METHOD_HANDLE ftn /* IN */)
+{
+ API_ENTER(getMethodAttribs)
+ DWORD temp = wrapHnd->getMethodAttribs(ftn);
+ API_LEAVE(getMethodAttribs)
+ return temp;
+}
+
+void WrapICorJitInfo::setMethodAttribs(CORINFO_METHOD_HANDLE ftn,/* IN */
+ CorInfoMethodRuntimeFlags attribs/* IN */)
+{
+ API_ENTER(setMethodAttribs);
+ wrapHnd->setMethodAttribs(ftn, attribs);
+ API_LEAVE(setMethodAttribs);
+}
+
+void WrapICorJitInfo::getMethodSig(CORINFO_METHOD_HANDLE ftn, /* IN */
+ CORINFO_SIG_INFO *sig, /* OUT */
+ CORINFO_CLASS_HANDLE memberParent/* IN */)
+{
+ API_ENTER(getMethodSig);
+ wrapHnd->getMethodSig(ftn, sig, memberParent);
+ API_LEAVE(getMethodSig);
+}
+
+bool WrapICorJitInfo::getMethodInfo(
+ CORINFO_METHOD_HANDLE ftn, /* IN */
+ CORINFO_METHOD_INFO* info /* OUT */)
+{
+ API_ENTER(getMethodInfo);
+ bool temp = wrapHnd->getMethodInfo(ftn, info);
+ API_LEAVE(getMethodInfo);
+ return temp;
+}
+
+CorInfoInline WrapICorJitInfo::canInline(
+ CORINFO_METHOD_HANDLE callerHnd, /* IN */
+ CORINFO_METHOD_HANDLE calleeHnd, /* IN */
+ DWORD* pRestrictions /* OUT */)
+{
+ API_ENTER(canInline);
+ CorInfoInline temp = wrapHnd->canInline(callerHnd, calleeHnd, pRestrictions);
+ API_LEAVE(canInline);
+ return temp;
+}
+
+void WrapICorJitInfo::reportInliningDecision(CORINFO_METHOD_HANDLE inlinerHnd,
+ CORINFO_METHOD_HANDLE inlineeHnd,
+ CorInfoInline inlineResult,
+ const char * reason)
+{
+ API_ENTER(reportInliningDecision);
+ wrapHnd->reportInliningDecision(inlinerHnd, inlineeHnd, inlineResult, reason);
+ API_LEAVE(reportInliningDecision);
+}
+
+bool WrapICorJitInfo::canTailCall(
+ CORINFO_METHOD_HANDLE callerHnd, /* IN */
+ CORINFO_METHOD_HANDLE declaredCalleeHnd, /* IN */
+ CORINFO_METHOD_HANDLE exactCalleeHnd, /* IN */
+ bool fIsTailPrefix /* IN */)
+{
+ API_ENTER(canTailCall);
+ bool temp = wrapHnd->canTailCall(callerHnd, declaredCalleeHnd, exactCalleeHnd, fIsTailPrefix);
+ API_LEAVE(canTailCall);
+ return temp;
+}
+
+void WrapICorJitInfo::reportTailCallDecision(CORINFO_METHOD_HANDLE callerHnd,
+ CORINFO_METHOD_HANDLE calleeHnd,
+ bool fIsTailPrefix,
+ CorInfoTailCall tailCallResult,
+ const char * reason)
+{
+ API_ENTER(reportTailCallDecision);
+ wrapHnd->reportTailCallDecision(callerHnd, calleeHnd, fIsTailPrefix, tailCallResult, reason);
+ API_LEAVE(reportTailCallDecision);
+}
+
+void WrapICorJitInfo::getEHinfo(
+ CORINFO_METHOD_HANDLE ftn, /* IN */
+ unsigned EHnumber, /* IN */
+ CORINFO_EH_CLAUSE* clause /* OUT */)
+{
+ API_ENTER(getEHinfo);
+ wrapHnd->getEHinfo(ftn, EHnumber, clause);
+ API_LEAVE(getEHinfo);
+}
+
+CORINFO_CLASS_HANDLE WrapICorJitInfo::getMethodClass(
+ CORINFO_METHOD_HANDLE method)
+{
+ API_ENTER(getMethodClass);
+ CORINFO_CLASS_HANDLE temp = wrapHnd->getMethodClass(method);
+ API_LEAVE(getMethodClass);
+ return temp;
+}
+
+CORINFO_MODULE_HANDLE WrapICorJitInfo::getMethodModule(
+ CORINFO_METHOD_HANDLE method)
+{
+ API_ENTER(getMethodModule);
+ CORINFO_MODULE_HANDLE temp = wrapHnd->getMethodModule(method);
+ API_LEAVE(getMethodModule);
+ return temp;
+}
+
+void WrapICorJitInfo::getMethodVTableOffset(
+ CORINFO_METHOD_HANDLE method, /* IN */
+ unsigned* offsetOfIndirection, /* OUT */
+ unsigned* offsetAfterIndirection /* OUT */)
+{
+ API_ENTER(getMethodVTableOffset);
+ wrapHnd->getMethodVTableOffset(method, offsetOfIndirection, offsetAfterIndirection);
+ API_LEAVE(getMethodVTableOffset);
+}
+
+#if COR_JIT_EE_VERSION > 460
+
+CorInfoIntrinsics WrapICorJitInfo::getIntrinsicID(
+ CORINFO_METHOD_HANDLE method,
+ bool* pMustExpand /* OUT */)
+{
+ API_ENTER(getIntrinsicID);
+ CorInfoIntrinsics temp = wrapHnd->getIntrinsicID(method, pMustExpand);
+ API_LEAVE(getIntrinsicID);
+ return temp;
+}
+
+#else
+
+CorInfoIntrinsics WrapICorJitInfo::getIntrinsicID(CORINFO_METHOD_HANDLE method)
+{
+ API_ENTER(getIntrinsicID);
+ CorInfoIntrinsics temp = wrapHnd->getIntrinsicID(method);
+ API_LEAVE(getIntrinsicID);
+ return temp;
+}
+
+#endif
+
+bool WrapICorJitInfo::isInSIMDModule(CORINFO_CLASS_HANDLE classHnd)
+{
+ API_ENTER(isInSIMDModule);
+ bool temp = wrapHnd->isInSIMDModule(classHnd);
+ API_LEAVE(isInSIMDModule);
+ return temp;
+}
+
+CorInfoUnmanagedCallConv WrapICorJitInfo::getUnmanagedCallConv(
+ CORINFO_METHOD_HANDLE method)
+{
+ API_ENTER(getUnmanagedCallConv);
+ CorInfoUnmanagedCallConv temp = wrapHnd->getUnmanagedCallConv(method);
+ API_LEAVE(getUnmanagedCallConv);
+ return temp;
+}
+
+BOOL WrapICorJitInfo::pInvokeMarshalingRequired(
+ CORINFO_METHOD_HANDLE method,
+ CORINFO_SIG_INFO* callSiteSig)
+{
+ API_ENTER(pInvokeMarshalingRequired);
+ BOOL temp = wrapHnd->pInvokeMarshalingRequired(method, callSiteSig);
+ API_LEAVE(pInvokeMarshalingRequired);
+ return temp;
+}
+
+BOOL WrapICorJitInfo::satisfiesMethodConstraints(
+ CORINFO_CLASS_HANDLE parent, // the exact parent of the method
+ CORINFO_METHOD_HANDLE method)
+{
+ API_ENTER(satisfiesMethodConstraints);
+ BOOL temp = wrapHnd->satisfiesMethodConstraints(parent, method);
+ API_LEAVE(satisfiesMethodConstraints);
+ return temp;
+}
+
+BOOL WrapICorJitInfo::isCompatibleDelegate(
+ CORINFO_CLASS_HANDLE objCls,
+ CORINFO_CLASS_HANDLE methodParentCls,
+ CORINFO_METHOD_HANDLE method,
+ CORINFO_CLASS_HANDLE delegateCls,
+ BOOL *pfIsOpenDelegate)
+{
+ API_ENTER(isCompatibleDelegate);
+ BOOL temp = wrapHnd->isCompatibleDelegate(objCls, methodParentCls, method, delegateCls, pfIsOpenDelegate);
+ API_LEAVE(isCompatibleDelegate);
+ return temp;
+}
+
+BOOL WrapICorJitInfo::isDelegateCreationAllowed(
+ CORINFO_CLASS_HANDLE delegateHnd,
+ CORINFO_METHOD_HANDLE calleeHnd)
+{
+ API_ENTER(isDelegateCreationAllowed);
+ BOOL temp = wrapHnd->isDelegateCreationAllowed(delegateHnd, calleeHnd);
+ API_LEAVE(isDelegateCreationAllowed);
+ return temp;
+}
+
+
+CorInfoInstantiationVerification WrapICorJitInfo::isInstantiationOfVerifiedGeneric(
+ CORINFO_METHOD_HANDLE method /* IN */)
+{
+ API_ENTER(isInstantiationOfVerifiedGeneric);
+ CorInfoInstantiationVerification temp = wrapHnd->isInstantiationOfVerifiedGeneric(method);
+ API_LEAVE(isInstantiationOfVerifiedGeneric);
+ return temp;
+}
+
+void WrapICorJitInfo::initConstraintsForVerification(
+ CORINFO_METHOD_HANDLE method, /* IN */
+ BOOL *pfHasCircularClassConstraints, /* OUT */
+ BOOL *pfHasCircularMethodConstraint /* OUT */)
+{
+ API_ENTER(initConstraintsForVerification);
+ wrapHnd->initConstraintsForVerification(method, pfHasCircularClassConstraints, pfHasCircularMethodConstraint);
+ API_LEAVE(initConstraintsForVerification);
+}
+
+CorInfoCanSkipVerificationResult WrapICorJitInfo::canSkipMethodVerification(
+ CORINFO_METHOD_HANDLE ftnHandle)
+{
+ API_ENTER(canSkipMethodVerification);
+ CorInfoCanSkipVerificationResult temp = wrapHnd->canSkipMethodVerification(ftnHandle);
+ API_LEAVE(canSkipMethodVerification);
+ return temp;
+}
+
+void WrapICorJitInfo::methodMustBeLoadedBeforeCodeIsRun(
+ CORINFO_METHOD_HANDLE method)
+{
+ API_ENTER(methodMustBeLoadedBeforeCodeIsRun);
+ wrapHnd->methodMustBeLoadedBeforeCodeIsRun(method);
+ API_LEAVE(methodMustBeLoadedBeforeCodeIsRun);
+}
+
+CORINFO_METHOD_HANDLE WrapICorJitInfo::mapMethodDeclToMethodImpl(
+ CORINFO_METHOD_HANDLE method)
+{
+ API_ENTER(mapMethodDeclToMethodImpl);
+ CORINFO_METHOD_HANDLE temp = wrapHnd->mapMethodDeclToMethodImpl(method);
+ API_LEAVE(mapMethodDeclToMethodImpl);
+ return temp;
+}
+
+void WrapICorJitInfo::getGSCookie(
+ GSCookie * pCookieVal,
+ GSCookie ** ppCookieVal )
+{
+ API_ENTER(getGSCookie);
+ wrapHnd->getGSCookie(pCookieVal, ppCookieVal);
+ API_LEAVE(getGSCookie);
+}
+
+/**********************************************************************************/
+//
+// ICorModuleInfo
+//
+/**********************************************************************************/
+
+void WrapICorJitInfo::resolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken)
+{
+ API_ENTER(resolveToken);
+ wrapHnd->resolveToken(pResolvedToken);
+ API_LEAVE(resolveToken);
+}
+
+#if COR_JIT_EE_VERSION > 460
+
+bool WrapICorJitInfo::tryResolveToken(/* IN, OUT */ CORINFO_RESOLVED_TOKEN * pResolvedToken)
+{
+ API_ENTER(tryResolveToken);
+ bool success = wrapHnd->tryResolveToken(pResolvedToken);
+ API_LEAVE(tryResolveToken);
+ return success;
+}
+
+#endif
+
+void WrapICorJitInfo::findSig(
+ CORINFO_MODULE_HANDLE module,
+ unsigned sigTOK,
+ CORINFO_CONTEXT_HANDLE context,
+ CORINFO_SIG_INFO *sig )
+{
+ API_ENTER(findSig);
+ wrapHnd->findSig(module, sigTOK, context, sig);
+ API_LEAVE(findSig);
+}
+
+void WrapICorJitInfo::findCallSiteSig(
+ CORINFO_MODULE_HANDLE module, /* IN */
+ unsigned methTOK, /* IN */
+ CORINFO_CONTEXT_HANDLE context, /* IN */
+ CORINFO_SIG_INFO *sig /* OUT */)
+{
+ API_ENTER(findCallSiteSig);
+ wrapHnd->findCallSiteSig(module, methTOK, context, sig);
+ API_LEAVE(findCallSiteSig);
+}
+
+CORINFO_CLASS_HANDLE WrapICorJitInfo::getTokenTypeAsHandle(
+ CORINFO_RESOLVED_TOKEN * pResolvedToken /* IN */)
+{
+ API_ENTER(getTokenTypeAsHandle);
+ CORINFO_CLASS_HANDLE temp = wrapHnd->getTokenTypeAsHandle(pResolvedToken);
+ API_LEAVE(getTokenTypeAsHandle);
+ return temp;
+}
+
+CorInfoCanSkipVerificationResult WrapICorJitInfo::canSkipVerification(
+ CORINFO_MODULE_HANDLE module /* IN */)
+{
+ API_ENTER(canSkipVerification);
+ CorInfoCanSkipVerificationResult temp = wrapHnd->canSkipVerification(module);
+ API_LEAVE(canSkipVerification);
+ return temp;
+}
+
+BOOL WrapICorJitInfo::isValidToken(
+ CORINFO_MODULE_HANDLE module, /* IN */
+ unsigned metaTOK /* IN */)
+{
+ API_ENTER(isValidToken);
+ BOOL result = wrapHnd->isValidToken(module, metaTOK);
+ API_LEAVE(isValidToken);
+ return result;
+}
+
+BOOL WrapICorJitInfo::isValidStringRef(
+ CORINFO_MODULE_HANDLE module, /* IN */
+ unsigned metaTOK /* IN */)
+{
+ API_ENTER(isValidStringRef);
+ BOOL temp = wrapHnd->isValidStringRef(module, metaTOK);
+ API_LEAVE(isValidStringRef);
+ return temp;
+}
+
+BOOL WrapICorJitInfo::shouldEnforceCallvirtRestriction(
+ CORINFO_MODULE_HANDLE scope)
+{
+ API_ENTER(shouldEnforceCallvirtRestriction);
+ BOOL temp = wrapHnd->shouldEnforceCallvirtRestriction(scope);
+ API_LEAVE(shouldEnforceCallvirtRestriction);
+ return temp;
+}
+
+/**********************************************************************************/
+//
+// ICorClassInfo
+//
+/**********************************************************************************/
+
+CorInfoType WrapICorJitInfo::asCorInfoType(CORINFO_CLASS_HANDLE cls)
+{
+ API_ENTER(asCorInfoType);
+ CorInfoType temp = wrapHnd->asCorInfoType(cls);
+ API_LEAVE(asCorInfoType);
+ return temp;
+}
+
+const char* WrapICorJitInfo::getClassName(CORINFO_CLASS_HANDLE cls)
+{
+ API_ENTER(getClassName);
+ const char* result = wrapHnd->getClassName(cls);
+ API_LEAVE(getClassName);
+ return result;
+}
+
+int WrapICorJitInfo::appendClassName(
+ __deref_inout_ecount(*pnBufLen) WCHAR** ppBuf,
+ int* pnBufLen,
+ CORINFO_CLASS_HANDLE cls,
+ BOOL fNamespace,
+ BOOL fFullInst,
+ BOOL fAssembly)
+{
+ API_ENTER(appendClassName);
+ WCHAR* pBuf = *ppBuf;
+ int nLen = wrapHnd->appendClassName(ppBuf, pnBufLen, cls, fNamespace, fFullInst, fAssembly);
+ API_LEAVE(appendClassName);
+ return nLen;
+}
+
+BOOL WrapICorJitInfo::isValueClass(CORINFO_CLASS_HANDLE cls)
+{
+ API_ENTER(isValueClass);
+ BOOL temp = wrapHnd->isValueClass(cls);
+ API_LEAVE(isValueClass);
+ return temp;
+}
+
+BOOL WrapICorJitInfo::canInlineTypeCheckWithObjectVTable(CORINFO_CLASS_HANDLE cls)
+{
+ API_ENTER(canInlineTypeCheckWithObjectVTable);
+ BOOL temp = wrapHnd->canInlineTypeCheckWithObjectVTable(cls);
+ API_LEAVE(canInlineTypeCheckWithObjectVTable);
+ return temp;
+}
+
+DWORD WrapICorJitInfo::getClassAttribs(
+ CORINFO_CLASS_HANDLE cls)
+{
+ API_ENTER(getClassAttribs);
+ DWORD temp = wrapHnd->getClassAttribs(cls);
+ API_LEAVE(getClassAttribs);
+ return temp;
+}
+
+BOOL WrapICorJitInfo::isStructRequiringStackAllocRetBuf(CORINFO_CLASS_HANDLE cls)
+{
+ API_ENTER(isStructRequiringStackAllocRetBuf);
+ BOOL temp = wrapHnd->isStructRequiringStackAllocRetBuf(cls);
+ API_LEAVE(isStructRequiringStackAllocRetBuf);
+ return temp;
+}
+
+CORINFO_MODULE_HANDLE WrapICorJitInfo::getClassModule(
+ CORINFO_CLASS_HANDLE cls)
+{
+ API_ENTER(getClassModule);
+ CORINFO_MODULE_HANDLE result = wrapHnd->getClassModule(cls);
+ API_LEAVE(getClassModule);
+ return result;
+}
+
+CORINFO_ASSEMBLY_HANDLE WrapICorJitInfo::getModuleAssembly(
+ CORINFO_MODULE_HANDLE mod)
+{
+ API_ENTER(getModuleAssembly);
+ CORINFO_ASSEMBLY_HANDLE result = wrapHnd->getModuleAssembly(mod);
+ API_LEAVE(getModuleAssembly);
+ return result;
+}
+
+const char* WrapICorJitInfo::getAssemblyName(
+ CORINFO_ASSEMBLY_HANDLE assem)
+{
+ API_ENTER(getAssemblyName);
+ const char* result = wrapHnd->getAssemblyName(assem);
+ API_LEAVE(getAssemblyName);
+ return result;
+}
+
+void* WrapICorJitInfo::LongLifetimeMalloc(size_t sz)
+{
+ API_ENTER(LongLifetimeMalloc);
+ void* result = wrapHnd->LongLifetimeMalloc(sz);
+ API_LEAVE(LongLifetimeMalloc);
+ return result;
+}
+
+void WrapICorJitInfo::LongLifetimeFree(void* obj)
+{
+ API_ENTER(LongLifetimeFree);
+ wrapHnd->LongLifetimeFree(obj);
+ API_LEAVE(LongLifetimeFree);
+}
+
+size_t WrapICorJitInfo::getClassModuleIdForStatics(
+ CORINFO_CLASS_HANDLE cls,
+ CORINFO_MODULE_HANDLE *pModule,
+ void **ppIndirection)
+{
+ API_ENTER(getClassModuleIdForStatics);
+ size_t temp = wrapHnd->getClassModuleIdForStatics(cls, pModule, ppIndirection);
+ API_LEAVE(getClassModuleIdForStatics);
+ return temp;
+}
+
+unsigned WrapICorJitInfo::getClassSize(CORINFO_CLASS_HANDLE cls)
+{
+ API_ENTER(getClassSize);
+ unsigned temp = wrapHnd->getClassSize(cls);
+ API_LEAVE(getClassSize);
+ return temp;
+}
+
+unsigned WrapICorJitInfo::getClassAlignmentRequirement(
+ CORINFO_CLASS_HANDLE cls,
+ BOOL fDoubleAlignHint)
+{
+ API_ENTER(getClassAlignmentRequirement);
+ unsigned temp = wrapHnd->getClassAlignmentRequirement(cls, fDoubleAlignHint);
+ API_LEAVE(getClassAlignmentRequirement);
+ return temp;
+}
+
+unsigned WrapICorJitInfo::getClassGClayout(
+ CORINFO_CLASS_HANDLE cls, /* IN */
+ BYTE *gcPtrs /* OUT */)
+{
+ API_ENTER(getClassGClayout);
+ unsigned temp = wrapHnd->getClassGClayout(cls, gcPtrs);
+ API_LEAVE(getClassGClayout);
+ return temp;
+}
+
+unsigned WrapICorJitInfo::getClassNumInstanceFields(
+ CORINFO_CLASS_HANDLE cls /* IN */)
+{
+ API_ENTER(getClassNumInstanceFields);
+ unsigned temp = wrapHnd->getClassNumInstanceFields(cls);
+ API_LEAVE(getClassNumInstanceFields);
+ return temp;
+}
+
+CORINFO_FIELD_HANDLE WrapICorJitInfo::getFieldInClass(
+ CORINFO_CLASS_HANDLE clsHnd,
+ INT num)
+{
+ API_ENTER(getFieldInClass);
+ CORINFO_FIELD_HANDLE temp = wrapHnd->getFieldInClass(clsHnd, num);
+ API_LEAVE(getFieldInClass);
+ return temp;
+}
+
+BOOL WrapICorJitInfo::checkMethodModifier(
+ CORINFO_METHOD_HANDLE hMethod,
+ LPCSTR modifier,
+ BOOL fOptional)
+{
+ API_ENTER(checkMethodModifier);
+ BOOL result = wrapHnd->checkMethodModifier(hMethod, modifier, fOptional);
+ API_LEAVE(checkMethodModifier);
+ return result;
+}
+
+CorInfoHelpFunc WrapICorJitInfo::getNewHelper(
+ CORINFO_RESOLVED_TOKEN * pResolvedToken,
+ CORINFO_METHOD_HANDLE callerHandle)
+{
+ API_ENTER(getNewHelper);
+ CorInfoHelpFunc temp = wrapHnd->getNewHelper(pResolvedToken, callerHandle);
+ API_LEAVE(getNewHelper);
+ return temp;
+}
+
+CorInfoHelpFunc WrapICorJitInfo::getNewArrHelper(
+ CORINFO_CLASS_HANDLE arrayCls)
+{
+ API_ENTER(getNewArrHelper);
+ CorInfoHelpFunc temp = wrapHnd->getNewArrHelper(arrayCls);
+ API_LEAVE(getNewArrHelper);
+ return temp;
+}
+
+CorInfoHelpFunc WrapICorJitInfo::getCastingHelper(
+ CORINFO_RESOLVED_TOKEN * pResolvedToken,
+ bool fThrowing)
+{
+ API_ENTER(getCastingHelper);
+ CorInfoHelpFunc temp = wrapHnd->getCastingHelper(pResolvedToken, fThrowing);
+ API_LEAVE(getCastingHelper);
+ return temp;
+}
+
+CorInfoHelpFunc WrapICorJitInfo::getSharedCCtorHelper(
+ CORINFO_CLASS_HANDLE clsHnd)
+{
+ API_ENTER(getSharedCCtorHelper);
+ CorInfoHelpFunc temp = wrapHnd->getSharedCCtorHelper(clsHnd);
+ API_LEAVE(getSharedCCtorHelper);
+ return temp;
+}
+
+CorInfoHelpFunc WrapICorJitInfo::getSecurityPrologHelper(
+ CORINFO_METHOD_HANDLE ftn)
+{
+ API_ENTER(getSecurityPrologHelper);
+ CorInfoHelpFunc temp = wrapHnd->getSecurityPrologHelper(ftn);
+ API_LEAVE(getSecurityPrologHelper);
+ return temp;
+}
+
+CORINFO_CLASS_HANDLE WrapICorJitInfo::getTypeForBox(
+ CORINFO_CLASS_HANDLE cls)
+{
+ API_ENTER(getTypeForBox);
+ CORINFO_CLASS_HANDLE temp = wrapHnd->getTypeForBox(cls);
+ API_LEAVE(getTypeForBox);
+ return temp;
+}
+
+CorInfoHelpFunc WrapICorJitInfo::getBoxHelper(
+ CORINFO_CLASS_HANDLE cls)
+{
+ API_ENTER(getBoxHelper);
+ CorInfoHelpFunc temp = wrapHnd->getBoxHelper(cls);
+ API_LEAVE(getBoxHelper);
+ return temp;
+}
+
+CorInfoHelpFunc WrapICorJitInfo::getUnBoxHelper(
+ CORINFO_CLASS_HANDLE cls)
+{
+ API_ENTER(getUnBoxHelper);
+ CorInfoHelpFunc temp = wrapHnd->getUnBoxHelper(cls);
+ API_LEAVE(getUnBoxHelper);
+ return temp;
+}
+
+#if COR_JIT_EE_VERSION > 460
+
+bool WrapICorJitInfo::getReadyToRunHelper(
+ CORINFO_RESOLVED_TOKEN * pResolvedToken,
+ CORINFO_LOOKUP_KIND * pGenericLookupKind,
+ CorInfoHelpFunc id,
+ CORINFO_CONST_LOOKUP * pLookup)
+{
+ API_ENTER(getReadyToRunHelper);
+ bool result = wrapHnd->getReadyToRunHelper(pResolvedToken, pGenericLookupKind, id, pLookup);
+ API_LEAVE(getReadyToRunHelper);
+ return result;
+}
+
+void WrapICorJitInfo::getReadyToRunDelegateCtorHelper(
+ CORINFO_RESOLVED_TOKEN * pTargetMethod,
+ CORINFO_CLASS_HANDLE delegateType,
+ CORINFO_CONST_LOOKUP * pLookup)
+{
+ API_ENTER(getReadyToRunDelegateCtorHelper);
+ wrapHnd->getReadyToRunDelegateCtorHelper(pTargetMethod, delegateType, pLookup);
+ API_LEAVE(getReadyToRunDelegateCtorHelper);
+}
+
+#else
+
+void WrapICorJitInfo::getReadyToRunHelper(
+ CORINFO_RESOLVED_TOKEN * pResolvedToken,
+ CorInfoHelpFunc id,
+ CORINFO_CONST_LOOKUP * pLookup)
+{
+ API_ENTER(getReadyToRunHelper);
+ wrapHnd->getReadyToRunHelper(pResolvedToken, id, pLookup);
+ API_LEAVE(getReadyToRunHelper);
+}
+
+#endif
+
+const char* WrapICorJitInfo::getHelperName(
+ CorInfoHelpFunc funcNum)
+{
+ API_ENTER(getHelperName);
+ const char* temp = wrapHnd->getHelperName(funcNum);
+ API_LEAVE(getHelperName);
+ return temp;
+}
+
+CorInfoInitClassResult WrapICorJitInfo::initClass(
+ CORINFO_FIELD_HANDLE field,
+
+ CORINFO_METHOD_HANDLE method,
+ CORINFO_CONTEXT_HANDLE context,
+ BOOL speculative)
+{
+ API_ENTER(initClass);
+ CorInfoInitClassResult temp = wrapHnd->initClass(field, method, context, speculative);
+ API_LEAVE(initClass);
+ return temp;
+}
+
+void WrapICorJitInfo::classMustBeLoadedBeforeCodeIsRun(
+ CORINFO_CLASS_HANDLE cls)
+{
+ API_ENTER(classMustBeLoadedBeforeCodeIsRun);
+ wrapHnd->classMustBeLoadedBeforeCodeIsRun(cls);
+ API_LEAVE(classMustBeLoadedBeforeCodeIsRun);
+}
+
+CORINFO_CLASS_HANDLE WrapICorJitInfo::getBuiltinClass(
+ CorInfoClassId classId)
+{
+ API_ENTER(getBuiltinClass);
+ CORINFO_CLASS_HANDLE temp = wrapHnd->getBuiltinClass(classId);
+ API_LEAVE(getBuiltinClass);
+ return temp;
+}
+
+CorInfoType WrapICorJitInfo::getTypeForPrimitiveValueClass(
+ CORINFO_CLASS_HANDLE cls)
+{
+ API_ENTER(getTypeForPrimitiveValueClass);
+ CorInfoType temp = wrapHnd->getTypeForPrimitiveValueClass(cls);
+ API_LEAVE(getTypeForPrimitiveValueClass);
+ return temp;
+}
+
+BOOL WrapICorJitInfo::canCast(
+ CORINFO_CLASS_HANDLE child,
+ CORINFO_CLASS_HANDLE parent )
+{
+ API_ENTER(canCast);
+ BOOL temp = wrapHnd->canCast(child, parent);
+ API_LEAVE(canCast);
+ return temp;
+}
+
+BOOL WrapICorJitInfo::areTypesEquivalent(
+ CORINFO_CLASS_HANDLE cls1,
+ CORINFO_CLASS_HANDLE cls2)
+{
+ API_ENTER(areTypesEquivalent);
+ BOOL temp = wrapHnd->areTypesEquivalent(cls1, cls2);
+ API_LEAVE(areTypesEquivalent);
+ return temp;
+}
+
+CORINFO_CLASS_HANDLE WrapICorJitInfo::mergeClasses(
+ CORINFO_CLASS_HANDLE cls1,
+ CORINFO_CLASS_HANDLE cls2)
+{
+ API_ENTER(mergeClasses);
+ CORINFO_CLASS_HANDLE temp = wrapHnd->mergeClasses(cls1, cls2);
+ API_LEAVE(mergeClasses);
+ return temp;
+}
+
+CORINFO_CLASS_HANDLE WrapICorJitInfo::getParentType(
+ CORINFO_CLASS_HANDLE cls)
+{
+ API_ENTER(getParentType);
+ CORINFO_CLASS_HANDLE temp = wrapHnd->getParentType(cls);
+ API_LEAVE(getParentType);
+ return temp;
+}
+
+CorInfoType WrapICorJitInfo::getChildType(
+ CORINFO_CLASS_HANDLE clsHnd,
+ CORINFO_CLASS_HANDLE *clsRet)
+{
+ API_ENTER(getChildType);
+ CorInfoType temp = wrapHnd->getChildType(clsHnd, clsRet);
+ API_LEAVE(getChildType);
+ return temp;
+}
+
+BOOL WrapICorJitInfo::satisfiesClassConstraints(
+ CORINFO_CLASS_HANDLE cls)
+{
+ API_ENTER(satisfiesClassConstraints);
+ BOOL temp = wrapHnd->satisfiesClassConstraints(cls);
+ API_LEAVE(satisfiesClassConstraints);
+ return temp;
+
+}
+
+BOOL WrapICorJitInfo::isSDArray(
+ CORINFO_CLASS_HANDLE cls)
+{
+ API_ENTER(isSDArray);
+ BOOL temp = wrapHnd->isSDArray(cls);
+ API_LEAVE(isSDArray);
+ return temp;
+}
+
+unsigned WrapICorJitInfo::getArrayRank(
+ CORINFO_CLASS_HANDLE cls)
+{
+ API_ENTER(getArrayRank);
+ unsigned result = wrapHnd->getArrayRank(cls);
+ API_LEAVE(getArrayRank);
+ return result;
+}
+
+void * WrapICorJitInfo::getArrayInitializationData(
+ CORINFO_FIELD_HANDLE field,
+ DWORD size)
+{
+ API_ENTER(getArrayInitializationData);
+ void *temp = wrapHnd->getArrayInitializationData(field, size);
+ API_LEAVE(getArrayInitializationData);
+ return temp;
+}
+
+CorInfoIsAccessAllowedResult WrapICorJitInfo::canAccessClass(
+ CORINFO_RESOLVED_TOKEN * pResolvedToken,
+ CORINFO_METHOD_HANDLE callerHandle,
+ CORINFO_HELPER_DESC *pAccessHelper)
+{
+ API_ENTER(canAccessClass);
+ CorInfoIsAccessAllowedResult temp = wrapHnd->canAccessClass(pResolvedToken, callerHandle, pAccessHelper);
+ API_LEAVE(canAccessClass);
+ return temp;
+}
+
+/**********************************************************************************/
+//
+// ICorFieldInfo
+//
+/**********************************************************************************/
+
+const char* WrapICorJitInfo::getFieldName(
+ CORINFO_FIELD_HANDLE ftn, /* IN */
+ const char **moduleName /* OUT */)
+{
+ API_ENTER(getFieldName);
+ const char* temp = wrapHnd->getFieldName(ftn, moduleName);
+ API_LEAVE(getFieldName);
+ return temp;
+}
+
+CORINFO_CLASS_HANDLE WrapICorJitInfo::getFieldClass(
+ CORINFO_FIELD_HANDLE field)
+{
+ API_ENTER(getFieldClass);
+ CORINFO_CLASS_HANDLE temp = wrapHnd->getFieldClass(field);
+ API_LEAVE(getFieldClass);
+ return temp;
+}
+
+CorInfoType WrapICorJitInfo::getFieldType(
+ CORINFO_FIELD_HANDLE field,
+ CORINFO_CLASS_HANDLE *structType,
+ CORINFO_CLASS_HANDLE memberParent/* IN */)
+{
+ API_ENTER(getFieldType);
+ CorInfoType temp = wrapHnd->getFieldType(field, structType, memberParent);
+ API_LEAVE(getFieldType);
+ return temp;
+}
+
+unsigned WrapICorJitInfo::getFieldOffset(
+ CORINFO_FIELD_HANDLE field)
+{
+ API_ENTER(getFieldOffset);
+ unsigned temp = wrapHnd->getFieldOffset(field);
+ API_LEAVE(getFieldOffset);
+ return temp;
+}
+
+bool WrapICorJitInfo::isWriteBarrierHelperRequired(
+ CORINFO_FIELD_HANDLE field)
+{
+ API_ENTER(isWriteBarrierHelperRequired);
+ bool result = wrapHnd->isWriteBarrierHelperRequired(field);
+ API_LEAVE(isWriteBarrierHelperRequired);
+ return result;
+}
+
+void WrapICorJitInfo::getFieldInfo(CORINFO_RESOLVED_TOKEN * pResolvedToken,
+ CORINFO_METHOD_HANDLE callerHandle,
+ CORINFO_ACCESS_FLAGS flags,
+ CORINFO_FIELD_INFO *pResult)
+{
+ API_ENTER(getFieldInfo);
+ wrapHnd->getFieldInfo(pResolvedToken, callerHandle, flags, pResult);
+ API_LEAVE(getFieldInfo);
+}
+
+bool WrapICorJitInfo::isFieldStatic(CORINFO_FIELD_HANDLE fldHnd)
+{
+ API_ENTER(isFieldStatic);
+ bool result = wrapHnd->isFieldStatic(fldHnd);
+ API_LEAVE(isFieldStatic);
+ return result;
+}
+
+/*********************************************************************************/
+//
+// ICorDebugInfo
+//
+/*********************************************************************************/
+
+void WrapICorJitInfo::getBoundaries(
+ CORINFO_METHOD_HANDLE ftn,
+ unsigned int *cILOffsets,
+ DWORD **pILOffsets,
+
+ ICorDebugInfo::BoundaryTypes *implictBoundaries)
+{
+ API_ENTER(getBoundaries);
+ wrapHnd->getBoundaries(ftn, cILOffsets, pILOffsets, implictBoundaries);
+ API_LEAVE(getBoundaries);
+}
+
+void WrapICorJitInfo::setBoundaries(
+ CORINFO_METHOD_HANDLE ftn,
+ ULONG32 cMap,
+ ICorDebugInfo::OffsetMapping *pMap)
+{
+ API_ENTER(setBoundaries);
+ wrapHnd->setBoundaries(ftn, cMap, pMap);
+ API_LEAVE(setBoundaries);
+}
+
+void WrapICorJitInfo::getVars(
+ CORINFO_METHOD_HANDLE ftn,
+ ULONG32 *cVars,
+ ICorDebugInfo::ILVarInfo **vars,
+ bool *extendOthers)
+
+{
+ API_ENTER(getVars);
+ wrapHnd->getVars(ftn, cVars, vars, extendOthers);
+ API_LEAVE(getVars);
+}
+
+void WrapICorJitInfo::setVars(
+ CORINFO_METHOD_HANDLE ftn,
+ ULONG32 cVars,
+ ICorDebugInfo::NativeVarInfo *vars)
+
+{
+ API_ENTER(setVars);
+ wrapHnd->setVars(ftn, cVars, vars);
+ API_LEAVE(setVars);
+}
+
+void * WrapICorJitInfo::allocateArray(
+ ULONG cBytes)
+{
+ API_ENTER(allocateArray);
+ void *temp = wrapHnd->allocateArray(cBytes);
+ API_LEAVE(allocateArray);
+ return temp;
+}
+
+void WrapICorJitInfo::freeArray(
+ void *array)
+{
+ API_ENTER(freeArray);
+ wrapHnd->freeArray(array);
+ API_LEAVE(freeArray);
+}
+
+/*********************************************************************************/
+//
+// ICorArgInfo
+//
+/*********************************************************************************/
+
+CORINFO_ARG_LIST_HANDLE WrapICorJitInfo::getArgNext(
+ CORINFO_ARG_LIST_HANDLE args /* IN */)
+{
+ API_ENTER(getArgNext);
+ CORINFO_ARG_LIST_HANDLE temp = wrapHnd->getArgNext(args);
+ API_LEAVE(getArgNext);
+ return temp;
+}
+
+CorInfoTypeWithMod WrapICorJitInfo::getArgType(
+ CORINFO_SIG_INFO* sig, /* IN */
+ CORINFO_ARG_LIST_HANDLE args, /* IN */
+ CORINFO_CLASS_HANDLE *vcTypeRet /* OUT */)
+{
+ API_ENTER(getArgType);
+ CorInfoTypeWithMod temp = wrapHnd->getArgType(sig, args, vcTypeRet);
+ API_LEAVE(getArgType);
+ return temp;
+}
+
+CORINFO_CLASS_HANDLE WrapICorJitInfo::getArgClass(
+ CORINFO_SIG_INFO* sig, /* IN */
+ CORINFO_ARG_LIST_HANDLE args /* IN */)
+{
+ API_ENTER(getArgClass);
+ CORINFO_CLASS_HANDLE temp = wrapHnd->getArgClass(sig, args);
+ API_LEAVE(getArgClass);
+ return temp;
+}
+
+CorInfoType WrapICorJitInfo::getHFAType(
+ CORINFO_CLASS_HANDLE hClass)
+{
+ API_ENTER(getHFAType);
+ CorInfoType temp = wrapHnd->getHFAType(hClass);
+ API_LEAVE(getHFAType);
+ return temp;
+}
+
+HRESULT WrapICorJitInfo::GetErrorHRESULT(
+ struct _EXCEPTION_POINTERS *pExceptionPointers)
+{
+ API_ENTER(GetErrorHRESULT);
+ HRESULT temp = wrapHnd->GetErrorHRESULT(pExceptionPointers);
+ API_LEAVE(GetErrorHRESULT);
+ return temp;
+}
+
+ULONG WrapICorJitInfo::GetErrorMessage(
+ __inout_ecount(bufferLength) LPWSTR buffer,
+ ULONG bufferLength)
+{
+ API_ENTER(GetErrorMessage);
+ ULONG temp = wrapHnd->GetErrorMessage(buffer, bufferLength);
+ API_LEAVE(GetErrorMessage);
+ return temp;
+}
+
+int WrapICorJitInfo::FilterException(
+ struct _EXCEPTION_POINTERS *pExceptionPointers)
+{
+ API_ENTER(FilterException);
+ int temp = wrapHnd->FilterException(pExceptionPointers);
+ API_LEAVE(FilterException);
+ return temp;
+}
+
+void WrapICorJitInfo::HandleException(
+ struct _EXCEPTION_POINTERS *pExceptionPointers)
+{
+ API_ENTER(HandleException);
+ wrapHnd->HandleException(pExceptionPointers);
+ API_LEAVE(HandleException);
+}
+
+void WrapICorJitInfo::ThrowExceptionForJitResult(
+ HRESULT result)
+{
+ API_ENTER(ThrowExceptionForJitResult);
+ wrapHnd->ThrowExceptionForJitResult(result);
+ API_LEAVE(ThrowExceptionForJitResult);
+}
+
+void WrapICorJitInfo::ThrowExceptionForHelper(
+ const CORINFO_HELPER_DESC * throwHelper)
+{
+ API_ENTER(ThrowExceptionForHelper);
+ wrapHnd->ThrowExceptionForHelper(throwHelper);
+ API_LEAVE(ThrowExceptionForHelper);
+}
+
+void WrapICorJitInfo::getEEInfo(
+ CORINFO_EE_INFO *pEEInfoOut)
+{
+ API_ENTER(getEEInfo);
+ wrapHnd->getEEInfo(pEEInfoOut);
+ API_LEAVE(getEEInfo);
+}
+
+LPCWSTR WrapICorJitInfo::getJitTimeLogFilename()
+{
+ API_ENTER(getJitTimeLogFilename);
+ LPCWSTR temp = wrapHnd->getJitTimeLogFilename();
+ API_LEAVE(getJitTimeLogFilename);
+ return temp;
+}
+
+mdMethodDef WrapICorJitInfo::getMethodDefFromMethod(
+ CORINFO_METHOD_HANDLE hMethod)
+{
+ API_ENTER(getMethodDefFromMethod);
+ mdMethodDef result = wrapHnd->getMethodDefFromMethod(hMethod);
+ API_LEAVE(getMethodDefFromMethod);
+ return result;
+}
+
+const char* WrapICorJitInfo::getMethodName(
+ CORINFO_METHOD_HANDLE ftn, /* IN */
+ const char **moduleName /* OUT */)
+{
+ API_ENTER(getMethodName);
+ const char* temp = wrapHnd->getMethodName(ftn, moduleName);
+ API_LEAVE(getMethodName);
+ return temp;
+}
+
+unsigned WrapICorJitInfo::getMethodHash(
+ CORINFO_METHOD_HANDLE ftn /* IN */)
+{
+ API_ENTER(getMethodHash);
+ unsigned temp = wrapHnd->getMethodHash(ftn);
+ API_LEAVE(getMethodHash);
+ return temp;
+}
+
+size_t WrapICorJitInfo::findNameOfToken(
+ CORINFO_MODULE_HANDLE module, /* IN */
+ mdToken metaTOK, /* IN */
+ __out_ecount(FQNameCapacity) char * szFQName, /* OUT */
+ size_t FQNameCapacity /* IN */)
+{
+ API_ENTER(findNameOfToken);
+ size_t result = wrapHnd->findNameOfToken(module, metaTOK, szFQName, FQNameCapacity);
+ API_LEAVE(findNameOfToken);
+ return result;
+}
+
+#if COR_JIT_EE_VERSION > 460
+
+bool WrapICorJitInfo::getSystemVAmd64PassStructInRegisterDescriptor(
+ /* IN */ CORINFO_CLASS_HANDLE structHnd,
+ /* OUT */ SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr)
+{
+ API_ENTER(getSystemVAmd64PassStructInRegisterDescriptor);
+ bool result = wrapHnd->getSystemVAmd64PassStructInRegisterDescriptor(structHnd, structPassInRegDescPtr);
+ API_LEAVE(getSystemVAmd64PassStructInRegisterDescriptor);
+ return result;
+}
+
+#endif
+
+DWORD WrapICorJitInfo::getThreadTLSIndex(
+ void **ppIndirection)
+{
+ API_ENTER(getThreadTLSIndex);
+ DWORD temp = wrapHnd->getThreadTLSIndex(ppIndirection);
+ API_LEAVE(getThreadTLSIndex);
+ return temp;
+}
+
+const void * WrapICorJitInfo::getInlinedCallFrameVptr(
+ void **ppIndirection)
+{
+ API_ENTER(getInlinedCallFrameVptr);
+ const void* temp = wrapHnd->getInlinedCallFrameVptr(ppIndirection);
+ API_LEAVE(getInlinedCallFrameVptr);
+ return temp;
+}
+
+LONG * WrapICorJitInfo::getAddrOfCaptureThreadGlobal(
+ void **ppIndirection)
+{
+ API_ENTER(getAddrOfCaptureThreadGlobal);
+ LONG * temp = wrapHnd->getAddrOfCaptureThreadGlobal(ppIndirection);
+ API_LEAVE(getAddrOfCaptureThreadGlobal);
+ return temp;
+}
+
+SIZE_T* WrapICorJitInfo::getAddrModuleDomainID(CORINFO_MODULE_HANDLE module)
+{
+ API_ENTER(getAddrModuleDomainID);
+ SIZE_T* result = wrapHnd->getAddrModuleDomainID(module);
+ API_LEAVE(getAddrModuleDomainID);
+ return result;
+}
+
+void* WrapICorJitInfo::getHelperFtn(
+ CorInfoHelpFunc ftnNum,
+ void **ppIndirection)
+{
+ API_ENTER(getHelperFtn);
+ void *temp = wrapHnd->getHelperFtn(ftnNum, ppIndirection);
+ API_LEAVE(getHelperFtn);
+ return temp;
+}
+
+void WrapICorJitInfo::getFunctionEntryPoint(
+ CORINFO_METHOD_HANDLE ftn, /* IN */
+ CORINFO_CONST_LOOKUP * pResult, /* OUT */
+ CORINFO_ACCESS_FLAGS accessFlags)
+{
+ API_ENTER(getFunctionEntryPoint);
+ wrapHnd->getFunctionEntryPoint(ftn, pResult, accessFlags);
+ API_LEAVE(getFunctionEntryPoint);
+}
+
+void WrapICorJitInfo::getFunctionFixedEntryPoint(
+ CORINFO_METHOD_HANDLE ftn,
+ CORINFO_CONST_LOOKUP * pResult)
+{
+ API_ENTER(getFunctionFixedEntryPoint);
+ wrapHnd->getFunctionFixedEntryPoint(ftn, pResult);
+ API_LEAVE(getFunctionFixedEntryPoint);
+}
+
+void* WrapICorJitInfo::getMethodSync(
+ CORINFO_METHOD_HANDLE ftn,
+ void **ppIndirection)
+{
+ API_ENTER(getMethodSync);
+ void *temp = wrapHnd->getMethodSync(ftn, ppIndirection);
+ API_LEAVE(getMethodSync);
+ return temp;
+}
+
+
+CorInfoHelpFunc WrapICorJitInfo::getLazyStringLiteralHelper(
+ CORINFO_MODULE_HANDLE handle)
+{
+ API_ENTER(getLazyStringLiteralHelper);
+ CorInfoHelpFunc temp = wrapHnd->getLazyStringLiteralHelper(handle);
+ API_LEAVE(getLazyStringLiteralHelper);
+ return temp;
+}
+
+CORINFO_MODULE_HANDLE WrapICorJitInfo::embedModuleHandle(
+ CORINFO_MODULE_HANDLE handle,
+ void **ppIndirection)
+{
+ API_ENTER(embedModuleHandle);
+ CORINFO_MODULE_HANDLE temp = wrapHnd->embedModuleHandle(handle, ppIndirection);
+ API_LEAVE(embedModuleHandle);
+ return temp;
+}
+
+CORINFO_CLASS_HANDLE WrapICorJitInfo::embedClassHandle(
+ CORINFO_CLASS_HANDLE handle,
+ void **ppIndirection)
+{
+ API_ENTER(embedClassHandle);
+ CORINFO_CLASS_HANDLE temp = wrapHnd->embedClassHandle(handle, ppIndirection);
+ API_LEAVE(embedClassHandle);
+ return temp;
+}
+
+CORINFO_METHOD_HANDLE WrapICorJitInfo::embedMethodHandle(
+ CORINFO_METHOD_HANDLE handle,
+ void **ppIndirection)
+{
+ API_ENTER(embedMethodHandle);
+ CORINFO_METHOD_HANDLE temp = wrapHnd->embedMethodHandle(handle, ppIndirection);
+ API_LEAVE(embedMethodHandle);
+ return temp;
+}
+
+CORINFO_FIELD_HANDLE WrapICorJitInfo::embedFieldHandle(
+ CORINFO_FIELD_HANDLE handle,
+ void **ppIndirection)
+{
+ API_ENTER(embedFieldHandle);
+ CORINFO_FIELD_HANDLE temp = wrapHnd->embedFieldHandle(handle, ppIndirection);
+ API_LEAVE(embedFieldHandle);
+ return temp;
+}
+
+void WrapICorJitInfo::embedGenericHandle(
+ CORINFO_RESOLVED_TOKEN * pResolvedToken,
+ BOOL fEmbedParent,
+ CORINFO_GENERICHANDLE_RESULT * pResult)
+{
+ API_ENTER(embedGenericHandle);
+ wrapHnd->embedGenericHandle(pResolvedToken, fEmbedParent, pResult);
+ API_LEAVE(embedGenericHandle);
+}
+
+CORINFO_LOOKUP_KIND WrapICorJitInfo::getLocationOfThisType(
+ CORINFO_METHOD_HANDLE context)
+{
+ API_ENTER(getLocationOfThisType);
+ CORINFO_LOOKUP_KIND temp = wrapHnd->getLocationOfThisType(context);
+ API_LEAVE(getLocationOfThisType);
+ return temp;
+}
+
+void* WrapICorJitInfo::getPInvokeUnmanagedTarget(
+ CORINFO_METHOD_HANDLE method,
+ void **ppIndirection)
+{
+ API_ENTER(getPInvokeUnmanagedTarget);
+ void *result = wrapHnd->getPInvokeUnmanagedTarget(method, ppIndirection);
+ API_LEAVE(getPInvokeUnmanagedTarget);
+ return result;
+}
+
+void* WrapICorJitInfo::getAddressOfPInvokeFixup(
+ CORINFO_METHOD_HANDLE method,
+ void **ppIndirection)
+{
+ API_ENTER(getAddressOfPInvokeFixup);
+ void *temp = wrapHnd->getAddressOfPInvokeFixup(method, ppIndirection);
+ API_LEAVE(getAddressOfPInvokeFixup);
+ return temp;
+}
+
+#if COR_JIT_EE_VERSION > 460
+
+void WrapICorJitInfo::getAddressOfPInvokeTarget(
+ CORINFO_METHOD_HANDLE method,
+ CORINFO_CONST_LOOKUP *pLookup)
+{
+ API_ENTER(getAddressOfPInvokeTarget);
+ wrapHnd->getAddressOfPInvokeTarget(method, pLookup);
+ API_LEAVE(getAddressOfPInvokeTarget);
+}
+
+#endif
+
+LPVOID WrapICorJitInfo::GetCookieForPInvokeCalliSig(
+ CORINFO_SIG_INFO* szMetaSig,
+ void ** ppIndirection)
+{
+ API_ENTER(GetCookieForPInvokeCalliSig);
+ LPVOID temp = wrapHnd->GetCookieForPInvokeCalliSig(szMetaSig, ppIndirection);
+ API_LEAVE(GetCookieForPInvokeCalliSig);
+ return temp;
+}
+
+bool WrapICorJitInfo::canGetCookieForPInvokeCalliSig(
+ CORINFO_SIG_INFO* szMetaSig)
+{
+ API_ENTER(canGetCookieForPInvokeCalliSig);
+ bool temp = wrapHnd->canGetCookieForPInvokeCalliSig(szMetaSig);
+ API_LEAVE(canGetCookieForPInvokeCalliSig);
+ return temp;
+}
+
+CORINFO_JUST_MY_CODE_HANDLE WrapICorJitInfo::getJustMyCodeHandle(
+ CORINFO_METHOD_HANDLE method,
+ CORINFO_JUST_MY_CODE_HANDLE**ppIndirection)
+{
+ API_ENTER(getJustMyCodeHandle);
+ CORINFO_JUST_MY_CODE_HANDLE temp = wrapHnd->getJustMyCodeHandle(method, ppIndirection);
+ API_LEAVE(getJustMyCodeHandle);
+ return temp;
+}
+
+void WrapICorJitInfo::GetProfilingHandle(
+ BOOL *pbHookFunction,
+ void **pProfilerHandle,
+ BOOL *pbIndirectedHandles)
+{
+ API_ENTER(GetProfilingHandle);
+ wrapHnd->GetProfilingHandle(pbHookFunction, pProfilerHandle, pbIndirectedHandles);
+ API_LEAVE(GetProfilingHandle);
+}
+
+void WrapICorJitInfo::getCallInfo(
+ CORINFO_RESOLVED_TOKEN * pResolvedToken,
+ CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken,
+ CORINFO_METHOD_HANDLE callerHandle,
+ CORINFO_CALLINFO_FLAGS flags,
+ CORINFO_CALL_INFO *pResult)
+{
+ API_ENTER(getCallInfo);
+ wrapHnd->getCallInfo(pResolvedToken, pConstrainedResolvedToken, callerHandle, flags, pResult);
+ API_LEAVE(getCallInfo);
+}
+
+BOOL WrapICorJitInfo::canAccessFamily(CORINFO_METHOD_HANDLE hCaller,
+ CORINFO_CLASS_HANDLE hInstanceType)
+{
+ API_ENTER(canAccessFamily);
+ BOOL temp = wrapHnd->canAccessFamily(hCaller, hInstanceType);
+ API_LEAVE(canAccessFamily);
+ return temp;
+}
+
+BOOL WrapICorJitInfo::isRIDClassDomainID(CORINFO_CLASS_HANDLE cls)
+{
+ API_ENTER(isRIDClassDomainID);
+ BOOL result = wrapHnd->isRIDClassDomainID(cls);
+ API_LEAVE(isRIDClassDomainID);
+ return result;
+}
+
+unsigned WrapICorJitInfo::getClassDomainID(
+ CORINFO_CLASS_HANDLE cls,
+ void **ppIndirection)
+{
+ API_ENTER(getClassDomainID);
+ unsigned temp = wrapHnd->getClassDomainID(cls, ppIndirection);
+ API_LEAVE(getClassDomainID);
+ return temp;
+}
+
+void* WrapICorJitInfo::getFieldAddress(
+ CORINFO_FIELD_HANDLE field,
+ void **ppIndirection)
+{
+ API_ENTER(getFieldAddress);
+ void *temp = wrapHnd->getFieldAddress(field, ppIndirection);
+ API_LEAVE(getFieldAddress);
+ return temp;
+}
+
+CORINFO_VARARGS_HANDLE WrapICorJitInfo::getVarArgsHandle(
+ CORINFO_SIG_INFO *pSig,
+ void **ppIndirection)
+{
+ API_ENTER(getVarArgsHandle);
+ CORINFO_VARARGS_HANDLE temp = wrapHnd->getVarArgsHandle(pSig, ppIndirection);
+ API_LEAVE(getVarArgsHandle);
+ return temp;
+}
+
+bool WrapICorJitInfo::canGetVarArgsHandle(
+ CORINFO_SIG_INFO *pSig)
+{
+ API_ENTER(canGetVarArgsHandle);
+ bool temp = wrapHnd->canGetVarArgsHandle(pSig);
+ API_LEAVE(canGetVarArgsHandle);
+ return temp;
+}
+
+InfoAccessType WrapICorJitInfo::constructStringLiteral(
+ CORINFO_MODULE_HANDLE module,
+ mdToken metaTok,
+ void **ppValue)
+{
+ API_ENTER(constructStringLiteral);
+ InfoAccessType temp = wrapHnd->constructStringLiteral(module, metaTok, ppValue);
+ API_LEAVE(constructStringLiteral);
+ return temp;
+}
+
+InfoAccessType WrapICorJitInfo::emptyStringLiteral(void **ppValue)
+{
+ API_ENTER(emptyStringLiteral);
+ InfoAccessType temp = wrapHnd->emptyStringLiteral(ppValue);
+ API_LEAVE(emptyStringLiteral);
+ return temp;
+}
+
+DWORD WrapICorJitInfo::getFieldThreadLocalStoreID(
+ CORINFO_FIELD_HANDLE field,
+ void **ppIndirection)
+{
+ API_ENTER(getFieldThreadLocalStoreID);
+ DWORD temp = wrapHnd->getFieldThreadLocalStoreID(field, ppIndirection);
+ API_LEAVE(getFieldThreadLocalStoreID);
+ return temp;
+}
+
+void WrapICorJitInfo::setOverride(
+ ICorDynamicInfo *pOverride,
+ CORINFO_METHOD_HANDLE currentMethod)
+{
+ API_ENTER(setOverride);
+ wrapHnd->setOverride(pOverride, currentMethod);
+ API_LEAVE(setOverride);
+}
+
+void WrapICorJitInfo::addActiveDependency(
+ CORINFO_MODULE_HANDLE moduleFrom,
+ CORINFO_MODULE_HANDLE moduleTo)
+{
+ API_ENTER(addActiveDependency);
+ wrapHnd->addActiveDependency(moduleFrom, moduleTo);
+ API_LEAVE(addActiveDependency);
+}
+
+CORINFO_METHOD_HANDLE WrapICorJitInfo::GetDelegateCtor(
+ CORINFO_METHOD_HANDLE methHnd,
+ CORINFO_CLASS_HANDLE clsHnd,
+ CORINFO_METHOD_HANDLE targetMethodHnd,
+ DelegateCtorArgs * pCtorData)
+{
+ API_ENTER(GetDelegateCtor);
+ CORINFO_METHOD_HANDLE temp = wrapHnd->GetDelegateCtor(methHnd, clsHnd, targetMethodHnd, pCtorData);
+ API_LEAVE(GetDelegateCtor);
+ return temp;
+}
+
+void WrapICorJitInfo::MethodCompileComplete(
+ CORINFO_METHOD_HANDLE methHnd)
+{
+ API_ENTER(MethodCompileComplete);
+ wrapHnd->MethodCompileComplete(methHnd);
+ API_LEAVE(MethodCompileComplete);
+}
+
+void* WrapICorJitInfo::getTailCallCopyArgsThunk(
+ CORINFO_SIG_INFO *pSig,
+ CorInfoHelperTailCallSpecialHandling flags)
+{
+ API_ENTER(getTailCallCopyArgsThunk);
+ void *result = wrapHnd->getTailCallCopyArgsThunk(pSig, flags);
+ API_LEAVE(getTailCallCopyArgsThunk);
+ return result;
+}
+
+/*********************************************************************************/
+//
+// ICorJitInfo
+//
+/*********************************************************************************/
+
+#if COR_JIT_EE_VERSION > 460
+
+DWORD WrapICorJitInfo::getJitFlags(CORJIT_FLAGS *jitFlags, DWORD sizeInBytes)
+{
+ API_ENTER(getJitFlags);
+ DWORD result = wrapHnd->getJitFlags(jitFlags, sizeInBytes);
+ API_LEAVE(getJitFlags);
+ return result;
+}
+
+bool WrapICorJitInfo::runWithErrorTrap(void(*function)(void*), void *param)
+{
+ return wrapHnd->runWithErrorTrap(function, param);
+}
+
+#endif
+
+IEEMemoryManager* WrapICorJitInfo::getMemoryManager()
+{
+ API_ENTER(getMemoryManager);
+ IEEMemoryManager * temp = wrapHnd->getMemoryManager();
+ API_LEAVE(getMemoryManager);
+ return temp;
+}
+
+void WrapICorJitInfo::allocMem(
+ ULONG hotCodeSize, /* IN */
+ ULONG coldCodeSize, /* IN */
+ ULONG roDataSize, /* IN */
+ ULONG xcptnsCount, /* IN */
+ CorJitAllocMemFlag flag, /* IN */
+ void ** hotCodeBlock, /* OUT */
+ void ** coldCodeBlock, /* OUT */
+ void ** roDataBlock /* OUT */)
+{
+ API_ENTER(allocMem);
+ wrapHnd->allocMem(hotCodeSize, coldCodeSize, roDataSize, xcptnsCount, flag, hotCodeBlock, coldCodeBlock, roDataBlock);
+ API_LEAVE(allocMem);
+}
+
+void WrapICorJitInfo::reserveUnwindInfo(
+ BOOL isFunclet, /* IN */
+ BOOL isColdCode, /* IN */
+ ULONG unwindSize /* IN */)
+{
+ API_ENTER(reserveUnwindInfo);
+ wrapHnd->reserveUnwindInfo(isFunclet, isColdCode, unwindSize);
+ API_LEAVE(reserveUnwindInfo);
+}
+
+void WrapICorJitInfo::allocUnwindInfo(
+ BYTE * pHotCode, /* IN */
+ BYTE * pColdCode, /* IN */
+ ULONG startOffset, /* IN */
+ ULONG endOffset, /* IN */
+ ULONG unwindSize, /* IN */
+ BYTE * pUnwindBlock, /* IN */
+ CorJitFuncKind funcKind /* IN */)
+{
+ API_ENTER(allocUnwindInfo);
+ wrapHnd->allocUnwindInfo(pHotCode, pColdCode, startOffset, endOffset, unwindSize, pUnwindBlock, funcKind);
+ API_LEAVE(allocUnwindInfo);
+}
+
+void *WrapICorJitInfo::allocGCInfo(size_t size /* IN */)
+{
+ API_ENTER(allocGCInfo);
+ void *temp = wrapHnd->allocGCInfo(size);
+ API_LEAVE(allocGCInfo);
+ return temp;
+}
+
+void WrapICorJitInfo::yieldExecution()
+{
+ API_ENTER(yieldExecution); //Nothing to record
+ wrapHnd->yieldExecution();
+ API_LEAVE(yieldExecution); //Nothing to recor)
+}
+
+void WrapICorJitInfo::setEHcount(unsigned cEH /* IN */)
+{
+ API_ENTER(setEHcount);
+ wrapHnd->setEHcount(cEH);
+ API_LEAVE(setEHcount);
+}
+
+void WrapICorJitInfo::setEHinfo(
+ unsigned EHnumber, /* IN */
+ const CORINFO_EH_CLAUSE *clause /* IN */)
+{
+ API_ENTER(setEHinfo);
+ wrapHnd->setEHinfo(EHnumber, clause);
+ API_LEAVE(setEHinfo);
+}
+
+BOOL WrapICorJitInfo::logMsg(unsigned level, const char* fmt, va_list args)
+{
+ API_ENTER(logMsg);
+ BOOL result = wrapHnd->logMsg(level, fmt, args);
+ API_LEAVE(logMsg);
+ return result;
+}
+
+int WrapICorJitInfo::doAssert(const char* szFile, int iLine, const char* szExpr)
+{
+ API_ENTER(doAssert);
+ int result = wrapHnd->doAssert(szFile, iLine, szExpr);
+ API_LEAVE(doAssert);
+ return result;
+}
+
+void WrapICorJitInfo::reportFatalError(CorJitResult result)
+{
+ API_ENTER(reportFatalError);
+ wrapHnd->reportFatalError(result);
+ API_LEAVE(reportFatalError);
+}
+
+HRESULT WrapICorJitInfo::allocBBProfileBuffer(
+ ULONG count,
+ ProfileBuffer **profileBuffer)
+{
+ API_ENTER(allocBBProfileBuffer);
+ HRESULT result = wrapHnd->allocBBProfileBuffer(count, profileBuffer);
+ API_LEAVE(allocBBProfileBuffer);
+ return result;
+}
+
+HRESULT WrapICorJitInfo::getBBProfileData(
+ CORINFO_METHOD_HANDLE ftnHnd,
+ ULONG *count,
+ ProfileBuffer **profileBuffer,
+ ULONG *numRuns)
+{
+ API_ENTER(getBBProfileData);
+ HRESULT temp = wrapHnd->getBBProfileData(ftnHnd, count, profileBuffer, numRuns);
+ API_LEAVE(getBBProfileData);
+ return temp;
+}
+
+void WrapICorJitInfo::recordCallSite(
+ ULONG instrOffset, /* IN */
+ CORINFO_SIG_INFO * callSig, /* IN */
+ CORINFO_METHOD_HANDLE methodHandle /* IN */)
+{
+ API_ENTER(recordCallSite);
+ wrapHnd->recordCallSite(instrOffset, callSig, methodHandle);
+ API_LEAVE(recordCallSite);
+}
+
+void WrapICorJitInfo::recordRelocation(
+ void *location, /* IN */
+ void *target, /* IN */
+ WORD fRelocType, /* IN */
+ WORD slotNum, /* IN */
+ INT32 addlDelta /* IN */)
+{
+ API_ENTER(recordRelocation);
+ wrapHnd->recordRelocation(location, target, fRelocType, slotNum, addlDelta);
+ API_LEAVE(recordRelocation);
+}
+
+WORD WrapICorJitInfo::getRelocTypeHint(void *target)
+{
+ API_ENTER(getRelocTypeHint);
+ WORD result = wrapHnd->getRelocTypeHint(target);
+ API_LEAVE(getRelocTypeHint);
+ return result;
+}
+
+void WrapICorJitInfo::getModuleNativeEntryPointRange(
+ void **pStart, /* OUT */
+ void **pEnd /* OUT */)
+{
+ API_ENTER(getModuleNativeEntryPointRange);
+ wrapHnd->getModuleNativeEntryPointRange(pStart, pEnd);
+ API_LEAVE(getModuleNativeEntryPointRange);
+}
+
+DWORD WrapICorJitInfo::getExpectedTargetArchitecture()
+{
+ API_ENTER(getExpectedTargetArchitecture);
+ DWORD result = wrapHnd->getExpectedTargetArchitecture();
+ API_LEAVE(getExpectedTargetArchitecture);
+ return result;
+}
+
+/**********************************************************************************/
+// clang-format on
+/**********************************************************************************/
AssemblyNamesList2* Compiler::s_pAltJitExcludeAssembliesList = nullptr;
#endif // ALT_JIT
+/*****************************************************************************
+ *
+ * Little helpers to grab the current cycle counter value; this is done
+ * differently based on target architecture, host toolchain, etc. The
+ * main thing is to keep the overhead absolutely minimal; in fact, on
+ * x86/x64 we use RDTSC even though it's not thread-safe; GetThreadCycles
+ * (which is monotonous) is just too expensive.
+ */
+#ifdef FEATURE_JIT_METHOD_PERF
+
+#if defined(_HOST_X86_) || defined(_HOST_AMD64_)
+
+#if defined(_MSC_VER)
+
+#include <intrin.h>
+inline bool _our_GetThreadCycles(unsigned __int64* cycleOut)
+{
+ *cycleOut = __rdtsc();
+ return true;
+}
+
+#elif defined(__clang__)
+
+inline bool _our_GetThreadCycles(unsigned __int64* cycleOut)
+{
+ uint64_t cycles;
+ asm volatile("rdtsc" : "=A"(cycles));
+ *cycleOut = cycles;
+ return true;
+}
+
+#else // neither _MSC_VER nor __clang__
+
+// The following *might* work - might as well try.
+#define _our_GetThreadCycles(cp) GetThreadCycles(cp)
+
+#endif
+
+#elif defined(_HOST_ARM_) || defined(_HOST_ARM64_)
+
+// If this doesn't work please see ../gc/gc.cpp for additional ARM
+// info (and possible solutions).
+#define _our_GetThreadCycles(cp) GetThreadCycles(cp)
+
+#else // not x86/x64 and not ARM
+
+// Don't know what this target is, but let's give it a try; if
+// someone really wants to make this work, please add the right
+// code here.
+#define _our_GetThreadCycles(cp) GetThreadCycles(cp)
+
+#endif // which host OS
+
+#endif // FEATURE_JIT_METHOD_PERF
/*****************************************************************************/
inline unsigned getCurTime()
{
{
/* Quit inlining if fgImport() failed for any reason. */
- if (compDonotInline())
+ if (!compDonotInline())
{
- return;
+ /* Filter out unimported BBs */
+
+ fgRemoveEmptyBlocks();
}
- /* Filter out unimported BBs */
+ EndPhase(PHASE_POST_IMPORT);
- fgRemoveEmptyBlocks();
+#ifdef FEATURE_JIT_METHOD_PERF
+ if (pCompJitTimer != nullptr)
+ {
+#if MEASURE_CLRAPI_CALLS
+ EndPhase(PHASE_CLR_API);
+#endif
+ pCompJitTimer->Terminate(this, CompTimeSummaryInfo::s_compTimeSummary, false);
+ }
+#endif
return;
}
#ifdef FEATURE_JIT_METHOD_PERF
if (pCompJitTimer)
{
- pCompJitTimer->Terminate(this, CompTimeSummaryInfo::s_compTimeSummary);
+#if MEASURE_CLRAPI_CALLS
+ EndPhase(PHASE_CLR_API);
+#endif
+ pCompJitTimer->Terminate(this, CompTimeSummaryInfo::s_compTimeSummary, true);
}
#endif
#ifdef FEATURE_JIT_METHOD_PERF
static bool checkedForJitTimeLog = false;
+ pCompJitTimer = nullptr;
+
if (!checkedForJitTimeLog)
{
// Call into VM to get the config strings. FEATURE_JIT_METHOD_PERF is enabled for
{
pCompJitTimer = JitTimer::Create(this, methodInfo->ILCodeSize);
}
- else
- {
- pCompJitTimer = nullptr;
- }
#endif // FEATURE_JIT_METHOD_PERF
#ifdef DEBUG
/*****************************************************************************/
+#if MEASURE_CLRAPI_CALLS
+
+struct WrapICorJitInfo : public ICorJitInfo
+{
+ //------------------------------------------------------------------------
+ // WrapICorJitInfo::makeOne: allocate an instance of WrapICorJitInfo
+ //
+ // Arguments:
+ // alloc - the allocator to get memory from for the instance
+ // compile - the compiler instance
+ // compHndRef - the ICorJitInfo handle from the EE; the caller's
+ // copy may be replaced with a "wrapper" instance
+ //
+ // Return Value:
+ // If the config flags indicate that ICorJitInfo should be wrapped,
+ // we return the "wrapper" instance; otherwise we return "nullptr".
+
+ static WrapICorJitInfo* makeOne(ArenaAllocator* alloc, Compiler* compiler, COMP_HANDLE& compHndRef /* INOUT */)
+ {
+ WrapICorJitInfo* wrap = nullptr;
+
+ if (JitConfig.JitEECallTimingInfo() != 0)
+ {
+ // It's too early to use the default allocator, so we do this
+ // in two steps to be safe (the constructor doesn't need to do
+ // anything except fill in the vtable pointer, so we let the
+ // compiler do it).
+ void* inst = alloc->allocateMemory(roundUp(sizeof(WrapICorJitInfo)));
+ if (inst != nullptr)
+ {
+ // If you get a build error here due to 'WrapICorJitInfo' being
+ // an abstract class, it's very likely that the wrapper bodies
+ // in ICorJitInfo_API_wrapper.hpp are no longer in sync with
+ // the EE interface; please be kind and update the header file.
+ wrap = new (inst, jitstd::placement_t()) WrapICorJitInfo();
+
+ wrap->wrapComp = compiler;
+
+ // Save the real handle and replace it with our wrapped version.
+ wrap->wrapHnd = compHndRef;
+ compHndRef = wrap;
+ }
+ }
+
+ return wrap;
+ }
+
+private:
+ Compiler* wrapComp;
+ COMP_HANDLE wrapHnd; // the "real thing"
+
+public:
+#include "ICorJitInfo_API_wrapper.hpp"
+};
+
+#endif // MEASURE_CLRAPI_CALLS
+
+/*****************************************************************************/
+
// Compile a single method
int jitNativeCode(CORINFO_METHOD_HANDLE methodHnd,
ArenaAllocator* pAlloc = nullptr;
ArenaAllocator alloc;
+#if MEASURE_CLRAPI_CALLS
+ WrapICorJitInfo* wrapCLR = nullptr;
+#endif
+
if (inlineInfo)
{
// Use inliner's memory allocator when compiling the inlinee.
ULONG* methodCodeSize;
CORJIT_FLAGS* compileFlags;
InlineInfo* inlineInfo;
+#if MEASURE_CLRAPI_CALLS
+ WrapICorJitInfo* wrapCLR;
+#endif
int result;
} param;
param.methodCodeSize = methodCodeSize;
param.compileFlags = compileFlags;
param.inlineInfo = inlineInfo;
- param.result = result;
+#if MEASURE_CLRAPI_CALLS
+ param.wrapCLR = nullptr;
+#endif
+ param.result = result;
setErrorTrap(compHnd, Param*, pParamOuter, ¶m)
{
pParam->pComp = (Compiler*)pParam->pAlloc->allocateMemory(roundUp(sizeof(*pParam->pComp)));
}
+#if MEASURE_CLRAPI_CALLS
+ pParam->wrapCLR = WrapICorJitInfo::makeOne(pParam->pAlloc, pParam->pComp, pParam->compHnd);
+#endif
+
// push this compiler on the stack (TLS)
pParam->pComp->prevCompiler = JitTls::GetCompiler();
JitTls::SetCompiler(pParam->pComp);
// Static variables
CritSecObject CompTimeSummaryInfo::s_compTimeSummaryLock;
CompTimeSummaryInfo CompTimeSummaryInfo::s_compTimeSummary;
+#if MEASURE_CLRAPI_CALLS
+double JitTimer::s_cyclesPerSec = CycleTimer::CyclesPerSecond();
+#endif
#endif // FEATURE_JIT_METHOD_PERF
#if defined(FEATURE_JIT_METHOD_PERF) || DUMP_FLOWGRAPHS || defined(FEATURE_TRACELOGGING)
};
CompTimeInfo::CompTimeInfo(unsigned byteCodeBytes)
- : m_byteCodeBytes(byteCodeBytes), m_totalCycles(0), m_parentPhaseEndSlop(0), m_timerFailure(false)
+ : m_byteCodeBytes(byteCodeBytes)
+ , m_totalCycles(0)
+ , m_parentPhaseEndSlop(0)
+ , m_timerFailure(false)
+#if MEASURE_CLRAPI_CALLS
+ , m_allClrAPIcalls(0)
+ , m_allClrAPIcycles(0)
+#endif
{
for (int i = 0; i < PHASE_NUMBER_OF; i++)
{
m_invokesByPhase[i] = 0;
m_cyclesByPhase[i] = 0;
+#if MEASURE_CLRAPI_CALLS
+ m_CLRinvokesByPhase[i] = 0;
+ m_CLRcyclesByPhase[i] = 0;
+#endif
+ }
+
+#if MEASURE_CLRAPI_CALLS
+ assert(ARRAYSIZE(m_perClrAPIcalls) == API_ICorJitInfo_Names::API_COUNT);
+ assert(ARRAYSIZE(m_perClrAPIcycles) == API_ICorJitInfo_Names::API_COUNT);
+ assert(ARRAYSIZE(m_maxClrAPIcycles) == API_ICorJitInfo_Names::API_COUNT);
+ for (int i = 0; i < API_ICorJitInfo_Names::API_COUNT; i++)
+ {
+ m_perClrAPIcalls[i] = 0;
+ m_perClrAPIcycles[i] = 0;
+ m_maxClrAPIcycles[i] = 0;
}
+#endif
}
bool CompTimeSummaryInfo::IncludedInFilteredData(CompTimeInfo& info)
return false; // info.m_byteCodeBytes < 10;
}
-void CompTimeSummaryInfo::AddInfo(CompTimeInfo& info)
+//------------------------------------------------------------------------
+// CompTimeSummaryInfo::AddInfo: Record timing info from one compile.
+//
+// Arguments:
+// info - The timing information to record.
+// includePhases - If "true", the per-phase info in "info" is valid,
+// which means that a "normal" compile has ended; if
+// the value is "false" we are recording the results
+// of a partial compile (typically an import-only run
+// on behalf of the inliner) in which case the phase
+// info is not valid and so we only record EE call
+// overhead.
+void CompTimeSummaryInfo::AddInfo(CompTimeInfo& info, bool includePhases)
{
if (info.m_timerFailure)
{
}
CritSecHolder timeLock(s_compTimeSummaryLock);
- m_numMethods++;
- bool includeInFiltered = IncludedInFilteredData(info);
+ if (includePhases)
+ {
+ bool includeInFiltered = IncludedInFilteredData(info);
- // Update the totals and maxima.
- m_total.m_byteCodeBytes += info.m_byteCodeBytes;
- m_maximum.m_byteCodeBytes = max(m_maximum.m_byteCodeBytes, info.m_byteCodeBytes);
- m_total.m_totalCycles += info.m_totalCycles;
- m_maximum.m_totalCycles = max(m_maximum.m_totalCycles, info.m_totalCycles);
+ m_numMethods++;
- if (includeInFiltered)
- {
- m_numFilteredMethods++;
- m_filtered.m_byteCodeBytes += info.m_byteCodeBytes;
- m_filtered.m_totalCycles += info.m_totalCycles;
- m_filtered.m_parentPhaseEndSlop += info.m_parentPhaseEndSlop;
- }
+ // Update the totals and maxima.
+ m_total.m_byteCodeBytes += info.m_byteCodeBytes;
+ m_maximum.m_byteCodeBytes = max(m_maximum.m_byteCodeBytes, info.m_byteCodeBytes);
+ m_total.m_totalCycles += info.m_totalCycles;
+ m_maximum.m_totalCycles = max(m_maximum.m_totalCycles, info.m_totalCycles);
+
+#if MEASURE_CLRAPI_CALLS
+ // Update the CLR-API values.
+ m_total.m_allClrAPIcalls += info.m_allClrAPIcalls;
+ m_maximum.m_allClrAPIcalls = max(m_maximum.m_allClrAPIcalls, info.m_allClrAPIcalls);
+ m_total.m_allClrAPIcycles += info.m_allClrAPIcycles;
+ m_maximum.m_allClrAPIcycles = max(m_maximum.m_allClrAPIcycles, info.m_allClrAPIcycles);
+#endif
- for (int i = 0; i < PHASE_NUMBER_OF; i++)
- {
- m_total.m_invokesByPhase[i] += info.m_invokesByPhase[i];
- m_total.m_cyclesByPhase[i] += info.m_cyclesByPhase[i];
if (includeInFiltered)
{
- m_filtered.m_invokesByPhase[i] += info.m_invokesByPhase[i];
- m_filtered.m_cyclesByPhase[i] += info.m_cyclesByPhase[i];
+ m_numFilteredMethods++;
+ m_filtered.m_byteCodeBytes += info.m_byteCodeBytes;
+ m_filtered.m_totalCycles += info.m_totalCycles;
+ m_filtered.m_parentPhaseEndSlop += info.m_parentPhaseEndSlop;
+ }
+
+ for (int i = 0; i < PHASE_NUMBER_OF; i++)
+ {
+ m_total.m_invokesByPhase[i] += info.m_invokesByPhase[i];
+ m_total.m_cyclesByPhase[i] += info.m_cyclesByPhase[i];
+
+#if MEASURE_CLRAPI_CALLS
+ m_total.m_CLRinvokesByPhase[i] += info.m_CLRinvokesByPhase[i];
+ m_total.m_CLRcyclesByPhase[i] += info.m_CLRcyclesByPhase[i];
+#endif
+
+ if (includeInFiltered)
+ {
+ m_filtered.m_invokesByPhase[i] += info.m_invokesByPhase[i];
+ m_filtered.m_cyclesByPhase[i] += info.m_cyclesByPhase[i];
+#if MEASURE_CLRAPI_CALLS
+ m_filtered.m_CLRinvokesByPhase[i] += info.m_CLRinvokesByPhase[i];
+ m_filtered.m_CLRcyclesByPhase[i] += info.m_CLRcyclesByPhase[i];
+#endif
+ }
+ m_maximum.m_cyclesByPhase[i] = max(m_maximum.m_cyclesByPhase[i], info.m_cyclesByPhase[i]);
+
+#if MEASURE_CLRAPI_CALLS
+ m_maximum.m_CLRcyclesByPhase[i] = max(m_maximum.m_CLRcyclesByPhase[i], info.m_CLRcyclesByPhase[i]);
+#endif
}
- m_maximum.m_cyclesByPhase[i] = max(m_maximum.m_cyclesByPhase[i], info.m_cyclesByPhase[i]);
+ m_total.m_parentPhaseEndSlop += info.m_parentPhaseEndSlop;
+ m_maximum.m_parentPhaseEndSlop = max(m_maximum.m_parentPhaseEndSlop, info.m_parentPhaseEndSlop);
}
- m_total.m_parentPhaseEndSlop += info.m_parentPhaseEndSlop;
- m_maximum.m_parentPhaseEndSlop = max(m_maximum.m_parentPhaseEndSlop, info.m_parentPhaseEndSlop);
+#if MEASURE_CLRAPI_CALLS
+ else
+ {
+ m_totMethods++;
+
+ // Update the "global" CLR-API values.
+ m_total.m_allClrAPIcalls += info.m_allClrAPIcalls;
+ m_maximum.m_allClrAPIcalls = max(m_maximum.m_allClrAPIcalls, info.m_allClrAPIcalls);
+ m_total.m_allClrAPIcycles += info.m_allClrAPIcycles;
+ m_maximum.m_allClrAPIcycles = max(m_maximum.m_allClrAPIcycles, info.m_allClrAPIcycles);
+
+ // Update the per-phase CLR-API values.
+ m_total.m_invokesByPhase[PHASE_CLR_API] += info.m_allClrAPIcalls;
+ m_maximum.m_invokesByPhase[PHASE_CLR_API] =
+ max(m_maximum.m_perClrAPIcalls[PHASE_CLR_API], info.m_allClrAPIcalls);
+ m_total.m_cyclesByPhase[PHASE_CLR_API] += info.m_allClrAPIcycles;
+ m_maximum.m_cyclesByPhase[PHASE_CLR_API] =
+ max(m_maximum.m_cyclesByPhase[PHASE_CLR_API], info.m_allClrAPIcycles);
+ }
+
+ for (int i = 0; i < API_ICorJitInfo_Names::API_COUNT; i++)
+ {
+ m_total.m_perClrAPIcalls[i] += info.m_perClrAPIcalls[i];
+ m_maximum.m_perClrAPIcalls[i] = max(m_maximum.m_perClrAPIcalls[i], info.m_perClrAPIcalls[i]);
+
+ m_total.m_perClrAPIcycles[i] += info.m_perClrAPIcycles[i];
+ m_maximum.m_perClrAPIcycles[i] = max(m_maximum.m_perClrAPIcycles[i], info.m_perClrAPIcycles[i]);
+
+ m_maximum.m_maxClrAPIcycles[i] = max(m_maximum.m_maxClrAPIcycles[i], info.m_maxClrAPIcycles[i]);
+ }
+#endif
}
// Static
return;
}
+ bool extraInfo = (JitConfig.JitEECallTimingInfo() != 0);
+ double totTime_ms = 0.0;
+
fprintf(f, "JIT Compilation time report:\n");
fprintf(f, " Compiled %d methods.\n", m_numMethods);
if (m_numMethods != 0)
{
fprintf(f, " Compiled %d bytecodes total (%d max, %8.2f avg).\n", m_total.m_byteCodeBytes,
m_maximum.m_byteCodeBytes, (double)m_total.m_byteCodeBytes / (double)m_numMethods);
- double totTime_ms = ((double)m_total.m_totalCycles / countsPerSec) * 1000.0;
+ totTime_ms = ((double)m_total.m_totalCycles / countsPerSec) * 1000.0;
fprintf(f, " Time: total: %10.3f Mcycles/%10.3f ms\n", ((double)m_total.m_totalCycles / 1000000.0),
totTime_ms);
fprintf(f, " max: %10.3f Mcycles/%10.3f ms\n", ((double)m_maximum.m_totalCycles) / 1000000.0,
fprintf(f, " avg: %10.3f Mcycles/%10.3f ms\n",
((double)m_total.m_totalCycles) / 1000000.0 / (double)m_numMethods, totTime_ms / (double)m_numMethods);
- fprintf(f, " Total time by phases:\n");
- fprintf(f, " PHASE inv/meth Mcycles time (ms) %% of total max (ms)\n");
- fprintf(f, " --------------------------------------------------------------------------------------\n");
+ const char* extraHdr1 = "";
+ const char* extraHdr2 = "";
+#if MEASURE_CLRAPI_CALLS
+ if (extraInfo)
+ {
+ extraHdr1 = " CLRs/meth % in CLR";
+ extraHdr2 = "-----------------------";
+ }
+#endif
+
+ fprintf(f, "\n Total time by phases:\n");
+ fprintf(f, " PHASE inv/meth Mcycles time (ms) %% of total max (ms)%s\n",
+ extraHdr1);
+ fprintf(f, " ---------------------------------------------------------------------------------------%s\n",
+ extraHdr2);
+
// Ensure that at least the names array and the Phases enum have the same number of entries:
assert(sizeof(PhaseNames) / sizeof(const char*) == PHASE_NUMBER_OF);
for (int i = 0; i < PHASE_NUMBER_OF; i++)
{
- double phase_tot_ms = (((double)m_total.m_cyclesByPhase[i]) / countsPerSec) * 1000.0;
- double phase_max_ms = (((double)m_maximum.m_cyclesByPhase[i]) / countsPerSec) * 1000.0;
+ double phase_tot_ms = (((double)m_total.m_cyclesByPhase[i]) / countsPerSec) * 1000.0;
+ double phase_max_ms = (((double)m_maximum.m_cyclesByPhase[i]) / countsPerSec) * 1000.0;
+ double phase_tot_pct = 100.0 * phase_tot_ms / totTime_ms;
+
+#if MEASURE_CLRAPI_CALLS
+ // Skip showing CLR API call info if we didn't collect any
+ if (i == PHASE_CLR_API && !extraInfo)
+ continue;
+#endif
+
// Indent nested phases, according to depth.
int ancPhase = PhaseParent[i];
while (ancPhase != -1)
fprintf(f, " ");
ancPhase = PhaseParent[ancPhase];
}
- fprintf(f, " %-30s %5.2f %10.2f %9.3f %8.2f%% %8.3f\n", PhaseNames[i],
+ fprintf(f, " %-30s %6.2f %10.2f %9.3f %8.2f%% %8.3f", PhaseNames[i],
((double)m_total.m_invokesByPhase[i]) / ((double)m_numMethods),
((double)m_total.m_cyclesByPhase[i]) / 1000000.0, phase_tot_ms, (phase_tot_ms * 100.0 / totTime_ms),
phase_max_ms);
+
+#if MEASURE_CLRAPI_CALLS
+ if (extraInfo && i != PHASE_CLR_API)
+ {
+ double nest_tot_ms = (((double)m_total.m_CLRcyclesByPhase[i]) / countsPerSec) * 1000.0;
+ double nest_percent = nest_tot_ms * 100.0 / totTime_ms;
+ double calls_per_fn = ((double)m_total.m_CLRinvokesByPhase[i]) / ((double)m_numMethods);
+
+ if (nest_percent > 0.1 || calls_per_fn > 10)
+ fprintf(f, " %5.1f %8.2f%%", calls_per_fn, nest_percent);
+ }
+#endif
+ fprintf(f, "\n");
}
// Show slop if it's over a certain percentage of the total
m_filtered.m_parentPhaseEndSlop);
}
}
+
+#if MEASURE_CLRAPI_CALLS
+ if (m_total.m_allClrAPIcalls > 0 && m_total.m_allClrAPIcycles > 0)
+ {
+ fprintf(f, "\n");
+ if (m_totMethods > 0)
+ fprintf(f, " Imported %u methods.\n\n", m_numMethods + m_totMethods);
+
+ fprintf(f, " CLR API # calls total time max time avg time %% "
+ "of total\n");
+ fprintf(f, " -------------------------------------------------------------------------------");
+ fprintf(f, "---------------------\n");
+
+ static const char* APInames[] = {
+#define DEF_CLR_API(name) #name,
+#include "ICorJitInfo_API_names.h"
+ };
+
+ unsigned shownCalls = 0;
+ double shownMillis = 0.0;
+#ifdef DEBUG
+ unsigned checkedCalls = 0;
+ double checkedMillis = 0.0;
+#endif
+
+ for (unsigned pass = 0; pass < 2; pass++)
+ {
+ for (unsigned i = 0; i < API_ICorJitInfo_Names::API_COUNT; i++)
+ {
+ unsigned calls = m_total.m_perClrAPIcalls[i];
+ if (calls == 0)
+ continue;
+
+ unsigned __int64 cycles = m_total.m_perClrAPIcycles[i];
+ double millis = 1000.0 * cycles / countsPerSec;
+
+ // Don't show the small fry to keep the results manageable
+ if (millis < 0.5)
+ {
+ // We always show the following API because it is always called
+ // exactly once for each method and its body is the simplest one
+ // possible (it just returns an integer constant), and therefore
+ // it can be used to measure the overhead of adding the CLR API
+ // timing code. Roughly speaking, on a 3GHz x64 box the overhead
+ // per call should be around 40 ns when using RDTSC, compared to
+ // about 140 ns when using GetThreadCycles() under Windows.
+ if (i != API_ICorJitInfo_Names::API_getExpectedTargetArchitecture)
+ continue;
+ }
+
+ // In the first pass we just compute the totals.
+ if (pass == 0)
+ {
+ shownCalls += m_total.m_perClrAPIcalls[i];
+ shownMillis += millis;
+ continue;
+ }
+
+ unsigned __int32 maxcyc = m_maximum.m_maxClrAPIcycles[i];
+ double max_ms = 1000.0 * maxcyc / countsPerSec;
+
+ fprintf(f, " %-40s", APInames[i]); // API name
+ fprintf(f, " %8u %9.1f ms", calls, millis); // #calls, total time
+ fprintf(f, " %8.1f ms %8.1f ns", max_ms, 1000000.0 * millis / calls); // max, avg time
+ fprintf(f, " %5.1f%%\n", 100.0 * millis / shownMillis); // % of total
+
+#ifdef DEBUG
+ checkedCalls += m_total.m_perClrAPIcalls[i];
+ checkedMillis += millis;
+#endif
+ }
+ }
+
+#ifdef DEBUG
+ assert(checkedCalls == shownCalls);
+ assert(checkedMillis == shownMillis);
+#endif
+
+ if (shownCalls > 0 || shownMillis > 0)
+ {
+ fprintf(f, " -------------------------");
+ fprintf(f, "---------------------------------------------------------------------------\n");
+ fprintf(f, " Total for calls shown above %8u %10.1f ms", shownCalls, shownMillis);
+ if (totTime_ms > 0.0)
+ fprintf(f, " (%4.1lf%% of overall JIT time)", shownMillis * 100.0 / totTime_ms);
+ fprintf(f, "\n");
+ }
+ fprintf(f, "\n");
+ }
+#endif
+
+ fprintf(f, "\n");
}
JitTimer::JitTimer(unsigned byteCodeSize) : m_info(byteCodeSize)
{
+#if MEASURE_CLRAPI_CALLS
+ m_CLRcallInvokes = 0;
+ m_CLRcallCycles = 0;
+#endif
+
#ifdef DEBUG
m_lastPhase = (Phases)-1;
+#if MEASURE_CLRAPI_CALLS
+ m_CLRcallAPInum = -1;
+#endif
#endif
unsigned __int64 threadCurCycles;
- if (GetThreadCycles(&threadCurCycles))
+ if (_our_GetThreadCycles(&threadCurCycles))
{
m_start = threadCurCycles;
m_curPhaseStart = threadCurCycles;
// assert((int)phase > (int)m_lastPhase); // We should end phases in increasing order.
unsigned __int64 threadCurCycles;
- if (GetThreadCycles(&threadCurCycles))
+ if (_our_GetThreadCycles(&threadCurCycles))
{
unsigned __int64 phaseCycles = (threadCurCycles - m_curPhaseStart);
+
// If this is not a leaf phase, the assumption is that the last subphase must have just recently ended.
// Credit the duration to "slop", the total of which should be very small.
if (PhaseHasChildren[phase])
// It is a leaf phase. Credit duration to it.
m_info.m_invokesByPhase[phase]++;
m_info.m_cyclesByPhase[phase] += phaseCycles;
+
+#if MEASURE_CLRAPI_CALLS
+ // Record the CLR API timing info as well.
+ m_info.m_CLRinvokesByPhase[phase] += m_CLRcallInvokes;
+ m_info.m_CLRcyclesByPhase[phase] += m_CLRcallCycles;
+#endif
+
// Credit the phase's ancestors, if any.
int ancPhase = PhaseParent[phase];
while (ancPhase != -1)
m_info.m_cyclesByPhase[ancPhase] += phaseCycles;
ancPhase = PhaseParent[ancPhase];
}
- // Did we just end the last phase?
- if (phase + 1 == PHASE_NUMBER_OF)
+
+#if MEASURE_CLRAPI_CALLS
+ const Phases lastPhase = PHASE_CLR_API;
+#else
+ const Phases lastPhase = PHASE_NUMBER_OF;
+#endif
+ if (phase + 1 == lastPhase)
{
m_info.m_totalCycles = (threadCurCycles - m_start);
}
}
}
}
+
#ifdef DEBUG
m_lastPhase = phase;
#endif
+#if MEASURE_CLRAPI_CALLS
+ m_CLRcallInvokes = 0;
+ m_CLRcallCycles = 0;
+#endif
+}
+
+#if MEASURE_CLRAPI_CALLS
+
+//------------------------------------------------------------------------
+// JitTimer::CLRApiCallEnter: Start the stopwatch for an EE call.
+//
+// Arguments:
+// apix - The API index - an "enum API_ICorJitInfo_Names" value.
+//
+
+void JitTimer::CLRApiCallEnter(unsigned apix)
+{
+ assert(m_CLRcallAPInum == -1); // Nested calls not allowed
+ m_CLRcallAPInum = apix;
+
+ // If we can't get the cycles, we'll just ignore this call
+ if (!_our_GetThreadCycles(&m_CLRcallStart))
+ m_CLRcallStart = 0;
+}
+
+//------------------------------------------------------------------------
+// JitTimer::CLRApiCallLeave: compute / record time spent in an EE call.
+//
+// Arguments:
+// apix - The API's "enum API_ICorJitInfo_Names" value; this value
+// should match the value passed to the most recent call to
+// "CLRApiCallEnter" (i.e. these must come as matched pairs),
+// and they also may not nest.
+//
+
+void JitTimer::CLRApiCallLeave(unsigned apix)
+{
+ // Make sure we're actually inside a measured CLR call.
+ assert(m_CLRcallAPInum != -1);
+ m_CLRcallAPInum = -1;
+
+ // Ignore this one if we don't have a valid starting counter.
+ if (m_CLRcallStart != 0)
+ {
+ if (JitConfig.JitEECallTimingInfo() != 0)
+ {
+ unsigned __int64 threadCurCycles;
+ if (_our_GetThreadCycles(&threadCurCycles))
+ {
+ // Compute the cycles spent in the call.
+ threadCurCycles -= m_CLRcallStart;
+
+ // Add the cycles to the 'phase' and bump its use count.
+ m_info.m_cyclesByPhase[PHASE_CLR_API] += threadCurCycles;
+ m_info.m_invokesByPhase[PHASE_CLR_API] += 1;
+
+ // Add the values to the "per API" info.
+ m_info.m_allClrAPIcycles += threadCurCycles;
+ m_info.m_allClrAPIcalls += 1;
+
+ m_info.m_perClrAPIcalls[apix] += 1;
+ m_info.m_perClrAPIcycles[apix] += threadCurCycles;
+ m_info.m_maxClrAPIcycles[apix] = max(m_info.m_maxClrAPIcycles[apix], (unsigned __int32)threadCurCycles);
+
+ // Subtract the cycles from the enclosing phase by bumping its start time
+ m_curPhaseStart += threadCurCycles;
+
+ // Update the running totals.
+ m_CLRcallInvokes += 1;
+ m_CLRcallCycles += threadCurCycles;
+ }
+ }
+
+ m_CLRcallStart = 0;
+ }
+
+ assert(m_CLRcallAPInum != -1); // No longer in this API call.
+ m_CLRcallAPInum = -1;
}
+#endif // MEASURE_CLRAPI_CALLS
+
CritSecObject JitTimer::s_csvLock;
LPCWSTR Compiler::JitTimeLogCsv()
}
// Completes the timing of the current method, and adds it to "sum".
-void JitTimer::Terminate(Compiler* comp, CompTimeSummaryInfo& sum)
+void JitTimer::Terminate(Compiler* comp, CompTimeSummaryInfo& sum, bool includePhases)
{
-#ifdef DEBUG
- unsigned __int64 totCycles2 = 0;
- for (int i = 0; i < PHASE_NUMBER_OF; i++)
+ if (includePhases)
{
- if (!PhaseHasChildren[i])
- {
- totCycles2 += m_info.m_cyclesByPhase[i];
- }
+ PrintCsvMethodStats(comp);
}
- // We include m_parentPhaseEndSlop in the next phase's time also (we probably shouldn't)
- // totCycles2 += m_info.m_parentPhaseEndSlop;
- assert(totCycles2 == m_info.m_totalCycles);
-#endif
-
- PrintCsvMethodStats(comp);
- sum.AddInfo(m_info);
+ sum.AddInfo(m_info, includePhases);
}
#endif // FEATURE_JIT_METHOD_PERF
extern const char* PhaseEnums[];
extern const LPCWSTR PhaseShortNames[];
+// The following enum provides a simple 1:1 mapping to CLR API's
+enum API_ICorJitInfo_Names
+{
+#define DEF_CLR_API(name) API_##name,
+#include "ICorJitInfo_API_names.h"
+ API_COUNT
+};
+
//---------------------------------------------------------------
// Compilation time.
//
unsigned __int64 m_totalCycles;
unsigned __int64 m_invokesByPhase[PHASE_NUMBER_OF];
unsigned __int64 m_cyclesByPhase[PHASE_NUMBER_OF];
+#if MEASURE_CLRAPI_CALLS
+ unsigned __int64 m_CLRinvokesByPhase[PHASE_NUMBER_OF];
+ unsigned __int64 m_CLRcyclesByPhase[PHASE_NUMBER_OF];
+#endif
// For better documentation, we call EndPhase on
// non-leaf phases. We should also call EndPhase on the
// last leaf subphase; obviously, the elapsed cycles between the EndPhase
unsigned __int64 m_parentPhaseEndSlop;
bool m_timerFailure;
+#if MEASURE_CLRAPI_CALLS
+ // The following measures the time spent inside each individual CLR API call.
+ unsigned m_allClrAPIcalls;
+ unsigned m_perClrAPIcalls[API_ICorJitInfo_Names::API_COUNT];
+ unsigned __int64 m_allClrAPIcycles;
+ unsigned __int64 m_perClrAPIcycles[API_ICorJitInfo_Names::API_COUNT];
+ unsigned __int32 m_maxClrAPIcycles[API_ICorJitInfo_Names::API_COUNT];
+#endif // MEASURE_CLRAPI_CALLS
+
CompTimeInfo(unsigned byteCodeBytes);
#endif
};
#ifdef FEATURE_JIT_METHOD_PERF
+#if MEASURE_CLRAPI_CALLS
+struct WrapICorJitInfo;
+#endif
+
// This class summarizes the JIT time information over the course of a run: the number of methods compiled,
// and the total and maximum timings. (These are instances of the "CompTimeInfo" type described above).
// The operation of adding a single method's timing to the summary may be performed concurrently by several
static CritSecObject s_compTimeSummaryLock;
int m_numMethods;
+ int m_totMethods;
CompTimeInfo m_total;
CompTimeInfo m_maximum;
// This is the unique CompTimeSummaryInfo object for this instance of the runtime.
static CompTimeSummaryInfo s_compTimeSummary;
- CompTimeSummaryInfo() : m_numMethods(0), m_total(0), m_maximum(0), m_numFilteredMethods(0), m_filtered(0)
+ CompTimeSummaryInfo()
+ : m_numMethods(0), m_totMethods(0), m_total(0), m_maximum(0), m_numFilteredMethods(0), m_filtered(0)
{
}
// Assumes that "info" is a completed CompTimeInfo for a compilation; adds it to the summary.
// This is thread safe.
- void AddInfo(CompTimeInfo& info);
+ void AddInfo(CompTimeInfo& info, bool includePhases);
// Print the summary information to "f".
// This is not thread-safe; assumed to be called by only one thread.
{
unsigned __int64 m_start; // Start of the compilation.
unsigned __int64 m_curPhaseStart; // Start of the current phase.
+#if MEASURE_CLRAPI_CALLS
+ unsigned __int64 m_CLRcallStart; // Start of the current CLR API call (if any).
+ unsigned __int64 m_CLRcallInvokes; // CLR API invokes under current outer so far
+ unsigned __int64 m_CLRcallCycles; // CLR API cycles under current outer so far.
+ int m_CLRcallAPInum; // The enum/index of the current CLR API call (or -1).
+ static double s_cyclesPerSec; // Cached for speedier measurements
+#endif
#ifdef DEBUG
Phases m_lastPhase; // The last phase that was completed (or (Phases)-1 to start).
#endif
// Ends the current phase (argument is for a redundant check).
void EndPhase(Phases phase);
+#if MEASURE_CLRAPI_CALLS
+ // Start and end a timed CLR API call.
+ void CLRApiCallEnter(unsigned apix);
+ void CLRApiCallLeave(unsigned apix);
+#endif // MEASURE_CLRAPI_CALLS
+
// Completes the timing of the current method, which is assumed to have "byteCodeBytes" bytes of bytecode,
// and adds it to "sum".
- void Terminate(Compiler* comp, CompTimeSummaryInfo& sum);
+ void Terminate(Compiler* comp, CompTimeSummaryInfo& sum, bool includePhases);
// Attempts to query the cycle counter of the current thread. If successful, returns "true" and sets
// *cycles to the cycle counter value. Otherwise, returns false and sets the "m_timerFailure" flag of
#endif
inline void EndPhase(Phases phase); // Indicate the end of the given phase.
+#if MEASURE_CLRAPI_CALLS
+ // Thin wrappers that call into JitTimer (if present).
+ inline void CLRApiCallEnter(unsigned apix);
+ inline void CLRApiCallLeave(unsigned apix);
+
+public:
+ inline void CLR_API_Enter(API_ICorJitInfo_Names ename);
+ inline void CLR_API_Leave(API_ICorJitInfo_Names ename);
+
+private:
+#endif
+
#if defined(DEBUG) || defined(INLINE_DATA) || defined(FEATURE_CLRSQM)
// These variables are associated with maintaining SQM data about compile time.
unsigned __int64 m_compCyclesAtEndOfInlining; // The thread-virtualized cycle count at the end of the inlining phase
return (fldHnd == FLD_GLOBAL_DS || fldHnd == FLD_GLOBAL_FS);
}
-#if defined(DEBUG) || defined(FEATURE_JIT_METHOD_PERF) || defined(FEATURE_SIMD)
+#if defined(DEBUG) || defined(FEATURE_JIT_METHOD_PERF) || defined(FEATURE_SIMD) || defined(FEATURE_TRACELOGGING)
inline bool Compiler::eeIsNativeMethod(CORINFO_METHOD_HANDLE method)
{
}
/*****************************************************************************/
+#if MEASURE_CLRAPI_CALLS
+
+inline void Compiler::CLRApiCallEnter(unsigned apix)
+{
+ if (pCompJitTimer != nullptr)
+ {
+ pCompJitTimer->CLRApiCallEnter(apix);
+ }
+}
+inline void Compiler::CLRApiCallLeave(unsigned apix)
+{
+ if (pCompJitTimer != nullptr)
+ {
+ pCompJitTimer->CLRApiCallLeave(apix);
+ }
+}
+
+inline void Compiler::CLR_API_Enter(API_ICorJitInfo_Names ename)
+{
+ CLRApiCallEnter(ename);
+}
+
+inline void Compiler::CLR_API_Leave(API_ICorJitInfo_Names ename)
+{
+ CLRApiCallLeave(ename);
+}
+
+#endif // MEASURE_CLRAPI_CALLS
+
+/*****************************************************************************/
bool Compiler::fgExcludeFromSsa(unsigned lclNum)
{
if (opts.MinOpts())
CompPhaseNameMacro(PHASE_GENERATE_CODE, "Generate code", "CODEGEN", false, -1)
CompPhaseNameMacro(PHASE_EMIT_CODE, "Emit code", "EMIT", false, -1)
CompPhaseNameMacro(PHASE_EMIT_GCEH, "Emit GC+EH tables", "EMT-GCEH", false, -1)
+
+#if MEASURE_CLRAPI_CALLS
+// The following is a "pseudo-phase" - it aggregates timing info
+// for calls through ICorJitInfo across all "real" phases.
+CompPhaseNameMacro(PHASE_CLR_API, "CLR API calls", "CLR-API", false, -1)
+#endif
// clang-format on
#undef CompPhaseNameMacro
#define LOOP_HOIST_STATS 0 // You can set this to 1 to get loop hoist stats in retail, as well
#endif
+// Timing calls to clr.dll is only available under certain conditions.
+#ifndef FEATURE_JIT_METHOD_PERF
+#define MEASURE_CLRAPI_CALLS 0 // Can't time these calls without METHOD_PERF.
+#endif
+#ifdef DEBUG
+#define MEASURE_CLRAPI_CALLS 0 // No point in measuring DEBUG code.
+#endif
+#if !defined(_HOST_X86_) && !defined(_HOST_AMD64_)
+#define MEASURE_CLRAPI_CALLS 0 // Cycle counters only hooked up on x86/x64.
+#endif
+#if !defined(_MSC_VER) && !defined(__clang__)
+#define MEASURE_CLRAPI_CALLS 0 // Only know how to do this with VC and Clang.
+#endif
+
+// If none of the above set the flag to 0, it's available.
+#ifndef MEASURE_CLRAPI_CALLS
+#define MEASURE_CLRAPI_CALLS 0 // Set to 1 to measure time in ICorJitInfo calls.
+#endif
+
/*****************************************************************************/
/* Portability Defines */
/*****************************************************************************/
CONFIG_INTEGER(JitInlinePolicyLegacy, W("JitInlinePolicyLegacy"), 0)
CONFIG_INTEGER(JitInlinePolicyModel, W("JitInlinePolicyModel"), 0)
+CONFIG_INTEGER(JitEECallTimingInfo, W("JitEECallTimingInfo"), 0)
+
#undef CONFIG_INTEGER
#undef CONFIG_STRING
#undef CONFIG_METHODSET
#elif defined(_TARGET_ARM_)
#define NATIVE_SYMBOL_READER_DLL W("Microsoft.DiaSymReader.Native.arm.dll")
#elif defined(_TARGET_ARM64_)
-// Use diasymreader until the package has an arm64 version - issue #7360
-//#define NATIVE_SYMBOL_READER_DLL W("Microsoft.DiaSymReader.Native.arm64.dll")
-#define NATIVE_SYMBOL_READER_DLL W("diasymreader.dll")
+#define NATIVE_SYMBOL_READER_DLL W("Microsoft.DiaSymReader.Native.arm64.dll")
#endif
#else
#define NATIVE_SYMBOL_READER_DLL W("diasymreader.dll")
#include "finalizerthread.h"
#include "threadsuspend.h"
#include "disassembler.h"
-#include "gcenv.ee.h"
#ifndef FEATURE_PAL
#include "dwreport.h"
g_pFreeObjectMethodTable->SetBaseSize(ObjSizeOf (ArrayBase));
g_pFreeObjectMethodTable->SetComponentSize(1);
-#ifdef FEATURE_STANDALONE_GC
- IGCToCLR* gcToClr = new (nothrow) GCToEEInterface();
- if (!gcToClr)
- ThrowOutOfMemory();
-#else
- IGCToCLR* gcToClr = nullptr;
-#endif
-
- IGCHeap *pGCHeap = InitializeGarbageCollector(gcToClr);
+ IGCHeap *pGCHeap = InitializeGarbageCollector(nullptr);
g_pGCHeap = pGCHeap;
if (!pGCHeap)
ThrowOutOfMemory();
#include "gcenv.h"
-#ifdef FEATURE_STANDALONE_GC
-#include "gcenv.ee.h"
-#else
-#include "../gc/env/gcenv.ee.h"
-#endif // FEATURE_STANDALONE_GC
-
#include "threadsuspend.h"
#ifdef FEATURE_COMINTEROP
// Destroy the Thread object
threadStubArgs.thread->DecExternalCount(FALSE);
return NULL;
-}
\ No newline at end of file
+}
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-#ifndef _GCENV_EE_H_
-#define _GCENV_EE_H_
-
-#include "gcinterface.h"
-
-#ifdef FEATURE_STANDALONE_GC
-
-class GCToEEInterface : public IGCToCLR {
-public:
- GCToEEInterface() = default;
- ~GCToEEInterface() = default;
-
- void SuspendEE(SUSPEND_REASON reason);
- void RestartEE(bool bFinishedGC);
- void GcScanRoots(promote_func* fn, int condemned, int max_gen, ScanContext* sc);
- void GcStartWork(int condemned, int max_gen);
- void AfterGcScanRoots(int condemned, int max_gen, ScanContext* sc);
- void GcBeforeBGCSweepWork();
- void GcDone(int condemned);
- bool RefCountedHandleCallbacks(Object * pObject);
- void SyncBlockCacheWeakPtrScan(HANDLESCANPROC scanProc, uintptr_t lp1, uintptr_t lp2);
- void SyncBlockCacheDemote(int max_gen);
- void SyncBlockCachePromotionsGranted(int max_gen);
- bool IsPreemptiveGCDisabled(Thread * pThread);
- void EnablePreemptiveGC(Thread * pThread);
- void DisablePreemptiveGC(Thread * pThread);
- gc_alloc_context * GetAllocContext(Thread * pThread);
- bool CatchAtSafePoint(Thread * pThread);
- void GcEnumAllocContexts(enum_alloc_context_func* fn, void* param);
- Thread* CreateBackgroundThread(GCBackgroundThreadFunction threadStart, void* arg);
-};
-
-#endif // FEATURE_STANDALONE_GC
-
-#endif // _GCENV_EE_H_
+#include "../gc/env/gcenv.ee.h"
#include "util.hpp"
+#include "gcenv.ee.h"
#include "gcenv.os.h"
#include "gcenv.interlocked.h"
#include "gcenv.interlocked.inl"
<ExcludeList Include="$(XunitTestBinBase)\GC\Scenarios\muldimjagary\muldimjagary\*">
<Issue>3392</Issue>
</ExcludeList>
- <ExcludeList Include="$(XunitTestBinBase)\GC\Scenarios\DoublinkList\dlstack\*">
- <Issue>6574</Issue>
- </ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)\JIT\Directed\coverage\importer\Desktop\bleref_il_d\bleref_il_d.cmd">
<Issue>2414</Issue>
</ExcludeList>
<!-- The following x86 failures only occur with RyuJIT/x86 -->
<ItemGroup Condition="'$(XunitTestBinBase)' != '' and '$(BuildArch)' == 'x86'">
+ <ExcludeList Include="$(XunitTestBinBase)\GC\Scenarios\DoublinkList\dlstack\*">
+ <Issue>6553</Issue>
+ </ExcludeList>
<ExcludeList Include="$(XunitTestBinBase)\JIT\Regression\CLR-x86-JIT\V1.2-Beta1\b103058\b103058\b103058.cmd">
<Issue>7008</Issue>
</ExcludeList>