[jit] In native-to-managed wrappers, emit the initlocals code for vtypes after the...
authorZoltan Varga <vargaz@gmail.com>
Thu, 5 Oct 2017 12:10:20 +0000 (14:10 +0200)
committerGitHub <noreply@github.com>
Thu, 5 Oct 2017 12:10:20 +0000 (14:10 +0200)
mono/mini/method-to-ir.c
mono/tests/libtest.c
mono/tests/pinvoke3.cs

index 8df37c178d64cab31e36c9db208bbe40d02f8163..7d8dce75ca07b42fd218a2507ec0102d551a8f7e 100644 (file)
@@ -7219,7 +7219,8 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
 {
        MonoError error;
        MonoInst *ins, **sp, **stack_start;
-       MonoBasicBlock *tblock = NULL, *init_localsbb = NULL;
+       MonoBasicBlock *tblock = NULL;
+       MonoBasicBlock *init_localsbb = NULL, *init_localsbb2 = NULL;
        MonoSimpleBasicBlock *bb = NULL, *original_bb = NULL;
        MonoMethod *cmethod, *method_definition;
        MonoInst **arg_array;
@@ -7556,7 +7557,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
        init_localsbb->next_bb = cfg->cbb;
        link_bblock (cfg, start_bblock, init_localsbb);
        link_bblock (cfg, init_localsbb, cfg->cbb);
-               
+       init_localsbb2 = init_localsbb;
        cfg->cbb = init_localsbb;
 
        if (cfg->gsharedvt && cfg->method == method) {
@@ -11934,6 +11935,13 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                                if (next_bb)
                                        MONO_START_BB (cfg, next_bb);
 
+                               /*
+                                * Parts of the initlocals code needs to come after this, since it might call methods like memset.
+                                */
+                               init_localsbb2 = cfg->cbb;
+                               NEW_BBLOCK (cfg, next_bb);
+                               MONO_START_BB (cfg, next_bb);
+
                                ip += 2;
                                break;
                        }
@@ -12708,6 +12716,14 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b
                cfg->cbb = init_localsbb;
                cfg->ip = NULL;
                for (i = 0; i < header->num_locals; ++i) {
+                       /*
+                        * Vtype initialization might need to be done after CEE_JIT_ATTACH, since it can make calls to memset (),
+                        * which need the trampoline code to work.
+                        */
+                       if (MONO_TYPE_ISSTRUCT (header->locals [i]))
+                               cfg->cbb = init_localsbb2;
+                       else
+                               cfg->cbb = init_localsbb;
                        emit_init_local (cfg, i, header->locals [i], init_locals);
                }
        }
index 185c987665e8ab25ee4bd915680c7167904e5b35..46f8cc5d3d522841e6afeee7fd527ce427d51504 100644 (file)
@@ -5500,6 +5500,38 @@ mono_test_marshal_thread_attach (SimpleDelegate del)
 #endif
 }
 
+typedef struct {
+       char arr [4 * 1024];
+} LargeStruct;
+
+typedef int (STDCALL *LargeStructDelegate) (LargeStruct *s);
+
+static void
+call_managed_large_vt (gpointer arg)
+{
+       LargeStructDelegate del = (LargeStructDelegate)arg;
+       LargeStruct s;
+
+       call_managed_res = del (&s);
+}
+
+LIBTEST_API int STDCALL
+mono_test_marshal_thread_attach_large_vt (SimpleDelegate del)
+{
+#ifdef WIN32
+       return 43;
+#else
+       int res;
+       pthread_t t;
+
+       res = pthread_create (&t, NULL, (gpointer (*)(gpointer))call_managed_large_vt, del);
+       g_assert (res == 0);
+       pthread_join (t, NULL);
+
+       return call_managed_res;
+#endif
+}
+
 typedef int (STDCALL *Callback) (void);
 
 static Callback callback;
index 075ef08bc48c809174db8e1e6d87f594713fa550..c1354ce9b544dc34baea80b26e75b16fa20e156b 100644 (file)
@@ -1120,6 +1120,44 @@ public class Tests {
                return res;
        }
 
+       public struct LargeStruct {
+            public Int16 s;
+            public Int16 v;
+            public UInt32 p;
+            public UInt32 e;
+            public Int32 l;
+            public Int32 ll;
+            public UInt16 h;
+            public Int16 r;
+            public Int16 pp;
+            public Int32 hh;
+            public Int32 bn;
+            public Int32 dn;
+            public Int32 dr;
+            public Int32 sh;
+            public Int32 ra;
+            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+            public Int32[] angle;
+            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+            public Int32[] width;
+            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3)]
+            public Int32[] edge;
+            [MarshalAs(UnmanagedType.ByValArray, SizeConst = 3 * 1024)]
+            public byte[] echo;
+       }
+
+       public delegate int LargeStructDelegate (ref LargeStruct s);
+
+       [DllImport ("libtest", EntryPoint="mono_test_marshal_thread_attach_large_vt")]
+       public static extern int mono_test_marshal_thread_attach_large_vt (LargeStructDelegate d);
+
+       public static int test_43_thread_attach_large_vt () {
+               int res = mono_test_marshal_thread_attach_large_vt (delegate (ref LargeStruct s) {
+                               return 43;
+                       });
+               return res;
+       }
+
        class Worker {
                volatile bool stop = false;
                public void Stop () {