< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 52
Coverable lines: 52
Total lines: 122
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 10
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)100%110%
GetMemoryBlock()100%110%
.ctor()100%110%
Release()0%440%
GetBlobs()0%220%
TryGetMemoryBlock(...)0%220%
AddBlob(...)100%110%
GetOrCreateVirtualHeap(...)0%220%

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Internal/VirtualHeap.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Collections.Generic;
 5using System.Reflection.Internal;
 6using System.Runtime.CompilerServices;
 7using System.Runtime.InteropServices;
 8using System.Threading;
 9
 10namespace System.Reflection.Metadata.Ecma335
 11{
 12    // Container for virtual heap blobs that unpins handles on finalization.
 13    // This is not handled via dispose because the only resource is managed memory
 14    // and we don't have user visible disposable object that could own this memory.
 15    //
 16    // Since the number of virtual blobs we need is small (the number of attribute classes in .winmd files)
 17    // we can create a pinned handle for each of them.
 18    // If we needed many more blobs we could create and pin a single byte[] and allocate blobs there.
 19    internal sealed class VirtualHeap : CriticalDisposableObject
 20    {
 21        private struct PinnedBlob
 22        {
 23            // can't be read-only since GCHandle is a mutable struct
 24            public GCHandle Handle;
 25
 26            public readonly int Length;
 27
 28            public PinnedBlob(GCHandle handle, int length)
 029            {
 030                Handle = handle;
 031                Length = length;
 032            }
 33
 34            public unsafe MemoryBlock GetMemoryBlock() =>
 035                new MemoryBlock((byte*)Handle.AddrOfPinnedObject(), Length);
 36        }
 37
 38        // maps raw value of StringHandle or BlobHandle to the corresponding pinned array
 39        private Dictionary<uint, PinnedBlob>? _blobs;
 40
 041        private VirtualHeap()
 042        {
 043            _blobs = new Dictionary<uint, PinnedBlob>();
 044        }
 45
 46        protected override void Release()
 047        {
 48#if FEATURE_CER
 49            // Make sure the current thread isn't aborted in the middle of the operation.
 50            RuntimeHelpers.PrepareConstrainedRegions();
 51            try
 52            { /* intentionally left blank */ }
 53            finally
 54#endif
 055            {
 056                var blobs = Interlocked.Exchange(ref _blobs, null);
 57
 058                if (blobs != null)
 059                {
 060                    foreach (var blobPair in blobs)
 061                    {
 062                        blobPair.Value.Handle.Free();
 063                    }
 064                }
 065            }
 066        }
 67
 68        private Dictionary<uint, PinnedBlob> GetBlobs()
 069        {
 070            var blobs = _blobs;
 071            if (blobs == null)
 072            {
 073                throw new ObjectDisposedException(nameof(VirtualHeap));
 74            }
 75
 076            return blobs;
 077        }
 78
 79        public bool TryGetMemoryBlock(uint rawHandle, out MemoryBlock block)
 080        {
 081            if (!GetBlobs().TryGetValue(rawHandle, out var blob))
 082            {
 083                block = default(MemoryBlock);
 084                return false;
 85            }
 86
 087            block = blob.GetMemoryBlock();
 088            return true;
 089        }
 90
 91        internal MemoryBlock AddBlob(uint rawHandle, byte[] value)
 092        {
 093            var blobs = GetBlobs();
 94
 95            MemoryBlock result;
 96#if FEATURE_CER
 97            RuntimeHelpers.PrepareConstrainedRegions();
 98            try
 99            { /* intentionally left blank */ }
 100            finally
 101#endif
 0102            {
 0103                var blob = new PinnedBlob(GCHandle.Alloc(value, GCHandleType.Pinned), value.Length);
 0104                blobs.Add(rawHandle, blob);
 0105                result = blob.GetMemoryBlock();
 0106            }
 107
 0108            return result;
 0109        }
 110
 111        internal static VirtualHeap GetOrCreateVirtualHeap(ref VirtualHeap? lazyHeap)
 0112        {
 0113            if (lazyHeap == null)
 0114            {
 0115                Interlocked.CompareExchange(ref lazyHeap, new VirtualHeap(), null);
 0116            }
 117
 0118            return lazyHeap;
 0119        }
 120    }
 121}
 122