/** * mono_mempool_alloc0: * * same as mono_mempool_alloc, but fills memory with zero. */ gpointer mono_mempool_alloc0 (MonoMemPool *pool, guint size) { gpointer rval; #ifdef MALLOC_ALLOCATION rval = mono_mempool_alloc (pool, size); #else size = (size + MEM_ALIGN - 1) & ~(MEM_ALIGN - 1); rval = pool->pos; pool->pos = (guint8*)rval + size; if (G_UNLIKELY (pool->pos >= pool->end)) { rval = mono_mempool_alloc (pool, size); } #ifdef TRACE_ALLOCATIONS else if (pool == mono_get_corlib ()->mempool) { mono_backtrace (size); } #endif #endif memset (rval, 0, size); return rval; }
static inline MonoBitSet* mono_bitset_mp_new_noinit (MonoMemPool *mp, guint32 max_size) { int size = mono_bitset_alloc_size (max_size, 0); gpointer mem; mem = mono_mempool_alloc (mp, size); return mono_bitset_mem_new (mem, max_size, MONO_BITSET_DONT_FREE); }
/** * mono_mempool_strdup: * * Same as strdup, but allocates memory from the mempool. * Returns: a pointer to the newly allocated string data inside the mempool. */ char* mono_mempool_strdup (MonoMemPool *pool, const char *s) { int l; char *res; if (s == NULL) return NULL; l = strlen (s); res = mono_mempool_alloc (pool, l + 1); memcpy (res, s, l + 1); return res; }
char* mono_mempool_strdup_vprintf (MonoMemPool *pool, const char *format, va_list args) { size_t buflen; char *buf; va_list args2; va_copy (args2, args); int len = vsnprintf (NULL, 0, format, args2); va_end (args2); if (len >= 0 && (buf = (char*)mono_mempool_alloc (pool, (buflen = (size_t) (len + 1)))) != NULL) { vsnprintf (buf, buflen, format, args); } else { buf = NULL; } return buf; }
/** * mono_mempool_alloc0: * * same as \c mono_mempool_alloc, but fills memory with zero. */ gpointer (mono_mempool_alloc0) (MonoMemPool *pool, guint size) { gpointer rval; // For the fast path, repeat the first few lines of mono_mempool_alloc size = ALIGN_SIZE (size); rval = pool->pos; pool->pos = (guint8*)rval + size; // If that doesn't work fall back on mono_mempool_alloc to handle new chunk allocation if (G_UNLIKELY (pool->pos >= pool->end)) { rval = mono_mempool_alloc (pool, size); } #ifdef TRACE_ALLOCATIONS else if (pool == mono_get_corlib ()->mempool) { mono_backtrace (size); } #endif memset (rval, 0, size); return rval; }
/* * mono_local_cprop: * * A combined local copy and constant propagation pass. */ void mono_local_cprop (MonoCompile *cfg) { MonoBasicBlock *bb; MonoInst **defs; gint32 *def_index; int max; restart: max = cfg->next_vreg; defs = mono_mempool_alloc (cfg->mempool, sizeof (MonoInst*) * (cfg->next_vreg + 1)); def_index = mono_mempool_alloc (cfg->mempool, sizeof (guint32) * (cfg->next_vreg + 1)); for (bb = cfg->bb_entry; bb; bb = bb->next_bb) { MonoInst *ins; int ins_index; int last_call_index; /* Manually init the defs entries used by the bblock */ MONO_BB_FOR_EACH_INS (bb, ins) { int sregs [MONO_MAX_SRC_REGS]; int num_sregs, i; if ((ins->dreg != -1) && (ins->dreg < max)) { defs [ins->dreg] = NULL; #if SIZEOF_REGISTER == 4 defs [ins->dreg + 1] = NULL; #endif } num_sregs = mono_inst_get_src_registers (ins, sregs); for (i = 0; i < num_sregs; ++i) { int sreg = sregs [i]; if (sreg < max) { defs [sreg] = NULL; #if SIZEOF_REGISTER == 4 defs [sreg + 1] = NULL; #endif } } } ins_index = 0; last_call_index = -1; MONO_BB_FOR_EACH_INS (bb, ins) { const char *spec = INS_INFO (ins->opcode); int regtype, srcindex, sreg; int num_sregs; int sregs [MONO_MAX_SRC_REGS]; if (ins->opcode == OP_NOP) { MONO_DELETE_INS (bb, ins); continue; } g_assert (ins->opcode > MONO_CEE_LAST); /* FIXME: Optimize this */ if (ins->opcode == OP_LDADDR) { MonoInst *var = ins->inst_p0; defs [var->dreg] = NULL; /* if (!MONO_TYPE_ISSTRUCT (var->inst_vtype)) break; */ } if (MONO_IS_STORE_MEMBASE (ins)) { sreg = ins->dreg; regtype = 'i'; if ((regtype == 'i') && (sreg != -1) && defs [sreg]) { MonoInst *def = defs [sreg]; if ((def->opcode == OP_MOVE) && (!defs [def->sreg1] || (def_index [def->sreg1] < def_index [sreg])) && !vreg_is_volatile (cfg, def->sreg1)) { int vreg = def->sreg1; if (cfg->verbose_level > 2) printf ("CCOPY: R%d -> R%d\n", sreg, vreg); ins->dreg = vreg; } } } num_sregs = mono_inst_get_src_registers (ins, sregs); for (srcindex = 0; srcindex < num_sregs; ++srcindex) { MonoInst *def; int nregs; nregs = mono_inst_get_src_registers (ins, sregs); regtype = spec [MONO_INST_SRC1 + srcindex]; sreg = sregs [srcindex]; if ((regtype == ' ') || (sreg == -1) || (!defs [sreg])) continue; def = defs [sreg]; /* Copy propagation */ /* * The first check makes sure the source of the copy did not change since * the copy was made. * The second check avoids volatile variables. * The third check avoids copy propagating local vregs through a call, * since the lvreg will be spilled * The fourth check avoids copy propagating a vreg in cases where * it would be eliminated anyway by reverse copy propagation later, * because propagating it would create another use for it, thus making * it impossible to use reverse copy propagation. */ /* Enabling this for floats trips up the fp stack */ /* * Enabling this for floats on amd64 seems to cause a failure in * basic-math.cs, most likely because it gets rid of some r8->r4 * conversions. */ if (MONO_IS_MOVE (def) && (!defs [def->sreg1] || (def_index [def->sreg1] < def_index [sreg])) && !vreg_is_volatile (cfg, def->sreg1) && /* This avoids propagating local vregs across calls */ ((get_vreg_to_inst (cfg, def->sreg1) || !defs [def->sreg1] || (def_index [def->sreg1] >= last_call_index) || (def->opcode == OP_VMOVE))) && !(defs [def->sreg1] && mono_inst_next (defs [def->sreg1], FILTER_IL_SEQ_POINT) == def) && (!MONO_ARCH_USE_FPSTACK || (def->opcode != OP_FMOVE)) && (def->opcode != OP_FMOVE)) { int vreg = def->sreg1; if (cfg->verbose_level > 2) printf ("CCOPY/2: R%d -> R%d\n", sreg, vreg); sregs [srcindex] = vreg; mono_inst_set_src_registers (ins, sregs); /* Allow further iterations */ srcindex = -1; continue; } /* Constant propagation */ /* FIXME: Make is_inst_imm a macro */ /* FIXME: Make is_inst_imm take an opcode argument */ /* is_inst_imm is only needed for binops */ if ((((def->opcode == OP_ICONST) || ((sizeof (gpointer) == 8) && (def->opcode == OP_I8CONST))) && (((srcindex == 0) && (ins->sreg2 == -1)) || mono_arch_is_inst_imm (def->inst_c0))) || (!MONO_ARCH_USE_FPSTACK && (def->opcode == OP_R8CONST))) { guint32 opcode2; /* srcindex == 1 -> binop, ins->sreg2 == -1 -> unop */ if ((srcindex == 1) && (ins->sreg1 != -1) && defs [ins->sreg1] && (defs [ins->sreg1]->opcode == OP_ICONST) && defs [ins->sreg2]) { /* Both arguments are constants, perform cfold */ mono_constant_fold_ins (cfg, ins, defs [ins->sreg1], defs [ins->sreg2], TRUE); } else if ((srcindex == 0) && (ins->sreg2 != -1) && defs [ins->sreg2]) { /* Arg 1 is constant, swap arguments if possible */ int opcode = ins->opcode; mono_constant_fold_ins (cfg, ins, defs [ins->sreg1], defs [ins->sreg2], TRUE); if (ins->opcode != opcode) { /* Allow further iterations */ srcindex = -1; continue; } } else if ((srcindex == 0) && (ins->sreg2 == -1)) { /* Constant unop, perform cfold */ mono_constant_fold_ins (cfg, ins, defs [ins->sreg1], NULL, TRUE); } opcode2 = mono_op_to_op_imm (ins->opcode); if ((opcode2 != -1) && mono_arch_is_inst_imm (def->inst_c0) && ((srcindex == 1) || (ins->sreg2 == -1))) { ins->opcode = opcode2; if ((def->opcode == OP_I8CONST) && (sizeof (gpointer) == 4)) { ins->inst_ls_word = def->inst_ls_word; ins->inst_ms_word = def->inst_ms_word; } else { ins->inst_imm = def->inst_c0; } sregs [srcindex] = -1; mono_inst_set_src_registers (ins, sregs); if ((opcode2 == OP_VOIDCALL) || (opcode2 == OP_CALL) || (opcode2 == OP_LCALL) || (opcode2 == OP_FCALL)) ((MonoCallInst*)ins)->fptr = (gpointer)ins->inst_imm; /* Allow further iterations */ srcindex = -1; continue; } else { /* Special cases */ #if defined(TARGET_X86) || defined(TARGET_AMD64) if ((ins->opcode == OP_X86_LEA) && (srcindex == 1)) { #if SIZEOF_REGISTER == 8 /* FIXME: Use OP_PADD_IMM when the new JIT is done */ ins->opcode = OP_LADD_IMM; #else ins->opcode = OP_ADD_IMM; #endif ins->inst_imm += def->inst_c0 << ins->backend.shift_amount; ins->sreg2 = -1; } #endif opcode2 = mono_load_membase_to_load_mem (ins->opcode); if ((srcindex == 0) && (opcode2 != -1) && mono_arch_is_inst_imm (def->inst_c0)) { ins->opcode = opcode2; ins->inst_imm = def->inst_c0 + ins->inst_offset; ins->sreg1 = -1; } } } else if (((def->opcode == OP_ADD_IMM) || (def->opcode == OP_LADD_IMM)) && (MONO_IS_LOAD_MEMBASE (ins) || MONO_ARCH_IS_OP_MEMBASE (ins->opcode))) { /* ADD_IMM is created by spill_global_vars */ /* * We have to guarantee that def->sreg1 haven't changed since def->dreg * was defined. cfg->frame_reg is assumed to remain constant. */ if ((def->sreg1 == cfg->frame_reg) || ((def->next == ins) && (def->dreg != def->sreg1))) { ins->inst_basereg = def->sreg1; ins->inst_offset += def->inst_imm; } } else if ((ins->opcode == OP_ISUB_IMM) && (def->opcode == OP_IADD_IMM) && (def->next == ins) && (def->dreg != def->sreg1)) { ins->sreg1 = def->sreg1; ins->inst_imm -= def->inst_imm; } else if ((ins->opcode == OP_IADD_IMM) && (def->opcode == OP_ISUB_IMM) && (def->next == ins) && (def->dreg != def->sreg1)) { ins->sreg1 = def->sreg1; ins->inst_imm -= def->inst_imm; } else if (ins->opcode == OP_STOREI1_MEMBASE_REG && (def->opcode == OP_ICONV_TO_U1 || def->opcode == OP_ICONV_TO_I1 || def->opcode == OP_SEXT_I4 || (SIZEOF_REGISTER == 8 && def->opcode == OP_LCONV_TO_U1)) && (!defs [def->sreg1] || (def_index [def->sreg1] < def_index [sreg]))) { /* Avoid needless sign extension */ ins->sreg1 = def->sreg1; } else if (ins->opcode == OP_STOREI2_MEMBASE_REG && (def->opcode == OP_ICONV_TO_U2 || def->opcode == OP_ICONV_TO_I2 || def->opcode == OP_SEXT_I4 || (SIZEOF_REGISTER == 8 && def->opcode == OP_LCONV_TO_I2)) && (!defs [def->sreg1] || (def_index [def->sreg1] < def_index [sreg]))) { /* Avoid needless sign extension */ ins->sreg1 = def->sreg1; } } /* Do strength reduction here */ /* FIXME: Add long/float */ switch (ins->opcode) { case OP_MOVE: case OP_XMOVE: if (ins->dreg == ins->sreg1) { MONO_DELETE_INS (bb, ins); spec = INS_INFO (ins->opcode); } break; case OP_ADD_IMM: case OP_IADD_IMM: case OP_SUB_IMM: case OP_ISUB_IMM: #if SIZEOF_REGISTER == 8 case OP_LADD_IMM: case OP_LSUB_IMM: #endif if (ins->inst_imm == 0) { ins->opcode = OP_MOVE; spec = INS_INFO (ins->opcode); } break; case OP_MUL_IMM: case OP_IMUL_IMM: #if SIZEOF_REGISTER == 8 case OP_LMUL_IMM: #endif if (ins->inst_imm == 0) { ins->opcode = (ins->opcode == OP_LMUL_IMM) ? OP_I8CONST : OP_ICONST; ins->inst_c0 = 0; ins->sreg1 = -1; } else if (ins->inst_imm == 1) { ins->opcode = OP_MOVE; } else if ((ins->opcode == OP_IMUL_IMM) && (ins->inst_imm == -1)) { ins->opcode = OP_INEG; } else if ((ins->opcode == OP_LMUL_IMM) && (ins->inst_imm == -1)) { ins->opcode = OP_LNEG; } else { int power2 = mono_is_power_of_two (ins->inst_imm); if (power2 >= 0) { ins->opcode = (ins->opcode == OP_MUL_IMM) ? OP_SHL_IMM : ((ins->opcode == OP_LMUL_IMM) ? OP_LSHL_IMM : OP_ISHL_IMM); ins->inst_imm = power2; } } spec = INS_INFO (ins->opcode); break; case OP_IREM_UN_IMM: case OP_IDIV_UN_IMM: { int c = ins->inst_imm; int power2 = mono_is_power_of_two (c); if (power2 >= 0) { if (ins->opcode == OP_IREM_UN_IMM) { ins->opcode = OP_IAND_IMM; ins->sreg2 = -1; ins->inst_imm = (1 << power2) - 1; } else if (ins->opcode == OP_IDIV_UN_IMM) { ins->opcode = OP_ISHR_UN_IMM; ins->sreg2 = -1; ins->inst_imm = power2; } } spec = INS_INFO (ins->opcode); break; } case OP_IDIV_IMM: { int c = ins->inst_imm; int power2 = mono_is_power_of_two (c); MonoInst *tmp1, *tmp2, *tmp3, *tmp4; /* FIXME: Move this elsewhere cause its hard to implement it here */ if (power2 == 1) { int r1 = mono_alloc_ireg (cfg); NEW_BIALU_IMM (cfg, tmp1, OP_ISHR_UN_IMM, r1, ins->sreg1, 31); mono_bblock_insert_after_ins (bb, ins, tmp1); NEW_BIALU (cfg, tmp2, OP_IADD, r1, r1, ins->sreg1); mono_bblock_insert_after_ins (bb, tmp1, tmp2); NEW_BIALU_IMM (cfg, tmp3, OP_ISHR_IMM, ins->dreg, r1, 1); mono_bblock_insert_after_ins (bb, tmp2, tmp3); NULLIFY_INS (ins); // We allocated a new vreg, so need to restart goto restart; } else if (power2 > 0) { int r1 = mono_alloc_ireg (cfg); NEW_BIALU_IMM (cfg, tmp1, OP_ISHR_IMM, r1, ins->sreg1, 31); mono_bblock_insert_after_ins (bb, ins, tmp1); NEW_BIALU_IMM (cfg, tmp2, OP_ISHR_UN_IMM, r1, r1, (32 - power2)); mono_bblock_insert_after_ins (bb, tmp1, tmp2); NEW_BIALU (cfg, tmp3, OP_IADD, r1, r1, ins->sreg1); mono_bblock_insert_after_ins (bb, tmp2, tmp3); NEW_BIALU_IMM (cfg, tmp4, OP_ISHR_IMM, ins->dreg, r1, power2); mono_bblock_insert_after_ins (bb, tmp3, tmp4); NULLIFY_INS (ins); // We allocated a new vreg, so need to restart goto restart; } break; } } if (spec [MONO_INST_DEST] != ' ') { MonoInst *def = defs [ins->dreg]; if (def && (def->opcode == OP_ADD_IMM) && (def->sreg1 == cfg->frame_reg) && (MONO_IS_STORE_MEMBASE (ins))) { /* ADD_IMM is created by spill_global_vars */ /* cfg->frame_reg is assumed to remain constant */ ins->inst_destbasereg = def->sreg1; ins->inst_offset += def->inst_imm; } } if ((spec [MONO_INST_DEST] != ' ') && !MONO_IS_STORE_MEMBASE (ins) && !vreg_is_volatile (cfg, ins->dreg)) { defs [ins->dreg] = ins; def_index [ins->dreg] = ins_index; } if (MONO_IS_CALL (ins)) last_call_index = ins_index; ins_index ++; } }
/* ============================================================================= * makeNestedTransaction - virtual public - override base method * ============================================================================= */ Transaction * vstm_ReadOnly_makeNestedTransaction(Thread * Self){ ReadOnlyTransaction* trx = (ReadOnlyTransaction*)mono_mempool_alloc(Self->mempoolForNestedTrxs, sizeof(ReadOnlyTransaction)); vstm_transaction_init_read_only(trx, Self->trx, NULL); return trx; }
/** * mono_perform_abc_removal: * @cfg: Control Flow Graph * * Performs the ABC removal from a cfg in SSA form. * It does the following: * - Prepare the evaluation area * - Allocate memory for the relation graph in the evaluation area * (of course, only for variable definitions) and summarize there all * variable definitions * - Allocate memory for the evaluation contexts in the evaluation area * - Recursively process all the BBs in the dominator tree (it is enough * to invoke the processing on the entry BB) * * cfg: the method code */ void mono_perform_abc_removal (MonoCompile *cfg) { MonoVariableRelationsEvaluationArea area; MonoBasicBlock *bb; int i; verbose_level = cfg->verbose_level; if (TRACE_ABC_REMOVAL) { printf ("\nRemoving array bound checks in %s\n", mono_method_full_name (cfg->method, TRUE)); } area.cfg = cfg; area.relations = (MonoSummarizedValueRelation *) mono_mempool_alloc (cfg->mempool, sizeof (MonoSummarizedValueRelation) * (cfg->next_vreg) * 2); area.contexts = (MonoRelationsEvaluationContext *) mono_mempool_alloc (cfg->mempool, sizeof (MonoRelationsEvaluationContext) * (cfg->next_vreg)); area.variable_value_kind = (MonoIntegerValueKind *) mono_mempool_alloc (cfg->mempool, sizeof (MonoIntegerValueKind) * (cfg->next_vreg)); for (i = 0; i < cfg->next_vreg; i++) { area.variable_value_kind [i] = MONO_UNKNOWN_INTEGER_VALUE; area.relations [i].relation = MONO_EQ_RELATION; area.relations [i].relation_is_static_definition = TRUE; MAKE_VALUE_ANY (area.relations [i].related_value); area.relations [i].next = NULL; } for (bb = cfg->bb_entry; bb; bb = bb->next_bb) { MonoInst *ins; if (TRACE_ABC_REMOVAL) printf ("\nABCREM BLOCK %d:\n", bb->block_num); for (ins = bb->code; ins; ins = ins->next) { const char *spec = INS_INFO (ins->opcode); if (spec [MONO_INST_DEST] == ' ' || MONO_IS_STORE_MEMBASE (ins)) continue; if (spec [MONO_INST_DEST] == 'i') { MonoIntegerValueKind effective_value_kind; MonoRelationsEvaluationRange range; MonoSummarizedValueRelation *type_relation; MonoInst *var; if (TRACE_ABC_REMOVAL) mono_print_ins (ins); var = get_vreg_to_inst (cfg, ins->dreg); if (var) area.variable_value_kind [ins->dreg] = type_to_value_kind (var->inst_vtype); effective_value_kind = get_relation_from_ins (&area, ins, &area.relations [ins->dreg], area.variable_value_kind [ins->dreg]); MONO_MAKE_RELATIONS_EVALUATION_RANGE_WEAK (range); apply_value_kind_to_range (&range, area.variable_value_kind [ins->dreg]); apply_value_kind_to_range (&range, effective_value_kind); if (range.upper < INT_MAX) { type_relation = (MonoSummarizedValueRelation *) mono_mempool_alloc (cfg->mempool, sizeof (MonoSummarizedValueRelation)); type_relation->relation = MONO_LE_RELATION; type_relation->related_value.type = MONO_CONSTANT_SUMMARIZED_VALUE; type_relation->related_value.value.constant.value = range.upper; type_relation->relation_is_static_definition = TRUE; type_relation->next = area.relations [ins->dreg].next; area.relations [ins->dreg].next = type_relation; if (TRACE_ABC_REMOVAL) { printf ("[var%d <= %d]", ins->dreg, range.upper); } } if (range.lower > INT_MIN) { type_relation = (MonoSummarizedValueRelation *) mono_mempool_alloc (cfg->mempool, sizeof (MonoSummarizedValueRelation)); type_relation->relation = MONO_GE_RELATION; type_relation->related_value.type = MONO_CONSTANT_SUMMARIZED_VALUE; type_relation->related_value.value.constant.value = range.lower; type_relation->relation_is_static_definition = TRUE; type_relation->next = area.relations [ins->dreg].next; area.relations [ins->dreg].next = type_relation; if (TRACE_ABC_REMOVAL) { printf ("[var%d >= %d]", ins->dreg, range.lower); } } if (TRACE_ABC_REMOVAL) { printf ("Summarized variable %d: ", ins->dreg); print_summarized_value (&(area.relations [ins->dreg].related_value)); printf ("\n"); } } } } /* Add symmetric relations */ for (i = 0; i < cfg->next_vreg; i++) { if (area.relations [i].related_value.type == MONO_VARIABLE_SUMMARIZED_VALUE) { int related_index = cfg->next_vreg + i; int related_variable = area.relations [i].related_value.value.variable.variable; area.relations [related_index].relation = MONO_EQ_RELATION; area.relations [related_index].relation_is_static_definition = TRUE; area.relations [related_index].related_value.type = MONO_VARIABLE_SUMMARIZED_VALUE; area.relations [related_index].related_value.value.variable.variable = i; area.relations [related_index].related_value.value.variable.delta = - area.relations [i].related_value.value.variable.delta; area.relations [related_index].next = area.relations [related_variable].next; area.relations [related_variable].next = &(area.relations [related_index]); if (TRACE_ABC_REMOVAL) { printf ("Added symmetric summarized value for variable variable %d (to %d): ", i, related_variable); print_summarized_value (&(area.relations [related_index].related_value)); printf ("\n"); } } } process_block (cfg, cfg->bblocks [0], &area); }
/** * mono_debug_add_method: */ MonoDebugMethodAddress * mono_debug_add_method (MonoMethod *method, MonoDebugMethodJitInfo *jit, MonoDomain *domain) { MonoDebugDataTable *table; MonoDebugMethodAddress *address; guint8 buffer [BUFSIZ]; guint8 *ptr, *oldptr; guint32 i, size, total_size, max_size; mono_debugger_lock (); table = lookup_data_table (domain); max_size = (5 * 5) + 1 + (10 * jit->num_line_numbers) + (25 + sizeof (gpointer)) * (1 + jit->num_params + jit->num_locals); if (max_size > BUFSIZ) ptr = oldptr = (guint8 *)g_malloc (max_size); else ptr = oldptr = buffer; write_leb128 (jit->prologue_end, ptr, &ptr); write_leb128 (jit->epilogue_begin, ptr, &ptr); write_leb128 (jit->num_line_numbers, ptr, &ptr); for (i = 0; i < jit->num_line_numbers; i++) { MonoDebugLineNumberEntry *lne = &jit->line_numbers [i]; write_sleb128 (lne->il_offset, ptr, &ptr); write_sleb128 (lne->native_offset, ptr, &ptr); } write_leb128 (jit->has_var_info, ptr, &ptr); if (jit->has_var_info) { *ptr++ = jit->this_var ? 1 : 0; if (jit->this_var) write_variable (jit->this_var, ptr, &ptr); write_leb128 (jit->num_params, ptr, &ptr); for (i = 0; i < jit->num_params; i++) write_variable (&jit->params [i], ptr, &ptr); write_leb128 (jit->num_locals, ptr, &ptr); for (i = 0; i < jit->num_locals; i++) write_variable (&jit->locals [i], ptr, &ptr); *ptr++ = jit->gsharedvt_info_var ? 1 : 0; if (jit->gsharedvt_info_var) { write_variable (jit->gsharedvt_info_var, ptr, &ptr); write_variable (jit->gsharedvt_locals_var, ptr, &ptr); } } size = ptr - oldptr; g_assert (size < max_size); total_size = size + sizeof (MonoDebugMethodAddress); if (method_is_dynamic (method)) { address = (MonoDebugMethodAddress *)g_malloc0 (total_size); } else { address = (MonoDebugMethodAddress *)mono_mempool_alloc (table->mp, total_size); } address->code_start = jit->code_start; address->code_size = jit->code_size; memcpy (&address->data, oldptr, size); if (max_size > BUFSIZ) g_free (oldptr); g_hash_table_insert (table->method_address_hash, method, address); mono_debugger_unlock (); return address; }
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_ins (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]; /* * Have to remove non-critical edges whose source ends with a BR_REG * ins too, since inserting a computation before the BR_REG could * overwrite the sreg1 of the ins. */ if ((in_bb->out_count > 1) || (in_bb->out_count == 1 && in_bb->last_ins && in_bb->last_ins->opcode == OP_BR_REG)) { 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 (mono_bb_is_fall_through (cfg, previous_bb)) { if (previous_bb != cfg->bb_entry) { 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; mono_unlink_bblock (cfg, previous_bb, bb); mono_link_bblock (cfg, new_bb_after_entry, bb); mono_link_bblock (cfg, previous_bb, new_bb_after_entry); 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_ins (bb->last_ins); } printf ("\n"); } } }