From 5f9f37432568b9abd91de39949ae860e9151798e Mon Sep 17 00:00:00 2001 From: Eugene Rozenfeld Date: Thu, 11 Oct 2018 13:03:26 -0700 Subject: JitEE interface additions to support object stack allocation. (#20283) Add two methods to JitEE interface: getHeapClassSize and canAllocateOnStack. Change JITEEVersionIdentifier. --- .../superpmi/superpmi-shared/icorjitinfoimpl.h | 5 ++ src/ToolBox/superpmi/superpmi-shared/lwmlist.h | 2 + .../superpmi/superpmi-shared/methodcontext.cpp | 44 +++++++++++++++ .../superpmi/superpmi-shared/methodcontext.h | 12 +++- .../superpmi-shim-collector/icorjitinfo.cpp | 19 +++++++ .../superpmi/superpmi-shim-counter/icorjitinfo.cpp | 13 +++++ .../superpmi/superpmi-shim-simple/icorjitinfo.cpp | 11 ++++ src/ToolBox/superpmi/superpmi/icorjitinfo.cpp | 13 +++++ src/inc/corinfo.h | 19 +++++-- src/jit/ICorJitInfo_API_names.h | 2 + src/jit/ICorJitInfo_API_wrapper.hpp | 16 ++++++ src/vm/jitinterface.cpp | 66 ++++++++++++++++++++++ src/vm/jitinterface.h | 2 + src/zap/zapinfo.cpp | 10 ++++ src/zap/zapinfo.h | 2 + 15 files changed, 230 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h b/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h index 29c1b44711..e21f72b668 100644 --- a/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h +++ b/src/ToolBox/superpmi/superpmi-shared/icorjitinfoimpl.h @@ -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 diff --git a/src/ToolBox/superpmi/superpmi-shared/lwmlist.h b/src/ToolBox/superpmi/superpmi-shared/lwmlist.h index 779a9b65c8..42ffc01423 100644 --- a/src/ToolBox/superpmi/superpmi-shared/lwmlist.h +++ b/src/ToolBox/superpmi/superpmi-shared/lwmlist.h @@ -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) diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp b/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp index 6ebe9881fb..ea6dbd4953 100644 --- a/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/ToolBox/superpmi/superpmi-shared/methodcontext.cpp @@ -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(); + + 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(); + + 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) diff --git a/src/ToolBox/superpmi/superpmi-shared/methodcontext.h b/src/ToolBox/superpmi/superpmi-shared/methodcontext.h index 0a71c8df68..fa7d699e62 100644 --- a/src/ToolBox/superpmi/superpmi-shared/methodcontext.h +++ b/src/ToolBox/superpmi/superpmi-shared/methodcontext.h @@ -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, diff --git a/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp index 32cc072d68..200152a046 100644 --- a/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/ToolBox/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -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"); diff --git a/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp index 8a3e80ca4c..c2100e245f 100644 --- a/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp +++ b/src/ToolBox/superpmi/superpmi-shim-counter/icorjitinfo.cpp @@ -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"); diff --git a/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp index 90b2fdb628..4ebd09a4f6 100644 --- a/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp +++ b/src/ToolBox/superpmi/superpmi-shim-simple/icorjitinfo.cpp @@ -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); diff --git a/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp b/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp index 3eb5a312a9..ac1abcc38d 100644 --- a/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp +++ b/src/ToolBox/superpmi/superpmi/icorjitinfo.cpp @@ -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"); diff --git a/src/inc/corinfo.h b/src/inc/corinfo.h index 88f8c1b8c2..b7728bf271 100644 --- a/src/inc/corinfo.h +++ b/src/inc/corinfo.h @@ -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 diff --git a/src/jit/ICorJitInfo_API_names.h b/src/jit/ICorJitInfo_API_names.h index c9edd544be..45a1a080ac 100644 --- a/src/jit/ICorJitInfo_API_names.h +++ b/src/jit/ICorJitInfo_API_names.h @@ -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) diff --git a/src/jit/ICorJitInfo_API_wrapper.hpp b/src/jit/ICorJitInfo_API_wrapper.hpp index 9eaeb5d179..970a9b8a30 100644 --- a/src/jit/ICorJitInfo_API_wrapper.hpp +++ b/src/jit/ICorJitInfo_API_wrapper.hpp @@ -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) diff --git a/src/vm/jitinterface.cpp b/src/vm/jitinterface.cpp index 7532f5e9aa..f52009ac3f 100644 --- a/src/vm/jitinterface.cpp +++ b/src/vm/jitinterface.cpp @@ -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 { diff --git a/src/vm/jitinterface.h b/src/vm/jitinterface.h index a4f6576cdf..d99a0ff2ec 100644 --- a/src/vm/jitinterface.h +++ b/src/vm/jitinterface.h @@ -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); diff --git a/src/zap/zapinfo.cpp b/src/zap/zapinfo.cpp index 341e0d82af..486cc18406 100644 --- a/src/zap/zapinfo.cpp +++ b/src/zap/zapinfo.cpp @@ -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); diff --git a/src/zap/zapinfo.h b/src/zap/zapinfo.h index 8b5ad1d4e8..70d6332790 100644 --- a/src/zap/zapinfo.h +++ b/src/zap/zapinfo.h @@ -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); -- cgit v1.2.3