From e0020238f469b3d4863ba8dfea5ddc25284c3453 Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Mon, 28 Oct 2019 10:59:53 -0400 Subject: [PATCH] [runtime] Implement support for SuppressGCTransitionAttribute. (mono/mono#17534) Fixes https://github.com/mono/mono/issues/17367. Commit migrated from https://github.com/mono/mono/commit/e4cc70f4b5038ec5d6500ba988d0bb67143658bc --- src/mono/mono/metadata/cominterop.c | 2 +- src/mono/mono/metadata/marshal-ilgen.c | 6 +++-- src/mono/mono/metadata/marshal.c | 41 +++++++++++++++++++++++++++++----- src/mono/mono/metadata/marshal.h | 4 ++-- 4 files changed, 42 insertions(+), 11 deletions(-) diff --git a/src/mono/mono/metadata/cominterop.c b/src/mono/mono/metadata/cominterop.c index 20f6129..299beab 100644 --- a/src/mono/mono/metadata/cominterop.c +++ b/src/mono/mono/metadata/cominterop.c @@ -1008,7 +1008,7 @@ cominterop_get_native_wrapper_adjusted (MonoMethod *method) } } - mono_marshal_emit_native_wrapper (m_class_get_image (method->klass), mb_native, sig_native, piinfo, mspecs, piinfo->addr, FALSE, TRUE, FALSE); + mono_marshal_emit_native_wrapper (m_class_get_image (method->klass), mb_native, sig_native, piinfo, mspecs, piinfo->addr, FALSE, TRUE, FALSE, FALSE); res = mono_mb_create_method (mb_native, sig_native, sig_native->param_count + 16); diff --git a/src/mono/mono/metadata/marshal-ilgen.c b/src/mono/mono/metadata/marshal-ilgen.c index d751f29..35cd3a1 100644 --- a/src/mono/mono/metadata/marshal-ilgen.c +++ b/src/mono/mono/metadata/marshal-ilgen.c @@ -1865,11 +1865,12 @@ gc_safe_transition_builder_cleanup (GCSafeTransitionBuilder *builder) * \param method if non-NULL, the pinvoke method to call * \param check_exceptions Whenever to check for pending exceptions after the native call * \param func_param the function to call is passed as a boxed IntPtr as the first parameter + * \param skip_gc_trans Whenever to skip GC transitions * * generates IL code for the pinvoke wrapper, the generated code calls \p func . */ static void -emit_native_wrapper_ilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethodPInvoke *piinfo, MonoMarshalSpec **mspecs, gpointer func, gboolean aot, gboolean check_exceptions, gboolean func_param) +emit_native_wrapper_ilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethodPInvoke *piinfo, MonoMarshalSpec **mspecs, gpointer func, gboolean aot, gboolean check_exceptions, gboolean func_param, gboolean skip_gc_trans) { EmitMarshalContext m; MonoMethodSignature *csig; @@ -1884,7 +1885,8 @@ emit_native_wrapper_ilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSi m.sig = sig; m.piinfo = piinfo; - need_gc_safe = gc_safe_transition_builder_init (&gc_safe_transition_builder, mb, func_param); + if (!skip_gc_trans) + need_gc_safe = gc_safe_transition_builder_init (&gc_safe_transition_builder, mb, func_param); /* we copy the signature, so that we can set pinvoke to 0 */ if (func_param) { diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index be89c4d..df78309 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -111,6 +111,10 @@ delegate_hash_table_remove (MonoDelegate *d); GENERATE_TRY_GET_CLASS_WITH_CACHE (stringbuilder, "System.Text", "StringBuilder"); static GENERATE_TRY_GET_CLASS_WITH_CACHE (unmanaged_function_pointer_attribute, "System.Runtime.InteropServices", "UnmanagedFunctionPointerAttribute"); +#ifdef ENABLE_NETCORE +static GENERATE_TRY_GET_CLASS_WITH_CACHE (suppress_gc_transition_attribute, "System.Runtime.InteropServices", "SuppressGCTransitionAttribute") +#endif + static MonoImage* get_method_image (MonoMethod *method) { @@ -3464,6 +3468,7 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, MonoMethod *res; GHashTable *cache; gboolean pinvoke = FALSE; + gboolean skip_gc_trans = FALSE; gpointer iter; int i; ERROR_DECL (emitted_error); @@ -3631,7 +3636,31 @@ mono_marshal_get_native_wrapper (MonoMethod *method, gboolean check_exceptions, mspecs = g_new (MonoMarshalSpec*, sig->param_count + 1); mono_method_get_marshal_info (method, mspecs); - mono_marshal_emit_native_wrapper (get_method_image (mb->method), mb, csig, piinfo, mspecs, piinfo->addr, aot, check_exceptions, FALSE); +#ifdef ENABLE_NETCORE + if (mono_class_try_get_suppress_gc_transition_attribute_class ()) { + MonoCustomAttrInfo *cinfo; + ERROR_DECL (error); + + cinfo = mono_custom_attrs_from_method_checked (method, error); + mono_error_assert_ok (error); + gboolean found = FALSE; + if (cinfo) { + for (i = 0; i < cinfo->num_attrs; ++i) { + MonoClass *ctor_class = cinfo->attrs [i].ctor->klass; + if (ctor_class == mono_class_try_get_suppress_gc_transition_attribute_class ()) { + found = TRUE; + break; + } + } + } + if (found) + skip_gc_trans = TRUE; + if (cinfo && !cinfo->cached) + mono_custom_attrs_free (cinfo); + } +#endif + + mono_marshal_emit_native_wrapper (get_method_image (mb->method), mb, csig, piinfo, mspecs, piinfo->addr, aot, check_exceptions, FALSE, skip_gc_trans); info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_PINVOKE); info->d.managed_to_native.method = method; @@ -3686,7 +3715,7 @@ mono_marshal_get_native_func_wrapper (MonoImage *image, MonoMethodSignature *sig mb = mono_mb_new (mono_defaults.object_class, name, MONO_WRAPPER_MANAGED_TO_NATIVE); mb->method->save_lmf = 1; - mono_marshal_emit_native_wrapper (image, mb, sig, piinfo, mspecs, func, FALSE, TRUE, FALSE); + mono_marshal_emit_native_wrapper (image, mb, sig, piinfo, mspecs, func, FALSE, TRUE, FALSE, FALSE); csig = mono_metadata_signature_dup_full (image, sig); csig->pinvoke = 0; @@ -3749,7 +3778,7 @@ mono_marshal_get_native_func_wrapper_aot (MonoClass *klass) mb = mono_mb_new (invoke->klass, name, MONO_WRAPPER_MANAGED_TO_NATIVE); mb->method->save_lmf = 1; - mono_marshal_emit_native_wrapper (image, mb, sig, piinfo, mspecs, NULL, FALSE, TRUE, TRUE); + mono_marshal_emit_native_wrapper (image, mb, sig, piinfo, mspecs, NULL, FALSE, TRUE, TRUE, FALSE); info = mono_wrapper_info_create (mb, WRAPPER_SUBTYPE_NATIVE_FUNC_AOT); info->d.managed_to_native.method = invoke; @@ -6414,14 +6443,14 @@ mono_marshal_get_type_object (MonoClass *klass) } void -mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethodPInvoke *piinfo, MonoMarshalSpec **mspecs, gpointer func, gboolean aot, gboolean check_exceptions, gboolean func_param) +mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethodPInvoke *piinfo, MonoMarshalSpec **mspecs, gpointer func, gboolean aot, gboolean check_exceptions, gboolean func_param, gboolean skip_gc_trans) { - get_marshal_cb ()->emit_native_wrapper (image, mb, sig, piinfo, mspecs, func, aot, check_exceptions, func_param); + get_marshal_cb ()->emit_native_wrapper (image, mb, sig, piinfo, mspecs, func, aot, check_exceptions, func_param, skip_gc_trans); } #ifndef ENABLE_ILGEN static void -emit_native_wrapper_noilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethodPInvoke *piinfo, MonoMarshalSpec **mspecs, gpointer func, gboolean aot, gboolean check_exceptions, gboolean func_param) +emit_native_wrapper_noilgen (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethodPInvoke *piinfo, MonoMarshalSpec **mspecs, gpointer func, gboolean aot, gboolean check_exceptions, gboolean func_param, gboolean skip_gc_trans) { } #endif diff --git a/src/mono/mono/metadata/marshal.h b/src/mono/mono/metadata/marshal.h index 50094c4..fa6a9ca 100644 --- a/src/mono/mono/metadata/marshal.h +++ b/src/mono/mono/metadata/marshal.h @@ -323,7 +323,7 @@ typedef struct { void (*emit_virtual_stelemref) (MonoMethodBuilder *mb, const char **param_names, MonoStelemrefKind kind); void (*emit_stelemref) (MonoMethodBuilder *mb); void (*emit_array_address) (MonoMethodBuilder *mb, int rank, int elem_size); - void (*emit_native_wrapper) (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethodPInvoke *piinfo, MonoMarshalSpec **mspecs, gpointer func, gboolean aot, gboolean check_exceptions, gboolean func_param); + void (*emit_native_wrapper) (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethodPInvoke *piinfo, MonoMarshalSpec **mspecs, gpointer func, gboolean aot, gboolean check_exceptions, gboolean func_param, gboolean skip_gc_trans); void (*emit_managed_wrapper) (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, uint32_t target_handle); void (*emit_runtime_invoke_body) (MonoMethodBuilder *mb, const char **param_names, MonoImage *image, MonoMethod *method, MonoMethodSignature *sig, MonoMethodSignature *callsig, gboolean virtual_, gboolean need_direct_wrapper); void (*emit_runtime_invoke_dynamic) (MonoMethodBuilder *mb); @@ -659,7 +659,7 @@ mono_signature_no_pinvoke (MonoMethod *method); /* Called from cominterop.c/remoting.c */ void -mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethodPInvoke *piinfo, MonoMarshalSpec **mspecs, gpointer func, gboolean aot, gboolean check_exceptions, gboolean func_param); +mono_marshal_emit_native_wrapper (MonoImage *image, MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethodPInvoke *piinfo, MonoMarshalSpec **mspecs, gpointer func, gboolean aot, gboolean check_exceptions, gboolean func_param, gboolean skip_gc_trans); void mono_marshal_emit_managed_wrapper (MonoMethodBuilder *mb, MonoMethodSignature *invoke_sig, MonoMarshalSpec **mspecs, EmitMarshalContext* m, MonoMethod *method, uint32_t target_handle); -- 2.7.4