Skip to content

Commit 6f2cfcd

Browse files
Delete indirections (#1532)
* Get rid of indirection in fat function pointers * Clean up after #1371 * Get rid of indirections around statics * Delete IndirectionNode
1 parent 67927bd commit 6f2cfcd

File tree

15 files changed

+41
-261
lines changed

15 files changed

+41
-261
lines changed

src/coreclr/jit/indirectcalltransformer.cpp

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
//
1313
// A fat function pointer is a pointer with the second least significant bit
1414
// (aka FAT_POINTER_MASK) set. If the bit is set, the pointer (after clearing the bit)
15-
// actually points to a tuple <method pointer, instantiation argument pointer> where
15+
// actually points to a tuple <method pointer, instantiation argument> where
1616
// instantiationArgument is a hidden first argument required by method pointer.
1717
//
1818
// Fat pointers are used in CoreRT as a replacement for instantiating stubs,
@@ -410,17 +410,16 @@ class IndirectCallTransformer
410410
// GetHiddenArgument: load hidden argument.
411411
//
412412
// Arguments:
413-
// fixedFptrAddress - pointer to the tuple <methodPointer, instantiationArgumentPointer>
413+
// fixedFptrAddress - pointer to the tuple <methodPointer, instantiationArgument>
414414
//
415415
// Return Value:
416416
// generic context hidden argument.
417417
GenTree* GetHiddenArgument(GenTree* fixedFptrAddress)
418418
{
419419
GenTree* fixedFptrAddressCopy = compiler->gtCloneExpr(fixedFptrAddress);
420420
GenTree* wordSize = new (compiler, GT_CNS_INT) GenTreeIntCon(TYP_I_IMPL, genTypeSize(TYP_I_IMPL));
421-
GenTree* hiddenArgumentPtrPtr =
421+
GenTree* hiddenArgumentPtr =
422422
compiler->gtNewOperNode(GT_ADD, pointerType, fixedFptrAddressCopy, wordSize);
423-
GenTree* hiddenArgumentPtr = compiler->gtNewOperNode(GT_IND, pointerType, hiddenArgumentPtrPtr);
424423
return compiler->gtNewOperNode(GT_IND, fixedFptrAddressCopy->TypeGet(), hiddenArgumentPtr);
425424
}
426425

src/coreclr/nativeaot/Common/src/Internal/Runtime/MethodTable.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,7 +1110,7 @@ internal IntPtr DynamicGcStaticsData
11101110
uint cbOffset = GetFieldOffset(EETypeField.ETF_DynamicGcStatics);
11111111
fixed (MethodTable* pThis = &this)
11121112
{
1113-
return (IntPtr)((byte*)pThis + cbOffset);
1113+
return *(IntPtr*)((byte*)pThis + cbOffset);
11141114
}
11151115
}
11161116
#if TYPE_LOADER_IMPLEMENTATION
@@ -1134,7 +1134,7 @@ internal IntPtr DynamicNonGcStaticsData
11341134
uint cbOffset = GetFieldOffset(EETypeField.ETF_DynamicNonGcStatics);
11351135
fixed (MethodTable* pThis = &this)
11361136
{
1137-
return (IntPtr)((byte*)pThis + cbOffset);
1137+
return *(IntPtr*)((byte*)pThis + cbOffset);
11381138
}
11391139
}
11401140
#if TYPE_LOADER_IMPLEMENTATION

src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/FunctionPointerOps.cs

Lines changed: 9 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -49,25 +49,6 @@ public override int GetHashCode()
4949
public IntPtr InstantiationArgument;
5050
}
5151

52-
private unsafe struct RuntimeGeneratedGenericMethodDescriptor
53-
{
54-
public GenericMethodDescriptor Descriptor;
55-
private IntPtr _MethodDictionaryPointer;
56-
57-
public void Set(IntPtr methodFunctionPointer, IntPtr methodDictionaryPointer)
58-
{
59-
_MethodDictionaryPointer = methodDictionaryPointer;
60-
Descriptor._MethodFunctionPointer = methodFunctionPointer;
61-
62-
// This is ONLY safe if this structure is never moved. Do not box this struct.
63-
fixed (IntPtr* pointerPointer = &_MethodDictionaryPointer)
64-
{
65-
Descriptor._MethodDictionaryPointerPointer = pointerPointer;
66-
}
67-
}
68-
}
69-
70-
7152
private static uint s_genericFunctionPointerNextIndex;
7253
private const uint c_genericDictionaryChunkSize = 1024;
7354
private static LowLevelList<IntPtr> s_genericFunctionPointerCollection = new LowLevelList<IntPtr>();
@@ -80,9 +61,11 @@ public static unsafe IntPtr GetGenericMethodFunctionPointer(IntPtr canonFunction
8061

8162
lock (s_genericFunctionPointerDictionary)
8263
{
83-
GenericMethodDescriptorInfo key;
84-
key.MethodFunctionPointer = canonFunctionPointer;
85-
key.InstantiationArgument = instantiationArgument;
64+
var key = new GenericMethodDescriptorInfo
65+
{
66+
MethodFunctionPointer = canonFunctionPointer,
67+
InstantiationArgument = instantiationArgument
68+
};
8669

8770
uint index = 0;
8871
if (!s_genericFunctionPointerDictionary.TryGetValue(key, out index))
@@ -99,13 +82,12 @@ public static unsafe IntPtr GetGenericMethodFunctionPointer(IntPtr canonFunction
9982
System.Diagnostics.Debug.Assert(newSubChunkIndex == 0);
10083

10184
// New generic descriptors are allocated on the native heap and not tracked in the GC.
102-
IntPtr pNewMem = Marshal.AllocHGlobal((int)(c_genericDictionaryChunkSize * sizeof(RuntimeGeneratedGenericMethodDescriptor)));
85+
IntPtr pNewMem = Marshal.AllocHGlobal((int)(c_genericDictionaryChunkSize * sizeof(GenericMethodDescriptor)));
10386
s_genericFunctionPointerCollection.Add(pNewMem);
10487
}
10588

106-
RuntimeGeneratedGenericMethodDescriptor* newDescriptor = &((RuntimeGeneratedGenericMethodDescriptor*)s_genericFunctionPointerCollection[newChunkIndex])[newSubChunkIndex];
107-
108-
newDescriptor->Set(canonFunctionPointer, instantiationArgument);
89+
((GenericMethodDescriptor*)s_genericFunctionPointerCollection[newChunkIndex])[newSubChunkIndex] =
90+
new GenericMethodDescriptor(canonFunctionPointer, instantiationArgument);
10991

11092
s_genericFunctionPointerDictionary.LookupOrAdd(key, index);
11193

@@ -116,9 +98,8 @@ public static unsafe IntPtr GetGenericMethodFunctionPointer(IntPtr canonFunction
11698
// Lookup within list
11799
int chunkIndex = (int)(index / c_genericDictionaryChunkSize);
118100
uint subChunkIndex = index % c_genericDictionaryChunkSize;
119-
RuntimeGeneratedGenericMethodDescriptor* genericRuntimeFunctionPointer = &((RuntimeGeneratedGenericMethodDescriptor*)s_genericFunctionPointerCollection[chunkIndex])[subChunkIndex];
101+
GenericMethodDescriptor* genericFunctionPointer = &((GenericMethodDescriptor*)s_genericFunctionPointerCollection[chunkIndex])[subChunkIndex];
120102

121-
GenericMethodDescriptor* genericFunctionPointer = &genericRuntimeFunctionPointer->Descriptor;
122103
System.Diagnostics.Debug.Assert(canonFunctionPointer == genericFunctionPointer->MethodFunctionPointer);
123104
System.Diagnostics.Debug.Assert(instantiationArgument == genericFunctionPointer->InstantiationArgument);
124105

src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/CompilerServices/GenericMethodDescriptor.cs

Lines changed: 5 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -6,24 +6,12 @@
66
namespace Internal.Runtime.CompilerServices
77
{
88
[System.Runtime.CompilerServices.ReflectionBlocked]
9-
public unsafe struct GenericMethodDescriptor
9+
public struct GenericMethodDescriptor
1010
{
11-
internal IntPtr _MethodFunctionPointer;
12-
internal IntPtr* _MethodDictionaryPointerPointer;
11+
public readonly IntPtr MethodFunctionPointer;
12+
public readonly IntPtr InstantiationArgument;
1313

14-
public IntPtr MethodFunctionPointer
15-
{
16-
get
17-
{
18-
return _MethodFunctionPointer;
19-
}
20-
}
21-
public IntPtr InstantiationArgument
22-
{
23-
get
24-
{
25-
return *_MethodDictionaryPointerPointer;
26-
}
27-
}
14+
public GenericMethodDescriptor(IntPtr methodFunctionPointer, IntPtr instantiationArgument)
15+
=> (MethodFunctionPointer, InstantiationArgument) = (methodFunctionPointer, instantiationArgument);
2816
}
2917
}

src/coreclr/nativeaot/System.Private.Reflection.Execution/src/Internal/Reflection/Execution/ExecutionEnvironmentImplementation.MappingTables.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1346,9 +1346,9 @@ public sealed override FieldAccessor TryGetFieldAccessor(
13461346
fieldOffset = fieldAccessMetadata.Offset;
13471347
staticsBase = fieldBase switch
13481348
{
1349-
FieldTableFlags.GCStatic => *(IntPtr*)TypeLoaderEnvironment.Instance.TryGetGcStaticFieldData(declaringTypeHandle),
1350-
FieldTableFlags.NonGCStatic => *(IntPtr*)TypeLoaderEnvironment.Instance.TryGetNonGcStaticFieldData(declaringTypeHandle),
1351-
_ => *(IntPtr*)TypeLoaderEnvironment.Instance.TryGetThreadStaticFieldData(declaringTypeHandle),
1349+
FieldTableFlags.GCStatic => TypeLoaderEnvironment.Instance.TryGetGcStaticFieldData(declaringTypeHandle),
1350+
FieldTableFlags.NonGCStatic => TypeLoaderEnvironment.Instance.TryGetNonGcStaticFieldData(declaringTypeHandle),
1351+
_ => TypeLoaderEnvironment.Instance.TryGetThreadStaticFieldData(declaringTypeHandle),
13521352
};
13531353
}
13541354
}

src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/GenericDictionaryCell.cs

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -243,10 +243,6 @@ private class StaticDataCell : GenericDictionaryCell
243243
{
244244
internal StaticDataKind DataKind;
245245
internal TypeDesc Type;
246-
#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING
247-
internal bool Direct; // Set this flag if a direct pointer to the static data is requested
248-
// otherwise, an extra indirection will be inserted
249-
#endif
250246

251247
internal override void Prepare(TypeBuilder builder)
252248
{
@@ -262,28 +258,10 @@ internal override IntPtr Create(TypeBuilder builder)
262258
switch (DataKind)
263259
{
264260
case StaticDataKind.NonGc:
265-
#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING
266-
if (Direct)
267-
{
268-
return TypeLoaderEnvironment.Instance.TryGetNonGcStaticFieldDataDirect(typeHandle);
269-
}
270-
else
271-
#endif
272-
{
273-
return TypeLoaderEnvironment.Instance.TryGetNonGcStaticFieldData(typeHandle);
274-
}
261+
return TypeLoaderEnvironment.Instance.TryGetNonGcStaticFieldData(typeHandle);
275262

276263
case StaticDataKind.Gc:
277-
#if SUPPORTS_NATIVE_METADATA_TYPE_LOADING
278-
if (Direct)
279-
{
280-
return TypeLoaderEnvironment.Instance.TryGetGcStaticFieldDataDirect(typeHandle);
281-
}
282-
else
283-
#endif
284-
{
285-
return TypeLoaderEnvironment.Instance.TryGetGcStaticFieldData(typeHandle);
286-
}
264+
return TypeLoaderEnvironment.Instance.TryGetGcStaticFieldData(typeHandle);
287265

288266
default:
289267
Debug.Assert(false);
@@ -1292,7 +1270,7 @@ internal static GenericDictionaryCell CreateCellFromFixupKindAndToken(MetadataFi
12921270
var staticDataKind = StaticDataKind.Gc;
12931271
TypeLoaderLogger.WriteLine("Direct StaticData (" + (staticDataKind == StaticDataKind.Gc ? "Gc" : "NonGc") + ": " + type.ToString());
12941272

1295-
cell = new StaticDataCell() { DataKind = staticDataKind, Type = type, Direct = true };
1273+
cell = new StaticDataCell() { DataKind = staticDataKind, Type = type };
12961274
}
12971275
break;
12981276

@@ -1302,7 +1280,7 @@ internal static GenericDictionaryCell CreateCellFromFixupKindAndToken(MetadataFi
13021280
var staticDataKind = StaticDataKind.NonGc;
13031281
TypeLoaderLogger.WriteLine("Direct StaticData (" + (staticDataKind == StaticDataKind.Gc ? "Gc" : "NonGc") + ": " + type.ToString());
13041282

1305-
cell = new StaticDataCell() { DataKind = staticDataKind, Type = type, Direct = true };
1283+
cell = new StaticDataCell() { DataKind = staticDataKind, Type = type };
13061284
}
13071285
break;
13081286

src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeBuilder.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1238,7 +1238,7 @@ private unsafe void FinishClassConstructor(TypeDesc type, TypeBuilderState state
12381238
// fat pointer within the non-GC static data.
12391239
IntPtr templateTypeStaticData = TypeLoaderEnvironment.Instance.TryGetNonGcStaticFieldData(GetRuntimeTypeHandle(state.TemplateType));
12401240
Debug.Assert(templateTypeStaticData != IntPtr.Zero);
1241-
IntPtr* templateTypeClassConstructorSlotPointer = (IntPtr*)((byte*)*((IntPtr*)templateTypeStaticData) + ClassConstructorOffset);
1241+
IntPtr* templateTypeClassConstructorSlotPointer = (IntPtr*)((byte*)templateTypeStaticData + ClassConstructorOffset);
12421242
IntPtr templateTypeClassConstructorFatFunctionPointer = templateTypeClassConstructorFatFunctionPointer = *templateTypeClassConstructorSlotPointer;
12431243

12441244
// Crack the fat function pointer into the raw class constructor method pointer and the generic type dictionary.
@@ -1249,7 +1249,7 @@ private unsafe void FinishClassConstructor(TypeDesc type, TypeBuilderState state
12491249
}
12501250

12511251
IntPtr generatedTypeStaticData = GetRuntimeTypeHandle(type).ToEETypePtr()->DynamicNonGcStaticsData;
1252-
IntPtr* generatedTypeClassConstructorSlotPointer = (IntPtr*)((byte*)*((IntPtr*)generatedTypeStaticData) + ClassConstructorOffset);
1252+
IntPtr* generatedTypeClassConstructorSlotPointer = (IntPtr*)((byte*)generatedTypeStaticData + ClassConstructorOffset);
12531253

12541254
if (exactClassConstructorFunctionPointer != IntPtr.Zero)
12551255
{

src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.Metadata.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -413,7 +413,7 @@ public static unsafe IntPtr TryGetStaticClassConstructionContext(RuntimeTypeHand
413413
if (RuntimeAugments.IsDynamicType(typeHandle))
414414
{
415415
// For dynamic types, its always possible to get the non-gc static data section directly.
416-
byte* ptr = (byte*)Instance.TryGetNonGcStaticFieldDataDirect(typeHandle);
416+
byte* ptr = (byte*)Instance.TryGetNonGcStaticFieldData(typeHandle);
417417

418418
// what we have now is the base address of the non-gc statics of the type
419419
// what we need is the cctor context, which is just before that

src/coreclr/nativeaot/System.Private.TypeLoader/src/Internal/Runtime/TypeLoader/TypeLoaderEnvironment.StaticsLookup.cs

Lines changed: 2 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public sealed partial class TypeLoaderEnvironment
3434
/// Get a pointer to the nongc static field data of a type. This function works for dynamic
3535
/// types, reflectable types, and for all generic types
3636
/// </summary>
37-
public IntPtr TryGetNonGcStaticFieldDataDirect(RuntimeTypeHandle runtimeTypeHandle)
37+
public IntPtr TryGetNonGcStaticFieldData(RuntimeTypeHandle runtimeTypeHandle)
3838
{
3939
unsafe
4040
{
@@ -71,27 +71,6 @@ public IntPtr TryGetNonGcStaticFieldDataDirect(RuntimeTypeHandle runtimeTypeHand
7171
return nonGcStaticsAddress;
7272
}
7373

74-
// The indirected helper function can be used to find all dynamic types not found via
75-
// TryGetStaticsInfoForNamedType as well as generics
76-
IntPtr ptrToStaticFieldData = TryGetNonGcStaticFieldData(runtimeTypeHandle);
77-
if (ptrToStaticFieldData == IntPtr.Zero)
78-
{
79-
return IntPtr.Zero;
80-
}
81-
else
82-
{
83-
unsafe
84-
{
85-
return *(IntPtr*)ptrToStaticFieldData;
86-
}
87-
}
88-
}
89-
90-
/// <summary>
91-
/// Get a pointer to a pointer to the nongc static field data of a type. This function works for all generic types
92-
/// </summary>
93-
public IntPtr TryGetNonGcStaticFieldData(RuntimeTypeHandle runtimeTypeHandle)
94-
{
9574
unsafe
9675
{
9776
// Non-generic, non-dynamic static data is found via the FieldAccessMap
@@ -129,7 +108,7 @@ public IntPtr TryGetNonGcStaticFieldData(RuntimeTypeHandle runtimeTypeHandle)
129108
/// Get a pointer to the gc static field data of a type. This function works for dynamic
130109
/// types, reflectable types, and for all generic types
131110
/// </summary>
132-
public IntPtr TryGetGcStaticFieldDataDirect(RuntimeTypeHandle runtimeTypeHandle)
111+
public IntPtr TryGetGcStaticFieldData(RuntimeTypeHandle runtimeTypeHandle)
133112
{
134113
unsafe
135114
{
@@ -159,27 +138,6 @@ public IntPtr TryGetGcStaticFieldDataDirect(RuntimeTypeHandle runtimeTypeHandle)
159138
return gcStaticsAddress;
160139
}
161140

162-
// The indirected helper function can be used to find all dynamic types not found via
163-
// TryGetStaticsInfoForNamedType as well as generics
164-
IntPtr ptrToStaticFieldData = TryGetGcStaticFieldData(runtimeTypeHandle);
165-
if (ptrToStaticFieldData == IntPtr.Zero)
166-
{
167-
return IntPtr.Zero;
168-
}
169-
else
170-
{
171-
unsafe
172-
{
173-
return *(IntPtr*)ptrToStaticFieldData;
174-
}
175-
}
176-
}
177-
178-
/// <summary>
179-
/// Get a pointer to a pointer to the gc static field data of a type. This function works for all generic types
180-
/// </summary>
181-
public IntPtr TryGetGcStaticFieldData(RuntimeTypeHandle runtimeTypeHandle)
182-
{
183141
unsafe
184142
{
185143
// Non-generic, non-dynamic static data is found via the FieldAccessMap

src/coreclr/tools/aot/ILCompiler.Compiler/Compiler/DependencyAnalysis/FatFunctionPointerNode.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,8 +84,8 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
8484
contextParameter = factory.ConstructedTypeSymbol(Method.OwningType);
8585
}
8686

87-
// The next entry is a pointer to the pointer to the context to be used for the canonical method
88-
builder.EmitPointerReloc(factory.Indirection(contextParameter));
87+
// The next entry is a pointer to the context to be used for the canonical method
88+
builder.EmitPointerReloc(contextParameter);
8989

9090
return builder.ToObjectData();
9191
}

0 commit comments

Comments
 (0)