From 1f1231c36a9b247aaf0111496d3c0a3b3611ef15 Mon Sep 17 00:00:00 2001 From: Egor Bogatov Date: Thu, 22 Sep 2022 18:52:57 +0200 Subject: [PATCH] Allocate RuntimeType objects on Frozen Object Heap (#75573) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Michal Strehovský Co-authored-by: Jan Kotas Co-authored-by: Jakob Botsch Nielsen --- src/coreclr/inc/clrconfigvalues.h | 5 - src/coreclr/inc/corinfo.h | 11 + src/coreclr/inc/crsttypes.h | 9 +- src/coreclr/inc/icorjitinfoimpl_generated.h | 8 + src/coreclr/inc/jiteeversionguid.h | 10 +- src/coreclr/jit/ICorJitInfo_API_names.h | 2 + src/coreclr/jit/ICorJitInfo_API_wrapper.hpp | 20 ++ src/coreclr/jit/assertionprop.cpp | 4 +- src/coreclr/jit/compiler.cpp | 5 + src/coreclr/jit/compiler.h | 12 +- src/coreclr/jit/ee_il_dll.cpp | 49 ++- src/coreclr/jit/emit.cpp | 39 +-- src/coreclr/jit/emitxarch.cpp | 12 - src/coreclr/jit/gentree.cpp | 26 +- src/coreclr/jit/gentree.h | 3 +- src/coreclr/jit/importer.cpp | 6 +- src/coreclr/jit/morph.cpp | 22 +- src/coreclr/jit/optcse.cpp | 2 +- src/coreclr/jit/valuenum.cpp | 3 +- .../tools/Common/JitInterface/CorInfoBase.cs | 311 ++++++++++-------- .../tools/Common/JitInterface/CorInfoImpl.cs | 23 ++ .../ThunkGenerator/ThunkInput.txt | 2 + .../tools/aot/jitinterface/jitinterface.h | 22 ++ .../tools/superpmi/superpmi-shared/lwmlist.h | 2 + .../superpmi-shared/methodcontext.cpp | 84 +++++ .../superpmi/superpmi-shared/methodcontext.h | 10 + .../superpmi-shim-collector/icorjitinfo.cpp | 19 ++ .../superpmi-shim-counter/icorjitinfo.cpp | 16 + .../superpmi-shim-simple/icorjitinfo.cpp | 14 + .../tools/superpmi/superpmi/icorjitinfo.cpp | 16 + src/coreclr/vm/appdomain.cpp | 4 +- src/coreclr/vm/appdomain.hpp | 8 +- src/coreclr/vm/frozenobjectheap.cpp | 14 +- src/coreclr/vm/frozenobjectheap.h | 1 - src/coreclr/vm/jitinterface.cpp | 70 ++++ src/coreclr/vm/methodtable.cpp | 21 +- src/coreclr/vm/methodtable.h | 11 +- src/coreclr/vm/methodtable.inl | 10 +- src/coreclr/vm/typedesc.cpp | 47 +-- src/coreclr/vm/typedesc.h | 70 +++- src/coreclr/vm/typehandle.cpp | 58 ++++ src/coreclr/vm/typehandle.h | 26 ++ src/coreclr/vm/typehandle.inl | 2 + src/coreclr/vm/vars.hpp | 10 +- 44 files changed, 748 insertions(+), 371 deletions(-) diff --git a/src/coreclr/inc/clrconfigvalues.h b/src/coreclr/inc/clrconfigvalues.h index 3f1219dd7daf6..596bb72f3ff46 100644 --- a/src/coreclr/inc/clrconfigvalues.h +++ b/src/coreclr/inc/clrconfigvalues.h @@ -404,11 +404,6 @@ CONFIG_DWORD_INFO(INTERNAL_LoaderHeapCallTracing, W("LoaderHeapCallTracing"), 0, RETAIL_CONFIG_DWORD_INFO(INTERNAL_CodeHeapReserveForJumpStubs, W("CodeHeapReserveForJumpStubs"), 1, "Percentage of code heap to reserve for jump stubs") RETAIL_CONFIG_DWORD_INFO(INTERNAL_BreakOnOutOfMemoryWithinRange, W("BreakOnOutOfMemoryWithinRange"), 0, "Break before out of memory within range exception is thrown") -/// -/// Frozen segments (aka Frozen Object Heap) -/// -RETAIL_CONFIG_DWORD_INFO(INTERNAL_UseFrozenObjectHeap, W("UseFrozenObjectHeap"), 1, "Use frozen object heap for certain types of objects (e.g. string literals) as an optimization.") - /// /// Log /// diff --git a/src/coreclr/inc/corinfo.h b/src/coreclr/inc/corinfo.h index 2be3d438c9327..848e1a53314c8 100644 --- a/src/coreclr/inc/corinfo.h +++ b/src/coreclr/inc/corinfo.h @@ -2265,6 +2265,13 @@ class ICorStaticInfo int bufferSize /* IN */ ) = 0; + // Calls ToString() for given pinned/frozen object handle + virtual int objectToString ( + void* handle, /* IN */ + char* buffer, /* OUT */ + int bufferSize /* IN */ + ) = 0; + /**********************************************************************************/ // // ICorClassInfo @@ -2475,6 +2482,10 @@ class ICorStaticInfo CORINFO_CLASS_HANDLE cls ) = 0; + virtual void* getRuntimeTypePointer( + CORINFO_CLASS_HANDLE cls + ) = 0; + virtual bool getReadyToRunHelper( CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_LOOKUP_KIND * pGenericLookupKind, diff --git a/src/coreclr/inc/crsttypes.h b/src/coreclr/inc/crsttypes.h index cc3d34ab58e2b..0a5b4492d8f4b 100644 --- a/src/coreclr/inc/crsttypes.h +++ b/src/coreclr/inc/crsttypes.h @@ -132,7 +132,8 @@ enum CrstType CrstVSDIndirectionCellLock = 114, CrstWrapperTemplate = 115, CrstFrozenObjectHeap = 116, - kNumberOfCrstTypes = 117 + CrstMethodTableExposedObject = 117, + kNumberOfCrstTypes = 118 }; #endif // __CRST_TYPES_INCLUDED @@ -259,7 +260,8 @@ int g_rgCrstLevelMap[] = 3, // CrstUnwindInfoTableLock 4, // CrstVSDIndirectionCellLock 3, // CrstWrapperTemplate - 0, // CrstFrozenObjectHeap + -1, // CrstFrozenObjectHeap + -1, // CrstMethodTableExposedObject }; // An array mapping CrstType to a stringized name. @@ -381,7 +383,8 @@ LPCSTR g_rgCrstNameMap[] = "CrstUnwindInfoTableLock", "CrstVSDIndirectionCellLock", "CrstWrapperTemplate", - "CrstFrozenObjectHeap" + "CrstFrozenObjectHeap", + "CrstMethodTableExposedObject" }; // Define a special level constant for unordered locks. diff --git a/src/coreclr/inc/icorjitinfoimpl_generated.h b/src/coreclr/inc/icorjitinfoimpl_generated.h index 3a5a164e9aa71..4e0e1094eb250 100644 --- a/src/coreclr/inc/icorjitinfoimpl_generated.h +++ b/src/coreclr/inc/icorjitinfoimpl_generated.h @@ -175,6 +175,11 @@ int getStringLiteral( char16_t* buffer, int bufferSize) override; +int objectToString( + void* handle, + char* buffer, + int bufferSize) override; + CorInfoType asCorInfoType( CORINFO_CLASS_HANDLE cls) override; @@ -280,6 +285,9 @@ CorInfoHelpFunc getBoxHelper( CorInfoHelpFunc getUnBoxHelper( CORINFO_CLASS_HANDLE cls) override; +void* getRuntimeTypePointer( + CORINFO_CLASS_HANDLE cls) override; + bool getReadyToRunHelper( CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, diff --git a/src/coreclr/inc/jiteeversionguid.h b/src/coreclr/inc/jiteeversionguid.h index 311217aee254b..8ec7e89f0ef06 100644 --- a/src/coreclr/inc/jiteeversionguid.h +++ b/src/coreclr/inc/jiteeversionguid.h @@ -43,11 +43,11 @@ typedef const GUID *LPCGUID; #define GUID_DEFINED #endif // !GUID_DEFINED -constexpr GUID JITEEVersionIdentifier = { /* eb8352bd-0a13-4b5b-badb-58f9ecc40c44 */ - 0xeb8352bd, - 0x0a13, - 0x4b5b, - {0xba, 0xdb, 0x58, 0xf9, 0xec, 0xc4, 0x0c, 0x44} +constexpr GUID JITEEVersionIdentifier = { /* 11b4ea58-c400-4c3d-995e-4e2f0676f6e8 */ + 0x11b4ea58, + 0xc400, + 0x4c3d, + {0x99, 0x5e, 0x4e, 0x2f, 0x6, 0x76, 0xf6, 0xe8} }; ////////////////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/src/coreclr/jit/ICorJitInfo_API_names.h b/src/coreclr/jit/ICorJitInfo_API_names.h index 0c5af5b9e802a..9ebd42f381af6 100644 --- a/src/coreclr/jit/ICorJitInfo_API_names.h +++ b/src/coreclr/jit/ICorJitInfo_API_names.h @@ -41,6 +41,7 @@ DEF_CLR_API(getTokenTypeAsHandle) DEF_CLR_API(isValidToken) DEF_CLR_API(isValidStringRef) DEF_CLR_API(getStringLiteral) +DEF_CLR_API(objectToString) DEF_CLR_API(asCorInfoType) DEF_CLR_API(getClassName) DEF_CLR_API(getClassNameFromMetadata) @@ -70,6 +71,7 @@ DEF_CLR_API(getSharedCCtorHelper) DEF_CLR_API(getTypeForBox) DEF_CLR_API(getBoxHelper) DEF_CLR_API(getUnBoxHelper) +DEF_CLR_API(getRuntimeTypePointer) DEF_CLR_API(getReadyToRunHelper) DEF_CLR_API(getReadyToRunDelegateCtorHelper) DEF_CLR_API(getHelperName) diff --git a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp index 96139cc6cd4ef..4bedcebcf3b0c 100644 --- a/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp +++ b/src/coreclr/jit/ICorJitInfo_API_wrapper.hpp @@ -374,6 +374,17 @@ int WrapICorJitInfo::getStringLiteral( return temp; } +int WrapICorJitInfo::objectToString( + void* handle, + char* buffer, + int bufferSize) +{ + API_ENTER(objectToString); + int temp = wrapHnd->objectToString(handle, buffer, bufferSize); + API_LEAVE(objectToString); + return temp; +} + CorInfoType WrapICorJitInfo::asCorInfoType( CORINFO_CLASS_HANDLE cls) { @@ -652,6 +663,15 @@ CorInfoHelpFunc WrapICorJitInfo::getUnBoxHelper( return temp; } +void* WrapICorJitInfo::getRuntimeTypePointer( + CORINFO_CLASS_HANDLE cls) +{ + API_ENTER(getRuntimeTypePointer); + void* temp = wrapHnd->getRuntimeTypePointer(cls); + API_LEAVE(getRuntimeTypePointer); + return temp; +} + bool WrapICorJitInfo::getReadyToRunHelper( CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, diff --git a/src/coreclr/jit/assertionprop.cpp b/src/coreclr/jit/assertionprop.cpp index 430287284e6f1..1bd0c2677f797 100644 --- a/src/coreclr/jit/assertionprop.cpp +++ b/src/coreclr/jit/assertionprop.cpp @@ -2149,7 +2149,7 @@ void Compiler::optDebugCheckAssertion(AssertionDsc* assertion) break; case O1K_LCLVAR: assert((lvaGetDesc(assertion->op1.lcl.lclNum)->lvType != TYP_REF) || - (assertion->op2.u1.iconVal == 0) || doesMethodHaveFrozenString()); + (assertion->op2.u1.iconVal == 0) || doesMethodHaveFrozenObjects()); break; case O1K_VALUE_NUMBER: assert((vnStore->TypeOfVN(assertion->op1.vn) != TYP_REF) || (assertion->op2.u1.iconVal == 0)); @@ -3423,7 +3423,7 @@ GenTree* Compiler::optConstantAssertionProp(AssertionDsc* curAssertion, // Make sure we don't retype const gc handles to TYP_I_IMPL // Although, it's possible for e.g. GTF_ICON_STATIC_HDL - if (!newTree->IsIntegralConst(0) && newTree->IsIconHandle(GTF_ICON_STR_HDL)) + if (!newTree->IsIntegralConst(0) && newTree->IsIconHandle(GTF_ICON_OBJ_HDL)) { if (tree->TypeIs(TYP_BYREF)) { diff --git a/src/coreclr/jit/compiler.cpp b/src/coreclr/jit/compiler.cpp index 334af8b06bd0c..b7eded2340759 100644 --- a/src/coreclr/jit/compiler.cpp +++ b/src/coreclr/jit/compiler.cpp @@ -9413,6 +9413,11 @@ void cTreeFlags(Compiler* comp, GenTree* tree) chars += printf("[ICON_STR_HDL]"); break; + case GTF_ICON_OBJ_HDL: + + chars += printf("[ICON_OBJ_HDL]"); + break; + case GTF_ICON_CONST_PTR: chars += printf("[ICON_CONST_PTR]"); diff --git a/src/coreclr/jit/compiler.h b/src/coreclr/jit/compiler.h index bc96171a9c747..3cd50affb2b5e 100644 --- a/src/coreclr/jit/compiler.h +++ b/src/coreclr/jit/compiler.h @@ -6806,7 +6806,7 @@ class Compiler #define OMF_HAS_EXPRUNTIMELOOKUP 0x00000080 // Method contains a runtime lookup to an expandable dictionary. #define OMF_HAS_PATCHPOINT 0x00000100 // Method contains patchpoints #define OMF_NEEDS_GCPOLLS 0x00000200 // Method needs GC polls -#define OMF_HAS_FROZEN_STRING 0x00000400 // Method has a frozen string (REF constant int), currently only on NativeAOT. +#define OMF_HAS_FROZEN_OBJECTS 0x00000400 // Method has frozen objects (REF constant int) #define OMF_HAS_PARTIAL_COMPILATION_PATCHPOINT 0x00000800 // Method contains partial compilation patchpoints #define OMF_HAS_TAILCALL_SUCCESSOR 0x00001000 // Method has potential tail call in a non BBJ_RETURN block #define OMF_HAS_MDNEWARRAY 0x00002000 // Method contains 'new' of an MD array @@ -6831,14 +6831,14 @@ class Compiler void addFatPointerCandidate(GenTreeCall* call); - bool doesMethodHaveFrozenString() const + bool doesMethodHaveFrozenObjects() const { - return (optMethodFlags & OMF_HAS_FROZEN_STRING) != 0; + return (optMethodFlags & OMF_HAS_FROZEN_OBJECTS) != 0; } - void setMethodHasFrozenString() + void setMethodHasFrozenObjects() { - optMethodFlags |= OMF_HAS_FROZEN_STRING; + optMethodFlags |= OMF_HAS_FROZEN_OBJECTS; } bool doesMethodHaveGuardedDevirtualization() const @@ -7798,7 +7798,7 @@ class Compiler const char* eeGetFieldName(CORINFO_FIELD_HANDLE fieldHnd, const char** classNamePtr = nullptr); #if defined(DEBUG) - const WCHAR* eeGetCPString(size_t stringHandle); + void eePrintFrozenObjectDescription(const char* prefix, size_t handle); unsigned eeTryGetClassSize(CORINFO_CLASS_HANDLE clsHnd); const char16_t* eeGetShortClassName(CORINFO_CLASS_HANDLE clsHnd); #endif diff --git a/src/coreclr/jit/ee_il_dll.cpp b/src/coreclr/jit/ee_il_dll.cpp index fedbae80a624c..71a0dd52630a5 100644 --- a/src/coreclr/jit/ee_il_dll.cpp +++ b/src/coreclr/jit/ee_il_dll.cpp @@ -1615,45 +1615,40 @@ const char16_t* Compiler::eeGetShortClassName(CORINFO_CLASS_HANDLE clsHnd) return param.classNameWidePtr; } -const WCHAR* Compiler::eeGetCPString(size_t strHandle) +void Compiler::eePrintFrozenObjectDescription(const char* prefix, size_t handle) { -#ifdef HOST_UNIX - return nullptr; -#else - char buff[512 + sizeof(CORINFO_String)]; - - // make this bulletproof, so it works even if we are wrong. - if (ReadProcessMemory(GetCurrentProcess(), (void*)strHandle, buff, 4, nullptr) == 0) + const int maxStrSize = 64; + char str[maxStrSize]; + int realLength = this->info.compCompHnd->objectToString((void*)handle, str, maxStrSize); + if (realLength == -1) { - return (nullptr); + printf("%s 'unknown frozen object'", prefix); + return; } - - CORINFO_String* asString = nullptr; - if (impGetStringClass() == *((CORINFO_CLASS_HANDLE*)strHandle)) + else if (realLength >= maxStrSize) { - // strHandle is a frozen string - // We assume strHandle is never an "interior" pointer in a frozen string - // (jit is not expected to perform such foldings) - asString = (CORINFO_String*)strHandle; + // string is too long, trim it and null-terminate + str[maxStrSize - 4] = '.'; + str[maxStrSize - 3] = '.'; + str[maxStrSize - 2] = '.'; + str[maxStrSize - 1] = 0; } else { - // strHandle is a pinned handle to a string object - asString = *((CORINFO_String**)strHandle); - } - - if (ReadProcessMemory(GetCurrentProcess(), asString, buff, sizeof(buff), nullptr) == 0) - { - return (nullptr); + // objectToString doesn't null-terminate buffer + str[realLength] = 0; } - if (asString->stringLen >= 255 || asString->chars[asString->stringLen] != 0) + for (int i = 0; i < min(maxStrSize, realLength); i++) { - return nullptr; + // Replace \n and \r symbols with whitespaces + if (str[i] == '\n' || str[i] == '\r') + { + str[i] = ' '; + } } - return (WCHAR*)(asString->chars); -#endif // HOST_UNIX + printf("%s '%s'\n", prefix, str); } #else // DEBUG void jitprintf(const char* fmt, ...) diff --git a/src/coreclr/jit/emit.cpp b/src/coreclr/jit/emit.cpp index b9130fa443efd..344bb9cdd8658 100644 --- a/src/coreclr/jit/emit.cpp +++ b/src/coreclr/jit/emit.cpp @@ -4129,42 +4129,15 @@ void emitter::emitDispCommentForHandle(size_t handle, size_t cookie, GenTreeFlag const char* str = nullptr; if (flag == GTF_ICON_STR_HDL) + { + str = "string handle"; + } + else if (flag == GTF_ICON_OBJ_HDL) { #ifdef DEBUG - const WCHAR* wstr = emitComp->eeGetCPString(handle); - // NOTE: eGetCPString always returns nullptr on Linux/ARM - if (wstr == nullptr) - { - str = "string handle"; - } - else - { - const size_t actualLen = wcslen(wstr); - const size_t maxLength = 63; - const size_t newLen = min(maxLength, actualLen); - - // +1 for null terminator - WCHAR buf[maxLength + 1] = {0}; - wcsncpy(buf, wstr, newLen); - for (size_t i = 0; i < newLen; i++) - { - // Escape \n and \r symbols - if (buf[i] == L'\n' || buf[i] == L'\r') - { - buf[i] = L' '; - } - } - if (actualLen > maxLength) - { - // Append "..." for long strings - buf[maxLength - 3] = L'.'; - buf[maxLength - 2] = L'.'; - buf[maxLength - 1] = L'.'; - } - printf("%s \"%S\"", commentPrefix, buf); - } + emitComp->eePrintFrozenObjectDescription(commentPrefix, handle); #else - str = "string handle"; + str = "frozen object handle"; #endif } else if (flag == GTF_ICON_CLASS_HDL) diff --git a/src/coreclr/jit/emitxarch.cpp b/src/coreclr/jit/emitxarch.cpp index 20a700e691340..5e1448748cefc 100644 --- a/src/coreclr/jit/emitxarch.cpp +++ b/src/coreclr/jit/emitxarch.cpp @@ -8756,18 +8756,6 @@ void emitter::emitDispAddrMode(instrDesc* id, bool noDetail) printf("]"); -// pretty print string if it looks like one -#ifdef DEBUG - if ((id->idGCref() == GCT_GCREF) && (id->idIns() == INS_mov) && (id->idAddr()->iiaAddrMode.amBaseReg == REG_NA)) - { - const WCHAR* str = emitComp->eeGetCPString(disp); - if (str != nullptr) - { - printf(" '%S'", str); - } - } -#endif - if (jdsc && !noDetail) { unsigned cnt = (jdsc->dsSize - 1) / TARGET_POINTER_SIZE; diff --git a/src/coreclr/jit/gentree.cpp b/src/coreclr/jit/gentree.cpp index 43d6d550f4ed0..5549a5166b386 100644 --- a/src/coreclr/jit/gentree.cpp +++ b/src/coreclr/jit/gentree.cpp @@ -6990,8 +6990,8 @@ GenTree* Compiler::gtNewStringLiteralNode(InfoAccessType iat, void* pValue) switch (iat) { case IAT_VALUE: - setMethodHasFrozenString(); - tree = gtNewIconEmbHndNode(pValue, nullptr, GTF_ICON_STR_HDL, nullptr); + setMethodHasFrozenObjects(); + tree = gtNewIconEmbHndNode(pValue, nullptr, GTF_ICON_OBJ_HDL, nullptr); tree->gtType = TYP_REF; #ifdef DEBUG tree->AsIntCon()->gtTargetHandle = (size_t)pValue; @@ -11095,18 +11095,11 @@ void Compiler::gtDispConst(GenTree* tree) case GT_CNS_INT: if (tree->IsIconHandle(GTF_ICON_STR_HDL)) { - const WCHAR* str = eeGetCPString(tree->AsIntCon()->gtIconVal); - // If *str points to a '\0' then don't print the string's values - if ((str != nullptr) && (*str != '\0')) - { - printf(" 0x%X \"%S\"", dspPtr(tree->AsIntCon()->gtIconVal), str); - } - else // We can't print the value of the string - { - // Note that eeGetCPString isn't currently implemented on Linux/ARM - // and instead always returns nullptr - printf(" 0x%X [ICON_STR_HDL]", dspPtr(tree->AsIntCon()->gtIconVal)); - } + printf(" 0x%X [ICON_STR_HDL]", dspPtr(tree->AsIntCon()->gtIconVal)); + } + else if (tree->IsIconHandle(GTF_ICON_OBJ_HDL)) + { + eePrintFrozenObjectDescription(" ", tree->AsIntCon()->gtIconVal); } else { @@ -11121,7 +11114,7 @@ void Compiler::gtDispConst(GenTree* tree) } else { - assert(doesMethodHaveFrozenString()); + assert(doesMethodHaveFrozenObjects()); printf(" 0x%llx", dspIconVal); } } @@ -11173,8 +11166,9 @@ void Compiler::gtDispConst(GenTree* tree) case GTF_ICON_STATIC_HDL: printf(" static"); break; + case GTF_ICON_OBJ_HDL: case GTF_ICON_STR_HDL: - unreached(); // This case is handled above + unreached(); // These cases are handled above break; case GTF_ICON_CONST_PTR: printf(" const ptr"); diff --git a/src/coreclr/jit/gentree.h b/src/coreclr/jit/gentree.h index 81b0406487991..1865e5b5cddb4 100644 --- a/src/coreclr/jit/gentree.h +++ b/src/coreclr/jit/gentree.h @@ -553,7 +553,8 @@ enum GenTreeFlags : unsigned int GTF_ICON_METHOD_HDL = 0x03000000, // GT_CNS_INT -- constant is a method handle GTF_ICON_FIELD_HDL = 0x04000000, // GT_CNS_INT -- constant is a field handle GTF_ICON_STATIC_HDL = 0x05000000, // GT_CNS_INT -- constant is a handle to static data - GTF_ICON_STR_HDL = 0x06000000, // GT_CNS_INT -- constant is a string handle + GTF_ICON_STR_HDL = 0x06000000, // GT_CNS_INT -- constant is a pinned handle pointing to a string object + GTF_ICON_OBJ_HDL = 0x12000000, // GT_CNS_INT -- constant is an object handle (e.g. frozen string or Type object) GTF_ICON_CONST_PTR = 0x07000000, // GT_CNS_INT -- constant is a pointer to immutable data, (e.g. IAT_PPVALUE) GTF_ICON_GLOBAL_PTR = 0x08000000, // GT_CNS_INT -- constant is a pointer to mutable data (e.g. from the VM state) GTF_ICON_VARG_HDL = 0x09000000, // GT_CNS_INT -- constant is a var arg cookie handle diff --git a/src/coreclr/jit/importer.cpp b/src/coreclr/jit/importer.cpp index 7c238103bfdef..15783fdf619bd 100644 --- a/src/coreclr/jit/importer.cpp +++ b/src/coreclr/jit/importer.cpp @@ -22127,9 +22127,9 @@ bool Compiler::impCanSkipCovariantStoreCheck(GenTree* value, GenTree* array) return true; } // Non-0 const refs can only occur with frozen objects - assert(value->IsIconHandle(GTF_ICON_STR_HDL)); - assert(doesMethodHaveFrozenString() || - (compIsForInlining() && impInlineInfo->InlinerCompiler->doesMethodHaveFrozenString())); + assert(value->IsIconHandle(GTF_ICON_OBJ_HDL)); + assert(doesMethodHaveFrozenObjects() || + (compIsForInlining() && impInlineInfo->InlinerCompiler->doesMethodHaveFrozenObjects())); } // Try and get a class handle for the array diff --git a/src/coreclr/jit/morph.cpp b/src/coreclr/jit/morph.cpp index f1c7d633077a1..1da2bc0ef0f42 100644 --- a/src/coreclr/jit/morph.cpp +++ b/src/coreclr/jit/morph.cpp @@ -8312,6 +8312,26 @@ GenTree* Compiler::fgMorphCall(GenTreeCall* call) call = fgMorphArgs(call); noway_assert(call->gtOper == GT_CALL); + // Try to replace CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPE with a constant gc handle + // pointing to a frozen segment + if (!gtIsActiveCSE_Candidate(call) && gtIsTypeHandleToRuntimeTypeHelper(call)) + { + GenTree* argNode = call->AsCall()->gtArgs.GetArgByIndex(0)->GetNode(); + CORINFO_CLASS_HANDLE hClass = gtGetHelperArgClassHandle(argNode); + if ((hClass != NO_CLASS_HANDLE) && !gtIsActiveCSE_Candidate(argNode)) + { + void* ptr = info.compCompHnd->getRuntimeTypePointer(hClass); + if (ptr != nullptr) + { + setMethodHasFrozenObjects(); + GenTree* retNode = gtNewIconEmbHndNode(ptr, nullptr, GTF_ICON_OBJ_HDL, nullptr); + retNode->gtType = TYP_REF; + INDEBUG(retNode->AsIntCon()->gtTargetHandle = (size_t)ptr); + return fgMorphTree(retNode); + } + } + } + // Assign DEF flags if it produces a definition from "return buffer". fgAssignSetVarDef(call); if (call->OperRequiresAsgFlag()) @@ -11161,7 +11181,7 @@ GenTree* Compiler::fgMorphSmpOp(GenTree* tree, MorphAddrContext* mac, bool* optA // if (!tree->AsIndir()->IsVolatile()) { - if (op1->IsIconHandle(GTF_ICON_STR_HDL)) + if (op1->IsIconHandle(GTF_ICON_OBJ_HDL)) { tree->gtFlags |= (GTF_IND_INVARIANT | GTF_IND_NONFAULTING | GTF_IND_NONNULL); } diff --git a/src/coreclr/jit/optcse.cpp b/src/coreclr/jit/optcse.cpp index 3d300d898e8bd..4bbfb81f91fac 100644 --- a/src/coreclr/jit/optcse.cpp +++ b/src/coreclr/jit/optcse.cpp @@ -812,7 +812,7 @@ bool Compiler::optValnumCSE_Locate() if (!enableConstCSE && // Unconditionally allow these constant handles to be CSE'd !tree->IsIconHandle(GTF_ICON_STATIC_HDL) && !tree->IsIconHandle(GTF_ICON_CLASS_HDL) && - !tree->IsIconHandle(GTF_ICON_STR_HDL)) + !tree->IsIconHandle(GTF_ICON_STR_HDL) && !tree->IsIconHandle(GTF_ICON_OBJ_HDL)) { continue; } diff --git a/src/coreclr/jit/valuenum.cpp b/src/coreclr/jit/valuenum.cpp index 5ea27c4b86680..fa233e19bc940 100644 --- a/src/coreclr/jit/valuenum.cpp +++ b/src/coreclr/jit/valuenum.cpp @@ -5254,6 +5254,7 @@ GenTreeFlags ValueNumStore::GetFoldedArithOpResultHandleFlags(ValueNum vn) case GTF_ICON_FIELD_HDL: case GTF_ICON_TOKEN_HDL: case GTF_ICON_STR_HDL: + case GTF_ICON_OBJ_HDL: case GTF_ICON_CONST_PTR: case GTF_ICON_VARG_HDL: case GTF_ICON_PINVKI_HDL: @@ -8189,7 +8190,7 @@ void Compiler::fgValueNumberTreeConst(GenTree* tree) } else { - assert(doesMethodHaveFrozenString()); // Constant object can be only frozen string. + assert(doesMethodHaveFrozenObjects()); tree->gtVNPair.SetBoth( vnStore->VNForHandle(ssize_t(tree->AsIntConCommon()->IconValue()), tree->GetIconHandleFlag())); } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs index 2aa2105765b84..8d8c426a7130d 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoBase.cs @@ -553,6 +553,21 @@ private static int _getStringLiteral(IntPtr thisHandle, IntPtr* ppException, COR } } + [UnmanagedCallersOnly] + private static int _objectToString(IntPtr thisHandle, IntPtr* ppException, void* handle, byte* buffer, int bufferSize) + { + var _this = GetThis(thisHandle); + try + { + return _this.objectToString(handle, buffer, bufferSize); + } + catch (Exception ex) + { + *ppException = _this.AllocException(ex); + return default; + } + } + [UnmanagedCallersOnly] private static CorInfoType _asCorInfoType(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* cls) { @@ -987,6 +1002,21 @@ private static CorInfoHelpFunc _getUnBoxHelper(IntPtr thisHandle, IntPtr* ppExce } } + [UnmanagedCallersOnly] + private static void* _getRuntimeTypePointer(IntPtr thisHandle, IntPtr* ppException, CORINFO_CLASS_STRUCT_* cls) + { + var _this = GetThis(thisHandle); + try + { + return _this.getRuntimeTypePointer(cls); + } + catch (Exception ex) + { + *ppException = _this.AllocException(ex); + return default; + } + } + [UnmanagedCallersOnly] private static byte _getReadyToRunHelper(IntPtr thisHandle, IntPtr* ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, CORINFO_CONST_LOOKUP* pLookup) { @@ -2592,9 +2622,10 @@ private static uint _getJitFlags(IntPtr thisHandle, IntPtr* ppException, CORJIT_ } } + private static IntPtr GetUnmanagedCallbacks() { - void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 175); + void** callbacks = (void**)Marshal.AllocCoTaskMem(sizeof(IntPtr) * 177); callbacks[0] = (delegate* unmanaged)&_isIntrinsic; callbacks[1] = (delegate* unmanaged)&_getMethodAttribs; @@ -2633,144 +2664,146 @@ private static IntPtr GetUnmanagedCallbacks() callbacks[34] = (delegate* unmanaged)&_isValidToken; callbacks[35] = (delegate* unmanaged)&_isValidStringRef; callbacks[36] = (delegate* unmanaged)&_getStringLiteral; - callbacks[37] = (delegate* unmanaged)&_asCorInfoType; - callbacks[38] = (delegate* unmanaged)&_getClassName; - callbacks[39] = (delegate* unmanaged)&_getClassNameFromMetadata; - callbacks[40] = (delegate* unmanaged)&_getTypeInstantiationArgument; - callbacks[41] = (delegate* unmanaged)&_appendClassName; - callbacks[42] = (delegate* unmanaged)&_isValueClass; - callbacks[43] = (delegate* unmanaged)&_canInlineTypeCheck; - callbacks[44] = (delegate* unmanaged)&_getClassAttribs; - callbacks[45] = (delegate* unmanaged)&_getClassModule; - callbacks[46] = (delegate* unmanaged)&_getModuleAssembly; - callbacks[47] = (delegate* unmanaged)&_getAssemblyName; - callbacks[48] = (delegate* unmanaged)&_LongLifetimeMalloc; - callbacks[49] = (delegate* unmanaged)&_LongLifetimeFree; - callbacks[50] = (delegate* unmanaged)&_getClassModuleIdForStatics; - callbacks[51] = (delegate* unmanaged)&_getClassSize; - callbacks[52] = (delegate* unmanaged)&_getHeapClassSize; - callbacks[53] = (delegate* unmanaged)&_canAllocateOnStack; - callbacks[54] = (delegate* unmanaged)&_getClassAlignmentRequirement; - callbacks[55] = (delegate* unmanaged)&_getClassGClayout; - callbacks[56] = (delegate* unmanaged)&_getClassNumInstanceFields; - callbacks[57] = (delegate* unmanaged)&_getFieldInClass; - callbacks[58] = (delegate* unmanaged)&_checkMethodModifier; - callbacks[59] = (delegate* unmanaged)&_getNewHelper; - callbacks[60] = (delegate* unmanaged)&_getNewArrHelper; - callbacks[61] = (delegate* unmanaged)&_getCastingHelper; - callbacks[62] = (delegate* unmanaged)&_getSharedCCtorHelper; - callbacks[63] = (delegate* unmanaged)&_getTypeForBox; - callbacks[64] = (delegate* unmanaged)&_getBoxHelper; - callbacks[65] = (delegate* unmanaged)&_getUnBoxHelper; - callbacks[66] = (delegate* unmanaged)&_getReadyToRunHelper; - callbacks[67] = (delegate* unmanaged)&_getReadyToRunDelegateCtorHelper; - callbacks[68] = (delegate* unmanaged)&_getHelperName; - callbacks[69] = (delegate* unmanaged)&_initClass; - callbacks[70] = (delegate* unmanaged)&_classMustBeLoadedBeforeCodeIsRun; - callbacks[71] = (delegate* unmanaged)&_getBuiltinClass; - callbacks[72] = (delegate* unmanaged)&_getTypeForPrimitiveValueClass; - callbacks[73] = (delegate* unmanaged)&_getTypeForPrimitiveNumericClass; - callbacks[74] = (delegate* unmanaged)&_canCast; - callbacks[75] = (delegate* unmanaged)&_areTypesEquivalent; - callbacks[76] = (delegate* unmanaged)&_compareTypesForCast; - callbacks[77] = (delegate* unmanaged)&_compareTypesForEquality; - callbacks[78] = (delegate* unmanaged)&_mergeClasses; - callbacks[79] = (delegate* unmanaged)&_isMoreSpecificType; - callbacks[80] = (delegate* unmanaged)&_getParentType; - callbacks[81] = (delegate* unmanaged)&_getChildType; - callbacks[82] = (delegate* unmanaged)&_satisfiesClassConstraints; - callbacks[83] = (delegate* unmanaged)&_isSDArray; - callbacks[84] = (delegate* unmanaged)&_getArrayRank; - callbacks[85] = (delegate* unmanaged)&_getArrayIntrinsicID; - callbacks[86] = (delegate* unmanaged)&_getArrayInitializationData; - callbacks[87] = (delegate* unmanaged)&_canAccessClass; - callbacks[88] = (delegate* unmanaged)&_getFieldName; - callbacks[89] = (delegate* unmanaged)&_getFieldClass; - callbacks[90] = (delegate* unmanaged)&_getFieldType; - callbacks[91] = (delegate* unmanaged)&_getFieldOffset; - callbacks[92] = (delegate* unmanaged)&_getFieldInfo; - callbacks[93] = (delegate* unmanaged)&_isFieldStatic; - callbacks[94] = (delegate* unmanaged)&_getBoundaries; - callbacks[95] = (delegate* unmanaged)&_setBoundaries; - callbacks[96] = (delegate* unmanaged)&_getVars; - callbacks[97] = (delegate* unmanaged)&_setVars; - callbacks[98] = (delegate* unmanaged)&_reportRichMappings; - callbacks[99] = (delegate* unmanaged)&_allocateArray; - callbacks[100] = (delegate* unmanaged)&_freeArray; - callbacks[101] = (delegate* unmanaged)&_getArgNext; - callbacks[102] = (delegate* unmanaged)&_getArgType; - callbacks[103] = (delegate* unmanaged)&_getExactClasses; - callbacks[104] = (delegate* unmanaged)&_getArgClass; - callbacks[105] = (delegate* unmanaged)&_getHFAType; - callbacks[106] = (delegate* unmanaged)&_GetErrorHRESULT; - callbacks[107] = (delegate* unmanaged)&_GetErrorMessage; - callbacks[108] = (delegate* unmanaged)&_FilterException; - callbacks[109] = (delegate* unmanaged)&_ThrowExceptionForJitResult; - callbacks[110] = (delegate* unmanaged)&_ThrowExceptionForHelper; - callbacks[111] = (delegate* unmanaged)&_runWithErrorTrap; - callbacks[112] = (delegate* unmanaged)&_runWithSPMIErrorTrap; - callbacks[113] = (delegate* unmanaged)&_getEEInfo; - callbacks[114] = (delegate* unmanaged)&_getJitTimeLogFilename; - callbacks[115] = (delegate* unmanaged)&_getMethodDefFromMethod; - callbacks[116] = (delegate* unmanaged)&_getMethodName; - callbacks[117] = (delegate* unmanaged)&_getMethodNameFromMetadata; - callbacks[118] = (delegate* unmanaged)&_getMethodHash; - callbacks[119] = (delegate* unmanaged)&_findNameOfToken; - callbacks[120] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; - callbacks[121] = (delegate* unmanaged)&_getLoongArch64PassStructInRegisterFlags; - callbacks[122] = (delegate* unmanaged)&_getThreadTLSIndex; - callbacks[123] = (delegate* unmanaged)&_getInlinedCallFrameVptr; - callbacks[124] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; - callbacks[125] = (delegate* unmanaged)&_getHelperFtn; - callbacks[126] = (delegate* unmanaged)&_getFunctionEntryPoint; - callbacks[127] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; - callbacks[128] = (delegate* unmanaged)&_getMethodSync; - callbacks[129] = (delegate* unmanaged)&_getLazyStringLiteralHelper; - callbacks[130] = (delegate* unmanaged)&_embedModuleHandle; - callbacks[131] = (delegate* unmanaged)&_embedClassHandle; - callbacks[132] = (delegate* unmanaged)&_embedMethodHandle; - callbacks[133] = (delegate* unmanaged)&_embedFieldHandle; - callbacks[134] = (delegate* unmanaged)&_embedGenericHandle; - callbacks[135] = (delegate* unmanaged)&_getLocationOfThisType; - callbacks[136] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; - callbacks[137] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; - callbacks[138] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; - callbacks[139] = (delegate* unmanaged)&_getJustMyCodeHandle; - callbacks[140] = (delegate* unmanaged)&_GetProfilingHandle; - callbacks[141] = (delegate* unmanaged)&_getCallInfo; - callbacks[142] = (delegate* unmanaged)&_canAccessFamily; - callbacks[143] = (delegate* unmanaged)&_isRIDClassDomainID; - callbacks[144] = (delegate* unmanaged)&_getClassDomainID; - callbacks[145] = (delegate* unmanaged)&_getFieldAddress; - callbacks[146] = (delegate* unmanaged)&_getStaticFieldCurrentClass; - callbacks[147] = (delegate* unmanaged)&_getVarArgsHandle; - callbacks[148] = (delegate* unmanaged)&_canGetVarArgsHandle; - callbacks[149] = (delegate* unmanaged)&_constructStringLiteral; - callbacks[150] = (delegate* unmanaged)&_emptyStringLiteral; - callbacks[151] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; - callbacks[152] = (delegate* unmanaged)&_addActiveDependency; - callbacks[153] = (delegate* unmanaged)&_GetDelegateCtor; - callbacks[154] = (delegate* unmanaged)&_MethodCompileComplete; - callbacks[155] = (delegate* unmanaged)&_getTailCallHelpers; - callbacks[156] = (delegate* unmanaged)&_convertPInvokeCalliToCall; - callbacks[157] = (delegate* unmanaged)&_notifyInstructionSetUsage; - callbacks[158] = (delegate* unmanaged)&_updateEntryPointForTailCall; - callbacks[159] = (delegate* unmanaged)&_allocMem; - callbacks[160] = (delegate* unmanaged)&_reserveUnwindInfo; - callbacks[161] = (delegate* unmanaged)&_allocUnwindInfo; - callbacks[162] = (delegate* unmanaged)&_allocGCInfo; - callbacks[163] = (delegate* unmanaged)&_setEHcount; - callbacks[164] = (delegate* unmanaged)&_setEHinfo; - callbacks[165] = (delegate* unmanaged)&_logMsg; - callbacks[166] = (delegate* unmanaged)&_doAssert; - callbacks[167] = (delegate* unmanaged)&_reportFatalError; - callbacks[168] = (delegate* unmanaged)&_getPgoInstrumentationResults; - callbacks[169] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; - callbacks[170] = (delegate* unmanaged)&_recordCallSite; - callbacks[171] = (delegate* unmanaged)&_recordRelocation; - callbacks[172] = (delegate* unmanaged)&_getRelocTypeHint; - callbacks[173] = (delegate* unmanaged)&_getExpectedTargetArchitecture; - callbacks[174] = (delegate* unmanaged)&_getJitFlags; + callbacks[37] = (delegate* unmanaged)&_objectToString; + callbacks[38] = (delegate* unmanaged)&_asCorInfoType; + callbacks[39] = (delegate* unmanaged)&_getClassName; + callbacks[40] = (delegate* unmanaged)&_getClassNameFromMetadata; + callbacks[41] = (delegate* unmanaged)&_getTypeInstantiationArgument; + callbacks[42] = (delegate* unmanaged)&_appendClassName; + callbacks[43] = (delegate* unmanaged)&_isValueClass; + callbacks[44] = (delegate* unmanaged)&_canInlineTypeCheck; + callbacks[45] = (delegate* unmanaged)&_getClassAttribs; + callbacks[46] = (delegate* unmanaged)&_getClassModule; + callbacks[47] = (delegate* unmanaged)&_getModuleAssembly; + callbacks[48] = (delegate* unmanaged)&_getAssemblyName; + callbacks[49] = (delegate* unmanaged)&_LongLifetimeMalloc; + callbacks[50] = (delegate* unmanaged)&_LongLifetimeFree; + callbacks[51] = (delegate* unmanaged)&_getClassModuleIdForStatics; + callbacks[52] = (delegate* unmanaged)&_getClassSize; + callbacks[53] = (delegate* unmanaged)&_getHeapClassSize; + callbacks[54] = (delegate* unmanaged)&_canAllocateOnStack; + callbacks[55] = (delegate* unmanaged)&_getClassAlignmentRequirement; + callbacks[56] = (delegate* unmanaged)&_getClassGClayout; + callbacks[57] = (delegate* unmanaged)&_getClassNumInstanceFields; + callbacks[58] = (delegate* unmanaged)&_getFieldInClass; + callbacks[59] = (delegate* unmanaged)&_checkMethodModifier; + callbacks[60] = (delegate* unmanaged)&_getNewHelper; + callbacks[61] = (delegate* unmanaged)&_getNewArrHelper; + callbacks[62] = (delegate* unmanaged)&_getCastingHelper; + callbacks[63] = (delegate* unmanaged)&_getSharedCCtorHelper; + callbacks[64] = (delegate* unmanaged)&_getTypeForBox; + callbacks[65] = (delegate* unmanaged)&_getBoxHelper; + callbacks[66] = (delegate* unmanaged)&_getUnBoxHelper; + callbacks[67] = (delegate* unmanaged)&_getRuntimeTypePointer; + callbacks[68] = (delegate* unmanaged)&_getReadyToRunHelper; + callbacks[69] = (delegate* unmanaged)&_getReadyToRunDelegateCtorHelper; + callbacks[70] = (delegate* unmanaged)&_getHelperName; + callbacks[71] = (delegate* unmanaged)&_initClass; + callbacks[72] = (delegate* unmanaged)&_classMustBeLoadedBeforeCodeIsRun; + callbacks[73] = (delegate* unmanaged)&_getBuiltinClass; + callbacks[74] = (delegate* unmanaged)&_getTypeForPrimitiveValueClass; + callbacks[75] = (delegate* unmanaged)&_getTypeForPrimitiveNumericClass; + callbacks[76] = (delegate* unmanaged)&_canCast; + callbacks[77] = (delegate* unmanaged)&_areTypesEquivalent; + callbacks[78] = (delegate* unmanaged)&_compareTypesForCast; + callbacks[79] = (delegate* unmanaged)&_compareTypesForEquality; + callbacks[80] = (delegate* unmanaged)&_mergeClasses; + callbacks[81] = (delegate* unmanaged)&_isMoreSpecificType; + callbacks[82] = (delegate* unmanaged)&_getParentType; + callbacks[83] = (delegate* unmanaged)&_getChildType; + callbacks[84] = (delegate* unmanaged)&_satisfiesClassConstraints; + callbacks[85] = (delegate* unmanaged)&_isSDArray; + callbacks[86] = (delegate* unmanaged)&_getArrayRank; + callbacks[87] = (delegate* unmanaged)&_getArrayIntrinsicID; + callbacks[88] = (delegate* unmanaged)&_getArrayInitializationData; + callbacks[89] = (delegate* unmanaged)&_canAccessClass; + callbacks[90] = (delegate* unmanaged)&_getFieldName; + callbacks[91] = (delegate* unmanaged)&_getFieldClass; + callbacks[92] = (delegate* unmanaged)&_getFieldType; + callbacks[93] = (delegate* unmanaged)&_getFieldOffset; + callbacks[94] = (delegate* unmanaged)&_getFieldInfo; + callbacks[95] = (delegate* unmanaged)&_isFieldStatic; + callbacks[96] = (delegate* unmanaged)&_getBoundaries; + callbacks[97] = (delegate* unmanaged)&_setBoundaries; + callbacks[98] = (delegate* unmanaged)&_getVars; + callbacks[99] = (delegate* unmanaged)&_setVars; + callbacks[100] = (delegate* unmanaged)&_reportRichMappings; + callbacks[101] = (delegate* unmanaged)&_allocateArray; + callbacks[102] = (delegate* unmanaged)&_freeArray; + callbacks[103] = (delegate* unmanaged)&_getArgNext; + callbacks[104] = (delegate* unmanaged)&_getArgType; + callbacks[105] = (delegate* unmanaged)&_getExactClasses; + callbacks[106] = (delegate* unmanaged)&_getArgClass; + callbacks[107] = (delegate* unmanaged)&_getHFAType; + callbacks[108] = (delegate* unmanaged)&_GetErrorHRESULT; + callbacks[109] = (delegate* unmanaged)&_GetErrorMessage; + callbacks[110] = (delegate* unmanaged)&_FilterException; + callbacks[111] = (delegate* unmanaged)&_ThrowExceptionForJitResult; + callbacks[112] = (delegate* unmanaged)&_ThrowExceptionForHelper; + callbacks[113] = (delegate* unmanaged)&_runWithErrorTrap; + callbacks[114] = (delegate* unmanaged)&_runWithSPMIErrorTrap; + callbacks[115] = (delegate* unmanaged)&_getEEInfo; + callbacks[116] = (delegate* unmanaged)&_getJitTimeLogFilename; + callbacks[117] = (delegate* unmanaged)&_getMethodDefFromMethod; + callbacks[118] = (delegate* unmanaged)&_getMethodName; + callbacks[119] = (delegate* unmanaged)&_getMethodNameFromMetadata; + callbacks[120] = (delegate* unmanaged)&_getMethodHash; + callbacks[121] = (delegate* unmanaged)&_findNameOfToken; + callbacks[122] = (delegate* unmanaged)&_getSystemVAmd64PassStructInRegisterDescriptor; + callbacks[123] = (delegate* unmanaged)&_getLoongArch64PassStructInRegisterFlags; + callbacks[124] = (delegate* unmanaged)&_getThreadTLSIndex; + callbacks[125] = (delegate* unmanaged)&_getInlinedCallFrameVptr; + callbacks[126] = (delegate* unmanaged)&_getAddrOfCaptureThreadGlobal; + callbacks[127] = (delegate* unmanaged)&_getHelperFtn; + callbacks[128] = (delegate* unmanaged)&_getFunctionEntryPoint; + callbacks[129] = (delegate* unmanaged)&_getFunctionFixedEntryPoint; + callbacks[130] = (delegate* unmanaged)&_getMethodSync; + callbacks[131] = (delegate* unmanaged)&_getLazyStringLiteralHelper; + callbacks[132] = (delegate* unmanaged)&_embedModuleHandle; + callbacks[133] = (delegate* unmanaged)&_embedClassHandle; + callbacks[134] = (delegate* unmanaged)&_embedMethodHandle; + callbacks[135] = (delegate* unmanaged)&_embedFieldHandle; + callbacks[136] = (delegate* unmanaged)&_embedGenericHandle; + callbacks[137] = (delegate* unmanaged)&_getLocationOfThisType; + callbacks[138] = (delegate* unmanaged)&_getAddressOfPInvokeTarget; + callbacks[139] = (delegate* unmanaged)&_GetCookieForPInvokeCalliSig; + callbacks[140] = (delegate* unmanaged)&_canGetCookieForPInvokeCalliSig; + callbacks[141] = (delegate* unmanaged)&_getJustMyCodeHandle; + callbacks[142] = (delegate* unmanaged)&_GetProfilingHandle; + callbacks[143] = (delegate* unmanaged)&_getCallInfo; + callbacks[144] = (delegate* unmanaged)&_canAccessFamily; + callbacks[145] = (delegate* unmanaged)&_isRIDClassDomainID; + callbacks[146] = (delegate* unmanaged)&_getClassDomainID; + callbacks[147] = (delegate* unmanaged)&_getFieldAddress; + callbacks[148] = (delegate* unmanaged)&_getStaticFieldCurrentClass; + callbacks[149] = (delegate* unmanaged)&_getVarArgsHandle; + callbacks[150] = (delegate* unmanaged)&_canGetVarArgsHandle; + callbacks[151] = (delegate* unmanaged)&_constructStringLiteral; + callbacks[152] = (delegate* unmanaged)&_emptyStringLiteral; + callbacks[153] = (delegate* unmanaged)&_getFieldThreadLocalStoreID; + callbacks[154] = (delegate* unmanaged)&_addActiveDependency; + callbacks[155] = (delegate* unmanaged)&_GetDelegateCtor; + callbacks[156] = (delegate* unmanaged)&_MethodCompileComplete; + callbacks[157] = (delegate* unmanaged)&_getTailCallHelpers; + callbacks[158] = (delegate* unmanaged)&_convertPInvokeCalliToCall; + callbacks[159] = (delegate* unmanaged)&_notifyInstructionSetUsage; + callbacks[160] = (delegate* unmanaged)&_updateEntryPointForTailCall; + callbacks[161] = (delegate* unmanaged)&_allocMem; + callbacks[162] = (delegate* unmanaged)&_reserveUnwindInfo; + callbacks[163] = (delegate* unmanaged)&_allocUnwindInfo; + callbacks[164] = (delegate* unmanaged)&_allocGCInfo; + callbacks[165] = (delegate* unmanaged)&_setEHcount; + callbacks[166] = (delegate* unmanaged)&_setEHinfo; + callbacks[167] = (delegate* unmanaged)&_logMsg; + callbacks[168] = (delegate* unmanaged)&_doAssert; + callbacks[169] = (delegate* unmanaged)&_reportFatalError; + callbacks[170] = (delegate* unmanaged)&_getPgoInstrumentationResults; + callbacks[171] = (delegate* unmanaged)&_allocPgoInstrumentationBySchema; + callbacks[172] = (delegate* unmanaged)&_recordCallSite; + callbacks[173] = (delegate* unmanaged)&_recordRelocation; + callbacks[174] = (delegate* unmanaged)&_getRelocTypeHint; + callbacks[175] = (delegate* unmanaged)&_getExpectedTargetArchitecture; + callbacks[176] = (delegate* unmanaged)&_getJitFlags; return (IntPtr)callbacks; } diff --git a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs index 05ca31588c1c2..cc087e8b31e21 100644 --- a/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs +++ b/src/coreclr/tools/Common/JitInterface/CorInfoImpl.cs @@ -9,6 +9,7 @@ using System.Runtime.CompilerServices; using System.Runtime.ExceptionServices; using System.Runtime.InteropServices; +using System.Text.Unicode; #if SUPPORT_JIT using Internal.Runtime.CompilerServices; @@ -1830,6 +1831,21 @@ private int getStringLiteral(CORINFO_MODULE_STRUCT_* module, uint metaTOK, char* return str.Length; } +#pragma warning disable CA1822 // Mark members as static + private int objectToString(void* handle, byte* buffer, int bufferSize) +#pragma warning restore CA1822 // Mark members as static + { + Debug.Assert(bufferSize > 0 && handle != null && buffer != null); + + // NOTE: this function is used for pinned/frozen handles + // it doesn't need to null-terminate the string + + ReadOnlySpan objStr = HandleToObject((IntPtr)handle).ToString(); + var bufferSpan = new Span(buffer, bufferSize); + Utf8.FromUtf16(objStr, bufferSpan, out _, out int written); + return written; + } + private CorInfoType asCorInfoType(CORINFO_CLASS_STRUCT_* cls) { var type = HandleToObject(cls); @@ -2327,6 +2343,13 @@ private CorInfoHelpFunc getUnBoxHelper(CORINFO_CLASS_STRUCT_* cls) return type.IsNullable ? CorInfoHelpFunc.CORINFO_HELP_UNBOX_NULLABLE : CorInfoHelpFunc.CORINFO_HELP_UNBOX; } +#pragma warning disable CA1822 // Mark members as static + private void* getRuntimeTypePointer(CORINFO_CLASS_STRUCT_* cls) +#pragma warning restore CA1822 // Mark members as static + { + return (void*)IntPtr.Zero; + } + private byte* getHelperName(CorInfoHelpFunc helpFunc) { return (byte*)GetPin(StringToUTF8(helpFunc.ToString())); diff --git a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt index b69ab664bd483..0294eced60258 100644 --- a/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt +++ b/src/coreclr/tools/Common/JitInterface/ThunkGenerator/ThunkInput.txt @@ -192,6 +192,7 @@ FUNCTIONS bool isValidToken(CORINFO_MODULE_HANDLE module, unsigned metaTOK) bool isValidStringRef(CORINFO_MODULE_HANDLE module, unsigned metaTOK) int getStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, char16_t* buffer, int bufferSize) + int objectToString(void* handle, char* buffer, int bufferSize) CorInfoType asCorInfoType(CORINFO_CLASS_HANDLE cls) const char* getClassName(CORINFO_CLASS_HANDLE cls) const char* getClassNameFromMetadata(CORINFO_CLASS_HANDLE cls, const char **namespaceName) @@ -221,6 +222,7 @@ FUNCTIONS CORINFO_CLASS_HANDLE getTypeForBox(CORINFO_CLASS_HANDLE cls) CorInfoHelpFunc getBoxHelper(CORINFO_CLASS_HANDLE cls) CorInfoHelpFunc getUnBoxHelper(CORINFO_CLASS_HANDLE cls) + void* getRuntimeTypePointer(CORINFO_CLASS_HANDLE cls) bool getReadyToRunHelper(CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_LOOKUP_KIND * pGenericLookupKind, CorInfoHelpFunc id, CORINFO_CONST_LOOKUP *pLookup) void getReadyToRunDelegateCtorHelper(CORINFO_RESOLVED_TOKEN * pTargetMethod, mdToken targetConstraint, CORINFO_CLASS_HANDLE delegateType, CORINFO_LOOKUP *pLookup) const char* getHelperName(CorInfoHelpFunc helpFunc) diff --git a/src/coreclr/tools/aot/jitinterface/jitinterface.h b/src/coreclr/tools/aot/jitinterface/jitinterface.h index 96cb5bbb40967..f12f60b98cb9c 100644 --- a/src/coreclr/tools/aot/jitinterface/jitinterface.h +++ b/src/coreclr/tools/aot/jitinterface/jitinterface.h @@ -48,6 +48,7 @@ struct JitInterfaceCallbacks bool (* isValidToken)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_MODULE_HANDLE module, unsigned metaTOK); bool (* isValidStringRef)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_MODULE_HANDLE module, unsigned metaTOK); int (* getStringLiteral)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_MODULE_HANDLE module, unsigned metaTOK, char16_t* buffer, int bufferSize); + int (* objectToString)(void * thisHandle, CorInfoExceptionClass** ppException, void* handle, char* buffer, int bufferSize); CorInfoType (* asCorInfoType)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); const char* (* getClassName)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); const char* (* getClassNameFromMetadata)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls, const char** namespaceName); @@ -77,6 +78,7 @@ struct JitInterfaceCallbacks CORINFO_CLASS_HANDLE (* getTypeForBox)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); CorInfoHelpFunc (* getBoxHelper)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); CorInfoHelpFunc (* getUnBoxHelper)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); + void* (* getRuntimeTypePointer)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_CLASS_HANDLE cls); bool (* getReadyToRunHelper)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, CORINFO_CONST_LOOKUP* pLookup); void (* getReadyToRunDelegateCtorHelper)(void * thisHandle, CorInfoExceptionClass** ppException, CORINFO_RESOLVED_TOKEN* pTargetMethod, unsigned int targetConstraint, CORINFO_CLASS_HANDLE delegateType, CORINFO_LOOKUP* pLookup); const char* (* getHelperName)(void * thisHandle, CorInfoExceptionClass** ppException, CorInfoHelpFunc helpFunc); @@ -563,6 +565,17 @@ class JitInterfaceWrapper : public ICorJitInfo return temp; } + virtual int objectToString( + void* handle, + char* buffer, + int bufferSize) +{ + CorInfoExceptionClass* pException = nullptr; + int temp = _callbacks->objectToString(_thisHandle, &pException, handle, buffer, bufferSize); + if (pException != nullptr) throw pException; + return temp; +} + virtual CorInfoType asCorInfoType( CORINFO_CLASS_HANDLE cls) { @@ -841,6 +854,15 @@ class JitInterfaceWrapper : public ICorJitInfo return temp; } + virtual void* getRuntimeTypePointer( + CORINFO_CLASS_HANDLE cls) +{ + CorInfoExceptionClass* pException = nullptr; + void* temp = _callbacks->getRuntimeTypePointer(_thisHandle, &pException, cls); + if (pException != nullptr) throw pException; + return temp; +} + virtual bool getReadyToRunHelper( CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, diff --git a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h index ce147abc89be6..a40f741eea317 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/lwmlist.h @@ -138,6 +138,7 @@ LWM(GetTypeForPrimitiveValueClass, DWORDLONG, DWORD) LWM(GetTypeForPrimitiveNumericClass, DWORDLONG, DWORD) LWM(GetUnboxedEntry, DWORDLONG, DLD); LWM(GetUnBoxHelper, DWORDLONG, DWORD) +LWM(GetRuntimeTypePointer, DWORDLONG, DWORDLONG) LWM(GetVarArgsHandle, GetVarArgsHandleValue, DLDL) LWM(GetVars, DWORDLONG, Agnostic_GetVars) LWM(InitClass, Agnostic_InitClass, DWORD) @@ -148,6 +149,7 @@ LWM(IsIntrinsicType, DWORDLONG, DWORD) LWM(IsSDArray, DWORDLONG, DWORD) LWM(IsValidStringRef, DLD, DWORD) LWM(GetStringLiteral, DLDD, DD) +LWM(ObjectToString, DLD, DD) LWM(IsValidToken, DLD, DWORD) LWM(IsValueClass, DWORDLONG, DWORD) LWM(MergeClasses, DLDL, DWORDLONG) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp index 23c52a3ebaec5..5eea6f742ba21 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.cpp @@ -2187,6 +2187,29 @@ CorInfoHelpFunc MethodContext::repGetUnBoxHelper(CORINFO_CLASS_HANDLE cls) return result; } +void MethodContext::recGetRuntimeTypePointer(CORINFO_CLASS_HANDLE cls, void* result) +{ + if (GetRuntimeTypePointer == nullptr) + GetRuntimeTypePointer = new LightWeightMap(); + + DWORDLONG key = CastHandle(cls); + DWORDLONG value = (DWORDLONG)result; + GetRuntimeTypePointer->Add(key, value); + DEBUG_REC(dmpGetRuntimeTypePointer(key, value)); +} +void MethodContext::dmpGetRuntimeTypePointer(DWORDLONG key, DWORDLONG value) +{ + printf("GetRuntimeTypePointer key cls-%016llX, value res-%016llX", key, value); +} +void* MethodContext::repGetRuntimeTypePointer(CORINFO_CLASS_HANDLE cls) +{ + DWORDLONG key = CastHandle(cls); + AssertMapAndKeyExist(GetRuntimeTypePointer, key, ": key %016llX", key); + DWORDLONG value = GetRuntimeTypePointer->Get(key); + DEBUG_REP(dmpGetRuntimeTypePointer(key, value)); + return (void*)value; +} + void MethodContext::recGetReadyToRunHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, @@ -4874,6 +4897,67 @@ int MethodContext::repGetStringLiteral(CORINFO_MODULE_HANDLE module, unsigned me } } +void MethodContext::recObjectToString(void* handle, char* buffer, int bufferSize, int length) +{ + if (ObjectToString == nullptr) + ObjectToString = new LightWeightMap(); + + DLD key; + ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding + key.A = CastHandle(handle); + key.B = (DWORD)bufferSize; + + DWORD strBuf = (DWORD)-1; + if (buffer != nullptr && length != -1) + { + int bufferRealSize = min(length, bufferSize); + strBuf = (DWORD)ObjectToString->AddBuffer((unsigned char*)buffer, (unsigned int)bufferRealSize); + } + + DD value; + value.A = (DWORD)length; + value.B = (DWORD)strBuf; + + ObjectToString->Add(key, value); + DEBUG_REC(dmpObjectToString(key, value)); +} +void MethodContext::dmpObjectToString(DLD key, DD value) +{ + printf("ObjectToString key hnd-%016llX bufSize-%u, len-%u", key.A, key.B, value.A); + ObjectToString->Unlock(); +} +int MethodContext::repObjectToString(void* handle, char* buffer, int bufferSize) +{ + if (ObjectToString == nullptr) + { + return -1; + } + + DLD key; + ZeroMemory(&key, sizeof(key)); // Zero key including any struct padding + key.A = CastHandle(handle); + key.B = (DWORD)bufferSize; + + int itemIndex = ObjectToString->GetIndex(key); + if (itemIndex < 0) + { + return -1; + } + else + { + DD value = ObjectToString->Get(key); + DEBUG_REP(dmpObjectToString(key, value)); + int srcBufferLength = (int)value.A; + if (buffer != nullptr && srcBufferLength > 0) + { + char* srcBuffer = (char*)ObjectToString->GetBuffer(value.B); + Assert(srcBuffer != nullptr); + memcpy(buffer, srcBuffer, min(srcBufferLength, bufferSize)); + } + return srcBufferLength; + } +} + void MethodContext::recGetHelperName(CorInfoHelpFunc funcNum, const char* result) { if (GetHelperName == nullptr) diff --git a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h index f9769119e20b5..96c19e8664d78 100644 --- a/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h +++ b/src/coreclr/tools/superpmi/superpmi-shared/methodcontext.h @@ -310,6 +310,10 @@ class MethodContext void dmpGetUnBoxHelper(DWORDLONG key, DWORD value); CorInfoHelpFunc repGetUnBoxHelper(CORINFO_CLASS_HANDLE cls); + void recGetRuntimeTypePointer(CORINFO_CLASS_HANDLE cls, void* result); + void dmpGetRuntimeTypePointer(DWORDLONG key, DWORDLONG value); + void* repGetRuntimeTypePointer(CORINFO_CLASS_HANDLE cls); + void recGetReadyToRunHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, @@ -618,6 +622,10 @@ class MethodContext void dmpGetStringLiteral(DLDD key, DD value); int repGetStringLiteral(CORINFO_MODULE_HANDLE module, unsigned metaTOK, char16_t* buffer, int bufferSize); + void recObjectToString(void* handle, char* buffer, int bufferSize, int length); + void dmpObjectToString(DLD key, DD value); + int repObjectToString(void* handle, char* buffer, int bufferSize); + void recGetHelperName(CorInfoHelpFunc funcNum, const char* result); void dmpGetHelperName(DWORD key, DWORD value); const char* repGetHelperName(CorInfoHelpFunc funcNum); @@ -1129,6 +1137,8 @@ enum mcPackets Packet_UpdateEntryPointForTailCall = 193, Packet_GetLoongArch64PassStructInRegisterFlags = 194, Packet_GetExactClasses = 195, + Packet_GetRuntimeTypePointer = 196, + Packet_ObjectToString = 197, }; void SetDebugDumpVariables(); diff --git a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp index ceb3f0b9e38ba..b19faebf60967 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-collector/icorjitinfo.cpp @@ -453,6 +453,17 @@ int interceptor_ICJI::getStringLiteral(CORINFO_MODULE_HANDLE module, /* IN * return temp; } +int interceptor_ICJI::objectToString(void* handle, /* IN */ + char* buffer, /* OUT */ + int bufferSize /* IN */ + ) +{ + mc->cr->AddCall("objectToString"); + int temp = original_ICorJitInfo->objectToString(handle, buffer, bufferSize); + mc->recObjectToString(handle, buffer, bufferSize, temp); + return temp; +} + /**********************************************************************************/ // // ICorClassInfo @@ -779,6 +790,14 @@ CorInfoHelpFunc interceptor_ICJI::getUnBoxHelper(CORINFO_CLASS_HANDLE cls) return temp; } +void* interceptor_ICJI::getRuntimeTypePointer(CORINFO_CLASS_HANDLE cls) +{ + mc->cr->AddCall("getRuntimeTypePointer"); + void* temp = original_ICorJitInfo->getRuntimeTypePointer(cls); + mc->recGetRuntimeTypePointer(cls, temp); + return temp; +} + bool interceptor_ICJI::getReadyToRunHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, diff --git a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp index 4f8ed3ab023d6..2a12825c89907 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-counter/icorjitinfo.cpp @@ -314,6 +314,15 @@ int interceptor_ICJI::getStringLiteral( return original_ICorJitInfo->getStringLiteral(module, metaTOK, buffer, bufferSize); } +int interceptor_ICJI::objectToString( + void* handle, + char* buffer, + int bufferSize) +{ + mcs->AddCall("objectToString"); + return original_ICorJitInfo->objectToString(handle, buffer, bufferSize); +} + CorInfoType interceptor_ICJI::asCorInfoType( CORINFO_CLASS_HANDLE cls) { @@ -535,6 +544,13 @@ CorInfoHelpFunc interceptor_ICJI::getUnBoxHelper( return original_ICorJitInfo->getUnBoxHelper(cls); } +void* interceptor_ICJI::getRuntimeTypePointer( + CORINFO_CLASS_HANDLE cls) +{ + mcs->AddCall("getRuntimeTypePointer"); + return original_ICorJitInfo->getRuntimeTypePointer(cls); +} + bool interceptor_ICJI::getReadyToRunHelper( CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, diff --git a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp index 7da0d2ebb4a45..808ccc3ab473d 100644 --- a/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi-shim-simple/icorjitinfo.cpp @@ -277,6 +277,14 @@ int interceptor_ICJI::getStringLiteral( return original_ICorJitInfo->getStringLiteral(module, metaTOK, buffer, bufferSize); } +int interceptor_ICJI::objectToString( + void* handle, + char* buffer, + int bufferSize) +{ + return original_ICorJitInfo->objectToString(handle, buffer, bufferSize); +} + CorInfoType interceptor_ICJI::asCorInfoType( CORINFO_CLASS_HANDLE cls) { @@ -469,6 +477,12 @@ CorInfoHelpFunc interceptor_ICJI::getUnBoxHelper( return original_ICorJitInfo->getUnBoxHelper(cls); } +void* interceptor_ICJI::getRuntimeTypePointer( + CORINFO_CLASS_HANDLE cls) +{ + return original_ICorJitInfo->getRuntimeTypePointer(cls); +} + bool interceptor_ICJI::getReadyToRunHelper( CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, diff --git a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp index 218123a05d891..efdfafffb8d3b 100644 --- a/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp +++ b/src/coreclr/tools/superpmi/superpmi/icorjitinfo.cpp @@ -388,6 +388,15 @@ int MyICJI::getStringLiteral(CORINFO_MODULE_HANDLE module, /* IN */ return jitInstance->mc->repGetStringLiteral(module, metaTOK, buffer, bufferSize); } +int MyICJI::objectToString(void* handle, /* IN */ + char* buffer, /* OUT */ + int bufferSize /* IN */ + ) +{ + jitInstance->mc->cr->AddCall("objectToString"); + return jitInstance->mc->repObjectToString(handle, buffer, bufferSize); +} + /**********************************************************************************/ // // ICorClassInfo @@ -663,6 +672,13 @@ CorInfoHelpFunc MyICJI::getUnBoxHelper(CORINFO_CLASS_HANDLE cls) return result; } +void* MyICJI::getRuntimeTypePointer(CORINFO_CLASS_HANDLE cls) +{ + jitInstance->mc->cr->AddCall("getRuntimeTypePointer"); + void* result = jitInstance->mc->repGetRuntimeTypePointer(cls); + return result; +} + bool MyICJI::getReadyToRunHelper(CORINFO_RESOLVED_TOKEN* pResolvedToken, CORINFO_LOOKUP_KIND* pGenericLookupKind, CorInfoHelpFunc id, diff --git a/src/coreclr/vm/appdomain.cpp b/src/coreclr/vm/appdomain.cpp index ef560aa44776c..76421d72dfce7 100644 --- a/src/coreclr/vm/appdomain.cpp +++ b/src/coreclr/vm/appdomain.cpp @@ -92,7 +92,7 @@ SPTR_IMPL(SystemDomain, SystemDomain, m_pSystemDomain); #ifndef DACCESS_COMPILE // Base Domain Statics -CrstStatic BaseDomain::m_SpecialStaticsCrst; +CrstStatic BaseDomain::m_MethodTableExposedClassObjectCrst; int BaseDomain::m_iNumberOfProcessors = 0; @@ -556,7 +556,7 @@ OBJECTHANDLE ThreadStaticHandleTable::AllocateHandles(DWORD nRequested) //***************************************************************************** void BaseDomain::Attach() { - m_SpecialStaticsCrst.Init(CrstSpecialStatics); + m_MethodTableExposedClassObjectCrst.Init(CrstMethodTableExposedObject); } BaseDomain::BaseDomain() diff --git a/src/coreclr/vm/appdomain.hpp b/src/coreclr/vm/appdomain.hpp index d56157f8e6ee6..ecf13313bef38 100644 --- a/src/coreclr/vm/appdomain.hpp +++ b/src/coreclr/vm/appdomain.hpp @@ -1094,6 +1094,12 @@ class BaseDomain return &m_crstLoaderAllocatorReferences; } + static CrstStatic* GetMethodTableExposedClassObjectLock() + { + LIMITED_METHOD_CONTRACT; + return &m_MethodTableExposedClassObjectCrst; + } + void AssertLoadLockHeld() { _ASSERTE(m_FileLoadLock.HasLock()); @@ -1135,7 +1141,7 @@ class BaseDomain #endif // FEATURE_COMINTEROP // Protects allocation of slot IDs for thread statics - static CrstStatic m_SpecialStaticsCrst; + static CrstStatic m_MethodTableExposedClassObjectCrst; public: // Only call this routine when you can guarantee there are no diff --git a/src/coreclr/vm/frozenobjectheap.cpp b/src/coreclr/vm/frozenobjectheap.cpp index cedade43fa125..781c2a710f51d 100644 --- a/src/coreclr/vm/frozenobjectheap.cpp +++ b/src/coreclr/vm/frozenobjectheap.cpp @@ -11,15 +11,12 @@ FrozenObjectHeapManager::FrozenObjectHeapManager(): m_Crst(CrstFrozenObjectHeap, CRST_UNSAFE_COOPGC), - m_CurrentSegment(nullptr), - m_Enabled(CLRConfig::GetConfigValue(CLRConfig::INTERNAL_UseFrozenObjectHeap) != 0) + m_CurrentSegment(nullptr) { } // Allocates an object of the give size (including header) on a frozen segment. -// May return nullptr in the following cases: -// 1) DOTNET_UseFrozenObjectHeap is 0 (disabled) -// 2) Object is too large (large than FOH_COMMIT_SIZE) +// May return nullptr if object is too large (larger than FOH_COMMIT_SIZE) // in such cases caller is responsible to find a more appropriate heap to allocate it Object* FrozenObjectHeapManager::TryAllocateObject(PTR_MethodTable type, size_t objectSize) { @@ -37,12 +34,6 @@ Object* FrozenObjectHeapManager::TryAllocateObject(PTR_MethodTable type, size_t CrstHolder ch(&m_Crst); - if (!m_Enabled) - { - // Disabled via DOTNET_UseFrozenObjectHeap=0 - return nullptr; - } - _ASSERT(type != nullptr); _ASSERT(FOH_COMMIT_SIZE >= MIN_OBJECT_SIZE); _ASSERT(FOH_SEGMENT_SIZE > FOH_COMMIT_SIZE); @@ -85,7 +76,6 @@ Object* FrozenObjectHeapManager::TryAllocateObject(PTR_MethodTable type, size_t #endif // !FEATURE_BASICFREEZE } - FrozenObjectSegment::FrozenObjectSegment(): m_pStart(nullptr), m_pCurrent(nullptr), diff --git a/src/coreclr/vm/frozenobjectheap.h b/src/coreclr/vm/frozenobjectheap.h index 703c3aaa6fc45..50c2a15f367e4 100644 --- a/src/coreclr/vm/frozenobjectheap.h +++ b/src/coreclr/vm/frozenobjectheap.h @@ -33,7 +33,6 @@ class FrozenObjectHeapManager Crst m_Crst; SArray m_FrozenSegments; FrozenObjectSegment* m_CurrentSegment; - bool m_Enabled; }; class FrozenObjectSegment diff --git a/src/coreclr/vm/jitinterface.cpp b/src/coreclr/vm/jitinterface.cpp index ca9aa65f9ce0c..2aa473dc6e9d7 100644 --- a/src/coreclr/vm/jitinterface.cpp +++ b/src/coreclr/vm/jitinterface.cpp @@ -715,6 +715,51 @@ int CEEInfo::getStringLiteral ( return result; } +int CEEInfo::objectToString ( + void* handle, + char* buffer, + int bufferSize) +{ + CONTRACTL{ + THROWS; + GC_TRIGGERS; + MODE_PREEMPTIVE; + } CONTRACTL_END; + + int charsCount = 0; + + // NOTE: this function is used for pinned/frozen handles + // it doesn't need to null-terminate the string + + _ASSERT(handle != nullptr && buffer != nullptr && bufferSize > 0); + + JIT_TO_EE_TRANSITION(); + + Object* obj = (Object*)handle; + + GCX_COOP(); + + StackSString stackStr; + + // Currently only supported for String and RuntimeType + if (obj->GetMethodTable()->IsString()) + { + ((StringObject*)obj)->GetSString(stackStr); + } + else if (obj->GetMethodTable() == g_pRuntimeTypeClass) + { + ((ReflectClassBaseObject*)obj)->GetType().GetName(stackStr); + } + + const UTF8* utf8data = stackStr.GetUTF8(); + charsCount = stackStr.GetCount(); + memcpy((BYTE*)buffer, (BYTE*)utf8data, min(bufferSize, charsCount)); + + EE_TO_JIT_TRANSITION(); + + return charsCount; +} + /* static */ size_t CEEInfo::findNameOfToken (Module* module, mdToken metaTOK, @@ -5945,6 +5990,31 @@ CorInfoHelpFunc CEEInfo::getUnBoxHelper(CORINFO_CLASS_HANDLE clsHnd) return CORINFO_HELP_UNBOX; } +/***********************************************************************/ +void* CEEInfo::getRuntimeTypePointer(CORINFO_CLASS_HANDLE clsHnd) +{ + CONTRACTL{ + THROWS; + GC_TRIGGERS; + MODE_PREEMPTIVE; + } CONTRACTL_END; + + void* pointer = nullptr; + + JIT_TO_EE_TRANSITION(); + + TypeHandle typeHnd(clsHnd); + if (!typeHnd.IsCanonicalSubtype() && typeHnd.IsManagedClassObjectPinned()) + { + GCX_COOP(); + pointer = OBJECTREFToObject(typeHnd.GetManagedClassObject()); + } + + EE_TO_JIT_TRANSITION(); + + return pointer; +} + /***********************************************************************/ bool CEEInfo::getReadyToRunHelper( CORINFO_RESOLVED_TOKEN * pResolvedToken, diff --git a/src/coreclr/vm/methodtable.cpp b/src/coreclr/vm/methodtable.cpp index e61162ac553c8..d42d4e3efc145 100644 --- a/src/coreclr/vm/methodtable.cpp +++ b/src/coreclr/vm/methodtable.cpp @@ -4219,26 +4219,7 @@ OBJECTREF MethodTable::GetManagedClassObject() { // Make sure that we have been restored CheckRestore(); - - REFLECTCLASSBASEREF refClass = NULL; - GCPROTECT_BEGIN(refClass); - refClass = (REFLECTCLASSBASEREF) AllocateObject(g_pRuntimeTypeClass); - - LoaderAllocator *pLoaderAllocator = GetLoaderAllocator(); - - ((ReflectClassBaseObject*)OBJECTREFToObject(refClass))->SetType(TypeHandle(this)); - ((ReflectClassBaseObject*)OBJECTREFToObject(refClass))->SetKeepAlive(pLoaderAllocator->GetExposedObject()); - - // Let all threads fight over who wins using InterlockedCompareExchange. - // Only the winner can set m_ExposedClassObject from NULL. - LOADERHANDLE exposedClassObjectHandle = pLoaderAllocator->AllocateHandle(refClass); - - if (InterlockedCompareExchangeT(&GetWriteableDataForWrite()->m_hExposedClassObject, exposedClassObjectHandle, static_cast(NULL))) - { - pLoaderAllocator->FreeHandle(exposedClassObjectHandle); - } - - GCPROTECT_END(); + TypeHandle(this).AllocateManagedClassObject(&GetWriteableDataForWrite()->m_hExposedClassObject); } RETURN(GetManagedClassObjectIfExists()); } diff --git a/src/coreclr/vm/methodtable.h b/src/coreclr/vm/methodtable.h index 07792d5fbf36d..d278196cb6474 100644 --- a/src/coreclr/vm/methodtable.h +++ b/src/coreclr/vm/methodtable.h @@ -299,11 +299,9 @@ struct MethodTableWriteableData }; DWORD m_dwFlags; // Lot of empty bits here. - /* - * m_hExposedClassObject is LoaderAllocator slot index to - * a RuntimeType instance for this class. - */ - LOADERHANDLE m_hExposedClassObject; + // Non-unloadable context: internal RuntimeType object handle + // Unloadable context: slot index in LoaderAllocator's pinned table + RUNTIMETYPEHANDLE m_hExposedClassObject; #ifdef _DEBUG // to avoid verify same method table too many times when it's not changing, we cache the GC count @@ -335,7 +333,7 @@ struct MethodTableWriteableData #endif - inline LOADERHANDLE GetExposedClassObjectHandle() const + inline RUNTIMETYPEHANDLE GetExposedClassObjectHandle() const { LIMITED_METHOD_CONTRACT; return m_hExposedClassObject; @@ -2718,7 +2716,6 @@ class MethodTable OBJECTREF GetManagedClassObject(); OBJECTREF GetManagedClassObjectIfExists(); - // ------------------------------------------------------------------ // Private part of MethodTable // ------------------------------------------------------------------ diff --git a/src/coreclr/vm/methodtable.inl b/src/coreclr/vm/methodtable.inl index 8f8f8178e2602..d7b7d263ff96e 100644 --- a/src/coreclr/vm/methodtable.inl +++ b/src/coreclr/vm/methodtable.inl @@ -1334,19 +1334,16 @@ inline OBJECTHANDLE MethodTable::GetLoaderAllocatorObjectHandle() return GetLoaderAllocator()->GetLoaderAllocatorObjectHandle(); } +#ifndef DACCESS_COMPILE //========================================================================================== FORCEINLINE OBJECTREF MethodTable::GetManagedClassObjectIfExists() { LIMITED_METHOD_CONTRACT; - // Logging will be done by the slow path - LOADERHANDLE handle = GetWriteableData_NoLogging()->GetExposedClassObjectHandle(); + const RUNTIMETYPEHANDLE handle = GetWriteableData_NoLogging()->m_hExposedClassObject; OBJECTREF retVal; - - // GET_LOADERHANDLE_VALUE_FAST macro is inlined here to let us give hint to the compiler - // when the return value is not null. - if (!LoaderAllocator::GetHandleValueFast(handle, &retVal) && + if (!TypeHandle::GetManagedClassObjectFromHandleFast(handle, &retVal) && !GetLoaderAllocator()->GetHandleValueFastPhase2(handle, &retVal)) { return NULL; @@ -1355,6 +1352,7 @@ FORCEINLINE OBJECTREF MethodTable::GetManagedClassObjectIfExists() COMPILER_ASSUME(retVal != NULL); return retVal; } +#endif //========================================================================================== inline void MethodTable::SetIsArray(CorElementType arrayType) diff --git a/src/coreclr/vm/typedesc.cpp b/src/coreclr/vm/typedesc.cpp index f613addf1418c..1812a0d4bd893 100644 --- a/src/coreclr/vm/typedesc.cpp +++ b/src/coreclr/vm/typedesc.cpp @@ -492,26 +492,9 @@ OBJECTREF ParamTypeDesc::GetManagedClassObject() } CONTRACTL_END; - if (m_hExposedClassObject == NULL) { - REFLECTCLASSBASEREF refClass = NULL; - GCPROTECT_BEGIN(refClass); - refClass = (REFLECTCLASSBASEREF) AllocateObject(g_pRuntimeTypeClass); - - LoaderAllocator *pLoaderAllocator = GetLoaderAllocator(); - TypeHandle th = TypeHandle(this); - ((ReflectClassBaseObject*)OBJECTREFToObject(refClass))->SetType(th); - ((ReflectClassBaseObject*)OBJECTREFToObject(refClass))->SetKeepAlive(pLoaderAllocator->GetExposedObject()); - - // Let all threads fight over who wins using InterlockedCompareExchange. - // Only the winner can set m_hExposedClassObject from NULL. - LOADERHANDLE hExposedClassObject = pLoaderAllocator->AllocateHandle(refClass); - - if (InterlockedCompareExchangeT(&m_hExposedClassObject, hExposedClassObject, static_cast(NULL))) - { - pLoaderAllocator->FreeHandle(hExposedClassObject); - } - - GCPROTECT_END(); + if (m_hExposedClassObject == NULL) + { + TypeHandle(this).AllocateManagedClassObject(&m_hExposedClassObject); } return GetManagedClassObjectIfExists(); } @@ -1596,7 +1579,6 @@ BOOL TypeVarTypeDesc::SatisfiesConstraints(SigTypeContext *pTypeContextOfConstra return TRUE; } - OBJECTREF TypeVarTypeDesc::GetManagedClassObject() { CONTRACTL { @@ -1610,26 +1592,9 @@ OBJECTREF TypeVarTypeDesc::GetManagedClassObject() } CONTRACTL_END; - if (m_hExposedClassObject == NULL) { - REFLECTCLASSBASEREF refClass = NULL; - GCPROTECT_BEGIN(refClass); - refClass = (REFLECTCLASSBASEREF) AllocateObject(g_pRuntimeTypeClass); - - LoaderAllocator *pLoaderAllocator = GetLoaderAllocator(); - TypeHandle th = TypeHandle(this); - ((ReflectClassBaseObject*)OBJECTREFToObject(refClass))->SetType(th); - ((ReflectClassBaseObject*)OBJECTREFToObject(refClass))->SetKeepAlive(pLoaderAllocator->GetExposedObject()); - - // Let all threads fight over who wins using InterlockedCompareExchange. - // Only the winner can set m_hExposedClassObject from NULL. - LOADERHANDLE hExposedClassObject = pLoaderAllocator->AllocateHandle(refClass); - - if (InterlockedCompareExchangeT(&m_hExposedClassObject, hExposedClassObject, static_cast(NULL))) - { - pLoaderAllocator->FreeHandle(hExposedClassObject); - } - - GCPROTECT_END(); + if (m_hExposedClassObject == NULL) + { + TypeHandle(this).AllocateManagedClassObject(&m_hExposedClassObject); } return GetManagedClassObjectIfExists(); } diff --git a/src/coreclr/vm/typedesc.h b/src/coreclr/vm/typedesc.h index 19833eede708b..c4a0a83043e59 100644 --- a/src/coreclr/vm/typedesc.h +++ b/src/coreclr/vm/typedesc.h @@ -240,6 +240,7 @@ class ParamTypeDesc : public TypeDesc { INDEBUGIMPL(BOOL Verify();) +#ifndef DACCESS_COMPILE OBJECTREF GetManagedClassObject(); OBJECTREF GetManagedClassObjectIfExists() @@ -252,18 +253,32 @@ class ParamTypeDesc : public TypeDesc { } CONTRACTL_END; - OBJECTREF objRet = NULL; - GET_LOADERHANDLE_VALUE_FAST(GetLoaderAllocator(), m_hExposedClassObject, &objRet); - return objRet; + const RUNTIMETYPEHANDLE handle = m_hExposedClassObject; + + OBJECTREF retVal; + if (!TypeHandle::GetManagedClassObjectFromHandleFast(handle, &retVal) && + !GetLoaderAllocator()->GetHandleValueFastPhase2(handle, &retVal)) + { + return NULL; + } + + COMPILER_ASSUME(retVal != NULL); + return retVal; } + OBJECTREF GetManagedClassObjectFast() { LIMITED_METHOD_CONTRACT; - OBJECTREF objRet = NULL; - LoaderAllocator::GetHandleValueFast(m_hExposedClassObject, &objRet); - return objRet; + OBJECTREF objRef; + if (!TypeHandle::GetManagedClassObjectFromHandleFast(m_hExposedClassObject, &objRef)) + { + return FALSE; + } + COMPILER_ASSUME(objRef != NULL); + return objRef; } +#endif TypeHandle GetModifiedType() { @@ -286,8 +301,13 @@ class ParamTypeDesc : public TypeDesc { protected: // the m_typeAndFlags field in TypeDesc tell what kind of parameterized type we have - TypeHandle m_Arg; // The type that is being modified - LOADERHANDLE m_hExposedClassObject; // handle back to the internal reflection Type object + + // The type that is being modified + TypeHandle m_Arg; + + // Non-unloadable context: internal RuntimeType object handle + // Unloadable context: slot index in LoaderAllocator's pinned table + RUNTIMETYPEHANDLE m_hExposedClassObject; }; /*************************************************************************/ @@ -358,6 +378,7 @@ class TypeVarTypeDesc : public TypeDesc return m_typeOrMethodDef; } +#ifndef DACCESS_COMPILE OBJECTREF GetManagedClassObject(); OBJECTREF GetManagedClassObjectIfExists() { @@ -369,18 +390,32 @@ class TypeVarTypeDesc : public TypeDesc } CONTRACTL_END; - OBJECTREF objRet = NULL; - GET_LOADERHANDLE_VALUE_FAST(GetLoaderAllocator(), m_hExposedClassObject, &objRet); - return objRet; + const RUNTIMETYPEHANDLE handle = m_hExposedClassObject; + + OBJECTREF retVal; + if (!TypeHandle::GetManagedClassObjectFromHandleFast(handle, &retVal) && + !GetLoaderAllocator()->GetHandleValueFastPhase2(handle, &retVal)) + { + return NULL; + } + + COMPILER_ASSUME(retVal != NULL); + return retVal; } + OBJECTREF GetManagedClassObjectFast() { LIMITED_METHOD_CONTRACT; - OBJECTREF objRet = NULL; - LoaderAllocator::GetHandleValueFast(m_hExposedClassObject, &objRet); - return objRet; + OBJECTREF objRef; + if (!TypeHandle::GetManagedClassObjectFromHandleFast(m_hExposedClassObject, &objRef)) + { + return FALSE; + } + COMPILER_ASSUME(objRef != NULL); + return objRef; } +#endif // Load the owning type. Note that the result is not guaranteed to be full loaded MethodDesc * LoadOwnerMethod(); @@ -425,9 +460,10 @@ class TypeVarTypeDesc : public TypeDesc // Constraints, determined on first call to GetConstraints Volatile m_numConstraints; // -1 until number has been determined PTR_TypeHandle m_constraints; - - // slot index back to the internal reflection Type object - LOADERHANDLE m_hExposedClassObject; + + // Non-unloadable context: internal RuntimeType object handle + // Unloadable context: slot index in LoaderAllocator's pinned table + RUNTIMETYPEHANDLE m_hExposedClassObject; // token for GenericParam entry mdGenericParam m_token; diff --git a/src/coreclr/vm/typehandle.cpp b/src/coreclr/vm/typehandle.cpp index 115aae3154361..88dce11a4fc17 100644 --- a/src/coreclr/vm/typehandle.cpp +++ b/src/coreclr/vm/typehandle.cpp @@ -15,6 +15,7 @@ #include "classloadlevel.h" #include "array.h" #include "castcache.h" +#include "frozenobjectheap.h" #ifdef _DEBUG_IMPL @@ -343,6 +344,63 @@ BOOL TypeHandle::IsCanonicalSubtype() const return (*this == TypeHandle(g_pCanonMethodTableClass)) || IsSharedByGenericInstantiations(); } +#ifndef DACCESS_COMPILE +bool TypeHandle::IsManagedClassObjectPinned() const +{ + LIMITED_METHOD_DAC_CONTRACT; + + // Function pointers are always mapped to typeof(IntPtr) + return !GetLoaderAllocator()->CanUnload() || IsFnPtrType(); +} + +void TypeHandle::AllocateManagedClassObject(RUNTIMETYPEHANDLE* pDest) +{ + REFLECTCLASSBASEREF refClass = NULL; + + PTR_LoaderAllocator allocator = GetLoaderAllocator(); + + if (!allocator->CanUnload()) + { + // Allocate RuntimeType on a frozen segment + // Take a lock here since we don't want to allocate redundant objects which won't be collected + CrstHolder exposedClassLock(AppDomain::GetMethodTableExposedClassObjectLock()); + + if (*pDest == NULL) + { + FrozenObjectHeapManager* foh = SystemDomain::GetFrozenObjectHeapManager(); + Object* obj = foh->TryAllocateObject(g_pRuntimeTypeClass, g_pRuntimeTypeClass->GetBaseSize()); + _ASSERTE(obj != NULL); + // Since objects are aligned we can use the lowest bit as a storage for "is pinned object" flag + _ASSERTE((((SSIZE_T)obj) & 1) == 0); + refClass = (REFLECTCLASSBASEREF)ObjectToOBJECTREF(obj); + refClass->SetType(*this); + RUNTIMETYPEHANDLE handle = (RUNTIMETYPEHANDLE)obj; + // Set the bit to 1 (we'll have to reset it before use) + handle |= 1; + *pDest = handle; + } + } + else + { + GCPROTECT_BEGIN(refClass); + refClass = (REFLECTCLASSBASEREF)AllocateObject(g_pRuntimeTypeClass); + refClass->SetKeepAlive(allocator->GetExposedObject()); + LOADERHANDLE exposedClassObjectHandle = allocator->AllocateHandle(refClass); + _ASSERTE((exposedClassObjectHandle & 1) == 0); + refClass->SetType(*this); + + // Let all threads fight over who wins using InterlockedCompareExchange. + // Only the winner can set m_ExposedClassObject from NULL. + if (InterlockedCompareExchangeT(pDest, exposedClassObjectHandle, static_cast(NULL))) + { + // GC will collect unused instance + allocator->FreeHandle(exposedClassObjectHandle); + } + GCPROTECT_END(); + } +} +#endif + /* static */ BOOL TypeHandle::IsCanonicalSubtypeInstantiation(Instantiation inst) { LIMITED_METHOD_DAC_CONTRACT; diff --git a/src/coreclr/vm/typehandle.h b/src/coreclr/vm/typehandle.h index decfa20df4274..037bc10205e17 100644 --- a/src/coreclr/vm/typehandle.h +++ b/src/coreclr/vm/typehandle.h @@ -323,6 +323,32 @@ class TypeHandle // BOOL IsCanonicalSubtype() const; +#ifndef DACCESS_COMPILE + bool IsManagedClassObjectPinned() const; + + // Allocates a RuntimeType object with the given TypeHandle. If the LoaderAllocator + // represents a not-unloadable context, it allocates the object on a frozen segment + // so the direct reference will be stored to the pDest argument. In case of unloadable + // context, an index to the pinned table will be saved. + void AllocateManagedClassObject(RUNTIMETYPEHANDLE* pDest); + + FORCEINLINE static bool GetManagedClassObjectFromHandleFast(RUNTIMETYPEHANDLE handle, OBJECTREF* pRef) + { + LIMITED_METHOD_CONTRACT; + + // For a non-unloadable context, handle is expected to be either null (is not cached yet) + // or be a direct pointer to a frozen RuntimeType object + + if (handle & 1) + { + // Clear the "is pinned object" bit from the managed reference + *pRef = (OBJECTREF)(handle - 1); + return true; + } + return false; + } +#endif + // Similar to IsCanonicalSubtype, but applied to a vector. static BOOL IsCanonicalSubtypeInstantiation(Instantiation inst); diff --git a/src/coreclr/vm/typehandle.inl b/src/coreclr/vm/typehandle.inl index ffe668a901f76..bd98e25ab0e23 100644 --- a/src/coreclr/vm/typehandle.inl +++ b/src/coreclr/vm/typehandle.inl @@ -232,6 +232,7 @@ inline void TypeHandle::ForEachComponentMethodTable(T &callback) const } } +#ifndef DACCESS_COMPILE FORCEINLINE OBJECTREF TypeHandle::GetManagedClassObjectFast() const { CONTRACTL @@ -276,5 +277,6 @@ FORCEINLINE OBJECTREF TypeHandle::GetManagedClassObjectFast() const return o; } +#endif #endif // _TYPEHANDLE_INL_ diff --git a/src/coreclr/vm/vars.hpp b/src/coreclr/vm/vars.hpp index ca46259c8181e..ccccb411fc2ef 100644 --- a/src/coreclr/vm/vars.hpp +++ b/src/coreclr/vm/vars.hpp @@ -89,16 +89,8 @@ class Crst; class RCWCleanupList; #endif // FEATURE_COMINTEROP -// -// loader handles are opaque types that track object pointers that have a lifetime -// that matches that of a loader allocator -// -struct LOADERHANDLE__ -{ - void* unused; -}; typedef TADDR LOADERHANDLE; - +typedef TADDR RUNTIMETYPEHANDLE; #ifdef DACCESS_COMPILE void OBJECTHANDLE_EnumMemoryRegions(OBJECTHANDLE handle);