2008-07-08 Zoltan Varga <vargaz@gmail.com>
+ * tramp-amd64.c (mono_arch_nullify_plt_entry): Read the nullified class
+ init trampoline from the AOT file as well.
+
+ * mini-amd64.c (mono_arch_register_lowlevel_calls): Register
+ mono_amd64_throw_exception as a jit icall since it is needed by the aot-only
+ code.
+
+ * mini.c (mini_init): Move the call to mono_exceptions_init () after
+ mono_init.
+
+ * exceptions-amd64.c: Add _full variants for the remaining exception code
+ creation functions as well, allow emission of relocatable code, remove
+ caching since that is now done by the caller.
+
+ * mini-exceptions.c: Add _full variants for the remaining exception code
+ creation functions as well, add aot-only support.
+
+ * aot-compiler.c (compile_method): Allow calls to methods of constructed types
+ if we can determine a proper token for them.
+ (add_wrappers): Add a few more wrappers.
+ (emit_method_code): Remove some dead code.
+ (emit_trampolines): Emit exception code too.
+
* mini.c (mono_method_to_ir): Call mono_array_new_2 if possible.
* jit-icalls.c (mono_array_new_2): New jit icall, specialized version of
g_assert (image_index < 255);
token = ji->token;
+ /* Marker */
+ encode_value ((255 << 24), buf, &buf);
+ encode_value (image_index, buf, &buf);
+ encode_value (token, buf, &buf);
+ } else if (token == 0) {
+ /* This might be a method of a constructed type like int[,].Set */
+ /* Obtain the token from information recorded by the JIT */
+ ji = g_hash_table_lookup (acfg->token_info_hash, method);
+ g_assert (ji);
+ image_index = get_image_index (acfg, ji->image);
+ g_assert (image_index < 255);
+ token = ji->token;
+
/* Marker */
encode_value ((255 << 24), buf, &buf);
encode_value (image_index, buf, &buf);
}
static MonoMethod*
-get_runtime_invoke (const char *signature)
+get_runtime_invoke_sig (MonoMethodSignature *sig)
{
MonoMethodBuilder *mb;
MonoMethod *m;
mb = mono_mb_new (mono_defaults.object_class, "FOO", MONO_WRAPPER_NONE);
- m = mono_mb_create_method (mb, mono_create_icall_signature (signature), 16);
+ m = mono_mb_create_method (mb, sig, 16);
return mono_marshal_get_runtime_invoke (m);
}
+static MonoMethod*
+get_runtime_invoke (const char *signature)
+{
+ return get_runtime_invoke_sig (mono_create_icall_signature (signature));
+}
+
static void
add_wrappers (MonoAotCompile *acfg)
{
MonoMethod *m;
int i, nallocators;
+ MonoMethodSignature *csig;
/*
* FIXME: Instead of AOTing all the wrappers, it might be better to redesign them
/* void runtime-invoke (string) [exception ctor] */
add_method (acfg, get_runtime_invoke ("void string"));
+ /* void runtime-invoke (string, string) [exception ctor] */
+ add_method (acfg, get_runtime_invoke ("void string string"));
+
+ /* string runtime-invoke () [Exception.ToString ()] */
+ add_method (acfg, get_runtime_invoke ("string"));
+
+ /* void runtime-invoke (string, Exception) [exception ctor] */
+ csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
+ csig->hasthis = 1;
+ csig->ret = &mono_defaults.void_class->byval_arg;
+ csig->params [0] = &mono_defaults.string_class->byval_arg;
+ csig->params [1] = &mono_defaults.exception_class->byval_arg;
+ add_method (acfg, get_runtime_invoke_sig (csig));
+
+ /* Assembly runtime-invoke (string, bool) [DoAssemblyResolve] */
+ csig = mono_metadata_signature_alloc (mono_defaults.corlib, 2);
+ csig->hasthis = 1;
+ csig->ret = &(mono_class_from_name (
+ mono_defaults.corlib, "System.Reflection", "Assembly"))->byval_arg;
+ csig->params [0] = &mono_defaults.string_class->byval_arg;
+ csig->params [1] = &mono_defaults.boolean_class->byval_arg;
+ add_method (acfg, get_runtime_invoke_sig (csig));
+
for (i = 0; i < acfg->image->tables [MONO_TABLE_METHOD].rows; ++i) {
MonoMethod *method;
guint32 token = MONO_TOKEN_METHOD_DEF | (i + 1);
emit_and_reloc_code (acfg, method, code, cfg->code_len, cfg->patch_info, FALSE);
-#if 0
- /* Collect and sort relocations */
- patches = g_ptr_array_new ();
- for (patch_info = cfg->patch_info; patch_info; patch_info = patch_info->next)
- g_ptr_array_add (patches, patch_info);
- g_ptr_array_sort (patches, compare_patches);
-
- start_index = 0;
- for (i = 0; i < cfg->code_len; i++) {
- patch_info = NULL;
- for (pindex = start_index; pindex < patches->len; ++pindex) {
- patch_info = g_ptr_array_index (patches, pindex);
- if (patch_info->ip.i >= i)
- break;
- }
-
-#ifdef MONO_ARCH_AOT_SUPPORTED
- skip = FALSE;
- if (patch_info && (patch_info->ip.i == i) && (pindex < patches->len)) {
- start_index = pindex;
-
- switch (patch_info->type) {
- case MONO_PATCH_INFO_NONE:
- break;
- case MONO_PATCH_INFO_GOT_OFFSET: {
- guint32 offset = mono_arch_get_patch_offset (code + i);
- emit_bytes (acfg, code + i, offset);
- emit_symbol_diff (acfg, "got", ".", offset);
-
- i += offset + 4 - 1;
- skip = TRUE;
- break;
- }
- default: {
- int plt_index;
- char *direct_call_target;
-
- if (!is_got_patch (patch_info->type))
- break;
-
- /*
- * If this patch is a call, try emitting a direct call instead of
- * through a PLT entry. This is possible if the called method is in
- * the same assembly and requires no initialization.
- */
- direct_call_target = NULL;
- if ((patch_info->type == MONO_PATCH_INFO_METHOD) && (patch_info->data.method->klass->image == cfg->method->klass->image)) {
- MonoCompile *callee_cfg = g_hash_table_lookup (acfg->method_to_cfg, patch_info->data.method);
- if (callee_cfg) {
- if (!callee_cfg->has_got_slots && (callee_cfg->method->klass->flags & TYPE_ATTRIBUTE_BEFORE_FIELD_INIT)) {
- //printf ("DIRECT: %s %s\n", mono_method_full_name (cfg->method, TRUE), mono_method_full_name (callee_cfg->method, TRUE));
- direct_call_target = g_strdup_printf (".Lm_%x", get_method_index (acfg, callee_cfg->method));
- patch_info->type = MONO_PATCH_INFO_NONE;
- acfg->stats.direct_calls ++;
- }
- }
-
- acfg->stats.all_calls ++;
- }
-
- if (!direct_call_target) {
- plt_index = get_plt_index (acfg, patch_info);
- if (plt_index != -1) {
- /* This patch has a PLT entry, so we must emit a call to the PLT entry */
- direct_call_target = g_strdup_printf (".Lp_%d", plt_index);
- }
- }
-
- if (direct_call_target) {
-#if defined(__i386__) || defined(__x86_64__)
- g_assert (code [i] == 0xe8);
- /* Need to make sure this is exactly 5 bytes long */
- emit_byte (acfg, '\xe8');
- emit_symbol_diff (acfg, direct_call_target, ".", -4);
- i += 4;
-#elif defined(__arm__)
-#ifdef USE_BIN_WRITER
- /* FIXME: Can't encode this using the current symbol writer functions */
- g_assert_not_reached ();
-#else
- emit_unset_mode (acfg);
- fprintf (acfg->fp, "bl %s\n", direct_call_target);
- i += 4 - 1;
-#endif
-#endif
- } else {
- got_slot = get_got_offset (acfg, patch_info);
-
- emit_bytes (acfg, code + i, mono_arch_get_patch_offset (code + i));
-#ifdef __x86_64__
- emit_symbol_diff (acfg, "got", ".", (unsigned int) ((got_slot * sizeof (gpointer)) - 4));
-#elif defined(__i386__)
- emit_int32 (acfg, (unsigned int) ((got_slot * sizeof (gpointer))));
-#elif defined(__arm__)
- emit_symbol_diff (acfg, "got", ".", (unsigned int) ((got_slot * sizeof (gpointer))) - 12);
-#else
- g_assert_not_reached ();
-#endif
-
- i += mono_arch_get_patch_offset (code + i) + 4 - 1;
- }
- skip = TRUE;
- }
- }
- }
-#endif /* MONO_ARCH_AOT_SUPPORTED */
-
- if (!skip)
- emit_bytes (acfg, code + i, 1);
- }
-#endif
-
emit_line (acfg);
}
}
static void
-emit_named_code (MonoAotCompile *acfg, char *name, guint8 *code, guint32 code_size,
- int got_offset, MonoJumpInfo *ji)
+emit_named_code (MonoAotCompile *acfg, const char *name, guint8 *code,
+ guint32 code_size, int got_offset, MonoJumpInfo *ji)
{
char *symbol;
guint32 buf_size;
g_ptr_array_add (patches, patch_info);
g_ptr_array_sort (patches, compare_patches);
- buf_size = patches->len * 128;
+ buf_size = patches->len * 128 + 128;
buf = g_malloc (buf_size);
p = buf;
{
char *symbol;
int tramp_type, i, offset;
+#ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
+ guint32 code_size;
+ MonoJumpInfo *ji;
+ guint8 *code;
+#endif
if (!acfg->aot_opts.full_aot)
return;
* method.
*/
for (tramp_type = 0; tramp_type < MONO_TRAMPOLINE_NUM; ++tramp_type) {
- guint32 code_size;
- MonoJumpInfo *ji;
- guint8 *code;
-
code = mono_arch_create_trampoline_code_full (tramp_type, &code_size, &ji, TRUE);
/* Emit trampoline code */
g_free (symbol);
}
+
+ code = mono_arch_get_nullified_class_init_trampoline (&code_size);
+ emit_named_code (acfg, "nullified_class_init_trampoline", code, code_size, acfg->got_offset, NULL);
+
+ /* Emit the exception related code pieces */
+ code = mono_arch_get_restore_context_full (&code_size, &ji, TRUE);
+ emit_named_code (acfg, "restore_context", code, code_size, acfg->got_offset, ji);
+ code = mono_arch_get_call_filter_full (&code_size, &ji, TRUE);
+ emit_named_code (acfg, "call_filter", code, code_size, acfg->got_offset, ji);
+ code = mono_arch_get_throw_exception_full (&code_size, &ji, TRUE);
+ emit_named_code (acfg, "throw_exception", code, code_size, acfg->got_offset, ji);
+ code = mono_arch_get_rethrow_exception_full (&code_size, &ji, TRUE);
+ emit_named_code (acfg, "rethrow_exception", code, code_size, acfg->got_offset, ji);
+ code = mono_arch_get_throw_exception_by_name_full (&code_size, &ji, TRUE);
+ emit_named_code (acfg, "throw_exception_by_name", code, code_size, acfg->got_offset, ji);
+ code = mono_arch_get_throw_corlib_exception_full (&code_size, &ji, TRUE);
+ emit_named_code (acfg, "throw_corlib_exception", code, code_size, acfg->got_offset, ji);
#endif
/*
skip = TRUE;
break;
}
- if (!patch_info->data.method->token)
- /*
- * The method is part of a constructed type like Int[,].Set (). It doesn't
- * have a token, and we can't make one, since the parent type is part of
- * assembly which contains the element type, and not the assembly which
- * referenced this type.
- */
- skip = TRUE;
+ if (!patch_info->data.method->token) {
+ /* The method is part of a constructed type like Int[,].Set (). */
+ if (!g_hash_table_lookup (acfg->token_info_hash, patch_info->data.method))
+ skip = TRUE;
+ }
if (patch_info->data.method->is_inflated && !g_hash_table_lookup (acfg->token_info_hash, patch_info->data.method))
/* FIXME: Can't encode these */
skip = TRUE;
GHashTable *wrappers;
MonoAssemblyName *image_names;
char **image_guids;
+ MonoAssembly *assembly;
MonoImage **image_table;
guint32 image_table_len;
gboolean out_of_date;
}
if (!usable) {
- if (mono_aot_only)
- g_error ("Failed to load AOT module '%s' while running with --aot-only.\n", aot_name);
+ if (mono_aot_only) {
+ fprintf (stderr, "Failed to load AOT module '%s' while running with --aot-only.\n", aot_name);
+ exit (1);
+ }
g_free (aot_name);
mono_dl_close (assembly->aot_module);
assembly->aot_module = NULL;
info = g_new0 (MonoAotModule, 1);
info->aot_name = aot_name;
+ info->assembly = assembly;
info->got = got;
info->got_size = *got_size_ptr;
info->got [0] = assembly->image;
ji->data.image = load_image (aot_module, decode_value (p, &p));
if (!ji->data.image)
goto cleanup;
+ if (ji->data.image == aot_module->assembly->image)
+ *got_offset = 0;
break;
case MONO_PATCH_INFO_FIELD:
case MONO_PATCH_INFO_SFLDA:
}
/*
- * Return the piece of code identified by NAME from the AOT file.
+ * Return the piece of code identified by NAME from the mscorlib AOT file.
*/
-static gpointer
-mono_aot_get_named_code (MonoAssembly *assembly, MonoAotModule *aot_module, char *name)
+gpointer
+mono_aot_get_named_code (const char *name)
{
char *symbol;
guint8 *p;
int n_patches, got_index, pindex;
MonoMemPool *mp;
gpointer code;
+ MonoImage *image;
+ MonoAssembly *assembly;
+ MonoAotModule *amodule;
+
+ image = mono_defaults.corlib;
+ g_assert (image);
+
+ mono_aot_lock ();
+
+ assembly = image->assembly;
+ g_assert (assembly);
+ amodule = (MonoAotModule*) g_hash_table_lookup (aot_modules, assembly);
+ g_assert (amodule);
+
+ mono_aot_unlock ();
/* Load the code */
got_index = decode_value (p, &p);
- patches = load_patch_info (aot_module, mp, n_patches, got_index, &got_slots, p, &p);
+ patches = load_patch_info (amodule, mp, n_patches, got_index, &got_slots, p, &p);
g_assert (patches);
for (pindex = 0; pindex < n_patches; ++pindex) {
MonoJumpInfo *ji = &patches [pindex];
gpointer target;
- g_assert (ji->type == MONO_PATCH_INFO_JIT_ICALL_ADDR);
-
/*
* When this code is executed, the runtime may not yet initalized, so
* resolve the patch info by hand.
*/
- if (!strcmp (ji->data.name, "mono_get_lmf_addr")) {
- target = mono_get_lmf_addr;
- } else if (!strcmp (ji->data.name, "mono_thread_force_interruption_checkpoint")) {
- target = mono_thread_force_interruption_checkpoint;
- } else if (strstr (ji->data.name, "trampoline_func_") == ji->data.name) {
- int tramp_type2 = atoi (ji->data.name + strlen ("trampoline_func_"));
- target = (gpointer)mono_get_trampoline_func (tramp_type2);
+ if (ji->type == MONO_PATCH_INFO_JIT_ICALL_ADDR) {
+ if (!strcmp (ji->data.name, "mono_get_lmf_addr")) {
+ target = mono_get_lmf_addr;
+ } else if (!strcmp (ji->data.name, "mono_thread_force_interruption_checkpoint")) {
+ target = mono_thread_force_interruption_checkpoint;
+ } else if (!strcmp (ji->data.name, "mono_exception_from_token")) {
+ target = mono_exception_from_token;
+ } else if (!strcmp (ji->data.name, "mono_throw_exception")) {
+ target = mono_get_throw_exception ();
+#ifdef __x86_64__
+ } else if (!strcmp (ji->data.name, "mono_amd64_throw_exception")) {
+ target = mono_amd64_throw_exception;
+#endif
+ } else if (strstr (ji->data.name, "trampoline_func_") == ji->data.name) {
+ int tramp_type2 = atoi (ji->data.name + strlen ("trampoline_func_"));
+ target = (gpointer)mono_get_trampoline_func (tramp_type2);
+ } else {
+ fprintf (stderr, "%s\n", ji->data.name);
+ g_assert_not_reached ();
+ target = NULL;
+ }
} else {
- fprintf (stderr, "%s\n", ji->data.name);
- g_assert_not_reached ();
- target = NULL;
+ /* Hopefully the code doesn't have patches which need method or
+ * domain to be set.
+ */
+ target = mono_resolve_patch_target (NULL, NULL, code, ji, FALSE);
}
- aot_module->got [got_slots [pindex]] = target;
+ amodule->got [got_slots [pindex]] = target;
}
g_free (got_slots);
char *symbol;
symbol = g_strdup_printf ("generic_trampoline_%d", tramp_type);
- generic_trampolines [tramp_type] = mono_aot_get_named_code (image->assembly, amodule, symbol);
+ generic_trampolines [tramp_type] = mono_aot_get_named_code (symbol);
g_free (symbol);
}
#ifdef __x86_64__
code = amodule->trampolines + (index * 16);
+ if (code_len)
+ *code_len = 16;
#else
g_assert_not_reached ();
#endif
g_assert_not_reached ();
}
+gpointer
+mono_aot_get_named_code (char *name)
+{
+ g_assert_not_reached ();
+}
+
#endif
gpointer
mono_arch_get_restore_context_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot)
{
- static guint8 *start = NULL;
- static gboolean inited = FALSE;
+ guint8 *start = NULL;
guint8 *code;
- if (inited)
- return start;
-
/* restore_contect (MonoContext *ctx) */
*ji = NULL;
*code_size = code - start;
- inited = TRUE;
-
return start;
}
gpointer
mono_arch_get_call_filter_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot)
{
- static guint8 *start;
- static gboolean inited = FALSE;
+ guint8 *start;
int i;
guint8 *code;
guint32 pos;
- if (inited)
- return start;
-
*ji = NULL;
start = code = mono_global_codeman_reserve (128);
*code_size = code - start;
- inited = TRUE;
-
return start;
}
* The first few arguments are dummy, to force the other arguments to be passed on
* the stack, this avoids overwriting the argument registers in the throw trampoline.
*/
-static void
-throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4,
- guint64 dummy5, guint64 dummy6,
- MonoObject *exc, guint64 rip, guint64 rsp,
- guint64 rbx, guint64 rbp, guint64 r12, guint64 r13,
- guint64 r14, guint64 r15, guint64 rdi, guint64 rsi,
- guint64 rax, guint64 rcx, guint64 rdx,
- guint64 rethrow)
+void
+mono_amd64_throw_exception (guint64 dummy1, guint64 dummy2, guint64 dummy3, guint64 dummy4,
+ guint64 dummy5, guint64 dummy6,
+ MonoObject *exc, guint64 rip, guint64 rsp,
+ guint64 rbx, guint64 rbp, guint64 r12, guint64 r13,
+ guint64 r14, guint64 r15, guint64 rdi, guint64 rsi,
+ guint64 rax, guint64 rcx, guint64 rdx,
+ guint64 rethrow)
{
static void (*restore_context) (MonoContext *);
MonoContext ctx;
}
static gpointer
-get_throw_trampoline (gboolean rethrow)
+get_throw_trampoline (gboolean rethrow, guint32 *code_size, MonoJumpInfo **ji, gboolean aot)
{
guint8* start;
guint8 *code;
code = start;
+ *ji = NULL;
+
amd64_mov_reg_reg (code, AMD64_R11, AMD64_RSP, 8);
/* reverse order */
amd64_push_imm (code, 0);
#endif
- amd64_mov_reg_imm (code, AMD64_R11, throw_exception);
+ if (aot) {
+ *ji = mono_patch_info_list_prepend (*ji, code - start, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_amd64_throw_exception");
+ amd64_mov_reg_membase (code, AMD64_R11, AMD64_RIP, 0, 8);
+ } else {
+ amd64_mov_reg_imm (code, AMD64_R11, mono_amd64_throw_exception);
+ }
amd64_call_reg (code, AMD64_R11);
amd64_breakpoint (code);
g_assert ((code - start) < 64);
+ *code_size = code - start;
+
return start;
}
gpointer
mono_arch_get_throw_exception_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot)
{
- static guint8* start;
- static gboolean inited = FALSE;
-
- if (inited)
- return start;
-
- start = get_throw_trampoline (FALSE);
-
- inited = TRUE;
-
- return start;
+ return get_throw_trampoline (FALSE, code_size, ji, aot);
}
gpointer
mono_arch_get_rethrow_exception_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot)
{
- static guint8* start;
- static gboolean inited = FALSE;
-
- if (inited)
- return start;
-
- start = get_throw_trampoline (TRUE);
-
- inited = TRUE;
-
- return start;
+ return get_throw_trampoline (TRUE, code_size, ji, aot);
}
gpointer
-mono_arch_get_throw_exception_by_name (void)
+mono_arch_get_throw_exception_by_name_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot)
{
- static guint8* start;
- static gboolean inited = FALSE;
+ guint8* start;
guint8 *code;
- if (inited)
- return start;
-
start = code = mono_global_codeman_reserve (64);
+ *ji = NULL;
+
/* Not used on amd64 */
amd64_breakpoint (code);
mono_arch_flush_icache (start, code - start);
+ *code_size = code - start;
+
return start;
}
* needs no relocations in the caller.
*/
gpointer
-mono_arch_get_throw_corlib_exception (void)
+mono_arch_get_throw_corlib_exception_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot)
{
static guint8* start;
- static gboolean inited = FALSE;
guint8 *code;
guint64 throw_ex;
- if (inited)
- return start;
-
start = code = mono_global_codeman_reserve (64);
+ *ji = NULL;
+
/* Push throw_ip */
amd64_push_reg (code, AMD64_ARG_REG2);
/* Call exception_from_token */
amd64_mov_reg_reg (code, AMD64_ARG_REG2, AMD64_ARG_REG1, 8);
- amd64_mov_reg_imm (code, AMD64_ARG_REG1, mono_defaults.exception_class->image);
- amd64_mov_reg_imm (code, AMD64_R11, mono_exception_from_token);
+ if (aot) {
+ *ji = mono_patch_info_list_prepend (*ji, code - start, MONO_PATCH_INFO_IMAGE, mono_defaults.exception_class->image);
+ amd64_mov_reg_membase (code, AMD64_ARG_REG1, AMD64_RIP, 0, 8);
+ *ji = mono_patch_info_list_prepend (*ji, code - start, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_exception_from_token");
+ amd64_mov_reg_membase (code, AMD64_R11, AMD64_RIP, 0, 8);
+ } else {
+ amd64_mov_reg_imm (code, AMD64_ARG_REG1, mono_defaults.exception_class->image);
+ amd64_mov_reg_imm (code, AMD64_R11, mono_exception_from_token);
+ }
amd64_call_reg (code, AMD64_R11);
/* Compute throw_ip */
/* Call throw_exception */
amd64_mov_reg_reg (code, AMD64_ARG_REG1, AMD64_RAX, 8);
- amd64_mov_reg_imm (code, AMD64_R11, throw_ex);
+ if (aot) {
+ *ji = mono_patch_info_list_prepend (*ji, code - start, MONO_PATCH_INFO_JIT_ICALL_ADDR, "mono_throw_exception");
+ amd64_mov_reg_membase (code, AMD64_R11, AMD64_RIP, 0, 8);
+ } else {
+ amd64_mov_reg_imm (code, AMD64_R11, throw_ex);
+ }
/* The original IP is on the stack */
amd64_jump_reg (code, AMD64_R11);
mono_arch_flush_icache (start, code - start);
- inited = TRUE;
+ *code_size = code - start;
return start;
}
void
mono_arch_register_lowlevel_calls (void)
{
+ /* The signature doesn't matter */
+ mono_register_jit_icall (mono_amd64_throw_exception, "mono_amd64_throw_exception", mono_create_icall_signature ("void"), TRUE);
}
void
guint32 code_size;
MonoJumpInfo *ji;
- restore_context_func = mono_arch_get_restore_context_full (&code_size, &ji, FALSE);
- call_filter_func = mono_arch_get_call_filter_full (&code_size, &ji, FALSE);
- throw_exception_func = mono_arch_get_throw_exception_full (&code_size, &ji, FALSE);
- rethrow_exception_func = mono_arch_get_rethrow_exception_full (&code_size, &ji, FALSE);
+ if (mono_aot_only) {
+ restore_context_func = mono_aot_get_named_code ("restore_context");
+ call_filter_func = mono_aot_get_named_code ("call_filter");
+ throw_exception_func = mono_aot_get_named_code ("throw_exception");
+ rethrow_exception_func = mono_aot_get_named_code ("rethrow_exception");
+ } else {
+ restore_context_func = mono_arch_get_restore_context_full (&code_size, &ji, FALSE);
+ call_filter_func = mono_arch_get_call_filter_full (&code_size, &ji, FALSE);
+ throw_exception_func = mono_arch_get_throw_exception_full (&code_size, &ji, FALSE);
+ rethrow_exception_func = mono_arch_get_rethrow_exception_full (&code_size, &ji, FALSE);
+ }
#else
#ifndef CUSTOM_EXCEPTION_HANDLING
restore_context_func = mono_arch_get_restore_context ();
mono_get_throw_exception_by_name (void)
{
gpointer code = NULL;
+#ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
+ guint32 code_size;
+ MonoJumpInfo *ji;
+#endif
/* This depends on corlib classes so cannot be inited in mono_exceptions_init () */
if (throw_exception_by_name_func)
return throw_exception_by_name_func;
- code = mono_arch_get_throw_exception_by_name ();
+#ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
+ if (mono_aot_only)
+ code = mono_aot_get_named_code ("throw_exception_by_name");
+ else
+ code = mono_arch_get_throw_exception_by_name_full (&code_size, &ji, FALSE);
+#else
+ code = mono_arch_get_throw_exception_by_name ();
+#endif
mono_memory_barrier ();
mono_get_throw_corlib_exception (void)
{
gpointer code = NULL;
+#ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
+ guint32 code_size;
+ MonoJumpInfo *ji;
+#endif
/* This depends on corlib classes so cannot be inited in mono_exceptions_init () */
if (throw_corlib_exception_func)
return throw_corlib_exception_func;
#if MONO_ARCH_HAVE_THROW_CORLIB_EXCEPTION
- code = mono_arch_get_throw_corlib_exception ();
+#ifdef MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES
+ if (mono_aot_only)
+ code = mono_aot_get_named_code ("throw_corlib_exception");
+ else
+ code = mono_arch_get_throw_corlib_exception_full (&code_size, &ji, FALSE);
+#else
+ code = mono_arch_get_throw_corlib_exception ();
+#endif
#else
g_assert_not_reached ();
#endif
mono_trampolines_init ();
- mono_exceptions_init ();
-
if (!g_thread_supported ())
g_thread_init (NULL);
#define JIT_INVOKE_WORKS
#ifdef JIT_INVOKE_WORKS
mono_install_runtime_invoke (mono_jit_runtime_invoke);
- mono_install_handler (mono_get_throw_exception ());
#endif
mono_install_stack_walk (mono_jit_walk_stack);
mono_install_get_cached_class_info (mono_aot_get_cached_class_info);
mono_install_vtable_trampoline (mini_get_vtable_trampoline ());
#endif
#endif
+
+ /* This must come after mono_init () in the aot-only case */
+ mono_exceptions_init ();
+ mono_install_handler (mono_get_throw_exception ());
+
mono_icall_init ();
mono_add_internal_call ("System.Diagnostics.StackFrame::get_frame_info",
void mono_print_ins_index (int i, MonoInst *ins) MONO_INTERNAL;
void mono_print_ins (MonoInst *ins) MONO_INTERNAL;
+/* AOT */
void mono_aot_init (void) MONO_INTERNAL;
gpointer mono_aot_get_method (MonoDomain *domain,
MonoMethod *method) MONO_INTERNAL;
gpointer mono_aot_plt_resolve (gpointer aot_module, guint32 plt_info_offset, guint8 *code) MONO_INTERNAL;
gpointer mono_aot_get_method_from_vt_slot (MonoDomain *domain, MonoVTable *vtable, int slot) MONO_INTERNAL;
gpointer mono_aot_create_specific_trampoline (MonoImage *image, gpointer arg1, MonoTrampolineType tramp_type, MonoDomain *domain, guint32 *code_len) MONO_INTERNAL;
+gpointer mono_aot_get_named_code (const char *name) MONO_INTERNAL;
gboolean mono_method_blittable (MonoMethod *method) MONO_INTERNAL;
gboolean mono_method_same_domain (MonoJitInfo *caller, MonoJitInfo *callee) MONO_INTERNAL;
guchar* mono_arch_create_trampoline_code_full (MonoTrampolineType tramp_type, guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
gpointer mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot) MONO_INTERNAL;
guint32 mono_arch_get_rgctx_lazy_fetch_offset (gpointer *regs) MONO_INTERNAL;
+gpointer mono_arch_get_nullified_class_init_trampoline (guint32 *code_len) MONO_INTERNAL;
GList *mono_arch_get_allocatable_int_vars (MonoCompile *cfg) MONO_INTERNAL;
GList *mono_arch_get_global_int_regs (MonoCompile *cfg) MONO_INTERNAL;
guint32 mono_arch_regalloc_cost (MonoCompile *cfg, MonoMethodVar *vmv) MONO_INTERNAL;
gpointer mono_arch_get_restore_context_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
gpointer mono_arch_get_throw_exception_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
gpointer mono_arch_get_rethrow_exception_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
+gpointer mono_arch_get_throw_exception_by_name_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
+gpointer mono_arch_get_throw_corlib_exception_full (guint32 *code_size, MonoJumpInfo **ji, gboolean aot) MONO_INTERNAL;
gboolean mono_arch_handle_exception (void *sigctx, gpointer obj, gboolean test_only) MONO_INTERNAL;
void mono_arch_handle_altstack_exception (void *sigctx, gpointer fault_addr, gboolean stack_ovf) MONO_INTERNAL;
gpointer mono_arch_ip_from_context (void *sigctx) MONO_INTERNAL;
void
mono_arch_nullify_plt_entry (guint8 *code)
{
+ if (mono_aot_only && !nullified_class_init_trampoline)
+ nullified_class_init_trampoline = mono_aot_get_named_code ("nullified_class_init_trampoline");
+
mono_arch_patch_plt_entry (code, nullified_class_init_trampoline);
}
if (AMD64_IS_ARGUMENT_REG (i) || i == AMD64_R10 || i == AMD64_R11)
amd64_mov_reg_membase (code, i, AMD64_RBP, saved_regs_offset + (i * 8), 8);
+ /*
+ * FIXME: When using aot-only, the called code might be a C vararg function
+ * which uses %rax as well.
+ * We could restore it, but we would have to use another register to store the
+ * target address, and we don't have any left.
+ * Also, the default AOT plt trampolines overwrite 'rax'.
+ */
+
for (i = 0; i < 8; ++i)
amd64_movsd_reg_membase (code, i, AMD64_RBP, saved_fpregs_offset + (i * 8));
tramp_type == MONO_TRAMPOLINE_GENERIC_CLASS_INIT ||
tramp_type == MONO_TRAMPOLINE_RGCTX_LAZY_FETCH)
amd64_ret (code);
- else
+ else {
/* call the compiled method */
- amd64_jump_reg (code, X86_EAX);
+ amd64_jump_reg (code, AMD64_RAX);
+ }
g_assert ((code - buf) <= 524);
mono_arch_flush_icache (buf, code - buf);
+ *code_size = code - buf;
+
if (tramp_type == MONO_TRAMPOLINE_CLASS_INIT) {
+ guint32 code_len;
+
/* Initialize the nullified class init trampoline used in the AOT case */
- nullified_class_init_trampoline = code = mono_global_codeman_reserve (16);
- x86_ret (code);
+ nullified_class_init_trampoline = mono_arch_get_nullified_class_init_trampoline (&code_len);
}
- *code_size = code - buf;
+ return buf;
+}
+
+gpointer
+mono_arch_get_nullified_class_init_trampoline (guint32 *code_len)
+{
+ guint8 *code, *buf;
+
+ code = buf = mono_global_codeman_reserve (16);
+ amd64_ret (code);
+
+ mono_arch_flush_icache (buf, code - buf);
+
+ *code_len = code - buf;
return buf;
}