Skip to content

Commit 1f1231c

Browse files
EgorBoMichalStrehovskyjkotasjakobbotsch
authored
Allocate RuntimeType objects on Frozen Object Heap (#75573)
Co-authored-by: Michal Strehovský <[email protected]> Co-authored-by: Jan Kotas <[email protected]> Co-authored-by: Jakob Botsch Nielsen <[email protected]>
1 parent 58b6828 commit 1f1231c

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

44 files changed

+748
-371
lines changed

src/coreclr/inc/clrconfigvalues.h

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -404,11 +404,6 @@ CONFIG_DWORD_INFO(INTERNAL_LoaderHeapCallTracing, W("LoaderHeapCallTracing"), 0,
404404
RETAIL_CONFIG_DWORD_INFO(INTERNAL_CodeHeapReserveForJumpStubs, W("CodeHeapReserveForJumpStubs"), 1, "Percentage of code heap to reserve for jump stubs")
405405
RETAIL_CONFIG_DWORD_INFO(INTERNAL_BreakOnOutOfMemoryWithinRange, W("BreakOnOutOfMemoryWithinRange"), 0, "Break before out of memory within range exception is thrown")
406406

407-
///
408-
/// Frozen segments (aka Frozen Object Heap)
409-
///
410-
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.")
411-
412407
///
413408
/// Log
414409
///

src/coreclr/inc/corinfo.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2265,6 +2265,13 @@ class ICorStaticInfo
22652265
int bufferSize /* IN */
22662266
) = 0;
22672267

2268+
// Calls ToString() for given pinned/frozen object handle
2269+
virtual int objectToString (
2270+
void* handle, /* IN */
2271+
char* buffer, /* OUT */
2272+
int bufferSize /* IN */
2273+
) = 0;
2274+
22682275
/**********************************************************************************/
22692276
//
22702277
// ICorClassInfo
@@ -2475,6 +2482,10 @@ class ICorStaticInfo
24752482
CORINFO_CLASS_HANDLE cls
24762483
) = 0;
24772484

2485+
virtual void* getRuntimeTypePointer(
2486+
CORINFO_CLASS_HANDLE cls
2487+
) = 0;
2488+
24782489
virtual bool getReadyToRunHelper(
24792490
CORINFO_RESOLVED_TOKEN * pResolvedToken,
24802491
CORINFO_LOOKUP_KIND * pGenericLookupKind,

src/coreclr/inc/crsttypes.h

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@ enum CrstType
132132
CrstVSDIndirectionCellLock = 114,
133133
CrstWrapperTemplate = 115,
134134
CrstFrozenObjectHeap = 116,
135-
kNumberOfCrstTypes = 117
135+
CrstMethodTableExposedObject = 117,
136+
kNumberOfCrstTypes = 118
136137
};
137138

138139
#endif // __CRST_TYPES_INCLUDED
@@ -259,7 +260,8 @@ int g_rgCrstLevelMap[] =
259260
3, // CrstUnwindInfoTableLock
260261
4, // CrstVSDIndirectionCellLock
261262
3, // CrstWrapperTemplate
262-
0, // CrstFrozenObjectHeap
263+
-1, // CrstFrozenObjectHeap
264+
-1, // CrstMethodTableExposedObject
263265
};
264266

265267
// An array mapping CrstType to a stringized name.
@@ -381,7 +383,8 @@ LPCSTR g_rgCrstNameMap[] =
381383
"CrstUnwindInfoTableLock",
382384
"CrstVSDIndirectionCellLock",
383385
"CrstWrapperTemplate",
384-
"CrstFrozenObjectHeap"
386+
"CrstFrozenObjectHeap",
387+
"CrstMethodTableExposedObject"
385388
};
386389

387390
// Define a special level constant for unordered locks.

src/coreclr/inc/icorjitinfoimpl_generated.h

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,11 @@ int getStringLiteral(
175175
char16_t* buffer,
176176
int bufferSize) override;
177177

178+
int objectToString(
179+
void* handle,
180+
char* buffer,
181+
int bufferSize) override;
182+
178183
CorInfoType asCorInfoType(
179184
CORINFO_CLASS_HANDLE cls) override;
180185

@@ -280,6 +285,9 @@ CorInfoHelpFunc getBoxHelper(
280285
CorInfoHelpFunc getUnBoxHelper(
281286
CORINFO_CLASS_HANDLE cls) override;
282287

288+
void* getRuntimeTypePointer(
289+
CORINFO_CLASS_HANDLE cls) override;
290+
283291
bool getReadyToRunHelper(
284292
CORINFO_RESOLVED_TOKEN* pResolvedToken,
285293
CORINFO_LOOKUP_KIND* pGenericLookupKind,

src/coreclr/inc/jiteeversionguid.h

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ typedef const GUID *LPCGUID;
4343
#define GUID_DEFINED
4444
#endif // !GUID_DEFINED
4545

46-
constexpr GUID JITEEVersionIdentifier = { /* eb8352bd-0a13-4b5b-badb-58f9ecc40c44 */
47-
0xeb8352bd,
48-
0x0a13,
49-
0x4b5b,
50-
{0xba, 0xdb, 0x58, 0xf9, 0xec, 0xc4, 0x0c, 0x44}
46+
constexpr GUID JITEEVersionIdentifier = { /* 11b4ea58-c400-4c3d-995e-4e2f0676f6e8 */
47+
0x11b4ea58,
48+
0xc400,
49+
0x4c3d,
50+
{0x99, 0x5e, 0x4e, 0x2f, 0x6, 0x76, 0xf6, 0xe8}
5151
};
5252

5353
//////////////////////////////////////////////////////////////////////////////////////////////////////////

src/coreclr/jit/ICorJitInfo_API_names.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ DEF_CLR_API(getTokenTypeAsHandle)
4141
DEF_CLR_API(isValidToken)
4242
DEF_CLR_API(isValidStringRef)
4343
DEF_CLR_API(getStringLiteral)
44+
DEF_CLR_API(objectToString)
4445
DEF_CLR_API(asCorInfoType)
4546
DEF_CLR_API(getClassName)
4647
DEF_CLR_API(getClassNameFromMetadata)
@@ -70,6 +71,7 @@ DEF_CLR_API(getSharedCCtorHelper)
7071
DEF_CLR_API(getTypeForBox)
7172
DEF_CLR_API(getBoxHelper)
7273
DEF_CLR_API(getUnBoxHelper)
74+
DEF_CLR_API(getRuntimeTypePointer)
7375
DEF_CLR_API(getReadyToRunHelper)
7476
DEF_CLR_API(getReadyToRunDelegateCtorHelper)
7577
DEF_CLR_API(getHelperName)

src/coreclr/jit/ICorJitInfo_API_wrapper.hpp

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -374,6 +374,17 @@ int WrapICorJitInfo::getStringLiteral(
374374
return temp;
375375
}
376376

377+
int WrapICorJitInfo::objectToString(
378+
void* handle,
379+
char* buffer,
380+
int bufferSize)
381+
{
382+
API_ENTER(objectToString);
383+
int temp = wrapHnd->objectToString(handle, buffer, bufferSize);
384+
API_LEAVE(objectToString);
385+
return temp;
386+
}
387+
377388
CorInfoType WrapICorJitInfo::asCorInfoType(
378389
CORINFO_CLASS_HANDLE cls)
379390
{
@@ -652,6 +663,15 @@ CorInfoHelpFunc WrapICorJitInfo::getUnBoxHelper(
652663
return temp;
653664
}
654665

666+
void* WrapICorJitInfo::getRuntimeTypePointer(
667+
CORINFO_CLASS_HANDLE cls)
668+
{
669+
API_ENTER(getRuntimeTypePointer);
670+
void* temp = wrapHnd->getRuntimeTypePointer(cls);
671+
API_LEAVE(getRuntimeTypePointer);
672+
return temp;
673+
}
674+
655675
bool WrapICorJitInfo::getReadyToRunHelper(
656676
CORINFO_RESOLVED_TOKEN* pResolvedToken,
657677
CORINFO_LOOKUP_KIND* pGenericLookupKind,

src/coreclr/jit/assertionprop.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2149,7 +2149,7 @@ void Compiler::optDebugCheckAssertion(AssertionDsc* assertion)
21492149
break;
21502150
case O1K_LCLVAR:
21512151
assert((lvaGetDesc(assertion->op1.lcl.lclNum)->lvType != TYP_REF) ||
2152-
(assertion->op2.u1.iconVal == 0) || doesMethodHaveFrozenString());
2152+
(assertion->op2.u1.iconVal == 0) || doesMethodHaveFrozenObjects());
21532153
break;
21542154
case O1K_VALUE_NUMBER:
21552155
assert((vnStore->TypeOfVN(assertion->op1.vn) != TYP_REF) || (assertion->op2.u1.iconVal == 0));
@@ -3423,7 +3423,7 @@ GenTree* Compiler::optConstantAssertionProp(AssertionDsc* curAssertion,
34233423

34243424
// Make sure we don't retype const gc handles to TYP_I_IMPL
34253425
// Although, it's possible for e.g. GTF_ICON_STATIC_HDL
3426-
if (!newTree->IsIntegralConst(0) && newTree->IsIconHandle(GTF_ICON_STR_HDL))
3426+
if (!newTree->IsIntegralConst(0) && newTree->IsIconHandle(GTF_ICON_OBJ_HDL))
34273427
{
34283428
if (tree->TypeIs(TYP_BYREF))
34293429
{

src/coreclr/jit/compiler.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9413,6 +9413,11 @@ void cTreeFlags(Compiler* comp, GenTree* tree)
94139413
chars += printf("[ICON_STR_HDL]");
94149414
break;
94159415

9416+
case GTF_ICON_OBJ_HDL:
9417+
9418+
chars += printf("[ICON_OBJ_HDL]");
9419+
break;
9420+
94169421
case GTF_ICON_CONST_PTR:
94179422

94189423
chars += printf("[ICON_CONST_PTR]");

src/coreclr/jit/compiler.h

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6806,7 +6806,7 @@ class Compiler
68066806
#define OMF_HAS_EXPRUNTIMELOOKUP 0x00000080 // Method contains a runtime lookup to an expandable dictionary.
68076807
#define OMF_HAS_PATCHPOINT 0x00000100 // Method contains patchpoints
68086808
#define OMF_NEEDS_GCPOLLS 0x00000200 // Method needs GC polls
6809-
#define OMF_HAS_FROZEN_STRING 0x00000400 // Method has a frozen string (REF constant int), currently only on NativeAOT.
6809+
#define OMF_HAS_FROZEN_OBJECTS 0x00000400 // Method has frozen objects (REF constant int)
68106810
#define OMF_HAS_PARTIAL_COMPILATION_PATCHPOINT 0x00000800 // Method contains partial compilation patchpoints
68116811
#define OMF_HAS_TAILCALL_SUCCESSOR 0x00001000 // Method has potential tail call in a non BBJ_RETURN block
68126812
#define OMF_HAS_MDNEWARRAY 0x00002000 // Method contains 'new' of an MD array
@@ -6831,14 +6831,14 @@ class Compiler
68316831

68326832
void addFatPointerCandidate(GenTreeCall* call);
68336833

6834-
bool doesMethodHaveFrozenString() const
6834+
bool doesMethodHaveFrozenObjects() const
68356835
{
6836-
return (optMethodFlags & OMF_HAS_FROZEN_STRING) != 0;
6836+
return (optMethodFlags & OMF_HAS_FROZEN_OBJECTS) != 0;
68376837
}
68386838

6839-
void setMethodHasFrozenString()
6839+
void setMethodHasFrozenObjects()
68406840
{
6841-
optMethodFlags |= OMF_HAS_FROZEN_STRING;
6841+
optMethodFlags |= OMF_HAS_FROZEN_OBJECTS;
68426842
}
68436843

68446844
bool doesMethodHaveGuardedDevirtualization() const
@@ -7798,7 +7798,7 @@ class Compiler
77987798
const char* eeGetFieldName(CORINFO_FIELD_HANDLE fieldHnd, const char** classNamePtr = nullptr);
77997799

78007800
#if defined(DEBUG)
7801-
const WCHAR* eeGetCPString(size_t stringHandle);
7801+
void eePrintFrozenObjectDescription(const char* prefix, size_t handle);
78027802
unsigned eeTryGetClassSize(CORINFO_CLASS_HANDLE clsHnd);
78037803
const char16_t* eeGetShortClassName(CORINFO_CLASS_HANDLE clsHnd);
78047804
#endif

src/coreclr/jit/ee_il_dll.cpp

Lines changed: 22 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1615,45 +1615,40 @@ const char16_t* Compiler::eeGetShortClassName(CORINFO_CLASS_HANDLE clsHnd)
16151615
return param.classNameWidePtr;
16161616
}
16171617

1618-
const WCHAR* Compiler::eeGetCPString(size_t strHandle)
1618+
void Compiler::eePrintFrozenObjectDescription(const char* prefix, size_t handle)
16191619
{
1620-
#ifdef HOST_UNIX
1621-
return nullptr;
1622-
#else
1623-
char buff[512 + sizeof(CORINFO_String)];
1624-
1625-
// make this bulletproof, so it works even if we are wrong.
1626-
if (ReadProcessMemory(GetCurrentProcess(), (void*)strHandle, buff, 4, nullptr) == 0)
1620+
const int maxStrSize = 64;
1621+
char str[maxStrSize];
1622+
int realLength = this->info.compCompHnd->objectToString((void*)handle, str, maxStrSize);
1623+
if (realLength == -1)
16271624
{
1628-
return (nullptr);
1625+
printf("%s 'unknown frozen object'", prefix);
1626+
return;
16291627
}
1630-
1631-
CORINFO_String* asString = nullptr;
1632-
if (impGetStringClass() == *((CORINFO_CLASS_HANDLE*)strHandle))
1628+
else if (realLength >= maxStrSize)
16331629
{
1634-
// strHandle is a frozen string
1635-
// We assume strHandle is never an "interior" pointer in a frozen string
1636-
// (jit is not expected to perform such foldings)
1637-
asString = (CORINFO_String*)strHandle;
1630+
// string is too long, trim it and null-terminate
1631+
str[maxStrSize - 4] = '.';
1632+
str[maxStrSize - 3] = '.';
1633+
str[maxStrSize - 2] = '.';
1634+
str[maxStrSize - 1] = 0;
16381635
}
16391636
else
16401637
{
1641-
// strHandle is a pinned handle to a string object
1642-
asString = *((CORINFO_String**)strHandle);
1643-
}
1644-
1645-
if (ReadProcessMemory(GetCurrentProcess(), asString, buff, sizeof(buff), nullptr) == 0)
1646-
{
1647-
return (nullptr);
1638+
// objectToString doesn't null-terminate buffer
1639+
str[realLength] = 0;
16481640
}
16491641

1650-
if (asString->stringLen >= 255 || asString->chars[asString->stringLen] != 0)
1642+
for (int i = 0; i < min(maxStrSize, realLength); i++)
16511643
{
1652-
return nullptr;
1644+
// Replace \n and \r symbols with whitespaces
1645+
if (str[i] == '\n' || str[i] == '\r')
1646+
{
1647+
str[i] = ' ';
1648+
}
16531649
}
16541650

1655-
return (WCHAR*)(asString->chars);
1656-
#endif // HOST_UNIX
1651+
printf("%s '%s'\n", prefix, str);
16571652
}
16581653
#else // DEBUG
16591654
void jitprintf(const char* fmt, ...)

src/coreclr/jit/emit.cpp

Lines changed: 6 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -4129,42 +4129,15 @@ void emitter::emitDispCommentForHandle(size_t handle, size_t cookie, GenTreeFlag
41294129

41304130
const char* str = nullptr;
41314131
if (flag == GTF_ICON_STR_HDL)
4132+
{
4133+
str = "string handle";
4134+
}
4135+
else if (flag == GTF_ICON_OBJ_HDL)
41324136
{
41334137
#ifdef DEBUG
4134-
const WCHAR* wstr = emitComp->eeGetCPString(handle);
4135-
// NOTE: eGetCPString always returns nullptr on Linux/ARM
4136-
if (wstr == nullptr)
4137-
{
4138-
str = "string handle";
4139-
}
4140-
else
4141-
{
4142-
const size_t actualLen = wcslen(wstr);
4143-
const size_t maxLength = 63;
4144-
const size_t newLen = min(maxLength, actualLen);
4145-
4146-
// +1 for null terminator
4147-
WCHAR buf[maxLength + 1] = {0};
4148-
wcsncpy(buf, wstr, newLen);
4149-
for (size_t i = 0; i < newLen; i++)
4150-
{
4151-
// Escape \n and \r symbols
4152-
if (buf[i] == L'\n' || buf[i] == L'\r')
4153-
{
4154-
buf[i] = L' ';
4155-
}
4156-
}
4157-
if (actualLen > maxLength)
4158-
{
4159-
// Append "..." for long strings
4160-
buf[maxLength - 3] = L'.';
4161-
buf[maxLength - 2] = L'.';
4162-
buf[maxLength - 1] = L'.';
4163-
}
4164-
printf("%s \"%S\"", commentPrefix, buf);
4165-
}
4138+
emitComp->eePrintFrozenObjectDescription(commentPrefix, handle);
41664139
#else
4167-
str = "string handle";
4140+
str = "frozen object handle";
41684141
#endif
41694142
}
41704143
else if (flag == GTF_ICON_CLASS_HDL)

src/coreclr/jit/emitxarch.cpp

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8756,18 +8756,6 @@ void emitter::emitDispAddrMode(instrDesc* id, bool noDetail)
87568756

87578757
printf("]");
87588758

8759-
// pretty print string if it looks like one
8760-
#ifdef DEBUG
8761-
if ((id->idGCref() == GCT_GCREF) && (id->idIns() == INS_mov) && (id->idAddr()->iiaAddrMode.amBaseReg == REG_NA))
8762-
{
8763-
const WCHAR* str = emitComp->eeGetCPString(disp);
8764-
if (str != nullptr)
8765-
{
8766-
printf(" '%S'", str);
8767-
}
8768-
}
8769-
#endif
8770-
87718759
if (jdsc && !noDetail)
87728760
{
87738761
unsigned cnt = (jdsc->dsSize - 1) / TARGET_POINTER_SIZE;

0 commit comments

Comments
 (0)