aboutsummaryrefslogtreecommitdiff
path: root/ARMeilleure/Translation
diff options
context:
space:
mode:
authorgdkchan <gab.dark.100@gmail.com>2020-05-03 19:54:50 -0300
committerGitHub <noreply@github.com>2020-05-04 08:54:50 +1000
commitf77694e4f774c9391aad5344e70a7c8721cfedc6 (patch)
tree36bccaeb153bd5d921c751966b8a734a7b4b6ae1 /ARMeilleure/Translation
parent1758424208335d1f4ff7c27c554e517c81bf72f6 (diff)
Implement a new physical memory manager and replace DeviceMemory (#856)
* Implement a new physical memory manager and replace DeviceMemory * Proper generic constraints * Fix debug build * Add memory tests * New CPU memory manager and general code cleanup * Remove host memory management from CPU project, use Ryujinx.Memory instead * Fix tests * Document exceptions on MemoryBlock * Fix leak on unix memory allocation * Proper disposal of some objects on tests * Fix JitCache not being set as initialized * GetRef without checks for 8-bits and 16-bits CAS * Add MemoryBlock destructor * Throw in separate method to improve codegen * Address PR feedback * QueryModified improvements * Fix memory write tracking not marking all pages as modified in some cases * Simplify MarkRegionAsModified * Remove XML doc for ghost param * Add back optimization to avoid useless buffer updates * Add Ryujinx.Cpu project, move MemoryManager there and remove MemoryBlockWrapper * Some nits * Do not perform address translation when size is 0 * Address PR feedback and format NativeInterface class * Remove ghost parameter description * Update Ryujinx.Cpu to .NET Core 3.1 * Address PR feedback * Fix build * Return a well defined value for GetPhysicalAddress with invalid VA, and do not return unmapped ranges as modified * Typo
Diffstat (limited to 'ARMeilleure/Translation')
-rw-r--r--ARMeilleure/Translation/ArmEmitterContext.cs4
-rw-r--r--ARMeilleure/Translation/Compiler.cs4
-rw-r--r--ARMeilleure/Translation/DirectCallStubs.cs19
-rw-r--r--ARMeilleure/Translation/JitCache.cs51
-rw-r--r--ARMeilleure/Translation/JumpTable.cs22
-rw-r--r--ARMeilleure/Translation/Translator.cs28
6 files changed, 52 insertions, 76 deletions
diff --git a/ARMeilleure/Translation/ArmEmitterContext.cs b/ARMeilleure/Translation/ArmEmitterContext.cs
index d1a2c92d..a905c722 100644
--- a/ARMeilleure/Translation/ArmEmitterContext.cs
+++ b/ARMeilleure/Translation/ArmEmitterContext.cs
@@ -37,7 +37,7 @@ namespace ARMeilleure.Translation
public OpCode CurrOp { get; set; }
- public MemoryManager Memory { get; }
+ public IMemoryManager Memory { get; }
public Aarch32Mode Mode { get; }
@@ -47,7 +47,7 @@ namespace ARMeilleure.Translation
public bool HighCq { get; }
- public ArmEmitterContext(MemoryManager memory, JumpTable jumpTable, long baseAddress, bool highCq, Aarch32Mode mode)
+ public ArmEmitterContext(IMemoryManager memory, JumpTable jumpTable, long baseAddress, bool highCq, Aarch32Mode mode)
{
Memory = memory;
JumpTable = jumpTable;
diff --git a/ARMeilleure/Translation/Compiler.cs b/ARMeilleure/Translation/Compiler.cs
index d27c3cce..ec2f2968 100644
--- a/ARMeilleure/Translation/Compiler.cs
+++ b/ARMeilleure/Translation/Compiler.cs
@@ -11,14 +11,14 @@ namespace ARMeilleure.Translation
{
public static T Compile<T>(ControlFlowGraph cfg, OperandType[] argTypes, OperandType retType, CompilerOptions options)
{
- CompiledFunction func = CompileAndGetCf(cfg, argTypes, retType, options);
+ CompiledFunction func = Compile(cfg, argTypes, retType, options);
IntPtr codePtr = JitCache.Map(func);
return Marshal.GetDelegateForFunctionPointer<T>(codePtr);
}
- public static CompiledFunction CompileAndGetCf(ControlFlowGraph cfg, OperandType[] argTypes, OperandType retType, CompilerOptions options)
+ public static CompiledFunction Compile(ControlFlowGraph cfg, OperandType[] argTypes, OperandType retType, CompilerOptions options)
{
Logger.StartPass(PassName.Dominance);
diff --git a/ARMeilleure/Translation/DirectCallStubs.cs b/ARMeilleure/Translation/DirectCallStubs.cs
index e6e87b2b..42a78c71 100644
--- a/ARMeilleure/Translation/DirectCallStubs.cs
+++ b/ARMeilleure/Translation/DirectCallStubs.cs
@@ -17,14 +17,9 @@ namespace ARMeilleure.Translation
private static GuestFunction _indirectCallStub;
private static GuestFunction _indirectTailCallStub;
- private static object _lock;
+ private static readonly object _lock = new object();
private static bool _initialized;
- static DirectCallStubs()
- {
- _lock = new object();
- }
-
public static void InitializeStubs()
{
if (_initialized) return;
@@ -85,11 +80,7 @@ namespace ARMeilleure.Translation
OperandType.I64
};
- return Compiler.Compile<GuestFunction>(
- cfg,
- argTypes,
- OperandType.I64,
- CompilerOptions.HighCq);
+ return Compiler.Compile<GuestFunction>(cfg, argTypes, OperandType.I64, CompilerOptions.HighCq);
}
/// <summary>
@@ -121,11 +112,7 @@ namespace ARMeilleure.Translation
OperandType.I64
};
- return Compiler.Compile<GuestFunction>(
- cfg,
- argTypes,
- OperandType.I64,
- CompilerOptions.HighCq);
+ return Compiler.Compile<GuestFunction>(cfg, argTypes, OperandType.I64, CompilerOptions.HighCq);
}
}
}
diff --git a/ARMeilleure/Translation/JitCache.cs b/ARMeilleure/Translation/JitCache.cs
index b004cc22..32d40c20 100644
--- a/ARMeilleure/Translation/JitCache.cs
+++ b/ARMeilleure/Translation/JitCache.cs
@@ -2,6 +2,7 @@ using ARMeilleure.CodeGen;
using ARMeilleure.Memory;
using System;
using System.Collections.Generic;
+using System.Diagnostics;
using System.Runtime.InteropServices;
namespace ARMeilleure.Translation
@@ -12,35 +13,33 @@ namespace ARMeilleure.Translation
private const int PageMask = PageSize - 1;
private const int CodeAlignment = 4; // Bytes
-
private const int CacheSize = 2047 * 1024 * 1024;
private static ReservedRegion _jitRegion;
-
- private static IntPtr _basePointer => _jitRegion.Pointer;
-
private static int _offset;
+ private static readonly List<JitCacheEntry> _cacheEntries = new List<JitCacheEntry>();
- private static List<JitCacheEntry> _cacheEntries;
-
- private static object _lock;
+ private static readonly object _lock = new object();
+ private static bool _initialized;
- static JitCache()
+ public static void Initialize(IJitMemoryAllocator allocator)
{
- _jitRegion = new ReservedRegion(CacheSize);
-
- if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ if (_initialized) return;
+ lock (_lock)
{
- _jitRegion.ExpandIfNeeded(PageSize);
- JitUnwindWindows.InstallFunctionTableHandler(_basePointer, CacheSize);
-
- // The first page is used for the table based SEH structs.
- _offset = PageSize;
- }
+ if (_initialized) return;
+ _jitRegion = new ReservedRegion(allocator, CacheSize);
- _cacheEntries = new List<JitCacheEntry>();
+ if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
+ {
+ _jitRegion.ExpandIfNeeded(PageSize);
+ JitUnwindWindows.InstallFunctionTableHandler(_jitRegion.Pointer, CacheSize);
- _lock = new object();
+ // The first page is used for the table based SEH structs.
+ _offset = PageSize;
+ }
+ _initialized = true;
+ }
}
public static IntPtr Map(CompiledFunction func)
@@ -49,9 +48,11 @@ namespace ARMeilleure.Translation
lock (_lock)
{
+ Debug.Assert(_initialized);
+
int funcOffset = Allocate(code.Length);
- IntPtr funcPtr = _basePointer + funcOffset;
+ IntPtr funcPtr = _jitRegion.Pointer + funcOffset;
Marshal.Copy(code, 0, funcPtr, code.Length);
@@ -77,18 +78,14 @@ namespace ARMeilleure.Translation
if (fullPagesSize != 0)
{
- IntPtr funcPtr = _basePointer + pageStart;
-
- MemoryManagement.Reprotect(funcPtr, (ulong)fullPagesSize, MemoryProtection.ReadAndExecute);
+ _jitRegion.Block.MapAsRx((ulong)pageStart, (ulong)fullPagesSize);
}
int remaining = endOffs - pageEnd;
if (remaining != 0)
{
- IntPtr funcPtr = _basePointer + pageEnd;
-
- MemoryManagement.Reprotect(funcPtr, (ulong)remaining, MemoryProtection.ReadWriteExecute);
+ _jitRegion.Block.MapAsRwx((ulong)pageEnd, (ulong)remaining);
}
}
@@ -132,7 +129,7 @@ namespace ARMeilleure.Translation
}
}
- entry = default(JitCacheEntry);
+ entry = default;
return false;
}
diff --git a/ARMeilleure/Translation/JumpTable.cs b/ARMeilleure/Translation/JumpTable.cs
index 5cad2944..e444e96d 100644
--- a/ARMeilleure/Translation/JumpTable.cs
+++ b/ARMeilleure/Translation/JumpTable.cs
@@ -9,13 +9,6 @@ namespace ARMeilleure.Translation
{
class JumpTable
{
- public static JumpTable Instance { get; }
-
- static JumpTable()
- {
- Instance = new JumpTable();
- }
-
// The jump table is a block of (guestAddress, hostAddress) function mappings.
// Each entry corresponds to one branch in a JIT compiled function. The entries are
// reserved specifically for each call.
@@ -60,23 +53,23 @@ namespace ARMeilleure.Translation
public IntPtr JumpPointer => _jumpRegion.Pointer;
public IntPtr DynamicPointer => _dynamicRegion.Pointer;
- public JumpTable()
+ public JumpTable(IJitMemoryAllocator allocator)
{
- _jumpRegion = new ReservedRegion(JumpTableByteSize);
- _dynamicRegion = new ReservedRegion(DynamicTableByteSize);
+ _jumpRegion = new ReservedRegion(allocator, JumpTableByteSize);
+ _dynamicRegion = new ReservedRegion(allocator, DynamicTableByteSize);
_targets = new ConcurrentDictionary<ulong, TranslatedFunction>();
_dependants = new ConcurrentDictionary<ulong, LinkedList<int>>();
}
- public void RegisterFunction(ulong address, TranslatedFunction func) {
+ public void RegisterFunction(ulong address, TranslatedFunction func)
+ {
address &= ~3UL;
_targets.AddOrUpdate(address, func, (key, oldFunc) => func);
long funcPtr = func.GetPointer().ToInt64();
// Update all jump table entries that target this address.
- LinkedList<int> myDependants;
- if (_dependants.TryGetValue(address, out myDependants))
+ if (_dependants.TryGetValue(address, out LinkedList<int> myDependants))
{
lock (myDependants)
{
@@ -125,8 +118,7 @@ namespace ARMeilleure.Translation
// Is the address we have already registered? If so, put the function address in the jump table.
// If not, it will point to the direct call stub.
long value = (long)DirectCallStubs.DirectCallStub(isJump);
- TranslatedFunction func;
- if (_targets.TryGetValue((ulong)address, out func))
+ if (_targets.TryGetValue((ulong)address, out TranslatedFunction func))
{
value = func.GetPointer().ToInt64();
}
diff --git a/ARMeilleure/Translation/Translator.cs b/ARMeilleure/Translation/Translator.cs
index 053c7328..700b54c2 100644
--- a/ARMeilleure/Translation/Translator.cs
+++ b/ARMeilleure/Translation/Translator.cs
@@ -9,6 +9,7 @@ using System.Collections.Concurrent;
using System.Threading;
using static ARMeilleure.IntermediateRepresentation.OperandHelper;
+using static ARMeilleure.IntermediateRepresentation.OperationHelper;
namespace ARMeilleure.Translation
{
@@ -18,30 +19,31 @@ namespace ARMeilleure.Translation
private const bool AlwaysTranslateFunctions = true; // If false, only translates a single block for lowCq.
- private MemoryManager _memory;
+ private readonly IMemoryManager _memory;
- private ConcurrentDictionary<ulong, TranslatedFunction> _funcs;
+ private readonly ConcurrentDictionary<ulong, TranslatedFunction> _funcs;
- private JumpTable _jumpTable;
+ private readonly JumpTable _jumpTable;
- private PriorityQueue<RejitRequest> _backgroundQueue;
+ private readonly PriorityQueue<RejitRequest> _backgroundQueue;
- private AutoResetEvent _backgroundTranslatorEvent;
+ private readonly AutoResetEvent _backgroundTranslatorEvent;
private volatile int _threadCount;
- public Translator(MemoryManager memory)
+ public Translator(IJitMemoryAllocator allocator, IMemoryManager memory)
{
_memory = memory;
_funcs = new ConcurrentDictionary<ulong, TranslatedFunction>();
- _jumpTable = JumpTable.Instance;
+ _jumpTable = new JumpTable(allocator);
_backgroundQueue = new PriorityQueue<RejitRequest>(2);
_backgroundTranslatorEvent = new AutoResetEvent(false);
+ JitCache.Initialize(allocator);
DirectCallStubs.InitializeStubs();
}
@@ -146,8 +148,8 @@ namespace ARMeilleure.Translation
{
ArmEmitterContext context = new ArmEmitterContext(_memory, _jumpTable, (long)address, highCq, Aarch32Mode.User);
- OperandHelper.PrepareOperandPool(highCq);
- OperationHelper.PrepareOperationPool(highCq);
+ PrepareOperandPool(highCq);
+ PrepareOperationPool(highCq);
Logger.StartPass(PassName.Decoding);
@@ -178,14 +180,12 @@ namespace ARMeilleure.Translation
OperandType[] argTypes = new OperandType[] { OperandType.I64 };
- CompilerOptions options = highCq
- ? CompilerOptions.HighCq
- : CompilerOptions.None;
+ CompilerOptions options = highCq ? CompilerOptions.HighCq : CompilerOptions.None;
GuestFunction func = Compiler.Compile<GuestFunction>(cfg, argTypes, OperandType.I64, options);
- OperandHelper.ResetOperandPool(highCq);
- OperationHelper.ResetOperationPool(highCq);
+ ResetOperandPool(highCq);
+ ResetOperationPool(highCq);
return new TranslatedFunction(func, rejit: !highCq);
}