*/
#include <config.h>
+#include <mono/utils/mono-compiler.h>
#ifndef DISABLE_JIT
static MonoMethodSignature *helper_sig_domain_get;
static MonoMethodSignature *helper_sig_rgctx_lazy_fetch_trampoline;
static MonoMethodSignature *helper_sig_llvmonly_imt_trampoline;
+static MonoMethodSignature *helper_sig_jit_thread_attach;
/* type loading helpers */
static GENERATE_GET_CLASS_WITH_CACHE (runtime_helpers, System.Runtime.CompilerServices, RuntimeHelpers)
case MONO_TYPE_TYPEDBYREF:
return OP_VMOVE;
case MONO_TYPE_GENERICINST:
+ if (MONO_CLASS_IS_SIMD (cfg, mono_class_from_mono_type (type)))
+ return OP_XMOVE;
type = &type->data.generic_class->container_class->byval_arg;
goto handle_enum;
case MONO_TYPE_VAR:
helper_sig_domain_get = mono_create_icall_signature ("ptr");
helper_sig_rgctx_lazy_fetch_trampoline = mono_create_icall_signature ("ptr ptr");
helper_sig_llvmonly_imt_trampoline = mono_create_icall_signature ("ptr ptr ptr");
+ helper_sig_jit_thread_attach = mono_create_icall_signature ("ptr ptr");
}
static MONO_NEVER_INLINE void
if (!(method->flags & METHOD_ATTRIBUTE_STATIC) &&
!(context_used & MONO_GENERIC_CONTEXT_USED_METHOD) &&
- !method->klass->valuetype)
- EMIT_NEW_ARGLOAD (cfg, this_ins, 0);
+ !method->klass->valuetype)
+ EMIT_NEW_VARLOAD (cfg, this_ins, cfg->this_arg, &mono_defaults.object_class->byval_arg);
if (context_used & MONO_GENERIC_CONTEXT_USED_METHOD) {
MonoInst *mrgctx_loc, *mrgctx_var;
emit_get_rgctx_klass (MonoCompile *cfg, int context_used,
MonoClass *klass, MonoRgctxInfoType rgctx_type)
{
- MonoJumpInfoRgctxEntry *entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->current_method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_CLASS, klass, rgctx_type);
- MonoInst *rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
+ MonoJumpInfoRgctxEntry *entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_CLASS, klass, rgctx_type);
+ MonoInst *rgctx = emit_get_rgctx (cfg, cfg->method, context_used);
return emit_rgctx_fetch (cfg, rgctx, entry);
}
emit_get_rgctx_sig (MonoCompile *cfg, int context_used,
MonoMethodSignature *sig, MonoRgctxInfoType rgctx_type)
{
- MonoJumpInfoRgctxEntry *entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->current_method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_SIGNATURE, sig, rgctx_type);
- MonoInst *rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
+ MonoJumpInfoRgctxEntry *entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_SIGNATURE, sig, rgctx_type);
+ MonoInst *rgctx = emit_get_rgctx (cfg, cfg->method, context_used);
return emit_rgctx_fetch (cfg, rgctx, entry);
}
call_info->sig = sig;
call_info->method = cmethod;
- entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->current_method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_GSHAREDVT_CALL, call_info, rgctx_type);
- rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
+ entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_GSHAREDVT_CALL, call_info, rgctx_type);
+ rgctx = emit_get_rgctx (cfg, cfg->method, context_used);
return emit_rgctx_fetch (cfg, rgctx, entry);
}
info->klass = klass;
info->method = virt_method;
- entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->current_method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_VIRT_METHOD, info, rgctx_type);
- rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
+ entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_VIRT_METHOD, info, rgctx_type);
+ rgctx = emit_get_rgctx (cfg, cfg->method, context_used);
return emit_rgctx_fetch (cfg, rgctx, entry);
}
MonoJumpInfoRgctxEntry *entry;
MonoInst *rgctx;
- entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->current_method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_GSHAREDVT_METHOD, info, MONO_RGCTX_INFO_METHOD_GSHAREDVT_INFO);
- rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
+ entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_GSHAREDVT_METHOD, info, MONO_RGCTX_INFO_METHOD_GSHAREDVT_INFO);
+ rgctx = emit_get_rgctx (cfg, cfg->method, context_used);
return emit_rgctx_fetch (cfg, rgctx, entry);
}
g_assert_not_reached ();
}
} else {
- MonoJumpInfoRgctxEntry *entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->current_method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_METHODCONST, cmethod, rgctx_type);
- MonoInst *rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
+ MonoJumpInfoRgctxEntry *entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_METHODCONST, cmethod, rgctx_type);
+ MonoInst *rgctx = emit_get_rgctx (cfg, cfg->method, context_used);
return emit_rgctx_fetch (cfg, rgctx, entry);
}
emit_get_rgctx_field (MonoCompile *cfg, int context_used,
MonoClassField *field, MonoRgctxInfoType rgctx_type)
{
- MonoJumpInfoRgctxEntry *entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->current_method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_FIELD, field, rgctx_type);
- MonoInst *rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
+ MonoJumpInfoRgctxEntry *entry = mono_patch_info_rgctx_entry_new (cfg->mempool, cfg->method, context_used & MONO_GENERIC_CONTEXT_USED_METHOD, MONO_PATCH_INFO_FIELD, field, rgctx_type);
+ MonoInst *rgctx = emit_get_rgctx (cfg, cfg->method, context_used);
return emit_rgctx_fetch (cfg, rgctx, entry);
}
cfg->signatures = g_slist_prepend_mempool (cfg->mempool, cfg->signatures, mono_method_signature (method));
return emit_llvmonly_calli (cfg, mono_method_signature (method), &val, addr);
} else {
- rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
+ rgctx = emit_get_rgctx (cfg, cfg->method, context_used);
return mono_emit_calli (cfg, mono_method_signature (method), &val, addr, NULL, rgctx);
}
have to get the method address from the RGCTX. */
MonoInst *addr = emit_get_rgctx_method (cfg, context_used, method,
MONO_RGCTX_INFO_GENERIC_METHOD_CODE);
- MonoInst *rgctx = emit_get_rgctx (cfg, cfg->current_method, context_used);
+ MonoInst *rgctx = emit_get_rgctx (cfg, cfg->method, context_used);
return mono_emit_calli (cfg, mono_method_signature (method), &val, addr, NULL, rgctx);
}
if (cfg->disable_inline)
return FALSE;
- if (cfg->gshared)
+ if (cfg->gsharedvt)
return FALSE;
if (cfg->inline_depth > 10)
* since it would mean inserting a call to mono_runtime_class_init()
* inside the inlined code
*/
+ if (cfg->gshared && method->klass->has_cctor && mini_class_check_context_used (cfg, method->klass))
+ return FALSE;
+
if (!(cfg->opt & MONO_OPT_SHARED)) {
/* The AggressiveInlining hint is a good excuse to force that cctor to run. */
if (method->iflags & METHOD_IMPL_ATTRIBUTE_AGGRESSIVE_INLINING) {
- vtable = mono_class_vtable (cfg->domain, method->klass);
- if (!vtable)
- return FALSE;
- if (!cfg->compile_aot) {
- MonoError error;
- if (!mono_runtime_class_init_full (vtable, &error)) {
- mono_error_cleanup (&error);
+ if (method->klass->has_cctor) {
+ vtable = mono_class_vtable (cfg->domain, method->klass);
+ if (!vtable)
return FALSE;
+ if (!cfg->compile_aot) {
+ MonoError error;
+ if (!mono_runtime_class_init_full (vtable, &error)) {
+ mono_error_cleanup (&error);
+ return FALSE;
+ }
}
}
} else if (mono_class_is_before_field_init (method->klass)) {
return TRUE;
}
-static MonoInst*
+MonoInst*
mini_emit_ldelema_1_ins (MonoCompile *cfg, MonoClass *klass, MonoInst *arr, MonoInst *index, gboolean bcheck)
{
MonoInst *ins;
* all inputs:
* http://everything2.com/?node_id=1051618
*/
+ } else if (cmethod->klass == mono_defaults.systemtype_class && !strcmp (cmethod->name, "op_Equality")) {
+ EMIT_NEW_BIALU (cfg, ins, OP_COMPARE, -1, args [0]->dreg, args [1]->dreg);
+ MONO_INST_NEW (cfg, ins, OP_PCEQ);
+ ins->dreg = alloc_preg (cfg);
+ ins->type = STACK_I4;
+ MONO_ADD_INS (cfg->cbb, ins);
+ return ins;
} else if (((!strcmp (cmethod->klass->image->assembly->aname.name, "MonoMac") ||
!strcmp (cmethod->klass->image->assembly->aname.name, "monotouch")) &&
!strcmp (cmethod->klass->name_space, "XamCore.ObjCRuntime") &&
if ((costs >= 0 && costs < 60) || inline_always || (costs >= 0 && (cmethod->iflags & METHOD_IMPL_ATTRIBUTE_AGGRESSIVE_INLINING))) {
if (cfg->verbose_level > 2)
printf ("INLINE END %s -> %s\n", mono_method_full_name (cfg->method, TRUE), mono_method_full_name (cmethod, TRUE));
-
+
cfg->stat_inlined_methods++;
/* always add some code to avoid block split failures */
}
/* Common call */
- INLINE_FAILURE ("call");
+ if (!(cmethod->iflags & METHOD_IMPL_ATTRIBUTE_AGGRESSIVE_INLINING))
+ INLINE_FAILURE ("call");
ins = mono_emit_method_call_full (cfg, cmethod, fsig, tail_call, sp, virtual_ ? sp [0] : NULL,
imt_arg, vtable_arg);
MONO_EMIT_NULL_CHECK (cfg, sp [0]->dreg);
+ if (sp [0]->opcode == OP_LDADDR && klass->simd_type && cfg->opt & MONO_OPT_SIMD) {
+ ins = mono_emit_simd_field_load (cfg, field, sp [0]);
+ if (ins) {
+ *sp++ = ins;
+ ins_flag = 0;
+ ip += 5;
+ break;
+ }
+ }
+
if (mini_is_gsharedvt_klass (klass)) {
MonoInst *offset_ins;
cmethod = (MonoMethod *)mono_method_get_wrapper_data (method, token);
if (cfg->compile_aot) {
- EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_ICALL_ADDR, cmethod);
+ if (cfg->direct_pinvoke && ip + 6 < end && (ip [6] == CEE_POP)) {
+ /*
+ * This is generated by emit_native_wrapper () to resolve the pinvoke address
+ * before the call, its not needed when using direct pinvoke.
+ * This is not an optimization, but its used to avoid looking up pinvokes
+ * on platforms which don't support dlopen ().
+ */
+ EMIT_NEW_PCONST (cfg, ins, NULL);
+ } else {
+ EMIT_NEW_AOTCONST (cfg, ins, MONO_PATCH_INFO_ICALL_ADDR, cmethod);
+ }
} else {
ptr = mono_lookup_internal_call (cmethod);
g_assert (ptr);
/* AOT code is only used in the root domain */
EMIT_NEW_PCONST (cfg, args [0], cfg->compile_aot ? NULL : cfg->domain);
- ins = mono_emit_jit_icall (cfg, mono_jit_thread_attach, args);
+ if (cfg->compile_aot) {
+ MonoInst *addr;
+
+ /*
+ * This is called on unattached threads, so it cannot go through the trampoline
+ * infrastructure. Use an indirect call through a got slot initialized at load time
+ * instead.
+ */
+ EMIT_NEW_AOTCONST (cfg, addr, MONO_PATCH_INFO_JIT_THREAD_ATTACH, NULL);
+ ins = mono_emit_calli (cfg, helper_sig_jit_thread_attach, args, addr, NULL, NULL);
+ } else {
+ ins = mono_emit_jit_icall (cfg, mono_jit_thread_attach, args);
+ }
MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, cfg->orig_domain_var->dreg, ins->dreg);
if (next_bb)
MONO_START_BB (cfg, next_bb);
-
ip += 2;
break;
}
mono_compile_create_var_for_vreg (cfg, &mono_defaults.double_class->byval_arg, OP_LOCAL, vreg);
break;
case 'v':
+ case 'x':
mono_compile_create_var_for_vreg (cfg, &ins->klass->byval_arg, OP_LOCAL, vreg);
break;
default:
NEW_BBLOCK (cfg, first_bb);
cfg->cbb = first_bb;
- if (!context_used && mini_class_has_reference_variant_generic_argument (cfg, klass, context_used)) {
+ if (!context_used && (mini_class_has_reference_variant_generic_argument (cfg, klass, context_used) || klass->is_array_special_interface)) {
if (is_isinst)
ret = emit_isinst_with_cache_nonshared (cfg, source, klass);
else
the values on the stack before emitting the last instruction of the bb.
*/
-#endif /* DISABLE_JIT */
+#else /* !DISABLE_JIT */
+
+MONO_EMPTY_SOURCE_FILE (method_to_ir);
+
+#endif /* !DISABLE_JIT */