[fix] 解决MethodBridge生成不稳定的问题

main
walon 2023-06-27 08:57:02 +08:00
parent 2988aef85a
commit 3d68dc4db3
5 changed files with 28 additions and 58 deletions

View File

@ -35,9 +35,9 @@ namespace HybridCLR.Editor.MethodBridge
private PlatformABI _platformABI; private PlatformABI _platformABI;
private readonly IReadOnlyList<MethodDef> _notGenericMethods; private readonly List<MethodDef> _notGenericMethods;
private readonly IReadOnlyCollection<GenericMethod> _genericMethods; private readonly List<GenericMethod> _genericMethods;
private readonly HashSet<GenericMethod> _preservedMethods; private readonly HashSet<GenericMethod> _preservedMethods;
@ -51,21 +51,22 @@ namespace HybridCLR.Editor.MethodBridge
private readonly HashSet<MethodDesc> _managed2nativeMethodSet = new HashSet<MethodDesc>(); private readonly HashSet<MethodDesc> _managed2nativeMethodSet = new HashSet<MethodDesc>();
private List<MethodDesc> _managed2nativeMethodList;
private readonly HashSet<MethodDesc> _native2managedMethodSet = new HashSet<MethodDesc>(); private readonly HashSet<MethodDesc> _native2managedMethodSet = new HashSet<MethodDesc>();
private List<MethodDesc> _native2managedMethodList;
private readonly HashSet<MethodDesc> _adjustThunkMethodSet = new HashSet<MethodDesc>(); private readonly HashSet<MethodDesc> _adjustThunkMethodSet = new HashSet<MethodDesc>();
private List<MethodDesc> _adjustThunkMethodList;
public Generator(Options options) public Generator(Options options)
{ {
_platformABI = options.PlatformABI; _platformABI = options.PlatformABI;
_notGenericMethods = options.NotGenericMethods;
_genericMethods = options.GenericMethods; List<(MethodDef, string)> notGenericMethodInfo = options.NotGenericMethods.Select(m => (m, m.FullName)).ToList();
notGenericMethodInfo.Sort((a, b) => string.Compare(a.Item2, b.Item2, StringComparison.Ordinal));
_notGenericMethods = notGenericMethodInfo.Select(m => m.Item1).ToList();
List<(GenericMethod, string)> genericMethodInfo = options.GenericMethods.Select(m => (m, m.ToString())).ToList();
genericMethodInfo.Sort((a, b) => string.CompareOrdinal(a.Item2, b.Item2));
_genericMethods = genericMethodInfo.Select(m => m.Item1).ToList();
_preservedMethods = options.SpeicalPreserveMethods; _preservedMethods = options.SpeicalPreserveMethods;
_templateCode = options.TemplateCode; _templateCode = options.TemplateCode;
_outputFile = options.OutputFile; _outputFile = options.OutputFile;
@ -182,31 +183,6 @@ namespace HybridCLR.Editor.MethodBridge
{ {
ProcessMethod(method.Method, method.KlassInst, method.MethodInst); ProcessMethod(method.Method, method.KlassInst, method.MethodInst);
} }
{
var sortedMethods = new SortedDictionary<string, MethodDesc>();
foreach (var method in _managed2nativeMethodSet)
{
sortedMethods.Add(method.CreateCallSigName(), method);
}
_managed2nativeMethodList = sortedMethods.Values.ToList();
}
{
var sortedMethods = new SortedDictionary<string, MethodDesc>();
foreach (var method in _native2managedMethodSet)
{
sortedMethods.Add(method.CreateCallSigName(), method);
}
_native2managedMethodList = sortedMethods.Values.ToList();
}
{
var sortedMethods = new SortedDictionary<string, MethodDesc>();
foreach (var method in _adjustThunkMethodSet)
{
sortedMethods.Add(method.CreateCallSigName(), method);
}
_adjustThunkMethodList = sortedMethods.Values.ToList();
}
} }
public void Generate() public void Generate()
@ -215,29 +191,38 @@ namespace HybridCLR.Editor.MethodBridge
List<string> lines = new List<string>(20_0000); List<string> lines = new List<string>(20_0000);
Debug.LogFormat("== managed2native:{0} native2managed:{1} adjustThunk:{2}", List<MethodDesc> managed2NativeMethodList = _managed2nativeMethodSet.ToList();
_managed2nativeMethodList.Count, _native2managedMethodList.Count, _adjustThunkMethodList.Count); managed2NativeMethodList.Sort((a, b) => string.CompareOrdinal(a.Sig, b.Sig));
foreach(var method in _managed2nativeMethodList) List<MethodDesc> native2ManagedMethodList = _native2managedMethodSet.ToList();
native2ManagedMethodList.Sort((a, b) => string.CompareOrdinal(a.Sig, b.Sig));
List<MethodDesc> adjustThunkMethodList = _adjustThunkMethodSet.ToList();
adjustThunkMethodList.Sort((a, b) => string.CompareOrdinal(a.Sig, b.Sig));
Debug.LogFormat("== managed2native:{0} native2managed:{1} adjustThunk:{2}",
managed2NativeMethodList.Count, native2ManagedMethodList.Count, adjustThunkMethodList.Count);
foreach(var method in managed2NativeMethodList)
{ {
_platformAdaptor.GenerateManaged2NativeMethod(method, lines); _platformAdaptor.GenerateManaged2NativeMethod(method, lines);
} }
_platformAdaptor.GenerateManaged2NativeStub(_managed2nativeMethodList, lines); _platformAdaptor.GenerateManaged2NativeStub(managed2NativeMethodList, lines);
foreach (var method in _native2managedMethodList) foreach (var method in native2ManagedMethodList)
{ {
_platformAdaptor.GenerateNative2ManagedMethod(method, lines); _platformAdaptor.GenerateNative2ManagedMethod(method, lines);
} }
_platformAdaptor.GenerateNative2ManagedStub(_native2managedMethodList, lines); _platformAdaptor.GenerateNative2ManagedStub(native2ManagedMethodList, lines);
foreach (var method in _adjustThunkMethodList) foreach (var method in adjustThunkMethodList)
{ {
_platformAdaptor.GenerateAdjustThunkMethod(method, lines); _platformAdaptor.GenerateAdjustThunkMethod(method, lines);
} }
_platformAdaptor.GenerateAdjustThunkStub(_adjustThunkMethodList, lines); _platformAdaptor.GenerateAdjustThunkStub(adjustThunkMethodList, lines);
frr.Replace("CODE", string.Join("\n", lines)); frr.Replace("CODE", string.Join("\n", lines));

View File

@ -19,12 +19,10 @@ namespace HybridCLR.Editor.MethodBridge
public override void GenerateManaged2NativeMethod(MethodDesc method, List<string> lines) public override void GenerateManaged2NativeMethod(MethodDesc method, List<string> lines)
{ {
int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.PlatformABI);
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" })); string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
string paramNameListStr = string.Join(", ", method.ParamInfos.Select(p => p.Managed2NativeParamValue(this.PlatformABI)).Concat(new string[] { "method" })); string paramNameListStr = string.Join(", ", method.ParamInfos.Select(p => p.Managed2NativeParamValue(this.PlatformABI)).Concat(new string[] { "method" }));
lines.Add($@" lines.Add($@"
// {method.MethodDef}
static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_t* argVarIndexs, StackObject* localVarBase, void* ret) static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_t* argVarIndexs, StackObject* localVarBase, void* ret)
{{ {{
typedef {method.ReturnInfo.Type.GetTypeName()} (*NativeMethod)({paramListStr}); typedef {method.ReturnInfo.Type.GetTypeName()} (*NativeMethod)({paramListStr});
@ -39,7 +37,6 @@ static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" })); string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
lines.Add($@" lines.Add($@"
// {method.MethodDef}
static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr}) static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr})
{{ {{
StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => p.Native2ManagedParamValue(this.PlatformABI)))} }}; StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => p.Native2ManagedParamValue(this.PlatformABI)))} }};
@ -57,7 +54,6 @@ static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" })); string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
lines.Add($@" lines.Add($@"
// {method.MethodDef}
static {method.ReturnInfo.Type.GetTypeName()} __N2M_AdjustorThunk_{method.CreateCallSigName()}({paramListStr}) static {method.ReturnInfo.Type.GetTypeName()} __N2M_AdjustorThunk_{method.CreateCallSigName()}({paramListStr})
{{ {{
StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => (p.Index == 0 ? $"(uint64_t)(*(uint8_t**)&__arg{p.Index} + sizeof(Il2CppObject))" : p.Native2ManagedParamValue(this.PlatformABI))))} }}; StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => (p.Index == 0 ? $"(uint64_t)(*(uint8_t**)&__arg{p.Index} + sizeof(Il2CppObject))" : p.Native2ManagedParamValue(this.PlatformABI))))} }};

View File

@ -20,7 +20,6 @@ namespace HybridCLR.Editor.MethodBridge
string paramNameListStr = string.Join(", ", method.ParamInfos.Select(p => p.Managed2NativeParamValue(this.PlatformABI)).Concat(new string[] { "method" })); string paramNameListStr = string.Join(", ", method.ParamInfos.Select(p => p.Managed2NativeParamValue(this.PlatformABI)).Concat(new string[] { "method" }));
lines.Add($@" lines.Add($@"
// {method.MethodDef}
static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_t* argVarIndexs, StackObject* localVarBase, void* ret) static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_t* argVarIndexs, StackObject* localVarBase, void* ret)
{{ {{
typedef {method.ReturnInfo.Type.GetTypeName()} (*NativeMethod)({paramListStr}); typedef {method.ReturnInfo.Type.GetTypeName()} (*NativeMethod)({paramListStr});
@ -34,7 +33,6 @@ static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" })); string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
lines.Add($@" lines.Add($@"
// {method.MethodDef}
static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr}) static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr})
{{ {{
StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => p.Native2ManagedParamValue(this.PlatformABI)))} }}; StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => p.Native2ManagedParamValue(this.PlatformABI)))} }};
@ -51,7 +49,6 @@ static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" })); string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
lines.Add($@" lines.Add($@"
// {method.MethodDef}
static {method.ReturnInfo.Type.GetTypeName()} __N2M_AdjustorThunk_{method.CreateCallSigName()}({paramListStr}) static {method.ReturnInfo.Type.GetTypeName()} __N2M_AdjustorThunk_{method.CreateCallSigName()}({paramListStr})
{{ {{
StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => (p.Index == 0 ? $"(uint64_t)(*(uint8_t**)&__arg{p.Index} + sizeof(Il2CppObject))" : p.Native2ManagedParamValue(this.PlatformABI))))} }}; StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => (p.Index == 0 ? $"(uint64_t)(*(uint8_t**)&__arg{p.Index} + sizeof(Il2CppObject))" : p.Native2ManagedParamValue(this.PlatformABI))))} }};

View File

@ -17,14 +17,11 @@ namespace HybridCLR.Editor.MethodBridge
public override void GenerateManaged2NativeMethod(MethodDesc method, List<string> lines) public override void GenerateManaged2NativeMethod(MethodDesc method, List<string> lines)
{ {
int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.PlatformABI);
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" })); string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
string paramTypeListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()}").Concat(new string[] { "const MethodInfo*" })); ; string paramTypeListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()}").Concat(new string[] { "const MethodInfo*" })); ;
string paramNameListStr = string.Join(", ", method.ParamInfos.Select(p => p.Managed2NativeParamValue(this.PlatformABI)).Concat(new string[] { "method" })); string paramNameListStr = string.Join(", ", method.ParamInfos.Select(p => p.Managed2NativeParamValue(this.PlatformABI)).Concat(new string[] { "method" }));
lines.Add($@" lines.Add($@"
// {method.MethodDef}
static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_t* argVarIndexs, StackObject* localVarBase, void* ret) static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_t* argVarIndexs, StackObject* localVarBase, void* ret)
{{ {{
typedef {method.ReturnInfo.Type.GetTypeName()} (*NativeMethod)({paramListStr}); typedef {method.ReturnInfo.Type.GetTypeName()} (*NativeMethod)({paramListStr});
@ -37,7 +34,6 @@ static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_
int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.PlatformABI); int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.PlatformABI);
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" })); string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
lines.Add($@" lines.Add($@"
// {method.MethodDef}
static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr}) static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr})
{{ {{
StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => p.Native2ManagedParamValue(this.PlatformABI)))} }}; StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => p.Native2ManagedParamValue(this.PlatformABI)))} }};
@ -53,7 +49,6 @@ static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}
int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.PlatformABI); int totalQuadWordNum = method.ParamInfos.Count + method.ReturnInfo.GetParamSlotNum(this.PlatformABI);
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" })); string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
lines.Add($@" lines.Add($@"
// {method.MethodDef}
static {method.ReturnInfo.Type.GetTypeName()} __N2M_AdjustorThunk_{method.CreateCallSigName()}({paramListStr}) static {method.ReturnInfo.Type.GetTypeName()} __N2M_AdjustorThunk_{method.CreateCallSigName()}({paramListStr})
{{ {{
StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => (p.Index == 0 ? $"(uint64_t)(*(uint8_t**)&__arg{p.Index} + sizeof(Il2CppObject))" : p.Native2ManagedParamValue(this.PlatformABI))))} }}; StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => (p.Index == 0 ? $"(uint64_t)(*(uint8_t**)&__arg{p.Index} + sizeof(Il2CppObject))" : p.Native2ManagedParamValue(this.PlatformABI))))} }};

View File

@ -21,7 +21,6 @@ namespace HybridCLR.Editor.MethodBridge
string paramNameListStr = string.Join(", ", method.ParamInfos.Select(p => p.Managed2NativeParamValue(this.PlatformABI)).Concat(new string[] { "method" })); string paramNameListStr = string.Join(", ", method.ParamInfos.Select(p => p.Managed2NativeParamValue(this.PlatformABI)).Concat(new string[] { "method" }));
lines.Add($@" lines.Add($@"
// {method.MethodDef}
static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_t* argVarIndexs, StackObject* localVarBase, void* ret) static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_t* argVarIndexs, StackObject* localVarBase, void* ret)
{{ {{
typedef {method.ReturnInfo.Type.GetTypeName()} (*NativeMethod)({paramListStr}); typedef {method.ReturnInfo.Type.GetTypeName()} (*NativeMethod)({paramListStr});
@ -35,7 +34,6 @@ static void __M2N_{method.CreateCallSigName()}(const MethodInfo* method, uint16_
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" })); string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
lines.Add($@" lines.Add($@"
// {method.MethodDef}
static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr}) static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}({paramListStr})
{{ {{
StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => p.Native2ManagedParamValue(this.PlatformABI)))} }}; StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => p.Native2ManagedParamValue(this.PlatformABI)))} }};
@ -52,7 +50,6 @@ static {method.ReturnInfo.Type.GetTypeName()} __N2M_{method.CreateCallSigName()}
string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" })); string paramListStr = string.Join(", ", method.ParamInfos.Select(p => $"{p.Type.GetTypeName()} __arg{p.Index}").Concat(new string[] { "const MethodInfo* method" }));
lines.Add($@" lines.Add($@"
// {method.MethodDef}
static {method.ReturnInfo.Type.GetTypeName()} __N2M_AdjustorThunk_{method.CreateCallSigName()}({paramListStr}) static {method.ReturnInfo.Type.GetTypeName()} __N2M_AdjustorThunk_{method.CreateCallSigName()}({paramListStr})
{{ {{
StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => (p.Index == 0 ? $"(uint64_t)(*(uint8_t**)&__arg{p.Index} + sizeof(Il2CppObject))" : p.Native2ManagedParamValue(this.PlatformABI))))} }}; StackObject args[{Math.Max(totalQuadWordNum, 1)}] = {{{string.Join(", ", method.ParamInfos.Select(p => (p.Index == 0 ? $"(uint64_t)(*(uint8_t**)&__arg{p.Index} + sizeof(Il2CppObject))" : p.Native2ManagedParamValue(this.PlatformABI))))} }};