From 51d4c0c650b332333bd3ab49816ff54940f4d2b7 Mon Sep 17 00:00:00 2001 From: liiir1985 Date: Thu, 30 Nov 2023 11:11:40 +0800 Subject: [PATCH] Improve missing method handling, better exception handling is now possible --- ILRuntime/CLR/Method/ILMethod.cs | 38 ++++++++++----- ILRuntime/Runtime/Enviorment/AppDomain.cs | 13 +++++ ILRuntime/Runtime/Intepreter/ILIntepreter.cs | 9 ++++ ILRuntimeTestBase/TestFramework/TestClass3.cs | 26 +++++++++- TestCases/CLRBindingTest.cs | 47 ++++++++++++++++++- 5 files changed, 118 insertions(+), 15 deletions(-) diff --git a/ILRuntime/CLR/Method/ILMethod.cs b/ILRuntime/CLR/Method/ILMethod.cs index dbf305a1..e4c12dde 100644 --- a/ILRuntime/CLR/Method/ILMethod.cs +++ b/ILRuntime/CLR/Method/ILMethod.cs @@ -736,29 +736,41 @@ unsafe void InitToken(ref OpCode code, object token, Dictionary typesByIndex = new List(); ThreadSafeDictionary mapTypeToken = new ThreadSafeDictionary(); ThreadSafeDictionary mapMethod = new ThreadSafeDictionary(); + ThreadSafeDictionary mapException = new ThreadSafeDictionary(); ThreadSafeDictionary mapString = new ThreadSafeDictionary(); Dictionary redirectMap = new Dictionary(); Dictionary fieldGetterMap = new Dictionary(); @@ -1544,6 +1545,18 @@ bool IsInvalidMethodReference(MethodReference _ref) } return false; } + + internal void CacheException(Exception ex) + { + mapException[ex.GetHashCode()] = ex; + } + + internal Exception GetException(int token) + { + if (mapException.TryGetValue(token, out var ex)) + return ex; + return null; + } internal IMethod GetMethod(object token, ILType contextType, ILMethod contextMethod, out bool invalidToken) diff --git a/ILRuntime/Runtime/Intepreter/ILIntepreter.cs b/ILRuntime/Runtime/Intepreter/ILIntepreter.cs index 2b5c2ca7..3ac3daf8 100644 --- a/ILRuntime/Runtime/Intepreter/ILIntepreter.cs +++ b/ILRuntime/Runtime/Intepreter/ILIntepreter.cs @@ -1971,6 +1971,15 @@ public object Run(ILMethod method, object instance, object[] p) IMethod m = domain.GetMethod(ip->TokenInteger); if (m == null) { + int exToken = (int)(((ulong)ip->TokenLong & 0xFFFFFFFF00000000) >> 32); + if (exToken > 0) + { + var ex = domain.GetException(exToken); + if (ex != null) + { + throw new ILRuntimeException(ex.Message, this, method, ex); + } + } //Irrelevant method int cnt = (int)ip->TokenLong; //Balance the stack diff --git a/ILRuntimeTestBase/TestFramework/TestClass3.cs b/ILRuntimeTestBase/TestFramework/TestClass3.cs index 28231a6d..cdbc33c0 100644 --- a/ILRuntimeTestBase/TestFramework/TestClass3.cs +++ b/ILRuntimeTestBase/TestFramework/TestClass3.cs @@ -1,4 +1,5 @@ -using System; +#define TEST_MISSING_METHOD +using System; using System.Collections.Generic; using System.Linq; using System.Text; @@ -103,6 +104,29 @@ public void Emit(T obj) { LoadAsset("123", obj); } + +#if TEST_MISSING_METHOD + public int missingField; + public void MissingMethodGeneric(T obj) + { + + } + + public void MissingMethod() + { + + } + + public static void MissingStaticMethod() + { + + } +#endif } +#if TEST_MISSING_METHOD + public class MissingType + { + } +#endif } diff --git a/TestCases/CLRBindingTest.cs b/TestCases/CLRBindingTest.cs index 29c0784d..ffdd3d76 100644 --- a/TestCases/CLRBindingTest.cs +++ b/TestCases/CLRBindingTest.cs @@ -1,4 +1,7 @@ -using ILRuntimeTest; +using ILRuntime.Runtime.CLRBinding; +using ILRuntime.Runtime.Intepreter; +using ILRuntimeTest; +using ILRuntimeTest.TestFramework; using System; using System.Collections.Generic; using System.Linq; @@ -139,5 +142,47 @@ public static void CLRBindingTestEnd() { ILRuntimeTest.TestBase.TestSession.LastSession.Appdomain.AllowUnboundCLRMethod = true; } + + [ILRuntimeTest.ILRuntimeTest(ExpectException = typeof(ILRuntimeException))] + public static void CLRBindingTestMissing01() + { + ILRuntimeTest.TestFramework.TestCLRBinding binding = new ILRuntimeTest.TestFramework.TestCLRBinding(); + binding.MissingMethod(); + } + + [ILRuntimeTest.ILRuntimeTest(ExpectException = typeof(ILRuntimeException))] + public static void CLRBindingTestMissing02() + { + ILRuntimeTest.TestFramework.TestCLRBinding binding = new ILRuntimeTest.TestFramework.TestCLRBinding(); + binding.MissingMethodGeneric(null); + } + + [ILRuntimeTest.ILRuntimeTest(ExpectException = typeof(ILRuntimeException))] + public static void CLRBindingTestMissing03() + { + ILRuntimeTest.TestFramework.TestCLRBinding binding = new ILRuntimeTest.TestFramework.TestCLRBinding(); + binding.missingField = 123; + } + + [ILRuntimeTest.ILRuntimeTest(ExpectException = typeof(ILRuntimeException))] + public static void CLRBindingTestMissing04() + { + ILRuntimeTest.TestFramework.TestCLRBinding binding = new ILRuntimeTest.TestFramework.TestCLRBinding(); + binding.Emit(null); + } + + [ILRuntimeTest.ILRuntimeTest(ExpectException = typeof(ILRuntimeException))] + public static void CLRBindingTestMissing05() + { + ILRuntimeTest.TestFramework.TestCLRBinding binding = new ILRuntimeTest.TestFramework.TestCLRBinding(); + binding.MissingMethodGeneric(null); + } + + [ILRuntimeTest.ILRuntimeTest(ExpectException = typeof(ILRuntimeException))] + public static void CLRBindingTestMissing08() + { + MissingType mt = new MissingType(); + + } } }