Skip to content

Commit

Permalink
Merge pull request dotnet#6522 from swaroop-sridhar/gcinfov2
Browse files Browse the repository at this point in the history
Implement GcInfo v2
  • Loading branch information
swaroop-sridhar authored Aug 5, 2016
2 parents 409fe37 + d302e64 commit 6bd9557
Show file tree
Hide file tree
Showing 30 changed files with 739 additions and 724 deletions.
2 changes: 2 additions & 0 deletions clrdefinitions.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ elseif (CLR_CMAKE_TARGET_ARCH_ARM64)
add_definitions(-DDBG_TARGET_64BIT=1)
add_definitions(-DDBG_TARGET_ARM64=1)
add_definitions(-DDBG_TARGET_WIN64=1)
add_definitions(-DFEATURE_MULTIREG_RETURN)
elseif (CLR_CMAKE_TARGET_ARCH_ARM)
if (CLR_CMAKE_PLATFORM_UNIX)
add_definitions(-DDBG_TARGET_ARM_UNIX)
Expand Down Expand Up @@ -166,6 +167,7 @@ add_definitions(-DFEATURE_SVR_GC)
add_definitions(-DFEATURE_SYMDIFF)
add_definitions(-DFEATURE_SYNTHETIC_CULTURES)
if(CLR_CMAKE_PLATFORM_UNIX_AMD64)
add_definitions(-DFEATURE_MULTIREG_RETURN)
add_definitions(-DFEATURE_UNIX_AMD64_STRUCT_PASSING)
add_definitions(-DFEATURE_UNIX_AMD64_STRUCT_PASSING_ITF)
endif (CLR_CMAKE_PLATFORM_UNIX_AMD64)
Expand Down
6 changes: 4 additions & 2 deletions src/debug/daccess/nidump.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3112,7 +3112,7 @@ void NativeImageDumper::DumpCompleteMethod(PTR_Module module, MethodIterator& mi
GCDump gcDump(gcInfoToken.Version);
gcDump.gcPrintf = stringOutFn;
#if !defined(_TARGET_X86_) && defined(USE_GC_INFO_DECODER)
GcInfoDecoder gcInfoDecoder(gcInfoToken, DECODE_CODE_LENGTH, 0);
GcInfoDecoder gcInfoDecoder(gcInfoToken, DECODE_CODE_LENGTH);
methodSize = gcInfoDecoder.GetCodeLength();
#endif

Expand Down Expand Up @@ -9440,7 +9440,9 @@ void NativeImageDumper::DumpReadyToRunMethod(PCODE pEntryPoint, PTR_RUNTIME_FUNC
GCDump gcDump(GCINFO_VERSION);
gcDump.gcPrintf = stringOutFn;
#if !defined(_TARGET_X86_) && defined(USE_GC_INFO_DECODER)
GcInfoDecoder gcInfoDecoder({ curGCInfoPtr, GCINFO_VERSION }, DECODE_CODE_LENGTH, 0);
UINT32 r2rversion = m_pReadyToRunHeader->MajorVersion;
UINT32 gcInfoVersion = GCInfoToken::ReadyToRunVersionToGcInfoVersion(r2rversion);
GcInfoDecoder gcInfoDecoder({ curGCInfoPtr, gcInfoVersion }, DECODE_CODE_LENGTH);
methodSize = gcInfoDecoder.GetCodeLength();
#endif

Expand Down
6 changes: 5 additions & 1 deletion src/gcdump/gcdumpnonx86.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -284,7 +284,8 @@ size_t GCDump::DumpGCTable(PTR_CBYTE gcInfoBlock,
| DECODE_VARARG
| DECODE_GENERICS_INST_CONTEXT
| DECODE_GC_LIFETIMES
| DECODE_PROLOG_LENGTH),
| DECODE_PROLOG_LENGTH
| DECODE_RETURN_KIND),
0);

if (NO_SECURITY_OBJECT != hdrdecoder.GetSecurityObjectStackSlot() ||
Expand Down Expand Up @@ -438,6 +439,9 @@ size_t GCDump::DumpGCTable(PTR_CBYTE gcInfoBlock,
gcPrintf("Size of parameter area: %x\n", hdrdecoder.GetSizeOfStackParameterArea());
#endif

ReturnKind returnKind = hdrdecoder.GetReturnKind();
gcPrintf("Return Kind: %s\n", ReturnKindToString(returnKind));

UINT32 cbEncodedMethodSize = hdrdecoder.GetCodeLength();
gcPrintf("Code size: %x\n", cbEncodedMethodSize);

Expand Down
63 changes: 57 additions & 6 deletions src/gcinfo/gcinfoencoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -324,13 +324,17 @@ typedef SimplerHashTable<const BitArray *, LiveStateFuncs, UINT32, GcInfoHashBeh
// Pi = partially-interruptible; methods with zero fully-interruptible ranges
GcInfoSize g_FiGcInfoSize;
GcInfoSize g_PiGcInfoSize;
// Number of methods with GcInfo that have SlimHeader
size_t g_NumSlimHeaders = 0;
// Number of methods with GcInfo that have FatHeader
size_t g_NumFatHeaders = 0;

GcInfoSize::GcInfoSize()
{
memset(this, 0, sizeof(*this));
}

GcInfoSize& operator+=(const GcInfoSize& other)
GcInfoSize& GcInfoSize::operator+=(const GcInfoSize& other)
{
TotalSize += other.TotalSize;

Expand All @@ -351,7 +355,7 @@ GcInfoSize& operator+=(const GcInfoSize& other)
GenericsCtxSize += other.GenericsCtxSize;
PspSymSize += other.PspSymSize;
StackBaseSize += other.StackBaseSize;
FrameMarkerSize += other.FrameMarkerSize;
ReversePInvokeFrameSize += other.ReversePInvokeFrameSize;
FixedAreaSize += other.FixedAreaSize;
NumCallSitesSize += other.NumCallSitesSize;
NumRangesSize += other.NumRangesSize;
Expand Down Expand Up @@ -398,8 +402,9 @@ void GcInfoSize::Log(DWORD level, const char * header)
LogSpew(LF_GCINFO, level, "GsCookie: %Iu\n", GsCookieSize);
LogSpew(LF_GCINFO, level, "PspSym: %Iu\n", PspSymSize);
LogSpew(LF_GCINFO, level, "GenericsCtx: %Iu\n", GenericsCtxSize);
LogSpew(LF_GCINFO, level, "FrameMarker: %Iu\n", FrameMarkerSize);
LogSpew(LF_GCINFO, level, "StackBase: %Iu\n", StackBaseSize);
LogSpew(LF_GCINFO, level, "FixedArea: %Iu\n", FixedAreaSize);
LogSpew(LF_GCINFO, level, "ReversePInvokeFrame: %Iu\n", ReversePInvokeFrameSize);
LogSpew(LF_GCINFO, level, "NumCallSites: %Iu\n", NumCallSitesSize);
LogSpew(LF_GCINFO, level, "NumRanges: %Iu\n", NumRangesSize);
LogSpew(LF_GCINFO, level, "CallSiteOffsets: %Iu\n", CallSitePosSize);
Expand Down Expand Up @@ -488,17 +493,27 @@ GcInfoEncoder::GcInfoEncoder(

m_StackBaseRegister = NO_STACK_BASE_REGISTER;
m_SizeOfEditAndContinuePreservedArea = NO_SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA;
m_ReversePInvokeFrameSlot = NO_REVERSE_PINVOKE_FRAME;
m_WantsReportOnlyLeaf = false;
m_IsVarArg = false;
m_pLastInterruptibleRange = NULL;

#ifdef _DEBUG
m_IsSlotTableFrozen = FALSE;
#endif //_DEBUG

#ifndef _TARGET_X86_
// If the compiler doesn't set the GCInfo, report RT_Unset.
// This is used for compatibility with JITs that aren't updated to use the new API.
m_ReturnKind = RT_Unset;
#else
m_ReturnKind = RT_Illegal;
#endif // _TARGET_X86_
m_CodeLength = 0;
#ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA
m_SizeOfStackOutgoingAndScratchArea = -1;
#endif // FIXED_STACK_PARAMETER_SCRATCH_AREA
#endif //_DEBUG

}

#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED
Expand Down Expand Up @@ -758,14 +773,24 @@ void GcInfoEncoder::SetSizeOfStackOutgoingAndScratchArea( UINT32 size )
}
#endif // FIXED_STACK_PARAMETER_SCRATCH_AREA

void GcInfoEncoder::SetReversePInvokeFrameSlot(INT32 spOffset)
{
m_ReversePInvokeFrameSlot = spOffset;
}

void GcInfoEncoder::SetReturnKind(ReturnKind returnKind)
{
_ASSERTE(IsValidReturnKind(returnKind));

m_ReturnKind = returnKind;
}

struct GcSlotDescAndId
{
GcSlotDesc m_SlotDesc;
UINT32 m_SlotId;
};


int __cdecl CompareSlotDescAndIdBySlotDesc(const void* p1, const void* p2)
{
const GcSlotDesc* pFirst = &reinterpret_cast<const GcSlotDescAndId*>(p1)->m_SlotDesc;
Expand Down Expand Up @@ -985,20 +1010,26 @@ void GcInfoEncoder::Build()
// Method header
///////////////////////////////////////////////////////////////////////


UINT32 hasSecurityObject = (m_SecurityObjectStackSlot != NO_SECURITY_OBJECT);
UINT32 hasGSCookie = (m_GSCookieStackSlot != NO_GS_COOKIE);
UINT32 hasContextParamType = (m_GenericsInstContextStackSlot != NO_GENERICS_INST_CONTEXT);
UINT32 hasReversePInvokeFrame = (m_ReversePInvokeFrameSlot != NO_REVERSE_PINVOKE_FRAME);

BOOL slimHeader = (!m_IsVarArg && !hasSecurityObject && !hasGSCookie && (m_PSPSymStackSlot == NO_PSP_SYM) &&
!hasContextParamType && !m_WantsReportOnlyLeaf && (m_InterruptibleRanges.Count() == 0) &&
!hasContextParamType && !m_WantsReportOnlyLeaf && (m_InterruptibleRanges.Count() == 0) && !hasReversePInvokeFrame &&
((m_StackBaseRegister == NO_STACK_BASE_REGISTER) || (NORMALIZE_STACK_BASE_REGISTER(m_StackBaseRegister) == 0))) &&
(m_SizeOfEditAndContinuePreservedArea == NO_SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA);

// All new code is generated for the latest GCINFO_VERSION.
// So, always encode RetunrKind and encode ReversePInvokeFrameSlot where applicable.
if (slimHeader)
{
// Slim encoding means nothing special, partially interruptible, maybe a default frame register
GCINFO_WRITE(m_Info1, 0, 1, FlagsSize); // Slim encoding
GCINFO_WRITE(m_Info1, (m_StackBaseRegister == NO_STACK_BASE_REGISTER) ? 0 : 1, 1, FlagsSize);

GCINFO_WRITE(m_Info1, m_ReturnKind, SIZE_OF_RETURN_KIND_IN_SLIM_HEADER, RetKindSize);
}
else
{
Expand All @@ -1011,6 +1042,9 @@ void GcInfoEncoder::Build()
GCINFO_WRITE(m_Info1, ((m_StackBaseRegister != NO_STACK_BASE_REGISTER) ? 1 : 0), 1, FlagsSize);
GCINFO_WRITE(m_Info1, (m_WantsReportOnlyLeaf ? 1 : 0), 1, FlagsSize);
GCINFO_WRITE(m_Info1, ((m_SizeOfEditAndContinuePreservedArea != NO_SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA) ? 1 : 0), 1, FlagsSize);
GCINFO_WRITE(m_Info1, (hasReversePInvokeFrame ? 1 : 0), 1, FlagsSize);

GCINFO_WRITE(m_Info1, m_ReturnKind, SIZE_OF_RETURN_KIND_IN_FAT_HEADER, RetKindSize);
}

_ASSERTE( m_CodeLength > 0 );
Expand Down Expand Up @@ -1109,6 +1143,12 @@ void GcInfoEncoder::Build()
GCINFO_WRITE_VARL_U(m_Info1, m_SizeOfEditAndContinuePreservedArea, SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE, EncPreservedSlots);
}

if (hasReversePInvokeFrame)
{
_ASSERTE(!slimHeader);
GCINFO_WRITE_VARL_S(m_Info1, NORMALIZE_STACK_SLOT(m_ReversePInvokeFrameSlot), REVERSE_PINVOKE_FRAME_ENCBASE, ReversePInvokeFrameSize);
}

#ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA
if (!slimHeader)
{
Expand Down Expand Up @@ -2305,6 +2345,15 @@ lExitSuccess:;
//-------------------------------------------------------------------

#ifdef MEASURE_GCINFO
if (slimHeader)
{
g_NumSlimHeaders++;
}
else
{
g_NumFatHeaders++;
}

m_CurrentMethodSize.NumMethods = 1;
#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED
m_CurrentMethodSize.NumCallSites = m_NumCallSites;
Expand All @@ -2331,6 +2380,8 @@ lExitSuccess:;
m_CurrentMethodSize.Log(LL_INFO100, "=== PartiallyInterruptible method breakdown ===\r\n");
g_PiGcInfoSize.Log(LL_INFO10, "=== PartiallyInterruptible global breakdown ===\r\n");
}
LogSpew(LF_GCINFO, LL_INFO10, "Total SlimHeaders: %Iu\n", g_NumSlimHeaders);
LogSpew(LF_GCINFO, LL_INFO10, "NumMethods: %Iu\n", g_NumFatHeaders);
#endif
}

Expand Down
26 changes: 24 additions & 2 deletions src/inc/gcinfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,15 @@ const unsigned this_OFFSET_FLAG = 0x2; // the offset is "this"
// The current GCInfo Version
//-----------------------------------------------------------------------------

#ifdef _TARGET_X86_
// X86 GcInfo encoding is yet to be changed.
#define GCINFO_VERSION 1
#else
#define GCINFO_VERSION 2
#endif // _TARGET_X86_

#define MIN_GCINFO_VERSION_WITH_RETURN_KIND 2
#define MIN_GCINFO_VERSION_WITH_REV_PINVOKE_FRAME 2
//-----------------------------------------------------------------------------
// GCInfoToken: A wrapper that contains the GcInfo data and version number.
//
Expand All @@ -45,14 +52,29 @@ const unsigned this_OFFSET_FLAG = 0x2; // the offset is "this"
// 1) The current GCINFO_VERSION for JITted and Ngened images
// 2) A function of the Ready - to - run major version stored in READYTORUN_HEADER
// for ready - to - run images.ReadyToRunJitManager::JitTokenToGCInfoVersion()
// provides the GcInfo version for any Method.Currently, there's only one
// version of GCInfo.
// provides the GcInfo version for any Method.
//-----------------------------------------------------------------------------

struct GCInfoToken
{
PTR_VOID Info;
UINT32 Version;

BOOL IsReturnKindAvailable()
{
return (Version >= MIN_GCINFO_VERSION_WITH_RETURN_KIND);
}
BOOL IsReversePInvokeFrameAvailable()
{
return (Version >= MIN_GCINFO_VERSION_WITH_REV_PINVOKE_FRAME);
}

static UINT32 ReadyToRunVersionToGcInfoVersion(UINT32 readyToRunMajorVersion)
{
// GcInfo version is 1 up to ReadyTorun version 1.x
// GcInfo version is current from ReadyToRun version 2.0
return (readyToRunMajorVersion == 1) ? 1 : GCINFO_VERSION;
}
};

/*****************************************************************************/
Expand Down
17 changes: 13 additions & 4 deletions src/inc/gcinfodecoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,7 @@ enum ICodeManagerFlags

enum GcInfoDecoderFlags
{
DECODE_EVERYTHING = 0x0,
DECODE_SECURITY_OBJECT = 0x01, // stack location of security object
DECODE_CODE_LENGTH = 0x02,
DECODE_VARARG = 0x04,
Expand All @@ -174,6 +175,8 @@ enum GcInfoDecoderFlags
DECODE_FOR_RANGES_CALLBACK = 0x200,
DECODE_PROLOG_LENGTH = 0x400, // length of the prolog (used to avoid reporting generics context)
DECODE_EDIT_AND_CONTINUE = 0x800,
DECODE_REVERSE_PINVOKE_VAR = 0x1000,
DECODE_RETURN_KIND = 0x2000
};

enum GcInfoHeaderFlags
Expand All @@ -190,11 +193,12 @@ enum GcInfoHeaderFlags
GC_INFO_HAS_STACK_BASE_REGISTER = 0x40,
GC_INFO_WANTS_REPORT_ONLY_LEAF = 0x80,
GC_INFO_HAS_EDIT_AND_CONTINUE_PRESERVED_SLOTS = 0x100,
GC_INFO_REVERSE_PINVOKE_FRAME = 0x200,

GC_INFO_FLAGS_BIT_SIZE = 9,
GC_INFO_FLAGS_BIT_SIZE_VERSION_1 = 9,
GC_INFO_FLAGS_BIT_SIZE = 10,
};


class BitStreamReader
{
public:
Expand Down Expand Up @@ -430,7 +434,7 @@ class GcInfoDecoder
// If you are not insterested in interruptibility or gc lifetime information, pass 0 as instructionOffset
GcInfoDecoder(
GCInfoToken gcInfoToken,
GcInfoDecoderFlags flags,
GcInfoDecoderFlags flags = DECODE_EVERYTHING,
UINT32 instructionOffset = 0
);

Expand Down Expand Up @@ -486,10 +490,12 @@ class GcInfoDecoder
UINT32 GetPrologSize();
INT32 GetPSPSymStackSlot();
INT32 GetGenericsInstContextStackSlot();
INT32 GetReversePInvokeStackSlot();
bool HasMethodDescGenericsInstContext();
bool HasMethodTableGenericsInstContext();
bool GetIsVarArg();
bool WantsReportOnlyLeaf();
ReturnKind GetReturnKind();
UINT32 GetCodeLength();
UINT32 GetStackBaseRegister();
UINT32 GetSizeOfEditAndContinuePreservedArea();
Expand All @@ -512,13 +518,16 @@ class GcInfoDecoder
bool m_WantsReportOnlyLeaf;
INT32 m_SecurityObjectStackSlot;
INT32 m_GSCookieStackSlot;
INT32 m_ReversePInvokeStackSlot;
UINT32 m_ValidRangeStart;
UINT32 m_ValidRangeEnd;
INT32 m_PSPSymStackSlot;
INT32 m_GenericsInstContextStackSlot;
UINT32 m_CodeLength;
UINT32 m_StackBaseRegister;
UINT32 m_SizeOfEditAndContinuePreservedArea;
INT32 m_ReversePInvokeFrameSlot;
ReturnKind m_ReturnKind;
#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED
UINT32 m_NumSafePoints;
UINT32 m_SafePointIndex;
Expand All @@ -533,8 +542,8 @@ class GcInfoDecoder
#ifdef _DEBUG
GcInfoDecoderFlags m_Flags;
PTR_CBYTE m_GcInfoAddress;
UINT32 m_Version;
#endif
UINT32 m_Version;

static bool SetIsInterruptibleCB (UINT32 startOffset, UINT32 stopOffset, LPVOID hCallback);

Expand Down
Loading

0 comments on commit 6bd9557

Please sign in to comment.