- Fixed assembly unloading. However, requires 'plugin_forcerungc' to be run multiple times over ~30 seconds at the main menu.

This commit is contained in:
MapleWheels
2026-05-15 18:41:39 -04:00
parent ada9a09410
commit cfde6f3579
3 changed files with 123 additions and 98 deletions
@@ -256,6 +256,7 @@ public sealed class AssemblyLoader : AssemblyLoadContext, IAssemblyLoaderService
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
public Result<Assembly> CompileScriptAssembly([NotNull] string assemblyName,
bool compileWithInternalAccess,
ImmutableArray<SyntaxTree> syntaxTrees,
@@ -348,6 +349,7 @@ public sealed class AssemblyLoader : AssemblyLoadContext, IAssemblyLoaderService
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
public FluentResults.Result<Assembly> LoadAssemblyFromFile(string assemblyFilePath,
ImmutableArray<string> additionalDependencyPaths)
{
@@ -434,6 +436,8 @@ public sealed class AssemblyLoader : AssemblyLoadContext, IAssemblyLoaderService
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
public FluentResults.Result<Assembly> GetAssemblyByName(string assemblyName)
{
if (IsDisposed)
@@ -481,6 +485,7 @@ public sealed class AssemblyLoader : AssemblyLoadContext, IAssemblyLoaderService
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
public FluentResults.Result<ImmutableArray<Type>> GetTypesInAssemblies()
{
if (IsDisposed)
@@ -501,6 +506,7 @@ public sealed class AssemblyLoader : AssemblyLoadContext, IAssemblyLoaderService
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
public IEnumerable<Type> UnsafeGetTypesInAssemblies()
{
if (IsDisposed)
@@ -529,6 +535,7 @@ public sealed class AssemblyLoader : AssemblyLoadContext, IAssemblyLoaderService
}
}
[MethodImpl(MethodImplOptions.NoInlining)]
public Result<Type> GetTypeInAssemblies(string typeName)
{
if (IsDisposed)
@@ -557,14 +564,12 @@ public sealed class AssemblyLoader : AssemblyLoadContext, IAssemblyLoaderService
return; // we don't want to invoke events twice nor cause strong GC handles.
IsDisposed = true;
this.Unload();
this.DisposeInternal();
// we want to call base finalizers
//GC.SuppressFinalize(this);
GC.SuppressFinalize(this);
}
~AssemblyLoader()
{
this.DisposeInternal();
this.Unload();
}
private void OnUnload(AssemblyLoadContext context)
@@ -579,9 +584,8 @@ public sealed class AssemblyLoader : AssemblyLoadContext, IAssemblyLoaderService
Thread.Sleep(1000/Timing.FixedUpdateRate-1);
}
var wf = new WeakReference<IAssemblyLoaderService>(this);
_loadedAssemblyData.Clear();
_onUnload?.Invoke(this);
this.DisposeInternal();
}
private void DisposeInternal()
@@ -592,6 +596,9 @@ public sealed class AssemblyLoader : AssemblyLoadContext, IAssemblyLoaderService
base.Unloading -= OnUnload;
this._dependencyResolvers.Clear();
this._loadedAssemblyData.Clear();
GC.Collect(GC.MaxGeneration, GCCollectionMode.Aggressive, true, true);
GC.WaitForFullGCComplete(10);
}
protected override Assembly Load(AssemblyName assemblyName)
@@ -660,6 +667,7 @@ public sealed class AssemblyLoader : AssemblyLoadContext, IAssemblyLoaderService
public readonly ImmutableArray<Type> Types;
public readonly ImmutableDictionary<string, Type> TypesByName;
[MethodImpl(MethodImplOptions.NoOptimization)]
public AssemblyData(Assembly assembly, byte[] assemblyImage)
{
Assembly = assembly ?? throw new ArgumentNullException(nameof(assembly));
@@ -669,6 +677,7 @@ public sealed class AssemblyLoader : AssemblyLoadContext, IAssemblyLoaderService
TypesByName = Types.ToImmutableDictionary(type => type.FullName, type => type);
}
[MethodImpl(MethodImplOptions.NoOptimization)]
public AssemblyData(Assembly assembly, string path)
{
Assembly = assembly ?? throw new ArgumentNullException(nameof(assembly));
@@ -696,6 +705,7 @@ public sealed class AssemblyLoader : AssemblyLoadContext, IAssemblyLoaderService
HashCode = AssemblyName.GetHashCode();
}
[MethodImpl(MethodImplOptions.NoOptimization)]
public AssemblyOrStringKey(string assemblyName)
{
if (assemblyName.IsNullOrWhiteSpace())