}
break;
case MONO_PATCH_INFO_CLASS_INIT:
+ case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
encode_klass_ref (acfg, patch_info->data.klass, p, &p);
break;
case MONO_PATCH_INFO_FIELD:
break;
case MONO_PATCH_INFO_VTABLE:
case MONO_PATCH_INFO_CLASS_INIT:
+ case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
case MONO_PATCH_INFO_CLASS:
case MONO_PATCH_INFO_IID:
case MONO_PATCH_INFO_ADJUSTED_IID:
static CRITICAL_SECTION jit_mutex;
static GHashTable *class_init_hash_addr = NULL;
+static GHashTable *delegate_trampoline_hash_addr = NULL;
static MonoCodeManager *global_codeman = NULL;
ins->inst_right = offset_ins;
trampoline = mono_create_delegate_trampoline (klass);
- NEW_PCONST (cfg, tramp_ins, trampoline);
+ NEW_AOTCONST (cfg, tramp_ins, MONO_PATCH_INFO_ABS, trampoline);
MONO_INST_NEW (cfg, store, CEE_STIND_I);
store->cil_code = ip;
* Optimize the common case of ldftn+delegate creation
*/
#if defined(MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE) && !defined(HAVE_WRITE_BARRIERS)
- /* FIXME: AOT */
/* FIXME: SGEN support */
- if ((sp > stack_start) && (ip + 6 + 5 < end) && ip_in_bb (cfg, bblock, ip + 6) && (ip [6] == CEE_NEWOBJ) && (ctor_method = mini_get_method (method, read32 (ip + 7), NULL, generic_context)) && (ctor_method->klass->parent == mono_defaults.multicastdelegate_class) && !cfg->compile_aot) {
+ if ((sp > stack_start) && (ip + 6 + 5 < end) && ip_in_bb (cfg, bblock, ip + 6) && (ip [6] == CEE_NEWOBJ) && (ctor_method = mini_get_method (method, read32 (ip + 7), NULL, generic_context)) && (ctor_method->klass->parent == mono_defaults.multicastdelegate_class)) {
MonoInst *target_ins;
ip += 6;
klass, ptr);
mono_domain_unlock (domain);
+ mono_jit_lock ();
+ if (!delegate_trampoline_hash_addr)
+ delegate_trampoline_hash_addr = g_hash_table_new (NULL, NULL);
+ g_hash_table_insert (delegate_trampoline_hash_addr, ptr, klass);
+ mono_jit_unlock ();
+
return ptr;
#else
return NULL;
return res;
}
+static MonoClass*
+mono_find_delegate_trampoline_by_addr (gconstpointer addr)
+{
+ MonoClass *res;
+
+ mono_jit_lock ();
+ if (delegate_trampoline_hash_addr)
+ res = g_hash_table_lookup (delegate_trampoline_hash_addr, addr);
+ else
+ res = NULL;
+ mono_jit_unlock ();
+ return res;
+}
+
static void
mono_dynamic_code_hash_insert (MonoDomain *domain, MonoMethod *method, MonoJitDynamicMethodInfo *ji)
{
case MONO_PATCH_INFO_CLASS_INIT:
target = mono_create_class_init_trampoline (mono_class_vtable (domain, patch_info->data.klass));
break;
+ case MONO_PATCH_INFO_DELEGATE_TRAMPOLINE:
+ target = mono_create_delegate_trampoline (patch_info->data.klass);
+ break;
case MONO_PATCH_INFO_SFLDA: {
MonoVTable *vtable = mono_class_vtable (domain, patch_info->data.field->parent);
if (!vtable->initialized && !(vtable->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT) && (method && mono_class_needs_cctor_run (vtable->klass, method)))
if (vtable) {
patch_info->type = MONO_PATCH_INFO_CLASS_INIT;
patch_info->data.klass = vtable->klass;
+ } else {
+ MonoClass *klass = mono_find_delegate_trampoline_by_addr (patch_info->data.target);
+ if (klass) {
+ patch_info->type = MONO_PATCH_INFO_DELEGATE_TRAMPOLINE;
+ patch_info->data.klass = klass;
+ }
}
}
break;
g_hash_table_destroy (jit_icall_name_hash);
if (class_init_hash_addr)
g_hash_table_destroy (class_init_hash_addr);
+ if (delegate_trampoline_hash_addr)
+ g_hash_table_destroy (delegate_trampoline_hash_addr);
g_free (emul_opcode_map);
mono_arch_cleanup ();