From 51d797e59b6406b06e8e471907ef4941d0f3bb0c Mon Sep 17 00:00:00 2001 From: Zoltan Varga Date: Wed, 8 Mar 2023 09:12:23 -0500 Subject: [PATCH] [mono][arm64] Implement delegate virtual invoke trampolines. (#83028) --- src/mono/mono/mini/mini-arm64.c | 67 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 3 deletions(-) diff --git a/src/mono/mono/mini/mini-arm64.c b/src/mono/mono/mini/mini-arm64.c index 843e18a..d1f1f93 100644 --- a/src/mono/mono/mini/mini-arm64.c +++ b/src/mono/mono/mini/mini-arm64.c @@ -160,6 +160,49 @@ get_delegate_invoke_impl (gboolean has_target, gboolean param_count, guint32 *co return MINI_ADDR_TO_FTNPTR (start); } +#define MAX_VIRTUAL_DELEGATE_OFFSET 32 + +static gpointer +get_delegate_virtual_invoke_impl (MonoTrampInfo **info, gboolean load_imt_reg, int offset) +{ + guint8 *code, *start; + const int size = 20; + char *tramp_name; + GSList *unwind_ops; + + if (offset / (int)sizeof (target_mgreg_t) > MAX_VIRTUAL_DELEGATE_OFFSET) + return NULL; + + MINI_BEGIN_CODEGEN (); + + start = code = mono_global_codeman_reserve (size); + + unwind_ops = mono_arch_get_cie_program (); + + /* Replace the this argument with the target */ + arm_ldrx (code, ARMREG_R0, ARMREG_R0, MONO_STRUCT_OFFSET (MonoDelegate, target)); + + if (load_imt_reg) + // FIXME: + g_assert_not_reached (); + + /* Load this->vtable [offset] */ + arm_ldrx (code, ARMREG_IP0, ARMREG_R0, MONO_STRUCT_OFFSET (MonoObject, vtable)); + arm_ldrx (code, ARMREG_IP0, ARMREG_IP0, offset); + + code = mono_arm_emit_brx (code, ARMREG_IP0); + + g_assert ((code - start) <= size); + + MINI_END_CODEGEN (start, code - start, MONO_PROFILER_CODE_BUFFER_DELEGATE_INVOKE, NULL); + + tramp_name = mono_get_delegate_virtual_invoke_impl_name (load_imt_reg, offset); + *info = mono_tramp_info_create (tramp_name, start, GPTRDIFF_TO_UINT32 (code - start), NULL, unwind_ops); + g_free (tramp_name); + + return start; +} + /* * mono_arch_get_delegate_invoke_impls: * @@ -172,19 +215,26 @@ mono_arch_get_delegate_invoke_impls (void) GSList *res = NULL; guint8 *code; guint32 code_len; - int i; char *tramp_name; + MonoTrampInfo *info = NULL; code = (guint8*)get_delegate_invoke_impl (TRUE, 0, &code_len); res = g_slist_prepend (res, mono_tramp_info_create ("delegate_invoke_impl_has_target", code, code_len, NULL, NULL)); - for (i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) { + for (int i = 0; i <= MAX_ARCH_DELEGATE_PARAMS; ++i) { code = (guint8*)get_delegate_invoke_impl (FALSE, i, &code_len); tramp_name = g_strdup_printf ("delegate_invoke_impl_target_%d", i); res = g_slist_prepend (res, mono_tramp_info_create (tramp_name, code, code_len, NULL, NULL)); g_free (tramp_name); } + for (int i = 0; i <= MAX_VIRTUAL_DELEGATE_OFFSET; ++i) { + get_delegate_virtual_invoke_impl (&info, FALSE, i * TARGET_SIZEOF_VOID_P); + res = g_slist_prepend (res, info); + //get_delegate_virtual_invoke_impl (&info, TRUE, i * TARGET_SIZEOF_VOID_P); + //res = g_slist_prepend (res, info); + } + return res; } @@ -243,7 +293,18 @@ mono_arch_get_delegate_invoke_impl (MonoMethodSignature *sig, gboolean has_targe gpointer mono_arch_get_delegate_virtual_invoke_impl (MonoMethodSignature *sig, MonoMethod *method, int offset, gboolean load_imt_reg) { - return NULL; + MonoTrampInfo *info; + gpointer code; + + if (load_imt_reg) + // FIXME: + return FALSE; + + code = get_delegate_virtual_invoke_impl (&info, load_imt_reg, offset); + if (code) + mono_tramp_info_register (info, NULL); + + return code; } gpointer -- 2.7.4