Skip to content

Commit 877daf6

Browse files
authored
[mono] Futher cleanups to delegate invocation (#83705)
* [mono] Cache delegate->method_ptr in MonoDelegateTrampInfo instead of in delegate->method_code. Repurpose the method_code field to store the MonoDelegateTrampInfo pointer for future optimizations. * Remove now unused MONO_PATCH_INFO_METHOD_CODE_SLOT. * Remove unused mono_runtime_create_delegate_trampoline (). * Reduce handle usage in mini_init_delegate (). * Small cleanups to mono_delegate_trampoline (). * Use the MonoDelegateTrampInfo from the delegate if possible.
1 parent 1795721 commit 877daf6

File tree

11 files changed

+38
-84
lines changed

11 files changed

+38
-84
lines changed

src/mono/mono/metadata/class-internals.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -755,9 +755,6 @@ mono_lookup_dynamic_token (MonoImage *image, guint32 token, MonoGenericContext *
755755
gpointer
756756
mono_lookup_dynamic_token_class (MonoImage *image, guint32 token, gboolean check_token, MonoClass **handle_class, MonoGenericContext *context, MonoError *error);
757757

758-
gpointer
759-
mono_runtime_create_delegate_trampoline (MonoClass *klass);
760-
761758
void
762759
mono_install_get_cached_class_info (MonoGetCachedClassInfo func);
763760

src/mono/mono/metadata/object-internals.h

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -687,7 +687,6 @@ typedef struct {
687687
gpointer (*create_jit_trampoline) (MonoMethod *method, MonoError *error);
688688
/* used to free a dynamic method */
689689
void (*free_method) (MonoMethod *method);
690-
gpointer (*create_delegate_trampoline) (MonoClass *klass);
691690
GHashTable *(*get_weak_field_indexes) (MonoImage *image);
692691
gboolean (*is_interpreter_enabled) (void);
693692
void (*init_mem_manager)(MonoMemoryManager*);
@@ -836,11 +835,8 @@ struct _MonoDelegate {
836835
gpointer delegate_trampoline;
837836
/* Extra argument passed to the target method in llvmonly mode */
838837
gpointer extra_arg;
839-
/*
840-
* If non-NULL, this points to a memory location which stores the address of
841-
* the compiled code of the method, or NULL if it is not yet compiled.
842-
*/
843-
guint8 **method_code;
838+
/* MonoDelegateTrampInfo */
839+
gpointer invoke_info;
844840
gpointer interp_method;
845841
/* Interp method that is executed when invoking the delegate */
846842
gpointer interp_invoke_impl;

src/mono/mono/metadata/object-offsets.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ DECL_OFFSET(MonoDelegate, target)
8585
DECL_OFFSET(MonoDelegate, method_ptr)
8686
DECL_OFFSET(MonoDelegate, invoke_impl)
8787
DECL_OFFSET(MonoDelegate, method)
88-
DECL_OFFSET(MonoDelegate, method_code)
88+
DECL_OFFSET(MonoDelegate, invoke_info)
8989
DECL_OFFSET(MonoDelegate, method_is_virtual)
9090
DECL_OFFSET(MonoDelegate, bound)
9191
DECL_OFFSET(MonoDelegate, extra_arg)

src/mono/mono/metadata/object.c

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -775,15 +775,6 @@ mono_compile_method_checked (MonoMethod *method, MonoError *error)
775775
return res;
776776
}
777777

778-
gpointer
779-
mono_runtime_create_delegate_trampoline (MonoClass *klass)
780-
{
781-
MONO_REQ_GC_NEUTRAL_MODE
782-
783-
g_assert (callbacks.create_delegate_trampoline);
784-
return callbacks.create_delegate_trampoline (klass);
785-
}
786-
787778
/**
788779
* mono_runtime_free_method:
789780
* \param method method to release

src/mono/mono/mini/aot-compiler.c

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6967,7 +6967,6 @@ encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info, guint8 *buf, guint
69676967
case MONO_PATCH_INFO_ICALL_ADDR:
69686968
case MONO_PATCH_INFO_ICALL_ADDR_CALL:
69696969
case MONO_PATCH_INFO_METHOD_RGCTX:
6970-
case MONO_PATCH_INFO_METHOD_CODE_SLOT:
69716970
case MONO_PATCH_INFO_METHOD_PINVOKE_ADDR_CACHE:
69726971
encode_method_ref (acfg, patch_info->data.method, p, &p);
69736972
break;
@@ -8936,7 +8935,6 @@ can_encode_patch (MonoAotCompile *acfg, MonoJumpInfo *patch_info)
89368935
case MONO_PATCH_INFO_METHOD:
89378936
case MONO_PATCH_INFO_METHOD_FTNDESC:
89388937
case MONO_PATCH_INFO_METHODCONST:
8939-
case MONO_PATCH_INFO_METHOD_CODE_SLOT:
89408938
case MONO_PATCH_INFO_METHOD_PINVOKE_ADDR_CACHE:
89418939
case MONO_PATCH_INFO_LLVMONLY_INTERP_ENTRY: {
89428940
MonoMethod *method = patch_info->data.method;

src/mono/mono/mini/aot-runtime.c

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3778,7 +3778,6 @@ decode_patch (MonoAotModule *aot_module, MonoMemPool *mp, MonoJumpInfo *ji, guin
37783778
case MONO_PATCH_INFO_ICALL_ADDR:
37793779
case MONO_PATCH_INFO_ICALL_ADDR_CALL:
37803780
case MONO_PATCH_INFO_METHOD_RGCTX:
3781-
case MONO_PATCH_INFO_METHOD_CODE_SLOT:
37823781
case MONO_PATCH_INFO_METHOD_PINVOKE_ADDR_CACHE:
37833782
case MONO_PATCH_INFO_LLVMONLY_INTERP_ENTRY: {
37843783
MethodRef ref;

src/mono/mono/mini/method-to-ir.c

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -3692,6 +3692,9 @@ handle_delegate_ctor (MonoCompile *cfg, MonoClass *klass, MonoInst *target, Mono
36923692
return obj;
36933693
}
36943694

3695+
/* Set invoke_info field */
3696+
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, invoke_info), info_ins->dreg);
3697+
36953698
/* Set method field */
36963699
if (target_method_context_used || invoke_context_used) {
36973700
// We copy from the delegate trampoline info as it's faster than a rgctx fetch
@@ -3704,21 +3707,6 @@ handle_delegate_ctor (MonoCompile *cfg, MonoClass *klass, MonoInst *target, Mono
37043707
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, method), method_ins->dreg);
37053708
}
37063709

3707-
/*
3708-
* To avoid looking up the compiled code belonging to the target method
3709-
* in mono_delegate_trampoline (), we allocate a per-domain memory slot to
3710-
* store it, and we fill it after the method has been compiled.
3711-
*/
3712-
if (!method->dynamic) {
3713-
MonoInst *code_slot_ins;
3714-
3715-
if (target_method_context_used)
3716-
code_slot_ins = emit_get_rgctx_method (cfg, target_method_context_used, method, MONO_RGCTX_INFO_METHOD_DELEGATE_CODE);
3717-
else
3718-
code_slot_ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_METHOD_CODE_SLOT, method);
3719-
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, method_code), code_slot_ins->dreg);
3720-
}
3721-
37223710
/* Set invoke_impl field */
37233711
dreg = alloc_preg (cfg);
37243712
MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, info_ins->dreg, MONO_STRUCT_OFFSET (MonoDelegateTrampInfo, invoke_impl));

src/mono/mono/mini/mini-runtime.c

Lines changed: 5 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1235,7 +1235,6 @@ mono_patch_info_hash (gconstpointer data)
12351235
case MONO_PATCH_INFO_SEQ_POINT_INFO:
12361236
case MONO_PATCH_INFO_METHOD_RGCTX:
12371237
case MONO_PATCH_INFO_SIGNATURE:
1238-
case MONO_PATCH_INFO_METHOD_CODE_SLOT:
12391238
case MONO_PATCH_INFO_AOT_JIT_INFO:
12401239
case MONO_PATCH_INFO_METHOD_PINVOKE_ADDR_CACHE:
12411240
case MONO_PATCH_INFO_GSHARED_METHOD_INFO:
@@ -1493,22 +1492,6 @@ mono_resolve_patch_target_ext (MonoMemoryManager *mem_manager, MonoMethod *metho
14931492
mono_error_assert_ok (error);
14941493
break;
14951494
}
1496-
case MONO_PATCH_INFO_METHOD_CODE_SLOT: {
1497-
gpointer code_slot;
1498-
1499-
MonoJitMemoryManager *jit_mm = jit_mm_for_method (patch_info->data.method);
1500-
jit_mm_lock (jit_mm);
1501-
if (!jit_mm->method_code_hash)
1502-
jit_mm->method_code_hash = g_hash_table_new (NULL, NULL);
1503-
code_slot = g_hash_table_lookup (jit_mm->method_code_hash, patch_info->data.method);
1504-
if (!code_slot) {
1505-
code_slot = mono_mem_manager_alloc0 (jit_mm->mem_manager, sizeof (gpointer));
1506-
g_hash_table_insert (jit_mm->method_code_hash, patch_info->data.method, code_slot);
1507-
}
1508-
jit_mm_unlock (jit_mm);
1509-
target = code_slot;
1510-
break;
1511-
}
15121495
case MONO_PATCH_INFO_METHOD_PINVOKE_ADDR_CACHE: {
15131496
target = mono_mem_manager_alloc0 (mem_manager, sizeof (gpointer));
15141497
break;
@@ -3900,7 +3883,7 @@ mini_init_delegate (MonoDelegateHandle delegate, MonoObjectHandle target, gpoint
39003883
if (!method && !addr) {
39013884
// Multicast delegate init
39023885
if (!mono_llvm_only) {
3903-
MONO_HANDLE_SETVAL (delegate, invoke_impl, gpointer, mono_create_delegate_trampoline (mono_handle_class (delegate)));
3886+
del->invoke_impl = mono_create_delegate_trampoline (mono_handle_class (delegate));
39043887
} else {
39053888
mini_llvmonly_init_delegate (del, NULL);
39063889
}
@@ -3925,13 +3908,11 @@ mini_init_delegate (MonoDelegateHandle delegate, MonoObjectHandle target, gpoint
39253908
}
39263909

39273910
if (method)
3928-
MONO_HANDLE_SETVAL (delegate, method, MonoMethod*, method);
3929-
3911+
del->method = method;
39303912
if (addr)
3931-
MONO_HANDLE_SETVAL (delegate, method_ptr, gpointer, addr);
3932-
3933-
MONO_HANDLE_SET (delegate, target, target);
3934-
MONO_HANDLE_SETVAL (delegate, invoke_impl, gpointer, mono_create_delegate_trampoline (mono_handle_class (delegate)));
3913+
del->method_ptr = addr;
3914+
MONO_OBJECT_SETREF_INTERNAL (del, target, MONO_HANDLE_RAW (target));
3915+
del->invoke_impl = mono_create_delegate_trampoline (mono_handle_class (delegate));
39353916

39363917
MonoDelegateTrampInfo *info = NULL;
39373918

@@ -4302,7 +4283,6 @@ free_jit_mem_manager (MonoMemoryManager *mem_manager)
43024283
g_hash_table_foreach (info->dynamic_code_hash, dynamic_method_info_free, NULL);
43034284
g_hash_table_destroy (info->dynamic_code_hash);
43044285
}
4305-
g_hash_table_destroy (info->method_code_hash);
43064286
g_hash_table_destroy (info->jump_trampoline_hash);
43074287
g_hash_table_destroy (info->jit_trampoline_hash);
43084288
g_hash_table_destroy (info->delegate_info_hash);
@@ -4562,7 +4542,6 @@ mini_init (const char *filename)
45624542
#ifdef JIT_TRAMPOLINES_WORK
45634543
callbacks.compile_method = mono_jit_compile_method;
45644544
callbacks.create_jit_trampoline = mono_create_jit_trampoline;
4565-
callbacks.create_delegate_trampoline = mono_create_delegate_trampoline;
45664545
callbacks.free_method = mono_jit_free_method;
45674546
callbacks.get_ftnptr = get_ftnptr_for_method;
45684547
#endif

src/mono/mono/mini/mini-runtime.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ typedef struct {
3232
GHashTable *static_rgctx_trampoline_hash;
3333
/* maps MonoMethod -> MonoJitDynamicMethodInfo */
3434
GHashTable *dynamic_code_hash;
35-
GHashTable *method_code_hash;
3635
/* Maps methods to a RuntimeInvokeInfo structure, protected by the associated MonoDomain lock */
3736
MonoConcurrentHashTable *runtime_invoke_hash;
3837
/* Maps MonoMethod to a GPtrArray containing sequence point locations */

src/mono/mono/mini/mini-trampolines.c

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -969,7 +969,8 @@ mono_delegate_trampoline (host_mgreg_t *regs, guint8 *code, gpointer *arg, guint
969969
MonoMethod *m;
970970
MonoMethod *method = NULL;
971971
ERROR_DECL (error);
972-
gboolean multicast, callvirt = FALSE, closed_over_null = FALSE;
972+
gboolean multicast, callvirt = FALSE;
973+
gboolean closed_static = FALSE, closed_over_null = FALSE;
973974
gboolean need_rgctx_tramp = FALSE;
974975
gboolean need_unbox_tramp = FALSE;
975976
gboolean enable_caching = TRUE;
@@ -978,14 +979,23 @@ mono_delegate_trampoline (host_mgreg_t *regs, guint8 *code, gpointer *arg, guint
978979
guint8 *impl_this = (guint8 *)tramp_info->impl_this;
979980
guint8 *impl_nothis = (guint8 *)tramp_info->impl_nothis;
980981
MonoMethodSignature *sig;
981-
gpointer addr, compiled_method;
982+
gpointer addr, invoke_impl, compiled_method;
982983

983984
UnlockedIncrement (&trampoline_calls);
984985

985986
/* Obtain the delegate object according to the calling convention */
986987
delegate = (MonoDelegate *)mono_arch_get_this_arg_from_call (regs, code);
987988
g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
988989

990+
/*
991+
* The 'arg' argument might point to a MonoDelegateTrampInfo which
992+
* has no method set, if the trampoline was created by
993+
* mono_create_delegate_trampoline (). Use the more precise info
994+
* from the delegate itself.
995+
*/
996+
if (delegate->invoke_info)
997+
tramp_info = (MonoDelegateTrampInfo*)delegate->invoke_info;
998+
989999
if (delegate->method) {
9901000
method = delegate->method;
9911001

@@ -1040,6 +1050,8 @@ mono_delegate_trampoline (host_mgreg_t *regs, guint8 *code, gpointer *arg, guint
10401050
callvirt = !delegate->target && sig->hasthis;
10411051
if (callvirt)
10421052
closed_over_null = tramp_info->invoke_sig->param_count == sig->param_count;
1053+
if (m_method_is_static (method) && sig->param_count == tramp_info->invoke_sig->param_count + 1)
1054+
closed_static = TRUE;
10431055

10441056
if (callvirt && !closed_over_null) {
10451057
/*
@@ -1051,7 +1063,7 @@ mono_delegate_trampoline (host_mgreg_t *regs, guint8 *code, gpointer *arg, guint
10511063
* If the call doesn't return a valuetype, then the vcall uses the same calling
10521064
* convention as a normal call.
10531065
*/
1054-
if ((mono_class_is_sealed (method->klass) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) && !MONO_TYPE_ISSTRUCT (sig->ret)) {
1066+
if ((mono_class_is_sealed (method->klass) || !m_method_is_virtual (method)) && !MONO_TYPE_ISSTRUCT (sig->ret)) {
10551067
callvirt = FALSE;
10561068
enable_caching = FALSE;
10571069
}
@@ -1066,7 +1078,7 @@ mono_delegate_trampoline (host_mgreg_t *regs, guint8 *code, gpointer *arg, guint
10661078
enable_caching = FALSE;
10671079
}
10681080

1069-
if (method->iflags & METHOD_IMPL_ATTRIBUTE_SYNCHRONIZED)
1081+
if (m_method_is_synchronized (method))
10701082
method = mono_marshal_get_synchronized_wrapper (method);
10711083

10721084
if (method == tramp_info->method)
@@ -1081,8 +1093,8 @@ mono_delegate_trampoline (host_mgreg_t *regs, guint8 *code, gpointer *arg, guint
10811093
*/
10821094
if (method && !callvirt) {
10831095
/* Avoid the overhead of looking up an already compiled method if possible */
1084-
if (enable_caching && delegate->method_code && *delegate->method_code) {
1085-
delegate->method_ptr = *delegate->method_code;
1096+
if (enable_caching && method == tramp_info->method && tramp_info->method_ptr) {
1097+
delegate->method_ptr = tramp_info->method_ptr;
10861098
} else {
10871099
compiled_method = addr = mono_jit_compile_method (method, error);
10881100
if (!is_ok (error)) {
@@ -1091,46 +1103,42 @@ mono_delegate_trampoline (host_mgreg_t *regs, guint8 *code, gpointer *arg, guint
10911103
}
10921104
addr = mini_add_method_trampoline (method, compiled_method, need_rgctx_tramp, need_unbox_tramp);
10931105
delegate->method_ptr = addr;
1094-
if (enable_caching && delegate->method_code)
1095-
*delegate->method_code = (guint8 *)delegate->method_ptr;
10961106
}
10971107
} else {
10981108
if (need_rgctx_tramp)
10991109
delegate->method_ptr = mono_create_static_rgctx_trampoline (method, delegate->method_ptr);
11001110
}
11011111

1102-
/* Necessary for !code condition to fallback to slow path */
1103-
code = NULL;
1112+
invoke_impl = NULL;
11041113

11051114
multicast = ((MonoMulticastDelegate*)delegate)->delegates != NULL;
11061115
if (!multicast && !callvirt) {
1107-
if (method && (method->flags & METHOD_ATTRIBUTE_STATIC) && mono_method_signature_internal (method)->param_count == mono_method_signature_internal (invoke)->param_count + 1)
1108-
/* Closed static delegate */
1109-
code = impl_this;
1116+
if (closed_static)
1117+
invoke_impl = impl_this;
11101118
else
1111-
code = delegate->target ? impl_this : impl_nothis;
1119+
invoke_impl = delegate->target ? impl_this : impl_nothis;
11121120
}
11131121

1114-
if (!code) {
1122+
if (!invoke_impl) {
11151123
/* The general, unoptimized case */
11161124
m = mono_marshal_get_delegate_invoke (invoke, delegate);
1117-
code = (guint8 *)mono_jit_compile_method (m, error);
1125+
invoke_impl = (guint8 *)mono_jit_compile_method (m, error);
11181126
if (!is_ok (error)) {
11191127
mono_error_set_pending_exception (error);
11201128
return NULL;
11211129
}
1122-
code = (guint8 *)mini_add_method_trampoline (m, code, mono_method_needs_static_rgctx_invoke (m, FALSE), FALSE);
1130+
invoke_impl = (guint8 *)mini_add_method_trampoline (m, invoke_impl, mono_method_needs_static_rgctx_invoke (m, FALSE), FALSE);
11231131
}
11241132

11251133
mono_memory_barrier ();
11261134

1127-
delegate->invoke_impl = mono_get_addr_from_ftnptr (code);
1135+
delegate->invoke_impl = mono_get_addr_from_ftnptr (invoke_impl);
11281136
if (enable_caching && !callvirt && tramp_info->method) {
11291137
tramp_info->method_ptr = delegate->method_ptr;
11301138
tramp_info->invoke_impl = delegate->invoke_impl;
11311139
}
11321140

1133-
return code;
1141+
return invoke_impl;
11341142
}
11351143

11361144
/*

src/mono/mono/mini/patch-info.h

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,6 @@ PATCH_INFO(SIGNATURE, "signature")
4444
PATCH_INFO(GSHAREDVT_CALL, "gsharedvt_call")
4545
PATCH_INFO(GSHAREDVT_METHOD, "gsharedvt_method")
4646
PATCH_INFO(OBJC_SELECTOR_REF, "objc_selector_ref")
47-
PATCH_INFO(METHOD_CODE_SLOT, "method_code_slot")
4847
PATCH_INFO(LDSTR_LIT, "ldstr_lit")
4948
PATCH_INFO(GC_NURSERY_START, "gc_nursery_start")
5049
PATCH_INFO(VIRT_METHOD, "virt_method")

0 commit comments

Comments
 (0)