Back to Dotnet

Contract GCInfo

docs/design/datacontracts/GCInfo.md

11.0.10017.9 KB
Original Source

Contract GCInfo

This contract is for fetching information related to GCInfo associated with native code. Currently, this contract does not support x86 architecture.

APIs of contract

csharp
public interface IGCInfoHandle { }
csharp
// Decodes GCInfo using the platform-specific encoding for the target architecture
IGCInfoHandle DecodePlatformSpecificGCInfo(TargetPointer gcInfoAddress, uint gcVersion);

// Decodes GCInfo using the interpreter encoding, regardless of target architecture
IGCInfoHandle DecodeInterpreterGCInfo(TargetPointer gcInfoAddress, uint gcVersion);

/* Methods to query information from the GCInfo */

// Fetches length of code as reported in GCInfo
uint GetCodeLength(IGCInfoHandle handle);

Version 1

Data descriptors used:

Data Descriptor NameFieldMeaning
none

Contracts used:

Contract Name
none

Constants:

Constant NameMeaningValue
NO_GS_COOKIEIndicates no GS cookie is present-1
NO_STACK_BASE_REGISTERIndicates no stack base register is used0xFFFFFFFF
NO_SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREAIndicates no Edit and Continue preserved area0xFFFFFFFF
NO_GENERICS_INST_CONTEXTIndicates no generics instantiation context-1
NO_REVERSE_PINVOKE_FRAMEIndicates no reverse P/Invoke frame-1
NO_PSP_SYMIndicates no PSP symbol-1

Implementation

The GCInfo contract has platform specific implementations as GCInfo differs per architecture. With the exception of x86, all platforms have a common encoding scheme with different encoding lengths and normalization functions for data. x86 uses an entirely different scheme which is not currently supported by this contract.

GCInfo Format

The GCInfo format consists of a header structure and following data types. The header is either 'slim' for simple methods that can use the compact encoding scheme or a 'fat' header containing more details.

GCInfo Header

Slim Header
NameBitsMeaningCondition
IsSlimHeader1If 0, this GCInfo uses the slim header encoding
UsingStackBaseRegister1If true, has stack base register of normalized value 0. Otherwise this GCInfo has no stack base register. Controls GC_INFO_HAS_STACK_BASE_REGISTER of HeaderFlags
CodeLengthCODE_LENGTH_ENCBASENormalized method length
NumSafePointsNUM_SAFE_POINTS_ENCBASENumber of safe points/callsites#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED

All other values are assumed to be 0.

Fat Header

The fat header is used for methods that cannot be encoded using the compact slim header format. It contains additional flags and optional fields based on method characteristics.

NameBitsMeaningCondition
IsSlimHeader1If 1, this GCInfo uses the fat header encoding
HeaderFlagsGC_INFO_FLAGS_BIT_SIZE (10)Bitfield containing various method flags
CodeLengthCODE_LENGTH_ENCBASENormalized method length
PrologSizeNORM_PROLOG_SIZE_ENCBASENormalized prolog size - 1If HeaderFlags has GC_INFO_HAS_GS_COOKIE or HeaderFlags & GC_INFO_HAS_GENERICS_INST_CONTEXT_MASK != 0
EpilogSizeNORM_EPILOG_SIZE_ENCBASENormalized epilog sizeIf HeaderFlags has GC_INFO_HAS_GS_COOKIE
GSCookieStackSlotGS_COOKIE_STACK_SLOT_ENCBASENormalized stack slot for GS cookieIf HeaderFlags has GC_INFO_HAS_GS_COOKIE
GenericsInstContextStackSlotGENERICS_INST_CONTEXT_STACK_SLOT_ENCBASENormalized stack slot for generics contextHeaderFlags & GC_INFO_HAS_GENERICS_INST_CONTEXT_MASK != 0
StackBaseRegisterSTACK_BASE_REGISTER_ENCBASENormalized stack base register numberIf HeaderFlags has GC_INFO_HAS_STACK_BASE_REGISTER
SizeOfEditAndContinuePreservedAreaSIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASESize of EnC preserved areaIf HeaderFlags has GC_INFO_HAS_EDIT_AND_CONTINUE_INFO
SizeOfEditAndContinueFixedStackFrameSIZE_OF_EDIT_AND_CONTINUE_FIXED_STACK_FRAME_ENCBASESize of EnC fixed stack frameIf HeaderFlags has GC_INFO_HAS_EDIT_AND_CONTINUE_INFO and platform is ARM64
ReversePInvokeFrameSlotREVERSE_PINVOKE_FRAME_ENCBASENormalized reverse P/Invoke frame slotIf GC_INFO_REVERSE_PINVOKE_FRAME
SizeOfStackOutgoingAndScratchAreaSIZE_OF_STACK_AREA_ENCBASESize of stack parameter areaPlatform dependent
NumSafePointsNUM_SAFE_POINTS_ENCBASENumber of safe points/callsites#ifdef PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED
NumInterruptibleRangesNUM_INTERRUPTIBLE_RANGES_ENCBASENumber of interruptible ranges
Header Flags

The HeaderFlags field contains the following bit flags:

FlagBit PositionMeaning
GC_INFO_IS_VARARG0x1Method uses variable arguments
GC_INFO_HAS_SECURITY_OBJECT0x2Method has security object (deprecated)
GC_INFO_HAS_GS_COOKIE0x4Method has GS cookie for stack protection
GC_INFO_HAS_PSP_SYM0x8Method has PSP symbol (deprecated)
GC_INFO_HAS_GENERICS_INST_CONTEXT_MASK0x30Mask for generics instantiation context type
GC_INFO_HAS_STACK_BASE_REGISTER0x40Method uses a stack base register
GC_INFO_WANTS_REPORT_ONLY_LEAF0x80AMD64: Report only leaf frames; ARM/ARM64: Has tail calls
GC_INFO_HAS_EDIT_AND_CONTINUE_INFO0x100Method has Edit and Continue information
GC_INFO_REVERSE_PINVOKE_FRAME0x200Method has reverse P/Invoke frame

GCInfo Body

Following the header, the GCInfo body contains several data sections in the following order:

  1. Call Sites Offsets - Encoded offsets of call sites/safe points (if PARTIALLY_INTERRUPTIBLE_GC_SUPPORTED)
  2. Interruptible Ranges - Ranges where the method can be interrupted for GC
  3. Slot Table - Information about GC-tracked slots (registers and stack locations)

The rest of the GCInfo body is not yet decoded in the cDAC.

Interruptible Ranges

Interruptible ranges define code regions where garbage collection can safely occur. Each range is encoded as:

  • StartOffset - Normalized code offset where the range begins
  • Length - Normalized length of the interruptible region

The ranges are encoded using delta compression, where each range's start offset is relative to the previous range's end offset.

Slot Table

The slot table describes all GC-tracked locations (registers and stack slots) used by the method. It consists of three sections:

  1. Register Slots - GC-tracked CPU registers
  2. Stack Slots - GC-tracked stack locations
  3. Untracked Slots - Stack locations that are not GC-tracked

Each slot entry contains:

  • Location - Register number or stack offset
  • Flags - GC slot type (base pointer, interior pointer, pinned, untracked)
  • Base - For stack slots: caller SP relative, SP relative, or frame register relative

Slots use delta encoding where consecutive entries encode only the difference from the previous entry when flags match.

Platform specific constants

AMD64

Encoding BaseValuePurpose
GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE6Base bits for generics instantiation context stack slot
GS_COOKIE_STACK_SLOT_ENCBASE6Base bits for GS cookie stack slot
CODE_LENGTH_ENCBASE8Base bits for encoding method code length
STACK_BASE_REGISTER_ENCBASE3Base bits for stack base register number
SIZE_OF_STACK_AREA_ENCBASE3Base bits for stack parameter area size
SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE4Base bits for Edit and Continue preserved area size
REVERSE_PINVOKE_FRAME_ENCBASE6Base bits for reverse P/Invoke frame slot
NUM_REGISTERS_ENCBASE2Base bits for number of register slots
NUM_STACK_SLOTS_ENCBASE2Base bits for number of stack slots
NUM_UNTRACKED_SLOTS_ENCBASE1Base bits for number of untracked slots
NORM_PROLOG_SIZE_ENCBASE5Base bits for normalized prolog size
NORM_EPILOG_SIZE_ENCBASE3Base bits for normalized epilog size
INTERRUPTIBLE_RANGE_DELTA1_ENCBASE6Base bits for first interruptible range delta
INTERRUPTIBLE_RANGE_DELTA2_ENCBASE6Base bits for second interruptible range delta
REGISTER_ENCBASE3Base bits for register slot encoding
REGISTER_DELTA_ENCBASE2Base bits for register slot delta encoding
STACK_SLOT_ENCBASE6Base bits for stack slot encoding
STACK_SLOT_DELTA_ENCBASE4Base bits for stack slot delta encoding
NUM_SAFE_POINTS_ENCBASE2Base bits for number of safe points
NUM_INTERRUPTIBLE_RANGES_ENCBASE1Base bits for number of interruptible ranges
AMD64 Normalization/Denormalization Rules
OperationNormalization (Encode)Denormalization (Decode)
Stack Base Registerreg ^ 0x5reg ^ 0x5
Code LengthNo changeNo change
Code OffsetNo changeNo change
Stack Slotoffset >> 3offset << 3
Stack Area Sizesize >> 3size << 3

ARM64

Encoding BaseValuePurpose
GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE6Base bits for generics instantiation context stack slot
GS_COOKIE_STACK_SLOT_ENCBASE6Base bits for GS cookie stack slot
CODE_LENGTH_ENCBASE8Base bits for encoding method code length
STACK_BASE_REGISTER_ENCBASE2Base bits for stack base register number
SIZE_OF_STACK_AREA_ENCBASE3Base bits for stack parameter area size
SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE4Base bits for Edit and Continue preserved area size
SIZE_OF_EDIT_AND_CONTINUE_FIXED_STACK_FRAME_ENCBASE4Base bits for Edit and Continue fixed stack frame size (ARM64 only)
REVERSE_PINVOKE_FRAME_ENCBASE6Base bits for reverse P/Invoke frame slot
NUM_REGISTERS_ENCBASE3Base bits for number of register slots
NUM_STACK_SLOTS_ENCBASE2Base bits for number of stack slots
NUM_UNTRACKED_SLOTS_ENCBASE1Base bits for number of untracked slots
NORM_PROLOG_SIZE_ENCBASE5Base bits for normalized prolog size
NORM_EPILOG_SIZE_ENCBASE3Base bits for normalized epilog size
INTERRUPTIBLE_RANGE_DELTA1_ENCBASE6Base bits for first interruptible range delta
INTERRUPTIBLE_RANGE_DELTA2_ENCBASE6Base bits for second interruptible range delta
REGISTER_ENCBASE3Base bits for register slot encoding
REGISTER_DELTA_ENCBASE2Base bits for register slot delta encoding
STACK_SLOT_ENCBASE6Base bits for stack slot encoding
STACK_SLOT_DELTA_ENCBASE4Base bits for stack slot delta encoding
NUM_SAFE_POINTS_ENCBASE3Base bits for number of safe points
NUM_INTERRUPTIBLE_RANGES_ENCBASE1Base bits for number of interruptible ranges
ARM64 Normalization/Denormalization Rules
OperationNormalization (Encode)Denormalization (Decode)
Stack Base Registerreg ^ 0x29reg ^ 0x29
Code Lengthlength >> 2length << 2
Code Offsetoffset >> 2offset << 2
Stack Slotoffset >> 3offset << 3
Stack Area Sizesize >> 3size << 3

ARM (32-bit)

Encoding BaseValuePurpose
GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE5Base bits for generics instantiation context stack slot
GS_COOKIE_STACK_SLOT_ENCBASE5Base bits for GS cookie stack slot
CODE_LENGTH_ENCBASE7Base bits for encoding method code length
STACK_BASE_REGISTER_ENCBASE1Base bits for stack base register number
SIZE_OF_STACK_AREA_ENCBASE3Base bits for stack parameter area size
SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE3Base bits for Edit and Continue preserved area size
REVERSE_PINVOKE_FRAME_ENCBASE5Base bits for reverse P/Invoke frame slot
NUM_REGISTERS_ENCBASE2Base bits for number of register slots
NUM_STACK_SLOTS_ENCBASE3Base bits for number of stack slots
NUM_UNTRACKED_SLOTS_ENCBASE3Base bits for number of untracked slots
NORM_PROLOG_SIZE_ENCBASE5Base bits for normalized prolog size
NORM_EPILOG_SIZE_ENCBASE3Base bits for normalized epilog size
INTERRUPTIBLE_RANGE_DELTA1_ENCBASE4Base bits for first interruptible range delta
INTERRUPTIBLE_RANGE_DELTA2_ENCBASE6Base bits for second interruptible range delta
REGISTER_ENCBASE2Base bits for register slot encoding
REGISTER_DELTA_ENCBASE1Base bits for register slot delta encoding
STACK_SLOT_ENCBASE6Base bits for stack slot encoding
STACK_SLOT_DELTA_ENCBASE4Base bits for stack slot delta encoding
NUM_SAFE_POINTS_ENCBASE3Base bits for number of safe points
NUM_INTERRUPTIBLE_RANGES_ENCBASE2Base bits for number of interruptible ranges
ARM (32-bit) Normalization/Denormalization Rules
OperationNormalization (Encode)Denormalization (Decode)
Stack Base Register((reg - 4) & 7) ^ 7(reg ^ 7) + 4
Code Lengthlength >> 1length << 1
Code Offsetoffset >> 1offset << 1
Stack Slotoffset >> 2offset << 2
Stack Area Sizesize >> 2size << 2

Interpreter (WASM / FEATURE_INTERPRETER)

The interpreter uses a platform-independent encoding where all normalization and denormalization functions are identity (no transformation). This encoding is used for WASM targets (where TargetGcInfoEncoding is InterpreterGcInfoEncoding) and on any architecture when FEATURE_INTERPRETER is enabled.

Encoding BaseValuePurpose
GENERICS_INST_CONTEXT_STACK_SLOT_ENCBASE6Base bits for generics instantiation context stack slot
GS_COOKIE_STACK_SLOT_ENCBASE6Base bits for GS cookie stack slot
CODE_LENGTH_ENCBASE8Base bits for encoding method code length
STACK_BASE_REGISTER_ENCBASE3Base bits for stack base register number
SIZE_OF_STACK_AREA_ENCBASE3Base bits for stack parameter area size
SIZE_OF_EDIT_AND_CONTINUE_PRESERVED_AREA_ENCBASE4Base bits for Edit and Continue preserved area size
REVERSE_PINVOKE_FRAME_ENCBASE6Base bits for reverse P/Invoke frame slot
NUM_REGISTERS_ENCBASE2Base bits for number of register slots
NUM_STACK_SLOTS_ENCBASE2Base bits for number of stack slots
NUM_UNTRACKED_SLOTS_ENCBASE1Base bits for number of untracked slots
NORM_PROLOG_SIZE_ENCBASE5Base bits for normalized prolog size
NORM_EPILOG_SIZE_ENCBASE3Base bits for normalized epilog size
INTERRUPTIBLE_RANGE_DELTA1_ENCBASE6Base bits for first interruptible range delta
INTERRUPTIBLE_RANGE_DELTA2_ENCBASE6Base bits for second interruptible range delta
REGISTER_ENCBASE3Base bits for register slot encoding
REGISTER_DELTA_ENCBASE2Base bits for register slot delta encoding
STACK_SLOT_ENCBASE6Base bits for stack slot encoding
STACK_SLOT_DELTA_ENCBASE4Base bits for stack slot delta encoding
NUM_SAFE_POINTS_ENCBASE2Base bits for number of safe points
NUM_INTERRUPTIBLE_RANGES_ENCBASE1Base bits for number of interruptible ranges
Interpreter Normalization/Denormalization Rules

All normalization and denormalization operations are identity functions (no transformation):

OperationNormalization (Encode)Denormalization (Decode)
Stack Base RegisterNo changeNo change
Code LengthNo changeNo change
Code OffsetNo changeNo change
Stack SlotNo changeNo change
Stack Area SizeNo changeNo change

The interpreter does not have a fixed stack parameter scratch area (HAS_FIXED_STACK_PARAMETER_SCRATCH_AREA = false).

Encoding Scheme

GCInfo uses a variable-length encoding scheme to efficiently store numeric values. The encoding is designed to use fewer bits for smaller, more common values.

Variable Length Unsigned Encoding

Numbers are encoded using a base number of bits plus extension bits when needed:

  1. Base Encoding: Use base bits to store the value
  2. Extension Bit: If the value doesn't fit in base bits, set bit base to 1 and use base+1 additional bits
  3. Continuation: This process continues until the value fits

The minimum encoding uses base+1 bits, where bit base indicates if more bits follow.

Example with base=3:

  • Value 0-6: Encoded in 4 bits as 0XXX (where XXX is the 3-bit value)
  • Value 7-14: Encoded in 8 bits as 1XXX YYYY (where XXX are the low 3 bits, YYYY are the next 4 bits)
  • Value 15+: Uses additional extension groups

Variable Length Signed Encoding

Signed values use the same encoding as unsigned, but with sign considerations:

  • A number fits in base bits if the topmost bit of the base-bit chunk matches the sign of the entire number
  • This ensures proper sign extension when decoding

Implementation

The GCInfo contract implementation follows this process:

csharp
IGCInfoHandle DecodePlatformSpecificGCInfo(TargetPointer gcInfoAddress, uint gcVersion)
{
    // Create a new decoder instance for the specified platform traits
    return new GcInfoDecoder<PlatformTraits>(target, gcInfoAddress, gcVersion);
}

IGCInfoHandle DecodeInterpreterGCInfo(TargetPointer gcInfoAddress, uint gcVersion)
{
    // Create a new decoder instance using the interpreter encoding
    return new GcInfoDecoder<InterpreterGCInfoTraits>(target, gcInfoAddress, gcVersion);
}

uint GetCodeLength(IGCInfoHandle handle)
{
    // Cast to the appropriate decoder type and return the decoded code length
    GcInfoDecoder<PlatformTraits> decoder = (GcInfoDecoder<PlatformTraits>)handle;
    return decoder.GetCodeLength();
}

The decoder reads and parses the GCInfo data structure sequentially, using the platform-specific encoding bases and normalization rules to reconstruct the original method metadata.