Skip to content

Commit

Permalink
Version 0.9.1, fix desyncs related to method names in traces
Browse files Browse the repository at this point in the history
  • Loading branch information
Zetrith committed Oct 19, 2023
1 parent 10349c3 commit 5adfff6
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 14 deletions.
4 changes: 3 additions & 1 deletion Source/Client/MultiplayerStatic.cs
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ public static class MultiplayerStatic
public static readonly Texture2D DiscordIcon = ContentFinder<Texture2D>.Get("Multiplayer/Discord");
public static readonly Texture2D Pulse = ContentFinder<Texture2D>.Get("Multiplayer/Pulse");

public static readonly Texture2D ChangeRelationIcon = ContentFinder<Texture2D>.Get("UI/Memes/Loyalist");
public static readonly Texture2D ChangeRelationIcon = ContentFinder<Texture2D>.Get("UI/Icons/VisitorsHelp");

static MultiplayerStatic()
{
Expand All @@ -48,6 +48,8 @@ static MultiplayerStatic()
}
);

Native.HarmonyOriginalGetter = MpUtil.GetOriginalFromHarmonyReplacement;

// UnityEngine.Debug.Log instead of Verse.Log.Message because the server runs on its own thread
ServerLog.info = str => Debug.Log($"MpServerLog: {str}");
ServerLog.error = str => Debug.Log($"MpServerLog Error: {str}");
Expand Down
6 changes: 3 additions & 3 deletions Source/Common/DeferredStackTracingImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,7 +96,7 @@ public unsafe static int TraceImpl(long[] traceIn, ref int hash)

trace[depth] = ret;

if (depth < HashInfluence)
if (depth < HashInfluence && info.nameHash != 0)
hash = HashCombineInt(hash, (int)info.nameHash);

if (++depth == MaxDepth)
Expand Down Expand Up @@ -135,7 +135,7 @@ static long UpdateNewElement(ref AddrInfo info, long ret)
info.stackUsage = stackUsage;

var rawName = Native.MethodNameFromAddr(ret, true); // Use the original instead of replacement for hashing
info.nameHash = rawName != null ? StableStringHash(rawName) : 1;
info.nameHash = rawName != null ? Native.GetMethodAggressiveInlining(ret) ? 0 : StableStringHash(rawName) : 1;

hashtableEntries++;
if (hashtableEntries > hashtableSize * LoadFactor)
Expand Down Expand Up @@ -179,7 +179,7 @@ static int ResizeHashtable()
return indexmask;
}

unsafe static long GetStackUsage(long addr)
static unsafe long GetStackUsage(long addr)
{
var ji = Native.mono_jit_info_table_find(Native.DomainPtr, (IntPtr)addr);

Expand Down
30 changes: 25 additions & 5 deletions Source/Common/Native.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Threading;
using HarmonyLib;

namespace Multiplayer.Client
{
Expand All @@ -19,6 +20,8 @@ public enum NativeOS
// current_thread->internal_thread->thread_info->tls[4]
public static long LmfPtr { get; private set; }

public static Func<long, MethodBase>? HarmonyOriginalGetter { get; set; }

public static void EarlyInit(NativeOS os)
{
if (os == NativeOS.Linux)
Expand Down Expand Up @@ -70,7 +73,7 @@ public static unsafe void InitLmfPtr(NativeOS os)
}
}

public static string MethodNameFromAddr(long addr, bool harmonyOriginals)
public static string? MethodNameFromAddr(long addr, bool harmonyOriginals)
{
var domain = DomainPtr;
var ji = mono_jit_info_table_find(domain, (IntPtr)addr);
Expand All @@ -80,18 +83,35 @@ public static string MethodNameFromAddr(long addr, bool harmonyOriginals)
var ptrToPrint = mono_jit_info_get_method(ji);
var codeStart = (long)mono_jit_info_get_code_start(ji);

if (harmonyOriginals)
if (harmonyOriginals && HarmonyOriginalGetter != null)
{
// var original = MpUtil.GetOriginalFromHarmonyReplacement(codeStart);
// if (original != null)
// ptrToPrint = original.MethodHandle.Value;
var original = HarmonyOriginalGetter(codeStart);
if (original != null)
ptrToPrint = original.MethodHandle.Value;
}

var name = mono_debug_print_stack_frame(ptrToPrint, -1, domain);

return string.IsNullOrEmpty(name) ? null : name;
}

private static ConstructorInfo RuntimeMethodHandleCtor = AccessTools.Constructor(typeof(RuntimeMethodHandle), new[]{typeof(IntPtr)});

public static bool GetMethodAggressiveInlining(long addr)
{
var domain = DomainPtr;
var ji = mono_jit_info_table_find(domain, (IntPtr)addr);

if (ji == IntPtr.Zero) return false;

var methodHandle = mono_jit_info_get_method(ji);
var methodInfo =
MethodBase.GetMethodFromHandle((RuntimeMethodHandle)RuntimeMethodHandleCtor.Invoke(new[] { (object)methodHandle }));

return (methodInfo.MethodImplementationFlags & MethodImplAttributes.AggressiveInlining) != 0;
}

// const string MonoWindows = "mono-2.0-sgen.dll";
const string MonoWindows = "mono-2.0-bdwgc";
const string MonoLinux = "libmonobdwgc-2.0.so";
const string MonoOSX = "libmonobdwgc-2.0.dylib";
Expand Down
4 changes: 2 additions & 2 deletions Source/Common/Version.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,8 @@ namespace Multiplayer.Common
{
public static class MpVersion
{
public const string Version = "0.9";
public const int Protocol = 34;
public const string Version = "0.9.1";
public const int Protocol = 35;

public const string ApiAssemblyName = "0MultiplayerAPI";

Expand Down
16 changes: 13 additions & 3 deletions Source/TestsOnMono/Program.cs
Original file line number Diff line number Diff line change
@@ -1,25 +1,35 @@
using System;
using System.Reflection;
using System.Runtime.CompilerServices;
using HarmonyLib;
using Multiplayer.Client;
using Multiplayer.Client.Desyncs;

class Program
{
public static unsafe void Main(string[] args)
public static void Main(string[] args)
{
Native.mini_parse_debug_option("disable_omit_fp");
Native.InitLmfPtr(Native.NativeOS.Dummy);
Native.EarlyInit(Native.NativeOS.Dummy);

Test();
Test1();
}

public static void Test()
{
int hash = 0;
long[] trace = new long[32];
long[] trace = new long[8];
DeferredStackTracingImpl.TraceImpl(trace, ref hash);
Console.WriteLine(hash);

foreach (long l in trace)
Console.WriteLine(Native.MethodNameFromAddr(l, false));
}

[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.NoInlining)]
public static void Test1()
{
Test();
}
}
1 change: 1 addition & 0 deletions Source/TestsOnMono/TestsOnMono.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

<ItemGroup>
<ProjectReference Include="..\Common\Common.csproj" />
<PackageReference Include="Lib.Harmony" Version="2.2.2" />
</ItemGroup>

</Project>

0 comments on commit 5adfff6

Please sign in to comment.