Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 6bd9557

Browse files
Merge pull request #6522 from swaroop-sridhar/gcinfov2
Implement GcInfo v2
2 parents 409fe37 + d302e64 commit 6bd9557

30 files changed

+739
-724
lines changed

clrdefinitions.cmake

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ elseif (CLR_CMAKE_TARGET_ARCH_ARM64)
2727
add_definitions(-DDBG_TARGET_64BIT=1)
2828
add_definitions(-DDBG_TARGET_ARM64=1)
2929
add_definitions(-DDBG_TARGET_WIN64=1)
30+
add_definitions(-DFEATURE_MULTIREG_RETURN)
3031
elseif (CLR_CMAKE_TARGET_ARCH_ARM)
3132
if (CLR_CMAKE_PLATFORM_UNIX)
3233
add_definitions(-DDBG_TARGET_ARM_UNIX)
@@ -166,6 +167,7 @@ add_definitions(-DFEATURE_SVR_GC)
166167
add_definitions(-DFEATURE_SYMDIFF)
167168
add_definitions(-DFEATURE_SYNTHETIC_CULTURES)
168169
if(CLR_CMAKE_PLATFORM_UNIX_AMD64)
170+
add_definitions(-DFEATURE_MULTIREG_RETURN)
169171
add_definitions(-DFEATURE_UNIX_AMD64_STRUCT_PASSING)
170172
add_definitions(-DFEATURE_UNIX_AMD64_STRUCT_PASSING_ITF)
171173
endif (CLR_CMAKE_PLATFORM_UNIX_AMD64)

src/debug/daccess/nidump.cpp

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3112,7 +3112,7 @@ void NativeImageDumper::DumpCompleteMethod(PTR_Module module, MethodIterator& mi
31123112
GCDump gcDump(gcInfoToken.Version);
31133113
gcDump.gcPrintf = stringOutFn;
31143114
#if !defined(_TARGET_X86_) && defined(USE_GC_INFO_DECODER)
3115-
GcInfoDecoder gcInfoDecoder(gcInfoToken, DECODE_CODE_LENGTH, 0);
3115+
GcInfoDecoder gcInfoDecoder(gcInfoToken, DECODE_CODE_LENGTH);
31163116
methodSize = gcInfoDecoder.GetCodeLength();
31173117
#endif
31183118

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

src/gcdump/gcdumpnonx86.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,8 @@ size_t GCDump::DumpGCTable(PTR_CBYTE gcInfoBlock,
284284
| DECODE_VARARG
285285
| DECODE_GENERICS_INST_CONTEXT
286286
| DECODE_GC_LIFETIMES
287-
| DECODE_PROLOG_LENGTH),
287+
| DECODE_PROLOG_LENGTH
288+
| DECODE_RETURN_KIND),
288289
0);
289290

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

442+
ReturnKind returnKind = hdrdecoder.GetReturnKind();
443+
gcPrintf("Return Kind: %s\n", ReturnKindToString(returnKind));
444+
441445
UINT32 cbEncodedMethodSize = hdrdecoder.GetCodeLength();
442446
gcPrintf("Code size: %x\n", cbEncodedMethodSize);
443447

src/gcinfo/gcinfoencoder.cpp

Lines changed: 57 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -324,13 +324,17 @@ typedef SimplerHashTable<const BitArray *, LiveStateFuncs, UINT32, GcInfoHashBeh
324324
// Pi = partially-interruptible; methods with zero fully-interruptible ranges
325325
GcInfoSize g_FiGcInfoSize;
326326
GcInfoSize g_PiGcInfoSize;
327+
// Number of methods with GcInfo that have SlimHeader
328+
size_t g_NumSlimHeaders = 0;
329+
// Number of methods with GcInfo that have FatHeader
330+
size_t g_NumFatHeaders = 0;
327331

328332
GcInfoSize::GcInfoSize()
329333
{
330334
memset(this, 0, sizeof(*this));
331335
}
332336

333-
GcInfoSize& operator+=(const GcInfoSize& other)
337+
GcInfoSize& GcInfoSize::operator+=(const GcInfoSize& other)
334338
{
335339
TotalSize += other.TotalSize;
336340

@@ -351,7 +355,7 @@ GcInfoSize& operator+=(const GcInfoSize& other)
351355
GenericsCtxSize += other.GenericsCtxSize;
352356
PspSymSize += other.PspSymSize;
353357
StackBaseSize += other.StackBaseSize;
354-
FrameMarkerSize += other.FrameMarkerSize;
358+
ReversePInvokeFrameSize += other.ReversePInvokeFrameSize;
355359
FixedAreaSize += other.FixedAreaSize;
356360
NumCallSitesSize += other.NumCallSitesSize;
357361
NumRangesSize += other.NumRangesSize;
@@ -398,8 +402,9 @@ void GcInfoSize::Log(DWORD level, const char * header)
398402
LogSpew(LF_GCINFO, level, "GsCookie: %Iu\n", GsCookieSize);
399403
LogSpew(LF_GCINFO, level, "PspSym: %Iu\n", PspSymSize);
400404
LogSpew(LF_GCINFO, level, "GenericsCtx: %Iu\n", GenericsCtxSize);
401-
LogSpew(LF_GCINFO, level, "FrameMarker: %Iu\n", FrameMarkerSize);
405+
LogSpew(LF_GCINFO, level, "StackBase: %Iu\n", StackBaseSize);
402406
LogSpew(LF_GCINFO, level, "FixedArea: %Iu\n", FixedAreaSize);
407+
LogSpew(LF_GCINFO, level, "ReversePInvokeFrame: %Iu\n", ReversePInvokeFrameSize);
403408
LogSpew(LF_GCINFO, level, "NumCallSites: %Iu\n", NumCallSitesSize);
404409
LogSpew(LF_GCINFO, level, "NumRanges: %Iu\n", NumRangesSize);
405410
LogSpew(LF_GCINFO, level, "CallSiteOffsets: %Iu\n", CallSitePosSize);
@@ -488,17 +493,27 @@ GcInfoEncoder::GcInfoEncoder(
488493

489494
m_StackBaseRegister = NO_STACK_BASE_REGISTER;
490495
m_SizeOfEditAndContinuePreservedArea = NO_SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA;
496+
m_ReversePInvokeFrameSlot = NO_REVERSE_PINVOKE_FRAME;
491497
m_WantsReportOnlyLeaf = false;
492498
m_IsVarArg = false;
493499
m_pLastInterruptibleRange = NULL;
494500

495501
#ifdef _DEBUG
496502
m_IsSlotTableFrozen = FALSE;
503+
#endif //_DEBUG
504+
505+
#ifndef _TARGET_X86_
506+
// If the compiler doesn't set the GCInfo, report RT_Unset.
507+
// This is used for compatibility with JITs that aren't updated to use the new API.
508+
m_ReturnKind = RT_Unset;
509+
#else
510+
m_ReturnKind = RT_Illegal;
511+
#endif // _TARGET_X86_
497512
m_CodeLength = 0;
498513
#ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA
499514
m_SizeOfStackOutgoingAndScratchArea = -1;
500515
#endif // FIXED_STACK_PARAMETER_SCRATCH_AREA
501-
#endif //_DEBUG
516+
502517
}
503518

504519
#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED
@@ -758,14 +773,24 @@ void GcInfoEncoder::SetSizeOfStackOutgoingAndScratchArea( UINT32 size )
758773
}
759774
#endif // FIXED_STACK_PARAMETER_SCRATCH_AREA
760775

776+
void GcInfoEncoder::SetReversePInvokeFrameSlot(INT32 spOffset)
777+
{
778+
m_ReversePInvokeFrameSlot = spOffset;
779+
}
780+
781+
void GcInfoEncoder::SetReturnKind(ReturnKind returnKind)
782+
{
783+
_ASSERTE(IsValidReturnKind(returnKind));
784+
785+
m_ReturnKind = returnKind;
786+
}
761787

762788
struct GcSlotDescAndId
763789
{
764790
GcSlotDesc m_SlotDesc;
765791
UINT32 m_SlotId;
766792
};
767793

768-
769794
int __cdecl CompareSlotDescAndIdBySlotDesc(const void* p1, const void* p2)
770795
{
771796
const GcSlotDesc* pFirst = &reinterpret_cast<const GcSlotDescAndId*>(p1)->m_SlotDesc;
@@ -985,20 +1010,26 @@ void GcInfoEncoder::Build()
9851010
// Method header
9861011
///////////////////////////////////////////////////////////////////////
9871012

1013+
9881014
UINT32 hasSecurityObject = (m_SecurityObjectStackSlot != NO_SECURITY_OBJECT);
9891015
UINT32 hasGSCookie = (m_GSCookieStackSlot != NO_GS_COOKIE);
9901016
UINT32 hasContextParamType = (m_GenericsInstContextStackSlot != NO_GENERICS_INST_CONTEXT);
1017+
UINT32 hasReversePInvokeFrame = (m_ReversePInvokeFrameSlot != NO_REVERSE_PINVOKE_FRAME);
9911018

9921019
BOOL slimHeader = (!m_IsVarArg && !hasSecurityObject && !hasGSCookie && (m_PSPSymStackSlot == NO_PSP_SYM) &&
993-
!hasContextParamType && !m_WantsReportOnlyLeaf && (m_InterruptibleRanges.Count() == 0) &&
1020+
!hasContextParamType && !m_WantsReportOnlyLeaf && (m_InterruptibleRanges.Count() == 0) && !hasReversePInvokeFrame &&
9941021
((m_StackBaseRegister == NO_STACK_BASE_REGISTER) || (NORMALIZE_STACK_BASE_REGISTER(m_StackBaseRegister) == 0))) &&
9951022
(m_SizeOfEditAndContinuePreservedArea == NO_SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA);
9961023

1024+
// All new code is generated for the latest GCINFO_VERSION.
1025+
// So, always encode RetunrKind and encode ReversePInvokeFrameSlot where applicable.
9971026
if (slimHeader)
9981027
{
9991028
// Slim encoding means nothing special, partially interruptible, maybe a default frame register
10001029
GCINFO_WRITE(m_Info1, 0, 1, FlagsSize); // Slim encoding
10011030
GCINFO_WRITE(m_Info1, (m_StackBaseRegister == NO_STACK_BASE_REGISTER) ? 0 : 1, 1, FlagsSize);
1031+
1032+
GCINFO_WRITE(m_Info1, m_ReturnKind, SIZE_OF_RETURN_KIND_IN_SLIM_HEADER, RetKindSize);
10021033
}
10031034
else
10041035
{
@@ -1011,6 +1042,9 @@ void GcInfoEncoder::Build()
10111042
GCINFO_WRITE(m_Info1, ((m_StackBaseRegister != NO_STACK_BASE_REGISTER) ? 1 : 0), 1, FlagsSize);
10121043
GCINFO_WRITE(m_Info1, (m_WantsReportOnlyLeaf ? 1 : 0), 1, FlagsSize);
10131044
GCINFO_WRITE(m_Info1, ((m_SizeOfEditAndContinuePreservedArea != NO_SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA) ? 1 : 0), 1, FlagsSize);
1045+
GCINFO_WRITE(m_Info1, (hasReversePInvokeFrame ? 1 : 0), 1, FlagsSize);
1046+
1047+
GCINFO_WRITE(m_Info1, m_ReturnKind, SIZE_OF_RETURN_KIND_IN_FAT_HEADER, RetKindSize);
10141048
}
10151049

10161050
_ASSERTE( m_CodeLength > 0 );
@@ -1109,6 +1143,12 @@ void GcInfoEncoder::Build()
11091143
GCINFO_WRITE_VARL_U(m_Info1, m_SizeOfEditAndContinuePreservedArea, SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE, EncPreservedSlots);
11101144
}
11111145

1146+
if (hasReversePInvokeFrame)
1147+
{
1148+
_ASSERTE(!slimHeader);
1149+
GCINFO_WRITE_VARL_S(m_Info1, NORMALIZE_STACK_SLOT(m_ReversePInvokeFrameSlot), REVERSE_PINVOKE_FRAME_ENCBASE, ReversePInvokeFrameSize);
1150+
}
1151+
11121152
#ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA
11131153
if (!slimHeader)
11141154
{
@@ -2305,6 +2345,15 @@ lExitSuccess:;
23052345
//-------------------------------------------------------------------
23062346

23072347
#ifdef MEASURE_GCINFO
2348+
if (slimHeader)
2349+
{
2350+
g_NumSlimHeaders++;
2351+
}
2352+
else
2353+
{
2354+
g_NumFatHeaders++;
2355+
}
2356+
23082357
m_CurrentMethodSize.NumMethods = 1;
23092358
#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED
23102359
m_CurrentMethodSize.NumCallSites = m_NumCallSites;
@@ -2331,6 +2380,8 @@ lExitSuccess:;
23312380
m_CurrentMethodSize.Log(LL_INFO100, "=== PartiallyInterruptible method breakdown ===\r\n");
23322381
g_PiGcInfoSize.Log(LL_INFO10, "=== PartiallyInterruptible global breakdown ===\r\n");
23332382
}
2383+
LogSpew(LF_GCINFO, LL_INFO10, "Total SlimHeaders: %Iu\n", g_NumSlimHeaders);
2384+
LogSpew(LF_GCINFO, LL_INFO10, "NumMethods: %Iu\n", g_NumFatHeaders);
23342385
#endif
23352386
}
23362387

src/inc/gcinfo.h

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,15 @@ const unsigned this_OFFSET_FLAG = 0x2; // the offset is "this"
3232
// The current GCInfo Version
3333
//-----------------------------------------------------------------------------
3434

35+
#ifdef _TARGET_X86_
36+
// X86 GcInfo encoding is yet to be changed.
3537
#define GCINFO_VERSION 1
38+
#else
39+
#define GCINFO_VERSION 2
40+
#endif // _TARGET_X86_
3641

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

5258
struct GCInfoToken
5359
{
5460
PTR_VOID Info;
5561
UINT32 Version;
62+
63+
BOOL IsReturnKindAvailable()
64+
{
65+
return (Version >= MIN_GCINFO_VERSION_WITH_RETURN_KIND);
66+
}
67+
BOOL IsReversePInvokeFrameAvailable()
68+
{
69+
return (Version >= MIN_GCINFO_VERSION_WITH_REV_PINVOKE_FRAME);
70+
}
71+
72+
static UINT32 ReadyToRunVersionToGcInfoVersion(UINT32 readyToRunMajorVersion)
73+
{
74+
// GcInfo version is 1 up to ReadyTorun version 1.x
75+
// GcInfo version is current from ReadyToRun version 2.0
76+
return (readyToRunMajorVersion == 1) ? 1 : GCINFO_VERSION;
77+
}
5678
};
5779

5880
/*****************************************************************************/

src/inc/gcinfodecoder.h

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,7 @@ enum ICodeManagerFlags
161161

162162
enum GcInfoDecoderFlags
163163
{
164+
DECODE_EVERYTHING = 0x0,
164165
DECODE_SECURITY_OBJECT = 0x01, // stack location of security object
165166
DECODE_CODE_LENGTH = 0x02,
166167
DECODE_VARARG = 0x04,
@@ -174,6 +175,8 @@ enum GcInfoDecoderFlags
174175
DECODE_FOR_RANGES_CALLBACK = 0x200,
175176
DECODE_PROLOG_LENGTH = 0x400, // length of the prolog (used to avoid reporting generics context)
176177
DECODE_EDIT_AND_CONTINUE = 0x800,
178+
DECODE_REVERSE_PINVOKE_VAR = 0x1000,
179+
DECODE_RETURN_KIND = 0x2000
177180
};
178181

179182
enum GcInfoHeaderFlags
@@ -190,11 +193,12 @@ enum GcInfoHeaderFlags
190193
GC_INFO_HAS_STACK_BASE_REGISTER = 0x40,
191194
GC_INFO_WANTS_REPORT_ONLY_LEAF = 0x80,
192195
GC_INFO_HAS_EDIT_AND_CONTINUE_PRESERVED_SLOTS = 0x100,
196+
GC_INFO_REVERSE_PINVOKE_FRAME = 0x200,
193197

194-
GC_INFO_FLAGS_BIT_SIZE = 9,
198+
GC_INFO_FLAGS_BIT_SIZE_VERSION_1 = 9,
199+
GC_INFO_FLAGS_BIT_SIZE = 10,
195200
};
196201

197-
198202
class BitStreamReader
199203
{
200204
public:
@@ -430,7 +434,7 @@ class GcInfoDecoder
430434
// If you are not insterested in interruptibility or gc lifetime information, pass 0 as instructionOffset
431435
GcInfoDecoder(
432436
GCInfoToken gcInfoToken,
433-
GcInfoDecoderFlags flags,
437+
GcInfoDecoderFlags flags = DECODE_EVERYTHING,
434438
UINT32 instructionOffset = 0
435439
);
436440

@@ -486,10 +490,12 @@ class GcInfoDecoder
486490
UINT32 GetPrologSize();
487491
INT32 GetPSPSymStackSlot();
488492
INT32 GetGenericsInstContextStackSlot();
493+
INT32 GetReversePInvokeStackSlot();
489494
bool HasMethodDescGenericsInstContext();
490495
bool HasMethodTableGenericsInstContext();
491496
bool GetIsVarArg();
492497
bool WantsReportOnlyLeaf();
498+
ReturnKind GetReturnKind();
493499
UINT32 GetCodeLength();
494500
UINT32 GetStackBaseRegister();
495501
UINT32 GetSizeOfEditAndContinuePreservedArea();
@@ -512,13 +518,16 @@ class GcInfoDecoder
512518
bool m_WantsReportOnlyLeaf;
513519
INT32 m_SecurityObjectStackSlot;
514520
INT32 m_GSCookieStackSlot;
521+
INT32 m_ReversePInvokeStackSlot;
515522
UINT32 m_ValidRangeStart;
516523
UINT32 m_ValidRangeEnd;
517524
INT32 m_PSPSymStackSlot;
518525
INT32 m_GenericsInstContextStackSlot;
519526
UINT32 m_CodeLength;
520527
UINT32 m_StackBaseRegister;
521528
UINT32 m_SizeOfEditAndContinuePreservedArea;
529+
INT32 m_ReversePInvokeFrameSlot;
530+
ReturnKind m_ReturnKind;
522531
#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED
523532
UINT32 m_NumSafePoints;
524533
UINT32 m_SafePointIndex;
@@ -533,8 +542,8 @@ class GcInfoDecoder
533542
#ifdef _DEBUG
534543
GcInfoDecoderFlags m_Flags;
535544
PTR_CBYTE m_GcInfoAddress;
536-
UINT32 m_Version;
537545
#endif
546+
UINT32 m_Version;
538547

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

0 commit comments

Comments
 (0)