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;
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;
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;
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;
}
}
-/*
- * 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);
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);
}
/*
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);
}
/*
}
}
+ /* 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);
}
}
#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
}
}
#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
}
{
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;
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;
}
EMIT_NEW_TEMPLOAD (cfg, ins, rvar->inst_c0);
*sp++ = ins;
}
+ mono_metadata_free_mh (cheader);
return costs + 1;
} else {
if (cfg->verbose_level > 2)
/* This gets rid of the newly added bblocks */
cfg->cbb = prev_cbb;
}
+ mono_metadata_free_mh (cheader);
return 0;
}
{
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);
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
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;
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;
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);
* 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);
}
#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
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
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)) {
/*
* 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;
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));
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);
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;
}