Improved BufferPool behavior

Improved BufferPool behavior:
- caching buffers via weak references
- ResizeAndFlushLeft can re-use already existing buffers
- GetBuffer can return the smallest fitting buffer for a specific size
- ResizeAndFlushLeft can handle first-chance OutOfMemoryException

Details:
When serializing large objects (>60 MB) on x86 platform the BufferPool.ResizeAndFlushLeft could throw OutOfMemoryException. The memory management could be optimized by caching previously allocated large buffers minimizing fragmentation of the Large Object Heap. The cached buffers are stored via WeakReferences to allow automatic garbage collection if needed.

ResizeAndFlushLeft  can now re-use cached buffers. First-chance OutOfMemoryException is caught and trigger full garbage collection. This can greatly improve stability on x86 platforms when serializing large objects.