X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mono%2Fmini%2Fmini.c;h=740ce48666b7ac03999a6b4cb7dd59705d82e7b7;hb=46c4f4e6587b08ccc6a086f6c422acf9e4f24856;hp=67aea21fee19ed726b0a15176cc95aba0d7f5aca;hpb=73e4bfeac790cee7681f3797caee41b65186fe7e;p=mono.git diff --git a/mono/mini/mini.c b/mono/mini/mini.c index 67aea21fee1..740ce48666b 100644 --- a/mono/mini/mini.c +++ b/mono/mini/mini.c @@ -85,8 +85,7 @@ gboolean mono_using_xdebug; #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; +#ifndef DISABLE_JIT gpointer mono_realloc_native_code (MonoCompile *cfg) @@ -199,6 +198,103 @@ void mono_nacl_fix_patches(const guint8 *code, MonoJumpInfo *ji) } #endif /* __native_client_codegen__ */ +#ifdef USE_JUMP_TABLES + +#define DEFAULT_JUMPTABLE_CHUNK_ELEMENTS 128 + +typedef struct MonoJumpTableChunk { + guint32 total; + guint32 active; + struct MonoJumpTableChunk *previous; + /* gpointer entries[total]; */ +} MonoJumpTableChunk; + +static MonoJumpTableChunk* g_jumptable; +#define mono_jumptable_lock() mono_mutex_lock (&jumptable_mutex) +#define mono_jumptable_unlock() mono_mutex_unlock (&jumptable_mutex) +static mono_mutex_t jumptable_mutex; + +static MonoJumpTableChunk* +mono_create_jumptable_chunk (guint32 max_entries) +{ + guint32 size = sizeof (MonoJumpTableChunk) + max_entries * sizeof(gpointer); + MonoJumpTableChunk *chunk = (MonoJumpTableChunk*) g_new0 (guchar, size); + chunk->total = max_entries; + return chunk; +} + +void +mono_jumptable_init (void) +{ + if (g_jumptable == NULL) { + mono_mutex_init_recursive (&jumptable_mutex); + g_jumptable = mono_create_jumptable_chunk (DEFAULT_JUMPTABLE_CHUNK_ELEMENTS); + } +} + +gpointer* +mono_jumptable_add_entry (void) +{ + return mono_jumptable_add_entries (1); +} + +gpointer* +mono_jumptable_add_entries (guint32 entries) +{ + guint32 index; + gpointer *result; + + mono_jumptable_init (); + mono_jumptable_lock (); + index = g_jumptable->active; + if (index + entries >= g_jumptable->total) { + /* + * Grow jumptable, by adding one more chunk. + * We cannot realloc jumptable, as there could be pointers + * to existing jump table entries in the code, so instead + * we just add one more chunk. + */ + guint32 max_entries = entries; + MonoJumpTableChunk *new_chunk; + + if (max_entries < DEFAULT_JUMPTABLE_CHUNK_ELEMENTS) + max_entries = DEFAULT_JUMPTABLE_CHUNK_ELEMENTS; + new_chunk = mono_create_jumptable_chunk (max_entries); + /* Link old jumptable, so that we could free it up later. */ + new_chunk->previous = g_jumptable; + g_jumptable = new_chunk; + index = 0; + } + g_jumptable->active = index + entries; + result = (gpointer*)((guchar*)g_jumptable + sizeof(MonoJumpTableChunk)) + index; + mono_jumptable_unlock(); + + return result; +} + +void +mono_jumptable_cleanup (void) +{ + if (g_jumptable) { + MonoJumpTableChunk *current = g_jumptable, *prev; + while (current != NULL) { + prev = current->previous; + g_free (current); + current = prev; + } + g_jumptable = NULL; + mono_mutex_destroy (&jumptable_mutex); + } +} + +gpointer* +mono_jumptable_get_entry (guint8 *code_ptr) +{ + return mono_arch_jumptable_entry_from_code (code_ptr); +} + +#endif /* USE_JUMP_TABLES */ + typedef struct { MonoExceptionClause *clause; MonoBasicBlock *basic_block; @@ -423,7 +519,7 @@ mono_reverse_branch_op (guint32 opcode) 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) { @@ -469,7 +565,7 @@ handle_enum: 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); @@ -480,7 +576,7 @@ handle_enum: 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: @@ -526,8 +622,8 @@ mono_type_to_load_membase (MonoCompile *cfg, MonoType *type) 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); @@ -535,25 +631,12 @@ mono_type_to_load_membase (MonoCompile *cfg, MonoType *type) return -1; } -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)); - return CEE_LDOBJ; - } - return mono_type_to_ldind (type); -} - -#ifndef DISABLE_JIT - 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); @@ -691,8 +774,6 @@ mono_decompose_op_imm (MonoCompile *cfg, MonoBasicBlock *bb, MonoInst *ins) bb->max_vreg = MAX (bb->max_vreg, cfg->next_vreg); } -#endif - static void set_vreg_to_inst (MonoCompile *cfg, int vreg, MonoInst *inst) { @@ -712,16 +793,6 @@ set_vreg_to_inst (MonoCompile *cfg, int vreg, MonoInst *inst) #define mono_type_is_long(type) (!(type)->byref && ((mono_type_get_underlying_type (type)->type == MONO_TYPE_I8) || (mono_type_get_underlying_type (type)->type == MONO_TYPE_U8))) #define mono_type_is_float(type) (!(type)->byref && (((type)->type == MONO_TYPE_R8) || ((type)->type == MONO_TYPE_R4))) -#ifdef DISABLE_JIT - -MonoInst* -mono_compile_create_var (MonoCompile *cfg, MonoType *type, int opcode) -{ - return NULL; -} - -#else - MonoInst* mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode, int vreg) { @@ -729,7 +800,7 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode, 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; @@ -757,7 +828,7 @@ mono_compile_create_var_for_vreg (MonoCompile *cfg, MonoType *type, int opcode, 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); } @@ -838,7 +909,7 @@ MonoInst* 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); @@ -851,19 +922,6 @@ mono_compile_create_var (MonoCompile *cfg, MonoType *type, int opcode) return mono_compile_create_var_for_vreg (cfg, type, opcode, dreg); } -/* - * Transform a MonoInst into a load from the variable of index var_index. - */ -void -mono_compile_make_var_load (MonoCompile *cfg, MonoInst *dest, gssize var_index) -{ - memset (dest, 0, sizeof (MonoInst)); - dest->inst_i0 = cfg->varinfo [var_index]; - dest->opcode = mini_type_to_ldind (cfg, dest->inst_i0->inst_vtype); - type_to_eval_stack_type (cfg, dest->inst_i0->inst_vtype, dest); - dest->klass = dest->inst_i0->klass; -} - MonoInst* mini_get_int_to_float_spill_area (MonoCompile *cfg) { @@ -878,8 +936,6 @@ mini_get_int_to_float_spill_area (MonoCompile *cfg) #endif } -#endif - void mono_mark_vreg_as_ref (MonoCompile *cfg, int vreg) { @@ -913,7 +969,8 @@ mono_mark_vreg_as_mp (MonoCompile *cfg, int vreg) } static MonoType* -type_from_stack_type (MonoInst *ins) { +type_from_stack_type (MonoInst *ins) +{ switch (ins->type) { case STACK_I4: return &mono_defaults.int32_class->byval_arg; case STACK_I8: return &mono_defaults.int64_class->byval_arg; @@ -944,7 +1001,8 @@ type_from_stack_type (MonoInst *ins) { } MonoType* -mono_type_from_stack_type (MonoInst *ins) { +mono_type_from_stack_type (MonoInst *ins) +{ return type_from_stack_type (ins); } @@ -1235,8 +1293,6 @@ compare_by_interval_start_pos_func (gconstpointer a, gconstpointer b) return 1; } -#ifndef DISABLE_JIT - #if 0 #define LSCAN_DEBUG(a) do { a; } while (0) #else @@ -1301,7 +1357,7 @@ mono_allocate_stack_slots2 (MonoCompile *cfg, gboolean backward, guint32 *stack_ 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 @@ -1312,7 +1368,7 @@ mono_allocate_stack_slots2 (MonoCompile *cfg, gboolean backward, guint32 *stack_ 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))) @@ -1323,7 +1379,7 @@ mono_allocate_stack_slots2 (MonoCompile *cfg, gboolean backward, guint32 *stack_ 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)) { @@ -1598,7 +1654,7 @@ mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_s 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 @@ -1608,7 +1664,7 @@ mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_s } 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) @@ -1622,7 +1678,7 @@ mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_s 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)) { @@ -1795,17 +1851,6 @@ mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_s return offsets; } -#else - -gint32* -mono_allocate_stack_slots (MonoCompile *cfg, gboolean backward, guint32 *stack_size, guint32 *stack_align) -{ - g_assert_not_reached (); - return NULL; -} - -#endif /* DISABLE_JIT */ - #define EMUL_HIT_SHIFT 3 #define EMUL_HIT_MASK ((1 << EMUL_HIT_SHIFT) - 1) /* small hit bitmap cache */ @@ -1854,7 +1899,8 @@ mini_register_opcode_emulation (int opcode, const char *name, const char *sigstr } static void -print_dfn (MonoCompile *cfg) { +print_dfn (MonoCompile *cfg) +{ int i, j; char *code; MonoBasicBlock *bb; @@ -2007,7 +2053,6 @@ mono_verify_cfg (MonoCompile *cfg) void mono_destroy_compile (MonoCompile *cfg) { -#ifndef DISABLE_JIT GSList *l; if (cfg->header) @@ -2034,11 +2079,8 @@ mono_destroy_compile (MonoCompile *cfg) g_free (cfg->vars); g_free (cfg->exception_message); g_free (cfg); -#endif } -#ifndef DISABLE_JIT - static MonoInst* mono_create_tls_get_offset (MonoCompile *cfg, int offset) { @@ -2071,12 +2113,15 @@ mini_tls_get_supported (MonoCompile *cfg, MonoTlsKey key) 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); @@ -2122,9 +2167,6 @@ mono_get_lmf_addr_intrinsic (MonoCompile* cfg) return mono_create_tls_get (cfg, TLS_KEY_LMF_ADDR); } -#endif /* !DISABLE_JIT */ - - void mono_add_patch_info (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target) { @@ -2196,8 +2238,6 @@ mono_add_var_location (MonoCompile *cfg, MonoInst *var, gboolean is_reg, int reg cfg->rgctx_loclist = g_slist_append_mempool (cfg->mempool, cfg->rgctx_loclist, entry); } -#ifndef DISABLE_JIT - static void mono_compile_create_vars (MonoCompile *cfg) { @@ -2529,7 +2569,7 @@ mono_codegen (MonoCompile *cfg) is_generic = TRUE; } - if (cfg->generic_sharing_context) + if (cfg->gshared) g_assert (is_generic); } @@ -2627,37 +2667,6 @@ mono_handle_out_of_line_bblock (MonoCompile *cfg) } } -#endif /* #ifndef DISABLE_JIT */ - -static MonoJitInfo* -create_jit_info_for_trampoline (MonoMethod *wrapper, MonoTrampInfo *info) -{ - MonoDomain *domain = mono_get_root_domain (); - MonoJitInfo *jinfo; - guint8 *uw_info; - guint32 info_len; - - if (info->uw_info) { - uw_info = info->uw_info; - info_len = info->uw_info_len; - } else { - uw_info = mono_unwind_ops_encode (info->unwind_ops, &info_len); - } - - jinfo = mono_domain_alloc0 (domain, MONO_SIZEOF_JIT_INFO); - jinfo->d.method = wrapper; - jinfo->code_start = info->code; - jinfo->code_size = info->code_size; - jinfo->unwind_info = mono_cache_unwind_info (uw_info, info_len); - - if (!info->uw_info) - g_free (uw_info); - - return jinfo; -} - -#ifndef DISABLE_JIT - static MonoJitInfo* create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile) { @@ -2671,7 +2680,7 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile) 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) { @@ -2683,7 +2692,7 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile) * 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; @@ -2728,7 +2737,7 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile) if (COMPILE_LLVM (cfg)) jinfo->from_llvm = TRUE; - if (cfg->generic_sharing_context) { + if (cfg->gshared) { MonoInst *inst; MonoGenericJitInfo *gi; GSList *loclist = NULL; @@ -2996,7 +3005,6 @@ create_jit_info (MonoCompile *cfg, MonoMethod *method_to_compile) return jinfo; } -#endif /* Return whenever METHOD is a gsharedvt method */ static gboolean @@ -3039,8 +3047,6 @@ is_open_method (MonoMethod *method) return FALSE; } -#ifndef DISABLE_JIT - #if defined(__native_client_codegen__) || USE_COOP_GC static void @@ -3098,6 +3104,42 @@ static void 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 (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->method->wrapper_type == MONO_WRAPPER_NATIVE_TO_MANAGED) { + if (cfg->verbose_level > 1) + printf ("SKIPPING SAFEPOINTS for native-to-managed wrappers.\n"); + return; + } + + if (cfg->method->wrapper_type == MONO_WRAPPER_MANAGED_TO_NATIVE) { + WrapperInfo *info = mono_marshal_get_wrapper_info (cfg->method); + + if (info && info->subtype == WRAPPER_SUBTYPE_ICALL_WRAPPER && + (info->d.icall.func == mono_thread_interruption_checkpoint || + info->d.icall.func == mono_threads_finish_blocking || + info->d.icall.func == mono_threads_reset_blocking_start)) { + /* These wrappers are called from the wrapper for the polling function, leading to potential stack overflow */ + if (cfg->verbose_level > 1) + printf ("SKIPPING SAFEPOINTS for wrapper %s\n", cfg->method->name); + return; + } + } if (cfg->verbose_level > 1) printf ("INSERTING SAFEPOINTS\n"); @@ -3230,7 +3272,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl cfg->orig_method = method; cfg->gen_seq_points = debug_options.gen_seq_points_compact_data || debug_options.gen_sdb_seq_points; cfg->gen_sdb_seq_points = debug_options.gen_sdb_seq_points; - cfg->flags = flags; + cfg->llvm_only = (flags & JIT_FLAG_LLVM_ONLY) != 0; #ifdef PLATFORM_ANDROID if (cfg->method->wrapper_type != MONO_WRAPPER_NONE) { @@ -3243,20 +3285,23 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl #if defined(__native_client_codegen__) || defined(USE_COOP_GC) cfg->opt |= MONO_OPT_LOOP; #endif - - cfg->explicit_null_checks = debug_options.explicit_null_checks; + cfg->explicit_null_checks = debug_options.explicit_null_checks || (flags & JIT_FLAG_EXPLICIT_NULL_CHECKS); cfg->soft_breakpoints = debug_options.soft_breakpoints; 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; + */ + if (cfg->llvm_only) + cfg->opt &= ~MONO_OPT_SIMD; cfg->r4fp = (cfg->opt & MONO_OPT_FLOAT32) ? 1 : 0; cfg->r4_stack_type = cfg->r4fp ? STACK_R4 : STACK_R8; @@ -3269,7 +3314,7 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl 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; @@ -3292,11 +3337,11 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl 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; @@ -3343,11 +3388,15 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl if (COMPILE_LLVM (cfg)) { mono_llvm_check_method_supported (cfg); if (cfg->disable_llvm) { - if (cfg->verbose_level >= 1) { + if (cfg->verbose_level >= cfg->llvm_only ? 0 : 1) { //nm = mono_method_full_name (cfg->method, TRUE); printf ("LLVM failed for '%s': %s\n", method->name, cfg->exception_message); //g_free (nm); } + if (cfg->llvm_only) { + cfg->disable_aot = TRUE; + return cfg; + } mono_destroy_compile (cfg); try_llvm = FALSE; goto restart_compile; @@ -3437,13 +3486,13 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl 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)); @@ -3570,6 +3619,8 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl 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)); @@ -3856,11 +3907,15 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl if (!cfg->disable_llvm) mono_llvm_emit_method (cfg); if (cfg->disable_llvm) { - if (cfg->verbose_level >= 1) { + if (cfg->verbose_level >= cfg->llvm_only ? 0 : 1) { //nm = mono_method_full_name (cfg->method, TRUE); printf ("LLVM failed for '%s': %s\n", method->name, cfg->exception_message); //g_free (nm); } + if (cfg->llvm_only) { + cfg->disable_aot = TRUE; + return cfg; + } mono_destroy_compile (cfg); try_llvm = FALSE; goto restart_compile; @@ -3946,17 +4001,63 @@ mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFl return cfg; } -#else +void* +mono_arch_instrument_epilog (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments) +{ + return mono_arch_instrument_epilog_full (cfg, func, p, enable_arguments, FALSE); +} -MonoCompile* -mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFlags flags, int parts, int aot_method_index) +void +mono_cfg_add_try_hole (MonoCompile *cfg, MonoExceptionClause *clause, guint8 *start, MonoBasicBlock *bb) { - g_assert_not_reached (); - return NULL; + TryBlockHole *hole = mono_mempool_alloc (cfg->mempool, sizeof (TryBlockHole)); + hole->clause = clause; + hole->start_offset = start - cfg->native_code; + hole->basic_block = bb; + + cfg->try_block_holes = g_slist_append_mempool (cfg->mempool, cfg->try_block_holes, hole); +} + +void +mono_cfg_set_exception (MonoCompile *cfg, int type) +{ + cfg->exception_type = type; } #endif /* DISABLE_JIT */ +static MonoJitInfo* +create_jit_info_for_trampoline (MonoMethod *wrapper, MonoTrampInfo *info) +{ + MonoDomain *domain = mono_get_root_domain (); + MonoJitInfo *jinfo; + guint8 *uw_info; + guint32 info_len; + + if (info->uw_info) { + uw_info = info->uw_info; + info_len = info->uw_info_len; + } else { + uw_info = mono_unwind_ops_encode (info->unwind_ops, &info_len); + } + + jinfo = mono_domain_alloc0 (domain, MONO_SIZEOF_JIT_INFO); + jinfo->d.method = wrapper; + jinfo->code_start = info->code; + jinfo->code_size = info->code_size; + jinfo->unwind_info = mono_cache_unwind_info (uw_info, info_len); + + if (!info->uw_info) + g_free (uw_info); + + return jinfo; +} + +/* + * mono_jit_compile_method_inner: + * + * Main entry point for the JIT. + */ gpointer mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, int opt, MonoException **jit_ex) { @@ -3986,7 +4087,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in 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) @@ -4015,6 +4116,10 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in */ return mono_get_addr_from_ftnptr ((gpointer)mono_icall_get_wrapper_full (mi, TRUE)); } else if (*name == 'I' && (strcmp (name, "Invoke") == 0)) { + if (mono_llvm_only) { + nm = mono_marshal_get_delegate_invoke (method, NULL); + return mono_get_addr_from_ftnptr (mono_compile_method (nm)); + } return mono_create_delegate_trampoline (target_domain, method->klass); } else if (*name == 'B' && (strcmp (name, "BeginInvoke") == 0)) { nm = mono_marshal_get_delegate_begin_invoke (method); @@ -4185,7 +4290,7 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in 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++; @@ -4277,82 +4382,34 @@ mono_jit_compile_method_inner (MonoMethod *method, MonoDomain *target_domain, in return code; } -#ifndef DISABLE_JIT - -void* -mono_arch_instrument_epilog (MonoCompile *cfg, void *func, void *p, gboolean enable_arguments) { - return mono_arch_instrument_epilog_full (cfg, func, p, enable_arguments, FALSE); -} - -void -mono_cfg_add_try_hole (MonoCompile *cfg, MonoExceptionClause *clause, guint8 *start, MonoBasicBlock *bb) +/* + * mini_get_underlying_type: + * + * Return the type the JIT will use during compilation. + * Handles: byref, enums, native types, generic sharing. + * For gsharedvt types, it will return the original VAR/MVAR. + */ +MonoType* +mini_get_underlying_type (MonoType *type) { - TryBlockHole *hole = mono_mempool_alloc (cfg->mempool, sizeof (TryBlockHole)); - hole->clause = clause; - hole->start_offset = start - cfg->native_code; - hole->basic_block = bb; - - cfg->try_block_holes = g_slist_append_mempool (cfg->mempool, cfg->try_block_holes, hole); + return mini_type_get_underlying_type (type); } void -mono_cfg_set_exception (MonoCompile *cfg, int type) -{ - cfg->exception_type = type; -} - -#endif - -/* Dummy versions of some arch specific functions to avoid ifdefs at call sites */ - -#ifndef MONO_ARCH_GSHAREDVT_SUPPORTED - -gboolean -mono_arch_gsharedvt_sig_supported (MonoMethodSignature *sig) -{ - return FALSE; -} - -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) -{ - g_assert_not_reached (); - return NULL; -} - -gpointer -mono_arch_get_gsharedvt_arg_trampoline (MonoDomain *domain, gpointer arg, gpointer addr) +mini_jit_init (void) { - g_assert_not_reached (); - return NULL; + mono_mutex_init_recursive (&jit_mutex); } -gpointer -mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot) +void +mini_jit_cleanup (void) { - g_assert_not_reached (); - return NULL; -} - +#ifndef DISABLE_JIT + g_free (emul_opcode_map); + g_free (emul_opcode_opcodes); #endif - -#if defined(MONO_ARCH_GSHAREDVT_SUPPORTED) && !defined(ENABLE_GSHAREDVT) - -gboolean -mono_arch_gsharedvt_sig_supported (MonoMethodSignature *sig) -{ - return FALSE; -} - -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) -{ - NOT_IMPLEMENTED; - return NULL; } -#endif - #ifndef ENABLE_LLVM void mono_llvm_emit_aot_file_info (MonoAotFileInfo *info, gboolean has_jitted_code) @@ -4366,136 +4423,25 @@ void mono_llvm_emit_aot_data (const char *symbol, guint8 *data, int data_len) } #endif -#ifdef USE_JUMP_TABLES -#define DEFAULT_JUMPTABLE_CHUNK_ELEMENTS 128 - -typedef struct MonoJumpTableChunk { - guint32 total; - guint32 active; - struct MonoJumpTableChunk *previous; - /* gpointer entries[total]; */ -} MonoJumpTableChunk; - -static MonoJumpTableChunk* g_jumptable; -#define mono_jumptable_lock() mono_mutex_lock (&jumptable_mutex) -#define mono_jumptable_unlock() mono_mutex_unlock (&jumptable_mutex) -static mono_mutex_t jumptable_mutex; - -static MonoJumpTableChunk* -mono_create_jumptable_chunk (guint32 max_entries) -{ - guint32 size = sizeof (MonoJumpTableChunk) + max_entries * sizeof(gpointer); - MonoJumpTableChunk *chunk = (MonoJumpTableChunk*) g_new0 (guchar, size); - chunk->total = max_entries; - return chunk; -} - -void -mono_jumptable_init (void) -{ - if (g_jumptable == NULL) { - mono_mutex_init_recursive (&jumptable_mutex); - g_jumptable = mono_create_jumptable_chunk (DEFAULT_JUMPTABLE_CHUNK_ELEMENTS); - } -} - -gpointer* -mono_jumptable_add_entry (void) -{ - return mono_jumptable_add_entries (1); -} +#ifdef DISABLE_JIT -gpointer* -mono_jumptable_add_entries (guint32 entries) +MonoCompile* +mini_method_compile (MonoMethod *method, guint32 opts, MonoDomain *domain, JitFlags flags, int parts, int aot_method_index) { - guint32 index; - gpointer *result; - - mono_jumptable_init (); - mono_jumptable_lock (); - index = g_jumptable->active; - if (index + entries >= g_jumptable->total) { - /* - * Grow jumptable, by adding one more chunk. - * We cannot realloc jumptable, as there could be pointers - * to existing jump table entries in the code, so instead - * we just add one more chunk. - */ - guint32 max_entries = entries; - MonoJumpTableChunk *new_chunk; - - if (max_entries < DEFAULT_JUMPTABLE_CHUNK_ELEMENTS) - max_entries = DEFAULT_JUMPTABLE_CHUNK_ELEMENTS; - new_chunk = mono_create_jumptable_chunk (max_entries); - /* Link old jumptable, so that we could free it up later. */ - new_chunk->previous = g_jumptable; - g_jumptable = new_chunk; - index = 0; - } - g_jumptable->active = index + entries; - result = (gpointer*)((guchar*)g_jumptable + sizeof(MonoJumpTableChunk)) + index; - mono_jumptable_unlock(); - - return result; + g_assert_not_reached (); + return NULL; } void -mono_jumptable_cleanup (void) -{ - if (g_jumptable) { - MonoJumpTableChunk *current = g_jumptable, *prev; - while (current != NULL) { - prev = current->previous; - g_free (current); - current = prev; - } - g_jumptable = NULL; - mono_mutex_destroy (&jumptable_mutex); - } -} - -gpointer* -mono_jumptable_get_entry (guint8 *code_ptr) -{ - return mono_arch_jumptable_entry_from_code (code_ptr); -} -#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: - * - * Return the type the JIT will use during compilation. - * Handles: byref, enums, native types, generic sharing. - * For gsharedvt types, it will return the original VAR/MVAR. - */ -MonoType* -mini_get_underlying_type (MonoCompile *cfg, MonoType *type) +mono_destroy_compile (MonoCompile *cfg) { - type = mini_type_get_underlying_type (cfg->generic_sharing_context, type); - return mini_native_type_replace_type (type); + g_assert_not_reached (); } void -mini_jit_init (void) +mono_add_patch_info (MonoCompile *cfg, int ip, MonoJumpInfoType type, gconstpointer target) { - mono_mutex_init_recursive (&jit_mutex); + g_assert_not_reached (); } -void -mini_jit_cleanup (void) -{ - g_free (emul_opcode_map); - g_free (emul_opcode_opcodes); -} +#endif /* DISABLE_JIT */