Skip to content

Commit

Permalink
[mini] make interp work with AOT image generated with aot=interp (#9295)
Browse files Browse the repository at this point in the history
[mini] make interp work with AOT image generated with aot=interp

[aot-compiler] use mono_aot_mode_is_interp instead of directly using the flag

---------
[interp] add FULL_AOT flags to AOT image when `--aot=interp` is used

fixes regression from 67e995c

---------
partial forward port of #9266

needs backporting to `2018-06`
  • Loading branch information
lewurm authored and monojenkins committed Jul 9, 2018
1 parent dc56ae2 commit 6062fa3
Show file tree
Hide file tree
Showing 6 changed files with 100 additions and 41 deletions.
20 changes: 16 additions & 4 deletions mono/mini/aot-compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ typedef struct MonoAotCompile {

MonoAotOptions aot_opts;
guint32 nmethods;
guint32 nextra_methods;
guint32 opts;
guint32 simd_opts;
MonoMemPool *mempool;
Expand Down Expand Up @@ -3716,8 +3717,12 @@ add_method_with_index (MonoAotCompile *acfg, MonoMethod *method, int index, gboo
acfg->nmethods = acfg->methods->len + 1;
}

if (method->wrapper_type || extra)
if (method->wrapper_type || extra) {
int token = mono_metadata_token_index (method->token) - 1;
if (token >= 0)
acfg->nextra_methods++;
g_ptr_array_add (acfg->extra_methods, method);
}
}

static gboolean
Expand Down Expand Up @@ -6969,7 +6974,7 @@ emit_trampolines (MonoAotCompile *acfg)
int tramp_type;
#endif

if ((!mono_aot_mode_is_full (&acfg->aot_opts) || acfg->aot_opts.llvm_only) && !acfg->aot_opts.interp)
if ((!mono_aot_mode_is_full (&acfg->aot_opts) || acfg->aot_opts.llvm_only) && !mono_aot_mode_is_interp (&acfg->aot_opts))
return;

g_assert (acfg->image->assembly);
Expand Down Expand Up @@ -10328,6 +10333,7 @@ init_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info)
info->got_size = acfg->got_offset * sizeof (gpointer);
info->plt_size = acfg->plt_offset;
info->nmethods = acfg->nmethods;
info->nextra_methods = acfg->nextra_methods;
info->flags = acfg->flags;
info->opts = acfg->opts;
info->simd_opts = acfg->simd_opts;
Expand Down Expand Up @@ -10464,6 +10470,7 @@ emit_aot_file_info (MonoAotCompile *acfg, MonoAotFileInfo *info)
emit_int32 (acfg, info->got_size);
emit_int32 (acfg, info->plt_size);
emit_int32 (acfg, info->nmethods);
emit_int32 (acfg, info->nextra_methods);
emit_int32 (acfg, info->flags);
emit_int32 (acfg, info->opts);
emit_int32 (acfg, info->simd_opts);
Expand Down Expand Up @@ -12654,6 +12661,11 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options,
acfg->is_full_aot = TRUE;
}

if (mono_aot_mode_is_interp (&acfg->aot_opts)) {
acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_INTERP);
acfg->is_full_aot = TRUE;
}

if (mono_threads_are_safepoints_enabled ())
acfg->flags = (MonoAotFileFlags)(acfg->flags | MONO_AOT_FILE_FLAG_SAFEPOINTS);

Expand All @@ -12679,7 +12691,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options,
}
}

if (!(acfg->aot_opts.interp && !mono_aot_mode_is_full (&acfg->aot_opts))) {
if (!(mono_aot_mode_is_interp (&acfg->aot_opts) && !mono_aot_mode_is_full (&acfg->aot_opts))) {
for (int method_index = 0; method_index < acfg->image->tables [MONO_TABLE_METHOD].rows; ++method_index)
g_ptr_array_add (acfg->method_order,GUINT_TO_POINTER (method_index));
}
Expand Down Expand Up @@ -12738,7 +12750,7 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options,
if (mono_aot_mode_is_full (&acfg->aot_opts) || mono_aot_mode_is_hybrid (&acfg->aot_opts))
mono_set_partial_sharing_supported (TRUE);

if (!(acfg->aot_opts.interp && !mono_aot_mode_is_full (&acfg->aot_opts))) {
if (!(mono_aot_mode_is_interp (&acfg->aot_opts) && !mono_aot_mode_is_full (&acfg->aot_opts))) {
res = collect_methods (acfg);
if (!res)
return 1;
Expand Down
23 changes: 18 additions & 5 deletions mono/mini/aot-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -1821,7 +1821,7 @@ check_usable (MonoAssembly *assembly, MonoAotFileInfo *info, guint8 *blob, char
char *build_info;
char *msg = NULL;
gboolean usable = TRUE;
gboolean full_aot, safepoints;
gboolean full_aot, interp, safepoints;
guint32 excluded_cpu_optimizations;

if (strcmp (assembly->image->guid, info->assembly_guid)) {
Expand All @@ -1837,15 +1837,22 @@ check_usable (MonoAssembly *assembly, MonoAotFileInfo *info, guint8 *blob, char
g_free (build_info);

full_aot = info->flags & MONO_AOT_FILE_FLAG_FULL_AOT;
interp = info->flags & MONO_AOT_FILE_FLAG_INTERP;

if (mono_aot_only && !full_aot) {
msg = g_strdup_printf ("not compiled with --aot=full");
usable = FALSE;
if (!interp) {
msg = g_strdup_printf ("not compiled with --aot=full");
usable = FALSE;
}
}
if (!mono_aot_only && full_aot) {
msg = g_strdup_printf ("compiled with --aot=full");
usable = FALSE;
}
if (mono_use_interpreter && !interp) {
msg = g_strdup_printf ("not compiled with --aot=interp");
usable = FALSE;
}
if (mono_llvm_only && !(info->flags & MONO_AOT_FILE_FLAG_LLVM_ONLY)) {
msg = g_strdup_printf ("not compiled with --aot=llvmonly");
usable = FALSE;
Expand Down Expand Up @@ -2149,7 +2156,7 @@ if (container_assm_name && !container_amodule) {
}

if (!usable) {
if (mono_aot_only && !mono_use_interpreter) {
if (mono_aot_only) {
g_error ("Failed to load AOT module '%s' while running in aot-only mode: %s.\n", found_aot_name, msg);
} else {
mono_trace (G_LOG_LEVEL_INFO, MONO_TRACE_AOT, "AOT: module %s is unusable: %s.", found_aot_name, msg);
Expand Down Expand Up @@ -4048,7 +4055,8 @@ load_method (MonoDomain *domain, MonoAotModule *amodule, MonoImage *image, MonoM
}
return NULL;
}
code = (guint8 *)amodule->methods [method_index];
if (method_index < amodule->info.nmethods)
code = (guint8 *)amodule->methods [method_index];
}

info = &amodule->blob [mono_aot_get_offset (amodule->method_info_offsets, method_index)];
Expand Down Expand Up @@ -4815,6 +4823,11 @@ mono_aot_get_method (MonoDomain *domain, MonoMethod *method, MonoError *error)
} else {
/* Common case */
method_index = mono_metadata_token_index (method->token) - 1;

guint32 num_methods = amodule->info.nmethods - amodule->info.nextra_methods;
if (method_index >= num_methods)
/* method not available in AOT image */
return NULL;
}

code = (guint8 *)load_method (domain, amodule, m_class_get_image (klass), method, method->token, method_index, error);
Expand Down
5 changes: 4 additions & 1 deletion mono/mini/aot-runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
#include "mini.h"

/* Version number of the AOT file format */
#define MONO_AOT_FILE_VERSION 145
#define MONO_AOT_FILE_VERSION 146

#define MONO_AOT_TRAMP_PAGE_SIZE 16384

Expand Down Expand Up @@ -69,6 +69,7 @@ typedef enum {
MONO_AOT_FILE_FLAG_SAFEPOINTS = 32,
MONO_AOT_FILE_FLAG_SEPARATE_DATA = 64,
MONO_AOT_FILE_FLAG_EAGER_LOAD = 128,
MONO_AOT_FILE_FLAG_INTERP = 256,
} MonoAotFileFlags;

typedef enum {
Expand Down Expand Up @@ -168,6 +169,8 @@ typedef struct MonoAotFileInfo
guint32 plt_size;
/* Number of methods */
guint32 nmethods;
/* Number of extra methods */
guint32 nextra_methods;
/* A union of MonoAotFileFlags */
guint32 flags;
/* Optimization flags used to compile the module */
Expand Down
9 changes: 6 additions & 3 deletions mono/mini/interp/transform.c
Original file line number Diff line number Diff line change
Expand Up @@ -774,9 +774,12 @@ jit_call_supported (MonoMethod *method, MonoMethodSignature *sig)
if (method->string_ctor)
return FALSE;

if (mono_aot_only && m_class_get_image (method->klass)->aot_module)
/* The AOTed version of the called method is assumed to be available in full-aot mode */
return TRUE;
if (mono_aot_only && m_class_get_image (method->klass)->aot_module) {
ERROR_DECL (error);
gpointer addr = mono_jit_compile_method_jit_only (method, error);
if (addr && mono_error_ok (error))
return TRUE;
}

for (l = mono_interp_jit_classes; l; l = l->next) {
char *class_name = l->data;
Expand Down
5 changes: 3 additions & 2 deletions mono/mini/mini-llvm.c
Original file line number Diff line number Diff line change
Expand Up @@ -8802,7 +8802,7 @@ emit_aot_file_info (MonoLLVMModule *module)
info = &module->aot_info;

/* Create an LLVM type to represent MonoAotFileInfo */
nfields = 2 + MONO_AOT_FILE_INFO_NUM_SYMBOLS + 16 + 5;
nfields = 2 + MONO_AOT_FILE_INFO_NUM_SYMBOLS + 17 + 5;
eltypes = g_new (LLVMTypeRef, nfields);
tindex = 0;
eltypes [tindex ++] = LLVMInt32Type ();
Expand All @@ -8811,7 +8811,7 @@ emit_aot_file_info (MonoLLVMModule *module)
for (i = 0; i < MONO_AOT_FILE_INFO_NUM_SYMBOLS; ++i)
eltypes [tindex ++] = LLVMPointerType (LLVMInt8Type (), 0);
/* Scalars */
for (i = 0; i < 15; ++i)
for (i = 0; i < 16; ++i)
eltypes [tindex ++] = LLVMInt32Type ();
/* Arrays */
eltypes [tindex ++] = LLVMArrayType (LLVMInt32Type (), MONO_AOT_TABLE_NUM);
Expand Down Expand Up @@ -8933,6 +8933,7 @@ emit_aot_file_info (MonoLLVMModule *module)
fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->got_size, FALSE);
fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->plt_size, FALSE);
fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->nmethods, FALSE);
fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->nextra_methods, FALSE);
fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->flags, FALSE);
fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->opts, FALSE);
fields [tindex ++] = LLVMConstInt (LLVMInt32Type (), info->simd_opts, FALSE);
Expand Down
79 changes: 53 additions & 26 deletions mono/mini/mini-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -2144,7 +2144,7 @@ compile_special (MonoMethod *method, MonoDomain *target_domain, MonoError *error
mono_lookup_pinvoke_call (method, NULL, NULL);
}
nm = mono_marshal_get_native_wrapper (method, TRUE, mono_aot_only);
gpointer compiled_method = mono_compile_method_checked (nm, error);
gpointer compiled_method = mono_jit_compile_method_jit_only (nm, error);
return_val_if_nok (error, NULL);
code = mono_get_addr_from_ftnptr (compiled_method);
jinfo = mono_jit_info_table_find (target_domain, code);
Expand Down Expand Up @@ -2176,19 +2176,24 @@ compile_special (MonoMethod *method, MonoDomain *target_domain, MonoError *error
} else if (*name == 'I' && (strcmp (name, "Invoke") == 0)) {
if (mono_llvm_only) {
nm = mono_marshal_get_delegate_invoke (method, NULL);
gpointer compiled_ptr = mono_compile_method_checked (nm, error);
gpointer compiled_ptr = mono_jit_compile_method_jit_only (nm, error);
mono_error_assert_ok (error);
return mono_get_addr_from_ftnptr (compiled_ptr);
}

/* HACK: missing gsharedvt_out wrappers to do transition to del tramp in interp-only mode */
if (mono_use_interpreter)
return NULL;

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);
gpointer compiled_ptr = mono_compile_method_checked (nm, error);
gpointer compiled_ptr = mono_jit_compile_method_jit_only (nm, error);
mono_error_assert_ok (error);
return mono_get_addr_from_ftnptr (compiled_ptr);
} else if (*name == 'E' && (strcmp (name, "EndInvoke") == 0)) {
nm = mono_marshal_get_delegate_end_invoke (method);
gpointer compiled_ptr = mono_compile_method_checked (nm, error);
gpointer compiled_ptr = mono_jit_compile_method_jit_only (nm, error);
mono_error_assert_ok (error);
return mono_get_addr_from_ftnptr (compiled_ptr);
}
Expand Down Expand Up @@ -2372,7 +2377,7 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, gboolean jit_
if (!code)
code = compile_special (method, target_domain, error);

if (!code && mono_aot_only && mono_use_interpreter && method->wrapper_type != MONO_WRAPPER_UNKNOWN)
if (!jit_only && !code && mono_aot_only && mono_use_interpreter && method->wrapper_type != MONO_WRAPPER_UNKNOWN)
code = mini_get_interp_callbacks ()->create_method_pointer (method, error);

if (!code) {
Expand Down Expand Up @@ -2661,17 +2666,19 @@ typedef struct {
MonoClass *ret_box_class;
MonoMethodSignature *sig;
gboolean gsharedvt_invoke;
gboolean use_interp;
gpointer *wrapper_arg;
} RuntimeInvokeInfo;

static RuntimeInvokeInfo*
create_runtime_invoke_info (MonoDomain *domain, MonoMethod *method, gpointer compiled_method, gboolean callee_gsharedvt, MonoError *error)
create_runtime_invoke_info (MonoDomain *domain, MonoMethod *method, gpointer compiled_method, gboolean callee_gsharedvt, gboolean use_interp, MonoError *error)
{
MonoMethod *invoke;
RuntimeInvokeInfo *info;

info = g_new0 (RuntimeInvokeInfo, 1);
info->compiled_method = compiled_method;
info->use_interp = use_interp;
if (mono_llvm_only && method->string_ctor)
info->sig = mono_marshal_get_string_ctor_signature (method);
else
Expand Down Expand Up @@ -2953,27 +2960,33 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
}
}

gboolean use_interp = FALSE;

if (callee) {
compiled_method = mono_jit_compile_method (callee, error);
compiled_method = mono_jit_compile_method_jit_only (callee, error);
if (!compiled_method) {
g_assert (!mono_error_ok (error));
return NULL;
}

if (mono_llvm_only) {
ji = mini_jit_info_table_find (mono_domain_get (), (char *)mono_get_addr_from_ftnptr (compiled_method), NULL);
callee_gsharedvt = mini_jit_info_is_gsharedvt (ji);
if (callee_gsharedvt)
callee_gsharedvt = mini_is_gsharedvt_variable_signature (mono_method_signature (jinfo_get_method (ji)));
}
if (mono_use_interpreter)
use_interp = TRUE;
else
return NULL;
} else {
if (mono_llvm_only) {
ji = mini_jit_info_table_find (mono_domain_get (), (char *)mono_get_addr_from_ftnptr (compiled_method), NULL);
callee_gsharedvt = mini_jit_info_is_gsharedvt (ji);
if (callee_gsharedvt)
callee_gsharedvt = mini_is_gsharedvt_variable_signature (mono_method_signature (jinfo_get_method (ji)));
}

if (!callee_gsharedvt)
compiled_method = mini_add_method_trampoline (callee, compiled_method, mono_method_needs_static_rgctx_invoke (callee, TRUE), FALSE);
if (!callee_gsharedvt)
compiled_method = mini_add_method_trampoline (callee, compiled_method, mono_method_needs_static_rgctx_invoke (callee, TRUE), FALSE);
}
} else {
compiled_method = NULL;
}

info = create_runtime_invoke_info (domain, method, compiled_method, callee_gsharedvt, error);
info = create_runtime_invoke_info (domain, method, compiled_method, callee_gsharedvt, use_interp, error);
if (!mono_error_ok (error))
return NULL;

Expand Down Expand Up @@ -3009,21 +3022,30 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
*exc = NULL;

#ifdef MONO_ARCH_DYN_CALL_SUPPORTED
static RuntimeInvokeDynamicFunction dyn_runtime_invoke = NULL;
if (info->dyn_call_info) {
if (!dyn_runtime_invoke) {
mono_domain_lock (domain);

invoke = mono_marshal_get_runtime_invoke_dynamic ();
dyn_runtime_invoke = (RuntimeInvokeDynamicFunction)mono_jit_compile_method_jit_only (invoke, error);
if (!dyn_runtime_invoke && mono_use_interpreter) {
info->use_interp = TRUE;
info->dyn_call_info = NULL;
} else if (!mono_error_ok (error)) {
mono_domain_unlock (domain);
return NULL;
}
mono_domain_unlock (domain);
}
}
if (info->dyn_call_info) {
MonoMethodSignature *sig = mono_method_signature (method);
gpointer *args;
static RuntimeInvokeDynamicFunction dyn_runtime_invoke;
int i, pindex, buf_size;
guint8 *buf;
guint8 retval [256];

if (!dyn_runtime_invoke) {
invoke = mono_marshal_get_runtime_invoke_dynamic ();
dyn_runtime_invoke = (RuntimeInvokeDynamicFunction)mono_jit_compile_method (invoke, error);
if (!mono_error_ok (error))
return NULL;
}

/* Convert the arguments to the format expected by start_dyn_call () */
args = (void **)g_alloca ((sig->param_count + sig->hasthis) * sizeof (gpointer));
pindex = 0;
Expand Down Expand Up @@ -3064,6 +3086,11 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
}
#endif

if (info->use_interp) {
error_init (error);
return mini_get_interp_callbacks ()->runtime_invoke (method, obj, params, exc, error);
}

MonoObject *result;

if (mono_llvm_only) {
Expand Down

0 comments on commit 6062fa3

Please sign in to comment.