Impl. index-based relocation information. Impl. cache file version field.

This commit is contained in:
LDj3SNuD 2020-01-16 17:46:43 +01:00
parent 7d0d9703a1
commit 61ab170071
11 changed files with 145 additions and 106 deletions

View file

@ -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);

View file

@ -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;

View file

@ -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)

View file

@ -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)

View file

@ -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());
}

View file

@ -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++;
}

View file

@ -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})";
}
}
}

View file

@ -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}\".");
}
}
}
}

View file

@ -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) }));

View file

@ -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)

View file

@ -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());
}