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

[NativeAOT] Reflection type refactoring #93440

Merged
merged 52 commits into from
Oct 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
52 commits
Select commit Hold shift + click to select a range
ae816dd
WIP
jkotas Sep 13, 2023
06007a0
Add conversions between Type and RuntimeTypeInfo
jkotas Sep 19, 2023
dc70efa
Comment out DisabledReflection for now
jkotas Sep 19, 2023
88333d5
Fix warnings
jkotas Sep 20, 2023
27db9eb
Implementing properties
jkotas Sep 23, 2023
55ea211
Create RuntimeType
jkotas Sep 27, 2023
ac8fb62
Fix RuntimeTypeHandle unifier
jkotas Sep 27, 2023
ca0f996
Cleanup
jkotas Sep 27, 2023
7575b84
GetElementType
jkotas Sep 28, 2023
9df456c
Make Type.Name work
jkotas Oct 1, 2023
5f365e0
Type.Make* implementation
jkotas Oct 2, 2023
c720ed5
Fix IsEnum
jkotas Oct 3, 2023
9656d3c
Rest of RuntimeType methods
jkotas Oct 3, 2023
396b08e
Remaining RuntimeType methods
jkotas Oct 4, 2023
c2ef7ba
Implement GetTypeCodeImpl
jkotas Oct 8, 2023
36ac928
Delete InternalGetHashCode
jkotas Oct 8, 2023
70ff565
Reorder implementations
jkotas Oct 9, 2023
a23a987
Add MetadataOnlyType
jkotas Oct 10, 2023
ba8f71c
Fix warnings
jkotas Oct 12, 2023
baea1e5
DisableReflection
jkotas Oct 12, 2023
56e6532
Implement IsInstanceOf
jkotas Oct 13, 2023
a368590
Fix some tests
jkotas Oct 13, 2023
b22b531
Style
jkotas Oct 13, 2023
c71c374
Fix build breaks
jkotas Oct 15, 2023
3ee2a83
Fix build breaks, cleanup
jkotas Oct 15, 2023
f1ac177
Delete MetadataOnlyType
jkotas Oct 20, 2023
970609f
Delete unused method
jkotas Oct 20, 2023
ecb6ff8
RuntimeType with fallbacks
jkotas Oct 23, 2023
3915f64
Bug fixes
jkotas Oct 24, 2023
10f808b
Delete DoNotThrowForAssembly
jkotas Oct 24, 2023
0a8ba6c
Fix TODO
jkotas Oct 24, 2023
9e8240c
Bug fixes
jkotas Oct 24, 2023
de2a003
Cleanup
jkotas Oct 25, 2023
64436e7
Bug fixes
jkotas Oct 25, 2023
959f5e5
Fix
jkotas Oct 26, 2023
92d5736
Fix
jkotas Oct 27, 2023
0129a0a
Cleanup
jkotas Oct 28, 2023
285e755
Fix disabled reflection
jkotas Oct 28, 2023
39e0cad
Cleanup
jkotas Oct 29, 2023
a3703a7
Delete ReflectionDomainSetup
jkotas Oct 29, 2023
fe4d855
Remove unnecessary abstraction layers
jkotas Oct 29, 2023
26de6d3
Cleanup
jkotas Oct 29, 2023
af3cc7f
CR Feedback
jkotas Oct 30, 2023
c75766f
Revert "DisableReflection"
jkotas Oct 30, 2023
13694f3
Cleanup
jkotas Oct 31, 2023
0fbf0be
Delete RunModuleConstructor abstraction
jkotas Oct 31, 2023
611f8ca
Fold ReflectionExecutionDomainCallbacks into ReflectionCoreCallbacks
jkotas Oct 31, 2023
9362aba
Merge branch 'main' into reflection
jkotas Oct 31, 2023
9a7e4ff
Nit
jkotas Oct 31, 2023
7d4fefb
Cleanup
jkotas Oct 31, 2023
d43a822
Use GCHandle to hold onto RuntimeTypeInfos
jkotas Oct 31, 2023
bb71be3
Add AggressiveInlining
jkotas Oct 31, 2023
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
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,7 @@ The .NET Foundation licenses this file to you under the MIT license.
<IlcArg Condition="$(IlcInstructionSet) != ''" Include="--instruction-set:$(IlcInstructionSet)" />
<IlcArg Condition="$(IlcDisableReflection) == 'true'" Include="--reflectiondata:none" />
<IlcArg Condition="$(IlcDisableReflection) == 'true'" Include="--feature:System.Collections.Generic.DefaultComparers=false" />
<IlcArg Condition="$(IlcDisableReflection) == 'true'" Include="--feature:System.Reflection=false" />
<IlcArg Condition="$(IlcMaxVectorTBitWidth) != ''" Include="--max-vectort-bitwidth:$(IlcMaxVectorTBitWidth)" />
<IlcArg Condition="$(IlcSingleThreaded) == 'true'" Include="--parallelism:1" />
<IlcArg Condition="$(IlcSystemModule) != ''" Include="--systemmodule:$(IlcSystemModule)" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -422,6 +422,15 @@ internal bool IsNullable
}
}

internal bool IsDefType
{
get
{
EETypeKind kind = Kind;
return kind == EETypeKind.CanonicalEEType || kind == EETypeKind.GenericTypeDefEEType;
}
}

internal bool IsCanonical
{
get
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,18 +25,14 @@ namespace System.Collections.Concurrent
// The key must be of a type that implements IEquatable<K>. The unifier calls IEquality<K>.Equals()
// and Object.GetHashCode() on the keys.
//
// The value must be a reference type that implements IKeyedItem<K>. The unifier invokes the
// IKeyedItem<K>.PrepareKey() method (outside the lock) on any value returned by the factory. This gives the value
// a chance to do any lazy evaluation of the keys while it's safe to do so.
// The value must be a reference type that implements IKeyedItem<K>.
//
// Deadlock risks:
// - Keys may be tested for equality and asked to compute their hashcode while the unifier
// holds its lock. Thus these operations must be written carefully to avoid deadlocks and
// reentrancy in to the table.
//
// - Values may get their IKeyedItem<K>.Key property called while the unifier holds its lock.
// Values that need to do lazy evaluation to compute their keys should do that in the PrepareKey()
// method which the unifier promises to call outside the lock prior to entering the value into the table.
//
// - The Factory method will never be called inside the unifier lock. If two threads race to
// enter a value for the same key, the Factory() may get invoked twice for the same key - one
Expand Down Expand Up @@ -150,10 +146,6 @@ public V GetOrAdd(K key)
return null;
}

// While still outside the lock, invoke the value's PrepareKey method to give the chance to do any lazy evaluation
// it needs to produce the key quickly and in a deadlock-free manner once we're inside the lock.
value.PrepareKey();

using (_lock.EnterScope())
{
V heyIWasHereFirst;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,19 +14,9 @@ namespace System.Collections.Concurrent
//
internal interface IKeyedItem<K> where K : IEquatable<K>
{
//
// This method is the keyed item's chance to do any lazy evaluation needed to produce the key quickly.
// Concurrent unifiers are guaranteed to invoke this method at least once and wait for it
// to complete before invoking the Key property. The unifier lock is NOT held across the call.
//
// PrepareKey() must be idempodent and thread-safe. It may be invoked multiple times and concurrently.
//
void PrepareKey();

//
// Produce the key. This is a high-traffic property and is called while the hash table's lock is held. Thus, it should
// return a precomputed stored value and refrain from invoking other methods. If the keyed item wishes to
// do lazy evaluation of the key, it should do so in the PrepareKey() method.
// return a precomputed stored value and refrain from invoking other methods.
//
K Key { get; }
}
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -697,10 +697,6 @@
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Internal.Reflection.Core.QScopeDefinition</Target>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Internal.Reflection.Core.ReflectionDomainSetup</Target>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Internal.Reflection.Extensions.NonPortable.CustomAttributeInheritanceRules</Target>
Expand All @@ -713,10 +709,6 @@
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Internal.Runtime.Augments.DynamicDelegateAugments</Target>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Internal.Runtime.Augments.ReflectionExecutionDomainCallbacks</Target>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:Internal.Runtime.Augments.RuntimeAugments</Target>
Expand Down Expand Up @@ -897,10 +889,6 @@
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:System.Runtime.InteropServices.PInvokeMarshal</Target>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:System.Runtime.InteropServices.UnsafeGCHandle</Target>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:System.Runtime.RuntimeImportAttribute</Target>
Expand All @@ -921,10 +909,6 @@
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:System.RuntimeExceptionHelpers</Target>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:System.RuntimeType</Target>
</Suppression>
<Suppression>
<DiagnosticId>CP0001</DiagnosticId>
<Target>T:System.Threading.Condition</Target>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,4 +20,9 @@
<type fullname="System.Reflection.Runtime.General.TypeUnifier" feature="System.Reflection.IsTypeConstructionEagerlyValidated" featurevalue="false">
<method signature="System.Boolean get_IsTypeConstructionEagerlyValidated()" body="stub" />
</type>

<type fullname="System.RuntimeType" feature="System.Reflection" featurevalue="false">
<method signature="System.Boolean get_IsReflectionDisabled()" body="stub" value="true" />
</type>

</linker>
Original file line number Diff line number Diff line change
Expand Up @@ -89,19 +89,6 @@ public virtual void TryGetILOffsetWithinMethod(IntPtr ip, out int ilOffset)
ilOffset = StackFrame.OFFSET_UNKNOWN;
}

/// <summary>
/// Makes reasonable effort to get the MethodBase reflection info. Returns null if it can't.
/// </summary>
public virtual void TryGetMethodBase(IntPtr methodStartAddress, out MethodBase method)
{
ReflectionExecutionDomainCallbacks reflectionCallbacks = RuntimeAugments.CallbacksIfAvailable;
method = null;
if (reflectionCallbacks != null)
{
method = reflectionCallbacks.GetMethodBaseFromStartAddressIfAvailable(methodStartAddress);
}
}

public static DeveloperExperience Default
{
get
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,19 +35,20 @@ public static class ReflectionAugments
//
public static void Initialize(ReflectionCoreCallbacks reflectionCoreCallbacks)
{
Debug.Assert(s_reflectionCoreCallbacks == null);
s_reflectionCoreCallbacks = reflectionCoreCallbacks;
}

public static TypeCode GetRuntimeTypeCode(Type type)
internal static TypeCode GetRuntimeTypeCode(RuntimeType type)
{
Debug.Assert(type != null);

EETypePtr eeType;
if (!type.TryGetEEType(out eeType))
EETypePtr eeType = type.ToEETypePtrMayBeNull();
if (eeType.IsNull)
{
// Type exists in metadata only. Aside from the enums, there is no chance a type with a TypeCode would not have an MethodTable,
// so if it's not an enum, return the default.
if (!type.IsEnum || type.IsGenericParameter)
if (!type.IsActualEnum)
return TypeCode.Object;
Type underlyingType = Enum.GetUnderlyingType(type);
eeType = underlyingType.TypeHandle.ToEETypePtr();
Expand Down Expand Up @@ -89,11 +90,6 @@ public static TypeCode GetRuntimeTypeCode(Type type)
return TypeCode.Object;
}

public static Type MakeGenericSignatureType(Type genericTypeDefinition, Type[] genericTypeArguments)
{
return new SignatureConstructedGenericType(genericTypeDefinition, genericTypeArguments);
}

public static TypeLoadException CreateTypeLoadException(string message, string typeName)
{
return new TypeLoadException(message, typeName);
Expand All @@ -109,6 +105,14 @@ internal static ReflectionCoreCallbacks ReflectionCoreCallbacks
}
}

internal static bool IsInitialized
{
get
{
return s_reflectionCoreCallbacks != null;
}
}

private static ReflectionCoreCallbacks s_reflectionCoreCallbacks;
}

Expand Down Expand Up @@ -153,14 +157,20 @@ public abstract object ActivatorCreateInstance(

public abstract IntPtr GetFunctionPointer(RuntimeMethodHandle runtimeMethodHandle, RuntimeTypeHandle declaringTypeHandle);

public abstract void RunModuleConstructor(Module module);

public abstract void MakeTypedReference(object target, FieldInfo[] flds, out Type type, out int offset);

public abstract Assembly[] GetLoadedAssemblies();

public abstract EnumInfo GetEnumInfo(Type type, Func<Type, string[], object[], bool, EnumInfo> create);

public abstract DynamicInvokeInfo GetDelegateDynamicInvokeInfo(Type type);

public abstract MethodInfo GetDelegateMethod(Delegate del);

public abstract MethodBase GetMethodBaseFromStartAddressIfAvailable(IntPtr methodStartAddress);

public abstract Assembly GetAssemblyForHandle(RuntimeTypeHandle typeHandle);

public abstract void RunClassConstructor(RuntimeTypeHandle typeHandle);
}
}
Loading
Loading