diff options
author | Jan Kotas <jkotas@microsoft.com> | 2015-12-29 00:05:54 +0300 |
---|---|---|
committer | Jan Kotas <jkotas@microsoft.com> | 2015-12-30 16:54:24 +0300 |
commit | 1bc1dfa2a8470ec9508e04b11d7504e7df907206 (patch) | |
tree | 7d8de2269e8647662494a4162096f5ddd14c7ce7 /src/System.Private.CoreLib | |
parent | 5a6227d2a5645cc429905654685f36b2c516e2ba (diff) |
Implement most RyuJIT intrinsics
- Add lookup of all RyuJIT intrinsics
- Update manage implementations of the intrinsics to fit with what RyuJIT is capable of
- Make intrinsic expansions by the codegen to be optional by providing fallback paths
- Fix USE_PORTABLE_HELPERS to be defined for portable runtime only
These changes are under CORERT ifdefs as necessary to be reconciled with .NET Native for UWP later.
Diffstat (limited to 'src/System.Private.CoreLib')
4 files changed, 392 insertions, 158 deletions
diff --git a/src/System.Private.CoreLib/src/System/GC.cs b/src/System.Private.CoreLib/src/System/GC.cs index cc1b7f568..812f966b1 100644 --- a/src/System.Private.CoreLib/src/System/GC.cs +++ b/src/System.Private.CoreLib/src/System/GC.cs @@ -121,11 +121,9 @@ namespace System } [Intrinsic] + [MethodImplAttribute(MethodImplOptions.NoInlining)] // disable optimizations public static void KeepAlive(Object obj) { - // This is actually an intrinsic and not a recursive function call. - // We have it here so that you can do "ldftn" on the method or reflection invoke it. - KeepAlive(obj); } // Returns the maximum GC generation. Currently assumes only 1 heap. diff --git a/src/System.Private.CoreLib/src/System/Math.cs b/src/System.Private.CoreLib/src/System/Math.cs index 80ce59eca..6af0d1c77 100644 --- a/src/System.Private.CoreLib/src/System/Math.cs +++ b/src/System.Private.CoreLib/src/System/Math.cs @@ -32,25 +32,25 @@ namespace System public const double PI = 3.14159265358979323846; public const double E = 2.7182818284590452354; - [System.Security.SecuritySafeCritical] // auto-generated + [Intrinsic] public static double Acos(double d) { return RuntimeImports.acos(d); } - [System.Security.SecuritySafeCritical] // auto-generated + [Intrinsic] public static double Asin(double d) { return RuntimeImports.asin(d); } - [System.Security.SecuritySafeCritical] // auto-generated + [Intrinsic] public static double Atan(double d) { return RuntimeImports.atan(d); } - [System.Security.SecuritySafeCritical] // auto-generated + [Intrinsic] public static double Atan2(double y, double x) { if (Double.IsInfinity(x) && Double.IsInfinity(y)) @@ -63,19 +63,19 @@ namespace System return Decimal.Ceiling(d); } - [System.Security.SecuritySafeCritical] // auto-generated + [Intrinsic] public static double Ceiling(double a) { return RuntimeImports.ceil(a); } - [System.Security.SecuritySafeCritical] // auto-generated + [Intrinsic] public static double Cos(double d) { return RuntimeImports.cos(d); } - [System.Security.SecuritySafeCritical] // auto-generated + [Intrinsic] public static double Cosh(double value) { return RuntimeImports.cosh(value); @@ -86,13 +86,12 @@ namespace System return Decimal.Floor(d); } - [System.Security.SecuritySafeCritical] // auto-generated + [Intrinsic] public static double Floor(double d) { return RuntimeImports.floor(d); } - [System.Security.SecuritySafeCritical] // auto-generated private static unsafe double InternalRound(double value, int digits, MidpointRounding mode) { if (Abs(value) < s_doubleRoundLimit) @@ -101,7 +100,7 @@ namespace System value *= power10; if (mode == MidpointRounding.AwayFromZero) { - double fraction = SplitFractionDouble(&value); + double fraction = RuntimeImports.modf(value, &value); if (Abs(fraction) >= 0.5d) { value += Sign(fraction); @@ -117,38 +116,31 @@ namespace System return value; } - [System.Security.SecuritySafeCritical] // auto-generated - private unsafe static double InternalTruncate(double d) - { - SplitFractionDouble(&d); - return d; - } - - [System.Security.SecuritySafeCritical] // auto-generated + [Intrinsic] public static double Sin(double a) { return RuntimeImports.sin(a); } - [System.Security.SecuritySafeCritical] // auto-generated + [Intrinsic] public static double Tan(double a) { return RuntimeImports.tan(a); } - [System.Security.SecuritySafeCritical] // auto-generated + [Intrinsic] public static double Sinh(double value) { return RuntimeImports.sinh(value); } - [System.Security.SecuritySafeCritical] // auto-generated + [Intrinsic] public static double Tanh(double value) { return RuntimeImports.tanh(value); } - [System.Security.SecuritySafeCritical] // auto-generated + [Intrinsic] public static double Round(double a) { // If the number has no fractional part do nothing @@ -217,43 +209,35 @@ namespace System return Decimal.Round(d, decimals, mode); } - [System.Security.SecurityCritical] // auto-generated - private static unsafe double SplitFractionDouble(double* value) - { - double incoming = *value; - double dblfrac = RuntimeImports.modf(incoming, value); - return dblfrac; - } - public static Decimal Truncate(Decimal d) { return Decimal.Truncate(d); } - public static double Truncate(double d) + public static unsafe double Truncate(double d) { - return InternalTruncate(d); + return RuntimeImports.modf(d, &d); } - [System.Security.SecuritySafeCritical] // auto-generated + [Intrinsic] public static double Sqrt(double d) { return RuntimeImports.sqrt(d); } - [System.Security.SecuritySafeCritical] // auto-generated + [Intrinsic] public static double Log(double d) { return RuntimeImports.log(d); } - [System.Security.SecuritySafeCritical] // auto-generated + [Intrinsic] public static double Log10(double d) { return RuntimeImports.log10(d); } - [System.Security.SecuritySafeCritical] // auto-generated + [Intrinsic] public static double Exp(double d) { if (Double.IsInfinity(d)) @@ -265,7 +249,7 @@ namespace System return RuntimeImports.exp(d); } - [System.Security.SecuritySafeCritical] // auto-generated + [Intrinsic] public static double Pow(double x, double y) { if (Double.IsNaN(y)) @@ -340,8 +324,93 @@ namespace System /*================================Abs========================================= **Returns the absolute value of it's argument. ============================================================================*/ + +#if CORERT + + [CLSCompliant(false)] + public static sbyte Abs(sbyte value) + { + if (value >= 0) + return value; + else + return AbsHelper(value); + } + + private static sbyte AbsHelper(sbyte value) + { + Contract.Requires(value < 0, "AbsHelper should only be called for negative values!"); + if (value == SByte.MinValue) + throw new OverflowException(SR.Overflow_NegateTwosCompNum); + Contract.EndContractBlock(); + return ((sbyte)(-value)); + } + + public static short Abs(short value) + { + if (value >= 0) + return value; + else + return AbsHelper(value); + } + + private static short AbsHelper(short value) + { + Contract.Requires(value < 0, "AbsHelper should only be called for negative values!"); + if (value == Int16.MinValue) + throw new OverflowException(SR.Overflow_NegateTwosCompNum); + Contract.EndContractBlock(); + return (short)-value; + } + + public static int Abs(int value) + { + if (value >= 0) + return value; + else + return AbsHelper(value); + } + + private static int AbsHelper(int value) + { + Contract.Requires(value < 0, "AbsHelper should only be called for negative values!"); + if (value == Int32.MinValue) + throw new OverflowException(SR.Overflow_NegateTwosCompNum); + Contract.EndContractBlock(); + return -value; + } + + public static long Abs(long value) + { + if (value >= 0) + return value; + else + return AbsHelper(value); + } + + private static long AbsHelper(long value) + { + Contract.Requires(value < 0, "AbsHelper should only be called for negative values!"); + if (value == Int64.MinValue) + throw new OverflowException(SR.Overflow_NegateTwosCompNum); + Contract.EndContractBlock(); + return -value; + } + + [Intrinsic] + public static float Abs(float value) + { + return (float)RuntimeImports.fabs(value); + } + + [Intrinsic] + public static double Abs(double value) + { + return RuntimeImports.fabs(value); + } + +#else // CORERT + [CLSCompliant(false)] - [NonVersionable] [Intrinsic] public static sbyte Abs(sbyte value) { @@ -350,7 +419,6 @@ namespace System return Abs(value); } - [NonVersionable] [Intrinsic] public static short Abs(short value) { @@ -359,7 +427,6 @@ namespace System return Abs(value); } - [NonVersionable] [Intrinsic] public static int Abs(int value) { @@ -368,7 +435,6 @@ namespace System return Abs(value); } - [NonVersionable] [Intrinsic] public static long Abs(long value) { @@ -377,8 +443,6 @@ namespace System return Abs(value); } - [System.Security.SecuritySafeCritical] // auto-generated - [NonVersionable] [Intrinsic] public static float Abs(float value) { @@ -387,17 +451,6 @@ namespace System return Abs(value); } - // This is special code to handle NaN (We need to make sure NaN's aren't - // negated). In CSharp, the else clause here should always be taken if - // value is NaN, since the normal case is taken if and only if value < 0. - // To illustrate this completely, a compiler has translated this into: - // "load value; load 0; bge; ret -value ; ret value". - // The bge command branches for comparisons with the unordered NaN. So - // it runs the else case, which returns +value instead of negating it. - // return (value < 0) ? -value : value; - - [System.Security.SecuritySafeCritical] // auto-generated - [NonVersionable] [Intrinsic] public static double Abs(double value) { @@ -406,14 +459,7 @@ namespace System return Abs(value); } - // This is special code to handle NaN (We need to make sure NaN's aren't - // negated). In CSharp, the else clause here should always be taken if - // value is NaN, since the normal case is taken if and only if value < 0. - // To illustrate this completely, a compiler has translated this into: - // "load value; load 0; bge; ret -value ; ret value". - // The bge command branches for comparisons with the unordered NaN. So - // it runs the else case, which returns +value instead of negating it. - // return (value < 0) ? -value : value; +#endif // CORERT public static Decimal Abs(Decimal value) { diff --git a/src/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs b/src/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs index 6e46d034a..4d596850b 100644 --- a/src/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs +++ b/src/System.Private.CoreLib/src/System/Runtime/RuntimeImports.cs @@ -549,6 +549,44 @@ namespace System.Runtime [RuntimeImport(RuntimeLibrary, "RhpEtwExceptionThrown")] internal extern static unsafe void RhpEtwExceptionThrown(char* exceptionTypeName, char* exceptionMessage, IntPtr faultingIP, long hresult); +#if CORERT + // + // Interlocked helpers + // + [MethodImplAttribute(MethodImplOptions.InternalCall)] + [RuntimeImport(RuntimeLibrary, "RhpLockCmpXchg32")] + internal extern static int InterlockedCompareExchange(ref int location1, int value, int comparand); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + [RuntimeImport(RuntimeLibrary, "RhpLockCmpXchg64")] + internal extern static long InterlockedCompareExchange(ref long location1, long value, long comparand); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] +#if BIT64 + [RuntimeImport(RuntimeLibrary, "RhpLockCmpXchg64")] +#else + [RuntimeImport(RuntimeLibrary, "RhpLockCmpXchg32")] +#endif + internal extern static IntPtr InterlockedCompareExchange(ref IntPtr location1, IntPtr value, IntPtr comparand); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + [RuntimeImport(RuntimeLibrary, "RhpCheckedLockCmpXchg")] + internal extern static object InterlockedCompareExchange(ref object location1, object value, object comparand); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + [RuntimeImport(RuntimeLibrary, "RhpCheckedXchg")] + internal extern static object InterlockedExchange(ref object location1, object value); + + [MethodImplAttribute(MethodImplOptions.InternalCall)] + [RuntimeImport(RuntimeLibrary, "RhpMemoryBarrier")] + internal extern static void MemoryBarrier(); + + [Intrinsic] + [MethodImplAttribute(MethodImplOptions.InternalCall)] + [RuntimeImport(RuntimeLibrary, "fabs")] + internal static extern double fabs(double x); +#endif // CORERT + [Intrinsic] [MethodImplAttribute(MethodImplOptions.InternalCall)] [RuntimeImport(RuntimeLibrary, "_copysign")] diff --git a/src/System.Private.CoreLib/src/System/Threading/Interlocked.cs b/src/System.Private.CoreLib/src/System/Threading/Interlocked.cs index e450853ae..55211b10f 100644 --- a/src/System.Private.CoreLib/src/System/Threading/Interlocked.cs +++ b/src/System.Private.CoreLib/src/System/Threading/Interlocked.cs @@ -1,108 +1,304 @@ // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. +using System.Runtime; using System.Runtime.CompilerServices; +using System.Runtime.Versioning; namespace System.Threading { public static class Interlocked { +#if CORERT + #region CompareExchange [Intrinsic] public static int CompareExchange(ref int location1, int value, int comparand) { -#if CORERT - // CORERT-TODO: Implement interlocked intrinsics - var oldValue = location1; - if (oldValue == comparand) - location1 = value; + return RuntimeImports.InterlockedCompareExchange(ref location1, value, comparand); + } + + [Intrinsic] + public static long CompareExchange(ref long location1, long value, long comparand) + { + return RuntimeImports.InterlockedCompareExchange(ref location1, value, comparand); + } + + [Intrinsic] + public static IntPtr CompareExchange(ref IntPtr location1, IntPtr value, IntPtr comparand) + { + return RuntimeImports.InterlockedCompareExchange(ref location1, value, comparand); + } + + [Intrinsic] + public static unsafe float CompareExchange(ref float location1, float value, float comparand) + { + float ret; + fixed (float * pLocation = &location1) + *(int*)&ret = CompareExchange(ref *(int*)pLocation, *(int*)&value, *(int*)&comparand); + return ret; + } + + [Intrinsic] + public static unsafe double CompareExchange(ref double location1, double value, double comparand) + { + double ret; + fixed (double * pLocation = &location1) + *(long*)&ret = CompareExchange(ref *(long*)pLocation, *(long*)&value, *(long*)&comparand); + return ret; + } + + [Intrinsic] + [NonVersionable] + public static T CompareExchange<T>(ref T location1, T value, T comparand) where T : class + { + // This method is implemented elsewhere in the toolchain for now + // Replace with regular implementation once ref locals are available in C# (https://github.com/dotnet/roslyn/issues/118) + throw new PlatformNotSupportedException(); + } + + [Intrinsic] + internal static T CompareExchange<T>(IntPtr location1, T value, T comparand) where T : class + { + // This method is implemented elsewhere in the toolchain for now + // Replace with regular implementation once ref locals are available in C# (https://github.com/dotnet/roslyn/issues/118) + throw new PlatformNotSupportedException(); + } + + [Intrinsic] + public static object CompareExchange(ref object location1, object value, object comparand) + { + return RuntimeImports.InterlockedCompareExchange(ref location1, value, comparand); + } + + #endregion + + #region Exchange + + [Intrinsic] + public static int Exchange(ref int location1, int value) + { + int oldValue; + + do + { + oldValue = location1; + } while (CompareExchange(ref location1, value, oldValue) != oldValue); + return oldValue; -#else + } + + [Intrinsic] + public static long Exchange(ref long location1, long value) + { + long oldValue; + + do + { + oldValue = location1; + } while (CompareExchange(ref location1, value, oldValue) != oldValue); + + return oldValue; + } + + [Intrinsic] + public static IntPtr Exchange(ref IntPtr location1, IntPtr value) + { + IntPtr oldValue; + + do + { + oldValue = location1; + } while (CompareExchange(ref location1, value, oldValue) != oldValue); + + return oldValue; + } + + [Intrinsic] + public static unsafe float Exchange(ref float location1, float value) + { + float ret; + fixed (float * pLocation = &location1) + *(int*)&ret = Exchange(ref *(int*)pLocation, *(int*)&value); + return ret; + } + + [Intrinsic] + public static unsafe double Exchange(ref double location1, double value) + { + double ret; + fixed (double* pLocation = &location1) + *(long*)&ret = Exchange(ref *(long*)pLocation, *(long*)&value); + return ret; + } + + [Intrinsic] + [NonVersionable] + public static T Exchange<T>(ref T location1, T value) where T : class + { + // This method is implemented elsewhere in the toolchain for now + // Implementat directly once ref locals are available in C# (https://github.com/dotnet/roslyn/issues/118) + throw new PlatformNotSupportedException(); + } + + [Intrinsic] + internal static T Exchange<T>(IntPtr location1, T value) where T : class + { + // This method is implemented elsewhere in the toolchain for now + // Implementat directly once ref locals are available in C# (https://github.com/dotnet/roslyn/issues/118) + throw new PlatformNotSupportedException(); + } + + [Intrinsic] + public static object Exchange(ref object location1, object value) + { + return RuntimeImports.InterlockedExchange(ref location1, value); + } + + #endregion + + #region Increment + + [Intrinsic] + public static int Increment(ref int location) + { + return ExchangeAdd(ref location, 1) + 1; + } + + [Intrinsic] + public static long Increment(ref long location) + { + return ExchangeAdd(ref location, 1) + 1; + } + + #endregion + + #region Decrement + + [Intrinsic] + public static int Decrement(ref int location) + { + return ExchangeAdd(ref location, -1) - 1; + } + + [Intrinsic] + public static long Decrement(ref long location) + { + return ExchangeAdd(ref location, -1) - 1; + } + + #endregion + + #region Add + + [Intrinsic] + public static int Add(ref int location1, int value) + { + return ExchangeAdd(ref location1, value) + value; + } + + [Intrinsic] + public static long Add(ref long location1, long value) + { + return ExchangeAdd(ref location1, value) + value; + } + + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static int ExchangeAdd(ref int location1, int value) + { + int oldValue; + + do + { + oldValue = location1; + } while (CompareExchange(ref location1, oldValue + value, oldValue) != oldValue); + + return oldValue; + } + + [Intrinsic] + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static long ExchangeAdd(ref long location1, long value) + { + long oldValue; + + do + { + oldValue = location1; + } while (CompareExchange(ref location1, oldValue + value, oldValue) != oldValue); + + return oldValue; + } + + #endregion + + #region MemoryBarrier + [Intrinsic] + public static void MemoryBarrier() + { + RuntimeImports.MemoryBarrier(); + } + #endregion + + #region Read + public static long Read(ref long location) + { + return CompareExchange(ref location, 0, 0); + } + #endregion + +#else // CORERT + + #region CompareExchange + + [Intrinsic] + public static int CompareExchange(ref int location1, int value, int comparand) + { // This is actually an intrinsic and not a recursive function call. // We have it here so that you can do "ldftn" on the method or reflection invoke it. return CompareExchange(ref location1, value, comparand); -#endif } [Intrinsic] public static long CompareExchange(ref long location1, long value, long comparand) { -#if CORERT - // CORERT-TODO: Implement interlocked intrinsics - var oldValue = location1; - if (oldValue == comparand) - location1 = value; - return oldValue; -#else // This is actually an intrinsic and not a recursive function call. // We have it here so that you can do "ldftn" on the method or reflection invoke it. return CompareExchange(ref location1, value, comparand); -#endif } [Intrinsic] public static IntPtr CompareExchange(ref IntPtr location1, IntPtr value, IntPtr comparand) { -#if CORERT - // CORERT-TODO: Implement interlocked intrinsics - var oldValue = location1; - if (oldValue == comparand) - location1 = value; - return oldValue; -#else // This is actually an intrinsic and not a recursive function call. // We have it here so that you can do "ldftn" on the method or reflection invoke it. return CompareExchange(ref location1, value, comparand); -#endif } [Intrinsic] public static float CompareExchange(ref float location1, float value, float comparand) { -#if CORERT - // CORERT-TODO: Implement interlocked intrinsics - var oldValue = location1; - if (oldValue == comparand) - location1 = value; - return oldValue; -#else // This is actually an intrinsic and not a recursive function call. // We have it here so that you can do "ldftn" on the method or reflection invoke it. return CompareExchange(ref location1, value, comparand); -#endif } [Intrinsic] public static double CompareExchange(ref double location1, double value, double comparand) { -#if CORERT - // CORERT-TODO: Implement interlocked intrinsics - var oldValue = location1; - if (oldValue == comparand) - location1 = value; - return oldValue; -#else // This is actually an intrinsic and not a recursive function call. // We have it here so that you can do "ldftn" on the method or reflection invoke it. return CompareExchange(ref location1, value, comparand); -#endif } [Intrinsic] public static T CompareExchange<T>(ref T location1, T value, T comparand) where T : class { -#if CORERT - // CORERT-TODO: Implement interlocked intrinsics - var oldValue = location1; - if (oldValue == comparand) - location1 = value; - return oldValue; -#else // This is actually an intrinsic and not a recursive function call. // We have it here so that you can do "ldftn" on the method or reflection invoke it. return CompareExchange<T>(ref location1, value, comparand); -#endif } public static object CompareExchange(ref object location1, object value, object comparand) @@ -120,16 +316,9 @@ namespace System.Threading [Intrinsic] public static int Exchange(ref int location1, int value) { -#if CORERT - // CORERT-TODO: Implement interlocked intrinsics - var oldValue = location1; - location1 = value; - return oldValue; -#else // This is actually an intrinsic and not a recursive function call. // We have it here so that you can do "ldftn" on the method or reflection invoke it. return Exchange(ref location1, value); -#endif } #if X86 @@ -149,47 +338,26 @@ namespace System.Threading [Intrinsic] public static long Exchange(ref long location1, long value) { -#if CORERT - // CORERT-TODO: Implement interlocked intrinsics - var oldValue = location1; - location1 = value; - return oldValue; -#else // This is actually an intrinsic and not a recursive function call. // We have it here so that you can do "ldftn" on the method or reflection invoke it. return Exchange(ref location1, value); -#endif } #endif [Intrinsic] public static IntPtr Exchange(ref IntPtr location1, IntPtr value) { -#if CORERT - // CORERT-TODO: Implement interlocked intrinsics - var oldValue = location1; - location1 = value; - return oldValue; -#else // This is actually an intrinsic and not a recursive function call. // We have it here so that you can do "ldftn" on the method or reflection invoke it. return Exchange(ref location1, value); -#endif } [Intrinsic] public static float Exchange(ref float location1, float value) { -#if CORERT - // CORERT-TODO: Implement interlocked intrinsics - var oldValue = location1; - location1 = value; - return oldValue; -#else // This is actually an intrinsic and not a recursive function call. // We have it here so that you can do "ldftn" on the method or reflection invoke it. return Exchange(ref location1, value); -#endif } #if X86 @@ -209,32 +377,18 @@ namespace System.Threading [Intrinsic] public static double Exchange(ref double location1, double value) { -#if CORERT - // CORERT-TODO: Implement interlocked intrinsics - var oldValue = location1; - location1 = value; - return oldValue; -#else // This is actually an intrinsic and not a recursive function call. // We have it here so that you can do "ldftn" on the method or reflection invoke it. return Exchange(ref location1, value); -#endif } #endif [Intrinsic] public static T Exchange<T>(ref T location1, T value) where T : class { -#if CORERT - // CORERT-TODO: Implement interlocked intrinsics - var oldValue = location1; - location1 = value; - return oldValue; -#else // This is actually an intrinsic and not a recursive function call. // We have it here so that you can do "ldftn" on the method or reflection invoke it. return Exchange<T>(ref location1, value); -#endif } [Intrinsic] @@ -356,13 +510,9 @@ namespace System.Threading [Intrinsic] public static void MemoryBarrier() { -#if CORERT - // CORERT-TODO: Implement interlocked intrinsics -#else // This is actually an intrinsic and not a recursive function call. // We have it here so that you can do "ldftn" on the method or reflection invoke it. MemoryBarrier(); -#endif } #endregion @@ -372,5 +522,7 @@ namespace System.Threading return Interlocked.CompareExchange(ref location, 0, 0); } #endregion + +#endif // CORERT } } |