Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit adbcc28

Browse files
committed
Prefer using Array.Length as upper for loop limit
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.
1 parent 0fa2c31 commit adbcc28

File tree

7 files changed

+32
-39
lines changed

7 files changed

+32
-39
lines changed

src/mscorlib/src/System/MulticastDelegate.cs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -466,10 +466,9 @@ public override sealed Delegate[] GetInvocationList()
466466
{
467467
// Create an array of delegate copies and each
468468
// element into the array
469-
int invocationCount = (int)_invocationCount;
470-
del = new Delegate[invocationCount];
469+
del = new Delegate[(int)_invocationCount];
471470

472-
for (int i = 0; i < invocationCount; i++)
471+
for (int i = 0; i < del.Length; i++)
473472
del[i] = (Delegate)invocationList[i];
474473
}
475474
return del;

src/mscorlib/src/System/Reflection/Assembly.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -573,19 +573,18 @@ public virtual Type[] GetTypes()
573573
{
574574
Module[] m = GetModules(false);
575575

576-
int iNumModules = m.Length;
577576
int iFinalLength = 0;
578-
Type[][] ModuleTypes = new Type[iNumModules][];
577+
Type[][] ModuleTypes = new Type[m.Length][];
579578

580-
for (int i = 0; i < iNumModules; i++)
579+
for (int i = 0; i < ModuleTypes.Length; i++)
581580
{
582581
ModuleTypes[i] = m[i].GetTypes();
583582
iFinalLength += ModuleTypes[i].Length;
584583
}
585584

586585
int iCurrent = 0;
587586
Type[] ret = new Type[iFinalLength];
588-
for (int i = 0; i < iNumModules; i++)
587+
for (int i = 0; i < ModuleTypes.Length; i++)
589588
{
590589
int iLength = ModuleTypes[i].Length;
591590
Array.Copy(ModuleTypes[i], 0, ret, iCurrent, iLength);
@@ -1515,13 +1514,14 @@ public override FileStream GetFile(String name)
15151514
public override FileStream[] GetFiles(bool getResourceModules)
15161515
{
15171516
Module[] m = GetModules(getResourceModules);
1518-
int iLength = m.Length;
1519-
FileStream[] fs = new FileStream[iLength];
1517+
FileStream[] fs = new FileStream[m.Length];
15201518

1521-
for(int i = 0; i < iLength; i++)
1519+
for (int i = 0; i < fs.Length; i++)
1520+
{
15221521
fs[i] = new FileStream(((RuntimeModule)m[i]).GetFullyQualifiedName(),
15231522
FileMode.Open,
15241523
FileAccess.Read, FileShare.Read, FileStream.DefaultBufferSize, false);
1524+
}
15251525

15261526
return fs;
15271527
}

src/mscorlib/src/System/Reflection/Emit/DynamicILGenerator.cs

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -520,22 +520,18 @@ internal override SignatureHelper GetMemberRefSignature(
520520
Type[] parameterTypes,
521521
Type[] optionalParameterTypes)
522522
{
523-
int cParams;
524-
int i;
525-
SignatureHelper sig;
526-
if (parameterTypes == null)
527-
cParams = 0;
528-
else
529-
cParams = parameterTypes.Length;
530-
sig = SignatureHelper.GetMethodSigHelper(call, returnType);
531-
for (i = 0; i < cParams; i++)
532-
sig.AddArgument(parameterTypes[i]);
523+
SignatureHelper sig = SignatureHelper.GetMethodSigHelper(call, returnType);
524+
if (parameterTypes != null)
525+
{
526+
foreach (Type t in parameterTypes)
527+
sig.AddArgument(t);
528+
}
533529
if (optionalParameterTypes != null && optionalParameterTypes.Length != 0)
534530
{
535531
// add the sentinel
536532
sig.AddSentinel();
537-
for (i = 0; i < optionalParameterTypes.Length; i++)
538-
sig.AddArgument(optionalParameterTypes[i]);
533+
foreach (Type t in optionalParameterTypes)
534+
sig.AddArgument(t);
539535
}
540536
return sig;
541537
}

src/mscorlib/src/System/Reflection/Emit/ILGenerator.cs

Lines changed: 4 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -388,20 +388,17 @@ private static void SortExceptions(__ExceptionInfo []exceptions)
388388
// Just a cheap insertion sort. We don't expect many exceptions (<10), where InsertionSort beats QuickSort.
389389
// If we have more exceptions than this in real life, we should consider moving to a QuickSort.
390390

391-
int least;
392-
__ExceptionInfo temp;
393-
int length = exceptions.Length;
394-
for (int i =0; i < length; i++)
391+
for (int i = 0; i < exceptions.Length; i++)
395392
{
396-
least = i;
397-
for (int j =i + 1; j < length; j++)
393+
int least = i;
394+
for (int j = i + 1; j < exceptions.Length; j++)
398395
{
399396
if (exceptions[least].IsInner(exceptions[j]))
400397
{
401398
least = j;
402399
}
403400
}
404-
temp = exceptions[i];
401+
__ExceptionInfo temp = exceptions[i];
405402
exceptions[i] = exceptions[least];
406403
exceptions[least] = temp;
407404
}

src/mscorlib/src/System/Reflection/Emit/ModuleBuilder.cs

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -404,12 +404,11 @@ internal MethodToken InternalGetConstructorToken(ConstructorInfo con, bool using
404404
if (parameters == null)
405405
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidConstructorInfo"));
406406

407-
int count = parameters.Length;
408-
Type[] parameterTypes = new Type[count];
409-
Type[][] requiredCustomModifiers = new Type[count][];
410-
Type[][] optionalCustomModifiers = new Type[count][];
407+
Type[] parameterTypes = new Type[parameters.Length];
408+
Type[][] requiredCustomModifiers = new Type[parameters.Length][];
409+
Type[][] optionalCustomModifiers = new Type[parameters.Length][];
411410

412-
for (int i = 0; i < count; i++)
411+
for (int i = 0; i < parameters.Length; i++)
413412
{
414413
if (parameters[i] == null)
415414
throw new ArgumentException(Environment.GetResourceString("Argument_InvalidConstructorInfo"));
@@ -603,12 +602,14 @@ private int GetMemberRefToken(MethodBase method, IEnumerable<Type> optionalParam
603602
internal SignatureHelper GetMemberRefSignature(CallingConventions call, Type returnType,
604603
Type[] parameterTypes, IEnumerable<Type> optionalParameterTypes, int cGenericParameters)
605604
{
606-
int cParams = (parameterTypes == null) ? 0 : parameterTypes.Length;
607605
SignatureHelper sig = SignatureHelper.GetMethodSigHelper(this, call, returnType, cGenericParameters);
608606

609-
for (int i = 0; i < cParams; i++)
607+
if (parameterTypes != null)
610608
{
611-
sig.AddArgument(parameterTypes[i]);
609+
foreach (Type t in parameterTypes)
610+
{
611+
sig.AddArgument(t);
612+
}
612613
}
613614

614615
if (optionalParameterTypes != null) {

src/mscorlib/src/System/Reflection/MdImport.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -408,7 +408,7 @@ public unsafe String GetUserString(int mdToken)
408408
return null;
409409

410410
char[] c = new char[length];
411-
for (int i = 0; i < length; i ++)
411+
for (int i = 0; i < c.Length; i ++)
412412
{
413413
#if ALIGN_ACCESS
414414
c[i] = (char)Marshal.ReadInt16( (IntPtr) (((char*)name) + i) );

src/mscorlib/src/System/Runtime/CompilerServices/ConditionalWeakTable.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -594,7 +594,7 @@ internal Container Resize(int newSize)
594594
// Reallocate both buckets and entries and rebuild the bucket and entries from scratch.
595595
// This serves both to scrub entries with expired keys and to put the new entries in the proper bucket.
596596
int[] newBuckets = new int[newSize];
597-
for (int bucketIndex = 0; bucketIndex < newSize; bucketIndex++)
597+
for (int bucketIndex = 0; bucketIndex < newBuckets.Length; bucketIndex++)
598598
{
599599
newBuckets[bucketIndex] = -1;
600600
}

0 commit comments

Comments
 (0)