diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2020-05-03 19:54:50 -0300 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-05-04 08:54:50 +1000 |
| commit | f77694e4f774c9391aad5344e70a7c8721cfedc6 (patch) | |
| tree | 36bccaeb153bd5d921c751966b8a734a7b4b6ae1 /ARMeilleure/Translation | |
| parent | 1758424208335d1f4ff7c27c554e517c81bf72f6 (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.cs | 4 | ||||
| -rw-r--r-- | ARMeilleure/Translation/Compiler.cs | 4 | ||||
| -rw-r--r-- | ARMeilleure/Translation/DirectCallStubs.cs | 19 | ||||
| -rw-r--r-- | ARMeilleure/Translation/JitCache.cs | 51 | ||||
| -rw-r--r-- | ARMeilleure/Translation/JumpTable.cs | 22 | ||||
| -rw-r--r-- | ARMeilleure/Translation/Translator.cs | 28 |
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); } |
