Remove unused tracing functionality from the CPU

This commit is contained in:
gdkchan 2018-07-03 18:18:03 -03:00
parent 741773910d
commit 5d32e28449
7 changed files with 79 additions and 204 deletions

View file

@ -4,8 +4,6 @@ public static class AOptimizations
{
public static bool DisableMemoryChecks = false;
public static bool GenerateCallStack = true;
private static bool UseAllSseIfAvailable = true;
private static bool UseSseIfAvailable = true;

View file

@ -1,12 +1,9 @@
using ChocolArm64.Decoder;
using ChocolArm64.Events;
using ChocolArm64.Instruction;
using ChocolArm64.Memory;
using ChocolArm64.State;
using ChocolArm64.Translation;
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Reflection.Emit;
namespace ChocolArm64
@ -15,24 +12,9 @@ namespace ChocolArm64
{
private ConcurrentDictionary<long, ATranslatedSub> CachedSubs;
private ConcurrentDictionary<long, string> SymbolTable;
public event EventHandler<ACpuTraceEventArgs> CpuTrace;
public bool EnableCpuTrace { get; set; }
public ATranslator(IReadOnlyDictionary<long, string> SymbolTable = null)
public ATranslator()
{
CachedSubs = new ConcurrentDictionary<long, ATranslatedSub>();
if (SymbolTable != null)
{
this.SymbolTable = new ConcurrentDictionary<long, string>(SymbolTable);
}
else
{
this.SymbolTable = new ConcurrentDictionary<long, string>();
}
}
internal void ExecuteSubroutine(AThread Thread, long Position)
@ -68,16 +50,6 @@ namespace ChocolArm64
{
do
{
if (EnableCpuTrace)
{
if (!SymbolTable.TryGetValue(Position, out string SubName))
{
SubName = string.Empty;
}
CpuTrace?.Invoke(this, new ACpuTraceEventArgs(Position, SubName));
}
if (!CachedSubs.TryGetValue(Position, out ATranslatedSub Sub))
{
Sub = TranslateTier0(State, Memory, Position);
@ -148,8 +120,6 @@ namespace ChocolArm64
string SubName = GetSubName(Position);
PropagateName(Cfg.Graph, SubName);
AILEmitterCtx Context = new AILEmitterCtx(this, Cfg.Graph, Cfg.Root, SubName);
if (Context.CurrBlock.Position != Position)
@ -185,22 +155,7 @@ namespace ChocolArm64
private string GetSubName(long Position)
{
return SymbolTable.GetOrAdd(Position, $"Sub{Position:x16}");
}
private void PropagateName(ABlock[] Graph, string Name)
{
foreach (ABlock Block in Graph)
{
AOpCode LastOp = Block.GetLastOp();
if (LastOp != null &&
(LastOp.Emitter == AInstEmit.Bl ||
LastOp.Emitter == AInstEmit.Blr))
{
SymbolTable.TryAdd(LastOp.Position + 4, Name);
}
}
return $"Sub{Position:x16}";
}
}
}

View file

@ -1,17 +0,0 @@
using System;
namespace ChocolArm64.Events
{
public class ACpuTraceEventArgs : EventArgs
{
public long Position { get; private set; }
public string SubName { get; private set; }
public ACpuTraceEventArgs(long Position, string SubName)
{
this.Position = Position;
this.SubName = SubName;
}
}
}

View file

@ -35,14 +35,6 @@ namespace ChocolArm64.Instruction
{
AOpCodeBImmAl Op = (AOpCodeBImmAl)Context.CurrOp;
if (AOptimizations.GenerateCallStack)
{
Context.EmitLdarg(ATranslatedSub.StateArgIdx);
Context.EmitLdc_I8(Op.Imm);
Context.EmitPrivateCall(typeof(AThreadState), nameof(AThreadState.EnterMethod));
}
Context.EmitLdc_I(Op.Position + 4);
Context.EmitStint(AThreadState.LRIndex);
Context.EmitStoreState();
@ -80,14 +72,6 @@ namespace ChocolArm64.Instruction
{
AOpCodeBReg Op = (AOpCodeBReg)Context.CurrOp;
if (AOptimizations.GenerateCallStack)
{
Context.EmitLdarg(ATranslatedSub.StateArgIdx);
Context.EmitLdintzr(Op.Rn);
Context.EmitPrivateCall(typeof(AThreadState), nameof(AThreadState.EnterMethod));
}
Context.EmitLdc_I(Op.Position + 4);
Context.EmitStint(AThreadState.LRIndex);
Context.EmitStoreState();
@ -100,14 +84,6 @@ namespace ChocolArm64.Instruction
{
AOpCodeBReg Op = (AOpCodeBReg)Context.CurrOp;
if (AOptimizations.GenerateCallStack)
{
Context.EmitLdarg(ATranslatedSub.StateArgIdx);
Context.EmitLdintzr(Op.Rn);
Context.EmitPrivateCall(typeof(AThreadState), nameof(AThreadState.JumpMethod));
}
Context.EmitStoreState();
Context.EmitLdintzr(Op.Rn);
@ -129,13 +105,6 @@ namespace ChocolArm64.Instruction
public static void Ret(AILEmitterCtx Context)
{
if (AOptimizations.GenerateCallStack)
{
Context.EmitLdarg(ATranslatedSub.StateArgIdx);
Context.EmitPrivateCall(typeof(AThreadState), nameof(AThreadState.ExitMethod));
}
Context.EmitStoreState();
Context.EmitLdint(AThreadState.LRIndex);

View file

@ -1,6 +1,5 @@
using ChocolArm64.Events;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.Intrinsics;
@ -80,17 +79,10 @@ namespace ChocolArm64.State
public event EventHandler<AInstExceptionEventArgs> SvcCall;
public event EventHandler<AInstUndefinedEventArgs> Undefined;
private Stack<long> CallStack;
private static Stopwatch TickCounter;
private static double HostTickFreq;
public AThreadState()
{
CallStack = new Stack<long>();
}
static AThreadState()
{
HostTickFreq = 1.0 / Stopwatch.Frequency;
@ -114,27 +106,5 @@ namespace ChocolArm64.State
{
Undefined?.Invoke(this, new AInstUndefinedEventArgs(Position, RawOpCode));
}
internal void EnterMethod(long Position)
{
CallStack.Push(Position);
}
internal void ExitMethod()
{
CallStack.TryPop(out _);
}
internal void JumpMethod(long Position)
{
CallStack.TryPop(out _);
CallStack.Push(Position);
}
public long[] GetCallStack()
{
return CallStack.ToArray();
}
}
}

View file

@ -1,22 +1,23 @@
using ChocolArm64.Memory;
using Ryujinx.HLE.Loaders.Executables;
using Ryujinx.HLE.OsHle;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
namespace Ryujinx.HLE.Loaders
{
class Executable
{
private AMemory Memory;
private List<ElfDyn> Dynamic;
private Dictionary<long, string> m_SymbolTable;
public IReadOnlyDictionary<long, string> SymbolTable => m_SymbolTable;
public ReadOnlyCollection<ElfSym> SymbolTable;
public string Name { get; private set; }
private AMemory Memory;
public long ImageBase { get; private set; }
public long ImageEnd { get; private set; }
@ -24,8 +25,6 @@ namespace Ryujinx.HLE.Loaders
{
Dynamic = new List<ElfDyn>();
m_SymbolTable = new Dictionary<long, string>();
Name = Exe.Name;
this.Memory = Memory;
@ -84,14 +83,18 @@ namespace Ryujinx.HLE.Loaders
long SymEntSize = GetFirstValue(ElfDynTag.DT_SYMENT);
List<ElfSym> Symbols = new List<ElfSym>();
while ((ulong)SymTblAddr < (ulong)StrTblAddr)
{
ElfSym Sym = GetSymbol(SymTblAddr, StrTblAddr);
m_SymbolTable.TryAdd(Sym.Value, Sym.Name);
Symbols.Add(Sym);
SymTblAddr += SymEntSize;
}
SymbolTable = Array.AsReadOnly(Symbols.OrderBy(x => x.Value).ToArray());
}
private void WriteData(

View file

@ -57,8 +57,6 @@ namespace Ryujinx.HLE.OsHle
private List<Executable> Executables;
private Dictionary<long, string> SymbolTable;
private long ImageBase;
private bool ShouldDispose;
@ -133,8 +131,6 @@ namespace Ryujinx.HLE.OsHle
return false;
}
MakeSymbolTable();
MapRWMemRegion(
MemoryRegions.MainStackAddress,
MemoryRegions.MainStackSize,
@ -201,7 +197,7 @@ namespace Ryujinx.HLE.OsHle
throw new ObjectDisposedException(nameof(Process));
}
AThread CpuThread = new AThread(GetTranslator(), Memory, EntryPoint);
AThread CpuThread = new AThread(new ATranslator(), Memory, EntryPoint);
KThread Thread = new KThread(CpuThread, this, ProcessorId, Priority);
@ -243,69 +239,22 @@ namespace Ryujinx.HLE.OsHle
throw new UndefinedInstructionException(e.Position, e.RawOpCode);
}
private void MakeSymbolTable()
{
SymbolTable = new Dictionary<long, string>();
foreach (Executable Exe in Executables)
{
foreach (KeyValuePair<long, string> KV in Exe.SymbolTable)
{
SymbolTable.TryAdd(Exe.ImageBase + KV.Key, KV.Value);
}
}
}
private ATranslator GetTranslator()
{
if (Translator == null)
{
Translator = new ATranslator(SymbolTable);
Translator.CpuTrace += CpuTraceHandler;
}
return Translator;
}
public void EnableCpuTracing()
{
Translator.EnableCpuTrace = true;
}
public void DisableCpuTracing()
{
Translator.EnableCpuTrace = false;
}
private void CpuTraceHandler(object sender, ACpuTraceEventArgs e)
{
string NsoName = string.Empty;
for (int Index = Executables.Count - 1; Index >= 0; Index--)
{
if (e.Position >= Executables[Index].ImageBase)
{
NsoName = $"{(e.Position - Executables[Index].ImageBase):x16}";
break;
}
}
Ns.Log.PrintDebug(LogClass.Cpu, $"Executing at 0x{e.Position:x16} {e.SubName} {NsoName}");
}
public void PrintStackTrace(AThreadState ThreadState)
{
long[] Positions = ThreadState.GetCallStack();
StringBuilder Trace = new StringBuilder();
Trace.AppendLine("Guest stack trace:");
foreach (long Position in Positions)
void AppendTrace(long Position)
{
if (!SymbolTable.TryGetValue(Position, out string SubName))
Executable Exe = GetNsoExecutable(Position);
if (Exe == null)
{
return;
}
if (!TryGetSubName(Exe, Position, out string SubName))
{
SubName = $"Sub{Position:x16}";
}
@ -314,13 +263,65 @@ namespace Ryujinx.HLE.OsHle
SubName = Demangler.Parse(SubName);
}
Trace.AppendLine(" " + SubName + " (" + GetNsoNameAndAddress(Position) + ")");
long Offset = Position - Exe.ImageBase;
string ExeNameWithAddr = $"{Exe.Name}:{Offset:x8}";
Trace.AppendLine(" " + SubName + " (" + ExeNameWithAddr + ")");
}
long FramePointer = (long)ThreadState.X29;
while (FramePointer != 0)
{
AppendTrace(Memory.ReadInt64(FramePointer + 8));
FramePointer = Memory.ReadInt64(FramePointer);
}
Ns.Log.PrintInfo(LogClass.Cpu, Trace.ToString());
}
private string GetNsoNameAndAddress(long Position)
private bool TryGetSubName(Executable Exe, long Position, out string Name)
{
Position -= Exe.ImageBase;
int Left = 0;
int Right = Exe.SymbolTable.Count - 1;
while (Left <= Right)
{
int Size = Right - Left;
int Middle = Left + (Size >> 1);
ElfSym Symbol = Exe.SymbolTable[Middle];
long EndPosition = Symbol.Value + Symbol.Size;
if ((ulong)Position >= (ulong)Symbol.Value && (ulong)Position < (ulong)EndPosition)
{
Name = Symbol.Name;
return true;
}
if ((ulong)Position < (ulong)Symbol.Value)
{
Right = Middle - 1;
}
else
{
Left = Middle + 1;
}
}
Name = null;
return false;
}
private Executable GetNsoExecutable(long Position)
{
string Name = string.Empty;
@ -328,15 +329,11 @@ namespace Ryujinx.HLE.OsHle
{
if (Position >= Executables[Index].ImageBase)
{
long Offset = Position - Executables[Index].ImageBase;
Name = $"{Executables[Index].Name}:{Offset:x8}";
break;
return Executables[Index];
}
}
return Name;
return null;
}
private int GetFreeTlsSlot(AThread Thread)