diff --git a/src/Compilers/Core/Portable/Microsoft.CodeAnalysis.csproj b/src/Compilers/Core/Portable/Microsoft.CodeAnalysis.csproj index 94c47e9a01e9e..dfe5d9e772867 100644 --- a/src/Compilers/Core/Portable/Microsoft.CodeAnalysis.csproj +++ b/src/Compilers/Core/Portable/Microsoft.CodeAnalysis.csproj @@ -7,6 +7,10 @@ true $(NetRoslynSourceBuild);netstandard2.0 $(DefineConstants);COMPILERCORE + + + $(DefineConstants);MICROSOFT_CODEANALYSIS_POOLEDOBJECTS_NO_POOLED_DISPOSER + true full true diff --git a/src/Dependencies/PooledObjects/ArrayBuilder.cs b/src/Dependencies/PooledObjects/ArrayBuilder.cs index c76055bead00d..35ab00e03a50b 100644 --- a/src/Dependencies/PooledObjects/ArrayBuilder.cs +++ b/src/Dependencies/PooledObjects/ArrayBuilder.cs @@ -16,6 +16,9 @@ namespace Microsoft.CodeAnalysis.PooledObjects [DebuggerDisplay("Count = {Count,nq}")] [DebuggerTypeProxy(typeof(ArrayBuilder<>.DebuggerProxy))] internal sealed partial class ArrayBuilder : IReadOnlyCollection, IReadOnlyList, ICollection +#if !MICROSOFT_CODEANALYSIS_POOLEDOBJECTS_NO_POOLED_DISPOSER + , IPooled +#endif { /// /// See for an explanation of this constant value. @@ -720,5 +723,49 @@ public ImmutableArray SelectDistinct(Func selector) set.Free(); return result.ToImmutableAndFree(); } + +#if !MICROSOFT_CODEANALYSIS_POOLEDOBJECTS_NO_POOLED_DISPOSER + + private static readonly ObjectPool> s_keepLargeInstancesPool = CreatePool(); + + public static PooledDisposer> GetInstance(out ArrayBuilder instance) + => GetInstance(discardLargeInstances: true, out instance); + + public static PooledDisposer> GetInstance(int capacity, out ArrayBuilder instance) + { + instance = GetInstance(capacity); + return new PooledDisposer>(instance); + } + + public static PooledDisposer> GetInstance(int capacity, T fillWithValue, out ArrayBuilder instance) + { + instance = GetInstance(capacity, fillWithValue); + return new PooledDisposer>(instance); + } + + public static PooledDisposer> GetInstance(bool discardLargeInstances, out ArrayBuilder instance) + { + // If we're discarding large instances (the default behavior), then just use the normal pool. If we're not, use + // a specific pool so that *other* normal callers don't accidentally get it and discard it. + instance = discardLargeInstances ? GetInstance() : s_keepLargeInstancesPool.Allocate(); + return new PooledDisposer>(instance, discardLargeInstances); + } + + void IPooled.Free(bool discardLargeInstances) + { + // If we're discarding large instances, use the default behavior (which already does that). Otherwise, always + // clear and free the instance back to its originating pool. + if (discardLargeInstances) + { + Free(); + } + else + { + this.Clear(); + _pool?.Free(this); + } + } + +#endif } } diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/ObjectPools/IPooled.cs b/src/Dependencies/PooledObjects/IPooled.cs similarity index 100% rename from src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/ObjectPools/IPooled.cs rename to src/Dependencies/PooledObjects/IPooled.cs diff --git a/src/Dependencies/PooledObjects/Microsoft.CodeAnalysis.PooledObjects.projitems b/src/Dependencies/PooledObjects/Microsoft.CodeAnalysis.PooledObjects.projitems index 97a2e3f5ca08f..3b563ade211f9 100644 --- a/src/Dependencies/PooledObjects/Microsoft.CodeAnalysis.PooledObjects.projitems +++ b/src/Dependencies/PooledObjects/Microsoft.CodeAnalysis.PooledObjects.projitems @@ -12,9 +12,11 @@ + + diff --git a/src/Dependencies/PooledObjects/PooledDisposer.cs b/src/Dependencies/PooledObjects/PooledDisposer.cs new file mode 100644 index 0000000000000..e497c4dbd16e9 --- /dev/null +++ b/src/Dependencies/PooledObjects/PooledDisposer.cs @@ -0,0 +1,18 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// See the LICENSE file in the project root for more information. + +#if !MICROSOFT_CODEANALYSIS_POOLEDOBJECTS_NO_POOLED_DISPOSER +using System; + +namespace Microsoft.CodeAnalysis.PooledObjects; + +internal readonly partial struct PooledDisposer( + TPoolable instance, + bool discardLargeInstances = true) : IDisposable + where TPoolable : class, IPooled +{ + void IDisposable.Dispose() + => instance?.Free(discardLargeInstances); +} +#endif diff --git a/src/Interactive/Host/Microsoft.CodeAnalysis.InteractiveHost.csproj b/src/Interactive/Host/Microsoft.CodeAnalysis.InteractiveHost.csproj index 067bc093a599f..b68db02519f4d 100644 --- a/src/Interactive/Host/Microsoft.CodeAnalysis.InteractiveHost.csproj +++ b/src/Interactive/Host/Microsoft.CodeAnalysis.InteractiveHost.csproj @@ -59,6 +59,8 @@ + + diff --git a/src/Workspaces/MSBuild/BuildHost/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.csproj b/src/Workspaces/MSBuild/BuildHost/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.csproj index 8101f56b8be6c..12380632d540f 100644 --- a/src/Workspaces/MSBuild/BuildHost/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.csproj +++ b/src/Workspaces/MSBuild/BuildHost/Microsoft.CodeAnalysis.Workspaces.MSBuild.BuildHost.csproj @@ -67,7 +67,6 @@ - diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CompilerExtensions.projitems b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CompilerExtensions.projitems index eb02e14e9ba88..97b4da66d0aed 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CompilerExtensions.projitems +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/CompilerExtensions.projitems @@ -604,9 +604,7 @@ - - diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/ObjectPools/ArrayBuilder.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/ObjectPools/ArrayBuilder.cs deleted file mode 100644 index 1d6d7630eb2d9..0000000000000 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/ObjectPools/ArrayBuilder.cs +++ /dev/null @@ -1,48 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// See the LICENSE file in the project root for more information. - -namespace Microsoft.CodeAnalysis.PooledObjects; - -internal sealed partial class ArrayBuilder : IPooled -{ - private static readonly ObjectPool> s_keepLargeInstancesPool = CreatePool(); - - public static PooledDisposer> GetInstance(out ArrayBuilder instance) - => GetInstance(discardLargeInstances: true, out instance); - - public static PooledDisposer> GetInstance(int capacity, out ArrayBuilder instance) - { - instance = GetInstance(capacity); - return new PooledDisposer>(instance); - } - - public static PooledDisposer> GetInstance(int capacity, T fillWithValue, out ArrayBuilder instance) - { - instance = GetInstance(capacity, fillWithValue); - return new PooledDisposer>(instance); - } - - public static PooledDisposer> GetInstance(bool discardLargeInstances, out ArrayBuilder instance) - { - // If we're discarding large instances (the default behavior), then just use the normal pool. If we're not, use - // a specific pool so that *other* normal callers don't accidentally get it and discard it. - instance = discardLargeInstances ? GetInstance() : s_keepLargeInstancesPool.Allocate(); - return new PooledDisposer>(instance, discardLargeInstances); - } - - void IPooled.Free(bool discardLargeInstances) - { - // If we're discarding large instances, use the default behavior (which already does that). Otherwise, always - // clear and free the instance back to its originating pool. - if (discardLargeInstances) - { - Free(); - } - else - { - this.Clear(); - _pool?.Free(this); - } - } -} diff --git a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/ObjectPools/PooledDisposer.cs b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/ObjectPools/PooledDisposer.cs index 895dd39043fa7..04475f8160883 100644 --- a/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/ObjectPools/PooledDisposer.cs +++ b/src/Workspaces/SharedUtilitiesAndExtensions/Compiler/Core/ObjectPools/PooledDisposer.cs @@ -8,9 +8,7 @@ namespace Microsoft.CodeAnalysis.PooledObjects; [NonCopyable] -internal readonly struct PooledDisposer(TPoolable instance, bool discardLargeInstances = true) : IDisposable +internal partial struct PooledDisposer where TPoolable : class, IPooled { - void IDisposable.Dispose() - => instance?.Free(discardLargeInstances); }