/* * mono_create_static_rgctx_trampoline: * * Return a static rgctx trampoline for M which branches to ADDR which should * point to the compiled code of M. * * Static rgctx trampolines are used when a shared generic method which doesn't * have a this argument is called indirectly, ie. from code which can't pass in * the rgctx argument. The trampoline sets the rgctx argument and jumps to the * methods code. These trampolines are similar to the unbox trampolines, they * perform the same task as the static rgctx wrappers, but they are smaller/faster, * and can be made to work with full AOT. * On PPC addr should be an ftnptr and the return value is an ftnptr too. */ gpointer mono_create_static_rgctx_trampoline (MonoMethod *m, gpointer addr) { gpointer ctx; gpointer res; MonoDomain *domain; RgctxTrampInfo tmp_info; RgctxTrampInfo *info; #ifdef PPC_USES_FUNCTION_DESCRIPTOR g_assert (((gpointer*)addr) [2] == 0); #endif if (mini_method_get_context (m)->method_inst) ctx = mono_method_lookup_rgctx (mono_class_vtable (mono_domain_get (), m->klass), mini_method_get_context (m)->method_inst); else ctx = mono_class_vtable (mono_domain_get (), m->klass); domain = mono_domain_get (); /* * In the AOT case, addr might point to either the method, or to an unbox trampoline, * so make the hash keyed on the m+addr pair. */ mono_domain_lock (domain); if (!domain_jit_info (domain)->static_rgctx_trampoline_hash) domain_jit_info (domain)->static_rgctx_trampoline_hash = g_hash_table_new (rgctx_tramp_info_hash, rgctx_tramp_info_equal); tmp_info.m = m; tmp_info.addr = addr; res = g_hash_table_lookup (domain_jit_info (domain)->static_rgctx_trampoline_hash, &tmp_info); mono_domain_unlock (domain); if (res) return res; if (mono_aot_only) res = mono_aot_get_static_rgctx_trampoline (ctx, addr); else res = mono_arch_get_static_rgctx_trampoline (m, ctx, addr); mono_domain_lock (domain); /* Duplicates inserted while we didn't hold the lock are OK */ info = mono_domain_alloc (domain, sizeof (RgctxTrampInfo)); info->m = m; info->addr = addr; g_hash_table_insert (domain_jit_info (domain)->static_rgctx_trampoline_hash, info, res); mono_domain_unlock (domain); static_rgctx_trampolines ++; return res; }
MonoSeqPointInfo* get_seq_points (MonoDomain *domain, MonoMethod *method) { MonoSeqPointInfo *seq_points; mono_domain_lock (domain); seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, method); if (!seq_points && method->is_inflated) { /* generic sharing + aot */ seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, mono_method_get_declaring_generic_method (method)); if (!seq_points) seq_points = g_hash_table_lookup (domain_jit_info (domain)->seq_points, mini_get_shared_method (method)); } mono_domain_unlock (domain); return seq_points; }
void mono_save_seq_point_info (MonoCompile *cfg) { MonoBasicBlock *bb; GSList *bb_seq_points, *l; MonoInst *last; MonoDomain *domain = cfg->domain; int i, seq_info_size; GSList **next = NULL; SeqPoint* seq_points; GByteArray* array; gboolean has_debug_data = cfg->gen_sdb_seq_points; if (!cfg->seq_points) return; seq_points = g_new0 (SeqPoint, cfg->seq_points->len); for (i = 0; i < cfg->seq_points->len; ++i) { SeqPoint *sp = &seq_points [i]; MonoInst *ins = g_ptr_array_index (cfg->seq_points, i); sp->il_offset = ins->inst_imm; sp->native_offset = ins->inst_offset; if (ins->flags & MONO_INST_NONEMPTY_STACK) sp->flags |= MONO_SEQ_POINT_FLAG_NONEMPTY_STACK; /* Used below */ ins->backend.size = i; } if (has_debug_data) { /* * For each sequence point, compute the list of sequence points immediately * following it, this is needed to implement 'step over' in the debugger agent. */ next = g_new0 (GSList*, cfg->seq_points->len); for (bb = cfg->bb_entry; bb; bb = bb->next_bb) { bb_seq_points = g_slist_reverse (bb->seq_points); last = NULL; for (l = bb_seq_points; l; l = l->next) { MonoInst *ins = l->data; if (ins->inst_imm == METHOD_ENTRY_IL_OFFSET || ins->inst_imm == METHOD_EXIT_IL_OFFSET) /* Used to implement method entry/exit events */ continue; if (ins->inst_offset == SEQ_POINT_NATIVE_OFFSET_DEAD_CODE) continue; if (last != NULL) { /* Link with the previous seq point in the same bb */ next [last->backend.size] = g_slist_append (next [last->backend.size], GUINT_TO_POINTER (ins->backend.size)); } else { /* Link with the last bb in the previous bblocks */ collect_pred_seq_points (bb, ins, next, 0); } last = ins; } if (bb->last_ins && bb->last_ins->opcode == OP_ENDFINALLY && bb->seq_points) { MonoBasicBlock *bb2; MonoInst *endfinally_seq_point = NULL; /* * The ENDFINALLY branches are not represented in the cfg, so link it with all seq points starting bbs. */ l = g_slist_last (bb->seq_points); if (l) { endfinally_seq_point = l->data; for (bb2 = cfg->bb_entry; bb2; bb2 = bb2->next_bb) { GSList *l = g_slist_last (bb2->seq_points); if (l) { MonoInst *ins = l->data; if (!(ins->inst_imm == METHOD_ENTRY_IL_OFFSET || ins->inst_imm == METHOD_EXIT_IL_OFFSET) && ins != endfinally_seq_point) next [endfinally_seq_point->backend.size] = g_slist_append (next [endfinally_seq_point->backend.size], GUINT_TO_POINTER (ins->backend.size)); } } } } } if (cfg->verbose_level > 2) { printf ("\nSEQ POINT MAP: \n"); for (i = 0; i < cfg->seq_points->len; ++i) { SeqPoint *sp = &seq_points [i]; GSList *l; if (!next [i]) continue; printf ("\tIL0x%x[0x%0x] ->", sp->il_offset, sp->native_offset); for (l = next [i]; l; l = l->next) { int next_index = GPOINTER_TO_UINT (l->data); printf (" IL0x%x", seq_points [next_index].il_offset); } printf ("\n"); } } } array = g_byte_array_new (); { /* Add sequence points to seq_point_info */ SeqPoint zero_seq_point = {0}; SeqPoint* last_seq_point = &zero_seq_point; for (i = 0; i < cfg->seq_points->len; ++i) { SeqPoint *sp = &seq_points [i]; GSList* next_list = NULL; if (has_debug_data) next_list = next[i]; if (seq_point_info_add_seq_point (array, sp, last_seq_point, next_list, has_debug_data)) last_seq_point = sp; if (has_debug_data) g_slist_free (next [i]); } } if (has_debug_data) g_free (next); cfg->seq_point_info = seq_point_info_new (array->len, TRUE, array->data, has_debug_data, &seq_info_size); mono_jit_stats.allocated_seq_points_size += seq_info_size; g_byte_array_free (array, TRUE); // FIXME: dynamic methods if (!cfg->compile_aot) { mono_domain_lock (domain); // FIXME: How can the lookup succeed ? if (!g_hash_table_lookup (domain_jit_info (domain)->seq_points, cfg->method_to_register)) g_hash_table_insert (domain_jit_info (domain)->seq_points, cfg->method_to_register, cfg->seq_point_info); mono_domain_unlock (domain); } g_ptr_array_free (cfg->seq_points, TRUE); cfg->seq_points = NULL; }