|
@@ -1,5 +1,6 @@
|
|
|
using System;
|
|
|
using System.Collections.Generic;
|
|
|
+using System.Runtime.CompilerServices;
|
|
|
using MonoMod.Utils;
|
|
|
|
|
|
namespace BepInEx.IL2CPP.Allocator
|
|
@@ -10,6 +11,48 @@ namespace BepInEx.IL2CPP.Allocator
|
|
|
internal abstract class UnixPageAllocator : PageAllocator
|
|
|
{
|
|
|
protected abstract IMemoryMapper OpenMemoryMap();
|
|
|
+
|
|
|
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
+ private static bool CheckFreeRegionBefore(IntPtr start, IntPtr hint, IntPtr[] result)
|
|
|
+ {
|
|
|
+ if (start.ToInt64() < hint.ToInt64())
|
|
|
+ {
|
|
|
+ var addr = start - PAGE_SIZE;
|
|
|
+ if (hint.ToInt64() - addr.ToInt64() < int.MaxValue)
|
|
|
+ result[0] = addr;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
|
|
|
+ private static bool CheckFreeRegionAfter(IntPtr end, IntPtr hint, IntPtr[] result)
|
|
|
+ {
|
|
|
+ if (hint.ToInt64() < end.ToInt64())
|
|
|
+ {
|
|
|
+ if (end.ToInt64() - hint.ToInt64() < int.MaxValue)
|
|
|
+ result[1] = end;
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ private IntPtr[] GetFreeAddresses(IntPtr hint)
|
|
|
+ {
|
|
|
+ var result = new IntPtr[2];
|
|
|
+ var prevEnd = IntPtr.Zero;
|
|
|
+ using var mapper = OpenMemoryMap();
|
|
|
+
|
|
|
+ while (mapper.FindNextFree(out var start, out var end))
|
|
|
+ {
|
|
|
+ if ((prevEnd + PAGE_SIZE).ToInt64() <= start.ToInt64())
|
|
|
+ if (CheckFreeRegionBefore(start, hint, result) || CheckFreeRegionAfter(prevEnd, hint, result))
|
|
|
+ return result;
|
|
|
+ prevEnd = end;
|
|
|
+ }
|
|
|
+ if (CheckFreeRegionAfter(prevEnd, hint, result))
|
|
|
+ return result;
|
|
|
+ throw new PageAllocatorException($"Could not find free region near {hint.ToInt64():X8}");
|
|
|
+ }
|
|
|
|
|
|
public override IntPtr Allocate(IntPtr hint)
|
|
|
{
|
|
@@ -23,7 +66,7 @@ namespace BepInEx.IL2CPP.Allocator
|
|
|
|
|
|
protected interface IMemoryMapper: IDisposable
|
|
|
{
|
|
|
- bool FindNextFree(ref IntPtr start, ref ulong size);
|
|
|
+ bool FindNextFree(out IntPtr start, out IntPtr end);
|
|
|
}
|
|
|
}
|
|
|
}
|