-
Notifications
You must be signed in to change notification settings - Fork 4.9k
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] Basic ISOSDacInterface::GetMethodDescData #106413
Closed
Closed
Changes from all commits
Commits
Show all changes
69 commits
Select commit
Hold shift + click to select a range
601938d
wip: NativeCodePointers and MethodDesc CodeData
lambdageek 5f3599c
checkpoint: PrecodeMachineDescriptor and KnownPrecodeType
lambdageek 2cf8fd4
checkpoint: StubPrecodeData, StubCodePageSize
lambdageek 7ef9016
GetTemporaryEntryPointIfExists
lambdageek 9cf7a7a
wip GetMethodEntryPointIfExists
lambdageek 2d1e34e
add contract
lambdageek 2d4252a
add missing descriptor fields
lambdageek c83ad25
fix data descriptor reads
lambdageek c6dae6f
add FixupPrecodeData
lambdageek 43e1748
add size of MethodDesc
lambdageek 72369e3
fix thumb flag logic
lambdageek 93f0a3d
WIP - broken - ExecutionManagerGetCodeMethodDesc
lambdageek 58aa614
fix build
lambdageek 4c211d4
fixup cdac_offsets<> -> cdac_data<>
lambdageek ce772d9
WIP RangeSectionMap
lambdageek 891f07f
tag ExecutionManager pointers
lambdageek 5717664
Add IJitManager::JitManagerKind
lambdageek 1eeb513
WIP JitCodeToMethodInfo
lambdageek 2a95bda
WIP NibbleMap
lambdageek ebf76a3
add HeapList
lambdageek 7defaef
fix datadescriptor.h typo
lambdageek 9181f3f
Add StoredSigMethodDesc
lambdageek 86954df
fix bit twiddling
lambdageek 0d0b592
fixup NonValidated.MethodDesc.NativeCodeSlotIndex
lambdageek 63e0334
fixup additional pointers packing index
lambdageek c177e4d
fix logic typo
lambdageek 3956b06
checkpoint: jitted methods validate
lambdageek 0b91b85
more asserts in legacy GetMethodDescData
lambdageek d3a8bb0
WIP: native code version
lambdageek 5fcdc60
WIP: native code version
lambdageek efad4ea
checkpoint start adding NativeCodeVersion operations
lambdageek 6febf72
checkpoint: NativeCodeVersionContract.GetSpecificNativeCodeVersion
lambdageek dd86095
remove AppDomain.CodeVersionManager from cdac
lambdageek 5b33737
WIP: il code version lookup table
lambdageek de58ab5
fixup build
lambdageek 0b6f6e4
wip: FindActiveILCodeVersion/FindActiveNativeCodeVersion
lambdageek 502cd31
implement GetModuleLookupMapElement
lambdageek 312f2ce
FindActiveILCodeVersion
lambdageek c813a78
checkpoint sketch out one working path through GetMethodDescData
lambdageek f225adb
fixup after rebase
lambdageek 2cb8e86
fixup rebae; remove duplicate global
lambdageek f4852d2
checkpoint: works on some methods (NO REJIT)
lambdageek da7065e
remove JitManagerKind in the runtime
lambdageek 818c21c
remove more
lambdageek 1f6a909
whitespace and comments
lambdageek 04f41f6
remove instance field initialization from PrecodeMachineDescriptor
lambdageek abf9df0
suggestion from code review make m_IsCollectible a const BYTE
lambdageek 71dee34
fixup
lambdageek 2fbc89e
Revert "fixup"
lambdageek 2e3b938
Revert "suggestion from code review make m_IsCollectible a const BYTE"
lambdageek 1776abe
move PrecodeStubs to a separate contract
lambdageek 099b5fa
ExecutionManager contract
lambdageek 50046b8
rename contract NativeCodePointers => CodeVersions
lambdageek e2d637b
ReJIT contract
lambdageek 7724fa8
formatting, comments and whitespace
lambdageek a53b3ae
cleanup
lambdageek 124ee6a
"NDirect" -> "PInvoke" in descriptor and contracts
lambdageek fb1676b
WIP: contract writeups
lambdageek f1d757e
fix build
lambdageek f1d7be8
placeholder ExecutionManager contract
lambdageek ebb4a67
placeholder ExecutionManager contract; updates to RTS and Loader
lambdageek aac3faf
refactor ExecutionManager
lambdageek ef51f0e
remove dead method from contract
lambdageek 92764a2
fix typo
lambdageek 4e1a620
Merge remote-tracking branch 'origin/main' into cdac-nativecodeptr
lambdageek 037c349
Apply suggestions from code review
lambdageek 25d8343
Add PrecodeStubs contract writeup
lambdageek ac0165a
Merge remote-tracking branch 'origin/main' into cdac-nativecodeptr
lambdageek 8f5e98b
Merge remote-tracking branch 'origin/main' into cdac-nativecodeptr
lambdageek File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,149 @@ | ||
# Contract CodeVersions | ||
|
||
This contract encapsulates support for [code versioning](../features/code-versioning.md) in the runtime. | ||
|
||
## APIs of contract | ||
|
||
```csharp | ||
internal struct NativeCodeVersionHandle | ||
{ | ||
// no public constructors | ||
internal readonly TargetPointer MethodDescAddress; | ||
internal readonly TargetPointer CodeVersionNodeAddress; | ||
internal NativeCodeVersionHandle(TargetPointer methodDescAddress, TargetPointer codeVersionNodeAddress) | ||
{ | ||
if (methodDescAddress != TargetPointer.Null && codeVersionNodeAddress != TargetPointer.Null) | ||
{ | ||
throw new ArgumentException("Only one of methodDescAddress and codeVersionNodeAddress can be non-null"); | ||
} | ||
MethodDescAddress = methodDescAddress; | ||
CodeVersionNodeAddress = codeVersionNodeAddress; | ||
} | ||
|
||
internal static NativeCodeVersionHandle Invalid => new(TargetPointer.Null, TargetPointer.Null); | ||
public bool Valid => MethodDescAddress != TargetPointer.Null || CodeVersionNodeAddress != TargetPointer.Null; | ||
} | ||
``` | ||
|
||
```csharp | ||
// Return a handle to the version of the native code that includes the given instruction pointer | ||
public virtual NativeCodeVersionHandle GetNativeCodeVersionForIP(TargetCodePointer ip); | ||
// Return a handle to the active version of the native code for a given method descriptor | ||
public virtual NativeCodeVersionHandle GetActiveNativeCodeVersion(TargetPointer methodDesc); | ||
|
||
// returns true if the given method descriptor supports multiple code versions | ||
public virtual bool CodeVersionManagerSupportsMethod(TargetPointer methodDesc); | ||
|
||
// Return the instruction pointer corresponding to the start of the given native code version | ||
public virtual TargetCodePointer GetNativeCode(NativeCodeVersionHandle codeVersionHandle); | ||
``` | ||
|
||
## Version 1 | ||
|
||
Data descriptors used: | ||
| Data Descriptor Name | Field | Meaning | | ||
| --- | --- | --- | | ||
| MethodDescVersioningState | ? | ? | | ||
| NativeCodeVersionNode | ? | ? | | ||
| ILCodeVersioningState | ? | ? | | ||
|
||
|
||
Global variables used: | ||
| Global Name | Type | Purpose | | ||
| --- | --- | --- | | ||
|
||
Contracts used: | ||
| Contract Name | | ||
| --- | | ||
| ExecutionManager | | ||
| Loader | | ||
| RuntimeTypeSystem | | ||
|
||
### Finding the start of a specific native code version | ||
|
||
```csharp | ||
NativeCodeVersionHandle GetNativeCodeVersionForIP(TargetCodePointer ip) | ||
{ | ||
Contracts.IExecutionManager executionManager = _target.Contracts.ExecutionManager; | ||
EECodeInfoHandle? info = executionManager.GetEECodeInfoHandle(ip); | ||
if (!info.HasValue) | ||
{ | ||
return NativeCodeVersionHandle.Invalid; | ||
} | ||
TargetPointer methodDescAddress = executionManager.GetMethodDesc(info.Value); | ||
if (methodDescAddress == TargetPointer.Null) | ||
{ | ||
return NativeCodeVersionHandle.Invalid; | ||
} | ||
IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; | ||
MethodDescHandle md = rts.GetMethodDescHandle(methodDescAddress); | ||
if (!rts.IsVersionable(md)) | ||
{ | ||
return new NativeCodeVersionHandle(methodDescAddress, codeVersionNodeAddress: TargetPointer.Null); | ||
} | ||
else | ||
{ | ||
TargetCodePointer startAddress = executionManager.GetStartAddress(info.Value); | ||
return GetSpecificNativeCodeVersion(md, startAddress); | ||
} | ||
} | ||
|
||
private NativeCodeVersionHandle GetSpecificNativeCodeVersion(MethodDescHandle md, TargetCodePointer startAddress) | ||
{ | ||
TargetPointer methodDescVersioningStateAddress = target.Contracts.RuntimeTypeSystem.GetMethodDescVersioningState(md); | ||
if (methodDescVersioningStateAddress == TargetPointer.Null) | ||
{ | ||
return NativeCodeVersionHandle.Invalid; | ||
} | ||
Data.MethodDescVersioningState methodDescVersioningStateData = _target.ProcessedData.GetOrAdd<Data.MethodDescVersioningState>(methodDescVersioningStateAddress); | ||
// CodeVersionManager::GetNativeCodeVersion(PTR_MethodDesc, PCODE startAddress) | ||
return FindFirstCodeVersion(methodDescVersioningStateData, (codeVersion) => | ||
{ | ||
return codeVersion.MethodDesc == md.Address && codeVersion.NativeCode == startAddress; | ||
}); | ||
} | ||
|
||
private NativeCodeVersionHandle FindFirstCodeVersion(Data.MethodDescVersioningState versioningState, Func<Data.NativeCodeVersionNode, bool> predicate) | ||
{ | ||
// NativeCodeVersion::Next, heavily inlined | ||
TargetPointer currentAddress = versioningState.NativeCodeVersionNode; | ||
while (currentAddress != TargetPointer.Null) | ||
{ | ||
Data.NativeCodeVersionNode current = _target.ProcessedData.GetOrAdd<Data.NativeCodeVersionNode>(currentAddress); | ||
if (predicate(current)) | ||
{ | ||
return new NativeCodeVersionHandle(methodDescAddress: TargetPointer.Null, currentAddress); | ||
} | ||
currentAddress = current.Next; | ||
} | ||
return NativeCodeVersionHandle.Invalid; | ||
} | ||
``` | ||
|
||
### Finding the active native code version of a method descriptor | ||
|
||
```csharp | ||
NativeCodeVersionHandle ICodeVersions.GetActiveNativeCodeVersion(TargetPointer methodDesc) | ||
{ | ||
// CodeVersionManager::GetActiveILCodeVersion | ||
// then ILCodeVersion::GetActiveNativeCodeVersion | ||
IRuntimeTypeSystem rts = _target.Contracts.RuntimeTypeSystem; | ||
MethodDescHandle md = rts.GetMethodDescHandle(methodDesc); | ||
TargetPointer mtAddr = rts.GetMethodTable(md); | ||
TypeHandle typeHandle = rts.GetTypeHandle(mtAddr); | ||
TargetPointer module = rts.GetModule(typeHandle); | ||
uint methodDefToken = rts.GetMethodToken(md); | ||
ILCodeVersionHandle methodDefActiveVersion = FindActiveILCodeVersion(module, methodDefToken); | ||
if (!methodDefActiveVersion.IsValid) | ||
{ | ||
return NativeCodeVersionHandle.Invalid; | ||
} | ||
return FindActiveNativeCodeVersion(methodDefActiveVersion, methodDesc); | ||
} | ||
``` | ||
|
||
**FIXME** | ||
|
||
### Determining whether a method descriptor supports code versioning | ||
|
||
**TODO** |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
# Contract ExecutionManager | ||
|
||
This contract | ||
|
||
|
||
## APIs of contract | ||
|
||
```csharp | ||
internal struct EECodeInfoHandle | ||
{ | ||
// no public constructor | ||
public readonly TargetPointer Address; | ||
internal EECodeInfoHandle(TargetPointer address) => Address = address; | ||
} | ||
``` | ||
|
||
```csharp | ||
// Collect execution engine info for a code block that includes the given instruction pointer. | ||
// Return a handle for the information, or null if an owning code block cannot be found. | ||
EECodeInfoHandle? GetEECodeInfoHandle(TargetCodePointer ip); | ||
// Get the method descriptor corresponding to the given code block | ||
TargetPointer GetMethodDesc(EECodeInfoHandle codeInfoHandle) => throw new NotImplementedException(); | ||
// Get the instruction pointer address of the start of the code block | ||
TargetCodePointer GetStartAddress(EECodeInfoHandle codeInfoHandle) => throw new NotImplementedException(); | ||
``` | ||
|
||
## Version 1 | ||
|
||
Data descriptors used: | ||
| Data Descriptor Name | Field | Meaning | | ||
| --- | --- | --- | | ||
| RangeSectionMap | TopLevelData | pointer to the outermost RangeSection | | ||
| RangeSectionFragment| ? | ? | | ||
| RangeSection | ? | ? | | ||
| RealCodeHeader | ? | ? | | ||
| HeapList | ? | ? | | ||
|
||
|
||
|
||
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 | ||
|
||
Contracts used: | ||
| Contract Name | | ||
| --- | | ||
|
||
```csharp | ||
``` | ||
|
||
**TODO** Methods | ||
|
||
### NibbleMap | ||
|
||
**TODO** |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we'll want to have a LoaderAllocator contract. There is a bunch of ... stuff... on there, and I feel like we'll likely need something there.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For this particular API (checking if the module is collectible), it seems like it should cut out the
LoaderAllocator
concept? Since once you're at theModule
(instead of a MethodDesc), the module's IsCollectible should match the module's loader allocator's IsCollectible.