JitEE interface additions to support object stack allocation. (#20283)
authorEugene Rozenfeld <erozen@microsoft.com>
Thu, 11 Oct 2018 20:03:26 +0000 (13:03 -0700)
committerGitHub <noreply@github.com>
Thu, 11 Oct 2018 20:03:26 +0000 (13:03 -0700)
Add two methods to JitEE interface: getHeapClassSize and canAllocateOnStack.

Change JITEEVersionIdentifier.

15 files changed:
src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h
src/ToolBox/superpmi/superpmi-shared/lwmlist.h
src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp
src/ToolBox/superpmi/superpmi-shared/methodcontext.h
src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp
src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp
src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp
src/ToolBox/superpmi/superpmi/icorjitinfo.cpp
src/inc/corinfo.h
src/jit/ICorJitInfo_API_names.h
src/jit/ICorJitInfo_API_wrapper.hpp
src/vm/jitinterface.cpp
src/vm/jitinterface.h
src/zap/zapinfo.cpp
src/zap/zapinfo.h

index 29c1b44..e21f72b 100644 (file)
@@ -326,6 +326,11 @@ size_t getClassModuleIdForStatics(CORINFO_CLASS_HANDLE cls, CORINFO_MODULE_HANDL
 // return the number of bytes needed by an instance of the class
 unsigned getClassSize(CORINFO_CLASS_HANDLE cls);
 
+// return the number of bytes needed by an instance of the class allocated on the heap
+unsigned getHeapClassSize(CORINFO_CLASS_HANDLE cls);
+
+BOOL canAllocateOnStack(CORINFO_CLASS_HANDLE cls);
+
 unsigned getClassAlignmentRequirement(CORINFO_CLASS_HANDLE cls, BOOL fDoubleAlignHint = FALSE);
 
 // This is only called for Value classes.  It returns a boolean array
index 779a9b6..42ffc01 100644 (file)
@@ -72,6 +72,8 @@ LWM(GetClassNameFromMetadata, DLD, DD)
 LWM(GetTypeInstantiationArgument, DWORDLONG, DWORDLONG)
 LWM(GetClassNumInstanceFields, DWORDLONG, DWORD)
 LWM(GetClassSize, DWORDLONG, DWORD)
+LWM(GetHeapClassSize, DWORDLONG, DWORD)
+LWM(CanAllocateOnStack, DWORDLONG, DWORD)
 LWM(GetCookieForPInvokeCalliSig, GetCookieForPInvokeCalliSigValue, DLDL)
 LWM(GetDefaultEqualityComparerClass, DWORDLONG, DWORDLONG)
 LWM(GetDelegateCtor, Agnostic_GetDelegateCtorIn, Agnostic_GetDelegateCtorOut)
index 6ebe988..ea6dbd4 100644 (file)
@@ -1722,6 +1722,50 @@ unsigned MethodContext::repGetClassSize(CORINFO_CLASS_HANDLE cls)
     return result;
 }
 
+void MethodContext::recGetHeapClassSize(CORINFO_CLASS_HANDLE cls, unsigned result)
+{
+    if (GetHeapClassSize == nullptr)
+        GetHeapClassSize = new LightWeightMap<DWORDLONG, DWORD>();
+
+    GetHeapClassSize->Add((DWORDLONG)cls, (DWORD)result);
+    DEBUG_REC(dmpGetHeapClassSize((DWORDLONG)cls, (DWORD)result));
+}
+void MethodContext::dmpGetHeapClassSize(DWORDLONG key, DWORD val)
+{
+    printf("GetHeapClassSize key %016llX, value %u", key, val);
+}
+unsigned MethodContext::repGetHeapClassSize(CORINFO_CLASS_HANDLE cls)
+{
+    AssertCodeMsg(GetHeapClassSize != nullptr, EXCEPTIONCODE_MC, "Didn't find %016llX", (DWORDLONG)cls);
+    AssertCodeMsg(GetHeapClassSize->GetIndex((DWORDLONG)cls) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX",
+        (DWORDLONG)cls);
+    unsigned result = (unsigned)GetHeapClassSize->Get((DWORDLONG)cls);
+    DEBUG_REP(dmpGetHeapClassSize((DWORDLONG)cls, (DWORD)result));
+    return result;
+}
+
+void MethodContext::recCanAllocateOnStack(CORINFO_CLASS_HANDLE cls, BOOL result)
+{
+    if (CanAllocateOnStack == nullptr)
+        CanAllocateOnStack = new LightWeightMap<DWORDLONG, DWORD>();
+
+    CanAllocateOnStack->Add((DWORDLONG)cls, (DWORD)result);
+    DEBUG_REC(dmpCanAllocateOnStack((DWORDLONG)cls, (DWORD)result));
+}
+void MethodContext::dmpCanAllocateOnStack(DWORDLONG key, DWORD val)
+{
+    printf("CanAllocateOnStack key %016llX, value %u", key, val);
+}
+BOOL MethodContext::repCanAllocateOnStack(CORINFO_CLASS_HANDLE cls)
+{
+    AssertCodeMsg(CanAllocateOnStack != nullptr, EXCEPTIONCODE_MC, "Didn't find %016llX", (DWORDLONG)cls);
+    AssertCodeMsg(CanAllocateOnStack->GetIndex((DWORDLONG)cls) != -1, EXCEPTIONCODE_MC, "Didn't find %016llX",
+        (DWORDLONG)cls);
+    BOOL result = (BOOL)CanAllocateOnStack->Get((DWORDLONG)cls);
+    DEBUG_REP(dmpCanAllocateOnStack((DWORDLONG)cls, (DWORD)result));
+    return result;
+}
+
 void MethodContext::recGetClassNumInstanceFields(CORINFO_CLASS_HANDLE cls, unsigned result)
 {
     if (GetClassNumInstanceFields == nullptr)
index 0a71c8d..fa7d699 100644 (file)
@@ -696,6 +696,14 @@ public:
     void dmpGetClassSize(DWORDLONG key, DWORD val);
     unsigned repGetClassSize(CORINFO_CLASS_HANDLE cls);
 
+    void recGetHeapClassSize(CORINFO_CLASS_HANDLE cls, unsigned result);
+    void dmpGetHeapClassSize(DWORDLONG key, DWORD val);
+    unsigned repGetHeapClassSize(CORINFO_CLASS_HANDLE cls);
+
+    void recCanAllocateOnStack(CORINFO_CLASS_HANDLE cls, BOOL result);
+    void dmpCanAllocateOnStack(DWORDLONG key, DWORD val);
+    BOOL repCanAllocateOnStack(CORINFO_CLASS_HANDLE cls);
+
     void recGetClassNumInstanceFields(CORINFO_CLASS_HANDLE cls, unsigned result);
     void dmpGetClassNumInstanceFields(DWORDLONG key, DWORD value);
     unsigned repGetClassNumInstanceFields(CORINFO_CLASS_HANDLE cls);
@@ -1309,7 +1317,7 @@ private:
 };
 
 // ********************* Please keep this up-to-date to ease adding more ***************
-// Highest packet number: 168
+// Highest packet number: 171
 // *************************************************************************************
 enum mcPackets
 {
@@ -1378,6 +1386,8 @@ enum mcPackets
     Packet_GetTypeInstantiationArgument                  = 167, // Added 12/4/17
     Packet_GetClassNumInstanceFields                     = 46,
     Packet_GetClassSize                                  = 47,
+    Packet_GetHeapClassSize                              = 170, // Added 10/5/2018
+    Packet_CanAllocateOnStack                            = 171, // Added 10/5/2018
     Packet_GetIntConfigValue                             = 151, // Added 2/12/2015
     Packet_GetStringConfigValue                          = 152, // Added 2/12/2015
     Packet_GetCookieForPInvokeCalliSig                   = 48,
index 32cc072..200152a 100644 (file)
@@ -683,6 +683,25 @@ unsigned interceptor_ICJI::getClassSize(CORINFO_CLASS_HANDLE cls)
     return temp;
 }
 
+// return the number of bytes needed by an instance of the class allocated on the heap
+unsigned interceptor_ICJI::getHeapClassSize(CORINFO_CLASS_HANDLE cls)
+{
+    mc->cr->AddCall("getHeapClassSize");
+    unsigned temp = original_ICorJitInfo->getHeapClassSize(cls);
+    mc->recGetHeapClassSize(cls, temp);
+    return temp;
+}
+
+BOOL interceptor_ICJI::canAllocateOnStack(
+    CORINFO_CLASS_HANDLE cls
+)
+{
+    mc->cr->AddCall("canAllocateOnStack");
+    BOOL temp = original_ICorJitInfo->canAllocateOnStack(cls);
+    mc->recCanAllocateOnStack(cls, temp);
+    return temp;
+}
+
 unsigned interceptor_ICJI::getClassAlignmentRequirement(CORINFO_CLASS_HANDLE cls, BOOL fDoubleAlignHint)
 {
     mc->cr->AddCall("getClassAlignmentRequirement");
index 8a3e80c..c2100e2 100644 (file)
@@ -519,6 +519,19 @@ unsigned interceptor_ICJI::getClassSize(CORINFO_CLASS_HANDLE cls)
     return original_ICorJitInfo->getClassSize(cls);
 }
 
+// return the number of bytes needed by an instance of the class allocated on the heap
+unsigned interceptor_ICJI::getHeapClassSize(CORINFO_CLASS_HANDLE cls)
+{
+    mcs->AddCall("getHeapClassSize");
+    return original_ICorJitInfo->getHeapClassSize(cls);
+}
+
+BOOL interceptor_ICJI::canAllocateOnStack(CORINFO_CLASS_HANDLE cls)
+{
+    mcs->AddCall("canAllocateOnStack");
+    return original_ICorJitInfo->canAllocateOnStack(cls);
+}
+
 unsigned interceptor_ICJI::getClassAlignmentRequirement(CORINFO_CLASS_HANDLE cls, BOOL fDoubleAlignHint)
 {
     mcs->AddCall("getClassAlignmentRequirement");
index 90b2fdb..4ebd09a 100644 (file)
@@ -464,6 +464,17 @@ unsigned interceptor_ICJI::getClassSize(CORINFO_CLASS_HANDLE cls)
     return original_ICorJitInfo->getClassSize(cls);
 }
 
+// return the number of bytes needed by an instance of the class allocated on the heap
+unsigned interceptor_ICJI::getHeapClassSize(CORINFO_CLASS_HANDLE cls)
+{
+    return original_ICorJitInfo->getHeapClassSize(cls);
+}
+
+BOOL interceptor_ICJI::canAllocateOnStack(CORINFO_CLASS_HANDLE cls)
+{
+    return original_ICorJitInfo->canAllocateOnStack(cls);
+}
+
 unsigned interceptor_ICJI::getClassAlignmentRequirement(CORINFO_CLASS_HANDLE cls, BOOL fDoubleAlignHint)
 {
     return original_ICorJitInfo->getClassAlignmentRequirement(cls, fDoubleAlignHint);
index 3eb5a31..ac1abcc 100644 (file)
@@ -577,6 +577,19 @@ unsigned MyICJI::getClassSize(CORINFO_CLASS_HANDLE cls)
     return jitInstance->mc->repGetClassSize(cls);
 }
 
+// return the number of bytes needed by an instance of the class allocated on the heap
+unsigned MyICJI::getHeapClassSize(CORINFO_CLASS_HANDLE cls)
+{
+    jitInstance->mc->cr->AddCall("getHeapClassSize");
+    return jitInstance->mc->repGetHeapClassSize(cls);
+}
+
+BOOL MyICJI::canAllocateOnStack(CORINFO_CLASS_HANDLE cls)
+{
+    jitInstance->mc->cr->AddCall("canAllocateOnStack");
+    return jitInstance->mc->repCanAllocateOnStack(cls);
+}
+
 unsigned MyICJI::getClassAlignmentRequirement(CORINFO_CLASS_HANDLE cls, BOOL fDoubleAlignHint)
 {
     jitInstance->mc->cr->AddCall("getClassAlignmentRequirement");
index 88f8c1b..b7728bf 100644 (file)
@@ -213,11 +213,11 @@ TODO: Talk about initializing strutures before use
     #define SELECTANY extern __declspec(selectany)
 #endif
 
-SELECTANY const GUID JITEEVersionIdentifier = { /* 45aafd4d-1d23-4647-9ce1-cf09a2677ca0 */
-    0x45aafd4d,
-    0x1d23,
-    0x4647,
-    {0x9c, 0xe1, 0xcf, 0x09, 0xa2, 0x67, 0x7c, 0xa0}
+SELECTANY const GUID JITEEVersionIdentifier = { /* 12768bf8-549c-455b-a3df-57a751a81813 */
+    0x12768bf8,
+    0x549c,
+    0x455b,
+    {0xa3, 0xdf, 0x57, 0xa7, 0x51, 0xa8, 0x18, 0x13}
 };
 
 //////////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -2383,6 +2383,15 @@ public:
             CORINFO_CLASS_HANDLE        cls
             ) = 0;
 
+    // return the number of bytes needed by an instance of the class allocated on the heap
+    virtual unsigned getHeapClassSize(
+        CORINFO_CLASS_HANDLE        cls
+    ) = 0;
+
+    virtual BOOL canAllocateOnStack(
+        CORINFO_CLASS_HANDLE cls
+    ) = 0;
+
     virtual unsigned getClassAlignmentRequirement (
             CORINFO_CLASS_HANDLE        cls,
             BOOL                        fDoubleAlignHint = FALSE
index c9edd54..45a1a08 100644 (file)
@@ -51,6 +51,8 @@ DEF_CLR_API(LongLifetimeMalloc)
 DEF_CLR_API(LongLifetimeFree)
 DEF_CLR_API(getClassModuleIdForStatics)
 DEF_CLR_API(getClassSize)
+DEF_CLR_API(getHeapClassSize)
+DEF_CLR_API(canAllocateOnStack)
 DEF_CLR_API(getClassAlignmentRequirement)
 DEF_CLR_API(getClassGClayout)
 DEF_CLR_API(getClassNumInstanceFields)
index 9eaeb5d..970a9b8 100644 (file)
@@ -481,6 +481,22 @@ unsigned WrapICorJitInfo::getClassSize(CORINFO_CLASS_HANDLE        cls)
     return temp;
 }
 
+unsigned WrapICorJitInfo::getHeapClassSize(CORINFO_CLASS_HANDLE     cls)
+{
+    API_ENTER(getHeapClassSize);
+    unsigned temp = wrapHnd->getHeapClassSize(cls);
+    API_LEAVE(getHeapClassSize);
+    return temp;
+}
+
+BOOL WrapICorJitInfo::canAllocateOnStack(CORINFO_CLASS_HANDLE    cls)
+{
+    API_ENTER(canAllocateOnStack);
+    BOOL temp = wrapHnd->canAllocateOnStack(cls);
+    API_LEAVE(canAllocateOnStack);
+    return temp;
+}
+
 unsigned WrapICorJitInfo::getClassAlignmentRequirement(
             CORINFO_CLASS_HANDLE        cls,
             BOOL                        fDoubleAlignHint)
index 7532f5e..f52009a 100644 (file)
@@ -1937,6 +1937,72 @@ CEEInfo::getClassSize(
     return result;
 }
 
+//---------------------------------------------------------------------------------------
+//
+// Get the size of a reference type as allocated on the heap. This includes the size of the fields
+// (and any padding between the fields) and the size of a method table pointer but doesn't include
+// object header size or any padding for minimum size.
+unsigned
+CEEInfo::getHeapClassSize(
+    CORINFO_CLASS_HANDLE clsHnd)
+{
+    CONTRACTL{
+        SO_TOLERANT;
+        NOTHROW;
+        GC_NOTRIGGER;
+        MODE_PREEMPTIVE;
+    } CONTRACTL_END;
+
+    unsigned result = 0;
+
+    JIT_TO_EE_TRANSITION_LEAF();
+
+    TypeHandle VMClsHnd(clsHnd);
+    MethodTable* pMT = VMClsHnd.GetMethodTable();
+    _ASSERTE(pMT);
+    _ASSERTE(!pMT->IsValueType());
+
+    // Add OBJECT_SIZE to account for method table pointer.
+    result = pMT->GetNumInstanceFieldBytes() + OBJECT_SIZE;
+
+    EE_TO_JIT_TRANSITION_LEAF();
+    return result;
+}
+
+//---------------------------------------------------------------------------------------
+//
+// Return TRUE if an object of this type can be allocated on the stack.
+BOOL CEEInfo::canAllocateOnStack(CORINFO_CLASS_HANDLE clsHnd)
+{
+    CONTRACTL{
+        SO_TOLERANT;
+        NOTHROW;
+        GC_NOTRIGGER;
+        MODE_PREEMPTIVE;
+    } CONTRACTL_END;
+
+    BOOL result = FALSE;
+
+    JIT_TO_EE_TRANSITION_LEAF();
+
+    TypeHandle VMClsHnd(clsHnd);
+    MethodTable* pMT = VMClsHnd.GetMethodTable();
+    _ASSERTE(pMT);
+    _ASSERTE(!pMT->IsValueType());
+
+    result = !pMT->HasFinalizer();
+
+#ifdef FEATURE_READYTORUN_COMPILER
+    if (IsReadyToRunCompilation() && !pMT->IsInheritanceChainLayoutFixedInCurrentVersionBubble())
+    {
+        result = false;
+    }
+#endif
+
+    EE_TO_JIT_TRANSITION_LEAF();
+    return result;
+}
+
 unsigned CEEInfo::getClassAlignmentRequirement(CORINFO_CLASS_HANDLE type, BOOL fDoubleAlignHint)
 {
     CONTRACTL {
index a4f6576..d99a0ff 100644 (file)
@@ -491,6 +491,8 @@ public:
     BOOL isStructRequiringStackAllocRetBuf(CORINFO_CLASS_HANDLE cls);
 
     unsigned getClassSize (CORINFO_CLASS_HANDLE cls);
+    unsigned getHeapClassSize(CORINFO_CLASS_HANDLE cls);
+    BOOL canAllocateOnStack(CORINFO_CLASS_HANDLE cls);
     unsigned getClassAlignmentRequirement(CORINFO_CLASS_HANDLE cls, BOOL fDoubleAlignHint);
     static unsigned getClassAlignmentRequirementStatic(TypeHandle clsHnd);
 
index 341e0d8..486cc18 100644 (file)
@@ -3315,6 +3315,16 @@ unsigned ZapInfo::getClassSize(CORINFO_CLASS_HANDLE cls)
     return size;
 }
 
+unsigned ZapInfo::getHeapClassSize(CORINFO_CLASS_HANDLE cls)
+{
+    return m_pEEJitInfo->getHeapClassSize(cls);
+}
+
+BOOL ZapInfo::canAllocateOnStack(CORINFO_CLASS_HANDLE cls)
+{
+    return m_pEEJitInfo->canAllocateOnStack(cls);
+}
+
 unsigned ZapInfo::getClassAlignmentRequirement(CORINFO_CLASS_HANDLE cls, BOOL fDoubleAlignHint)
 {
     return m_pEEJitInfo->getClassAlignmentRequirement(cls, fDoubleAlignHint);
index 8b5ad1d..70d6332 100644 (file)
@@ -529,6 +529,8 @@ public:
     size_t getClassModuleIdForStatics(CORINFO_CLASS_HANDLE cls, CORINFO_MODULE_HANDLE *pModule, void **ppIndirection);
 
     unsigned getClassSize(CORINFO_CLASS_HANDLE cls);
+    unsigned getHeapClassSize(CORINFO_CLASS_HANDLE cls);
+    BOOL canAllocateOnStack(CORINFO_CLASS_HANDLE cls);
     unsigned getClassAlignmentRequirement(CORINFO_CLASS_HANDLE cls, BOOL fDoubleAlignHint);
 
     CORINFO_FIELD_HANDLE getFieldInClass(CORINFO_CLASS_HANDLE clsHnd, INT num);