Skip to content

This is an incomplete implementation of a new randomized allocation s… #98167

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

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions src/coreclr/debug/daccess/dacdbiimpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6567,10 +6567,10 @@ HRESULT DacHeapWalker::Init(CORDB_ADDRESS start, CORDB_ADDRESS end)
j++;
}
}
if ((&g_global_alloc_context)->alloc_ptr != nullptr)
if (g_global_alloc_context->alloc_ptr != nullptr)
{
mAllocInfo[j].Ptr = (CORDB_ADDRESS)(&g_global_alloc_context)->alloc_ptr;
mAllocInfo[j].Limit = (CORDB_ADDRESS)(&g_global_alloc_context)->alloc_limit;
mAllocInfo[j].Ptr = (CORDB_ADDRESS)g_global_alloc_context->alloc_ptr;
mAllocInfo[j].Limit = (CORDB_ADDRESS)g_global_alloc_context->alloc_limit;
}

mThreadCount = j;
Expand Down
12 changes: 6 additions & 6 deletions src/coreclr/debug/daccess/request.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -685,8 +685,8 @@ ClrDataAccess::GetThreadAllocData(CLRDATA_ADDRESS addr, struct DacpAllocData *da

Thread* thread = PTR_Thread(TO_TADDR(addr));

data->allocBytes = TO_CDADDR(thread->m_alloc_context.alloc_bytes);
data->allocBytesLoh = TO_CDADDR(thread->m_alloc_context.alloc_bytes_uoh);
data->allocBytes = TO_CDADDR(thread->m_alloc_context.gc_alloc_context.alloc_bytes);
data->allocBytesLoh = TO_CDADDR(thread->m_alloc_context.gc_alloc_context.alloc_bytes_uoh);

SOSDacLeave();
return hr;
Expand Down Expand Up @@ -740,8 +740,8 @@ ClrDataAccess::GetThreadData(CLRDATA_ADDRESS threadAddr, struct DacpThreadData *
threadData->osThreadId = (DWORD)thread->m_OSThreadId;
threadData->state = thread->m_State;
threadData->preemptiveGCDisabled = thread->m_fPreemptiveGCDisabled;
threadData->allocContextPtr = TO_CDADDR(thread->m_alloc_context.alloc_ptr);
threadData->allocContextLimit = TO_CDADDR(thread->m_alloc_context.alloc_limit);
threadData->allocContextPtr = TO_CDADDR(thread->m_alloc_context.gc_alloc_context.alloc_ptr);
threadData->allocContextLimit = TO_CDADDR(thread->m_alloc_context.gc_alloc_context.alloc_limit);

threadData->fiberData = NULL;

Expand Down Expand Up @@ -5300,8 +5300,8 @@ HRESULT ClrDataAccess::GetGlobalAllocationContext(
}

SOSDacEnter();
*allocPtr = (CLRDATA_ADDRESS)((&g_global_alloc_context)->alloc_ptr);
*allocLimit = (CLRDATA_ADDRESS)((&g_global_alloc_context)->alloc_limit);
*allocPtr = (CLRDATA_ADDRESS)(g_global_alloc_context->alloc_ptr);
*allocLimit = (CLRDATA_ADDRESS)(g_global_alloc_context->alloc_limit);
SOSDacLeave();
return hr;
}
Expand Down
2 changes: 1 addition & 1 deletion src/coreclr/inc/dacvars.h
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ DEFINE_DACVAR(ProfControlBlock, dac__g_profControlBlock, ::g_profControlBlock)
DEFINE_DACVAR(PTR_DWORD, dac__g_card_table, ::g_card_table)
DEFINE_DACVAR(PTR_BYTE, dac__g_lowest_address, ::g_lowest_address)
DEFINE_DACVAR(PTR_BYTE, dac__g_highest_address, ::g_highest_address)
DEFINE_DACVAR(gc_alloc_context, dac__g_global_alloc_context, ::g_global_alloc_context)
DEFINE_DACVAR(UNKNOWN_POINTER_TYPE, dac__g_global_alloc_context, ::g_global_alloc_context)

DEFINE_DACVAR(IGCHeap, dac__g_pGCHeap, ::g_pGCHeap)

Expand Down
10 changes: 5 additions & 5 deletions src/coreclr/vm/amd64/JitHelpers_InlineGetThread.asm
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ LEAF_ENTRY JIT_TrialAllocSFastMP_InlineGetThread, _TEXT
; m_BaseSize is guaranteed to be a multiple of 8.

INLINE_GETTHREAD r11
mov r10, [r11 + OFFSET__Thread__m_alloc_context__alloc_limit]
mov r10, [r11 + OFFSET__Thread__m_alloc_context__fast_alloc_helper_limit]
mov rax, [r11 + OFFSET__Thread__m_alloc_context__alloc_ptr]

add rdx, rax
Expand All @@ -65,7 +65,7 @@ NESTED_ENTRY JIT_BoxFastMP_InlineGetThread, _TEXT
mov r8d, [rcx + OFFSET__MethodTable__m_BaseSize]

INLINE_GETTHREAD r11
mov r10, [r11 + OFFSET__Thread__m_alloc_context__alloc_limit]
mov r10, [r11 + OFFSET__Thread__m_alloc_context__fast_alloc_helper_limit]
mov rax, [r11 + OFFSET__Thread__m_alloc_context__alloc_ptr]

add r8, rax
Expand Down Expand Up @@ -136,7 +136,7 @@ LEAF_ENTRY AllocateStringFastMP_InlineGetThread, _TEXT
and edx, -8

INLINE_GETTHREAD r11
mov r10, [r11 + OFFSET__Thread__m_alloc_context__alloc_limit]
mov r10, [r11 + OFFSET__Thread__m_alloc_context__fast_alloc_helper_limit]
mov rax, [r11 + OFFSET__Thread__m_alloc_context__alloc_ptr]

add rdx, rax
Expand Down Expand Up @@ -189,7 +189,7 @@ LEAF_ENTRY JIT_NewArr1VC_MP_InlineGetThread, _TEXT


INLINE_GETTHREAD r11
mov r10, [r11 + OFFSET__Thread__m_alloc_context__alloc_limit]
mov r10, [r11 + OFFSET__Thread__m_alloc_context__fast_alloc_helper_limit]
mov rax, [r11 + OFFSET__Thread__m_alloc_context__alloc_ptr]

add r8, rax
Expand Down Expand Up @@ -238,7 +238,7 @@ LEAF_ENTRY JIT_NewArr1OBJ_MP_InlineGetThread, _TEXT
; to be a multiple of 8.

INLINE_GETTHREAD r11
mov r10, [r11 + OFFSET__Thread__m_alloc_context__alloc_limit]
mov r10, [r11 + OFFSET__Thread__m_alloc_context__fast_alloc_helper_limit]
mov rax, [r11 + OFFSET__Thread__m_alloc_context__alloc_ptr]

add r8, rax
Expand Down
32 changes: 16 additions & 16 deletions src/coreclr/vm/amd64/JitHelpers_Slow.asm
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ endif


extern g_global_alloc_lock:dword
extern g_global_alloc_context:qword
extern g_global_ee_alloc_context:qword

LEAF_ENTRY JIT_TrialAllocSFastSP, _TEXT

Expand All @@ -183,15 +183,15 @@ LEAF_ENTRY JIT_TrialAllocSFastSP, _TEXT
inc [g_global_alloc_lock]
jnz JIT_NEW

mov rax, [g_global_alloc_context + OFFSETOF__gc_alloc_context__alloc_ptr] ; alloc_ptr
mov r10, [g_global_alloc_context + OFFSETOF__gc_alloc_context__alloc_limit] ; limit_ptr
mov rax, [g_global_ee_alloc_context + OFFSETOF__ee_alloc_context__alloc_ptr] ; alloc_ptr
mov r10, [g_global_ee_alloc_context + OFFSETOF__ee_alloc_context__fast_alloc_helper_limit] ; fast_alloc_helper_limit_ptr

add r8, rax

cmp r8, r10
ja AllocFailed

mov qword ptr [g_global_alloc_context + OFFSETOF__gc_alloc_context__alloc_ptr], r8 ; update the alloc ptr
mov qword ptr [g_global_ee_alloc_context + OFFSETOF__ee_alloc_context__alloc_ptr], r8 ; update the alloc ptr
mov [rax], rcx
mov [g_global_alloc_lock], -1

Expand All @@ -211,8 +211,8 @@ NESTED_ENTRY JIT_BoxFastUP, _TEXT
inc [g_global_alloc_lock]
jnz JIT_Box

mov rax, [g_global_alloc_context + OFFSETOF__gc_alloc_context__alloc_ptr] ; alloc_ptr
mov r10, [g_global_alloc_context + OFFSETOF__gc_alloc_context__alloc_limit] ; limit_ptr
mov rax, [g_global_ee_alloc_context + OFFSETOF__ee_alloc_context__alloc_ptr] ; alloc_ptr
mov r10, [g_global_ee_alloc_context + OFFSETOF__ee_alloc_context__fast_alloc_helper_limit] ; fast_alloc_helper_limit_ptr

add r8, rax

Expand All @@ -222,7 +222,7 @@ NESTED_ENTRY JIT_BoxFastUP, _TEXT
test rdx, rdx
je NullRef

mov qword ptr [g_global_alloc_context + OFFSETOF__gc_alloc_context__alloc_ptr], r8 ; update the alloc ptr
mov qword ptr [g_global_ee_alloc_context + OFFSETOF__ee_alloc_context__alloc_ptr], r8 ; update the alloc ptr
mov [rax], rcx
mov [g_global_alloc_lock], -1

Expand Down Expand Up @@ -290,15 +290,15 @@ LEAF_ENTRY AllocateStringFastUP, _TEXT
inc [g_global_alloc_lock]
jnz FramedAllocateString

mov rax, [g_global_alloc_context + OFFSETOF__gc_alloc_context__alloc_ptr] ; alloc_ptr
mov r10, [g_global_alloc_context + OFFSETOF__gc_alloc_context__alloc_limit] ; limit_ptr
mov rax, [g_global_ee_alloc_context + OFFSETOF__ee_alloc_context__alloc_ptr] ; alloc_ptr
mov r10, [g_global_ee_alloc_context + OFFSETOF__ee_alloc_context__fast_alloc_helper_limit] ; fast_alloc_helper_limit_ptr

add r8, rax

cmp r8, r10
ja AllocFailed

mov qword ptr [g_global_alloc_context + OFFSETOF__gc_alloc_context__alloc_ptr], r8 ; update the alloc ptr
mov qword ptr [g_global_ee_alloc_context + OFFSETOF__ee_alloc_context__alloc_ptr], r8 ; update the alloc ptr
mov [rax], r11
mov [g_global_alloc_lock], -1

Expand Down Expand Up @@ -346,16 +346,16 @@ LEAF_ENTRY JIT_NewArr1VC_UP, _TEXT
inc [g_global_alloc_lock]
jnz JIT_NewArr1

mov rax, [g_global_alloc_context + OFFSETOF__gc_alloc_context__alloc_ptr] ; alloc_ptr
mov r10, [g_global_alloc_context + OFFSETOF__gc_alloc_context__alloc_limit] ; limit_ptr
mov rax, [g_global_ee_alloc_context + OFFSETOF__ee_alloc_context__alloc_ptr] ; alloc_ptr
mov r10, [g_global_ee_alloc_context + OFFSETOF__ee_alloc_context__fast_alloc_helper_limit] ; fast_alloc_helper_limit_ptr

add r8, rax
jc AllocFailed

cmp r8, r10
ja AllocFailed

mov qword ptr [g_global_alloc_context + OFFSETOF__gc_alloc_context__alloc_ptr], r8 ; update the alloc ptr
mov qword ptr [g_global_ee_alloc_context + OFFSETOF__ee_alloc_context__alloc_ptr], r8 ; update the alloc ptr
mov [rax], rcx
mov [g_global_alloc_lock], -1

Expand Down Expand Up @@ -399,15 +399,15 @@ LEAF_ENTRY JIT_NewArr1OBJ_UP, _TEXT
inc [g_global_alloc_lock]
jnz JIT_NewArr1

mov rax, [g_global_alloc_context + OFFSETOF__gc_alloc_context__alloc_ptr] ; alloc_ptr
mov r10, [g_global_alloc_context + OFFSETOF__gc_alloc_context__alloc_limit] ; limit_ptr
mov rax, [g_global_ee_alloc_context + OFFSETOF__ee_alloc_context__alloc_ptr] ; alloc_ptr
mov r10, [g_global_ee_alloc_context + OFFSETOF__ee_alloc_context__fast_alloc_helper_limit] ; fast_alloc_helper_limit_ptr

add r8, rax

cmp r8, r10
ja AllocFailed

mov qword ptr [g_global_alloc_context + OFFSETOF__gc_alloc_context__alloc_ptr], r8 ; update the alloc ptr
mov qword ptr [g_global_ee_alloc_context + OFFSETOF__ee_alloc_context__alloc_ptr], r8 ; update the alloc ptr
mov [rax], rcx
mov [g_global_alloc_lock], -1

Expand Down
16 changes: 8 additions & 8 deletions src/coreclr/vm/amd64/asmconstants.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,17 +119,17 @@ ASMCONSTANTS_C_ASSERT(OFFSETOF__Thread__m_pFrame
#define Thread_m_pFrame OFFSETOF__Thread__m_pFrame


#define OFFSET__Thread__m_alloc_context__alloc_ptr 0x58
ASMCONSTANTS_C_ASSERT(OFFSET__Thread__m_alloc_context__alloc_ptr == offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_ptr));
#define OFFSET__Thread__m_alloc_context__alloc_ptr 0x60
ASMCONSTANTS_C_ASSERT(OFFSET__Thread__m_alloc_context__alloc_ptr == offsetof(Thread, m_alloc_context) + offsetof(ee_alloc_context, gc_alloc_context) + offsetof(gc_alloc_context, alloc_ptr));

#define OFFSET__Thread__m_alloc_context__alloc_limit 0x60
ASMCONSTANTS_C_ASSERT(OFFSET__Thread__m_alloc_context__alloc_limit == offsetof(Thread, m_alloc_context) + offsetof(gc_alloc_context, alloc_limit));
#define OFFSET__Thread__m_alloc_context__fast_alloc_helper_limit 0x58
ASMCONSTANTS_C_ASSERT(OFFSET__Thread__m_alloc_context__fast_alloc_helper_limit == offsetof(Thread, m_alloc_context) + offsetof(ee_alloc_context, fast_alloc_helper_limit_ptr));

#define OFFSETOF__gc_alloc_context__alloc_ptr 0x0
ASMCONSTANT_OFFSETOF_ASSERT(gc_alloc_context, alloc_ptr);
#define OFFSETOF__ee_alloc_context__alloc_ptr 0x8
ASMCONSTANTS_C_ASSERT(OFFSETOF__ee_alloc_context__alloc_ptr == offsetof(ee_alloc_context, gc_alloc_context) + offsetof(gc_alloc_context, alloc_ptr));

#define OFFSETOF__gc_alloc_context__alloc_limit 0x8
ASMCONSTANT_OFFSETOF_ASSERT(gc_alloc_context, alloc_limit);
#define OFFSETOF__ee_alloc_context__fast_alloc_helper_limit 0x0
ASMCONSTANTS_C_ASSERT(OFFSETOF__ee_alloc_context__fast_alloc_helper_limit == offsetof(ee_alloc_context, fast_alloc_helper_limit_ptr));

#define OFFSETOF__ThreadExceptionState__m_pCurrentTracker 0x000
ASMCONSTANTS_C_ASSERT(OFFSETOF__ThreadExceptionState__m_pCurrentTracker
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,7 @@ typedef VPTR(class VirtualCallStubManager) PTR_VirtualCallStubManager;
typedef VPTR(class VirtualCallStubManagerManager) PTR_VirtualCallStubManagerManager;
typedef VPTR(class IGCHeap) PTR_IGCHeap;
typedef VPTR(class ModuleBase) PTR_ModuleBase;
typedef DPTR(struct gc_alloc_context) PTR_gc_alloc_context;

//
// _UNCHECKED_OBJECTREF is for code that can't deal with DEBUG OBJECTREFs
Expand Down
18 changes: 16 additions & 2 deletions src/coreclr/vm/gcenv.ee.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -444,6 +444,20 @@ gc_alloc_context * GCToEEInterface::GetAllocContext()
return pThread->GetAllocContext();
}

void InvokeGCAllocCallback(ee_alloc_context* pEEAllocContext, enum_alloc_context_func* fn, void* param)
{
gc_alloc_context* pAllocContext = &pEEAllocContext->gc_alloc_context;
fn(pAllocContext, param);
if(pEEAllocContext->fast_alloc_helper_limit_ptr > pAllocContext->alloc_limit ||
pAllocContext->alloc_ptr > pEEAllocContext->fast_alloc_helper_limit_ptr)
{
// fast_alloc_limit_ptr should be in the range [alloc_ptr, alloc_limit].
// If it isn't that means the GC just moved the allocation context to a
// different region of memory within the callback and we need to fix it up.
pEEAllocContext->SetFastAllocHelperLimit();
}
}

void GCToEEInterface::GcEnumAllocContexts(enum_alloc_context_func* fn, void* param)
{
CONTRACTL
Expand All @@ -458,12 +472,12 @@ void GCToEEInterface::GcEnumAllocContexts(enum_alloc_context_func* fn, void* par
Thread * pThread = NULL;
while ((pThread = ThreadStore::GetThreadList(pThread)) != NULL)
{
fn(pThread->GetAllocContext(), param);
InvokeGCAllocCallback(pThread->GetEEAllocContext(), fn, param);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't get why we would want to trigger sampling logic while enumerating allocs. Perhaps I am missing the utility of the GcEnumAllocContexts(), are we attempting to create some side-effect?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is enumerating alloc contexts. I assume that this wrapper is here to do catch up of the runtime-owned side of the alloc context with the GC-owned side of the alloc context.

Every time GC updates the GC-owned side of the alloc context (that happens in number of GC/EE interface calls), the runtime side needs to do a catch up to update the runtime-owned side. It is what I meant by "spread through many places".

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, this isn't triggering a sampling callback directly but we do need to keep the fast alloc limit coherent with the GC's limit in the event that the GC changed the limit field inside this callback.

that happens in number of GC/EE interface calls

So far I only noticed limit updates happening in two calls, GCHeap::Alloc and this enumeration callback. Technically FixAllocationContext() also changes limit, but it appears to only get used when zeroing out an AC in which case I also zeroed out the fast alloc helper limit.

}
}
else
{
fn(&g_global_alloc_context, param);
InvokeGCAllocCallback(&g_global_ee_alloc_context, fn, param);
}
}

Expand Down
3 changes: 2 additions & 1 deletion src/coreclr/vm/gcheaputilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,8 @@ bool g_sw_ww_enabled_for_gc_heap = false;

#endif // FEATURE_USE_SOFTWARE_WRITE_WATCH_FOR_GC_HEAP

GVAL_IMPL_INIT(gc_alloc_context, g_global_alloc_context, {});
ee_alloc_context g_global_ee_alloc_context = {};
GPTR_IMPL_INIT(gc_alloc_context, g_global_alloc_context, &(g_global_ee_alloc_context.gc_alloc_context));

enum GC_LOAD_STATUS {
GC_LOAD_STATUS_BEFORE_START,
Expand Down
32 changes: 31 additions & 1 deletion src/coreclr/vm/gcheaputilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,32 @@ GPTR_DECL(IGCHeap, g_pGCHeap);
#ifndef DACCESS_COMPILE
extern "C" {
#endif // !DACCESS_COMPILE

// This struct adds some state that is only visible to the EE onto the standard gc_alloc_context
typedef struct _ee_alloc_context
{
uint8_t* fast_alloc_helper_limit_ptr;
gc_alloc_context gc_alloc_context;

public:
void init()
{
LIMITED_METHOD_CONTRACT;
fast_alloc_helper_limit_ptr = 0;
gc_alloc_context.init();
}

inline void SetFastAllocHelperLimit()
{
// If sampling is off this is just setting fast_alloc_helper_limit_ptr = alloc_limit
// If sampling is on then we'd do some pseudo-random number generation to decide what is
// the next sampled byte in the gc_alloc_context, if any.

//TODO: implement sampling limit placement strategy
fast_alloc_helper_limit_ptr = gc_alloc_context.alloc_limit;
}
} ee_alloc_context;

GPTR_DECL(uint8_t,g_lowest_address);
GPTR_DECL(uint8_t,g_highest_address);
GPTR_DECL(uint32_t,g_card_table);
Expand All @@ -21,7 +47,11 @@ GVAL_DECL(GCHeapType, g_heap_type);
// for all allocations. In order to avoid extra indirections in assembly
// allocation helpers, the EE owns the global allocation context and the
// GC will update it when it needs to.
GVAL_DECL(gc_alloc_context, g_global_alloc_context);
extern "C" ee_alloc_context g_global_ee_alloc_context;

// This is a pointer into the g_global_ee_alloc_context for the GC visible
// subset of the data
GPTR_DECL(gc_alloc_context, g_global_alloc_context);
#ifndef DACCESS_COMPILE
}
#endif // !DACCESS_COMPILE
Expand Down
Loading