Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Clean up memory usage #368

Merged
merged 5 commits into from
Dec 4, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 52 additions & 0 deletions src/Microsoft.Diagnostics.Runtime/src/Builders/AppDomainBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// 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.

using Microsoft.Diagnostics.Runtime.DacInterface;
using Microsoft.Diagnostics.Runtime.Implementation;

namespace Microsoft.Diagnostics.Runtime.Builders
{
class AppDomainBuilder : IAppDomainData
{
private readonly SOSDac _sos;
private readonly AppDomainStoreData _appDomainStore;
private AppDomainData _appDomainData;

public ulong SharedDomain => _appDomainStore.SharedDomain;
public ulong SystemDomain => _appDomainStore.SystemDomain;
public int AppDomainCount => _appDomainStore.AppDomainCount;

public IAppDomainHelpers Helpers { get; }
public string Name
{
get
{
if (SharedDomain == Address)
return "Shared Domain";

if (SystemDomain == Address)
return "System Domain";

return _sos.GetAppDomainName(Address);
}
}

public int Id => _appDomainData.Id;
public ulong Address { get; private set; }

public AppDomainBuilder(SOSDac sos, IAppDomainHelpers helpers)
{
_sos = sos;
Helpers = helpers;

_sos.GetAppDomainStoreData(out _appDomainStore);
}

public bool Init(ulong address)
{
Address = address;
return _sos.GetAppDomainData(Address, out _appDomainData);
}
}
}
50 changes: 50 additions & 0 deletions src/Microsoft.Diagnostics.Runtime/src/Builders/CCWBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// 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.

using Microsoft.Diagnostics.Runtime.DacInterface;
using Microsoft.Diagnostics.Runtime.Implementation;
using System.Collections.Generic;

namespace Microsoft.Diagnostics.Runtime.Builders
{
internal class CCWBuilder : ICCWData
{
private CCWData _ccwData;
private readonly SOSDac _sos;
private readonly RuntimeBuilder _builder;

public CCWBuilder(SOSDac sos, RuntimeBuilder builder)
{
_sos = sos;
_builder = builder;
}

public bool Init(ulong obj)
{
if (!_sos.GetObjectData(obj, out V45ObjectData data))
return false;

if (data.CCW == 0)
return false;

Address = data.CCW;
return _sos.GetCCWData(data.CCW, out _ccwData);
}

public ulong Address { get; private set; }

ulong ICCWData.Address => _ccwData.CCWAddress;
ulong ICCWData.IUnknown => _ccwData.OuterIUnknown;
ulong ICCWData.Object => _ccwData.ManagedObject;
ulong ICCWData.Handle => _ccwData.Handle;
int ICCWData.RefCount => _ccwData.RefCount + _ccwData.JupiterRefCount;
int ICCWData.JupiterRefCount => _ccwData.JupiterRefCount;

IReadOnlyList<ComInterfaceData> ICCWData.GetInterfaces()
{
COMInterfacePointerData[] ifs = _sos.GetCCWInterfaces(Address, _ccwData.InterfaceCount);
return _builder.CreateComInterfaces(ifs);
}
}
}
49 changes: 49 additions & 0 deletions src/Microsoft.Diagnostics.Runtime/src/Builders/FieldBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
// 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.

using Microsoft.Diagnostics.Runtime.DacInterface;
using Microsoft.Diagnostics.Runtime.Implementation;
using System;

namespace Microsoft.Diagnostics.Runtime.Builders
{
class FieldBuilder : IFieldData, IDisposable
{
private readonly SOSDac _sos;
private FieldData _fieldData;

public IFieldHelpers Helpers { get; }

public ClrElementType ElementType => (ClrElementType)_fieldData.ElementType;

public uint Token => _fieldData.FieldToken;

public int Offset => (int)_fieldData.Offset;

public ulong TypeMethodTable => _fieldData.TypeMethodTable;

public ObjectPool<FieldBuilder> Owner { get; set; }

public ulong NextField => _fieldData.NextField;

public bool IsContextLocal => _fieldData.IsContextLocal != 0;
public bool IsStatic => _fieldData.IsStatic != 0;
public bool IsThreadLocal => _fieldData.IsThreadLocal != 0;

public FieldBuilder(SOSDac sos, IFieldHelpers helpers)
{
_sos = sos;
Helpers = helpers;
}

internal bool Init(ulong fieldDesc) => _sos.GetFieldData(fieldDesc, out _fieldData);

public void Dispose()
{
var owner = Owner;
Owner = null;
owner?.Return(this);
}
}
}
68 changes: 68 additions & 0 deletions src/Microsoft.Diagnostics.Runtime/src/Builders/MethodBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// 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.

using Microsoft.Diagnostics.Runtime.DacInterface;
using Microsoft.Diagnostics.Runtime.Implementation;
using System;

namespace Microsoft.Diagnostics.Runtime.Builders
{
class MethodBuilder : IMethodData, IDisposable
{
private readonly SOSDac _sos;
private MethodDescData _mdData;
private CodeHeaderData _codeHeaderData;

public MethodBuilder(SOSDac sos, IMethodHelpers helpers)
{
_sos = sos;
Helpers = helpers;
}

public bool Init(ulong mt, int i)
{
ulong slot = _sos.GetMethodTableSlot(mt, i);

if (!_sos.GetCodeHeaderData(slot, out _codeHeaderData))
return false;

MethodDesc = _codeHeaderData.MethodDesc;
return _sos.GetMethodDescData(_codeHeaderData.MethodDesc, 0, out _mdData);
}

public bool Init(ulong methodDesc)
{
MethodDesc = methodDesc;
if (!_sos.GetMethodDescData(methodDesc, 0, out _mdData))
return false;

ulong slot = _sos.GetMethodTableSlot(_mdData.MethodTable, _mdData.SlotNumber);

return _sos.GetCodeHeaderData(slot, out _codeHeaderData);
}

public ObjectPool<MethodBuilder> Owner { get; set; }
public IMethodHelpers Helpers { get; }

public uint Token => _mdData.MDToken;

public ulong MethodDesc { get; private set; }
public MethodCompilationType CompilationType => (MethodCompilationType)_codeHeaderData.JITType;

public ulong HotStart => _mdData.NativeCodeAddr;

public uint HotSize => _codeHeaderData.HotRegionSize;

public ulong ColdStart => _codeHeaderData.ColdRegionStart;

public uint ColdSize => _codeHeaderData.ColdRegionSize;

public void Dispose()
{
var owner = Owner;
Owner = null;
owner?.Return(this);
}
}
}
68 changes: 68 additions & 0 deletions src/Microsoft.Diagnostics.Runtime/src/Builders/ModuleBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// 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.

using Microsoft.Diagnostics.Runtime.DacInterface;
using Microsoft.Diagnostics.Runtime.Implementation;
using System.Collections.Generic;

namespace Microsoft.Diagnostics.Runtime.Builders
{
internal class ModuleBuilder : IModuleData
{
private ModuleData _moduleData;
private readonly SOSDac _sos;
private readonly Dictionary<ulong, ulong> _moduleSizes;

public ModuleBuilder(IModuleHelpers helpers, SOSDac sos, Dictionary<ulong, ulong> moduleSizes)
{
_sos = sos;
_moduleSizes = moduleSizes;
Helpers = helpers;
}

public IModuleHelpers Helpers { get; }

public ulong Address { get; private set; }

public bool IsPEFile => _moduleData.IsPEFile != 0;
public ulong PEImageBase => _moduleData.PEFile;
public ulong ILImageBase => _moduleData.ILBase;
public ulong Size => _moduleSizes.GetOrDefault(Address);
public ulong MetadataStart => _moduleData.MetadataStart;
public ulong MetadataLength => _moduleData.MetadataSize;
public string Name
{
get
{
if (_moduleData.PEFile != 0)
return _sos.GetPEFileName(_moduleData.PEFile);

return null;
}
}

public string AssemblyName
{
get
{
if (_moduleData.Assembly != 0)
return _sos.GetAssemblyName(_moduleData.Assembly);

return null;
}
}


public bool IsReflection => _moduleData.IsReflection != 0;

public ulong AssemblyAddress => _moduleData.Assembly;


public bool Init(ulong address)
{
Address = address;
return _sos.GetModuleData(Address, out _moduleData);
}
}
}
36 changes: 36 additions & 0 deletions src/Microsoft.Diagnostics.Runtime/src/Builders/ObjectPool.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// 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.

using System;
using System.Collections.Concurrent;

namespace Microsoft.Diagnostics.Runtime.Builders
{
internal sealed class ObjectPool<T>
{
private readonly ConcurrentBag<T> _bag = new ConcurrentBag<T>();
private readonly Func<T> _generator;
private readonly Action<ObjectPool<T>, T> _setOwner;

public ObjectPool(Func<T> generator, Action<ObjectPool<T>, T> setOwner)
{
_generator = generator;
_setOwner = setOwner;
}

public T Rent()
{
if (!_bag.TryTake(out T result))
result = _generator();

_setOwner(this, result);
return result;
}

public void Return(T t)
{
_bag.Add(t);
}
}
}
50 changes: 50 additions & 0 deletions src/Microsoft.Diagnostics.Runtime/src/Builders/RCWBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// 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.

using Microsoft.Diagnostics.Runtime.DacInterface;
using Microsoft.Diagnostics.Runtime.Implementation;
using System.Collections.Generic;

namespace Microsoft.Diagnostics.Runtime.Builders
{
internal class RCWBuilder : IRCWData
{
private RCWData _rcwData;
private readonly SOSDac _sos;
private readonly RuntimeBuilder _builder;

public RCWBuilder(SOSDac sos, RuntimeBuilder builder)
{
_sos = sos;
_builder = builder;
}

public bool Init(ulong obj)
{
if (!_sos.GetObjectData(obj, out V45ObjectData data))
return false;

if (data.RCW == 0)
return false;

Address = data.RCW;
return _sos.GetRCWData(data.RCW, out _rcwData);
}

public ulong Address { get; private set; }

ulong IRCWData.IUnknown => _rcwData.IUnknownPointer;
ulong IRCWData.VTablePointer => _rcwData.VTablePointer;
int IRCWData.RefCount => _rcwData.RefCount;
ulong IRCWData.ManagedObject => _rcwData.ManagedObject;
bool IRCWData.Disconnected => _rcwData.IsDisconnected != 0;
ulong IRCWData.CreatorThread => _rcwData.CreatorThread;

IReadOnlyList<ComInterfaceData> IRCWData.GetInterfaces()
{
COMInterfacePointerData[] ifs = _sos.GetRCWInterfaces(Address, _rcwData.InterfaceCount);
return _builder.CreateComInterfaces(ifs);
}
}
}
Loading