Inlinable ArraySegment ctor (#9433)
authorBen Adams <thundercat@illyriad.co.uk>
Thu, 9 Feb 2017 15:11:09 +0000 (15:11 +0000)
committerJan Kotas <jkotas@microsoft.com>
Thu, 9 Feb 2017 15:11:09 +0000 (07:11 -0800)
src/mscorlib/src/System/ArraySegment.cs
src/mscorlib/src/System/ThrowHelper.cs

index b767e7b..03556e4 100644 (file)
@@ -15,8 +15,6 @@
 
 using System.Collections;
 using System.Collections.Generic;
-using System.Runtime.InteropServices;
-using System.Diagnostics;
 using System.Diagnostics.Contracts;
 
 namespace System
@@ -46,14 +44,10 @@ namespace System
 
         public ArraySegment(T[] array, int offset, int count)
         {
-            if (array == null)
-                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
-            if (offset < 0)
-                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.offset, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
-            if (count < 0)
-                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
-            if (array.Length - offset < count)
-                ThrowHelper.ThrowArgumentException(ExceptionResource.Argument_InvalidOffLen);
+            // Validate arguments, check is minimal instructions with reduced branching for inlinable fast-path
+            // Failure should be rare and location determination and message is delegated to failure functions
+            if (array == null || (offset | count) < 0 || (array.Length - offset < count))
+                ThrowHelper.ThrowArraySegmentCtorValidationFailedExceptions(array, offset, count);
             Contract.EndContractBlock();
 
             _array = array;
index 5ba7a30..a48bb60 100644 (file)
@@ -39,7 +39,6 @@ namespace System {
     using Collections.Generic;
     using System.Runtime.CompilerServices;
     using System.Runtime.Serialization;
-    using System.Diagnostics;
     using System.Diagnostics.Contracts;
 
     [Pure]
@@ -125,8 +124,12 @@ namespace System {
             throw GetArgumentException(resource, argument);
         }
 
+        private static ArgumentNullException GetArgumentNullException(ExceptionArgument argument) {
+            return new ArgumentNullException(GetArgumentName(argument));
+        }
+
         internal static void ThrowArgumentNullException(ExceptionArgument argument) {
-            throw new ArgumentNullException(GetArgumentName(argument));
+            throw GetArgumentNullException(argument);
         }
 
         internal static void ThrowArgumentNullException(ExceptionResource resource) {
@@ -209,6 +212,22 @@ namespace System {
             throw GetInvalidOperationException(ExceptionResource.InvalidOperation_EnumOpCantHappen);
         }
 
+        internal static void ThrowArraySegmentCtorValidationFailedExceptions(Array array, int offset, int count) {
+            throw GetArraySegmentCtorValidationFailedException(array, offset, count);
+        }
+
+        private static Exception GetArraySegmentCtorValidationFailedException(Array array, int offset, int count) {
+            if (array == null)
+                return GetArgumentNullException(ExceptionArgument.array);
+            if (offset < 0)
+                return GetArgumentOutOfRangeException(ExceptionArgument.offset, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+            if (count < 0)
+                return GetArgumentOutOfRangeException(ExceptionArgument.count, ExceptionResource.ArgumentOutOfRange_NeedNonNegNum);
+
+            Debug.Assert(array.Length - offset < count);
+            return GetArgumentException(ExceptionResource.Argument_InvalidOffLen);
+        }
+
         private static ArgumentException GetArgumentException(ExceptionResource resource) {
             return new ArgumentException(GetResourceString(resource));
         }