From: Rodrigo Kumpera Date: Thu, 1 Dec 2016 19:16:10 +0000 (-0800) Subject: Merge pull request #4048 from kumpera/iface_casting_cleanup X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=commitdiff_plain;h=ce166860ea51867004930efea92cb7c86178900f;hp=-c;p=mono.git Merge pull request #4048 from kumpera/iface_casting_cleanup [mini] Reorg casting code + optimize casting of magic array interfaces. --- ce166860ea51867004930efea92cb7c86178900f diff --combined mono/mini/aot-compiler.c index 32b0caa8802,cc8422f06f4..91b9b1c52b7 --- a/mono/mini/aot-compiler.c +++ b/mono/mini/aot-compiler.c @@@ -3144,8 -3144,7 +3144,7 @@@ encode_method_ref (MonoAotCompile *acfg case MONO_WRAPPER_PROXY_ISINST: case MONO_WRAPPER_LDFLD: case MONO_WRAPPER_LDFLDA: - case MONO_WRAPPER_STFLD: - case MONO_WRAPPER_ISINST: { + case MONO_WRAPPER_STFLD: { g_assert (info); encode_klass_ref (acfg, info->d.proxy.klass, p, &p); break; @@@ -5847,7 -5846,6 +5846,7 @@@ encode_patch (MonoAotCompile *acfg, Mon break; case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG: case MONO_PATCH_INFO_GET_TLS_TRAMP: + case MONO_PATCH_INFO_JIT_THREAD_ATTACH: break; default: g_warning ("unable to handle jump info %d", patch_info->type); @@@ -7273,7 -7271,6 +7272,6 @@@ can_encode_method (MonoAotCompile *acfg case MONO_WRAPPER_LDFLD: case MONO_WRAPPER_LDFLDA: case MONO_WRAPPER_STELEMREF: - case MONO_WRAPPER_ISINST: case MONO_WRAPPER_PROXY_ISINST: case MONO_WRAPPER_ALLOC: case MONO_WRAPPER_REMOTING_INVOKE: @@@ -7645,7 -7642,7 +7643,7 @@@ compile_method (MonoAotCompile *acfg, M * encountered. */ depth = GPOINTER_TO_UINT (g_hash_table_lookup (acfg->method_depth, method)); - if (!acfg->aot_opts.no_instances && depth < 32) { + if (!acfg->aot_opts.no_instances && depth < 32 && mono_aot_mode_is_full (&acfg->aot_opts)) { for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next) { switch (patch_info->type) { case MONO_PATCH_INFO_RGCTX_FETCH: @@@ -7664,7 -7661,7 +7662,7 @@@ if (!m) break; - if (m->is_inflated) { + if (m->is_inflated && mono_aot_mode_is_full (&acfg->aot_opts)) { if (!(mono_class_generic_sharing_enabled (m->klass) && mono_method_is_generic_sharable_full (m, FALSE, FALSE, FALSE)) && (!method_has_type_vars (m) || mono_method_is_generic_sharable_full (m, TRUE, TRUE, FALSE))) { @@@ -9869,8 -9866,7 +9867,8 @@@ collect_methods (MonoAotCompile *acfg } } - add_generic_instances (acfg); + if (mono_aot_mode_is_full (&acfg->aot_opts)) + add_generic_instances (acfg); if (mono_aot_mode_is_full (&acfg->aot_opts)) add_wrappers (acfg); @@@ -9925,7 -9921,7 +9923,7 @@@ compile_methods (MonoAotCompile *acfg g_free (methods); for (i = 0; i < threads->len; ++i) { - mono_thread_info_wait_one_handle (g_ptr_array_index (threads, i), INFINITE, FALSE); + mono_thread_info_wait_one_handle (g_ptr_array_index (threads, i), MONO_INFINITE_WAIT, FALSE); mono_threads_close_thread_handle (g_ptr_array_index (threads, i)); } } else { @@@ -10499,11 -10495,6 +10497,11 @@@ add_preinit_got_slots (MonoAotCompile * get_got_offset (acfg, FALSE, ji); get_got_offset (acfg, TRUE, ji); + ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoJumpInfo)); + ji->type = MONO_PATCH_INFO_JIT_THREAD_ATTACH; + get_got_offset (acfg, FALSE, ji); + get_got_offset (acfg, TRUE, ji); + for (i = 0; i < sizeof (preinited_jit_icalls) / sizeof (char*); ++i) { ji = (MonoJumpInfo *)mono_mempool_alloc0 (acfg->mempool, sizeof (MonoAotCompile)); ji->type = MONO_PATCH_INFO_INTERNAL_METHOD; diff --combined mono/mini/aot-runtime.c index 7d9a9114dbb,9be49e9773c..d479dfeec89 --- a/mono/mini/aot-runtime.c +++ b/mono/mini/aot-runtime.c @@@ -903,8 -903,7 +903,7 @@@ decode_method_ref_with_target (MonoAotM } case MONO_WRAPPER_LDFLD: case MONO_WRAPPER_LDFLDA: - case MONO_WRAPPER_STFLD: - case MONO_WRAPPER_ISINST: { + case MONO_WRAPPER_STFLD: { MonoClass *klass = decode_klass_ref (module, p, &p, error); if (!klass) return FALSE; @@@ -914,8 -913,6 +913,6 @@@ ref->method = mono_marshal_get_ldflda_wrapper (&klass->byval_arg); else if (wrapper_type == MONO_WRAPPER_STFLD) ref->method = mono_marshal_get_stfld_wrapper (&klass->byval_arg); - else if (wrapper_type == MONO_WRAPPER_ISINST) - ref->method = mono_marshal_get_isinst (klass); else { mono_error_set_bad_image_name (error, module->aot_name, "Unknown AOT wrapper type %d", wrapper_type); return FALSE; @@@ -3703,7 -3700,6 +3700,7 @@@ decode_patch (MonoAotModule *aot_module } case MONO_PATCH_INFO_GC_SAFE_POINT_FLAG: case MONO_PATCH_INFO_GET_TLS_TRAMP: + case MONO_PATCH_INFO_JIT_THREAD_ATTACH: break; case MONO_PATCH_INFO_AOT_JIT_INFO: ji->data.index = decode_value (p, &p); diff --combined mono/mini/method-to-ir.c index 87a0974d0d6,cada92ac7bc..1b82009833f --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@@ -156,7 -156,6 +156,7 @@@ emit_llvmonly_virtual_call (MonoCompil 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) @@@ -368,7 -367,6 +368,7 @@@ mono_create_helper_signatures (void 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 @@@ -1574,267 -1572,10 +1574,10 @@@ emit_runtime_constant (MonoCompile *cfg return ins; } - static void - mini_emit_interface_bitmap_check (MonoCompile *cfg, int intf_bit_reg, int base_reg, int offset, MonoClass *klass) - { - int ibitmap_reg = alloc_preg (cfg); - #ifdef COMPRESSED_INTERFACE_BITMAP - MonoInst *args [2]; - MonoInst *res, *ins; - NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, ibitmap_reg, base_reg, offset); - MONO_ADD_INS (cfg->cbb, ins); - args [0] = ins; - args [1] = emit_runtime_constant (cfg, MONO_PATCH_INFO_IID, klass); - res = mono_emit_jit_icall (cfg, mono_class_interface_match, args); - MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, intf_bit_reg, res->dreg); - #else - int ibitmap_byte_reg = alloc_preg (cfg); - - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, ibitmap_reg, base_reg, offset); - - if (cfg->compile_aot) { - int iid_reg = alloc_preg (cfg); - int shifted_iid_reg = alloc_preg (cfg); - int ibitmap_byte_address_reg = alloc_preg (cfg); - int masked_iid_reg = alloc_preg (cfg); - int iid_one_bit_reg = alloc_preg (cfg); - int iid_bit_reg = alloc_preg (cfg); - MONO_EMIT_NEW_AOTCONST (cfg, iid_reg, klass, MONO_PATCH_INFO_IID); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_SHR_IMM, shifted_iid_reg, iid_reg, 3); - MONO_EMIT_NEW_BIALU (cfg, OP_PADD, ibitmap_byte_address_reg, ibitmap_reg, shifted_iid_reg); - MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU1_MEMBASE, ibitmap_byte_reg, ibitmap_byte_address_reg, 0); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_IAND_IMM, masked_iid_reg, iid_reg, 7); - MONO_EMIT_NEW_ICONST (cfg, iid_one_bit_reg, 1); - MONO_EMIT_NEW_BIALU (cfg, OP_ISHL, iid_bit_reg, iid_one_bit_reg, masked_iid_reg); - MONO_EMIT_NEW_BIALU (cfg, OP_IAND, intf_bit_reg, ibitmap_byte_reg, iid_bit_reg); - } else { - MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADI1_MEMBASE, ibitmap_byte_reg, ibitmap_reg, klass->interface_id >> 3); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_AND_IMM, intf_bit_reg, ibitmap_byte_reg, 1 << (klass->interface_id & 7)); - } - #endif - } - - /* - * Emit code which loads into "intf_bit_reg" a nonzero value if the MonoClass - * stored in "klass_reg" implements the interface "klass". - */ - static void - mini_emit_load_intf_bit_reg_class (MonoCompile *cfg, int intf_bit_reg, int klass_reg, MonoClass *klass) - { - mini_emit_interface_bitmap_check (cfg, intf_bit_reg, klass_reg, MONO_STRUCT_OFFSET (MonoClass, interface_bitmap), klass); - } - - /* - * Emit code which loads into "intf_bit_reg" a nonzero value if the MonoVTable - * stored in "vtable_reg" implements the interface "klass". - */ - static void - mini_emit_load_intf_bit_reg_vtable (MonoCompile *cfg, int intf_bit_reg, int vtable_reg, MonoClass *klass) - { - mini_emit_interface_bitmap_check (cfg, intf_bit_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, interface_bitmap), klass); - } - - /* - * Emit code which checks whenever the interface id of @klass is smaller than - * than the value given by max_iid_reg. - */ - static void - mini_emit_max_iid_check (MonoCompile *cfg, int max_iid_reg, MonoClass *klass, - MonoBasicBlock *false_target) - { - if (cfg->compile_aot) { - int iid_reg = alloc_preg (cfg); - MONO_EMIT_NEW_AOTCONST (cfg, iid_reg, klass, MONO_PATCH_INFO_IID); - MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, max_iid_reg, iid_reg); - } - else - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, max_iid_reg, klass->interface_id); - if (false_target) - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBLT_UN, false_target); - else - MONO_EMIT_NEW_COND_EXC (cfg, LT_UN, "InvalidCastException"); - } - - /* Same as above, but obtains max_iid from a vtable */ - static void - mini_emit_max_iid_check_vtable (MonoCompile *cfg, int vtable_reg, MonoClass *klass, - MonoBasicBlock *false_target) - { - int max_iid_reg = alloc_preg (cfg); - - MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU4_MEMBASE, max_iid_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, max_interface_id)); - mini_emit_max_iid_check (cfg, max_iid_reg, klass, false_target); - } - - /* Same as above, but obtains max_iid from a klass */ - static void - mini_emit_max_iid_check_class (MonoCompile *cfg, int klass_reg, MonoClass *klass, - MonoBasicBlock *false_target) - { - int max_iid_reg = alloc_preg (cfg); - - MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU4_MEMBASE, max_iid_reg, klass_reg, MONO_STRUCT_OFFSET (MonoClass, max_interface_id)); - mini_emit_max_iid_check (cfg, max_iid_reg, klass, false_target); - } - - static void - mini_emit_isninst_cast_inst (MonoCompile *cfg, int klass_reg, MonoClass *klass, MonoInst *klass_ins, MonoBasicBlock *false_target, MonoBasicBlock *true_target) - { - int idepth_reg = alloc_preg (cfg); - int stypes_reg = alloc_preg (cfg); - int stype = alloc_preg (cfg); - - mono_class_setup_supertypes (klass); - - if (klass->idepth > MONO_DEFAULT_SUPERTABLE_SIZE) { - MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU2_MEMBASE, idepth_reg, klass_reg, MONO_STRUCT_OFFSET (MonoClass, idepth)); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, idepth_reg, klass->idepth); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBLT_UN, false_target); - } - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, stypes_reg, klass_reg, MONO_STRUCT_OFFSET (MonoClass, supertypes)); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, stype, stypes_reg, ((klass->idepth - 1) * SIZEOF_VOID_P)); - if (klass_ins) { - MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, stype, klass_ins->dreg); - } else if (cfg->compile_aot) { - int const_reg = alloc_preg (cfg); - MONO_EMIT_NEW_CLASSCONST (cfg, const_reg, klass); - MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, stype, const_reg); - } else { - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, stype, klass); - } - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, true_target); - } - - static void - mini_emit_isninst_cast (MonoCompile *cfg, int klass_reg, MonoClass *klass, MonoBasicBlock *false_target, MonoBasicBlock *true_target) - { - mini_emit_isninst_cast_inst (cfg, klass_reg, klass, NULL, false_target, true_target); - } - - static void - mini_emit_iface_cast (MonoCompile *cfg, int vtable_reg, MonoClass *klass, MonoBasicBlock *false_target, MonoBasicBlock *true_target) - { - int intf_reg = alloc_preg (cfg); - - mini_emit_max_iid_check_vtable (cfg, vtable_reg, klass, false_target); - mini_emit_load_intf_bit_reg_vtable (cfg, intf_reg, vtable_reg, klass); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, intf_reg, 0); - if (true_target) - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, true_target); - else - MONO_EMIT_NEW_COND_EXC (cfg, EQ, "InvalidCastException"); - } - - /* - * Variant of the above that takes a register to the class, not the vtable. - */ - static void - mini_emit_iface_class_cast (MonoCompile *cfg, int klass_reg, MonoClass *klass, MonoBasicBlock *false_target, MonoBasicBlock *true_target) - { - int intf_bit_reg = alloc_preg (cfg); - - mini_emit_max_iid_check_class (cfg, klass_reg, klass, false_target); - mini_emit_load_intf_bit_reg_class (cfg, intf_bit_reg, klass_reg, klass); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, intf_bit_reg, 0); - if (true_target) - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, true_target); - else - MONO_EMIT_NEW_COND_EXC (cfg, EQ, "InvalidCastException"); - } - - static inline void - mini_emit_class_check_inst (MonoCompile *cfg, int klass_reg, MonoClass *klass, MonoInst *klass_inst) - { - if (klass_inst) { - MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, klass_reg, klass_inst->dreg); - } else { - MonoInst *ins = emit_runtime_constant (cfg, MONO_PATCH_INFO_CLASS, klass); - MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, klass_reg, ins->dreg); - } - MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "InvalidCastException"); - } - - static inline void - mini_emit_class_check (MonoCompile *cfg, int klass_reg, MonoClass *klass) - { - mini_emit_class_check_inst (cfg, klass_reg, klass, NULL); - } - - static inline void - mini_emit_class_check_branch (MonoCompile *cfg, int klass_reg, MonoClass *klass, int branch_op, MonoBasicBlock *target) - { - if (cfg->compile_aot) { - int const_reg = alloc_preg (cfg); - MONO_EMIT_NEW_CLASSCONST (cfg, const_reg, klass); - MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, klass_reg, const_reg); - } else { - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, klass_reg, klass); - } - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, branch_op, target); - } - - static void - mini_emit_castclass (MonoCompile *cfg, int obj_reg, int klass_reg, MonoClass *klass, MonoBasicBlock *object_is_null); - - static void - mini_emit_castclass_inst (MonoCompile *cfg, int obj_reg, int klass_reg, MonoClass *klass, MonoInst *klass_inst, MonoBasicBlock *object_is_null) - { - if (klass->rank) { - int rank_reg = alloc_preg (cfg); - int eclass_reg = alloc_preg (cfg); - - g_assert (!klass_inst); - MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU1_MEMBASE, rank_reg, klass_reg, MONO_STRUCT_OFFSET (MonoClass, rank)); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, rank_reg, klass->rank); - MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "InvalidCastException"); - // MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, klass)); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, eclass_reg, klass_reg, MONO_STRUCT_OFFSET (MonoClass, cast_class)); - if (klass->cast_class == mono_defaults.object_class) { - int parent_reg = alloc_preg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, parent_reg, eclass_reg, MONO_STRUCT_OFFSET (MonoClass, parent)); - mini_emit_class_check_branch (cfg, parent_reg, mono_defaults.enum_class->parent, OP_PBNE_UN, object_is_null); - mini_emit_class_check (cfg, eclass_reg, mono_defaults.enum_class); - } else if (klass->cast_class == mono_defaults.enum_class->parent) { - mini_emit_class_check_branch (cfg, eclass_reg, mono_defaults.enum_class->parent, OP_PBEQ, object_is_null); - mini_emit_class_check (cfg, eclass_reg, mono_defaults.enum_class); - } else if (klass->cast_class == mono_defaults.enum_class) { - mini_emit_class_check (cfg, eclass_reg, mono_defaults.enum_class); - } else if (mono_class_is_interface (klass->cast_class)) { - mini_emit_iface_class_cast (cfg, eclass_reg, klass->cast_class, NULL, NULL); - } else { - // Pass -1 as obj_reg to skip the check below for arrays of arrays - mini_emit_castclass (cfg, -1, eclass_reg, klass->cast_class, object_is_null); - } - - if ((klass->rank == 1) && (klass->byval_arg.type == MONO_TYPE_SZARRAY) && (obj_reg != -1)) { - /* Check that the object is a vector too */ - int bounds_reg = alloc_preg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, bounds_reg, obj_reg, MONO_STRUCT_OFFSET (MonoArray, bounds)); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, bounds_reg, 0); - MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "InvalidCastException"); - } - } else { - int idepth_reg = alloc_preg (cfg); - int stypes_reg = alloc_preg (cfg); - int stype = alloc_preg (cfg); - - mono_class_setup_supertypes (klass); - - if (klass->idepth > MONO_DEFAULT_SUPERTABLE_SIZE) { - MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU2_MEMBASE, idepth_reg, klass_reg, MONO_STRUCT_OFFSET (MonoClass, idepth)); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, idepth_reg, klass->idepth); - MONO_EMIT_NEW_COND_EXC (cfg, LT_UN, "InvalidCastException"); - } - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, stypes_reg, klass_reg, MONO_STRUCT_OFFSET (MonoClass, supertypes)); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, stype, stypes_reg, ((klass->idepth - 1) * SIZEOF_VOID_P)); - mini_emit_class_check_inst (cfg, stype, klass, klass_inst); - } - } - - static void - mini_emit_castclass (MonoCompile *cfg, int obj_reg, int klass_reg, MonoClass *klass, MonoBasicBlock *object_is_null) + MonoInst* + mini_emit_runtime_constant (MonoCompile *cfg, MonoJumpInfoType patch_type, gpointer data) { - mini_emit_castclass_inst (cfg, obj_reg, klass_reg, klass, NULL, object_is_null); + return emit_runtime_constant (cfg, patch_type, data); } static void @@@ -2775,8 -2516,6 +2518,6 @@@ emit_get_gsharedvt_info_klass (MonoComp static MonoInst* emit_get_rgctx_method (MonoCompile *cfg, int context_used, MonoMethod *cmethod, MonoRgctxInfoType rgctx_type); - static MonoInst* - emit_get_rgctx_klass (MonoCompile *cfg, int context_used, MonoClass *klass, MonoRgctxInfoType rgctx_type); static MonoInst* mono_emit_method_call_full (MonoCompile *cfg, MonoMethod *method, MonoMethodSignature *sig, gboolean tail, @@@ -3399,7 -3138,7 +3140,7 @@@ mini_emit_stobj (MonoCompile *cfg, Mono if (!size_ins && (cfg->opt & MONO_OPT_INTRINS) && mono_emit_wb_aware_memcpy (cfg, klass, iargs, n, align)) { return; } else if (context_used) { - iargs [2] = emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS); + iargs [2] = mini_emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS); } else { iargs [2] = emit_runtime_constant (cfg, MONO_PATCH_INFO_CLASS, klass); if (!cfg->compile_aot) @@@ -3501,8 -3240,8 +3242,8 @@@ emit_get_rgctx (MonoCompile *cfg, MonoM 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; @@@ -3679,12 -3418,12 +3420,12 @@@ emit_rgctx_fetch (MonoCompile *cfg, Mon return mono_emit_abs_call (cfg, MONO_PATCH_INFO_RGCTX_FETCH, entry, helper_sig_rgctx_lazy_fetch_trampoline, &rgctx); } - static MonoInst* - emit_get_rgctx_klass (MonoCompile *cfg, int context_used, + MonoInst* + mini_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); } @@@ -3693,8 -3432,8 +3434,8 @@@ static MonoInst 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); } @@@ -3711,8 -3450,8 +3452,8 @@@ emit_get_rgctx_gsharedvt_call (MonoComp 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); } @@@ -3734,8 -3473,8 +3475,8 @@@ emit_get_rgctx_virt_method (MonoCompil 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); } @@@ -3747,8 -3486,8 +3488,8 @@@ emit_get_rgctx_gsharedvt_method (MonoCo 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); } @@@ -3777,8 -3516,8 +3518,8 @@@ emit_get_rgctx_method (MonoCompile *cfg 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); } @@@ -3788,8 -3527,8 +3529,8 @@@ static MonoInst 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); } @@@ -3868,7 -3607,7 +3609,7 @@@ emit_class_init (MonoCompile *cfg, Mono context_used = mini_class_check_context_used (cfg, klass); if (context_used) { - vtable_arg = emit_get_rgctx_klass (cfg, context_used, + vtable_arg = mini_emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_VTABLE); } else { MonoVTable *vtable = mono_class_vtable (cfg->domain, klass); @@@ -3929,8 -3668,8 +3670,8 @@@ emit_seq_point (MonoCompile *cfg, MonoM } } - static void - save_cast_details (MonoCompile *cfg, MonoClass *klass, int obj_reg, gboolean null_check) + void + mini_save_cast_details (MonoCompile *cfg, MonoClass *klass, int obj_reg, gboolean null_check) { if (mini_get_debug_options ()->better_cast_details) { int vtable_reg = alloc_preg (cfg); @@@ -3962,7 -3701,7 +3703,7 @@@ if (context_used) { MonoInst *class_ins; - class_ins = emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS); + class_ins = mini_emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS); to_klass_reg = class_ins->dreg; } else { to_klass_reg = alloc_preg (cfg); @@@ -3975,8 -3714,8 +3716,8 @@@ } } - static void - reset_cast_details (MonoCompile *cfg) + void + mini_reset_cast_details (MonoCompile *cfg) { /* Reset the variables holding the cast details */ if (mini_get_debug_options ()->better_cast_details) { @@@ -3999,7 -3738,7 +3740,7 @@@ mini_emit_check_array_type (MonoCompil context_used = mini_class_check_context_used (cfg, array_class); - save_cast_details (cfg, array_class, obj->dreg, FALSE); + mini_save_cast_details (cfg, array_class, obj->dreg, FALSE); MONO_EMIT_NEW_LOAD_MEMBASE_FAULT (cfg, vtable_reg, obj->dreg, MONO_STRUCT_OFFSET (MonoObject, vtable)); @@@ -4013,7 -3752,7 +3754,7 @@@ } else if (context_used) { MonoInst *vtable_ins; - vtable_ins = emit_get_rgctx_klass (cfg, context_used, array_class, MONO_RGCTX_INFO_VTABLE); + vtable_ins = mini_emit_get_rgctx_klass (cfg, context_used, array_class, MONO_RGCTX_INFO_VTABLE); MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, vtable_reg, vtable_ins->dreg); } else { if (cfg->compile_aot) { @@@ -4035,7 -3774,7 +3776,7 @@@ MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "ArrayTypeMismatchException"); - reset_cast_details (cfg); + mini_reset_cast_details (cfg); } /** @@@ -4059,7 -3798,7 +3800,7 @@@ handle_unbox_nullable (MonoCompile* cfg 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); } @@@ -4111,15 -3850,15 +3852,15 @@@ handle_unbox (MonoCompile *cfg, MonoCla /* This assertion is from the unboxcast insn */ g_assert (klass->rank == 0); - element_class = emit_get_rgctx_klass (cfg, context_used, + element_class = mini_emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_ELEMENT_KLASS); MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, eclass_reg, element_class->dreg); MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "InvalidCastException"); } else { - save_cast_details (cfg, klass->element_class, obj_reg, FALSE); + mini_save_cast_details (cfg, klass->element_class, obj_reg, FALSE); mini_emit_class_check (cfg, eclass_reg, klass->element_class); - reset_cast_details (cfg); + mini_reset_cast_details (cfg); } NEW_BIALU_IMM (cfg, add, OP_ADD_IMM, alloc_dreg (cfg, STACK_MP), obj_reg, sizeof (MonoObject)); @@@ -4233,7 -3972,7 +3974,7 @@@ handle_alloc (MonoCompile *cfg, MonoCla rgctx_info = MONO_RGCTX_INFO_KLASS; else rgctx_info = MONO_RGCTX_INFO_VTABLE; - data = emit_get_rgctx_klass (cfg, context_used, klass, rgctx_info); + data = mini_emit_get_rgctx_klass (cfg, context_used, klass, rgctx_info); if (cfg->opt & MONO_OPT_SHARED) { EMIT_NEW_DOMAINCONST (cfg, iargs [0]); @@@ -4326,7 -4065,7 +4067,7 @@@ handle_box (MonoCompile *cfg, MonoInst 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); } @@@ -4430,34 -4169,6 +4171,6 @@@ } } - static gboolean - mini_class_has_reference_variant_generic_argument (MonoCompile *cfg, MonoClass *klass, int context_used) - { - int i; - MonoGenericContainer *container; - MonoGenericInst *ginst; - - if (mono_class_is_ginst (klass)) { - container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class); - ginst = mono_class_get_generic_class (klass)->context.class_inst; - } else if (mono_class_is_gtd (klass) && context_used) { - container = mono_class_get_generic_container (klass); - ginst = container->context.class_inst; - } else { - return FALSE; - } - - for (i = 0; i < container->type_argc; ++i) { - MonoType *type; - if (!(mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))) - continue; - type = ginst->type_argv [i]; - if (mini_type_is_reference (type)) - return TRUE; - } - return FALSE; - } - static GHashTable* direct_icall_type_hash; static gboolean @@@ -4500,493 -4211,6 +4213,6 @@@ method_needs_stack_walk (MonoCompile *c return FALSE; } - #define is_complex_isinst(klass) (mono_class_is_interface (klass) || klass->rank || mono_class_is_nullable (klass) || mono_class_is_marshalbyref (klass) || mono_class_is_sealed (klass) || klass->byval_arg.type == MONO_TYPE_VAR || klass->byval_arg.type == MONO_TYPE_MVAR) - - static MonoInst* - emit_isinst_with_cache (MonoCompile *cfg, MonoClass *klass, MonoInst **args) - { - MonoMethod *mono_isinst = mono_marshal_get_isinst_with_cache (); - return mono_emit_method_call (cfg, mono_isinst, args, NULL); - } - - static MonoInst* - emit_castclass_with_cache (MonoCompile *cfg, MonoClass *klass, MonoInst **args) - { - MonoMethod *mono_castclass = mono_marshal_get_castclass_with_cache (); - MonoInst *res; - - save_cast_details (cfg, klass, args [0]->dreg, TRUE); - res = mono_emit_method_call (cfg, mono_castclass, args, NULL); - reset_cast_details (cfg); - - return res; - } - - static int - get_castclass_cache_idx (MonoCompile *cfg) - { - /* Each CASTCLASS_CACHE patch needs a unique index which identifies the call site */ - cfg->castclass_cache_index ++; - return (cfg->method_index << 16) | cfg->castclass_cache_index; - } - - - static MonoInst* - emit_isinst_with_cache_nonshared (MonoCompile *cfg, MonoInst *obj, MonoClass *klass) - { - MonoInst *args [3]; - int idx; - - args [0] = obj; /* obj */ - EMIT_NEW_CLASSCONST (cfg, args [1], klass); /* klass */ - - idx = get_castclass_cache_idx (cfg); /* inline cache*/ - args [2] = emit_runtime_constant (cfg, MONO_PATCH_INFO_CASTCLASS_CACHE, GINT_TO_POINTER (idx)); - - return emit_isinst_with_cache (cfg, klass, args); - } - - static MonoInst* - emit_castclass_with_cache_nonshared (MonoCompile *cfg, MonoInst *obj, MonoClass *klass) - { - MonoInst *args [3]; - int idx; - - /* obj */ - args [0] = obj; - - /* klass */ - EMIT_NEW_CLASSCONST (cfg, args [1], klass); - - /* inline cache*/ - idx = get_castclass_cache_idx (cfg); - args [2] = emit_runtime_constant (cfg, MONO_PATCH_INFO_CASTCLASS_CACHE, GINT_TO_POINTER (idx)); - - /*The wrapper doesn't inline well so the bloat of inlining doesn't pay off.*/ - return emit_castclass_with_cache (cfg, klass, args); - } - - /* - * Returns NULL and set the cfg exception on error. - */ - static MonoInst* - handle_castclass (MonoCompile *cfg, MonoClass *klass, MonoInst *src, int context_used) - { - MonoBasicBlock *is_null_bb; - int obj_reg = src->dreg; - int vtable_reg = alloc_preg (cfg); - MonoInst *klass_inst = NULL; - - if (MONO_INS_IS_PCONST_NULL (src)) - return src; - - if (context_used) { - MonoInst *args [3]; - - if (mini_class_has_reference_variant_generic_argument (cfg, klass, context_used) || is_complex_isinst (klass)) { - MonoInst *cache_ins; - - cache_ins = emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_CAST_CACHE); - - /* obj */ - args [0] = src; - - /* klass - it's the second element of the cache entry*/ - EMIT_NEW_LOAD_MEMBASE (cfg, args [1], OP_LOAD_MEMBASE, alloc_preg (cfg), cache_ins->dreg, sizeof (gpointer)); - - /* cache */ - args [2] = cache_ins; - - return emit_castclass_with_cache (cfg, klass, args); - } - - klass_inst = emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS); - } - - NEW_BBLOCK (cfg, is_null_bb); - - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, obj_reg, 0); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, is_null_bb); - - save_cast_details (cfg, klass, obj_reg, FALSE); - - if (mono_class_is_interface (klass)) { - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable)); - mini_emit_iface_cast (cfg, vtable_reg, klass, NULL, NULL); - } else { - int klass_reg = alloc_preg (cfg); - - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable)); - - if (!klass->rank && !cfg->compile_aot && !(cfg->opt & MONO_OPT_SHARED) && mono_class_is_sealed (klass)) { - /* the remoting code is broken, access the class for now */ - if (0) { /*FIXME what exactly is broken? This change refers to r39380 from 2005 and mention some remoting fixes were due.*/ - MonoVTable *vt = mono_class_vtable (cfg->domain, klass); - if (!vt) { - mono_cfg_set_exception (cfg, MONO_EXCEPTION_TYPE_LOAD); - cfg->exception_ptr = klass; - return NULL; - } - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, vtable_reg, vt); - } else { - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, klass)); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, klass_reg, klass); - } - MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "InvalidCastException"); - } else { - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, klass)); - mini_emit_castclass_inst (cfg, obj_reg, klass_reg, klass, klass_inst, is_null_bb); - } - } - - MONO_START_BB (cfg, is_null_bb); - - reset_cast_details (cfg); - - return src; - } - - /* - * Returns NULL and set the cfg exception on error. - */ - static MonoInst* - handle_isinst (MonoCompile *cfg, MonoClass *klass, MonoInst *src, int context_used) - { - MonoInst *ins; - MonoBasicBlock *is_null_bb, *false_bb, *end_bb; - int obj_reg = src->dreg; - int vtable_reg = alloc_preg (cfg); - int res_reg = alloc_ireg_ref (cfg); - MonoInst *klass_inst = NULL; - - if (context_used) { - MonoInst *args [3]; - - if(mini_class_has_reference_variant_generic_argument (cfg, klass, context_used) || is_complex_isinst (klass)) { - MonoInst *cache_ins = emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_CAST_CACHE); - - args [0] = src; /* obj */ - - /* klass - it's the second element of the cache entry*/ - EMIT_NEW_LOAD_MEMBASE (cfg, args [1], OP_LOAD_MEMBASE, alloc_preg (cfg), cache_ins->dreg, sizeof (gpointer)); - - args [2] = cache_ins; /* cache */ - return emit_isinst_with_cache (cfg, klass, args); - } - - klass_inst = emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS); - } - - NEW_BBLOCK (cfg, is_null_bb); - NEW_BBLOCK (cfg, false_bb); - NEW_BBLOCK (cfg, end_bb); - - /* Do the assignment at the beginning, so the other assignment can be if converted */ - EMIT_NEW_UNALU (cfg, ins, OP_MOVE, res_reg, obj_reg); - ins->type = STACK_OBJ; - ins->klass = klass; - - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, obj_reg, 0); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_IBEQ, is_null_bb); - - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, vtable_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable)); - - if (mono_class_is_interface (klass)) { - g_assert (!context_used); - /* the is_null_bb target simply copies the input register to the output */ - mini_emit_iface_cast (cfg, vtable_reg, klass, false_bb, is_null_bb); - } else { - int klass_reg = alloc_preg (cfg); - - if (klass->rank) { - int rank_reg = alloc_preg (cfg); - int eclass_reg = alloc_preg (cfg); - - g_assert (!context_used); - MONO_EMIT_NEW_LOAD_MEMBASE_OP (cfg, OP_LOADU1_MEMBASE, rank_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, rank)); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, rank_reg, klass->rank); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, false_bb); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, klass)); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, eclass_reg, klass_reg, MONO_STRUCT_OFFSET (MonoClass, cast_class)); - if (klass->cast_class == mono_defaults.object_class) { - int parent_reg = alloc_preg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, parent_reg, eclass_reg, MONO_STRUCT_OFFSET (MonoClass, parent)); - mini_emit_class_check_branch (cfg, parent_reg, mono_defaults.enum_class->parent, OP_PBNE_UN, is_null_bb); - mini_emit_class_check_branch (cfg, eclass_reg, mono_defaults.enum_class, OP_PBEQ, is_null_bb); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, false_bb); - } else if (klass->cast_class == mono_defaults.enum_class->parent) { - mini_emit_class_check_branch (cfg, eclass_reg, mono_defaults.enum_class->parent, OP_PBEQ, is_null_bb); - mini_emit_class_check_branch (cfg, eclass_reg, mono_defaults.enum_class, OP_PBEQ, is_null_bb); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, false_bb); - } else if (klass->cast_class == mono_defaults.enum_class) { - mini_emit_class_check_branch (cfg, eclass_reg, mono_defaults.enum_class, OP_PBEQ, is_null_bb); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, false_bb); - } else if (mono_class_is_interface (klass->cast_class)) { - mini_emit_iface_class_cast (cfg, eclass_reg, klass->cast_class, false_bb, is_null_bb); - } else { - if ((klass->rank == 1) && (klass->byval_arg.type == MONO_TYPE_SZARRAY)) { - /* Check that the object is a vector too */ - int bounds_reg = alloc_preg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, bounds_reg, obj_reg, MONO_STRUCT_OFFSET (MonoArray, bounds)); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, bounds_reg, 0); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, false_bb); - } - - /* the is_null_bb target simply copies the input register to the output */ - mini_emit_isninst_cast (cfg, eclass_reg, klass->cast_class, false_bb, is_null_bb); - } - } else if (mono_class_is_nullable (klass)) { - g_assert (!context_used); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, klass)); - /* the is_null_bb target simply copies the input register to the output */ - mini_emit_isninst_cast (cfg, klass_reg, klass->cast_class, false_bb, is_null_bb); - } else { - if (!cfg->compile_aot && !(cfg->opt & MONO_OPT_SHARED) && mono_class_is_sealed (klass)) { - g_assert (!context_used); - /* the remoting code is broken, access the class for now */ - if (0) {/*FIXME what exactly is broken? This change refers to r39380 from 2005 and mention some remoting fixes were due.*/ - MonoVTable *vt = mono_class_vtable (cfg->domain, klass); - if (!vt) { - mono_cfg_set_exception (cfg, MONO_EXCEPTION_TYPE_LOAD); - cfg->exception_ptr = klass; - return NULL; - } - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, vtable_reg, vt); - } else { - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, klass)); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, klass_reg, klass); - } - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, false_bb); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, is_null_bb); - } else { - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, vtable_reg, MONO_STRUCT_OFFSET (MonoVTable, klass)); - /* the is_null_bb target simply copies the input register to the output */ - mini_emit_isninst_cast_inst (cfg, klass_reg, klass, klass_inst, false_bb, is_null_bb); - } - } - } - - MONO_START_BB (cfg, false_bb); - - MONO_EMIT_NEW_PCONST (cfg, res_reg, 0); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb); - - MONO_START_BB (cfg, is_null_bb); - - MONO_START_BB (cfg, end_bb); - - return ins; - } - - static MonoInst* - handle_cisinst (MonoCompile *cfg, MonoClass *klass, MonoInst *src) - { - /* This opcode takes as input an object reference and a class, and returns: - 0) if the object is an instance of the class, - 1) if the object is not instance of the class, - 2) if the object is a proxy whose type cannot be determined */ - - MonoInst *ins; - #ifndef DISABLE_REMOTING - MonoBasicBlock *true_bb, *false_bb, *false2_bb, *end_bb, *no_proxy_bb, *interface_fail_bb; - #else - MonoBasicBlock *true_bb, *false_bb, *end_bb; - #endif - int obj_reg = src->dreg; - int dreg = alloc_ireg (cfg); - int tmp_reg; - #ifndef DISABLE_REMOTING - int klass_reg = alloc_preg (cfg); - #endif - - NEW_BBLOCK (cfg, true_bb); - NEW_BBLOCK (cfg, false_bb); - NEW_BBLOCK (cfg, end_bb); - #ifndef DISABLE_REMOTING - NEW_BBLOCK (cfg, false2_bb); - NEW_BBLOCK (cfg, no_proxy_bb); - #endif - - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, obj_reg, 0); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, false_bb); - - if (mono_class_is_interface (klass)) { - #ifndef DISABLE_REMOTING - NEW_BBLOCK (cfg, interface_fail_bb); - #endif - - tmp_reg = alloc_preg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable)); - #ifndef DISABLE_REMOTING - mini_emit_iface_cast (cfg, tmp_reg, klass, interface_fail_bb, true_bb); - MONO_START_BB (cfg, interface_fail_bb); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, tmp_reg, MONO_STRUCT_OFFSET (MonoVTable, klass)); - - mini_emit_class_check_branch (cfg, klass_reg, mono_defaults.transparent_proxy_class, OP_PBNE_UN, false_bb); - - tmp_reg = alloc_preg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info)); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tmp_reg, 0); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBNE_UN, false2_bb); - #else - mini_emit_iface_cast (cfg, tmp_reg, klass, false_bb, true_bb); - #endif - } else { - #ifndef DISABLE_REMOTING - tmp_reg = alloc_preg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable)); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, tmp_reg, MONO_STRUCT_OFFSET (MonoVTable, klass)); - - mini_emit_class_check_branch (cfg, klass_reg, mono_defaults.transparent_proxy_class, OP_PBNE_UN, no_proxy_bb); - tmp_reg = alloc_preg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoTransparentProxy, remote_class)); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, tmp_reg, MONO_STRUCT_OFFSET (MonoRemoteClass, proxy_class)); - - tmp_reg = alloc_preg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info)); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tmp_reg, 0); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, no_proxy_bb); - - mini_emit_isninst_cast (cfg, klass_reg, klass, false2_bb, true_bb); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, false2_bb); - - MONO_START_BB (cfg, no_proxy_bb); - - mini_emit_isninst_cast (cfg, klass_reg, klass, false_bb, true_bb); - #else - g_error ("transparent proxy support is disabled while trying to JIT code that uses it"); - #endif - } - - MONO_START_BB (cfg, false_bb); - - MONO_EMIT_NEW_ICONST (cfg, dreg, 1); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb); - - #ifndef DISABLE_REMOTING - MONO_START_BB (cfg, false2_bb); - - MONO_EMIT_NEW_ICONST (cfg, dreg, 2); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb); - #endif - - MONO_START_BB (cfg, true_bb); - - MONO_EMIT_NEW_ICONST (cfg, dreg, 0); - - MONO_START_BB (cfg, end_bb); - - /* FIXME: */ - MONO_INST_NEW (cfg, ins, OP_ICONST); - ins->dreg = dreg; - ins->type = STACK_I4; - - return ins; - } - - static MonoInst* - handle_ccastclass (MonoCompile *cfg, MonoClass *klass, MonoInst *src) - { - /* This opcode takes as input an object reference and a class, and returns: - 0) if the object is an instance of the class, - 1) if the object is a proxy whose type cannot be determined - an InvalidCastException exception is thrown otherwhise*/ - - MonoInst *ins; - #ifndef DISABLE_REMOTING - MonoBasicBlock *end_bb, *ok_result_bb, *no_proxy_bb, *interface_fail_bb, *fail_1_bb; - #else - MonoBasicBlock *ok_result_bb; - #endif - int obj_reg = src->dreg; - int dreg = alloc_ireg (cfg); - int tmp_reg = alloc_preg (cfg); - - #ifndef DISABLE_REMOTING - int klass_reg = alloc_preg (cfg); - NEW_BBLOCK (cfg, end_bb); - #endif - - NEW_BBLOCK (cfg, ok_result_bb); - - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, obj_reg, 0); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, ok_result_bb); - - save_cast_details (cfg, klass, obj_reg, FALSE); - - if (mono_class_is_interface (klass)) { - #ifndef DISABLE_REMOTING - NEW_BBLOCK (cfg, interface_fail_bb); - - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable)); - mini_emit_iface_cast (cfg, tmp_reg, klass, interface_fail_bb, ok_result_bb); - MONO_START_BB (cfg, interface_fail_bb); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, tmp_reg, MONO_STRUCT_OFFSET (MonoVTable, klass)); - - mini_emit_class_check (cfg, klass_reg, mono_defaults.transparent_proxy_class); - - tmp_reg = alloc_preg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info)); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tmp_reg, 0); - MONO_EMIT_NEW_COND_EXC (cfg, EQ, "InvalidCastException"); - - MONO_EMIT_NEW_ICONST (cfg, dreg, 1); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb); - #else - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable)); - mini_emit_iface_cast (cfg, tmp_reg, klass, NULL, NULL); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, ok_result_bb); - #endif - } else { - #ifndef DISABLE_REMOTING - NEW_BBLOCK (cfg, no_proxy_bb); - - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoObject, vtable)); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, tmp_reg, MONO_STRUCT_OFFSET (MonoVTable, klass)); - mini_emit_class_check_branch (cfg, klass_reg, mono_defaults.transparent_proxy_class, OP_PBNE_UN, no_proxy_bb); - - tmp_reg = alloc_preg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoTransparentProxy, remote_class)); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, tmp_reg, MONO_STRUCT_OFFSET (MonoRemoteClass, proxy_class)); - - tmp_reg = alloc_preg (cfg); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, tmp_reg, obj_reg, MONO_STRUCT_OFFSET (MonoTransparentProxy, custom_type_info)); - MONO_EMIT_NEW_BIALU_IMM (cfg, OP_COMPARE_IMM, -1, tmp_reg, 0); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_PBEQ, no_proxy_bb); - - NEW_BBLOCK (cfg, fail_1_bb); - - mini_emit_isninst_cast (cfg, klass_reg, klass, fail_1_bb, ok_result_bb); - - MONO_START_BB (cfg, fail_1_bb); - - MONO_EMIT_NEW_ICONST (cfg, dreg, 1); - MONO_EMIT_NEW_BRANCH_BLOCK (cfg, OP_BR, end_bb); - - MONO_START_BB (cfg, no_proxy_bb); - - mini_emit_castclass (cfg, obj_reg, klass_reg, klass, ok_result_bb); - #else - g_error ("Transparent proxy support is disabled while trying to JIT code that uses it"); - #endif - } - - MONO_START_BB (cfg, ok_result_bb); - - MONO_EMIT_NEW_ICONST (cfg, dreg, 0); - - #ifndef DISABLE_REMOTING - MONO_START_BB (cfg, end_bb); - #endif - - /* FIXME: */ - MONO_INST_NEW (cfg, ins, OP_ICONST); - ins->dreg = dreg; - ins->type = STACK_I4; - - return ins; - } - static G_GNUC_UNUSED MonoInst* handle_enum_has_flag (MonoCompile *cfg, MonoClass *klass, MonoInst *enum_this, MonoInst *enum_flag) { @@@ -5209,7 -4433,7 +4435,7 @@@ handle_constrained_gsharedvt_call (Mono args [1] = emit_get_rgctx_method (cfg, mono_method_check_context_used (cmethod), cmethod, MONO_RGCTX_INFO_METHOD); else EMIT_NEW_METHODCONST (cfg, args [1], cmethod); - args [2] = emit_get_rgctx_klass (cfg, mono_class_check_context_used (constrained_class), constrained_class, MONO_RGCTX_INFO_KLASS); + args [2] = mini_emit_get_rgctx_klass (cfg, mono_class_check_context_used (constrained_class), constrained_class, MONO_RGCTX_INFO_KLASS); /* !fsig->hasthis is for the wrapper for the Object.GetType () icall */ if (fsig->hasthis && fsig->param_count) { @@@ -5317,7 -4541,7 +4543,7 @@@ mono_method_check_inlining (MonoCompil if (cfg->disable_inline) return FALSE; - if (cfg->gshared) + if (cfg->gsharedvt) return FALSE; if (cfg->inline_depth > 10) @@@ -5351,22 -4575,17 +4577,22 @@@ * 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)) { @@@ -7090,6 -6309,12 +6316,12 @@@ emit_init_local (MonoCompile *cfg, int } } + int + mini_inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **sp, guchar *ip, guint real_offset, gboolean inline_always) + { + return inline_method (cfg, cmethod, fsig, sp, ip, real_offset, inline_always); + } + /* * inline_method: * @@@ -7221,7 -6446,7 +6453,7 @@@ inline_method (MonoCompile *cfg, MonoMe 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 */ @@@ -8059,7 -7284,7 +7291,7 @@@ handle_ctor_call (MonoCompile *cfg, Mon cmethod, MONO_RGCTX_INFO_METHOD_RGCTX); } else { if (context_used) { - vtable_arg = emit_get_rgctx_klass (cfg, context_used, + vtable_arg = mini_emit_get_rgctx_klass (cfg, context_used, cmethod->klass, MONO_RGCTX_INFO_VTABLE); } else { MonoVTable *vtable = mono_class_vtable (cfg->domain, cmethod->klass); @@@ -9605,7 -8830,7 +8837,7 @@@ mono_method_to_ir (MonoCompile *cfg, Mo if (pass_vtable) { if (context_used) { - vtable_arg = emit_get_rgctx_klass (cfg, context_used, cmethod->klass, MONO_RGCTX_INFO_VTABLE); + vtable_arg = mini_emit_get_rgctx_klass (cfg, context_used, cmethod->klass, MONO_RGCTX_INFO_VTABLE); } else { MonoVTable *vtable = mono_class_vtable (cfg->domain, cmethod->klass); @@@ -11655,7 -10880,7 +10887,7 @@@ * * super_info.static_data + field->offset */ - static_data = emit_get_rgctx_klass (cfg, context_used, + static_data = mini_emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_STATIC_DATA); if (mini_is_gsharedvt_klass (klass)) { @@@ -11906,7 -11131,7 +11138,7 @@@ /* FIXME: Use OP_NEWARR and decompose later to help abcrem */ /* vtable */ - args [0] = emit_get_rgctx_klass (cfg, context_used, + args [0] = mini_emit_get_rgctx_klass (cfg, context_used, array_class, MONO_RGCTX_INFO_VTABLE); /* array len */ args [1] = sp [0]; @@@ -12162,7 -11387,7 +11394,7 @@@ if (context_used) { MonoInst *klass_ins; - klass_ins = emit_get_rgctx_klass (cfg, context_used, + klass_ins = mini_emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS); // FIXME: @@@ -12199,7 -11424,7 +11431,7 @@@ MonoInst *const_ins; int type_reg = alloc_preg (cfg); - const_ins = emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS); + const_ins = mini_emit_get_rgctx_klass (cfg, context_used, klass, MONO_RGCTX_INFO_KLASS); MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, addr->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, klass), const_ins->dreg); MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, type_reg, const_ins->dreg, MONO_STRUCT_OFFSET (MonoClass, byval_arg)); MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, addr->dreg, MONO_STRUCT_OFFSET (MonoTypedRef, type), type_reg); @@@ -12296,7 -11521,7 +11528,7 @@@ mono_class_init (tclass); if (context_used) { - ins = emit_get_rgctx_klass (cfg, context_used, + ins = mini_emit_get_rgctx_klass (cfg, context_used, tclass, MONO_RGCTX_INFO_REFLECTION_TYPE); } else if (cfg->compile_aot) { if (method->wrapper_type) { @@@ -12328,7 -11553,7 +11560,7 @@@ if (context_used) { if (handle_class == mono_defaults.typehandle_class) { - ins = emit_get_rgctx_klass (cfg, context_used, + ins = mini_emit_get_rgctx_klass (cfg, context_used, mono_class_from_mono_type ((MonoType *)handle), MONO_RGCTX_INFO_TYPE); } else if (handle_class == mono_defaults.methodhandle_class) { @@@ -12731,22 -11956,6 +11963,6 @@@ ip += 6; break; } - case CEE_MONO_CISINST: - case CEE_MONO_CCASTCLASS: { - int token; - CHECK_STACK (1); - --sp; - CHECK_OPSIZE (6); - token = read32 (ip + 2); - klass = (MonoClass *)mono_method_get_wrapper_data (method, token); - if (ip [1] == CEE_MONO_CISINST) - ins = handle_cisinst (cfg, klass, sp [0]); - else - ins = handle_ccastclass (cfg, klass, sp [0]); - *sp++ = ins; - ip += 6; - break; - } case CEE_MONO_SAVE_LMF: case CEE_MONO_RESTORE_LMF: ip += 2; @@@ -12879,24 -12088,13 +12095,24 @@@ /* 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; } @@@ -15153,73 -14351,6 +14369,6 @@@ mono_spill_global_vars (MonoCompile *cf g_free (live_range_end_bb); } - static void - mono_decompose_typecheck (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins) - { - MonoInst *ret, *move, *source; - MonoClass *klass = ins->klass; - int context_used = mini_class_check_context_used (cfg, klass); - int is_isinst = ins->opcode == OP_ISINST; - g_assert (is_isinst || ins->opcode == OP_CASTCLASS); - source = get_vreg_to_inst (cfg, ins->sreg1); - if (!source || source == (MonoInst *) -1) - source = mono_compile_create_var_for_vreg (cfg, &mono_defaults.object_class->byval_arg, OP_LOCAL, ins->sreg1); - g_assert (source && source != (MonoInst *) -1); - - MonoBasicBlock *first_bb; - NEW_BBLOCK (cfg, first_bb); - cfg->cbb = first_bb; - - 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 - ret = emit_castclass_with_cache_nonshared (cfg, source, klass); - } else if (!context_used && (mono_class_is_marshalbyref (klass) || mono_class_is_interface (klass))) { - MonoInst *iargs [1]; - int costs; - - iargs [0] = source; - if (is_isinst) { - MonoMethod *wrapper = mono_marshal_get_isinst (klass); - costs = inline_method (cfg, wrapper, mono_method_signature (wrapper), iargs, 0, 0, TRUE); - } else { - MonoMethod *wrapper = mono_marshal_get_castclass (klass); - save_cast_details (cfg, klass, source->dreg, TRUE); - costs = inline_method (cfg, wrapper, mono_method_signature (wrapper), iargs, 0, 0, TRUE); - reset_cast_details (cfg); - } - g_assert (costs > 0); - ret = iargs [0]; - } else { - if (is_isinst) - ret = handle_isinst (cfg, klass, source, context_used); - else - ret = handle_castclass (cfg, klass, source, context_used); - } - EMIT_NEW_UNALU (cfg, move, OP_MOVE, ins->dreg, ret->dreg); - - g_assert (cfg->cbb->code || first_bb->code); - MonoInst *prev = ins->prev; - mono_replace_ins (cfg, bb, ins, &prev, first_bb, cfg->cbb); - } - - void - mono_decompose_typechecks (MonoCompile *cfg) - { - for (MonoBasicBlock *bb = cfg->bb_entry; bb; bb = bb->next_bb) { - MonoInst *ins; - MONO_BB_FOR_EACH_INS (bb, ins) { - switch (ins->opcode) { - case OP_ISINST: - case OP_CASTCLASS: - mono_decompose_typecheck (cfg, bb, ins); - break; - } - } - } - } - /** * FIXME: diff --combined mono/mini/mini.c index fa01d62cfe7,30609c8352c..0f26b72293a --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@@ -47,6 -47,7 +47,7 @@@ #include #include #include + #include #include #include #include @@@ -85,10 -86,6 +86,10 @@@ int mono_break_at_bb_bb_num gboolean mono_do_x86_stack_align = TRUE; gboolean mono_using_xdebug; +/* Counters */ +static guint32 discarded_code; +static double discarded_jit_time; + #define mono_jit_lock() mono_os_mutex_lock (&jit_mutex) #define mono_jit_unlock() mono_os_mutex_unlock (&jit_mutex) static mono_mutex_t jit_mutex; @@@ -2146,10 -2143,8 +2147,10 @@@ mono_compile_create_vars (MonoCompile * cfg->args = (MonoInst **)mono_mempool_alloc0 (cfg->mempool, (sig->param_count + sig->hasthis) * sizeof (MonoInst*)); - if (sig->hasthis) + if (sig->hasthis) { cfg->args [0] = mono_compile_create_var (cfg, &cfg->method->klass->this_arg, OP_ARG); + cfg->this_arg = cfg->args [0]; + } for (i = 0; i < sig->param_count; ++i) { cfg->args [i + sig->hasthis] = mono_compile_create_var (cfg, sig->params [i], OP_ARG); @@@ -2419,10 -2414,13 +2420,10 @@@ mono_codegen (MonoCompile *cfg if (cfg->verbose_level > 0) { char* nm = mono_method_get_full_name (cfg->method); - char *opt_descr = mono_opt_descr (cfg->opt); - g_print ("Method %s emitted at %p to %p (code length %d) [%s] with opts %s\n", + g_print ("Method %s emitted at %p to %p (code length %d) [%s]\n", nm, - cfg->native_code, cfg->native_code + cfg->code_len, cfg->code_len, cfg->domain->friendly_name, - opt_descr); + cfg->native_code, cfg->native_code + cfg->code_len, cfg->code_len, cfg->domain->friendly_name); g_free (nm); - g_free (opt_descr); } { @@@ -2946,8 -2944,7 +2947,8 @@@ is_open_method (MonoMethod *method return FALSE; } -static void mono_insert_nop_in_empty_bb (MonoCompile *cfg) +static void +mono_insert_nop_in_empty_bb (MonoCompile *cfg) { MonoBasicBlock *bb; for (bb = cfg->bb_entry; bb; bb = bb->next_bb) { @@@ -4037,6 -4034,34 +4038,34 @@@ mini_method_compile (MonoMethod *method return cfg; } + gboolean + mini_class_has_reference_variant_generic_argument (MonoCompile *cfg, MonoClass *klass, int context_used) + { + int i; + MonoGenericContainer *container; + MonoGenericInst *ginst; + + if (mono_class_is_ginst (klass)) { + container = mono_class_get_generic_container (mono_class_get_generic_class (klass)->container_class); + ginst = mono_class_get_generic_class (klass)->context.class_inst; + } else if (mono_class_is_gtd (klass) && context_used) { + container = mono_class_get_generic_container (klass); + ginst = container->context.class_inst; + } else { + return FALSE; + } + + for (i = 0; i < container->type_argc; ++i) { + MonoType *type; + if (!(mono_generic_container_get_param_info (container, i)->flags & (MONO_GEN_PARAM_VARIANT|MONO_GEN_PARAM_COVARIANT))) + continue; + type = ginst->type_argv [i]; + if (mini_type_is_reference (type)) + return TRUE; + } + return FALSE; + } + void* mono_arch_instrument_epilog (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments) { @@@ -4261,9 -4286,7 +4290,9 @@@ mono_jit_compile_method_inner (MonoMeth jit_timer = mono_time_track_start (); cfg = mini_method_compile (method, opt, target_domain, JIT_FLAG_RUN_CCTORS, 0, -1); - mono_time_track_end (&mono_jit_stats.jit_time, jit_timer); + double jit_time = 0.0; + mono_time_track_end (&jit_time, jit_timer); + mono_jit_stats.jit_time += jit_time; prof_method = cfg->method; @@@ -4331,8 -4354,7 +4360,8 @@@ /* We can't use a domain specific method in another domain */ if ((target_domain == mono_domain_get ()) || info->domain_neutral) { code = info->code_start; -// printf("Discarding code for method %s\n", method->name); + discarded_code ++; + discarded_jit_time += jit_time; } } if (code == NULL) { @@@ -4452,9 -4474,6 +4481,9 @@@ mini_get_underlying_type (MonoType *typ void mini_jit_init (void) { + mono_counters_register ("Discarded method code", MONO_COUNTER_JIT | MONO_COUNTER_INT, &discarded_code); + mono_counters_register ("Time spent JITting discarded code", MONO_COUNTER_JIT | MONO_COUNTER_DOUBLE, &discarded_jit_time); + mono_os_mutex_init_recursive (&jit_mutex); #ifndef DISABLE_JIT current_backend = g_new0 (MonoBackend, 1); diff --combined mono/mini/mini.h index 66b87a1025c,d272ed32858..b3eb72a0d3f --- a/mono/mini/mini.h +++ b/mono/mini/mini.h @@@ -125,7 -125,7 +125,7 @@@ #endif /* Version number of the AOT file format */ -#define MONO_AOT_FILE_VERSION 137 +#define MONO_AOT_FILE_VERSION 138 //TODO: This is x86/amd64 specific. #define mono_simd_shuffle_mask(a,b,c,d) ((a) | ((b) << 2) | ((c) << 4) | ((d) << 6)) @@@ -1193,14 -1193,6 +1193,14 @@@ typedef struct * The calling assembly in llvmonly mode. */ MonoImage *calling_image; + + /* + * The stack frame "high water mark" for ThreadAbortExceptions. + * We will rethrow the exception upon exiting a catch clause that's + * in a function stack frame above the water mark(isn't being called by + * the catch block that caught the ThreadAbortException). + */ + gpointer abort_exc_stack_threshold; } MonoJitTlsData; /* @@@ -1593,7 -1585,6 +1593,7 @@@ typedef struct MonoMethod *current_method; /* The method currently processed by method_to_ir () */ MonoMethod *method_to_register; /* The method to register in JIT info tables */ MonoGenericContext *generic_context; + MonoInst *this_arg; MonoBackend *backend; @@@ -2651,6 -2642,19 +2651,19 @@@ int mono_method_to_ir (Mo MonoInst *return_var, MonoInst **inline_args, guint inline_offset, gboolean is_virtual_call); + //the following methods could just be renamed/moved from method-to-ir.c + int mini_inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, MonoInst **sp, guchar *ip, + guint real_offset, gboolean inline_always); + + MonoInst* mini_emit_get_rgctx_klass (MonoCompile *cfg, int context_used, MonoClass *klass, MonoRgctxInfoType rgctx_type); + MonoInst* mini_emit_runtime_constant (MonoCompile *cfg, MonoJumpInfoType patch_type, gpointer data); + void mini_save_cast_details (MonoCompile *cfg, MonoClass *klass, int obj_reg, gboolean null_check); + void mini_reset_cast_details (MonoCompile *cfg); + void mini_emit_class_check (MonoCompile *cfg, int klass_reg, MonoClass *klass); + + gboolean mini_class_has_reference_variant_generic_argument (MonoCompile *cfg, MonoClass *klass, int context_used); + + MonoInst *mono_decompose_opcode (MonoCompile *cfg, MonoInst *ins); void mono_decompose_long_opts (MonoCompile *cfg); void mono_decompose_vtype_opts (MonoCompile *cfg); @@@ -2662,6 -2666,8 +2675,8 @@@ void mono_spill_global_var void mono_allocate_gsharedvt_vars (MonoCompile *cfg); void mono_if_conversion (MonoCompile *cfg); + + /* Delegates */ gpointer mini_get_delegate_arg (MonoMethod *method, gpointer method_ptr); void mini_init_delegate (MonoDelegate *del);