From e19848c52fd43582578d3b913a24e1d8927697c1 Mon Sep 17 00:00:00 2001 From: mikedn Date: Thu, 12 Jan 2017 22:59:10 +0200 Subject: [PATCH] Prefer using Array.Length as upper for loop limit (dotnet/coreclr#8923) The JIT can't eliminate range checks if it can't "see" Length and uses loop cloning which generates a lot of code. Even in cases where not all range checks can be eliminated and loop cloning is used anyway it's still preferable to have fewer range checks. For example, SortExceptions is ~140 bytes shorter after this change, despite the fact that loop cloning is still being used. Commit migrated from https://github.com/dotnet/coreclr/commit/01a9eaaa14fc3de8f11eafa6155af8ce4e44e9e9 --- .../src/mscorlib/src/System/MulticastDelegate.cs | 5 ++--- .../src/mscorlib/src/System/Reflection/Assembly.cs | 14 +++++++------- .../src/System/Reflection/Emit/DynamicILGenerator.cs | 20 ++++++++------------ .../src/System/Reflection/Emit/ILGenerator.cs | 11 ++++------- .../src/System/Reflection/Emit/ModuleBuilder.cs | 17 +++++++++-------- .../src/mscorlib/src/System/Reflection/MdImport.cs | 2 +- .../Runtime/CompilerServices/ConditionalWeakTable.cs | 2 +- 7 files changed, 32 insertions(+), 39 deletions(-) diff --git a/src/coreclr/src/mscorlib/src/System/MulticastDelegate.cs b/src/coreclr/src/mscorlib/src/System/MulticastDelegate.cs index a7b244c..aa3271c 100644 --- a/src/coreclr/src/mscorlib/src/System/MulticastDelegate.cs +++ b/src/coreclr/src/mscorlib/src/System/MulticastDelegate.cs @@ -466,10 +466,9 @@ namespace System { // Create an array of delegate copies and each // element into the array - int invocationCount = (int)_invocationCount; - del = new Delegate[invocationCount]; + del = new Delegate[(int)_invocationCount]; - for (int i = 0; i < invocationCount; i++) + for (int i = 0; i < del.Length; i++) del[i] = (Delegate)invocationList[i]; } return del; diff --git a/src/coreclr/src/mscorlib/src/System/Reflection/Assembly.cs b/src/coreclr/src/mscorlib/src/System/Reflection/Assembly.cs index 677e4aa..2efd48d 100644 --- a/src/coreclr/src/mscorlib/src/System/Reflection/Assembly.cs +++ b/src/coreclr/src/mscorlib/src/System/Reflection/Assembly.cs @@ -573,11 +573,10 @@ namespace System.Reflection { Module[] m = GetModules(false); - int iNumModules = m.Length; int iFinalLength = 0; - Type[][] ModuleTypes = new Type[iNumModules][]; + Type[][] ModuleTypes = new Type[m.Length][]; - for (int i = 0; i < iNumModules; i++) + for (int i = 0; i < ModuleTypes.Length; i++) { ModuleTypes[i] = m[i].GetTypes(); iFinalLength += ModuleTypes[i].Length; @@ -585,7 +584,7 @@ namespace System.Reflection int iCurrent = 0; Type[] ret = new Type[iFinalLength]; - for (int i = 0; i < iNumModules; i++) + for (int i = 0; i < ModuleTypes.Length; i++) { int iLength = ModuleTypes[i].Length; Array.Copy(ModuleTypes[i], 0, ret, iCurrent, iLength); @@ -1515,13 +1514,14 @@ namespace System.Reflection public override FileStream[] GetFiles(bool getResourceModules) { Module[] m = GetModules(getResourceModules); - int iLength = m.Length; - FileStream[] fs = new FileStream[iLength]; + FileStream[] fs = new FileStream[m.Length]; - for(int i = 0; i < iLength; i++) + for (int i = 0; i < fs.Length; i++) + { fs[i] = new FileStream(((RuntimeModule)m[i]).GetFullyQualifiedName(), FileMode.Open, FileAccess.Read, FileShare.Read, FileStream.DefaultBufferSize, false); + } return fs; } diff --git a/src/coreclr/src/mscorlib/src/System/Reflection/Emit/DynamicILGenerator.cs b/src/coreclr/src/mscorlib/src/System/Reflection/Emit/DynamicILGenerator.cs index 9e1d829..ed3ab07 100644 --- a/src/coreclr/src/mscorlib/src/System/Reflection/Emit/DynamicILGenerator.cs +++ b/src/coreclr/src/mscorlib/src/System/Reflection/Emit/DynamicILGenerator.cs @@ -520,22 +520,18 @@ namespace System.Reflection.Emit Type[] parameterTypes, Type[] optionalParameterTypes) { - int cParams; - int i; - SignatureHelper sig; - if (parameterTypes == null) - cParams = 0; - else - cParams = parameterTypes.Length; - sig = SignatureHelper.GetMethodSigHelper(call, returnType); - for (i = 0; i < cParams; i++) - sig.AddArgument(parameterTypes[i]); + SignatureHelper sig = SignatureHelper.GetMethodSigHelper(call, returnType); + if (parameterTypes != null) + { + foreach (Type t in parameterTypes) + sig.AddArgument(t); + } if (optionalParameterTypes != null && optionalParameterTypes.Length != 0) { // add the sentinel sig.AddSentinel(); - for (i = 0; i < optionalParameterTypes.Length; i++) - sig.AddArgument(optionalParameterTypes[i]); + foreach (Type t in optionalParameterTypes) + sig.AddArgument(t); } return sig; } diff --git a/src/coreclr/src/mscorlib/src/System/Reflection/Emit/ILGenerator.cs b/src/coreclr/src/mscorlib/src/System/Reflection/Emit/ILGenerator.cs index 716e85a..b7d7e3f 100644 --- a/src/coreclr/src/mscorlib/src/System/Reflection/Emit/ILGenerator.cs +++ b/src/coreclr/src/mscorlib/src/System/Reflection/Emit/ILGenerator.cs @@ -388,20 +388,17 @@ namespace System.Reflection.Emit // Just a cheap insertion sort. We don't expect many exceptions (<10), where InsertionSort beats QuickSort. // If we have more exceptions than this in real life, we should consider moving to a QuickSort. - int least; - __ExceptionInfo temp; - int length = exceptions.Length; - for (int i =0; i < length; i++) + for (int i = 0; i < exceptions.Length; i++) { - least = i; - for (int j =i + 1; j < length; j++) + int least = i; + for (int j = i + 1; j < exceptions.Length; j++) { if (exceptions[least].IsInner(exceptions[j])) { least = j; } } - temp = exceptions[i]; + __ExceptionInfo temp = exceptions[i]; exceptions[i] = exceptions[least]; exceptions[least] = temp; } diff --git a/src/coreclr/src/mscorlib/src/System/Reflection/Emit/ModuleBuilder.cs b/src/coreclr/src/mscorlib/src/System/Reflection/Emit/ModuleBuilder.cs index 00ca23f..e080134 100644 --- a/src/coreclr/src/mscorlib/src/System/Reflection/Emit/ModuleBuilder.cs +++ b/src/coreclr/src/mscorlib/src/System/Reflection/Emit/ModuleBuilder.cs @@ -404,12 +404,11 @@ namespace System.Reflection.Emit if (parameters == null) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidConstructorInfo")); - int count = parameters.Length; - Type[] parameterTypes = new Type[count]; - Type[][] requiredCustomModifiers = new Type[count][]; - Type[][] optionalCustomModifiers = new Type[count][]; + Type[] parameterTypes = new Type[parameters.Length]; + Type[][] requiredCustomModifiers = new Type[parameters.Length][]; + Type[][] optionalCustomModifiers = new Type[parameters.Length][]; - for (int i = 0; i < count; i++) + for (int i = 0; i < parameters.Length; i++) { if (parameters[i] == null) throw new ArgumentException(Environment.GetResourceString("Argument_InvalidConstructorInfo")); @@ -603,12 +602,14 @@ namespace System.Reflection.Emit internal SignatureHelper GetMemberRefSignature(CallingConventions call, Type returnType, Type[] parameterTypes, IEnumerable optionalParameterTypes, int cGenericParameters) { - int cParams = (parameterTypes == null) ? 0 : parameterTypes.Length; SignatureHelper sig = SignatureHelper.GetMethodSigHelper(this, call, returnType, cGenericParameters); - for (int i = 0; i < cParams; i++) + if (parameterTypes != null) { - sig.AddArgument(parameterTypes[i]); + foreach (Type t in parameterTypes) + { + sig.AddArgument(t); + } } if (optionalParameterTypes != null) { diff --git a/src/coreclr/src/mscorlib/src/System/Reflection/MdImport.cs b/src/coreclr/src/mscorlib/src/System/Reflection/MdImport.cs index bbdf948..dc6b726 100644 --- a/src/coreclr/src/mscorlib/src/System/Reflection/MdImport.cs +++ b/src/coreclr/src/mscorlib/src/System/Reflection/MdImport.cs @@ -408,7 +408,7 @@ namespace System.Reflection return null; char[] c = new char[length]; - for (int i = 0; i < length; i ++) + for (int i = 0; i < c.Length; i ++) { #if ALIGN_ACCESS c[i] = (char)Marshal.ReadInt16( (IntPtr) (((char*)name) + i) ); diff --git a/src/coreclr/src/mscorlib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs b/src/coreclr/src/mscorlib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs index 7455967..2c19d98 100644 --- a/src/coreclr/src/mscorlib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs +++ b/src/coreclr/src/mscorlib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs @@ -594,7 +594,7 @@ namespace System.Runtime.CompilerServices // Reallocate both buckets and entries and rebuild the bucket and entries from scratch. // This serves both to scrub entries with expired keys and to put the new entries in the proper bucket. int[] newBuckets = new int[newSize]; - for (int bucketIndex = 0; bucketIndex < newSize; bucketIndex++) + for (int bucketIndex = 0; bucketIndex < newBuckets.Length; bucketIndex++) { newBuckets[bucketIndex] = -1; } -- 2.7.4