* [mono] Clean up the delegate ctor code.
* Merge the virtual and non-virtual cases.
* Reorder the code in handle_delegate_ctor () to reduce the llvm_only conditionals.
* Name variables etc. delegate info instead of delegate trampoline.
* Avoid setting the del->is_virtual field if its FALSE.
* Remove some code which is already done by mono_resolve_patch_target_ext ().
* Remove some dead code.
* Unify the virtual/non-virtual case for llvmonly as well.
case MONO_PATCH_INFO_ADJUSTED_IID:
encode_klass_ref (acfg, patch_info->data.klass, p, &p);
break;
- case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
+ case MONO_PATCH_INFO_DELEGATE_INFO:
encode_klass_ref (acfg, patch_info->data.del_tramp->klass, p, &p);
if (patch_info->data.del_tramp->method) {
encode_value (1, p, &p);
break;
case MONO_PATCH_INFO_FIELD:
case MONO_PATCH_INFO_METHOD:
- case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
+ case MONO_PATCH_INFO_DELEGATE_INFO:
case MONO_PATCH_INFO_VIRT_METHOD:
case MONO_PATCH_INFO_GSHAREDVT_METHOD:
case MONO_PATCH_INFO_GSHAREDVT_CALL: {
return FALSE;
}
break;
- case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE: {
+ case MONO_PATCH_INFO_DELEGATE_INFO: {
if (!can_encode_class (acfg, patch_info->data.del_tramp->klass)) {
//printf ("Skip: %s\n", mono_type_full_name (m_class_get_byval_arg (patch_info->data.klass)));
return FALSE;
break;
case MONO_PATCH_INFO_FIELD:
case MONO_PATCH_INFO_METHOD:
- case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
+ case MONO_PATCH_INFO_DELEGATE_INFO:
case MONO_PATCH_INFO_VIRT_METHOD:
case MONO_PATCH_INFO_GSHAREDVT_METHOD:
case MONO_PATCH_INFO_GSHAREDVT_CALL:
if (!ji->data.klass)
goto cleanup;
break;
- case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
+ case MONO_PATCH_INFO_DELEGATE_INFO:
ji->data.del_tramp = (MonoDelegateClassMethodPair *)mono_mempool_alloc0 (mp, sizeof (MonoDelegateClassMethodPair));
ji->data.del_tramp->klass = decode_klass_ref (aot_module, p, &p, error);
mono_error_cleanup (error); /* FIXME don't swallow the error */
entry->data = decode_resolve_method_ref (aot_module, p, &p, error);
mono_error_assert_ok (error);
break;
- case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
+ case MONO_PATCH_INFO_DELEGATE_INFO:
case MONO_PATCH_INFO_VIRT_METHOD:
case MONO_PATCH_INFO_GSHAREDVT_METHOD:
case MONO_PATCH_INFO_GSHAREDVT_CALL: {
if (imethod->del_info && imethod->del_info->klass == del->object.vtable->klass) {
*out_info = imethod->del_info;
} else if (!imethod->del_info) {
- imethod->del_info = mono_create_delegate_trampoline_info (del->object.vtable->klass, method);
+ imethod->del_info = mono_create_delegate_trampoline_info (del->object.vtable->klass, method, FALSE);
*out_info = imethod->del_info;
}
}
ERROR_DECL (error);
MonoFtnDesc *ftndesc;
+ if (info && info->is_virtual) {
+ del->method = mono_object_get_virtual_method_internal (del->target, info->method);
+ /* Create a new one below for the new class+method pair */
+ info = NULL;
+ }
+
if (!info && !del->method) {
// Multicast delegate init
// Have to set the invoke_impl field
if (G_UNLIKELY (!info)) {
g_assert (del->method);
- info = mono_create_delegate_trampoline_info (del->object.vtable->klass, del->method);
+ info = mono_create_delegate_trampoline_info (del->object.vtable->klass, del->method, FALSE);
}
del->method = info->method;
del->invoke_impl = ftndesc;
}
-void
-mini_llvmonly_init_delegate_virtual (MonoDelegate *del, MonoObject *target, MonoMethod *method)
-{
- g_assert (target);
-
- del->method = mono_object_get_virtual_method_internal (target, method);
-
- mini_llvmonly_init_delegate (del, NULL);
-}
-
/*
* resolve_iface_call:
*
G_EXTERN_C MonoFtnDesc* mini_llvmonly_resolve_generic_virtual_iface_call (MonoVTable *vt, int imt_slot, MonoMethod *imt_method);
G_EXTERN_C MonoFtnDesc* mini_llvmonly_resolve_vcall_gsharedvt_fast (MonoObject *this_obj, int slot);
G_EXTERN_C void mini_llvmonly_init_delegate (MonoDelegate *del, MonoDelegateTrampInfo *info);
-G_EXTERN_C void mini_llvmonly_init_delegate_virtual (MonoDelegate *del, MonoObject *target, MonoMethod *method);
/* Used for regular llvm as well */
G_EXTERN_C void mini_llvm_init_method (MonoAotFileInfo *info, gpointer aot_module, gpointer method_info, MonoVTable *vtable);
case MONO_PATCH_INFO_METHODCONST:
case MONO_PATCH_INFO_FIELD:
case MONO_PATCH_INFO_VIRT_METHOD:
- case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
+ case MONO_PATCH_INFO_DELEGATE_INFO:
case MONO_PATCH_INFO_GSHAREDVT_METHOD:
case MONO_PATCH_INFO_GSHAREDVT_CALL:
data = (gpointer)patch_info->data.target;
}
static MonoInst*
-emit_get_rgctx_dele_tramp (MonoCompile *cfg, int context_used,
- MonoClass *klass, MonoMethod *virt_method, gboolean _virtual, MonoRgctxInfoType rgctx_type)
+emit_get_rgctx_dele_tramp_info (MonoCompile *cfg, int context_used,
+ MonoClass *klass, MonoMethod *method, gboolean is_virtual, MonoRgctxInfoType rgctx_type)
{
MonoDelegateClassMethodPair *info;
MonoJumpInfoRgctxEntry *entry;
info = (MonoDelegateClassMethodPair *)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoDelegateClassMethodPair));
info->klass = klass;
- info->method = virt_method;
- info->is_virtual = _virtual;
+ info->method = method;
+ info->is_virtual = is_virtual;
- entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->method, context_used_is_mrgctx (cfg, context_used), MONO_PATCH_INFO_DELEGATE_TRAMPOLINE, info, rgctx_type);
+ if (!context_used) {
+ MonoInst *ins;
+
+ g_assert (rgctx_type == MONO_RGCTX_INFO_DELEGATE_TRAMP_INFO);
+ if (cfg->compile_aot) {
+ EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_DELEGATE_INFO, info);
+ } else {
+ MonoDelegateTrampInfo *tramp_info = mono_create_delegate_trampoline_info (klass, method, is_virtual);
+ EMIT_NEW_PCONST (cfg, ins, tramp_info);
+ }
+ return ins;
+ }
+
+ entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->method, context_used_is_mrgctx (cfg, context_used), MONO_PATCH_INFO_DELEGATE_INFO, info, rgctx_type);
return emit_rgctx_fetch (cfg, context_used, entry);
}
* Returns NULL and set the cfg exception on error.
*/
static G_GNUC_UNUSED MonoInst*
-handle_delegate_ctor (MonoCompile *cfg, MonoClass *klass, MonoInst *target, MonoMethod *method, int target_method_context_used, int invoke_context_used, gboolean virtual_)
+handle_delegate_ctor (MonoCompile *cfg, MonoClass *klass, MonoInst *target, MonoMethod *method, int target_method_context_used, int invoke_context_used, gboolean is_virtual)
{
MonoInst *ptr;
int dreg;
- gpointer trampoline;
- MonoInst *obj, *tramp_ins;
- guint8 **code_slot;
+ MonoInst *obj, *info_ins;
- if (virtual_ && !cfg->llvm_only) {
+ if (is_virtual && !cfg->llvm_only) {
MonoMethod *invoke = mono_get_delegate_invoke_internal (klass);
g_assert (invoke);
if (!obj)
return NULL;
- /* Inline the contents of mono_delegate_ctor */
+ /* Inline the contents of mini_init_delegate */
/* Set target field */
/* Optimize away setting of NULL target */
}
}
+ info_ins = emit_get_rgctx_dele_tramp_info (cfg, target_method_context_used | invoke_context_used, klass, method, is_virtual, MONO_RGCTX_INFO_DELEGATE_TRAMP_INFO);
+
+ if (cfg->llvm_only) {
+ MonoInst *args [] = {
+ obj,
+ info_ins
+ };
+ mono_emit_jit_icall (cfg, mini_llvmonly_init_delegate, args);
+ return obj;
+ }
+
/* Set method field */
- if (!(target_method_context_used || invoke_context_used) && !cfg->llvm_only) {
- //If compiling with gsharing enabled, it's faster to load method the delegate trampoline info than to use a rgctx slot
+ if (target_method_context_used || invoke_context_used) {
+ // We copy from the delegate trampoline info as it's faster than a rgctx fetch
+ dreg = alloc_preg (cfg);
+ MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, info_ins->dreg, MONO_STRUCT_OFFSET (MonoDelegateTrampInfo, method));
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, method), dreg);
+ } else {
+ // This is emitted as a constant store for the non-shared case.
MonoInst *method_ins = emit_get_rgctx_method (cfg, target_method_context_used, method, MONO_RGCTX_INFO_METHOD);
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, method), method_ins->dreg);
}
- if (cfg->llvm_only) {
- if (virtual_) {
- MonoInst *args [ ] = {
- obj,
- target,
- emit_get_rgctx_method (cfg, target_method_context_used, method, MONO_RGCTX_INFO_METHOD)
- };
- mono_emit_jit_icall (cfg, mini_llvmonly_init_delegate_virtual, args);
- return obj;
- }
- }
-
/*
* To avoid looking up the compiled code belonging to the target method
* in mono_delegate_trampoline (), we allocate a per-domain memory slot to
* store it, and we fill it after the method has been compiled.
*/
- if (!method->dynamic && !cfg->llvm_only) {
+ if (!method->dynamic) {
MonoInst *code_slot_ins;
- if (target_method_context_used) {
+ if (target_method_context_used)
code_slot_ins = emit_get_rgctx_method (cfg, target_method_context_used, method, MONO_RGCTX_INFO_METHOD_DELEGATE_CODE);
- } else {
- MonoJitMemoryManager *jit_mm = (MonoJitMemoryManager*)cfg->jit_mm;
-
- jit_mm_lock (jit_mm);
- if (!jit_mm->method_code_hash)
- jit_mm->method_code_hash = g_hash_table_new (NULL, NULL);
- code_slot = (guint8 **)g_hash_table_lookup (jit_mm->method_code_hash, method);
- if (!code_slot) {
- code_slot = (guint8 **)mono_mem_manager_alloc0 (jit_mm->mem_manager, sizeof (gpointer));
- g_hash_table_insert (jit_mm->method_code_hash, method, code_slot);
- }
- jit_mm_unlock (jit_mm);
-
+ else
code_slot_ins = mini_emit_runtime_constant (cfg, MONO_PATCH_INFO_METHOD_CODE_SLOT, method);
- }
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, method_code), code_slot_ins->dreg);
}
- if (target_method_context_used || invoke_context_used) {
- tramp_ins = emit_get_rgctx_dele_tramp (cfg, target_method_context_used | invoke_context_used, klass, method, virtual_, MONO_RGCTX_INFO_DELEGATE_TRAMP_INFO);
-
- //This is emitted as a constant store for the non-shared case.
- //We copy from the delegate trampoline info as it's faster than a rgctx fetch
- dreg = alloc_preg (cfg);
- if (!cfg->llvm_only) {
- MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, tramp_ins->dreg, MONO_STRUCT_OFFSET (MonoDelegateTrampInfo, method));
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, method), dreg);
- }
- } else if (cfg->compile_aot) {
- MonoDelegateClassMethodPair *del_tramp;
-
- del_tramp = (MonoDelegateClassMethodPair *)mono_mempool_alloc0 (cfg->mempool, sizeof (MonoDelegateClassMethodPair));
- del_tramp->klass = klass;
- del_tramp->method = method;
- del_tramp->is_virtual = virtual_;
- EMIT_NEW_AOTCONST (cfg, tramp_ins, MONO_PATCH_INFO_DELEGATE_TRAMPOLINE, del_tramp);
- } else {
- if (virtual_)
- trampoline = mono_create_delegate_virtual_trampoline (klass, method);
- else
- trampoline = mono_create_delegate_trampoline_info (klass, method);
- EMIT_NEW_PCONST (cfg, tramp_ins, trampoline);
- }
-
- if (cfg->llvm_only) {
- MonoInst *args [ ] = {
- obj,
- tramp_ins
- };
- mono_emit_jit_icall (cfg, mini_llvmonly_init_delegate, args);
- return obj;
- }
-
/* Set invoke_impl field */
- if (virtual_) {
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, invoke_impl), tramp_ins->dreg);
- } else {
- dreg = alloc_preg (cfg);
- MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, tramp_ins->dreg, MONO_STRUCT_OFFSET (MonoDelegateTrampInfo, invoke_impl));
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, invoke_impl), dreg);
+ dreg = alloc_preg (cfg);
+ MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, info_ins->dreg, MONO_STRUCT_OFFSET (MonoDelegateTrampInfo, invoke_impl));
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, invoke_impl), dreg);
+ if (!is_virtual) {
dreg = alloc_preg (cfg);
- MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, tramp_ins->dreg, MONO_STRUCT_OFFSET (MonoDelegateTrampInfo, method_ptr));
+ MONO_EMIT_NEW_LOAD_MEMBASE (cfg, dreg, info_ins->dreg, MONO_STRUCT_OFFSET (MonoDelegateTrampInfo, method_ptr));
MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STORE_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, method_ptr), dreg);
}
- dreg = alloc_preg (cfg);
- MONO_EMIT_NEW_ICONST (cfg, dreg, virtual_ ? 1 : 0);
- MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, method_is_virtual), dreg);
+ if (is_virtual) {
+ dreg = alloc_preg (cfg);
+ MONO_EMIT_NEW_ICONST (cfg, dreg, 1);
+ MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREI1_MEMBASE_REG, obj->dreg, MONO_STRUCT_OFFSET (MonoDelegate, method_is_virtual), dreg);
+ }
/* All the checks which are in mono_delegate_ctor () are done by the delegate trampoline */
return res;
}
case MONO_RGCTX_INFO_DELEGATE_TRAMP_INFO: {
- MonoDelegateClassMethodPair *dele_info = (MonoDelegateClassMethodPair*)data;
- gpointer trampoline;
-
- if (dele_info->is_virtual)
- trampoline = mono_create_delegate_virtual_trampoline (dele_info->klass, dele_info->method);
- else
- trampoline = mono_create_delegate_trampoline_info (dele_info->klass, dele_info->method);
+ MonoDelegateClassMethodPair *del_info = (MonoDelegateClassMethodPair*)data;
+ gpointer trampoline = mono_create_delegate_trampoline_info (del_info->klass, del_info->method, del_info->is_virtual);
g_assert (trampoline);
return trampoline;
}
case MONO_RGCTX_INFO_METHOD_DELEGATE_CODE:
return MONO_PATCH_INFO_METHOD;
case MONO_RGCTX_INFO_DELEGATE_TRAMP_INFO:
- return MONO_PATCH_INFO_DELEGATE_TRAMPOLINE;
+ return MONO_PATCH_INFO_DELEGATE_INFO;
case MONO_RGCTX_INFO_VIRT_METHOD:
case MONO_RGCTX_INFO_VIRT_METHOD_CODE:
case MONO_RGCTX_INFO_VIRT_METHOD_BOX_TYPE:
entry_data = info;
break;
}
- case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE: {
+ case MONO_PATCH_INFO_DELEGATE_INFO: {
MonoDelegateClassMethodPair *info;
MonoDelegateClassMethodPair *oinfo = entry->data->data.del_tramp;
switch (entry->data->type) {
case MONO_PATCH_INFO_GSHAREDVT_CALL:
case MONO_PATCH_INFO_VIRT_METHOD:
- case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
+ case MONO_PATCH_INFO_DELEGATE_INFO:
g_free (entry_data);
break;
case MONO_PATCH_INFO_GSHAREDVT_METHOD: {
memcpy (res->data.rgctx_entry, patch_info->data.rgctx_entry, sizeof (MonoJumpInfoRgctxEntry));
res->data.rgctx_entry->data = mono_patch_info_dup_mp (mp, res->data.rgctx_entry->data);
break;
- case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
+ case MONO_PATCH_INFO_DELEGATE_INFO:
res->data.del_tramp = (MonoDelegateClassMethodPair *)mono_mempool_alloc0 (mp, sizeof (MonoDelegateClassMethodPair));
memcpy (res->data.del_tramp, patch_info->data.del_tramp, sizeof (MonoDelegateClassMethodPair));
break;
return hash | ji->data.table->table_size;
case MONO_PATCH_INFO_GSHAREDVT_METHOD:
return hash | GPOINTER_TO_UINT (ji->data.gsharedvt_method->method);
- case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
+ case MONO_PATCH_INFO_DELEGATE_INFO:
return (guint)(hash | (gsize)ji->data.del_tramp->klass | (gsize)ji->data.del_tramp->method | (gsize)ji->data.del_tramp->is_virtual);
case MONO_PATCH_INFO_VIRT_METHOD: {
MonoJumpInfoVirtMethod *info = ji->data.virt_method;
}
case MONO_PATCH_INFO_GSHAREDVT_METHOD:
return ji1->data.gsharedvt_method->method == ji2->data.gsharedvt_method->method;
- case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
+ case MONO_PATCH_INFO_DELEGATE_INFO:
return ji1->data.del_tramp->klass == ji2->data.del_tramp->klass && ji1->data.del_tramp->method == ji2->data.del_tramp->method && ji1->data.del_tramp->is_virtual == ji2->data.del_tramp->is_virtual;
case MONO_PATCH_INFO_SPECIFIC_TRAMPOLINE_LAZY_FETCH_ADDR:
return ji1->data.uindex == ji2->data.uindex;
MonoRuntimeGenericContextInfoTemplate *entry = &info->entries [i];
MonoRuntimeGenericContextInfoTemplate *new_entry = &res->entries [i];
switch (mini_rgctx_info_type_to_patch_info_type (entry->info_type)) {
- case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE: {
+ case MONO_PATCH_INFO_DELEGATE_INFO: {
MonoDelegateClassMethodPair *old_info = (MonoDelegateClassMethodPair*)entry->data;
MonoDelegateClassMethodPair *new_info = mono_mem_manager_alloc0 (mem_manager, sizeof (MonoDelegateClassMethodPair));
memcpy (new_info, old_info, sizeof (MonoDelegateClassMethodPair));
target = mono_class_vtable_checked (patch_info->data.klass, error);
mono_error_assert_ok (error);
break;
- case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE: {
+ case MONO_PATCH_INFO_DELEGATE_INFO: {
MonoDelegateClassMethodPair *del_tramp = patch_info->data.del_tramp;
- if (del_tramp->is_virtual)
- target = mono_create_delegate_virtual_trampoline (del_tramp->klass, del_tramp->method);
- else
- target = mono_create_delegate_trampoline_info (del_tramp->klass, del_tramp->method);
+ target = mono_create_delegate_trampoline_info (del_tramp->klass, del_tramp->method, del_tramp->is_virtual);
break;
}
case MONO_PATCH_INFO_SFLDA: {
static void runtime_invoke_info_free (gpointer value);
static gint
-class_method_pair_equal (gconstpointer ka, gconstpointer kb)
+delegate_class_method_pair_equal (gconstpointer ka, gconstpointer kb)
{
- const MonoClassMethodPair *apair = (const MonoClassMethodPair *)ka;
- const MonoClassMethodPair *bpair = (const MonoClassMethodPair *)kb;
+ const MonoDelegateClassMethodPair *apair = (const MonoDelegateClassMethodPair *)ka;
+ const MonoDelegateClassMethodPair *bpair = (const MonoDelegateClassMethodPair *)kb;
- return apair->klass == bpair->klass && apair->method == bpair->method ? 1 : 0;
+ return apair->klass == bpair->klass && apair->method == bpair->method && apair->is_virtual == bpair->is_virtual ? 1 : 0;
}
static guint
-class_method_pair_hash (gconstpointer data)
+delegate_class_method_pair_hash (gconstpointer data)
{
- const MonoClassMethodPair *pair = (const MonoClassMethodPair *)data;
+ const MonoDelegateClassMethodPair *pair = (const MonoDelegateClassMethodPair *)data;
- return (guint)((gsize)pair->klass ^ (gsize)pair->method);
+ return (guint)((gsize)pair->klass ^ (gsize)pair->method ^ (gsize)pair->is_virtual);
}
static void
info->jump_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
info->jump_target_hash = g_hash_table_new (NULL, NULL);
info->jit_trampoline_hash = g_hash_table_new (mono_aligned_addr_hash, NULL);
- info->delegate_trampoline_hash = g_hash_table_new (class_method_pair_hash, class_method_pair_equal);
+ info->delegate_info_hash = g_hash_table_new (delegate_class_method_pair_hash, delegate_class_method_pair_equal);
info->seq_points = g_hash_table_new_full (mono_aligned_addr_hash, NULL, NULL, mono_seq_point_info_free);
info->runtime_invoke_hash = mono_conc_hashtable_new_full (mono_aligned_addr_hash, NULL, NULL, runtime_invoke_info_free);
info->arch_seq_points = g_hash_table_new (mono_aligned_addr_hash, NULL);
g_hash_table_destroy (info->method_code_hash);
g_hash_table_destroy (info->jump_trampoline_hash);
g_hash_table_destroy (info->jit_trampoline_hash);
- g_hash_table_destroy (info->delegate_trampoline_hash);
+ g_hash_table_destroy (info->delegate_info_hash);
g_hash_table_destroy (info->static_rgctx_trampoline_hash);
g_hash_table_destroy (info->mrgctx_hash);
g_hash_table_destroy (info->interp_method_pointer_hash);
/* This needs a wrapper so it can have a preserveall cconv */
register_icall (mini_llvmonly_init_vtable_slot, mono_icall_sig_ptr_ptr_int, FALSE);
register_icall (mini_llvmonly_init_delegate, mono_icall_sig_void_object_ptr, TRUE);
- register_icall (mini_llvmonly_init_delegate_virtual, mono_icall_sig_void_object_object_ptr, TRUE);
register_icall (mini_llvmonly_throw_nullref_exception, mono_icall_sig_void, TRUE);
register_icall (mini_llvmonly_throw_aot_failed_exception, mono_icall_sig_void_ptr, TRUE);
register_icall (mini_llvmonly_interp_entry_gsharedvt, mono_icall_sig_void_ptr_ptr_ptr, TRUE);
/* Maps methods/klasses to the address of the given type of trampoline */
GHashTable *jump_trampoline_hash;
GHashTable *jit_trampoline_hash;
- GHashTable *delegate_trampoline_hash;
+ GHashTable *delegate_info_hash;
/* Maps ClassMethodPair -> MonoDelegateTrampInfo */
GHashTable *static_rgctx_trampoline_hash;
/* maps MonoMethod -> MonoJitDynamicMethodInfo */
MonoMethod *invoke = tramp_info->invoke;
guint8 *impl_this = (guint8 *)tramp_info->impl_this;
guint8 *impl_nothis = (guint8 *)tramp_info->impl_nothis;
- ERROR_DECL (err);
MonoMethodSignature *sig;
gpointer addr, compiled_method;
- gboolean is_remote = FALSE;
UnlockedIncrement (&trampoline_calls);
* (ctor_with_method () does this, but it doesn't store the wrapper back into
* delegate->method).
*/
- if (!is_remote) {
- sig = tramp_info->sig;
- if (!(sig && method == tramp_info->method)) {
- error_init (err);
- sig = mono_method_signature_checked (method, err);
- if (!sig) {
- mono_error_set_pending_exception (err);
- return NULL;
- }
+ sig = tramp_info->sig;
+ if (!(sig && method == tramp_info->method)) {
+ sig = mono_method_signature_checked (method, error);
+ if (!sig) {
+ mono_error_set_pending_exception (error);
+ return NULL;
}
+ }
- if (sig->hasthis && m_class_is_valuetype (method->klass)) {
- gboolean need_unbox = TRUE;
+ if (sig->hasthis && m_class_is_valuetype (method->klass)) {
+ gboolean need_unbox = TRUE;
- if (tramp_info->invoke_sig->param_count > sig->param_count && m_type_is_byref (tramp_info->invoke_sig->params [0]))
- need_unbox = FALSE;
+ if (tramp_info->invoke_sig->param_count > sig->param_count && m_type_is_byref (tramp_info->invoke_sig->params [0]))
+ need_unbox = FALSE;
- if (need_unbox) {
- if (mono_aot_only)
- need_unbox_tramp = TRUE;
- else
- method = mono_marshal_get_unbox_wrapper (method);
- }
+ if (need_unbox) {
+ if (mono_aot_only)
+ need_unbox_tramp = TRUE;
+ else
+ method = mono_marshal_get_unbox_wrapper (method);
}
}
// If "delegate->method_ptr" is null mono_get_addr_from_ftnptr will fail if
if (method) {
sig = tramp_info->sig;
if (!(sig && method == tramp_info->method)) {
- error_init (err);
- sig = mono_method_signature_checked (method, err);
+ sig = mono_method_signature_checked (method, error);
if (!sig) {
- mono_error_set_pending_exception (err);
+ mono_error_set_pending_exception (error);
return NULL;
}
}
* mono_create_delegate_trampoline_info:
*
* Create a trampoline info structure for the KLASS+METHOD pair.
+ * If VIRTUAL is true, the delegate was created using ldvirtftn, so invoking it needs
+ * to either do a virtual call or do a virtual method lookup.
*/
MonoDelegateTrampInfo*
-mono_create_delegate_trampoline_info (MonoClass *klass, MonoMethod *method)
+mono_create_delegate_trampoline_info (MonoClass *klass, MonoMethod *method, gboolean is_virtual)
{
MonoMethod *invoke;
ERROR_DECL (error);
MonoDelegateTrampInfo *tramp_info;
- MonoClassMethodPair pair, *dpair;
+ MonoDelegateClassMethodPair pair, *dpair;
MonoMemoryManager *mm_class, *mm_method, *mm;
MonoJitMemoryManager *jit_mm;
pair.klass = klass;
pair.method = method;
+ pair.is_virtual = is_virtual;
if (method) {
mm_class = m_class_get_mem_manager (klass);
}
jit_mm_lock (jit_mm);
- tramp_info = (MonoDelegateTrampInfo *)g_hash_table_lookup (jit_mm->delegate_trampoline_hash, &pair);
+ tramp_info = (MonoDelegateTrampInfo *)g_hash_table_lookup (jit_mm->delegate_info_hash, &pair);
jit_mm_unlock (jit_mm);
if (tramp_info)
return tramp_info;
tramp_info->klass = klass;
tramp_info->invoke = invoke;
tramp_info->invoke_sig = mono_method_signature_internal (invoke);
+ tramp_info->is_virtual = is_virtual;
// FIXME: Use a different conditional
#ifndef HOST_WASM
if (!mono_llvm_only) {
tramp_info->sig = mono_method_signature_checked (method, error);
tramp_info->need_rgctx_tramp = mono_method_needs_static_rgctx_invoke (method, FALSE);
}
+
#ifndef HOST_WASM
- if (!mono_llvm_only) {
- guint32 code_size = 0;
- tramp_info->invoke_impl = mono_create_specific_trampoline (jit_mm->mem_manager, tramp_info, MONO_TRAMPOLINE_DELEGATE, &code_size);
- g_assert (code_size);
+ if (is_virtual) {
+ tramp_info->invoke_impl = mono_get_delegate_virtual_invoke_impl (mono_method_signature_internal (invoke), method);
+ } else {
+ if (!mono_llvm_only) {
+ guint32 code_size = 0;
+ tramp_info->invoke_impl = mono_create_specific_trampoline (jit_mm->mem_manager, tramp_info, MONO_TRAMPOLINE_DELEGATE, &code_size);
+ g_assert (code_size);
+ }
}
#endif
- dpair = (MonoClassMethodPair *)mono_mem_manager_alloc0 (jit_mm->mem_manager, sizeof (MonoClassMethodPair));
- memcpy (dpair, &pair, sizeof (MonoClassMethodPair));
+ dpair = (MonoDelegateClassMethodPair *)mono_mem_manager_alloc0 (jit_mm->mem_manager, sizeof (MonoDelegateClassMethodPair));
+ memcpy (dpair, &pair, sizeof (MonoDelegateClassMethodPair));
/* store trampoline address */
jit_mm_lock (jit_mm);
- g_hash_table_insert (jit_mm->delegate_trampoline_hash, dpair, tramp_info);
+ g_hash_table_insert (jit_mm->delegate_info_hash, dpair, tramp_info);
jit_mm_unlock (jit_mm);
return tramp_info;
if (mono_llvm_only || (mono_use_interpreter && !mono_aot_only))
return (gpointer)no_delegate_trampoline;
- return mono_create_delegate_trampoline_info (klass, NULL)->invoke_impl;
-}
-
-gpointer
-mono_create_delegate_virtual_trampoline (MonoClass *klass, MonoMethod *method)
-{
- MonoMethod *invoke = mono_get_delegate_invoke_internal (klass);
- g_assert (invoke);
-
- return mono_get_delegate_virtual_invoke_impl (mono_method_signature_internal (invoke), method);
+ return mono_create_delegate_trampoline_info (klass, NULL, FALSE)->invoke_impl;
}
gpointer
gpointer impl_this;
gpointer impl_nothis;
gboolean need_rgctx_tramp;
+ gboolean is_virtual;
} MonoDelegateTrampInfo;
/*
gpointer mono_create_jit_trampoline (MonoMethod *method, MonoError *error);
gpointer mono_create_jit_trampoline_from_token (MonoImage *image, guint32 token);
gpointer mono_create_delegate_trampoline (MonoClass *klass);
-MonoDelegateTrampInfo* mono_create_delegate_trampoline_info (MonoClass *klass, MonoMethod *method);
-gpointer mono_create_delegate_virtual_trampoline (MonoClass *klass, MonoMethod *method);
+MonoDelegateTrampInfo* mono_create_delegate_trampoline_info (MonoClass *klass, MonoMethod *method, gboolean is_virtual);
gpointer mono_create_rgctx_lazy_fetch_trampoline (guint32 offset);
gpointer mono_create_static_rgctx_trampoline (MonoMethod *m, gpointer addr);
gpointer mono_create_ftnptr_arg_trampoline (gpointer arg, gpointer addr);
PATCH_INFO(GOT_OFFSET, "got_offset")
PATCH_INFO(DECLSEC, "declsec")
PATCH_INFO(RVA, "rva")
-PATCH_INFO(DELEGATE_TRAMPOLINE, "delegate_trampoline")
+PATCH_INFO(DELEGATE_INFO, "delegate_info")
PATCH_INFO(ICALL_ADDR, "icall_addr")
/* The address of a C function implementing a JIT icall */
PATCH_INFO(JIT_ICALL_ADDR, "jit_icall_addr")