From 012f8610237dfe44034c9d8daea0b90fac75ca9f Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Thu, 5 Oct 2017 14:10:20 +0200 Subject: [PATCH] [jit] In native-to-managed wrappers, emit the initlocals code for vtypes after the code for CEE_JIT_ATTACH, since the init code can make calls to methods like memset () which can go through the trampoline code. Fixes #59182. (#5678) --- mono/mini/method-to-ir.c | 20 ++++++++++++++++++-- mono/tests/libtest.c | 32 ++++++++++++++++++++++++++++++++ mono/tests/pinvoke3.cs | 38 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 88 insertions(+), 2 deletions(-) diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 8df37c178d6..7d8dce75ca0 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -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); } } diff --git a/mono/tests/libtest.c b/mono/tests/libtest.c index 185c987665e..46f8cc5d3d5 100644 --- a/mono/tests/libtest.c +++ b/mono/tests/libtest.c @@ -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; diff --git a/mono/tests/pinvoke3.cs b/mono/tests/pinvoke3.cs index 075ef08bc48..c1354ce9b54 100644 --- a/mono/tests/pinvoke3.cs +++ b/mono/tests/pinvoke3.cs @@ -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 () { -- 2.25.1