From 04a4c3f2ce12907e13c67307c5b2247445026400 Mon Sep 17 00:00:00 2001 From: Bernhard Urban Date: Mon, 23 Sep 2019 22:08:25 +0200 Subject: [PATCH] [coop runtime] add a GC transition and relax some GC related assertions (#7036) * [coop] add missing gc_unsafe transition frame #3: 0x02a39fd4 monotouchtest`log_callback(log_domain=0x00000000, log_level="error", message="../../../../../mono/metadata/object.c:1905: Expected GC Unsafe mode but was in STATE_BLOCKING state", fatal=4, user_data=0x00000000) at runtime.m:1251:3 frame #4: 0x02a03f78 monotouchtest`monoeg_g_logv_nofree(log_domain=0x00000000, log_level=G_LOG_LEVEL_ERROR, format=, args=) at goutput.c:149:2 [opt] frame #5: 0x02a03f14 monotouchtest`monoeg_g_logv(log_domain=, log_level=, format=, args=) at goutput.c:156:10 [opt] frame #6: 0x02a03fa8 monotouchtest`monoeg_g_log(log_domain=, log_level=, format=) at goutput.c:165:2 [opt] frame #7: 0x029e54f8 monotouchtest`assert_gc_unsafe_mode(file="../../../../../mono/metadata/object.c", lineno=1905) at checked-build.c:396:3 [opt] frame #8: 0x0294ef98 monotouchtest`mono_class_vtable_checked(domain=0x16d87b70, klass=0x17bfab98, error=0x19498a08) at object.c:1905:2 [opt] frame #9: 0x0298f0dc monotouchtest`get_current_thread_ptr_for_domain(domain=0x16d87b70, thread=0x03f645d0) at threads.c:635:2 [opt] frame #10: 0x0298d9dc monotouchtest`mono_thread_current at threads.c:2026:23 [opt] frame #11: 0x02992a80 monotouchtest`mono_runtime_set_pending_exception(exc=0x0357e4a0, overwrite=0) at threads.c:5176:23 [opt] frame #12: 0x02a3c650 monotouchtest`::xamarin_process_nsexception_using_mode(ns_exception=name: "System.ApplicationException" - reason: "3,14", throwManagedAsDefault=false) at runtime.m:2369:4 frame #13: 0x02a3c478 monotouchtest`::xamarin_process_nsexception(ns_exception=name: "System.ApplicationException" - reason: "3,14") at runtime.m:2336:2 frame #14: 0x0270b488 monotouchtest`::xamarin_pinvoke_wrapper_objc_msgSendSuper18(__p__0=0x0357d0f0, __p__1=0x02ad1ef2) at pinvokes.m:5732:4 frame #15: 0x02a64764 monotouchtest`do_icall(frame=, sig=0x17d70bf0, op=, sp=0x19498fa0, ptr=, save_last_error=0) at interp.c:1947:3 [opt] frame #16: 0x02a632b8 monotouchtest`do_icall_wrapper(frame=0x194991b0, sig=0x17d70bf0, op=547, sp=0x19498fb0, ptr=0x0270b408, save_last_error=0) at interp.c:2037:7 [opt] Messaging::void_objc_msgSendSuper @ 396160394 "calli.nat.fast" || frame #17: 0x02a51d5c monotouchtest`interp_exec_method_full(frame=0x194991b0, context=, clause_args=, error=) at interp.c:3229:9 [opt] ObjCExceptionTest::InvokeManagedExceptionThrower @ 396160296 "vcall" || frame #18: 0x02a524e8 monotouchtest`interp_exec_method_full(frame=0x19499370, context=, clause_args=, error=) at interp.c:3400:4 [opt] ExceptionsTest::ManagedExceptionPassthrough @ 396150902 "vcallvirt.fast" || frame #19: 0x02a521cc monotouchtest`interp_exec_method_full(frame=0x194994d0, context=, clause_args=, error=) at interp.c:3325:4 [opt] Object::runtime_invoke_direct_void__this__ @ 401347822 "vcall" || frame #20: 0x02a524e8 monotouchtest`interp_exec_method_full(frame=0x19499588, context=, clause_args=, error=) at interp.c:3400:4 [opt] frame #21: 0x02a506f8 monotouchtest`interp_runtime_invoke(method=, obj=0x0357c4f0, params=0x00000000, exc=0x1949965c, error=0x194998b8) at interp.c:1766:2 [opt] frame #22: 0x028a739c monotouchtest`mono_jit_runtime_invoke(method=0x17534858, obj=, params=0x00000000, exc=, error=0x194998b8) at mini-runtime.c:3170:12 [opt] frame #23: 0x02951cfc monotouchtest`do_runtime_invoke(method=0x17534858, obj=0x0357c4f0, params=0x00000000, exc=0x00000000, error=0x194998b8) at object.c:3017:11 [opt] frame #24: 0x0294e6d4 monotouchtest`mono_runtime_invoke_checked(method=, obj=, params=, error=) at class-getters.h:24:1 [opt] [artificial] frame #25: 0x02955408 monotouchtest`mono_runtime_try_invoke_array(method=0x17534858, obj=0x0357c4f0, params=0x00000000, exc=0x00000000, error=0x194998b8) at object.c:5564:10 [opt] frame #26: 0x02905fac monotouchtest`ves_icall_InternalInvoke(method=, this_arg=, params=0x00000000, exc=0x19499f0c) at icall.c:3753:8 [opt] frame #27: 0x02a64788 monotouchtest`do_icall(frame=, sig=0x17496978, op=, sp=0x19499d88, ptr=, save_last_error=0) at interp.c:1982:20 [opt] frame #28: 0x02a632b8 monotouchtest`do_icall_wrapper(frame=0x19499fb0, sig=0x17496978, op=552, sp=0x19499da0, ptr=0x02905bec, save_last_error=0) at interp.c:2037:7 [opt] RuntimeMethodInfo::InternalInvoke @ 400702536 "calli.nat.fast" || frame #29: 0x02a51d5c monotouchtest`interp_exec_method_full(frame=0x19499fb0, context=, clause_args=, error=) at interp.c:3229:9 [opt] RuntimeMethodInfo::Invoke @ 400701852 "call" || frame #30: 0x02a524e8 monotouchtest`interp_exec_method_full(frame=0x1949a110, context=, clause_args=, error=) at interp.c:3400:4 [opt] MethodBase::Invoke @ 400700872 "callvirt.fast" || frame #31: 0x02a521cc monotouchtest`interp_exec_method_full(frame=0x1949a280, context=, clause_args=, error=) at interp.c:3325:4 [opt] * [coop] relax a couple GC state assertions * [coop] update doc for enabling GC assertions * [coop] relax a GC assertion in release trampoline --- runtime/COOP.md | 38 +++++++++++++++++++++++++++++++++ runtime/runtime.m | 4 +++- runtime/trampolines.m | 4 ++-- tools/common/StaticRegistrar.cs | 2 +- 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/runtime/COOP.md b/runtime/COOP.md index a2501c4f00b1..086ef1fd67a6 100644 --- a/runtime/COOP.md +++ b/runtime/COOP.md @@ -120,3 +120,41 @@ Debugging tips * Display the current thread state: display (void *) mono_thread_info_current ()->thread_state + +Enable GC Assertions +==================== + +Apply this patch to the iOS SDK (here only done for the `arm64_32` runtime): +```patch +diff --git a/sdks/builds/ios.mk b/sdks/builds/ios.mk +index 571dbd797a8..5bbe30040d2 100644 +--- a/sdks/builds/ios.mk ++++ b/sdks/builds/ios.mk +@@ -155,7 +155,7 @@ watchos64_32_sysroot = -isysroot $(watchos64_32_sysroot_path) + # explicitly disable dtrace, since it requires inline assembly, which is disabled on AppleTV (and mono's configure.ac doesn't know that (yet at least)) + ios-targettv_CONFIGURE_FLAGS = --enable-dtrace=no --enable-llvm-runtime --with-bitcode=yes + ios-targetwatch_CONFIGURE_FLAGS = --enable-cooperative-suspend --enable-llvm-runtime --with-bitcode=yes +-ios-targetwatch64_32_CONFIGURE_FLAGS = --enable-cooperative-suspend --enable-llvm-runtime --with-bitcode=yes ++ios-targetwatch64_32_CONFIGURE_FLAGS = --enable-cooperative-suspend --enable-llvm-runtime --with-bitcode=yes --enable-checked-build=gc + + ios-target32_SYSROOT = $(ios_sysroot) -miphoneos-version-min=$(IOS_VERSION_MIN) + ios-target32s_SYSROOT = $(ios_sysroot) -miphoneos-version-min=$(IOS_VERSION_MIN) +``` + +and make sure you build `xamarin-macios` with `MONO_BUILD_FROM_SOURCE=1`. Also modify `mtouch` such that it enables checked-build: + +```patch +diff --git a/tools/mtouch/mtouch.cs b/tools/mtouch/mtouch.cs +index 1ef159b79..cb2caf426 100644 +--- a/tools/mtouch/mtouch.cs ++++ b/tools/mtouch/mtouch.cs +@@ -649,6 +654,8 @@ namespace Xamarin.Bundler + sw.WriteLine ("\tsetenv (\"MONO_GC_PARAMS\", \"{0}\", 1);", app.MonoGCParams); + foreach (var kvp in app.EnvironmentVariables) + sw.WriteLine ("\tsetenv (\"{0}\", \"{1}\", 1);", kvp.Key.Replace ("\"", "\\\""), kvp.Value.Replace ("\"", "\\\"")); ++ sw.WriteLine ("\tsetenv (\"MONO_CHECK_MODE\", \"gc\", 1);"); ++ + sw.WriteLine ("\txamarin_supports_dynamic_registration = {0};", app.DynamicRegistrationSupported ? "TRUE" : "FALSE"); + sw.WriteLine ("}"); + sw.WriteLine (); +``` diff --git a/runtime/runtime.m b/runtime/runtime.m index 19e9e74bfcaf..79cdc638aadf 100644 --- a/runtime/runtime.m +++ b/runtime/runtime.m @@ -512,7 +512,7 @@ -(void) xamarinSetGCHandle: (int) gc_handle; get_raw_gchandle_safe (id self) { // COOP: we call a selector, and that must only be done in SAFE mode. - MONO_ASSERT_GC_SAFE; + MONO_ASSERT_GC_SAFE_OR_DETACHED; id xself = self; return (int) [xself xamarinGetGCHandle]; } @@ -2361,8 +2361,10 @@ -(void) xamarinSetGCHandle: (int) gc_handle; exc_handle = [[ns_exception userInfo] objectForKey: @"XamarinManagedExceptionHandle"]; if (exc_handle != NULL) { int handle = [exc_handle getHandle]; + MONO_ENTER_GC_UNSAFE; MonoObject *exc = mono_gchandle_get_target (handle); mono_runtime_set_pending_exception ((MonoException *) exc, false); + MONO_EXIT_GC_UNSAFE; } else { int handle = xamarin_create_ns_exception (ns_exception, &exception_gchandle); if (exception_gchandle != 0) { diff --git a/runtime/trampolines.m b/runtime/trampolines.m index bdab794b5c5c..cc3ffc879570 100644 --- a/runtime/trampolines.m +++ b/runtime/trampolines.m @@ -613,7 +613,7 @@ xamarin_release_trampoline (id self, SEL sel) { // COOP: does not access managed memory: any mode, but it assumes safe mode upon entry (it takes locks, and doesn't switch to safe mode). - MONO_ASSERT_GC_SAFE; + MONO_ASSERT_GC_SAFE_OR_DETACHED; int ref_count; bool detach = false; @@ -676,7 +676,7 @@ xamarin_retain_trampoline (id self, SEL sel) { // COOP: safe mode upon entry, switches to unsafe when acccessing managed memory. - MONO_ASSERT_GC_SAFE; + MONO_ASSERT_GC_SAFE_OR_DETACHED; pthread_mutex_lock (&refcount_mutex); diff --git a/tools/common/StaticRegistrar.cs b/tools/common/StaticRegistrar.cs index c8aa9666e518..9591b211396a 100644 --- a/tools/common/StaticRegistrar.cs +++ b/tools/common/StaticRegistrar.cs @@ -3862,7 +3862,7 @@ void Specialize (AutoIndentStringBuilder sb, ObjCMethod method, List if (App.Embeddinator) body.WriteLine ("xamarin_embeddinator_initialize ();"); - body.WriteLine ("MONO_ASSERT_GC_SAFE;"); + body.WriteLine ("MONO_ASSERT_GC_SAFE_OR_DETACHED;"); body.WriteLine ("MONO_THREAD_ATTACH;"); // COOP: this will switch to GC_UNSAFE body.WriteLine ();