Impl. index-based relocation information. Impl. cache file version field.
This commit is contained in:
parent
7d0d9703a1
commit
61ab170071
11 changed files with 145 additions and 106 deletions
|
@ -882,7 +882,7 @@ namespace ARMeilleure.CodeGen.X86
|
|||
}
|
||||
else if (dest != null && dest.Kind == OperandKind.Register && info.OpRImm64 != BadOp)
|
||||
{
|
||||
string name = source.Name;
|
||||
int? index = source.Index;
|
||||
|
||||
int rexPrefix = GetRexPrefix(dest, source, type, rrm: false);
|
||||
|
||||
|
@ -893,9 +893,9 @@ namespace ARMeilleure.CodeGen.X86
|
|||
|
||||
WriteByte((byte)(info.OpRImm64 + (dest.GetRegister().Index & 0b111)));
|
||||
|
||||
if (_aotInfo != null && name != null)
|
||||
if (_aotInfo != null && index != null)
|
||||
{
|
||||
_aotInfo.WriteRelocEntry(new RelocEntry((int)_stream.Position, name));
|
||||
_aotInfo.WriteRelocEntry(new RelocEntry((int)_stream.Position, (int)index));
|
||||
}
|
||||
|
||||
WriteUInt64(imm);
|
||||
|
|
|
@ -290,9 +290,9 @@ namespace ARMeilleure.Instructions
|
|||
|
||||
private static Operand EmitPtPointerLoad(ArmEmitterContext context, Operand address, Operand lblFallbackPath)
|
||||
{
|
||||
string name = nameof(MemoryManager.PageTable);
|
||||
|
||||
Operand pte = Const(context.Memory.PageTable.ToInt64(), Aot.Enabled, name);
|
||||
Operand pte = Aot.Enabled
|
||||
? Const(context.Memory.PageTable.ToInt64(), true, Aot.PageTableIndex)
|
||||
: Const(context.Memory.PageTable.ToInt64());
|
||||
|
||||
int bit = MemoryManager.PageBits;
|
||||
|
||||
|
|
|
@ -13,7 +13,7 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||
|
||||
public bool DisableCF { get; private set; }
|
||||
|
||||
public string Name { get; private set; }
|
||||
public int? Index { get; private set; }
|
||||
|
||||
public LinkedList<Node> Assignments { get; }
|
||||
public LinkedList<Node> Uses { get; }
|
||||
|
@ -40,13 +40,13 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||
Value = (uint)value;
|
||||
}
|
||||
|
||||
public Operand(long value, bool disableCF = false, string name = null) : this(OperandKind.Constant, OperandType.I64)
|
||||
public Operand(long value, bool disableCF = false, int? index = null) : this(OperandKind.Constant, OperandType.I64)
|
||||
{
|
||||
Value = (ulong)value;
|
||||
|
||||
DisableCF = disableCF;
|
||||
|
||||
Name = name;
|
||||
Index = index;
|
||||
}
|
||||
|
||||
public Operand(ulong value) : this(OperandKind.Constant, OperandType.I64)
|
||||
|
|
|
@ -22,9 +22,9 @@ namespace ARMeilleure.IntermediateRepresentation
|
|||
return new Operand(value);
|
||||
}
|
||||
|
||||
public static Operand Const(long value, bool disableCF = false, string name = null)
|
||||
public static Operand Const(long value, bool disableCF = false, int? index = null)
|
||||
{
|
||||
return new Operand(value, disableCF, name);
|
||||
return new Operand(value, disableCF, index);
|
||||
}
|
||||
|
||||
public static Operand Const(ulong value)
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
using ARMeilleure.CodeGen;
|
||||
using ARMeilleure.Memory;
|
||||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Diagnostics;
|
||||
|
@ -13,6 +12,8 @@ namespace ARMeilleure.Translation.AOT
|
|||
{
|
||||
public static class Aot
|
||||
{
|
||||
private const int InternalVersion = 0;
|
||||
|
||||
private const string BaseDir = "Ryujinx";
|
||||
|
||||
private const string TitleIdTextDefault = "0000000000000000";
|
||||
|
@ -22,6 +23,8 @@ namespace ARMeilleure.Translation.AOT
|
|||
|
||||
internal const int MinCodeLengthToSave = 0x180; // Bytes.
|
||||
|
||||
internal const int PageTableIndex = -1;
|
||||
|
||||
private const CompressionLevel SaveCompressionLevel = CompressionLevel.Fastest;
|
||||
|
||||
private static readonly MemoryStream _infosStream;
|
||||
|
@ -72,7 +75,7 @@ namespace ARMeilleure.Translation.AOT
|
|||
_disposed = false;
|
||||
}
|
||||
|
||||
public static void Init(string titleIdText, string displayVersion, bool enabled = true, bool readOnlyMode = false)
|
||||
public static void Init(string titleIdText, string displayVersion, bool enabled, bool readOnlyMode)
|
||||
{
|
||||
if (String.IsNullOrEmpty(titleIdText) || titleIdText == TitleIdTextDefault)
|
||||
{
|
||||
|
@ -140,31 +143,38 @@ namespace ARMeilleure.Translation.AOT
|
|||
{
|
||||
cacheStream.Seek((long)hashSize, SeekOrigin.Begin);
|
||||
|
||||
ReadHeader(cacheStream, out int infosLen, out int codesLen, out int relocsLen);
|
||||
ReadHeader(cacheStream, out int cacheFileVersion, out int infosLen, out int codesLen, out int relocsLen);
|
||||
|
||||
if (infosLen % InfoEntry.Size == 0)
|
||||
if (cacheFileVersion == (int)InternalVersion)
|
||||
{
|
||||
byte[] infosBuf = new byte[infosLen];
|
||||
byte[] codesBuf = new byte[codesLen];
|
||||
byte[] relocsBuf = new byte[relocsLen];
|
||||
|
||||
cacheStream.Read(infosBuf, 0, infosLen);
|
||||
cacheStream.Read(codesBuf, 0, codesLen);
|
||||
cacheStream.Read(relocsBuf, 0, relocsLen);
|
||||
|
||||
if (cacheStream.Position == cacheStream.Length)
|
||||
if (infosLen % InfoEntry.Size == 0)
|
||||
{
|
||||
try
|
||||
byte[] infosBuf = new byte[infosLen];
|
||||
byte[] codesBuf = new byte[codesLen];
|
||||
byte[] relocsBuf = new byte[relocsLen];
|
||||
|
||||
cacheStream.Read(infosBuf, 0, infosLen);
|
||||
cacheStream.Read(codesBuf, 0, codesLen);
|
||||
cacheStream.Read(relocsBuf, 0, relocsLen);
|
||||
|
||||
if (cacheStream.Position == cacheStream.Length)
|
||||
{
|
||||
_infosStream. Write(infosBuf, 0, infosLen);
|
||||
_codesStream. Write(codesBuf, 0, codesLen);
|
||||
_relocsStream.Write(relocsBuf, 0, relocsLen);
|
||||
try
|
||||
{
|
||||
_infosStream. Write(infosBuf, 0, infosLen);
|
||||
_codesStream. Write(codesBuf, 0, codesLen);
|
||||
_relocsStream.Write(relocsBuf, 0, relocsLen);
|
||||
}
|
||||
catch
|
||||
{
|
||||
_infosStream. SetLength(0L);
|
||||
_codesStream. SetLength(0L);
|
||||
_relocsStream.SetLength(0L);
|
||||
}
|
||||
}
|
||||
catch
|
||||
else
|
||||
{
|
||||
_infosStream. SetLength(0L);
|
||||
_codesStream. SetLength(0L);
|
||||
_relocsStream.SetLength(0L);
|
||||
InvalidateCompressedCacheStream(compressedCacheStream);
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -216,12 +226,15 @@ namespace ARMeilleure.Translation.AOT
|
|||
|
||||
private static void ReadHeader(
|
||||
MemoryStream cacheStream,
|
||||
out int cacheFileVersion,
|
||||
out int infosLen,
|
||||
out int codesLen,
|
||||
out int relocsLen)
|
||||
{
|
||||
BinaryReader headerReader = new BinaryReader(cacheStream, EncodingCache.UTF8NoBOM, true);
|
||||
|
||||
cacheFileVersion = headerReader.ReadInt32();
|
||||
|
||||
infosLen = headerReader.ReadInt32();
|
||||
codesLen = headerReader.ReadInt32();
|
||||
relocsLen = headerReader.ReadInt32();
|
||||
|
@ -303,6 +316,8 @@ namespace ARMeilleure.Translation.AOT
|
|||
{
|
||||
BinaryWriter headerWriter = new BinaryWriter(cacheStream, EncodingCache.UTF8NoBOM, true);
|
||||
|
||||
headerWriter.Write((int)InternalVersion);
|
||||
|
||||
headerWriter.Write((int)_infosStream. Length); // infosLen
|
||||
headerWriter.Write((int)_codesStream. Length); // codesLen
|
||||
headerWriter.Write((int)_relocsStream.Length); // relocsLen
|
||||
|
@ -375,10 +390,10 @@ namespace ARMeilleure.Translation.AOT
|
|||
|
||||
for (int i = 0; i < relocEntriesCount; i++)
|
||||
{
|
||||
int position = relocReader.ReadInt32();
|
||||
string name = relocReader.ReadString();
|
||||
int position = relocReader.ReadInt32();
|
||||
int index = relocReader.ReadInt32();
|
||||
|
||||
relocEntries[i] = new RelocEntry(position, name);
|
||||
relocEntries[i] = new RelocEntry(position, index);
|
||||
}
|
||||
|
||||
return relocEntries;
|
||||
|
@ -390,11 +405,11 @@ namespace ARMeilleure.Translation.AOT
|
|||
{
|
||||
byte[] immBytes = new byte[8];
|
||||
|
||||
if (relocEntry.Name == nameof(MemoryManager.PageTable))
|
||||
if (relocEntry.Index == PageTableIndex)
|
||||
{
|
||||
immBytes = BitConverter.GetBytes((ulong)pageTable.ToInt64());
|
||||
}
|
||||
else if (Delegates.TryGetDelegateFuncPtr(relocEntry.Name, out IntPtr funcPtr))
|
||||
else if (Delegates.TryGetDelegateFuncPtr(relocEntry.Index, out IntPtr funcPtr)) // By delegate index.
|
||||
{
|
||||
immBytes = BitConverter.GetBytes((ulong)funcPtr.ToInt64());
|
||||
}
|
||||
|
|
|
@ -29,7 +29,7 @@ namespace ARMeilleure.Translation.AOT
|
|||
public void WriteRelocEntry(RelocEntry relocEntry)
|
||||
{
|
||||
_relocWriter.Write(relocEntry.Position);
|
||||
_relocWriter.Write(relocEntry.Name);
|
||||
_relocWriter.Write(relocEntry.Index);
|
||||
|
||||
RelocEntriesCount++;
|
||||
}
|
||||
|
|
|
@ -2,18 +2,18 @@ namespace ARMeilleure.Translation.AOT
|
|||
{
|
||||
struct RelocEntry
|
||||
{
|
||||
public int Position;
|
||||
public string Name;
|
||||
public int Position;
|
||||
public int Index;
|
||||
|
||||
public RelocEntry(int position, string name)
|
||||
public RelocEntry(int position, int index)
|
||||
{
|
||||
Position = position;
|
||||
Name = name;
|
||||
Index = index;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"({nameof(Position)} = {Position}, {nameof(Name)} = {Name})";
|
||||
return $"({nameof(Position)} = {Position}, {nameof(Index)} = {Index})";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
|
@ -9,50 +7,13 @@ namespace ARMeilleure.Translation
|
|||
{
|
||||
private readonly Delegate _dlg; // Ensure that this delegate will not be garbage collected.
|
||||
|
||||
public IntPtr FuncPtr { get; }
|
||||
public OperandType RetType { get; }
|
||||
public IntPtr FuncPtr { get; }
|
||||
|
||||
public DelegateInfo(Delegate dlg)
|
||||
{
|
||||
_dlg = dlg;
|
||||
|
||||
FuncPtr = Marshal.GetFunctionPointerForDelegate<Delegate>(dlg);
|
||||
RetType = GetOperandType(dlg.Method.ReturnType);
|
||||
}
|
||||
|
||||
private static OperandType GetOperandType(Type type)
|
||||
{
|
||||
if (type == typeof(bool) || type == typeof(byte) ||
|
||||
type == typeof(char) || type == typeof(short) ||
|
||||
type == typeof(int) || type == typeof(sbyte) ||
|
||||
type == typeof(ushort) || type == typeof(uint))
|
||||
{
|
||||
return OperandType.I32;
|
||||
}
|
||||
else if (type == typeof(long) || type == typeof(ulong))
|
||||
{
|
||||
return OperandType.I64;
|
||||
}
|
||||
else if (type == typeof(double))
|
||||
{
|
||||
return OperandType.FP64;
|
||||
}
|
||||
else if (type == typeof(float))
|
||||
{
|
||||
return OperandType.FP32;
|
||||
}
|
||||
else if (type == typeof(V128))
|
||||
{
|
||||
return OperandType.V128;
|
||||
}
|
||||
else if (type == typeof(void))
|
||||
{
|
||||
return OperandType.None;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Invalid type \"{type.Name}\".");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -7,16 +7,11 @@ namespace ARMeilleure.Translation
|
|||
{
|
||||
static class Delegates
|
||||
{
|
||||
public static bool TryGetDelegateFuncPtr(string key, out IntPtr funcPtr)
|
||||
public static bool TryGetDelegateFuncPtr(int index, out IntPtr funcPtr) // By delegate index.
|
||||
{
|
||||
if (key == null)
|
||||
if (index >= 0 && index < _delegates.Count)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(key));
|
||||
}
|
||||
|
||||
if (_delegates.TryGetValue(key, out DelegateInfo dlgInfo))
|
||||
{
|
||||
funcPtr = dlgInfo.FuncPtr;
|
||||
funcPtr = _delegates.Values[index].FuncPtr;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -28,38 +23,61 @@ namespace ARMeilleure.Translation
|
|||
}
|
||||
}
|
||||
|
||||
public static DelegateInfo GetDelegateInfo(string key)
|
||||
public static IntPtr GetDelegateFuncPtr(MethodInfo info)
|
||||
{
|
||||
if (key == null)
|
||||
if (info == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(key));
|
||||
throw new ArgumentNullException(nameof(info));
|
||||
}
|
||||
|
||||
string key = GetKey(info);
|
||||
|
||||
if (!_delegates.TryGetValue(key, out DelegateInfo dlgInfo))
|
||||
{
|
||||
throw new ArgumentException($"({nameof(key)} = {key})");
|
||||
}
|
||||
|
||||
return dlgInfo;
|
||||
return dlgInfo.FuncPtr;
|
||||
}
|
||||
|
||||
public static int GetDelegateIndex(MethodInfo info)
|
||||
{
|
||||
if (info == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(info));
|
||||
}
|
||||
|
||||
string key = GetKey(info);
|
||||
|
||||
int index = _delegates.IndexOfKey(key);
|
||||
|
||||
if (index == -1)
|
||||
{
|
||||
throw new ArgumentException($"({nameof(key)} = {key})");
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
private static void SetDelegateInfo(MethodInfo info)
|
||||
{
|
||||
string key = $"{info.DeclaringType.Name}.{info.Name}";
|
||||
string key = GetKey(info);
|
||||
|
||||
Delegate dlg = DelegateHelpers.GetDelegate(info);
|
||||
|
||||
if (!_delegates.TryAdd(key, new DelegateInfo(dlg)))
|
||||
{
|
||||
throw new ArgumentException($"({nameof(key)} = {key})");
|
||||
}
|
||||
_delegates.Add(key, new DelegateInfo(dlg)); // ArgumentException (key)
|
||||
}
|
||||
|
||||
private static readonly Dictionary<string, DelegateInfo> _delegates;
|
||||
private static string GetKey(MethodInfo info)
|
||||
{
|
||||
return $"{info.DeclaringType.Name}.{info.Name}";
|
||||
}
|
||||
|
||||
private static readonly SortedList<string, DelegateInfo> _delegates;
|
||||
|
||||
static Delegates()
|
||||
{
|
||||
_delegates = new Dictionary<string, DelegateInfo>();
|
||||
_delegates = new SortedList<string, DelegateInfo>();
|
||||
|
||||
SetDelegateInfo(typeof(Math).GetMethod(nameof(Math.Abs), new Type[] { typeof(double) }));
|
||||
SetDelegateInfo(typeof(Math).GetMethod(nameof(Math.Ceiling), new Type[] { typeof(double) }));
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using ARMeilleure.IntermediateRepresentation;
|
||||
using ARMeilleure.State;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
@ -81,11 +82,55 @@ namespace ARMeilleure.Translation
|
|||
|
||||
public Operand Call(MethodInfo info, params Operand[] callArgs)
|
||||
{
|
||||
string name = $"{info.DeclaringType.Name}.{info.Name}";
|
||||
IntPtr funcPtr = Delegates.GetDelegateFuncPtr(info);
|
||||
|
||||
DelegateInfo dlgInfo = Delegates.GetDelegateInfo(name);
|
||||
OperandType retType = GetOperandType(info.ReturnType);
|
||||
|
||||
return Call(Const(dlgInfo.FuncPtr.ToInt64(), Aot.Enabled, name), dlgInfo.RetType, callArgs);
|
||||
if (Aot.Enabled)
|
||||
{
|
||||
int index = Delegates.GetDelegateIndex(info);
|
||||
|
||||
return Call(Const(funcPtr.ToInt64(), true, index), retType, callArgs);
|
||||
}
|
||||
else
|
||||
{
|
||||
return Call(Const(funcPtr.ToInt64()), retType, callArgs);
|
||||
}
|
||||
}
|
||||
|
||||
private static OperandType GetOperandType(Type type)
|
||||
{
|
||||
if (type == typeof(bool) || type == typeof(byte) ||
|
||||
type == typeof(char) || type == typeof(short) ||
|
||||
type == typeof(int) || type == typeof(sbyte) ||
|
||||
type == typeof(ushort) || type == typeof(uint))
|
||||
{
|
||||
return OperandType.I32;
|
||||
}
|
||||
else if (type == typeof(long) || type == typeof(ulong))
|
||||
{
|
||||
return OperandType.I64;
|
||||
}
|
||||
else if (type == typeof(double))
|
||||
{
|
||||
return OperandType.FP64;
|
||||
}
|
||||
else if (type == typeof(float))
|
||||
{
|
||||
return OperandType.FP32;
|
||||
}
|
||||
else if (type == typeof(V128))
|
||||
{
|
||||
return OperandType.V128;
|
||||
}
|
||||
else if (type == typeof(void))
|
||||
{
|
||||
return OperandType.None;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Invalid type \"{type.Name}\".");
|
||||
}
|
||||
}
|
||||
|
||||
public Operand Call(Operand address, OperandType returnType, params Operand[] callArgs)
|
||||
|
|
|
@ -584,7 +584,7 @@ namespace Ryujinx.HLE.HOS
|
|||
|
||||
Logger.PrintInfo(LogClass.Loader, "AOT Init...");
|
||||
|
||||
Aot.Init(TitleIdText, DisplayVersion);
|
||||
Aot.Init(TitleIdText, DisplayVersion, enabled: true, readOnlyMode: false);
|
||||
|
||||
ProgramLoader.LoadStaticObjects(this, metaData, staticObjects.ToArray());
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue