From 33604b1581a02cffa02fb43ae2ea0ab32b56a38d Mon Sep 17 00:00:00 2001 From: Vlad - Alexandru Ionescu Date: Wed, 26 Apr 2023 20:31:34 +0200 Subject: [PATCH 01/14] try to add virt delegates --- src/mono/mono/metadata/marshal-lightweight.c | 2 +- src/mono/mono/metadata/marshal.c | 22 ++++------------ src/mono/mono/metadata/marshal.h | 2 +- src/mono/mono/metadata/metadata-internals.h | 1 + src/mono/mono/metadata/metadata.c | 27 ++++++++++++++++++++ src/mono/mono/mini/aot-compiler.c | 7 +++++ 6 files changed, 42 insertions(+), 19 deletions(-) diff --git a/src/mono/mono/metadata/marshal-lightweight.c b/src/mono/mono/metadata/marshal-lightweight.c index 06a20123dbee6..28cb6e8244d10 100644 --- a/src/mono/mono/metadata/marshal-lightweight.c +++ b/src/mono/mono/metadata/marshal-lightweight.c @@ -1990,7 +1990,7 @@ emit_delegate_end_invoke_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *sig) } static void -emit_delegate_invoke_internal_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethodSignature *invoke_sig, MonoMethodSignature *target_method_sig, gboolean static_method_with_first_arg_bound, gboolean callvirt, gboolean closed_over_null, MonoMethod *method, MonoMethod *target_method, MonoClass *target_class, MonoGenericContext *ctx, MonoGenericContainer *container) +emit_delegate_invoke_internal_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethodSignature *invoke_sig, MonoMethodSignature *target_method_sig, gboolean static_method_with_first_arg_bound, gboolean callvirt, gboolean closed_over_null, MonoMethod *method, MonoMethod *target_method, MonoGenericContext *ctx, MonoGenericContainer *container) { int local_i, local_len, local_delegates, local_d, local_target, local_res = 0; int pos0, pos1, pos2; diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index 977ecd9e768e7..8bafea59dca20 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -2092,7 +2092,6 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt GHashTable *cache; gpointer cache_key = NULL; char *name; - MonoClass *target_class = NULL; gboolean closed_over_null = FALSE; MonoGenericContext *ctx = NULL; MonoGenericContainer *container = NULL; @@ -2113,25 +2112,14 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt */ if (callvirt) { subtype = WRAPPER_SUBTYPE_DELEGATE_INVOKE_VIRTUAL; - if (target_method->is_inflated) { - ERROR_DECL (error); - MonoType *target_type; - - g_assert (method->signature->hasthis); - target_type = mono_class_inflate_generic_type_checked (method->signature->params [0], - mono_method_get_context (method), error); - mono_error_assert_ok (error); /* FIXME don't swallow the error */ - target_class = mono_class_from_mono_type_internal (target_type); - } else { - target_class = target_method->klass; - } - - closed_over_null = sig->param_count == mono_method_signature_internal (target_method)->param_count; /* * We don't want to use target_method's signature because it can be freed early */ - target_method_sig = mono_method_signature_internal (target_method); + target_method_sig = mono_metadata_signature_dup_delegate_invoke_to_target (invoke_sig); + // target_method_sig = mono_method_signature_internal (target_method); + + closed_over_null = sig->param_count == target_method_sig->param_count; } if (static_method_with_first_arg_bound) { @@ -2241,7 +2229,7 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt /* FIXME: Other subtypes */ mb->mem_manager = m_method_get_mem_manager (method); - get_marshal_cb ()->emit_delegate_invoke_internal (mb, sig, invoke_sig, target_method_sig, static_method_with_first_arg_bound, callvirt, closed_over_null, method, target_method, target_class, ctx, container); + get_marshal_cb ()->emit_delegate_invoke_internal (mb, sig, invoke_sig, target_method_sig, static_method_with_first_arg_bound, callvirt, closed_over_null, method, target_method, ctx, container); get_marshal_cb ()->mb_skip_visibility (mb); diff --git a/src/mono/mono/metadata/marshal.h b/src/mono/mono/metadata/marshal.h index e6ad3153bbfda..9f261cf01a7fc 100644 --- a/src/mono/mono/metadata/marshal.h +++ b/src/mono/mono/metadata/marshal.h @@ -328,7 +328,7 @@ typedef struct { void (*emit_runtime_invoke_dynamic) (MonoMethodBuilder *mb); void (*emit_delegate_begin_invoke) (MonoMethodBuilder *mb, MonoMethodSignature *sig); void (*emit_delegate_end_invoke) (MonoMethodBuilder *mb, MonoMethodSignature *sig); - void (*emit_delegate_invoke_internal) (MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethodSignature *invoke_sig, MonoMethodSignature *target_method_sig, gboolean static_method_with_first_arg_bound, gboolean callvirt, gboolean closed_over_null, MonoMethod *method, MonoMethod *target_method, MonoClass *target_class, MonoGenericContext *ctx, MonoGenericContainer *container); + void (*emit_delegate_invoke_internal) (MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethodSignature *invoke_sig, MonoMethodSignature *target_method_sig, gboolean static_method_with_first_arg_bound, gboolean callvirt, gboolean closed_over_null, MonoMethod *method, MonoMethod *target_method, MonoGenericContext *ctx, MonoGenericContainer *container); void (*emit_synchronized_wrapper) (MonoMethodBuilder *mb, MonoMethod *method, MonoGenericContext *ctx, MonoGenericContainer *container, MonoMethod *enter_method, MonoMethod *exit_method, MonoMethod *gettypefromhandle_method); void (*emit_unbox_wrapper) (MonoMethodBuilder *mb, MonoMethod *method); void (*emit_array_accessor_wrapper) (MonoMethodBuilder *mb, MonoMethod *method, MonoMethodSignature *sig, MonoGenericContext *ctx); diff --git a/src/mono/mono/metadata/metadata-internals.h b/src/mono/mono/metadata/metadata-internals.h index 009861f03dfe4..d06a407136963 100644 --- a/src/mono/mono/metadata/metadata-internals.h +++ b/src/mono/mono/metadata/metadata-internals.h @@ -985,6 +985,7 @@ MonoMethodSignature *mono_metadata_signature_dup_full (MonoImage *image,MonoMet MonoMethodSignature *mono_metadata_signature_dup_mempool (MonoMemPool *mp, MonoMethodSignature *sig); MonoMethodSignature *mono_metadata_signature_dup_mem_manager (MonoMemoryManager *mem_manager, MonoMethodSignature *sig); MonoMethodSignature *mono_metadata_signature_dup_add_this (MonoImage *image, MonoMethodSignature *sig, MonoClass *klass); +MonoMethodSignature *mono_metadata_signature_dup_delegate_invoke_to_target (MonoMethodSignature *sig); MonoGenericInst * mono_get_shared_generic_inst (MonoGenericContainer *container); diff --git a/src/mono/mono/metadata/metadata.c b/src/mono/mono/metadata/metadata.c index c564777f84837..838202234d896 100644 --- a/src/mono/mono/metadata/metadata.c +++ b/src/mono/mono/metadata/metadata.c @@ -2512,6 +2512,33 @@ mono_metadata_signature_dup (MonoMethodSignature *sig) return mono_metadata_signature_dup_full (NULL, sig); } +/** + * mono_metadata_signature_dup_delegate_invoke_to_target: + * \param sig method signature + * + * Duplicate an existing \c MonoMethodSignature but removes first param from it so it can + * be used as signature for a delegate target method. + * This is a Mono runtime internal function. + * + * \returns the new \c MonoMethodSignature structure. + */ +MonoMethodSignature* +mono_metadata_signature_dup_delegate_invoke_to_target (MonoMethodSignature *sig) +{ + MonoMethodSignature *res = mono_metadata_signature_dup_full (NULL, sig); + + for (int i = 0 ; i < sig->param_count - 1; i ++) { + res->params [i] = sig->params [i + 1]; + } + + res->param_count --; + + // if (res->params [res->param_count - 1]) + // mono_metadata_free_type (res->params [res->param_count --]); + + return res; +} + /* * mono_metadata_signature_size: * diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 20a90856b6a64..7f67609d822f1 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -4965,6 +4965,13 @@ add_full_aot_wrappers (MonoAotCompile *acfg) continue; } + method = mono_get_delegate_invoke_internal (klass); + + if (!strcmp(method->name, "Foo") || !strcmp(method->name, "ToString") || !strcmp(method->name, "Invoke")) { + m = mono_marshal_get_delegate_invoke_internal (method, TRUE, FALSE, NULL); + add_method (acfg, m); + } + if (cattr) { int j; From e0d201dde3b07fea43b2640c2223b159ba04a12a Mon Sep 17 00:00:00 2001 From: Vlad - Alexandru Ionescu Date: Fri, 28 Apr 2023 14:59:54 +0200 Subject: [PATCH 02/14] Added encode and decode of klass for DELEGATE_VIRTUAL subtype Signed-off-by: Vlad - Alexandru Ionescu --- src/mono/mono/metadata/marshal-lightweight.c | 10 ++++++++-- src/mono/mono/mini/aot-compiler.c | 18 +++++++++-------- src/mono/mono/mini/aot-runtime.c | 21 ++++++++++++++++++-- 3 files changed, 37 insertions(+), 12 deletions(-) diff --git a/src/mono/mono/metadata/marshal-lightweight.c b/src/mono/mono/metadata/marshal-lightweight.c index 28cb6e8244d10..5ce2770555421 100644 --- a/src/mono/mono/metadata/marshal-lightweight.c +++ b/src/mono/mono/metadata/marshal-lightweight.c @@ -2088,9 +2088,15 @@ emit_delegate_invoke_internal_ilgen (MonoMethodBuilder *mb, MonoMethodSignature if (callvirt) { if (!closed_over_null) { - for (i = 1; i <= sig->param_count; ++i) + for (i = 1; i <= sig->param_count; ++i) { mono_mb_emit_ldarg (mb, i); - mono_mb_emit_ldarg (mb, 1); + if (i == 1 && MONO_TYPE_ISSTRUCT (sig->params [0])) + mono_mb_emit_op (mb, CEE_BOX, mono_class_from_mono_type_internal (sig->params [0])); + } + if (MONO_TYPE_ISSTRUCT (sig->params [0])) + mono_mb_emit_ldarg_addr (mb, 1); + else + mono_mb_emit_ldarg (mb, 1); mono_mb_emit_ldarg (mb, 0); mono_mb_emit_icall (mb, mono_get_addr_compiled_method); mono_mb_emit_op (mb, CEE_CALLI, target_method_sig); diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 7f67609d822f1..1ba93d467d5d6 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -3913,8 +3913,11 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 WrapperInfo *wrapper_info = mono_marshal_get_wrapper_info (method); encode_value (0, p, &p); + encode_value (wrapper_info ? wrapper_info->subtype : 0, p, &p); + if (method->wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE) - encode_value (wrapper_info ? wrapper_info->subtype : 0, p, &p); + encode_klass_ref (acfg, method->klass, p, &p); + encode_signature (acfg, sig, p, &p); } break; @@ -4949,6 +4952,12 @@ add_full_aot_wrappers (MonoAotCompile *acfg) add_method (acfg, m); + sig = mono_method_signature_internal (method); + if (sig->param_count && !m_class_is_byreflike (mono_class_from_mono_type_internal (sig->params [0]))) { + m = mono_marshal_get_delegate_invoke_internal (method, TRUE, FALSE, NULL); + add_method (acfg, m); + } + method = try_get_method_nofail (klass, "BeginInvoke", -1, 0); if (method) add_method (acfg, mono_marshal_get_delegate_begin_invoke (method)); @@ -4965,13 +4974,6 @@ add_full_aot_wrappers (MonoAotCompile *acfg) continue; } - method = mono_get_delegate_invoke_internal (klass); - - if (!strcmp(method->name, "Foo") || !strcmp(method->name, "ToString") || !strcmp(method->name, "Invoke")) { - m = mono_marshal_get_delegate_invoke_internal (method, TRUE, FALSE, NULL); - add_method (acfg, m); - } - if (cattr) { int j; diff --git a/src/mono/mono/mini/aot-runtime.c b/src/mono/mono/mini/aot-runtime.c index 84b032829be53..5ebf5949db7fd 100644 --- a/src/mono/mono/mini/aot-runtime.c +++ b/src/mono/mono/mini/aot-runtime.c @@ -1273,11 +1273,28 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod * These wrappers are associated with a signature, not with a method. * Since we can't decode them into methods, they need a target method. */ - if (!target) - return FALSE; + MonoClass *klass; + MonoMethodSignature *sig; + // if (!target) + // return FALSE; + if (wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE) { subtype = (WrapperSubtype)decode_value (p, &p); + if (subtype == WRAPPER_SUBTYPE_DELEGATE_INVOKE_VIRTUAL) { + gboolean res; + MonoMethod *method; + int mcount, i; + klass = decode_klass_ref (module, p, &p, error); + sig = decode_signature_with_target (module, NULL, p, &p); + + MonoMethod **klass_methods = m_class_get_methods (klass); + for (i = 0; i < mcount; ++i) { + if ( sig && mono_metadata_signature_equal (mono_method_signature_internal (klass_methods[i]), sig)) { + ref->method = klass_methods[i]; + } + } + } info = mono_marshal_get_wrapper_info (target); if (info) { if (info->subtype != subtype) From 6b6dae9507728f4559b2941533efa8fab54b7147 Mon Sep 17 00:00:00 2001 From: Vlad - Alexandru Ionescu Date: Fri, 28 Apr 2023 17:10:49 +0200 Subject: [PATCH 03/14] Changed how construction of callvirt delegate is done Signed-off-by: Vlad - Alexandru Ionescu --- src/mono/mono/mini/aot-compiler.c | 4 ++-- src/mono/mono/mini/aot-runtime.c | 16 ++++------------ 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 1ba93d467d5d6..da39edf039daf 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -3917,8 +3917,8 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 if (method->wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE) encode_klass_ref (acfg, method->klass, p, &p); - - encode_signature (acfg, sig, p, &p); + else + encode_signature (acfg, sig, p, &p); } break; } diff --git a/src/mono/mono/mini/aot-runtime.c b/src/mono/mono/mini/aot-runtime.c index 5ebf5949db7fd..a620bca9d8e93 100644 --- a/src/mono/mono/mini/aot-runtime.c +++ b/src/mono/mono/mini/aot-runtime.c @@ -1274,7 +1274,7 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod * Since we can't decode them into methods, they need a target method. */ MonoClass *klass; - MonoMethodSignature *sig; + MonoMethod *invoke; // if (!target) // return FALSE; @@ -1282,18 +1282,10 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod if (wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE) { subtype = (WrapperSubtype)decode_value (p, &p); if (subtype == WRAPPER_SUBTYPE_DELEGATE_INVOKE_VIRTUAL) { - gboolean res; - MonoMethod *method; - int mcount, i; klass = decode_klass_ref (module, p, &p, error); - sig = decode_signature_with_target (module, NULL, p, &p); - - MonoMethod **klass_methods = m_class_get_methods (klass); - for (i = 0; i < mcount; ++i) { - if ( sig && mono_metadata_signature_equal (mono_method_signature_internal (klass_methods[i]), sig)) { - ref->method = klass_methods[i]; - } - } + invoke = mono_get_delegate_invoke_internal (klass); + ref->method = mono_marshal_get_delegate_invoke_internal(invoke, TRUE, FALSE, NULL); + break; } info = mono_marshal_get_wrapper_info (target); if (info) { From c98a74893b3e31066df1dee048828cc2bceb860f Mon Sep 17 00:00:00 2001 From: Vlad - Alexandru Ionescu Date: Tue, 2 May 2023 12:24:09 +0200 Subject: [PATCH 04/14] Encode class only for delegate_invoke_virtual subtype Signed-off-by: Vlad - Alexandru Ionescu --- src/mono/mono/mini/aot-compiler.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index da39edf039daf..9dada76da80ce 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -3778,6 +3778,8 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 MonoJumpInfoToken *ji; guint8 *p = buf; + printf("NAME = %s\n", method->name); + /* * The encoding for most methods is as follows: * - image index encoded as a leb128 @@ -3915,7 +3917,7 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 encode_value (0, p, &p); encode_value (wrapper_info ? wrapper_info->subtype : 0, p, &p); - if (method->wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE) + if (wrapper_info && wrapper_info->subtype == WRAPPER_SUBTYPE_DELEGATE_INVOKE_VIRTUAL) encode_klass_ref (acfg, method->klass, p, &p); else encode_signature (acfg, sig, p, &p); From 0dbe14f4e58e5bed34af8efde8443786f4868b61 Mon Sep 17 00:00:00 2001 From: Vlad - Alexandru Ionescu Date: Tue, 2 May 2023 12:53:44 +0200 Subject: [PATCH 05/14] Added condition for encoding wrapper subtype --- src/mono/mono/mini/aot-compiler.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 9dada76da80ce..48c382e7b12bd 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -3915,7 +3915,8 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 WrapperInfo *wrapper_info = mono_marshal_get_wrapper_info (method); encode_value (0, p, &p); - encode_value (wrapper_info ? wrapper_info->subtype : 0, p, &p); + if (method->wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE) + encode_value (wrapper_info ? wrapper_info->subtype : 0, p, &p); if (wrapper_info && wrapper_info->subtype == WRAPPER_SUBTYPE_DELEGATE_INVOKE_VIRTUAL) encode_klass_ref (acfg, method->klass, p, &p); From 030c8af7300f13447b622fa52cc5a1f5ed45edc3 Mon Sep 17 00:00:00 2001 From: Vlad - Alexandru Ionescu Date: Thu, 4 May 2023 14:52:05 +0200 Subject: [PATCH 06/14] Repro issue with iOS HelloiOS --- src/mono/sample/iOS/Makefile | 8 ++++---- src/mono/sample/iOS/Program.cs | 14 ++++++++++---- 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/src/mono/sample/iOS/Makefile b/src/mono/sample/iOS/Makefile index ef24938c6fd30..d53d70d707983 100644 --- a/src/mono/sample/iOS/Makefile +++ b/src/mono/sample/iOS/Makefile @@ -1,10 +1,10 @@ MONO_CONFIG?=Debug -MONO_ARCH?=x64 +MONO_ARCH?=arm64 DOTNET := ../../../../dotnet.sh USE_LLVM=true -AOT?=false -TARGET?=iossimulator -DEPLOY_AND_RUN?=true +AOT?=true +TARGET?=ios +DEPLOY_AND_RUN?=false APP_SANDBOX?=false STRIP_DEBUG_SYMBOLS?=false # only used when measuring SOD via build-appbundle make target diff --git a/src/mono/sample/iOS/Program.cs b/src/mono/sample/iOS/Program.cs index 1c9839a8ae0a2..a2d0382290c2a 100644 --- a/src/mono/sample/iOS/Program.cs +++ b/src/mono/sample/iOS/Program.cs @@ -30,10 +30,16 @@ public static async Task Main(string[] args) public static async Task Main(string[] args) #endif { - unsafe { - // Register a managed callback (will be called by UIButton, see main.m) - delegate* unmanaged unmanagedPtr = &OnButtonClick; - ios_register_button_click(unmanagedPtr); + // unsafe { + // // Register a managed callback (will be called by UIButton, see main.m) + // delegate* unmanaged unmanagedPtr = &OnButtonClick; + // ios_register_button_click(unmanagedPtr); + // } + try { + var del = (Func)Delegate.CreateDelegate (typeof (Func), null, typeof (object).GetMethod ("ToString")); + del ("Foo"); + } catch(Exception e) { + Console.WriteLine(e); } const string msg = "Hello World!\n.NET 8.0"; for (int i = 0; i < msg.Length; i++) From 01231ce06c94e08d91931191b123ac8b6225cb4f Mon Sep 17 00:00:00 2001 From: Vlad - Alexandru Ionescu Date: Wed, 10 May 2023 20:04:11 +0200 Subject: [PATCH 07/14] Inst generic types for delegates Signed-off-by: Vlad - Alexandru Ionescu --- src/mono/mono/metadata/loader-internals.h | 3 +- src/mono/mono/metadata/marshal.c | 8 ++- src/mono/mono/mini/aot-compiler.c | 63 +++++++++++++++++++++-- src/mono/mono/mini/aot-runtime.c | 15 +++--- 4 files changed, 74 insertions(+), 15 deletions(-) diff --git a/src/mono/mono/metadata/loader-internals.h b/src/mono/mono/metadata/loader-internals.h index 3f64f48c6272e..af05fa36fa5f4 100644 --- a/src/mono/mono/metadata/loader-internals.h +++ b/src/mono/mono/metadata/loader-internals.h @@ -52,11 +52,12 @@ struct _MonoDllMap { #endif typedef struct { + GHashTable *delegate_invoke_cache; + GHashTable *delegate_invoke_virtual_cache; /* * indexed by MonoMethodSignature * Protected by the marshal lock */ - GHashTable *delegate_invoke_cache; GHashTable *delegate_begin_invoke_cache; GHashTable *delegate_end_invoke_cache; GHashTable *runtime_invoke_signature_cache; diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index 8bafea59dca20..0acb3e879a4d1 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -2138,7 +2138,7 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt /* * For generic delegates, create a generic wrapper, and return an instance to help AOT. */ - if (method->is_inflated && subtype == WRAPPER_SUBTYPE_NONE) { + if (method->is_inflated && (subtype == WRAPPER_SUBTYPE_NONE || subtype == WRAPPER_SUBTYPE_DELEGATE_INVOKE_VIRTUAL)) { ctx = &((MonoMethodInflated*)method)->context; method = ((MonoMethodInflated*)method)->declaring; @@ -2154,7 +2154,10 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt * Check cache */ if (ctx) { - cache = get_cache (&((MonoMethodInflated*)orig_method)->owner->wrapper_caches.delegate_invoke_cache, mono_aligned_addr_hash, NULL); + if (callvirt) + cache = get_cache (&((MonoMethodInflated*)orig_method)->owner->wrapper_caches.delegate_invoke_virtual_cache, mono_aligned_addr_hash, NULL); + else + cache = get_cache (&((MonoMethodInflated*)orig_method)->owner->wrapper_caches.delegate_invoke_cache, mono_aligned_addr_hash, NULL); res = check_generic_delegate_wrapper_cache (cache, orig_method, method, ctx); if (res) return res; @@ -6377,6 +6380,7 @@ void mono_wrapper_caches_free (MonoWrapperCaches *cache) { free_hash (cache->delegate_invoke_cache); + free_hash (cache->delegate_invoke_virtual_cache); free_hash (cache->delegate_begin_invoke_cache); free_hash (cache->delegate_end_invoke_cache); free_hash (cache->delegate_bound_static_invoke_cache); diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 48c382e7b12bd..2796ff5db1a4e 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -3912,14 +3912,14 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 encode_klass_ref (acfg, method->klass, p, &p); } else { MonoMethodSignature *sig = mono_method_signature_internal (method); - WrapperInfo *wrapper_info = mono_marshal_get_wrapper_info (method); + // WrapperInfo *wrapper_info = mono_marshal_get_wrapper_info (method); encode_value (0, p, &p); if (method->wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE) - encode_value (wrapper_info ? wrapper_info->subtype : 0, p, &p); + encode_value (info ? info->subtype : 0, p, &p); - if (wrapper_info && wrapper_info->subtype == WRAPPER_SUBTYPE_DELEGATE_INVOKE_VIRTUAL) - encode_klass_ref (acfg, method->klass, p, &p); + if (info && info->subtype == WRAPPER_SUBTYPE_DELEGATE_INVOKE_VIRTUAL) + encode_klass_ref (acfg, info->d.delegate_invoke.method->klass, p, &p); else encode_signature (acfg, sig, p, &p); } @@ -4532,6 +4532,39 @@ can_marshal_struct (MonoClass *klass) return can_marshal; } +/* Create a ref shared instantiation */ +static void +create_ref_shared_inst (MonoAotCompile *acfg, MonoMethod *method, MonoGenericContext *ctx) +{ + MonoGenericContext shared_context; + MonoType **args; + MonoGenericInst *inst; + MonoGenericContainer *container; + + memset (ctx, 0, sizeof (MonoGenericContext)); + + if (mono_class_is_gtd (method->klass)) { + shared_context = mono_class_get_generic_container (method->klass)->context; + inst = shared_context.class_inst; + + args = g_new0 (MonoType*, inst->type_argc); + for (guint i = 0; i < inst->type_argc; ++i) + args [i] = mono_get_object_type (); + ctx->class_inst = mono_metadata_get_generic_inst (inst->type_argc, args); + } + if (method->is_generic) { + container = mono_method_get_generic_container (method); + g_assert (!container->is_anonymous && container->is_method); + shared_context = container->context; + inst = shared_context.method_inst; + + args = g_new0 (MonoType*, inst->type_argc); + for (int i = 0; i < container->type_argc; ++i) + args [i] = mono_get_object_type (); + ctx->method_inst = mono_metadata_get_generic_inst (inst->type_argc, args); + } +} + static void create_gsharedvt_inst (MonoAotCompile *acfg, MonoMethod *method, MonoGenericContext *ctx) { @@ -4948,8 +4981,28 @@ add_full_aot_wrappers (MonoAotCompile *acfg) if (!m_class_is_delegate (klass) || klass == mono_defaults.delegate_class || klass == mono_defaults.multicastdelegate_class) continue; + method = mono_get_delegate_invoke_internal (klass); + if (mono_class_is_gtd (klass)) { + MonoGenericContext ctx; + MonoMethod *inst, *gshared; + + create_ref_shared_inst (acfg, method, &ctx); + + inst = mono_class_inflate_generic_method_checked (method, &ctx, error); + g_assert (is_ok (error)); /* FIXME don't swallow the error */ + + sig = mono_method_signature_internal (method); + if (sig->param_count && !m_class_is_byreflike (mono_class_from_mono_type_internal (sig->params [0]))) { + m = mono_marshal_get_delegate_invoke_internal (inst, TRUE, FALSE, NULL); + + gshared = mini_get_shared_method_full (m, SHARE_MODE_NONE, error); + mono_error_assert_ok (error); + + add_extra_method (acfg, gshared); + } + } + if (!mono_class_is_gtd (klass)) { - method = mono_get_delegate_invoke_internal (klass); m = mono_marshal_get_delegate_invoke (method, NULL); diff --git a/src/mono/mono/mini/aot-runtime.c b/src/mono/mono/mini/aot-runtime.c index a620bca9d8e93..9d065171aa3cd 100644 --- a/src/mono/mono/mini/aot-runtime.c +++ b/src/mono/mono/mini/aot-runtime.c @@ -1269,14 +1269,8 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod ref->method = wrapper; } } else { - /* - * These wrappers are associated with a signature, not with a method. - * Since we can't decode them into methods, they need a target method. - */ MonoClass *klass; MonoMethod *invoke; - // if (!target) - // return FALSE; if (wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE) { @@ -1287,6 +1281,13 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod ref->method = mono_marshal_get_delegate_invoke_internal(invoke, TRUE, FALSE, NULL); break; } + + /* + * These wrappers are associated with a signature, not with a method. + * Since we can't decode them into methods, they need a target method. + */ + if (!target) + return FALSE; info = mono_marshal_get_wrapper_info (target); if (info) { if (info->subtype != subtype) @@ -1296,7 +1297,7 @@ decode_method_ref_with_target (MonoAotModule *module, MethodRef *ref, MonoMethod return FALSE; } } - if (sig_matches_target (module, target, p, &p)) + if (target && sig_matches_target (module, target, p, &p)) ref->method = target; else return FALSE; From 1b80a474da77e34077ba1f4af58cfc19fd006f59 Mon Sep 17 00:00:00 2001 From: Vlad - Alexandru Ionescu Date: Thu, 11 May 2023 15:42:13 +0200 Subject: [PATCH 08/14] Reverted HelloiOS sample app changes Signed-off-by: Vlad - Alexandru Ionescu --- src/mono/sample/iOS/Makefile | 8 ++++---- src/mono/sample/iOS/Program.cs | 14 ++++---------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/src/mono/sample/iOS/Makefile b/src/mono/sample/iOS/Makefile index d53d70d707983..ef24938c6fd30 100644 --- a/src/mono/sample/iOS/Makefile +++ b/src/mono/sample/iOS/Makefile @@ -1,10 +1,10 @@ MONO_CONFIG?=Debug -MONO_ARCH?=arm64 +MONO_ARCH?=x64 DOTNET := ../../../../dotnet.sh USE_LLVM=true -AOT?=true -TARGET?=ios -DEPLOY_AND_RUN?=false +AOT?=false +TARGET?=iossimulator +DEPLOY_AND_RUN?=true APP_SANDBOX?=false STRIP_DEBUG_SYMBOLS?=false # only used when measuring SOD via build-appbundle make target diff --git a/src/mono/sample/iOS/Program.cs b/src/mono/sample/iOS/Program.cs index a2d0382290c2a..1c9839a8ae0a2 100644 --- a/src/mono/sample/iOS/Program.cs +++ b/src/mono/sample/iOS/Program.cs @@ -30,16 +30,10 @@ public static async Task Main(string[] args) public static async Task Main(string[] args) #endif { - // unsafe { - // // Register a managed callback (will be called by UIButton, see main.m) - // delegate* unmanaged unmanagedPtr = &OnButtonClick; - // ios_register_button_click(unmanagedPtr); - // } - try { - var del = (Func)Delegate.CreateDelegate (typeof (Func), null, typeof (object).GetMethod ("ToString")); - del ("Foo"); - } catch(Exception e) { - Console.WriteLine(e); + unsafe { + // Register a managed callback (will be called by UIButton, see main.m) + delegate* unmanaged unmanagedPtr = &OnButtonClick; + ios_register_button_click(unmanagedPtr); } const string msg = "Hello World!\n.NET 8.0"; for (int i = 0; i < msg.Length; i++) From 1405f3f4202918972933b567e2727106014a6e5d Mon Sep 17 00:00:00 2001 From: Vlad - Alexandru Ionescu Date: Fri, 12 May 2023 23:39:05 +0200 Subject: [PATCH 09/14] Added by reference check Signed-off-by: Vlad - Alexandru Ionescu --- src/mono/mono/mini/aot-compiler.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 0a30f9abc22da..a3eca9df8987a 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -3790,8 +3790,6 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 MonoJumpInfoToken *ji; guint8 *p = buf; - printf("NAME = %s\n", method->name); - /* * The encoding for most methods is as follows: * - image index encoded as a leb128 @@ -5012,7 +5010,7 @@ add_full_aot_wrappers (MonoAotCompile *acfg) g_assert (is_ok (error)); /* FIXME don't swallow the error */ sig = mono_method_signature_internal (method); - if (sig->param_count && !m_class_is_byreflike (mono_class_from_mono_type_internal (sig->params [0]))) { + if (sig->param_count && !m_class_is_byreflike (mono_class_from_mono_type_internal (sig->params [0])) && !m_type_is_byref (sig->params [0])) m = mono_marshal_get_delegate_invoke_internal (inst, TRUE, FALSE, NULL); gshared = mini_get_shared_method_full (m, SHARE_MODE_NONE, error); @@ -5029,7 +5027,7 @@ add_full_aot_wrappers (MonoAotCompile *acfg) add_method (acfg, m); sig = mono_method_signature_internal (method); - if (sig->param_count && !m_class_is_byreflike (mono_class_from_mono_type_internal (sig->params [0]))) { + if (sig->param_count && !m_class_is_byreflike (mono_class_from_mono_type_internal (sig->params [0])) && !m_type_is_byref (sig->params [0])) m = mono_marshal_get_delegate_invoke_internal (method, TRUE, FALSE, NULL); add_method (acfg, m); } From 3144e6e90ea7ad3261d9fc4a6020a2c034323bd6 Mon Sep 17 00:00:00 2001 From: Vlad - Alexandru Ionescu Date: Sat, 13 May 2023 03:26:02 +0200 Subject: [PATCH 10/14] Fixed typo Signed-off-by: Vlad - Alexandru Ionescu --- src/mono/mono/mini/aot-compiler.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index a3eca9df8987a..71499235f94bf 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -5010,7 +5010,7 @@ add_full_aot_wrappers (MonoAotCompile *acfg) g_assert (is_ok (error)); /* FIXME don't swallow the error */ sig = mono_method_signature_internal (method); - if (sig->param_count && !m_class_is_byreflike (mono_class_from_mono_type_internal (sig->params [0])) && !m_type_is_byref (sig->params [0])) + if (sig->param_count && !m_class_is_byreflike (mono_class_from_mono_type_internal (sig->params [0])) && !m_type_is_byref (sig->params [0])) { m = mono_marshal_get_delegate_invoke_internal (inst, TRUE, FALSE, NULL); gshared = mini_get_shared_method_full (m, SHARE_MODE_NONE, error); @@ -5027,7 +5027,7 @@ add_full_aot_wrappers (MonoAotCompile *acfg) add_method (acfg, m); sig = mono_method_signature_internal (method); - if (sig->param_count && !m_class_is_byreflike (mono_class_from_mono_type_internal (sig->params [0])) && !m_type_is_byref (sig->params [0])) + if (sig->param_count && !m_class_is_byreflike (mono_class_from_mono_type_internal (sig->params [0])) && !m_type_is_byref (sig->params [0])) { m = mono_marshal_get_delegate_invoke_internal (method, TRUE, FALSE, NULL); add_method (acfg, m); } From 3658fbca55a0a817e7ce24c550c3a1ef52a5fe82 Mon Sep 17 00:00:00 2001 From: Vlad - Alexandru Ionescu Date: Thu, 18 May 2023 11:04:15 +0200 Subject: [PATCH 11/14] Moved signature change to use generic version of the wrapper and fixed indentation Signed-off-by: Vlad - Alexandru Ionescu --- src/mono/mono/metadata/marshal.c | 20 ++++++++++---------- src/mono/mono/metadata/metadata.c | 6 +----- 2 files changed, 11 insertions(+), 15 deletions(-) diff --git a/src/mono/mono/metadata/marshal.c b/src/mono/mono/metadata/marshal.c index a05764bfecd7c..0307dc16a515a 100644 --- a/src/mono/mono/metadata/marshal.c +++ b/src/mono/mono/metadata/marshal.c @@ -2110,18 +2110,9 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt * call is made to that method with the first delegate argument as this. This is * a non-documented .NET feature. */ - if (callvirt) { + if (callvirt) subtype = WRAPPER_SUBTYPE_DELEGATE_INVOKE_VIRTUAL; - /* - * We don't want to use target_method's signature because it can be freed early - */ - target_method_sig = mono_metadata_signature_dup_delegate_invoke_to_target (invoke_sig); - // target_method_sig = mono_method_signature_internal (target_method); - - closed_over_null = sig->param_count == target_method_sig->param_count; - } - if (static_method_with_first_arg_bound) { subtype = WRAPPER_SUBTYPE_DELEGATE_INVOKE_BOUND; g_assert (!callvirt); @@ -2150,6 +2141,15 @@ mono_marshal_get_delegate_invoke_internal (MonoMethod *method, gboolean callvirt invoke_sig = sig = mono_signature_no_pinvoke (method); } + if (subtype == WRAPPER_SUBTYPE_DELEGATE_INVOKE_VIRTUAL) { + /* + * We don't want to use target_method's signature because it can be freed early + */ + target_method_sig = mono_metadata_signature_dup_delegate_invoke_to_target (invoke_sig); + + closed_over_null = sig->param_count == target_method_sig->param_count; + } + /* * Check cache */ diff --git a/src/mono/mono/metadata/metadata.c b/src/mono/mono/metadata/metadata.c index 838202234d896..b9b30d622349f 100644 --- a/src/mono/mono/metadata/metadata.c +++ b/src/mono/mono/metadata/metadata.c @@ -2530,11 +2530,7 @@ mono_metadata_signature_dup_delegate_invoke_to_target (MonoMethodSignature *sig) for (int i = 0 ; i < sig->param_count - 1; i ++) { res->params [i] = sig->params [i + 1]; } - - res->param_count --; - - // if (res->params [res->param_count - 1]) - // mono_metadata_free_type (res->params [res->param_count --]); + res->param_count --; return res; } From 26bf6bff0a32d0cc87c7edf1d5636b169a22a781 Mon Sep 17 00:00:00 2001 From: Vlad - Alexandru Ionescu Date: Fri, 19 May 2023 00:27:09 +0200 Subject: [PATCH 12/14] Deallocate args Signed-off-by: Vlad - Alexandru Ionescu --- src/mono/mono/mini/aot-compiler.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 10f3854f16ad9..3b96b67a72b5f 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -4569,6 +4569,7 @@ create_ref_shared_inst (MonoAotCompile *acfg, MonoMethod *method, MonoGenericCon for (guint i = 0; i < inst->type_argc; ++i) args [i] = mono_get_object_type (); ctx->class_inst = mono_metadata_get_generic_inst (inst->type_argc, args); + g_free (args); } if (method->is_generic) { container = mono_method_get_generic_container (method); @@ -4580,6 +4581,7 @@ create_ref_shared_inst (MonoAotCompile *acfg, MonoMethod *method, MonoGenericCon for (int i = 0; i < container->type_argc; ++i) args [i] = mono_get_object_type (); ctx->method_inst = mono_metadata_get_generic_inst (inst->type_argc, args); + g_free (args); } } From 3e4c73d25ac2dac6bf3279886795382ece3cb1cb Mon Sep 17 00:00:00 2001 From: Vlad - Alexandru Ionescu Date: Sun, 21 May 2023 14:51:17 +0200 Subject: [PATCH 13/14] Added check for primitives Signed-off-by: Vlad - Alexandru Ionescu --- src/mono/mono/metadata/marshal-lightweight.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/mono/mono/metadata/marshal-lightweight.c b/src/mono/mono/metadata/marshal-lightweight.c index 5ce2770555421..a4fb731434b67 100644 --- a/src/mono/mono/metadata/marshal-lightweight.c +++ b/src/mono/mono/metadata/marshal-lightweight.c @@ -1989,6 +1989,8 @@ emit_delegate_end_invoke_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *sig) mono_mb_emit_restore_result (mb, sig->ret); } +#define MONO_TYPE_IS_PRIMITIVE(t) ((!m_type_is_byref ((t)) && ((((t)->type >= MONO_TYPE_BOOLEAN && (t)->type <= MONO_TYPE_R8) || ((t)->type >= MONO_TYPE_I && (t)->type <= MONO_TYPE_U))))) + static void emit_delegate_invoke_internal_ilgen (MonoMethodBuilder *mb, MonoMethodSignature *sig, MonoMethodSignature *invoke_sig, MonoMethodSignature *target_method_sig, gboolean static_method_with_first_arg_bound, gboolean callvirt, gboolean closed_over_null, MonoMethod *method, MonoMethod *target_method, MonoGenericContext *ctx, MonoGenericContainer *container) { @@ -2090,10 +2092,10 @@ emit_delegate_invoke_internal_ilgen (MonoMethodBuilder *mb, MonoMethodSignature if (!closed_over_null) { for (i = 1; i <= sig->param_count; ++i) { mono_mb_emit_ldarg (mb, i); - if (i == 1 && MONO_TYPE_ISSTRUCT (sig->params [0])) + if (i == 1 && (MONO_TYPE_ISSTRUCT (sig->params [0]) || MONO_TYPE_IS_PRIMITIVE (sig->params [0]))) mono_mb_emit_op (mb, CEE_BOX, mono_class_from_mono_type_internal (sig->params [0])); } - if (MONO_TYPE_ISSTRUCT (sig->params [0])) + if (MONO_TYPE_ISSTRUCT (sig->params [0]) || MONO_TYPE_IS_PRIMITIVE (sig->params [0])) mono_mb_emit_ldarg_addr (mb, 1); else mono_mb_emit_ldarg (mb, 1); From d44a7aebc59466bf406e8f022a785fe9bf95bd0d Mon Sep 17 00:00:00 2001 From: Vlad - Alexandru Ionescu Date: Mon, 22 May 2023 10:05:39 +0200 Subject: [PATCH 14/14] Remove commented line Signed-off-by: Vlad - Alexandru Ionescu --- src/mono/mono/mini/aot-compiler.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/mono/mono/mini/aot-compiler.c b/src/mono/mono/mini/aot-compiler.c index 3b96b67a72b5f..52147fcbec951 100644 --- a/src/mono/mono/mini/aot-compiler.c +++ b/src/mono/mono/mini/aot-compiler.c @@ -3922,7 +3922,6 @@ encode_method_ref (MonoAotCompile *acfg, MonoMethod *method, guint8 *buf, guint8 encode_klass_ref (acfg, method->klass, p, &p); } else { MonoMethodSignature *sig = mono_method_signature_internal (method); - // WrapperInfo *wrapper_info = mono_marshal_get_wrapper_info (method); encode_value (0, p, &p); if (method->wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE)