Skip to content

Commit

Permalink
Allocate RuntimeType objects on Frozen Object Heap (#75573)
Browse files Browse the repository at this point in the history
Co-authored-by: Michal Strehovský <MichalStrehovsky@users.noreply.github.com>
Co-authored-by: Jan Kotas <jkotas@microsoft.com>
Co-authored-by: Jakob Botsch Nielsen <Jakob.botsch.nielsen@gmail.com>
  • Loading branch information
4 people committed Sep 22, 2022
1 parent 58b6828 commit 1f1231c
Show file tree
Hide file tree
Showing 44 changed files with 748 additions and 371 deletions.
5 changes: 0 additions & 5 deletions src/coreclr/inc/clrconfigvalues.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
///
Expand Down
11 changes: 11 additions & 0 deletions src/coreclr/inc/corinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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,
Expand Down
9 changes: 6 additions & 3 deletions src/coreclr/inc/crsttypes.h
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,8 @@ enum CrstType
CrstVSDIndirectionCellLock = 114,
CrstWrapperTemplate = 115,
CrstFrozenObjectHeap = 116,
kNumberOfCrstTypes = 117
CrstMethodTableExposedObject = 117,
kNumberOfCrstTypes = 118
};

#endif // __CRST_TYPES_INCLUDED
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -381,7 +383,8 @@ LPCSTR g_rgCrstNameMap[] =
"CrstUnwindInfoTableLock",
"CrstVSDIndirectionCellLock",
"CrstWrapperTemplate",
"CrstFrozenObjectHeap"
"CrstFrozenObjectHeap",
"CrstMethodTableExposedObject"
};

// Define a special level constant for unordered locks.
Expand Down
8 changes: 8 additions & 0 deletions src/coreclr/inc/icorjitinfoimpl_generated.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -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,
Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/inc/jiteeversionguid.h
Original file line number Diff line number Diff line change
Expand Up @@ -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}
};

//////////////////////////////////////////////////////////////////////////////////////////////////////////
Expand Down
2 changes: 2 additions & 0 deletions src/coreclr/jit/ICorJitInfo_API_names.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
Expand Down
20 changes: 20 additions & 0 deletions src/coreclr/jit/ICorJitInfo_API_wrapper.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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,
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/jit/assertionprop.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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));
Expand Down Expand Up @@ -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))
{
Expand Down
5 changes: 5 additions & 0 deletions src/coreclr/jit/compiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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]");
Expand Down
12 changes: 6 additions & 6 deletions src/coreclr/jit/compiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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
Expand Down
49 changes: 22 additions & 27 deletions src/coreclr/jit/ee_il_dll.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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, ...)
Expand Down
39 changes: 6 additions & 33 deletions src/coreclr/jit/emit.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
12 changes: 0 additions & 12 deletions src/coreclr/jit/emitxarch.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
Loading

0 comments on commit 1f1231c

Please sign in to comment.