Skip to content

Commit

Permalink
[marshal] Emit GC Safe transitions around foreign icalls.
Browse files Browse the repository at this point in the history
A foreign icall is added using mono_add_internal_call and that is not coop GC
aware.  (The runtime uses mono_add_internal_call_with_flags or
mono_add_internal_call_internal)

Under hybrid suspend, foreign icalls will run in GC Safe mode and transition to
GC Unsafe only when the call back into the runtime or invoke managed code.

Fixes mono#11138
  • Loading branch information
lambdageek committed Oct 19, 2018
1 parent 78b7d90 commit 0029c91
Showing 1 changed file with 20 additions and 0 deletions.
20 changes: 20 additions & 0 deletions mono/metadata/marshal-ilgen.c
Original file line number Diff line number Diff line change
Expand Up @@ -6305,12 +6305,19 @@ emit_native_icall_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethod *method, Mono
gboolean save_handles_to_locals = FALSE;
IcallHandlesLocal *handles_locals = NULL;
MonoMethodSignature *sig = mono_method_signature (method);
gboolean need_gc_safe = FALSE;
GCSafeTransitionBuilder gc_safe_transition_builder;

(void) mono_lookup_internal_call_full (method, &uses_handles, &foreign_icall);

/* If it uses handles and MonoError, it had better check exceptions */
g_assert (!uses_handles || check_exceptions);

if (G_UNLIKELY (foreign_icall)) {
/* FIXME: we only want the transitions for hybrid suspend. Q: What to do about AOT? */
need_gc_safe = gc_safe_transition_builder_init (&gc_safe_transition_builder, mb, FALSE);
}

if (uses_handles) {
MonoMethodSignature *ret;
MonoMethodSignature *generic_sig = NULL;
Expand Down Expand Up @@ -6356,6 +6363,10 @@ emit_native_icall_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethod *method, Mono
call_sig = ret;
}

if (G_UNLIKELY (need_gc_safe)) {
gc_safe_transition_builder_add_locals (&gc_safe_transition_builder);
}

if (uses_handles) {
handle_stack_mark_class = mono_class_load_from_name (mono_get_corlib (), "Mono", "RuntimeStructs/HandleStackMark");
error_class = mono_class_load_from_name (mono_get_corlib (), "Mono", "RuntimeStructs/MonoError");
Expand Down Expand Up @@ -6462,6 +6473,9 @@ emit_native_icall_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethod *method, Mono
mono_mb_emit_ldarg (mb, i + sig->hasthis);
}

if (G_UNLIKELY (need_gc_safe))
gc_safe_transition_builder_emit_enter (&gc_safe_transition_builder, &piinfo->method, aot);

if (aot) {
mono_mb_emit_byte (mb, MONO_CUSTOM_PREFIX);
mono_mb_emit_op (mb, CEE_MONO_ICALL_ADDR, &piinfo->method);
Expand All @@ -6471,6 +6485,9 @@ emit_native_icall_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethod *method, Mono
mono_mb_emit_native_call (mb, call_sig, piinfo->addr);
}

if (G_UNLIKELY (need_gc_safe))
gc_safe_transition_builder_emit_exit (&gc_safe_transition_builder);

if (uses_handles) {
if (MONO_TYPE_IS_REFERENCE (sig->ret)) {
// if (ret != NULL_HANDLE) {
Expand Down Expand Up @@ -6517,6 +6534,9 @@ emit_native_icall_wrapper_ilgen (MonoMethodBuilder *mb, MonoMethod *method, Mono
mono_mb_emit_icall (mb, mono_icall_end);
}

if (G_UNLIKELY (need_gc_safe))
gc_safe_transition_builder_cleanup (&gc_safe_transition_builder);

if (check_exceptions)
emit_thread_interrupt_checkpoint (mb);
mono_mb_emit_byte (mb, CEE_RET);
Expand Down

0 comments on commit 0029c91

Please sign in to comment.