Merge pull request #4904 from kumpera/more_opts
authorRodrigo Kumpera <kumpera@users.noreply.github.com>
Sat, 27 May 2017 19:29:01 +0000 (12:29 -0700)
committerGitHub <noreply@github.com>
Sat, 27 May 2017 19:29:01 +0000 (12:29 -0700)
[runtime] Change jit_info_table_num_elements to O(1).

69 files changed:
configure.ac
external/bockbuild
mcs/class/Mono.Posix/Assembly/AssemblyInfo.cs
mcs/class/Mono.Posix/Mono.Posix.NETStandard-netstandard_2_0.csproj [new file with mode: 0644]
mcs/class/Mono.Posix/Mono.Unix.Native/Stdlib.cs
mcs/class/Mono.Posix/Mono.Unix.Native/Syscall.cs
mcs/class/Mono.Posix/Test/Mono.Unix.Native/StdlibTest.cs
mcs/class/corlib/Mono/RuntimeStructs.cs
mcs/class/corlib/System.IO/FileStream.cs
mcs/class/corlib/System/TimeZoneInfo.cs
mcs/class/corlib/Test/System.IO/FileTest.cs
mcs/class/corlib/Test/System/DecimalTest-Microsoft.cs
mcs/class/corlib/corert/Debug.cs
mcs/class/referencesource/mscorlib/system/io/filesystemenumerable.cs
mcs/errors/cs1031-3.cs [new file with mode: 0644]
mcs/mcs/cs-tokenizer.cs
mcs/mcs/expression.cs
mcs/tests/test-async-92.cs [new file with mode: 0644]
mcs/tests/ver-il-net_4_x.xml
mcs/tools/mkbundle/mkbundle.cs
mono/dis/Makefile.am
mono/metadata/appdomain.c
mono/metadata/class.c
mono/metadata/cominterop.c
mono/metadata/domain-internals.h
mono/metadata/handle.c
mono/metadata/handle.h
mono/metadata/icall-def.h
mono/metadata/icall.c
mono/metadata/marshal.c
mono/metadata/marshal.h
mono/metadata/mempool-internals.h
mono/metadata/object-internals.h
mono/metadata/object.c
mono/metadata/sgen-mono.c
mono/metadata/w32error-unix.c
mono/metadata/w32error.h
mono/metadata/w32file-unix.c
mono/metadata/w32socket-unix.c
mono/mini/Makefile.am.in
mono/mini/MemoryIntrinsics.il [new file with mode: 0644]
mono/mini/aot-runtime.c
mono/mini/debugger-agent.c
mono/mini/decompose.c
mono/mini/interp/interp-internals.h
mono/mini/interp/interp-stubs.c [new file with mode: 0644]
mono/mini/interp/interp.c
mono/mini/interp/interp.h
mono/mini/interp/mintops.c
mono/mini/interp/mintops.def
mono/mini/interp/transform.c
mono/mini/jit-icalls.c
mono/mini/memory-access.c
mono/mini/method-to-ir.c
mono/mini/mini-arm.c
mono/mini/mini-exceptions.c
mono/mini/mini-runtime.c
mono/mini/mini.h
mono/mini/tramp-arm.c
mono/mini/unaligned.cs [new file with mode: 0644]
mono/tests/Makefile.am
mono/tests/appdomain-unload-asmload.cs [new file with mode: 0644]
mono/tests/cominterop.cs
mono/tests/libtest.c
mono/tests/marshal2.cs
mono/unit-tests/Makefile.am
mono/utils/mono-proclib.c
msvc/libmono-static.vcxproj
msvc/libmono-static.vcxproj.filters

index 86a2354b389338d03914c8895349d15b7ba3c0db..c5c7ba58b9e3cfbd99ec0da64a13c1f3872cee0f 100644 (file)
@@ -40,7 +40,7 @@ MONO_VERSION_BUILD=`echo $VERSION | cut -d . -f 3`
 # This can be reset to 0 when Mono's version number is bumped
 # since it's part of the corlib version (the prefix '1' in the full
 # version number is to ensure the number isn't treated as octal in C)
-MONO_CORLIB_COUNTER=1
+MONO_CORLIB_COUNTER=2
 MONO_CORLIB_VERSION=`printf "1%02d%02d%02d%03d" $MONO_VERSION_MAJOR $MONO_VERSION_MINOR $MONO_VERSION_BUILD $MONO_CORLIB_COUNTER`
 
 AC_DEFINE_UNQUOTED(MONO_CORLIB_VERSION,$MONO_CORLIB_VERSION,[Version of the corlib-runtime interface])
index c783777342f4d39b58f3c2e6a1659eedf504ac87..7dba4865168e7719aacf21bec5497ae99f8a86e4 160000 (submodule)
@@ -1 +1 @@
-Subproject commit c783777342f4d39b58f3c2e6a1659eedf504ac87
+Subproject commit 7dba4865168e7719aacf21bec5497ae99f8a86e4
index e26c50b01cde1b892035effbd81e3348ff5379c5..ce6b749678d9c5c296dcef1ea33bf45f7021dfe3 100644 (file)
@@ -34,9 +34,16 @@ using System.Reflection;
 using System.Runtime.InteropServices;
 using System.Security.Permissions;
 
-[assembly: AssemblyVersion (Consts.FxVersion)]
 
+
+#if MONO_POSIX_NETSTANDARD_BUILD
+[assembly: AssemblyVersion ("1.0.0.0")]
+[assembly: AssemblyTitle("Mono.Posix.NETStandard.dll")]
+#else
+[assembly: AssemblyVersion (Consts.FxVersion)]
 [assembly: AssemblyTitle("Mono.Posix.dll")]
+#endif
+
 [assembly: AssemblyDescription("Unix Integration Classes")]
 
 [assembly: CLSCompliant (true)]
@@ -48,9 +55,11 @@ using System.Security.Permissions;
 
 */
 
+#if !MONO_POSIX_NETSTANDARD_BUILD
+// We are using ../Open.snk for MONO_POSIX_NETSTANDARD_BUILD
 [assembly: AssemblyDelaySign (true)]
 [assembly: AssemblyKeyFile ("../mono.pub")]
-
+#endif
 /*
  * TODO:
  * 
diff --git a/mcs/class/Mono.Posix/Mono.Posix.NETStandard-netstandard_2_0.csproj b/mcs/class/Mono.Posix/Mono.Posix.NETStandard-netstandard_2_0.csproj
new file mode 100644 (file)
index 0000000..8563586
--- /dev/null
@@ -0,0 +1,35 @@
+<Project Sdk="Microsoft.NET.Sdk">\r
+\r
+  <PropertyGroup>\r
+    <TargetFramework>netstandard2.0</TargetFramework>\r
+    <AllowUnsafeBlocks>true</AllowUnsafeBlocks>\r
+    <AssemblyName>Mono.Posix.NETStandard</AssemblyName>\r
+    <GenerateAssemblyDescriptionAttribute>false</GenerateAssemblyDescriptionAttribute>\r
+    <GenerateAssemblyTitleAttribute>false</GenerateAssemblyTitleAttribute>\r
+    <GenerateAssemblyVersionAttribute>false</GenerateAssemblyVersionAttribute>\r
+    <EnableDefaultItems>false</EnableDefaultItems>\r
+    <SignAssembly>true</SignAssembly>\r
+    <DelaySign>true</DelaySign>\r
+    <AssemblyOriginatorKeyFile>..\Open.snk</AssemblyOriginatorKeyFile>\r
+    <!--<BaseIntermediateOutputPath>obj-netstandard2.0</BaseIntermediateOutputPath>\r
+    <IntermediateOutputPath>obj-netstandard2.0</IntermediateOutputPath>-->\r
+  </PropertyGroup>\r
+\r
+  <PropertyGroup>\r
+    <DefineConstants>$(DefineConstants);MONO_POSIX_NETSTANDARD_BUILD</DefineConstants>\r
+  </PropertyGroup>\r
+\r
+  <PropertyGroup Condition="'$(ForceUseLibC)' == 'true'">\r
+    <DefineConstants>$(DefineConstants);FORCE_USE_LIBC_NOT_MSVC</DefineConstants>\r
+  </PropertyGroup>\r
+\r
+  <ItemGroup>\r
+    <Compile Include=".\Assembly\**\*.cs" />\r
+    <Compile Include=".\Mono.Posix\**\*.cs" />\r
+    <Compile Include=".\Mono.Unix\**\*.cs" />\r
+    <Compile Include=".\Mono.Unix.Native\**\*.cs" />\r
+    <Compile Include="..\..\build\common\Locale.cs" />\r
+    <Compile Remove=".\Mono.Unix.Native\CdeclFunction.cs" />\r
+  </ItemGroup>\r
+\r
+</Project>\r
index dbabb29c7f1b70c9544914abb197388d7af0a1ab..59b66ca26fb29dc0e61bfc05ece530bffe03bf18 100644 (file)
@@ -309,6 +309,7 @@ namespace Mono.Unix.Native {
        public delegate void SignalHandler (int signal);
 
 
+#if !NETSTANDARD2_0
        internal class XPrintfFunctions
        {
                internal delegate object XPrintf (object[] parameters);
@@ -335,6 +336,7 @@ namespace Mono.Unix.Native {
                        syslog = new XPrintf (_syslog.Invoke);
                }
        }
+#endif
 
        //
        // Convention: Functions that are part of the C standard library go here.
@@ -378,7 +380,11 @@ namespace Mono.Unix.Native {
        //
        public class Stdlib
        {
+#if FORCE_USE_LIBC_NOT_MSVC
+               internal const string LIBC = "c";
+#else
                internal const string LIBC = "msvcrt";
+#endif
                internal const string MPH  = "MonoPosixHelper";
 
                // It is possible for Mono.Posix and MonoPosixHelper to get out of sync,
@@ -771,6 +777,7 @@ namespace Mono.Unix.Native {
                        return sys_fprintf (stream, "%s", message);
                }
 
+#if !NETSTANDARD2_0
                [Obsolete ("Not necessarily portable due to cdecl restrictions.\n" +
                                "Use fprintf (IntPtr, string) instead.")]
                public static int fprintf (IntPtr stream, string format, params object[] parameters)
@@ -781,6 +788,7 @@ namespace Mono.Unix.Native {
                        Array.Copy (parameters, 0, _parameters, 2, parameters.Length);
                        return (int) XPrintfFunctions.fprintf (_parameters);
                }
+#endif
 
                /* SKIP: fscanf(3) */
 
@@ -793,6 +801,7 @@ namespace Mono.Unix.Native {
                        return sys_printf ("%s", message);
                }
 
+#if !NETSTANDARD2_0
                [Obsolete ("Not necessarily portable due to cdecl restrictions.\n" +
                                "Use printf (string) instead.")]
                public static int printf (string format, params object[] parameters)
@@ -802,6 +811,7 @@ namespace Mono.Unix.Native {
                        Array.Copy (parameters, 0, _parameters, 1, parameters.Length);
                        return (int) XPrintfFunctions.printf (_parameters);
                }
+#endif
 
                /* SKIP: scanf(3) */
 
@@ -823,6 +833,7 @@ namespace Mono.Unix.Native {
                        return sys_snprintf (s, (ulong) s.Capacity, "%s", message);
                }
 
+#if !NETSTANDARD2_0
                [CLSCompliant (false)]
                [Obsolete ("Not necessarily portable due to cdecl restrictions.\n" +
                                "Use snprintf (StringBuilder, string) instead.")]
@@ -853,6 +864,7 @@ namespace Mono.Unix.Native {
                        Array.Copy (parameters, 0, _parameters, 3, parameters.Length);
                        return (int) XPrintfFunctions.snprintf (_parameters);
                }
+#endif
 
                /*
                 * SKIP:
index 4ae330d5b46f74420f5ed35603c04f4f6cae15fc..c750e5fa86b353b625f01b0f5d1227c6a43c4dc4 100644 (file)
@@ -4387,6 +4387,7 @@ namespace Mono.Unix.Native {
                        return UnixMarshal.EscapeFormatString (message, new char[]{'m'});
                }
 
+#if !NETSTANDARD2_0
                [Obsolete ("Not necessarily portable due to cdecl restrictions.\n" +
                                "Use syslog(SyslogFacility, SyslogLevel, string) instead.")]
                public static int syslog (SyslogFacility facility, SyslogLevel level, 
@@ -4415,6 +4416,7 @@ namespace Mono.Unix.Native {
                        Array.Copy (parameters, 0, _parameters, 2, parameters.Length);
                        return (int) XPrintfFunctions.syslog (_parameters);
                }
+#endif
 
                [DllImport (MPH, SetLastError=true,
                                EntryPoint="Mono_Posix_Syscall_closelog")]
index aa0c06b76c61b87b2f76f222457d2069badf59ac..e429af7f726cc3ade48060848ba35b91604988a5 100644 (file)
@@ -56,7 +56,7 @@ namespace MonoTests.Mono.Unix.Native {
                        Assert.IsFalse (NativeConvert.ToSignum (st.signalReceived) == Signum.SIGURG,
                                        "#IH: Signal Handler invoked when it should have been removed!");
                }
-
+#if !NETCOREAPP2_0
                [Test]
                // MSVCRT.DLL doesn't export snprintf(3).
                [Category ("NotDotNet")]
@@ -92,6 +92,7 @@ namespace MonoTests.Mono.Unix.Native {
                        Assert.AreEqual (s.ToString(), expected,
                                        "#SNPF: printf of many builtin types failed");
                }
+#endif
        }
 }
 
index f70ee556ac6adb177de9fa5cc15cc469928fefca..92884a2591d87096214b2498460e1c9499351f3a 100644 (file)
@@ -51,7 +51,7 @@ namespace Mono {
 
                // handle.h HandleStackMark
                struct HandleStackMark {
-                       int size;
+                       int size, interior_size;
                        IntPtr chunk;
                }
 
index 664d9305745369610b87f6ce3d9a44050db45507..f6b752d1784fdb631a7f8439de3426608c39c963 100644 (file)
@@ -224,14 +224,6 @@ namespace System.IO
                                }
                        }
 
-                       if (access == FileAccess.Read && mode != FileMode.Create && mode != FileMode.OpenOrCreate &&
-                                       mode != FileMode.CreateNew && !File.Exists (path)) {
-                               // don't leak the path information for isolated storage
-                               string msg = Locale.GetText ("Could not find file \"{0}\".");
-                               string fname = GetSecureFileName (path);
-                               throw new FileNotFoundException (String.Format (msg, fname), fname);
-                       }
-
                        // IsolatedStorage needs to keep the Name property to the default "[Unknown]"
                        if (!anonymous)
                                this.name = path;
index 5c812b6f592288d5ac486919837ee6170de6ddde..1c5cdd3ae820dc363687a19efbfe553ca31b6b20 100644 (file)
@@ -574,11 +574,17 @@ namespace System
 #if LIBC
                private static TimeZoneInfo FindSystemTimeZoneByFileName (string id, string filepath)
                {
-                       if (!File.Exists (filepath))
-                               throw new TimeZoneNotFoundException ();
-
-                       using (FileStream stream = File.OpenRead (filepath)) {
+                       FileStream stream = null;
+                       try {
+                               stream = File.OpenRead (filepath);      
+                       } catch (Exception ex) {
+                               throw new TimeZoneNotFoundException ("Couldn't read time zone file " + filepath, ex);
+                       }
+                       try {
                                return BuildFromStream (id, stream);
+                       } finally {
+                               if (stream != null)
+                                       stream.Dispose();
                        }
                }
 #endif
index cf95e49fa3a8774831a9cefea2ab49ea12d3ff9d..4fc95243fe0b899020c9f96256de8d9387082442 100644 (file)
@@ -14,6 +14,8 @@ using System;
 using System.IO;
 using System.Globalization;
 using System.Threading;
+using System.Runtime.InteropServices;
+
 
 using NUnit.Framework;
 
@@ -2680,5 +2682,53 @@ namespace MonoTests.System.IO
                        MoveTest (FileAccess.ReadWrite, FileShare.Write | FileShare.Delete, true);
                        MoveTest (FileAccess.ReadWrite, FileShare.ReadWrite | FileShare.Delete, true);
                }
+
+
+               [DllImport ("libc", SetLastError=true)]
+               public static extern int symlink (string oldpath, string newpath);
+
+               [Test]
+               public void SymLinkLoop ()
+               {
+                       if (!RunningOnUnix)
+                               Assert.Ignore ("Symlink are hard on windows");
+
+                       var name1 = Path.GetRandomFileName ();
+                       var name2 = Path.GetRandomFileName ();
+
+                       var path1 = Path.Combine (Path.GetTempPath (), name1);
+                       var path2 = Path.Combine (Path.GetTempPath (), name2);
+
+                       File.Delete (path1);
+                       File.Delete (path2);
+
+                       try {
+                               symlink (path1, path2);
+                               symlink (path2, path1);
+
+                               Assert.IsTrue (File.Exists (path1), "File.Exists must return true for path1 symlink loop");
+                               Assert.IsTrue (File.Exists (path2), "File.Exists must return true for path2 symlink loop");
+
+                               try {
+                                       using (var f = File.Open (path1, FileMode.Open, FileAccess.Read)) {
+                                               Assert.Fail ("File.Open must throw for symlink loops");
+                                       }
+                               } catch (IOException ex) {
+                                       Assert.AreEqual (0x80070781u, (uint)ex.HResult, "Ensure HRESULT is correct");
+                               }
+
+                               File.Delete (path1); //Delete must not throw and must work
+                               Assert.IsFalse (File.Exists (path1), "File.Delete must delete symlink loops");
+
+                       } finally {
+                               try {
+                                       File.Delete (path1);
+                                       File.Delete (path2);
+                               } catch (IOException) {
+                                       //Don't double fault any exception from the tests.
+                               }
+
+                       }
+               }
        }
 }
index 261e9b5692537a0593711614e27b619b917e3637..c168a31e4267f0059f18815f65a7b5043ff16872 100644 (file)
@@ -14,6 +14,8 @@ using System.Runtime.CompilerServices;
 using System.Threading;
 using System.Collections.Generic;
 
+#pragma warning disable CS1718
+
 namespace MonoTests.System
 {
        [TestFixture]
index eda79f7927d24d7faec8bcac20d1d8fff7bc2976..31959c173984ea0d2d5a32ab360e8b6bfccd340b 100644 (file)
@@ -2,8 +2,6 @@ namespace System.Diagnostics.Private
 {
        static partial class Debug
        {
-               static readonly string NewLine = Environment.NewLine;
-
                static void ShowAssertDialog (string stackTrace, string message, string detailMessage)
                {
                        // FIXME should we g_error in this case?
index 145bbb5424b7ffae80cfb0d158a3c230a822a941..c9fca00b3e437277f5fc58b1c8e9a9e2af2710f2 100644 (file)
@@ -783,9 +783,10 @@ namespace System.IO
         internal override DirectoryInfo CreateObject(SearchResult result)
         {
             String name = result.FullPath;
-            String permissionName = name + "\\.";
 
 #if MONO_FEATURE_CAS
+            String permissionName = name + "\\.";
+
 #if FEATURE_CORECLR
             FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, permissionName);
             state.EnsureState();
@@ -821,9 +822,10 @@ namespace System.IO
             if (isDir)
             {
                 String name = result.FullPath;
-                String permissionName = name + "\\.";
 
 #if MONO_FEATURE_CAS
+                String permissionName = name + "\\.";
+
 #if FEATURE_CORECLR
                 FileSecurityState state = new FileSecurityState(FileSecurityStateAccess.Read, String.Empty, permissionName);
                 state.EnsureState();
diff --git a/mcs/errors/cs1031-3.cs b/mcs/errors/cs1031-3.cs
new file mode 100644 (file)
index 0000000..3126dfa
--- /dev/null
@@ -0,0 +1,18 @@
+// CS1031: Type expected
+// Line: 16
+
+public class B<Y>  where Y: B<Y>
+{
+}
+
+public class A<X>: B<A<X>>
+{
+}
+
+public class Repro
+{
+       public static void Main (string[] args)
+       {
+               var h = typeof (B<A<>>);
+       }
+}
\ No newline at end of file
index e6a95fe8163a3590acb9f23602cc10d4cdec63dd..d6314ff005a3222079d9eb1eb746b258780da2f8 100644 (file)
@@ -1267,7 +1267,8 @@ namespace Mono.CSharp
                        else if (the_token == Token.INTERR_NULLABLE || the_token == Token.STAR)
                                goto again;
                        else if (the_token == Token.OP_GENERICS_LT) {
-                               if (!parse_less_than (ref genericDimension))
+                               int unused = 0;
+                               if (!parse_less_than (ref unused))
                                        return false;
                                goto again;
                        } else if (the_token == Token.OPEN_BRACKET) {
index c054330db202f339be76b7a07f01626fd207f7fe..9042dcdabad8e5405cbbbc086953ade32d7dfc81 100644 (file)
@@ -7570,14 +7570,21 @@ namespace Mono.CSharp
                        bool is_value_type = type.IsStructOrEnum;
                        VariableReference vr = target as VariableReference;
 
+                       bool prepare_await = ec.HasSet (BuilderContext.Options.AsyncBody) && arguments?.ContainsEmitWithAwait () == true;
+
                        if (target != null && is_value_type && (vr != null || method == null)) {
+                               if (prepare_await) {
+                                       arguments = arguments.Emit (ec, false, true);
+                                       prepare_await = false;
+                               }
+                               
                                target.AddressOf (ec, AddressOp.Store);
                        } else if (vr != null && vr.IsRef) {
                                vr.EmitLoad (ec);
                        }
 
                        if (arguments != null) {
-                               if (ec.HasSet (BuilderContext.Options.AsyncBody) && (arguments.Count > (this is NewInitialize ? 0 : 1)) && arguments.ContainsEmitWithAwait ())
+                               if (prepare_await)
                                        arguments = arguments.Emit (ec, false, true);
 
                                arguments.Emit (ec);
diff --git a/mcs/tests/test-async-92.cs b/mcs/tests/test-async-92.cs
new file mode 100644 (file)
index 0000000..e41ac00
--- /dev/null
@@ -0,0 +1,22 @@
+using System.Threading.Tasks;
+
+public class A
+{
+       public async Task<ValueType> Test1 (int input2)
+       {
+               return new ValueType (await Task.FromResult (12345));
+       }
+
+       public static void Main ()
+       {
+               var a = new A ();
+               a.Test1 (1).Wait ();
+       }
+}
+
+public struct ValueType
+{
+       public ValueType (int field2)
+       {
+       }
+}
index 4882b788602ee9e5fb99495bac6bd98d1c8d546c..b06aba48fd5ead3c9127195304de99dfdf14ce4f 100644 (file)
       </method>
     </type>
   </test>
+  <test name="test-943.cs">
+    <type name="MyStruct">
+      <method name="Int32 get_X()" attrs="2182">
+        <size>14</size>
+      </method>
+      <method name="Void set_X(Int32)" attrs="2182">
+        <size>8</size>
+      </method>
+    </type>
+    <type name="X">
+      <method name="Int32 Main()" attrs="150">
+        <size>44</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+  </test>
   <test name="test-95.cs">
     <type name="X">
       <method name="Int32 Main()" attrs="150">
       </method>
     </type>
   </test>
+  <test name="test-async-92.cs">
+    <type name="A">
+      <method name="System.Threading.Tasks.Task`1[ValueType] Test1(Int32)" attrs="134">
+        <size>33</size>
+      </method>
+      <method name="Void Main()" attrs="150">
+        <size>20</size>
+      </method>
+      <method name="Void .ctor()" attrs="6278">
+        <size>7</size>
+      </method>
+    </type>
+    <type name="ValueType">
+      <method name="Void .ctor(Int32)" attrs="6278">
+        <size>2</size>
+      </method>
+    </type>
+    <type name="A+&lt;Test1&gt;c__async0">
+      <method name="Void MoveNext()" attrs="486">
+        <size>174</size>
+      </method>
+      <method name="Void SetStateMachine(System.Runtime.CompilerServices.IAsyncStateMachine)" attrs="486">
+        <size>13</size>
+      </method>
+    </type>
+  </test>
   <test name="test-cls-00.cs">
     <type name="CLSCLass_6">
       <method name="Void add_Disposed(Delegate)" attrs="2182">
index a76e9f88c92a1440897c007e92937f4d16b89311..ab13accc034c54695fba45e8b4deecf3854a0f30 100755 (executable)
@@ -1110,6 +1110,14 @@ void          mono_register_config_for_assembly (const char* assembly_name, cons
                }
 
                if (error != null) {
+                       Console.Error.WriteLine ("Failure to load i18n assemblies, the following directories were searched for the assemblies:");
+                       foreach (var path in link_paths){
+                               Console.Error.WriteLine ("   Path: " + path);
+                       }
+                       if (custom_mode){
+                               Console.WriteLine ("In Custom mode, you need to provide the directory to lookup assemblies from using -L");
+                       }
+                       
                        Error ("Couldn't load one or more of the i18n assemblies: " + error);
                        Environment.Exit (1);
                }
@@ -1183,7 +1191,12 @@ void          mono_register_config_for_assembly (const char* assembly_name, cons
                Assembly a = null;
                
                try {
+                       if (!quiet)
+                               Console.WriteLine ("Attempting to load assembly: {0}", assembly);
                        a = universe.LoadFile (assembly);
+                       if (!quiet)
+                               Console.WriteLine ("Assembly {0} loaded successfully.", assembly);
+                       
                } catch (FileNotFoundException){
                        Error ($"Cannot find assembly `{assembly}'");
                } catch (IKVM.Reflection.BadImageFormatException f) {
@@ -1206,6 +1219,8 @@ void          mono_register_config_for_assembly (const char* assembly_name, cons
                string total_log = "";
                foreach (string dir in link_paths){
                        string full_path = Path.Combine (dir, assembly);
+                       if (!quiet)
+                               Console.WriteLine ("Attempting to load assembly from: " + full_path);
                        if (!assembly.EndsWith (".dll") && !assembly.EndsWith (".exe"))
                                full_path += ".dll";
                        
index 14090d8c3ecc5d60c50a5d2225e23b0a559b3e47..06085362c54484072e624443e2c11b6a9dc573c3 100644 (file)
@@ -8,7 +8,7 @@ if SUPPORT_SGEN
 metadata_lib=$(top_builddir)/mono/metadata/libmonoruntimesgen-static.la
 gc_lib=$(top_builddir)/mono/sgen/libmonosgen-static.la
 else
-metadata_lib=$(top_builddir)/mono/metadata/libmonoruntime-static.a
+metadata_lib=$(top_builddir)/mono/metadata/libmonoruntime-static.la
 gc_lib=$(LIBGC_STATIC_LIBS)
 endif
 
index f8de9e2d23e3842a747a4948d641847b77f3464c..7bcd8fa7a752ca25f81c4f58b7d898492a6e7961 100644 (file)
@@ -1148,6 +1148,7 @@ leave:
 MonoAssembly*
 mono_try_assembly_resolve_handle (MonoDomain *domain, MonoStringHandle fname, MonoAssembly *requesting, gboolean refonly, MonoError *error)
 {
+       HANDLE_FUNCTION_ENTER ();
        MonoAssembly *ret = NULL;
        MonoMethod *method;
        MonoBoolean isrefonly;
@@ -1156,7 +1157,7 @@ mono_try_assembly_resolve_handle (MonoDomain *domain, MonoStringHandle fname, Mo
        error_init (error);
 
        if (mono_runtime_get_no_exec ())
-               return ret;
+               goto leave;
 
        g_assert (domain != NULL && !MONO_HANDLE_IS_NULL (fname));
 
@@ -1167,14 +1168,16 @@ mono_try_assembly_resolve_handle (MonoDomain *domain, MonoStringHandle fname, Mo
        MonoReflectionAssemblyHandle requesting_handle;
        if (requesting) {
                requesting_handle = mono_assembly_get_object_handle (domain, requesting, error);
-               return_val_if_nok (error, ret);
+               if (!is_ok (error))
+                       goto leave;
        }
        params [0] = MONO_HANDLE_RAW (fname);
        params[1] = requesting ? MONO_HANDLE_RAW (requesting_handle) : NULL;
        params [2] = &isrefonly;
        MonoReflectionAssemblyHandle result = MONO_HANDLE_NEW (MonoReflectionAssembly, mono_runtime_invoke_checked (method, domain->domain, params, error));
        ret = !MONO_HANDLE_IS_NULL (result) ? MONO_HANDLE_GETVAL (result, assembly) : NULL;
-       return ret;
+leave:
+       HANDLE_FUNCTION_RETURN_VAL (ret);
 }
 
 MonoAssembly *
@@ -1243,6 +1246,7 @@ add_assemblies_to_domain (MonoDomain *domain, MonoAssembly *ass, GHashTable *ht)
 static void
 mono_domain_fire_assembly_load (MonoAssembly *assembly, gpointer user_data)
 {
+       HANDLE_FUNCTION_ENTER ();
        static MonoClassField *assembly_load_field;
        static MonoMethod *assembly_load_method;
        MonoError error;
@@ -1253,7 +1257,7 @@ mono_domain_fire_assembly_load (MonoAssembly *assembly, gpointer user_data)
 
        if (!domain->domain)
                /* This can happen during startup */
-               return;
+               goto leave;
 #ifdef ASSEMBLY_LOAD_DEBUG
        fprintf (stderr, "Loading %s into domain %s\n", assembly->aname.name, domain->friendly_name);
 #endif
@@ -1271,7 +1275,7 @@ mono_domain_fire_assembly_load (MonoAssembly *assembly, gpointer user_data)
        mono_field_get_value ((MonoObject*) domain->domain, assembly_load_field, &load_value);
        if (load_value == NULL) {
                /* No events waiting to be triggered */
-               return;
+               goto leave;
        }
 
        MonoReflectionAssemblyHandle ref_assembly = mono_assembly_get_object_handle (domain, assembly, &error);
@@ -1286,6 +1290,8 @@ mono_domain_fire_assembly_load (MonoAssembly *assembly, gpointer user_data)
 
        mono_runtime_invoke_checked (assembly_load_method, domain->domain, params, &error);
        mono_error_cleanup (&error);
+leave:
+       HANDLE_FUNCTION_RETURN ();
 }
 
 /*
index ee0695ceccfbdb32dd39229a366fef7f3f01824d..4ed4f39da3dc5d648fa30936fb8d50f1d3fd7974 100644 (file)
@@ -9106,10 +9106,25 @@ mono_class_get_methods (MonoClass* klass, gpointer *iter)
 static MonoMethod*
 mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
 {
-       MonoMethod** method;
+       gboolean static_iter = FALSE;
+
        if (!iter)
                return NULL;
-       if (klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)) {
+
+       /*
+        * If the lowest bit of the iterator is 1, this is an iterator for static metadata,
+        * and the upper bits contain an index. Otherwise, the iterator is a pointer into
+        * klass->methods.
+        */
+       if ((gsize)(*iter) & 1)
+               static_iter = TRUE;
+       /* Use the static metadata only if klass->methods is not yet initialized */
+       if (!static_iter && !(klass->methods || !MONO_CLASS_HAS_STATIC_METADATA (klass)))
+               static_iter = TRUE;
+
+       if (!static_iter) {
+               MonoMethod** methodptr;
+
                if (!*iter) {
                        mono_class_setup_methods (klass);
                        /*
@@ -9119,20 +9134,22 @@ mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
                        if (!klass->methods)
                                return NULL;
                        /* start from the first */
-                       method = &klass->methods [0];
+                       methodptr = &klass->methods [0];
                } else {
-                       method = (MonoMethod **)*iter;
-                       method++;
+                       methodptr = (MonoMethod **)*iter;
+                       methodptr++;
                }
+               if (*iter)
+                       g_assert ((guint64)(*iter) > 0x100);
                int mcount = mono_class_get_method_count (klass);
-               while (method < &klass->methods [mcount]) {
-                       if (*method && ((*method)->flags & METHOD_ATTRIBUTE_VIRTUAL))
+               while (methodptr < &klass->methods [mcount]) {
+                       if (*methodptr && ((*methodptr)->flags & METHOD_ATTRIBUTE_VIRTUAL))
                                break;
-                       method ++;
+                       methodptr ++;
                }
-               if (method < &klass->methods [mcount]) {
-                       *iter = method;
-                       return *method;
+               if (methodptr < &klass->methods [mcount]) {
+                       *iter = methodptr;
+                       return *methodptr;
                } else {
                        return NULL;
                }
@@ -9144,7 +9161,7 @@ mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
                if (!*iter) {
                        start_index = 0;
                } else {
-                       start_index = GPOINTER_TO_UINT (*iter);
+                       start_index = GPOINTER_TO_UINT (*iter) >> 1;
                }
 
                int first_idx = mono_class_get_first_method_idx (klass);
@@ -9165,7 +9182,7 @@ mono_class_get_virtual_methods (MonoClass* klass, gpointer *iter)
                        mono_error_cleanup (&error); /* FIXME don't swallow the error */
 
                        /* Add 1 here so the if (*iter) check fails */
-                       *iter = GUINT_TO_POINTER (i + 1);
+                       *iter  = GUINT_TO_POINTER (((i + 1) << 1) | 1);
                        return res;
                } else {
                        return NULL;
index 86309ef20234d4dd559726f0c9fcfe1a32f08e32..d522657b62f0b97efa9792ba77734e29d2882e12 100644 (file)
@@ -1090,7 +1090,7 @@ mono_cominterop_get_invoke (MonoMethod *method)
        for (i = 1; i <= sig->param_count; i++)
                mono_mb_emit_ldarg (mb, i);
 
-       if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
+       if ((method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) || mono_class_is_interface (method->klass)) {
                MonoMethod * native_wrapper = mono_cominterop_get_native_wrapper(method);
                mono_mb_emit_managed_call (mb, native_wrapper, NULL);
        }
index be325b9cc705c9c6efc420046a5918f671f1c4dc..f235f01c01ac8f090d63012133210f13219c95b4 100644 (file)
@@ -242,6 +242,8 @@ struct _MonoJitInfo {
         * d.tramp_info contains additional data in this case.
         */
        gboolean    is_trampoline:1;
+       /* Whenever this jit info refers to an interpreter method */
+       gboolean    is_interp:1;
 
        /* FIXME: Embed this after the structure later*/
        gpointer    gc_info; /* Currently only used by SGen */
index 00a11e67319e375ff9004906341b53320767fbcb..bdb1c773593c3f03c5ff7d5a57263a4057bcc9cb 100644 (file)
@@ -73,66 +73,12 @@ const MonoObjectHandle mono_null_value_handle = NULL;
 
 #define THIS_IS_AN_OK_NUMBER_OF_HANDLES 100
 
-enum {
-       HANDLE_CHUNK_PTR_OBJ = 0x0, /* chunk element points to beginning of a managed object */
-       HANDLE_CHUNK_PTR_INTERIOR = 0x1, /* chunk element points into the middle of a managed object */
-       HANDLE_CHUNK_PTR_MASK = 0x1
-};
-
-/* number of bits in each word of the interior pointer bitmap */
-#define INTERIOR_HANDLE_BITMAP_BITS_PER_WORD (sizeof(guint32) << 3)
-
-static gboolean
-bitset_bits_test (guint32 *bitmaps, int idx)
-{
-       int w = idx / INTERIOR_HANDLE_BITMAP_BITS_PER_WORD;
-       int b = idx % INTERIOR_HANDLE_BITMAP_BITS_PER_WORD;
-       guint32 bitmap = bitmaps [w];
-       guint32 mask = 1u << b;
-       return ((bitmap & mask) != 0);
-}
-
-static void
-bitset_bits_set (guint32 *bitmaps, int idx)
-{
-       int w = idx / INTERIOR_HANDLE_BITMAP_BITS_PER_WORD;
-       int b = idx % INTERIOR_HANDLE_BITMAP_BITS_PER_WORD;
-       guint32 *bitmap = &bitmaps [w];
-       guint32 mask = 1u << b;
-       *bitmap |= mask;
-}
-static void
-bitset_bits_clear (guint32 *bitmaps, int idx)
-{
-       int w = idx / INTERIOR_HANDLE_BITMAP_BITS_PER_WORD;
-       int b = idx % INTERIOR_HANDLE_BITMAP_BITS_PER_WORD;
-       guint32 *bitmap = &bitmaps [w];
-       guint32 mask = ~(1u << b);
-       *bitmap &= mask;
-}
-
-static gpointer*
-chunk_element_objslot_init (HandleChunk *chunk, int idx, gboolean interior)
-{
-       if (interior)
-               bitset_bits_set (chunk->interior_bitmap, idx);
-       else
-               bitset_bits_clear (chunk->interior_bitmap, idx);
-       return &chunk->elems [idx].o;
-}
-
 static HandleChunkElem*
 chunk_element (HandleChunk *chunk, int idx)
 {
        return &chunk->elems[idx];
 }
 
-static guint
-chunk_element_kind (HandleChunk *chunk, int idx)
-{
-       return bitset_bits_test (chunk->interior_bitmap, idx) ? HANDLE_CHUNK_PTR_INTERIOR : HANDLE_CHUNK_PTR_OBJ;
-}
-
 static HandleChunkElem*
 handle_to_chunk_element (MonoObjectHandle o)
 {
@@ -207,25 +153,12 @@ mono_handle_chunk_leak_check (HandleStack *handles) {
 }
 #endif
 
-MonoRawHandle
-#ifndef MONO_HANDLE_TRACK_OWNER
-mono_handle_new (MonoObject *object)
-#else
-mono_handle_new (MonoObject *object, const char *owner)
-#endif
-{
-#ifndef MONO_HANDLE_TRACK_OWNER
-       return mono_handle_new_full (object, FALSE);
-#else
-       return mono_handle_new_full (object, FALSE, owner);
-#endif
-}
 /* Actual handles implementation */
 MonoRawHandle
 #ifndef MONO_HANDLE_TRACK_OWNER
-mono_handle_new_full (gpointer rawptr, gboolean interior)
+mono_handle_new (MonoObject *obj)
 #else
-mono_handle_new_full (gpointer rawptr, gboolean interior, const char *owner)
+mono_handle_new (MonoObject *obj, const char *owner)
 #endif
 {
        MonoThreadInfo *info = mono_thread_info_current ();
@@ -238,7 +171,7 @@ mono_handle_new_full (gpointer rawptr, gboolean interior, const char *owner)
 retry:
        if (G_LIKELY (top->size < OBJECTS_PER_HANDLES_CHUNK)) {
                int idx = top->size;
-               gpointer* objslot = chunk_element_objslot_init (top, idx, interior);
+               gpointer* objslot = &top->elems [idx].o;
                /* can be interrupted anywhere here, so:
                 * 1. make sure the new slot is null
                 * 2. make the new slot scannable (increment size)
@@ -251,7 +184,7 @@ retry:
                mono_memory_write_barrier ();
                top->size++;
                mono_memory_write_barrier ();
-               *objslot = rawptr;
+               *objslot = obj;
                SET_OWNER (top,idx);
                SET_SP (handles, top, idx);
                return objslot;
@@ -266,7 +199,6 @@ retry:
        }
        HandleChunk *new_chunk = g_new (HandleChunk, 1);
        new_chunk->size = 0;
-       memset (new_chunk->interior_bitmap, 0, INTERIOR_HANDLE_BITMAP_WORDS);
        new_chunk->prev = top;
        new_chunk->next = NULL;
        /* make sure size == 0 before new chunk is visible */
@@ -276,20 +208,51 @@ retry:
        goto retry;
 }
 
+MonoRawHandle
+#ifndef MONO_HANDLE_TRACK_OWNER
+mono_handle_new_interior (gpointer rawptr)
+#else
+mono_handle_new_interior (gpointer rawptr, const char *owner)
+#endif
+{
+       MonoThreadInfo *info = mono_thread_info_current ();
+       HandleStack *handles = (HandleStack *)info->handle_stack;
+       HandleChunk *top = handles->interior;
+#ifdef MONO_HANDLE_TRACK_SP
+       mono_handle_chunk_leak_check (handles);
+#endif
+
+       g_assert (top);
 
+       /*
+        * Don't extend the chunk now, interior handles are
+        * only used for icall arguments, they shouldn't
+        * overflow.
+        */
+       g_assert (top->size < OBJECTS_PER_HANDLES_CHUNK);
+       int idx = top->size;
+       gpointer *objslot = &top->elems [idx].o;
+       *objslot = NULL;
+       mono_memory_write_barrier ();
+       top->size++;
+       mono_memory_write_barrier ();
+       *objslot = rawptr;
+       SET_OWNER (top,idx);
+       SET_SP (handles, top, idx);
+       return objslot;
+}
 
 HandleStack*
 mono_handle_stack_alloc (void)
 {
-       HandleStack *stack = g_new (HandleStack, 1);
-       HandleChunk *chunk = g_new (HandleChunk, 1);
+       HandleStack *stack = g_new0 (HandleStack, 1);
+       HandleChunk *chunk = g_new0 (HandleChunk, 1);
+       HandleChunk *interior = g_new0 (HandleChunk, 1);
 
-       chunk->size = 0;
-       memset (chunk->interior_bitmap, 0, INTERIOR_HANDLE_BITMAP_WORDS);
-       chunk->prev = chunk->next = NULL;
        mono_memory_write_barrier ();
        stack->top = stack->bottom = chunk;
-#ifdef MONO_HANDLE_TRACK_OWNER
+       stack->interior = interior;
+#ifdef MONO_HANDLE_TRACK_SP
        stack->stackmark_sp = NULL;
 #endif
        return stack;
@@ -309,9 +272,44 @@ mono_handle_stack_free (HandleStack *stack)
                c = next;
        }
        g_free (c);
+       g_free (stack->interior);
        g_free (stack);
 }
 
+void
+mono_handle_stack_free_domain (HandleStack *stack, MonoDomain *domain)
+{
+       /* Called by the GC while clearing out objects of the given domain from the heap. */
+       /* If there are no handles-related bugs, there is nothing to do: if a
+        * thread accessed objects from the domain it was aborted, so any
+        * threads left alive cannot have any handles that point into the
+        * unloading domain.  However if there is a handle leak, the handle stack is not */
+       if (!stack)
+               return;
+       /* Root domain only unloaded when mono is shutting down, don't need to check anything */
+       if (domain == mono_get_root_domain () || mono_runtime_is_shutting_down ())
+               return;
+       HandleChunk *cur = stack->bottom;
+       HandleChunk *last = stack->top;
+       if (!cur)
+               return;
+       while (cur) {
+               for (int idx = 0; idx < cur->size; ++idx) {
+                       HandleChunkElem *elem = &cur->elems[idx];
+                       if (!elem->o)
+                               continue;
+                       g_assert (mono_object_domain (elem->o) != domain);
+               }
+               if (cur == last)
+                       break;
+               cur = cur->next;
+       }
+       /* We don't examine the interior pointers here because the GC treats
+        * them conservatively and anyway we don't have enough information here to
+        * find the object's vtable.
+        */
+}
+
 static void
 check_handle_stack_monotonic (HandleStack *stack)
 {
@@ -362,46 +360,32 @@ mono_handle_stack_scan (HandleStack *stack, GcScanFunc func, gpointer gc_data, g
 
          Note that if we're running, we know the world is stopped.
        */
-       HandleChunk *cur = stack->bottom;
-       HandleChunk *last = stack->top;
-
-       if (!cur)
-               return;
+       if (precise) {
+               HandleChunk *cur = stack->bottom;
+               HandleChunk *last = stack->top;
 
-       while (cur) {
-               /* assume that object pointers will be much more common than interior pointers.
-                * scan the object pointers by iterating over the chunk elements.
-                * scan the interior pointers by iterating over the bitmap bits.
-                */
-               if (precise) {
+               while (cur) {
                        for (int i = 0; i < cur->size; ++i) {
                                HandleChunkElem* elem = chunk_element (cur, i);
-                               int kind = chunk_element_kind (cur, i);
                                gpointer* obj_slot = &elem->o;
-                               if (kind == HANDLE_CHUNK_PTR_OBJ && *obj_slot != NULL)
+                               if (*obj_slot != NULL)
                                        func (obj_slot, gc_data);
                        }
-               } else {
-                       int elem_idx = 0;
-                       for (int i = 0; i < INTERIOR_HANDLE_BITMAP_WORDS; ++i) {
-                               elem_idx = i * INTERIOR_HANDLE_BITMAP_BITS_PER_WORD;
-                               if (elem_idx >= cur->size)
-                                       break;
-                               /* no interior pointers in the range */ 
-                               if (cur->interior_bitmap [i] == 0)
-                                       continue;
-                               for (int j = 0; j < INTERIOR_HANDLE_BITMAP_BITS_PER_WORD && elem_idx < cur->size; ++j,++elem_idx) {
-                                       HandleChunkElem *elem = chunk_element (cur, elem_idx);
-                                       int kind = chunk_element_kind (cur, elem_idx);
-                                       gpointer *ptr_slot = &elem->o;
-                                       if (kind == HANDLE_CHUNK_PTR_INTERIOR && *ptr_slot != NULL)
-                                               func (ptr_slot, gc_data);
-                               }
-                       }            
+                       if (cur == last)
+                               break;
+                       cur = cur->next;
+               }
+       } else {
+               HandleChunk *cur = stack->interior;
+
+               if (!cur)
+                       return;
+               for (int i = 0; i < cur->size; ++i) {
+                       HandleChunkElem* elem = chunk_element (cur, i);
+                       gpointer* ptr_slot = &elem->o;
+                       if (*ptr_slot != NULL)
+                               func (ptr_slot, gc_data);
                }
-               if (cur == last)
-                       break;
-               cur = cur->next;
        }
 }
 
@@ -488,7 +472,6 @@ mono_gchandle_from_handle (MonoObjectHandle handle, mono_bool pinned)
        HandleChunk *chunk = chunk_element_to_chunk_idx (stack, elem, &elem_idx);
        /* gchandles cannot deal with interior pointers */
        g_assert (chunk != NULL);
-       g_assert (chunk_element_kind (chunk, elem_idx) != HANDLE_CHUNK_PTR_INTERIOR);
        return mono_gchandle_new (MONO_HANDLE_RAW (handle), pinned);
 }
 
index fd6d0cfffee7cbd002523a8a2b2ee1bc06604140..5a8e3356268585de1d5f97412760f4e3918a22b2 100644 (file)
@@ -25,7 +25,6 @@
 
 G_BEGIN_DECLS
 
-
 /*
 Handle stack.
 
@@ -73,13 +72,8 @@ typedef struct {
 #endif
 } HandleChunkElem;
 
-/* number of guint32's needed to store the interior pointers bitmap */
-#define INTERIOR_HANDLE_BITMAP_WORDS ((OBJECTS_PER_HANDLES_CHUNK + 31) / 32)
-
 struct _HandleChunk {
        int size; //number of handles
-       /* bits in the range 0..size-1 of interior_bitmap are valid; rest are ignored. */
-       guint32 interior_bitmap [INTERIOR_HANDLE_BITMAP_WORDS];
        HandleChunk *prev, *next;
        HandleChunkElem elems [OBJECTS_PER_HANDLES_CHUNK];
 };
@@ -90,10 +84,13 @@ typedef struct {
 #ifdef MONO_HANDLE_TRACK_SP
        gpointer stackmark_sp; // C stack pointer top when from most recent mono_stack_mark_init
 #endif
+       /* Chunk for storing interior pointers. Not extended right now */
+       HandleChunk *interior;
 } HandleStack;
 
+// Keep this in sync with RuntimeStructs.cs
 typedef struct {
-       int size;
+       int size, interior_size;
        HandleChunk *chunk;
 #ifdef MONO_HANDLE_TRACK_SP
        gpointer prev_sp; // C stack pointer from prior mono_stack_mark_init
@@ -108,18 +105,20 @@ typedef void (*GcScanFunc) (gpointer*, gpointer);
 #ifndef MONO_HANDLE_TRACK_OWNER
 MonoRawHandle mono_handle_new (MonoObject *object);
 MonoRawHandle mono_handle_new_full (gpointer rawptr, gboolean interior);
+MonoRawHandle mono_handle_new_interior (gpointer rawptr);
 #else
 MonoRawHandle mono_handle_new (MonoObject *object, const char* owner);
 MonoRawHandle mono_handle_new_full (gpointer rawptr, gboolean interior, const char *owner);
+MonoRawHandle mono_handle_new_interior (gpointer rawptr, const char *owner);
 #endif
 
-
 void mono_handle_stack_scan (HandleStack *stack, GcScanFunc func, gpointer gc_data, gboolean precise);
 gboolean mono_handle_stack_is_empty (HandleStack *stack);
 HandleStack* mono_handle_stack_alloc (void);
 void mono_handle_stack_free (HandleStack *handlestack);
 MonoRawHandle mono_stack_mark_pop_value (MonoThreadInfo *info, HandleStackMark *stackmark, MonoRawHandle value);
 void mono_stack_mark_record_size (MonoThreadInfo *info, HandleStackMark *stackmark, const char *func_name);
+void mono_handle_stack_free_domain (HandleStack *stack, MonoDomain *domain);
 
 #ifdef MONO_HANDLE_TRACK_SP
 void mono_handle_chunk_leak_check (HandleStack *handles);
@@ -134,6 +133,7 @@ mono_stack_mark_init (MonoThreadInfo *info, HandleStackMark *stackmark)
        HandleStack *handles = (HandleStack *)info->handle_stack;
        stackmark->size = handles->top->size;
        stackmark->chunk = handles->top;
+       stackmark->interior_size = handles->interior->size;
 #ifdef MONO_HANDLE_TRACK_SP
        stackmark->prev_sp = handles->stackmark_sp;
        handles->stackmark_sp = sptop;
@@ -148,6 +148,7 @@ mono_stack_mark_pop (MonoThreadInfo *info, HandleStackMark *stackmark)
        old_top->size = stackmark->size;
        mono_memory_write_barrier ();
        handles->top = old_top;
+       handles->interior->size = stackmark->interior_size;
 #ifdef MONO_HANDLE_TRACK_SP
        mono_memory_write_barrier (); /* write to top before prev_sp */
        handles->stackmark_sp = stackmark->prev_sp;
@@ -403,20 +404,6 @@ This is why we evaluate index and value before any call to MONO_HANDLE_RAW or ot
                mono_handle_array_getref (MONO_HANDLE_CAST(MonoObject, (DEST)), (HANDLE), (IDX)); \
        } while (0)
 
-/* Handles into the interior of objects.
- *
- * Typically when working with value types, we pass them by reference.  In the case where the value type
- * is a field in a managed class, the reference will be a pointer into the middle of a managed object.
- * We need to identify such pointers in order for SGen to scan them correctly.
- */
-
-#ifndef MONO_HANDLE_TRACK_OWNER
-#define MONO_HANDLE_NEW_GET_VALPTR(HANDLE,TYPE,FIELD) (TYPE_VALUE_HANDLE_NAME(TYPE))(mono_handle_new_full (&(HANDLE)->__raw->FIELD), TRUE))
-#else
-#define MONO_HANDLE_NEW_GET_VALPTR(HANDLE,TYPE,FIELD) (TYPE_VALUE_HANDLE_NAME(TYPE))(mono_handle_new_full (&(HANDLE)->__raw->FIELD), TRUE, HANDLE_OWNER_STRINGIFY(__FILE__, __LINE__))
-#endif
-
-
 #define MONO_HANDLE_ASSIGN(DESTH, SRCH)                                \
        mono_handle_assign (MONO_HANDLE_CAST (MonoObject, (DESTH)), MONO_HANDLE_CAST(MonoObject, (SRCH)))
 
index b8d6b81b1e76643bf7ea75cdcdfba5500dd831d0..51b333dce30ef07cdbf32d762525d9698e32770e 100644 (file)
@@ -207,9 +207,9 @@ ICALL(DECIMAL_13, "ToSingle", mono_decimal_to_float)
 #endif
 
 ICALL_TYPE(DELEGATE, "System.Delegate", DELEGATE_1)
-ICALL(DELEGATE_1, "AllocDelegateLike_internal", ves_icall_System_Delegate_AllocDelegateLike_internal)
-ICALL(DELEGATE_2, "CreateDelegate_internal", ves_icall_System_Delegate_CreateDelegate_internal)
-ICALL(DELEGATE_3, "GetVirtualMethod_internal", ves_icall_System_Delegate_GetVirtualMethod_internal)
+HANDLES(ICALL(DELEGATE_1, "AllocDelegateLike_internal", ves_icall_System_Delegate_AllocDelegateLike_internal))
+HANDLES(ICALL(DELEGATE_2, "CreateDelegate_internal", ves_icall_System_Delegate_CreateDelegate_internal))
+HANDLES(ICALL(DELEGATE_3, "GetVirtualMethod_internal", ves_icall_System_Delegate_GetVirtualMethod_internal))
 
 ICALL_TYPE(DEBUGR, "System.Diagnostics.Debugger", DEBUGR_1)
 ICALL(DEBUGR_1, "IsAttached_internal", ves_icall_System_Diagnostics_Debugger_IsAttached_internal)
@@ -683,8 +683,8 @@ ICALL(MARSHAL_7, "FreeHGlobal", ves_icall_System_Runtime_InteropServices_Marshal
 ICALL(MARSHAL_44, "GetCCW", ves_icall_System_Runtime_InteropServices_Marshal_GetCCW)
 ICALL(MARSHAL_8, "GetComSlotForMethodInfoInternal", ves_icall_System_Runtime_InteropServices_Marshal_GetComSlotForMethodInfoInternal)
 #endif
-ICALL(MARSHAL_9, "GetDelegateForFunctionPointerInternal", ves_icall_System_Runtime_InteropServices_Marshal_GetDelegateForFunctionPointerInternal)
-ICALL(MARSHAL_10, "GetFunctionPointerForDelegateInternal", ves_icall_System_Runtime_InteropServices_Marshal_GetFunctionPointerForDelegateInternal)
+HANDLES(ICALL(MARSHAL_9, "GetDelegateForFunctionPointerInternal", ves_icall_System_Runtime_InteropServices_Marshal_GetDelegateForFunctionPointerInternal))
+HANDLES(ICALL(MARSHAL_10, "GetFunctionPointerForDelegateInternal", ves_icall_System_Runtime_InteropServices_Marshal_GetFunctionPointerForDelegateInternal))
 #ifndef DISABLE_COM
 ICALL(MARSHAL_52, "GetHRForException_WinRT", ves_icall_System_Runtime_InteropServices_Marshal_GetHRForException_WinRT)
 ICALL(MARSHAL_45, "GetIDispatchForObjectInternal", ves_icall_System_Runtime_InteropServices_Marshal_GetIDispatchForObjectInternal)
@@ -697,9 +697,9 @@ ICALL(MARSHAL_47, "GetObjectForCCW", ves_icall_System_Runtime_InteropServices_Ma
 ICALL(MARSHAL_54, "GetRawIUnknownForComObjectNoAddRef", ves_icall_System_Runtime_InteropServices_Marshal_GetRawIUnknownForComObjectNoAddRef)
 ICALL(MARSHAL_48, "IsComObject", ves_icall_System_Runtime_InteropServices_Marshal_IsComObject)
 #endif
-ICALL(MARSHAL_12, "OffsetOf", ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf)
-ICALL(MARSHAL_13, "Prelink", ves_icall_System_Runtime_InteropServices_Marshal_Prelink)
-ICALL(MARSHAL_14, "PrelinkAll", ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll)
+HANDLES(ICALL(MARSHAL_12, "OffsetOf", ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf))
+HANDLES(ICALL(MARSHAL_13, "Prelink", ves_icall_System_Runtime_InteropServices_Marshal_Prelink))
+HANDLES(ICALL(MARSHAL_14, "PrelinkAll", ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll))
 HANDLES(ICALL(MARSHAL_15, "PtrToStringAnsi(intptr)", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi))
 ICALL(MARSHAL_16, "PtrToStringAnsi(intptr,int)", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringAnsi_len)
 ICALL(MARSHAL_17, "PtrToStringBSTR", ves_icall_System_Runtime_InteropServices_Marshal_PtrToStringBSTR)
@@ -716,7 +716,7 @@ ICALL(MARSHAL_23, "ReAllocHGlobal", ves_icall_System_Runtime_InteropServices_Mar
 ICALL(MARSHAL_49, "ReleaseComObjectInternal", ves_icall_System_Runtime_InteropServices_Marshal_ReleaseComObjectInternal)
 ICALL(MARSHAL_29, "ReleaseInternal", ves_icall_System_Runtime_InteropServices_Marshal_ReleaseInternal)
 #endif
-ICALL(MARSHAL_30, "SizeOf", ves_icall_System_Runtime_InteropServices_Marshal_SizeOf)
+HANDLES(ICALL(MARSHAL_30, "SizeOf", ves_icall_System_Runtime_InteropServices_Marshal_SizeOf))
 ICALL(MARSHAL_31, "StringToBSTR", ves_icall_System_Runtime_InteropServices_Marshal_StringToBSTR)
 ICALL(MARSHAL_32, "StringToHGlobalAnsi", ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalAnsi)
 ICALL(MARSHAL_33, "StringToHGlobalUni", ves_icall_System_Runtime_InteropServices_Marshal_StringToHGlobalUni)
index 67acdcb521040d6570080ebe4d068ba3bae0648e..79329f935382f75dd2d2ba9e3be1e2825d17d45e 100644 (file)
@@ -6170,99 +6170,92 @@ ves_icall_RuntimeType_MakePointerType (MonoReflectionTypeHandle ref_type, MonoEr
        return mono_type_get_object_handle (domain, &pklass->byval_arg, error);
 }
 
-ICALL_EXPORT MonoObject *
-ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
-                                                  MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
+ICALL_EXPORT MonoObjectHandle
+ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionTypeHandle ref_type, MonoObjectHandle target,
+                                                  MonoReflectionMethodHandle info, MonoBoolean throwOnBindFailure, MonoError *error)
 {
-       MonoError error;
-       MonoClass *delegate_class = mono_class_from_mono_type (type->type);
-       MonoObject *delegate;
+       MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
+       MonoClass *delegate_class = mono_class_from_mono_type (type);
        gpointer func;
-       MonoMethod *method = info->method;
+       MonoMethod *method = MONO_HANDLE_GETVAL (info, method);
        MonoMethodSignature *sig = mono_method_signature(method);
 
-       mono_class_init_checked (delegate_class, &error);
-       if (mono_error_set_pending_exception (&error))
-               return NULL;
+       mono_class_init_checked (delegate_class, error);
+       return_val_if_nok (error, NULL_HANDLE);
 
        if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
                /* FIXME improve this exception message */
-               mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
+               mono_error_set_execution_engine (error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
                                                 __func__,
                                                 "delegate_class->parent == mono_defaults.multicastdelegate_class");
-               mono_error_set_pending_exception (&error);
-               return NULL;
+               return NULL_HANDLE;
        }
 
        if (mono_security_core_clr_enabled ()) {
-               if (!mono_security_core_clr_ensure_delegate_creation (method, &error)) {
+               MonoError security_error;
+               if (!mono_security_core_clr_ensure_delegate_creation (method, &security_error)) {
                        if (throwOnBindFailure)
-                               mono_error_set_pending_exception (&error);
+                               mono_error_move (error, &security_error);
                        else
-                               mono_error_cleanup (&error);
-                       return NULL;
+                               mono_error_cleanup (&security_error);
+                       return NULL_HANDLE;
                }
        }
 
        if (sig->generic_param_count && method->wrapper_type == MONO_WRAPPER_NONE) {
                if (!method->is_inflated) {
-                       mono_set_pending_exception(mono_get_exception_argument("method", " Cannot bind to the target method because its signature differs from that of the delegate type"));
-                       return NULL;
+                       mono_error_set_argument (error, "method", " Cannot bind to the target method because its signature differs from that of the delegate type");
+                       return NULL_HANDLE;
                }
        }
 
-       delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
-       if (mono_error_set_pending_exception (&error))
-               return NULL;
+       MonoObjectHandle delegate = MONO_HANDLE_NEW (MonoObject, mono_object_new_checked (MONO_HANDLE_DOMAIN (ref_type), delegate_class, error));
+       return_val_if_nok (error, NULL_HANDLE);
 
        if (method_is_dynamic (method)) {
                /* Creating a trampoline would leak memory */
-               func = mono_compile_method_checked (method, &error);
-               if (mono_error_set_pending_exception (&error))
-                       return NULL;
+               func = mono_compile_method_checked (method, error);
+               return_val_if_nok (error, NULL_HANDLE);
        } else {
-               if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
-                       method = mono_object_get_virtual_method (target, method);
-               gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, &error);
-               if (mono_error_set_pending_exception (&error))
-                       return NULL;
+               if (!MONO_HANDLE_IS_NULL (target) && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_handle_class (target)) {
+                       method = mono_object_handle_get_virtual_method (target, method, error);
+                       return_val_if_nok (error, NULL_HANDLE);
+               }
+               gpointer trampoline = mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE, error);
+               return_val_if_nok (error, NULL_HANDLE);
                func = mono_create_ftnptr (mono_domain_get (), trampoline);
        }
 
-       mono_delegate_ctor_with_method (delegate, target, func, method, &error);
-       if (mono_error_set_pending_exception (&error))
-               return NULL;
+       mono_delegate_ctor_with_method (delegate, target, func, method, error);
+       return_val_if_nok (error, NULL_HANDLE);
        return delegate;
 }
 
-ICALL_EXPORT MonoMulticastDelegate *
-ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
+ICALL_EXPORT MonoMulticastDelegateHandle
+ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegateHandle delegate, MonoError *error)
 {
-       MonoError error;
-       MonoMulticastDelegate *ret;
+       error_init (error);
 
-       g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
+       MonoClass *klass = mono_handle_class (delegate);
+       g_assert (mono_class_has_parent (klass, mono_defaults.multicastdelegate_class));
 
-       ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
-       if (mono_error_set_pending_exception (&error))
-               return NULL;
+       MonoMulticastDelegateHandle ret = MONO_HANDLE_NEW (MonoMulticastDelegate,  mono_object_new_checked (MONO_HANDLE_DOMAIN (delegate), klass, error));
+       return_val_if_nok (error, MONO_HANDLE_CAST (MonoMulticastDelegate, NULL_HANDLE));
 
-       ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
+       MONO_HANDLE_SETVAL (MONO_HANDLE_CAST (MonoDelegate, ret), invoke_impl, gpointer, mono_runtime_create_delegate_trampoline (klass));
 
        return ret;
 }
 
-ICALL_EXPORT MonoReflectionMethod*
-ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
+ICALL_EXPORT MonoReflectionMethodHandle
+ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegateHandle delegate, MonoError *error)
 {
-       MonoReflectionMethod *ret = NULL;
-       MonoError error;
-       MonoMethod *m;
+       error_init (error);
 
-       m = mono_object_get_virtual_method (delegate->target, delegate->method);
-       ret = mono_method_get_object_checked (mono_domain_get (), m, m->klass, &error);
-       mono_error_set_pending_exception (&error);
-       return ret;
+       MonoObjectHandle delegate_target = MONO_HANDLE_NEW_GET (MonoObject, delegate, target);
+       MonoMethod *m = mono_object_handle_get_virtual_method (delegate_target, MONO_HANDLE_GETVAL (delegate, method), error);
+       return_val_if_nok (error, MONO_HANDLE_CAST (MonoReflectionMethod, NULL_HANDLE));
+       return mono_method_get_object_handle (mono_domain_get (), m, m->klass, error);
 }
 
 /* System.Buffer */
@@ -7508,38 +7501,34 @@ prelink_method (MonoMethod *method, MonoError *error)
                return;
        mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
        if (exc_class) {
-               mono_error_set_exception_instance (error,
-                       mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
+               mono_error_set_generic_error (error, "System", exc_class, "%s", exc_arg);
                return;
        }
        /* create the wrapper, too? */
 }
 
 ICALL_EXPORT void
-ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
+ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethodHandle method, MonoError *error)
 {
-       MonoError error;
+       error_init (error);
 
-       prelink_method (method->method, &error);
-       mono_error_set_pending_exception (&error);
+       prelink_method (MONO_HANDLE_GETVAL (method, method), error);
 }
 
 ICALL_EXPORT void
-ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
+ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionTypeHandle type, MonoError *error)
 {
-       MonoError error;
-       MonoClass *klass = mono_class_from_mono_type (type->type);
+       error_init (error);
+       MonoClass *klass = mono_class_from_mono_type (MONO_HANDLE_GETVAL (type, type));
        MonoMethod* m;
        gpointer iter = NULL;
 
-       mono_class_init_checked (klass, &error);
-       if (mono_error_set_pending_exception (&error))
-               return;
+       mono_class_init_checked (klass, error);
+       return_if_nok (error);
 
        while ((m = mono_class_get_methods (klass, &iter))) {
-               prelink_method (m, &error);
-               if (mono_error_set_pending_exception (&error))
-                       return;
+               prelink_method (m, error);
+               return_if_nok (error);
        }
 }
 
index b82e49d8ea51e9ae7701734751d53e6d7fe92e06..f60de81c46bdd63387cdb457671478449335dcdb 100644 (file)
@@ -89,7 +89,7 @@ static void ftnptr_eh_callback_default (guint32 gchandle);
 static MonoFtnPtrEHCallback ftnptr_eh_callback = ftnptr_eh_callback_default;
 
 static void
-delegate_hash_table_add (MonoDelegate *d);
+delegate_hash_table_add (MonoDelegateHandle d);
 
 static void
 delegate_hash_table_remove (MonoDelegate *d);
@@ -179,9 +179,15 @@ mono_string_to_byvalwstr (gpointer dst, MonoString *src, int size);
 gpointer
 mono_delegate_to_ftnptr (MonoDelegate *delegate);
 
+gpointer
+mono_delegate_handle_to_ftnptr (MonoDelegateHandle delegate, MonoError *error);
+
 MonoDelegate*
 mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn);
 
+MonoDelegateHandle
+mono_ftnptr_to_delegate_handle (MonoClass *klass, gpointer ftn, MonoError *error);
+
 gpointer
 mono_array_to_savearray (MonoArray *array);
 
@@ -431,25 +437,44 @@ mono_marshal_unlock_internal (void)
 
 /* This is a JIT icall, it sets the pending exception and return NULL on error */
 gpointer
-mono_delegate_to_ftnptr (MonoDelegate *delegate)
+mono_delegate_to_ftnptr (MonoDelegate *delegate_raw)
 {
+       HANDLE_FUNCTION_ENTER ();
        MonoError error;
+       MONO_HANDLE_DCL (MonoDelegate, delegate);
+       gpointer result = mono_delegate_handle_to_ftnptr (delegate, &error);
+       mono_error_set_pending_exception (&error);
+       HANDLE_FUNCTION_RETURN_VAL (result);
+}
+
+gpointer
+mono_delegate_handle_to_ftnptr (MonoDelegateHandle delegate, MonoError *error)
+{
+       HANDLE_FUNCTION_ENTER ();
+       gpointer result = NULL;
+       error_init (error);
        MonoMethod *method, *wrapper;
        MonoClass *klass;
        uint32_t target_handle = 0;
 
-       if (!delegate)
-               return NULL;
+       if (MONO_HANDLE_IS_NULL (delegate))
+               goto leave;
 
-       if (delegate->delegate_trampoline)
-               return delegate->delegate_trampoline;
+       if (MONO_HANDLE_GETVAL (delegate, delegate_trampoline)) {
+               result = MONO_HANDLE_GETVAL (delegate, delegate_trampoline);
+               goto leave;
+       }
 
-       klass = ((MonoObject *)delegate)->vtable->klass;
+       klass = mono_handle_class (delegate);
        g_assert (klass->delegate);
 
-       method = delegate->method;
-       if (delegate->method_is_virtual)
-               method = mono_object_get_virtual_method (delegate->target, method);
+       method = MONO_HANDLE_GETVAL (delegate, method);
+       if (MONO_HANDLE_GETVAL (delegate, method_is_virtual)) {
+               MonoObjectHandle delegate_target = MONO_HANDLE_NEW_GET (MonoObject, delegate, target);
+               method = mono_object_handle_get_virtual_method (delegate_target, method, error);
+               if (!is_ok (error))
+                       goto leave;
+       }
 
        if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) {
                const char *exc_class, *exc_arg;
@@ -458,38 +483,39 @@ mono_delegate_to_ftnptr (MonoDelegate *delegate)
                ftnptr = mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
                if (!ftnptr) {
                        g_assert (exc_class);
-                       mono_set_pending_exception (mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
-                       return NULL;
+                       mono_error_set_generic_error (error, "System", exc_class, "%s", exc_arg);
+                       goto leave;
                }
-               return ftnptr;
+               result = ftnptr;
+               goto leave;
        }
 
-       if (delegate->target) {
+       MonoObjectHandle delegate_target = MONO_HANDLE_NEW_GET (MonoObject, delegate, target);
+       if (!MONO_HANDLE_IS_NULL (delegate_target)) {
                /* Produce a location which can be embedded in JITted code */
-               target_handle = mono_gchandle_new_weakref (delegate->target, FALSE);
+               target_handle = mono_gchandle_new_weakref (MONO_HANDLE_RAW (delegate_target), FALSE); /* FIXME: a version of mono_gchandle_new_weakref that takes a coop handle */
        }
 
-       wrapper = mono_marshal_get_managed_wrapper (method, klass, target_handle, &error);
-       if (!is_ok (&error))
-               goto fail;
+       wrapper = mono_marshal_get_managed_wrapper (method, klass, target_handle, error);
+       if (!is_ok (error))
+               goto leave;
 
-       delegate->delegate_trampoline = mono_compile_method_checked (wrapper, &error);
-       if (!is_ok (&error))
-               goto fail;
+       MONO_HANDLE_SETVAL (delegate, delegate_trampoline, gpointer, mono_compile_method_checked (wrapper, error));
+       if (!is_ok (error))
+               goto leave;
 
        // Add the delegate to the delegate hash table
        delegate_hash_table_add (delegate);
 
        /* when the object is collected, collect the dynamic method, too */
-       mono_object_register_finalizer ((MonoObject*)delegate);
+       mono_object_register_finalizer ((MonoObject*) MONO_HANDLE_RAW (delegate));
 
-       return delegate->delegate_trampoline;
+       result = MONO_HANDLE_GETVAL (delegate, delegate_trampoline);
 
-fail:
-       if (target_handle != 0)
+leave:
+       if (!is_ok (error) && target_handle != 0)
                mono_gchandle_free (target_handle);
-       mono_error_set_pending_exception (&error);
-       return NULL;
+       HANDLE_FUNCTION_RETURN_VAL (result);
 }
 
 /* 
@@ -521,7 +547,7 @@ delegate_hash_table_remove (MonoDelegate *d)
 }
 
 static void
-delegate_hash_table_add (MonoDelegate *d)
+delegate_hash_table_add (MonoDelegateHandle d)
 {
        guint32 gchandle;
        guint32 old_gchandle;
@@ -529,14 +555,15 @@ delegate_hash_table_add (MonoDelegate *d)
        mono_marshal_lock ();
        if (delegate_hash_table == NULL)
                delegate_hash_table = delegate_hash_table_new ();
+       gpointer delegate_trampoline = MONO_HANDLE_GETVAL (d, delegate_trampoline);
        if (mono_gc_is_moving ()) {
-               gchandle = mono_gchandle_new_weakref ((MonoObject*)d, FALSE);
-               old_gchandle = GPOINTER_TO_UINT (g_hash_table_lookup (delegate_hash_table, d->delegate_trampoline));
-               g_hash_table_insert (delegate_hash_table, d->delegate_trampoline, GUINT_TO_POINTER (gchandle));
+               gchandle = mono_gchandle_new_weakref ((MonoObject*) MONO_HANDLE_RAW (d), FALSE);
+               old_gchandle = GPOINTER_TO_UINT (g_hash_table_lookup (delegate_hash_table, delegate_trampoline));
+               g_hash_table_insert (delegate_hash_table, delegate_trampoline, GUINT_TO_POINTER (gchandle));
                if (old_gchandle)
                        mono_gchandle_free (old_gchandle);
        } else {
-               g_hash_table_insert (delegate_hash_table, d->delegate_trampoline, d);
+               g_hash_table_insert (delegate_hash_table, delegate_trampoline, MONO_HANDLE_RAW (d));
        }
        mono_marshal_unlock ();
 }
@@ -590,12 +617,23 @@ parse_unmanaged_function_pointer_attr (MonoClass *klass, MonoMethodPInvoke *piin
 MonoDelegate*
 mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn)
 {
+       HANDLE_FUNCTION_ENTER ();
        MonoError error;
+       MonoDelegateHandle result = mono_ftnptr_to_delegate_handle (klass, ftn, &error);
+       mono_error_set_pending_exception (&error);
+       HANDLE_FUNCTION_RETURN_OBJ (result);
+}
+
+MonoDelegateHandle
+mono_ftnptr_to_delegate_handle (MonoClass *klass, gpointer ftn, MonoError *error)
+{
+       HANDLE_FUNCTION_ENTER ();
+       error_init (error);
        guint32 gchandle;
-       MonoDelegate *d;
+       MonoDelegateHandle d = MONO_HANDLE_NEW (MonoDelegate, NULL);
 
        if (ftn == NULL)
-               return NULL;
+               goto leave;
 
        mono_marshal_lock ();
        if (delegate_hash_table == NULL)
@@ -605,30 +643,26 @@ mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn)
                gchandle = GPOINTER_TO_UINT (g_hash_table_lookup (delegate_hash_table, ftn));
                mono_marshal_unlock ();
                if (gchandle)
-                       d = (MonoDelegate*)mono_gchandle_get_target (gchandle);
-               else
-                       d = NULL;
+                       MONO_HANDLE_ASSIGN (d, MONO_HANDLE_CAST (MonoDelegate, mono_gchandle_get_target_handle (gchandle)));
        } else {
-               d = (MonoDelegate *)g_hash_table_lookup (delegate_hash_table, ftn);
+               MONO_HANDLE_ASSIGN (d, MONO_HANDLE_NEW (MonoDelegate, g_hash_table_lookup (delegate_hash_table, ftn)));
                mono_marshal_unlock ();
        }
-       if (d == NULL) {
+       if (MONO_HANDLE_IS_NULL (d)) {
                /* This is a native function, so construct a delegate for it */
                MonoMethodSignature *sig;
                MonoMethod *wrapper;
                MonoMarshalSpec **mspecs;
                MonoMethod *invoke = mono_get_delegate_invoke (klass);
                MonoMethodPInvoke piinfo;
-               MonoObject *this_obj;
+               MonoObjectHandle  this_obj;
                int i;
 
                if (use_aot_wrappers) {
                        wrapper = mono_marshal_get_native_func_wrapper_aot (klass);
-                       this_obj = mono_value_box_checked (mono_domain_get (), mono_defaults.int_class, &ftn, &error);
-                       if (!is_ok (&error)) {
-                               mono_error_set_pending_exception (&error);
-                               return NULL;
-                       }
+                       this_obj = MONO_HANDLE_NEW (MonoObject, mono_value_box_checked (mono_domain_get (), mono_defaults.int_class, &ftn, error));
+                       if (!is_ok (error))
+                               goto leave;
                } else {
                        memset (&piinfo, 0, sizeof (piinfo));
                        parse_unmanaged_function_pointer_attr (klass, &piinfo);
@@ -640,7 +674,7 @@ mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn)
                        sig->hasthis = 0;
 
                        wrapper = mono_marshal_get_native_func_wrapper (klass->image, sig, &piinfo, mspecs, ftn);
-                       this_obj = NULL;
+                       this_obj = MONO_HANDLE_NEW (MonoObject, NULL);
 
                        for (i = mono_method_signature (invoke)->param_count; i >= 0; i--)
                                if (mspecs [i])
@@ -649,25 +683,24 @@ mono_ftnptr_to_delegate (MonoClass *klass, gpointer ftn)
                        g_free (sig);
                }
 
-               d = (MonoDelegate*)mono_object_new_checked (mono_domain_get (), klass, &error);
-               if (!mono_error_ok (&error)) {
-                       mono_error_set_pending_exception (&error);
-                       return NULL;
-               }
-               gpointer compiled_ptr = mono_compile_method_checked (wrapper, &error);
-               if (mono_error_set_pending_exception (&error))
-                       return NULL;
-               mono_delegate_ctor_with_method ((MonoObject*)d, this_obj, compiled_ptr, wrapper, &error);
-               if (mono_error_set_pending_exception (&error))
-                       return NULL;
-       }
+               MONO_HANDLE_ASSIGN (d, MONO_HANDLE_NEW (MonoDelegate, mono_object_new_checked (mono_domain_get (), klass, error)));
+               if (!is_ok (error))
+                       goto leave;
+               gpointer compiled_ptr = mono_compile_method_checked (wrapper, error);
+               if (!is_ok (error))
+                       goto leave;
 
-       if (d->object.vtable->domain != mono_domain_get ()) {
-               mono_set_pending_exception (mono_get_exception_not_supported ("Delegates cannot be marshalled from native code into a domain other than their home domain"));
-               return NULL;
+               mono_delegate_ctor_with_method (MONO_HANDLE_CAST (MonoObject, d), this_obj, compiled_ptr, wrapper, error);
+               if (!is_ok (error))
+                       goto leave;
        }
 
-       return d;
+       g_assert (!MONO_HANDLE_IS_NULL (d));
+       if (MONO_HANDLE_DOMAIN (d) != mono_domain_get ())
+               mono_error_set_not_supported (error, "Delegates cannot be marshalled from native code into a domain other than their home domain");
+
+leave:
+       HANDLE_FUNCTION_RETURN_REF (MonoDelegate, d);
 }
 
 void
@@ -11025,18 +11058,23 @@ ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void)
 }
 
 guint32 
-ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype)
+ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionTypeHandle rtype, MonoError *error)
 {
        MonoClass *klass;
        MonoType *type;
        guint32 layout;
 
-       MONO_CHECK_ARG_NULL (rtype, 0);
+       error_init (error);
+
+       if (MONO_HANDLE_IS_NULL (rtype)) {
+               mono_error_set_argument_null (error, "type", "");
+               return 0;
+       }
 
-       type = rtype->type;
+       type = MONO_HANDLE_GETVAL (rtype, type);
        klass = mono_class_from_mono_type (type);
        if (!mono_class_init (klass)) {
-               mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
+               mono_error_set_for_class_failure (error, klass);
                return 0;
        }
 
@@ -11045,13 +11083,7 @@ ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rty
        if (type->type == MONO_TYPE_PTR || type->type == MONO_TYPE_FNPTR) {
                return sizeof (gpointer);
        } else if (layout == TYPE_ATTRIBUTE_AUTO_LAYOUT) {
-               gchar *msg;
-               MonoException *exc;
-
-               msg = g_strdup_printf ("Type %s cannot be marshaled as an unmanaged structure.", klass->name);
-               exc = mono_get_exception_argument ("t", msg);
-               g_free (msg);
-               mono_set_pending_exception (exc);
+               mono_error_set_argument (error, "t", "Type %s cannot be marshaled as an unmanaged structure.", klass->name);
                return 0;
        }
 
@@ -11157,26 +11189,29 @@ ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer s
 }
 
 int
-ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name)
+ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionTypeHandle ref_type, MonoStringHandle field_name, MonoError *error)
 {
-       MonoError error;
-       MonoMarshalType *info;
-       MonoClass *klass;
-       char *fname;
-       int match_index = -1;
-       
-       MONO_CHECK_ARG_NULL (type, 0);
-       MONO_CHECK_ARG_NULL (field_name, 0);
-
-       fname = mono_string_to_utf8_checked (field_name, &error);
-       if (mono_error_set_pending_exception (&error))
+       error_init (error);
+       if (MONO_HANDLE_IS_NULL (ref_type)) {
+               mono_error_set_argument_null (error, "type", "");
                return 0;
-       klass = mono_class_from_mono_type (type->type);
+       }
+       if (MONO_HANDLE_IS_NULL (field_name)) {
+               mono_error_set_argument_null (error, "fieldName", "");
+               return 0;
+       }
+
+       char *fname = mono_string_handle_to_utf8 (field_name, error);
+       return_val_if_nok (error, 0);
+
+       MonoType *type = MONO_HANDLE_GETVAL (ref_type, type);
+       MonoClass *klass = mono_class_from_mono_type (type);
        if (!mono_class_init (klass)) {
-               mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
+               mono_error_set_for_class_failure (error, klass);
                return 0;
        }
 
+       int match_index = -1;
        while (klass && match_index == -1) {
                MonoClassField* field;
                int i = 0;
@@ -11198,21 +11233,14 @@ ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *t
        g_free (fname);
 
        if(match_index == -1) {
-               MonoException* exc;
-               gchar *tmp;
-
                /* Get back original class instance */
-               klass = mono_class_from_mono_type (type->type);
+               klass = mono_class_from_mono_type (type);
 
-               tmp = g_strdup_printf ("Field passed in is not a marshaled member of the type %s", klass->name);
-               exc = mono_get_exception_argument ("fieldName", tmp);
-               g_free (tmp);
-               mono_set_pending_exception ((MonoException*)exc);
+               mono_error_set_argument (error, "fieldName", "Field passed in is not a marshaled member of the type %s", klass->name);
                return 0;
        }
 
-       info = mono_marshal_load_type_info (klass);     
+       MonoMarshalType *info = mono_marshal_load_type_info (klass);
        return info->fields [match_index].offset;
 }
 
@@ -11438,22 +11466,24 @@ ves_icall_System_Runtime_InteropServices_Marshal_UnsafeAddrOfPinnedArrayElement
        return mono_array_addr_with_size_fast (arrayobj, mono_array_element_size (arrayobj->obj.vtable->klass), index);
 }
 
-MonoDelegate*
-ves_icall_System_Runtime_InteropServices_Marshal_GetDelegateForFunctionPointerInternal (void *ftn, MonoReflectionType *type)
+MonoDelegateHandle
+ves_icall_System_Runtime_InteropServices_Marshal_GetDelegateForFunctionPointerInternal (void *ftn, MonoReflectionTypeHandle type, MonoError *error)
 {
-       MonoClass *klass = mono_type_get_class (type->type);
+       error_init (error);
+       MonoClass *klass = mono_type_get_class (MONO_HANDLE_GETVAL (type, type));
        if (!mono_class_init (klass)) {
-               mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
+               mono_error_set_for_class_failure (error, klass);
                return NULL;
        }
 
-       return mono_ftnptr_to_delegate (klass, ftn);
+       return mono_ftnptr_to_delegate_handle (klass, ftn, error);
 }
 
 gpointer
-ves_icall_System_Runtime_InteropServices_Marshal_GetFunctionPointerForDelegateInternal (MonoDelegate *delegate)
+ves_icall_System_Runtime_InteropServices_Marshal_GetFunctionPointerForDelegateInternal (MonoDelegateHandle delegate, MonoError *error)
 {
-       return mono_delegate_to_ftnptr (delegate);
+       error_init (error);
+       return mono_delegate_handle_to_ftnptr (delegate, error);
 }
 
 /**
@@ -12337,9 +12367,9 @@ static MonoObjectHandle
 mono_icall_handle_new (gpointer rawobj)
 {
 #ifdef MONO_HANDLE_TRACK_OWNER
-       return mono_handle_new_full (rawobj, FALSE, "<marshal args>");
+       return mono_handle_new (rawobj, "<marshal args>");
 #else
-       return mono_handle_new_full (rawobj, FALSE);
+       return mono_handle_new (rawobj);
 #endif
 }
 
@@ -12347,8 +12377,8 @@ static MonoObjectHandle
 mono_icall_handle_new_interior (gpointer rawobj)
 {
 #ifdef MONO_HANDLE_TRACK_OWNER
-       return mono_handle_new_full (rawobj, TRUE, "<marshal args>");
+       return mono_handle_new_interior (rawobj, "<marshal args>");
 #else
-       return mono_handle_new_full (rawobj, TRUE);
+       return mono_handle_new_interior (rawobj);
 #endif
 }
index 57018b828d41dbe1d0ee050ce98a27161586be3e..657193859061b252a75605813143c38043dd4af0 100644 (file)
@@ -458,7 +458,7 @@ guint32
 ves_icall_System_Runtime_InteropServices_Marshal_GetLastWin32Error (void);
 
 guint32 
-ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionType *rtype);
+ves_icall_System_Runtime_InteropServices_Marshal_SizeOf (MonoReflectionTypeHandle rtype, MonoError *error);
 
 void
 ves_icall_System_Runtime_InteropServices_Marshal_StructureToPtr (MonoObject *obj, gpointer dst, MonoBoolean delete_old);
@@ -470,7 +470,7 @@ MonoObject *
 ves_icall_System_Runtime_InteropServices_Marshal_PtrToStructure_type (gpointer src, MonoReflectionType *type);
 
 int
-ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionType *type, MonoString *field_name);
+ves_icall_System_Runtime_InteropServices_Marshal_OffsetOf (MonoReflectionTypeHandle type, MonoStringHandle field_name, MonoError *error);
 
 gpointer
 ves_icall_System_Runtime_InteropServices_Marshal_StringToBSTR (MonoString *string);
@@ -514,11 +514,11 @@ ves_icall_System_Runtime_InteropServices_Marshal_FreeBSTR (void *ptr);
 void*
 ves_icall_System_Runtime_InteropServices_Marshal_UnsafeAddrOfPinnedArrayElement (MonoArray *arrayobj, int index);
 
-MonoDelegate*
-ves_icall_System_Runtime_InteropServices_Marshal_GetDelegateForFunctionPointerInternal (void *ftn, MonoReflectionType *type);
+MonoDelegateHandle
+ves_icall_System_Runtime_InteropServices_Marshal_GetDelegateForFunctionPointerInternal (void *ftn, MonoReflectionTypeHandle type, MonoError *error);
 
 gpointer
-ves_icall_System_Runtime_InteropServices_Marshal_GetFunctionPointerForDelegateInternal (MonoDelegate *delegate);
+ves_icall_System_Runtime_InteropServices_Marshal_GetFunctionPointerForDelegateInternal (MonoDelegateHandle delegate, MonoError *error);
 
 int
 ves_icall_System_Runtime_InteropServices_Marshal_AddRefInternal (gpointer pUnk);
index d2cf14781b077e8f00e6371770e1996bdb0c3f7f..3458232139c4d3a83dac251c024476ef30e19fd8 100644 (file)
@@ -61,6 +61,20 @@ g_slist_append_mempool (MonoMemPool *mp, GSList *list, gpointer data)
                return new_list;
 }
 
+static inline GList*
+g_list_append_mempool (MonoMemPool *mp, GList *list, gpointer data)
+{
+       GList *new_list;
+
+       new_list = (GList *) mono_mempool_alloc0 (mp, sizeof (GList));
+       new_list->data = data;
+       new_list->prev = g_list_last (list);
+       if (new_list->prev)
+               new_list->prev->next = new_list;
+
+       return list ? list : new_list;
+}
+
 char*
 mono_mempool_strdup_vprintf (MonoMemPool *pool, const char *format, va_list args);
 
index 59b1cc558995810ce60a38bd480b4515d0c5ccbc..7af56df2a72e2c59963beca822adaea5cf906cdd 100644 (file)
@@ -655,10 +655,10 @@ void
 mono_method_return_message_restore (MonoMethod *method, gpointer *params, MonoArray *out_args, MonoError *error);
 
 gboolean
-mono_delegate_ctor_with_method (MonoObject *this_obj, MonoObject *target, gpointer addr, MonoMethod *method, MonoError *error);
+mono_delegate_ctor_with_method (MonoObjectHandle this_obj, MonoObjectHandle target, gpointer addr, MonoMethod *method, MonoError *error);
 
 gboolean
-mono_delegate_ctor         (MonoObject *this_obj, MonoObject *target, gpointer addr, MonoError *error);
+mono_delegate_ctor         (MonoObjectHandle this_obj, MonoObjectHandle target, gpointer addr, MonoError *error);
 
 void*
 mono_class_get_allocation_ftn (MonoVTable *vtable, gboolean for_box, gboolean *pass_size_in_words);
@@ -768,12 +768,18 @@ struct _MonoDelegate {
        MonoBoolean method_is_virtual;
 };
 
+/* Safely access System.Delegate from native code */
+TYPED_HANDLE_DECL (MonoDelegate);
+
 typedef struct _MonoMulticastDelegate MonoMulticastDelegate;
 struct _MonoMulticastDelegate {
        MonoDelegate delegate;
        MonoArray *delegates;
 };
 
+/* Safely access System.MulticastDelegate from native code */
+TYPED_HANDLE_DECL (MonoMulticastDelegate);
+
 struct _MonoReflectionField {
        MonoObject object;
        MonoClass *klass;
index 92aa723f20a73f61c7ffec75631e46b6ee77ec94..d30f0413ac22f999432912235b52810720881244 100644 (file)
@@ -7817,43 +7817,44 @@ mono_print_unhandled_exception (MonoObject *exc)
  * On failure returns FALSE and sets \p error.
  */
 gboolean
-mono_delegate_ctor_with_method (MonoObject *this_obj, MonoObject *target, gpointer addr, MonoMethod *method, MonoError *error)
+mono_delegate_ctor_with_method (MonoObjectHandle this_obj, MonoObjectHandle target, gpointer addr, MonoMethod *method, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
        error_init (error);
-       MonoDelegate *delegate = (MonoDelegate *)this_obj;
+       MonoDelegateHandle delegate = MONO_HANDLE_CAST (MonoDelegate, this_obj);
 
-       g_assert (this_obj);
+       g_assert (!MONO_HANDLE_IS_NULL (this_obj));
        g_assert (addr);
 
-       g_assert (mono_class_has_parent (mono_object_class (this_obj), mono_defaults.multicastdelegate_class));
+       MonoClass *klass = mono_handle_class (this_obj);
+       g_assert (mono_class_has_parent (klass, mono_defaults.multicastdelegate_class));
 
        if (method)
-               delegate->method = method;
+               MONO_HANDLE_SETVAL (delegate, method, MonoMethod*, method);
 
        mono_stats.delegate_creations++;
 
 #ifndef DISABLE_REMOTING
-       if (target && mono_object_is_transparent_proxy (target)) {
+       if (!MONO_HANDLE_IS_NULL (target) && mono_class_is_transparent_proxy (mono_handle_class (target))) {
                g_assert (method);
                method = mono_marshal_get_remoting_invoke (method);
 #ifdef ENABLE_INTERPRETER
                //g_error ("need RuntimeMethod in method_ptr when using interpreter");
 #endif
-               delegate->method_ptr = mono_compile_method_checked (method, error);
+               MONO_HANDLE_SETVAL (delegate, method_ptr, gpointer, mono_compile_method_checked (method, error));
                return_val_if_nok (error, FALSE);
-               MONO_OBJECT_SETREF (delegate, target, target);
+               MONO_HANDLE_SET (delegate, target, target);
        } else
 #endif
        {
-               delegate->method_ptr = addr;
-               MONO_OBJECT_SETREF (delegate, target, target);
+               MONO_HANDLE_SETVAL (delegate, method_ptr, gpointer, addr);
+               MONO_HANDLE_SET (delegate, target, target);
        }
 
-       delegate->invoke_impl = callbacks.create_delegate_trampoline (delegate->object.vtable->domain, delegate->object.vtable->klass);
+       MONO_HANDLE_SETVAL (delegate, invoke_impl, gpointer, callbacks.create_delegate_trampoline (MONO_HANDLE_DOMAIN (delegate), mono_handle_class (delegate)));
        if (callbacks.init_delegate)
-               callbacks.init_delegate (delegate);
+               callbacks.init_delegate (MONO_HANDLE_RAW (delegate)); /* FIXME: update init_delegate callback to take a MonoDelegateHandle */
        return TRUE;
 }
 
@@ -7867,7 +7868,7 @@ mono_delegate_ctor_with_method (MonoObject *this_obj, MonoObject *target, gpoint
  * On failure returns FALSE and sets \p error.
  */
 gboolean
-mono_delegate_ctor (MonoObject *this_obj, MonoObject *target, gpointer addr, MonoError *error)
+mono_delegate_ctor (MonoObjectHandle this_obj, MonoObjectHandle target, gpointer addr, MonoError *error)
 {
        MONO_REQ_GC_UNSAFE_MODE;
 
index 44adebbc0039700d42ef2ce34d3f9fb5bfd90735..7cb7f291259d689cacb1404e3142f599b5118b1a 100644 (file)
@@ -893,6 +893,10 @@ mono_gc_clear_domain (MonoDomain * domain)
 
        sgen_clear_nursery_fragments ();
 
+       FOREACH_THREAD (info) {
+               mono_handle_stack_free_domain ((HandleStack*)info->client_info.info.handle_stack, domain);
+       } FOREACH_THREAD_END
+
        if (sgen_mono_xdomain_checks && domain != mono_get_root_domain ()) {
                sgen_scan_for_registered_roots_in_domain (domain, ROOT_TYPE_NORMAL);
                sgen_scan_for_registered_roots_in_domain (domain, ROOT_TYPE_WBARRIER);
index dbbc43bc6f86643cbc5ec0a5706a45490091dddc..df41473dfe896fbc0e1fbe07c82f20b00a360eeb 100644 (file)
@@ -65,7 +65,7 @@ mono_w32error_unix_to_win32 (guint32 error)
        case EIO: return ERROR_INVALID_HANDLE;
        case EINTR: return ERROR_IO_PENDING; /* best match I could find */
        case EPIPE: return ERROR_WRITE_FAULT;
-       case ELOOP: return ERROR_ACCESS_DENIED; /* Empirically found by testing desktop dotnet. */
+       case ELOOP: return ERROR_CANT_RESOLVE_FILENAME;
 
        default:
                g_error ("%s: unknown error (%d) \"%s\"", __FILE__, error, g_strerror (error));
index c8fb1717a52225a1bb1fda4186822b821fc2a1b0..439bdd81a2a0d366e5f1a3fec63ac8448cbfed49 100644 (file)
@@ -42,6 +42,7 @@
 #define ERROR_FILENAME_EXCED_RANGE 206
 #define ERROR_DIRECTORY            267
 #define ERROR_IO_PENDING           997
+#define ERROR_CANT_RESOLVE_FILENAME 1921
 #define ERROR_ENCRYPTION_FAILED    6000
 #define WSAEINTR                   10004
 #define WSAEBADF                   10009
index f6e4d2df5138873927882d9bd3cda436dcba411b..6fcb0f691f19ed0ec8c362698b4ee38fe6893e9a 100644 (file)
@@ -2518,7 +2518,6 @@ gboolean mono_w32file_delete(const gunichar2 *name)
        gchar *filename;
        gint retval;
        gboolean ret = FALSE;
-       guint32 attrs;
 #if 0
        struct stat statbuf;
        FileShare *shareinfo;
@@ -2539,14 +2538,6 @@ gboolean mono_w32file_delete(const gunichar2 *name)
                return(FALSE);
        }
 
-       attrs = mono_w32file_get_attributes (name);
-       if (attrs == INVALID_FILE_ATTRIBUTES) {
-               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_IO_LAYER, "%s: file attributes error", __func__);
-               /* Error set by mono_w32file_get_attributes() */
-               g_free (filename);
-               return(FALSE);
-       }
-
 #if 0
        /* Check to make sure sharing allows us to open the file for
         * writing.  See bug 323389.
@@ -3748,7 +3739,7 @@ mono_w32file_get_attributes (const gunichar2 *name)
        }
 
        result = _wapi_stat (utf8_name, &buf);
-       if (result == -1 && errno == ENOENT) {
+       if (result == -1 && (errno == ENOENT || errno == ELOOP)) {
                /* Might be a dangling symlink... */
                result = _wapi_lstat (utf8_name, &buf);
        }
index 70b36ed2fa36feb4b22bd3579f3dc6e551a35207..75d90df2ed919996d24da13192ded7818e02f240 100644 (file)
@@ -12,6 +12,7 @@
 #include <pthread.h>
 #include <string.h>
 #include <stdlib.h>
+#include <sys/types.h>
 #include <sys/socket.h>
 #ifdef HAVE_SYS_IOCTL_H
 #include <sys/ioctl.h>
@@ -27,7 +28,6 @@
 #endif
 #include <errno.h>
 #include <fcntl.h>
-#include <sys/types.h>
 #ifdef HAVE_SYS_UIO_H
 #include <sys/uio.h>
 #endif
index e0db07a52b4a8042be12b8a32a6e8b42ae7826e1..a08d93b4137fe71b2f60d77b25010a51bd3d5638 100755 (executable)
@@ -401,6 +401,9 @@ interp_sources =    \
        interp/mintops.def      \
        interp/mintops.c        \
        interp/transform.c
+else
+interp_sources = \
+       interp/interp-stubs.c
 endif
 
 if ENABLE_LLVM
@@ -502,6 +505,8 @@ test_sources =                      \
        aot-tests.cs \
        gc-test.cs \
        gshared.cs \
+       unaligned.cs    \
+       MemoryIntrinsics.il     \
        mixed.cs
 
 if NACL_CODEGEN
@@ -521,6 +526,7 @@ regtests_UNIVERSAL = \
        devirtualization.exe \
        generics.exe \
        basic-simd.exe \
+       unaligned.exe   \
        basic-vectors.exe
 
 if NACL_CODEGEN
@@ -654,6 +660,9 @@ nacl.exe: nacl.cs TestDriver.dll
 generics.exe: generics.cs TestDriver.dll generics-variant-types.dll
        $(MCS) -out:$@ $(CSFLAGS) $< -r:TestDriver.dll -r:generics-variant-types.dll -r:$(CLASS)/System.Core.dll
 
+unaligned.exe: unaligned.cs TestDriver.dll MemoryIntrinsics.dll
+       $(MCS) -out:$@ $(CSFLAGS) $< -r:TestDriver.dll -r:MemoryIntrinsics.dll
+
 %.exe: %.cs TestDriver.dll
        $(MCS) -out:$@ $(CSFLAGS) $< -r:TestDriver.dll
 
@@ -666,6 +675,9 @@ TestDriver.dll: $(srcdir)/TestDriver.cs $(srcdir)/TestHelpers.cs
 generics-variant-types.dll: generics-variant-types.il
        $(ILASM) -dll -output=$@ $<
 
+MemoryIntrinsics.dll: MemoryIntrinsics.il
+       $(ILASM) -dll -output=$@ $<
+
 if NACL_CODEGEN
 GENMDESC_OPTS=--nacl
 else !NACL_CODEGEN
@@ -770,6 +782,7 @@ gsharedvtcheck:
        $(MAKE) fullaotcheck GSHAREDVT=1
 
 fullaot_regtests = $(regtests) aot-tests.exe $(if $(GSHAREDVT),gshared.exe)
+fullaot_testing_deps = generics-variant-types.dll TestDriver.dll MemoryIntrinsics.dll
 
 FULLAOT_LIBS_UNIVERSAL = \
        mscorlib.dll \
@@ -795,17 +808,18 @@ FULLAOT_LIBS_DISABLED += \
        System.Configuration.dll
 endif
 
+
 FULLAOT_LIBS = $(filter-out $(FULLAOT_LIBS_DISABLED),$(FULLAOT_LIBS_UNIVERSAL))
 
 FULLAOT_TMP_DIR=$(top_builddir)/mono/mini/fullaot-tmp
 
 # This currently only works on amd64/arm
-fullaotcheck: $(mono) $(fullaot_regtests)
+fullaotcheck: $(mono) $(fullaot_regtests) $(fullaot_testing_deps)
        rm -rf $(FULLAOT_TMP_DIR)
        mkdir $(FULLAOT_TMP_DIR)
        $(MAKE) fullaot-libs AOT_FLAGS="full,$(MONO_FULLAOT_ADDITIONAL_ARGS)$(INVARIANT_AOT_OPTIONS)" GSHAREDVT=$(GSHAREDVT)
-       cp $(regtests) $(fullaot_regtests) generics-variant-types.dll TestDriver.dll $(FULLAOT_TMP_DIR)/
-       MONO_PATH=$(FULLAOT_TMP_DIR) $(top_builddir)/runtime/mono-wrapper $(MOBILE_RUNTIME_ARG) $(LLVM_AOT_RUNTIME_OPTS) $(GSHAREDVT_RUNTIME_OPTS) --aot="full,$(MONO_FULLAOT_ADDITIONAL_ARGS)$(INVARIANT_AOT_OPTIONS)" $(FULLAOT_TMP_DIR)/{generics-variant-types.dll,TestDriver.dll,*.exe} || exit 1
+       cp $(regtests) $(fullaot_regtests) $(fullaot_testing_deps) $(FULLAOT_TMP_DIR)/
+       MONO_PATH=$(FULLAOT_TMP_DIR) $(top_builddir)/runtime/mono-wrapper $(MOBILE_RUNTIME_ARG) $(LLVM_AOT_RUNTIME_OPTS) $(GSHAREDVT_RUNTIME_OPTS) --aot="full,$(MONO_FULLAOT_ADDITIONAL_ARGS)$(INVARIANT_AOT_OPTIONS)" $(FULLAOT_TMP_DIR)/{*.dll,*.exe} || exit 1
        ln -s $(if $(MONO_EXECUTABLE),$(MONO_EXECUTABLE),$$PWD/mono) $(FULLAOT_TMP_DIR)/
        for i in $(fullaot_regtests); do echo $$i; MONO_PATH=$(FULLAOT_TMP_DIR) $(top_builddir)/runtime/mono-wrapper $(MOBILE_RUNTIME_ARG) --full-aot $(FULLAOT_TMP_DIR)/$$i --exclude '!FULLAOT' $(ARCH_FULLAOT_EXCLUDE) || exit 1; done
 
@@ -827,8 +841,8 @@ llvmonlycheck: mono $(llvmonly_regtests)
        rm -rf fullaot-tmp
        mkdir fullaot-tmp
        $(MAKE) fullaot-libs AOT_FLAGS="llvmonly,$(MONO_FULLAOT_ADDITIONAL_ARGS)$(INVARIANT_AOT_OPTIONS)"
-       cp $(llvmonly_regtests) generics-variant-types.dll TestDriver.dll fullaot-tmp/
-       MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper  $(MOBILE_RUNTIME_ARG) --aot=llvmonly fullaot-tmp/{generics-variant-types.dll,TestDriver.dll,*.exe} || exit 1
+       cp $(llvmonly_regtests) $(fullaot_testing_deps) fullaot-tmp/
+       MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper  $(MOBILE_RUNTIME_ARG) --aot=llvmonly fullaot-tmp/{*.dll,*.exe} || exit 1
        ln -s $$PWD/mono fullaot-tmp/
        for i in $(llvmonly_regtests); do echo $$i; MONO_PATH=fullaot-tmp $(top_builddir)/runtime/mono-wrapper $(MOBILE_RUNTIME_ARG) --llvmonly fullaot-tmp/$$i --exclude '!BITCODE' || exit 1; done
 
diff --git a/mono/mini/MemoryIntrinsics.il b/mono/mini/MemoryIntrinsics.il
new file mode 100644 (file)
index 0000000..dd4c9b5
--- /dev/null
@@ -0,0 +1,180 @@
+.assembly extern mscorlib
+{
+       .publickeytoken = (B7 7A 5C 56 19 34 E0 89 )
+       .ver 4:0:0:0
+}
+
+.assembly 'MemoryIntrinsics'
+{
+       .custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78  63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 )
+       .hash algorithm 0x00008004
+       .ver 0:0:0:0
+}
+.module 'instrics-lib.dll'
+.imagebase 0x00400000
+.file alignment 0x00000200
+.stackreserve 0x00100000
+.subsystem 0x0003
+.corflags 0x00000001
+
+.namespace Mono {
+       .class public abstract auto ansi sealed beforefieldinit Intrinsics extends [mscorlib]System.Object
+       {
+               .method public hidebysig static void  Cpobj<T>(void* 'to', void* from) cil managed
+               {
+                       ldarg.0
+                       ldarg.1
+                       cpobj !!T
+                       ret
+               }
+
+               .method public hidebysig static !!T Ldobj<T>(void* 'from') cil managed
+               {
+                       ldarg.0
+                       ldobj !!T
+                       ret
+               }
+
+               .method public hidebysig static void Stobj<T>(void* 'to', !!T 'value') cil managed
+               {
+                       ldarg.0
+                       ldarg.1
+                       stobj !!T
+                       ret
+               }
+
+               .method public hidebysig static void LdobjStObjPair<T>(void* 'to', void* 'from') cil managed
+               {
+                       ldarg.0
+                       ldarg.1
+                       ldobj !!T
+                       stobj !!T
+                       ret
+               }
+
+               .method public hidebysig static void Cpblk(void* 'to', void* 'from', int32 size) cil managed
+               {
+                       ldarg.0
+                       ldarg.1
+                       ldarg.2
+                       cpblk
+                       ret
+               }
+
+               .method public hidebysig static void Initblk<T>(void* 'to', int32 'value', int32 'size') cil managed
+               {
+                       ldarg.0
+                       ldarg.1
+                       ldarg.2
+                       initblk
+                       ret
+               }
+
+               //Unaligned intrinsics
+               .method public hidebysig static void UnalignedCpobj<T>(void* 'to', void* from) cil managed
+               {
+                       ldarg.0
+                       ldarg.1
+                       unaligned. 1
+                       cpobj !!T
+                       ret
+               }
+
+               .method public hidebysig static !!T UnalignedLdobj<T>(void* 'from') cil managed
+               {
+                       ldarg.0
+                       unaligned. 1
+                       ldobj !!T
+                       ret
+               }
+
+               .method public hidebysig static void UnalignedStobj<T>(void* 'to', !!T 'value') cil managed
+               {
+                       ldarg.0
+                       ldarg.1
+                       unaligned. 1
+                       stobj !!T
+                       ret
+               }
+
+               .method public hidebysig static void UnalignedLdobjStObjPair<T>(void* 'to', void* 'from') cil managed
+               {
+                       ldarg.0
+                       ldarg.1
+                       unaligned. 1
+                       ldobj !!T
+                       stobj !!T
+                       ret
+               }
+
+               .method public hidebysig static void UnalignedCpblk(void* 'to', void* 'from', int32 size) cil managed
+               {
+                       ldarg.0
+                       ldarg.1
+                       ldarg.2
+                       unaligned. 1
+                       cpblk
+                       ret
+               }
+
+               .method public hidebysig static void UnalignedInit(void* 'to', int32 'value', int32 'size') cil managed
+               {
+                       ldarg.0
+                       ldarg.1
+                       ldarg.2
+                       unaligned. 1
+                       initblk
+                       ret
+               }
+
+               //Unaligned ldind
+               .method public hidebysig static int16 UnalignedLdInd2(void* 'from') cil managed
+               {
+                       ldarg.0
+                       unaligned. 1
+                       ldind.i2
+                       ret
+               }
+
+               .method public hidebysig static int32 UnalignedLdInd4(void* 'from') cil managed
+               {
+                       ldarg.0
+                       unaligned. 1
+                       ldind.i4
+                       ret
+               }
+
+               .method public hidebysig static int64 UnalignedLdInd8(void* 'from') cil managed
+               {
+                       ldarg.0
+                       unaligned. 1
+                       ldind.i8
+                       ret
+               }
+
+               .method public hidebysig static float32 UnalignedLdIndR4(void* 'from') cil managed
+               {
+                       ldarg.0
+                       unaligned. 1
+                       ldind.r4
+                       ret
+               }
+
+               .method public hidebysig static float64 UnalignedLdIndR8(void* 'from') cil managed
+               {
+                       ldarg.0
+                       unaligned. 1
+                       ldind.r8
+                       ret
+               }
+
+               .method public hidebysig static native int UnalignedLdIndI(void* 'from') cil managed
+               {
+                       ldarg.0
+                       unaligned. 1
+                       ldind.i
+                       ret
+               }
+
+       }
+}
index 782106c45e17b519200a104fc6a09695e0e22758..30ef9a64ad7bc9628a0e2a5a52c7306b469dd6d1 100644 (file)
@@ -3941,9 +3941,11 @@ load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoM
                                        if (!method)
                                                return NULL;
                                }
-                               full_name = mono_method_full_name (method, TRUE);
-                               mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT: NOT FOUND: %s.", full_name);
-                               g_free (full_name);
+                               if (!(method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL)) {
+                                       full_name = mono_method_full_name (method, TRUE);
+                                       mono_trace (G_LOG_LEVEL_DEBUG, MONO_TRACE_AOT, "AOT: NOT FOUND: %s.", full_name);
+                                       g_free (full_name);
+                               }
                        }
                        return NULL;
                }
index c639fa9e756e5c095b0e73f81b1c78b94651d6a8..bfdddb37547e5dac5d9f4f094b1084d87b359826 100644 (file)
 #include <mono/utils/mono-threads.h>
 #include <mono/utils/networking.h>
 #include <mono/utils/mono-proclib.h>
+#include <mono/utils/w32api.h>
 #include "debugger-agent.h"
 #include "mini.h"
 #include "seq-points.h"
-#include <mono/utils/w32api.h>
+#include "interp/interp.h"
 
 /*
  * On iOS we can't use System.Environment.Exit () as it will do the wrong
@@ -137,6 +138,7 @@ typedef struct
        MonoContext ctx;
        MonoDebugMethodJitInfo *jit;
        MonoJitInfo *ji;
+       MonoInterpFrameHandle interp_frame;
        int flags;
        mgreg_t *reg_locations [MONO_MAX_IREGS];
        /*
@@ -2480,6 +2482,35 @@ static void invoke_method (void);
  * SUSPEND/RESUME
  */
 
+static MonoJitInfo*
+get_top_method_ji (gpointer ip, MonoDomain **domain, gpointer *out_ip)
+{
+       MonoJitInfo *ji;
+
+       if (out_ip)
+               *out_ip = ip;
+
+       ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, domain);
+       if (!ji) {
+               /* Could be an interpreter method */
+
+               MonoLMF *lmf = mono_get_lmf ();
+               MonoInterpFrameHandle *frame;
+
+               g_assert (((guint64)lmf->previous_lmf) & 2);
+               MonoLMFExt *ext = (MonoLMFExt*)lmf;
+
+               g_assert (ext->interp_exit);
+               frame = ext->interp_exit_data;
+               ji = mono_interp_frame_get_jit_info (frame);
+               if (domain)
+                       *domain = mono_domain_get ();
+               if (out_ip)
+                       *out_ip = mono_interp_frame_get_ip (frame);
+       }
+       return ji;
+}
+
 /*
  * save_thread_context:
  *
@@ -2619,13 +2650,23 @@ thread_interrupt (DebuggerTlsData *tls, MonoThreadInfo *info, MonoJitInfo *ji)
                         * suspended when it returns to managed code, so the parent's ctx should
                         * remain valid.
                         */
+                       MonoThreadUnwindState *state = mono_thread_info_get_suspend_state (info);
+
                        data.last_frame_set = FALSE;
-                       mono_get_eh_callbacks ()->mono_walk_stack_with_state (get_last_frame, mono_thread_info_get_suspend_state (info), MONO_UNWIND_SIGNAL_SAFE, &data);
+                       mono_get_eh_callbacks ()->mono_walk_stack_with_state (get_last_frame, state, MONO_UNWIND_SIGNAL_SAFE, &data);
                        if (data.last_frame_set) {
                                gpointer jit_tls = ((MonoThreadInfo*)tls->thread->thread_info)->jit_data;
 
                                memcpy (&tls->async_last_frame, &data.last_frame, sizeof (StackFrameInfo));
 
+                               if (data.last_frame.type == FRAME_TYPE_INTERP_TO_MANAGED) {
+                                       /*
+                                        * Store the current lmf instead of the parent one, since that
+                                        * contains the interp exit data.
+                                        */
+                                       data.lmf = state->unwind_data [MONO_UNWIND_DATA_LMF];
+                               }
+
                                copy_unwind_state_from_frame_data (&tls->async_state, &data, jit_tls);
                                copy_unwind_state_from_frame_data (&tls->context, &data, jit_tls);
                        } else {
@@ -2751,8 +2792,8 @@ process_suspend (DebuggerTlsData *tls, MonoContext *ctx)
                return;
        }
 
-       ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, NULL);
-
+       ji = get_top_method_ji (ip, NULL, NULL);
+       g_assert (ji);
        /* Can't suspend in these methods */
        method = jinfo_get_method (ji);
        if (method->klass == mono_defaults.string_class && (!strcmp (method->name, "memset") || strstr (method->name, "memcpy")))
@@ -3051,7 +3092,7 @@ process_frame (StackFrameInfo *info, MonoContext *ctx, gpointer user_data)
        SeqPoint sp;
        int flags = 0;
 
-       if (info->type != FRAME_TYPE_MANAGED) {
+       if (info->type != FRAME_TYPE_MANAGED && info->type != FRAME_TYPE_INTERP) {
                if (info->type == FRAME_TYPE_DEBUGGER_INVOKE) {
                        /* Mark the last frame as an invoke frame */
                        if (ud->frames)
@@ -3104,6 +3145,7 @@ process_frame (StackFrameInfo *info, MonoContext *ctx, gpointer user_data)
        frame->native_offset = info->native_offset;
        frame->flags = flags;
        frame->ji = info->ji;
+       frame->interp_frame = info->interp_frame;
        if (info->reg_locations)
                memcpy (frame->reg_locations, info->reg_locations, MONO_MAX_IREGS * sizeof (mgreg_t*));
        if (ctx) {
@@ -4096,7 +4138,7 @@ jit_end (MonoProfiler *prof, MonoMethod *method, MonoJitInfo *jinfo, int result)
 
        send_type_load (method->klass);
 
-       if (!result)
+       if (!result && jinfo)
                add_pending_breakpoints (method, jinfo);
 }
 
@@ -4229,11 +4271,15 @@ insert_breakpoint (MonoSeqPointInfo *seq_points, MonoDomain *domain, MonoJitInfo
        if (it.seq_point.native_offset == SEQ_POINT_NATIVE_OFFSET_DEAD_CODE) {
                DEBUG_PRINTF (1, "[dbg] Attempting to insert seq point at dead IL offset %d, ignoring.\n", (int)bp->il_offset);
        } else if (count == 0) {
+               if (ji->is_interp) {
+                       mono_interp_set_breakpoint (ji, inst->ip);
+               } else {
 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
-               mono_arch_set_breakpoint (ji, inst->ip);
+                       mono_arch_set_breakpoint (ji, inst->ip);
 #else
-               NOT_IMPLEMENTED;
+                       NOT_IMPLEMENTED;
 #endif
+               }
        }
 
        DEBUG_PRINTF (1, "[dbg] Inserted breakpoint at %s:[il=0x%x,native=0x%x] [%p](%d).\n", mono_method_full_name (jinfo_get_method (ji), TRUE), (int)it.seq_point.il_offset, (int)it.seq_point.native_offset, inst->ip, count);
@@ -4255,7 +4301,10 @@ remove_breakpoint (BreakpointInstance *inst)
        g_assert (count > 0);
 
        if (count == 1 && inst->native_offset != SEQ_POINT_NATIVE_OFFSET_DEAD_CODE) {
-               mono_arch_clear_breakpoint (ji, ip);
+               if (ji->is_interp)
+                       mono_interp_clear_breakpoint (ji, ip);
+               else
+                       mono_arch_clear_breakpoint (ji, ip);
                DEBUG_PRINTF (1, "[dbg] Clear breakpoint at %s [%p].\n", mono_method_full_name (jinfo_get_method (ji), TRUE), ip);
        }
 #else
@@ -4372,12 +4421,15 @@ set_bp_in_method (MonoDomain *domain, MonoMethod *method, MonoSeqPointInfo *seq_
                /* Might be AOTed code */
                mono_class_init (method->klass);
                code = mono_aot_get_method_checked (domain, method, &oerror);
-               g_assert (code);
-               mono_error_assert_ok (&oerror);
-               ji = mono_jit_info_table_find (domain, (char *)code);
+               if (code) {
+                       mono_error_assert_ok (&oerror);
+                       ji = mono_jit_info_table_find (domain, (char *)code);
+               } else {
+                       /* Might be interpreted */
+                       ji = mono_interp_find_jit_info (domain, method);
+               }
                g_assert (ji);
        }
-       g_assert (code);
 
        insert_breakpoint (seq_points, domain, ji, bp, error);
 }
@@ -4636,16 +4688,15 @@ ss_update (SingleStepReq *req, MonoJitInfo *ji, SeqPoint *sp, DebuggerTlsData *t
                }
        }
 
-       MonoDebugMethodAsyncInfo* asyncMethod = mono_debug_lookup_method_async_debug_info (method);
-       if (asyncMethod) {
-               for (int i = 0; i < asyncMethod->num_awaits; i++)
-               {
-                       if (asyncMethod->yield_offsets[i] == sp->il_offset || asyncMethod->resume_offsets[i] == sp->il_offset) {
-                               mono_debug_free_method_async_debug_info (asyncMethod);
+       MonoDebugMethodAsyncInfo* async_method = mono_debug_lookup_method_async_debug_info (method);
+       if (async_method) {
+               for (int i = 0; i < async_method->num_awaits; i++) {
+                       if (async_method->yield_offsets[i] == sp->il_offset || async_method->resume_offsets[i] == sp->il_offset) {
+                               mono_debug_free_method_async_debug_info (async_method);
                                return FALSE;
                        }
                }
-               mono_debug_free_method_async_debug_info (asyncMethod);
+               mono_debug_free_method_async_debug_info (async_method);
        }
 
        if (req->size != STEP_SIZE_LINE)
@@ -4756,7 +4807,7 @@ get_notify_debugger_of_wait_completion_method ()
 }
 
 static void
-process_breakpoint_inner (DebuggerTlsData *tls, gboolean from_signal)
+process_breakpoint (DebuggerTlsData *tls, gboolean from_signal)
 {
        MonoJitInfo *ji;
        guint8 *ip;
@@ -4777,11 +4828,27 @@ process_breakpoint_inner (DebuggerTlsData *tls, gboolean from_signal)
 
        ip = (guint8 *)MONO_CONTEXT_GET_IP (ctx);
        ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, NULL);
+
+       if (!ji) {
+               /* Interpreter */
+               // FIXME: Pass a flag instead to detect this
+               MonoLMF *lmf = mono_get_lmf ();
+               MonoInterpFrameHandle *frame;
+
+               g_assert (((guint64)lmf->previous_lmf) & 2);
+               MonoLMFExt *ext = (MonoLMFExt*)lmf;
+
+               g_assert (ext->interp_exit);
+               frame = ext->interp_exit_data;
+               ji = mono_interp_frame_get_jit_info (frame);
+               ip = mono_interp_frame_get_ip (frame);
+       }
+
        g_assert (ji && !ji->is_trampoline);
        method = jinfo_get_method (ji);
 
        /* Compute the native offset of the breakpoint from the ip */
-       native_offset = ip - (guint8*)ji->code_start;   
+       native_offset = ip - (guint8*)ji->code_start;
 
        /* 
         * Skip the instruction causing the breakpoint signal.
@@ -4936,9 +5003,9 @@ process_signal_event (void (*func) (DebuggerTlsData*, gboolean))
 }
 
 static void
-process_breakpoint (void)
+process_breakpoint_from_signal (void)
 {
-       process_signal_event (process_breakpoint_inner);
+       process_signal_event (process_breakpoint);
 }
 
 static void
@@ -4980,19 +5047,30 @@ mono_debugger_agent_breakpoint_hit (void *sigctx)
         * problems, like the original signal is disabled, libgc can't handle altstack, etc.
         * So set up the signal context to return to the real breakpoint handler function.
         */
-       resume_from_signal_handler (sigctx, process_breakpoint);
+       resume_from_signal_handler (sigctx, process_breakpoint_from_signal);
 }
 
+typedef struct {
+       gboolean found;
+       MonoContext *ctx;
+} UserBreakCbData;
+
 static gboolean
-user_break_cb (StackFrameInfo *frame, MonoContext *ctx, gpointer data)
+user_break_cb (StackFrameInfo *frame, MonoContext *ctx, gpointer user_data)
 {
+       UserBreakCbData *data = user_data;
+
+       if (frame->type == FRAME_TYPE_INTERP_TO_MANAGED) {
+               data->found = TRUE;
+               return TRUE;
+       }
        if (frame->managed) {
-               *(MonoContext*)data = *ctx;
+               data->found = TRUE;
+               *data->ctx = *ctx;
 
                return TRUE;
-       } else {
-               return FALSE;
        }
+       return FALSE;
 }
 
 /*
@@ -5005,11 +5083,15 @@ mono_debugger_agent_user_break (void)
                MonoContext ctx;
                int suspend_policy;
                GSList *events;
+               UserBreakCbData data;
+
+               memset (&data, 0, sizeof (UserBreakCbData));
+               data.ctx = &ctx;
 
                /* Obtain a context */
                MONO_CONTEXT_SET_IP (&ctx, NULL);
-               mono_walk_stack_with_ctx (user_break_cb, NULL, (MonoUnwindOptions)0, &ctx);
-               g_assert (MONO_CONTEXT_GET_IP (&ctx) != NULL);
+               mono_walk_stack_with_ctx (user_break_cb, NULL, (MonoUnwindOptions)0, &data);
+               g_assert (data.found);
 
                mono_loader_lock ();
                events = create_event_list (EVENT_KIND_USER_BREAK, NULL, NULL, NULL, &suspend_policy);
@@ -5051,8 +5133,6 @@ process_single_step_inner (DebuggerTlsData *tls, gboolean from_signal)
        SeqPoint sp;
        MonoSeqPointInfo *info;
 
-       ip = (guint8 *)MONO_CONTEXT_GET_IP (ctx);
-
        /* Skip the instruction causing the single step */
        if (from_signal)
                mono_arch_skip_single_step (ctx);
@@ -5072,14 +5152,15 @@ process_single_step_inner (DebuggerTlsData *tls, gboolean from_signal)
        if (mono_thread_internal_current () != ss_req->thread)
                return;
 
-       if (log_level > 0) {
-               ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, &domain);
+       ip = (guint8 *)MONO_CONTEXT_GET_IP (ctx);
+
+       ji = get_top_method_ji (ip, &domain, (gpointer*)&ip);
+       g_assert (ji && !ji->is_trampoline);
 
+       if (log_level > 0) {
                DEBUG_PRINTF (1, "[%p] Single step event (depth=%s) at %s (%p)[0x%x], sp %p, last sp %p\n", (gpointer) (gsize) mono_native_thread_id_get (), ss_depth_to_string (ss_req->depth), mono_method_full_name (jinfo_get_method (ji), TRUE), MONO_CONTEXT_GET_IP (ctx), (int)((guint8*)MONO_CONTEXT_GET_IP (ctx) - (guint8*)ji->code_start), MONO_CONTEXT_GET_SP (ctx), ss_req->last_sp);
        }
 
-       ji = mini_jit_info_table_find (mono_domain_get (), (char*)ip, &domain);
-       g_assert (ji && !ji->is_trampoline);
        method = jinfo_get_method (ji);
        g_assert (method);
 
@@ -5114,8 +5195,10 @@ process_single_step_inner (DebuggerTlsData *tls, gboolean from_signal)
         * The ip points to the instruction causing the single step event, which is before
         * the offset recorded in the seq point map, so find the next seq point after ip.
         */
-       if (!mono_find_next_seq_point_for_native_offset (domain, method, (guint8*)ip - (guint8*)ji->code_start, &info, &sp))
+       if (!mono_find_next_seq_point_for_native_offset (domain, method, (guint8*)ip - (guint8*)ji->code_start, &info, &sp)) {
+               g_assert_not_reached ();
                return;
+       }
 
        il_offset = sp.il_offset;
 
@@ -5230,7 +5313,7 @@ debugger_agent_breakpoint_from_context (MonoContext *ctx)
        mono_thread_state_init_from_monoctx (&tls->restore_state, ctx);
        memcpy (&tls->handler_ctx, ctx, sizeof (MonoContext));
 
-       process_breakpoint_inner (tls, FALSE);
+       process_breakpoint (tls, FALSE);
 
        memcpy (ctx, &tls->restore_state.ctx, sizeof (MonoContext));
        memcpy (&tls->restore_state, &orig_restore_state, sizeof (MonoThreadUnwindState));
@@ -5250,8 +5333,10 @@ start_single_stepping (void)
 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
        int val = InterlockedIncrement (&ss_count);
 
-       if (val == 1)
+       if (val == 1) {
                mono_arch_start_single_stepping ();
+               mono_interp_start_single_stepping ();
+       }
 #else
        g_assert_not_reached ();
 #endif
@@ -5263,8 +5348,10 @@ stop_single_stepping (void)
 #ifdef MONO_ARCH_SOFT_DEBUG_SUPPORTED
        int val = InterlockedDecrement (&ss_count);
 
-       if (val == 0)
+       if (val == 0) {
                mono_arch_stop_single_stepping ();
+               mono_interp_stop_single_stepping ();
+       }
 #else
        g_assert_not_reached ();
 #endif
@@ -6707,6 +6794,24 @@ set_var (MonoType *t, MonoDebugVarInfo *var, MonoContext *ctx, MonoDomain *domai
        }
 }
 
+static void
+set_interp_var (MonoType *t, gpointer addr, guint8 *val_buf)
+{
+       int size;
+
+       if (t->byref) {
+               addr = *(gpointer*)addr;
+               g_assert (addr);
+       }
+
+       if (MONO_TYPE_IS_REFERENCE (t))
+               size = sizeof (gpointer);
+       else
+               size = mono_class_value_size (mono_class_from_mono_type (t), NULL);
+
+       memcpy (addr, val_buf, size);
+}
+
 static void
 clear_event_request (int req_id, int etype)
 {
@@ -9376,7 +9481,13 @@ thread_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
                // FIXME: Check that the ip change is safe
 
                DEBUG_PRINTF (1, "[dbg] Setting IP to %s:0x%0x(0x%0x)\n", tls->frames [0]->actual_method->name, (int)sp.il_offset, (int)sp.native_offset);
-               MONO_CONTEXT_SET_IP (&tls->restore_state.ctx, (guint8*)tls->frames [0]->ji->code_start + sp.native_offset);
+
+               if (tls->frames [0]->ji->is_interp) {
+                       MonoJitTlsData *jit_data = ((MonoThreadInfo*)thread->thread_info)->jit_data;
+                       mono_interp_set_resume_state (jit_data, NULL, tls->frames [0]->interp_frame, (guint8*)tls->frames [0]->ji->code_start + sp.native_offset);
+               } else {
+                       MONO_CONTEXT_SET_IP (&tls->restore_state.ctx, (guint8*)tls->frames [0]->ji->code_start + sp.native_offset);
+               }
                break;
        }
        default:
@@ -9442,7 +9553,7 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
 
        sig = mono_method_signature (frame->actual_method);
 
-       if (!jit->has_var_info || !mono_get_seq_points (frame->domain, frame->actual_method))
+       if (!(jit->has_var_info || frame->ji->is_interp) || !mono_get_seq_points (frame->domain, frame->actual_method))
                /*
                 * The method is probably from an aot image compiled without soft-debug, variables might be dead, etc.
                 */
@@ -9463,9 +9574,17 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
 
                                DEBUG_PRINTF (4, "[dbg]   send arg %d.\n", pos);
 
-                               g_assert (pos >= 0 && pos < jit->num_params);
+                               if (frame->ji->is_interp) {
+                                       guint8 *addr;
+
+                                       addr = mono_interp_frame_get_arg (frame->interp_frame, pos);
+
+                                       buffer_add_value_full (buf, sig->params [pos], addr, frame->domain, FALSE, NULL);
+                               } else {
+                                       g_assert (pos >= 0 && pos < jit->num_params);
 
-                               add_var (buf, jit, sig->params [pos], &jit->params [pos], &frame->ctx, frame->domain, FALSE);
+                                       add_var (buf, jit, sig->params [pos], &jit->params [pos], &frame->ctx, frame->domain, FALSE);
+                               }
                        } else {
                                MonoDebugLocalsInfo *locals;
 
@@ -9475,30 +9594,57 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
                                        pos = locals->locals [pos].index;
                                        mono_debug_free_locals (locals);
                                }
-                               g_assert (pos >= 0 && pos < jit->num_locals);
 
                                DEBUG_PRINTF (4, "[dbg]   send local %d.\n", pos);
 
-                               add_var (buf, jit, header->locals [pos], &jit->locals [pos], &frame->ctx, frame->domain, FALSE);
+                               if (frame->ji->is_interp) {
+                                       guint8 *addr;
+
+                                       addr = mono_interp_frame_get_local (frame->interp_frame, pos);
+
+                                       buffer_add_value_full (buf, header->locals [pos], addr, frame->domain, FALSE, NULL);
+                               } else {
+                                       g_assert (pos >= 0 && pos < jit->num_locals);
+
+                                       add_var (buf, jit, header->locals [pos], &jit->locals [pos], &frame->ctx, frame->domain, FALSE);
+                               }
                        }
                }
                mono_metadata_free_mh (header);
                break;
        }
        case CMD_STACK_FRAME_GET_THIS: {
+               if (frame->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE)
+                       return ERR_ABSENT_INFORMATION;
                if (frame->api_method->klass->valuetype) {
                        if (!sig->hasthis) {
                                MonoObject *p = NULL;
                                buffer_add_value (buf, &mono_defaults.object_class->byval_arg, &p, frame->domain);
                        } else {
-                               add_var (buf, jit, &frame->actual_method->klass->this_arg, jit->this_var, &frame->ctx, frame->domain, TRUE);
+                               if (frame->ji->is_interp) {
+                                       guint8 *addr;
+
+                                       addr = mono_interp_frame_get_this (frame->interp_frame);
+
+                                       buffer_add_value_full (buf, &frame->actual_method->klass->this_arg, addr, frame->domain, FALSE, NULL);
+                               } else {
+                                       add_var (buf, jit, &frame->actual_method->klass->this_arg, jit->this_var, &frame->ctx, frame->domain, TRUE);
+                               }
                        }
                } else {
                        if (!sig->hasthis) {
                                MonoObject *p = NULL;
                                buffer_add_value (buf, &frame->actual_method->klass->byval_arg, &p, frame->domain);
                        } else {
-                               add_var (buf, jit, &frame->api_method->klass->byval_arg, jit->this_var, &frame->ctx, frame->domain, TRUE);
+                               if (frame->ji->is_interp) {
+                                       guint8 *addr;
+
+                                       addr = mono_interp_frame_get_this (frame->interp_frame);
+
+                                       buffer_add_value_full (buf, &frame->api_method->klass->byval_arg, addr, frame->domain, FALSE, NULL);
+                               } else {
+                                       add_var (buf, jit, &frame->api_method->klass->byval_arg, jit->this_var, &frame->ctx, frame->domain, TRUE);
+                               }
                        }
                }
                break;
@@ -9507,7 +9653,8 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
                MonoError error;
                guint8 *val_buf;
                MonoType *t;
-               MonoDebugVarInfo *var;
+               MonoDebugVarInfo *var = NULL;
+               gboolean is_arg = FALSE;
 
                len = decode_int (p, &p, end);
                header = mono_method_get_header_checked (frame->actual_method, &error);
@@ -9523,6 +9670,7 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
 
                                t = sig->params [pos];
                                var = &jit->params [pos];
+                               is_arg = TRUE;
                        } else {
                                MonoDebugLocalsInfo *locals;
 
@@ -9546,7 +9694,17 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
                        if (err != ERR_NONE)
                                return err;
 
-                       set_var (t, var, &frame->ctx, frame->domain, val_buf, frame->reg_locations, &tls->restore_state.ctx);
+                       if (frame->ji->is_interp) {
+                               guint8 *addr;
+
+                               if (is_arg)
+                                       addr = mono_interp_frame_get_arg (frame->interp_frame, pos);
+                               else
+                                       addr = mono_interp_frame_get_local (frame->interp_frame, pos);
+                               set_interp_var (t, addr, val_buf);
+                       } else {
+                               set_var (t, var, &frame->ctx, frame->domain, val_buf, frame->reg_locations, &tls->restore_state.ctx);
+                       }
                }
                mono_metadata_free_mh (header);
                break;
@@ -9564,15 +9722,23 @@ frame_commands (int command, guint8 *p, guint8 *end, Buffer *buf)
                t = &frame->actual_method->klass->byval_arg;
                /* Checked by the sender */
                g_assert (MONO_TYPE_ISSTRUCT (t));
-               var = jit->this_var;
-               g_assert (var);
 
                val_buf = (guint8 *)g_alloca (mono_class_instance_size (mono_class_from_mono_type (t)));
                err = decode_value (t, frame->domain, val_buf, p, &p, end);
                if (err != ERR_NONE)
                        return err;
 
-               set_var (&frame->actual_method->klass->this_arg, var, &frame->ctx, frame->domain, val_buf, frame->reg_locations, &tls->restore_state.ctx);
+               if (frame->ji->is_interp) {
+                       guint8 *addr;
+
+                       addr = mono_interp_frame_get_this (frame->interp_frame);
+                       set_interp_var (&frame->actual_method->klass->this_arg, addr, val_buf);
+               } else {
+                       var = jit->this_var;
+                       g_assert (var);
+
+                       set_var (&frame->actual_method->klass->this_arg, var, &frame->ctx, frame->domain, val_buf, frame->reg_locations, &tls->restore_state.ctx);
+               }
                break;
        }
        default:
index 1c3060f162477cc8db01fbc0c64c6eb2c6f3ebbb..93668ac852457377081ddd806f9b8f65ad75b32a 100644 (file)
@@ -1227,8 +1227,8 @@ mono_decompose_vtype_opts (MonoCompile *cfg)
 
                                        EMIT_NEW_VARLOADA ((cfg), (src), src_var, src_var->inst_vtype);
                                        EMIT_NEW_VARLOADA ((cfg), (dest), dest_var, dest_var->inst_vtype);
+                                       mini_emit_memory_copy (cfg, dest, src, src_var->klass, src_var->backend.is_pinvoke, 0);
 
-                                       mini_emit_stobj (cfg, dest, src, src_var->klass, src_var->backend.is_pinvoke);
                                        break;
                                }
                                case OP_VZERO:
@@ -1273,7 +1273,7 @@ mono_decompose_vtype_opts (MonoCompile *cfg)
 
                                        dreg = alloc_preg (cfg);
                                        EMIT_NEW_BIALU_IMM (cfg, dest, OP_ADD_IMM, dreg, ins->inst_destbasereg, ins->inst_offset);
-                                       mini_emit_stobj (cfg, dest, src, src_var->klass, src_var->backend.is_pinvoke);
+                                       mini_emit_memory_copy (cfg, dest, src, src_var->klass, src_var->backend.is_pinvoke, 0);
                                        break;
                                }
                                case OP_LOADV_MEMBASE: {
@@ -1290,7 +1290,7 @@ mono_decompose_vtype_opts (MonoCompile *cfg)
                                        dreg = alloc_preg (cfg);
                                        EMIT_NEW_BIALU_IMM (cfg, src, OP_ADD_IMM, dreg, ins->inst_basereg, ins->inst_offset);
                                        EMIT_NEW_VARLOADA (cfg, dest, dest_var, dest_var->inst_vtype);
-                                       mini_emit_stobj (cfg, dest, src, dest_var->klass, dest_var->backend.is_pinvoke);
+                                       mini_emit_memory_copy (cfg, dest, src, dest_var->klass, dest_var->backend.is_pinvoke, 0);
                                        break;
                                }
                                case OP_OUTARG_VT: {
index cc4cd237c677f3be75f9b93162979168aef28f7d..3b19a6d1bdaba5b7215c34a9ece4020672d6abf7 100644 (file)
@@ -105,6 +105,7 @@ struct _MonoInvocation {
        stackval       *stack_args; /* parent */
        stackval       *stack;
        stackval       *sp; /* For GC stack marking */
+       unsigned char  *locals;
        /* exception info */
        unsigned char  invoke_trap;
        const unsigned short  *ip;
diff --git a/mono/mini/interp/interp-stubs.c b/mono/mini/interp/interp-stubs.c
new file mode 100644 (file)
index 0000000..176e45b
--- /dev/null
@@ -0,0 +1,98 @@
+#include <config.h>
+
+#ifndef ENABLE_INTERPRETER
+
+#include "interp.h"
+
+/* Dummy versions of interpreter functions to avoid ifdefs at call sites */
+
+MonoJitInfo*
+mono_interp_find_jit_info (MonoDomain *domain, MonoMethod *method)
+{
+       return NULL;
+}
+
+void
+mono_interp_set_breakpoint (MonoJitInfo *jinfo, gpointer ip)
+{
+       g_assert_not_reached ();
+}
+
+void
+mono_interp_clear_breakpoint (MonoJitInfo *jinfo, gpointer ip)
+{
+       g_assert_not_reached ();
+}
+
+MonoJitInfo*
+mono_interp_frame_get_jit_info (MonoInterpFrameHandle frame)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+gpointer
+mono_interp_frame_get_ip (MonoInterpFrameHandle frame)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+gpointer
+mono_interp_frame_get_arg (MonoInterpFrameHandle frame, int pos)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+gpointer
+mono_interp_frame_get_local (MonoInterpFrameHandle frame, int pos)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+gpointer
+mono_interp_frame_get_this (MonoInterpFrameHandle frame)
+{
+       g_assert_not_reached ();
+       return NULL;
+}
+
+void
+mono_interp_start_single_stepping (void)
+{
+}
+
+void
+mono_interp_stop_single_stepping (void)
+{
+}
+
+void
+mono_interp_set_resume_state (MonoJitTlsData *jit_tls, MonoException *ex, MonoInterpFrameHandle interp_frame, gpointer handler_ip)
+{
+       g_assert_not_reached ();
+}
+
+void
+mono_interp_run_finally (StackFrameInfo *frame, int clause_index, gpointer handler_ip)
+{
+       g_assert_not_reached ();
+}
+
+void
+mono_interp_frame_iter_init (MonoInterpStackIter *iter, gpointer interp_exit_data)
+{
+       g_assert_not_reached ();
+}
+
+gboolean
+mono_interp_frame_iter_next (MonoInterpStackIter *iter, StackFrameInfo *frame)
+{
+       g_assert_not_reached ();
+       return FALSE;
+}
+
+#endif
+
index 68d3b3998a457502b485c9df372cd8aea54b47e9..0b530d8330a0b45321f15d8797b1931dc2507e63 100644 (file)
@@ -66,6 +66,7 @@
 
 #include <mono/mini/mini.h>
 #include <mono/mini/jit-icalls.h>
+#include <mono/mini/debugger-agent.h>
 
 #ifdef TARGET_ARM
 #include <mono/mini/mini-arm.h>
@@ -104,6 +105,8 @@ init_frame (MonoInvocation *frame, MonoInvocation *parent_frame, RuntimeMethod *
  * Used for testing.
  */
 GSList *jit_classes;
+/* If TRUE, interpreted code will be interrupted at function entry/backward branches */
+static gboolean ss_enabled;
 
 void ves_exec_method (MonoInvocation *frame);
 
@@ -204,14 +207,27 @@ static void debug_enter (MonoInvocation *frame, int *tracing)
 /* Set the current execution state to the resume state in context */
 #define SET_RESUME_STATE(context) do { \
                ip = (context)->handler_ip;                                             \
+               if (frame->ex) { \
                sp->data.p = frame->ex;                                                                                 \
                ++sp;                                                                                                                   \
+               } \
                frame->ex = NULL;                                                                                               \
                (context)->has_resume_state = 0;                                                                \
                (context)->handler_frame = NULL;                                                                \
                goto main_loop;                                                                                                 \
        } while (0)
 
+static void
+set_context (ThreadContext *context)
+{
+       MonoJitTlsData *jit_tls;
+
+       mono_native_tls_set_value (thread_context_id, context);
+       jit_tls = mono_tls_get_jit_tls ();
+       if (jit_tls)
+               jit_tls->interp_context = context;
+}
+
 static void
 ves_real_abort (int line, MonoMethod *mh,
                const unsigned short *ip, stackval *stack, stackval *sp)
@@ -234,6 +250,19 @@ ves_real_abort (int line, MonoMethod *mh,
                THROW_EX (mono_get_exception_execution_engine (NULL), ip); \
        } while (0);
 
+static RuntimeMethod*
+lookup_runtime_method (MonoDomain *domain, MonoMethod *method)
+{
+       RuntimeMethod *rtm;
+       MonoJitDomainInfo *info;
+
+       info = domain_jit_info (domain);
+       mono_domain_jit_code_hash_lock (domain);
+       rtm = mono_internal_hash_table_lookup (&info->interp_code_hash, method);
+       mono_domain_jit_code_hash_unlock (domain);
+       return rtm;
+}
+
 RuntimeMethod*
 mono_interp_get_runtime_method (MonoDomain *domain, MonoMethod *method, MonoError *error)
 {
@@ -278,6 +307,30 @@ mono_interp_create_trampoline (MonoDomain *domain, MonoMethod *method, MonoError
        return mono_interp_get_runtime_method (domain, method, error);
 }
 
+/*
+ * interp_push_lmf:
+ *
+ * Push an LMF frame on the LMF stack
+ * to mark the transition to native code.
+ * This is needed for the native code to
+ * be able to do stack walks.
+ */
+static void
+interp_push_lmf (MonoLMFExt *ext, MonoInvocation *frame)
+{
+       memset (ext, 0, sizeof (MonoLMFExt));
+       ext->interp_exit = TRUE;
+       ext->interp_exit_data = frame;
+
+       mono_push_lmf (ext);
+}
+
+static void
+interp_pop_lmf (MonoLMFExt *ext)
+{
+       mono_pop_lmf (&ext->lmf);
+}
+
 static inline RuntimeMethod*
 get_virtual_method (MonoDomain *domain, RuntimeMethod *runtime_method, MonoObject *obj)
 {
@@ -943,19 +996,11 @@ ves_pinvoke_method (MonoInvocation *frame, MonoMethodSignature *sig, MonoFuncV a
        context->current_frame = frame;
        context->managed_code = 0;
 
-       /*
-        * Push an LMF frame on the LMF stack
-        * to mark the transition to native code.
-        */
-       memset (&ext, 0, sizeof (ext));
-       ext.interp_exit = TRUE;
-       ext.interp_exit_data = frame;
-
-       mono_push_lmf (&ext);
+       interp_push_lmf (&ext, frame);
 
        mono_interp_enter_icall_trampoline (addr, margs);
 
-       mono_pop_lmf (&ext.lmf);
+       interp_pop_lmf (&ext);
 
        context->managed_code = 1;
        /* domain can only be changed by native code */
@@ -1307,7 +1352,7 @@ mono_interp_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoOb
        int i, type, isobject = 0;
        void *ret = NULL;
        stackval result;
-       stackval *args = alloca (sizeof (stackval) * (sig->param_count + !!sig->hasthis));
+       stackval *args;
        ThreadContext context_struct;
        MonoInvocation *old_frame = NULL;
        jmp_buf env;
@@ -1323,8 +1368,8 @@ mono_interp_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoOb
                        context->domain = mono_domain_get ();
                        context->current_frame = old_frame;
                        context->managed_code = 0;
-               } else 
-                       mono_native_tls_set_value (thread_context_id, NULL);
+               } else
+                       set_context (NULL);
                if (exc != NULL)
                        *exc = (MonoObject *)frame.ex;
                return retval;
@@ -1336,7 +1381,7 @@ mono_interp_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoOb
                context_struct.base_frame = &frame;
                context_struct.env_frame = &frame;
                context_struct.current_env = &env;
-               mono_native_tls_set_value (thread_context_id, context);
+               set_context (context);
        }
        else
                old_frame = context->current_frame;
@@ -1384,6 +1429,7 @@ mono_interp_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoOb
                break;
        }
 
+       args = alloca (sizeof (stackval) * (sig->param_count + !!sig->hasthis));
        if (sig->hasthis)
                args [0].data.p = obj;
 
@@ -1453,13 +1499,14 @@ handle_enum:
        if (method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
                method = mono_marshal_get_native_wrapper (method, FALSE, FALSE);
        INIT_FRAME (&frame,context->current_frame,args,&result,mono_get_root_domain (),method,error);
+
        if (exc)
                frame.invoke_trap = 1;
        context->managed_code = 1;
        ves_exec_method_with_context (&frame, context, NULL, NULL, -1);
        context->managed_code = 0;
        if (context == &context_struct)
-               mono_native_tls_set_value (thread_context_id, NULL);
+               set_context (NULL);
        else
                context->current_frame = old_frame;
        if (frame.ex != NULL) {
@@ -1519,10 +1566,10 @@ interp_entry (InterpEntryData *data)
                memset (context, 0, sizeof (ThreadContext));
                context_struct.base_frame = &frame;
                context_struct.env_frame = &frame;
-               mono_native_tls_set_value (thread_context_id, context);
-       }
-       else
+               set_context (context);
+       } else {
                old_frame = context->current_frame;
+       }
        context->domain = mono_domain_get ();
 
        args = alloca (sizeof (stackval) * (sig->param_count + (sig->hasthis ? 1 : 0)));
@@ -1615,7 +1662,7 @@ interp_entry (InterpEntryData *data)
        ves_exec_method_with_context (&frame, context, NULL, NULL, -1);
        context->managed_code = 0;
        if (context == &context_struct)
-               mono_native_tls_set_value (thread_context_id, NULL);
+               set_context (NULL);
        else
                context->current_frame = old_frame;
 
@@ -2088,8 +2135,17 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, uns
                g_print ("(%p) Transforming %s\n", mono_thread_internal_current (), mn);
                g_free (mn);
 #endif
+
+               MonoLMFExt ext;
+
+               /* Use the parent frame as the current frame is not complete yet */
+               interp_push_lmf (&ext, frame->parent);
+
                frame->ex = mono_interp_transform_method (frame->runtime_method, context);
                context->managed_code = 1;
+
+               interp_pop_lmf (&ext);
+
                if (frame->ex) {
                        rtm = NULL;
                        ip = NULL;
@@ -2112,6 +2168,7 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, uns
        vtalloc = vt_sp;
 #endif
        locals = (unsigned char *) vt_sp + rtm->vt_stack_size;
+       frame->locals = locals;
        child_frame.parent = frame;
 
        if (filter_exception) {
@@ -2136,10 +2193,18 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, uns
                MINT_IN_CASE(MINT_NOP)
                        ++ip;
                        MINT_IN_BREAK;
-               MINT_IN_CASE(MINT_BREAK)
+               MINT_IN_CASE(MINT_BREAK) {
                        ++ip;
-                       G_BREAKPOINT (); /* this is not portable... */
+
+                       MonoLMFExt ext;
+
+                       interp_push_lmf (&ext, frame);
+
+                       mono_debugger_agent_user_break ();
+
+                       interp_pop_lmf (&ext);
                        MINT_IN_BREAK;
+               }
                MINT_IN_CASE(MINT_LDNULL) 
                        sp->data.p = NULL;
                        ++ip;
@@ -2257,6 +2322,7 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, uns
                        vtalloc = vt_sp;
 #endif
                        locals = vt_sp + rtm->vt_stack_size;
+                       frame->locals = locals;
                        ip = rtm->new_body_start; /* bypass storing input args from callers frame */
                        MINT_IN_BREAK;
                }
@@ -2567,15 +2633,7 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, uns
                                }
                        }
 
-                       /*
-                        * Push an LMF frame on the LMF stack
-                        * to mark the transition to compiled code.
-                        */
-                       memset (&ext, 0, sizeof (ext));
-                       ext.interp_exit = TRUE;
-                       ext.interp_exit_data = frame;
-
-                       mono_push_lmf (&ext);
+                       interp_push_lmf (&ext, frame);
 
                        switch (pindex) {
                        case 0: {
@@ -2631,7 +2689,7 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, uns
                                break;
                        }
 
-                       mono_pop_lmf (&ext.lmf);
+                       interp_pop_lmf (&ext);
 
                        if (context->has_resume_state) {
                                /*
@@ -2819,7 +2877,7 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, uns
                        goto exit_frame;
                MINT_IN_CASE(MINT_RET_VOID)
                        if (sp > frame->stack)
-                               g_warning ("ret.void: more values on stack: %d", sp-frame->stack);
+                               g_warning ("ret.void: more values on stack: %d %s", sp-frame->stack, mono_method_full_name (frame->runtime_method->method, TRUE));
                        goto exit_frame;
                MINT_IN_CASE(MINT_RET_VT)
                        i32 = READ32(ip + 1);
@@ -3110,7 +3168,7 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, uns
                                gint offset;
                                ip += 2 * (guint32)sp->data.i;
                                offset = READ32 (ip);
-                               ip = st + offset;
+                               ip = ip + offset;
                        } else {
                                ip = st;
                        }
@@ -3486,10 +3544,13 @@ ves_exec_method_with_context (MonoInvocation *frame, ThreadContext *context, uns
                        MINT_IN_BREAK;
                MINT_IN_CASE(MINT_CPOBJ) {
                        c = rtm->data_items[* (guint16 *)(ip + 1)];
-                       g_assert (c->byval_arg.type == MONO_TYPE_VALUETYPE);
+                       g_assert (c->valuetype);
                        /* if this assertion fails, we need to add a write barrier */
                        g_assert (!MONO_TYPE_IS_REFERENCE (&c->byval_arg));
-                       stackval_from_data (&c->byval_arg, &sp [-2], sp [-1].data.p, FALSE);
+                       if (c->byval_arg.type == MONO_TYPE_VALUETYPE)
+                               stackval_from_data (&c->byval_arg, &sp [-2], sp [-1].data.p, FALSE);
+                       else
+                               stackval_from_data (&c->byval_arg, sp [-2].data.p, sp [-1].data.p, FALSE);
                        ip += 2;
                        sp -= 2;
                        MINT_IN_BREAK;
@@ -3661,6 +3722,7 @@ array_constructed:
                        frame->ex_handler = NULL;
                        if (!sp->data.p)
                                sp->data.p = mono_get_exception_null_reference ();
+
                        THROW_EX ((MonoException *)sp->data.p, ip);
                        MINT_IN_BREAK;
                MINT_IN_CASE(MINT_LDFLDA_UNSAFE)
@@ -4513,6 +4575,72 @@ array_constructed:
                        ++ip;
                        mono_jit_set_domain (context->original_domain);
                        MINT_IN_BREAK;
+               MINT_IN_CASE(MINT_SDB_INTR_LOC)
+                       if (G_UNLIKELY (ss_enabled)) {
+                               MonoLMFExt ext;
+                               static void (*ss_tramp) (void);
+
+                               if (!ss_tramp) {
+                                       void *tramp = mini_get_single_step_trampoline ();
+                                       mono_memory_barrier ();
+                                       ss_tramp = tramp;
+                               }
+
+                               /*
+                                * Make this point to the MINT_SDB_SEQ_POINT instruction which follows this since
+                                * the address of that instruction is stored as the seq point address.
+                                */
+                               frame->ip = ip + 1;
+
+                               interp_push_lmf (&ext, frame);
+                               /*
+                                * Use the same trampoline as the JIT. This ensures that
+                                * the debugger has the context for the last interpreter
+                                * native frame.
+                                */
+                               ss_tramp ();
+                               interp_pop_lmf (&ext);
+
+                               if (context->has_resume_state) {
+                                       if (frame == context->handler_frame)
+                                               SET_RESUME_STATE (context);
+                                       else
+                                               goto exit_frame;
+                               }
+                       }
+                       ++ip;
+                       MINT_IN_BREAK;
+               MINT_IN_CASE(MINT_SDB_SEQ_POINT)
+                       /* Just a placeholder for a breakpoint */
+                       ++ip;
+                       MINT_IN_BREAK;
+               MINT_IN_CASE(MINT_SDB_BREAKPOINT) {
+                       MonoLMFExt ext;
+
+                       static void (*bp_tramp) (void);
+                       if (!bp_tramp) {
+                               void *tramp = mini_get_breakpoint_trampoline ();
+                               mono_memory_barrier ();
+                               bp_tramp = tramp;
+                       }
+
+                       frame->ip = ip;
+
+                       interp_push_lmf (&ext, frame);
+                       /* Use the same trampoline as the JIT */
+                       bp_tramp ();
+                       interp_pop_lmf (&ext);
+
+                       if (context->has_resume_state) {
+                               if (frame == context->handler_frame)
+                                       SET_RESUME_STATE (context);
+                               else
+                                       goto exit_frame;
+                       }
+
+                       ++ip;
+                       MINT_IN_BREAK;
+               }
 
 #define RELOP(datamem, op) \
        --sp; \
@@ -5058,7 +5186,7 @@ ves_exec_method (MonoInvocation *frame)
                context_struct.current_env = &env;
                context_struct.search_for_handler = 0;
                context_struct.managed_code = 0;
-               mono_native_tls_set_value (thread_context_id, context);
+               set_context (context);
        }
        frame->ip = NULL;
        frame->parent = context->current_frame;
@@ -5076,7 +5204,7 @@ ves_exec_method (MonoInvocation *frame)
                        mono_unhandled_exception ((MonoObject*)frame->ex);
        }
        if (context->base_frame == frame)
-               mono_native_tls_set_value (thread_context_id, NULL);
+               set_context (NULL);
        else
                context->current_frame = frame->parent;
 }
@@ -5099,7 +5227,7 @@ void
 mono_interp_init ()
 {
        mono_native_tls_alloc (&thread_context_id, NULL);
-       mono_native_tls_set_value (thread_context_id, NULL);
+       set_context (NULL);
 
        mono_interp_transform_init ();
 }
@@ -5275,12 +5403,16 @@ mono_interp_regression_list (int verbose, int count, char *images [])
  *   Set the state the interpeter will continue to execute from after execution returns to the interpreter.
  */
 void
-mono_interp_set_resume_state (MonoException *ex, StackFrameInfo *frame, gpointer handler_ip)
+mono_interp_set_resume_state (MonoJitTlsData *jit_tls, MonoException *ex, MonoInterpFrameHandle interp_frame, gpointer handler_ip)
 {
-       ThreadContext *context = mono_native_tls_get_value (thread_context_id);
+       ThreadContext *context;
+
+       g_assert (jit_tls);
+       context = jit_tls->interp_context;
+       g_assert (context);
 
        context->has_resume_state = TRUE;
-       context->handler_frame = frame->interp_frame;
+       context->handler_frame = interp_frame;
        /* This is on the stack, so it doesn't need a wbarrier */
        context->handler_frame->ex = ex;
        context->handler_ip = handler_ip;
@@ -5326,20 +5458,115 @@ mono_interp_frame_iter_next (MonoInterpStackIter *iter, StackFrameInfo *frame)
 
        memset (frame, 0, sizeof (StackFrameInfo));
        /* pinvoke frames doesn't have runtime_method set */
-       while (iframe && !iframe->runtime_method)
+       while (iframe && !(iframe->runtime_method && iframe->runtime_method->code))
                iframe = iframe->parent;
        if (!iframe)
                return FALSE;
 
        frame->type = FRAME_TYPE_INTERP;
+       // FIXME:
+       frame->domain = mono_domain_get ();
        frame->interp_frame = iframe;
        frame->method = iframe->runtime_method->method;
        frame->actual_method = frame->method;
        /* This is the offset in the interpreter IR */
-       frame->native_offset = iframe->ip - iframe->runtime_method->code;
+       frame->native_offset = (guint8*)iframe->ip - (guint8*)iframe->runtime_method->code;
        frame->ji = iframe->runtime_method->jinfo;
 
        stack_iter->current = iframe->parent;
 
        return TRUE;
 }
+
+MonoJitInfo*
+mono_interp_find_jit_info (MonoDomain *domain, MonoMethod *method)
+{
+       RuntimeMethod* rtm;
+
+       rtm = lookup_runtime_method (domain, method);
+       if (rtm)
+               return rtm->jinfo;
+       else
+               return NULL;
+}
+
+void
+mono_interp_set_breakpoint (MonoJitInfo *jinfo, gpointer ip)
+{
+       guint16 *code = (guint16*)ip;
+       g_assert (*code == MINT_SDB_SEQ_POINT);
+       *code = MINT_SDB_BREAKPOINT;
+}
+
+void
+mono_interp_clear_breakpoint (MonoJitInfo *jinfo, gpointer ip)
+{
+       guint16 *code = (guint16*)ip;
+       g_assert (*code == MINT_SDB_BREAKPOINT);
+       *code = MINT_SDB_SEQ_POINT;
+}
+
+MonoJitInfo*
+mono_interp_frame_get_jit_info (MonoInterpFrameHandle frame)
+{
+       MonoInvocation *iframe = (MonoInvocation*)frame;
+
+       g_assert (iframe->runtime_method);
+       return iframe->runtime_method->jinfo;
+}
+
+gpointer
+mono_interp_frame_get_ip (MonoInterpFrameHandle frame)
+{
+       MonoInvocation *iframe = (MonoInvocation*)frame;
+
+       g_assert (iframe->runtime_method);
+       return (gpointer)iframe->ip;
+}
+
+gpointer
+mono_interp_frame_get_arg (MonoInterpFrameHandle frame, int pos)
+{
+       MonoInvocation *iframe = (MonoInvocation*)frame;
+
+       g_assert (iframe->runtime_method);
+
+       int arg_offset = iframe->runtime_method->arg_offsets [pos + (iframe->runtime_method->hasthis ? 1 : 0)];
+
+       return iframe->args + arg_offset;
+}
+
+gpointer
+mono_interp_frame_get_local (MonoInterpFrameHandle frame, int pos)
+{
+       MonoInvocation *iframe = (MonoInvocation*)frame;
+
+       g_assert (iframe->runtime_method);
+
+       return iframe->locals + iframe->runtime_method->local_offsets [pos];
+}
+
+gpointer
+mono_interp_frame_get_this (MonoInterpFrameHandle frame)
+{
+       MonoInvocation *iframe = (MonoInvocation*)frame;
+
+       g_assert (iframe->runtime_method);
+       g_assert (iframe->runtime_method->hasthis);
+
+       int arg_offset = iframe->runtime_method->arg_offsets [0];
+
+       return iframe->args + arg_offset;
+}
+
+void
+mono_interp_start_single_stepping (void)
+{
+       ss_enabled = TRUE;
+}
+
+void
+mono_interp_stop_single_stepping (void)
+{
+       ss_enabled = FALSE;
+}
index cf922507500bc16adae32d32dd1ed0ccf0283c5f..6abf93a6f0a38c900820258f6b73859f2b35d048 100644 (file)
@@ -28,6 +28,8 @@ struct _MonoInterpStackIter {
        gpointer dummy [8];
 };
 
+typedef gpointer MonoInterpFrameHandle;
+
 int
 mono_interp_regression_list (int verbose, int count, char *images []);
 
@@ -53,7 +55,7 @@ void
 interp_walk_stack_with_ctx (MonoInternalStackWalk func, MonoContext *ctx, MonoUnwindOptions options, void *user_data);
 
 void
-mono_interp_set_resume_state (MonoException *ex, StackFrameInfo *frame, gpointer handler_ip);
+mono_interp_set_resume_state (MonoJitTlsData *jit_tls, MonoException *ex, MonoInterpFrameHandle interp_frame, gpointer handler_ip);
 
 void
 mono_interp_run_finally (StackFrameInfo *frame, int clause_index, gpointer handler_ip);
@@ -64,4 +66,34 @@ mono_interp_frame_iter_init (MonoInterpStackIter *iter, gpointer interp_exit_dat
 gboolean
 mono_interp_frame_iter_next (MonoInterpStackIter *iter, StackFrameInfo *frame);
 
+MonoJitInfo*
+mono_interp_find_jit_info (MonoDomain *domain, MonoMethod *method);
+
+void
+mono_interp_set_breakpoint (MonoJitInfo *jinfo, gpointer ip);
+
+void
+mono_interp_clear_breakpoint (MonoJitInfo *jinfo, gpointer ip);
+
+MonoJitInfo*
+mono_interp_frame_get_jit_info (MonoInterpFrameHandle frame);
+
+gpointer
+mono_interp_frame_get_ip (MonoInterpFrameHandle frame);
+
+gpointer
+mono_interp_frame_get_arg (MonoInterpFrameHandle frame, int pos);
+
+gpointer
+mono_interp_frame_get_local (MonoInterpFrameHandle frame, int pos);
+
+gpointer
+mono_interp_frame_get_this (MonoInterpFrameHandle frame);
+
+void
+mono_interp_start_single_stepping (void);
+
+void
+mono_interp_stop_single_stepping (void);
+
 #endif /* __MONO_MINI_INTERPRETER_H__ */
index e1c58ecf7a968643c8ac0ae638088dfa4f4aea01..b0fa6358c894a4ea71e3611569634a8eee56c310 100644 (file)
@@ -106,7 +106,7 @@ mono_interp_dis_mintop(const guint16 *base, const guint16 *ip)
                        if (i > 0)
                                g_print (", ");
                        offset = (gint32)READ32 (p);
-                       g_print ("IL_%04x", ip - base + 3 + 2 * sval + offset);
+                       g_print ("IL_%04x", p + offset);
                        p += 2;
                }
                g_print (")");
index 190c6647d08adef26aee2599bfc0bbe2c2be21e1..647e5838607a5b02433365592919a620f745feb6 100644 (file)
@@ -521,3 +521,6 @@ OPDEF(MINT_MONO_JIT_DETACH, "mono_jit_detach", 1, MintOpNoArgs)
 
 // FIXME: MintOp
 OPDEF(MINT_JIT_CALL, "mono_jit_call", 2, MintOpNoArgs)
+OPDEF(MINT_SDB_INTR_LOC, "sdb_intr_loc", 1, MintOpNoArgs)
+OPDEF(MINT_SDB_SEQ_POINT, "sdb_seq_point", 1, MintOpNoArgs)
+OPDEF(MINT_SDB_BREAKPOINT, "sdb_breakpoint", 1, MintOpNoArgs)
index 9354aa8737c61109ddc52c4e8e9744d18e05b506..a309a4a9fab839713de230df79eb0176c92631e1 100644 (file)
@@ -15,6 +15,7 @@
 #include <mono/metadata/marshal.h>
 #include <mono/metadata/profiler-private.h>
 #include <mono/metadata/tabledefs.h>
+#include <mono/metadata/seq-points-data.h>
 
 #include <mono/mini/mini.h>
 
@@ -34,6 +35,31 @@ typedef struct
        unsigned char flags;
 } StackInfo;
 
+typedef struct {
+       guint8 *ip;
+       GSList *preds;
+       GSList *seq_points;
+       SeqPoint *last_seq_point;
+
+       // This will hold a list of last sequence points of incoming basic blocks
+       SeqPoint **pred_seq_points;
+       guint num_pred_seq_points;
+} InterpBasicBlock;
+
+typedef enum {
+       RELOC_SHORT_BRANCH,
+       RELOC_LONG_BRANCH,
+       RELOC_SWITCH
+} RelocType;
+
+typedef struct {
+       RelocType type;
+       /* In the interpreter IR */
+       int offset;
+       /* In the IL code */
+       int target;
+} Reloc;
+
 typedef struct
 {
        MonoMethod *method;
@@ -45,7 +71,6 @@ typedef struct
        const unsigned char *in_start;
        int code_size;
        int *in_offsets;
-       int *forward_refs;
        StackInfo **stack_state;
        int *stack_height;
        int *vt_stack_size;
@@ -65,6 +90,14 @@ typedef struct
        void **data_items;
        GHashTable *data_hash;
        int *clause_indexes;
+       gboolean gen_sdb_seq_points;
+       GPtrArray *seq_points;
+       InterpBasicBlock **offset_to_bb;
+       InterpBasicBlock *entry_bb;
+       MonoMemPool     *mempool;
+       GList *basic_blocks;
+       GPtrArray *relocs;
+       gboolean verbose_level;
 } TransformData;
 
 #define MINT_TYPE_I1 0
@@ -150,7 +183,7 @@ grow_code (TransformData *td)
        } while (0)
 
 static void 
-handle_branch(TransformData *td, int short_op, int long_op, int offset) 
+handle_branch (TransformData *td, int short_op, int long_op, int offset)
 {
        int shorten_branch = 0;
        int target = td->ip + offset - td->il_code;
@@ -168,12 +201,18 @@ handle_branch(TransformData *td, int short_op, int long_op, int offset)
                        shorten_branch = 1;
                }
        } else {
-               int prev = td->forward_refs [target];
-               td->forward_refs [td->ip - td->il_code] = prev;
-               td->forward_refs [target] = td->ip - td->il_code;
-               offset = 0;
+               offset = 0xffff;
                if (td->header->code_size <= 25000) /* FIX to be precise somehow? */
                        shorten_branch = 1;
+
+               Reloc *reloc = mono_mempool_alloc0 (td->mempool, sizeof (Reloc));
+               if (shorten_branch)
+                       reloc->type = RELOC_SHORT_BRANCH;
+               else
+                       reloc->type = RELOC_LONG_BRANCH;
+               reloc->offset = td->new_ip - td->new_code;
+               reloc->target = target;
+               g_ptr_array_add (td->relocs, reloc);
        }
        if (shorten_branch) {
                ADD_CODE(td, short_op);
@@ -554,11 +593,13 @@ load_local(TransformData *td, int n)
                WRITE32(td, &size);
        } else {
                g_assert (mt < MINT_TYPE_VT);
-               if (mt == MINT_TYPE_I4 && !td->is_bb_start [td->in_start - td->il_code] && td->last_new_ip != NULL &&
+               if (!td->gen_sdb_seq_points &&
+                       mt == MINT_TYPE_I4 && !td->is_bb_start [td->in_start - td->il_code] && td->last_new_ip != NULL &&
                        td->last_new_ip [0] == MINT_STLOC_I4 && td->last_new_ip [1] == offset) {
                        td->last_new_ip [0] = MINT_STLOC_NP_I4;
-               } else if (mt == MINT_TYPE_O && !td->is_bb_start [td->in_start - td->il_code] && td->last_new_ip != NULL &&
-                       td->last_new_ip [0] == MINT_STLOC_O && td->last_new_ip [1] == offset) {
+               } else if (!td->gen_sdb_seq_points &&
+                                  mt == MINT_TYPE_O && !td->is_bb_start [td->in_start - td->il_code] && td->last_new_ip != NULL &&
+                                  td->last_new_ip [0] == MINT_STLOC_O && td->last_new_ip [1] == offset) {
                        td->last_new_ip [0] = MINT_STLOC_NP_O;
                } else {
                        ADD_CODE(td, MINT_LDLOC_I1 + (mt - MINT_TYPE_I1));
@@ -696,22 +737,8 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target
                        else
                                target_method = (MonoMethod *)mono_method_get_wrapper_data (method, token);
                        csignature = mono_method_signature (target_method);
-                       if (target_method->klass == mono_defaults.string_class) {
-                               if (target_method->name [0] == 'g') {
-                                       if (strcmp (target_method->name, "get_Chars") == 0)
-                                               op = MINT_GETCHR;
-                                       else if (strcmp (target_method->name, "get_Length") == 0)
-                                               op = MINT_STRLEN;
-                               }
-                       } else if (mono_class_is_subclass_of (target_method->klass, mono_defaults.array_class, FALSE)) {
-                               if (!strcmp (target_method->name, "get_Rank")) {
-                                       op = MINT_ARRAY_RANK;
-                               } else if (!strcmp (target_method->name, "get_Length")) {
-                                       op = MINT_LDLEN;
-                               } else if (!strcmp (target_method->name, "Address")) {
-                                       op = readonly ? MINT_LDELEMA : MINT_LDELEMA_TC;
-                               }
-                       } else if (target_method && generic_context) {
+
+                       if (generic_context) {
                                csignature = mono_inflate_generic_signature (csignature, generic_context, &error);
                                mono_error_cleanup (&error); /* FIXME: don't swallow the error */
                                target_method = mono_class_inflate_generic_method_checked (target_method, generic_context, &error);
@@ -722,6 +749,33 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target
                csignature = mono_method_signature (target_method);
        }
 
+       /* Intrinsics */
+       if (target_method) {
+               if (target_method->klass == mono_defaults.string_class) {
+                       if (target_method->name [0] == 'g') {
+                               if (strcmp (target_method->name, "get_Chars") == 0)
+                                       op = MINT_GETCHR;
+                               else if (strcmp (target_method->name, "get_Length") == 0)
+                                       op = MINT_STRLEN;
+                       }
+               } else if (mono_class_is_subclass_of (target_method->klass, mono_defaults.array_class, FALSE)) {
+                       if (!strcmp (target_method->name, "get_Rank")) {
+                               op = MINT_ARRAY_RANK;
+                       } else if (!strcmp (target_method->name, "get_Length")) {
+                               op = MINT_LDLEN;
+                       } else if (!strcmp (target_method->name, "Address")) {
+                               op = readonly ? MINT_LDELEMA : MINT_LDELEMA_TC;
+                       }
+               } else if (target_method->klass->image == mono_defaults.corlib &&
+                                  (strcmp (target_method->klass->name_space, "System.Diagnostics") == 0) &&
+                                  (strcmp (target_method->klass->name, "Debugger") == 0)) {
+                       if (!strcmp (target_method->name, "Break") && csignature->param_count == 0) {
+                               if (mini_should_insert_breakpoint (method))
+                                       op = MINT_BREAK;
+                       }
+               }
+       }
+
        if (constrained_class) {
                if (constrained_class->enumtype && !strcmp (target_method->name, "GetHashCode")) {
                        /* Use the corresponding method from the base type to avoid boxing */
@@ -793,7 +847,7 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target
                mono_class_init (target_method->klass);
 
        CHECK_STACK (td, csignature->param_count + csignature->hasthis);
-       if (!calli && (!virtual || (target_method->flags & METHOD_ATTRIBUTE_VIRTUAL) == 0) &&
+       if (!calli && op == -1 && (!virtual || (target_method->flags & METHOD_ATTRIBUTE_VIRTUAL) == 0) &&
                (target_method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) == 0 && 
                (target_method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) == 0 &&
                !(target_method->iflags & METHOD_IMPL_ATTRIBUTE_NOINLINING)) {
@@ -802,7 +856,7 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target
 
                if (/*mono_metadata_signature_equal (method->signature, target_method->signature) */ method == target_method && *(td->ip + 5) == CEE_RET) {
                        int offset;
-                       if (mono_interp_traceopt)
+                       if (td->verbose_level)
                                g_print ("Optimize tail call of %s.%s\n", target_method->klass->name, target_method->name);
 
                        for (i = csignature->param_count - 1 + !!csignature->hasthis; i >= 0; --i)
@@ -818,7 +872,7 @@ interp_transform_call (TransformData *td, MonoMethod *method, MonoMethod *target
                } else {
                        /* mheader might not exist if this is a delegate invoc, etc */
                        if (mheader && *mheader->code == CEE_RET && called_inited) {
-                               if (mono_interp_traceopt)
+                               if (td->verbose_level)
                                        g_print ("Inline (empty) call of %s.%s\n", target_method->klass->name, target_method->name);
                                for (i = 0; i < csignature->param_count; i++) {
                                        ADD_CODE (td, MINT_POP); /*FIX: vt */
@@ -926,6 +980,109 @@ interp_field_from_token (MonoMethod *method, guint32 token, MonoClass **klass, M
        return field;
 }
 
+static InterpBasicBlock*
+get_bb (TransformData *td, InterpBasicBlock *cbb, unsigned char *ip)
+{
+       int offset = ip - td->il_code;
+       InterpBasicBlock *bb = td->offset_to_bb [offset];
+
+       if (!bb) {
+               bb = mono_mempool_alloc0 (td->mempool, sizeof (InterpBasicBlock));
+               bb->ip = ip;
+               td->offset_to_bb [offset] = bb;
+
+               td->basic_blocks = g_list_append_mempool (td->mempool, td->basic_blocks, bb);
+       }
+
+       if (cbb)
+               bb->preds = g_slist_prepend_mempool (td->mempool, bb->preds, cbb);
+       return bb;
+}
+
+/*
+ * get_basic_blocks:
+ *
+ *   Compute the set of IL level basic blocks.
+ */
+static void
+get_basic_blocks (TransformData *td)
+{
+       guint8 *start = (guint8*)td->il_code;
+       guint8 *end = (guint8*)td->il_code + td->code_size;
+       guint8 *ip = start;
+       unsigned char *target;
+       int i;
+       guint cli_addr;
+       const MonoOpcode *opcode;
+       InterpBasicBlock *cbb;
+
+       td->offset_to_bb = mono_mempool_alloc0 (td->mempool, sizeof (InterpBasicBlock*) * (end - start + 1));
+       td->entry_bb = cbb = get_bb (td, NULL, start);
+
+       while (ip < end) {
+               cli_addr = ip - start;
+               td->offset_to_bb [cli_addr] = cbb;
+               i = mono_opcode_value ((const guint8 **)&ip, end);
+               opcode = &mono_opcodes [i];
+               switch (opcode->argument) {
+               case MonoInlineNone:
+                       ip++;
+                       break;
+               case MonoInlineString:
+               case MonoInlineType:
+               case MonoInlineField:
+               case MonoInlineMethod:
+               case MonoInlineTok:
+               case MonoInlineSig:
+               case MonoShortInlineR:
+               case MonoInlineI:
+                       ip += 5;
+                       break;
+               case MonoInlineVar:
+                       ip += 3;
+                       break;
+               case MonoShortInlineVar:
+               case MonoShortInlineI:
+                       ip += 2;
+                       break;
+               case MonoShortInlineBrTarget:
+                       target = start + cli_addr + 2 + (signed char)ip [1];
+                       get_bb (td, cbb, target);
+                       ip += 2;
+                       cbb = get_bb (td, cbb, ip);
+                       break;
+               case MonoInlineBrTarget:
+                       target = start + cli_addr + 5 + (gint32)read32 (ip + 1);
+                       get_bb (td, cbb, target);
+                       ip += 5;
+                       cbb = get_bb (td, cbb, ip);
+                       break;
+               case MonoInlineSwitch: {
+                       guint32 n = read32 (ip + 1);
+                       guint32 j;
+                       ip += 5;
+                       cli_addr += 5 + 4 * n;
+                       target = start + cli_addr;
+                       get_bb (td, cbb, target);
+
+                       for (j = 0; j < n; ++j) {
+                               target = start + cli_addr + (gint32)read32 (ip);
+                               get_bb (td, cbb, target);
+                               ip += 4;
+                       }
+                       cbb = get_bb (td, cbb, ip);
+                       break;
+               }
+               case MonoInlineR:
+               case MonoInlineI8:
+                       ip += 9;
+                       break;
+               default:
+                       g_assert_not_reached ();
+               }
+       }
+}
+
 static void
 interp_save_debug_info (RuntimeMethod *rtm, MonoMethodHeader *header, TransformData *td, GArray *line_numbers)
 {
@@ -940,14 +1097,26 @@ interp_save_debug_info (RuntimeMethod *rtm, MonoMethodHeader *header, TransformD
         */
 
        dinfo = g_new0 (MonoDebugMethodJitInfo, 1);
+       dinfo->num_params = rtm->param_count;
+       dinfo->params = g_new0 (MonoDebugVarInfo, dinfo->num_params);
        dinfo->num_locals = header->num_locals;
        dinfo->locals = g_new0 (MonoDebugVarInfo, header->num_locals);
        dinfo->code_start = (guint8*)rtm->code;
        dinfo->code_size = td->new_ip - td->new_code;
        dinfo->epilogue_begin = 0;
-       dinfo->has_var_info = FALSE;
+       dinfo->has_var_info = TRUE;
        dinfo->num_line_numbers = line_numbers->len;
        dinfo->line_numbers = g_new0 (MonoDebugLineNumberEntry, dinfo->num_line_numbers);
+
+       for (i = 0; i < dinfo->num_params; i++) {
+               MonoDebugVarInfo *var = &dinfo->params [i];
+               var->type = rtm->param_types [i];
+       }
+       for (i = 0; i < dinfo->num_locals; i++) {
+               MonoDebugVarInfo *var = &dinfo->locals [i];
+               var->type = header->locals [i];
+       }
+
        for (i = 0; i < dinfo->num_line_numbers; i++)
                dinfo->line_numbers [i] = g_array_index (line_numbers, MonoDebugLineNumberEntry, i);
        mono_debug_add_method (rtm->method, dinfo, mono_domain_get ());
@@ -955,6 +1124,201 @@ interp_save_debug_info (RuntimeMethod *rtm, MonoMethodHeader *header, TransformD
        mono_debug_free_method_jit_info (dinfo);
 }
 
+/* Same as the code in seq-points.c */
+static void
+insert_pred_seq_point (SeqPoint *last_sp, SeqPoint *sp, GSList **next)
+{
+       GSList *l;
+       int src_index = last_sp->next_offset;
+       int dst_index = sp->next_offset;
+
+       /* bb->in_bb might contain duplicates */
+       for (l = next [src_index]; l; l = l->next)
+               if (GPOINTER_TO_UINT (l->data) == dst_index)
+                       break;
+       if (!l)
+               next [src_index] = g_slist_append (next [src_index], GUINT_TO_POINTER (dst_index));
+}
+
+static void
+recursively_make_pred_seq_points (TransformData *td, InterpBasicBlock *bb)
+{
+       const gpointer MONO_SEQ_SEEN_LOOP = GINT_TO_POINTER(-1);
+       GSList *l;
+
+       GArray *predecessors = g_array_new (FALSE, TRUE, sizeof (gpointer));
+       GHashTable *seen = g_hash_table_new_full (g_direct_hash, NULL, NULL, NULL);
+
+       // Insert/remove sentinel into the memoize table to detect loops containing bb
+       bb->pred_seq_points = MONO_SEQ_SEEN_LOOP;
+
+       for (l = bb->preds; l; l = l->next) {
+               InterpBasicBlock *in_bb = l->data;
+
+               // This bb has the last seq point, append it and continue
+               if (in_bb->last_seq_point != NULL) {
+                       predecessors = g_array_append_val (predecessors, in_bb->last_seq_point);
+                       continue;
+               }
+
+               // We've looped or handled this before, exit early.
+               // No last sequence points to find.
+               if (in_bb->pred_seq_points == MONO_SEQ_SEEN_LOOP)
+                       continue;
+
+               // Take sequence points from incoming basic blocks
+
+               if (in_bb == td->entry_bb)
+                       continue;
+
+               if (in_bb->pred_seq_points == NULL)
+                       recursively_make_pred_seq_points (td, in_bb);
+
+               // Union sequence points with incoming bb's
+               for (int i=0; i < in_bb->num_pred_seq_points; i++) {
+                       if (!g_hash_table_lookup (seen, in_bb->pred_seq_points [i])) {
+                               g_array_append_val (predecessors, in_bb->pred_seq_points [i]);
+                               g_hash_table_insert (seen, in_bb->pred_seq_points [i], (gpointer)&MONO_SEQ_SEEN_LOOP);
+                       }
+               }
+               // predecessors = g_array_append_vals (predecessors, in_bb->pred_seq_points, in_bb->num_pred_seq_points);
+       }
+
+       g_hash_table_destroy (seen);
+
+       if (predecessors->len != 0) {
+               bb->pred_seq_points = mono_mempool_alloc0 (td->mempool, sizeof (SeqPoint *) * predecessors->len);
+               bb->num_pred_seq_points = predecessors->len;
+
+               for (int newer = 0; newer < bb->num_pred_seq_points; newer++) {
+                       bb->pred_seq_points [newer] = g_array_index (predecessors, gpointer, newer);
+               }
+       }
+
+       g_array_free (predecessors, TRUE);
+}
+
+static void
+collect_pred_seq_points (TransformData *td, InterpBasicBlock *bb, SeqPoint *seqp, GSList **next)
+{
+       // Doesn't have a last sequence point, must find from incoming basic blocks
+       if (bb->pred_seq_points == NULL && bb != td->entry_bb)
+               recursively_make_pred_seq_points (td, bb);
+
+       for (int i = 0; i < bb->num_pred_seq_points; i++)
+               insert_pred_seq_point (bb->pred_seq_points [i], seqp, next);
+
+       return;
+}
+
+static void
+save_seq_points (TransformData *td)
+{
+       RuntimeMethod *rtm = td->rtm;
+       GByteArray *array;
+       int i, seq_info_size;
+       MonoSeqPointInfo *info;
+       MonoDomain *domain = mono_domain_get ();
+       GSList **next = NULL;
+       GList *bblist;
+
+       if (!td->gen_sdb_seq_points)
+               return;
+
+       /*
+        * For each sequence point, compute the list of sequence points immediately
+        * following it, this is needed to implement 'step over' in the debugger agent.
+        * Similar to the code in mono_save_seq_point_info ().
+        */
+       for (i = 0; i < td->seq_points->len; ++i) {
+               SeqPoint *sp = g_ptr_array_index (td->seq_points, i);
+
+               /* Store the seq point index here temporarily */
+               sp->next_offset = i;
+       }
+       next = mono_mempool_alloc0 (td->mempool, sizeof (GList*) * td->seq_points->len);
+       for (bblist = td->basic_blocks; bblist; bblist = bblist->next) {
+               InterpBasicBlock *bb = bblist->data;
+
+               GSList *bb_seq_points = g_slist_reverse (bb->seq_points);
+               SeqPoint *last = NULL;
+               for (GSList *l = bb_seq_points; l; l = l->next) {
+                       SeqPoint *sp = l->data;
+
+                       if (sp->il_offset == METHOD_ENTRY_IL_OFFSET || sp->il_offset == METHOD_EXIT_IL_OFFSET)
+                               /* Used to implement method entry/exit events */
+                               continue;
+
+                       if (last != NULL) {
+                               /* Link with the previous seq point in the same bb */
+                               next [last->next_offset] = g_slist_append_mempool (td->mempool, next [last->next_offset], GINT_TO_POINTER (sp->next_offset));
+                       } else {
+                               /* Link with the last bb in the previous bblocks */
+                               collect_pred_seq_points (td, bb, sp, next);
+                       }
+                       last = sp;
+               }
+       }
+
+       /* Serialize the seq points into a byte array */
+       array = g_byte_array_new ();
+       SeqPoint zero_seq_point = {0};
+       SeqPoint* last_seq_point = &zero_seq_point;
+       for (i = 0; i < td->seq_points->len; ++i) {
+               SeqPoint *sp = (SeqPoint*)g_ptr_array_index (td->seq_points, i);
+
+               sp->next_offset = 0;
+               if (mono_seq_point_info_add_seq_point (array, sp, last_seq_point, next [i], TRUE))
+                       last_seq_point = sp;
+       }
+
+       if (td->verbose_level) {
+               g_print ("\nSEQ POINT MAP FOR %s: \n", td->method->name);
+
+               for (i = 0; i < td->seq_points->len; ++i) {
+                       SeqPoint *sp = (SeqPoint*)g_ptr_array_index (td->seq_points, i);
+                       GSList *l;
+
+                       if (!next [i])
+                               continue;
+
+                       g_print ("\tIL0x%x[0x%0x] ->", sp->il_offset, sp->native_offset);
+                       for (l = next [i]; l; l = l->next) {
+                               int next_index = GPOINTER_TO_UINT (l->data);
+                               g_print (" IL0x%x", ((SeqPoint*)g_ptr_array_index (td->seq_points, next_index))->il_offset);
+                       }
+                       g_print ("\n");
+               }
+       }
+
+       info = mono_seq_point_info_new (array->len, TRUE, array->data, TRUE, &seq_info_size);
+       mono_jit_stats.allocated_seq_points_size += seq_info_size;
+
+       g_byte_array_free (array, TRUE);
+
+       mono_domain_lock (domain);
+       g_hash_table_insert (domain_jit_info (domain)->seq_points, rtm->method, info);
+       mono_domain_unlock (domain);
+}
+
+static void
+emit_seq_point (TransformData *td, int il_offset, InterpBasicBlock *cbb, gboolean nonempty_stack)
+{
+       SeqPoint *seqp;
+
+       seqp = mono_mempool_alloc0 (td->mempool, sizeof (SeqPoint));
+       seqp->il_offset = il_offset;
+       seqp->native_offset = (guint8*)td->new_ip - (guint8*)td->new_code;
+       if (nonempty_stack)
+               seqp->flags |= MONO_SEQ_POINT_FLAG_NONEMPTY_STACK;
+
+       ADD_CODE (td, MINT_SDB_SEQ_POINT);
+       g_ptr_array_add (td->seq_points, seqp);
+
+       cbb->seq_points = g_slist_prepend_mempool (td->mempool, cbb->seq_points, seqp);
+       cbb->last_seq_point = seqp;
+}
+
 static void
 generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, MonoGenericContext *generic_context)
 {
@@ -976,8 +1340,20 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
        TransformData td;
        int generating_code = 1;
        GArray *line_numbers;
+       MonoDebugMethodInfo *minfo;
+       MonoBitSet *seq_point_locs = NULL;
+       MonoBitSet *seq_point_set_locs = NULL;
+       gboolean sym_seq_points = FALSE;
+       InterpBasicBlock *bb_exit = NULL;
+       static gboolean verbose_method_inited;
+       static char* verbose_method_name;
+
+       if (!verbose_method_inited) {
+               verbose_method_name = getenv ("MONO_VERBOSE_METHOD");
+               verbose_method_inited = TRUE;
+       }
 
-       memset(&td, 0, sizeof(td));
+       memset (&td, 0, sizeof(td));
        td.method = method;
        td.rtm = rtm;
        td.is_bb_start = is_bb_start;
@@ -987,8 +1363,8 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
        td.max_code_size = td.code_size;
        td.new_code = (unsigned short *)g_malloc(td.max_code_size * sizeof(gushort));
        td.new_code_end = td.new_code + td.max_code_size;
+       td.mempool = mono_mempool_new ();
        td.in_offsets = g_malloc0(header->code_size * sizeof(int));
-       td.forward_refs = g_malloc(header->code_size * sizeof(int));
        td.stack_state = g_malloc0(header->code_size * sizeof(StackInfo *));
        td.stack_height = g_malloc(header->code_size * sizeof(int));
        td.vt_stack_size = g_malloc(header->code_size * sizeof(int));
@@ -997,12 +1373,61 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
        td.data_items = NULL;
        td.data_hash = g_hash_table_new (NULL, NULL);
        td.clause_indexes = g_malloc (header->code_size * sizeof (int));
+       td.gen_sdb_seq_points = debug_options.gen_sdb_seq_points;
+       td.seq_points = g_ptr_array_new ();
+       td.relocs = g_ptr_array_new ();
+       td.verbose_level = mono_interp_traceopt;
        rtm->data_items = td.data_items;
        for (i = 0; i < header->code_size; i++) {
-               td.forward_refs [i] = -1;
                td.stack_height [i] = -1;
                td.clause_indexes [i] = -1;
        }
+
+       if (verbose_method_name) {
+               const char *name = verbose_method_name;
+
+               if ((strchr (name, '.') > name) || strchr (name, ':')) {
+                       MonoMethodDesc *desc;
+
+                       desc = mono_method_desc_new (name, TRUE);
+                       if (mono_method_desc_full_match (desc, method)) {
+                               td.verbose_level = 4;
+                       }
+                       mono_method_desc_free (desc);
+               } else {
+                       if (strcmp (method->name, name) == 0)
+                               td.verbose_level = 4;
+               }
+       }
+
+       if (td.gen_sdb_seq_points) {
+               get_basic_blocks (&td);
+
+               minfo = mono_debug_lookup_method (method);
+
+               if (minfo) {
+                       MonoSymSeqPoint *sps;
+                       int i, n_il_offsets;
+
+                       mono_debug_get_seq_points (minfo, NULL, NULL, NULL, &sps, &n_il_offsets);
+                       // FIXME: Free
+                       seq_point_locs = mono_bitset_mem_new (mono_mempool_alloc0 (td.mempool, mono_bitset_alloc_size (header->code_size, 0)), header->code_size, 0);
+                       seq_point_set_locs = mono_bitset_mem_new (mono_mempool_alloc0 (td.mempool, mono_bitset_alloc_size (header->code_size, 0)), header->code_size, 0);
+                       sym_seq_points = TRUE;
+
+                       for (i = 0; i < n_il_offsets; ++i) {
+                               if (sps [i].il_offset < header->code_size)
+                                       mono_bitset_set_fast (seq_point_locs, sps [i].il_offset);
+                       }
+                       g_free (sps);
+               } else if (!method->wrapper_type && !method->dynamic && mono_debug_image_has_debug_info (method->klass->image)) {
+                       /* Methods without line number info like auto-generated property accessors */
+                       seq_point_locs = mono_bitset_new (header->code_size, 0);
+                       seq_point_set_locs = mono_bitset_new (header->code_size, 0);
+                       sym_seq_points = TRUE;
+               }
+       }
+
        td.new_ip = td.new_code;
        td.last_new_ip = NULL;
 
@@ -1045,7 +1470,7 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
        td.ip = header->code;
        end = td.ip + header->code_size;
 
-       if (mono_interp_traceopt) {
+       if (td.verbose_level) {
                char *tmp = mono_disasm_code (NULL, method, td.ip, end);
                char *name = mono_method_full_name (method, TRUE);
                g_print ("Method %s, original code:\n", name);
@@ -1069,6 +1494,12 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
                }
        }
 
+       if (sym_seq_points) {
+               InterpBasicBlock *cbb = td.offset_to_bb [0];
+               g_assert (cbb);
+               emit_seq_point (&td, METHOD_ENTRY_IL_OFFSET, cbb, FALSE);
+       }
+
        while (td.ip < end) {
                int in_offset;
 
@@ -1080,38 +1511,10 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
                td.in_start = td.ip;
 
                MonoDebugLineNumberEntry lne;
-               lne.native_offset = td.new_ip - td.new_code;
-               lne.il_offset = td.ip - header->code;
+               lne.native_offset = (guint8*)td.new_ip - (guint8*)td.new_code;
+               lne.il_offset = in_offset;
                g_array_append_val (line_numbers, lne);
 
-               while (td.forward_refs [in_offset] >= 0) {
-                       int j = td.forward_refs [in_offset];
-                       int slot;
-                       td.forward_refs [in_offset] = td.forward_refs [j];
-                       if (td.in_offsets [j] < 0) {                        
-                               int old_switch_offset = -td.in_offsets [j];
-                               int new_switch_offset = td.in_offsets [old_switch_offset];
-                               int switch_case = (j - old_switch_offset - 5) / 4;
-                               int n_cases = read32 (header->code + old_switch_offset + 1);
-                               offset = (td.new_ip - td.new_code) - (new_switch_offset + 2 * n_cases + 3);
-                               slot = new_switch_offset + 3 + 2 * switch_case;
-                               td.new_code [slot] = * (unsigned short *)(&offset);
-                               td.new_code [slot + 1] = * ((unsigned short *)&offset + 1);
-                       } else {
-                               int op = td.new_code [td.in_offsets [j]];
-                               if (mono_interp_opargtype [op] == MintOpShortBranch) {
-                                       offset = (td.new_ip - td.new_code) - td.in_offsets [j];
-                                       g_assert (offset <= 32767);
-                                       slot = td.in_offsets [j] + 1;
-                                       td.new_code [slot] = offset;
-                               } else {
-                                       offset = (td.new_ip - td.new_code) - td.in_offsets [j];
-                                       slot = td.in_offsets [j] + 1;
-                                       td.new_code [slot] = * (unsigned short *)(&offset);
-                                       td.new_code [slot + 1] = * ((unsigned short *)&offset + 1);
-                               }
-                       }
-               }
                if (td.stack_height [in_offset] >= 0) {
                        g_assert (is_bb_start [in_offset]);
                        if (td.stack_height [in_offset] > 0)
@@ -1127,7 +1530,7 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
                                ++td.ip;
                        continue;
                }
-               if (mono_interp_traceopt > 1) {
+               if (td.verbose_level > 1) {
                        printf("IL_%04lx %s %-10s -> IL_%04lx, sp %ld, %s %-12s vt_sp %u (max %u)\n", 
                                td.ip - td.il_code,
                                td.is_bb_start [td.ip - td.il_code] == 3 ? "<>" :
@@ -1138,6 +1541,26 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
                                (td.sp > td.stack && (td.sp [-1].type == STACK_TYPE_O || td.sp [-1].type == STACK_TYPE_VT)) ? (td.sp [-1].klass == NULL ? "?" : td.sp [-1].klass->name) : "",
                                td.vt_sp, td.max_vt_sp);
                }
+
+               if (sym_seq_points && mono_bitset_test_fast (seq_point_locs, td.ip - header->code)) {
+                       InterpBasicBlock *cbb = td.offset_to_bb [td.ip - header->code];
+                       g_assert (cbb);
+
+                       /*
+                        * Make methods interruptable at the beginning, and at the targets of
+                        * backward branches.
+                        */
+                       if (in_offset == 0 || g_slist_length (cbb->preds) > 1)
+                               ADD_CODE (&td, MINT_SDB_INTR_LOC);
+
+                       emit_seq_point (&td, in_offset, cbb, FALSE);
+
+                       mono_bitset_set_fast (seq_point_set_locs, td.ip - header->code);
+               }
+
+               if (sym_seq_points)
+                       bb_exit = td.offset_to_bb [td.ip - header->code];
+
                switch (*td.ip) {
                case CEE_NOP: 
                        /* lose it */
@@ -1318,7 +1741,20 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
                case CEE_CALLVIRT: /* Fall through */
                case CEE_CALLI:    /* Fall through */
                case CEE_CALL: {
+                       gboolean need_seq_point = FALSE;
+
+                       if (sym_seq_points && !mono_bitset_test_fast (seq_point_locs, td.ip + 5 - header->code))
+                               need_seq_point = TRUE;
+
                        interp_transform_call (&td, method, NULL, domain, generic_context, is_bb_start, body_start_offset, constrained_class, readonly);
+
+                       if (need_seq_point) {
+                               InterpBasicBlock *cbb = td.offset_to_bb [td.ip - header->code];
+                               g_assert (cbb);
+
+                               emit_seq_point (&td, td.ip - header->code, cbb, TRUE);
+                       }
+
                        constrained_class = NULL;
                        readonly = FALSE;
                        break;
@@ -1337,6 +1773,13 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
                                g_warning ("%s.%s: CEE_RET: more values on stack: %d", td.method->klass->name, td.method->name, td.sp - td.stack);
                        if (td.vt_sp != vt_size)
                                g_error ("%s.%s: CEE_RET: value type stack: %d vs. %d", td.method->klass->name, td.method->name, td.vt_sp, vt_size);
+
+                       if (sym_seq_points) {
+                               InterpBasicBlock *cbb = td.offset_to_bb [td.ip - header->code];
+                               g_assert (cbb);
+                               emit_seq_point (&td, METHOD_EXIT_IL_OFFSET, bb_exit, FALSE);
+                       }
+
                        if (vt_size == 0)
                                SIMPLE_OP(td, signature->ret->type == MONO_TYPE_VOID ? MINT_RET_VOID : MINT_RET);
                        else {
@@ -1456,15 +1899,12 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
                case CEE_SWITCH: {
                        guint32 n;
                        const unsigned char *next_ip;
-                       const unsigned char *base_ip = td.ip;
-                       unsigned short *next_new_ip;
                        ++td.ip;
                        n = read32 (td.ip);
                        ADD_CODE (&td, MINT_SWITCH);
                        WRITE32 (&td, &n);
                        td.ip += 4;
                        next_ip = td.ip + n * 4;
-                       next_new_ip = td.new_ip + n * 2;
                        --td.sp;
                        int stack_height = td.sp - td.stack;
                        for (i = 0; i < n; i++) {
@@ -1475,16 +1915,19 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
                                        if (stack_height > 0 && stack_height != td.stack_height [target])
                                                g_warning ("SWITCH with back branch and non-empty stack");
 #endif
-                                       target = td.in_offsets [target] - (next_new_ip - td.new_code);
+                                       target = td.in_offsets [target] - (td.new_ip - td.new_code);
                                } else {
                                        td.stack_height [target] = stack_height;
                                        td.vt_stack_size [target] = td.vt_sp;
                                        if (stack_height > 0)
                                                td.stack_state [target] = g_memdup (td.stack, stack_height * sizeof (td.stack [0]));
-                                       int prev = td.forward_refs [target];
-                                       td.forward_refs [td.ip - td.il_code] = prev;
-                                       td.forward_refs [target] = td.ip - td.il_code;
-                                       td.in_offsets [td.ip - td.il_code] = - (base_ip - td.il_code);
+
+                                       Reloc *reloc = mono_mempool_alloc0 (td.mempool, sizeof (Reloc));
+                                       reloc->type = RELOC_SWITCH;
+                                       reloc->offset = td.new_ip - td.new_code;
+                                       reloc->target = target;
+                                       g_ptr_array_add (td.relocs, reloc);
+                                       target = 0xffff;
                                }
                                WRITE32 (&td, &target);
                                td.ip += 4;
@@ -1942,12 +2385,13 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
                        MonoString *s;
                        token = mono_metadata_token_index (read32 (td.ip + 1));
                        td.ip += 5;
-                       if (method->wrapper_type != MONO_WRAPPER_NONE) {
-                               s = mono_string_new_wrapper(
-                                       mono_method_get_wrapper_data (method, token));
-                       }
-                       else
+                       if (method->wrapper_type == MONO_WRAPPER_DYNAMIC_METHOD) {
+                               s = mono_method_get_wrapper_data (method, token);
+                       } else if (method->wrapper_type != MONO_WRAPPER_NONE) {
+                               s = mono_string_new_wrapper (mono_method_get_wrapper_data (method, token));
+                       } else {
                                s = mono_ldstr (domain, image, token);
+                       }
                        ADD_CODE(&td, MINT_LDSTR);
                        ADD_CODE(&td, get_data_item_index (&td, s));
                        PUSH_TYPE(&td, STACK_TYPE_O, mono_defaults.string_class);
@@ -3237,8 +3681,7 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
                                ++td.ip;
                                break;
                        case CEE_UNALIGNED_:
-                               ++td.ip;
-                               /* FIX: should do something? */;
+                               td.ip += 2;
                                break;
                        case CEE_VOLATILE_:
                                ++td.ip;
@@ -3342,9 +3785,35 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
                td.last_ip = td.in_start;
        }
 
-       if (mono_interp_traceopt) {
+       /* Handle relocations */
+       for (int i = 0; i < td.relocs->len; ++i) {
+               Reloc *reloc = g_ptr_array_index (td.relocs, i);
+
+               int offset = td.in_offsets [reloc->target] - reloc->offset;
+
+               switch (reloc->type) {
+               case RELOC_SHORT_BRANCH:
+                       g_assert (td.new_code [reloc->offset + 1] == 0xffff);
+                       td.new_code [reloc->offset + 1] = offset;
+                       break;
+               case RELOC_LONG_BRANCH:
+                       g_assert_not_reached ();
+                       break;
+               case RELOC_SWITCH: {
+                       guint16 *v = (guint16*)&offset;
+                       td.new_code [reloc->offset] = *(guint16*)v;
+                       td.new_code [reloc->offset + 1] = *(guint16*)(v + 1);
+                       break;
+               }
+               default:
+                       g_assert_not_reached ();
+                       break;
+               }
+       }
+
+       if (td.verbose_level) {
                const guint16 *p = td.new_code;
-               printf("Runtime method: %p, VT stack size: %d\n", rtm, td.max_vt_sp);
+               printf("Runtime method: %s %p, VT stack size: %d\n", mono_method_full_name (method, TRUE), rtm, td.max_vt_sp);
                printf("Calculated stack size: %d, stated size: %d\n", td.max_stack_height, header->max_stack);
                while (p < td.new_ip) {
                        p = mono_interp_dis_mintop(td.new_code, p);
@@ -3384,6 +3853,7 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
        /* Create a MonoJitInfo for the interpreted method by creating the interpreter IR as the native code. */
        int jinfo_len = mono_jit_info_size (0, header->num_clauses, 0);
        MonoJitInfo *jinfo = (MonoJitInfo *)mono_domain_alloc0 (domain, jinfo_len);
+       jinfo->is_interp = 1;
        rtm->jinfo = jinfo;
        mono_jit_info_init (jinfo, method, (guint8*)rtm->code, code_len, 0, header->num_clauses, 0);
        for (i = 0; i < jinfo->num_clauses; ++i) {
@@ -3391,17 +3861,18 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
                MonoExceptionClause *c = rtm->clauses + i;
 
                ei->flags = c->flags;
-               ei->try_start = rtm->code + c->try_offset;
-               ei->try_end = rtm->code + c->try_offset + c->try_len;
-               ei->handler_start = rtm->code + c->handler_offset;
+               ei->try_start = (guint8*)(rtm->code + c->try_offset);
+               ei->try_end = (guint8*)(rtm->code + c->try_offset + c->try_len);
+               ei->handler_start = (guint8*)(rtm->code + c->handler_offset);
                if (ei->flags == MONO_EXCEPTION_CLAUSE_FILTER || ei->flags == MONO_EXCEPTION_CLAUSE_FINALLY) {
                } else {
                        ei->data.catch_class = c->data.catch_class;
                }
        }
 
+       save_seq_points (&td);
+
        g_free (td.in_offsets);
-       g_free (td.forward_refs);
        for (i = 0; i < header->code_size; ++i)
                g_free (td.stack_state [i]);
        g_free (td.stack_state);
@@ -3411,7 +3882,10 @@ generate (MonoMethod *method, RuntimeMethod *rtm, unsigned char *is_bb_start, Mo
        g_free (td.stack);
        g_hash_table_destroy (td.data_hash);
        g_free (td.clause_indexes);
+       g_ptr_array_free (td.seq_points, TRUE);
        g_array_free (line_numbers, TRUE);
+       g_ptr_array_free (td.relocs, TRUE);
+       mono_mempool_destroy (td.mempool);
 }
 
 static mono_mutex_t calc_section;
@@ -3482,7 +3956,7 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont
                mono_os_mutex_lock(&calc_section);
                if (runtime_method->transformed) {
                        mono_os_mutex_unlock(&calc_section);
-                       mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_OK);
+                       mono_profiler_method_end_jit (method, runtime_method->jinfo, MONO_PROFILE_OK);
                        return NULL;
                }
 
@@ -3657,7 +4131,7 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont
        if (runtime_method->transformed) {
                mono_os_mutex_unlock(&calc_section);
                g_free (is_bb_start);
-               mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_OK);
+               mono_profiler_method_end_jit (method, runtime_method->jinfo, MONO_PROFILE_OK);
                return NULL;
        }
 
@@ -3708,7 +4182,8 @@ mono_interp_transform_method (RuntimeMethod *runtime_method, ThreadContext *cont
 
        g_free (is_bb_start);
 
-       mono_profiler_method_end_jit (method, NULL, MONO_PROFILE_OK);
+       // FIXME: Add a different callback ?
+       mono_profiler_method_end_jit (method, runtime_method->jinfo, MONO_PROFILE_OK);
        runtime_method->transformed = TRUE;
        mono_os_mutex_unlock(&calc_section);
 
index 401ac247e2a0569fb100aa530f9df08cb1682c03..648e69cf18cc49cff4c27e6ee517637df2d83a68 100644 (file)
@@ -1458,11 +1458,15 @@ mono_generic_class_init (MonoVTable *vtable)
 }
 
 void
-ves_icall_mono_delegate_ctor (MonoObject *this_obj, MonoObject *target, gpointer addr)
+ves_icall_mono_delegate_ctor (MonoObject *this_obj_raw, MonoObject *target_raw, gpointer addr)
 {
+       HANDLE_FUNCTION_ENTER ();
        MonoError error;
+       MONO_HANDLE_DCL (MonoObject, this_obj);
+       MONO_HANDLE_DCL (MonoObject, target);
        mono_delegate_ctor (this_obj, target, addr, &error);
        mono_error_set_pending_exception (&error);
+       HANDLE_FUNCTION_RETURN ();
 }
 
 gpointer
index f20d6790eea5bb45770d5d44fab00404aedbbbcb..6a6e11006cc0d395d8cd093cb51f6f667547cc98 100644 (file)
@@ -8,22 +8,25 @@
 
 #ifndef DISABLE_JIT
 
+#include <mono/metadata/gc-internals.h>
 #include <mono/utils/mono-memory-model.h>
 
 #include "mini.h"
 #include "ir-emit.h"
+#include "jit-icalls.h"
 
 #define MAX_INLINE_COPIES 10
+#define MAX_INLINE_COPY_SIZE 10000
 
 void 
 mini_emit_memset (MonoCompile *cfg, int destreg, int offset, int size, int val, int align)
 {
        int val_reg;
 
+       /*FIXME arbitrary hack to avoid unbound code expansion.*/
+       g_assert (size < MAX_INLINE_COPY_SIZE);
        g_assert (val == 0);
-
-       if (align == 0)
-               align = 4;
+       g_assert (align > 0);
 
        if ((size <= SIZEOF_REGISTER) && (size <= align)) {
                switch (size) {
@@ -51,39 +54,51 @@ mini_emit_memset (MonoCompile *cfg, int destreg, int offset, int size, int val,
        else
                MONO_EMIT_NEW_ICONST (cfg, val_reg, val);
 
-       if (align < 4) {
-               /* This could be optimized further if neccesary */
-               while (size >= 1) {
-                       MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, destreg, offset, val_reg);
-                       offset += 1;
-                       size -= 1;
-               }
-               return;
-       }       
-
-       if (!cfg->backend->no_unaligned_access && SIZEOF_REGISTER == 8) {
-               if (offset % 8) {
-                       MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, destreg, offset, val_reg);
-                       offset += 4;
-                       size -= 4;
-               }
+       if (align < SIZEOF_VOID_P) {
+               if (align % 2 == 1)
+                       goto set_1;
+               if (align % 4 == 2)
+                       goto set_2;
+               if (SIZEOF_VOID_P == 8 && align % 8 == 4)
+                       goto set_4;
+       }
+
+       //Unaligned offsets don't naturaly happen in the runtime, so it's ok to be conservative in how we copy
+       //We assume that input src and dest are be aligned to `align` so offset just worsen it
+       int offsets_mask = offset & 0x7; //we only care about the misalignment part
+       if (offsets_mask) {
+               if (offsets_mask % 2 == 1)
+                       goto set_1;
+               if (offsets_mask % 4 == 2)
+                       goto set_2;
+               if (SIZEOF_VOID_P == 8 && offsets_mask % 8 == 4)
+                       goto set_4;
+       }
+
+       if (SIZEOF_REGISTER == 8) {
                while (size >= 8) {
                        MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI8_MEMBASE_REG, destreg, offset, val_reg);
                        offset += 8;
                        size -= 8;
                }
-       }       
+       }
 
+set_4:
        while (size >= 4) {
                MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, destreg, offset, val_reg);
                offset += 4;
                size -= 4;
        }
+
+
+set_2:
        while (size >= 2) {
                MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI2_MEMBASE_REG, destreg, offset, val_reg);
                offset += 2;
                size -= 2;
        }
+
+set_1:
        while (size >= 1) {
                MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, destreg, offset, val_reg);
                offset += 1;
@@ -96,25 +111,32 @@ mini_emit_memcpy (MonoCompile *cfg, int destreg, int doffset, int srcreg, int so
 {
        int cur_reg;
 
-       if (align == 0)
-               align = 4;
-
        /*FIXME arbitrary hack to avoid unbound code expansion.*/
-       g_assert (size < 10000);
+       g_assert (size < MAX_INLINE_COPY_SIZE);
+       g_assert (align > 0);
+
+       if (align < SIZEOF_VOID_P) {
+               if (align == 4)
+                       goto copy_4;
+               if (align == 2)
+                       goto copy_2;
+               goto copy_1;
+       }
 
-       if (align < 4) {
-               /* This could be optimized further if neccesary */
-               while (size >= 1) {
-                       cur_reg = alloc_preg (cfg);
-                       MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI1_MEMBASE, cur_reg, srcreg, soffset);
-                       MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, destreg, doffset, cur_reg);
-                       doffset += 1;
-                       soffset += 1;
-                       size -= 1;
-               }
+       //Unaligned offsets don't naturaly happen in the runtime, so it's ok to be conservative in how we copy
+       //We assume that input src and dest are be aligned to `align` so offset just worsen it
+       int offsets_mask = (doffset | soffset) & 0x7; //we only care about the misalignment part
+       if (offsets_mask) {
+               if (offsets_mask % 2 == 1)
+                       goto copy_1;
+               if (offsets_mask % 4 == 2)
+                       goto copy_2;
+               if (SIZEOF_VOID_P == 8 && offsets_mask % 8 == 4)
+                       goto copy_4;
        }
 
-       if (!cfg->backend->no_unaligned_access && SIZEOF_REGISTER == 8) {
+
+       if (SIZEOF_REGISTER == 8) {
                while (size >= 8) {
                        cur_reg = alloc_preg (cfg);
                        MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI8_MEMBASE, cur_reg, srcreg, soffset);
@@ -123,8 +145,9 @@ mini_emit_memcpy (MonoCompile *cfg, int destreg, int doffset, int srcreg, int so
                        soffset += 8;
                        size -= 8;
                }
-       }       
+       }
 
+copy_4:
        while (size >= 4) {
                cur_reg = alloc_preg (cfg);
                MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, cur_reg, srcreg, soffset);
@@ -133,6 +156,8 @@ mini_emit_memcpy (MonoCompile *cfg, int destreg, int doffset, int srcreg, int so
                soffset += 4;
                size -= 4;
        }
+
+copy_2:
        while (size >= 2) {
                cur_reg = alloc_preg (cfg);
                MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI2_MEMBASE, cur_reg, srcreg, soffset);
@@ -141,6 +166,8 @@ mini_emit_memcpy (MonoCompile *cfg, int destreg, int doffset, int srcreg, int so
                soffset += 2;
                size -= 2;
        }
+
+copy_1:
        while (size >= 1) {
                cur_reg = alloc_preg (cfg);
                MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI1_MEMBASE, cur_reg, srcreg, soffset);
@@ -157,7 +184,7 @@ mini_emit_memcpy_internal (MonoCompile *cfg, MonoInst *dest, MonoInst *src, Mono
        /* FIXME: Optimize the case when src/dest is OP_LDADDR */
 
        /* We can't do copies at a smaller granule than the provided alignment */
-       if (size_ins || ((size / align > MAX_INLINE_COPIES) && !(cfg->opt & MONO_OPT_INTRINS))) {
+       if (size_ins || (size / align > MAX_INLINE_COPIES) || !(cfg->opt & MONO_OPT_INTRINS)) {
                MonoInst *iargs [3];
                iargs [0] = dest;
                iargs [1] = src;
@@ -177,7 +204,7 @@ mini_emit_memset_internal (MonoCompile *cfg, MonoInst *dest, MonoInst *value_ins
        /* FIXME: Optimize the case when dest is OP_LDADDR */
 
        /* We can't do copies at a smaller granule than the provided alignment */
-       if (value_ins || size_ins || value != 0 || ((size / align > MAX_INLINE_COPIES) && !(cfg->opt & MONO_OPT_INTRINS))) {
+       if (value_ins || size_ins || value != 0 || (size / align > MAX_INLINE_COPIES) || !(cfg->opt & MONO_OPT_INTRINS)) {
                MonoInst *iargs [3];
                iargs [0] = dest;
 
@@ -207,12 +234,232 @@ mini_emit_memset_const_size (MonoCompile *cfg, MonoInst *dest, int value, int si
        mini_emit_memset_internal (cfg, dest, NULL, value, NULL, size, align);
 }
 
+
+static void
+create_write_barrier_bitmap (MonoCompile *cfg, MonoClass *klass, unsigned *wb_bitmap, int offset)
+{
+       MonoClassField *field;
+       gpointer iter = NULL;
+
+       while ((field = mono_class_get_fields (klass, &iter))) {
+               int foffset;
+
+               if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
+                       continue;
+               foffset = klass->valuetype ? field->offset - sizeof (MonoObject): field->offset;
+               if (mini_type_is_reference (mono_field_get_type (field))) {
+                       g_assert ((foffset % SIZEOF_VOID_P) == 0);
+                       *wb_bitmap |= 1 << ((offset + foffset) / SIZEOF_VOID_P);
+               } else {
+                       MonoClass *field_class = mono_class_from_mono_type (field->type);
+                       if (field_class->has_references)
+                               create_write_barrier_bitmap (cfg, field_class, wb_bitmap, offset + foffset);
+               }
+       }
+}
+
+static gboolean
+mini_emit_wb_aware_memcpy (MonoCompile *cfg, MonoClass *klass, MonoInst *iargs[4], int size, int align)
+{
+       int dest_ptr_reg, tmp_reg, destreg, srcreg, offset;
+       unsigned need_wb = 0;
+
+       if (align == 0)
+               align = 4;
+
+       /*types with references can't have alignment smaller than sizeof(void*) */
+       if (align < SIZEOF_VOID_P)
+               return FALSE;
+
+       if (size > 5 * SIZEOF_VOID_P)
+               return FALSE;
+
+       create_write_barrier_bitmap (cfg, klass, &need_wb, 0);
+
+       destreg = iargs [0]->dreg;
+       srcreg = iargs [1]->dreg;
+       offset = 0;
+
+       dest_ptr_reg = alloc_preg (cfg);
+       tmp_reg = alloc_preg (cfg);
+
+       /*tmp = dreg*/
+       EMIT_NEW_UNALU (cfg, iargs [0], OP_MOVE, dest_ptr_reg, destreg);
+
+       while (size >= SIZEOF_VOID_P) {
+               MonoInst *load_inst;
+               MONO_INST_NEW (cfg, load_inst, OP_LOAD_MEMBASE);
+               load_inst->dreg = tmp_reg;
+               load_inst->inst_basereg = srcreg;
+               load_inst->inst_offset = offset;
+               MONO_ADD_INS (cfg->cbb, load_inst);
+
+               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, dest_ptr_reg, 0, tmp_reg);
+
+               if (need_wb & 0x1)
+                       mini_emit_write_barrier (cfg, iargs [0], load_inst);
+
+               offset += SIZEOF_VOID_P;
+               size -= SIZEOF_VOID_P;
+               need_wb >>= 1;
+
+               /*tmp += sizeof (void*)*/
+               if (size >= SIZEOF_VOID_P) {
+                       NEW_BIALU_IMM (cfg, iargs [0], OP_PADD_IMM, dest_ptr_reg, dest_ptr_reg, SIZEOF_VOID_P);
+                       MONO_ADD_INS (cfg->cbb, iargs [0]);
+               }
+       }
+
+       /* Those cannot be references since size < sizeof (void*) */
+       while (size >= 4) {
+               MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, tmp_reg, srcreg, offset);
+               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, destreg, offset, tmp_reg);
+               offset += 4;
+               size -= 4;
+       }
+
+       while (size >= 2) {
+               MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI2_MEMBASE, tmp_reg, srcreg, offset);
+               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI2_MEMBASE_REG, destreg, offset, tmp_reg);
+               offset += 2;
+               size -= 2;
+       }
+
+       while (size >= 1) {
+               MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI1_MEMBASE, tmp_reg, srcreg, offset);
+               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, destreg, offset, tmp_reg);
+               offset += 1;
+               size -= 1;
+       }
+
+       return TRUE;
+}
+
+static void
+mini_emit_memory_copy_internal (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *klass, int explicit_align, gboolean native)
+{
+       MonoInst *iargs [4];
+       int size;
+       guint32 align = 0;
+       MonoInst *size_ins = NULL;
+       MonoInst *memcpy_ins = NULL;
+
+       g_assert (klass);
+       /*
+       Fun fact about @native. It's false that @klass will have no ref when @native is true.
+       This happens in pinvoke2. What goes is that marshal.c uses CEE_MONO_LDOBJNATIVE and pass klass.
+       The actual stuff being copied will have no refs, but @klass might.
+       This means we can't assert !(klass->has_references && native).
+       */
+
+       if (cfg->gshared)
+               klass = mono_class_from_mono_type (mini_get_underlying_type (&klass->byval_arg));
+
+       /*
+        * This check breaks with spilled vars... need to handle it during verification anyway.
+        * g_assert (klass && klass == src->klass && klass == dest->klass);
+        */
+
+       if (mini_is_gsharedvt_klass (klass)) {
+               g_assert (!native);
+               size_ins = mini_emit_get_gsharedvt_info_klass (cfg, klass, MONO_RGCTX_INFO_VALUE_SIZE);
+               memcpy_ins = mini_emit_get_gsharedvt_info_klass (cfg, klass, MONO_RGCTX_INFO_MEMCPY);
+       }
+
+       if (native)
+               size = mono_class_native_size (klass, &align);
+       else
+               size = mono_class_value_size (klass, &align);
+
+       if (!align)
+               align = SIZEOF_VOID_P;
+       if (explicit_align)
+               align = explicit_align;
+
+       if (mini_type_is_reference (&klass->byval_arg)) { // Refs *MUST* be naturally aligned
+               MonoInst *store, *load;
+               int dreg = alloc_ireg_ref (cfg);
+
+               NEW_LOAD_MEMBASE (cfg, load, OP_LOAD_MEMBASE, dreg, src->dreg, 0);
+               MONO_ADD_INS (cfg->cbb, load);
+
+               NEW_STORE_MEMBASE (cfg, store, OP_STORE_MEMBASE_REG, dest->dreg, 0, dreg);
+               MONO_ADD_INS (cfg->cbb, store);
+
+               mini_emit_write_barrier (cfg, dest, src);
+       } else if (cfg->gen_write_barriers && (klass->has_references || size_ins) && !native) {         /* if native is true there should be no references in the struct */
+               /* Avoid barriers when storing to the stack */
+               if (!((dest->opcode == OP_ADD_IMM && dest->sreg1 == cfg->frame_reg) ||
+                         (dest->opcode == OP_LDADDR))) {
+                       int context_used;
+
+                       iargs [0] = dest;
+                       iargs [1] = src;
+
+                       context_used = mini_class_check_context_used (cfg, klass);
+
+                       /* It's ok to intrinsify under gsharing since shared code types are layout stable. */
+                       if (!size_ins && (cfg->opt & MONO_OPT_INTRINS) && mini_emit_wb_aware_memcpy (cfg, klass, iargs, size, align)) {
+                       } else if (size_ins || align < SIZEOF_VOID_P) {
+                               if (context_used) {
+                                       iargs [2] = mini_emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS);
+                               }  else {
+                                       iargs [2] = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_CLASS, klass);
+                                       if (!cfg->compile_aot)
+                                               mono_class_compute_gc_descriptor (klass);
+                               }
+                               if (size_ins)
+                                       mono_emit_jit_icall (cfg, mono_gsharedvt_value_copy, iargs);
+                               else
+                                       mono_emit_jit_icall (cfg, mono_value_copy, iargs);
+                       } else {
+                               /* We don't unroll more than 5 stores to avoid code bloat. */
+                               /*This is harmless and simplify mono_gc_get_range_copy_func */
+                               size += (SIZEOF_VOID_P - 1);
+                               size &= ~(SIZEOF_VOID_P - 1);
+
+                               EMIT_NEW_ICONST (cfg, iargs [2], size);
+                               mono_emit_jit_icall (cfg, mono_gc_get_range_copy_func (), iargs);
+                       }
+                       return;
+               }
+       }
+
+       if (size_ins) {
+               iargs [0] = dest;
+               iargs [1] = src;
+               iargs [2] = size_ins;
+               mini_emit_calli (cfg, mono_method_signature (mini_get_memcpy_method ()), iargs, memcpy_ins, NULL, NULL);
+       } else {
+               mini_emit_memcpy_const_size (cfg, dest, src, size, align);
+       }
+}
+
 MonoInst*
 mini_emit_memory_load (MonoCompile *cfg, MonoType *type, MonoInst *src, int offset, int ins_flag)
 {
        MonoInst *ins;
 
-       EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, type, src->dreg, offset);
+       if (ins_flag & MONO_INST_UNALIGNED) {
+               MonoInst *addr, *tmp_var;
+               int align;
+               int size = mono_type_size (type, &align);
+
+               if (offset) {
+                       MonoInst *add_offset;
+                       NEW_BIALU_IMM (cfg, add_offset, OP_PADD_IMM, alloc_preg (cfg), src->dreg, offset);
+                       MONO_ADD_INS (cfg->cbb, add_offset);
+                       src = add_offset;
+               }
+
+               tmp_var = mono_compile_create_var (cfg, type, OP_LOCAL);
+               EMIT_NEW_VARLOADA (cfg, addr, tmp_var, tmp_var->inst_vtype);
+
+               mini_emit_memcpy_const_size (cfg, addr, src, size, 1);
+               EMIT_NEW_TEMPLOAD (cfg, ins, tmp_var->inst_c0);
+       } else {
+               EMIT_NEW_LOAD_MEMBASE_TYPE (cfg, ins, type, src->dreg, offset);
+       }
        ins->flags |= ins_flag;
 
        if (ins_flag & MONO_INST_VOLATILE) {
@@ -233,6 +480,16 @@ mini_emit_memory_store (MonoCompile *cfg, MonoType *type, MonoInst *dest, MonoIn
                /* Volatile stores have release semantics, see 12.6.7 in Ecma 335 */
                mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_REL);
        }
+
+       if (ins_flag & MONO_INST_UNALIGNED) {
+               MonoInst *addr, *mov, *tmp_var;
+
+               tmp_var = mono_compile_create_var (cfg, type, OP_LOCAL);
+               EMIT_NEW_TEMPSTORE (cfg, mov, tmp_var->inst_c0, value);
+               EMIT_NEW_VARLOADA (cfg, addr, tmp_var, tmp_var->inst_vtype);
+               mini_emit_memory_copy_internal (cfg, dest, addr, mono_class_from_mono_type (type), 1, FALSE);
+       }
+
        /* FIXME: should check item at sp [1] is compatible with the type of the store. */
 
        EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, type, dest->dreg, 0, value->dreg);
@@ -247,7 +504,7 @@ mini_emit_memory_store (MonoCompile *cfg, MonoType *type, MonoInst *dest, MonoIn
 void
 mini_emit_memory_copy_bytes (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoInst *size, int ins_flag)
 {
-       int align = SIZEOF_VOID_P;
+       int align = (ins_flag & MONO_INST_UNALIGNED) ? 1 : SIZEOF_VOID_P;
 
        /*
         * FIXME: It's unclear whether we should be emitting both the acquire
@@ -262,11 +519,9 @@ mini_emit_memory_copy_bytes (MonoCompile *cfg, MonoInst *dest, MonoInst *src, Mo
                mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_SEQ);
        }
 
-       if ((cfg->opt & MONO_OPT_INTRINS) && (size->opcode == OP_ICONST) && size->inst_c0 < 10000) {
+       if ((cfg->opt & MONO_OPT_INTRINS) && (size->opcode == OP_ICONST)) {
                mini_emit_memcpy_const_size (cfg, dest, src, size->inst_c0, align);
        } else {
-               if (cfg->verbose_level > 3)
-                       printf ("EMITING REGULAR COPY\n");
                mini_emit_memcpy_internal (cfg, dest, src, size, 0, align);
        }
 
@@ -279,7 +534,7 @@ mini_emit_memory_copy_bytes (MonoCompile *cfg, MonoInst *dest, MonoInst *src, Mo
 void
 mini_emit_memory_init_bytes (MonoCompile *cfg, MonoInst *dest, MonoInst *value, MonoInst *size, int ins_flag)
 {
-       int align = SIZEOF_VOID_P;
+       int align = (ins_flag & MONO_INST_UNALIGNED) ? 1 : SIZEOF_VOID_P;
 
        if (ins_flag & MONO_INST_VOLATILE) {
                /* Volatile stores have release semantics, see 12.6.7 in Ecma 335 */
@@ -295,4 +550,37 @@ mini_emit_memory_init_bytes (MonoCompile *cfg, MonoInst *dest, MonoInst *value,
 
 }
 
+/*
+ * If @klass is a valuetype, emit code to copy a value with source address in @src and destination address in @dest.
+ * If @klass is a ref type, copy a pointer instead.
+ */
+
+void
+mini_emit_memory_copy (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *klass, gboolean native, int ins_flag)
+{
+       int explicit_align = 0;
+       if (ins_flag & MONO_INST_UNALIGNED)
+               explicit_align = 1;
+
+       /*
+        * FIXME: It's unclear whether we should be emitting both the acquire
+        * and release barriers for cpblk. It is technically both a load and
+        * store operation, so it seems like that's the sensible thing to do.
+        *
+        * FIXME: We emit full barriers on both sides of the operation for
+        * simplicity. We should have a separate atomic memcpy method instead.
+        */
+       if (ins_flag & MONO_INST_VOLATILE) {
+               /* Volatile loads have acquire semantics, see 12.6.7 in Ecma 335 */
+               mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_SEQ);
+       }
+
+       mini_emit_memory_copy_internal (cfg, dest, src, klass, explicit_align, native);
+
+       if (ins_flag & MONO_INST_VOLATILE) {
+               /* Volatile loads have acquire semantics, see 12.6.7 in Ecma 335 */
+               mini_emit_memory_barrier (cfg, MONO_MEMORY_BARRIER_SEQ);
+       }
+}
+
 #endif
index 0a34f582c637abdd9d565e7ee08a6305f752c2f4..3817d2809f9e0acecb6c2857f0be4a0246017371 100644 (file)
@@ -2827,29 +2827,6 @@ mini_get_memcpy_method (void)
        return memcpy_method;
 }
 
-static void
-create_write_barrier_bitmap (MonoCompile *cfg, MonoClass *klass, unsigned *wb_bitmap, int offset)
-{
-       MonoClassField *field;
-       gpointer iter = NULL;
-
-       while ((field = mono_class_get_fields (klass, &iter))) {
-               int foffset;
-
-               if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
-                       continue;
-               foffset = klass->valuetype ? field->offset - sizeof (MonoObject): field->offset;
-               if (mini_type_is_reference (mono_field_get_type (field))) {
-                       g_assert ((foffset % SIZEOF_VOID_P) == 0);
-                       *wb_bitmap |= 1 << ((offset + foffset) / SIZEOF_VOID_P);
-               } else {
-                       MonoClass *field_class = mono_class_from_mono_type (field->type);
-                       if (field_class->has_references)
-                               create_write_barrier_bitmap (cfg, field_class, wb_bitmap, offset + foffset);
-               }
-       }
-}
-
 void
 mini_emit_write_barrier (MonoCompile *cfg, MonoInst *ptr, MonoInst *value)
 {
@@ -2863,6 +2840,8 @@ mini_emit_write_barrier (MonoCompile *cfg, MonoInst *ptr, MonoInst *value)
        if (!cfg->gen_write_barriers)
                return;
 
+       //method->wrapper_type != MONO_WRAPPER_WRITE_BARRIER && !MONO_INS_IS_PCONST_NULL (sp [1])
+
        card_table = mono_gc_get_card_table (&card_table_shift_bits, &card_table_mask);
 
        mono_gc_get_nursery (&nursery_shift_bits, &nursery_size);
@@ -2906,177 +2885,6 @@ mini_emit_write_barrier (MonoCompile *cfg, MonoInst *ptr, MonoInst *value)
        EMIT_NEW_DUMMY_USE (cfg, dummy_use, value);
 }
 
-gboolean
-mini_emit_wb_aware_memcpy (MonoCompile *cfg, MonoClass *klass, MonoInst *iargs[4], int size, int align)
-{
-       int dest_ptr_reg, tmp_reg, destreg, srcreg, offset;
-       unsigned need_wb = 0;
-
-       if (align == 0)
-               align = 4;
-
-       /*types with references can't have alignment smaller than sizeof(void*) */
-       if (align < SIZEOF_VOID_P)
-               return FALSE;
-
-       if (size > 5 * SIZEOF_VOID_P)
-               return FALSE;
-
-       create_write_barrier_bitmap (cfg, klass, &need_wb, 0);
-
-       destreg = iargs [0]->dreg;
-       srcreg = iargs [1]->dreg;
-       offset = 0;
-
-       dest_ptr_reg = alloc_preg (cfg);
-       tmp_reg = alloc_preg (cfg);
-
-       /*tmp = dreg*/
-       EMIT_NEW_UNALU (cfg, iargs [0], OP_MOVE, dest_ptr_reg, destreg);
-
-       while (size >= SIZEOF_VOID_P) {
-               MonoInst *load_inst;
-               MONO_INST_NEW (cfg, load_inst, OP_LOAD_MEMBASE);
-               load_inst->dreg = tmp_reg;
-               load_inst->inst_basereg = srcreg;
-               load_inst->inst_offset = offset;
-               MONO_ADD_INS (cfg->cbb, load_inst);
-
-               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, dest_ptr_reg, 0, tmp_reg);
-
-               if (need_wb & 0x1)
-                       mini_emit_write_barrier (cfg, iargs [0], load_inst);
-
-               offset += SIZEOF_VOID_P;
-               size -= SIZEOF_VOID_P;
-               need_wb >>= 1;
-
-               /*tmp += sizeof (void*)*/
-               if (size >= SIZEOF_VOID_P) {
-                       NEW_BIALU_IMM (cfg, iargs [0], OP_PADD_IMM, dest_ptr_reg, dest_ptr_reg, SIZEOF_VOID_P);
-                       MONO_ADD_INS (cfg->cbb, iargs [0]);
-               }
-       }
-
-       /* Those cannot be references since size < sizeof (void*) */
-       while (size >= 4) {
-               MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI4_MEMBASE, tmp_reg, srcreg, offset);
-               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI4_MEMBASE_REG, destreg, offset, tmp_reg);
-               offset += 4;
-               size -= 4;
-       }
-
-       while (size >= 2) {
-               MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI2_MEMBASE, tmp_reg, srcreg, offset);
-               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI2_MEMBASE_REG, destreg, offset, tmp_reg);
-               offset += 2;
-               size -= 2;
-       }
-
-       while (size >= 1) {
-               MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI1_MEMBASE, tmp_reg, srcreg, offset);
-               MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, destreg, offset, tmp_reg);
-               offset += 1;
-               size -= 1;
-       }
-
-       return TRUE;
-}
-
-/*
- * Emit code to copy a valuetype of type @klass whose address is stored in
- * @src->dreg to memory whose address is stored at @dest->dreg.
- */
-void
-mini_emit_stobj (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *klass, gboolean native)
-{
-       MonoInst *iargs [4];
-       int n;
-       guint32 align = 0;
-       MonoMethod *memcpy_method;
-       MonoInst *size_ins = NULL;
-       MonoInst *memcpy_ins = NULL;
-
-       g_assert (klass);
-       if (cfg->gshared)
-               klass = mono_class_from_mono_type (mini_get_underlying_type (&klass->byval_arg));
-
-       /*
-        * This check breaks with spilled vars... need to handle it during verification anyway.
-        * g_assert (klass && klass == src->klass && klass == dest->klass);
-        */
-
-       if (mini_is_gsharedvt_klass (klass)) {
-               g_assert (!native);
-               size_ins = mini_emit_get_gsharedvt_info_klass (cfg, klass, MONO_RGCTX_INFO_VALUE_SIZE);
-               memcpy_ins = mini_emit_get_gsharedvt_info_klass (cfg, klass, MONO_RGCTX_INFO_MEMCPY);
-       }
-
-       if (native)
-               n = mono_class_native_size (klass, &align);
-       else
-               n = mono_class_value_size (klass, &align);
-
-       if (!align)
-               align = SIZEOF_VOID_P;
-       /* if native is true there should be no references in the struct */
-       if (cfg->gen_write_barriers && (klass->has_references || size_ins) && !native) {
-               /* Avoid barriers when storing to the stack */
-               if (!((dest->opcode == OP_ADD_IMM && dest->sreg1 == cfg->frame_reg) ||
-                         (dest->opcode == OP_LDADDR))) {
-                       int context_used;
-
-                       iargs [0] = dest;
-                       iargs [1] = src;
-
-                       context_used = mini_class_check_context_used (cfg, klass);
-
-                       /* It's ok to intrinsify under gsharing since shared code types are layout stable. */
-                       if (!size_ins && (cfg->opt & MONO_OPT_INTRINS) && mini_emit_wb_aware_memcpy (cfg, klass, iargs, n, align)) {
-                               return;
-                       } else if (size_ins || align < SIZEOF_VOID_P) {
-                               if (context_used) {
-                                       iargs [2] = mini_emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS);
-                               }  else {
-                                       iargs [2] = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_CLASS, klass);
-                                       if (!cfg->compile_aot)
-                                               mono_class_compute_gc_descriptor (klass);
-                               }
-                               if (size_ins)
-                                       mono_emit_jit_icall (cfg, mono_gsharedvt_value_copy, iargs);
-                               else
-                                       mono_emit_jit_icall (cfg, mono_value_copy, iargs);
-                       } else {
-                               /* We don't unroll more than 5 stores to avoid code bloat. */
-                               /*This is harmless and simplify mono_gc_get_range_copy_func */
-                               n += (SIZEOF_VOID_P - 1);
-                               n &= ~(SIZEOF_VOID_P - 1);
-
-                               EMIT_NEW_ICONST (cfg, iargs [2], n);
-                               mono_emit_jit_icall (cfg, mono_gc_get_range_copy_func (), iargs);
-                       }
-               }
-       }
-
-       if (!size_ins && (cfg->opt & MONO_OPT_INTRINS) && n <= sizeof (gpointer) * 8) {
-               /* FIXME: Optimize the case when src/dest is OP_LDADDR */
-               mini_emit_memcpy (cfg, dest->dreg, 0, src->dreg, 0, n, align);
-       } else {
-               iargs [0] = dest;
-               iargs [1] = src;
-               if (size_ins)
-                       iargs [2] = size_ins;
-               else
-                       EMIT_NEW_ICONST (cfg, iargs [2], n);
-               
-               memcpy_method = mini_get_memcpy_method ();
-               if (memcpy_ins)
-                       mini_emit_calli (cfg, mono_method_signature (memcpy_method), iargs, memcpy_ins, NULL, NULL);
-               else
-                       mono_emit_method_call (cfg, memcpy_method, iargs, NULL);
-       }
-}
-
 MonoMethod*
 mini_get_memset_method (void)
 {
@@ -4763,54 +4571,6 @@ mini_emit_ldelema_ins (MonoCompile *cfg, MonoMethod *cmethod, MonoInst **sp, uns
        return addr;
 }
 
-static MonoBreakPolicy
-always_insert_breakpoint (MonoMethod *method)
-{
-       return MONO_BREAK_POLICY_ALWAYS;
-}
-
-static MonoBreakPolicyFunc break_policy_func = always_insert_breakpoint;
-
-/**
- * mono_set_break_policy:
- * \param policy_callback the new callback function
- *
- * Allow embedders to decide wherther to actually obey breakpoint instructions
- * (both break IL instructions and \c Debugger.Break method calls), for example
- * to not allow an app to be aborted by a perfectly valid IL opcode when executing
- * untrusted or semi-trusted code.
- *
- * \p policy_callback will be called every time a break point instruction needs to
- * be inserted with the method argument being the method that calls \c Debugger.Break
- * or has the IL \c break instruction. The callback should return \c MONO_BREAK_POLICY_NEVER
- * if it wants the breakpoint to not be effective in the given method.
- * \c MONO_BREAK_POLICY_ALWAYS is the default.
- */
-void
-mono_set_break_policy (MonoBreakPolicyFunc policy_callback)
-{
-       if (policy_callback)
-               break_policy_func = policy_callback;
-       else
-               break_policy_func = always_insert_breakpoint;
-}
-
-static gboolean
-should_insert_brekpoint (MonoMethod *method) {
-       switch (break_policy_func (method)) {
-       case MONO_BREAK_POLICY_ALWAYS:
-               return TRUE;
-       case MONO_BREAK_POLICY_NEVER:
-               return FALSE;
-       case MONO_BREAK_POLICY_ON_DBG:
-               g_warning ("mdb no longer supported");
-               return FALSE;
-       default:
-               g_warning ("Incorrect value returned from break policy callback");
-               return FALSE;
-       }
-}
-
 /* optimize the simple GetGenericValueImpl/SetGenericValueImpl generic icalls */
 static MonoInst*
 emit_array_generic_access (MonoCompile *cfg, MonoMethodSignature *fsig, MonoInst **args, int is_set)
@@ -5114,6 +4874,31 @@ mini_emit_inst_for_sharable_method (MonoCompile *cfg, MonoMethod *cmethod, MonoM
        return NULL;
 }
 
+
+static gboolean
+mono_type_is_native_blittable (MonoType *t)
+{
+       if (MONO_TYPE_IS_REFERENCE (t))
+               return FALSE;
+
+       if (MONO_TYPE_IS_PRIMITIVE_SCALAR (t))
+               return TRUE;
+
+       MonoClass *klass = mono_class_from_mono_type (t);
+
+       //MonoClass::blitable depends on mono_class_setup_fields being done.
+       mono_class_setup_fields (klass);
+       if (!klass->blittable)
+               return FALSE;
+
+       // If the native marshal size is different we can't convert PtrToStructure to a type load
+       if (mono_class_native_size (klass, NULL) != mono_class_value_size (klass, NULL))
+               return FALSE;
+
+       return TRUE;
+}
+
+
 static MonoInst*
 mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **args)
 {
@@ -5930,7 +5715,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                           (strcmp (cmethod->klass->name_space, "System.Diagnostics") == 0) &&
                           (strcmp (cmethod->klass->name, "Debugger") == 0)) {
                if (!strcmp (cmethod->name, "Break") && fsig->param_count == 0) {
-                       if (should_insert_brekpoint (cfg->method)) {
+                       if (mini_should_insert_breakpoint (cfg->method)) {
                                ins = mono_emit_jit_icall (cfg, mono_debugger_agent_user_break, NULL);
                        } else {
                                MONO_INST_NEW (cfg, ins, OP_NOP);
@@ -6029,6 +5814,20 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                        MONO_ADD_INS (cfg->cbb, ins);
                        return ins;
                }
+       } else if (cmethod->klass->image == mono_defaults.corlib &&
+                       (strcmp (cmethod->klass->name_space, "System.Runtime.InteropServices") == 0) &&
+                       (strcmp (cmethod->klass->name, "Marshal") == 0)) {
+               //Convert Marshal.PtrToStructure<T> of blittable T to direct loads
+               if (strcmp (cmethod->name, "PtrToStructure") == 0 &&
+                               cmethod->is_inflated &&
+                               fsig->param_count == 1 &&
+                               !mini_method_check_context_used (cfg, cmethod)) {
+
+                       MonoGenericContext *method_context = mono_method_get_context (cmethod);
+                       MonoType *arg0 = method_context->method_inst->type_argv [0];
+                       if (mono_type_is_native_blittable (arg0))
+                               return mini_emit_memory_load (cfg, arg0, args [0], 0, 0);
+               }
        }
 
 #ifdef MONO_ARCH_SIMD_INTRINSICS
@@ -7958,7 +7757,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        MONO_ADD_INS (cfg->cbb, ins);
                        break;
                case CEE_BREAK:
-                       if (should_insert_brekpoint (cfg->method)) {
+                       if (mini_should_insert_breakpoint (cfg->method)) {
                                ins = mono_emit_jit_icall (cfg, mono_debugger_agent_user_break, NULL);
                        } else {
                                MONO_INST_NEW (cfg, ins, OP_NOP);
@@ -9853,23 +9652,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        klass = mini_get_class (method, token, generic_context);
                        CHECK_TYPELOAD (klass);
                        sp -= 2;
-                       if (generic_class_is_reference_type (cfg, klass)) {
-                               MonoInst *store, *load;
-                               int dreg = alloc_ireg_ref (cfg);
-
-                               NEW_LOAD_MEMBASE (cfg, load, OP_LOAD_MEMBASE, dreg, sp [1]->dreg, 0);
-                               load->flags |= ins_flag;
-                               MONO_ADD_INS (cfg->cbb, load);
-
-                               NEW_STORE_MEMBASE (cfg, store, OP_STORE_MEMBASE_REG, sp [0]->dreg, 0, dreg);
-                               store->flags |= ins_flag;
-                               MONO_ADD_INS (cfg->cbb, store);
-
-                               if (cfg->gen_write_barriers && cfg->method->wrapper_type != MONO_WRAPPER_WRITE_BARRIER)
-                                       mini_emit_write_barrier (cfg, sp [0], sp [1]);
-                       } else {
-                               mini_emit_stobj (cfg, sp [0], sp [1], klass, FALSE);
-                       }
+                       mini_emit_memory_copy (cfg, sp [0], sp [1], klass, FALSE, ins_flag);
                        ins_flag = 0;
                        ip += 5;
                        break;
@@ -9918,14 +9701,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                        }
 
                        /* Optimize the ldobj+stobj combination */
-                       /* The reference case ends up being a load+store anyway */
-                       /* Skip this if the operation is volatile. */
-                       if (((ip [5] == CEE_STOBJ) && ip_in_bb (cfg, cfg->cbb, ip + 5) && read32 (ip + 6) == token) && !generic_class_is_reference_type (cfg, klass) && !(ins_flag & MONO_INST_VOLATILE)) {
+                       if (((ip [5] == CEE_STOBJ) && ip_in_bb (cfg, cfg->cbb, ip + 5) && read32 (ip + 6) == token)) {
                                CHECK_STACK (1);
 
                                sp --;
 
-                               mini_emit_stobj (cfg, sp [0], sp [1], klass, FALSE);
+                               mini_emit_memory_copy (cfg, sp [0], sp [1], klass, FALSE, ins_flag);
 
                                ip += 5 + 5;
                                ins_flag = 0;
@@ -10596,7 +10377,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                                dreg = alloc_ireg_mp (cfg);
                                                EMIT_NEW_BIALU (cfg, ins, OP_PADD, dreg, sp [0]->dreg, offset_ins->dreg);
                                                wbarrier_ptr_ins = ins;
-                                               /* The decomposition will call mini_emit_stobj () which will emit a wbarrier if needed */
+                                               /* The decomposition will call mini_emit_memory_copy () which will emit a wbarrier if needed */
                                                EMIT_NEW_STORE_MEMBASE_TYPE (cfg, store, field->type, dreg, 0, sp [1]->dreg);
                                        } else {
                                                EMIT_NEW_STORE_MEMBASE_TYPE (cfg, store, field->type, sp [0]->dreg, foffset, sp [1]->dreg);
@@ -11857,7 +11638,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                        temp = mono_compile_create_var (cfg, &klass->byval_arg, OP_LOCAL);
                                        temp->backend.is_pinvoke = 1;
                                        EMIT_NEW_TEMPLOADA (cfg, dest, temp->inst_c0);
-                                       mini_emit_stobj (cfg, dest, src, klass, TRUE);
+                                       mini_emit_memory_copy (cfg, dest, src, klass, TRUE, 0);
 
                                        EMIT_NEW_TEMPLOAD (cfg, dest, temp->inst_c0);
                                        dest->type = STACK_VTYPE;
@@ -11888,7 +11669,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                } else {
                                        EMIT_NEW_RETLOADA (cfg, ins);
                                }
-                               mini_emit_stobj (cfg, ins, sp [0], klass, TRUE);
+                               mini_emit_memory_copy (cfg, ins, sp [0], klass, TRUE, 0);
                                
                                if (sp != stack_start)
                                        UNVERIFIED;
@@ -14406,11 +14187,4 @@ NOTES
   the values on the stack before emitting the last instruction of the bb.
 */
 
-#else /* !DISABLE_JIT */
-
-void
-mono_set_break_policy (MonoBreakPolicyFunc policy_callback)
-{
-}
-
 #endif /* !DISABLE_JIT */
index 96c7d3a6adf2743440a7ef17e0a3a48ccba1b0ef..10a9daa20ef24f7fd45f015a82d119d3c3f80a17 100644 (file)
@@ -323,7 +323,7 @@ mono_arm_patchable_bl (guint8 *code, int cond)
        return code;
 }
 
-#if defined(__ARM_EABI__) && defined(__linux__) && !defined(PLATFORM_ANDROID) && !defined(__native_client__)
+#if defined(__ARM_EABI__) && defined(__linux__) && !defined(PLATFORM_ANDROID) && !defined(__native_client__) && !defined(MONO_CROSS_COMPILE)
 #define HAVE_AEABI_READ_TP 1
 #endif
 
@@ -337,7 +337,6 @@ mono_arch_have_fast_tls (void)
 #ifdef HAVE_AEABI_READ_TP
        static gboolean have_fast_tls = FALSE;
         static gboolean inited = FALSE;
-       gpointer tp1, tp2;
 
        if (mini_get_debug_options ()->use_fallback_tls)
                return FALSE;
@@ -345,10 +344,14 @@ mono_arch_have_fast_tls (void)
        if (inited)
                return have_fast_tls;
 
-       tp1 = __aeabi_read_tp ();
-       asm volatile("mrc p15, 0, %0, c13, c0, 3" : "=r" (tp2));
+       if (v7_supported) {
+               gpointer tp1, tp2;
 
-       have_fast_tls = tp1 && tp1 == tp2;
+               tp1 = __aeabi_read_tp ();
+               asm volatile("mrc p15, 0, %0, c13, c0, 3" : "=r" (tp2));
+
+               have_fast_tls = tp1 && tp1 == tp2;
+       }
        inited = TRUE;
        return have_fast_tls;
 #else
@@ -359,6 +362,7 @@ mono_arch_have_fast_tls (void)
 static guint8*
 emit_tls_get (guint8 *code, int dreg, int tls_offset)
 {
+       g_assert (v7_supported);
        ARM_MRC (code, 15, 0, dreg, 13, 0, 3);
        ARM_LDR_IMM (code, dreg, dreg, tls_offset);
        return code;
@@ -368,6 +372,7 @@ static guint8*
 emit_tls_set (guint8 *code, int sreg, int tls_offset)
 {
        int tp_reg = (sreg != ARMREG_R0) ? ARMREG_R0 : ARMREG_R1;
+       g_assert (v7_supported);
        ARM_MRC (code, 15, 0, tp_reg, 13, 0, 3);
        ARM_STR_IMM (code, sreg, tp_reg, tls_offset);
        return code;
index b6b1d813399f21e758c9ff90188d8b3f9ddf139e..7878372c10cd57257517b52809e147cb42c654bf 100644 (file)
@@ -1070,6 +1070,7 @@ mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoDomain
        mgreg_t *new_reg_locations [MONO_MAX_IREGS];
        gboolean get_reg_locations = unwind_options & MONO_UNWIND_REG_LOCATIONS;
        gboolean async = mono_thread_info_is_async_context ();
+       Unwinder unwinder;
 
        if (mono_llvm_only) {
                GSList *l, *ips;
@@ -1114,9 +1115,11 @@ mono_walk_stack_full (MonoJitStackWalk func, MonoContext *start_ctx, MonoDomain
        memcpy (&ctx, start_ctx, sizeof (MonoContext));
        memset (reg_locations, 0, sizeof (reg_locations));
 
+       unwinder_init (&unwinder);
+
        while (MONO_CONTEXT_GET_SP (&ctx) < jit_tls->end_of_stack) {
                frame.lmf = lmf;
-               res = mono_find_jit_info_ext (domain, jit_tls, NULL, &ctx, &new_ctx, NULL, &lmf, get_reg_locations ? new_reg_locations : NULL, &frame);
+               res = unwinder_unwind_frame (&unwinder, domain, jit_tls, NULL, &ctx, &new_ctx, NULL, &lmf, get_reg_locations ? new_reg_locations : NULL, &frame);
                if (!res)
                        return;
 
@@ -1633,7 +1636,7 @@ mono_handle_exception_internal_first_pass (MonoContext *ctx, MonoObject *obj, gi
 
                gpointer ip;
                if (in_interp)
-                       ip = (guint16*)ji->code_start + frame.native_offset;
+                       ip = (guint8*)ji->code_start + frame.native_offset;
                else
                        ip = MONO_CONTEXT_GET_IP (ctx);
 
@@ -2009,7 +2012,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
                }
 
                if (in_interp)
-                       ip = (guint16*)ji->code_start + frame.native_offset;
+                       ip = (guint8*)ji->code_start + frame.native_offset;
                else
                        ip = MONO_CONTEXT_GET_IP (ctx);
 
@@ -2131,7 +2134,7 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
                                                 * like the call which transitioned to JITted code has succeeded, but the
                                                 * return value register etc. is not set, so we have to be careful.
                                                 */
-                                               mono_interp_set_resume_state (mono_ex, &frame, ei->handler_start);
+                                               mono_interp_set_resume_state (jit_tls, mono_ex, frame.interp_frame, ei->handler_start);
                                                /* Undo the IP adjustment done by mono_arch_unwind_frame () */
 #if defined(TARGET_AMD64)
                                                ctx->gregs [AMD64_RIP] ++;
@@ -2260,6 +2263,9 @@ mono_debugger_run_finally (MonoContext *start_ctx)
  * mono_handle_exception:
  * \param ctx saved processor state
  * \param obj the exception object
+ *
+ *   Handle the exception OBJ starting from the state CTX. Modify CTX to point to the handler clause if the exception is caught, and
+ * return TRUE.
  */
 gboolean
 mono_handle_exception (MonoContext *ctx, MonoObject *obj)
@@ -3407,31 +3413,3 @@ mono_debug_personality (void)
        g_assert_not_reached ();
 }
 #endif
-
-#ifndef ENABLE_INTERPRETER
-/* Stubs of interpreter functions */
-void
-mono_interp_set_resume_state (MonoException *ex, StackFrameInfo *frame, gpointer handler_ip)
-{
-       g_assert_not_reached ();
-}
-
-void
-mono_interp_run_finally (StackFrameInfo *frame, int clause_index, gpointer handler_ip)
-{
-       g_assert_not_reached ();
-}
-
-void
-mono_interp_frame_iter_init (MonoInterpStackIter *iter, gpointer interp_exit_data)
-{
-       g_assert_not_reached ();
-}
-
-gboolean
-mono_interp_frame_iter_next (MonoInterpStackIter *iter, StackFrameInfo *frame)
-{
-       g_assert_not_reached ();
-       return FALSE;
-}
-#endif
index b5d79629a54132d93550187554ac8b08557f4815..7d427a915ee53263ccff6c19689782a15c5c48d7 100644 (file)
@@ -583,23 +583,23 @@ break_count (void)
 G_GNUC_UNUSED gboolean
 mono_debug_count (void)
 {
-       static int count = 0;
+       static int count = 0, int_val = 0;
        static gboolean inited;
-       static char *value;
 
        count ++;
 
        if (!inited) {
-               value = g_getenv ("COUNT");
+               char *value = g_getenv ("COUNT");
+               if (value) {
+                       int_val = atoi (value);
+                       g_free (value);
+               }
                inited = TRUE;
        }
 
-       if (!value)
+       if (!int_val)
                return TRUE;
 
-       int int_val = atoi (value);
-       g_free (value);
-
        if (count == int_val)
                break_count ();
 
@@ -4547,6 +4547,56 @@ mono_personality (void)
        g_assert_not_reached ();
 }
 
+
+static MonoBreakPolicy
+always_insert_breakpoint (MonoMethod *method)
+{
+       return MONO_BREAK_POLICY_ALWAYS;
+}
+
+static MonoBreakPolicyFunc break_policy_func = always_insert_breakpoint;
+
+/**
+ * mono_set_break_policy:
+ * \param policy_callback the new callback function
+ *
+ * Allow embedders to decide whether to actually obey breakpoint instructions
+ * (both break IL instructions and \c Debugger.Break method calls), for example
+ * to not allow an app to be aborted by a perfectly valid IL opcode when executing
+ * untrusted or semi-trusted code.
+ *
+ * \p policy_callback will be called every time a break point instruction needs to
+ * be inserted with the method argument being the method that calls \c Debugger.Break
+ * or has the IL \c break instruction. The callback should return \c MONO_BREAK_POLICY_NEVER
+ * if it wants the breakpoint to not be effective in the given method.
+ * \c MONO_BREAK_POLICY_ALWAYS is the default.
+ */
+void
+mono_set_break_policy (MonoBreakPolicyFunc policy_callback)
+{
+       if (policy_callback)
+               break_policy_func = policy_callback;
+       else
+               break_policy_func = always_insert_breakpoint;
+}
+
+gboolean
+mini_should_insert_breakpoint (MonoMethod *method)
+{
+       switch (break_policy_func (method)) {
+       case MONO_BREAK_POLICY_ALWAYS:
+               return TRUE;
+       case MONO_BREAK_POLICY_NEVER:
+               return FALSE;
+       case MONO_BREAK_POLICY_ON_DBG:
+               g_warning ("mdb no longer supported");
+               return FALSE;
+       default:
+               g_warning ("Incorrect value returned from break policy callback");
+               return FALSE;
+       }
+}
+
 // Custom handlers currently only implemented by Windows.
 #ifndef HOST_WIN32
 gboolean
index 6eb32809205aa44af20d634bfaf7607a344fa0e3..ed10d8f937934da36d172b9a60b1b2847947453d 100644 (file)
@@ -1217,11 +1217,12 @@ typedef struct {
         */
        gpointer abort_exc_stack_threshold;
 
-
        /*
         * List of methods being JIT'd in the current thread.
         */
        int active_jit_methods;
+
+       gpointer interp_context;
 } MonoJitTlsData;
 
 /*
@@ -2481,6 +2482,7 @@ MonoInst* mono_emit_jit_icall_by_info (MonoCompile *cfg, int il_offset, MonoJitI
 MonoInst* mono_emit_method_call (MonoCompile *cfg, MonoMethod *method, MonoInst **args, MonoInst *this_ins);
 void      mono_create_helper_signatures (void);
 MonoInst* mono_emit_native_call (MonoCompile *cfg, gconstpointer func, MonoMethodSignature *sig, MonoInst **args);
+gboolean  mini_should_insert_breakpoint (MonoMethod *method);
 
 gboolean  mini_class_is_system_array (MonoClass *klass);
 MonoMethodSignature *mono_get_element_address_signature (int arity);
@@ -2652,11 +2654,11 @@ MonoInst*         mini_emit_get_gsharedvt_info_klass (MonoCompile *cfg, MonoClas
 MonoInst*         mini_emit_calli (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **args, MonoInst *addr, MonoInst *imt_arg, MonoInst *rgctx_arg);
 MonoInst*         mini_emit_memory_barrier (MonoCompile *cfg, int kind);
 void              mini_emit_write_barrier (MonoCompile *cfg, MonoInst *ptr, MonoInst *value);
-gboolean          mini_emit_wb_aware_memcpy (MonoCompile *cfg, MonoClass *klass, MonoInst *iargs[4], int size, int align);
 MonoInst*         mini_emit_memory_load (MonoCompile *cfg, MonoType *type, MonoInst *src, int offset, int ins_flag);
 void              mini_emit_memory_store (MonoCompile *cfg, MonoType *type, MonoInst *dest, MonoInst *value, int ins_flag);
 void              mini_emit_memory_copy_bytes (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoInst *size, int ins_flag);
 void              mini_emit_memory_init_bytes (MonoCompile *cfg, MonoInst *dest, MonoInst *value, MonoInst *size, int ins_flag);
+void              mini_emit_memory_copy (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *klass, gboolean native, int ins_flag);
 
 MonoMethod*       mini_get_memcpy_method (void);
 MonoMethod*       mini_get_memset_method (void);
index 51c0cac6de625a0579fd85b262059f98a9e3f1f2..723238f4e94b55edada227fd251ffe40344a769b 100644 (file)
@@ -847,26 +847,31 @@ mono_arch_get_enter_icall_trampoline (MonoTrampInfo **info)
        guint8 *start = NULL, *code, *label_gexits [gregs_num], *label_fexits [fregs_num], *label_leave_tramp [3], *label_is_float_ret;
        MonoJumpInfo *ji = NULL;
        GSList *unwind_ops = NULL;
-       int buf_len, i, framesize = 0, off_methodargs, off_targetaddr;
+       int buf_len, i, framesize, off_methodargs, off_targetaddr;
        const int fp_reg = ARMREG_R7;
 
        buf_len = 512 + 1024;
        start = code = (guint8 *) mono_global_codeman_reserve (buf_len);
 
-       off_methodargs = framesize;
+       framesize = 5 * sizeof (mgreg_t); /* lr, r4, r8, r6 and plus one */
+
+       off_methodargs = -framesize;
        framesize += sizeof (mgreg_t);
 
-       off_targetaddr = framesize;
+       off_targetaddr = -framesize;
        framesize += sizeof (mgreg_t);
 
-       framesize = ALIGN_TO (framesize, MONO_ARCH_FRAME_ALIGNMENT);
+       framesize = ALIGN_TO (framesize + 4 * sizeof (mgreg_t), MONO_ARCH_FRAME_ALIGNMENT);
 
        /* allocate space on stack for argument passing */
        const int stack_space = ALIGN_TO (((gregs_num - ARMREG_R3) * sizeof (mgreg_t)), MONO_ARCH_FRAME_ALIGNMENT);
 
-       /* use r4, r5 and r6 as scratch registers */
-       ARM_PUSH (code, (1 << fp_reg) | (1 << ARMREG_LR) | (1 << ARMREG_R4) | (1 << ARMREG_R5) | (1 << ARMREG_R6));
+       /* iOS ABI */
+       ARM_PUSH (code, (1 << fp_reg) | (1 << ARMREG_LR));
        ARM_MOV_REG_REG (code, fp_reg, ARMREG_SP);
+
+       /* use r4, r8 and r6 as scratch registers */
+       ARM_PUSH (code, (1 << ARMREG_R4) | (1 << ARMREG_R8) | (1 << ARMREG_R6));
        ARM_SUB_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, stack_space + framesize);
 
        /* save InterpMethodArguments* onto stack */
@@ -878,32 +883,32 @@ mono_arch_get_enter_icall_trampoline (MonoTrampInfo **info)
        /* load pointer to InterpMethodArguments* into r4 */
        ARM_MOV_REG_REG (code, ARMREG_R4, ARMREG_R1);
 
-       /* move flen into r5 */
-       ARM_LDR_IMM (code, ARMREG_R5, ARMREG_R4, MONO_STRUCT_OFFSET (InterpMethodArguments, flen));
+       /* move flen into r8 */
+       ARM_LDR_IMM (code, ARMREG_R8, ARMREG_R4, MONO_STRUCT_OFFSET (InterpMethodArguments, flen));
        /* load pointer to fargs into r6 */
        ARM_LDR_IMM (code, ARMREG_R6, ARMREG_R4, MONO_STRUCT_OFFSET (InterpMethodArguments, fargs));
 
        for (i = 0; i < fregs_num; ++i) {
-               ARM_CMP_REG_IMM (code, ARMREG_R5, 0, 0);
+               ARM_CMP_REG_IMM (code, ARMREG_R8, 0, 0);
                label_fexits [i] = code;
                ARM_B_COND (code, ARMCOND_EQ, 0);
 
                g_assert (i <= ARM_VFP_D7); /* otherwise, need to pass args on stack */
                ARM_FLDD (code, i, ARMREG_R6, i * sizeof (double));
-               ARM_SUB_REG_IMM8 (code, ARMREG_R5, ARMREG_R5, 1);
+               ARM_SUB_REG_IMM8 (code, ARMREG_R8, ARMREG_R8, 1);
        }
 
        for (i = 0; i < fregs_num; i++)
                arm_patch (label_fexits [i], code);
 
-       /* move ilen into r5 */
-       ARM_LDR_IMM (code, ARMREG_R5, ARMREG_R4, MONO_STRUCT_OFFSET (InterpMethodArguments, ilen));
+       /* move ilen into r8 */
+       ARM_LDR_IMM (code, ARMREG_R8, ARMREG_R4, MONO_STRUCT_OFFSET (InterpMethodArguments, ilen));
        /* load pointer to iargs into r6 */
        ARM_LDR_IMM (code, ARMREG_R6, ARMREG_R4, MONO_STRUCT_OFFSET (InterpMethodArguments, iargs));
 
        int stack_offset = 0;
        for (i = 0; i < gregs_num; i++) {
-               ARM_CMP_REG_IMM (code, ARMREG_R5, 0, 0);
+               ARM_CMP_REG_IMM (code, ARMREG_R8, 0, 0);
                label_gexits [i] = code;
                ARM_B_COND (code, ARMCOND_EQ, 0);
 
@@ -914,7 +919,7 @@ mono_arch_get_enter_icall_trampoline (MonoTrampInfo **info)
                        ARM_STR_IMM (code, ARMREG_R4, ARMREG_SP, stack_offset);
                        stack_offset += sizeof (mgreg_t);
                }
-               ARM_SUB_REG_IMM8 (code, ARMREG_R5, ARMREG_R5, 1);
+               ARM_SUB_REG_IMM8 (code, ARMREG_R8, ARMREG_R8, 1);
        }
 
        for (i = 0; i < gregs_num; i++)
@@ -930,24 +935,24 @@ mono_arch_get_enter_icall_trampoline (MonoTrampInfo **info)
        ARM_LDR_IMM (code, ARMREG_R4, fp_reg, off_methodargs);
 
        /* load is_float_ret */
-       ARM_LDR_IMM (code, ARMREG_R5, ARMREG_R4, MONO_STRUCT_OFFSET (InterpMethodArguments, is_float_ret));
+       ARM_LDR_IMM (code, ARMREG_R8, ARMREG_R4, MONO_STRUCT_OFFSET (InterpMethodArguments, is_float_ret));
 
        /* check if a float return value is expected */
-       ARM_CMP_REG_IMM (code, ARMREG_R5, 0, 0);
+       ARM_CMP_REG_IMM (code, ARMREG_R8, 0, 0);
        label_is_float_ret = code;
        ARM_B_COND (code, ARMCOND_NE, 0);
 
        /* greg return */
        /* load retval */
-       ARM_LDR_IMM (code, ARMREG_R5, ARMREG_R4, MONO_STRUCT_OFFSET (InterpMethodArguments, retval));
+       ARM_LDR_IMM (code, ARMREG_R8, ARMREG_R4, MONO_STRUCT_OFFSET (InterpMethodArguments, retval));
 
-       ARM_CMP_REG_IMM (code, ARMREG_R5, 0, 0);
+       ARM_CMP_REG_IMM (code, ARMREG_R8, 0, 0);
        label_leave_tramp [0] = code;
        ARM_B_COND (code, ARMCOND_EQ, 0);
 
        /* store greg result, always write back 64bit */
-       ARM_STR_IMM (code, ARMREG_R0, ARMREG_R5, 0);
-       ARM_STR_IMM (code, ARMREG_R1, ARMREG_R5, 4);
+       ARM_STR_IMM (code, ARMREG_R0, ARMREG_R8, 0);
+       ARM_STR_IMM (code, ARMREG_R1, ARMREG_R8, 4);
 
        label_leave_tramp [1] = code;
        ARM_B_COND (code, ARMCOND_AL, 0);
@@ -955,20 +960,22 @@ mono_arch_get_enter_icall_trampoline (MonoTrampInfo **info)
        /* freg return */
        arm_patch (label_is_float_ret, code);
        /* load retval */
-       ARM_LDR_IMM (code, ARMREG_R5, ARMREG_R4, MONO_STRUCT_OFFSET (InterpMethodArguments, retval));
+       ARM_LDR_IMM (code, ARMREG_R8, ARMREG_R4, MONO_STRUCT_OFFSET (InterpMethodArguments, retval));
 
-       ARM_CMP_REG_IMM (code, ARMREG_R5, 0, 0);
+       ARM_CMP_REG_IMM (code, ARMREG_R8, 0, 0);
        label_leave_tramp [2] = code;
        ARM_B_COND (code, ARMCOND_EQ, 0);
 
        /* store freg result */
-       ARM_FSTD (code, ARM_VFP_F0, ARMREG_R5, 0);
+       ARM_FSTD (code, ARM_VFP_F0, ARMREG_R8, 0);
 
        for (i = 0; i < 3; i++)
                arm_patch (label_leave_tramp [i], code);
 
+       ARM_ADD_REG_IMM8 (code, ARMREG_SP, ARMREG_SP, stack_space + framesize);
+       ARM_POP (code, (1 << ARMREG_R4) | (1 << ARMREG_R8) | (1 << ARMREG_R6));
        ARM_MOV_REG_REG (code, ARMREG_SP, fp_reg);
-       ARM_POP (code, (1 << fp_reg) | (1 << ARMREG_PC) | (1 << ARMREG_R4) | (1 << ARMREG_R5) | (1 << ARMREG_R6));
+       ARM_POP (code, (1 << fp_reg) | (1 << ARMREG_PC));
 
        g_assert (code - start < buf_len);
 
diff --git a/mono/mini/unaligned.cs b/mono/mini/unaligned.cs
new file mode 100644 (file)
index 0000000..397fbbb
--- /dev/null
@@ -0,0 +1,307 @@
+using System;
+using System.Runtime.CompilerServices;
+using Mono;
+
+/*
+ * Regression tests for the mono JIT.
+ *
+ * Each test needs to be of the form:
+ *
+ * static int test_<result>_<name> ();
+ *
+ * where <result> is an integer (the value that needs to be returned by
+ * the method to make it pass.
+ * <name> is a user-displayed name used to identify the test.
+ *
+ * The tests can be driven in two ways:
+ * *) running the program directly: Main() uses reflection to find and invoke
+ *     the test methods (this is useful mostly to check that the tests are correct)
+ * *) with the --regression switch of the jit (this is the preferred way since
+ *     all the tests will be run with optimizations on and off)
+ *
+ * The reflection logic could be moved to a .dll since we need at least another
+ * regression test file written in IL code to have better control on how
+ * the IL code looks.
+ */
+
+#if __MOBILE__
+namespace UnalignedTests
+{
+#endif
+
+
+class Tests {
+
+#if !__MOBILE__
+       public static int Main (string[] args) {
+               return TestDriver.RunTests (typeof (Tests), args);
+       }
+#endif
+
+
+       public static unsafe int test_0_ldobj_r4 ()
+       {
+               byte *ptr = stackalloc byte [32];
+               float f = (float)123.44f;
+               *(float*)ptr = (float)f;
+
+               int expected = *(int*)ptr;
+
+               Intrinsics.UnalignedStobj<int> (ptr + 1, expected);
+               if (Intrinsics.UnalignedLdobj<float> (ptr + 1) != f)
+                       return 1;
+
+               return 0;
+       }
+
+       public static unsafe int test_0_ldobj_r8 ()
+       {
+               byte *ptr = stackalloc byte [32];
+               double f = 34423.44f;
+               *(double*)ptr = (double)f;
+
+               long expected = *(long*)ptr;
+
+               Intrinsics.UnalignedStobj<long> (ptr + 3, expected);
+               if (Intrinsics.UnalignedLdobj<double> (ptr + 3) != f)
+                       return 1;
+
+               return 0;
+       }
+
+       public static unsafe int test_0_ldobj ()
+       {
+               byte *ptr = stackalloc byte [20];
+               for (int i = 0; i < 20; ++i)
+                       ptr [i] = (byte)i;
+
+
+               if (Intrinsics.UnalignedLdobj<short> (ptr + 0) != 0x0100)
+                       return 1;
+
+               if (Intrinsics.UnalignedLdobj<short> (ptr + 1) != 0x0201)
+                       return 2;
+
+               if (Intrinsics.UnalignedLdobj<short> (ptr + 2) != 0x0302)
+                       return 3;
+
+               if (Intrinsics.UnalignedLdobj<int> (ptr + 1) != 0x04030201)
+                       return 4;
+
+               if (Intrinsics.UnalignedLdobj<int> (ptr + 2) != 0x05040302)
+                       return 5;
+
+               if (Intrinsics.UnalignedLdobj<long> (ptr + 1) != 0x0807060504030201)
+                       return 6;
+
+               if (Intrinsics.UnalignedLdobj<long> (ptr + 6) != 0xD0C0B0A09080706)
+                       return 7;
+
+               return 0;
+       }
+
+       public static unsafe int test_0_ldind ()
+       {
+               byte *ptr = stackalloc byte [20];
+               for (int i = 0; i < 20; ++i)
+                       ptr [i] = (byte)i;
+
+
+               if (Intrinsics.UnalignedLdInd2 (ptr + 0) != 0x0100)
+                       return 1;
+
+               if (Intrinsics.UnalignedLdInd2 (ptr + 1) != 0x0201)
+                       return 2;
+
+               if (Intrinsics.UnalignedLdInd2 (ptr + 2) != 0x0302)
+                       return 3;
+
+               if (Intrinsics.UnalignedLdInd4 (ptr + 1) != 0x04030201)
+                       return 4;
+
+               if (Intrinsics.UnalignedLdInd4 (ptr + 2) != 0x05040302)
+                       return 5;
+
+               if (Intrinsics.UnalignedLdInd8 (ptr + 1) != 0x0807060504030201)
+                       return 6;
+
+               if (Intrinsics.UnalignedLdInd8 (ptr + 6) != 0xD0C0B0A09080706)
+                       return 7;
+
+               return 0;
+       }
+       public static unsafe int test_0_cpobj ()
+       {
+               byte *dest = stackalloc byte [20];
+               byte *src = stackalloc byte [20];
+               for (int i = 0; i < 20; ++i)
+                       src [i] = (byte)i;
+
+               Intrinsics.UnalignedCpobj<short> (dest + 0, src + 0);
+               if (dest [0] != src [0] || dest [1] != src [1])
+                       return 1;
+
+               Intrinsics.UnalignedCpobj<short> (dest + 1, src + 0);
+               if (dest [1] != src [0] || dest [2] != src [1])
+                       return 2;
+
+               Intrinsics.UnalignedCpobj<short> (dest + 0, src + 1);
+               if (dest [0] != src [1] || dest [1] != src [2])
+                       return 3;
+
+               Intrinsics.UnalignedCpobj<short> (dest + 1, src + 1);
+               if (dest [1] != src [1] || dest [2] != src [2])
+                       return 3;
+
+               Intrinsics.UnalignedCpobj<int> (dest + 3, src);
+               for (int i = 0; i < 4; ++i) {
+                       if (dest [i + 3] != src [i])
+                               return 4;
+               }
+
+               Intrinsics.UnalignedCpobj<int> (dest + 1, src + 2);
+               for (int i = 0; i < 4; ++i) {
+                       if (dest [i + 1] != src [i + 2])
+                               return 5;
+               }
+
+               Intrinsics.UnalignedCpobj<long> (dest + 1, src + 2);
+               for (int i = 0; i < 8; ++i) {
+                       if (dest [i + 1] != src [i + 2])
+                               return 6;
+               }
+
+               Intrinsics.UnalignedCpobj<long> (dest + 7, src + 2);
+               for (int i = 0; i < 8; ++i) {
+                       if (dest [i + 7] != src [i + 2])
+                               return 7;
+               }
+
+               return 0;
+       }
+
+       public static unsafe int test_0_stobj ()
+       {
+               byte *ptr = stackalloc byte [20];
+
+               Intrinsics.UnalignedStobj <short> (ptr + 0, 0x6688);
+               if (ptr [0] != 0x88 || ptr [1] != 0x66)
+                       return 1;
+
+               Intrinsics.UnalignedStobj <short> (ptr + 1, 0x6589);
+               if (ptr [1] != 0x89 || ptr [2] != 0x65)
+                       return 2;
+
+               Intrinsics.UnalignedStobj <int> (ptr + 1, 0x60708090);
+               if (ptr [1] != 0x90 || ptr [2] != 0x80 || ptr [3] != 0x70 || ptr [4] != 0x60)
+                       return 3;
+
+               Intrinsics.UnalignedStobj <long> (ptr + 1, 0x405060708090);
+               if (ptr [1] != 0x90 || ptr [2] != 0x80 || ptr [3] != 0x70 || ptr [4] != 0x60 || ptr [5] != 0x50 || ptr [6] != 0x40)
+                       return 4;
+
+               return 0;
+       }
+
+       public static unsafe int test_0_ldobj_stobj ()
+       {
+               byte *dest = stackalloc byte [20];
+               byte *src = stackalloc byte [20];
+
+               for (int i = 0; i < 20; ++i)
+                       src [i] = (byte)i;
+
+               Intrinsics.UnalignedLdobjStObjPair<short> (dest + 0, src + 0);
+               if (dest [0] != src [0] || dest [1] != src [1])
+                       return 1;
+
+               Intrinsics.UnalignedLdobjStObjPair<short> (dest + 1, src + 0);
+               if (dest [1] != src [0] || dest [2] != src [1])
+                       return 2;
+
+               Intrinsics.UnalignedLdobjStObjPair<short> (dest + 0, src + 1);
+               if (dest [0] != src [1] || dest [1] != src [2])
+                       return 3;
+
+               Intrinsics.UnalignedLdobjStObjPair<short> (dest + 1, src + 1);
+               if (dest [1] != src [1] || dest [2] != src [2])
+                       return 3;
+
+               Intrinsics.UnalignedLdobjStObjPair<int> (dest + 1, src + 1);
+               if (dest [1] != src [1] || dest [2] != src [2])
+                       return 4;
+
+               Intrinsics.UnalignedLdobjStObjPair<long> (dest + 1, src + 1);
+               if (dest [1] != src [1] || dest [2] != src [2])
+                       return 5;
+
+
+               return 0;
+       }
+
+
+       public static unsafe int test_0_cpblk ()
+       {
+               byte *dest = stackalloc byte [20];
+               byte *src = stackalloc byte [20];
+               for (int i = 0; i < 20; ++i)
+                       src [i] = (byte)i;
+
+
+               Intrinsics.UnalignedCpblk (dest + 0, src + 0, 2);
+               if (dest [0] != src [0] || dest [1] != src [1])
+                       return 1;
+
+               Intrinsics.UnalignedCpblk (dest + 1, src + 0, 2);
+               if (dest [1] != src [0] || dest [2] != src [1])
+                       return 2;
+
+               Intrinsics.UnalignedCpblk (dest + 0, src + 1, 2);
+               if (dest [0] != src [1] || dest [1] != src [2])
+                       return 3;
+
+               Intrinsics.UnalignedCpblk (dest + 1, src + 1, 2);
+               if (dest [1] != src [1] || dest [2] != src [2])
+                       return 3;
+
+               Intrinsics.UnalignedCpblk (dest + 1, src + 1, 4);
+               for (int i = 0; i < 4; ++i) {
+                       if (dest [i + 1] != src [i + 1])
+                               return 4;
+               }
+
+               Intrinsics.UnalignedCpblk (dest + 1, src + 1, 8);
+               for (int i = 0; i < 8; ++i) {
+                       if (dest [i + 1] != src [i + 1])
+                               return 5;
+               }
+
+               return 0;
+       }
+
+
+       public static unsafe int test_0_initblk ()
+       {
+               byte *ptr = stackalloc byte [20];
+
+               for (int i = 0; i < 20; ++i)
+                       ptr [i] = (byte)i;
+
+               Intrinsics.UnalignedInit (ptr, 30, 2);
+               if (ptr [0] != 30 || ptr [1] != 30)
+                       return 1;
+
+               Intrinsics.UnalignedInit (ptr + 1, 31, 2);
+               if (ptr[0] != 30 || ptr [1] != 31 || ptr [2] != 31)
+                       return 2;
+
+               return 0;
+       }
+}
+
+#if __MOBILE__
+}
+#endif
+
+
+
index 58b826ef15af98b6039bd5bc4e6f91d0462f49e3..f4182ec0e34202ea1a22c865aedd346985ae00e8 100755 (executable)
@@ -463,6 +463,7 @@ TESTS_CS_SRC=               \
        assemblyresolve_event2.2.cs     \
        appdomain-unload-callback.cs    \
        appdomain-unload-doesnot-raise-pending-events.cs        \
+       appdomain-unload-asmload.cs     \
        unload-appdomain-on-shutdown.cs \
        bug-47295.cs    \
        loader.cs       \
diff --git a/mono/tests/appdomain-unload-asmload.cs b/mono/tests/appdomain-unload-asmload.cs
new file mode 100644 (file)
index 0000000..5f79890
--- /dev/null
@@ -0,0 +1,57 @@
+using System;
+using System.Threading.Tasks;
+
+/* This is a regression test that checks that after an AssemblyLoad event fires
+ * in a domain, the domain can be unloaded.  In bug # 56694, a
+ * System.Reflection.Assembly object from the unloaded domain was kept alive
+ * and crashed the GC.  */
+namespace AppDomainUnloadAsmLoad
+{
+       class Program
+       {
+               static void Main(string[] args)
+               {
+                       // Need some threads in play
+                       new Program().Run().Wait();
+               }
+
+               private async Task Run()
+               {
+                       var appDomain = AppDomain.CreateDomain("Test subdomain", null, AppDomain.CurrentDomain.SetupInformation);
+                       try
+                       {
+                               var driver = (AppDomainTestDriver)appDomain.CreateInstanceAndUnwrap(typeof(AppDomainTestDriver).Assembly.FullName,
+                                                                                                   typeof(AppDomainTestDriver).FullName);
+                               driver.Test();
+                       }
+                       finally
+                       {
+                               AppDomain.Unload(appDomain);
+                       }
+               }
+       }
+
+       class AppDomainTestDriver : MarshalByRefObject
+       {
+               static AppDomainTestDriver()
+               {
+                       // Needs a callback so that the runtime fires the
+                       // AssembyLoad event for this domain and materializes a System.Reflection.Assembly
+                       AppDomain.CurrentDomain.AssemblyLoad += CurrentDomain_AssemblyLoad;
+               }
+
+               private static void CurrentDomain_AssemblyLoad(object sender, AssemblyLoadEventArgs args)
+               {
+               }
+
+               internal void Test()
+               {
+                       /* this can be any class from any assembly that hasn't
+                        * already been loaded into the test domain.
+                        * System.Xml.dll is good because all the tests link
+                        * against it, but it's not otherwise used by this
+                        * domain. */
+                       var foo = default(System.Xml.XmlException);
+               }
+    }
+}
index cc86c7387d0b7728ac01e1d8733786d3b6f4c907..aecae40401d0b921845a313fde973fe7d126c7cc 100644 (file)
@@ -533,6 +533,9 @@ public class Tests
                        if (TestITestDelegate (itest) != 0)
                                return 174;
 
+                       if (TestIfaceNoIcall (itest as ITestPresSig) != 0)
+                               return 201;
+
                        itest = new TestClass ();
 
                        if (TestITest (itest) != 0)
@@ -543,6 +546,7 @@ public class Tests
                        if (TestITest (itest) != 0)
                                return 176;
 
+
 #endif
 
                        #endregion // Runtime Callable Wrapper Tests
@@ -775,6 +779,7 @@ public class Tests
                void ITestIn ([MarshalAs (UnmanagedType.Interface)]ITest val);
                [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
                void ITestOut ([MarshalAs (UnmanagedType.Interface)]out ITest val);
+               int Return22NoICall();
        }
 
        [ComImport ()]
@@ -826,6 +831,8 @@ public class Tests
                [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
                [PreserveSig ()]
                int ITestOut ([MarshalAs (UnmanagedType.Interface)]out ITestPresSig val);
+               [PreserveSig ()]
+               int Return22NoICall();
        }
 
        [System.Runtime.InteropServices.GuidAttribute ("00000000-0000-0000-0000-000000000002")]
@@ -865,6 +872,9 @@ public class Tests
                public virtual extern void ITestIn ([MarshalAs (UnmanagedType.Interface)]ITest val);
                [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
                public virtual extern void ITestOut ([MarshalAs (UnmanagedType.Interface)]out ITest val);
+
+               [MethodImplAttribute (MethodImplOptions.InternalCall, MethodCodeType = MethodCodeType.Runtime)]
+               public virtual extern int Return22NoICall();
        }
 
        [System.Runtime.InteropServices.GuidAttribute ("00000000-0000-0000-0000-000000000002")]
@@ -1004,6 +1014,11 @@ public class Tests
                        val = new ManagedTestPresSig ();
                        return 0;
                }
+
+               public int Return22NoICall()
+               {
+                       return 88;
+               }
        }
 
        public class ManagedTest : ITest
@@ -1093,6 +1108,11 @@ public class Tests
                                return new ManagedTest ();
                        }
                }
+
+               public int Return22NoICall()
+               {
+                       return 99;
+               }
        }
 
        public static int mono_test_marshal_variant_in_callback (VarEnum vt, object obj)
@@ -1306,6 +1326,10 @@ public class Tests
                }
                return 0;
        }
+
+       public static int TestIfaceNoIcall (ITestPresSig itest) {
+               return itest.Return22NoICall () == 22 ? 0 : 1;
+       }
 }
 
 public class TestVisible
index 4517eda2f74f64ddc41f8e2453372f4b17e5fd12..b94b29d52fd8eae95c11e0877adcc1269a91093d 100644 (file)
@@ -3337,6 +3337,7 @@ typedef struct
        int (STDCALL *DoubleIn)(MonoComObject* pUnk, double a);
        int (STDCALL *ITestIn)(MonoComObject* pUnk, MonoComObject* pUnk2);
        int (STDCALL *ITestOut)(MonoComObject* pUnk, MonoComObject* *ppUnk);
+       int (STDCALL *Return22NoICall)(MonoComObject* pUnk);
 } MonoIUnknown;
 
 struct MonoComObject
@@ -3453,6 +3454,13 @@ ITestOut(MonoComObject* pUnk, MonoComObject* *ppUnk)
        return S_OK;
 }
 
+LIBTEST_API int STDCALL
+Return22NoICall(MonoComObject* pUnk)
+{
+       return 22;
+}
+
+
 static void create_com_object (MonoComObject** pOut);
 
 LIBTEST_API int STDCALL 
@@ -3484,6 +3492,7 @@ static void create_com_object (MonoComObject** pOut)
        (*pOut)->vtbl->ITestIn = ITestIn;
        (*pOut)->vtbl->ITestOut = ITestOut;
        (*pOut)->vtbl->get_ITest = get_ITest;
+       (*pOut)->vtbl->Return22NoICall = Return22NoICall;
 }
 
 static MonoComObject* same_object = NULL;
index 8a0d43f3a3660255097fa2cb59e9e21a2f399697..05550ac2277e360581cabe68284d821f3fd55787 100644 (file)
@@ -277,4 +277,20 @@ public class Tests {
                        return 1;
                return 0;
        }
+
+       public static int test_0_generic_ptr_to_struct () {
+               int size = Marshal.SizeOf (typeof (SimpleStruct2));
+               IntPtr p = Marshal.AllocHGlobal (size);
+
+               Marshal.WriteInt32 (p, 0, 1); //a
+               Marshal.WriteInt32 (p, 4, 2); //a
+
+               var s = Marshal.PtrToStructure<SimpleStruct2> (p);
+
+               if (s.a != 1)
+                       return 1;
+               if (s.b != 2)
+                       return 2;
+               return 0;
+       }
 }
index b2c969ba0bd0cbfd5a79ecebc4eeb6f8732856cb..ec04c4d1c5f17f5df5dab43b834893dc048783f1 100644 (file)
@@ -10,6 +10,7 @@ endif
 if !CROSS_COMPILE
 if !HOST_WIN32
 if SUPPORT_BOEHM
+if SUPPORT_SGEN
 
 noinst_LTLIBRARIES = libtestlib.la
 libtestlib_la_SOURCES =
@@ -54,6 +55,7 @@ check-local:
                echo "</test-case></results></test-suite></test-results>" >> TestResult-unit-tests.xml; \
        fi;
 
+endif SUPPORT_SGEN
 endif SUPPORT_BOEHM
 endif !HOST_WIN32
 endif !CROSS_COMPILE
index f733896a6d73ae9a4997347724b5790488230aa4..5c5b891d607ab952d55bc3699d857566c6ce9c64 100644 (file)
@@ -131,11 +131,11 @@ mono_process_list (int *size)
                mib [2] = KERN_PROC_ALL;
                mib [3] = 0;
 
-               res = sysctl (mib, 4, NULL, &data_len, NULL, 0);
+               res = sysctl (mib, 3, NULL, &data_len, NULL, 0);
                if (res)
                        return NULL;
                processes = (struct kinfo_proc *) g_malloc (data_len);
-               res = sysctl (mib, 4, processes, &data_len, NULL, 0);
+               res = sysctl (mib, 3, processes, &data_len, NULL, 0);
                if (res < 0) {
                        g_free (processes);
                        if (errno != ENOMEM)
index f5449aa086c20d8e6a2b95bcd9a3c28021cba134..70dc4b0554c6eb8d780d1a2c8dcd7feb348ab91a 100644 (file)
     <ClCompile Include="..\mono\mini\mini-native-types.c" />\r
     <ClCompile Include="..\mono\mini\type-checking.c" />\r
     <ClCompile Include="..\mono\mini\lldb.c" />\r
+    <ClCompile Include="..\mono\mini\interp\interp-stubs.c" />\r
   </ItemGroup>\r
   <PropertyGroup Label="Globals">\r
     <ProjectGuid>{CB0D9E92-293C-439C-9AC7-C5F59B6E0772}</ProjectGuid>\r
   <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />\r
   <ImportGroup Label="ExtensionTargets">\r
   </ImportGroup>\r
-</Project>
\ No newline at end of file
+</Project>\r
index 3ff2406521426133728ed01ee90cfdaa43931fda..029b9d162c15144f2740162e2726bb56fb2572ac 100644 (file)
     <ClCompile Include="..\mono\mini\lldb.c">\r
       <Filter>Source Files</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\mono\mini\interp\interp-stubs.c">\r
+      <Filter>Source Files</Filter>\r
+    </ClCompile>\r
   </ItemGroup>\r
   <ItemGroup>\r
     <ClInclude Include="..\mono\mini\abcremoval.h">\r
       <Filter>Resource Files</Filter>\r
     </None>\r
   </ItemGroup>\r
-</Project>
\ No newline at end of file
+</Project>\r