#include <mono/metadata/profiler.h>
#include <mono/metadata/monitor.h>
#include <mono/metadata/debug-mono-symfile.h>
-#include <mono/utils/mono-compiler.h>
#include <mono/utils/mono-memory-model.h>
#include <mono/utils/mono-error-internals.h>
#include <mono/metadata/mono-basic-block.h>
static MonoMethodSignature *helper_sig_set_tls_tramp;
/* type loading helpers */
-static GENERATE_GET_CLASS_WITH_CACHE (runtime_helpers, System.Runtime.CompilerServices, RuntimeHelpers)
-static GENERATE_TRY_GET_CLASS_WITH_CACHE (debuggable_attribute, System.Diagnostics, DebuggableAttribute)
+static GENERATE_GET_CLASS_WITH_CACHE (runtime_helpers, "System.Runtime.CompilerServices", "RuntimeHelpers")
+static GENERATE_TRY_GET_CLASS_WITH_CACHE (debuggable_attribute, "System.Diagnostics", "DebuggableAttribute")
/*
* Instruction metadata
#undef MINI_OP
#undef MINI_OP3
-#define MONO_INIT_VARINFO(vi,id) do { \
- (vi)->range.first_use.pos.bid = 0xffff; \
- (vi)->reg = -1; \
- (vi)->idx = (id); \
-} while (0)
-
guint32
mono_alloc_ireg (MonoCompile *cfg)
{
* pack the arguments into an array, and do the rest of the work in in an icall.
*/
if (((cmethod->klass == mono_defaults.object_class) || mono_class_is_interface (cmethod->klass) || (!cmethod->klass->valuetype && cmethod->klass->image != mono_defaults.corlib)) &&
- (MONO_TYPE_IS_VOID (fsig->ret) || MONO_TYPE_IS_PRIMITIVE (fsig->ret) || MONO_TYPE_IS_REFERENCE (fsig->ret) || MONO_TYPE_ISSTRUCT (fsig->ret) || mini_is_gsharedvt_type (fsig->ret)) &&
+ (MONO_TYPE_IS_VOID (fsig->ret) || MONO_TYPE_IS_PRIMITIVE (fsig->ret) || MONO_TYPE_IS_REFERENCE (fsig->ret) || MONO_TYPE_ISSTRUCT (fsig->ret) || mono_class_is_enum (mono_class_from_mono_type (fsig->ret)) || mini_is_gsharedvt_type (fsig->ret)) &&
(fsig->param_count == 0 || (!fsig->hasthis && fsig->param_count == 1) || (fsig->param_count == 1 && (MONO_TYPE_IS_REFERENCE (fsig->params [0]) || fsig->params [0]->byref || mini_is_gsharedvt_type (fsig->params [0]))))) {
MonoInst *args [16];
if (mini_is_gsharedvt_type (fsig->ret)) {
ins = handle_unbox_gsharedvt (cfg, mono_class_from_mono_type (fsig->ret), ins);
- } else if (MONO_TYPE_IS_PRIMITIVE (fsig->ret) || MONO_TYPE_ISSTRUCT (fsig->ret)) {
+ } else if (MONO_TYPE_IS_PRIMITIVE (fsig->ret) || MONO_TYPE_ISSTRUCT (fsig->ret) || mono_class_is_enum (mono_class_from_mono_type (fsig->ret))) {
MonoInst *add;
/* Unbox */
* Get rid of the begin and end bblocks if possible to aid local
* optimizations.
*/
- mono_merge_basic_blocks (cfg, prev_cbb, sbblock);
+ if (prev_cbb->out_count == 1)
+ mono_merge_basic_blocks (cfg, prev_cbb, sbblock);
if ((prev_cbb->out_count == 1) && (prev_cbb->out_bb [0]->in_count == 1) && (prev_cbb->out_bb [0] != ebblock))
mono_merge_basic_blocks (cfg, prev_cbb, prev_cbb->out_bb [0]);
gboolean variant_iface = FALSE;
guint32 slot;
int offset;
+ gboolean special_array_interface = cmethod->klass->is_array_special_interface;
/*
* In llvm-only mode, vtables contain function descriptors instead of
return emit_extra_arg_calli (cfg, fsig, sp, arg_reg, call_target);
}
- if (!fsig->generic_param_count && is_iface && !variant_iface && !is_gsharedvt) {
+ if (!fsig->generic_param_count && is_iface && !variant_iface && !is_gsharedvt && !special_array_interface) {
/*
* A simple interface call
*
return emit_llvmonly_calli (cfg, fsig, sp, ftndesc_ins);
}
- if ((fsig->generic_param_count || variant_iface) && !is_gsharedvt) {
+ if ((fsig->generic_param_count || variant_iface || special_array_interface) && !is_gsharedvt) {
/*
* This is similar to the interface case, the vtable slot points to an imt thunk which is
* dynamically extended as more instantiations are discovered.
mono_bitset_set_fast (seq_point_locs, sps [i].il_offset);
}
g_free (sps);
+
+ MonoDebugMethodAsyncInfo* asyncMethod = mono_debug_lookup_method_async_debug_info (method);
+ if (asyncMethod) {
+ for (i = 0; asyncMethod != NULL && i < asyncMethod->num_awaits; i++)
+ {
+ mono_bitset_set_fast (seq_point_locs, asyncMethod->resume_offsets[i]);
+ mono_bitset_set_fast (seq_point_locs, asyncMethod->yield_offsets[i]);
+ }
+ mono_debug_free_method_async_debug_info (asyncMethod);
+ }
} 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);
CHECK_CFG_ERROR;
}
}
+
+ if (constrained_class->enumtype && !strcmp (cmethod->name, "GetHashCode")) {
+ /* Use the corresponding method from the base type to avoid boxing */
+ MonoType *base_type = mono_class_enum_basetype (constrained_class);
+ g_assert (base_type);
+ constrained_class = mono_class_from_mono_type (base_type);
+ cmethod = mono_class_get_method_from_name (constrained_class, cmethod->name, 0);
+ g_assert (cmethod);
+ }
}
if (!dont_verify && !cfg->skip_visibility) {
* request a generic sharing context.
*/
if (context_used &&
- ((method->flags & METHOD_ATTRIBUTE_STATIC) || method->klass->valuetype))
+ ((cfg->method->flags & METHOD_ATTRIBUTE_STATIC) || cfg->method->klass->valuetype))
mono_get_vtable_var (cfg);
}
guint32 offset;
int idx, static_data_reg, array_reg, dreg;
- GSHAREDVT_FAILURE (op);
+ if (context_used && cfg->gsharedvt && mini_is_gsharedvt_klass (klass))
+ GSHAREDVT_FAILURE (op);
static_data_reg = alloc_ireg (cfg);
MONO_EMIT_NEW_LOAD_MEMBASE (cfg, static_data_reg, thread_ins->dreg, MONO_STRUCT_OFFSET (MonoInternalThread, static_data));
int orig_next_vreg;
guint32 *vreg_to_lvreg;
guint32 *lvregs;
- guint32 i, lvregs_len;
+ guint32 i, lvregs_len, lvregs_size;
gboolean dest_has_lvreg = FALSE;
MonoStackType stacktypes [128];
MonoInst **live_range_start, **live_range_end;
*/
orig_next_vreg = cfg->next_vreg;
vreg_to_lvreg = (guint32 *)mono_mempool_alloc0 (cfg->mempool, sizeof (guint32) * cfg->next_vreg);
- lvregs = (guint32 *)mono_mempool_alloc (cfg->mempool, sizeof (guint32) * 1024);
+ lvregs_size = 1024;
+ lvregs = (guint32 *)mono_mempool_alloc (cfg->mempool, sizeof (guint32) * lvregs_size);
lvregs_len = 0;
/*
}
g_assert (sreg != -1);
vreg_to_lvreg [var->dreg] = sreg;
- g_assert (lvregs_len < 1024);
+ if (lvregs_len >= lvregs_size) {
+ guint32 *new_lvregs = mono_mempool_alloc0 (cfg->mempool, sizeof (guint32) * lvregs_size * 2);
+ memcpy (new_lvregs, lvregs, sizeof (guint32) * lvregs_size);
+ lvregs = new_lvregs;
+ lvregs_size *= 2;
+ }
lvregs [lvregs_len ++] = var->dreg;
}
}
if (dest_has_lvreg) {
g_assert (ins->dreg != -1);
vreg_to_lvreg [prev_dreg] = ins->dreg;
- g_assert (lvregs_len < 1024);
+ if (lvregs_len >= lvregs_size) {
+ guint32 *new_lvregs = mono_mempool_alloc0 (cfg->mempool, sizeof (guint32) * lvregs_size * 2);
+ memcpy (new_lvregs, lvregs, sizeof (guint32) * lvregs_size);
+ lvregs = new_lvregs;
+ lvregs_size *= 2;
+ }
lvregs [lvregs_len ++] = prev_dreg;
dest_has_lvreg = FALSE;
}