Add option to measure time spent inside calls to the CLR. (#7357)
authorPeter Kukol <pkukol@users.noreply.github.com>
Thu, 29 Sep 2016 01:29:33 +0000 (18:29 -0700)
committerGitHub <noreply@github.com>
Thu, 29 Sep 2016 01:29:33 +0000 (18:29 -0700)
* Add option to measure time spent inside calls to the CLR (off by default).

23 files changed:
src/gc/env/gcenv.ee.h
src/gc/gc.cpp
src/gc/gc.h
src/gc/gccommon.cpp
src/gc/gcenv.ee.standalone.inl [deleted file]
src/gc/gcinterface.ee.h [deleted file]
src/gc/gcinterface.h
src/gc/sample/gcenv.ee.cpp
src/gc/sample/gcenv.h
src/jit/ICorJitInfo_API_names.h [new file with mode: 0644]
src/jit/ICorJitInfo_API_wrapper.hpp [new file with mode: 0644]
src/jit/compiler.cpp
src/jit/compiler.h
src/jit/compiler.hpp
src/jit/compphases.h
src/jit/jit.h
src/jit/jitconfigvalues.h
src/vm/ceeload.h
src/vm/ceemain.cpp
src/vm/gcenv.ee.cpp
src/vm/gcenv.ee.h
src/vm/gcenv.h
tests/issues.targets

index dc6c1d8..f71380e 100644 (file)
@@ -7,11 +7,36 @@
 #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.
 
index 205adee..ea392c2 100644 (file)
@@ -5231,7 +5231,7 @@ void gc_heap::gc_thread_function ()
             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;
@@ -26046,9 +26046,9 @@ gc_heap::suspend_EE ()
     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
 }
 
@@ -26062,7 +26062,7 @@ gc_heap::bgc_suspend_EE ()
     }
     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++)
@@ -26077,7 +26077,7 @@ gc_heap::bgc_suspend_EE ()
     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();
 }
@@ -35204,7 +35204,7 @@ GCHeap::GarbageCollectGeneration (unsigned int gen, gc_reason reason)
 
         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);
index ca9c28d..9c64587 100644 (file)
@@ -15,11 +15,7 @@ Module Name:
 #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
index 3a951cc..f6afc5f 100644 (file)
@@ -22,10 +22,6 @@ SVAL_IMPL_INIT(uint32_t,IGCHeap,maxGeneration,2);
 
 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);
 
@@ -141,6 +137,7 @@ void InitializeHeapType(bool bServerHeap)
 IGCHeap* InitializeGarbageCollector(IGCToCLR* clrToGC)
 {
     LIMITED_METHOD_CONTRACT;
+    UNREFERENCED_PARAMETER(clrToGC);
 
     IGCHeapInternal* heap;
 #ifdef FEATURE_SVR_GC
@@ -151,14 +148,6 @@ IGCHeap* InitializeGarbageCollector(IGCToCLR* clrToGC)
 #endif
 
     g_theGCHeap = heap;
-
-#ifdef FEATURE_STANDALONE_GC
-    assert(clrToGC != nullptr);
-    g_theGCToCLR = clrToGC;
-#else
-    assert(clrToGC == nullptr);
-#endif
-
     return heap;
 }
 
diff --git a/src/gc/gcenv.ee.standalone.inl b/src/gc/gcenv.ee.standalone.inl
deleted file mode 100644 (file)
index 2ecc6fc..0000000
+++ /dev/null
@@ -1,128 +0,0 @@
-// 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__
diff --git a/src/gc/gcinterface.ee.h b/src/gc/gcinterface.ee.h
deleted file mode 100644 (file)
index 36d20c7..0000000
+++ /dev/null
@@ -1,97 +0,0 @@
-// 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_
index f9ff098..e27646c 100644 (file)
@@ -5,37 +5,6 @@
 #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.
@@ -86,6 +55,7 @@ struct segment_info
 
 class Object;
 class IGCHeap;
+class IGCToCLR;
 
 // Initializes the garbage collector. Should only be called
 // once, during EE startup.
index 25d829e..691004d 100644 (file)
@@ -129,7 +129,7 @@ void ThreadStore::AttachCurrentThread()
     g_pThreadList = pThread;
 }
 
-void GCToEEInterface::SuspendEE(SUSPEND_REASON reason)
+void GCToEEInterface::SuspendEE(GCToEEInterface::SUSPEND_REASON reason)
 {
     g_theGCHeap->SetGCInProgress(TRUE);
 
index 94d6939..3f43a3f 100644 (file)
@@ -2,12 +2,6 @@
 // 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
 
diff --git a/src/jit/ICorJitInfo_API_names.h b/src/jit/ICorJitInfo_API_names.h
new file mode 100644 (file)
index 0000000..601afbd
--- /dev/null
@@ -0,0 +1,171 @@
+// 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
diff --git a/src/jit/ICorJitInfo_API_wrapper.hpp b/src/jit/ICorJitInfo_API_wrapper.hpp
new file mode 100644 (file)
index 0000000..4272b27
--- /dev/null
@@ -0,0 +1,1666 @@
+// 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
+/**********************************************************************************/
index 07613e7..4a74930 100644 (file)
@@ -48,6 +48,60 @@ bool                Compiler::s_pAltJitExcludeAssembliesListInitialized = false;
 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()
 {
@@ -4100,14 +4154,24 @@ void Compiler::compCompile(void** methodCodePtr, ULONG* methodCodeSize, CORJIT_F
     {
         /* 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;
     }
@@ -4523,7 +4587,10 @@ void Compiler::compCompile(void** methodCodePtr, ULONG* methodCodeSize, CORJIT_F
 #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
 
@@ -4685,6 +4752,8 @@ int Compiler::compCompile(CORINFO_METHOD_HANDLE methodHnd,
 #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
@@ -4701,10 +4770,6 @@ int Compiler::compCompile(CORINFO_METHOD_HANDLE methodHnd,
     {
         pCompJitTimer = JitTimer::Create(this, methodInfo->ILCodeSize);
     }
-    else
-    {
-        pCompJitTimer = nullptr;
-    }
 #endif // FEATURE_JIT_METHOD_PERF
 
 #ifdef DEBUG
@@ -6056,6 +6121,65 @@ void Compiler::compDispLocalVars()
 
 /*****************************************************************************/
 
+#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,
@@ -6079,6 +6203,10 @@ START:
     ArenaAllocator* pAlloc = nullptr;
     ArenaAllocator  alloc;
 
+#if MEASURE_CLRAPI_CALLS
+    WrapICorJitInfo* wrapCLR = nullptr;
+#endif
+
     if (inlineInfo)
     {
         // Use inliner's memory allocator when compiling the inlinee.
@@ -6116,6 +6244,9 @@ START:
         ULONG*                methodCodeSize;
         CORJIT_FLAGS*         compileFlags;
         InlineInfo*           inlineInfo;
+#if MEASURE_CLRAPI_CALLS
+        WrapICorJitInfo* wrapCLR;
+#endif
 
         int result;
     } param;
@@ -6131,7 +6262,10 @@ START:
     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, &param)
     {
@@ -6158,6 +6292,10 @@ START:
                 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);
@@ -6938,6 +7076,9 @@ void Compiler::compDispCallArgStats(FILE* fout)
 // 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)
@@ -6969,13 +7110,36 @@ int PhaseParent[] = {
 };
 
 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)
@@ -6983,7 +7147,19 @@ 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)
     {
@@ -6991,37 +7167,94 @@ void CompTimeSummaryInfo::AddInfo(CompTimeInfo& info)
     }
 
     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
@@ -7041,13 +7274,16 @@ void CompTimeSummaryInfo::Print(FILE* f)
         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,
@@ -7055,15 +7291,36 @@ void CompTimeSummaryInfo::Print(FILE* f)
         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)
@@ -7071,10 +7328,23 @@ void CompTimeSummaryInfo::Print(FILE* f)
                 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
@@ -7127,16 +7397,116 @@ void CompTimeSummaryInfo::Print(FILE* f)
                     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;
@@ -7150,9 +7520,10 @@ void JitTimer::EndPhase(Phases phase)
     // 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])
@@ -7164,6 +7535,13 @@ void JitTimer::EndPhase(Phases 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)
@@ -7171,8 +7549,13 @@ void JitTimer::EndPhase(Phases phase)
                 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);
             }
@@ -7182,11 +7565,92 @@ void JitTimer::EndPhase(Phases phase)
             }
         }
     }
+
 #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()
@@ -7285,25 +7749,14 @@ void JitTimer::PrintCsvMethodStats(Compiler* comp)
 }
 
 // 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
 
index 5b109e9..4b0ef4e 100644 (file)
@@ -926,6 +926,14 @@ extern const char*   PhaseNames[];
 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.
 //
@@ -949,6 +957,10 @@ struct CompTimeInfo
     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
@@ -960,12 +972,25 @@ struct CompTimeInfo
     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
@@ -977,6 +1002,7 @@ class CompTimeSummaryInfo
     static CritSecObject s_compTimeSummaryLock;
 
     int          m_numMethods;
+    int          m_totMethods;
     CompTimeInfo m_total;
     CompTimeInfo m_maximum;
 
@@ -996,13 +1022,14 @@ public:
     // 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.
@@ -1017,6 +1044,13 @@ class JitTimer
 {
     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
@@ -1045,9 +1079,15 @@ public:
     // 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
@@ -8693,6 +8733,18 @@ private:
 #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
index 904da76..c53bf4c 100644 (file)
@@ -3962,7 +3962,7 @@ inline bool jitStaticFldIsGlobAddr(CORINFO_FIELD_HANDLE fldHnd)
     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)
 {
@@ -4425,6 +4425,36 @@ inline void Compiler::EndPhase(Phases phase)
 }
 
 /*****************************************************************************/
+#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())
index fa3d585..ac1bb63 100644 (file)
@@ -91,6 +91,12 @@ CompPhaseNameMacro(PHASE_LINEAR_SCAN_RESOLVE,    "LSRA resolve",
 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
index d4e40ac..8ef0dcf 100644 (file)
@@ -488,6 +488,25 @@ typedef ptrdiff_t ssize_t;
 #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 */
 /*****************************************************************************/
index 954e863..ae93461 100644 (file)
@@ -261,6 +261,8 @@ CONFIG_STRING(JitInlineReplayFile, W("JitInlineReplayFile"))
 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
index fdb2305..ce2e76e 100644 (file)
@@ -103,9 +103,7 @@ class PersistentInlineTrackingMap;
 #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")
index 6e56e69..1a19e63 100644 (file)
 #include "finalizerthread.h"
 #include "threadsuspend.h"
 #include "disassembler.h"
-#include "gcenv.ee.h"
 
 #ifndef FEATURE_PAL
 #include "dwreport.h"
@@ -3720,15 +3719,7 @@ void InitializeGarbageCollector()
     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();
index 9ceeb34..b294581 100644 (file)
 
 #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
@@ -844,4 +838,4 @@ Thread* GCToEEInterface::CreateBackgroundThread(GCBackgroundThreadFunction threa
     // Destroy the Thread object
     threadStubArgs.thread->DecExternalCount(FALSE);
     return NULL;
-}
\ No newline at end of file
+}
index 6a84b9d..1d6c9bf 100644 (file)
@@ -2,38 +2,4 @@
 // 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"
index bc4f644..08dcc71 100644 (file)
@@ -48,6 +48,7 @@
 
 #include "util.hpp"
 
+#include "gcenv.ee.h"
 #include "gcenv.os.h"
 #include "gcenv.interlocked.h"
 #include "gcenv.interlocked.inl"
index 687c427..ce79761 100644 (file)
@@ -40,9 +40,6 @@
         <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>