diff options
author | Mike Krüger <mkrueger@xamarin.com> | 2013-09-19 22:10:40 +0400 |
---|---|---|
committer | Mike Krüger <mkrueger@xamarin.com> | 2013-09-19 22:10:40 +0400 |
commit | 2442a71d3c62089e6297ad41fb74d784ebb3326e (patch) | |
tree | 7bf307f987dde9cc43aa222b570841a0439b525f /ICSharpCode.NRefactory.IKVM | |
parent | 6d88b6a8fbdc678ccf5f35c2e3ce9ca45e4ea6e5 (diff) |
Implemented special interning provider.
Diffstat (limited to 'ICSharpCode.NRefactory.IKVM')
-rw-r--r-- | ICSharpCode.NRefactory.IKVM/FastInterningProvider.cs | 130 | ||||
-rw-r--r-- | ICSharpCode.NRefactory.IKVM/ICSharpCode.NRefactory.IKVM.csproj | 1 | ||||
-rw-r--r-- | ICSharpCode.NRefactory.IKVM/IkvmLoader.cs | 1 |
3 files changed, 132 insertions, 0 deletions
diff --git a/ICSharpCode.NRefactory.IKVM/FastInterningProvider.cs b/ICSharpCode.NRefactory.IKVM/FastInterningProvider.cs new file mode 100644 index 00000000..5effc8dd --- /dev/null +++ b/ICSharpCode.NRefactory.IKVM/FastInterningProvider.cs @@ -0,0 +1,130 @@ +// Copyright (c) 2010-2013 AlphaSierraPapa for the SharpDevelop Team +// +// Permission is hereby granted, free of charge, to any person obtaining a copy of this +// software and associated documentation files (the "Software"), to deal in the Software +// without restriction, including without limitation the rights to use, copy, modify, merge, +// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons +// to whom the Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all copies or +// substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, +// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR +// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE +// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR +// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Runtime.CompilerServices; + +using ICSharpCode.NRefactory.Utils; + +namespace ICSharpCode.NRefactory.TypeSystem.Implementation +{ + /// <summary> + /// Fast interning provider. The main difference is that it only supports to intern non frozen objects. + /// </summary> + sealed class FastInterningProvider : InterningProvider + { + sealed class ListComparer : IEqualityComparer<IEnumerable> + { + public bool Equals(IEnumerable a, IEnumerable b) + { + if (a.GetType() != b.GetType()) + return false; + IEnumerator e1 = a.GetEnumerator(); + IEnumerator e2 = b.GetEnumerator(); + while (e1.MoveNext()) { + // e1 has more elements than e2; or elements are different + if (!e2.MoveNext() || e1.Current != e2.Current) + return false; + } + if (e2.MoveNext()) // e2 has more elements than e1 + return false; + // No need to dispose e1/e2: non-generic IEnumerator doesn't implement IDisposable, + // and the underlying enumerator will likely be a List<T>.Enumerator which has an empty Dispose() method. + return true; + } + + public int GetHashCode(IEnumerable obj) + { + int hashCode = obj.GetType().GetHashCode(); + unchecked { + foreach (object o in obj) { + hashCode *= 27; + hashCode += RuntimeHelpers.GetHashCode(o); + } + } + return hashCode; + } + } + + Dictionary<object, object> byValueDict = new Dictionary<object, object>(); + Dictionary<int, ISupportsInterning> supportsInternDict = new Dictionary<int, ISupportsInterning>(); + Dictionary<IEnumerable, IEnumerable> listDict = new Dictionary<IEnumerable, IEnumerable>(new ListComparer()); + + public override ISupportsInterning Intern(ISupportsInterning obj) + { + if (obj == null) + return null; + + ISupportsInterning output; + var hashCode = obj.GetHashCodeForInterning (); + if (supportsInternDict.TryGetValue(hashCode, out output)) { + return output; + } else { + // ensure objects are frozen when we put them into the dictionary + // note that Freeze may change the hash code of the object + FreezableHelper.Freeze(obj); + supportsInternDict.Add (hashCode, obj); + return obj; + } + } + + public override string Intern(string text) + { + if (text == null) + return null; + + object output; + if (byValueDict.TryGetValue(text, out output)) + return (string)output; + else + return text; + } + + public override object InternValue(object obj) + { + if (obj == null) + return null; + + object output; + if (byValueDict.TryGetValue(obj, out output)) + return output; + else + return obj; + } + + public override IList<T> InternList<T>(IList<T> list) + { + if (list == null) + return null; + if (list.Count == 0) + return EmptyList<T>.Instance; + if (!list.IsReadOnly) + list = new ReadOnlyCollection<T>(list); + IEnumerable output; + if (listDict.TryGetValue(list, out output)) + list = (IList<T>)output; + else + listDict.Add(list, list); + return list; + } + } +} diff --git a/ICSharpCode.NRefactory.IKVM/ICSharpCode.NRefactory.IKVM.csproj b/ICSharpCode.NRefactory.IKVM/ICSharpCode.NRefactory.IKVM.csproj index 8ef5b98e..ea42305a 100644 --- a/ICSharpCode.NRefactory.IKVM/ICSharpCode.NRefactory.IKVM.csproj +++ b/ICSharpCode.NRefactory.IKVM/ICSharpCode.NRefactory.IKVM.csproj @@ -44,6 +44,7 @@ <Compile Include="IntConstantValue.cs" />
<Compile Include="StructConstantValue.cs" />
<Compile Include="ShortConstantValue.cs" />
+ <Compile Include="FastInterningProvider.cs" />
</ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<ItemGroup>
diff --git a/ICSharpCode.NRefactory.IKVM/IkvmLoader.cs b/ICSharpCode.NRefactory.IKVM/IkvmLoader.cs index 9d73743f..92d5ccf2 100644 --- a/ICSharpCode.NRefactory.IKVM/IkvmLoader.cs +++ b/ICSharpCode.NRefactory.IKVM/IkvmLoader.cs @@ -74,6 +74,7 @@ namespace ICSharpCode.NRefactory.TypeSystem /// </summary> public IkvmLoader() { + interningProvider = new FastInterningProvider (); } #region Load Assembly From Disk |