From: Vlad Brezae Date: Fri, 6 Jan 2017 00:46:29 +0000 (+0200) Subject: [corlib] Avoid unbounded resizes of ephemeron arrays X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=a3b053bacf4436f213391b9776d2ab89b8cf3ff7;p=mono.git [corlib] Avoid unbounded resizes of ephemeron arrays We compute the size of the array based on how many live ephemerons it stores, and not based on the previous size of the array which doesn't indicate anything. Fixes leak from #47388. --- diff --git a/mcs/class/corlib/System.Runtime.CompilerServices/ConditionalWeakTable.cs b/mcs/class/corlib/System.Runtime.CompilerServices/ConditionalWeakTable.cs index 8574472acb1..6d212bd210e 100644 --- a/mcs/class/corlib/System.Runtime.CompilerServices/ConditionalWeakTable.cs +++ b/mcs/class/corlib/System.Runtime.CompilerServices/ConditionalWeakTable.cs @@ -72,12 +72,28 @@ namespace System.Runtime.CompilerServices { } + private void RecomputeSize () + { + size = 0; + for (int i = 0; i < data.Length; i++) { + if (data [i].key != null) + size++; + } + } + /*LOCKING: _lock must be held*/ - void Rehash () { - uint newSize = (uint)HashHelpers.GetPrime ((data.Length << 1) | 1); - //Console.WriteLine ("--- resizing from {0} to {1}", data.Length, newSize); + private void Rehash () + { + // Size doesn't track elements that die without being removed. Before attempting + // to rehash we traverse the array to see how many entries are left alive. We + // rehash the array into a new one which has a capacity relative to the number of + // live entries. + RecomputeSize (); + + uint newLength = (uint)HashHelpers.GetPrime (((int)(size / LOAD_FACTOR) << 1) | 1); + //Console.WriteLine ("--- resizing from {0} to {1}", data.Length, newLength); - Ephemeron[] tmp = new Ephemeron [newSize]; + Ephemeron[] tmp = new Ephemeron [newLength]; GC.register_ephemeron_array (tmp); size = 0;