Skip to content
This repository has been archived by the owner on Nov 1, 2020. It is now read-only.

Commit

Permalink
This is the internal component of CoreRT#2485 (#2485), which ports a…
Browse files Browse the repository at this point in the history
… number of GC changes done within the last month or two from CoreCLR to CoreRT. The only changes to anything in Native/gc are:

         1. Move an assert under #ifndef FEATURE_REDHAWK since it only is a useful assert on CoreCLR (#2485 (comment))
         2. Add UNREFERENCED_PARAMETERs to things in gc.cpp and elsewhere that were producing warnings

     All other changes in Native/gc are directly from CoreCLR without modification. I have validated that I am able to do PerfView GC analysis with these changes (since the CoreCLR changes touched ETW eventing).

[tfs-changeset: 1644465]
  • Loading branch information
dotnet-bot committed Jan 13, 2017
1 parent 85dde75 commit e567896
Show file tree
Hide file tree
Showing 35 changed files with 967 additions and 891 deletions.
11 changes: 11 additions & 0 deletions src/Native/Runtime/eventtrace.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,18 @@
#define _VMEVENTTRACE_H_

#include "eventtracebase.h"
#include "gcinterface.h"

#if defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)
struct ProfilingScanContext : ScanContext
{
BOOL fProfilerPinned;
void * pvEtwContext;
void *pHeapId;

ProfilingScanContext(BOOL fProfilerPinnedParam);
};
#endif // defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE)

namespace ETW
{
Expand Down
12 changes: 11 additions & 1 deletion src/Native/Runtime/gcheaputilities.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,14 @@
#include "gcheaputilities.h"

// This is the global GC heap, maintained by the VM.
GPTR_IMPL(IGCHeap, g_pGCHeap);
GPTR_IMPL(IGCHeap, g_pGCHeap);

// These globals are variables used within the GC and maintained
// by the EE for use in write barriers. It is the responsibility
// of the GC to communicate updates to these globals to the EE through
// GCToEEInterface::StompWriteBarrier.
GPTR_IMPL_INIT(uint32_t, g_card_table, nullptr);
GPTR_IMPL_INIT(uint8_t, g_lowest_address, nullptr);
GPTR_IMPL_INIT(uint8_t, g_highest_address, nullptr);
uint8_t* g_ephemeral_low = (uint8_t*)1;
uint8_t* g_ephemeral_high = (uint8_t*)~0;
13 changes: 13 additions & 0 deletions src/Native/Runtime/gcheaputilities.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,19 @@
// The singular heap instance.
GPTR_DECL(IGCHeap, g_pGCHeap);

#ifndef DACCESS_COMPILE
extern "C" {
#endif // !DACCESS_COMPILE
GPTR_DECL(uint8_t,g_lowest_address);
GPTR_DECL(uint8_t,g_highest_address);
GPTR_DECL(uint32_t,g_card_table);
#ifndef DACCESS_COMPILE
}
#endif // !DACCESS_COMPILE

extern "C" uint8_t* g_ephemeral_low;
extern "C" uint8_t* g_ephemeral_high;

// GCHeapUtilities provides a number of static methods
// that operate on the global heap instance. It can't be
// instantiated.
Expand Down
209 changes: 197 additions & 12 deletions src/Native/Runtime/gcrhenv.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,25 @@

#include "holder.h"

#ifdef FEATURE_ETW
#ifndef _INC_WINDOWS
typedef void* LPVOID;
typedef uint32_t UINT;
typedef void* PVOID;
typedef uint64_t ULONGLONG;
typedef uint32_t ULONG;
typedef int64_t LONGLONG;
typedef uint8_t BYTE;
typedef uint16_t UINT16;
#endif // _INC_WINDOWS

#include "etwevents.h"
#include "eventtrace.h"
#else // FEATURE_ETW
#include "etmdummy.h"
#define ETW_EVENT_ENABLED(e,f) false
#endif // FEATURE_ETW

GPTR_IMPL(EEType, g_pFreeObjectEEType);

#define USE_CLR_CACHE_SIZE_BEHAVIOR
Expand Down Expand Up @@ -119,7 +138,7 @@ UInt32 EtwCallback(UInt32 IsEnabled, RH_ETW_CONTEXT * pContext)
FireEtwGCSettings(GCHeapUtilities::GetGCHeap()->GetValidSegmentSize(FALSE),
GCHeapUtilities::GetGCHeap()->GetValidSegmentSize(TRUE),
GCHeapUtilities::IsServerHeap());
GCHeapUtilities::GetGCHeap()->TraceGCSegments();
GCHeapUtilities::GetGCHeap()->DiagTraceGCSegments();
}

// Special check for the runtime provider's GCHeapCollectKeyword. Profilers
Expand Down Expand Up @@ -686,8 +705,8 @@ void RedhawkGCInterface::ScanHeap(GcScanObjectFunction pfnScanCallback, void *pC
// static
void RedhawkGCInterface::ScanObject(void *pObject, GcScanObjectFunction pfnScanCallback, void *pContext)
{
#if !defined(DACCESS_COMPILE) && (defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE))
GCHeapUtilities::GetGCHeap()->WalkObject((Object*)pObject, (walk_fn)pfnScanCallback, pContext);
#if !defined(DACCESS_COMPILE) && defined(FEATURE_EVENT_TRACE)
GCHeapUtilities::GetGCHeap()->DiagWalkObject((Object*)pObject, (walk_fn)pfnScanCallback, pContext);
#else
UNREFERENCED_PARAMETER(pObject);
UNREFERENCED_PARAMETER(pfnScanCallback);
Expand Down Expand Up @@ -759,7 +778,7 @@ void RedhawkGCInterface::ScanStaticRoots(GcScanRootFunction pfnScanCallback, voi
// static
void RedhawkGCInterface::ScanHandleTableRoots(GcScanRootFunction pfnScanCallback, void *pContext)
{
#if !defined(DACCESS_COMPILE) && (defined(GC_PROFILING) || defined(FEATURE_EVENT_TRACE))
#if !defined(DACCESS_COMPILE) && defined(FEATURE_EVENT_TRACE)
ScanRootsContext sContext;
sContext.m_pfnCallback = pfnScanCallback;
sContext.m_pContext = pContext;
Expand Down Expand Up @@ -1148,6 +1167,166 @@ Thread* GCToEEInterface::CreateBackgroundThread(GCBackgroundThreadFunction threa
return threadStubArgs.m_pThread;
}

void GCToEEInterface::DiagGCStart(int gen, bool isInduced)
{
UNREFERENCED_PARAMETER(gen);
UNREFERENCED_PARAMETER(isInduced);
}

void GCToEEInterface::DiagUpdateGenerationBounds()
{
}

void GCToEEInterface::DiagWalkFReachableObjects(void* gcContext)
{
UNREFERENCED_PARAMETER(gcContext);
}

void GCToEEInterface::DiagGCEnd(size_t index, int gen, int reason, bool fConcurrent)
{
UNREFERENCED_PARAMETER(index);
UNREFERENCED_PARAMETER(gen);
UNREFERENCED_PARAMETER(reason);
UNREFERENCED_PARAMETER(fConcurrent);
}

// Note on last parameter: when calling this for bgc, only ETW
// should be sending these events so that existing profapi profilers
// don't get confused.
void WalkMovedReferences(uint8_t* begin, uint8_t* end,
ptrdiff_t reloc,
size_t context,
BOOL fCompacting,
BOOL fBGC)
{
UNREFERENCED_PARAMETER(begin);
UNREFERENCED_PARAMETER(end);
UNREFERENCED_PARAMETER(reloc);
UNREFERENCED_PARAMETER(context);
UNREFERENCED_PARAMETER(fCompacting);
UNREFERENCED_PARAMETER(fBGC);
}

//
// Diagnostics code
//

#ifdef FEATURE_EVENT_TRACE
inline BOOL ShouldTrackMovementForProfilerOrEtw()
{
if (ETW::GCLog::ShouldTrackMovementForEtw())
return true;

return false;
}
#endif // FEATURE_EVENT_TRACE

void GCToEEInterface::DiagWalkSurvivors(void* gcContext)
{
#ifdef FEATURE_EVENT_TRACE
if (ShouldTrackMovementForProfilerOrEtw())
{
size_t context = 0;
ETW::GCLog::BeginMovedReferences(&context);
GCHeapUtilities::GetGCHeap()->DiagWalkSurvivorsWithType(gcContext, &WalkMovedReferences, context, walk_for_gc);
ETW::GCLog::EndMovedReferences(context);
}
#else
UNREFERENCED_PARAMETER(gcContext);
#endif // FEATURE_EVENT_TRACE
}

void GCToEEInterface::DiagWalkLOHSurvivors(void* gcContext)
{
#ifdef FEATURE_EVENT_TRACE
if (ShouldTrackMovementForProfilerOrEtw())
{
size_t context = 0;
ETW::GCLog::BeginMovedReferences(&context);
GCHeapUtilities::GetGCHeap()->DiagWalkSurvivorsWithType(gcContext, &WalkMovedReferences, context, walk_for_loh);
ETW::GCLog::EndMovedReferences(context);
}
#else
UNREFERENCED_PARAMETER(gcContext);
#endif // FEATURE_EVENT_TRACE
}

void GCToEEInterface::DiagWalkBGCSurvivors(void* gcContext)
{
#ifdef FEATURE_EVENT_TRACE
if (ShouldTrackMovementForProfilerOrEtw())
{
size_t context = 0;
ETW::GCLog::BeginMovedReferences(&context);
GCHeapUtilities::GetGCHeap()->DiagWalkSurvivorsWithType(gcContext, &WalkMovedReferences, context, walk_for_bgc);
ETW::GCLog::EndMovedReferences(context);
}
#else
UNREFERENCED_PARAMETER(gcContext);
#endif // FEATURE_EVENT_TRACE
}

void GCToEEInterface::StompWriteBarrier(WriteBarrierParameters* args)
{
// CoreRT doesn't patch the write barrier like CoreCLR does, but it
// still needs to record the changes in the GC heap.
assert(args != nullptr);
switch (args->operation)
{
case WriteBarrierOp::StompResize:
// StompResize requires a new card table, a new lowest address, and
// a new highest address
assert(args->card_table != nullptr);
assert(args->lowest_address != nullptr);
assert(args->highest_address != nullptr);
g_card_table = args->card_table;

// We need to make sure that other threads executing checked write barriers
// will see the g_card_table update before g_lowest/highest_address updates.
// Otherwise, the checked write barrier may AV accessing the old card table
// with address that it does not cover. Write barriers access card table
// without memory barriers for performance reasons, so we need to flush
// the store buffers here.
FlushProcessWriteBuffers();

g_lowest_address = args->lowest_address;
VolatileStore(&g_highest_address, args->highest_address);
return;
case WriteBarrierOp::StompEphemeral:
// StompEphemeral requires a new ephemeral low and a new ephemeral high
assert(args->ephemeral_low != nullptr);
assert(args->ephemeral_high != nullptr);
g_ephemeral_low = args->ephemeral_low;
g_ephemeral_high = args->ephemeral_high;
return;
case WriteBarrierOp::Initialize:
// This operation should only be invoked once, upon initialization.
assert(g_card_table == nullptr);
assert(g_lowest_address == nullptr);
assert(g_highest_address == nullptr);
assert(args->card_table != nullptr);
assert(args->lowest_address != nullptr);
assert(args->highest_address != nullptr);
assert(args->ephemeral_low != nullptr);
assert(args->ephemeral_high != nullptr);
assert(args->is_runtime_suspended && "the runtime must be suspended here!");

g_card_table = args->card_table;
g_lowest_address = args->lowest_address;
g_highest_address = args->highest_address;
g_ephemeral_low = args->ephemeral_low;
g_ephemeral_high = args->ephemeral_high;
return;
case WriteBarrierOp::SwitchToWriteWatch:
case WriteBarrierOp::SwitchToNonWriteWatch:
assert(!"CoreRT does not have an implementation of non-OS WriteWatch");
return;
default:
assert(!"Unknokwn WriteBarrierOp enum");
return;
}
}

#endif // !DACCESS_COMPILE

// NOTE: this method is not in thread.cpp because it needs access to the layout of alloc_context for DAC to know the
Expand Down Expand Up @@ -1339,14 +1518,6 @@ MethodTable * g_pFreeObjectMethodTable;
int32_t g_TrapReturningThreads;
bool g_fFinalizerRunOnShutDown;

void StompWriteBarrierEphemeral(bool /* isRuntimeSuspended */)
{
}

void StompWriteBarrierResize(bool /* isRuntimeSuspended */, bool /*bReqUpperBoundsCheck*/)
{
}

bool IsGCThread()
{
return false;
Expand Down Expand Up @@ -1425,3 +1596,17 @@ void CPUGroupInfo::GetGroupForProcessor(uint16_t /*processor_number*/, uint16_t
{
ASSERT_UNCONDITIONALLY("NYI: CPUGroupInfo::GetGroupForProcessor");
}

#ifdef FEATURE_EVENT_TRACE
ProfilingScanContext::ProfilingScanContext(BOOL fProfilerPinnedParam)
: ScanContext()
{
pHeapId = NULL;
fProfilerPinned = fProfilerPinnedParam;
pvEtwContext = NULL;
#ifdef FEATURE_CONSERVATIVE_GC
// To not confuse GCScan::GcScanRoots
promotion = g_pConfig->GetGCConservative();
#endif
}
#endif // FEATURE_EVENT_TRACE
4 changes: 2 additions & 2 deletions src/Native/Runtime/profheapwalkhelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ BOOL HeapWalkHelper(Object * pBO, void * pvContext)
//if (pMT->ContainsPointersOrCollectible())
{
// First round through calculates the number of object refs for this class
GCHeapUtilities::GetGCHeap()->WalkObject(pBO, &CountContainedObjectRef, (void *)&cNumRefs);
GCHeapUtilities::GetGCHeap()->DiagWalkObject(pBO, &CountContainedObjectRef, (void *)&cNumRefs);

if (cNumRefs > 0)
{
Expand All @@ -166,7 +166,7 @@ BOOL HeapWalkHelper(Object * pBO, void * pvContext)

// Second round saves off all of the ref values
OBJECTREF * pCurObjRef = arrObjRef;
GCHeapUtilities::GetGCHeap()->WalkObject(pBO, &SaveContainedObjectRef, (void *)&pCurObjRef);
GCHeapUtilities::GetGCHeap()->DiagWalkObject(pBO, &SaveContainedObjectRef, (void *)&pCurObjRef);
}
}

Expand Down
5 changes: 2 additions & 3 deletions src/Native/Runtime/unix/PalRedhawkUnix.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1457,13 +1457,12 @@ void GCToOSInterface::YieldThread(uint32_t switchCount)

// Reserve virtual memory range.
// Parameters:
// address - starting virtual address, it can be NULL to let the function choose the starting address
// size - size of the virtual memory range
// alignment - requested memory alignment, 0 means no specific alignment requested
// flags - flags to control special settings like write watching
// Return:
// Starting virtual address of the reserved range
void* GCToOSInterface::VirtualReserve(void* address, size_t size, size_t alignment, uint32_t flags)
void* GCToOSInterface::VirtualReserve(size_t size, size_t alignment, uint32_t flags)
{
ASSERT_MSG(!(flags & VirtualReserveFlags::WriteWatch), "WriteWatch not supported on Unix");

Expand All @@ -1474,7 +1473,7 @@ void* GCToOSInterface::VirtualReserve(void* address, size_t size, size_t alignme

size_t alignedSize = size + (alignment - OS_PAGE_SIZE);

void * pRetVal = mmap(address, alignedSize, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);
void * pRetVal = mmap(nullptr, alignedSize, PROT_NONE, MAP_ANON | MAP_PRIVATE, -1, 0);

if (pRetVal != NULL)
{
Expand Down
2 changes: 1 addition & 1 deletion src/Native/Runtime/windows/PalRedhawkMinWin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1482,7 +1482,7 @@ void GCToOSInterface::YieldThread(uint32_t /*switchCount*/)
// flags - flags to control special settings like write watching
// Return:
// Starting virtual address of the reserved range
void* GCToOSInterface::VirtualReserve(void* address, size_t size, size_t alignment, uint32_t flags)
void* GCToOSInterface::VirtualReserve(size_t size, size_t alignment, uint32_t flags)
{
DWORD memFlags = (flags & VirtualReserveFlags::WriteWatch) ? (MEM_RESERVE | MEM_WRITE_WATCH) : MEM_RESERVE;
return ::VirtualAlloc(0, size, memFlags, PAGE_READWRITE);
Expand Down
2 changes: 1 addition & 1 deletion src/Native/gc/env/gcenv.base.h
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ inline HRESULT HRESULT_FROM_WIN32(unsigned long x)
#define UNREFERENCED_PARAMETER(P) (void)(P)

#ifdef PLATFORM_UNIX
#define _vsnprintf vsnprintf
#define _vsnprintf_s(string, sizeInBytes, count, format, args) vsnprintf(string, sizeInBytes, format, args)
#define sprintf_s snprintf
#define swprintf_s swprintf
#endif
Expand Down
10 changes: 10 additions & 0 deletions src/Native/gc/env/gcenv.ee.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,16 @@ class GCToEEInterface
static void GcEnumAllocContexts(enum_alloc_context_func* fn, void* param);

static Thread* CreateBackgroundThread(GCBackgroundThreadFunction threadStart, void* arg);

// Diagnostics methods.
static void DiagGCStart(int gen, bool isInduced);
static void DiagUpdateGenerationBounds();
static void DiagGCEnd(size_t index, int gen, int reason, bool fConcurrent);
static void DiagWalkFReachableObjects(void* gcContext);
static void DiagWalkSurvivors(void* gcContext);
static void DiagWalkLOHSurvivors(void* gcContext);
static void DiagWalkBGCSurvivors(void* gcContext);
static void StompWriteBarrier(WriteBarrierParameters* args);
};

#endif // __GCENV_EE_H__
Loading

0 comments on commit e567896

Please sign in to comment.