Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reimplement stubs to improve performance #65738

Merged
merged 11 commits into from
Mar 17, 2022
1 change: 0 additions & 1 deletion src/coreclr/inc/daccess.h
Original file line number Diff line number Diff line change
Expand Up @@ -614,7 +614,6 @@ typedef struct _DacGlobals
#endif // TARGET_ARM

ULONG fn__ThePreStubPatchLabel;
ULONG fn__PrecodeFixupThunk;
#ifdef FEATURE_COMINTEROP
ULONG fn__Unknown_AddRef;
ULONG fn__Unknown_AddRefSpecial;
Expand Down
54 changes: 53 additions & 1 deletion src/coreclr/inc/executableallocator.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@

#ifndef DACCESS_COMPILE

//#define LOG_EXECUTABLE_ALLOCATOR_STATISTICS

// This class is responsible for allocation of all the executable memory in the runtime.
class ExecutableAllocator
{
Expand Down Expand Up @@ -49,7 +51,17 @@ class ExecutableAllocator
};

typedef void (*FatalErrorHandler)(UINT errorCode, LPCWSTR pszMessage);

#ifdef LOG_EXECUTABLE_ALLOCATOR_STATISTICS
static int64_t g_mapTimeSum;
static int64_t g_mapTimeWithLockSum;
static int64_t g_unmapTimeSum;
static int64_t g_unmapTimeWithLockSum;
static int64_t g_mapFindRXTimeSum;
static int64_t g_mapCreateTimeSum;

static int64_t g_releaseCount;
static int64_t g_reserveCount;
#endif
// Instance of the allocator
static ExecutableAllocator* g_instance;

Expand Down Expand Up @@ -142,8 +154,28 @@ class ExecutableAllocator
// Initialize the allocator instance
bool Initialize();

#ifdef LOG_EXECUTABLE_ALLOCATOR_STATISTICS
static CRITSEC_COOKIE s_LoggerCriticalSection;

struct LogEntry
{
const char* source;
const char* function;
int line;
int count;
};

static LogEntry s_usageLog[256];
static int s_logMaxIndex;
#endif

public:

#ifdef LOG_EXECUTABLE_ALLOCATOR_STATISTICS
static void LogUsage(const char* source, int line, const char* function);
static void DumpHolderUsage();
#endif

// Return the ExecuteAllocator singleton instance
static ExecutableAllocator* Instance();

Expand Down Expand Up @@ -201,6 +233,8 @@ class ExecutableAllocator
void UnmapRW(void* pRW);
};

#define ExecutableWriterHolder ExecutableWriterHolderNoLog

// Holder class to map read-execute memory as read-write so that it can be modified without using read-write-execute mapping.
// At the moment the implementation is dummy, returning the same addresses for both cases and expecting them to be read-write-execute.
// The class uses the move semantics to ensure proper unmapping in case of re-assigning of the holder value.
Expand Down Expand Up @@ -274,6 +308,24 @@ class ExecutableWriterHolder
{
return m_addressRW;
}

void AssignExecutableWriterHolder(T* addressRX, size_t size)
{
*this = ExecutableWriterHolder(addressRX, size);
}
};

#ifdef LOG_EXECUTABLE_ALLOCATOR_STATISTICS
#undef ExecutableWriterHolder
#ifdef TARGET_UNIX
#define ExecutableWriterHolder ExecutableAllocator::LogUsage(__FILE__, __LINE__, __PRETTY_FUNCTION__); ExecutableWriterHolderNoLog
#define AssignExecutableWriterHolder(addressRX, size) AssignExecutableWriterHolder(addressRX, size); ExecutableAllocator::LogUsage(__FILE__, __LINE__, __PRETTY_FUNCTION__);
#else
#define ExecutableWriterHolder ExecutableAllocator::LogUsage(__FILE__, __LINE__, __FUNCTION__); ExecutableWriterHolderNoLog
#define AssignExecutableWriterHolder(addressRX, size) AssignExecutableWriterHolder(addressRX, size); ExecutableAllocator::LogUsage(__FILE__, __LINE__, __FUNCTION__);
#endif
#else
#define ExecutableWriterHolder ExecutableWriterHolderNoLog
#endif

#endif // !DACCESS_COMPILE
16 changes: 13 additions & 3 deletions src/coreclr/inc/holder.h
Original file line number Diff line number Diff line change
Expand Up @@ -934,15 +934,25 @@ using NonVMComHolder = SpecializedWrapper<_TYPE, DoTheRelease<_TYPE>>;
// } // foo->DecRef() on out of scope
//
//-----------------------------------------------------------------------------

template<typename _TYPE>
class ExecutableWriterHolder;
class ExecutableWriterHolderNoLog;

template <typename TYPE>
class ExecutableAllocator;

template <typename TYPE, typename LOGGER=ExecutableAllocator>
FORCEINLINE void StubRelease(TYPE* value)
{
if (value)
{
ExecutableWriterHolder<TYPE> stubWriterHolder(value, sizeof(TYPE));
#ifdef LOG_EXECUTABLE_ALLOCATOR_STATISTICS
#ifdef TARGET_UNIX
LOGGER::LogUsage(__FILE__, __LINE__, __PRETTY_FUNCTION__);
#else
LOGGER::LogUsage(__FILE__, __LINE__, __FUNCTION__);
#endif
#endif // LOG_EXECUTABLE_ALLOCATOR_STATISTICS
ExecutableWriterHolderNoLog<TYPE> stubWriterHolder(value, sizeof(TYPE));
stubWriterHolder.GetRW()->DecRef();
}
}
Expand Down
42 changes: 33 additions & 9 deletions src/coreclr/inc/loaderheap.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,15 @@ class UnlockedLoaderHeap
friend class ClrDataAccess;
#endif

public:

enum class HeapKind
{
Data,
Executable,
Interleaved
};

private:
// Linked list of ClrVirtualAlloc'd pages
PTR_LoaderHeapBlock m_pFirstBlock;
Expand All @@ -208,12 +217,16 @@ class UnlockedLoaderHeap
// When we need to commit pages from our reserved list, number of bytes to commit at a time
DWORD m_dwCommitBlockSize;

// For interleaved heap (RX pages interleaved with RW ones), this specifies the allocation granularity,
// which is the individual code block size
DWORD m_dwGranularity;

// Range list to record memory ranges in
RangeList * m_pRangeList;

size_t m_dwTotalAlloc;

DWORD m_Options;
HeapKind m_kind;

LoaderHeapFreeBlock *m_pFirstFreeBlock;

Expand Down Expand Up @@ -263,6 +276,7 @@ class UnlockedLoaderHeap

public:
BOOL m_fExplicitControl; // Am I a LoaderHeap or an ExplicitControlLoaderHeap?
void (*m_codePageGenerator)(BYTE* pageBase, BYTE* pageBaseRX);

#ifdef DACCESS_COMPILE
public:
Expand All @@ -283,7 +297,9 @@ class UnlockedLoaderHeap
const BYTE* dwReservedRegionAddress,
SIZE_T dwReservedRegionSize,
RangeList *pRangeList = NULL,
BOOL fMakeExecutable = FALSE);
HeapKind kind = HeapKind::Data,
void (*codePageGenerator)(BYTE* pageBase, BYTE* pageBaseRX) = NULL,
DWORD dwGranularity = 1);

~UnlockedLoaderHeap();
#endif
Expand Down Expand Up @@ -400,6 +416,7 @@ class UnlockedLoaderHeap
}

BOOL IsExecutable();
BOOL IsInterleaved();

public:
#ifdef _DEBUG
Expand Down Expand Up @@ -443,14 +460,18 @@ class LoaderHeap : public UnlockedLoaderHeap, public ILoaderHeapBackout
LoaderHeap(DWORD dwReserveBlockSize,
DWORD dwCommitBlockSize,
RangeList *pRangeList = NULL,
BOOL fMakeExecutable = FALSE,
BOOL fUnlocked = FALSE
UnlockedLoaderHeap::HeapKind kind = UnlockedLoaderHeap::HeapKind::Data,
BOOL fUnlocked = FALSE,
void (*codePageGenerator)(BYTE* pageBase, BYTE* pageBaseRX) = NULL,
DWORD dwGranularity = 1
)
: UnlockedLoaderHeap(dwReserveBlockSize,
dwCommitBlockSize,
NULL, 0,
pRangeList,
fMakeExecutable),
kind,
codePageGenerator,
dwGranularity),
m_CriticalSection(fUnlocked ? NULL : CreateLoaderHeapLock())
{
WRAPPER_NO_CONTRACT;
Expand All @@ -463,15 +484,18 @@ class LoaderHeap : public UnlockedLoaderHeap, public ILoaderHeapBackout
const BYTE* dwReservedRegionAddress,
SIZE_T dwReservedRegionSize,
RangeList *pRangeList = NULL,
BOOL fMakeExecutable = FALSE,
BOOL fUnlocked = FALSE
UnlockedLoaderHeap::HeapKind kind = UnlockedLoaderHeap::HeapKind::Data,
BOOL fUnlocked = FALSE,
void (*codePageGenerator)(BYTE* pageBase, BYTE* pageBaseRX) = NULL,
DWORD dwGranularity = 1
)
: UnlockedLoaderHeap(dwReserveBlockSize,
dwCommitBlockSize,
dwReservedRegionAddress,
dwReservedRegionSize,
pRangeList,
fMakeExecutable),
kind,
codePageGenerator, dwGranularity),
m_CriticalSection(fUnlocked ? NULL : CreateLoaderHeapLock())
{
WRAPPER_NO_CONTRACT;
Expand Down Expand Up @@ -776,7 +800,7 @@ class ExplicitControlLoaderHeap : public UnlockedLoaderHeap
)
: UnlockedLoaderHeap(0, 0, NULL, 0,
pRangeList,
fMakeExecutable)
fMakeExecutable ? UnlockedLoaderHeap::HeapKind::Executable : UnlockedLoaderHeap::HeapKind::Data)
{
WRAPPER_NO_CONTRACT;
m_fExplicitControl = TRUE;
Expand Down
4 changes: 2 additions & 2 deletions src/coreclr/minipal/Windows/doublemapping.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,8 @@ void *VMToOSInterface::CommitDoubleMappedMemory(void* pStart, size_t size, bool

bool VMToOSInterface::ReleaseDoubleMappedMemory(void *mapperHandle, void* pStart, size_t offset, size_t size)
{
// Zero the memory before the unmapping
VirtualAlloc(pStart, size, MEM_COMMIT, PAGE_READWRITE);
LPVOID result = VirtualAlloc(pStart, size, MEM_COMMIT, PAGE_READWRITE);
assert(result != NULL);
memset(pStart, 0, size);
return UnmapViewOfFile(pStart);
}
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/pal/inc/unixasmmacrosamd64.inc
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@

.macro PATCH_LABEL Name
.global C_FUNC(\Name)
C_FUNC(\Name):
C_FUNC(\Name) = .
.endm

.macro LEAF_ENTRY Name, Section
Expand Down
Loading