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

This commit is contained in:
LDj3SNuD 2020-01-16 17:46:43 +01:00
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) 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); int rexPrefix = GetRexPrefix(dest, source, type, rrm: false);
@ -893,9 +893,9 @@ namespace ARMeilleure.CodeGen.X86
WriteByte((byte)(info.OpRImm64 + (dest.GetRegister().Index & 0b111))); 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); WriteUInt64(imm);

View file

@ -290,9 +290,9 @@ namespace ARMeilleure.Instructions
private static Operand EmitPtPointerLoad(ArmEmitterContext context, Operand address, Operand lblFallbackPath) private static Operand EmitPtPointerLoad(ArmEmitterContext context, Operand address, Operand lblFallbackPath)
{ {
string name = nameof(MemoryManager.PageTable); Operand pte = Aot.Enabled
? Const(context.Memory.PageTable.ToInt64(), true, Aot.PageTableIndex)
Operand pte = Const(context.Memory.PageTable.ToInt64(), Aot.Enabled, name); : Const(context.Memory.PageTable.ToInt64());
int bit = MemoryManager.PageBits; int bit = MemoryManager.PageBits;

View file

@ -13,7 +13,7 @@ namespace ARMeilleure.IntermediateRepresentation
public bool DisableCF { get; private set; } 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> Assignments { get; }
public LinkedList<Node> Uses { get; } public LinkedList<Node> Uses { get; }
@ -40,13 +40,13 @@ namespace ARMeilleure.IntermediateRepresentation
Value = (uint)value; 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; Value = (ulong)value;
DisableCF = disableCF; DisableCF = disableCF;
Name = name; Index = index;
} }
public Operand(ulong value) : this(OperandKind.Constant, OperandType.I64) public Operand(ulong value) : this(OperandKind.Constant, OperandType.I64)

View file

@ -22,9 +22,9 @@ namespace ARMeilleure.IntermediateRepresentation
return new Operand(value); 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) public static Operand Const(ulong value)

View file

@ -1,5 +1,4 @@
using ARMeilleure.CodeGen; using ARMeilleure.CodeGen;
using ARMeilleure.Memory;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Diagnostics; using System.Diagnostics;
@ -13,6 +12,8 @@ namespace ARMeilleure.Translation.AOT
{ {
public static class Aot public static class Aot
{ {
private const int InternalVersion = 0;
private const string BaseDir = "Ryujinx"; private const string BaseDir = "Ryujinx";
private const string TitleIdTextDefault = "0000000000000000"; private const string TitleIdTextDefault = "0000000000000000";
@ -22,6 +23,8 @@ namespace ARMeilleure.Translation.AOT
internal const int MinCodeLengthToSave = 0x180; // Bytes. internal const int MinCodeLengthToSave = 0x180; // Bytes.
internal const int PageTableIndex = -1;
private const CompressionLevel SaveCompressionLevel = CompressionLevel.Fastest; private const CompressionLevel SaveCompressionLevel = CompressionLevel.Fastest;
private static readonly MemoryStream _infosStream; private static readonly MemoryStream _infosStream;
@ -72,7 +75,7 @@ namespace ARMeilleure.Translation.AOT
_disposed = false; _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) if (String.IsNullOrEmpty(titleIdText) || titleIdText == TitleIdTextDefault)
{ {
@ -140,8 +143,10 @@ namespace ARMeilleure.Translation.AOT
{ {
cacheStream.Seek((long)hashSize, SeekOrigin.Begin); 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 (cacheFileVersion == (int)InternalVersion)
{
if (infosLen % InfoEntry.Size == 0) if (infosLen % InfoEntry.Size == 0)
{ {
byte[] infosBuf = new byte[infosLen]; byte[] infosBuf = new byte[infosLen];
@ -182,6 +187,11 @@ namespace ARMeilleure.Translation.AOT
InvalidateCompressedCacheStream(compressedCacheStream); InvalidateCompressedCacheStream(compressedCacheStream);
} }
} }
else
{
InvalidateCompressedCacheStream(compressedCacheStream);
}
}
catch catch
{ {
InvalidateCompressedCacheStream(compressedCacheStream); InvalidateCompressedCacheStream(compressedCacheStream);
@ -216,12 +226,15 @@ namespace ARMeilleure.Translation.AOT
private static void ReadHeader( private static void ReadHeader(
MemoryStream cacheStream, MemoryStream cacheStream,
out int cacheFileVersion,
out int infosLen, out int infosLen,
out int codesLen, out int codesLen,
out int relocsLen) out int relocsLen)
{ {
BinaryReader headerReader = new BinaryReader(cacheStream, EncodingCache.UTF8NoBOM, true); BinaryReader headerReader = new BinaryReader(cacheStream, EncodingCache.UTF8NoBOM, true);
cacheFileVersion = headerReader.ReadInt32();
infosLen = headerReader.ReadInt32(); infosLen = headerReader.ReadInt32();
codesLen = headerReader.ReadInt32(); codesLen = headerReader.ReadInt32();
relocsLen = headerReader.ReadInt32(); relocsLen = headerReader.ReadInt32();
@ -303,6 +316,8 @@ namespace ARMeilleure.Translation.AOT
{ {
BinaryWriter headerWriter = new BinaryWriter(cacheStream, EncodingCache.UTF8NoBOM, true); BinaryWriter headerWriter = new BinaryWriter(cacheStream, EncodingCache.UTF8NoBOM, true);
headerWriter.Write((int)InternalVersion);
headerWriter.Write((int)_infosStream. Length); // infosLen headerWriter.Write((int)_infosStream. Length); // infosLen
headerWriter.Write((int)_codesStream. Length); // codesLen headerWriter.Write((int)_codesStream. Length); // codesLen
headerWriter.Write((int)_relocsStream.Length); // relocsLen headerWriter.Write((int)_relocsStream.Length); // relocsLen
@ -376,9 +391,9 @@ namespace ARMeilleure.Translation.AOT
for (int i = 0; i < relocEntriesCount; i++) for (int i = 0; i < relocEntriesCount; i++)
{ {
int position = relocReader.ReadInt32(); int position = relocReader.ReadInt32();
string name = relocReader.ReadString(); int index = relocReader.ReadInt32();
relocEntries[i] = new RelocEntry(position, name); relocEntries[i] = new RelocEntry(position, index);
} }
return relocEntries; return relocEntries;
@ -390,11 +405,11 @@ namespace ARMeilleure.Translation.AOT
{ {
byte[] immBytes = new byte[8]; byte[] immBytes = new byte[8];
if (relocEntry.Name == nameof(MemoryManager.PageTable)) if (relocEntry.Index == PageTableIndex)
{ {
immBytes = BitConverter.GetBytes((ulong)pageTable.ToInt64()); 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()); immBytes = BitConverter.GetBytes((ulong)funcPtr.ToInt64());
} }

View file

@ -29,7 +29,7 @@ namespace ARMeilleure.Translation.AOT
public void WriteRelocEntry(RelocEntry relocEntry) public void WriteRelocEntry(RelocEntry relocEntry)
{ {
_relocWriter.Write(relocEntry.Position); _relocWriter.Write(relocEntry.Position);
_relocWriter.Write(relocEntry.Name); _relocWriter.Write(relocEntry.Index);
RelocEntriesCount++; RelocEntriesCount++;
} }

View file

@ -3,17 +3,17 @@ namespace ARMeilleure.Translation.AOT
struct RelocEntry struct RelocEntry
{ {
public int Position; public int Position;
public string Name; public int Index;
public RelocEntry(int position, string name) public RelocEntry(int position, int index)
{ {
Position = position; Position = position;
Name = name; Index = index;
} }
public override string ToString() 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;
using System.Runtime.InteropServices; using System.Runtime.InteropServices;
@ -10,49 +8,12 @@ namespace ARMeilleure.Translation
private readonly Delegate _dlg; // Ensure that this delegate will not be garbage collected. private readonly Delegate _dlg; // Ensure that this delegate will not be garbage collected.
public IntPtr FuncPtr { get; } public IntPtr FuncPtr { get; }
public OperandType RetType { get; }
public DelegateInfo(Delegate dlg) public DelegateInfo(Delegate dlg)
{ {
_dlg = dlg; _dlg = dlg;
FuncPtr = Marshal.GetFunctionPointerForDelegate<Delegate>(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 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)); funcPtr = _delegates.Values[index].FuncPtr;
}
if (_delegates.TryGetValue(key, out DelegateInfo dlgInfo))
{
funcPtr = dlgInfo.FuncPtr;
return true; 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)) if (!_delegates.TryGetValue(key, out DelegateInfo dlgInfo))
{ {
throw new ArgumentException($"({nameof(key)} = {key})"); 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) private static void SetDelegateInfo(MethodInfo info)
{ {
string key = $"{info.DeclaringType.Name}.{info.Name}"; string key = GetKey(info);
Delegate dlg = DelegateHelpers.GetDelegate(info); Delegate dlg = DelegateHelpers.GetDelegate(info);
if (!_delegates.TryAdd(key, new DelegateInfo(dlg))) _delegates.Add(key, new DelegateInfo(dlg)); // ArgumentException (key)
{
throw new ArgumentException($"({nameof(key)} = {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() 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.Abs), new Type[] { typeof(double) }));
SetDelegateInfo(typeof(Math).GetMethod(nameof(Math.Ceiling), 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.IntermediateRepresentation;
using ARMeilleure.State;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Reflection; using System.Reflection;
@ -81,11 +82,55 @@ namespace ARMeilleure.Translation
public Operand Call(MethodInfo info, params Operand[] callArgs) 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) 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..."); Logger.PrintInfo(LogClass.Loader, "AOT Init...");
Aot.Init(TitleIdText, DisplayVersion); Aot.Init(TitleIdText, DisplayVersion, enabled: true, readOnlyMode: false);
ProgramLoader.LoadStaticObjects(this, metaData, staticObjects.ToArray()); ProgramLoader.LoadStaticObjects(this, metaData, staticObjects.ToArray());
} }