diff --git a/src/SOS/Strike/strike.cpp b/src/SOS/Strike/strike.cpp index db8cf6191f..c4f7966f92 100644 --- a/src/SOS/Strike/strike.cpp +++ b/src/SOS/Strike/strike.cpp @@ -6806,7 +6806,7 @@ DECLARE_API(GCInfo) // Mutable table pointer since we need to pass the appropriate // offset into the table to DumpGCTable. - GCInfoToken gcInfoToken = { table, GCINFO_VERSION }; + GCInfoToken gcInfoToken = { table, GCInfoVersion() }; unsigned int methodSize = (unsigned int)codeHeaderData.MethodSize; g_targetMachine->DumpGCInfo(gcInfoToken, methodSize, ExtOut, true /*encBytes*/, true /*bPrintHeader*/); @@ -7453,7 +7453,7 @@ HRESULT displayGcInfo(BOOL fWithGCInfo, const DacpCodeHeaderData& codeHeaderData return E_OUTOFMEMORY; } - GCInfoToken gcInfoToken = { table, GCINFO_VERSION }; + GCInfoToken gcInfoToken = { table, GCInfoVersion() }; g_targetMachine->DumpGCInfo(gcInfoToken, methodSize, DecodeGCTableEntry, false /*encBytes*/, false /*bPrintHeader*/); } return S_OK; diff --git a/src/shared/gcdump/gcdumpnonx86.cpp b/src/shared/gcdump/gcdumpnonx86.cpp index 919bf60d88..4568477e3a 100644 --- a/src/shared/gcdump/gcdumpnonx86.cpp +++ b/src/shared/gcdump/gcdumpnonx86.cpp @@ -502,8 +502,11 @@ 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)); + if (hdrdecoder.Version() < 4) + { + ReturnKind returnKind = hdrdecoder.GetReturnKind(); + gcPrintf("Return Kind: %s\n", ReturnKindToString(returnKind)); + } UINT32 cbEncodedMethodSize = hdrdecoder.GetCodeLength(); gcPrintf("Code size: %x\n", cbEncodedMethodSize); diff --git a/src/shared/inc/gcinfo.h b/src/shared/inc/gcinfo.h index d526405c9f..cdcbb9eb14 100644 --- a/src/shared/inc/gcinfo.h +++ b/src/shared/inc/gcinfo.h @@ -4,6 +4,7 @@ // ****************************************************************************** // WARNING!!!: These values are used by SOS in the diagnostics repo. Values should // added or removed in a backwards and forwards compatible way. +// There are scenarios in diagnostics that support parsing of old GC Info formats. // See: https://github.com/dotnet/diagnostics/blob/main/src/shared/inc/gcinfo.h // ****************************************************************************** @@ -36,7 +37,18 @@ const unsigned this_OFFSET_FLAG = 0x2; // the offset is "this" // The current GCInfo Version //----------------------------------------------------------------------------- -#define GCINFO_VERSION 3 +#define GCINFO_VERSION 4 + +#ifdef SOS_INCLUDE +extern bool IsRuntimeVersionAtLeast(DWORD major); +inline int GCInfoVersion() +{ + // In SOS we only care about ability to parse/dump the GC Info. + // Since v2 and v3 had the same file format and v1 is no longer supported, + // we can assume that everything before net10.0 uses GCInfo v3. + return IsRuntimeVersionAtLeast(10) ? 4 : 3; +} +#endif //----------------------------------------------------------------------------- // GCInfoToken: A wrapper that contains the GcInfo data and version number. @@ -67,15 +79,11 @@ struct GCInfoToken static uint32_t ReadyToRunVersionToGcInfoVersion(uint32_t readyToRunMajorVersion, uint32_t readyToRunMinorVersion) { - // Once MINIMUM_READYTORUN_MAJOR_VERSION is bumped to 10+ - // delete the following and just return GCINFO_VERSION - // - // R2R 9.0 and 9.1 use GCInfo v2 - // R2R 9.2 uses GCInfo v3 - if (readyToRunMajorVersion == 9 && readyToRunMinorVersion < 2) - return 2; - +#ifdef SOS_INCLUDE + return GCInfoVersion(); +#else return GCINFO_VERSION; +#endif } }; diff --git a/src/shared/inc/gcinfodecoder.h b/src/shared/inc/gcinfodecoder.h index 6f62a3f874..450e1fbf2f 100644 --- a/src/shared/inc/gcinfodecoder.h +++ b/src/shared/inc/gcinfodecoder.h @@ -16,6 +16,10 @@ #ifndef _GC_INFO_DECODER_ #define _GC_INFO_DECODER_ +#ifdef SOS_INCLUDE +#define DECODE_OLD_FORMATS +#endif + #define _max(a, b) (((a) > (b)) ? (a) : (b)) #define _min(a, b) (((a) < (b)) ? (a) : (b)) @@ -222,7 +226,7 @@ enum GcInfoDecoderFlags 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, + DECODE_RETURN_KIND = 0x2000, // Unused starting with v4 format #if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) DECODE_HAS_TAILCALLS = 0x4000, #endif // TARGET_ARM || TARGET_ARM64 || TARGET_LOONGARCH64 @@ -248,7 +252,6 @@ enum GcInfoHeaderFlags GC_INFO_HAS_EDIT_AND_CONTINUE_INFO = 0x100, GC_INFO_REVERSE_PINVOKE_FRAME = 0x200, - GC_INFO_FLAGS_BIT_SIZE_VERSION_1 = 9, GC_INFO_FLAGS_BIT_SIZE = 10, }; @@ -466,6 +469,8 @@ struct GcSlotDesc GcSlotFlags Flags; }; + +template class GcSlotDecoder { public: @@ -508,12 +513,13 @@ class GcSlotDecoder }; #ifdef USE_GC_INFO_DECODER -class GcInfoDecoder +template +class TGcInfoDecoder { public: // If you are not interested in interruptibility or gc lifetime information, pass 0 as instructionOffset - GcInfoDecoder( + TGcInfoDecoder( GCInfoToken gcInfoToken, GcInfoDecoderFlags flags = DECODE_EVERYTHING, UINT32 instructionOffset = 0 @@ -528,14 +534,12 @@ class GcInfoDecoder #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED bool IsSafePoint(); - bool AreSafePointsInterruptible(); - bool IsInterruptibleSafePoint(); - bool CouldBeInterruptibleSafePoint(); + bool CouldBeSafePoint(); - // This is used for gccoverage + // This is used for gcinfodumper bool IsSafePoint(UINT32 codeOffset); - typedef void EnumerateSafePointsCallback (GcInfoDecoder* decoder, UINT32 offset, void * hCallback); + typedef void EnumerateSafePointsCallback (TGcInfoDecoder * decoder, UINT32 offset, void * hCallback); void EnumerateSafePoints(EnumerateSafePointsCallback * pCallback, void * hCallback); #endif @@ -597,6 +601,10 @@ class GcInfoDecoder UINT32 GetSizeOfStackParameterArea(); #endif // FIXED_STACK_PARAMETER_SCRATCH_AREA + inline UINT32 Version() + { + return m_Version; + } private: BitStreamReader m_Reader; @@ -617,6 +625,7 @@ class GcInfoDecoder #ifdef TARGET_ARM64 UINT32 m_SizeOfEditAndContinueFixedStackFrame; #endif + // Unused starting with v4 format ReturnKind m_ReturnKind; #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED UINT32 m_NumSafePoints; @@ -636,6 +645,24 @@ class GcInfoDecoder #endif UINT32 m_Version; + inline UINT32 NormalizeCodeOffset(UINT32 offset) + { +#ifdef DECODE_OLD_FORMATS + if (Version() < 4) + return offset; +#endif + return GcInfoEncoding::NORMALIZE_CODE_OFFSET(offset); + } + + inline UINT32 DenormalizeCodeOffset(UINT32 offset) + { +#ifdef DECODE_OLD_FORMATS + if (Version() < 4) + return offset; +#endif + return GcInfoEncoding::DENORMALIZE_CODE_OFFSET(offset); + } + bool PredecodeFatHeader(int remainingFlags); static bool SetIsInterruptibleCB (UINT32 startOffset, UINT32 stopOffset, void * hCallback); @@ -666,7 +693,7 @@ class GcInfoDecoder bool IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD); void ReportUntrackedSlots( - GcSlotDecoder& slotDecoder, + GcSlotDecoder& slotDecoder, PREGDISPLAY pRD, unsigned flags, GCEnumCallback pCallBack, @@ -694,7 +721,7 @@ class GcInfoDecoder inline void ReportSlotToGC( - GcSlotDecoder& slotDecoder, + GcSlotDecoder& slotDecoder, UINT32 slotIndex, PREGDISPLAY pRD, bool reportScratchSlots, @@ -751,6 +778,9 @@ class GcInfoDecoder } } }; + +typedef TGcInfoDecoder GcInfoDecoder; + #endif // USE_GC_INFO_DECODER diff --git a/src/shared/inc/gcinfotypes.h b/src/shared/inc/gcinfotypes.h index b770bb1bbc..f6620f7ac7 100644 --- a/src/shared/inc/gcinfotypes.h +++ b/src/shared/inc/gcinfotypes.h @@ -5,6 +5,16 @@ #ifndef __GCINFOTYPES_H__ #define __GCINFOTYPES_H__ +// HACK: debugreturn.h breaks constexpr +#ifdef debug_instrumented_return +#undef return +#endif // debug_instrumented_return + +// HACK: debugreturn.h breaks constexpr +#if defined(debug_instrumented_return) || defined(_DEBUGRETURN_H_) +#undef return +#endif // debug_instrumented_return + #ifndef FEATURE_NATIVEAOT #include "gcinfo.h" #endif @@ -14,7 +24,7 @@ #endif // _MSC_VER // ***************************************************************************** -// WARNING!!!: These values and code are used in the runtime repo and SOS in the +// WARNING!!!: These values and code are used in the runtime repo and SOS in the // diagnostics repo. Should updated in a backwards and forwards compatible way. // See: https://github.com/dotnet/diagnostics/blob/main/src/shared/inc/gcinfotypes.h // https://github.com/dotnet/runtime/blob/main/src/coreclr/inc/gcinfotypes.h @@ -350,7 +360,8 @@ inline const char *ReturnKindToString(ReturnKind returnKind) #ifdef TARGET_X86 #include // For memcmp() -#include "bitvector.h" // for ptrArgTP + +#define MAX_PTRARG_OFS 1024 #ifndef FASTCALL #define FASTCALL __fastcall @@ -611,284 +622,293 @@ void FASTCALL decodeCallPattern(int pattern, #ifndef TARGET_POINTER_SIZE #define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target #endif -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64) -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6) -#define NORMALIZE_STACK_SLOT(x) ((x)>>3) -#define DENORMALIZE_STACK_SLOT(x) ((x)<<3) -#define NORMALIZE_CODE_LENGTH(x) (x) -#define DENORMALIZE_CODE_LENGTH(x) (x) -// Encode RBP as 0 -#define NORMALIZE_STACK_BASE_REGISTER(x) ((x) ^ 5) -#define DENORMALIZE_STACK_BASE_REGISTER(x) ((x) ^ 5) -#define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>3) -#define DENORMALIZE_SIZE_OF_STACK_AREA(x) ((x)<<3) -#define CODE_OFFSETS_NEED_NORMALIZATION 0 -#define NORMALIZE_CODE_OFFSET(x) (x) -#define DENORMALIZE_CODE_OFFSET(x) (x) -#define NORMALIZE_REGISTER(x) (x) -#define DENORMALIZE_REGISTER(x) (x) -#define NORMALIZE_NUM_SAFE_POINTS(x) (x) -#define DENORMALIZE_NUM_SAFE_POINTS(x) (x) -#define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) -#define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) - -#define PSP_SYM_STACK_SLOT_ENCBASE 6 -#define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 6 -#define SECURITY_OBJECT_STACK_SLOT_ENCBASE 6 -#define GS_COOKIE_STACK_SLOT_ENCBASE 6 -#define CODE_LENGTH_ENCBASE 8 -#define SIZE_OF_RETURN_KIND_IN_SLIM_HEADER 2 -#define SIZE_OF_RETURN_KIND_IN_FAT_HEADER 4 -#define STACK_BASE_REGISTER_ENCBASE 3 -#define SIZE_OF_STACK_AREA_ENCBASE 3 -#define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 4 -#define REVERSE_PINVOKE_FRAME_ENCBASE 6 -#define NUM_REGISTERS_ENCBASE 2 -#define NUM_STACK_SLOTS_ENCBASE 2 -#define NUM_UNTRACKED_SLOTS_ENCBASE 1 -#define NORM_PROLOG_SIZE_ENCBASE 5 -#define NORM_EPILOG_SIZE_ENCBASE 3 -#define NORM_CODE_OFFSET_DELTA_ENCBASE 3 -#define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 6 -#define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 6 -#define REGISTER_ENCBASE 3 -#define REGISTER_DELTA_ENCBASE 2 -#define STACK_SLOT_ENCBASE 6 -#define STACK_SLOT_DELTA_ENCBASE 4 -#define NUM_SAFE_POINTS_ENCBASE 2 -#define NUM_INTERRUPTIBLE_RANGES_ENCBASE 1 -#define NUM_EH_CLAUSES_ENCBASE 2 -#define POINTER_SIZE_ENCBASE 3 -#define LIVESTATE_RLE_RUN_ENCBASE 2 -#define LIVESTATE_RLE_SKIP_ENCBASE 4 + +#define TargetGcInfoEncoding AMD64GcInfoEncoding + +struct AMD64GcInfoEncoding { + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK = (64); + + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 = (6); + static inline constexpr int32_t NORMALIZE_STACK_SLOT (int32_t x) { return ((x)>>3); } + static inline constexpr int32_t DENORMALIZE_STACK_SLOT (int32_t x) { return ((x)<<3); } + static inline constexpr uint32_t NORMALIZE_CODE_LENGTH (uint32_t x) { return (x); } + static inline constexpr uint32_t DENORMALIZE_CODE_LENGTH (uint32_t x) { return (x); } + + // Encode RBP as 0 + static inline constexpr uint32_t NORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return ((x) ^ 5); } + static inline constexpr uint32_t DENORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return ((x) ^ 5); } + static inline constexpr uint32_t NORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return ((x)>>3); } + static inline constexpr uint32_t DENORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return ((x)<<3); } + static const bool CODE_OFFSETS_NEED_NORMALIZATION = false; + static inline constexpr uint32_t NORMALIZE_CODE_OFFSET (uint32_t x) { return (x); } + static inline constexpr uint32_t DENORMALIZE_CODE_OFFSET (uint32_t x) { return (x); } + + static const int PSP_SYM_STACK_SLOT_ENCBASE = 6; + static const int GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE = 6; + static const int SECURITY_OBJECT_STACK_SLOT_ENCBASE = 6; + static const int GS_COOKIE_STACK_SLOT_ENCBASE = 6; + static const int CODE_LENGTH_ENCBASE = 8; + static const int SIZE_OF_RETURN_KIND_IN_SLIM_HEADER = 2; + static const int SIZE_OF_RETURN_KIND_IN_FAT_HEADER = 4; + static const int STACK_BASE_REGISTER_ENCBASE = 3; + static const int SIZE_OF_STACK_AREA_ENCBASE = 3; + static const int SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE = 4; + static const int REVERSE_PINVOKE_FRAME_ENCBASE = 6; + static const int NUM_REGISTERS_ENCBASE = 2; + static const int NUM_STACK_SLOTS_ENCBASE = 2; + static const int NUM_UNTRACKED_SLOTS_ENCBASE = 1; + static const int NORM_PROLOG_SIZE_ENCBASE = 5; + static const int NORM_EPILOG_SIZE_ENCBASE = 3; + static const int NORM_CODE_OFFSET_DELTA_ENCBASE = 3; + static const int INTERRUPTIBLE_RANGE_DELTA1_ENCBASE = 6; + static const int INTERRUPTIBLE_RANGE_DELTA2_ENCBASE = 6; + static const int REGISTER_ENCBASE = 3; + static const int REGISTER_DELTA_ENCBASE = 2; + static const int STACK_SLOT_ENCBASE = 6; + static const int STACK_SLOT_DELTA_ENCBASE = 4; + static const int NUM_SAFE_POINTS_ENCBASE = 2; + static const int NUM_INTERRUPTIBLE_RANGES_ENCBASE = 1; + static const int NUM_EH_CLAUSES_ENCBASE = 2; + static const int POINTER_SIZE_ENCBASE = 3; + static const int LIVESTATE_RLE_RUN_ENCBASE = 2; + static const int LIVESTATE_RLE_SKIP_ENCBASE = 4; +}; #elif defined(TARGET_ARM) #ifndef TARGET_POINTER_SIZE #define TARGET_POINTER_SIZE 4 // equal to sizeof(void*) and the managed pointer size in bytes for this target #endif -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64) -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6) -#define NORMALIZE_STACK_SLOT(x) ((x)>>2) -#define DENORMALIZE_STACK_SLOT(x) ((x)<<2) -#define NORMALIZE_CODE_LENGTH(x) ((x)>>1) -#define DENORMALIZE_CODE_LENGTH(x) ((x)<<1) -// Encode R11 as zero -#define NORMALIZE_STACK_BASE_REGISTER(x) ((((x) - 4) & 7) ^ 7) -#define DENORMALIZE_STACK_BASE_REGISTER(x) (((x) ^ 7) + 4) -#define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>2) -#define DENORMALIZE_SIZE_OF_STACK_AREA(x) ((x)<<2) -#define CODE_OFFSETS_NEED_NORMALIZATION 1 -#define NORMALIZE_CODE_OFFSET(x) (x) // Instructions are 2/4 bytes long in Thumb/ARM states, -#define DENORMALIZE_CODE_OFFSET(x) (x) // but the safe-point offsets are encoded with a -1 adjustment. -#define NORMALIZE_REGISTER(x) (x) -#define DENORMALIZE_REGISTER(x) (x) -#define NORMALIZE_NUM_SAFE_POINTS(x) (x) -#define DENORMALIZE_NUM_SAFE_POINTS(x) (x) -#define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) -#define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) - -// The choices of these encoding bases only affects space overhead -// and performance, not semantics/correctness. -#define PSP_SYM_STACK_SLOT_ENCBASE 5 -#define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 5 -#define SECURITY_OBJECT_STACK_SLOT_ENCBASE 5 -#define GS_COOKIE_STACK_SLOT_ENCBASE 5 -#define CODE_LENGTH_ENCBASE 7 -#define SIZE_OF_RETURN_KIND_IN_SLIM_HEADER 2 -#define SIZE_OF_RETURN_KIND_IN_FAT_HEADER 2 -#define STACK_BASE_REGISTER_ENCBASE 1 -#define SIZE_OF_STACK_AREA_ENCBASE 3 -#define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 3 -#define REVERSE_PINVOKE_FRAME_ENCBASE 5 -#define NUM_REGISTERS_ENCBASE 2 -#define NUM_STACK_SLOTS_ENCBASE 3 -#define NUM_UNTRACKED_SLOTS_ENCBASE 3 -#define NORM_PROLOG_SIZE_ENCBASE 5 -#define NORM_EPILOG_SIZE_ENCBASE 3 -#define NORM_CODE_OFFSET_DELTA_ENCBASE 3 -#define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 4 -#define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 6 -#define REGISTER_ENCBASE 2 -#define REGISTER_DELTA_ENCBASE 1 -#define STACK_SLOT_ENCBASE 6 -#define STACK_SLOT_DELTA_ENCBASE 4 -#define NUM_SAFE_POINTS_ENCBASE 3 -#define NUM_INTERRUPTIBLE_RANGES_ENCBASE 2 -#define NUM_EH_CLAUSES_ENCBASE 3 -#define POINTER_SIZE_ENCBASE 3 -#define LIVESTATE_RLE_RUN_ENCBASE 2 -#define LIVESTATE_RLE_SKIP_ENCBASE 4 + +#define TargetGcInfoEncoding ARM32GcInfoEncoding + +struct ARM32GcInfoEncoding { + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK = (64); + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 = (6); + static inline constexpr int32_t NORMALIZE_STACK_SLOT (int32_t x) { return ((x)>>2); } + static inline constexpr int32_t DENORMALIZE_STACK_SLOT (int32_t x) { return ((x)<<2); } + static inline constexpr uint32_t NORMALIZE_CODE_LENGTH (uint32_t x) { return ((x)>>1); } + static inline constexpr uint32_t DENORMALIZE_CODE_LENGTH (uint32_t x) { return ((x)<<1); } + // Encode R11 as zero + static inline constexpr uint32_t NORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return ((((x) - 4) & 7) ^ 7); } + static inline constexpr uint32_t DENORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return (((x) ^ 7) + 4); } + static inline constexpr uint32_t NORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return ((x)>>2); } + static inline constexpr uint32_t DENORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return ((x)<<2); } + static const bool CODE_OFFSETS_NEED_NORMALIZATION = true; + static inline constexpr uint32_t NORMALIZE_CODE_OFFSET (uint32_t x) { return ((x)>>1) /* Instructions are 2/4 bytes long in Thumb/ARM states */; } + static inline constexpr uint32_t DENORMALIZE_CODE_OFFSET (uint32_t x) { return ((x)<<1); } + + // The choices of these encoding bases only affects space overhead + // and performance, not semantics/correctness. + static const int PSP_SYM_STACK_SLOT_ENCBASE = 5; + static const int GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE = 5; + static const int SECURITY_OBJECT_STACK_SLOT_ENCBASE = 5; + static const int GS_COOKIE_STACK_SLOT_ENCBASE = 5; + static const int CODE_LENGTH_ENCBASE = 7; + static const int SIZE_OF_RETURN_KIND_IN_SLIM_HEADER = 2; + static const int SIZE_OF_RETURN_KIND_IN_FAT_HEADER = 2; + static const int STACK_BASE_REGISTER_ENCBASE = 1; + static const int SIZE_OF_STACK_AREA_ENCBASE = 3; + static const int SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE = 3; + static const int REVERSE_PINVOKE_FRAME_ENCBASE = 5; + static const int NUM_REGISTERS_ENCBASE = 2; + static const int NUM_STACK_SLOTS_ENCBASE = 3; + static const int NUM_UNTRACKED_SLOTS_ENCBASE = 3; + static const int NORM_PROLOG_SIZE_ENCBASE = 5; + static const int NORM_EPILOG_SIZE_ENCBASE = 3; + static const int NORM_CODE_OFFSET_DELTA_ENCBASE = 3; + static const int INTERRUPTIBLE_RANGE_DELTA1_ENCBASE = 4; + static const int INTERRUPTIBLE_RANGE_DELTA2_ENCBASE = 6; + static const int REGISTER_ENCBASE = 2; + static const int REGISTER_DELTA_ENCBASE = 1; + static const int STACK_SLOT_ENCBASE = 6; + static const int STACK_SLOT_DELTA_ENCBASE = 4; + static const int NUM_SAFE_POINTS_ENCBASE = 3; + static const int NUM_INTERRUPTIBLE_RANGES_ENCBASE = 2; + static const int NUM_EH_CLAUSES_ENCBASE = 3; + static const int POINTER_SIZE_ENCBASE = 3; + static const int LIVESTATE_RLE_RUN_ENCBASE = 2; + static const int LIVESTATE_RLE_SKIP_ENCBASE = 4; +}; #elif defined(TARGET_ARM64) #ifndef TARGET_POINTER_SIZE #define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target #endif -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64) -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6) -#define NORMALIZE_STACK_SLOT(x) ((x)>>3) // GC Pointers are 8-bytes aligned -#define DENORMALIZE_STACK_SLOT(x) ((x)<<3) -#define NORMALIZE_CODE_LENGTH(x) ((x)>>2) // All Instructions are 4 bytes long -#define DENORMALIZE_CODE_LENGTH(x) ((x)<<2) -#define NORMALIZE_STACK_BASE_REGISTER(x) ((x)^29) // Encode Frame pointer X29 as zero -#define DENORMALIZE_STACK_BASE_REGISTER(x) ((x)^29) -#define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>3) -#define DENORMALIZE_SIZE_OF_STACK_AREA(x) ((x)<<3) -#define CODE_OFFSETS_NEED_NORMALIZATION 0 -#define NORMALIZE_CODE_OFFSET(x) (x) // Instructions are 4 bytes long, but the safe-point -#define DENORMALIZE_CODE_OFFSET(x) (x) // offsets are encoded with a -1 adjustment. -#define NORMALIZE_REGISTER(x) (x) -#define DENORMALIZE_REGISTER(x) (x) -#define NORMALIZE_NUM_SAFE_POINTS(x) (x) -#define DENORMALIZE_NUM_SAFE_POINTS(x) (x) -#define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) -#define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) - -#define PSP_SYM_STACK_SLOT_ENCBASE 6 -#define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 6 -#define SECURITY_OBJECT_STACK_SLOT_ENCBASE 6 -#define GS_COOKIE_STACK_SLOT_ENCBASE 6 -#define CODE_LENGTH_ENCBASE 8 -#define SIZE_OF_RETURN_KIND_IN_SLIM_HEADER 2 -#define SIZE_OF_RETURN_KIND_IN_FAT_HEADER 4 -#define STACK_BASE_REGISTER_ENCBASE 2 // FP encoded as 0, SP as 2. -#define SIZE_OF_STACK_AREA_ENCBASE 3 -#define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 4 -#define SIZE_OF_EDIT_AND_CONTINUE_FIXED_STACK_FRAME_ENCBASE 4 -#define REVERSE_PINVOKE_FRAME_ENCBASE 6 -#define NUM_REGISTERS_ENCBASE 3 -#define NUM_STACK_SLOTS_ENCBASE 2 -#define NUM_UNTRACKED_SLOTS_ENCBASE 1 -#define NORM_PROLOG_SIZE_ENCBASE 5 -#define NORM_EPILOG_SIZE_ENCBASE 3 -#define NORM_CODE_OFFSET_DELTA_ENCBASE 3 -#define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 6 -#define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 6 -#define REGISTER_ENCBASE 3 -#define REGISTER_DELTA_ENCBASE 2 -#define STACK_SLOT_ENCBASE 6 -#define STACK_SLOT_DELTA_ENCBASE 4 -#define NUM_SAFE_POINTS_ENCBASE 3 -#define NUM_INTERRUPTIBLE_RANGES_ENCBASE 1 -#define NUM_EH_CLAUSES_ENCBASE 2 -#define POINTER_SIZE_ENCBASE 3 -#define LIVESTATE_RLE_RUN_ENCBASE 2 -#define LIVESTATE_RLE_SKIP_ENCBASE 4 + +#define TargetGcInfoEncoding ARM64GcInfoEncoding + +struct ARM64GcInfoEncoding { + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK = (64); + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 = (6); + // GC Pointers are 8-bytes aligned + static inline constexpr int32_t NORMALIZE_STACK_SLOT (int32_t x) { return ((x)>>3); } + static inline constexpr int32_t DENORMALIZE_STACK_SLOT (int32_t x) { return ((x)<<3); } + // All Instructions are 4 bytes long + static inline constexpr uint32_t NORMALIZE_CODE_LENGTH (uint32_t x) { return ((x)>>2); } + static inline constexpr uint32_t DENORMALIZE_CODE_LENGTH (uint32_t x) { return ((x)<<2); } + // Encode Frame pointer X29 as zero + static inline constexpr uint32_t NORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return ((x)^29); } + static inline constexpr uint32_t DENORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return ((x)^29); } + static inline constexpr uint32_t NORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return ((x)>>3); } + static inline constexpr uint32_t DENORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return ((x)<<3); } + static const bool CODE_OFFSETS_NEED_NORMALIZATION = true; + // Instructions are 4 bytes long + static inline constexpr uint32_t NORMALIZE_CODE_OFFSET (uint32_t x) { return ((x)>>2); } + static inline constexpr uint32_t DENORMALIZE_CODE_OFFSET (uint32_t x) { return ((x)<<2); } + + static const int PSP_SYM_STACK_SLOT_ENCBASE = 6; + static const int GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE = 6; + static const int SECURITY_OBJECT_STACK_SLOT_ENCBASE = 6; + static const int GS_COOKIE_STACK_SLOT_ENCBASE = 6; + static const int CODE_LENGTH_ENCBASE = 8; + static const int SIZE_OF_RETURN_KIND_IN_SLIM_HEADER = 2; + static const int SIZE_OF_RETURN_KIND_IN_FAT_HEADER = 4; + // FP encoded as 0, SP as 2. + static const int STACK_BASE_REGISTER_ENCBASE = 2; + static const int SIZE_OF_STACK_AREA_ENCBASE = 3; + static const int SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE = 4; + static const int SIZE_OF_EDIT_AND_CONTINUE_FIXED_STACK_FRAME_ENCBASE = 4; + static const int REVERSE_PINVOKE_FRAME_ENCBASE = 6; + static const int NUM_REGISTERS_ENCBASE = 3; + static const int NUM_STACK_SLOTS_ENCBASE = 2; + static const int NUM_UNTRACKED_SLOTS_ENCBASE = 1; + static const int NORM_PROLOG_SIZE_ENCBASE = 5; + static const int NORM_EPILOG_SIZE_ENCBASE = 3; + static const int NORM_CODE_OFFSET_DELTA_ENCBASE = 3; + static const int INTERRUPTIBLE_RANGE_DELTA1_ENCBASE = 6; + static const int INTERRUPTIBLE_RANGE_DELTA2_ENCBASE = 6; + static const int REGISTER_ENCBASE = 3; + static const int REGISTER_DELTA_ENCBASE = 2; + static const int STACK_SLOT_ENCBASE = 6; + static const int STACK_SLOT_DELTA_ENCBASE = 4; + static const int NUM_SAFE_POINTS_ENCBASE = 3; + static const int NUM_INTERRUPTIBLE_RANGES_ENCBASE = 1; + static const int NUM_EH_CLAUSES_ENCBASE = 2; + static const int POINTER_SIZE_ENCBASE = 3; + static const int LIVESTATE_RLE_RUN_ENCBASE = 2; + static const int LIVESTATE_RLE_SKIP_ENCBASE = 4; +}; #elif defined(TARGET_LOONGARCH64) #ifndef TARGET_POINTER_SIZE #define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target #endif -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64) -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6) -#define NORMALIZE_STACK_SLOT(x) ((x)>>3) // GC Pointers are 8-bytes aligned -#define DENORMALIZE_STACK_SLOT(x) ((x)<<3) -#define NORMALIZE_CODE_LENGTH(x) ((x)>>2) // All Instructions are 4 bytes long -#define DENORMALIZE_CODE_LENGTH(x) ((x)<<2) -#define NORMALIZE_STACK_BASE_REGISTER(x) ((x) == 22 ? 0 : 1) // Encode Frame pointer fp=$22 as zero -#define DENORMALIZE_STACK_BASE_REGISTER(x) ((x) == 0 ? 22 : 3) -#define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>3) -#define DENORMALIZE_SIZE_OF_STACK_AREA(x) ((x)<<3) -#define CODE_OFFSETS_NEED_NORMALIZATION 0 -#define NORMALIZE_CODE_OFFSET(x) (x) // Instructions are 4 bytes long, but the safe-point -#define DENORMALIZE_CODE_OFFSET(x) (x) // offsets are encoded with a -1 adjustment. -#define NORMALIZE_REGISTER(x) (x) -#define DENORMALIZE_REGISTER(x) (x) -#define NORMALIZE_NUM_SAFE_POINTS(x) (x) -#define DENORMALIZE_NUM_SAFE_POINTS(x) (x) -#define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) -#define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) - -#define PSP_SYM_STACK_SLOT_ENCBASE 6 -#define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 6 -#define SECURITY_OBJECT_STACK_SLOT_ENCBASE 6 -#define GS_COOKIE_STACK_SLOT_ENCBASE 6 -#define CODE_LENGTH_ENCBASE 8 -#define SIZE_OF_RETURN_KIND_IN_SLIM_HEADER 2 -#define SIZE_OF_RETURN_KIND_IN_FAT_HEADER 4 -// FP/SP encoded as 0 or 1. -#define STACK_BASE_REGISTER_ENCBASE 2 -#define SIZE_OF_STACK_AREA_ENCBASE 3 -#define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 4 -#define REVERSE_PINVOKE_FRAME_ENCBASE 6 -#define NUM_REGISTERS_ENCBASE 3 -#define NUM_STACK_SLOTS_ENCBASE 2 -#define NUM_UNTRACKED_SLOTS_ENCBASE 1 -#define NORM_PROLOG_SIZE_ENCBASE 5 -#define NORM_EPILOG_SIZE_ENCBASE 3 -#define NORM_CODE_OFFSET_DELTA_ENCBASE 3 -#define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 6 -#define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 6 -#define REGISTER_ENCBASE 3 -#define REGISTER_DELTA_ENCBASE 2 -#define STACK_SLOT_ENCBASE 6 -#define STACK_SLOT_DELTA_ENCBASE 4 -#define NUM_SAFE_POINTS_ENCBASE 3 -#define NUM_INTERRUPTIBLE_RANGES_ENCBASE 1 -#define NUM_EH_CLAUSES_ENCBASE 2 -#define POINTER_SIZE_ENCBASE 3 -#define LIVESTATE_RLE_RUN_ENCBASE 2 -#define LIVESTATE_RLE_SKIP_ENCBASE 4 + +#define TargetGcInfoEncoding LoongArch64GcInfoEncoding + +struct LoongArch64GcInfoEncoding { + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK = (64); + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 = (6); + // GC Pointers are 8-bytes aligned + static inline constexpr int32_t NORMALIZE_STACK_SLOT (int32_t x) { return ((x)>>3); } + static inline constexpr int32_t DENORMALIZE_STACK_SLOT (int32_t x) { return ((x)<<3); } + // All Instructions are 4 bytes long + static inline constexpr uint32_t NORMALIZE_CODE_LENGTH (uint32_t x) { return ((x)>>2); } + static inline constexpr uint32_t DENORMALIZE_CODE_LENGTH (uint32_t x) { return ((x)<<2); } + // Encode Frame pointer fp=$22 as zero + static inline constexpr uint32_t NORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return ((x) == 22 ? 0u : 1u); } + static inline constexpr uint32_t DENORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return ((x) == 0 ? 22u : 3u); } + static inline constexpr uint32_t NORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return ((x)>>3); } + static inline constexpr uint32_t DENORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return ((x)<<3); } + static const bool CODE_OFFSETS_NEED_NORMALIZATION = true; + // Instructions are 4 bytes long + static inline constexpr uint32_t NORMALIZE_CODE_OFFSET (uint32_t x) { return ((x)>>2); } + static inline constexpr uint32_t DENORMALIZE_CODE_OFFSET (uint32_t x) { return ((x)<<2); } + + static const int PSP_SYM_STACK_SLOT_ENCBASE = 6; + static const int GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE = 6; + static const int SECURITY_OBJECT_STACK_SLOT_ENCBASE = 6; + static const int GS_COOKIE_STACK_SLOT_ENCBASE = 6; + static const int CODE_LENGTH_ENCBASE = 8; + static const int SIZE_OF_RETURN_KIND_IN_SLIM_HEADER = 2; + static const int SIZE_OF_RETURN_KIND_IN_FAT_HEADER = 4; + // FP/SP encoded as 0 or 1. + static const int STACK_BASE_REGISTER_ENCBASE = 2; + static const int SIZE_OF_STACK_AREA_ENCBASE = 3; + static const int SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE = 4; + static const int REVERSE_PINVOKE_FRAME_ENCBASE = 6; + static const int NUM_REGISTERS_ENCBASE = 3; + static const int NUM_STACK_SLOTS_ENCBASE = 2; + static const int NUM_UNTRACKED_SLOTS_ENCBASE = 1; + static const int NORM_PROLOG_SIZE_ENCBASE = 5; + static const int NORM_EPILOG_SIZE_ENCBASE = 3; + static const int NORM_CODE_OFFSET_DELTA_ENCBASE = 3; + static const int INTERRUPTIBLE_RANGE_DELTA1_ENCBASE = 6; + static const int INTERRUPTIBLE_RANGE_DELTA2_ENCBASE = 6; + static const int REGISTER_ENCBASE = 3; + static const int REGISTER_DELTA_ENCBASE = 2; + static const int STACK_SLOT_ENCBASE = 6; + static const int STACK_SLOT_DELTA_ENCBASE = 4; + static const int NUM_SAFE_POINTS_ENCBASE = 3; + static const int NUM_INTERRUPTIBLE_RANGES_ENCBASE = 1; + static const int NUM_EH_CLAUSES_ENCBASE = 2; + static const int POINTER_SIZE_ENCBASE = 3; + static const int LIVESTATE_RLE_RUN_ENCBASE = 2; + static const int LIVESTATE_RLE_SKIP_ENCBASE = 4; +}; #elif defined(TARGET_RISCV64) #ifndef TARGET_POINTER_SIZE #define TARGET_POINTER_SIZE 8 // equal to sizeof(void*) and the managed pointer size in bytes for this target #endif -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64) -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6) -#define NORMALIZE_STACK_SLOT(x) ((x)>>3) // GC Pointers are 8-bytes aligned -#define DENORMALIZE_STACK_SLOT(x) ((x)<<3) -#define NORMALIZE_CODE_LENGTH(x) ((x)>>2) // All Instructions are 4 bytes long -#define DENORMALIZE_CODE_LENGTH(x) ((x)<<2) -#define NORMALIZE_STACK_BASE_REGISTER(x) ((x) == 8 ? 0 : 1) // Encode Frame pointer X8 as zero, sp/x2 as 1 -#define DENORMALIZE_STACK_BASE_REGISTER(x) ((x) == 0 ? 8 : 2) -#define NORMALIZE_SIZE_OF_STACK_AREA(x) ((x)>>3) -#define DENORMALIZE_SIZE_OF_STACK_AREA(x) ((x)<<3) -#define CODE_OFFSETS_NEED_NORMALIZATION 0 -#define NORMALIZE_CODE_OFFSET(x) (x) // Instructions are 4 bytes long, but the safe-point -#define DENORMALIZE_CODE_OFFSET(x) (x) // offsets are encoded with a -1 adjustment. -#define NORMALIZE_REGISTER(x) (x) -#define DENORMALIZE_REGISTER(x) (x) -#define NORMALIZE_NUM_SAFE_POINTS(x) (x) -#define DENORMALIZE_NUM_SAFE_POINTS(x) (x) -#define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) -#define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) - -#define PSP_SYM_STACK_SLOT_ENCBASE 6 -#define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 6 -#define SECURITY_OBJECT_STACK_SLOT_ENCBASE 6 -#define GS_COOKIE_STACK_SLOT_ENCBASE 6 -#define CODE_LENGTH_ENCBASE 8 -#define SIZE_OF_RETURN_KIND_IN_SLIM_HEADER 2 -#define SIZE_OF_RETURN_KIND_IN_FAT_HEADER 4 -#define STACK_BASE_REGISTER_ENCBASE 2 -// FP encoded as 0, SP as 1 -#define SIZE_OF_STACK_AREA_ENCBASE 3 -#define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 4 -#define SIZE_OF_EDIT_AND_CONTINUE_FIXED_STACK_FRAME_ENCBASE 4 -#define REVERSE_PINVOKE_FRAME_ENCBASE 6 -#define NUM_REGISTERS_ENCBASE 3 -#define NUM_STACK_SLOTS_ENCBASE 2 -#define NUM_UNTRACKED_SLOTS_ENCBASE 1 -#define NORM_PROLOG_SIZE_ENCBASE 5 -#define NORM_EPILOG_SIZE_ENCBASE 3 -#define NORM_CODE_OFFSET_DELTA_ENCBASE 3 -#define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 6 -#define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 6 -#define REGISTER_ENCBASE 3 -#define REGISTER_DELTA_ENCBASE 2 -#define STACK_SLOT_ENCBASE 6 -#define STACK_SLOT_DELTA_ENCBASE 4 -#define NUM_SAFE_POINTS_ENCBASE 3 -#define NUM_INTERRUPTIBLE_RANGES_ENCBASE 1 -#define NUM_EH_CLAUSES_ENCBASE 2 -#define POINTER_SIZE_ENCBASE 3 -#define LIVESTATE_RLE_RUN_ENCBASE 2 -#define LIVESTATE_RLE_SKIP_ENCBASE 4 +#define TargetGcInfoEncoding RISCV64GcInfoEncoding + +struct RISCV64GcInfoEncoding { + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK = (64); + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 = (6); + // GC Pointers are 8-bytes aligned + static inline constexpr int32_t NORMALIZE_STACK_SLOT (int32_t x) { return ((x)>>3); } + static inline constexpr int32_t DENORMALIZE_STACK_SLOT (int32_t x) { return ((x)<<3); } + // All Instructions are 4 bytes long + static inline constexpr uint32_t NORMALIZE_CODE_LENGTH (uint32_t x) { return ((x)>>2); } + static inline constexpr uint32_t DENORMALIZE_CODE_LENGTH (uint32_t x) { return ((x)<<2); } + // Encode Frame pointer X8 as zero, sp/x2 as 1 + static inline constexpr uint32_t NORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return ((x) == 8 ? 0u : 1u); } + static inline constexpr uint32_t DENORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return ((x) == 0 ? 8u : 2u); } + static inline constexpr uint32_t NORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return ((x)>>3); } + static inline constexpr uint32_t DENORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return ((x)<<3); } + static const bool CODE_OFFSETS_NEED_NORMALIZATION = true; + // Instructions are 4 bytes long + static inline constexpr uint32_t NORMALIZE_CODE_OFFSET (uint32_t x) { return ((x)>>2); } + static inline constexpr uint32_t DENORMALIZE_CODE_OFFSET (uint32_t x) { return ((x)<<2); } + + static const int PSP_SYM_STACK_SLOT_ENCBASE = 6; + static const int GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE = 6; + static const int SECURITY_OBJECT_STACK_SLOT_ENCBASE = 6; + static const int GS_COOKIE_STACK_SLOT_ENCBASE = 6; + static const int CODE_LENGTH_ENCBASE = 8; + static const int SIZE_OF_RETURN_KIND_IN_SLIM_HEADER = 2; + static const int SIZE_OF_RETURN_KIND_IN_FAT_HEADER = 4; + static const int STACK_BASE_REGISTER_ENCBASE = 2; + // FP encoded as 0, SP as 1 + static const int SIZE_OF_STACK_AREA_ENCBASE = 3; + static const int SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE = 4; + static const int SIZE_OF_EDIT_AND_CONTINUE_FIXED_STACK_FRAME_ENCBASE = 4; + static const int REVERSE_PINVOKE_FRAME_ENCBASE = 6; + static const int NUM_REGISTERS_ENCBASE = 3; + static const int NUM_STACK_SLOTS_ENCBASE = 2; + static const int NUM_UNTRACKED_SLOTS_ENCBASE = 1; + static const int NORM_PROLOG_SIZE_ENCBASE = 5; + static const int NORM_EPILOG_SIZE_ENCBASE = 3; + static const int NORM_CODE_OFFSET_DELTA_ENCBASE = 3; + static const int INTERRUPTIBLE_RANGE_DELTA1_ENCBASE = 6; + static const int INTERRUPTIBLE_RANGE_DELTA2_ENCBASE = 6; + static const int REGISTER_ENCBASE = 3; + static const int REGISTER_DELTA_ENCBASE = 2; + static const int STACK_SLOT_ENCBASE = 6; + static const int STACK_SLOT_DELTA_ENCBASE = 4; + static const int NUM_SAFE_POINTS_ENCBASE = 3; + static const int NUM_INTERRUPTIBLE_RANGES_ENCBASE = 1; + static const int NUM_EH_CLAUSES_ENCBASE = 2; + static const int POINTER_SIZE_ENCBASE = 3; + static const int LIVESTATE_RLE_RUN_ENCBASE = 2; + static const int LIVESTATE_RLE_SKIP_ENCBASE = 4; +}; -#else +#else // defined(TARGET_xxx) #ifndef TARGET_X86 #ifdef PORTABILITY_WARNING @@ -899,57 +919,60 @@ PORTABILITY_WARNING("Please specialize these definitions for your platform!") #ifndef TARGET_POINTER_SIZE #define TARGET_POINTER_SIZE 4 // equal to sizeof(void*) and the managed pointer size in bytes for this target #endif -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK (64) -#define NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 (6) -#define NORMALIZE_STACK_SLOT(x) (x) -#define DENORMALIZE_STACK_SLOT(x) (x) -#define NORMALIZE_CODE_LENGTH(x) (x) -#define DENORMALIZE_CODE_LENGTH(x) (x) -#define NORMALIZE_STACK_BASE_REGISTER(x) (x) -#define DENORMALIZE_STACK_BASE_REGISTER(x) (x) -#define NORMALIZE_SIZE_OF_STACK_AREA(x) (x) -#define DENORMALIZE_SIZE_OF_STACK_AREA(x) (x) -#define CODE_OFFSETS_NEED_NORMALIZATION 0 -#define NORMALIZE_CODE_OFFSET(x) (x) -#define DENORMALIZE_CODE_OFFSET(x) (x) -#define NORMALIZE_REGISTER(x) (x) -#define DENORMALIZE_REGISTER(x) (x) -#define NORMALIZE_NUM_SAFE_POINTS(x) (x) -#define DENORMALIZE_NUM_SAFE_POINTS(x) (x) -#define NORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) -#define DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(x) (x) - -#define PSP_SYM_STACK_SLOT_ENCBASE 6 -#define GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE 6 -#define SECURITY_OBJECT_STACK_SLOT_ENCBASE 6 -#define GS_COOKIE_STACK_SLOT_ENCBASE 6 -#define CODE_LENGTH_ENCBASE 6 -#define SIZE_OF_RETURN_KIND_IN_SLIM_HEADER 2 -#define SIZE_OF_RETURN_KIND_IN_FAT_HEADER 2 -#define STACK_BASE_REGISTER_ENCBASE 3 -#define SIZE_OF_STACK_AREA_ENCBASE 6 -#define SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE 3 -#define REVERSE_PINVOKE_FRAME_ENCBASE 6 -#define NUM_REGISTERS_ENCBASE 3 -#define NUM_STACK_SLOTS_ENCBASE 5 -#define NUM_UNTRACKED_SLOTS_ENCBASE 5 -#define NORM_PROLOG_SIZE_ENCBASE 4 -#define NORM_EPILOG_SIZE_ENCBASE 3 -#define NORM_CODE_OFFSET_DELTA_ENCBASE 3 -#define INTERRUPTIBLE_RANGE_DELTA1_ENCBASE 5 -#define INTERRUPTIBLE_RANGE_DELTA2_ENCBASE 5 -#define REGISTER_ENCBASE 3 -#define REGISTER_DELTA_ENCBASE REGISTER_ENCBASE -#define STACK_SLOT_ENCBASE 6 -#define STACK_SLOT_DELTA_ENCBASE 4 -#define NUM_SAFE_POINTS_ENCBASE 4 -#define NUM_INTERRUPTIBLE_RANGES_ENCBASE 1 -#define NUM_EH_CLAUSES_ENCBASE 2 -#define POINTER_SIZE_ENCBASE 3 -#define LIVESTATE_RLE_RUN_ENCBASE 2 -#define LIVESTATE_RLE_SKIP_ENCBASE 4 -#endif +#define TargetGcInfoEncoding X86GcInfoEncoding + +struct X86GcInfoEncoding { + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK = (64); + static const uint32_t NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2 = (6); + static inline constexpr int32_t NORMALIZE_STACK_SLOT (int32_t x) { return (x); } + static inline constexpr int32_t DENORMALIZE_STACK_SLOT (int32_t x) { return (x); } + static inline constexpr uint32_t NORMALIZE_CODE_LENGTH (uint32_t x) { return (x); } + static inline constexpr uint32_t DENORMALIZE_CODE_LENGTH (uint32_t x) { return (x); } + static inline constexpr uint32_t NORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return (x); } + static inline constexpr uint32_t DENORMALIZE_STACK_BASE_REGISTER (uint32_t x) { return (x); } + static inline constexpr uint32_t NORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return (x); } + static inline constexpr uint32_t DENORMALIZE_SIZE_OF_STACK_AREA (uint32_t x) { return (x); } + static const bool CODE_OFFSETS_NEED_NORMALIZATION = false; + static inline constexpr uint32_t NORMALIZE_CODE_OFFSET (uint32_t x) { return (x); } + static inline constexpr uint32_t DENORMALIZE_CODE_OFFSET (uint32_t x) { return (x); } + + static const int PSP_SYM_STACK_SLOT_ENCBASE = 6; + static const int GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE = 6; + static const int SECURITY_OBJECT_STACK_SLOT_ENCBASE = 6; + static const int GS_COOKIE_STACK_SLOT_ENCBASE = 6; + static const int CODE_LENGTH_ENCBASE = 6; + static const int SIZE_OF_RETURN_KIND_IN_SLIM_HEADER = 2; + static const int SIZE_OF_RETURN_KIND_IN_FAT_HEADER = 2; + static const int STACK_BASE_REGISTER_ENCBASE = 3; + static const int SIZE_OF_STACK_AREA_ENCBASE = 6; + static const int SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE = 3; + static const int REVERSE_PINVOKE_FRAME_ENCBASE = 6; + static const int NUM_REGISTERS_ENCBASE = 3; + static const int NUM_STACK_SLOTS_ENCBASE = 5; + static const int NUM_UNTRACKED_SLOTS_ENCBASE = 5; + static const int NORM_PROLOG_SIZE_ENCBASE = 4; + static const int NORM_EPILOG_SIZE_ENCBASE = 3; + static const int NORM_CODE_OFFSET_DELTA_ENCBASE = 3; + static const int INTERRUPTIBLE_RANGE_DELTA1_ENCBASE = 5; + static const int INTERRUPTIBLE_RANGE_DELTA2_ENCBASE = 5; + static const int REGISTER_ENCBASE = 3; + static const int REGISTER_DELTA_ENCBASE = REGISTER_ENCBASE; + static const int STACK_SLOT_ENCBASE = 6; + static const int STACK_SLOT_DELTA_ENCBASE = 4; + static const int NUM_SAFE_POINTS_ENCBASE = 4; + static const int NUM_INTERRUPTIBLE_RANGES_ENCBASE = 1; + static const int NUM_EH_CLAUSES_ENCBASE = 2; + static const int POINTER_SIZE_ENCBASE = 3; + static const int LIVESTATE_RLE_RUN_ENCBASE = 2; + static const int LIVESTATE_RLE_SKIP_ENCBASE = 4; +}; + +#endif // defined(TARGET_xxx) + +#ifdef debug_instrumented_return +#define return debug_instrumented_return +#endif // debug_instrumented_return #endif // !__GCINFOTYPES_H__ diff --git a/src/shared/vm/gcinfodecoder.cpp b/src/shared/vm/gcinfodecoder.cpp index 097037fd81..7dff38b946 100644 --- a/src/shared/vm/gcinfodecoder.cpp +++ b/src/shared/vm/gcinfodecoder.cpp @@ -72,9 +72,9 @@ } #endif // !LOG_PIPTR -bool GcInfoDecoder::SetIsInterruptibleCB (UINT32 startOffset, UINT32 stopOffset, void * hCallback) +template bool TGcInfoDecoder::SetIsInterruptibleCB (UINT32 startOffset, UINT32 stopOffset, void * hCallback) { - GcInfoDecoder *pThis = (GcInfoDecoder*)hCallback; + TGcInfoDecoder *pThis = (TGcInfoDecoder*)hCallback; bool fStop = pThis->m_InstructionOffset >= startOffset && pThis->m_InstructionOffset < stopOffset; @@ -86,13 +86,16 @@ bool GcInfoDecoder::SetIsInterruptibleCB (UINT32 startOffset, UINT32 stopOffset, } // returns true if we decoded all that was asked; -bool GcInfoDecoder::PredecodeFatHeader(int remainingFlags) +template bool TGcInfoDecoder::PredecodeFatHeader(int remainingFlags) { - int numFlagBits = (m_Version == 1) ? GC_INFO_FLAGS_BIT_SIZE_VERSION_1 : GC_INFO_FLAGS_BIT_SIZE; - m_headerFlags = (GcInfoHeaderFlags)m_Reader.Read(numFlagBits); - - m_ReturnKind = (ReturnKind)((UINT32)m_Reader.Read(SIZE_OF_RETURN_KIND_IN_FAT_HEADER)); + m_headerFlags = (GcInfoHeaderFlags)m_Reader.Read(GC_INFO_FLAGS_BIT_SIZE); +#ifdef DECODE_OLD_FORMATS + if (Version() < 4) + { + m_ReturnKind = (ReturnKind)((UINT32)m_Reader.Read(GcInfoEncoding::SIZE_OF_RETURN_KIND_IN_FAT_HEADER)); + } +#endif remainingFlags &= ~(DECODE_RETURN_KIND | DECODE_VARARG); #if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) remainingFlags &= ~DECODE_HAS_TAILCALLS; @@ -103,7 +106,7 @@ bool GcInfoDecoder::PredecodeFatHeader(int remainingFlags) return true; } - m_CodeLength = (UINT32)DENORMALIZE_CODE_LENGTH((UINT32)m_Reader.DecodeVarLengthUnsigned(CODE_LENGTH_ENCBASE)); + m_CodeLength = GcInfoEncoding::DENORMALIZE_CODE_LENGTH((UINT32)m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::CODE_LENGTH_ENCBASE)); remainingFlags &= ~DECODE_CODE_LENGTH; if (remainingFlags == 0) { @@ -115,21 +118,21 @@ bool GcInfoDecoder::PredecodeFatHeader(int remainingFlags) { // Note that normalization as a code offset can be different than // normalization as code length - UINT32 normCodeLength = NORMALIZE_CODE_OFFSET(m_CodeLength); + UINT32 normCodeLength = NormalizeCodeOffset(m_CodeLength); // Decode prolog/epilog information - UINT32 normPrologSize = (UINT32)m_Reader.DecodeVarLengthUnsigned(NORM_PROLOG_SIZE_ENCBASE) + 1; - UINT32 normEpilogSize = (UINT32)m_Reader.DecodeVarLengthUnsigned(NORM_EPILOG_SIZE_ENCBASE); + UINT32 normPrologSize = (UINT32)m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::NORM_PROLOG_SIZE_ENCBASE) + 1; + UINT32 normEpilogSize = (UINT32)m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::NORM_EPILOG_SIZE_ENCBASE); - m_ValidRangeStart = (UINT32)DENORMALIZE_CODE_OFFSET(normPrologSize); - m_ValidRangeEnd = (UINT32)DENORMALIZE_CODE_OFFSET(normCodeLength - normEpilogSize); + m_ValidRangeStart = DenormalizeCodeOffset(normPrologSize); + m_ValidRangeEnd = DenormalizeCodeOffset(normCodeLength - normEpilogSize); _ASSERTE(m_ValidRangeStart < m_ValidRangeEnd); } else if ((m_headerFlags & GC_INFO_HAS_GENERICS_INST_CONTEXT_MASK) != GC_INFO_HAS_GENERICS_INST_CONTEXT_NONE) { // Decode prolog information - UINT32 normPrologSize = (UINT32)m_Reader.DecodeVarLengthUnsigned(NORM_PROLOG_SIZE_ENCBASE) + 1; - m_ValidRangeStart = (UINT32)DENORMALIZE_CODE_OFFSET(normPrologSize); + UINT32 normPrologSize = (UINT32)m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::NORM_PROLOG_SIZE_ENCBASE) + 1; + m_ValidRangeStart = DenormalizeCodeOffset(normPrologSize); // satisfy asserts that assume m_GSCookieValidRangeStart != 0 ==> m_GSCookieValidRangeStart < m_GSCookieValidRangeEnd m_ValidRangeEnd = m_ValidRangeStart + 1; } @@ -148,7 +151,7 @@ bool GcInfoDecoder::PredecodeFatHeader(int remainingFlags) // Decode the offset to the GS cookie. if (m_headerFlags & GC_INFO_HAS_GS_COOKIE) { - m_GSCookieStackSlot = (INT32)DENORMALIZE_STACK_SLOT(m_Reader.DecodeVarLengthSigned(GS_COOKIE_STACK_SLOT_ENCBASE)); + m_GSCookieStackSlot = GcInfoEncoding::DENORMALIZE_STACK_SLOT((INT32)m_Reader.DecodeVarLengthSigned(GcInfoEncoding::GS_COOKIE_STACK_SLOT_ENCBASE)); } else { @@ -166,7 +169,7 @@ bool GcInfoDecoder::PredecodeFatHeader(int remainingFlags) // The PSPSym is relative to the caller SP on IA64 and the initial stack pointer before any stack allocation on X64 (InitialSP). if (m_headerFlags & GC_INFO_HAS_PSP_SYM) { - m_PSPSymStackSlot = (INT32)DENORMALIZE_STACK_SLOT(m_Reader.DecodeVarLengthSigned(PSP_SYM_STACK_SLOT_ENCBASE)); + m_PSPSymStackSlot = GcInfoEncoding::DENORMALIZE_STACK_SLOT((INT32)m_Reader.DecodeVarLengthSigned(GcInfoEncoding::PSP_SYM_STACK_SLOT_ENCBASE)); } else { @@ -183,7 +186,7 @@ bool GcInfoDecoder::PredecodeFatHeader(int remainingFlags) // Decode the offset to the generics type context. if ((m_headerFlags & GC_INFO_HAS_GENERICS_INST_CONTEXT_MASK) != GC_INFO_HAS_GENERICS_INST_CONTEXT_NONE) { - m_GenericsInstContextStackSlot = (INT32)DENORMALIZE_STACK_SLOT(m_Reader.DecodeVarLengthSigned(GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE)); + m_GenericsInstContextStackSlot = GcInfoEncoding::DENORMALIZE_STACK_SLOT((INT32)m_Reader.DecodeVarLengthSigned(GcInfoEncoding::GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE)); } else { @@ -199,7 +202,7 @@ bool GcInfoDecoder::PredecodeFatHeader(int remainingFlags) if (m_headerFlags & GC_INFO_HAS_STACK_BASE_REGISTER) { - m_StackBaseRegister = (UINT32)DENORMALIZE_STACK_BASE_REGISTER(m_Reader.DecodeVarLengthUnsigned(STACK_BASE_REGISTER_ENCBASE)); + m_StackBaseRegister = GcInfoEncoding::DENORMALIZE_STACK_BASE_REGISTER((UINT32)m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::STACK_BASE_REGISTER_ENCBASE)); } else { @@ -208,9 +211,9 @@ bool GcInfoDecoder::PredecodeFatHeader(int remainingFlags) if (m_headerFlags & GC_INFO_HAS_EDIT_AND_CONTINUE_INFO) { - m_SizeOfEditAndContinuePreservedArea = (UINT32)m_Reader.DecodeVarLengthUnsigned(SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE); + m_SizeOfEditAndContinuePreservedArea = (UINT32)m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE); #ifdef TARGET_ARM64 - m_SizeOfEditAndContinueFixedStackFrame = (UINT32)m_Reader.DecodeVarLengthUnsigned(SIZE_OF_EDIT_AND_CONTINUE_FIXED_STACK_FRAME_ENCBASE); + m_SizeOfEditAndContinueFixedStackFrame = (UINT32)m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::SIZE_OF_EDIT_AND_CONTINUE_FIXED_STACK_FRAME_ENCBASE); #endif } else @@ -230,7 +233,7 @@ bool GcInfoDecoder::PredecodeFatHeader(int remainingFlags) if (m_headerFlags & GC_INFO_REVERSE_PINVOKE_FRAME) { - m_ReversePInvokeFrameStackSlot = (INT32)DENORMALIZE_STACK_SLOT(m_Reader.DecodeVarLengthSigned(REVERSE_PINVOKE_FRAME_ENCBASE)); + m_ReversePInvokeFrameStackSlot = GcInfoEncoding::DENORMALIZE_STACK_SLOT((INT32)m_Reader.DecodeVarLengthSigned(GcInfoEncoding::REVERSE_PINVOKE_FRAME_ENCBASE)); } else { @@ -245,13 +248,14 @@ bool GcInfoDecoder::PredecodeFatHeader(int remainingFlags) } #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA - m_SizeOfStackOutgoingAndScratchArea = (UINT32)DENORMALIZE_SIZE_OF_STACK_AREA(m_Reader.DecodeVarLengthUnsigned(SIZE_OF_STACK_AREA_ENCBASE)); + m_SizeOfStackOutgoingAndScratchArea = GcInfoEncoding::DENORMALIZE_SIZE_OF_STACK_AREA((UINT32)m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::SIZE_OF_STACK_AREA_ENCBASE)); #endif // FIXED_STACK_PARAMETER_SCRATCH_AREA return false; } -GcInfoDecoder::GcInfoDecoder( +template +TGcInfoDecoder::TGcInfoDecoder( GCInfoToken gcInfoToken, GcInfoDecoderFlags flags, UINT32 breakOffset @@ -291,7 +295,7 @@ GcInfoDecoder::GcInfoDecoder( if (m_Reader.ReadOneFast()) { m_headerFlags = GC_INFO_HAS_STACK_BASE_REGISTER; - m_StackBaseRegister = (UINT32)DENORMALIZE_STACK_BASE_REGISTER(0); + m_StackBaseRegister = GcInfoEncoding::DENORMALIZE_STACK_BASE_REGISTER(0); } else { @@ -299,8 +303,12 @@ GcInfoDecoder::GcInfoDecoder( m_StackBaseRegister = NO_STACK_BASE_REGISTER; } - m_ReturnKind = (ReturnKind)((UINT32)m_Reader.Read(SIZE_OF_RETURN_KIND_IN_SLIM_HEADER)); - +#ifdef DECODE_OLD_FORMATS + if (Version() < 4) + { + m_ReturnKind = (ReturnKind)((UINT32)m_Reader.Read(GcInfoEncoding::SIZE_OF_RETURN_KIND_IN_SLIM_HEADER)); + } +#endif remainingFlags &= ~(DECODE_RETURN_KIND | DECODE_VARARG); #if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) remainingFlags &= ~DECODE_HAS_TAILCALLS; @@ -312,7 +320,7 @@ GcInfoDecoder::GcInfoDecoder( return; } - m_CodeLength = (UINT32)DENORMALIZE_CODE_LENGTH((UINT32)m_Reader.DecodeVarLengthUnsigned(CODE_LENGTH_ENCBASE)); + m_CodeLength = GcInfoEncoding::DENORMALIZE_CODE_LENGTH((UINT32)m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::CODE_LENGTH_ENCBASE)); // // predecoding the rest of slim header does not require any reading. @@ -351,7 +359,7 @@ GcInfoDecoder::GcInfoDecoder( } #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED - m_NumSafePoints = (UINT32) DENORMALIZE_NUM_SAFE_POINTS(m_Reader.DecodeVarLengthUnsigned(NUM_SAFE_POINTS_ENCBASE)); + m_NumSafePoints = (UINT32) m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::NUM_SAFE_POINTS_ENCBASE); m_SafePointIndex = m_NumSafePoints; #endif @@ -361,7 +369,7 @@ GcInfoDecoder::GcInfoDecoder( } else { - m_NumInterruptibleRanges = (UINT32) DENORMALIZE_NUM_INTERRUPTIBLE_RANGES(m_Reader.DecodeVarLengthUnsigned(NUM_INTERRUPTIBLE_RANGES_ENCBASE)); + m_NumInterruptibleRanges = (UINT32) m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::NUM_INTERRUPTIBLE_RANGES_ENCBASE); } #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED @@ -369,18 +377,25 @@ GcInfoDecoder::GcInfoDecoder( { if(m_NumSafePoints) { - // Safepoints are encoded with a -1 adjustment - // DECODE_GC_LIFETIMES adjusts the offset accordingly, but DECODE_INTERRUPTIBILITY does not - // adjust here - UINT32 offset = flags & DECODE_INTERRUPTIBILITY ? m_InstructionOffset - 1 : m_InstructionOffset; - m_SafePointIndex = FindSafePoint(offset); +#ifdef DECODE_OLD_FORMATS + if (Version() < 4) + { + // Safepoints are encoded with a -1 adjustment + // DECODE_GC_LIFETIMES adjusts the offset accordingly, but DECODE_INTERRUPTIBILITY does not + // adjust here + UINT32 offset = flags & DECODE_INTERRUPTIBILITY ? m_InstructionOffset - 1 : m_InstructionOffset; + m_SafePointIndex = FindSafePoint(offset); + } +#else + m_SafePointIndex = FindSafePoint(m_InstructionOffset); +#endif } } else if(flags & DECODE_FOR_RANGES_CALLBACK) { // Note that normalization as a code offset can be different than // normalization as code length - UINT32 normCodeLength = NORMALIZE_CODE_OFFSET(m_CodeLength); + UINT32 normCodeLength = NormalizeCodeOffset(m_CodeLength); UINT32 numBitsPerOffset = CeilOfLog2(normCodeLength); m_Reader.Skip(m_NumSafePoints * numBitsPerOffset); @@ -399,51 +414,41 @@ GcInfoDecoder::GcInfoDecoder( } } -bool GcInfoDecoder::IsInterruptible() +template bool TGcInfoDecoder::IsInterruptible() { _ASSERTE( m_Flags & DECODE_INTERRUPTIBILITY ); return m_IsInterruptible; } -bool GcInfoDecoder::HasInterruptibleRanges() +template bool TGcInfoDecoder::HasInterruptibleRanges() { _ASSERTE(m_Flags & (DECODE_INTERRUPTIBILITY | DECODE_GC_LIFETIMES)); return m_NumInterruptibleRanges > 0; } -bool GcInfoDecoder::IsSafePoint() +template bool TGcInfoDecoder::IsSafePoint() { _ASSERTE(m_Flags & (DECODE_INTERRUPTIBILITY | DECODE_GC_LIFETIMES)); return m_SafePointIndex != m_NumSafePoints; } -bool GcInfoDecoder::AreSafePointsInterruptible() -{ - return m_Version >= 3; -} - -bool GcInfoDecoder::IsInterruptibleSafePoint() -{ - return IsSafePoint() && AreSafePointsInterruptible(); -} - -bool GcInfoDecoder::CouldBeInterruptibleSafePoint() +template bool TGcInfoDecoder::CouldBeSafePoint() { // This is used in asserts. Ideally it would return false // if current location canot possibly be a safepoint. // However in some cases we optimize away "boring" callsites when no variables are tracked. // So there is no way to tell precisely that a point is indeed not a safe point. // Thus we do what we can here, but this could be better if we could have more data - return AreSafePointsInterruptible() && m_NumInterruptibleRanges == 0; + return m_NumInterruptibleRanges == 0; } -bool GcInfoDecoder::HasMethodDescGenericsInstContext() +template bool TGcInfoDecoder::HasMethodDescGenericsInstContext() { _ASSERTE( m_Flags & DECODE_GENERICS_INST_CONTEXT ); return (m_headerFlags & GC_INFO_HAS_GENERICS_INST_CONTEXT_MASK) == GC_INFO_HAS_GENERICS_INST_CONTEXT_MD; } -bool GcInfoDecoder::HasMethodTableGenericsInstContext() +template bool TGcInfoDecoder::HasMethodTableGenericsInstContext() { _ASSERTE( m_Flags & DECODE_GENERICS_INST_CONTEXT ); return (m_headerFlags & GC_INFO_HAS_GENERICS_INST_CONTEXT_MASK) == GC_INFO_HAS_GENERICS_INST_CONTEXT_MT; @@ -451,18 +456,22 @@ bool GcInfoDecoder::HasMethodTableGenericsInstContext() #ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED -// This is used for gccoverage: is the given offset +// This is used for gcinfodumper: is the given offset // a call-return offset with partially-interruptible GC info? -bool GcInfoDecoder::IsSafePoint(UINT32 codeOffset) +template bool TGcInfoDecoder::IsSafePoint(UINT32 codeOffset) { _ASSERTE(m_Flags == DECODE_EVERYTHING && m_InstructionOffset == 0); if(m_NumSafePoints == 0) return false; -#if defined(TARGET_AMD64) || defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) - // Safepoints are encoded with a -1 adjustment - codeOffset--; +#ifdef DECODE_OLD_FORMATS + if (Version() < 4) + { + // Safepoints are encoded with a -1 adjustment, adjust before searching. + codeOffset--; + } #endif + size_t savedPos = m_Reader.GetCurrentPos(); UINT32 safePointIndex = FindSafePoint(codeOffset); m_Reader.SetCurrentPos(savedPos); @@ -477,13 +486,14 @@ bool GcInfoDecoder::IsSafePoint(UINT32 codeOffset) // the whole run will be under 64 bytes, so likely we will stay in the same cache line. #define MAX_LINEAR_SEARCH 32 +template NOINLINE -UINT32 GcInfoDecoder::NarrowSafePointSearch(size_t savedPos, UINT32 breakOffset, UINT32* searchEnd) +UINT32 TGcInfoDecoder::NarrowSafePointSearch(size_t savedPos, UINT32 breakOffset, UINT32* searchEnd) { INT32 low = 0; INT32 high = (INT32)m_NumSafePoints; - const UINT32 numBitsPerOffset = CeilOfLog2(NORMALIZE_CODE_OFFSET(m_CodeLength)); + const UINT32 numBitsPerOffset = CeilOfLog2(NormalizeCodeOffset(m_CodeLength)); while (high - low > MAX_LINEAR_SEARCH) { const INT32 mid = (low + high) / 2; @@ -502,39 +512,33 @@ UINT32 GcInfoDecoder::NarrowSafePointSearch(size_t savedPos, UINT32 breakOffset, return low; } -UINT32 GcInfoDecoder::FindSafePoint(UINT32 breakOffset) +template UINT32 TGcInfoDecoder::FindSafePoint(UINT32 breakOffset) { _ASSERTE(m_NumSafePoints > 0); UINT32 result = m_NumSafePoints; const size_t savedPos = m_Reader.GetCurrentPos(); - const UINT32 numBitsPerOffset = CeilOfLog2(NORMALIZE_CODE_OFFSET(m_CodeLength)); + const UINT32 numBitsPerOffset = CeilOfLog2(NormalizeCodeOffset(m_CodeLength)); -#if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) - // Safepoints are encoded with a -1 adjustment - if ((breakOffset & 1) != 0) -#endif + const UINT32 normBreakOffset = NormalizeCodeOffset(breakOffset); + UINT32 linearSearchStart = 0; + UINT32 linearSearchEnd = m_NumSafePoints; + if (linearSearchEnd - linearSearchStart > MAX_LINEAR_SEARCH) + { + linearSearchStart = NarrowSafePointSearch(savedPos, normBreakOffset, &linearSearchEnd); + } + + for (UINT32 i = linearSearchStart; i < linearSearchEnd; i++) { - const UINT32 normBreakOffset = NORMALIZE_CODE_OFFSET(breakOffset); - UINT32 linearSearchStart = 0; - UINT32 linearSearchEnd = m_NumSafePoints; - if (linearSearchEnd - linearSearchStart > MAX_LINEAR_SEARCH) + UINT32 spOffset = (UINT32)m_Reader.Read(numBitsPerOffset); + if (spOffset == normBreakOffset) { - linearSearchStart = NarrowSafePointSearch(savedPos, normBreakOffset, &linearSearchEnd); + result = i; + break; } - for (UINT32 i = linearSearchStart; i < linearSearchEnd; i++) + if (spOffset > normBreakOffset) { - UINT32 spOffset = (UINT32)m_Reader.Read(numBitsPerOffset); - if (spOffset == normBreakOffset) - { - result = i; - break; - } - - if (spOffset > normBreakOffset) - { - break; - } + break; } } @@ -545,21 +549,24 @@ UINT32 GcInfoDecoder::FindSafePoint(UINT32 breakOffset) return result; } -void GcInfoDecoder::EnumerateSafePoints(EnumerateSafePointsCallback *pCallback, void * hCallback) +template void TGcInfoDecoder::EnumerateSafePoints(EnumerateSafePointsCallback *pCallback, void * hCallback) { if(m_NumSafePoints == 0) return; - const UINT32 numBitsPerOffset = CeilOfLog2(NORMALIZE_CODE_OFFSET(m_CodeLength)); + const UINT32 numBitsPerOffset = CeilOfLog2(NormalizeCodeOffset(m_CodeLength)); for(UINT32 i = 0; i < m_NumSafePoints; i++) { UINT32 normOffset = (UINT32)m_Reader.Read(numBitsPerOffset); - UINT32 offset = DENORMALIZE_CODE_OFFSET(normOffset) + 2; + UINT32 offset = DenormalizeCodeOffset(normOffset); -#if defined(TARGET_AMD64) || defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) - // Safepoints are encoded with a -1 adjustment - offset--; +#ifdef DECODE_OLD_FORMATS + if (Version() < 4) + { + // Safepoints are encoded with a -1 adjustment, adjust before reporting + offset++; + } #endif pCallback(this, offset, hCallback); @@ -567,7 +574,7 @@ void GcInfoDecoder::EnumerateSafePoints(EnumerateSafePointsCallback *pCallback, } #endif -void GcInfoDecoder::EnumerateInterruptibleRanges ( +template void TGcInfoDecoder::EnumerateInterruptibleRanges ( EnumerateInterruptibleRangesCallback *pCallback, void * hCallback) { @@ -578,14 +585,14 @@ void GcInfoDecoder::EnumerateInterruptibleRanges ( for(UINT32 i=0; i INT32 TGcInfoDecoder::GetGSCookieStackSlot() { _ASSERTE( m_Flags & DECODE_GS_COOKIE ); return m_GSCookieStackSlot; } -INT32 GcInfoDecoder::GetReversePInvokeFrameStackSlot() +template INT32 TGcInfoDecoder::GetReversePInvokeFrameStackSlot() { _ASSERTE(m_Flags & DECODE_REVERSE_PINVOKE_VAR); return m_ReversePInvokeFrameStackSlot; } -UINT32 GcInfoDecoder::GetGSCookieValidRangeStart() +template UINT32 TGcInfoDecoder::GetGSCookieValidRangeStart() { _ASSERTE( m_Flags & DECODE_GS_COOKIE ); return m_ValidRangeStart; } -UINT32 GcInfoDecoder::GetGSCookieValidRangeEnd() +template UINT32 TGcInfoDecoder::GetGSCookieValidRangeEnd() { _ASSERTE( m_Flags & DECODE_GS_COOKIE ); return m_ValidRangeEnd; } -UINT32 GcInfoDecoder::GetPrologSize() +template UINT32 TGcInfoDecoder::GetPrologSize() { _ASSERTE( m_Flags & DECODE_PROLOG_LENGTH ); return m_ValidRangeStart; } -INT32 GcInfoDecoder::GetGenericsInstContextStackSlot() +template INT32 TGcInfoDecoder::GetGenericsInstContextStackSlot() { _ASSERTE( m_Flags & DECODE_GENERICS_INST_CONTEXT ); return m_GenericsInstContextStackSlot; } -INT32 GcInfoDecoder::GetPSPSymStackSlot() +template INT32 TGcInfoDecoder::GetPSPSymStackSlot() { _ASSERTE( m_Flags & DECODE_PSP_SYM ); return m_PSPSymStackSlot; } -bool GcInfoDecoder::GetIsVarArg() +template bool TGcInfoDecoder::GetIsVarArg() { _ASSERTE( m_Flags & DECODE_VARARG ); return m_headerFlags & GC_INFO_IS_VARARG; } #if defined(TARGET_ARM) || defined(TARGET_ARM64) || defined(TARGET_LOONGARCH64) || defined(TARGET_RISCV64) -bool GcInfoDecoder::HasTailCalls() +template bool TGcInfoDecoder::HasTailCalls() { _ASSERTE( m_Flags & DECODE_HAS_TAILCALLS ); return ((m_headerFlags & GC_INFO_HAS_TAILCALLS) != 0); } #endif // TARGET_ARM || TARGET_ARM64 || TARGET_LOONGARCH64 || TARGET_RISCV64 -bool GcInfoDecoder::WantsReportOnlyLeaf() +template bool TGcInfoDecoder::WantsReportOnlyLeaf() { // Only AMD64 with JIT64 can return false here. #ifdef TARGET_AMD64 @@ -661,40 +668,40 @@ bool GcInfoDecoder::WantsReportOnlyLeaf() #endif } -UINT32 GcInfoDecoder::GetCodeLength() +template UINT32 TGcInfoDecoder::GetCodeLength() { // SUPPORTS_DAC; _ASSERTE( m_Flags & DECODE_CODE_LENGTH ); return m_CodeLength; } -ReturnKind GcInfoDecoder::GetReturnKind() +template ReturnKind TGcInfoDecoder::GetReturnKind() { // SUPPORTS_DAC; - _ASSERTE( m_Flags & DECODE_RETURN_KIND ); + _ASSERTE(m_Flags & DECODE_RETURN_KIND); return m_ReturnKind; } -UINT32 GcInfoDecoder::GetStackBaseRegister() +template UINT32 TGcInfoDecoder::GetStackBaseRegister() { return m_StackBaseRegister; } -UINT32 GcInfoDecoder::GetSizeOfEditAndContinuePreservedArea() +template UINT32 TGcInfoDecoder::GetSizeOfEditAndContinuePreservedArea() { _ASSERTE( m_Flags & DECODE_EDIT_AND_CONTINUE ); return m_SizeOfEditAndContinuePreservedArea; } #ifdef TARGET_ARM64 -UINT32 GcInfoDecoder::GetSizeOfEditAndContinueFixedStackFrame() +template UINT32 TGcInfoDecoder::GetSizeOfEditAndContinueFixedStackFrame() { _ASSERTE( m_Flags & DECODE_EDIT_AND_CONTINUE ); return m_SizeOfEditAndContinueFixedStackFrame; } #endif -size_t GcInfoDecoder::GetNumBytesRead() +template size_t TGcInfoDecoder::GetNumBytesRead() { return (m_Reader.GetCurrentPos() + 7) / 8; } @@ -702,7 +709,7 @@ size_t GcInfoDecoder::GetNumBytesRead() #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA -UINT32 GcInfoDecoder::GetSizeOfStackParameterArea() +template UINT32 TGcInfoDecoder::GetSizeOfStackParameterArea() { return m_SizeOfStackOutgoingAndScratchArea; } @@ -710,7 +717,7 @@ UINT32 GcInfoDecoder::GetSizeOfStackParameterArea() #endif // FIXED_STACK_PARAMETER_SCRATCH_AREA -bool GcInfoDecoder::EnumerateLiveSlots( +template bool TGcInfoDecoder::EnumerateLiveSlots( PREGDISPLAY pRD, bool reportScratchSlots, unsigned inputFlags, @@ -731,23 +738,14 @@ bool GcInfoDecoder::EnumerateLiveSlots( return true; } - // - // If this is a non-leaf frame and we are executing a call, the unwinder has given us the PC - // of the call instruction. We should adjust it to the PC of the instruction after the call in order to - // obtain transition information for scratch slots. However, we always assume scratch slots to be - // dead for non-leaf frames (except for ResumableFrames), so we don't need to adjust the PC. - // If this is a non-leaf frame and we are not executing a call (i.e.: a fault occurred in the function), - // then it would be incorrect to adjust the PC - // - _ASSERTE(GC_SLOT_INTERIOR == GC_CALL_INTERIOR); _ASSERTE(GC_SLOT_PINNED == GC_CALL_PINNED); _ASSERTE( m_Flags & DECODE_GC_LIFETIMES ); - GcSlotDecoder slotDecoder; + GcSlotDecoder slotDecoder; - UINT32 normBreakOffset = NORMALIZE_CODE_OFFSET(m_InstructionOffset); + UINT32 normBreakOffset = NormalizeCodeOffset(m_InstructionOffset); // Normalized break offset // Relative to interruptible ranges #if PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED @@ -768,8 +766,8 @@ bool GcInfoDecoder::EnumerateLiveSlots( // Skip interruptibility information for(UINT32 i=0; i 0) && m_Reader.ReadOneFast()) { - numBitsPerOffset = (UINT32) m_Reader.DecodeVarLengthUnsigned(POINTER_SIZE_ENCBASE) + 1; + numBitsPerOffset = (UINT32) m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::POINTER_SIZE_ENCBASE) + 1; _ASSERTE(numBitsPerOffset != 0); } @@ -871,11 +869,11 @@ bool GcInfoDecoder::EnumerateLiveSlots( // RLE encoded bool fSkip = (m_Reader.ReadOneFast() == 0); bool fReport = true; - UINT32 readSlots = (UINT32)m_Reader.DecodeVarLengthUnsigned( fSkip ? LIVESTATE_RLE_SKIP_ENCBASE : LIVESTATE_RLE_RUN_ENCBASE ); + UINT32 readSlots = (UINT32)m_Reader.DecodeVarLengthUnsigned( fSkip ? GcInfoEncoding::LIVESTATE_RLE_SKIP_ENCBASE : GcInfoEncoding::LIVESTATE_RLE_RUN_ENCBASE ); fSkip = !fSkip; while (readSlots < numSlots) { - UINT32 cnt = (UINT32)m_Reader.DecodeVarLengthUnsigned( fSkip ? LIVESTATE_RLE_SKIP_ENCBASE : LIVESTATE_RLE_RUN_ENCBASE ) + 1; + UINT32 cnt = (UINT32)m_Reader.DecodeVarLengthUnsigned( fSkip ? GcInfoEncoding::LIVESTATE_RLE_SKIP_ENCBASE : GcInfoEncoding::LIVESTATE_RLE_RUN_ENCBASE ) + 1; if (fReport) { for(UINT32 slotIndex = readSlots; slotIndex < readSlots + cnt; slotIndex++) @@ -935,11 +933,11 @@ bool GcInfoDecoder::EnumerateLiveSlots( // If no info is found for the call site, we default to fully-interruptible LOG((LF_GCROOTS, LL_INFO1000000, "No GC info found for call site at offset %x. Defaulting to fully-interruptible information.\n", (int) m_InstructionOffset)); - UINT32 numChunks = (numInterruptibleLength + NUM_NORM_CODE_OFFSETS_PER_CHUNK - 1) / NUM_NORM_CODE_OFFSETS_PER_CHUNK; - UINT32 breakChunk = pseudoBreakOffset / NUM_NORM_CODE_OFFSETS_PER_CHUNK; + UINT32 numChunks = (numInterruptibleLength + GcInfoEncoding::NUM_NORM_CODE_OFFSETS_PER_CHUNK - 1) / GcInfoEncoding::NUM_NORM_CODE_OFFSETS_PER_CHUNK; + UINT32 breakChunk = pseudoBreakOffset / GcInfoEncoding::NUM_NORM_CODE_OFFSETS_PER_CHUNK; _ASSERTE(breakChunk < numChunks); - UINT32 numBitsPerPointer = (UINT32) m_Reader.DecodeVarLengthUnsigned(POINTER_SIZE_ENCBASE); + UINT32 numBitsPerPointer = (UINT32) m_Reader.DecodeVarLengthUnsigned(GcInfoEncoding::POINTER_SIZE_ENCBASE); if(!numBitsPerPointer) goto ReportUntracked; @@ -973,11 +971,11 @@ bool GcInfoDecoder::EnumerateLiveSlots( // RLE encoded bool fSkip = (m_Reader.ReadOneFast() == 0); bool fReport = true; - UINT32 readSlots = (UINT32)m_Reader.DecodeVarLengthUnsigned( fSkip ? LIVESTATE_RLE_SKIP_ENCBASE : LIVESTATE_RLE_RUN_ENCBASE ); + UINT32 readSlots = (UINT32)m_Reader.DecodeVarLengthUnsigned( fSkip ? GcInfoEncoding::LIVESTATE_RLE_SKIP_ENCBASE : GcInfoEncoding::LIVESTATE_RLE_RUN_ENCBASE ); fSkip = !fSkip; while (readSlots < numSlots) { - UINT32 cnt = (UINT32)m_Reader.DecodeVarLengthUnsigned( fSkip ? LIVESTATE_RLE_SKIP_ENCBASE : LIVESTATE_RLE_RUN_ENCBASE ) + 1; + UINT32 cnt = (UINT32)m_Reader.DecodeVarLengthUnsigned( fSkip ? GcInfoEncoding::LIVESTATE_RLE_SKIP_ENCBASE : GcInfoEncoding::LIVESTATE_RLE_RUN_ENCBASE ) + 1; if (fReport) { numCouldBeLiveSlots += cnt; @@ -1029,15 +1027,15 @@ bool GcInfoDecoder::EnumerateLiveSlots( // We need to find a new run else if (fSkipFirst) { - UINT32 tmp = (UINT32)couldBeLiveReader.DecodeVarLengthUnsigned( LIVESTATE_RLE_SKIP_ENCBASE ) + 1; + UINT32 tmp = (UINT32)couldBeLiveReader.DecodeVarLengthUnsigned( GcInfoEncoding::LIVESTATE_RLE_SKIP_ENCBASE ) + 1; slotIndex += tmp; - cnt = (UINT32)couldBeLiveReader.DecodeVarLengthUnsigned( LIVESTATE_RLE_RUN_ENCBASE ); + cnt = (UINT32)couldBeLiveReader.DecodeVarLengthUnsigned( GcInfoEncoding::LIVESTATE_RLE_RUN_ENCBASE ); } else { - UINT32 tmp = (UINT32)couldBeLiveReader.DecodeVarLengthUnsigned( LIVESTATE_RLE_RUN_ENCBASE ) + 1; + UINT32 tmp = (UINT32)couldBeLiveReader.DecodeVarLengthUnsigned( GcInfoEncoding::LIVESTATE_RLE_RUN_ENCBASE ) + 1; slotIndex += tmp; - cnt = (UINT32)couldBeLiveReader.DecodeVarLengthUnsigned( LIVESTATE_RLE_SKIP_ENCBASE ); + cnt = (UINT32)couldBeLiveReader.DecodeVarLengthUnsigned( GcInfoEncoding::LIVESTATE_RLE_SKIP_ENCBASE ); } UINT32 isLive = (UINT32) finalStateReader.Read(1); @@ -1045,16 +1043,16 @@ bool GcInfoDecoder::EnumerateLiveSlots( if(chunk == breakChunk) { // Read transitions - UINT32 normBreakOffsetDelta = pseudoBreakOffset % NUM_NORM_CODE_OFFSETS_PER_CHUNK; + UINT32 normBreakOffsetDelta = pseudoBreakOffset % GcInfoEncoding::NUM_NORM_CODE_OFFSETS_PER_CHUNK; for(;;) { if(!m_Reader.ReadOneFast()) break; - UINT32 transitionOffset = (UINT32) m_Reader.Read(NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2); + UINT32 transitionOffset = (UINT32) m_Reader.Read(GcInfoEncoding::NUM_NORM_CODE_OFFSETS_PER_CHUNK_LOG2); lifetimeTransitionsCount++; - _ASSERTE(transitionOffset && transitionOffset < NUM_NORM_CODE_OFFSETS_PER_CHUNK); + _ASSERTE(transitionOffset && transitionOffset < GcInfoEncoding::NUM_NORM_CODE_OFFSETS_PER_CHUNK); if(transitionOffset > normBreakOffsetDelta) { isLive ^= 1; @@ -1101,7 +1099,7 @@ bool GcInfoDecoder::EnumerateLiveSlots( return true; } -void GcInfoDecoder::EnumerateUntrackedSlots( +template void TGcInfoDecoder::EnumerateUntrackedSlots( PREGDISPLAY pRD, unsigned inputFlags, GCEnumCallback pCallBack, @@ -1113,13 +1111,13 @@ void GcInfoDecoder::EnumerateUntrackedSlots( _ASSERTE( m_Flags & DECODE_GC_LIFETIMES ); - GcSlotDecoder slotDecoder; + GcSlotDecoder slotDecoder; // Skip interruptibility information for(UINT32 i=0; i void TGcInfoDecoder::ReportUntrackedSlots( + GcSlotDecoder& slotDecoder, PREGDISPLAY pRD, unsigned inputFlags, GCEnumCallback pCallBack, @@ -1155,11 +1153,11 @@ void GcInfoDecoder::ReportUntrackedSlots( } } -void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) +template void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) { if (reader.ReadOneFast()) { - m_NumRegisters = (UINT32) reader.DecodeVarLengthUnsigned(NUM_REGISTERS_ENCBASE); + m_NumRegisters = (UINT32) reader.DecodeVarLengthUnsigned(GcInfoEncoding::NUM_REGISTERS_ENCBASE); } else { @@ -1168,8 +1166,8 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) UINT32 numStackSlots; if (reader.ReadOneFast()) { - numStackSlots = (UINT32) reader.DecodeVarLengthUnsigned(NUM_STACK_SLOTS_ENCBASE); - m_NumUntracked = (UINT32) reader.DecodeVarLengthUnsigned(NUM_UNTRACKED_SLOTS_ENCBASE); + numStackSlots = (UINT32) reader.DecodeVarLengthUnsigned(GcInfoEncoding::NUM_STACK_SLOTS_ENCBASE); + m_NumUntracked = (UINT32) reader.DecodeVarLengthUnsigned(GcInfoEncoding::NUM_UNTRACKED_SLOTS_ENCBASE); } else { @@ -1186,8 +1184,8 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) _ASSERTE(i < MAX_PREDECODED_SLOTS); - UINT32 normRegNum = (UINT32) reader.DecodeVarLengthUnsigned(REGISTER_ENCBASE); - UINT32 regNum = DENORMALIZE_REGISTER(normRegNum); + UINT32 normRegNum = (UINT32) reader.DecodeVarLengthUnsigned(GcInfoEncoding::REGISTER_ENCBASE); + UINT32 regNum = normRegNum; GcSlotFlags flags = (GcSlotFlags) reader.Read(2); m_SlotArray[0].Slot.RegisterNumber = regNum; @@ -1198,15 +1196,15 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) { if(flags) { - normRegNum = (UINT32) reader.DecodeVarLengthUnsigned(REGISTER_ENCBASE); - regNum = DENORMALIZE_REGISTER(normRegNum); + normRegNum = (UINT32) reader.DecodeVarLengthUnsigned(GcInfoEncoding::REGISTER_ENCBASE); + regNum = normRegNum; flags = (GcSlotFlags) reader.Read(2); } else { - UINT32 normRegDelta = (UINT32) reader.DecodeVarLengthUnsigned(REGISTER_DELTA_ENCBASE) + 1; + UINT32 normRegDelta = (UINT32) reader.DecodeVarLengthUnsigned(GcInfoEncoding::REGISTER_DELTA_ENCBASE) + 1; normRegNum += normRegDelta; - regNum = DENORMALIZE_REGISTER(normRegNum); + regNum = normRegNum; } m_SlotArray[i].Slot.RegisterNumber = regNum; @@ -1219,8 +1217,8 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) // We have stack slots left and more room to predecode GcStackSlotBase spBase = (GcStackSlotBase) reader.Read(2); - UINT32 normSpOffset = (INT32) reader.DecodeVarLengthSigned(STACK_SLOT_ENCBASE); - INT32 spOffset = DENORMALIZE_STACK_SLOT(normSpOffset); + UINT32 normSpOffset = (INT32) reader.DecodeVarLengthSigned(GcInfoEncoding::STACK_SLOT_ENCBASE); + INT32 spOffset = GcInfoEncoding::DENORMALIZE_STACK_SLOT(normSpOffset); GcSlotFlags flags = (GcSlotFlags) reader.Read(2); m_SlotArray[i].Slot.Stack.SpOffset = spOffset; @@ -1234,15 +1232,15 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) if(flags) { - normSpOffset = (INT32) reader.DecodeVarLengthSigned(STACK_SLOT_ENCBASE); - spOffset = DENORMALIZE_STACK_SLOT(normSpOffset); + normSpOffset = (INT32) reader.DecodeVarLengthSigned(GcInfoEncoding::STACK_SLOT_ENCBASE); + spOffset = GcInfoEncoding::DENORMALIZE_STACK_SLOT(normSpOffset); flags = (GcSlotFlags) reader.Read(2); } else { - INT32 normSpOffsetDelta = (INT32) reader.DecodeVarLengthUnsigned(STACK_SLOT_DELTA_ENCBASE); + INT32 normSpOffsetDelta = (INT32) reader.DecodeVarLengthUnsigned(GcInfoEncoding::STACK_SLOT_DELTA_ENCBASE); normSpOffset += normSpOffsetDelta; - spOffset = DENORMALIZE_STACK_SLOT(normSpOffset); + spOffset = GcInfoEncoding::DENORMALIZE_STACK_SLOT(normSpOffset); } m_SlotArray[i].Slot.Stack.SpOffset = spOffset; @@ -1256,8 +1254,8 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) // We have untracked stack slots left and more room to predecode GcStackSlotBase spBase = (GcStackSlotBase) reader.Read(2); - UINT32 normSpOffset = (INT32) reader.DecodeVarLengthSigned(STACK_SLOT_ENCBASE); - INT32 spOffset = DENORMALIZE_STACK_SLOT(normSpOffset); + UINT32 normSpOffset = (INT32) reader.DecodeVarLengthSigned(GcInfoEncoding::STACK_SLOT_ENCBASE); + INT32 spOffset = GcInfoEncoding::DENORMALIZE_STACK_SLOT(normSpOffset); GcSlotFlags flags = (GcSlotFlags) reader.Read(2); m_SlotArray[i].Slot.Stack.SpOffset = spOffset; @@ -1271,15 +1269,15 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) if(flags) { - normSpOffset = (INT32) reader.DecodeVarLengthSigned(STACK_SLOT_ENCBASE); - spOffset = DENORMALIZE_STACK_SLOT(normSpOffset); + normSpOffset = (INT32) reader.DecodeVarLengthSigned(GcInfoEncoding::STACK_SLOT_ENCBASE); + spOffset = GcInfoEncoding::DENORMALIZE_STACK_SLOT(normSpOffset); flags = (GcSlotFlags) reader.Read(2); } else { - INT32 normSpOffsetDelta = (INT32) reader.DecodeVarLengthUnsigned(STACK_SLOT_DELTA_ENCBASE); + INT32 normSpOffsetDelta = (INT32) reader.DecodeVarLengthUnsigned(GcInfoEncoding::STACK_SLOT_DELTA_ENCBASE); normSpOffset += normSpOffsetDelta; - spOffset = DENORMALIZE_STACK_SLOT(normSpOffset); + spOffset = GcInfoEncoding::DENORMALIZE_STACK_SLOT(normSpOffset); } m_SlotArray[i].Slot.Stack.SpOffset = spOffset; @@ -1310,12 +1308,12 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) { if(flags) { - reader.DecodeVarLengthUnsigned(REGISTER_ENCBASE); + reader.DecodeVarLengthUnsigned(GcInfoEncoding::REGISTER_ENCBASE); flags = (GcSlotFlags) reader.Read(2); } else { - reader.DecodeVarLengthUnsigned(REGISTER_DELTA_ENCBASE); + reader.DecodeVarLengthUnsigned(GcInfoEncoding::REGISTER_DELTA_ENCBASE); } } @@ -1326,7 +1324,7 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) // Skip the first stack slot reader.Read(2); - reader.DecodeVarLengthSigned(STACK_SLOT_ENCBASE); + reader.DecodeVarLengthSigned(GcInfoEncoding::STACK_SLOT_ENCBASE); flags = (GcSlotFlags) reader.Read(2); i++; } @@ -1340,12 +1338,12 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) if(flags) { - reader.DecodeVarLengthSigned(STACK_SLOT_ENCBASE); + reader.DecodeVarLengthSigned(GcInfoEncoding::STACK_SLOT_ENCBASE); flags = (GcSlotFlags) reader.Read(2); } else { - reader.DecodeVarLengthUnsigned(STACK_SLOT_DELTA_ENCBASE); + reader.DecodeVarLengthUnsigned(GcInfoEncoding::STACK_SLOT_DELTA_ENCBASE); } } } @@ -1357,7 +1355,7 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) // Skip the first untracked slot reader.Read(2); - reader.DecodeVarLengthSigned(STACK_SLOT_ENCBASE); + reader.DecodeVarLengthSigned(GcInfoEncoding::STACK_SLOT_ENCBASE); flags = (GcSlotFlags) reader.Read(2); i++; } @@ -1370,19 +1368,19 @@ void GcSlotDecoder::DecodeSlotTable(BitStreamReader& reader) if(flags) { - reader.DecodeVarLengthSigned(STACK_SLOT_ENCBASE); + reader.DecodeVarLengthSigned(GcInfoEncoding::STACK_SLOT_ENCBASE); flags = (GcSlotFlags) reader.Read(2); } else { - reader.DecodeVarLengthUnsigned(STACK_SLOT_DELTA_ENCBASE); + reader.DecodeVarLengthUnsigned(GcInfoEncoding::STACK_SLOT_DELTA_ENCBASE); } } } } } -const GcSlotDesc* GcSlotDecoder::GetSlotDesc(UINT32 slotIndex) +template const GcSlotDesc* GcSlotDecoder::GetSlotDesc(UINT32 slotIndex) { _ASSERTE(slotIndex < m_NumSlots); @@ -1405,23 +1403,23 @@ const GcSlotDesc* GcSlotDecoder::GetSlotDesc(UINT32 slotIndex) if(m_NumDecodedSlots == 0) { // Decode the first register - UINT32 normRegNum = (UINT32) m_SlotReader.DecodeVarLengthUnsigned(REGISTER_ENCBASE); - m_pLastSlot->Slot.RegisterNumber = DENORMALIZE_REGISTER(normRegNum); + UINT32 normRegNum = (UINT32) m_SlotReader.DecodeVarLengthUnsigned(GcInfoEncoding::REGISTER_ENCBASE); + m_pLastSlot->Slot.RegisterNumber = normRegNum; m_pLastSlot->Flags = (GcSlotFlags) m_SlotReader.Read(2); } else { if(m_pLastSlot->Flags) { - UINT32 normRegNum = (UINT32) m_SlotReader.DecodeVarLengthUnsigned(REGISTER_ENCBASE); - m_pLastSlot->Slot.RegisterNumber = DENORMALIZE_REGISTER(normRegNum); + UINT32 normRegNum = (UINT32) m_SlotReader.DecodeVarLengthUnsigned(GcInfoEncoding::REGISTER_ENCBASE); + m_pLastSlot->Slot.RegisterNumber = normRegNum; m_pLastSlot->Flags = (GcSlotFlags) m_SlotReader.Read(2); } else { - UINT32 normRegDelta = (UINT32) m_SlotReader.DecodeVarLengthUnsigned(REGISTER_DELTA_ENCBASE) + 1; - UINT32 normRegNum = normRegDelta + NORMALIZE_REGISTER(m_pLastSlot->Slot.RegisterNumber); - m_pLastSlot->Slot.RegisterNumber = DENORMALIZE_REGISTER(normRegNum); + UINT32 normRegDelta = (UINT32) m_SlotReader.DecodeVarLengthUnsigned(GcInfoEncoding::REGISTER_DELTA_ENCBASE) + 1; + UINT32 normRegNum = normRegDelta + m_pLastSlot->Slot.RegisterNumber; + m_pLastSlot->Slot.RegisterNumber = normRegNum; } } } @@ -1435,8 +1433,8 @@ const GcSlotDesc* GcSlotDecoder::GetSlotDesc(UINT32 slotIndex) { // Decode the first stack slot or first untracked slot m_pLastSlot->Slot.Stack.Base = (GcStackSlotBase) m_SlotReader.Read(2); - UINT32 normSpOffset = (INT32) m_SlotReader.DecodeVarLengthSigned(STACK_SLOT_ENCBASE); - m_pLastSlot->Slot.Stack.SpOffset = DENORMALIZE_STACK_SLOT(normSpOffset); + UINT32 normSpOffset = (INT32) m_SlotReader.DecodeVarLengthSigned(GcInfoEncoding::STACK_SLOT_ENCBASE); + m_pLastSlot->Slot.Stack.SpOffset = GcInfoEncoding::DENORMALIZE_STACK_SLOT(normSpOffset); m_pLastSlot->Flags = (GcSlotFlags) m_SlotReader.Read(2); } else @@ -1445,15 +1443,15 @@ const GcSlotDesc* GcSlotDecoder::GetSlotDesc(UINT32 slotIndex) if(m_pLastSlot->Flags) { - INT32 normSpOffset = (INT32) m_SlotReader.DecodeVarLengthSigned(STACK_SLOT_ENCBASE); - m_pLastSlot->Slot.Stack.SpOffset = DENORMALIZE_STACK_SLOT(normSpOffset); + INT32 normSpOffset = (INT32) m_SlotReader.DecodeVarLengthSigned(GcInfoEncoding::STACK_SLOT_ENCBASE); + m_pLastSlot->Slot.Stack.SpOffset = GcInfoEncoding::DENORMALIZE_STACK_SLOT(normSpOffset); m_pLastSlot->Flags = (GcSlotFlags) m_SlotReader.Read(2); } else { - INT32 normSpOffsetDelta = (INT32) m_SlotReader.DecodeVarLengthUnsigned(STACK_SLOT_DELTA_ENCBASE); - INT32 normSpOffset = normSpOffsetDelta + NORMALIZE_STACK_SLOT(m_pLastSlot->Slot.Stack.SpOffset); - m_pLastSlot->Slot.Stack.SpOffset = DENORMALIZE_STACK_SLOT(normSpOffset); + INT32 normSpOffsetDelta = (INT32) m_SlotReader.DecodeVarLengthUnsigned(GcInfoEncoding::STACK_SLOT_DELTA_ENCBASE); + INT32 normSpOffset = normSpOffsetDelta + GcInfoEncoding::NORMALIZE_STACK_SLOT(m_pLastSlot->Slot.Stack.SpOffset); + m_pLastSlot->Slot.Stack.SpOffset = GcInfoEncoding::DENORMALIZE_STACK_SLOT(normSpOffset); } } } @@ -1472,7 +1470,7 @@ const GcSlotDesc* GcSlotDecoder::GetSlotDesc(UINT32 slotIndex) #if defined(TARGET_AMD64) -OBJECTREF* GcInfoDecoder::GetRegisterSlot( +template OBJECTREF* TGcInfoDecoder::GetRegisterSlot( int regNum, PREGDISPLAY pRD ) @@ -1494,7 +1492,7 @@ OBJECTREF* GcInfoDecoder::GetRegisterSlot( } #if defined(TARGET_UNIX) && !defined(FEATURE_NATIVEAOT) -OBJECTREF* GcInfoDecoder::GetCapturedRegister( +template OBJECTREF* TGcInfoDecoder::GetCapturedRegister( int regNum, PREGDISPLAY pRD ) @@ -1511,7 +1509,7 @@ OBJECTREF* GcInfoDecoder::GetCapturedRegister( } #endif // TARGET_UNIX && !FEATURE_NATIVEAOT -bool GcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) { _ASSERTE(regNum >= 0 && regNum <= 16); _ASSERTE(regNum != 4); // rsp @@ -1532,7 +1530,7 @@ bool GcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) } -bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) { #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA _ASSERTE( m_Flags & DECODE_GC_LIFETIMES ); @@ -1547,7 +1545,7 @@ bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, P } -void GcInfoDecoder::ReportRegisterToGC( // AMD64 +template void TGcInfoDecoder::ReportRegisterToGC( // AMD64 int regNum, unsigned gcFlags, PREGDISPLAY pRD, @@ -1607,7 +1605,7 @@ void GcInfoDecoder::ReportRegisterToGC( // AMD64 #elif defined(TARGET_ARM) -OBJECTREF* GcInfoDecoder::GetRegisterSlot( +template OBJECTREF* TGcInfoDecoder::GetRegisterSlot( int regNum, PREGDISPLAY pRD ) @@ -1649,7 +1647,7 @@ OBJECTREF* GcInfoDecoder::GetRegisterSlot( } #if defined(TARGET_UNIX) && !defined(FEATURE_NATIVEAOT) -OBJECTREF* GcInfoDecoder::GetCapturedRegister( +template OBJECTREF* TGcInfoDecoder::GetCapturedRegister( int regNum, PREGDISPLAY pRD ) @@ -1667,7 +1665,7 @@ OBJECTREF* GcInfoDecoder::GetCapturedRegister( #endif // TARGET_UNIX && !FEATURE_NATIVEAOT -bool GcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) { _ASSERTE(regNum >= 0 && regNum <= 14); _ASSERTE(regNum != 13); // sp @@ -1676,7 +1674,7 @@ bool GcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) } -bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) { #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA _ASSERTE( m_Flags & DECODE_GC_LIFETIMES ); @@ -1691,7 +1689,7 @@ bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, P } -void GcInfoDecoder::ReportRegisterToGC( // ARM +template void TGcInfoDecoder::ReportRegisterToGC( // ARM int regNum, unsigned gcFlags, PREGDISPLAY pRD, @@ -1730,7 +1728,7 @@ void GcInfoDecoder::ReportRegisterToGC( // ARM #elif defined(TARGET_ARM64) -OBJECTREF* GcInfoDecoder::GetRegisterSlot( +template OBJECTREF* TGcInfoDecoder::GetRegisterSlot( int regNum, PREGDISPLAY pRD ) @@ -1765,7 +1763,7 @@ OBJECTREF* GcInfoDecoder::GetRegisterSlot( #endif } -bool GcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) { _ASSERTE(regNum >= 0 && regNum <= 30); _ASSERTE(regNum != 18); @@ -1773,7 +1771,7 @@ bool GcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) return regNum <= 17 || regNum >= 29; // R12 and R14/LR are both scratch registers } -bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) { #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA _ASSERTE( m_Flags & DECODE_GC_LIFETIMES ); @@ -1788,7 +1786,7 @@ bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, P } -void GcInfoDecoder::ReportRegisterToGC( // ARM64 +template void TGcInfoDecoder::ReportRegisterToGC( // ARM64 int regNum, unsigned gcFlags, PREGDISPLAY pRD, @@ -1847,7 +1845,7 @@ void GcInfoDecoder::ReportRegisterToGC( // ARM64 } #if defined(TARGET_UNIX) && !defined(FEATURE_NATIVEAOT) -OBJECTREF* GcInfoDecoder::GetCapturedRegister( +template OBJECTREF* TGcInfoDecoder::GetCapturedRegister( int regNum, PREGDISPLAY pRD ) @@ -1876,7 +1874,7 @@ OBJECTREF* GcInfoDecoder::GetCapturedRegister( #elif defined(TARGET_LOONGARCH64) #if defined(TARGET_UNIX) && !defined(FEATURE_NATIVEAOT) -OBJECTREF* GcInfoDecoder::GetCapturedRegister( +template OBJECTREF* TGcInfoDecoder::GetCapturedRegister( int regNum, PREGDISPLAY pRD ) @@ -1892,7 +1890,7 @@ OBJECTREF* GcInfoDecoder::GetCapturedRegister( } #endif // TARGET_UNIX && !FEATURE_NATIVEAOT -OBJECTREF* GcInfoDecoder::GetRegisterSlot( +template OBJECTREF* TGcInfoDecoder::GetRegisterSlot( int regNum, PREGDISPLAY pRD ) @@ -1921,14 +1919,14 @@ OBJECTREF* GcInfoDecoder::GetRegisterSlot( #endif } -bool GcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) { _ASSERTE(regNum >= 0 && regNum <= 31); return (regNum <= 21 && ((regNum >= 4) || (regNum == 1))); } -bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) { #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA _ASSERTE( m_Flags & DECODE_GC_LIFETIMES ); @@ -1942,7 +1940,7 @@ bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, P #endif } -void GcInfoDecoder::ReportRegisterToGC( +template void TGcInfoDecoder::ReportRegisterToGC( int regNum, unsigned gcFlags, PREGDISPLAY pRD, @@ -2003,7 +2001,7 @@ void GcInfoDecoder::ReportRegisterToGC( #elif defined(TARGET_RISCV64) #if defined(TARGET_UNIX) && !defined(FEATURE_NATIVEAOT) -OBJECTREF* GcInfoDecoder::GetCapturedRegister( +template OBJECTREF* TGcInfoDecoder::GetCapturedRegister( int regNum, PREGDISPLAY pRD ) @@ -2019,7 +2017,7 @@ OBJECTREF* GcInfoDecoder::GetCapturedRegister( } #endif // TARGET_UNIX && !FEATURE_NATIVEAOT -OBJECTREF* GcInfoDecoder::GetRegisterSlot( +template OBJECTREF* TGcInfoDecoder::GetRegisterSlot( int regNum, PREGDISPLAY pRD ) @@ -2059,14 +2057,14 @@ OBJECTREF* GcInfoDecoder::GetRegisterSlot( #endif } -bool GcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) { _ASSERTE(regNum >= 0 && regNum <= 31); return (regNum >= 5 && regNum <= 7) || (regNum >= 10 and regNum <= 17) || regNum >= 28 || regNum == 1; } -bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) { #ifdef FIXED_STACK_PARAMETER_SCRATCH_AREA _ASSERTE( m_Flags & DECODE_GC_LIFETIMES ); @@ -2080,7 +2078,7 @@ bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, P #endif } -void GcInfoDecoder::ReportRegisterToGC( +template void TGcInfoDecoder::ReportRegisterToGC( int regNum, unsigned gcFlags, PREGDISPLAY pRD, @@ -2140,7 +2138,7 @@ void GcInfoDecoder::ReportRegisterToGC( #else // Unknown platform -OBJECTREF* GcInfoDecoder::GetRegisterSlot( +template OBJECTREF* TGcInfoDecoder::GetRegisterSlot( int regNum, PREGDISPLAY pRD ) @@ -2149,19 +2147,19 @@ OBJECTREF* GcInfoDecoder::GetRegisterSlot( return NULL; } -bool GcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchRegister(int regNum, PREGDISPLAY pRD) { PORTABILITY_ASSERT("GcInfoDecoder::IsScratchRegister"); return false; } -bool GcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) +template bool TGcInfoDecoder::IsScratchStackSlot(INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD) { _ASSERTE( !"NYI" ); return false; } -void GcInfoDecoder::ReportRegisterToGC( +template void TGcInfoDecoder::ReportRegisterToGC( int regNum, unsigned gcFlags, PREGDISPLAY pRD, @@ -2175,7 +2173,7 @@ void GcInfoDecoder::ReportRegisterToGC( #endif // Unknown platform -OBJECTREF* GcInfoDecoder::GetStackSlot( +template OBJECTREF* TGcInfoDecoder::GetStackSlot( INT32 spOffset, GcStackSlotBase spBase, PREGDISPLAY pRD @@ -2215,7 +2213,7 @@ OBJECTREF* GcInfoDecoder::GetStackSlot( } #ifdef DACCESS_COMPILE -int GcInfoDecoder::GetStackReg(int spBase) +template int TGcInfoDecoder::GetStackReg(int spBase) { #if defined(TARGET_AMD64) int esp = 4; @@ -2238,7 +2236,7 @@ int GcInfoDecoder::GetStackReg(int spBase) } #endif // DACCESS_COMPILE -void GcInfoDecoder::ReportStackSlotToGC( +template void TGcInfoDecoder::ReportStackSlotToGC( INT32 spOffset, GcStackSlotBase spBase, unsigned gcFlags, @@ -2273,6 +2271,7 @@ void GcInfoDecoder::ReportStackSlotToGC( pCallBack(hCallBack, pObjRef, gcFlags DAC_ARG(DacSlotLocation(GetStackReg(spBase), spOffset, true))); } +// Instantiate the decoder so other files can use it +template class TGcInfoDecoder; #endif // USE_GC_INFO_DECODER -