Skip to content

Commit

Permalink
Replace null pointer function pointer call with helpful exception. (#…
Browse files Browse the repository at this point in the history
…1866)

* Replace null pointer function pointer call with helpful exception.

* Fix typos, make exception messages consistent

* Tweak JIT conditions and helpers for better trimming

* Same tweak to 'code_writers.h'

---------

Co-authored-by: Sergio Pedri <sergio0694@live.com>
  • Loading branch information
manodasanW and Sergio0694 authored Nov 11, 2024
1 parent 93482af commit 58c60a9
Show file tree
Hide file tree
Showing 9 changed files with 213 additions and 22 deletions.
4 changes: 2 additions & 2 deletions src/WinRT.Runtime/IWinRTObject.net5.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ internal sealed bool IsInterfaceImplementedFallback(RuntimeTypeHandle interfaceT
#if NET
if (!RuntimeFeature.IsDynamicCodeCompiled)
{
return throwIfNotImplemented ? throw new NotSupportedException($"IDynamicInterfaceCastable is not supported for generic type '{type}'.") : false;
return throwIfNotImplemented ? throw new NotSupportedException($"'IDynamicInterfaceCastable' is not supported for generic type '{type}'.") : false;
}
#endif

Expand Down Expand Up @@ -104,7 +104,7 @@ internal sealed bool IsInterfaceImplementedFallback(RuntimeTypeHandle interfaceT
#if NET
if (!RuntimeFeature.IsDynamicCodeCompiled)
{
return throwIfNotImplemented ? throw new NotSupportedException($"IDynamicInterfaceCastable is not supported for generic type '{type}'.") : false;
return throwIfNotImplemented ? throw new NotSupportedException($"'IDynamicInterfaceCastable' is not supported for generic type '{type}'.") : false;
}
#endif

Expand Down
4 changes: 2 additions & 2 deletions src/WinRT.Runtime/Projections/CollectionHybrid.net5.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ interface IReadOnlyCollection<T> : global::System.Collections.Generic.IReadOnlyC
#if NET
if (!RuntimeFeature.IsDynamicCodeCompiled)
{
throw new NotSupportedException($"IDynamicInterfaceCastable is not supported for generic type argument '{typeof(T)}'.");
throw new NotSupportedException($"'IDynamicInterfaceCastable' is not supported for generic type argument '{typeof(T)}'.");
}
#endif

Expand Down Expand Up @@ -77,7 +77,7 @@ interface ICollection<T> : global::System.Collections.Generic.ICollection<T>
#if NET
if (!RuntimeFeature.IsDynamicCodeCompiled)
{
throw new NotSupportedException($"IDynamicInterfaceCastable is not supported for generic type argument '{typeof(T)}'.");
throw new NotSupportedException($"'IDynamicInterfaceCastable' is not supported for generic type argument '{typeof(T)}'.");
}
#endif

Expand Down
27 changes: 27 additions & 0 deletions src/WinRT.Runtime/Projections/IDictionary.net5.cs
Original file line number Diff line number Diff line change
Expand Up @@ -168,13 +168,37 @@ internal static class IMapMethods<K, V>
internal volatile unsafe static delegate*<IObjectReference, K, void> _Remove;
internal volatile static bool _RcwHelperInitialized;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe void EnsureInitialized()
{
if (RuntimeFeature.IsDynamicCodeCompiled)
{
return;
}

if (!_RcwHelperInitialized)
{
[DoesNotReturn]
static void ThrowNotInitialized()
{
throw new NotImplementedException(
$"Type '{typeof(global::System.Collections.Generic.IDictionary<K, V>)}' was called without initializing the RCW methods using 'IDictionaryMethods.InitRcwHelper'. " +
$"If using 'IDynamicInterfaceCastable' support to do a dynamic cast to this interface, ensure the 'InitRcwHelper' method is called.");
}

ThrowNotInitialized();
}
}

public static unsafe V Lookup(IObjectReference obj, K key)
{
EnsureInitialized();
return _Lookup(obj, key);
}

public static unsafe bool HasKey(IObjectReference obj, K key)
{
EnsureInitialized();
return _HasKey(obj, key);
}

Expand All @@ -184,6 +208,7 @@ public static unsafe bool HasKey(IObjectReference obj, K key)
// See https://github.com/dotnet/runtime/blob/main/docs/design/tools/illink/feature-checks.md.
if (!RuntimeFeature.IsDynamicCodeCompiled)
{
EnsureInitialized();
return _GetView(obj);
}

Expand All @@ -210,11 +235,13 @@ public static unsafe bool HasKey(IObjectReference obj, K key)

public static unsafe bool Insert(IObjectReference obj, K key, V value)
{
EnsureInitialized();
return _Insert(obj, key, value);
}

public static unsafe void Remove(IObjectReference obj, K key)
{
EnsureInitialized();
_Remove(obj, key);
}

Expand Down
48 changes: 48 additions & 0 deletions src/WinRT.Runtime/Projections/IEnumerable.net5.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
Expand Down Expand Up @@ -44,12 +45,35 @@ internal static class IIterableMethods<T>
internal volatile unsafe static delegate*<IObjectReference, IEnumerator<T>> _First;
internal volatile static bool _RcwHelperInitialized;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe void EnsureInitialized()
{
if (RuntimeFeature.IsDynamicCodeCompiled)
{
return;
}

if (!_RcwHelperInitialized)
{
[DoesNotReturn]
static void ThrowNotInitialized()
{
throw new NotImplementedException(
$"Type '{typeof(global::System.Collections.Generic.IEnumerable<T>)}' was called without initializing the RCW methods using 'IEnumerableMethods.InitRcwHelper'. " +
$"If using 'IDynamicInterfaceCastable' support to do a dynamic cast to this interface, ensure the 'InitRcwHelper' method is called.");
}

ThrowNotInitialized();
}
}

public unsafe static IEnumerator<T> First(IObjectReference obj)
{
// Early return to ensure things are trimmed correctly on NAOT.
// See https://github.com/dotnet/runtime/blob/main/docs/design/tools/illink/feature-checks.md.
if (!RuntimeFeature.IsDynamicCodeCompiled)
{
EnsureInitialized();
return _First(obj);
}

Expand Down Expand Up @@ -470,6 +494,28 @@ internal static class IIteratorMethods<T>
internal volatile unsafe static delegate*<IObjectReference, T[], uint> _GetMany;
internal volatile static bool _RcwHelperInitialized;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe void EnsureInitialized()
{
if (RuntimeFeature.IsDynamicCodeCompiled)
{
return;
}

if (!_RcwHelperInitialized)
{
[DoesNotReturn]
static void ThrowNotInitialized()
{
throw new NotImplementedException(
$"'{typeof(global::System.Collections.Generic.IEnumerator<T>)}' was called without initializing the RCW methods using 'IEnumeratorMethods.InitRcwHelper'. " +
$"If using IDynamicInterfaceCastable support to do a dynamic cast to this interface, ensure InitRcwHelper is called.");
}

ThrowNotInitialized();
}
}

public static unsafe bool MoveNext(IObjectReference obj)
{
var ThisPtr = obj.ThisPtr;
Expand All @@ -485,6 +531,7 @@ public static unsafe uint GetMany(IObjectReference obj, ref T[] items)
// See https://github.com/dotnet/runtime/blob/main/docs/design/tools/illink/feature-checks.md.
if (!RuntimeFeature.IsDynamicCodeCompiled)
{
EnsureInitialized();
return _GetMany(obj, items);
}

Expand Down Expand Up @@ -518,6 +565,7 @@ public static unsafe uint GetMany(IObjectReference obj, ref T[] items)

public static unsafe T get_Current(IObjectReference obj)
{
EnsureInitialized();
return _GetCurrent(obj);
}

Expand Down
46 changes: 38 additions & 8 deletions src/WinRT.Runtime/Projections/IList.net5.cs
Original file line number Diff line number Diff line change
Expand Up @@ -995,7 +995,29 @@ internal static class IVectorMethods<T>
internal volatile unsafe static delegate*<IObjectReference, uint, T[], uint> _GetMany;
internal volatile unsafe static delegate*<IObjectReference, T[], void> _ReplaceAll;
internal volatile static bool _RcwHelperInitialized;
internal volatile unsafe static delegate*<bool> _EnsureEnumerableInitialized;
internal volatile unsafe static delegate*<bool> _EnsureEnumerableInitialized;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe void EnsureInitialized()
{
if (RuntimeFeature.IsDynamicCodeCompiled)
{
return;
}

if (!_RcwHelperInitialized)
{
[DoesNotReturn]
static void ThrowNotInitialized()
{
throw new NotImplementedException(
$"Type '{typeof(global::System.Collections.Generic.IList<T>)}' was called without initializing the RCW methods using 'IListMethods.InitRcwHelper'. " +
$"If using 'IDynamicInterfaceCastable' support to do a dynamic cast to this interface, ensure the 'InitRcwHelper' method is called.");
}

ThrowNotInitialized();
}
}

public static unsafe uint get_Size(IObjectReference obj)
{
Expand All @@ -1008,6 +1030,7 @@ public static unsafe uint get_Size(IObjectReference obj)

public static unsafe T GetAt(IObjectReference obj, uint index)
{
EnsureInitialized();
return _GetAt(obj, index);
}

Expand All @@ -1016,7 +1039,8 @@ public static unsafe T GetAt(IObjectReference obj, uint index)
// Early return to ensure things are trimmed correctly on NAOT.
// See https://github.com/dotnet/runtime/blob/main/docs/design/tools/illink/feature-checks.md.
if (!RuntimeFeature.IsDynamicCodeCompiled)
{
{
EnsureInitialized();
return _GetView(obj);
}

Expand All @@ -1042,17 +1066,20 @@ public static unsafe T GetAt(IObjectReference obj, uint index)
}

public static unsafe bool IndexOf(IObjectReference obj, T value, out uint index)
{
{
EnsureInitialized();
return _IndexOf(obj, value, out index);
}

public static unsafe void SetAt(IObjectReference obj, uint index, T value)
{
{
EnsureInitialized();
_SetAt(obj, index, value);
}

public static unsafe void InsertAt(IObjectReference obj, uint index, T value)
{
{
EnsureInitialized();
_InsertAt(obj, index, value);
}

Expand All @@ -1064,7 +1091,8 @@ public static unsafe void RemoveAt(IObjectReference obj, uint index)
}

public static unsafe void Append(IObjectReference obj, T value)
{
{
EnsureInitialized();
_Append(obj, value);
}

Expand All @@ -1087,7 +1115,8 @@ public static unsafe uint GetMany(IObjectReference obj, uint startIndex, ref T[]
// Early return to ensure things are trimmed correctly on NAOT.
// See https://github.com/dotnet/runtime/blob/main/docs/design/tools/illink/feature-checks.md.
if (!RuntimeFeature.IsDynamicCodeCompiled)
{
{
EnsureInitialized();
return _GetMany(obj, startIndex, items);
}

Expand Down Expand Up @@ -1123,7 +1152,8 @@ public static unsafe void ReplaceAll(IObjectReference obj, T[] items)
// Early return to ensure things are trimmed correctly on NAOT.
// See https://github.com/dotnet/runtime/blob/main/docs/design/tools/illink/feature-checks.md.
if (!RuntimeFeature.IsDynamicCodeCompiled)
{
{
EnsureInitialized();
_ReplaceAll(obj, items);

return;
Expand Down
32 changes: 28 additions & 4 deletions src/WinRT.Runtime/Projections/IReadOnlyDictionary.net5.cs
Original file line number Diff line number Diff line change
Expand Up @@ -112,15 +112,39 @@ internal volatile unsafe static delegate*<
out global::Windows.Foundation.Collections.IMapView<K, V>,
out global::Windows.Foundation.Collections.IMapView<K, V>,
void> _Split;
internal volatile static bool _RcwHelperInitialized;
internal volatile static bool _RcwHelperInitialized;

[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static unsafe void EnsureInitialized()
{
if (RuntimeFeature.IsDynamicCodeCompiled)
{
return;
}

if (!_RcwHelperInitialized)
{
[DoesNotReturn]
static void ThrowNotInitialized()
{
throw new NotImplementedException(
$"Type '{typeof(global::System.Collections.Generic.IReadOnlyDictionary<K, V>)}' was called without initializing the RCW methods using 'IReadOnlyDictionaryMethods.InitRcwHelper'. " +
$"If using 'IDynamicInterfaceCastable' support to do a dynamic cast to this interface, ensure the 'InitRcwHelper' method is called.");
}

ThrowNotInitialized();
}
}

public static unsafe V Lookup(IObjectReference obj, K key)
{
EnsureInitialized();
return _Lookup(obj, key);
}

public static unsafe bool HasKey(IObjectReference obj, K key)
{
{
EnsureInitialized();
return _HasKey(obj, key);
}

Expand All @@ -129,9 +153,9 @@ public static unsafe void Split(IObjectReference obj, out global::Windows.Founda
// Early return to ensure things are trimmed correctly on NAOT.
// See https://github.com/dotnet/runtime/blob/main/docs/design/tools/illink/feature-checks.md.
if (!RuntimeFeature.IsDynamicCodeCompiled)
{
{
EnsureInitialized();
_Split(obj, out first, out second);

return;
}

Expand Down
18 changes: 16 additions & 2 deletions src/WinRT.Runtime/Projections/IReadOnlyList.net5.cs
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ internal static class IVectorViewMethods<T>
internal volatile unsafe static delegate*<IObjectReference, uint, T[], uint> _GetMany;
internal volatile static bool _RcwHelperInitialized;

internal static unsafe bool EnsureInitialized()
internal static unsafe void EnsureInitialized()
{
if (RuntimeFeature.IsDynamicCodeCompiled)
{
Expand Down Expand Up @@ -128,9 +128,22 @@ static void InitRcwHelperFallbackIfNeeded()
initRcwHelperFallback();
}
}

return;
}

return true;
if (!_RcwHelperInitialized)
{
[DoesNotReturn]
static void ThrowNotInitialized()
{
throw new NotImplementedException(
$"Type '{typeof(global::System.Collections.Generic.IReadOnlyList<T>)}' was called without initializing the RCW methods using 'IReadOnlyListMethods.InitRcwHelper'. " +
$"If using 'IDynamicInterfaceCastable' support to do a dynamic cast to this interface, ensure the 'InitRcwHelper' method is called.");
}

ThrowNotInitialized();
}
}

public static unsafe T GetAt(IObjectReference obj, uint index)
Expand Down Expand Up @@ -161,6 +174,7 @@ public static unsafe uint GetMany(IObjectReference obj, uint startIndex, ref T[]
// See https://github.com/dotnet/runtime/blob/main/docs/design/tools/illink/feature-checks.md.
if (!RuntimeFeature.IsDynamicCodeCompiled)
{
EnsureInitialized();
return _GetMany(obj, startIndex, items);
}

Expand Down
Loading

0 comments on commit 58c60a9

Please sign in to comment.