diff --git a/Jint/Pooling/ObjectPool.cs b/Jint/Pooling/ObjectPool.cs index 21d833a28..a65cc3ab7 100644 --- a/Jint/Pooling/ObjectPool.cs +++ b/Jint/Pooling/ObjectPool.cs @@ -57,6 +57,7 @@ private struct Element // expect to be able to satisfy most requests from it. private T _firstItem; private readonly Element[] _items; + private int _currentSlowPooledItems; // factory is stored for the lifetime of the pool. We will call this only when pool needs to // expand. compared to "new T()", Func gives more flexibility to implementers and faster @@ -158,13 +159,16 @@ internal T Allocate() private T AllocateSlow() { - var items = _items; + if (_currentSlowPooledItems <= 0) + return CreateInstance(); + var items = _items; for (int i = 0; i < items.Length; i++) { T inst = items[i].Value; if (inst is not null) { + _currentSlowPooledItems--; items[i].Value = null; return inst; } @@ -202,6 +206,9 @@ internal void Free(T obj) private void FreeSlow(T obj) { var items = _items; + if (_currentSlowPooledItems >= items.Length) + return; + for (int i = 0; i < items.Length; i++) { if (ReferenceEquals(items[i].Value, null)) @@ -209,6 +216,7 @@ private void FreeSlow(T obj) // Intentionally not using interlocked here. // In a worst case scenario two objects may be stored into same slot. // It is very unlikely to happen and will only mean that one of the objects will get collected. + _currentSlowPooledItems++; items[i].Value = obj; break; }