@@ -4,6 +4,29 @@ This contract encapsulates support for [code versioning](../features/code-versio
4
4
5
5
## APIs of contract
6
6
7
+ ``` csharp
8
+ internal readonly struct ILCodeVersionHandle
9
+ {
10
+ internal readonly TargetPointer Module ;
11
+ internal readonly uint MethodDefinition ;
12
+ internal readonly TargetPointer ILCodeVersionNode ;
13
+ internal ILCodeVersionHandle (TargetPointer module , uint methodDef , TargetPointer ilCodeVersionNodeAddress )
14
+ {
15
+ if (module != TargetPointer .Null && ilCodeVersionNodeAddress != TargetPointer .Null )
16
+ throw new ArgumentException (" Both MethodDesc and ILCodeVersionNode cannot be non-null" );
17
+
18
+ if (module != TargetPointer .Null && methodDef == 0 )
19
+ throw new ArgumentException (" MethodDefinition must be non-zero if Module is non-null" );
20
+
21
+ Module = module ;
22
+ MethodDefinition = methodDef ;
23
+ ILCodeVersionNode = ilCodeVersionNodeAddress ;
24
+ }
25
+ public static ILCodeVersionHandle Invalid => new ILCodeVersionHandle (TargetPointer .Null , 0 , TargetPointer .Null );
26
+ public bool IsValid => Module != TargetPointer .Null || ILCodeVersionNode != TargetPointer .Null ;
27
+ }
28
+ ```
29
+
7
30
``` csharp
8
31
internal struct NativeCodeVersionHandle
9
32
{
@@ -26,10 +49,19 @@ internal struct NativeCodeVersionHandle
26
49
```
27
50
28
51
``` csharp
52
+ // Return a handle to the active version of the IL code for a given method descriptor
53
+ public virtual ILCodeVersionHandle GetActiveILCodeVersion (TargetPointer methodDesc );
54
+ // Return a handle to the IL code version representing the given native code version
55
+ public virtual ILCodeVersionHandle GetILCodeVersion (NativeCodeVersionHandle codeVersionHandle );
56
+ // Return all of the IL code versions for a given method descriptor
57
+ public virtual IEnumerable < ILCodeVersionHandle > GetILCodeVersions (TargetPointer methodDesc );
58
+
29
59
// Return a handle to the version of the native code that includes the given instruction pointer
30
60
public virtual NativeCodeVersionHandle GetNativeCodeVersionForIP (TargetCodePointer ip );
31
61
// Return a handle to the active version of the native code for a given method descriptor
32
62
public virtual NativeCodeVersionHandle GetActiveNativeCodeVersion (TargetPointer methodDesc );
63
+ // Return a handle to the active version of the native code for a given method descriptor and IL code version. The IL code version and method descriptor must represent the same method
64
+ public virtual NativeCodeVersionHandle GetActiveNativeCodeVersionForILCodeVersion (TargetPointer methodDesc , ILCodeVersionHandle ilCodeVersionHandle );
33
65
34
66
// returns true if the given method descriptor supports multiple code versions
35
67
public virtual bool CodeVersionManagerSupportsMethod (TargetPointer methodDesc );
@@ -52,11 +84,13 @@ Data descriptors used:
52
84
| NativeCodeVersionNode | NativeCode | indicates an explicit native code version node |
53
85
| NativeCodeVersionNode | Flags | ` NativeCodeVersionNodeFlags ` flags, see below |
54
86
| NativeCodeVersionNode | VersionId | Version ID corresponding to the parent IL code version |
87
+ | ILCodeVersioningState | FirstVersionNode | pointer to the first ` ILCodeVersionNode ` |
55
88
| ILCodeVersioningState | ActiveVersionKind | an ` ILCodeVersionKind ` value indicating which fields of the active version are value |
56
89
| ILCodeVersioningState | ActiveVersionNode | if the active version is explicit, the NativeCodeVersionNode for the active version |
57
90
| ILCodeVersioningState | ActiveVersionModule | if the active version is synthetic or unknown, the pointer to the Module that defines the method |
58
91
| ILCodeVersioningState | ActiveVersionMethodDef | if the active version is synthetic or unknown, the MethodDef token for the method |
59
92
| ILCodeVersionNode | VersionId | Version ID of the node |
93
+ | ILCodeVersionNode | Next | Pointer to the next ` ILCodeVersionNode ` |
60
94
61
95
The flag indicates that the default version of the code for a method desc is active:
62
96
``` csharp
@@ -93,6 +127,40 @@ Contracts used:
93
127
| Loader |
94
128
| RuntimeTypeSystem |
95
129
130
+ ### Finding all of the ILCodeVersions for a method
131
+ ``` csharp
132
+ IEnumerable < ILCodeVersionHandle > ICodeVersions .GetILCodeVersions (TargetPointer methodDesc )
133
+ {
134
+ // CodeVersionManager::GetILCodeVersions
135
+ IRuntimeTypeSystem rts = _target .Contracts .RuntimeTypeSystem ;
136
+ MethodDescHandle md = rts .GetMethodDescHandle (methodDesc );
137
+ TargetPointer mtAddr = rts .GetMethodTable (md );
138
+ TypeHandle typeHandle = rts .GetTypeHandle (mtAddr );
139
+ TargetPointer module = rts .GetModule (typeHandle );
140
+ uint methodDefToken = rts .GetMethodToken (md );
141
+
142
+ ModuleHandle moduleHandle = _target .Contracts .Loader .GetModuleHandle (module );
143
+ TargetPointer ilCodeVersionTable = _target .Contracts .Loader .GetLookupTables (moduleHandle ).MethodDefToILCodeVersioningState ;
144
+ TargetPointer ilVersionStateAddress = _target .Contracts .Loader .GetModuleLookupMapElement (ilCodeVersionTable , methodDefToken , out var _ );
145
+
146
+ // always add the synthetic version
147
+ yield return new ILCodeVersionHandle (module , methodDefToken , TargetPointer .Null );
148
+
149
+ // if explicit versions exist, iterate linked list and return them
150
+ if (ilVersionStateAddress != TargetPointer .Null )
151
+ {
152
+ Data .ILCodeVersioningState ilState = _target .ProcessedData .GetOrAdd <Data .ILCodeVersioningState >(ilVersionStateAddress );
153
+ TargetPointer nodePointer = ilState .FirstVersionNode ;
154
+ while (nodePointer != TargetPointer .Null )
155
+ {
156
+ Data .ILCodeVersionNode current = _target .ProcessedData .GetOrAdd <Data .ILCodeVersionNode >(nodePointer );
157
+ yield return new ILCodeVersionHandle (TargetPointer .Null , 0 , nodePointer );
158
+ nodePointer = current .Next ;
159
+ }
160
+ }
161
+ }
162
+ ```
163
+
96
164
### Finding the start of a specific native code version
97
165
98
166
``` csharp
@@ -235,7 +303,7 @@ bool IsActiveNativeCodeVersion(NativeCodeVersionHandle nativeCodeVersion)
235
303
236
304
NativeCodeVersionHandle FindActiveNativeCodeVersion (ILCodeVersionHandle methodDefActiveVersion , TargetPointer methodDescAddress )
237
305
{
238
- TargetNUInt ? ilVersionId = default ;
306
+ TargetNUInt ilVersionId = GetId ( ilcodeVersion ) ;
239
307
if (methodDefActiveVersion .Module != TargetPointer .Null )
240
308
{
241
309
NativeCodeVersionHandle provisionalHandle = new NativeCodeVersionHandle (methodDescAddress : methodDescAddress , codeVersionNodeAddress : TargetPointer .Null );
@@ -256,7 +324,7 @@ NativeCodeVersionHandle FindActiveNativeCodeVersion(ILCodeVersionHandle methodDe
256
324
MethodDescHandle md = rts .GetMethodDescHandle (methodDescAddress );
257
325
return FindFirstCodeVersion (rts , md , (codeVersion ) =>
258
326
{
259
- return (! ilVersionId . HasValue || ilVersionId . Value . Value == codeVersion .ILVersionId . Value )
327
+ return (ilVersionId == codeVersion .ILVersionId )
260
328
&& ((NativeCodeVersionNodeFlags )codeVersion .Flags ).HasFlag (NativeCodeVersionNodeFlags .IsActiveChild );
261
329
});
262
330
}
0 commit comments