#define mono_jit_unlock() mono_mutex_unlock (&jit_mutex)
static mono_mutex_t jit_mutex;
-/* Whenever to check for pending exceptions in managed-to-native wrappers */
-gboolean check_for_pending_exc = TRUE;
-
gpointer
mono_realloc_native_code (MonoCompile *cfg)
{
guint
mono_type_to_store_membase (MonoCompile *cfg, MonoType *type)
{
- type = mini_get_underlying_type (cfg, type);
+ type = mini_get_underlying_type (type);
handle_enum:
switch (type->type) {
goto handle_enum;
case MONO_TYPE_VAR:
case MONO_TYPE_MVAR:
- g_assert (mini_type_var_is_vt (cfg, type));
+ g_assert (mini_type_var_is_vt (type));
return OP_STOREV_MEMBASE;
default:
g_error ("unknown type 0x%02x in type_to_store_membase", type->type);
guint
mono_type_to_load_membase (MonoCompile *cfg, MonoType *type)
{
- type = mini_get_underlying_type (cfg, type);
+ type = mini_get_underlying_type (type);
switch (type->type) {
case MONO_TYPE_I1:
break;
case MONO_TYPE_VAR:
case MONO_TYPE_MVAR:
- g_assert (cfg->generic_sharing_context);
- g_assert (mini_type_var_is_vt (cfg, type));
+ g_assert (cfg->gshared);
+ g_assert (mini_type_var_is_vt (type));
return OP_LOADV_MEMBASE;
default:
g_error ("unknown type 0x%02x in type_to_load_membase", type->type);
static guint
mini_type_to_ldind (MonoCompile* cfg, MonoType *type)
{
- type = mini_get_underlying_type (cfg, type);
- if (cfg->generic_sharing_context && !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
- g_assert (mini_type_var_is_vt (cfg, type));
+ type = mini_get_underlying_type (type);
+ if (cfg->gshared && !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
+ g_assert (mini_type_var_is_vt (type));
return CEE_LDOBJ;
}
return mono_type_to_ldind (type);
guint
mini_type_to_stind (MonoCompile* cfg, MonoType *type)
{
- type = mini_get_underlying_type (cfg, type);
- if (cfg->generic_sharing_context && !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
- g_assert (mini_type_var_is_vt (cfg, type));
+ type = mini_get_underlying_type (type);
+ if (cfg->gshared && !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR)) {
+ g_assert (mini_type_var_is_vt (type));
return CEE_STOBJ;
}
return mono_type_to_stind (type);
int num = cfg->num_varinfo;
gboolean regpair;
- type = mini_get_underlying_type (cfg, type);
+ type = mini_get_underlying_type (type);
if ((num + 1) >= cfg->varinfo_count) {
int orig_count = cfg->varinfo_count;
if (type->byref) {
mono_mark_vreg_as_mp (cfg, vreg);
} else {
- if ((MONO_TYPE_ISSTRUCT (type) && inst->klass->has_references) || mini_type_is_reference (cfg, type)) {
+ if ((MONO_TYPE_ISSTRUCT (type) && inst->klass->has_references) || mini_type_is_reference (type)) {
inst->flags |= MONO_INST_GC_TRACK;
mono_mark_vreg_as_ref (cfg, vreg);
}
mono_compile_create_var (MonoCompile *cfg, MonoType *type, int opcode)
{
int dreg;
- type = mini_get_underlying_type (cfg, type);
+ type = mini_get_underlying_type (type);
if (mono_type_is_long (type))
dreg = mono_alloc_dreg (cfg, STACK_I8);
inst = cfg->varinfo [vmv->idx];
t = mono_type_get_underlying_type (inst->inst_vtype);
- if (cfg->gsharedvt && mini_is_gsharedvt_variable_type (cfg, t))
+ if (cfg->gsharedvt && mini_is_gsharedvt_variable_type (t))
continue;
/* inst->backend.is_pinvoke indicates native sized value types, this is used by the
else {
int ialign;
- size = mini_type_stack_size (NULL, t, &ialign);
+ size = mini_type_stack_size (t, &ialign);
align = ialign;
if (MONO_CLASS_IS_SIMD (cfg, mono_class_from_mono_type (t)))
if (cfg->disable_reuse_stack_slots)
reuse_slot = FALSE;
- t = mini_get_underlying_type (cfg, t);
+ t = mini_get_underlying_type (t);
switch (t->type) {
case MONO_TYPE_GENERICINST:
if (!mono_type_generic_inst_is_valuetype (t)) {
inst = cfg->varinfo [vmv->idx];
t = mono_type_get_underlying_type (inst->inst_vtype);
- if (cfg->gsharedvt && mini_is_gsharedvt_variable_type (cfg, t))
+ if (cfg->gsharedvt && mini_is_gsharedvt_variable_type (t))
continue;
/* inst->backend.is_pinvoke indicates native sized value types, this is used by the
} else {
int ialign;
- size = mini_type_stack_size (NULL, t, &ialign);
+ size = mini_type_stack_size (t, &ialign);
align = ialign;
if (mono_class_from_mono_type (t)->exception_type)
if (cfg->disable_reuse_stack_slots)
reuse_slot = FALSE;
- t = mini_get_underlying_type (cfg, t);
+ t = mini_get_underlying_type (t);
switch (t->type) {
case MONO_TYPE_GENERICINST:
if (!mono_type_generic_inst_is_valuetype (t)) {
MonoInst*
mono_create_tls_get (MonoCompile *cfg, MonoTlsKey key)
{
+ if (!MONO_ARCH_HAVE_TLS_GET)
+ return NULL;
+
/*
* TLS offsets might be different at AOT time, so load them from a GOT slot and
* use a different opcode.
*/
if (cfg->compile_aot) {
- if (MONO_ARCH_HAVE_TLS_GET && ARCH_HAVE_TLS_GET_REG) {
+ if (ARCH_HAVE_TLS_GET_REG) {
MonoInst *ins, *c;
EMIT_NEW_TLS_OFFSETCONST (cfg, c, key);
is_generic = TRUE;
}
- if (cfg->generic_sharing_context)
+ if (cfg->gshared)
g_assert (is_generic);
}
g_assert (method_to_compile == cfg->method);
header = cfg->header;
- if (cfg->generic_sharing_context)
+ if (cfg->gshared)
flags |= JIT_INFO_HAS_GENERIC_JIT_INFO;
if (cfg->arch_eh_jit_info) {
* mono_arch_get_argument_info () is not signal safe.
*/
arg_info = g_newa (MonoJitArgumentInfo, sig->param_count + 1);
- stack_size = mono_arch_get_argument_info (cfg->generic_sharing_context, sig, sig->param_count, arg_info);
+ stack_size = mono_arch_get_argument_info (sig, sig->param_count, arg_info);
if (stack_size)
flags |= JIT_INFO_HAS_ARCH_EH_INFO;
if (COMPILE_LLVM (cfg))
jinfo->from_llvm = TRUE;
- if (cfg->generic_sharing_context) {
+ if (cfg->gshared) {
MonoInst *inst;
MonoGenericJitInfo *gi;
GSList *loclist = NULL;
mono_create_gc_safepoint (MonoCompile *cfg, MonoBasicBlock *bblock)
{
MonoInst *poll_addr, *ins;
- if (cfg->verbose_level)
+ if (cfg->verbose_level > 1)
printf ("ADDING SAFE POINT TO BB %d\n", bblock->block_num);
#if defined(__native_client_codegen__)
if (bblock->flags & BB_EXCEPTION_HANDLER) {
MonoInst *eh_op = bblock->code;
- // we only skip the ops that start EH blocks.
- if (eh_op && eh_op->opcode != OP_START_HANDLER && eh_op->opcode != OP_GET_EX_OBJ)
+ if (eh_op && eh_op->opcode != OP_START_HANDLER && eh_op->opcode != OP_GET_EX_OBJ) {
eh_op = NULL;
+ } else {
+ MonoInst *next_eh_op = eh_op ? eh_op->next : NULL;
+ // skip all EH relateds ops
+ while (next_eh_op && (next_eh_op->opcode == OP_START_HANDLER || next_eh_op->opcode == OP_GET_EX_OBJ)) {
+ eh_op = next_eh_op;
+ next_eh_op = eh_op->next;
+ }
+ }
mono_bblock_insert_after_ins (bblock, eh_op, poll_addr);
mono_bblock_insert_after_ins (bblock, poll_addr, ins);
mono_insert_safepoints (MonoCompile *cfg)
{
MonoBasicBlock *bb;
+ if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) {
+ WrapperInfo *info = mono_marshal_get_wrapper_info (cfg->method);
+#if defined(__native_client__) || defined(__native_client_codegen__)
+ gpointer poll_func = &mono_nacl_gc;
+#elif defined(USE_COOP_GC)
+ gpointer poll_func = &mono_threads_state_poll;
+#else
+ gpointer poll_func = NULL;
+#endif
- if (cfg->verbose_level)
+ if (info && info->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER && info->d.icall.func == poll_func) {
+ if (cfg->verbose_level > 1)
+ printf ("SKIPPING SAFEPOINTS for the polling function icall\n");
+ return;
+ }
+ }
+
+
+ if (cfg->verbose_level > 1)
printf ("INSERTING SAFEPOINTS\n");
+ if (cfg->verbose_level > 2)
+ mono_print_code (cfg, "BEFORE SAFEPOINTS");
for (bb = cfg->bb_entry; bb; bb = bb->next_bb) {
if (bb->loop_body_start || bb == cfg->bb_entry || bb->flags & BB_EXCEPTION_HANDLER)
mono_create_gc_safepoint (cfg, bb);
}
+
+ if (cfg->verbose_level > 2)
+ mono_print_code (cfg, "AFTER SAFEPOINTS");
+
}
#else
* field in the returned struct to see if compilation succeded.
*/
MonoCompile*
-mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFlags flags, int parts)
+mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFlags flags, int parts, int aot_method_index)
{
MonoMethodHeader *header;
MonoMethodSignature *sig;
if (MONO_METHOD_COMPILE_BEGIN_ENABLED ())
MONO_PROBE_METHOD_COMPILE_BEGIN (method);
+ gsharedvt_method = is_gsharedvt_method (method);
+
/*
* In AOT mode, method can be the following:
- * - the generic method definition. In this case, we are compiling the fully shared
- * version of the method, i.e. the version where all the type parameters are
- * reference types.
* - a gsharedvt method.
- * - a method inflated with type parameters. This is for partial sharing.
+ * - a method inflated with type parameters. This is for ref/partial sharing.
* - a method inflated with concrete types.
*/
- if (compile_aot)
- try_generic_shared = mono_class_generic_sharing_enabled (method->klass) &&
- (opts & MONO_OPT_GSHARED) && ((method->is_generic || method->klass->generic_container) || (!method->klass->generic_class && mono_method_is_generic_sharable_full (method, TRUE, FALSE, FALSE)));
- else
+ if (compile_aot) {
+ if (is_open_method (method)) {
+ try_generic_shared = TRUE;
+ method_is_gshared = TRUE;
+ } else {
+ try_generic_shared = FALSE;
+ }
+ g_assert (opts & MONO_OPT_GSHARED);
+ } else {
try_generic_shared = mono_class_generic_sharing_enabled (method->klass) &&
(opts & MONO_OPT_GSHARED) && mono_method_is_generic_sharable (method, FALSE);
+ if (mini_is_gsharedvt_sharable_method (method)) {
+ if (!mono_debug_count ())
+ try_generic_shared = FALSE;
+ }
+ }
/*
if (try_generic_shared && !mono_debug_count ())
mono_stats.generics_unsharable_methods++;
}
- if (mini_is_gsharedvt_sharable_method (method)) {
- if (!mono_debug_count ())
- try_generic_shared = FALSE;
- if (compile_aot)
- try_generic_shared = FALSE;
- }
-
- gsharedvt_method = is_gsharedvt_method (method);
- if (gsharedvt_method || (compile_aot && is_open_method (method))) {
- /* We are AOTing a gshared method directly */
- method_is_gshared = TRUE;
- g_assert (compile_aot);
- try_generic_shared = TRUE;
- }
-
#ifdef ENABLE_LLVM
try_llvm = mono_use_llvm || llvm;
#endif
cfg->check_pinvoke_callconv = debug_options.check_pinvoke_callconv;
cfg->disable_direct_icalls = disable_direct_icalls;
if (try_generic_shared)
- cfg->generic_sharing_context = (MonoGenericSharingContext*)&cfg->gsctx;
+ cfg->gshared = TRUE;
cfg->compile_llvm = try_llvm;
cfg->token_info_hash = g_hash_table_new (NULL, NULL);
+ if (cfg->compile_aot)
+ cfg->method_index = aot_method_index;
if (!mono_debug_count ())
cfg->opt &= ~MONO_OPT_FLOAT32;
return cfg;
}
- if (cfg->generic_sharing_context && (gsharedvt_method || mini_is_gsharedvt_sharable_method (method))) {
+ if (cfg->gshared && (gsharedvt_method || mini_is_gsharedvt_sharable_method (method))) {
MonoMethodInflated *inflated;
MonoGenericContext *context;
cfg->gsharedvt = TRUE;
// FIXME:
cfg->disable_llvm = TRUE;
+ cfg->exception_message = g_strdup ("gsharedvt");
}
- if (cfg->generic_sharing_context) {
+ if (cfg->gshared) {
method_to_register = method_to_compile;
- cfg->gshared = TRUE;
} else {
g_assert (method == method_to_compile);
method_to_register = method;
char *method_name;
method_name = mono_method_full_name (method, TRUE);
- g_print ("converting %s%s%smethod %s\n", COMPILE_LLVM (cfg) ? "llvm " : "", cfg->gsharedvt ? "gsharedvt " : "", (cfg->generic_sharing_context && !cfg->gsharedvt) ? "gshared " : "", method_name);
+ g_print ("converting %s%s%smethod %s\n", COMPILE_LLVM (cfg) ? "llvm " : "", cfg->gsharedvt ? "gsharedvt " : "", (cfg->gshared && !cfg->gsharedvt) ? "gshared " : "", method_name);
/*
if (COMPILE_LLVM (cfg))
g_print ("converting llvm method %s\n", method_name = mono_method_full_name (method, TRUE));
else if (cfg->gsharedvt)
g_print ("converting gsharedvt method %s\n", method_name = mono_method_full_name (method_to_compile, TRUE));
- else if (cfg->generic_sharing_context)
+ else if (cfg->gshared)
g_print ("converting shared method %s\n", method_name = mono_method_full_name (method_to_compile, TRUE));
else
g_print ("converting method %s\n", method_name = mono_method_full_name (method, TRUE));
if (!COMPILE_LLVM (cfg))
mono_if_conversion (cfg);
+ MONO_SUSPEND_CHECK ();
+
/* Depth-first ordering on basic blocks */
cfg->bblocks = mono_mempool_alloc (cfg->mempool, sizeof (MonoBasicBlock*) * (cfg->num_bblocks + 1));
#else
MonoCompile*
-mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFlags flags, int parts)
+mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFlags flags, int parts, int aot_method_index)
{
g_assert_not_reached ();
return NULL;
else
mono_lookup_pinvoke_call (method, NULL, NULL);
}
- nm = mono_marshal_get_native_wrapper (method, check_for_pending_exc, mono_aot_only);
+ nm = mono_marshal_get_native_wrapper (method, TRUE, mono_aot_only);
code = mono_get_addr_from_ftnptr (mono_compile_method (nm));
jinfo = mono_jit_info_table_find (target_domain, code);
if (!jinfo)
jit_timer = g_timer_new ();
- cfg = mini_method_compile (method, opt, target_domain, JIT_FLAG_RUN_CCTORS, 0);
+ cfg = mini_method_compile (method, opt, target_domain, JIT_FLAG_RUN_CCTORS, 0, -1);
prof_method = cfg->method;
g_timer_stop (jit_timer);
code = cfg->native_code;
- if (cfg->generic_sharing_context && mono_method_is_generic_sharable (method, FALSE))
+ if (cfg->gshared && mono_method_is_generic_sharable (method, FALSE))
mono_stats.generics_shared_methods++;
if (cfg->gsharedvt)
mono_stats.gsharedvt_methods++;
}
gpointer
-mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_sig, MonoMethodSignature *gsharedvt_sig, MonoGenericSharingContext *gsctx, gboolean gsharedvt_in, gint32 vcall_offset, gboolean calli)
+mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_sig, MonoMethodSignature *gsharedvt_sig, gboolean gsharedvt_in, gint32 vcall_offset, gboolean calli)
{
g_assert_not_reached ();
return NULL;
}
gpointer
-mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_sig, MonoMethodSignature *gsharedvt_sig, MonoGenericSharingContext *gsctx, gboolean gsharedvt_in, gint32 vcall_offset, gboolean calli)
+mono_arch_get_gsharedvt_call_info (gpointer addr, MonoMethodSignature *normal_sig, MonoMethodSignature *gsharedvt_sig, gboolean gsharedvt_in, gint32 vcall_offset, gboolean calli)
{
NOT_IMPLEMENTED;
return NULL;
#endif
+#ifndef ENABLE_LLVM
+void
+mono_llvm_emit_aot_file_info (MonoAotFileInfo *info, gboolean has_jitted_code)
+{
+ g_assert_not_reached ();
+}
+
+void mono_llvm_emit_aot_data (const char *symbol, guint8 *data, int data_len)
+{
+ g_assert_not_reached ();
+}
+#endif
+
#ifdef USE_JUMP_TABLES
#define DEFAULT_JUMPTABLE_CHUNK_ELEMENTS 128
}
#endif
-/*
- * mini_replace_type:
- *
- * Replace the type used in the metadata stream with what the JIT will actually use during compilation.
-*/
-MonoType*
-mini_replace_type (MonoType *type)
-{
- type = mono_type_get_underlying_type (type);
- return mini_native_type_replace_type (type);
-}
-
/*
* mini_get_underlying_type:
*
* For gsharedvt types, it will return the original VAR/MVAR.
*/
MonoType*
-mini_get_underlying_type (MonoCompile *cfg, MonoType *type)
+mini_get_underlying_type (MonoType *type)
{
- type = mini_type_get_underlying_type (cfg->generic_sharing_context, type);
- return mini_native_type_replace_type (type);
+ return mini_type_get_underlying_type (type);
}
void