X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmethod-to-ir.c;h=87e259d63fc861391516ae38453a44fa365fed3d;hb=8219a5b7639b02781dd1d49bd872d8382bfd7851;hp=713dcec075eba5cf4566a458ed25c0b3c25181e3;hpb=2b408cb9feffcb70783cddccd5df0b3a9c76fb1f;p=mono.git diff --git a/mono/mini/method-to-ir.c b/mono/mini/method-to-ir.c index 713dcec075e..87e259d63fc 100644 --- a/mono/mini/method-to-ir.c +++ b/mono/mini/method-to-ir.c @@ -464,8 +464,7 @@ mono_link_bblock (MonoCompile *cfg, MonoBasicBlock *from, MonoBasicBlock* to) static int mono_find_block_region (MonoCompile *cfg, int offset) { - MonoMethod *method = cfg->method; - MonoMethodHeader *header = mono_method_get_header (method); + MonoMethodHeader *header = cfg->header; MonoExceptionClause *clause; int i; @@ -494,10 +493,8 @@ mono_find_block_region (MonoCompile *cfg, int offset) static GList* mono_find_final_block (MonoCompile *cfg, unsigned char *ip, unsigned char *target, int type) { - MonoMethod *method = cfg->method; - MonoMethodHeader *header = mono_method_get_header (method); + MonoMethodHeader *header = cfg->header; MonoExceptionClause *clause; - MonoBasicBlock *handler; int i; GList *res = NULL; @@ -505,11 +502,8 @@ mono_find_final_block (MonoCompile *cfg, unsigned char *ip, unsigned char *targe clause = &header->clauses [i]; if (MONO_OFFSET_IN_CLAUSE (clause, (ip - header->code)) && (!MONO_OFFSET_IN_CLAUSE (clause, (target - header->code)))) { - if (clause->flags == type) { - handler = cfg->cil_offset_to_bb [clause->handler_offset]; - g_assert (handler); - res = g_list_append (res, handler); - } + if (clause->flags == type) + res = g_list_append (res, clause); } } return res; @@ -1192,7 +1186,7 @@ mono_compile_get_interface_var (MonoCompile *cfg, int slot, MonoInst *ins) int pos, vnum; /* inlining can result in deeper stacks */ - if (slot >= mono_method_get_header (cfg->method)->max_stack) + if (slot >= cfg->header->max_stack) return mono_compile_create_var (cfg, type_from_stack_type (ins), OP_LOCAL); pos = ins->type - 1 + slot * STACK_MAX; @@ -1376,17 +1370,26 @@ mini_emit_load_intf_reg_vtable (MonoCompile *cfg, int intf_reg, int vtable_reg, } } -/* - * 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 (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; + if (cfg->compile_aot) + EMIT_NEW_AOTCONST (cfg, args [1], MONO_PATCH_INFO_IID, klass); + else + EMIT_NEW_ICONST (cfg, args [1], klass->interface_id); + 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, klass_reg, G_STRUCT_OFFSET (MonoClass, interface_bitmap)); + MONO_EMIT_NEW_LOAD_MEMBASE (cfg, ibitmap_reg, base_reg, offset); if (cfg->compile_aot) { int iid_reg = alloc_preg (cfg); @@ -1407,6 +1410,17 @@ mini_emit_load_intf_bit_reg_class (MonoCompile *cfg, int intf_bit_reg, int klass 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, G_STRUCT_OFFSET (MonoClass, interface_bitmap), klass); } /* @@ -1416,30 +1430,7 @@ mini_emit_load_intf_bit_reg_class (MonoCompile *cfg, int intf_bit_reg, int klass static void mini_emit_load_intf_bit_reg_vtable (MonoCompile *cfg, int intf_bit_reg, int vtable_reg, MonoClass *klass) { - int ibitmap_reg = alloc_preg (cfg); - int ibitmap_byte_reg = alloc_preg (cfg); - - MONO_EMIT_NEW_LOAD_MEMBASE (cfg, ibitmap_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, interface_bitmap)); - - 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_ISHR_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_AND_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_IAND_IMM, intf_bit_reg, ibitmap_byte_reg, 1 << (klass->interface_id & 7)); - } + mini_emit_interface_bitmap_check (cfg, intf_bit_reg, vtable_reg, G_STRUCT_OFFSET (MonoVTable, interface_bitmap), klass); } /* @@ -2602,6 +2593,9 @@ mini_emit_stobj (MonoCompile *cfg, MonoInst *dest, MonoInst *src, MonoClass *kla } } + /* FIXME: this does the memcpy as well (or + should), so we don't need the memcpy + afterwards */ mono_emit_jit_icall (cfg, mono_value_copy, iargs); } } @@ -4239,8 +4233,10 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign #if HAVE_WRITE_BARRIERS if (is_ref) { + MonoInst *dummy_use; MonoMethod *write_barrier = mono_gc_get_write_barrier (); mono_emit_method_call (cfg, write_barrier, &args [0], NULL); + EMIT_NEW_DUMMY_USE (cfg, dummy_use, args [1]); } #endif } @@ -4277,8 +4273,10 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign } #if HAVE_WRITE_BARRIERS if (is_ref) { + MonoInst *dummy_use; MonoMethod *write_barrier = mono_gc_get_write_barrier (); mono_emit_method_call (cfg, write_barrier, &args [0], NULL); + EMIT_NEW_DUMMY_USE (cfg, dummy_use, args [1]); } #endif } @@ -4334,7 +4332,7 @@ mini_redirect_call (MonoCompile *cfg, MonoMethod *method, { if (method->klass == mono_defaults.string_class) { /* managed string allocation support */ - if (strcmp (method->name, "InternalAllocateStr") == 0 && !(mono_profiler_events & MONO_PROFILE_STRING_ALLOC)) { + if (strcmp (method->name, "InternalAllocateStr") == 0 && !(mono_profiler_events & MONO_PROFILE_ALLOCATIONS)) { MonoInst *iargs [2]; MonoVTable *vtable = mono_class_vtable (cfg->domain, method->klass); MonoMethod *managed_alloc = NULL; @@ -4486,6 +4484,8 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, cheader = mono_method_get_header (cmethod); if (cheader == NULL || mono_loader_get_last_error ()) { + if (cheader) + mono_metadata_free_mh (cheader); mono_loader_clear_error (); return 0; } @@ -4616,6 +4616,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, EMIT_NEW_TEMPLOAD (cfg, ins, rvar->inst_c0); *sp++ = ins; } + mono_metadata_free_mh (cheader); return costs + 1; } else { if (cfg->verbose_level > 2) @@ -4626,6 +4627,7 @@ inline_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSignature *fsig, /* This gets rid of the newly added bblocks */ cfg->cbb = prev_cbb; } + mono_metadata_free_mh (cheader); return 0; } @@ -5004,8 +5006,9 @@ set_exception_type_from_invalid_il (MonoCompile *cfg, MonoMethod *method, unsign { char *method_fname = mono_method_full_name (method, TRUE); char *method_code; + MonoMethodHeader *header = mono_method_get_header (method); - if (mono_method_get_header (method)->code_size == 0) + if (header->code_size == 0) method_code = g_strdup ("method body is empty."); else method_code = mono_disasm_code_one (NULL, method, ip, NULL); @@ -5013,6 +5016,7 @@ set_exception_type_from_invalid_il (MonoCompile *cfg, MonoMethod *method, unsign cfg->exception_message = g_strdup_printf ("Invalid IL code in %s: %s\n", method_fname, method_code); g_free (method_fname); g_free (method_code); + mono_metadata_free_mh (header); } static void @@ -5119,7 +5123,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b MonoError error; MonoInst *ins, **sp, **stack_start; MonoBasicBlock *bblock, *tblock = NULL, *init_localsbb = NULL; - MonoSimpleBasicBlock *bb = NULL; + MonoSimpleBasicBlock *bb = NULL, *original_bb = NULL; MonoMethod *cmethod, *method_definition; MonoInst **arg_array; MonoMethodHeader *header; @@ -5525,7 +5529,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b skip_dead_blocks = !dont_verify; if (skip_dead_blocks) { - bb = mono_basic_block_split (method, &error); + original_bb = bb = mono_basic_block_split (method, &error); if (!mono_error_ok (&error)) { mono_error_cleanup (&error); UNVERIFIED; @@ -6077,7 +6081,12 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b array_rank = cmethod->klass->rank; fsig = mono_method_signature (cmethod); } else { - if (mono_method_signature (cmethod)->pinvoke) { + fsig = mono_method_signature (cmethod); + + if (!fsig) + goto load_error; + + if (fsig->pinvoke) { MonoMethod *wrapper = mono_marshal_get_native_wrapper (cmethod, check_for_pending_exc, FALSE); fsig = mono_method_signature (wrapper); @@ -6235,7 +6244,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b * emit_get_rgctx_method () calls mono_class_vtable () so check * for type load errors before. */ - mono_class_vtable (cfg->domain, cmethod->klass); + mono_class_setup_vtable (cmethod->klass); CHECK_TYPELOAD (cmethod->klass); } @@ -6964,9 +6973,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b #if HAVE_WRITE_BARRIERS if (*ip == CEE_STIND_REF && method->wrapper_type != MONO_WRAPPER_WRITE_BARRIER && !((sp [1]->opcode == OP_PCONST) && (sp [1]->inst_p0 == 0))) { + MonoInst *dummy_use; /* insert call to write barrier */ MonoMethod *write_barrier = mono_gc_get_write_barrier (); mono_emit_method_call (cfg, write_barrier, sp, NULL); + EMIT_NEW_DUMMY_USE (cfg, dummy_use, sp [1]); } #endif @@ -7902,13 +7913,15 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b if (mini_type_to_stind (cfg, field->type) == CEE_STIND_REF && !(sp [1]->opcode == OP_PCONST && sp [1]->inst_c0 == 0)) { /* insert call to write barrier */ MonoMethod *write_barrier = mono_gc_get_write_barrier (); - MonoInst *iargs [2]; + MonoInst *iargs [2], *dummy_use; int dreg; dreg = alloc_preg (cfg); EMIT_NEW_BIALU_IMM (cfg, iargs [0], OP_PADD_IMM, dreg, sp [0]->dreg, foffset); iargs [1] = sp [1]; mono_emit_method_call (cfg, write_barrier, iargs, NULL); + + EMIT_NEW_DUMMY_USE (cfg, dummy_use, sp [1]); } #endif @@ -8915,11 +8928,16 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b if ((handlers = mono_find_final_block (cfg, ip, target, MONO_EXCEPTION_CLAUSE_FINALLY))) { GList *tmp; + MonoExceptionClause *clause; + for (tmp = handlers; tmp; tmp = tmp->next) { - tblock = tmp->data; + clause = tmp->data; + tblock = cfg->cil_offset_to_bb [clause->handler_offset]; + g_assert (tblock); link_bblock (cfg, bblock, tblock); MONO_INST_NEW (cfg, ins, OP_CALL_HANDLER); ins->inst_target_bb = tblock; + ins->inst_eh_block = clause; MONO_ADD_INS (bblock, ins); bblock->has_call_handler = 1; if (COMPILE_LLVM (cfg)) { @@ -9338,12 +9356,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b /* * Optimize the common case of ldftn+delegate creation */ -#if defined(MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE) && !defined(HAVE_WRITE_BARRIERS) - /* FIXME: SGEN support */ if ((sp > stack_start) && (ip + 6 + 5 < end) && ip_in_bb (cfg, bblock, ip + 6) && (ip [6] == CEE_NEWOBJ)) { MonoMethod *ctor_method = mini_get_method (cfg, method, read32 (ip + 7), NULL, generic_context); if (ctor_method && (ctor_method->klass->parent == mono_defaults.multicastdelegate_class)) { - MonoInst *target_ins; MonoMethod *invoke; int invoke_context_used = 0; @@ -9354,7 +9369,11 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b if (cfg->generic_sharing_context) invoke_context_used = mono_method_check_context_used (invoke); +#if defined(MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE) && !defined(HAVE_WRITE_BARRIERS) + /* FIXME: SGEN support */ if (invoke_context_used == 0) { + MonoInst *target_ins; + ip += 6; if (cfg->verbose_level > 3) g_print ("converting (in B%d: stack: %d) %s", bblock->block_num, (int)(sp - stack_start), mono_disasm_code_one (NULL, method, ip, NULL)); @@ -9366,9 +9385,9 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b sp ++; break; } +#endif } } -#endif argconst = emit_get_rgctx_method (cfg, context_used, cmethod, MONO_RGCTX_INFO_METHOD); ins = mono_emit_jit_icall (cfg, mono_ldftn, &argconst); @@ -9819,39 +9838,38 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b cfg->exception_type = MONO_EXCEPTION_INVALID_PROGRAM; cfg->exception_message = g_strdup_printf ("Method %s is too complex.", mname); g_free (mname); + mono_metadata_free_mh (header); + mono_basic_block_free (original_bb); return -1; } if ((cfg->verbose_level > 2) && (cfg->method == method)) mono_print_code (cfg, "AFTER METHOD-TO-IR"); + mono_metadata_free_mh (header); + mono_basic_block_free (original_bb); return inline_costs; exception_exit: g_assert (cfg->exception_type != MONO_EXCEPTION_NONE); - g_slist_free (class_inits); - mono_basic_block_free (bb); - dont_inline = g_list_remove (dont_inline, method); - return -1; + goto cleanup; inline_failure: - g_slist_free (class_inits); - mono_basic_block_free (bb); - dont_inline = g_list_remove (dont_inline, method); - return -1; + goto cleanup; load_error: - g_slist_free (class_inits); - mono_basic_block_free (bb); - dont_inline = g_list_remove (dont_inline, method); cfg->exception_type = MONO_EXCEPTION_TYPE_LOAD; - return -1; + goto cleanup; unverified: + set_exception_type_from_invalid_il (cfg, method, ip); + goto cleanup; + + cleanup: g_slist_free (class_inits); - mono_basic_block_free (bb); + mono_basic_block_free (original_bb); dont_inline = g_list_remove (dont_inline, method); - set_exception_type_from_invalid_il (cfg, method, ip); + mono_metadata_free_mh (header); return -1; }