Merge pull request #1658 from esdrubal/spgenerics
authorZoltan Varga <vargaz@gmail.com>
Thu, 26 Mar 2015 13:43:06 +0000 (09:43 -0400)
committerZoltan Varga <vargaz@gmail.com>
Thu, 26 Mar 2015 13:43:06 +0000 (09:43 -0400)
Improved generics in exception's stack traces and mono-symbolicate.

17 files changed:
mcs/class/corlib/System.Diagnostics/StackFrame.cs
mcs/class/corlib/System/Environment.cs
mcs/class/corlib/System/Exception.cs
mcs/tools/mono-symbolicate/LocationProvider.cs
mcs/tools/mono-symbolicate/Makefile
mcs/tools/mono-symbolicate/Test/StackTraceDumper.cs
mcs/tools/mono-symbolicate/Test/symbolicate.expected
mcs/tools/mono-symbolicate/symbolicate.cs
mono/metadata/appdomain.c
mono/metadata/icall.c
mono/metadata/object-internals.h
mono/metadata/seq-points-data.c
mono/metadata/seq-points-data.h
mono/mini/aot-compiler.c
mono/mini/aot-runtime.c
mono/mini/mini-exceptions.c
mono/mini/mini.h

index 7cc62c77c86adfabc79555f21ed250464cb49efd..2593f96c68d372382cf6f37764c29f9966fe58bf 100644 (file)
@@ -50,6 +50,7 @@ namespace System.Diagnostics {
                private int ilOffset = OFFSET_UNKNOWN;
                private int nativeOffset = OFFSET_UNKNOWN;
                private long methodAddress;
+               private uint methodIndex;
                private MethodBase methodBase;
                private string fileName;
                private int lineNumber;
@@ -60,7 +61,7 @@ namespace System.Diagnostics {
                #endregion
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               extern static int GetILOffsetFromFile (string path, int methodToken, int nativeOffset);
+               extern static int GetILOffsetFromFile (string path, int methodToken, uint methodIndex, int nativeOffset);
 
                [MethodImplAttribute(MethodImplOptions.InternalCall)]
                extern static bool get_frame_info (int skip, bool needFileInfo, out MethodBase method,
@@ -174,6 +175,11 @@ namespace System.Diagnostics {
                        return methodAddress;
                }
 
+               internal uint GetMethodIndex ()
+               {
+                       return methodIndex;
+               }
+
                internal string GetInternalMethodName ()
                {
                        return internalMethodName;
index 3f4426c81f77404a20fa4c8dda1c15ca744fb4b8..efa397bd7bc01f3610a38f99aeaab4ea6332bdae 100644 (file)
@@ -57,7 +57,7 @@ namespace System {
                 * of icalls, do not require an increment.
                 */
 #pragma warning disable 169
-               private const int mono_corlib_version = 123;
+               private const int mono_corlib_version = 124;
 #pragma warning restore 169
 
                [ComVisible (true)]
index 18232333a4f1d60c23eba5dd2ec95f5dd556c882..684c4971f568673527d205ee11343d71fec09680 100644 (file)
@@ -209,10 +209,13 @@ namespace System
                                } else {
                                        GetFullNameForStackTrace (sb, frame.GetMethod ());
 
-                                       if (frame.GetILOffset () == -1)
-                                               sb.AppendFormat ("<0x{0:x5} + 0x{1:x5}> ", frame.GetMethodAddress (), frame.GetNativeOffset ());
-                                       else
+                                       if (frame.GetILOffset () == -1) {
+                                               sb.AppendFormat (" <0x{0:x5} + 0x{1:x5}> ", frame.GetMethodAddress (), frame.GetNativeOffset ());
+                                               if (frame.GetMethodIndex () != 0xffffff)
+                                                       sb.AppendFormat ("{0} ", frame.GetMethodIndex ());
+                                       } else {
                                                sb.AppendFormat (" [0x{0:x5}] ", frame.GetILOffset ());
+                                       }
 
                                        sb.AppendFormat ("in {0}:{1} ", frame.GetSecureFileName (),
                                                                         frame.GetFileLineNumber ());
@@ -346,10 +349,23 @@ namespace System
                        return this;
                }
 
-               internal void GetFullNameForStackTrace (StringBuilder sb, MethodBase mi)
+               internal static void GetFullNameForStackTrace (StringBuilder sb, MethodBase mi)
                {
-                       ParameterInfo[] p = mi.GetParametersInternal ();
-                       sb.Append (mi.DeclaringType.ToString ());
+                       var declaringType = mi.DeclaringType;
+                       if (declaringType.IsGenericType && !declaringType.IsGenericTypeDefinition)
+                               declaringType = declaringType.GetGenericTypeDefinition ();
+
+                       // Get generic definition
+                       var bindingflags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
+                       foreach (var m in declaringType.GetMethods (bindingflags)) {
+                               if (m.MetadataToken == mi.MetadataToken) {
+                                       mi = m;
+                                       break;
+                               }
+                       }
+
+                       sb.Append (declaringType.ToString ());
+
                        sb.Append (".");
                        sb.Append (mi.Name);
 
@@ -364,11 +380,17 @@ namespace System
                                sb.Append ("]");
                        }
 
+                       ParameterInfo[] p = mi.GetParametersInternal ();
+
                        sb.Append (" (");
                        for (int i = 0; i < p.Length; ++i) {
                                if (i > 0)
                                        sb.Append (", ");
+
                                Type pt = p[i].ParameterType;
+                               if (pt.IsGenericType && ! pt.IsGenericTypeDefinition)
+                                       pt = pt.GetGenericTypeDefinition ();
+
                                if (pt.IsClass && !String.IsNullOrEmpty (pt.Namespace)) {
                                        sb.Append (pt.Namespace);
                                        sb.Append (".");
index 61bc822d04affee2f49a649f7c8be9c8ebc23a0b..113ea7ed6fe818704cf2efd8d254dd2408600662 100644 (file)
@@ -1,6 +1,7 @@
 using System;
 using System.IO;
 using System.Linq;
+using System.Text;
 using System.Reflection;
 using System.Diagnostics;
 using System.Collections.Generic;
@@ -16,70 +17,48 @@ namespace Symbolicate
 
        class LocationProvider {
                class AssemblyLocationProvider {
-                       AssemblyDefinition assembly;
+                       Assembly assembly;
                        MonoSymbolFile symbolFile;
                        string seqPointDataPath;
 
-                       public AssemblyLocationProvider (AssemblyDefinition assembly, MonoSymbolFile symbolFile, string seqPointDataPath)
+                       public AssemblyLocationProvider (Assembly assembly, MonoSymbolFile symbolFile, string seqPointDataPath)
                        {
                                this.assembly = assembly;
                                this.symbolFile = symbolFile;
                                this.seqPointDataPath = seqPointDataPath;
                        }
 
-                       public bool TryGetLocation (string methodFullName, string[] methodParamsTypes, int offset, bool isOffsetIL, out Location location)
+                       public bool TryGetLocation (string methodStr, string typeFullName, int offset, bool isOffsetIL, uint methodIndex, out Location location)
                        {
                                location = default (Location);
                                if (symbolFile == null)
                                        return false;
 
-                               var typeNameEnd = methodFullName.LastIndexOf (".");
-                               var typeName = methodFullName.Substring (0, typeNameEnd);
-                               var methodName = methodFullName.Substring (typeNameEnd + 1, methodFullName.Length - typeNameEnd - 1);
-
-                               var type = assembly.MainModule.Types.FirstOrDefault (t => t.FullName == typeName);
+                               var type = assembly.GetTypes().FirstOrDefault (t => t.FullName == typeFullName);
                                if (type == null)
                                        return false;
 
-                               var method = type.Methods.FirstOrDefault (m => {
-                                       if (m.Name != methodName)
-                                               return false;
-
-                                       if (m.Parameters.Count != methodParamsTypes.Length)
-                                               return false;
-
-                                       for (var i = 0; i < methodParamsTypes.Length; i++) {
-                                               var paramType = m.Parameters[i].ParameterType;
-                                               if (paramType.Name != methodParamsTypes[i])
-                                                       return false;
-                                       }
-
-                                       return true;
-                               });
-
+                               var bindingflags = BindingFlags.Instance | BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic;
+                               var method = type.GetMethods(bindingflags).FirstOrDefault (m => GetMethodFullName (m) == methodStr);
                                if (method == null)
                                        return false;
 
-                               int ilOffset = (isOffsetIL)? offset : GetILOffsetFromFile (method.MetadataToken.ToInt32 (), offset);
+                               int ilOffset = (isOffsetIL)? offset : GetILOffsetFromFile (method.MetadataToken, methodIndex, offset);
                                if (ilOffset < 0)
                                        return false;
 
-                               var methodSymbol = symbolFile.Methods [method.MetadataToken.RID-1];
+                               var methodSymbol = symbolFile.Methods [(method.MetadataToken & 0x00ffffff) - 1];
 
-                               foreach (var lineNumber in methodSymbol.GetLineNumberTable ().LineNumbers) {
-                                       if (lineNumber.Offset < ilOffset)
-                                               continue;
-
-                                       location.FileName = symbolFile.Sources [lineNumber.File-1].FileName;
-                                       location.Line = lineNumber.Row;
-                                       return true;
-                               }
+                               var lineNumbers = methodSymbol.GetLineNumberTable ().LineNumbers;
+                               var lineNumber = lineNumbers.FirstOrDefault (l => l.Offset >= ilOffset) ?? lineNumbers.Last ();
 
-                               return false;
+                               location.FileName = symbolFile.Sources [lineNumber.File-1].FileName;
+                               location.Line = lineNumber.Row;
+                               return true;
                        }
 
                        static MethodInfo methodGetIL;
-                       private int GetILOffsetFromFile (int methodToken, int nativeOffset)
+                       private int GetILOffsetFromFile (int methodToken, uint methodIndex, int nativeOffset)
                        {
                                if (string.IsNullOrEmpty (seqPointDataPath))
                                        return -1;
@@ -90,7 +69,23 @@ namespace Symbolicate
                                if (methodGetIL == null)
                                        throw new Exception ("System.Diagnostics.StackFrame.GetILOffsetFromFile could not be found, make sure you have an updated mono installed.");
 
-                               return (int) methodGetIL.Invoke (null, new object[] {seqPointDataPath, methodToken, nativeOffset});
+                               return (int) methodGetIL.Invoke (null, new object[] {seqPointDataPath, methodToken, methodIndex, nativeOffset});
+                       }
+
+                       static MethodInfo methodGetMethodFullName;
+                       private string GetMethodFullName (MethodBase m)
+                       {
+
+                               if (methodGetMethodFullName == null)
+                                       methodGetMethodFullName = typeof (Exception).GetMethod ("GetFullNameForStackTrace", BindingFlags.NonPublic | BindingFlags.Static);
+
+                               if (methodGetMethodFullName == null)
+                                       throw new Exception ("System.Exception.GetFullNameForStackTrace could not be found, make sure you have an updated mono installed.");
+
+                               StringBuilder sb = new StringBuilder ();
+                               methodGetMethodFullName.Invoke (null, new object[] {sb, m});
+
+                               return sb.ToString ();
                        }
                }
 
@@ -111,7 +106,7 @@ namespace Symbolicate
                        if (!File.Exists (assemblyPath))
                                throw new ArgumentException ("assemblyPath does not exist: "+ assemblyPath);
 
-                       var assembly = AssemblyDefinition.ReadAssembly (assemblyPath);
+                       var assembly = Assembly.LoadFrom (assemblyPath);
                        MonoSymbolFile symbolFile = null;
 
                        var symbolPath = assemblyPath + ".mdb";
@@ -128,7 +123,7 @@ namespace Symbolicate
 
                        directories.Add (Path.GetDirectoryName (assemblyPath));
 
-                       foreach (var assemblyRef in assembly.MainModule.AssemblyReferences) {
+                       foreach (var assemblyRef in assembly.GetReferencedAssemblies ()) {
                                string refPath = null;
                                foreach (var dir in directories) {
                                        refPath = Path.Combine (dir, assemblyRef.Name);
@@ -158,11 +153,11 @@ namespace Symbolicate
                        directories.Add (directory);
                }
 
-               public bool TryGetLocation (string methodName, string[] methodParams, int offset, bool isOffsetIL, out Location location)
+               public bool TryGetLocation (string method, string typeFullName, int offset, bool isOffsetIL, uint methodIndex, out Location location)
                {
                        location = default (Location);
                        foreach (var assembly in assemblies.Values) {
-                               if (assembly.TryGetLocation (methodName, methodParams, offset, isOffsetIL, out location))
+                               if (assembly.TryGetLocation (method, typeFullName, offset, isOffsetIL, methodIndex, out location))
                                        return true;
                        }
 
index 2e4666a5fd9feae38f6f5e60f284bb3cfb0b1773..7e14ab8a62fe7e42a917c0be74fd0e5417a5c793 100644 (file)
@@ -13,7 +13,7 @@ include ../../build/executable.make
 
 LIB_PATH = $(topdir)/class/lib/$(PROFILE)
 
-MONO = MONO_PATH=$(LIB_PATH)$(PLATFORM_PATH_SEPARATOR)$$MONO_PATH $(RUNTIME)
+MONO = MONO_PATH=$(LIB_PATH)$(PLATFORM_PATH_SEPARATOR)$$MONO_PATH $(RUNTIME) -O=-inline
 
 OUT_DIR = Test/out
 TEST_CS = Test/StackTraceDumper.cs
index 4fbcf7819f3c1296173d1a083a94f640c92113c4..c9d6b55d110f354096d384554ddfc309bd3faa38 100644 (file)
 using System;
+using System.Collections.Generic;
 
 class StackTraceDumper {
-       public static void Main () {
-               // Stacktrace with no depth
+
+       public static void Main ()
+       {
+               try {
+                       throw new Exception ("Stacktrace with 1 frame");
+               } catch (Exception e) {
+                       Console.WriteLine (e);
+               }
+
+               try {
+                       ThrowException ("Stacktrace with 2 frames");
+               } catch (Exception e) {
+                       Console.WriteLine (e);
+               }
+
                try {
-                       throw new Exception ();
+                       ThrowException ("Stacktrace with 3 frames", 2);
                } catch (Exception e) {
                        Console.WriteLine (e);
                }
-               // Stacktrace with depth of 1
+
+               try {
+                       var message = "Stack frame with method overload using ref parameter";
+                       ThrowException (ref message);
+               } catch (Exception e) {
+                       Console.WriteLine (e);
+               }
+
+               try {
+                       int i;
+                       ThrowException ("Stack frame with method overload using out parameter", out i);
+               } catch (Exception e) {
+                       Console.WriteLine (e);
+               }
+
                try {
-                       ThrowException ();
+                       ThrowExceptionGeneric<double> ("Stack frame with 1 generic parameter");
                } catch (Exception e) {
                        Console.WriteLine (e);
                }
-               // Stacktrace with depth of 2
+
+               try {
+                       ThrowExceptionGeneric<double,string> ("Stack frame with 2 generic parameters");
+               } catch (Exception e) {
+                       Console.WriteLine (e);
+               }
+
+               try {
+                       ThrowExceptionGeneric (12);
+               } catch (Exception e) {
+                       Console.WriteLine (e);
+               }
+
+               try {
+                       InnerClass.ThrowException ("Stack trace with inner class");
+               } catch (Exception e) {
+                       Console.WriteLine (e);
+               }
+
+               try {
+                       InnerGenericClass<string>.ThrowException ("Stack trace with inner generic class");
+               } catch (Exception e) {
+                       Console.WriteLine (e);
+               }
+
                try {
-                       ThrowException2 ();
+                       InnerGenericClass<string>.ThrowException ("Stack trace with inner generic class and method generic parameter", "string");
                } catch (Exception e) {
                        Console.WriteLine (e);
                }
+
+               try {
+                       InnerGenericClass<string>.ThrowException<string> ("Stack trace with inner generic class and generic overload", "string");
+               } catch (Exception e) {
+                       Console.WriteLine (e);
+               }
+
+               try {
+                       InnerGenericClass<string>.InnerInnerGenericClass<int>.ThrowException ("Stack trace with 2 inner generic class and generic overload");
+               } catch (Exception e) {
+                       Console.WriteLine (e);
+               }
+
+               try {
+                       InnerGenericClass<int>.InnerInnerGenericClass<string>.ThrowException ("Stack trace with 2 inner generic class and generic overload");
+               } catch (Exception e) {
+                       Console.WriteLine (e);
+               }
+       }
+
+       public static void ThrowException (string message)
+       {
+               throw new Exception (message);
+       }
+
+       public static void ThrowException (ref string message)
+       {
+               throw new Exception (message);
+       }
+
+       public static void ThrowException (string message, int i)
+       {
+               if (i > 1)
+                       ThrowException (message, --i);
+
+               throw new Exception (message);
+       }
+
+       public static void ThrowException (string message, out int o)
+       {
+               throw new Exception (message);
        }
 
-       public static void ThrowException () {
-               Console.WriteLine ("Exception is not in the first line!");
-               throw new Exception ();
+       public static void ThrowExceptionGeneric<T> (string message)
+       {
+               throw new Exception (message);
        }
 
-       public static void ThrowException2 () {
-               ThrowException ();
+       public static void ThrowExceptionGeneric<T> (T a1)
+       {
+               throw new Exception ("Stack frame with generic method overload");
        }
 
+       public static void ThrowExceptionGeneric<T> (List<string> a1)
+       {
+               throw new Exception ("Stack frame with generic method overload");
+       }
+
+       public static void ThrowExceptionGeneric<T> (List<T> a1)
+       {
+               throw new Exception ("Stack frame with generic method overload");
+       }
+
+       public static void ThrowExceptionGeneric<T1,T2> (string message)
+       {
+               throw new Exception (message);
+       }
+
+       class InnerClass {
+               public static void ThrowException (string message)
+               {
+                       throw new Exception (message);
+               }
+       }
+
+       class InnerGenericClass<T> {
+               public static void ThrowException (string message)
+               {
+                       throw new Exception (message);
+               }
+
+               public static void ThrowException (string message, T arg)
+               {
+                       Console.WriteLine ("Generic to string:" + arg.ToString());
+                       throw new Exception (message);
+               }
+
+               public static void ThrowException<T1> (string message, T1 arg)
+               {
+                       throw new Exception (message);
+               }
+
+               public class InnerInnerGenericClass<T2> {
+                       public static void ThrowException (T message)
+                       {
+                               throw new Exception (message as string);
+                       }
+
+                       public static void ThrowException (T2 message)
+                       {
+                               throw new Exception (message as string);
+                       }
+               }
+       }
 }
\ No newline at end of file
index 3e19b82af1ff9ea4c03be9298c73feca689f3eff..59182caba3c29e8731c6c68182b6610969b1a319 100644 (file)
@@ -1,11 +1,43 @@
-System.Exception: Exception of type 'System.Exception' was thrown.
-  at StackTraceDumper.Main () in StackTraceDumper.cs:7 
-Exception is not in the first line!
-System.Exception: Exception of type 'System.Exception' was thrown.
-  at StackTraceDumper.ThrowException () in StackTraceDumper.cs:27 
-  at StackTraceDumper.Main () in StackTraceDumper.cs:13 
-Exception is not in the first line!
-System.Exception: Exception of type 'System.Exception' was thrown.
-  at StackTraceDumper.ThrowException () in StackTraceDumper.cs:27 
-  at StackTraceDumper.ThrowException2 () in StackTraceDumper.cs:31 
-  at StackTraceDumper.Main () in StackTraceDumper.cs:19 
+System.Exception: Stacktrace with 1 frame
+  at StackTraceDumper.Main () in StackTraceDumper.cs:9 
+System.Exception: Stacktrace with 2 frames
+  at StackTraceDumper.ThrowException (System.String message) in StackTraceDumper.cs:97 
+  at StackTraceDumper.Main () in StackTraceDumper.cs:15 
+System.Exception: Stacktrace with 3 frames
+  at StackTraceDumper.ThrowException (System.String message, Int32 i) in StackTraceDumper.cs:110 
+  at StackTraceDumper.ThrowException (System.String message, Int32 i) in StackTraceDumper.cs:108 
+  at StackTraceDumper.Main () in StackTraceDumper.cs:21 
+System.Exception: Stack frame with method overload using ref parameter
+  at StackTraceDumper.ThrowException (System.String& message) in StackTraceDumper.cs:102 
+  at StackTraceDumper.Main () in StackTraceDumper.cs:28 
+System.Exception: Stack frame with method overload using out parameter
+  at StackTraceDumper.ThrowException (System.String message, System.Int32& o) in StackTraceDumper.cs:115 
+  at StackTraceDumper.Main () in StackTraceDumper.cs:35 
+System.Exception: Stack frame with 1 generic parameter
+  at StackTraceDumper.ThrowExceptionGeneric[T] (System.String message) in StackTraceDumper.cs:120 
+  at StackTraceDumper.Main () in StackTraceDumper.cs:41 
+System.Exception: Stack frame with 2 generic parameters
+  at StackTraceDumper.ThrowExceptionGeneric[T1,T2] (System.String message) in StackTraceDumper.cs:140 
+  at StackTraceDumper.Main () in StackTraceDumper.cs:47 
+System.Exception: Stack frame with generic method overload
+  at StackTraceDumper.ThrowExceptionGeneric[T] (T a1) in StackTraceDumper.cs:125 
+  at StackTraceDumper.Main () in StackTraceDumper.cs:53 
+System.Exception: Stack trace with inner class
+  at StackTraceDumper+InnerClass.ThrowException (System.String message) in StackTraceDumper.cs:146 
+  at StackTraceDumper.Main () in StackTraceDumper.cs:59 
+System.Exception: Stack trace with inner generic class
+  at StackTraceDumper+InnerGenericClass`1[T].ThrowException (System.String message) in StackTraceDumper.cs:153 
+  at StackTraceDumper.Main () in StackTraceDumper.cs:65 
+Generic to string:string
+System.Exception: Stack trace with inner generic class and method generic parameter
+  at StackTraceDumper+InnerGenericClass`1[T].ThrowException (System.String message, T arg) in StackTraceDumper.cs:159 
+  at StackTraceDumper.Main () in StackTraceDumper.cs:71 
+System.Exception: Stack trace with inner generic class and generic overload
+  at StackTraceDumper+InnerGenericClass`1[T].ThrowException[T1] (System.String message, T1 arg) in StackTraceDumper.cs:164 
+  at StackTraceDumper.Main () in StackTraceDumper.cs:77 
+System.Exception: Stack trace with 2 inner generic class and generic overload
+  at StackTraceDumper+InnerGenericClass`1+InnerInnerGenericClass`1[T,T2].ThrowException (T message) in StackTraceDumper.cs:170 
+  at StackTraceDumper.Main () in StackTraceDumper.cs:83 
+System.Exception: Stack trace with 2 inner generic class and generic overload
+  at StackTraceDumper+InnerGenericClass`1+InnerInnerGenericClass`1[T,T2].ThrowException (T2 message) in StackTraceDumper.cs:175 
+  at StackTraceDumper.Main () in StackTraceDumper.cs:89 
index 93cbabc0a9bdd57c46e5bd30f7e9d2b66814fe78..4dd23e3d1bd16fea494ae918bcfd269b2532bc09 100644 (file)
@@ -7,7 +7,7 @@ namespace Symbolicate
 {
        public class Program
        {
-               static Regex regex = new Regex (@"\w*at (?<MethodName>.+) \((?<MethodParams>.*)\) *(\[0x(?<IL>.+)\]|<0x.* \+ 0x(?<NativeOffset>.+)>) in <filename unknown>:0");
+               static Regex regex = new Regex (@"\w*at (?<Method>.+) *(\[0x(?<IL>.+)\]|<0x.+ \+ 0x(?<NativeOffset>.+)>( (?<MethodIndex>\d+)|)) in <filename unknown>:0");
 
                public static int Main (String[] args)
                {
@@ -42,31 +42,48 @@ namespace Symbolicate
                        if (!match.Success)
                                return line;
 
-                       var methodName = match.Groups ["MethodName"].Value;
-                       var methodParams = ParseParametersTypes (match.Groups ["MethodParams"].Value);
+                       string typeFullName;
+                       var methodStr = match.Groups ["Method"].Value.Trim ();
+                       if (!TryParseMethodType (methodStr, out typeFullName))
+                               return line;
 
                        var isOffsetIL = !string.IsNullOrEmpty (match.Groups ["IL"].Value);
                        var offsetVarName = (isOffsetIL)? "IL" : "NativeOffset";
                        var offset = int.Parse (match.Groups [offsetVarName].Value, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
 
+                       uint methodIndex = 0xffffff;
+                       if (!string.IsNullOrEmpty (match.Groups ["MethodIndex"].Value))
+                               methodIndex = uint.Parse (match.Groups ["MethodIndex"].Value, CultureInfo.InvariantCulture);
+
                        Location location;
-                       if (!locProvider.TryGetLocation (methodName, methodParams, offset, isOffsetIL, out location))
+                       if (!locProvider.TryGetLocation (methodStr, typeFullName, offset, isOffsetIL, methodIndex, out location))
                                return line;
 
                        return line.Replace ("<filename unknown>:0", string.Format ("{0}:{1}", location.FileName, location.Line));
                }
 
-               static string[] ParseParametersTypes (string parameters)
+               static bool TryParseMethodType (string str, out string typeFullName)
                {
-                       if (string.IsNullOrEmpty (parameters))
-                               return new string [0];
+                       typeFullName = null;
+
+                       var methodNameEnd = str.IndexOf ("(");
+                       if (methodNameEnd == -1)
+                               return false;
+
+                       // Remove parameters
+                       str = str.Substring (0, methodNameEnd);
+
+                       // Remove generic parameters
+                       str = Regex.Replace (str, @"\[[^\[\]]*\]", "");
+
+                       var typeNameEnd = str.LastIndexOf (".");
+                       if (methodNameEnd == -1 || typeNameEnd == -1)
+                               return false;
 
-                       var paramsArray = parameters.Split (',');
-                       var paramsTypes = new string [paramsArray.Length];
-                       for (var i = 0; i < paramsArray.Length; i++)
-                               paramsTypes [i] = paramsArray [i].Trim ().Split (new char[]{' '}, 2)[0];
+                       // Remove method name
+                       typeFullName = str.Substring (0, typeNameEnd);
 
-                       return paramsTypes;
+                       return true;
                }
        }
 }
\ No newline at end of file
index c471e60f009ff0235f69ca71ab1976f075c30360..bdcef635937b1f672fe9b7fea63c16fd62259eeb 100644 (file)
@@ -78,7 +78,7 @@
  * Changes which are already detected at runtime, like the addition
  * of icalls, do not require an increment.
  */
-#define MONO_CORLIB_VERSION 123
+#define MONO_CORLIB_VERSION 124
 
 typedef struct
 {
index e662224f80f6649406e7af9ad08a8f82f62410da..8c3c09b8e74149f889328b3053560c28f3665afd 100644 (file)
@@ -7309,12 +7309,12 @@ ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
 }
 
 ICALL_EXPORT int
-ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, int methodToken, int nativeOffset)
+ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
 {
        guint32 il_offset;
        char *path_str = mono_string_to_utf8 (path);
 
-       if (!seq_point_data_get_il_offset (path_str, methodToken, nativeOffset, &il_offset))
+       if (!seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
                il_offset = -1;
 
        g_free (path_str);
index 548f49b7fb333ca5ff7175bc247d2fd95093210a..5862f9e180f13330314fafd349bb51558697bfe1 100644 (file)
@@ -363,6 +363,7 @@ typedef struct {
        gint32 il_offset;
        gint32 native_offset;
        gint64 method_address;
+       gint32 method_index;
        MonoReflectionMethod *method;
        MonoString *filename;
        gint32 line;
index a3ff693eceabb01ceaffbc2cf80eb5de1f920dc5..391a1b63c6ad7cdd008f0c0c9978a603c2a2fa23 100644 (file)
@@ -411,7 +411,8 @@ seq_point_data_read (SeqPointData *data, char *path)
        data->entry_count = entry_count;
 
        for (i=0; i<entry_count; i++) {
-               data->entries [i].token = decode_var_int (buffer, &buffer);
+               data->entries [i].method_token = decode_var_int (buffer, &buffer);
+               data->entries [i].method_index = decode_var_int (buffer, &buffer);
                buffer += seq_point_info_read (&data->entries [i].seq_points, buffer, TRUE);
                data->entries [i].free_seq_points = TRUE;
        }
@@ -442,7 +443,8 @@ seq_point_data_write (SeqPointData *data, char *path)
        encode_var_int (buffer, &buffer, data->entry_count);
 
        for (i=0; i<data->entry_count; i++) {
-               encode_var_int (buffer, &buffer, data->entries [i].token);
+               encode_var_int (buffer, &buffer, data->entries [i].method_token);
+               encode_var_int (buffer, &buffer, data->entries [i].method_index);
                buffer += seq_point_info_write (data->entries [i].seq_points, buffer);
        }
 
@@ -453,24 +455,25 @@ seq_point_data_write (SeqPointData *data, char *path)
 }
 
 void
-seq_point_data_add (SeqPointData *data, guint32 token, MonoSeqPointInfo* info)
+seq_point_data_add (SeqPointData *data, guint32 method_token, guint32 method_index, MonoSeqPointInfo* info)
 {
        int i;
 
        g_assert (data->entry_count < data->entry_capacity);
        i = data->entry_count++;
        data->entries [i].seq_points = info;
-       data->entries [i].token = token;
+       data->entries [i].method_token = method_token;
+       data->entries [i].method_index = method_index;
        data->entries [i].free_seq_points = FALSE;
 }
 
 gboolean
-seq_point_data_get (SeqPointData *data, guint32 token, MonoSeqPointInfo** info)
+seq_point_data_get (SeqPointData *data, guint32 method_token, guint32 method_index, MonoSeqPointInfo** info)
 {
        int i;
 
        for (i=0; i<data->entry_count; i++) {
-               if (data->entries [i].token == token) {
+               if (data->entries [i].method_token == method_token && (method_index == 0xffffff || data->entries [i].method_index == method_index)) {
                        (*info) = data->entries [i].seq_points;
                        return TRUE;
                }
@@ -479,7 +482,7 @@ seq_point_data_get (SeqPointData *data, guint32 token, MonoSeqPointInfo** info)
 }
 
 gboolean
-seq_point_data_get_il_offset (char *path, guint32 token, guint32 native_offset, guint32 *il_offset)
+seq_point_data_get_il_offset (char *path, guint32 method_token, guint32 method_index, guint32 native_offset, guint32 *il_offset)
 {
        SeqPointData sp_data;
        MonoSeqPointInfo *seq_points;
@@ -488,7 +491,7 @@ seq_point_data_get_il_offset (char *path, guint32 token, guint32 native_offset,
        if (!seq_point_data_read (&sp_data, path))
                return FALSE;
 
-       if (!seq_point_data_get (&sp_data, token, &seq_points))
+       if (!seq_point_data_get (&sp_data, method_token, method_index, &seq_points))
                return FALSE;
 
        if (!seq_point_find_prev_by_native_offset (seq_points, native_offset, &sp))
index a7f0b29502525249b9e44d2f01221f8933b1cc40..730770001783454cd3a7caca36c8b0ca83cc95bc 100644 (file)
@@ -81,7 +81,8 @@ seq_point_find_by_il_offset (MonoSeqPointInfo* info, int il_offset, SeqPoint* se
  */
 
 typedef struct {
-       guint32 token;
+       guint32 method_token;
+       guint32 method_index;
        MonoSeqPointInfo* seq_points;
        gboolean free_seq_points;
 } SeqPointDataEntry;
@@ -105,12 +106,12 @@ gboolean
 seq_point_data_write (SeqPointData *data, char *path);
 
 void
-seq_point_data_add (SeqPointData *data, guint32 token, MonoSeqPointInfo* info);
+seq_point_data_add (SeqPointData *data, guint32 methodToken, guint32 methodIndex, MonoSeqPointInfo* info);
 
 gboolean
-seq_point_data_get (SeqPointData *data, guint32 token, MonoSeqPointInfo** info);
+seq_point_data_get (SeqPointData *data, guint32 methodToken, guint32 methodIndex, MonoSeqPointInfo** info);
 
 gboolean
-seq_point_data_get_il_offset (char *path, guint32 token, guint32 native_offset, guint32 *il_offset);
+seq_point_data_get_il_offset (char *path, guint32 methodToken, guint32 methodIndex, guint32 native_offset, guint32 *il_offset);
 
 #endif /* __MONO_SEQ_POINTS_DATA_H__ */
\ No newline at end of file
index 650e05ca67022f92accf8c6d6f854f6a353a1820..fe3033391d723d902b04da44ecd95e991e29de3c 100644 (file)
@@ -7894,7 +7894,7 @@ emit_exception_info (MonoAotCompile *acfg)
                                        seq_point_data_init (&sp_data, acfg->nmethods);
                                        seq_points_to_file = TRUE;
                                }
-                               seq_point_data_add (&sp_data, cfg->method->token, cfg->seq_point_info);
+                               seq_point_data_add (&sp_data, cfg->method->token, cfg->method_index, cfg->seq_point_info);
                        }
                } else {
                        offsets [i] = 0;
index e429461931065c719b5549e1bce5c6862ddffaeb..0038b3ded34b8d6fdbcf438a3809ab2048f7b8d8 100644 (file)
@@ -3868,6 +3868,13 @@ find_aot_method (MonoMethod *method, MonoAotModule **out_amodule)
        return index;
 }
 
+guint32
+mono_aot_find_method_index (MonoMethod *method)
+{
+       MonoAotModule *out_amodule;
+       return find_aot_method (method, &out_amodule);
+}
+
 /*
  * mono_aot_get_method:
  *
index 345c13135b9683ef20cddde91e9cb79eb4a76bf2..9f21cd5b3ed05a9c9d9026bdf7fb0fc14bdbab18 100644 (file)
@@ -700,6 +700,8 @@ ves_icall_get_trace (MonoException *exc, gint32 skip, MonoBoolean need_file_info
                }
                else
                        MONO_OBJECT_SETREF (sf, method, mono_method_get_object (domain, method, NULL));
+
+               sf->method_index = ji->from_aot ? mono_aot_find_method_index (method) : 0xffffff;
                sf->method_address = (gsize) ji->code_start;
                sf->native_offset = (char *)ip - (char *)ji->code_start;
 
index bb66a6a3c57688581b90ace2010e2f501b3c17ea..ed15138085513c93fd4be6e833e2ae75fa83408f 100644 (file)
@@ -2277,6 +2277,7 @@ gboolean mono_aot_is_pagefault              (void *ptr);
 void     mono_aot_handle_pagefault          (void *ptr);
 void     mono_aot_register_jit_icall        (const char *name, gpointer addr);
 void*    mono_aot_readonly_field_override   (MonoClassField *field);
+guint32  mono_aot_find_method_index         (MonoMethod *method);
 
 /* This is an exported function */
 MONO_API void     mono_aot_register_globals          (gpointer *globals);