X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmethod-to-ir.c;h=b9586d3b99b661e63080e5716c525245b86ddc00;hb=43885518391833af4c69fec7d7c768d202bc2d1d;hp=a3b98ec1f03369de16ec769a65a0eda0701616c4;hpb=07d11978e373154dd07388292a4658f78c5d4911;p=mono.git diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index a3b98ec1f03..b9586d3b99b 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -99,7 +99,7 @@ } while (0) #define GENERIC_SHARING_FAILURE(opcode) do { \ if (cfg->generic_sharing_context) { \ - if (cfg->verbose_level > -1) \ + if (cfg->verbose_level > 1) \ printf ("sharing failed for method %s.%s.%s/%d opcode %s line %d\n", method->klass->name_space, method->klass->name, method->name, method->signature->param_count, mono_opcode_name ((opcode)), __LINE__); \ cfg->exception_type = MONO_EXCEPTION_GENERIC_SHARING_FAILED; \ goto exception_exit; \ @@ -2193,6 +2193,18 @@ emit_imt_argument (MonoCompile *cfg, MonoCallInst *call, MonoInst *imt_arg) } #endif +static MonoJumpInfo * +mono_patch_info_new (MonoMemPool *mp, int ip, MonoJumpInfoType type, gconstpointer target) +{ + MonoJumpInfo *ji = mono_mempool_alloc (mp, sizeof (MonoJumpInfo)); + + ji->ip.i = ip; + ji->type = type; + ji->data.target = target; + + return ji; +} + inline static MonoInst* mono_emit_jit_icall (MonoCompile *cfg, gconstpointer func, MonoInst **args); @@ -2306,8 +2318,8 @@ mono_emit_rgctx_calli (MonoCompile *cfg, MonoMethodSignature *sig, MonoInst **ar } static MonoInst* -mono_emit_imt_method_call (MonoCompile *cfg, MonoMethod *method, MonoMethodSignature *sig, - MonoInst **args, MonoInst *this, MonoInst *imt_arg) +mono_emit_method_call_full (MonoCompile *cfg, MonoMethod *method, MonoMethodSignature *sig, + MonoInst **args, MonoInst *this, MonoInst *imt_arg) { gboolean virtual = this != NULL; gboolean enable_for_aot = TRUE; @@ -2316,7 +2328,7 @@ mono_emit_imt_method_call (MonoCompile *cfg, MonoMethod *method, MonoMethodSigna if (method->string_ctor) { /* Create the real signature */ /* FIXME: Cache these */ - MonoMethodSignature *ctor_sig = mono_metadata_signature_dup (sig); + MonoMethodSignature *ctor_sig = mono_metadata_signature_dup_full (cfg->mempool, sig); ctor_sig->ret = &mono_defaults.string_class->byval_arg; sig = ctor_sig; @@ -2431,10 +2443,9 @@ mono_emit_imt_method_call (MonoCompile *cfg, MonoMethod *method, MonoMethodSigna } static inline MonoInst* -mono_emit_method_call (MonoCompile *cfg, MonoMethod *method, MonoMethodSignature *sig, - MonoInst **args, MonoInst *this) +mono_emit_method_call (MonoCompile *cfg, MonoMethod *method, MonoInst **args, MonoInst *this) { - return mono_emit_imt_method_call (cfg, method, sig, args, this, NULL); + return mono_emit_method_call_full (cfg, method, mono_method_signature (method), args, this, NULL); } MonoInst* @@ -2463,6 +2474,30 @@ mono_emit_jit_icall (MonoCompile *cfg, gconstpointer func, MonoInst **args) return mono_emit_native_call (cfg, mono_icall_get_wrapper (info), info->sig, args); } +/* + * mono_emit_abs_call: + * + * Emit a call to the runtime function described by PATCH_TYPE and DATA. + */ +inline static MonoInst* +mono_emit_abs_call (MonoCompile *cfg, MonoJumpInfoType patch_type, gconstpointer data, + MonoMethodSignature *sig, MonoInst **args) +{ + MonoJumpInfo *ji = mono_patch_info_new (cfg->mempool, 0, patch_type, data); + MonoInst *ins; + + /* + * We pass ji as the call address, the PATCH_INFO_ABS resolving code will + * handle it. + */ + if (cfg->abs_patches == NULL) + cfg->abs_patches = g_hash_table_new (NULL, NULL); + g_hash_table_insert (cfg->abs_patches, ji, ji); + ins = mono_emit_native_call (cfg, ji, sig, args); + ((MonoCallInst*)ins)->fptr_is_patch = TRUE; + return ins; +} + static MonoMethod* get_memcpy_method (void) { @@ -2507,7 +2542,7 @@ mini_emit_stobj (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *kla EMIT_NEW_ICONST (cfg, iargs [2], n); memcpy_method = get_memcpy_method (); - mono_emit_method_call (cfg, memcpy_method, memcpy_method->signature, iargs, NULL); + mono_emit_method_call (cfg, memcpy_method, iargs, NULL); } } @@ -2544,7 +2579,7 @@ mini_emit_initobj (MonoCompile *cfg, MonoInst *dest, const guchar *ip, MonoClass iargs [0] = dest; EMIT_NEW_ICONST (cfg, iargs [1], 0); EMIT_NEW_ICONST (cfg, iargs [2], n); - mono_emit_method_call (cfg, memset_method, memset_method->signature, iargs, NULL); + mono_emit_method_call (cfg, memset_method, iargs, NULL); } } @@ -2602,54 +2637,51 @@ emit_get_rgctx (MonoCompile *cfg, MonoMethod *method, int context_used) (rgctx) = emit_get_rgctx (cfg, method, (context_used)); \ } while (0) -static MonoInst* -emit_get_rgctx_other_table_ptr (MonoCompile *cfg, MonoInst *rgc_ptr, int slot) +static MonoJumpInfoRgctxEntry * +mono_patch_info_rgctx_entry_new (MonoMemPool *mp, MonoMethod *method, gboolean in_mrgctx, MonoJumpInfoType patch_type, gconstpointer patch_data, int info_type) { - MonoMethodSignature *sig = helper_sig_rgctx_lazy_fetch_trampoline; - guint8 *tramp = mini_create_rgctx_lazy_fetch_trampoline (slot); + MonoJumpInfoRgctxEntry *res = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfoRgctxEntry)); + res->method = method; + res->in_mrgctx = in_mrgctx; + res->data = mono_mempool_alloc0 (mp, sizeof (MonoJumpInfo)); + res->data->type = patch_type; + res->data->data.target = patch_data; + res->info_type = info_type; - return mono_emit_native_call (cfg, tramp, sig, &rgc_ptr); + return res; +} + +static inline MonoInst* +emit_rgctx_fetch (MonoCompile *cfg, MonoInst *rgctx, MonoJumpInfoRgctxEntry *entry) +{ + 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 *rgctx, MonoClass *klass, int rgctx_type) { - guint32 slot = mono_method_lookup_or_register_other_info (cfg->current_method, - context_used & MONO_GENERIC_CONTEXT_USED_METHOD, &klass->byval_arg, rgctx_type, cfg->generic_context); + 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); - return emit_get_rgctx_other_table_ptr (cfg, rgctx, slot); + return emit_rgctx_fetch (cfg, rgctx, entry); } static MonoInst* emit_get_rgctx_method (MonoCompile *cfg, int context_used, MonoInst *rgctx, MonoMethod *cmethod, int rgctx_type) { - guint32 slot = mono_method_lookup_or_register_other_info (cfg->current_method, - context_used & MONO_GENERIC_CONTEXT_USED_METHOD, cmethod, rgctx_type, cfg->generic_context); + 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); - return emit_get_rgctx_other_table_ptr (cfg, rgctx, slot); + return emit_rgctx_fetch (cfg, rgctx, entry); } static MonoInst* emit_get_rgctx_field (MonoCompile *cfg, int context_used, MonoInst *rgctx, MonoClassField *field, int rgctx_type) { - guint32 slot = mono_method_lookup_or_register_other_info (cfg->current_method, - context_used & MONO_GENERIC_CONTEXT_USED_METHOD, field, rgctx_type, cfg->generic_context); + 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); - return emit_get_rgctx_other_table_ptr (cfg, rgctx, slot); -} - -static MonoInst* -emit_get_rgctx_method_rgctx (MonoCompile *cfg, int context_used, - MonoInst *rgctx, MonoMethod *rgctx_method) -{ - guint32 slot = mono_method_lookup_or_register_other_info (cfg->current_method, - context_used & MONO_GENERIC_CONTEXT_USED_METHOD, rgctx_method, - MONO_RGCTX_INFO_METHOD_RGCTX, cfg->generic_context); - - return emit_get_rgctx_other_table_ptr (cfg, rgctx, slot); + return emit_rgctx_fetch (cfg, rgctx, entry); } /** @@ -2667,7 +2699,7 @@ handle_unbox_nullable (MonoCompile* cfg, MonoInst* val, MonoClass* klass, int co return mono_emit_rgctx_calli (cfg, mono_method_signature (method), &val, addr, rgctx); } else { - return mono_emit_method_call (cfg, method, mono_method_signature (method), &val, NULL); + return mono_emit_method_call (cfg, method, &val, NULL); } } @@ -2741,7 +2773,7 @@ handle_alloc (MonoCompile *cfg, MonoClass *klass, gboolean for_box) if (managed_alloc) { EMIT_NEW_VTABLECONST (cfg, iargs [0], vtable); - return mono_emit_method_call (cfg, managed_alloc, mono_method_signature (managed_alloc), iargs, NULL); + return mono_emit_method_call (cfg, managed_alloc, iargs, NULL); } alloc_ftn = mono_class_get_allocation_ftn (vtable, for_box, &pass_lw); if (pass_lw) { @@ -2779,12 +2811,9 @@ handle_alloc_from_inst (MonoCompile *cfg, MonoClass *klass, MonoInst *data_inst, iargs [1] = data_inst; alloc_ftn = mono_object_new; } else { - g_assert (!cfg->compile_aot); - if (managed_alloc) { iargs [0] = data_inst; - return mono_emit_method_call (cfg, managed_alloc, - mono_method_signature (managed_alloc), iargs, NULL); + return mono_emit_method_call (cfg, managed_alloc, iargs, NULL); } iargs [0] = data_inst; @@ -2801,7 +2830,7 @@ handle_box (MonoCompile *cfg, MonoInst *val, MonoClass *klass) if (mono_class_is_nullable (klass)) { MonoMethod* method = mono_class_get_method_from_name (klass, "Box", 1); - return mono_emit_method_call (cfg, method, mono_method_signature (method), &val, NULL); + return mono_emit_method_call (cfg, method, &val, NULL); } alloc = handle_alloc (cfg, klass, TRUE); @@ -2812,17 +2841,23 @@ handle_box (MonoCompile *cfg, MonoInst *val, MonoClass *klass) } static MonoInst * -handle_box_from_inst (MonoCompile *cfg, MonoInst *val, MonoClass *klass, MonoInst *data_inst) +handle_box_from_inst (MonoCompile *cfg, MonoInst *val, MonoClass *klass, int context_used, MonoInst *rgctx, MonoInst *data_inst) { MonoInst *alloc, *ins; - g_assert (!mono_class_is_nullable (klass)); + if (mono_class_is_nullable (klass)) { + MonoMethod* method = mono_class_get_method_from_name (klass, "Box", 1); + MonoInst *addr = emit_get_rgctx_method (cfg, context_used, rgctx, method, + MONO_RGCTX_INFO_GENERIC_METHOD_CODE); - alloc = handle_alloc_from_inst (cfg, klass, data_inst, TRUE); + return mono_emit_rgctx_calli (cfg, mono_method_signature (method), &val, addr, rgctx); + } else { + alloc = handle_alloc_from_inst (cfg, klass, data_inst, TRUE); - EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, alloc->dreg, sizeof (MonoObject), val->dreg); + EMIT_NEW_STORE_MEMBASE_TYPE (cfg, ins, &klass->byval_arg, alloc->dreg, sizeof (MonoObject), val->dreg); - return alloc; + return alloc; + } } static MonoInst* @@ -3511,7 +3546,7 @@ mini_emit_ldelema_ins (MonoCompile *cfg, MonoMethod *cmethod, MonoInst **sp, uns element_size = mono_class_array_element_size (cmethod->klass->element_class); addr_method = mono_marshal_get_array_address (rank, element_size); - addr = mono_emit_method_call (cfg, addr_method, addr_method->signature, sp, NULL); + addr = mono_emit_method_call (cfg, addr_method, sp, NULL); return addr; } @@ -3848,7 +3883,7 @@ mini_redirect_call (MonoCompile *cfg, MonoMethod *method, return NULL; EMIT_NEW_VTABLECONST (cfg, iargs [0], vtable); iargs [1] = args [0]; - return mono_emit_method_call (cfg, managed_alloc, mono_method_signature (managed_alloc), iargs, this); + return mono_emit_method_call (cfg, managed_alloc, iargs, this); } } return NULL; @@ -4308,7 +4343,7 @@ gboolean check_linkdemand (MonoCompile *cfg, MonoMethod *caller, MonoMethod *cal NEW_ICONST (cfg, args [0], 4); NEW_METHODCONST (cfg, args [1], caller); - mono_emit_method_call (cfg, secman->linkdemandsecurityexception, mono_method_signature (secman->linkdemandsecurityexception), args, NULL); + mono_emit_method_call (cfg, secman->linkdemandsecurityexception, args, NULL); } else if (cfg->exception_type == MONO_EXCEPTION_NONE) { /* don't hide previous results */ cfg->exception_type = MONO_EXCEPTION_SECURITY_LINKDEMAND; @@ -4342,7 +4377,7 @@ emit_throw_method_access_exception (MonoCompile *cfg, MonoMethod *caller, MonoMe EMIT_NEW_METHODCONST (cfg, args [0], caller); EMIT_NEW_METHODCONST (cfg, args [1], callee); - mono_emit_method_call (cfg, thrower, mono_method_signature (thrower), args, NULL); + mono_emit_method_call (cfg, thrower, args, NULL); } static MonoMethod* @@ -4364,7 +4399,7 @@ emit_throw_verification_exception (MonoCompile *cfg, MonoBasicBlock *bblock, uns { MonoMethod *thrower = verification_exception (); - mono_emit_method_call (cfg, thrower, mono_method_signature (thrower), NULL, NULL); + mono_emit_method_call (cfg, thrower, NULL, NULL); } static void @@ -5174,7 +5209,7 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ EMIT_NEW_DECLSECCONST (cfg, args[0], image, actions.demand); EMIT_NEW_ICONST (cfg, args [1], actions.demand.size); /* Calls static void SecurityManager.InternalDemand (byte* permissions, int size); */ - mono_emit_method_call (cfg, secman->demand, mono_method_signature (secman->demand), args, NULL); + mono_emit_method_call (cfg, secman->demand, args, NULL); } if (actions.noncasdemand.blob) { /* CLR 1.x uses a .noncasdemand (but 2.x doesn't) */ @@ -5182,20 +5217,20 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ EMIT_NEW_DECLSECCONST (cfg, args[0], image, actions.noncasdemand); EMIT_NEW_ICONST (cfg, args [1], actions.noncasdemand.size); /* Calls static void SecurityManager.InternalDemand (byte* permissions, int size); */ - mono_emit_method_call (cfg, secman->demand, mono_method_signature (secman->demand), args, NULL); + mono_emit_method_call (cfg, secman->demand, args, NULL); } if (actions.demandchoice.blob) { /* New in 2.0, Demand must succeed for one of the permissions (i.e. not all) */ EMIT_NEW_DECLSECCONST (cfg, args[0], image, actions.demandchoice); EMIT_NEW_ICONST (cfg, args [1], actions.demandchoice.size); /* Calls static void SecurityManager.InternalDemandChoice (byte* permissions, int size); */ - mono_emit_method_call (cfg, secman->demandchoice, mono_method_signature (secman->demandchoice), args, NULL); + mono_emit_method_call (cfg, secman->demandchoice, args, NULL); } } /* we must Demand SecurityPermission.Unmanaged before p/invoking */ if (pinvoke) { - mono_emit_method_call (cfg, secman->demandunmanaged, mono_method_signature (secman->demandunmanaged), NULL, NULL); + mono_emit_method_call (cfg, secman->demandunmanaged, NULL, NULL); } if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) { @@ -5437,10 +5472,9 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ token = read32 (ip + 4); klass = mini_get_class (method, token, generic_context); CHECK_TYPELOAD (klass); - if (cfg->generic_sharing_context && mono_class_check_context_used (klass)) - GENERIC_SHARING_FAILURE (CEE_INITOBJ); - - if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) { + if (generic_class_is_reference_type (cfg, klass)) { + MONO_EMIT_NEW_PCONST (cfg, cfg->locals [ip [1]]->dreg, NULL); + } else if (MONO_TYPE_IS_REFERENCE (&klass->byval_arg)) { MONO_EMIT_NEW_PCONST (cfg, cfg->locals [ip [1]]->dreg, NULL); } else if (MONO_TYPE_ISSTRUCT (&klass->byval_arg)) { MONO_EMIT_NEW_VZERO (cfg, cfg->locals [ip [1]]->dreg, klass); @@ -5601,8 +5635,6 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ CHECK_OPSIZE (5); if (stack_start != sp) UNVERIFIED; - MONO_INST_NEW_CALL (cfg, call, OP_JMP); - ins = (MonoInst*)call; token = read32 (ip + 1); /* FIXME: check the signature matches */ cmethod = mini_get_method (cfg, method, token, NULL, generic_context); @@ -5619,13 +5651,37 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ CHECK_CFG_EXCEPTION; } +#ifdef __x86_64__ + { + MonoMethodSignature *fsig = mono_method_signature (cmethod); + int i, n; + + /* FIXME: Remove OP_JMP from mini-amd64.c when the old JIT is removed */ + + /* Handle tail calls similarly to calls */ + n = fsig->param_count + fsig->hasthis; + + MONO_INST_NEW_CALL (cfg, call, OP_TAILCALL); + call->method = cmethod; + call->tail_call = TRUE; + call->signature = mono_method_signature (cmethod); + call->args = mono_mempool_alloc (cfg->mempool, sizeof (MonoInst*) * n); + call->inst.inst_p0 = cmethod; + for (i = 0; i < n; ++i) + EMIT_NEW_ARGLOAD (cfg, call->args [i], i); + + mono_arch_emit_call (cfg, call); + MONO_ADD_INS (bblock, (MonoInst*)call); + } +#else + MONO_INST_NEW_CALL (cfg, call, OP_JMP); + ins = (MonoInst*)call; ins->inst_p0 = cmethod; MONO_ADD_INS (bblock, ins); +#endif + ip += 5; start_new_bblock = 1; - - /* FIXME: */ - cfg->disable_aot = 1; break; } case CEE_CALLI: @@ -5828,10 +5884,6 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ mono_get_vtable_var (cfg); } - // FIXME: - if (!cmethod) - GENERIC_SHARING_FAILURE (*ip); - if (pass_vtable) { if (context_used) { MonoInst *rgctx; @@ -5853,7 +5905,7 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ MonoInst *rgctx; EMIT_GET_RGCTX (rgctx, context_used); - vtable_arg = emit_get_rgctx_method_rgctx (cfg, context_used, rgctx, cmethod); + vtable_arg = emit_get_rgctx_method (cfg, context_used, rgctx, cmethod, MONO_RGCTX_INFO_METHOD_RGCTX); } else { EMIT_NEW_METHOD_RGCTX_CONST (cfg, vtable_arg, cmethod); } @@ -5906,8 +5958,6 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ /* FIXME: This should be a managed pointer */ this_arg_temp = mono_compile_create_var (cfg, &mono_defaults.int_class->byval_arg, OP_LOCAL); - /* Because of the PCONST below */ - cfg->disable_aot = TRUE; EMIT_NEW_TEMPLOAD (cfg, iargs [0], this_temp->inst_c0); if (context_used) { MonoInst *rgctx; @@ -5916,11 +5966,10 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ iargs [1] = emit_get_rgctx_method (cfg, context_used, rgctx, cmethod, MONO_RGCTX_INFO_METHOD); EMIT_NEW_TEMPLOADA (cfg, iargs [2], this_arg_temp->inst_c0); addr = mono_emit_jit_icall (cfg, - mono_helper_compile_generic_method_wo_context, iargs); + mono_helper_compile_generic_method, iargs); } else { EMIT_NEW_METHODCONST (cfg, iargs [1], cmethod); - EMIT_NEW_PCONST (cfg, iargs [2], mono_method_get_context (cmethod)); - EMIT_NEW_TEMPLOADA (cfg, iargs [3], this_arg_temp->inst_c0); + EMIT_NEW_TEMPLOADA (cfg, iargs [2], this_arg_temp->inst_c0); addr = mono_emit_jit_icall (cfg, mono_helper_compile_generic_method, iargs); } @@ -5970,9 +6019,6 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ } #endif - /* FIXME: */ - cfg->disable_aot = 1; - ins = (MonoInst*)call; ins->inst_p0 = cmethod; ins->inst_p1 = arg_array [0]; @@ -6225,16 +6271,16 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ int rgctx_reg = mono_alloc_preg (cfg); MONO_EMIT_NEW_UNALU (cfg, OP_MOVE, rgctx_reg, vtable_arg->dreg); - ins = (MonoInst*)mono_emit_method_call (cfg, cmethod, fsig, sp, virtual ? sp [0] : NULL); + ins = (MonoInst*)mono_emit_method_call_full (cfg, cmethod, fsig, sp, virtual ? sp [0] : NULL, NULL); call = (MonoCallInst*)ins; mono_call_inst_add_outarg_reg (cfg, call, rgctx_reg, MONO_ARCH_RGCTX_REG, FALSE); #else GENERIC_SHARING_FAILURE (*ip); #endif } else if (imt_arg) { - ins = (MonoInst*)mono_emit_imt_method_call (cfg, cmethod, fsig, sp, virtual ? sp [0] : NULL, imt_arg); + ins = (MonoInst*)mono_emit_method_call_full (cfg, cmethod, fsig, sp, virtual ? sp [0] : NULL, imt_arg); } else { - ins = (MonoInst*)mono_emit_method_call (cfg, cmethod, fsig, sp, virtual ? sp [0] : NULL); + ins = (MonoInst*)mono_emit_method_call_full (cfg, cmethod, fsig, sp, virtual ? sp [0] : NULL, NULL); } if (!MONO_TYPE_IS_VOID (fsig->ret)) @@ -7015,8 +7061,11 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ if (mini_class_is_system_array (cmethod->klass)) { g_assert (!context_used); EMIT_NEW_METHODCONST (cfg, *sp, cmethod); - if (fsig->param_count == 2) - /* Avoid varargs in the common case */ + + /* Avoid varargs in the common case */ + if (fsig->param_count == 1) + alloc = mono_emit_jit_icall (cfg, mono_array_new_1, sp); + else if (fsig->param_count == 2) alloc = mono_emit_jit_icall (cfg, mono_array_new_2, sp); else alloc = handle_array_new (cfg, fsig->param_count, sp, ip); @@ -7025,7 +7074,7 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ /* we simply pass a null pointer */ EMIT_NEW_PCONST (cfg, *sp, NULL); /* now call the string ctor */ - alloc = mono_emit_method_call (cfg, cmethod, fsig, sp, NULL); + alloc = mono_emit_method_call_full (cfg, cmethod, fsig, sp, NULL, NULL); } else { MonoInst* callvirt_this_arg = NULL; @@ -7065,10 +7114,7 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ * As a workaround, we call class cctors before allocating objects. */ if (mini_field_access_needs_cctor_run (cfg, method, vtable) && !(g_slist_find (class_inits, vtable))) { - guint8 *tramp = mono_create_class_init_trampoline (vtable); - mono_emit_native_call (cfg, tramp, - helper_sig_class_init_trampoline, - NULL); + mono_emit_abs_call (cfg, MONO_PATCH_INFO_CLASS_INIT, vtable->klass, helper_sig_class_init_trampoline, NULL); if (cfg->verbose_level > 2) printf ("class %s.%s needs init call for ctor\n", cmethod->klass->name_space, cmethod->klass->name); class_inits = g_slist_prepend (class_inits, vtable); @@ -7099,7 +7145,7 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ inline_costs += costs - 5; } else { INLINE_FAILURE; - mono_emit_method_call (cfg, cmethod, fsig, sp, callvirt_this_arg); + mono_emit_method_call_full (cfg, cmethod, fsig, sp, callvirt_this_arg, NULL); } } else if (context_used && (cmethod->klass->valuetype || @@ -7115,7 +7161,7 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ mono_emit_calli (cfg, fsig, sp, cmethod_addr); } else { INLINE_FAILURE; - mono_emit_method_call (cfg, cmethod, fsig, sp, callvirt_this_arg); + mono_emit_method_call_full (cfg, cmethod, fsig, sp, callvirt_this_arg, NULL); } } @@ -7189,7 +7235,7 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ ip += 5; } break; - case CEE_ISINST: + case CEE_ISINST: { CHECK_STACK (1); --sp; CHECK_OPSIZE (5); @@ -7199,11 +7245,24 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ if (sp [0]->type != STACK_OBJ) UNVERIFIED; - if (cfg->generic_sharing_context && mono_class_check_context_used (klass)) - GENERIC_SHARING_FAILURE (CEE_ISINST); + if (cfg->generic_sharing_context) + context_used = mono_class_check_context_used (klass); - if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE) { - + if (context_used) { + MonoInst *rgctx, *args [2]; + + /* obj */ + args [0] = *sp; + + /* klass */ + EMIT_GET_RGCTX (rgctx, context_used); + args [1] = emit_get_rgctx_klass (cfg, context_used, rgctx, klass, MONO_RGCTX_INFO_KLASS); + + *sp = mono_emit_jit_icall (cfg, mono_object_isinst, args); + sp++; + ip += 5; + inline_costs += 2; + } else if (klass->marshalbyref || klass->flags & TYPE_ATTRIBUTE_INTERFACE) { MonoMethod *mono_isinst; MonoInst *iargs [1]; int costs; @@ -7230,6 +7289,7 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ ip += 5; } break; + } case CEE_UNBOX_ANY: { MonoInst *rgctx = NULL; @@ -7314,7 +7374,6 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ } case CEE_BOX: { MonoInst *val; - int context_used = 0; CHECK_STACK (1); --sp; @@ -7326,13 +7385,9 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ mono_save_token_info (cfg, image, token, klass); - if (cfg->generic_sharing_context) { + if (cfg->generic_sharing_context) context_used = mono_class_check_context_used (klass); - if (context_used & MONO_GENERIC_CONTEXT_USED_METHOD) - GENERIC_SHARING_FAILURE (*ip); - } - if (generic_class_is_reference_type (cfg, klass)) { *sp++ = val; ip += 5; @@ -7383,21 +7438,16 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ if (context_used) { MonoInst *rgctx; + MonoInst *data; + int rgctx_info; - if (mono_class_is_nullable (klass)) { - GENERIC_SHARING_FAILURE (CEE_BOX); - } else { - MonoInst *data; - int rgctx_info; - - EMIT_GET_RGCTX (rgctx, context_used); - if (cfg->opt & MONO_OPT_SHARED) - rgctx_info = MONO_RGCTX_INFO_KLASS; - else - rgctx_info = MONO_RGCTX_INFO_VTABLE; - data = emit_get_rgctx_klass (cfg, context_used, rgctx, klass, rgctx_info); - *sp++ = handle_box_from_inst (cfg, val, klass, data); - } + EMIT_GET_RGCTX (rgctx, context_used); + if (cfg->opt & MONO_OPT_SHARED) + rgctx_info = MONO_RGCTX_INFO_KLASS; + else + rgctx_info = MONO_RGCTX_INFO_VTABLE; + data = emit_get_rgctx_klass (cfg, context_used, rgctx, klass, rgctx_info); + *sp++ = handle_box_from_inst (cfg, val, klass, context_used, rgctx, data); } else { *sp++ = handle_box (cfg, val, klass); } @@ -7499,7 +7549,7 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ inline_costs += costs; break; } else { - mono_emit_method_call (cfg, stfld_wrapper, mono_method_signature (stfld_wrapper), iargs, NULL); + mono_emit_method_call (cfg, stfld_wrapper, iargs, NULL); } } else { MonoInst *store; @@ -7535,7 +7585,7 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ inline_costs += costs; break; } else { - ins = mono_emit_method_call (cfg, wrapper, mono_method_signature (wrapper), iargs, NULL); + ins = mono_emit_method_call (cfg, wrapper, iargs, NULL); *sp++ = ins; } } else { @@ -7665,7 +7715,7 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ * the calling convention, so assign it manually, and make a call * using a signature without parameters. */ - call = (MonoCallInst*)mono_emit_native_call (cfg, mono_get_trampoline_code (MONO_TRAMPOLINE_GENERIC_CLASS_INIT), helper_sig_generic_class_init_trampoline, &vtable); + call = (MonoCallInst*)mono_emit_abs_call (cfg, MONO_PATCH_INFO_GENERIC_CLASS_INIT, NULL, helper_sig_generic_class_init_trampoline, &vtable); #ifdef MONO_ARCH_VTABLE_REG mono_call_inst_add_outarg_reg (cfg, call, vtable->dreg, MONO_ARCH_VTABLE_REG, FALSE); #else @@ -7700,10 +7750,7 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ CHECK_TYPELOAD (klass); if (!addr) { if (mini_field_access_needs_cctor_run (cfg, method, vtable) && !(g_slist_find (class_inits, vtable))) { - guint8 *tramp = mono_create_class_init_trampoline (vtable); - mono_emit_native_call (cfg, tramp, - helper_sig_class_init_trampoline, - NULL); + mono_emit_abs_call (cfg, MONO_PATCH_INFO_CLASS_INIT, vtable->klass, helper_sig_class_init_trampoline, NULL); if (cfg->verbose_level > 2) printf ("class %s.%s needs init call for %s\n", klass->name_space, klass->name, field->name); class_inits = g_slist_prepend (class_inits, vtable); @@ -7834,9 +7881,6 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ load->flags |= ins_flag; ins_flag = 0; *sp++ = load; - - /* fixme: dont see the problem why this does not work */ - //cfg->disable_aot = TRUE; } } ip += 5; @@ -7940,7 +7984,7 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ EMIT_NEW_PCONST (cfg, iargs [1], (char*)data_ptr); } EMIT_NEW_ICONST (cfg, iargs [2], data_size); - mono_emit_method_call (cfg, memcpy_method, memcpy_method->signature, iargs, NULL); + mono_emit_method_call (cfg, memcpy_method, iargs, NULL); ip += 11; } @@ -8080,7 +8124,7 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ iargs [1] = sp [1]; iargs [0] = sp [0]; - mono_emit_method_call (cfg, helper, mono_method_signature (helper), iargs, NULL); + mono_emit_method_call (cfg, helper, iargs, NULL); } else { if (sp [1]->opcode == OP_ICONST) { int array_reg = sp [0]->dreg; @@ -8113,12 +8157,13 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ MONO_ADD_INS (bblock, ins); *sp++ = ins; + mono_decompose_opcode (cfg, ins); + ++ip; break; } case CEE_REFANYVAL: { MonoInst *src_var, *src; - int context_used = 0; int klass_reg = alloc_preg (cfg); int dreg = alloc_preg (cfg); @@ -8131,25 +8176,29 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ CHECK_TYPELOAD (klass); mono_class_init (klass); - if (cfg->generic_sharing_context) { + if (cfg->generic_sharing_context) context_used = mono_class_check_context_used (klass); - if (context_used && cfg->compile_aot) - GENERIC_SHARING_FAILURE (*ip); - } + + // FIXME: + src_var = get_vreg_to_inst (cfg, sp [0]->dreg); + if (!src_var) + src_var = mono_compile_create_var_for_vreg (cfg, &mono_defaults.typed_reference_class->byval_arg, OP_LOCAL, sp [0]->dreg); + EMIT_NEW_VARLOADA (cfg, src, src_var, src_var->inst_vtype); + MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, src->dreg, G_STRUCT_OFFSET (MonoTypedRef, klass)); if (context_used) { + MonoInst *rgctx, *klass_ins; + + EMIT_GET_RGCTX (rgctx, context_used); + klass_ins = emit_get_rgctx_klass (cfg, context_used, rgctx, klass, MONO_RGCTX_INFO_KLASS); + // FIXME: - GENERIC_SHARING_FAILURE (*ip); + MONO_EMIT_NEW_BIALU (cfg, OP_COMPARE, -1, klass_reg, klass_ins->dreg); + MONO_EMIT_NEW_COND_EXC (cfg, NE_UN, "InvalidCastException"); } else { - // FIXME: - src_var = get_vreg_to_inst (cfg, sp [0]->dreg); - if (!src_var) - src_var = mono_compile_create_var_for_vreg (cfg, &mono_defaults.typed_reference_class->byval_arg, OP_LOCAL, sp [0]->dreg); - EMIT_NEW_VARLOADA (cfg, src, src_var, src_var->inst_vtype); - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, klass_reg, src->dreg, G_STRUCT_OFFSET (MonoTypedRef, klass)); mini_emit_class_check (cfg, klass_reg, klass); - EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, dreg, src->dreg, G_STRUCT_OFFSET (MonoTypedRef, value)); } + EMIT_NEW_LOAD_MEMBASE (cfg, ins, OP_LOAD_MEMBASE, dreg, src->dreg, G_STRUCT_OFFSET (MonoTypedRef, value)); ins->type = STACK_MP; *sp++ = ins; ip += 5; @@ -8157,7 +8206,6 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ } case CEE_MKREFANY: { MonoInst *loc, *addr; - int context_used = 0; CHECK_STACK (1); MONO_INST_NEW (cfg, ins, *ip); @@ -8167,17 +8215,21 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ CHECK_TYPELOAD (klass); mono_class_init (klass); - if (cfg->generic_sharing_context) { + if (cfg->generic_sharing_context) context_used = mono_class_check_context_used (klass); - if (context_used && cfg->compile_aot) - GENERIC_SHARING_FAILURE (CEE_MKREFANY); - } loc = mono_compile_create_var (cfg, &mono_defaults.typed_reference_class->byval_arg, OP_LOCAL); EMIT_NEW_TEMPLOADA (cfg, addr, loc->inst_c0); if (context_used) { - GENERIC_SHARING_FAILURE (CEE_MKREFANY); + MonoInst *rgctx, *const_ins; + int type_reg = alloc_preg (cfg); + + EMIT_GET_RGCTX (rgctx, context_used); + const_ins = emit_get_rgctx_klass (cfg, context_used, rgctx, klass, MONO_RGCTX_INFO_KLASS); + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, addr->dreg, G_STRUCT_OFFSET (MonoTypedRef, klass), const_ins->dreg); + MONO_EMIT_NEW_BIALU_IMM (cfg, OP_ADD_IMM, type_reg, const_ins->dreg, G_STRUCT_OFFSET (MonoClass, byval_arg)); + MONO_EMIT_NEW_STORE_MEMBASE (cfg, OP_STOREP_MEMBASE_REG, addr->dreg, G_STRUCT_OFFSET (MonoTypedRef, type), type_reg); } else if (cfg->compile_aot) { int const_reg = alloc_preg (cfg); int type_reg = alloc_preg (cfg); @@ -8202,7 +8254,6 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ case CEE_LDTOKEN: { gpointer handle; MonoClass *handle_class; - int context_used = 0; CHECK_STACK_OVF (1); @@ -8279,7 +8330,6 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ if (context_used) { MonoInst *rgctx; - g_assert (!cfg->compile_aot); EMIT_GET_RGCTX (rgctx, context_used); ins = emit_get_rgctx_klass (cfg, context_used, rgctx, tclass, MONO_RGCTX_INFO_REFLECTION_TYPE); } else if (cfg->compile_aot) { @@ -8304,8 +8354,6 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ if (context_used) { MonoInst *rgctx; - g_assert (!cfg->compile_aot); - EMIT_GET_RGCTX (rgctx, context_used); if (handle_class == mono_defaults.typehandle_class) { ins = emit_get_rgctx_klass (cfg, context_used, rgctx, @@ -8784,6 +8832,8 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ goto load_error; mono_class_init (cmethod->klass); + mono_save_token_info (cfg, image, n, cmethod); + if (cfg->generic_sharing_context) context_used = mono_method_check_context_used (cmethod); @@ -8865,8 +8915,8 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ goto load_error; mono_class_init (cmethod->klass); - if (cfg->generic_sharing_context && mono_method_check_context_used (cmethod)) - GENERIC_SHARING_FAILURE (CEE_LDVIRTFTN); + if (cfg->generic_sharing_context) + context_used = mono_method_check_context_used (cmethod); if (mono_security_get_mode () == MONO_SECURITY_MODE_CAS) { if (check_linkdemand (cfg, method, cmethod)) @@ -8878,8 +8928,17 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ --sp; args [0] = *sp; - EMIT_NEW_METHODCONST (cfg, args [1], cmethod); - *sp++ = mono_emit_jit_icall (cfg, mono_ldvirtfn, args); + + if (context_used) { + MonoInst *rgctx; + + EMIT_GET_RGCTX (rgctx, context_used); + args [1] = emit_get_rgctx_method (cfg, context_used, rgctx, cmethod, MONO_RGCTX_INFO_METHOD); + *sp++ = mono_emit_jit_icall (cfg, mono_ldvirtfn_gshared, args); + } else { + EMIT_NEW_METHODCONST (cfg, args [1], cmethod); + *sp++ = mono_emit_jit_icall (cfg, mono_ldvirtfn, args); + } ip += 6; inline_costs += 10 * num_calls++; @@ -9059,10 +9118,10 @@ mono_method_to_ir2 (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_ iargs [2] = sp [2]; if (ip [1] == CEE_CPBLK) { MonoMethod *memcpy_method = get_memcpy_method (); - mono_emit_method_call (cfg, memcpy_method, memcpy_method->signature, iargs, NULL); + mono_emit_method_call (cfg, memcpy_method, iargs, NULL); } else { MonoMethod *memset_method = get_memset_method (); - mono_emit_method_call (cfg, memset_method, memset_method->signature, iargs, NULL); + mono_emit_method_call (cfg, memset_method, iargs, NULL); } } ip += 2;