@@ -16,16 +16,12 @@ internal static class SegmentedArrayHelper
1616 // Large value types may benefit from a smaller number.
1717 internal const int IntrosortSizeThreshold = 16 ;
1818
19- /// <summary>
20- /// A combination of <see cref="MethodImplOptions.AggressiveInlining"/> and
21- /// <see cref="F:System.Runtime.CompilerServices.MethodImplOptions.AggressiveOptimization"/>.
22- /// </summary>
23- [ SuppressMessage ( "Documentation" , "CA1200:Avoid using cref tags with a prefix" , Justification = "The field is not supported in all compilation targets." ) ]
24- internal const MethodImplOptions FastPathMethodImplOptions = MethodImplOptions . AggressiveInlining | ( MethodImplOptions ) 512 ;
25-
26- [ MethodImpl ( FastPathMethodImplOptions ) ]
19+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
2720 internal static int GetSegmentSize < T > ( )
2821 {
22+ #if NETCOREAPP3_0_OR_NEWER
23+ return InlineCalculateSegmentSize ( Unsafe . SizeOf < T > ( ) ) ;
24+ #else
2925 if ( Unsafe . SizeOf < T > ( ) == Unsafe . SizeOf < object > ( ) )
3026 {
3127 return ReferenceTypeSegmentHelper . SegmentSize ;
@@ -34,11 +30,15 @@ internal static int GetSegmentSize<T>()
3430 {
3531 return ValueTypeSegmentHelper < T > . SegmentSize ;
3632 }
33+ #endif
3734 }
3835
39- [ MethodImpl ( FastPathMethodImplOptions ) ]
36+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
4037 internal static int GetSegmentShift < T > ( )
4138 {
39+ #if NETCOREAPP3_0_OR_NEWER
40+ return InlineCalculateSegmentShift ( Unsafe . SizeOf < T > ( ) ) ;
41+ #else
4242 if ( Unsafe . SizeOf < T > ( ) == Unsafe . SizeOf < object > ( ) )
4343 {
4444 return ReferenceTypeSegmentHelper . SegmentShift ;
@@ -47,11 +47,15 @@ internal static int GetSegmentShift<T>()
4747 {
4848 return ValueTypeSegmentHelper < T > . SegmentShift ;
4949 }
50+ #endif
5051 }
5152
52- [ MethodImpl ( FastPathMethodImplOptions ) ]
53+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
5354 internal static int GetOffsetMask < T > ( )
5455 {
56+ #if NETCOREAPP3_0_OR_NEWER
57+ return InlineCalculateOffsetMask ( Unsafe . SizeOf < T > ( ) ) ;
58+ #else
5559 if ( Unsafe . SizeOf < T > ( ) == Unsafe . SizeOf < object > ( ) )
5660 {
5761 return ReferenceTypeSegmentHelper . OffsetMask ;
@@ -60,6 +64,7 @@ internal static int GetOffsetMask<T>()
6064 {
6165 return ValueTypeSegmentHelper < T > . OffsetMask ;
6266 }
67+ #endif
6368 }
6469
6570 /// <summary>
@@ -121,6 +126,31 @@ private static int CalculateOffsetMask(int segmentSize)
121126 return segmentSize - 1 ;
122127 }
123128
129+ // Faster inline implementation for NETCOREAPP to avoid static constructors and non-inlineable
130+ // generics with runtime lookups
131+ #if NETCOREAPP3_0_OR_NEWER
132+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
133+ private static int InlineCalculateSegmentSize ( int elementSize )
134+ {
135+ return 1 << InlineCalculateSegmentShift ( elementSize ) ;
136+ }
137+
138+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
139+ private static int InlineCalculateSegmentShift ( int elementSize )
140+ {
141+ // Default Large Object Heap size threshold
142+ // https://github.com/dotnet/runtime/blob/c9d69e38d0e54bea5d188593ef6c3b30139f3ab1/src/coreclr/src/gc/gc.h#L111
143+ const uint Threshold = 85000 ;
144+ return System . Numerics . BitOperations . Log2 ( ( uint ) ( ( Threshold / elementSize ) - ( 2 * Unsafe . SizeOf < object > ( ) ) ) ) ;
145+ }
146+
147+ [ MethodImpl ( MethodImplOptions . AggressiveInlining ) ]
148+ private static int InlineCalculateOffsetMask ( int elementSize )
149+ {
150+ return InlineCalculateSegmentSize ( elementSize ) - 1 ;
151+ }
152+ #endif
153+
124154 internal static class TestAccessor
125155 {
126156 public static int CalculateSegmentSize ( int elementSize )
0 commit comments