#include "jit-icalls.h"
#include "jit.h"
#include "debugger-agent.h"
+#include "seq-points.h"
#define BRANCH_COST 10
#define INLINE_LENGTH_LIMIT 20
LOAD_ERROR; \
} while (0)
+#define CHECK_CFG_ERROR do {\
+ if (!mono_error_ok (&cfg->error)) { \
+ mono_cfg_set_exception (cfg, MONO_EXCEPTION_MONO_ERROR); \
+ goto mono_error_exit; \
+ } \
+ } while (0)
+
/* Determine whenever 'ins' represents a load of the 'this' argument */
#define MONO_CHECK_THIS(ins) (mono_method_signature (cfg->method)->hasthis && ((ins)->opcode == OP_MOVE) && ((ins)->sreg1 == cfg->args [0]->dreg))
* call void class [mscorlib]System.Runtime.CompilerServices.RuntimeHelpers::InitializeArray(class [mscorlib]System.Array, valuetype [mscorlib]System.RuntimeFieldHandle)
*/
if (ip [0] == CEE_DUP && ip [1] == CEE_LDTOKEN && ip [5] == 0x4 && ip [6] == CEE_CALL) {
+ MonoError error;
guint32 token = read32 (ip + 7);
guint32 field_token = read32 (ip + 2);
guint32 field_index = field_token & 0xffffff;
int size = 0;
MonoMethod *cmethod;
MonoClass *dummy_class;
- MonoClassField *field = mono_field_from_token (method->klass->image, field_token, &dummy_class, NULL);
+ MonoClassField *field = mono_field_from_token_checked (method->klass->image, field_token, &dummy_class, NULL, &error);
int dummy_align;
- if (!field)
+ if (!field) {
+ mono_error_cleanup (&error); /* FIXME don't swallow the error */
return NULL;
+ }
*out_field_token = field_token;
seq_points = FALSE;
}
- if (cfg->gen_seq_points && cfg->method == method) {
+ if (cfg->gen_seq_points_debug_data && cfg->method == method) {
minfo = mono_debug_lookup_method (method);
if (minfo) {
int i, n_il_offsets;
}
g_free (il_offsets);
g_free (line_numbers);
+ } else if (!method->wrapper_type && !method->dynamic && mono_debug_image_has_debug_info (method->klass->image)) {
+ /* Methods without line number info like auto-generated property accessors */
+ seq_point_locs = mono_bitset_mem_new (mono_mempool_alloc0 (cfg->mempool, mono_bitset_alloc_size (header->code_size, 0)), header->code_size, 0);
+ seq_point_set_locs = mono_bitset_mem_new (mono_mempool_alloc0 (cfg->mempool, mono_bitset_alloc_size (header->code_size, 0)), header->code_size, 0);
+ sym_seq_points = TRUE;
}
}
skip_dead_blocks = !dont_verify;
if (skip_dead_blocks) {
- original_bb = bb = mono_basic_block_split (method, &error);
- if (!mono_error_ok (&error)) {
- mono_error_cleanup (&error);
- UNVERIFIED;
- }
+ original_bb = bb = mono_basic_block_split (method, &cfg->error);
+ CHECK_CFG_ERROR;
g_assert (bb);
}
} else if (constrained_call) {
fsig = mono_method_signature (cmethod);
} else {
- fsig = mono_method_get_signature_full (cmethod, image, token, generic_context);
+ fsig = mono_method_get_signature_checked (cmethod, image, token, generic_context, &cfg->error);
+ CHECK_CFG_ERROR;
}
}
mono_save_token_info (cfg, image, token, cil_method);
- if (!MONO_TYPE_IS_VOID (fsig->ret)) {
- /*
- * Need to emit an implicit seq point after every non-void call so single stepping through nested calls like
- * foo (bar (), baz ())
- * works correctly. MS does this also:
- * http://stackoverflow.com/questions/6937198/making-your-net-language-step-correctly-in-the-debugger
- * The problem with this approach is that the debugger will stop after all calls returning a value,
- * even for simple cases, like:
- * int i = foo ();
- */
- /* Special case a few common successor opcodes */
- if (!(ip + 5 < end && (ip [5] == CEE_POP || ip [5] == CEE_NOP)) && !(seq_point_locs && mono_bitset_test_fast (seq_point_locs, ip + 5 - header->code)))
- need_seq_point = TRUE;
- }
+ if (!(seq_point_locs && mono_bitset_test_fast (seq_point_locs, ip + 5 - header->code)))
+ need_seq_point = TRUE;
n = fsig->param_count + fsig->hasthis;
}
else if (method->wrapper_type != MONO_WRAPPER_NONE) {
MonoInst *iargs [1];
+ char *str = mono_method_get_wrapper_data (method, n);
- EMIT_NEW_PCONST (cfg, iargs [0], mono_method_get_wrapper_data (method, n));
+ if (cfg->compile_aot)
+ EMIT_NEW_LDSTRLITCONST (cfg, iargs [0], str);
+ else
+ EMIT_NEW_PCONST (cfg, iargs [0], str);
*sp = mono_emit_jit_icall (cfg, mono_string_new_wrapper, iargs);
} else {
if (cfg->opt & MONO_OPT_SHARED) {
cmethod = mini_get_method (cfg, method, token, NULL, generic_context);
if (!cmethod || mono_loader_get_last_error ())
LOAD_ERROR;
- fsig = mono_method_get_signature (cmethod, image, token);
- if (!fsig)
- LOAD_ERROR;
+ fsig = mono_method_get_signature_checked (cmethod, image, token, NULL, &cfg->error);
+ CHECK_CFG_ERROR;
mono_save_token_info (cfg, image, token, cmethod);
ip += 5;
inline_costs += 5;
+ if (!(seq_point_locs && mono_bitset_test_fast (seq_point_locs, ip - header->code)))
+ emit_seq_point (cfg, method, ip, FALSE, TRUE);
break;
}
case CEE_CASTCLASS:
klass = field->parent;
}
else {
- field = mono_field_from_token (image, token, &klass, generic_context);
+ field = mono_field_from_token_checked (image, token, &klass, generic_context, &cfg->error);
+ CHECK_CFG_ERROR;
}
- if (!field)
- LOAD_ERROR;
if (!dont_verify && !cfg->skip_visibility && !mono_method_can_access_field (method, field))
FIELD_ACCESS_FAILURE (method, field);
mono_class_init (klass);
MONO_INST_NEW (cfg, ins, *ip);
--sp;
CHECK_OPSIZE (5);
- klass = mono_class_get_and_inflate_typespec_checked (image, read32 (ip + 1), generic_context, &error);
- mono_error_cleanup (&error); /* FIXME don't swallow the error */
+ klass = mini_get_class (method, read32 (ip + 1), generic_context);
CHECK_TYPELOAD (klass);
- mono_class_init (klass);
context_used = mini_class_check_context_used (cfg, klass);
MONO_INST_NEW (cfg, ins, *ip);
--sp;
CHECK_OPSIZE (5);
- klass = mono_class_get_and_inflate_typespec_checked (image, read32 (ip + 1), generic_context, &error);
- mono_error_cleanup (&error); /* FIXME don't swallow the error */
+ klass = mini_get_class (method, read32 (ip + 1), generic_context);
CHECK_TYPELOAD (klass);
- mono_class_init (klass);
context_used = mini_class_check_context_used (cfg, klass);
CHECK_OPSIZE (6);
token = read32 (ip + 2);
if (mono_metadata_token_table (token) == MONO_TABLE_TYPESPEC && !image_is_dynamic (method->klass->image) && !generic_context) {
- MonoType *type = mono_type_create_from_typespec_checked (image, token, &error);
- mono_error_cleanup (&error); /* FIXME don't swallow the error */
- if (!type)
- UNVERIFIED;
+ MonoType *type = mono_type_create_from_typespec_checked (image, token, &cfg->error);
+ CHECK_CFG_ERROR;
val = mono_type_size (type, &ialign);
} else {
- MonoClass *klass = mono_class_get_and_inflate_typespec_checked (image, token, generic_context, &error);
- mono_error_cleanup (&error); /* FIXME don't swallow the error */
+ MonoClass *klass = mini_get_class (method, token, generic_context);
CHECK_TYPELOAD (klass);
- mono_class_init (klass);
+
val = mono_type_size (&klass->byval_arg, &ialign);
if (mini_is_gsharedvt_klass (cfg, klass))
}
/* Add a sequence point for method entry/exit events */
- if (seq_points) {
+ if (cfg->gen_seq_points_debug_data) {
NEW_SEQ_POINT (cfg, ins, METHOD_ENTRY_IL_OFFSET, FALSE);
MONO_ADD_INS (init_localsbb, ins);
NEW_SEQ_POINT (cfg, ins, METHOD_EXIT_IL_OFFSET, FALSE);
mono_print_code (cfg, "AFTER METHOD-TO-IR");
goto cleanup;
+
+mono_error_exit:
+ g_assert (!mono_error_ok (&cfg->error));
+ goto cleanup;
exception_exit:
g_assert (cfg->exception_type != MONO_EXCEPTION_NONE);