Skip to content

Commit

Permalink
[interp] Improve mixed mode execution support, using full-aot+interp …
Browse files Browse the repository at this point in the history
…as the configuration. (#7764)

* [interp] Handle mono_handle_exception () returning a ctx which refers to JITted code by restoring the context.

* [aot] Clear the pinvoke flag from the interp_in wrapper signatures, so they get an lmf in mini_get_interp_in_wrapper (), this is needed for mixed-mode exception handling.

* [aot] Change the semantics of the 'interp' option, use it only to emit additional interp wrappers etc. instead of disabling code generation as well.

* [aot] Emit more interp-in/interp-out wrappers when using --aot=full,interp.

* Add a --interp=interp-only= command line option, used for testing.
In full-aot+interp mode, prefer full-aot code instead of interp code, except for methods in the classes listed
in the interp-only option.
Use normal runtime invokes in full-aot+interp mode.

* [interp] Prefer AOTed code when making calls out of interpreted code in full-aot mode.

* [aot] When running with --aot=interp, preserve the previous behavior of only emitting interp wrappers and trampolines.
  • Loading branch information
vargaz committed Mar 23, 2018
1 parent 9c63d1b commit 67e995c
Show file tree
Hide file tree
Showing 7 changed files with 70 additions and 48 deletions.
85 changes: 41 additions & 44 deletions mono/mini/aot-compiler.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ typedef struct MonoAotOptions {
gboolean metadata_only;
gboolean bind_to_runtime_version;
MonoAotMode mode;
gboolean interp;
gboolean no_dlsym;
gboolean static_link;
gboolean asm_only;
Expand Down Expand Up @@ -418,7 +419,7 @@ static char*
get_plt_entry_debug_sym (MonoAotCompile *acfg, MonoJumpInfo *ji, GHashTable *cache);

static void
add_gsharedvt_wrappers (MonoAotCompile *acfg, MonoMethodSignature *sig, gboolean gsharedvt_in, gboolean gsharedvt_out);
add_gsharedvt_wrappers (MonoAotCompile *acfg, MonoMethodSignature *sig, gboolean gsharedvt_in, gboolean gsharedvt_out, gboolean interp_in);

static void
add_profile_instances (MonoAotCompile *acfg, ProfileData *data);
Expand Down Expand Up @@ -4366,7 +4367,7 @@ add_wrappers (MonoAotCompile *acfg)
if (method->iflags & METHOD_IMPL_ATTRIBUTE_INTERNAL_CALL) {
if (acfg->aot_opts.llvm_only) {
/* The wrappers have a different signature (hasthis is not set) so need to add this too */
add_gsharedvt_wrappers (acfg, mono_method_signature (method), FALSE, TRUE);
add_gsharedvt_wrappers (acfg, mono_method_signature (method), FALSE, TRUE, FALSE);
}
}
}
Expand Down Expand Up @@ -4569,13 +4570,13 @@ method_has_type_vars (MonoMethod *method)
static
gboolean mono_aot_mode_is_full (MonoAotOptions *opts)
{
return opts->mode == MONO_AOT_MODE_FULL || opts->mode == MONO_AOT_MODE_INTERP;
return opts->mode == MONO_AOT_MODE_FULL;
}

static
gboolean mono_aot_mode_is_interp (MonoAotOptions *opts)
{
return opts->mode == MONO_AOT_MODE_INTERP;
return opts->interp;
}

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

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

g_assert (acfg->image->assembly);
Expand Down Expand Up @@ -7361,7 +7362,7 @@ mono_aot_parse_options (const char *aot_options, MonoAotOptions *opts)
} else if (str_begins_with (arg, "hybrid")) {
opts->mode = MONO_AOT_MODE_HYBRID;
} else if (str_begins_with (arg, "interp")) {
opts->mode = MONO_AOT_MODE_INTERP;
opts->interp = TRUE;
} else if (str_begins_with (arg, "threads=")) {
opts->nthreads = atoi (arg + strlen ("threads="));
} else if (str_begins_with (arg, "static")) {
Expand Down Expand Up @@ -7679,7 +7680,7 @@ is_concrete_type (MonoType *t)

/* LOCKING: Assumes the loader lock is held */
static void
add_gsharedvt_wrappers (MonoAotCompile *acfg, MonoMethodSignature *sig, gboolean gsharedvt_in, gboolean gsharedvt_out)
add_gsharedvt_wrappers (MonoAotCompile *acfg, MonoMethodSignature *sig, gboolean gsharedvt_in, gboolean gsharedvt_out, gboolean interp_in)
{
MonoMethod *wrapper;
gboolean concrete = TRUE;
Expand All @@ -7702,19 +7703,8 @@ add_gsharedvt_wrappers (MonoAotCompile *acfg, MonoMethodSignature *sig, gboolean
if (add_out)
g_hash_table_insert (acfg->gsharedvt_out_signatures, sig, sig);

if (!sig->has_type_parameters) {
//printf ("%s\n", mono_signature_full_name (sig));

if (gsharedvt_in) {
wrapper = mini_get_gsharedvt_in_sig_wrapper (sig);
add_extra_method (acfg, wrapper);
}
if (gsharedvt_out) {
wrapper = mini_get_gsharedvt_out_sig_wrapper (sig);
add_extra_method (acfg, wrapper);
}
} else {
/* For signatures creared during generic sharing, convert them to a concrete signature if possible */
if (sig->has_type_parameters) {
/* For signatures created during generic sharing, convert them to a concrete signature if possible */
MonoMethodSignature *copy = mono_metadata_signature_dup (sig);
int i;

Expand All @@ -7728,21 +7718,26 @@ add_gsharedvt_wrappers (MonoAotCompile *acfg, MonoMethodSignature *sig, gboolean
if (!is_concrete_type (copy->params [i]))
concrete = FALSE;
}
if (concrete) {
copy->has_type_parameters = 0;

if (gsharedvt_in) {
wrapper = mini_get_gsharedvt_in_sig_wrapper (copy);
add_extra_method (acfg, wrapper);
}
copy->has_type_parameters = 0;
if (!concrete)
return;
sig = copy;
}

if (gsharedvt_out) {
wrapper = mini_get_gsharedvt_out_sig_wrapper (copy);
add_extra_method (acfg, wrapper);
}
//printf ("%s\n", mono_signature_full_name (sig));

//printf ("%s\n", mono_method_full_name (wrapper, 1));
}
if (gsharedvt_in) {
wrapper = mini_get_gsharedvt_in_sig_wrapper (sig);
add_extra_method (acfg, wrapper);
}
if (gsharedvt_out) {
wrapper = mini_get_gsharedvt_out_sig_wrapper (sig);
add_extra_method (acfg, wrapper);
}
if (interp_in) {
wrapper = mini_get_interp_in_wrapper (sig);
add_extra_method (acfg, wrapper);
//printf ("X: %s\n", mono_method_full_name (wrapper, 1));
}
}

Expand Down Expand Up @@ -8026,14 +8021,18 @@ compile_method (MonoAotCompile *acfg, MonoMethod *method)

if (!cfg->method->wrapper_type || cfg->method->wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE)
/* These only need out wrappers */
add_gsharedvt_wrappers (acfg, mono_method_signature (cfg->method), FALSE, TRUE);
add_gsharedvt_wrappers (acfg, mono_method_signature (cfg->method), FALSE, TRUE, FALSE);

for (l = cfg->signatures; l; l = l->next) {
MonoMethodSignature *sig = mono_metadata_signature_dup ((MonoMethodSignature*)l->data);

/* These only need in wrappers */
add_gsharedvt_wrappers (acfg, sig, TRUE, FALSE);
add_gsharedvt_wrappers (acfg, sig, TRUE, FALSE, FALSE);
}
} else if (mono_aot_mode_is_full (&acfg->aot_opts) && mono_aot_mode_is_interp (&acfg->aot_opts)) {
/* The interpreter uses these wrappers to call aot-ed code */
if (!cfg->method->wrapper_type || cfg->method->wrapper_type == MONO_WRAPPER_DELEGATE_INVOKE)
add_gsharedvt_wrappers (acfg, mono_method_signature (cfg->method), FALSE, TRUE, TRUE);
}

/*
Expand Down Expand Up @@ -12411,6 +12410,7 @@ static const char* interp_in_static_sigs[] = {
"void ptr",
"void int32 ptr&",
"void uint32 ptr&",
"void"
};

int
Expand Down Expand Up @@ -12576,12 +12576,9 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options,
}
}

if (!mono_aot_mode_is_interp (&acfg->aot_opts)) {
int method_index;

for (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));
}
if (!(acfg->aot_opts.interp && !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));
}

acfg->num_trampolines [MONO_AOT_TRAMP_SPECIFIC] = mono_aot_mode_is_full (&acfg->aot_opts) ? acfg->aot_opts.ntrampolines : 0;
Expand All @@ -12599,7 +12596,6 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options,
arch_init (acfg);

if (mono_use_llvm || acfg->aot_opts.llvm) {

/*
* Emit all LLVM code into a separate assembly/object file and link with it
* normally.
Expand Down Expand Up @@ -12639,9 +12635,8 @@ 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 (!mono_aot_mode_is_interp (&acfg->aot_opts)) {
if (!(acfg->aot_opts.interp && !mono_aot_mode_is_full (&acfg->aot_opts))) {
res = collect_methods (acfg);

if (!res)
return 1;
}
Expand Down Expand Up @@ -12678,6 +12673,8 @@ mono_compile_assembly (MonoAssembly *ass, guint32 opts, const char *aot_options,
if (mono_aot_mode_is_interp (&acfg->aot_opts)) {
for (int i = 0; i < sizeof (interp_in_static_sigs) / sizeof (const char *); i++) {
MonoMethodSignature *sig = mono_create_icall_signature (interp_in_static_sigs [i]);
sig = mono_metadata_signature_dup_full (mono_get_corlib (), sig);
sig->pinvoke = FALSE;
MonoMethod *wrapper = mini_get_interp_in_wrapper (sig);
add_method (acfg, wrapper);
}
Expand Down
8 changes: 8 additions & 0 deletions mono/mini/interp/interp.c
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,11 @@ interp_throw (ThreadContext *context, MonoException *ex, InterpFrame *frame, gco
* pushed above, which points to our frames.
*/
mono_handle_exception (&ctx, (MonoObject*)ex);
if (MONO_CONTEXT_GET_IP (&ctx) != 0) {
/* We need to unwind into non-interpreter code */
mono_restore_context (&ctx);
g_assert_not_reached ();
}

interp_pop_lmf (&ext);

Expand Down Expand Up @@ -1628,6 +1633,7 @@ interp_entry (InterpEntryData *data)
}
}

memset (&result, 0, sizeof (result));
init_frame (&frame, NULL, data->rmethod, args, &result);

type = rmethod->rtype;
Expand Down Expand Up @@ -5188,6 +5194,8 @@ interp_parse_options (const char *options)

if (strncmp (arg, "jit=", 4) == 0)
mono_interp_jit_classes = g_slist_prepend (mono_interp_jit_classes, arg + 4);
if (strncmp (arg, "interp-only=", 4) == 0)
mono_interp_only_classes = g_slist_prepend (mono_interp_only_classes, arg + strlen ("interp-only="));
}
}

Expand Down
4 changes: 4 additions & 0 deletions mono/mini/interp/transform.c
Original file line number Diff line number Diff line change
Expand Up @@ -774,6 +774,10 @@ jit_call_supported (MonoMethod *method, MonoMethodSignature *sig)
if (method->string_ctor)
return FALSE;

if (mono_aot_only && method->klass->image->aot_module)
/* The AOTed version of the called method is assumed to be available in full-aot mode */
return TRUE;

for (l = mono_interp_jit_classes; l; l = l->next) {
char *class_name = l->data;
// FIXME: Namespaces
Expand Down
4 changes: 3 additions & 1 deletion mono/mini/mini-exceptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -2215,7 +2215,9 @@ mono_handle_exception_internal (MonoContext *ctx, MonoObject *obj, gboolean resu
*/
mini_get_interp_callbacks ()->set_resume_state (jit_tls, mono_ex, ei, frame.interp_frame, ei->handler_start);
/* Undo the IP adjustment done by mono_arch_unwind_frame () */
mono_arch_undo_ip_adjustment (ctx);
/* ip == 0 means an interpreter frame */
if (MONO_CONTEXT_GET_IP (ctx) != 0)
mono_arch_undo_ip_adjustment (ctx);
} else {
MONO_CONTEXT_SET_IP (ctx, ei->handler_start);
}
Expand Down
14 changes: 12 additions & 2 deletions mono/mini/mini-runtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@ GList* mono_aot_paths;
static GPtrArray *profile_options;

static GSList *tramp_infos;
GSList *mono_interp_only_classes;

static void register_icalls (void);

Expand Down Expand Up @@ -2065,10 +2066,19 @@ mono_jit_compile_method_with_opt (MonoMethod *method, guint32 opt, gboolean jit_
MonoJitInfo *ji;
MonoJitICallInfo *callinfo = NULL;
WrapperInfo *winfo = NULL;
gboolean use_interp = FALSE;

error_init (error);

if (mono_use_interpreter && !jit_only) {
if (mono_use_interpreter && !mono_aot_only && !jit_only)
use_interp = TRUE;
if (!use_interp && mono_interp_only_classes) {
for (GSList *l = mono_interp_only_classes; l; l = l->next) {
if (!strcmp (method->klass->name, (char*)l->data))
use_interp = TRUE;
}
}
if (use_interp) {
code = mini_get_interp_callbacks ()->create_method_pointer (method, error);
if (code)
return code;
Expand Down Expand Up @@ -2706,7 +2716,7 @@ mono_jit_runtime_invoke (MonoMethod *method, void *obj, void **params, MonoObjec
MonoJitInfo *ji = NULL;
gboolean callee_gsharedvt = FALSE;

if (mono_use_interpreter)
if (mono_use_interpreter && !mono_aot_only)
return mini_get_interp_callbacks ()->runtime_invoke (method, obj, params, exc, error);

error_init (error);
Expand Down
1 change: 1 addition & 0 deletions mono/mini/mini-runtime.h
Original file line number Diff line number Diff line change
Expand Up @@ -333,6 +333,7 @@ extern GSList *mono_single_method_list;
extern GHashTable *mono_single_method_hash;
extern GList* mono_aot_paths;
extern MonoDebugOptions mini_debug_options;
extern GSList *mono_interp_only_classes;

static inline MonoMethod*
jinfo_get_method (MonoJitInfo *ji)
Expand Down
2 changes: 1 addition & 1 deletion mono/mini/mini-trampolines.c
Original file line number Diff line number Diff line change
Expand Up @@ -1609,7 +1609,7 @@ no_delegate_trampoline (void)
gpointer
mono_create_delegate_trampoline (MonoDomain *domain, MonoClass *klass)
{
if (mono_llvm_only || mono_use_interpreter)
if (mono_llvm_only || (mono_use_interpreter && !mono_aot_only))
return no_delegate_trampoline;

return mono_create_delegate_trampoline_info (domain, klass, NULL)->invoke_impl;
Expand Down

0 comments on commit 67e995c

Please sign in to comment.