diff --git a/Jenkinsfile b/Jenkinsfile
index 7180626..a434278 100644
--- a/Jenkinsfile
+++ b/Jenkinsfile
@@ -39,8 +39,8 @@ node {
} else {
buildMode = "Debug"
}
- bat "rmdir /Q /S \"bin\""
- bat "rmdir /Q /S \"bin-test\""
+ bat "IF EXIST \"bin\"rmdir /Q /S \"bin\""
+ bat "IF EXIST \"bin-test\" rmdir /Q /S \"bin-test\""
bat "\"${tool 'MSBuild'}msbuild\" Torch.sln /p:Configuration=${buildMode} /p:Platform=x64 /t:Clean"
bat "\"${tool 'MSBuild'}msbuild\" Torch.sln /p:Configuration=${buildMode} /p:Platform=x64"
}
diff --git a/Torch.Server/Torch.Server.csproj b/Torch.Server/Torch.Server.csproj
index 3208cd3..d632099 100644
--- a/Torch.Server/Torch.Server.csproj
+++ b/Torch.Server/Torch.Server.csproj
@@ -221,6 +221,7 @@
+
@@ -261,6 +262,9 @@
PluginsControl.xaml
+
+ ProfilerConfigControl.xaml
+
TorchUI.xaml
@@ -349,6 +353,10 @@
Designer
MSBuild:Compile
+
+ Designer
+ MSBuild:Compile
+
MSBuild:Compile
Designer
diff --git a/Torch.Server/ViewModels/Entities/EntityViewModel.cs b/Torch.Server/ViewModels/Entities/EntityViewModel.cs
index 08ad9ae..f9b8dcd 100644
--- a/Torch.Server/ViewModels/Entities/EntityViewModel.cs
+++ b/Torch.Server/ViewModels/Entities/EntityViewModel.cs
@@ -1,4 +1,8 @@
-using VRage.Game.ModAPI;
+using System.Windows.Controls;
+using Torch.API.Managers;
+using Torch.Collections;
+using Torch.Managers.Profiler;
+using VRage.Game.ModAPI;
using VRage.ModAPI;
using VRageMath;
@@ -9,6 +13,12 @@ namespace Torch.Server.ViewModels.Entities
protected EntityTreeViewModel Tree { get; }
public IMyEntity Entity { get; }
public long Id => Entity.EntityId;
+ public ProfilerEntryViewModel Profiler
+ {
+ get => ProfilerTreeAlias[0];
+ set => ProfilerTreeAlias[0] = value;
+ }
+ public MtObservableList ProfilerTreeAlias { get; } = new MtObservableList(1){null};
public virtual string Name
{
@@ -46,6 +56,7 @@ namespace Torch.Server.ViewModels.Entities
{
Entity = entity;
Tree = tree;
+ Profiler = TorchBase.Instance.Managers.GetManager()?.EntityData(entity, Profiler);
}
public EntityViewModel()
diff --git a/Torch.Server/ViewModels/Entities/GridViewModel.cs b/Torch.Server/ViewModels/Entities/GridViewModel.cs
index b591c99..9cbd2cc 100644
--- a/Torch.Server/ViewModels/Entities/GridViewModel.cs
+++ b/Torch.Server/ViewModels/Entities/GridViewModel.cs
@@ -2,7 +2,9 @@
using System.Linq;
using Sandbox.Game.Entities;
using Sandbox.ModAPI;
+using Torch.API.Managers;
using Torch.Collections;
+using Torch.Managers.Profiler;
using Torch.Server.ViewModels.Blocks;
namespace Torch.Server.ViewModels.Entities
diff --git a/Torch.Server/ViewModels/ProfilerViewModel.cs b/Torch.Server/ViewModels/ProfilerViewModel.cs
new file mode 100644
index 0000000..247f6c8
--- /dev/null
+++ b/Torch.Server/ViewModels/ProfilerViewModel.cs
@@ -0,0 +1,85 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using Torch.API.Managers;
+using Torch.Collections;
+using Torch.Managers.Profiler;
+
+namespace Torch.Server.ViewModels
+{
+ public class ProfilerViewModel : ViewModel
+ {
+ public MtObservableList ProfilerTreeAlias { get; } = new MtObservableList();
+
+ private readonly ProfilerManager _manager;
+
+ public ProfilerViewModel()
+ {
+ _manager = null;
+ }
+
+ public ProfilerViewModel(ProfilerManager profilerManager)
+ {
+ _manager = profilerManager;
+ ProfilerTreeAlias.Add(_manager.SessionData());
+ ProfilerTreeAlias.Add(_manager.EntitiesData());
+ }
+
+ ///
+ public bool ProfileGridsUpdate
+ {
+ get => _manager?.ProfileGridsUpdate ?? false;
+ set
+ {
+ if (_manager != null)
+ _manager.ProfileGridsUpdate = value;
+ OnPropertyChanged();
+ }
+ }
+
+ ///
+ public bool ProfileBlocksUpdate
+ {
+ get => _manager?.ProfileBlocksUpdate ?? false;
+ set
+ {
+ if (_manager != null)
+ _manager.ProfileBlocksUpdate = value;
+ OnPropertyChanged();
+ }
+ }
+
+ ///
+ public bool ProfileEntityComponentsUpdate
+ {
+ get => _manager?.ProfileEntityComponentsUpdate ?? false;
+ set
+ {
+ if (_manager != null)
+ _manager.ProfileEntityComponentsUpdate = value;
+ OnPropertyChanged();
+ }
+ }
+
+ ///
+ public bool ProfileGridSystemUpdates
+ {
+ get => _manager?.ProfileGridSystemUpdates ?? false;
+ set
+ {
+ if (_manager != null)
+ _manager.ProfileGridSystemUpdates = value;
+ OnPropertyChanged();
+ }
+ }
+
+ ///
+ public bool ProfileSessionComponentsUpdate
+ {
+ get => _manager?.ProfileSessionComponentsUpdate ?? false;
+ set => _manager.ProfileSessionComponentsUpdate = value;
+ }
+ }
+}
diff --git a/Torch.Server/Views/ChatControl.xaml.cs b/Torch.Server/Views/ChatControl.xaml.cs
index 6c966cc..a6c1cb7 100644
--- a/Torch.Server/Views/ChatControl.xaml.cs
+++ b/Torch.Server/Views/ChatControl.xaml.cs
@@ -44,7 +44,7 @@ namespace Torch.Server
public void BindServer(ITorchServer server)
{
_server = (TorchBase)server;
- Dispatcher.Invoke(() =>
+ Dispatcher.InvokeAsync(() =>
{
ChatItems.Inlines.Clear();
});
@@ -59,7 +59,7 @@ namespace Torch.Server
switch (state)
{
case TorchSessionState.Loading:
- Dispatcher.Invoke(() => ChatItems.Inlines.Clear());
+ Dispatcher.InvokeAsync(() => ChatItems.Inlines.Clear());
break;
case TorchSessionState.Loaded:
{
@@ -112,7 +112,7 @@ namespace Torch.Server
ChatScroller.ScrollToBottom();
}
else
- Dispatcher.Invoke(() => InsertMessage(msg));
+ Dispatcher.InvokeAsync(() => InsertMessage(msg));
}
private void SendButton_Click(object sender, RoutedEventArgs e)
diff --git a/Torch.Server/Views/Entities/GridView.xaml b/Torch.Server/Views/Entities/GridView.xaml
index e4a63b6..36620ee 100644
--- a/Torch.Server/Views/Entities/GridView.xaml
+++ b/Torch.Server/Views/Entities/GridView.xaml
@@ -3,7 +3,7 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:local="clr-namespace:Torch.Server.Views.Entities"
+ xmlns:profiler="clr-namespace:Torch.Managers.Profiler;assembly=Torch"
xmlns:entities="clr-namespace:Torch.Server.ViewModels.Entities"
mc:Ignorable="d">
@@ -18,5 +18,15 @@
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/Torch.Server/Views/ProfilerConfigControl.xaml b/Torch.Server/Views/ProfilerConfigControl.xaml
new file mode 100644
index 0000000..b90876f
--- /dev/null
+++ b/Torch.Server/Views/ProfilerConfigControl.xaml
@@ -0,0 +1,34 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/Torch.Server/Views/ProfilerConfigControl.xaml.cs b/Torch.Server/Views/ProfilerConfigControl.xaml.cs
new file mode 100644
index 0000000..8ecb7bd
--- /dev/null
+++ b/Torch.Server/Views/ProfilerConfigControl.xaml.cs
@@ -0,0 +1,36 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+using System.Windows;
+using System.Windows.Controls;
+using System.Windows.Data;
+using System.Windows.Documents;
+using System.Windows.Input;
+using System.Windows.Media;
+using System.Windows.Media.Imaging;
+using System.Windows.Navigation;
+using System.Windows.Shapes;
+using Torch.API.Managers;
+using Torch.Managers.Profiler;
+using Torch.Server.ViewModels;
+
+namespace Torch.Server.Views
+{
+ ///
+ /// Interaction logic for ProfilerControl.xaml
+ ///
+ public partial class ProfilerControl : UserControl
+ {
+ public ProfilerControl()
+ {
+ InitializeComponent();
+ }
+
+ public void BindServer(TorchServer server)
+ {
+ DataContext = new ProfilerViewModel(server.Managers.GetManager());
+ }
+ }
+}
diff --git a/Torch.Server/Views/TorchUI.xaml b/Torch.Server/Views/TorchUI.xaml
index 1848f6c..97729f7 100644
--- a/Torch.Server/Views/TorchUI.xaml
+++ b/Torch.Server/Views/TorchUI.xaml
@@ -69,6 +69,9 @@
+
+
+
diff --git a/Torch.Server/Views/TorchUI.xaml.cs b/Torch.Server/Views/TorchUI.xaml.cs
index 92b1083..6e7716d 100644
--- a/Torch.Server/Views/TorchUI.xaml.cs
+++ b/Torch.Server/Views/TorchUI.xaml.cs
@@ -48,6 +48,7 @@ namespace Torch.Server
Chat.BindServer(server);
PlayerList.BindServer(server);
Plugins.BindServer(server);
+ Profiler.BindServer(server);
LoadConfig((TorchConfig)server.Config);
}
diff --git a/Torch/Collections/MTObservableCollection.cs b/Torch/Collections/MTObservableCollection.cs
index 6cc3d38..8cd5a18 100644
--- a/Torch/Collections/MTObservableCollection.cs
+++ b/Torch/Collections/MTObservableCollection.cs
@@ -3,13 +3,10 @@ using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
-using System.Diagnostics;
using System.Linq;
-using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
-using System.Windows.Threading;
using Torch.Utils;
namespace Torch.Collections
@@ -35,6 +32,11 @@ namespace Torch.Collections
_threadViews = new ThreadLocal(() => new ThreadView(this));
}
+ ///
+ /// Should this observable collection actually dispatch events.
+ ///
+ public bool NotificationsEnabled { get; protected set; } = true;
+
///
/// Takes a snapshot of this collection. Note: This call is only done when a read lock is acquired.
///
@@ -54,7 +56,7 @@ namespace Torch.Collections
///
public void Add(TV item)
{
- using(Lock.WriteUsing())
+ using (Lock.WriteUsing())
{
Backing.Add(item);
MarkSnapshotsDirty();
@@ -66,7 +68,7 @@ namespace Torch.Collections
///
public void Clear()
{
- using(Lock.WriteUsing())
+ using (Lock.WriteUsing())
{
Backing.Clear();
MarkSnapshotsDirty();
@@ -92,11 +94,13 @@ namespace Torch.Collections
///
public bool Remove(TV item)
{
- using(Lock.UpgradableReadUsing()) {
+ using (Lock.UpgradableReadUsing())
+ {
int? oldIndex = (Backing as IList)?.IndexOf(item);
if (oldIndex == -1)
return false;
- using(Lock.WriteUsing()) {
+ using (Lock.WriteUsing())
+ {
if (!Backing.Remove(item))
return false;
MarkSnapshotsDirty();
@@ -125,6 +129,56 @@ namespace Torch.Collections
#endregion
#region Event Wrappers
+ private readonly WeakReference _deferredSnapshot = new WeakReference(null);
+ private bool _deferredSnapshotTaken = false;
+ ///
+ /// Disposable that stops update signals and signals a full refresh when disposed.
+ ///
+ public IDisposable DeferredUpdate()
+ {
+ using (Lock.WriteUsing())
+ {
+ if (_deferredSnapshotTaken)
+ return new DummyToken();
+ DeferredUpdateToken token;
+ if (!_deferredSnapshot.TryGetTarget(out token))
+ _deferredSnapshot.SetTarget(token = new DeferredUpdateToken());
+ token.SetCollection(this);
+ return token;
+ }
+ }
+
+ private struct DummyToken : IDisposable
+ {
+ public void Dispose()
+ {
+ }
+ }
+
+ private class DeferredUpdateToken : IDisposable
+ {
+ private MtObservableCollection _collection;
+
+ internal void SetCollection(MtObservableCollection c)
+ {
+ c._deferredSnapshotTaken = true;
+ _collection = c;
+ c.NotificationsEnabled = false;
+ }
+
+ public void Dispose()
+ {
+ using (_collection.Lock.WriteUsing())
+ {
+ _collection.NotificationsEnabled = true;
+ _collection.OnPropertyChanged(nameof(Count));
+ _collection.OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
+ _collection._deferredSnapshotTaken = false;
+ }
+
+ }
+ }
+
protected void OnPropertyChanged(string propName)
{
NotifyEvent(this, new PropertyChangedEventArgs(propName));
@@ -133,20 +187,23 @@ namespace Torch.Collections
protected void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
NotifyEvent(this, e);
+ OnPropertyChanged("Item[]");
}
protected void NotifyEvent(object sender, PropertyChangedEventArgs args)
{
- _propertyChangedEvent.Raise(sender, args);
+ if (NotificationsEnabled)
+ _propertyChangedEvent.Raise(sender, args);
}
protected void NotifyEvent(object sender, NotifyCollectionChangedEventArgs args)
{
- _collectionChangedEvent.Raise(sender, args);
+ if (NotificationsEnabled)
+ _collectionChangedEvent.Raise(sender, args);
}
- private readonly DispatcherEvent _propertyChangedEvent =
- new DispatcherEvent();
+ private readonly MtObservableEvent _propertyChangedEvent =
+ new MtObservableEvent();
///
public event PropertyChangedEventHandler PropertyChanged
{
@@ -154,85 +211,14 @@ namespace Torch.Collections
remove => _propertyChangedEvent.Remove(value);
}
- private readonly DispatcherEvent _collectionChangedEvent =
- new DispatcherEvent();
+ private readonly MtObservableEvent _collectionChangedEvent =
+ new MtObservableEvent();
///
public event NotifyCollectionChangedEventHandler CollectionChanged
{
add => _collectionChangedEvent.Add(value);
remove => _collectionChangedEvent.Remove(value);
}
- ///
- /// Event that invokes handlers registered by dispatchers on dispatchers.
- ///
- /// Event argument type
- /// Event handler delegate type
- private sealed class DispatcherEvent where TEvtArgs : EventArgs
- {
- private delegate void DelInvokeHandler(TEvtHandle handler, object sender, TEvtArgs args);
-
- private static readonly DelInvokeHandler _invokeDirectly;
- static DispatcherEvent()
- {
- MethodInfo invoke = typeof(TEvtHandle).GetMethod("Invoke", BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
- Debug.Assert(invoke != null, "No invoke method on handler type");
- _invokeDirectly = (DelInvokeHandler)Delegate.CreateDelegate(typeof(DelInvokeHandler), invoke);
- }
-
- private static Dispatcher CurrentDispatcher => Dispatcher.FromThread(Thread.CurrentThread);
-
-
- private event EventHandler _event;
-
- internal void Raise(object sender, TEvtArgs args)
- {
- _event?.Invoke(sender, args);
- }
-
- internal void Add(TEvtHandle evt)
- {
- if (evt == null)
- return;
- _event += new DispatcherDelegate(evt).Invoke;
- }
-
- internal void Remove(TEvtHandle evt)
- {
- if (_event == null || evt == null)
- return;
- Delegate[] invokeList = _event.GetInvocationList();
- for (int i = invokeList.Length - 1; i >= 0; i--)
- {
- var wrapper = (DispatcherDelegate)invokeList[i].Target;
- if (wrapper._delegate.Equals(evt))
- {
- _event -= wrapper.Invoke;
- return;
- }
- }
- }
-
- private struct DispatcherDelegate
- {
- private readonly Dispatcher _dispatcher;
- internal readonly TEvtHandle _delegate;
-
- internal DispatcherDelegate(TEvtHandle del)
- {
- _dispatcher = CurrentDispatcher;
- _delegate = del;
- }
-
- public void Invoke(object sender, TEvtArgs args)
- {
- if (_dispatcher == null || _dispatcher == CurrentDispatcher)
- _invokeDirectly(_delegate, sender, args);
- else
- // (Delegate) (object) == dual cast so that the compiler likes it
- _dispatcher.BeginInvoke((Delegate)(object)_delegate, DispatcherPriority.DataBind, sender, args);
- }
- }
- }
#endregion
diff --git a/Torch/Collections/MtObservableDictionary.cs b/Torch/Collections/MtObservableDictionary.cs
index feeda30..00bf2d7 100644
--- a/Torch/Collections/MtObservableDictionary.cs
+++ b/Torch/Collections/MtObservableDictionary.cs
@@ -91,12 +91,6 @@ namespace Torch.Collections
///
private ProxyCollection ObservableValues { get; }
- internal void RaiseFullReset()
- {
- OnPropertyChanged(nameof(Count));
- OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
- }
-
///
/// Proxy collection capable of raising notifications when the parent collection changes.
///
diff --git a/Torch/Collections/MtObservableEvent.cs b/Torch/Collections/MtObservableEvent.cs
new file mode 100644
index 0000000..cc27c6b
--- /dev/null
+++ b/Torch/Collections/MtObservableEvent.cs
@@ -0,0 +1,80 @@
+using System;
+using System.Diagnostics;
+using System.Reflection;
+using System.Threading;
+using System.Windows.Threading;
+
+namespace Torch.Collections
+{
+ ///
+ /// Event that invokes handlers registered by dispatchers on dispatchers.
+ ///
+ /// Event argument type
+ /// Event handler delegate type
+ internal sealed class MtObservableEvent where TEvtArgs : EventArgs
+ {
+ private delegate void DelInvokeHandler(TEvtHandle handler, object sender, TEvtArgs args);
+
+ private static readonly DelInvokeHandler _invokeDirectly;
+ static MtObservableEvent()
+ {
+ MethodInfo invoke = typeof(TEvtHandle).GetMethod("Invoke", BindingFlags.Instance | BindingFlags.Public | BindingFlags.DeclaredOnly);
+ Debug.Assert(invoke != null, "No invoke method on handler type");
+ _invokeDirectly = (DelInvokeHandler)Delegate.CreateDelegate(typeof(DelInvokeHandler), invoke);
+ }
+
+ private static Dispatcher CurrentDispatcher => Dispatcher.FromThread(Thread.CurrentThread);
+
+
+ private event EventHandler Event;
+
+ internal void Raise(object sender, TEvtArgs args)
+ {
+ Event?.Invoke(sender, args);
+ }
+
+ internal void Add(TEvtHandle evt)
+ {
+ if (evt == null)
+ return;
+ Event += new DispatcherDelegate(evt).Invoke;
+ }
+
+ internal void Remove(TEvtHandle evt)
+ {
+ if (Event == null || evt == null)
+ return;
+ Delegate[] invokeList = Event.GetInvocationList();
+ for (int i = invokeList.Length - 1; i >= 0; i--)
+ {
+ var wrapper = (DispatcherDelegate)invokeList[i].Target;
+ if (wrapper._delegate.Equals(evt))
+ {
+ Event -= wrapper.Invoke;
+ return;
+ }
+ }
+ }
+
+ private struct DispatcherDelegate
+ {
+ private readonly Dispatcher _dispatcher;
+ internal readonly TEvtHandle _delegate;
+
+ internal DispatcherDelegate(TEvtHandle del)
+ {
+ _dispatcher = CurrentDispatcher;
+ _delegate = del;
+ }
+
+ public void Invoke(object sender, TEvtArgs args)
+ {
+ if (_dispatcher == null || _dispatcher == CurrentDispatcher)
+ _invokeDirectly(_delegate, sender, args);
+ else
+ // (Delegate) (object) == dual cast so that the compiler likes it
+ _dispatcher.BeginInvoke((Delegate)(object)_delegate, DispatcherPriority.DataBind, sender, args);
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/Torch/Collections/MtObservableList.cs b/Torch/Collections/MtObservableList.cs
index ec64c64..b290d03 100644
--- a/Torch/Collections/MtObservableList.cs
+++ b/Torch/Collections/MtObservableList.cs
@@ -106,7 +106,8 @@ namespace Torch.Collections
///
public void Sort(Func selector, IComparer comparer = null)
{
- using (Lock.ReadUsing())
+ using (DeferredUpdate())
+ using (Lock.WriteUsing())
{
comparer = comparer ?? Comparer.Default;
if (Backing is List lst)
@@ -118,8 +119,6 @@ namespace Torch.Collections
foreach (T v in sortedItems)
Backing.Add(v);
}
-
- OnCollectionChanged(new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset));
}
}
}
diff --git a/Torch/Managers/PatchManager/PatchUtilities.cs b/Torch/Managers/PatchManager/PatchUtilities.cs
new file mode 100644
index 0000000..baf797e
--- /dev/null
+++ b/Torch/Managers/PatchManager/PatchUtilities.cs
@@ -0,0 +1,41 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Text;
+using System.Threading.Tasks;
+using Torch.Managers.PatchManager.MSIL;
+using Torch.Managers.PatchManager.Transpile;
+
+namespace Torch.Managers.PatchManager
+{
+ ///
+ /// Functions that let you read and write MSIL to methods directly.
+ ///
+ public class PatchUtilities
+ {
+ ///
+ /// Gets the content of a method as an instruction stream
+ ///
+ /// Method to examine
+ /// instruction stream
+ public static IEnumerable ReadInstructions(MethodBase method)
+ {
+ var context = new MethodContext(method);
+ context.Read();
+ context.CheckIntegrity();
+ return context.Instructions;
+ }
+
+ ///
+ /// Writes the given instruction stream to the given IL generator, fixing short branch instructions.
+ ///
+ /// Instruction stream
+ /// Output
+ public static void EmitInstructions(IEnumerable insn, LoggingIlGenerator generator)
+ {
+ MethodTranspiler.Emit(insn, generator);
+ }
+ }
+}
diff --git a/Torch/Managers/PatchManager/Transpile/MethodTranspiler.cs b/Torch/Managers/PatchManager/Transpile/MethodTranspiler.cs
index e2db491..ac0d209 100644
--- a/Torch/Managers/PatchManager/Transpile/MethodTranspiler.cs
+++ b/Torch/Managers/PatchManager/Transpile/MethodTranspiler.cs
@@ -27,6 +27,8 @@ namespace Torch.Managers.PatchManager.Transpile
{
if (parameter.Name.Equals("__methodBody"))
paramList.Add(baseMethod.GetMethodBody());
+ else if (parameter.Name.Equals("__methodBase"))
+ paramList.Add(baseMethod);
else if (parameter.Name.Equals("__localCreator"))
paramList.Add(localCreator);
else if (parameter.ParameterType == typeof(IEnumerable))
@@ -42,6 +44,12 @@ namespace Torch.Managers.PatchManager.Transpile
k.Emit(output);
}
+ internal static void Emit(IEnumerable input, LoggingIlGenerator output)
+ {
+ foreach (MsilInstruction k in FixBranchAndReturn(input, null))
+ k.Emit(output);
+ }
+
private static IEnumerable FixBranchAndReturn(IEnumerable insn, Label? retTarget)
{
foreach (MsilInstruction i in insn)
diff --git a/Torch/Managers/Profiler/FatProfilerEntry.cs b/Torch/Managers/Profiler/FatProfilerEntry.cs
new file mode 100644
index 0000000..6479a96
--- /dev/null
+++ b/Torch/Managers/Profiler/FatProfilerEntry.cs
@@ -0,0 +1,50 @@
+using System;
+using System.Collections.Generic;
+using System.Runtime.CompilerServices;
+using Torch.Collections;
+
+namespace Torch.Managers.Profiler
+{
+ public class FatProfilerEntry : SlimProfilerEntry
+ {
+ private readonly ConditionalWeakTable