Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[cdac] Implement ExecutionManager.ReadyToRunJitManager.GetMethodInfo (minus handling of hot/cold lookup) #109766

Merged
merged 21 commits into from
Nov 15, 2024
Merged
Show file tree
Hide file tree
Changes from 19 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
d33dae7
Move CodePointerFromAddress to shared helper
elinor-fung Nov 7, 2024
5f9d138
Add ReadyToRunInfo to data descriptor
elinor-fung Nov 7, 2024
b560944
ReadyToRunJitManager: check if address is in a thunk for READYTORUN_H…
elinor-fung Nov 7, 2024
f9fb15a
ReadyToRunJitManager: find runtime function entry corresponding to ad…
elinor-fung Nov 7, 2024
e736087
Add HashMap to data descriptor
elinor-fung Nov 7, 2024
512f7c2
ReadyToRunJitManager: look up method desc for entry point, add HashMa…
elinor-fung Nov 7, 2024
3f4793d
ReadyToRunJitManager: return CodeBlock, update CodeBlock to take/stor…
elinor-fung Nov 7, 2024
db938d7
Pass map address to HashMapLookup instead of processed data, handle s…
elinor-fung Nov 11, 2024
435e42c
Allow explicitly specifying field size for test helper to layout fiel…
elinor-fung Nov 12, 2024
56418c4
Start using Moq
elinor-fung Nov 12, 2024
a7066d2
Add test for ExecutionManager.GetMethodDesc for R2R
elinor-fung Nov 12, 2024
d2d22c1
Fix merge
elinor-fung Nov 12, 2024
97d4eb4
Fix returned value when not found in hash map
elinor-fung Nov 12, 2024
7112857
Tests for no match and multiple runtime functions
elinor-fung Nov 12, 2024
12d1fb6
Add HashMap tests
elinor-fung Nov 12, 2024
0321eaf
Update ExecutionManager.md
elinor-fung Nov 12, 2024
447ce76
Make TestPlaceholderTarget constructor take a reader delegate and alw…
elinor-fung Nov 13, 2024
a68371d
Clean up ExecutionManagerTestBuilder
elinor-fung Nov 13, 2024
6377e17
Remove unused and incorrect field in data descriptor
elinor-fung Nov 13, 2024
6f81060
Fix handling of code pointer / address conversion
elinor-fung Nov 14, 2024
6d00a3c
Update src/coreclr/vm/readytoruninfo.h
elinor-fung Nov 14, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
150 changes: 112 additions & 38 deletions docs/design/datacontracts/ExecutionManager.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,30 +28,57 @@ struct CodeBlockHandle
## Version 1

The execution manager uses two data structures to map the entire target address space to native executable code.
The range section map is used to partition the address space into large chunks which point to range section fragments. Each chunk is relatively large. If there is any executable code in the chunk, the chunk will contain one or more range section fragments that cover subsets of the chunk. Conversely if a massive method is JITed a single range section fragment may span multiple adjacent chunks.
The [range section map](#rangesectionmap) is used to partition the address space into large chunks which point to range section fragments. Each chunk is relatively large. If there is any executable code in the chunk, the chunk will contain one or more range section fragments that cover subsets of the chunk. Conversely if a massive method is JITed a single range section fragment may span multiple adjacent chunks.

Within a range section fragment, a nibble map structure is used to map arbitrary IP addresses back to the start of the method (and to the code header which immediately preceeeds the entrypoint to the code).
Within a range section fragment, a [nibble map](#nibblemap) structure is used to map arbitrary IP addresses back to the start of the method (and to the code header which immediately preceeeds the entrypoint to the code).

Data descriptors used:
| Data Descriptor Name | Field | Meaning |
| --- | --- | --- |
| RangeSectionMap | TopLevelData | pointer to the outermost RangeSection |
| RangeSectionFragment| ? | ? |
| RangeSection | ? | ? |
| RealCodeHeader | ? | ? |
| HeapList | ? | ? |


| `RangeSectionMap` | `TopLevelData` | Pointer to the outermost RangeSection |
| `RangeSectionFragment`| `RangeBegin` | Begin address of the fragment |
| `RangeSectionFragment`| `RangeEndOpen` | End address of the fragment |
| `RangeSectionFragment`| `RangeSection` | Pointer to the corresponding `RangeSection` |
| `RangeSectionFragment`| `Next` | Pointer to the next fragment |
| `RangeSection` | `RangeBegin` | Begin address of the range section |
| `RangeSection` | `RangeEndOpen` | End address of the range section |
| `RangeSection` | `NextForDelete` | Pointer to next range section for deletion |
| `RangeSection` | `JitManager` | Pointer to the JIT manager |
| `RangeSection` | `Flags` | Flags for the range section |
| `RangeSection` | `HeapList` | Pointer to the heap list |
| `RangeSection` | `R2RModule` | ReadyToRun module |
| `CodeHeapListNode` | `Next` | Next node |
| `CodeHeapListNode` | `StartAddress` | Start address of the used portion of the code heap |
| `CodeHeapListNode` | `EndAddress` | End address of the used portion of the code heap |
| `CodeHeapListNode` | `MapBase` | Start of the map - start address rounded down based on OS page size |
| `CodeHeapListNode` | `HeaderMap` | Bit array used to find the start of methods - relative to `MapBase` |
| `RealCodeHeader` | `MethodDesc` | Pointer to the corresponding `MethodDesc` |
| `Module` | `ReadyToRunInfo` | Pointer to the `ReadyToRunInfo` for the module |
| `ReadyToRunInfo` | `CompositeInfo` | Pointer to composite R2R info - or itself for non-composite |
| `ReadyToRunInfo` | `NumRuntimeFunctions` | Number of `RuntimeFunctions` |
| `ReadyToRunInfo` | `RuntimeFunctions` | Pointer to an array of `RuntimeFunctions` |
| `ReadyToRunInfo` | `DelayLoadMethodCallThunks` | Pointer to an `ImageDataDirectory` for the delay load method call thunks |
| `ReadyToRunInfo` | `EntryPointToMethodDescMap` | `HashMap` of entry point addresses to `MethodDesc` pointers |
| `ImageDataDirectory` | `VirtualAddress` | Virtual address of the image data directory |
| `ImageDataDirectory` | `Size` | Size of the data |
| `RuntimeFunction` | `BeginAddress` | Begin address of the function |
| `HashMap` | `Buckets` | Pointer to the buckets of a `HashMap` |
| `Bucket` | `Keys` | Array of keys of `HashMapSlotsPerBucket` length |
| `Bucket` | `Values` | Array of values of `HashMapSlotsPerBucket` length |

Global variables used:
| Global Name | Type | Purpose |
| --- | --- | --- |
| ExecutionManagerCodeRangeMapAddress | TargetPointer | Pointer to the global RangeSectionMap
| StubCodeBlockLast | uint8 | Maximum sentinel code header value indentifying a stub code block
| `ExecutionManagerCodeRangeMapAddress` | TargetPointer | Pointer to the global RangeSectionMap |
| `StubCodeBlockLast` | uint8 | Maximum sentinel code header value indentifying a stub code block |
| `HashMapSlotsPerBucket` | uint32 | Number of slots in each bucket of a `HashMap` |
| `HashMapValueMask` | uint64 | Bitmask used when storing values in a `HashMap` |
| `FeatureEHFunclets` | uint8 | 1 if EH funclets are enabled, 0 otherwise |

Contracts used:
| Contract Name |
| --- |
| `PlatformMetadata` |

The bulk of the work is done by the `GetCodeBlockHandle` API that maps a code pointer to information about the containing jitted method.

Expand Down Expand Up @@ -97,46 +124,93 @@ There are two `JitManager`s: the "EE JitManager" for jitted code and "R2R JitMan
The EE JitManager `GetMethodInfo` implements the nibble map lookup, summarized below, followed by returning the `RealCodeHeader` data:

```csharp
bool GetMethodInfo(RangeSection rangeSection, TargetCodePointer jittedCodeAddress, [NotNullWhen(true)] out CodeBlock? info)
bool GetMethodInfo(RangeSection rangeSection, TargetCodePointer jittedCodeAddress, [NotNullWhen(true)] out CodeBlock? info)
{
TargetPointer start = FindMethodCode(rangeSection, jittedCodeAddress); // nibble map lookup
if (start == TargetPointer.Null)
{
TargetPointer start = FindMethodCode(rangeSection, jittedCodeAddress); // nibble map lookup
if (start == TargetPointer.Null)
{
return false;
}
TargetNUInt relativeOffset = jittedCodeAddress - start;
int codeHeaderOffset = Target.PointerSize;
TargetPointer codeHeaderIndirect = start - codeHeaderOffset;
if (RangeSection.IsStubCodeBlock(Target, codeHeaderIndirect))
{
return false;
}
TargetPointer codeHeaderAddress = Target.ReadPointer(codeHeaderIndirect);
Data.RealCodeHeader realCodeHeader = Target.ProcessedData.GetOrAdd<Data.RealCodeHeader>(codeHeaderAddress);
info = new CodeBlock(jittedCodeAddress, codeHeaderOffset, relativeOffset, realCodeHeader, rangeSection.Data!.JitManager);
return true;
return false;
}
TargetNUInt relativeOffset = jittedCodeAddress - start;
int codeHeaderOffset = Target.PointerSize;
TargetPointer codeHeaderIndirect = start - codeHeaderOffset;
if (RangeSection.IsStubCodeBlock(Target, codeHeaderIndirect))
{
return false;
}
TargetPointer codeHeaderAddress = Target.ReadPointer(codeHeaderIndirect);
Data.RealCodeHeader realCodeHeader = Target.ProcessedData.GetOrAdd<Data.RealCodeHeader>(codeHeaderAddress);
info = new CodeBlock(jittedCodeAddress, realCodeHeader.MethodDesc, relativeOffset, rangeSection.Data!.JitManager);
return true;
}
```

The R2R JitManager `GetMethodInfo` finds the runtime function corresponding to an address and maps its entry point pack to a method:

```csharp
bool GetMethodInfo(RangeSection rangeSection, TargetCodePointer jittedCodeAddress, [NotNullWhen(true)] out CodeBlock? info)
{
if (rangeSection.Data == null)
throw new ArgumentException(nameof(rangeSection));

info = default;

TargetPointer r2rModule = Target.ReadPointer(/* range section address + RangeSection::R2RModule offset */);
TargetPointer r2rInfo = Target.ReadPointer(r2rModule + /* Module::ReadyToRunInfo offset */);

// Check if address is in a thunk
if (IsStubCodeBlockThunk(rangeSection.Data, r2rInfo, jittedCodeAddress))
return false;

// Find the relative address that we are looking for
TargetCodePointer code = /* code pointer from jittedCodeAddress using PlatformMetadata.GetCodePointerFlags */
TargetPointer imageBase = Target.ReadPointer(/* range section address + RangeSection::RangeBegin offset */);
TargetPointer relativeAddr = code - imageBase;

TargetPointer runtimeFunctions = Target.ReadPointer(r2rInfo + /* ReadyToRunInfo::RuntimeFunctions offset */);
int index = // Iterate through runtimeFunctions and find index of function with relativeAddress
if (index < 0)
return false;

bool featureEHFunclets = Target.ReadGlobal<byte>(Constants.Globals.FeatureEHFunclets) != 0;
if (featureEHFunclets)
{
// TODO: [cdac] Look up in hot/cold mapping lookup table and if the method is in the cold block,
// get the index of the associated hot block.
}

TargetPointer function = runtimeFunctions + (ulong)(index * /* size of RuntimeFunction */);

TargetPointer startAddress = imageBase + Target.Read<uint>(function + /* RuntimeFunction::BeginAddress offset */);
TargetPointer entryPoint = /* code pointer from startAddress using PlatformMetadata.GetCodePointerFlags */

TargetPointer mapAddress = r2rInfo + /* ReadyToRunInfo::EntryPointToMethodDescMap offset */;
TargetPointer methodDesc = /* look up entryPoint in HashMap at mapAddress */;

// TODO: [cdac] Handle method with cold code when computing relative offset
TargetNUInt relativeOffset = new TargetNUInt(code - startAddress);

info = new CodeBlock(startAddress.Value, methodDesc, relativeOffset, rangeSection.Data!.JitManager);
return true;
}
```

The `CodeBlock` encapsulates the `RealCodeHeader` data from the target runtime together with the start of the jitted method
The `CodeBlock` encapsulates the `MethodDesc` data from the target runtime together with the start of the jitted method

```csharp
class CodeBlock
{
private readonly int _codeHeaderOffset;

public TargetCodePointer StartAddress { get; }
// note: this is the address of the pointer to the "real code header", you need to
// dereference it to get the address of _codeHeaderData
public TargetPointer CodeHeaderAddress => StartAddress - _codeHeaderOffset;
private Data.RealCodeHeader _codeHeaderData;
public TargetPointer MethodDesc { get; }
public TargetPointer JitManagerAddress { get; }
public TargetNUInt RelativeOffset { get; }
public CodeBlock(TargetCodePointer startAddress, int codeHeaderOffset, TargetNUInt relativeOffset, Data.RealCodeHeader codeHeaderData, TargetPointer jitManagerAddress)

public CodeBlock(TargetCodePointer startAddress, TargetPointer methodDesc, TargetNUInt relativeOffset, TargetPointer jitManagerAddress)
{
_codeHeaderOffset = codeHeaderOffset;
StartAddress = startAddress;
_codeHeaderData = codeHeaderData;
MethodDesc = methodDesc;
RelativeOffset = relativeOffset;
JitManagerAddress = jitManagerAddress;
}
Expand All @@ -151,13 +225,13 @@ The remaining contract APIs extract fields of the `CodeBlock`:
```csharp
TargetPointer IExecutionManager.GetMethodDesc(CodeBlockHandle codeInfoHandle)
{
/* find EECodeBlock info for codeInfoHandle.Address*/
/* find CodeBlock info for codeInfoHandle.Address*/
return info.MethodDescAddress;
}

TargetCodePointer IExecutionManager.GetStartAddress(CodeBlockHandle codeInfoHandle)
{
/* find EECodeBlock info for codeInfoHandle.Address*/
/* find CodeBlock info for codeInfoHandle.Address*/
return info.StartAddress;
}
```
Expand Down
34 changes: 34 additions & 0 deletions src/coreclr/debug/runtimeinfo/datadescriptor.h
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,7 @@ CDAC_TYPE_FIELD(Module, /*pointer*/, ThunkHeap, cdac_data<Module>::ThunkHeap)
CDAC_TYPE_FIELD(Module, /*pointer*/, DynamicMetadata, cdac_data<Module>::DynamicMetadata)
CDAC_TYPE_FIELD(Module, /*pointer*/, Path, cdac_data<Module>::Path)
CDAC_TYPE_FIELD(Module, /*pointer*/, FileName, cdac_data<Module>::FileName)
CDAC_TYPE_FIELD(Module, /*pointer*/, ReadyToRunInfo, cdac_data<Module>::ReadyToRunInfo)

CDAC_TYPE_FIELD(Module, /*pointer*/, FieldDefToDescMap, cdac_data<Module>::FieldDefToDescMap)
CDAC_TYPE_FIELD(Module, /*pointer*/, ManifestModuleReferencesMap, cdac_data<Module>::ManifestModuleReferencesMap)
Expand Down Expand Up @@ -412,6 +413,37 @@ CDAC_TYPE_INDETERMINATE(FixupPrecodeData)
CDAC_TYPE_FIELD(FixupPrecodeData, /*pointer*/, MethodDesc, offsetof(FixupPrecodeData, MethodDesc))
CDAC_TYPE_END(FixupPrecodeData)

CDAC_TYPE_BEGIN(ReadyToRunInfo)
CDAC_TYPE_INDETERMINATE(ReadyToRunInfo)
CDAC_TYPE_FIELD(ReadyToRunInfo, /*pointer*/, CompositeInfo, cdac_data<ReadyToRunInfo>::CompositeInfo)
CDAC_TYPE_FIELD(ReadyToRunInfo, /*uint32*/, NumRuntimeFunctions, cdac_data<ReadyToRunInfo>::NumRuntimeFunctions)
CDAC_TYPE_FIELD(ReadyToRunInfo, /*pointer*/, RuntimeFunctions, cdac_data<ReadyToRunInfo>::RuntimeFunctions)
CDAC_TYPE_FIELD(ReadyToRunInfo, /*pointer*/, DelayLoadMethodCallThunks, cdac_data<ReadyToRunInfo>::DelayLoadMethodCallThunks)
CDAC_TYPE_FIELD(ReadyToRunInfo, /*HashMap*/, EntryPointToMethodDescMap, cdac_data<ReadyToRunInfo>::EntryPointToMethodDescMap)
CDAC_TYPE_END(ReadyToRunInfo)

CDAC_TYPE_BEGIN(ImageDataDirectory)
CDAC_TYPE_SIZE(sizeof(IMAGE_DATA_DIRECTORY))
CDAC_TYPE_FIELD(ImageDataDirectory, /*uint32*/, VirtualAddress, offsetof(IMAGE_DATA_DIRECTORY, VirtualAddress))
CDAC_TYPE_FIELD(ImageDataDirectory, /*uint32*/, Size, offsetof(IMAGE_DATA_DIRECTORY, Size))
CDAC_TYPE_END(ImageDataDirectory)

CDAC_TYPE_BEGIN(RuntimeFunction)
CDAC_TYPE_SIZE(sizeof(RUNTIME_FUNCTION))
CDAC_TYPE_FIELD(RuntimeFunction, /*uint32*/, BeginAddress, offsetof(RUNTIME_FUNCTION, BeginAddress))
CDAC_TYPE_END(RuntimeFunction)

CDAC_TYPE_BEGIN(HashMap)
CDAC_TYPE_INDETERMINATE(HashMap)
CDAC_TYPE_FIELD(HashMap, /*pointer*/, Buckets, cdac_data<HashMap>::Buckets)
CDAC_TYPE_END(HashMap)

CDAC_TYPE_BEGIN(Bucket)
CDAC_TYPE_SIZE(sizeof(Bucket))
CDAC_TYPE_FIELD(Bucket, /*pointer*/, Keys, offsetof(Bucket, m_rgKeys))
CDAC_TYPE_FIELD(Bucket, /*pointer*/, Values, offsetof(Bucket, m_rgValues))
CDAC_TYPE_END(Bucket)

CDAC_TYPE_BEGIN(RangeSectionMap)
CDAC_TYPE_INDETERMINATE(RangeSectionMap)
CDAC_TYPE_FIELD(RangeSectionMap, /*pointer*/, TopLevelData, cdac_data<RangeSectionMap>::TopLevelData)
Expand Down Expand Up @@ -501,6 +533,8 @@ CDAC_GLOBAL(ObjectToMethodTableUnmask, uint8, 1 | 1 << 1)
#endif //TARGET_64BIT
CDAC_GLOBAL(SOSBreakingChangeVersion, uint8, SOS_BREAKING_CHANGE_VERSION)
CDAC_GLOBAL(DirectorySeparator, uint8, (uint8_t)DIRECTORY_SEPARATOR_CHAR_A)
CDAC_GLOBAL(HashMapSlotsPerBucket, uint32, SLOTS_PER_BUCKET)
CDAC_GLOBAL(HashMapValueMask, uint64, VALUE_MASK)
CDAC_GLOBAL(MethodDescAlignment, uint64, MethodDesc::ALIGNMENT)
CDAC_GLOBAL(ObjectHeaderSize, uint64, OBJHEADER_SIZE)
CDAC_GLOBAL(SyncBlockValueToObjectOffset, uint16, OBJHEADER_SIZE - cdac_data<ObjHeader>::SyncBlockValue)
Expand Down
1 change: 1 addition & 0 deletions src/coreclr/vm/ceeload.h
Original file line number Diff line number Diff line change
Expand Up @@ -1649,6 +1649,7 @@ struct cdac_data<Module>
static constexpr size_t DynamicMetadata = offsetof(Module, m_pDynamicMetadata);
static constexpr size_t Path = offsetof(Module, m_path);
static constexpr size_t FileName = offsetof(Module, m_fileName);
static constexpr size_t ReadyToRunInfo = offsetof(Module, m_pReadyToRunInfo);

// Lookup map pointers
static constexpr size_t FieldDefToDescMap = offsetof(Module, m_FieldDefToDescMap);
Expand Down
2 changes: 0 additions & 2 deletions src/coreclr/vm/codeman.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5888,8 +5888,6 @@ BOOL ReadyToRunJitManager::JitCodeToMethodInfo(RangeSection * pRangeSection,
// Save the raw entry
PTR_RUNTIME_FUNCTION RawFunctionEntry = pRuntimeFunctions + MethodIndex;

ULONG UMethodIndex = (ULONG)MethodIndex;

const int lookupIndex = HotColdMappingLookupTable::LookupMappingForMethod(pInfo, (ULONG)MethodIndex);
if ((lookupIndex != -1) && ((lookupIndex & 1) == 1))
{
Expand Down
7 changes: 2 additions & 5 deletions src/coreclr/vm/codeman.h
Original file line number Diff line number Diff line change
Expand Up @@ -23,10 +23,9 @@ Module Name:
An IJitManager knows about which method bodies live in each RangeSection.
It can handle methods of one given CodeType. It can map a method body to
a MethodDesc. It knows where the GCInfo about the method lives.
Today, we have three IJitManagers viz.
Today, we have two IJitManagers:
1. EEJitManager for JITcompiled code generated by clrjit.dll
2. NativeImageJitManager for ngenned code.
3. ReadyToRunJitManager for version resiliant ReadyToRun code
2. ReadyToRunJitManager for version resiliant ReadyToRun code

An ICodeManager knows how to crack a specific format of GCInfo. There is
a default format (handled by ExecutionManager::GetDefaultCodeManager())
Expand Down Expand Up @@ -73,7 +72,6 @@ class MethodDesc;
class ICorJitCompiler;
class IJitManager;
class EEJitManager;
class NativeImageJitManager;
class ReadyToRunJitManager;
class ExecutionManager;
class Thread;
Expand Down Expand Up @@ -1657,7 +1655,6 @@ class HostCodeHeap;
typedef VPTR(class HostCodeHeap) PTR_HostCodeHeap;

typedef VPTR(class EEJitManager) PTR_EEJitManager;
typedef VPTR(class NativeImageJitManager) PTR_NativeImageJitManager;
typedef VPTR(class ReadyToRunJitManager) PTR_ReadyToRunJitManager;

struct JumpStubBlockHeader
Expand Down
2 changes: 0 additions & 2 deletions src/coreclr/vm/hash.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,6 @@ const DWORD g_rgPrimes[] = {
};
const SIZE_T g_rgNumPrimes = sizeof(g_rgPrimes) / sizeof(*g_rgPrimes);

const unsigned int SLOTS_PER_BUCKET = 4;

#ifndef DACCESS_COMPILE

void *PtrHashMap::operator new(size_t size, LoaderHeap *pHeap)
Expand Down
14 changes: 12 additions & 2 deletions src/coreclr/vm/hash.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ typedef ULONG_PTR UPTR;
class Bucket;
class HashMap;

const unsigned int SLOTS_PER_BUCKET = 4;

//-------------------------------------------------------
// class Bucket
// used by hash table implementation
Expand All @@ -54,8 +56,8 @@ typedef DPTR(class Bucket) PTR_Bucket;
class Bucket
{
public:
UPTR m_rgKeys[4];
UPTR m_rgValues[4];
UPTR m_rgKeys[SLOTS_PER_BUCKET];
UPTR m_rgValues[SLOTS_PER_BUCKET];

#define VALUE_MASK (sizeof(LPVOID) == 4 ? 0x7FFFFFFF : I64(0x7FFFFFFFFFFFFFFF))

Expand Down Expand Up @@ -532,6 +534,14 @@ class HashMap

return m_cbInserts-m_cbDeletes;
}

friend struct ::cdac_data<HashMap>;
};

template<>
struct cdac_data<HashMap>
{
static constexpr size_t Buckets = offsetof(HashMap, m_rgBuckets);
};

//---------------------------------------------------------------------------------------
Expand Down
18 changes: 15 additions & 3 deletions src/coreclr/vm/readytoruninfo.h
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class ReadyToRunCoreInfo
PTR_PEImageLayout m_pLayout;
PTR_READYTORUN_CORE_HEADER m_pCoreHeader;
Volatile<bool> m_fForbidLoadILBodyFixups;

public:
ReadyToRunCoreInfo();
ReadyToRunCoreInfo(PEImageLayout * pLayout, READYTORUN_CORE_HEADER * pCoreHeader);
Expand Down Expand Up @@ -123,7 +123,7 @@ class ReadyToRunInfo
PTR_READYTORUN_IMPORT_SECTION m_pImportSections;
DWORD m_nImportSections;

bool m_readyToRunCodeDisabled; // Is
bool m_readyToRunCodeDisabled; // Is
elinor-fung marked this conversation as resolved.
Show resolved Hide resolved

NativeFormat::NativeReader m_nativeReader;
NativeFormat::NativeArray m_methodDefEntryPoints;
Expand Down Expand Up @@ -335,8 +335,20 @@ class ReadyToRunInfo

PTR_MethodDesc GetMethodDescForEntryPointInNativeImage(PCODE entryPoint);
void SetMethodDescForEntryPointInNativeImage(PCODE entryPoint, PTR_MethodDesc methodDesc);

PTR_ReadyToRunCoreInfo GetComponentInfo() { return dac_cast<PTR_ReadyToRunCoreInfo>(&m_component); }

friend struct ::cdac_data<ReadyToRunInfo>;
};

template<>
struct cdac_data<ReadyToRunInfo>
{
static constexpr size_t CompositeInfo = offsetof(ReadyToRunInfo, m_pCompositeInfo);
static constexpr size_t NumRuntimeFunctions = offsetof(ReadyToRunInfo, m_nRuntimeFunctions);
static constexpr size_t RuntimeFunctions = offsetof(ReadyToRunInfo, m_pRuntimeFunctions);
static constexpr size_t DelayLoadMethodCallThunks = offsetof(ReadyToRunInfo, m_pSectionDelayLoadMethodCallThunks);
static constexpr size_t EntryPointToMethodDescMap = offsetof(ReadyToRunInfo, m_entryPointToMethodDescMap);
};

class DynamicHelpers
Expand Down
Loading
Loading