X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini.c;h=e9a5ca2101f4ec5caedf466613dd494ba25cd9ec;hb=279b47e476642431c7f96e105ed32f133d6ed5a3;hp=af81c97d37bc848f434ceb11b82f3f4473de54fa;hpb=9f263368a98b07a5e33dd12da8164b3d521fd767;p=mono.git diff --git a/mono/mini/mini.c b/mono/mini/mini.c index af81c97d37b..e9a5ca2101f 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -59,6 +59,7 @@ #include #include #include +#include #include #include #include @@ -195,8 +196,6 @@ static int mini_verbose = 0; #define mono_jit_unlock() LeaveCriticalSection (&jit_mutex) static CRITICAL_SECTION jit_mutex; -static GHashTable *rgctx_lazy_fetch_trampoline_hash = NULL; - static MonoCodeManager *global_codeman = NULL; /* FIXME: Make this static again */ @@ -950,7 +949,7 @@ mono_unlink_bblock (MonoCompile *cfg, MonoBasicBlock *from, MonoBasicBlock* to) * * Return whenever BB1 and BB2 are linked in the CFG. */ -static gboolean +gboolean mono_bblocks_linked (MonoBasicBlock *bb1, MonoBasicBlock *bb2) { int i; @@ -1168,8 +1167,8 @@ split_bblock (MonoCompile *cfg, MonoBasicBlock *first, MonoBasicBlock *second) { } } -static guint32 -reverse_branch_op (guint32 opcode) +guint32 +mono_reverse_branch_op (guint32 opcode) { static const int reverse_map [] = { CEE_BNE_UN, CEE_BLT, CEE_BLE, CEE_BGT, CEE_BGE, @@ -1928,6 +1927,8 @@ mono_op_imm_to_op (int opcode) return OP_ISUB; case OP_LSUB_IMM: return OP_LSUB; + case OP_IMUL_IMM: + return OP_IMUL; case OP_AND_IMM: #if SIZEOF_VOID_P == 4 return OP_IAND; @@ -4924,48 +4925,12 @@ get_runtime_generic_context (MonoCompile *cfg, MonoMethod *method, int context_u } } -gpointer -mini_create_rgctx_lazy_fetch_trampoline (guint32 offset) -{ - static gboolean inited = FALSE; - static int num_trampolines = 0; - - gpointer tramp, ptr; - - mono_jit_lock (); - if (rgctx_lazy_fetch_trampoline_hash) - tramp = g_hash_table_lookup (rgctx_lazy_fetch_trampoline_hash, GUINT_TO_POINTER (offset)); - else - tramp = NULL; - mono_jit_unlock (); - if (tramp) - return tramp; - - tramp = mono_arch_create_rgctx_lazy_fetch_trampoline (offset); - ptr = mono_create_ftnptr (mono_get_root_domain (), tramp); - - mono_jit_lock (); - if (!rgctx_lazy_fetch_trampoline_hash) - rgctx_lazy_fetch_trampoline_hash = g_hash_table_new (NULL, NULL); - g_hash_table_insert (rgctx_lazy_fetch_trampoline_hash, GUINT_TO_POINTER (offset), ptr); - mono_jit_unlock (); - - if (!inited) { - mono_counters_register ("RGCTX num lazy fetch trampolines", - MONO_COUNTER_GENERICS | MONO_COUNTER_INT, &num_trampolines); - inited = TRUE; - } - num_trampolines++; - - return ptr; -} - static MonoInst* get_runtime_generic_context_other_table_ptr (MonoCompile *cfg, MonoBasicBlock *bblock, MonoInst *rgc_ptr, guint32 slot, const unsigned char *ip) { MonoMethodSignature *sig = helper_sig_rgctx_lazy_fetch_trampoline; - guint8 *tramp = mini_create_rgctx_lazy_fetch_trampoline (slot); + guint8 *tramp = mono_create_rgctx_lazy_fetch_trampoline (slot); int temp; MonoInst *field; @@ -6297,6 +6262,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b mrgctx = mono_method_lookup_rgctx (mono_class_vtable (cfg->domain, cmethod->klass), mini_method_get_context (cmethod)->method_inst); + cfg->disable_aot = TRUE; NEW_PCONST (cfg, vtable_arg, mrgctx); } @@ -6360,11 +6326,10 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b generic_context, rgctx, MONO_RGCTX_INFO_METHOD, ip); NEW_TEMPLOADA (cfg, iargs [2], this_arg_temp->inst_c0); temp = mono_emit_jit_icall (cfg, bblock, - mono_helper_compile_generic_method_wo_context, iargs, ip); + mono_helper_compile_generic_method, iargs, ip); } else { NEW_METHODCONST (cfg, iargs [1], cmethod); - NEW_PCONST (cfg, iargs [2], mono_method_get_context (cmethod)); - NEW_TEMPLOADA (cfg, iargs [3], this_arg_temp->inst_c0); + NEW_TEMPLOADA (cfg, iargs [2], this_arg_temp->inst_c0); temp = mono_emit_jit_icall (cfg, bblock, mono_helper_compile_generic_method, iargs, ip); } @@ -8044,7 +8009,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b call = mono_emit_call_args (cfg, bblock, sig, NULL, FALSE, FALSE, ip, FALSE); call->inst.opcode = OP_TRAMPCALL_VTABLE; - call->fptr = mono_get_trampoline_code (MONO_TRAMPOLINE_GENERIC_CLASS_INIT); + call->fptr = mono_create_generic_class_init_trampoline (); call->inst.inst_left = vtable; @@ -8623,7 +8588,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b if (sp [2]->opcode == OP_PCONST && sp [2]->inst_p0 == NULL) { MonoInst *load; NEW_LDELEMA (cfg, load, sp, mono_defaults.object_class); - MONO_INST_NEW (cfg, ins, stelem_to_stind [*ip - CEE_STELEM_I]); + MONO_INST_NEW (cfg, ins, CEE_STIND_REF); ins->inst_left = load; ins->inst_right = sp [2]; MONO_ADD_INS (bblock, ins); @@ -9457,10 +9422,7 @@ mono_method_to_ir (MonoCompile *cfg, MonoMethod *method, MonoBasicBlock *start_b } else { NEW_METHODCONST (cfg, argconst, cmethod); } - if (method->wrapper_type != MONO_WRAPPER_SYNCHRONIZED) - temp = mono_emit_jit_icall (cfg, bblock, mono_ldftn, &argconst, ip); - else - temp = mono_emit_jit_icall (cfg, bblock, mono_ldftn_nosync, &argconst, ip); + temp = mono_emit_jit_icall (cfg, bblock, mono_ldftn, &argconst, ip); NEW_TEMPLOAD (cfg, *sp, temp); sp ++; @@ -10114,7 +10076,7 @@ mono_icall_get_wrapper (MonoJitICallInfo* callinfo) wrapper = mono_marshal_get_icall_wrapper (callinfo->sig, name, callinfo->func, check_for_pending_exc); g_free (name); - trampoline = mono_create_ftnptr (domain, mono_create_jit_trampoline_in_domain (domain, wrapper, TRUE)); + trampoline = mono_create_ftnptr (domain, mono_create_jit_trampoline_in_domain (domain, wrapper)); mono_register_jit_icall_wrapper (callinfo, trampoline); callinfo->trampoline = trampoline; @@ -10150,19 +10112,6 @@ typedef struct { GSList *slots; } StackSlotInfo; -static inline GSList* -g_slist_prepend_mempool (MonoMemPool *mp, GSList *list, - gpointer data) -{ - GSList *new_list; - - new_list = mono_mempool_alloc (mp, sizeof (GSList)); - new_list->data = data; - new_list->next = list; - - return new_list; -} - static gint compare_by_interval_start_pos_func (gconstpointer a, gconstpointer b) { @@ -10991,8 +10940,8 @@ mono_destroy_compile (MonoCompile *cfg) mono_mempool_destroy (cfg->mempool); g_list_free (cfg->ldstr_list); g_hash_table_destroy (cfg->token_info_hash); - - g_free (cfg->reverse_inst_list); + if (cfg->abs_patches) + g_hash_table_destroy (cfg->abs_patches); g_free (cfg->varinfo); g_free (cfg->vars); @@ -11306,6 +11255,11 @@ mono_patch_info_dup_mp (MonoMemPool *mp, MonoJumpInfo *patch_info) res->data.table = mono_mempool_alloc (mp, sizeof (MonoJumpInfoBBTable)); memcpy (res->data.table, patch_info->data.table, sizeof (MonoJumpInfoBBTable)); break; + case MONO_PATCH_INFO_RGCTX_FETCH: + res->data.rgctx_entry = mono_mempool_alloc (mp, sizeof (MonoJumpInfoRgctxEntry)); + memcpy (res->data.rgctx_entry, patch_info->data.rgctx_entry, sizeof (MonoJumpInfoRgctxEntry)); + res->data.rgctx_entry->data = mono_patch_info_dup_mp (mp, res->data.rgctx_entry->data); + break; default: break; } @@ -11329,16 +11283,16 @@ mono_patch_info_hash (gconstpointer data) case MONO_PATCH_INFO_CLASS: case MONO_PATCH_INFO_IID: case MONO_PATCH_INFO_ADJUSTED_IID: - return (ji->type << 8) | (gssize)ji->data.klass; - case MONO_PATCH_INFO_FIELD: - case MONO_PATCH_INFO_SFLDA: - return (ji->type << 8) | (gssize)ji->data.field; + case MONO_PATCH_INFO_CLASS_INIT: case MONO_PATCH_INFO_METHODCONST: case MONO_PATCH_INFO_METHOD: case MONO_PATCH_INFO_METHOD_JUMP: - return (ji->type << 8) | (gssize)ji->data.method; case MONO_PATCH_INFO_IMAGE: - return (ji->type << 8) | (gssize)ji->data.image; + case MONO_PATCH_INFO_INTERNAL_METHOD: + case MONO_PATCH_INFO_JIT_ICALL_ADDR: + case MONO_PATCH_INFO_FIELD: + case MONO_PATCH_INFO_SFLDA: + return (ji->type << 8) | (gssize)ji->data.target; default: return (ji->type << 8); } @@ -11371,7 +11325,7 @@ mono_patch_info_equal (gconstpointer ka, gconstpointer kb) return 0; break; default: - if (ji1->data.name != ji2->data.name) + if (ji1->data.target != ji2->data.target) return 0; break; } @@ -11411,18 +11365,9 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, target = mono_icall_get_wrapper (mi); break; } - case MONO_PATCH_INFO_METHOD_JUMP: { - GSList *list; - - /* get the trampoline to the method from the domain */ - target = mono_create_jump_trampoline (domain, patch_info->data.method, TRUE); - if (!domain->jump_target_hash) - domain->jump_target_hash = g_hash_table_new (NULL, NULL); - list = g_hash_table_lookup (domain->jump_target_hash, patch_info->data.method); - list = g_slist_prepend (list, ip); - g_hash_table_insert (domain->jump_target_hash, patch_info->data.method, list); + case MONO_PATCH_INFO_METHOD_JUMP: + target = mono_create_jump_trampoline (domain, patch_info->data.method, FALSE); break; - } case MONO_PATCH_INFO_METHOD: if (patch_info->data.method == method) { target = code; @@ -11430,7 +11375,7 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, /* get the trampoline to the method from the domain */ if (method && method->wrapper_type == MONO_WRAPPER_STATIC_RGCTX_INVOKE) { target = mono_create_jit_trampoline_in_domain (mono_domain_get (), - patch_info->data.method, FALSE); + patch_info->data.method); } else { target = mono_create_jit_trampoline (patch_info->data.method); } @@ -11558,11 +11503,40 @@ mono_resolve_patch_target (MonoMethod *method, MonoDomain *domain, guint8 *code, case MONO_PATCH_INFO_INTERRUPTION_REQUEST_FLAG: target = mono_thread_interruption_request_flag (); break; + case MONO_PATCH_INFO_METHOD_RGCTX: + target = mono_method_lookup_rgctx (mono_class_vtable (domain, patch_info->data.method->klass), mini_method_get_context (patch_info->data.method)->method_inst); + break; case MONO_PATCH_INFO_BB_OVF: case MONO_PATCH_INFO_EXC_OVF: case MONO_PATCH_INFO_GOT_OFFSET: case MONO_PATCH_INFO_NONE: break; + case MONO_PATCH_INFO_RGCTX_FETCH: { + MonoJumpInfoRgctxEntry *entry = patch_info->data.rgctx_entry; + guint32 slot = -1; + + switch (entry->data->type) { + case MONO_PATCH_INFO_CLASS: + slot = mono_method_lookup_or_register_other_info (entry->method, entry->in_mrgctx, &entry->data->data.klass->byval_arg, entry->info_type, mono_method_get_context (entry->method)); + break; + case MONO_PATCH_INFO_METHOD: + case MONO_PATCH_INFO_METHODCONST: + slot = mono_method_lookup_or_register_other_info (entry->method, entry->in_mrgctx, entry->data->data.method, entry->info_type, mono_method_get_context (entry->method)); + break; + case MONO_PATCH_INFO_FIELD: + slot = mono_method_lookup_or_register_other_info (entry->method, entry->in_mrgctx, entry->data->data.field, entry->info_type, mono_method_get_context (entry->method)); + break; + default: + g_assert_not_reached (); + break; + } + + target = mono_create_rgctx_lazy_fetch_trampoline (slot); + break; + } + case MONO_PATCH_INFO_GENERIC_CLASS_INIT: + target = mono_create_generic_class_init_trampoline (); + break; default: g_assert_not_reached (); } @@ -11644,672 +11618,6 @@ decompose_pass (MonoCompile *cfg) { } } -static void -nullify_basic_block (MonoBasicBlock *bb) -{ - bb->in_count = 0; - bb->out_count = 0; - bb->in_bb = NULL; - bb->out_bb = NULL; - bb->next_bb = NULL; - bb->code = bb->last_ins = NULL; - bb->cil_code = NULL; -} - -static void -replace_out_block (MonoBasicBlock *bb, MonoBasicBlock *orig, MonoBasicBlock *repl) -{ - int i; - - for (i = 0; i < bb->out_count; i++) { - MonoBasicBlock *ob = bb->out_bb [i]; - if (ob == orig) { - if (!repl) { - if (bb->out_count > 1) { - bb->out_bb [i] = bb->out_bb [bb->out_count - 1]; - } - bb->out_count--; - } else { - bb->out_bb [i] = repl; - } - } - } -} - -static void -replace_in_block (MonoBasicBlock *bb, MonoBasicBlock *orig, MonoBasicBlock *repl) -{ - int i; - - for (i = 0; i < bb->in_count; i++) { - MonoBasicBlock *ib = bb->in_bb [i]; - if (ib == orig) { - if (!repl) { - if (bb->in_count > 1) { - bb->in_bb [i] = bb->in_bb [bb->in_count - 1]; - } - bb->in_count--; - } else { - bb->in_bb [i] = repl; - } - } - } -} - -static void -replace_out_block_in_code (MonoBasicBlock *bb, MonoBasicBlock *orig, MonoBasicBlock *repl) { - MonoInst *ins; - - for (ins = bb->code; ins != NULL; ins = ins->next) { - switch (ins->opcode) { - case OP_BR: - if (ins->inst_target_bb == orig) - ins->inst_target_bb = repl; - break; - case OP_CALL_HANDLER: - if (ins->inst_target_bb == orig) - ins->inst_target_bb = repl; - break; - case OP_SWITCH: { - int i; - int n = GPOINTER_TO_INT (ins->klass); - for (i = 0; i < n; i++ ) { - if (ins->inst_many_bb [i] == orig) - ins->inst_many_bb [i] = repl; - } - break; - } - default: - if (MONO_IS_COND_BRANCH_OP (ins)) { - if (ins->inst_true_bb == orig) - ins->inst_true_bb = repl; - if (ins->inst_false_bb == orig) - ins->inst_false_bb = repl; - } else if (MONO_IS_JUMP_TABLE (ins)) { - int i; - MonoJumpInfoBBTable *table = MONO_JUMP_TABLE_FROM_INS (ins); - for (i = 0; i < table->table_size; i++ ) { - if (table->table [i] == orig) - table->table [i] = repl; - } - } - - break; - } - } -} - -/** - * Check if a bb is useless (is just made of NOPs and ends with an - * unconditional branch, or nothing). - * If it is so, unlink it from the CFG and nullify it, and return TRUE. - * Otherwise, return FALSE; - */ -static gboolean -remove_block_if_useless (MonoCompile *cfg, MonoBasicBlock *bb, MonoBasicBlock *previous_bb) { - MonoBasicBlock *target_bb = NULL; - MonoInst *inst; - - /* Do not touch handlers */ - if (bb->region != -1) { - bb->not_useless = TRUE; - return FALSE; - } - - MONO_BB_FOR_EACH_INS (bb, inst) { - switch (inst->opcode) { - case OP_NOP: - break; - case OP_BR: - target_bb = inst->inst_target_bb; - break; - default: - bb->not_useless = TRUE; - return FALSE; - } - } - - if (target_bb == NULL) { - if ((bb->out_count == 1) && (bb->out_bb [0] == bb->next_bb)) { - target_bb = bb->next_bb; - } else { - /* Do not touch empty BBs that do not "fall through" to their next BB (like the exit BB) */ - return FALSE; - } - } - - /* Do not touch BBs following a switch (they are the "default" branch) */ - if ((previous_bb->last_ins != NULL) && (previous_bb->last_ins->opcode == OP_SWITCH)) { - return FALSE; - } - - /* Do not touch BBs following the entry BB and jumping to something that is not */ - /* thiry "next" bb (the entry BB cannot contain the branch) */ - if ((previous_bb == cfg->bb_entry) && (bb->next_bb != target_bb)) { - return FALSE; - } - - /* - * Do not touch BBs following a try block as the code in - * mini_method_compile needs them to compute the length of the try block. - */ - if (MONO_BBLOCK_IS_IN_REGION (previous_bb, MONO_REGION_TRY)) - return FALSE; - - /* Check that there is a target BB, and that bb is not an empty loop (Bug 75061) */ - if ((target_bb != NULL) && (target_bb != bb)) { - int i; - - if (cfg->verbose_level > 1) { - printf ("remove_block_if_useless, removed BB%d\n", bb->block_num); - } - - /* unlink_bblock () modifies the bb->in_bb array so can't use a for loop here */ - while (bb->in_count) { - MonoBasicBlock *in_bb = bb->in_bb [0]; - mono_unlink_bblock (cfg, in_bb, bb); - link_bblock (cfg, in_bb, target_bb); - replace_out_block_in_code (in_bb, bb, target_bb); - } - - mono_unlink_bblock (cfg, bb, target_bb); - - if ((previous_bb != cfg->bb_entry) && - (previous_bb->region == bb->region) && - ((previous_bb->last_ins == NULL) || - ((previous_bb->last_ins->opcode != OP_BR) && - (! (MONO_IS_COND_BRANCH_OP (previous_bb->last_ins))) && - (previous_bb->last_ins->opcode != OP_SWITCH)))) { - for (i = 0; i < previous_bb->out_count; i++) { - if (previous_bb->out_bb [i] == target_bb) { - MonoInst *jump; - MONO_INST_NEW (cfg, jump, OP_BR); - MONO_ADD_INS (previous_bb, jump); - jump->cil_code = previous_bb->cil_code; - jump->inst_target_bb = target_bb; - break; - } - } - } - - previous_bb->next_bb = bb->next_bb; - nullify_basic_block (bb); - - return TRUE; - } else { - return FALSE; - } -} - -void -mono_merge_basic_blocks (MonoCompile *cfg, MonoBasicBlock *bb, MonoBasicBlock *bbn) -{ - MonoInst *inst; - MonoBasicBlock *prev_bb; - int i; - - bb->has_array_access |= bbn->has_array_access; - bb->extended |= bbn->extended; - - mono_unlink_bblock (cfg, bb, bbn); - for (i = 0; i < bbn->out_count; ++i) - mono_link_bblock (cfg, bb, bbn->out_bb [i]); - while (bbn->out_count) - mono_unlink_bblock (cfg, bbn, bbn->out_bb [0]); - - /* Handle the branch at the end of the bb */ - for (inst = bb->code; inst != NULL; inst = inst->next) { - if (inst->opcode == OP_CALL_HANDLER) { - g_assert (inst->inst_target_bb == bbn); - NULLIFY_INS (inst); - } - if (MONO_IS_JUMP_TABLE (inst)) { - int i; - MonoJumpInfoBBTable *table = MONO_JUMP_TABLE_FROM_INS (inst); - for (i = 0; i < table->table_size; i++ ) { - /* Might be already NULL from a previous merge */ - if (table->table [i]) - g_assert (table->table [i] == bbn); - table->table [i] = NULL; - } - /* Can't nullify this as later instructions depend on it */ - } - } - if (bb->last_ins && MONO_IS_COND_BRANCH_OP (bb->last_ins)) { - g_assert (bb->last_ins->inst_false_bb == bbn); - bb->last_ins->inst_false_bb = NULL; - bb->extended = TRUE; - } else if (bb->last_ins && MONO_IS_BRANCH_OP (bb->last_ins)) { - NULLIFY_INS (bb->last_ins); - } - - if (bb->last_ins) { - if (bbn->code) { - bb->last_ins->next = bbn->code; - bbn->code->prev = bb->last_ins; - bb->last_ins = bbn->last_ins; - } - } else { - bb->code = bbn->code; - bb->last_ins = bbn->last_ins; - } - for (prev_bb = cfg->bb_entry; prev_bb && prev_bb->next_bb != bbn; prev_bb = prev_bb->next_bb) - ; - if (prev_bb) { - prev_bb->next_bb = bbn->next_bb; - } else { - /* bbn might not be in the bb list yet */ - if (bb->next_bb == bbn) - bb->next_bb = bbn->next_bb; - } - nullify_basic_block (bbn); -} - -static void -move_basic_block_to_end (MonoCompile *cfg, MonoBasicBlock *bb) -{ - MonoBasicBlock *bbn, *next; - - next = bb->next_bb; - - /* Find the previous */ - for (bbn = cfg->bb_entry; bbn->next_bb && bbn->next_bb != bb; bbn = bbn->next_bb) - ; - if (bbn->next_bb) { - bbn->next_bb = bb->next_bb; - } - - /* Find the last */ - for (bbn = cfg->bb_entry; bbn->next_bb; bbn = bbn->next_bb) - ; - bbn->next_bb = bb; - bb->next_bb = NULL; - - /* Add a branch */ - if (next && (!bb->last_ins || ((bb->last_ins->opcode != OP_NOT_REACHED) && (bb->last_ins->opcode != OP_BR) && (bb->last_ins->opcode != OP_BR_REG) && (!MONO_IS_COND_BRANCH_OP (bb->last_ins))))) { - MonoInst *ins; - - MONO_INST_NEW (cfg, ins, OP_BR); - MONO_ADD_INS (bb, ins); - link_bblock (cfg, bb, next); - ins->inst_target_bb = next; - } -} - -/* - * mono_remove_block: - * - * Remove BB from the control flow graph - */ -void -mono_remove_bblock (MonoCompile *cfg, MonoBasicBlock *bb) -{ - MonoBasicBlock *tmp_bb; - - for (tmp_bb = cfg->bb_entry; tmp_bb && tmp_bb->next_bb != bb; tmp_bb = tmp_bb->next_bb) - ; - - g_assert (tmp_bb); - tmp_bb->next_bb = bb->next_bb; -} - -/* checks that a and b represent the same instructions, conservatively, - * it can return FALSE also for two trees that are equal. - * FIXME: also make sure there are no side effects. - */ -static int -same_trees (MonoInst *a, MonoInst *b) -{ - int arity; - if (a->opcode != b->opcode) - return FALSE; - arity = mono_burg_arity [a->opcode]; - if (arity == 1) { - if (a->ssa_op == b->ssa_op && a->ssa_op == MONO_SSA_LOAD && a->inst_i0 == b->inst_i0) - return TRUE; - return same_trees (a->inst_left, b->inst_left); - } else if (arity == 2) { - return same_trees (a->inst_left, b->inst_left) && same_trees (a->inst_right, b->inst_right); - } else if (arity == 0) { - switch (a->opcode) { - case OP_ICONST: - return a->inst_c0 == b->inst_c0; - default: - return FALSE; - } - } - return FALSE; -} - -static int -get_unsigned_condbranch (int opcode) -{ - switch (opcode) { - case CEE_BLE: return CEE_BLE_UN; - case CEE_BLT: return CEE_BLT_UN; - case CEE_BGE: return CEE_BGE_UN; - case CEE_BGT: return CEE_BGT_UN; - } - g_assert_not_reached (); - return 0; -} - -static int -tree_is_unsigned (MonoInst* ins) { - switch (ins->opcode) { - case OP_ICONST: - return (int)ins->inst_c0 >= 0; - /* array lengths are positive as are string sizes */ - case CEE_LDLEN: - case OP_STRLEN: - return TRUE; - case CEE_CONV_U1: - case CEE_CONV_U2: - case CEE_CONV_U4: - case CEE_CONV_OVF_U1: - case CEE_CONV_OVF_U2: - case CEE_CONV_OVF_U4: - return TRUE; - case CEE_LDIND_U1: - case CEE_LDIND_U2: - case CEE_LDIND_U4: - return TRUE; - default: - return FALSE; - } -} - -/* check if an unsigned compare can be used instead of two signed compares - * for (val < 0 || val > limit) conditionals. - * Returns TRUE if the optimization has been applied. - * Note that this can't be applied if the second arg is not positive... - */ -static int -try_unsigned_compare (MonoCompile *cfg, MonoBasicBlock *bb) -{ - MonoBasicBlock *truet, *falset; - MonoInst *cmp_inst = bb->last_ins->inst_left; - MonoInst *condb; - if (!cmp_inst->inst_right->inst_c0 == 0) - return FALSE; - truet = bb->last_ins->inst_true_bb; - falset = bb->last_ins->inst_false_bb; - if (falset->in_count != 1) - return FALSE; - condb = falset->last_ins; - /* target bb must have one instruction */ - if (!condb || (condb != falset->code)) - return FALSE; - if ((((condb->opcode == CEE_BLE || condb->opcode == CEE_BLT) && (condb->inst_false_bb == truet)) - || ((condb->opcode == CEE_BGE || condb->opcode == CEE_BGT) && (condb->inst_true_bb == truet))) - && same_trees (cmp_inst->inst_left, condb->inst_left->inst_left)) { - if (!tree_is_unsigned (condb->inst_left->inst_right)) - return FALSE; - condb->opcode = get_unsigned_condbranch (condb->opcode); - /* change the original condbranch to just point to the new unsigned check */ - bb->last_ins->opcode = OP_BR; - bb->last_ins->inst_target_bb = falset; - replace_out_block (bb, truet, NULL); - replace_in_block (truet, bb, NULL); - return TRUE; - } - return FALSE; -} - -/* - * Optimizes the branches on the Control Flow Graph - * - */ -void -mono_optimize_branches (MonoCompile *cfg) -{ - int i, changed = FALSE; - MonoBasicBlock *bb, *bbn; - guint32 niterations; - - /* - * Some crazy loops could cause the code below to go into an infinite - * loop, see bug #53003 for an example. To prevent this, we put an upper - * bound on the number of iterations. - */ - if (cfg->num_bblocks > 1000) - niterations = cfg->num_bblocks * 2; - else - niterations = 1000; - - do { - MonoBasicBlock *previous_bb; - changed = FALSE; - niterations --; - - /* we skip the entry block (exit is handled specially instead ) */ - for (previous_bb = cfg->bb_entry, bb = cfg->bb_entry->next_bb; bb; previous_bb = bb, bb = bb->next_bb) { - /* dont touch code inside exception clauses */ - if (bb->region != -1) - continue; - - if (!bb->not_useless && remove_block_if_useless (cfg, bb, previous_bb)) { - changed = TRUE; - continue; - } - - if ((bbn = bb->next_bb) && bbn->in_count == 0 && bb->region == bbn->region) { - if (cfg->verbose_level > 2) - g_print ("nullify block triggered %d\n", bbn->block_num); - - bb->next_bb = bbn->next_bb; - - for (i = 0; i < bbn->out_count; i++) - replace_in_block (bbn->out_bb [i], bbn, NULL); - - nullify_basic_block (bbn); - changed = TRUE; - } - - if (bb->out_count == 1) { - bbn = bb->out_bb [0]; - - /* conditional branches where true and false targets are the same can be also replaced with OP_BR */ - if (bb->last_ins && (bb->last_ins->opcode != OP_BR) && MONO_IS_COND_BRANCH_OP (bb->last_ins)) { - if (!cfg->new_ir) { - MonoInst *pop; - MONO_INST_NEW (cfg, pop, CEE_POP); - pop->inst_left = bb->last_ins->inst_left->inst_left; - mono_add_ins_to_end (bb, pop); - MONO_INST_NEW (cfg, pop, CEE_POP); - pop->inst_left = bb->last_ins->inst_left->inst_right; - mono_add_ins_to_end (bb, pop); - } - bb->last_ins->opcode = OP_BR; - bb->last_ins->inst_target_bb = bb->last_ins->inst_true_bb; - changed = TRUE; - if (cfg->verbose_level > 2) - g_print ("cond branch removal triggered in %d %d\n", bb->block_num, bb->out_count); - } - - if (bb->region == bbn->region && bb->next_bb == bbn) { - /* the block are in sequence anyway ... */ - - /* branches to the following block can be removed */ - if (bb->last_ins && bb->last_ins->opcode == OP_BR) { - bb->last_ins->opcode = OP_NOP; - changed = TRUE; - if (cfg->verbose_level > 2) - g_print ("br removal triggered %d -> %d\n", bb->block_num, bbn->block_num); - } - - if (bbn->in_count == 1 && !bb->extended) { - if (bbn != cfg->bb_exit) { - if (cfg->verbose_level > 2) - g_print ("block merge triggered %d -> %d\n", bb->block_num, bbn->block_num); - mono_merge_basic_blocks (cfg, bb, bbn); - changed = TRUE; - continue; - } - - //mono_print_bb_code (bb); - } - } - } - - if ((bbn = bb->next_bb) && bbn->in_count == 0 && bb->region == bbn->region) { - if (cfg->verbose_level > 2) { - g_print ("nullify block triggered %d\n", bbn->block_num); - } - bb->next_bb = bbn->next_bb; - - for (i = 0; i < bbn->out_count; i++) - replace_in_block (bbn->out_bb [i], bbn, NULL); - - nullify_basic_block (bbn); - changed = TRUE; - continue; - } - - if (bb->out_count == 1) { - bbn = bb->out_bb [0]; - - if (bb->last_ins && bb->last_ins->opcode == OP_BR) { - bbn = bb->last_ins->inst_target_bb; - if (bb->region == bbn->region && bbn->code && bbn->code->opcode == OP_BR && - bbn->code->inst_target_bb->region == bb->region) { - - if (cfg->verbose_level > 2) - g_print ("branch to branch triggered %d -> %d -> %d\n", bb->block_num, bbn->block_num, bbn->code->inst_target_bb->block_num); - - replace_in_block (bbn, bb, NULL); - replace_out_block (bb, bbn, bbn->code->inst_target_bb); - link_bblock (cfg, bb, bbn->code->inst_target_bb); - bb->last_ins->inst_target_bb = bbn->code->inst_target_bb; - changed = TRUE; - continue; - } - } - } else if (bb->out_count == 2) { - if (bb->last_ins && MONO_IS_COND_BRANCH_NOFP (bb->last_ins)) { - int branch_result; - MonoBasicBlock *taken_branch_target = NULL, *untaken_branch_target = NULL; - - if (cfg->new_ir) { - if (bb->last_ins->flags & MONO_INST_CFOLD_TAKEN) - branch_result = BRANCH_TAKEN; - else if (bb->last_ins->flags & MONO_INST_CFOLD_NOT_TAKEN) - branch_result = BRANCH_NOT_TAKEN; - else - branch_result = BRANCH_UNDEF; - } - else - branch_result = mono_eval_cond_branch (bb->last_ins); - - if (branch_result == BRANCH_TAKEN) { - taken_branch_target = bb->last_ins->inst_true_bb; - untaken_branch_target = bb->last_ins->inst_false_bb; - } else if (branch_result == BRANCH_NOT_TAKEN) { - taken_branch_target = bb->last_ins->inst_false_bb; - untaken_branch_target = bb->last_ins->inst_true_bb; - } - if (taken_branch_target) { - /* if mono_eval_cond_branch () is ever taken to handle - * non-constant values to compare, issue a pop here. - */ - bb->last_ins->opcode = OP_BR; - bb->last_ins->inst_target_bb = taken_branch_target; - if (!bb->extended) - mono_unlink_bblock (cfg, bb, untaken_branch_target); - changed = TRUE; - continue; - } - bbn = bb->last_ins->inst_true_bb; - if (bb->region == bbn->region && bbn->code && bbn->code->opcode == OP_BR && - bbn->code->inst_target_bb->region == bb->region) { - if (cfg->verbose_level > 2) - g_print ("cbranch1 to branch triggered %d -> (%d) %d (0x%02x)\n", - bb->block_num, bbn->block_num, bbn->code->inst_target_bb->block_num, - bbn->code->opcode); - - /* - * Unlink, then relink bblocks to avoid various - * tricky situations when the two targets of the branch - * are equal, or will become equal after the change. - */ - mono_unlink_bblock (cfg, bb, bb->last_ins->inst_true_bb); - mono_unlink_bblock (cfg, bb, bb->last_ins->inst_false_bb); - - bb->last_ins->inst_true_bb = bbn->code->inst_target_bb; - - link_bblock (cfg, bb, bb->last_ins->inst_true_bb); - link_bblock (cfg, bb, bb->last_ins->inst_false_bb); - - changed = TRUE; - continue; - } - - bbn = bb->last_ins->inst_false_bb; - if (bbn && bb->region == bbn->region && bbn->code && bbn->code->opcode == OP_BR && - bbn->code->inst_target_bb->region == bb->region) { - if (cfg->verbose_level > 2) - g_print ("cbranch2 to branch triggered %d -> (%d) %d (0x%02x)\n", - bb->block_num, bbn->block_num, bbn->code->inst_target_bb->block_num, - bbn->code->opcode); - - mono_unlink_bblock (cfg, bb, bb->last_ins->inst_true_bb); - mono_unlink_bblock (cfg, bb, bb->last_ins->inst_false_bb); - - bb->last_ins->inst_false_bb = bbn->code->inst_target_bb; - - link_bblock (cfg, bb, bb->last_ins->inst_true_bb); - link_bblock (cfg, bb, bb->last_ins->inst_false_bb); - - changed = TRUE; - continue; - } - - bbn = bb->last_ins->inst_false_bb; - /* - * If bb is an extended bb, it could contain an inside branch to bbn. - * FIXME: Enable the optimization if that is not true. - * If bblocks_linked () is true, then merging bb and bbn - * would require addition of an extra branch at the end of bbn - * slowing down loops. - */ - if (cfg->new_ir && bbn && bb->region == bbn->region && bbn->in_count == 1 && cfg->enable_extended_bblocks && bbn != cfg->bb_exit && !bb->extended && !bbn->out_of_line && !mono_bblocks_linked (bbn, bb)) { - g_assert (bbn->in_bb [0] == bb); - if (cfg->verbose_level > 2) - g_print ("merge false branch target triggered BB%d -> BB%d\n", bb->block_num, bbn->block_num); - mono_merge_basic_blocks (cfg, bb, bbn); - changed = TRUE; - continue; - } - } - - /* detect and optimize to unsigned compares checks like: if (v < 0 || v > limit */ - if (bb->last_ins && bb->last_ins->opcode == CEE_BLT && !cfg->new_ir && bb->last_ins->inst_left->inst_right->opcode == OP_ICONST) { - if (try_unsigned_compare (cfg, bb)) { - /*g_print ("applied in bb %d (->%d) %s\n", bb->block_num, bb->last_ins->inst_target_bb->block_num, mono_method_full_name (cfg->method, TRUE));*/ - changed = TRUE; - continue; - } - } - - if (bb->last_ins && MONO_IS_COND_BRANCH_NOFP (bb->last_ins)) { - if (bb->last_ins->inst_false_bb && bb->last_ins->inst_false_bb->out_of_line && (bb->region == bb->last_ins->inst_false_bb->region)) { - /* Reverse the branch */ - bb->last_ins->opcode = reverse_branch_op (bb->last_ins->opcode); - bbn = bb->last_ins->inst_false_bb; - bb->last_ins->inst_false_bb = bb->last_ins->inst_true_bb; - bb->last_ins->inst_true_bb = bbn; - - move_basic_block_to_end (cfg, bb->last_ins->inst_true_bb); - if (cfg->verbose_level > 2) - g_print ("cbranch to throw block triggered %d.\n", - bb->block_num); - } - } - } - } - } while (changed && (niterations > 0)); -} - static void mono_compile_create_vars (MonoCompile *cfg) { @@ -12496,7 +11804,7 @@ mini_select_instructions (MonoCompile *cfg) bb->last_ins->inst_true_bb = bb->last_ins->inst_false_bb; bb->last_ins->inst_false_bb = tmp; - bb->last_ins->opcode = reverse_branch_op (bb->last_ins->opcode); + bb->last_ins->opcode = mono_reverse_branch_op (bb->last_ins->opcode); } else { MonoInst *ins; @@ -12721,7 +12029,7 @@ mono_codegen (MonoCompile *cfg) if (cfg->method->dynamic) { guint unwindlen = 0; -#ifdef _WIN64 +#ifdef MONO_ARCH_HAVE_UNWIND_TABLE unwindlen = mono_arch_unwindinfo_get_size (cfg->arch.unwindinfo); #endif /* Allocate the code into a separate memory pool so it can be freed */ @@ -12752,6 +12060,11 @@ mono_codegen (MonoCompile *cfg) switch (patch_info->type) { case MONO_PATCH_INFO_ABS: { MonoJitICallInfo *info = mono_find_jit_icall_by_addr (patch_info->data.target); + + /* + * Change patches of type MONO_PATCH_INFO_ABS into patches describing the + * absolute address. + */ if (info) { //printf ("TEST %s %p\n", info->name, patch_info->data.target); // FIXME: CLEAN UP THIS MESS. @@ -12777,19 +12090,33 @@ mono_codegen (MonoCompile *cfg) } } } - else { + + if (patch_info->type == MONO_PATCH_INFO_ABS && !cfg->new_ir) { MonoVTable *vtable = mono_find_class_init_trampoline_by_addr (patch_info->data.target); if (vtable) { patch_info->type = MONO_PATCH_INFO_CLASS_INIT; patch_info->data.klass = vtable->klass; - } else { - MonoClass *klass = mono_find_delegate_trampoline_by_addr (patch_info->data.target); - if (klass) { - patch_info->type = MONO_PATCH_INFO_DELEGATE_TRAMPOLINE; - patch_info->data.klass = klass; + } + } + + if (patch_info->type == MONO_PATCH_INFO_ABS) { + MonoClass *klass = mono_find_delegate_trampoline_by_addr (patch_info->data.target); + if (klass) { + patch_info->type = MONO_PATCH_INFO_DELEGATE_TRAMPOLINE; + patch_info->data.klass = klass; + } + } + + if (patch_info->type == MONO_PATCH_INFO_ABS) { + if (cfg->abs_patches) { + MonoJumpInfo *abs_ji = g_hash_table_lookup (cfg->abs_patches, patch_info->data.target); + if (abs_ji) { + patch_info->type = abs_ji->type; + patch_info->data.target = abs_ji->data.target; } } } + break; } case MONO_PATCH_INFO_SWITCH: { @@ -12817,6 +12144,20 @@ mono_codegen (MonoCompile *cfg) patch_info->data.table->table = (MonoBasicBlock**)table; break; } + case MONO_PATCH_INFO_METHOD_JUMP: { + GSList *list; + MonoDomain *domain = cfg->domain; + unsigned char *ip = cfg->native_code + patch_info->ip.i; + + mono_domain_lock (domain); + if (!domain->jump_target_hash) + domain->jump_target_hash = g_hash_table_new (NULL, NULL); + list = g_hash_table_lookup (domain->jump_target_hash, patch_info->data.method); + list = g_slist_prepend (list, ip); + g_hash_table_insert (domain->jump_target_hash, patch_info->data.method, list); + mono_domain_unlock (domain); + break; + } default: /* do nothing */ break; @@ -12873,135 +12214,6 @@ if (valgrind_register){ #endif } -void -mono_remove_critical_edges (MonoCompile *cfg) -{ - MonoBasicBlock *bb; - MonoBasicBlock *previous_bb; - - if (cfg->verbose_level > 3) { - for (bb = cfg->bb_entry; bb; bb = bb->next_bb) { - int i; - printf ("remove_critical_edges, BEFORE BB%d (in:", bb->block_num); - for (i = 0; i < bb->in_count; i++) { - printf (" %d", bb->in_bb [i]->block_num); - } - printf (") (out:"); - for (i = 0; i < bb->out_count; i++) { - printf (" %d", bb->out_bb [i]->block_num); - } - printf (")"); - if (bb->last_ins != NULL) { - printf (" "); - mono_print_tree (bb->last_ins); - } - printf ("\n"); - } - } - - for (previous_bb = cfg->bb_entry, bb = previous_bb->next_bb; bb != NULL; previous_bb = previous_bb->next_bb, bb = bb->next_bb) { - if (bb->in_count > 1) { - int in_bb_index; - for (in_bb_index = 0; in_bb_index < bb->in_count; in_bb_index++) { - MonoBasicBlock *in_bb = bb->in_bb [in_bb_index]; - if (in_bb->out_count > 1) { - MonoBasicBlock *new_bb = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock)); - new_bb->block_num = cfg->num_bblocks++; -// new_bb->real_offset = bb->real_offset; - new_bb->region = bb->region; - - /* Do not alter the CFG while altering the BB list */ - if (previous_bb->region == bb->region) { - if (previous_bb != cfg->bb_entry) { - /* If previous_bb "followed through" to bb, */ - /* keep it linked with a OP_BR */ - if ((previous_bb->last_ins == NULL) || - ((previous_bb->last_ins->opcode != OP_BR) && - (! (MONO_IS_COND_BRANCH_OP (previous_bb->last_ins))) && - (previous_bb->last_ins->opcode != OP_SWITCH))) { - int i; - /* Make sure previous_bb really falls through bb */ - for (i = 0; i < previous_bb->out_count; i++) { - if (previous_bb->out_bb [i] == bb) { - MonoInst *jump; - MONO_INST_NEW (cfg, jump, OP_BR); - MONO_ADD_INS (previous_bb, jump); - jump->cil_code = previous_bb->cil_code; - jump->inst_target_bb = bb; - break; - } - } - } - } else { - /* We cannot add any inst to the entry BB, so we must */ - /* put a new BB in the middle to hold the OP_BR */ - MonoInst *jump; - MonoBasicBlock *new_bb_after_entry = mono_mempool_alloc0 ((cfg)->mempool, sizeof (MonoBasicBlock)); - new_bb_after_entry->block_num = cfg->num_bblocks++; -// new_bb_after_entry->real_offset = bb->real_offset; - new_bb_after_entry->region = bb->region; - - MONO_INST_NEW (cfg, jump, OP_BR); - MONO_ADD_INS (new_bb_after_entry, jump); - jump->cil_code = bb->cil_code; - jump->inst_target_bb = bb; - - previous_bb->next_bb = new_bb_after_entry; - previous_bb = new_bb_after_entry; - - if (cfg->verbose_level > 2) { - printf ("remove_critical_edges, added helper BB%d jumping to BB%d\n", new_bb_after_entry->block_num, bb->block_num); - } - } - } - - /* Insert new_bb in the BB list */ - previous_bb->next_bb = new_bb; - new_bb->next_bb = bb; - previous_bb = new_bb; - - /* Setup in_bb and out_bb */ - new_bb->in_bb = mono_mempool_alloc ((cfg)->mempool, sizeof (MonoBasicBlock*)); - new_bb->in_bb [0] = in_bb; - new_bb->in_count = 1; - new_bb->out_bb = mono_mempool_alloc ((cfg)->mempool, sizeof (MonoBasicBlock*)); - new_bb->out_bb [0] = bb; - new_bb->out_count = 1; - - /* Relink in_bb and bb to (from) new_bb */ - replace_out_block (in_bb, bb, new_bb); - replace_out_block_in_code (in_bb, bb, new_bb); - replace_in_block (bb, in_bb, new_bb); - - if (cfg->verbose_level > 2) { - printf ("remove_critical_edges, removed critical edge from BB%d to BB%d (added BB%d)\n", in_bb->block_num, bb->block_num, new_bb->block_num); - } - } - } - } - } - - if (cfg->verbose_level > 3) { - for (bb = cfg->bb_entry; bb; bb = bb->next_bb) { - int i; - printf ("remove_critical_edges, AFTER BB%d (in:", bb->block_num); - for (i = 0; i < bb->in_count; i++) { - printf (" %d", bb->in_bb [i]->block_num); - } - printf (") (out:"); - for (i = 0; i < bb->out_count; i++) { - printf (" %d", bb->out_bb [i]->block_num); - } - printf (")"); - if (bb->last_ins != NULL) { - printf (" "); - mono_print_tree (bb->last_ins); - } - printf ("\n"); - } - } -} - static MonoGenericInst* get_object_generic_inst (int type_argc) { @@ -13098,10 +12310,16 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool cfg->verbose_level = mini_verbose; cfg->compile_aot = compile_aot; cfg->skip_visibility = method->skip_visibility; + cfg->orig_method = method; if (try_generic_shared) cfg->generic_sharing_context = (MonoGenericSharingContext*)&cfg->generic_sharing_context; cfg->token_info_hash = g_hash_table_new (NULL, NULL); + if (cfg->compile_aot && !try_generic_shared && (method->is_generic || method->klass->generic_container)) { + cfg->exception_type = MONO_EXCEPTION_GENERIC_SHARING_FAILED; + return cfg; + } + /* The debugger has no liveness information, so avoid sharing registers/stack slots */ if (mono_debug_using_mono_debugger () || debug_options.mdb_optimizations) { cfg->disable_reuse_registers = TRUE; @@ -13326,7 +12544,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool g_print ("found unreachable code in BB%d\n", bbn->block_num); /* There may exist unreachable branches to this bb */ bb->next_bb = bbn->next_bb; - nullify_basic_block (bbn); + mono_nullify_basic_block (bbn); } else { bb = bb->next_bb; } @@ -13597,7 +12815,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, gbool bb->last_ins->inst_true_bb = bb->last_ins->inst_false_bb; bb->last_ins->inst_false_bb = tmp; - bb->last_ins->opcode = reverse_branch_op (bb->last_ins->opcode); + bb->last_ins->opcode = mono_reverse_branch_op (bb->last_ins->opcode); } else { MonoInst *inst = mono_mempool_alloc0 (cfg->mempool, sizeof (MonoInst)); inst->opcode = OP_BR; @@ -14356,10 +13574,8 @@ SIG_HANDLER_SIGNATURE (sigsegv_signal_handler) MonoException *exc = NULL; #endif MonoJitInfo *ji; - -#ifdef MONO_ARCH_SIGSEGV_ON_ALTSTACK MonoJitTlsData *jit_tls = TlsGetValue (mono_jit_tls_id); -#endif + GET_CONTEXT; #ifdef MONO_ARCH_USE_SIGACTION @@ -14549,13 +13765,13 @@ SIG_HANDLER_SIGNATURE (sigprof_signal_handler) MonoJitInfo res; MonoContext new_mono_context; int native_offset; - ji = mono_arch_find_jit_info (domain, jit_tls, &res, NULL, &mono_context, + ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context, &new_mono_context, NULL, &lmf, &native_offset, NULL); while ((ji != NULL) && (current_frame_index <= call_chain_depth)) { ips [current_frame_index] = MONO_CONTEXT_GET_IP (&new_mono_context); current_frame_index ++; mono_context = new_mono_context; - ji = mono_arch_find_jit_info (domain, jit_tls, &res, NULL, &mono_context, + ji = mono_find_jit_info (domain, jit_tls, &res, NULL, &mono_context, &new_mono_context, NULL, &lmf, &native_offset, NULL); } } @@ -15037,6 +14253,32 @@ mini_get_debug_options (void) { return &debug_options; } + +static void +mini_create_jit_domain_info (MonoDomain *domain) +{ + MonoJitDomainInfo *info = g_new0 (MonoJitDomainInfo, 1); + + domain->runtime_info = info; +} + +static void +delete_jump_list (gpointer key, gpointer value, gpointer user_data) +{ + g_slist_free (value); +} + +static void +mini_free_jit_domain_info (MonoDomain *domain) +{ + MonoJitDomainInfo *info = jit_domain_info (domain); + + if (info->jump_target_got_slot_hash) { + g_hash_table_foreach (info->jump_target_got_slot_hash, delete_jump_list, NULL); + g_hash_table_destroy (info->jump_target_got_slot_hash); + } + g_free (domain->runtime_info); +} MonoDomain * mini_init (const char *filename, const char *runtime_version) @@ -15105,6 +14347,8 @@ mini_init (const char *filename, const char *runtime_version) mono_install_jump_trampoline (mono_create_jump_trampoline); mono_install_remoting_trampoline (mono_jit_create_remoting_trampoline); mono_install_delegate_trampoline (mono_create_delegate_trampoline); + mono_install_create_domain_hook (mini_create_jit_domain_info); + mono_install_free_domain_hook (mini_free_jit_domain_info); #endif #define JIT_INVOKE_WORKS #ifdef JIT_INVOKE_WORKS @@ -15318,12 +14562,9 @@ mini_init (const char *filename, const char *runtime_version) register_icall (mono_array_new_specific, "mono_array_new_specific", "object ptr int32", FALSE); register_icall (mono_runtime_class_init, "mono_runtime_class_init", "void ptr", FALSE); register_icall (mono_ldftn, "mono_ldftn", "ptr ptr", FALSE); - register_icall (mono_ldftn_nosync, "mono_ldftn_nosync", "ptr ptr", FALSE); register_icall (mono_ldvirtfn, "mono_ldvirtfn", "ptr object ptr", FALSE); register_icall (mono_ldvirtfn_gshared, "mono_ldvirtfn_gshared", "ptr object ptr", FALSE); - register_icall (mono_helper_compile_generic_method, "compile_generic_method", "ptr object ptr ptr ptr", FALSE); - register_icall (mono_helper_compile_generic_method_wo_context, "compile_generic_method_wo_context", - "ptr object ptr ptr", FALSE); + register_icall (mono_helper_compile_generic_method, "compile_generic_method", "ptr object ptr ptr", FALSE); register_icall (mono_helper_ldstr, "helper_ldstr", "object ptr int", FALSE); register_icall (mono_helper_ldstr_mscorlib, "helper_ldstr_mscorlib", "object int", FALSE); register_icall (mono_helper_newobj_mscorlib, "helper_newobj_mscorlib", "object int", FALSE); @@ -15333,6 +14574,7 @@ mini_init (const char *filename, const char *runtime_version) register_icall (mono_create_corlib_exception_0, "mono_create_corlib_exception_0", "object int", TRUE); register_icall (mono_create_corlib_exception_1, "mono_create_corlib_exception_1", "object int object", TRUE); register_icall (mono_create_corlib_exception_2, "mono_create_corlib_exception_2", "object int object object", TRUE); + register_icall (mono_array_new_1, "mono_array_new_1", "object ptr int", FALSE); register_icall (mono_array_new_2, "mono_array_new_2", "object ptr int int", FALSE); #endif