What is the purpose of _HACK methods in System.Internal (.net 4.0 on x64)

In mscorlib.net 4.0 on x64, there is a System.Internal class that contains three static methods with the suffix _HACK . Does anyone have any idea what the purpose of these methods is?

Here is the output of the .NET Reflector:

 internal static class Internal { // Methods private static void CommonlyUsedGenericInstantiations_HACK() { Array.Sort<double>(null); Array.Sort<int>(null); Array.Sort<IntPtr>(null); new ArraySegment<byte>(new byte[1], 0, 0); new Dictionary<char, object>(); new Dictionary<Guid, byte>(); new Dictionary<Guid, object>(); new Dictionary<Guid, Guid>(); new Dictionary<short, IntPtr>(); new Dictionary<int, byte>(); new Dictionary<int, int>(); new Dictionary<int, object>(); new Dictionary<IntPtr, bool>(); new Dictionary<IntPtr, short>(); new Dictionary<object, bool>(); new Dictionary<object, char>(); new Dictionary<object, Guid>(); new Dictionary<object, int>(); new Dictionary<object, long>(); new Dictionary<uint, WeakReference>(); new Dictionary<object, uint>(); new Dictionary<uint, object>(); new Dictionary<long, object>(); new Dictionary<MemberTypes, object>(); new EnumEqualityComparer<MemberTypes>(); new Dictionary<object, KeyValuePair<object, object>>(); new Dictionary<KeyValuePair<object, object>, object>(); NullableHelper_HACK<bool>(); NullableHelper_HACK<byte>(); NullableHelper_HACK<char>(); NullableHelper_HACK<DateTime>(); NullableHelper_HACK<decimal>(); NullableHelper_HACK<double>(); NullableHelper_HACK<Guid>(); NullableHelper_HACK<short>(); NullableHelper_HACK<int>(); NullableHelper_HACK<long>(); NullableHelper_HACK<float>(); NullableHelper_HACK<TimeSpan>(); NullableHelper_HACK<DateTimeOffset>(); new List<bool>(); new List<byte>(); new List<char>(); new List<DateTime>(); new List<decimal>(); new List<double>(); new List<Guid>(); new List<short>(); new List<int>(); new List<long>(); new List<TimeSpan>(); new List<sbyte>(); new List<float>(); new List<ushort>(); new List<uint>(); new List<ulong>(); new List<IntPtr>(); new List<KeyValuePair<object, object>>(); new List<GCHandle>(); new List<DateTimeOffset>(); RuntimeType.RuntimeTypeCache.Prejitinit_HACK(); new CerArrayList<RuntimeMethodInfo>(0); new CerArrayList<RuntimeConstructorInfo>(0); new CerArrayList<RuntimePropertyInfo>(0); new CerArrayList<RuntimeEventInfo>(0); new CerArrayList<RuntimeFieldInfo>(0); new CerArrayList<RuntimeType>(0); new KeyValuePair<char, ushort>('\0', 0); new KeyValuePair<ushort, double>(0, double.MinValue); new KeyValuePair<object, int>(string.Empty, -2147483648); new KeyValuePair<int, int>(-2147483648, -2147483648); SZArrayHelper_HACK<bool>(null); SZArrayHelper_HACK<byte>(null); SZArrayHelper_HACK<DateTime>(null); SZArrayHelper_HACK<decimal>(null); SZArrayHelper_HACK<double>(null); SZArrayHelper_HACK<Guid>(null); SZArrayHelper_HACK<short>(null); SZArrayHelper_HACK<int>(null); SZArrayHelper_HACK<long>(null); SZArrayHelper_HACK<TimeSpan>(null); SZArrayHelper_HACK<sbyte>(null); SZArrayHelper_HACK<float>(null); SZArrayHelper_HACK<ushort>(null); SZArrayHelper_HACK<uint>(null); SZArrayHelper_HACK<ulong>(null); SZArrayHelper_HACK<DateTimeOffset>(null); SZArrayHelper_HACK<CustomAttributeTypedArgument>(null); SZArrayHelper_HACK<CustomAttributeNamedArgument>(null); } private static T NullableHelper_HACK<T>() where T: struct { Nullable.Compare<T>(null, null); Nullable.Equals<T>(null, null); T? nullable = null; return nullable.GetValueOrDefault(); } private static void SZArrayHelper_HACK<T>(SZArrayHelper oSZArrayHelper) { oSZArrayHelper.get_Count<T>(); oSZArrayHelper.get_Item<T>(0); oSZArrayHelper.GetEnumerator<T>(); } } 
+7
source share
3 answers

I think it covers, but adds my own interpretation. This is code generation optimization. When jitter generates code for a generic class, it only needs to create several versions of it. There, which covers any reference type, why you see the object that is used in the code. And there is each for each individual type of value. That's why you see bytes, bool, short, int, uint are popular.

This code lives in mscorlib.dll and therefore is available in precompiled form in the ngen-ed image. Which jitter can then be used directly without the need to generate machine code on the fly. In fact, this workaround for ngen is unable to guess the front which common instances will be required. Obviously, it is not practical to exhaust all possible combinations, especially for a class like Dictionary <>. They no doubt analyzed a bunch of code to find out which common type arguments are most popular, possibly starting with the structure itself.

+4
source

It seems that the code guarantees that these functions and objects were created (according to @usr, it is NGEN that will execute these instances). This method is also common in C ++ to ensure that specific template instances are compiled into a library.

0
source

Jeremy Willcock is not entirely correct: this is not aimed at JIT, but at the NGEN compiler. It creates a basic-static native dll from a managed dll. JIT does not care about these instances.

0
source

All Articles