summaryrefslogtreecommitdiff
path: root/modules/mono/mono_gd/gd_mono.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/mono/mono_gd/gd_mono.cpp')
-rw-r--r--modules/mono/mono_gd/gd_mono.cpp96
1 files changed, 32 insertions, 64 deletions
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp
index 306a1997ab..39c3bd8934 100644
--- a/modules/mono/mono_gd/gd_mono.cpp
+++ b/modules/mono/mono_gd/gd_mono.cpp
@@ -129,14 +129,13 @@ void gd_mono_profiler_init() {
}
}
-#if defined(DEBUG_ENABLED)
-
void gd_mono_debug_init() {
-
- mono_debug_init(MONO_DEBUG_FORMAT_MONO);
-
CharString da_args = OS::get_singleton()->get_environment("GODOT_MONO_DEBUGGER_AGENT").utf8();
+ if (da_args.length()) {
+ OS::get_singleton()->set_environment("GODOT_MONO_DEBUGGER_AGENT", String());
+ }
+
#ifdef TOOLS_ENABLED
int da_port = GLOBAL_DEF("mono/debugger_agent/port", 23685);
bool da_suspend = GLOBAL_DEF("mono/debugger_agent/wait_for_debugger", false);
@@ -159,6 +158,10 @@ void gd_mono_debug_init() {
return; // Exported games don't use the project settings to setup the debugger agent
#endif
+ // Debugging enabled
+
+ mono_debug_init(MONO_DEBUG_FORMAT_MONO);
+
// --debugger-agent=help
const char *options[] = {
"--soft-breakpoints",
@@ -167,7 +170,6 @@ void gd_mono_debug_init() {
mono_jit_parse_options(2, (char **)options);
}
-#endif // defined(DEBUG_ENABLED)
#endif // !defined(JAVASCRIPT_ENABLED)
#if defined(JAVASCRIPT_ENABLED)
@@ -175,6 +177,7 @@ MonoDomain *gd_initialize_mono_runtime() {
const char *vfs_prefix = "managed";
int enable_debugging = 0;
+ // TODO: Provide a way to enable debugging on WASM release builds.
#ifdef DEBUG_ENABLED
enable_debugging = 1;
#endif
@@ -185,9 +188,7 @@ MonoDomain *gd_initialize_mono_runtime() {
}
#else
MonoDomain *gd_initialize_mono_runtime() {
-#ifdef DEBUG_ENABLED
gd_mono_debug_init();
-#endif
#if defined(IPHONE_ENABLED) || defined(ANDROID_ENABLED)
// I don't know whether this actually matters or not
@@ -249,7 +250,6 @@ void GDMono::add_mono_shared_libs_dir_to_path() {
}
void GDMono::determine_mono_dirs(String &r_assembly_rootdir, String &r_config_dir) {
-
String bundled_assembly_rootdir = GodotSharpDirs::get_data_mono_lib_dir();
String bundled_config_dir = GodotSharpDirs::get_data_mono_etc_dir();
@@ -312,7 +312,6 @@ void GDMono::determine_mono_dirs(String &r_assembly_rootdir, String &r_config_di
}
void GDMono::initialize() {
-
ERR_FAIL_NULL(Engine::get_singleton());
print_verbose("Mono: Initializing module...");
@@ -411,7 +410,6 @@ void GDMono::initialize() {
}
void GDMono::initialize_load_assemblies() {
-
#ifndef MONO_GLUE_ENABLED
CRASH_NOW_MSG("Mono: This binary was built with 'mono_glue=no'; cannot load assemblies.");
#endif
@@ -424,6 +422,9 @@ void GDMono::initialize_load_assemblies() {
#if defined(TOOLS_ENABLED)
bool tool_assemblies_loaded = _load_tools_assemblies();
CRASH_COND_MSG(!tool_assemblies_loaded, "Mono: Failed to load '" TOOLS_ASM_NAME "' assemblies.");
+
+ if (Main::is_project_manager())
+ return;
#endif
// Load the project's main assembly. This doesn't necessarily need to succeed.
@@ -469,6 +470,7 @@ uint64_t get_editor_api_hash() {
uint32_t get_bindings_version() {
GD_UNREACHABLE();
}
+
uint32_t get_cs_glue_version() {
GD_UNREACHABLE();
}
@@ -511,14 +513,12 @@ void GDMono::_init_exception_policy() {
}
void GDMono::add_assembly(uint32_t p_domain_id, GDMonoAssembly *p_assembly) {
-
assemblies[p_domain_id][p_assembly->get_name()] = p_assembly;
}
GDMonoAssembly *GDMono::get_loaded_assembly(const String &p_name) {
-
- if (p_name == "mscorlib")
- return get_corlib_assembly();
+ if (p_name == "mscorlib" && corlib_assembly)
+ return corlib_assembly;
MonoDomain *domain = mono_domain_get();
uint32_t domain_id = domain ? mono_domain_get_id(domain) : 0;
@@ -527,8 +527,9 @@ GDMonoAssembly *GDMono::get_loaded_assembly(const String &p_name) {
}
bool GDMono::load_assembly(const String &p_name, GDMonoAssembly **r_assembly, bool p_refonly) {
-
+#ifdef DEBUG_ENABLED
CRASH_COND(!r_assembly);
+#endif
MonoAssemblyName *aname = mono_assembly_name_new(p_name.utf8());
bool result = load_assembly(p_name, aname, r_assembly, p_refonly);
@@ -539,27 +540,26 @@ bool GDMono::load_assembly(const String &p_name, GDMonoAssembly **r_assembly, bo
}
bool GDMono::load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly) {
+#ifdef DEBUG_ENABLED
+ CRASH_COND(!r_assembly);
+#endif
+
+ return load_assembly(p_name, p_aname, r_assembly, p_refonly, GDMonoAssembly::get_default_search_dirs());
+}
+bool GDMono::load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly, const Vector<String> &p_search_dirs) {
+#ifdef DEBUG_ENABLED
CRASH_COND(!r_assembly);
+#endif
print_verbose("Mono: Loading assembly " + p_name + (p_refonly ? " (refonly)" : "") + "...");
- MonoImageOpenStatus status = MONO_IMAGE_OK;
- MonoAssembly *assembly = mono_assembly_load_full(p_aname, nullptr, &status, p_refonly);
+ GDMonoAssembly *assembly = GDMonoAssembly::load(p_name, p_aname, p_refonly, p_search_dirs);
if (!assembly)
return false;
- ERR_FAIL_COND_V(status != MONO_IMAGE_OK, false);
-
- uint32_t domain_id = mono_domain_get_id(mono_domain_get());
-
- GDMonoAssembly **stored_assembly = assemblies[domain_id].getptr(p_name);
-
- ERR_FAIL_COND_V(stored_assembly == nullptr, false);
- ERR_FAIL_COND_V((*stored_assembly)->get_assembly() != assembly, false);
-
- *r_assembly = *stored_assembly;
+ *r_assembly = assembly;
print_verbose("Mono: Assembly " + p_name + (p_refonly ? " (refonly)" : "") + " loaded from path: " + (*r_assembly)->get_path());
@@ -567,7 +567,6 @@ bool GDMono::load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMo
}
bool GDMono::load_assembly_from(const String &p_name, const String &p_path, GDMonoAssembly **r_assembly, bool p_refonly) {
-
CRASH_COND(!r_assembly);
print_verbose("Mono: Loading assembly " + p_name + (p_refonly ? " (refonly)" : "") + "...");
@@ -615,7 +614,6 @@ String ApiAssemblyInfo::to_string(ApiAssemblyInfo::Type p_type) {
}
bool GDMono::_load_corlib_assembly() {
-
if (corlib_assembly)
return true;
@@ -629,7 +627,6 @@ bool GDMono::_load_corlib_assembly() {
#ifdef TOOLS_ENABLED
bool GDMono::copy_prebuilt_api_assembly(ApiAssemblyInfo::Type p_api_type, const String &p_config) {
-
String src_dir = GodotSharpDirs::get_data_editor_prebuilt_api_dir().plus_file(p_config);
String dst_dir = GodotSharpDirs::get_res_assemblies_base_dir().plus_file(p_config);
@@ -700,7 +697,6 @@ static bool try_get_cached_api_hash_for(const String &p_api_assemblies_dir, bool
}
static void create_cached_api_hash_for(const String &p_api_assemblies_dir) {
-
String core_api_assembly_path = p_api_assemblies_dir.plus_file(CORE_API_ASSEMBLY_NAME ".dll");
String editor_api_assembly_path = p_api_assemblies_dir.plus_file(EDITOR_API_ASSEMBLY_NAME ".dll");
String cached_api_hash_path = p_api_assemblies_dir.plus_file("api_hash_cache.cfg");
@@ -743,7 +739,6 @@ bool GDMono::_temp_domain_load_are_assemblies_out_of_sync(const String &p_config
}
String GDMono::update_api_assemblies_from_prebuilt(const String &p_config, const bool *p_core_api_out_of_sync, const bool *p_editor_api_out_of_sync) {
-
#define FAIL_REASON(m_out_of_sync, m_prebuilt_exists) \
( \
(m_out_of_sync ? \
@@ -800,7 +795,6 @@ String GDMono::update_api_assemblies_from_prebuilt(const String &p_config, const
#endif
bool GDMono::_load_core_api_assembly(LoadedApiAssembly &r_loaded_api_assembly, const String &p_config, bool p_refonly) {
-
if (r_loaded_api_assembly.assembly)
return true;
@@ -834,7 +828,6 @@ bool GDMono::_load_core_api_assembly(LoadedApiAssembly &r_loaded_api_assembly, c
#ifdef TOOLS_ENABLED
bool GDMono::_load_editor_api_assembly(LoadedApiAssembly &r_loaded_api_assembly, const String &p_config, bool p_refonly) {
-
if (r_loaded_api_assembly.assembly)
return true;
@@ -911,7 +904,6 @@ bool GDMono::_try_load_api_assemblies_preset() {
}
void GDMono::_load_api_assemblies() {
-
bool api_assemblies_loaded = _try_load_api_assemblies_preset();
#if defined(TOOLS_ENABLED) && !defined(GD_MONO_SINGLE_APPDOMAIN)
@@ -964,7 +956,6 @@ void GDMono::_load_api_assemblies() {
#ifdef TOOLS_ENABLED
bool GDMono::_load_tools_assemblies() {
-
if (tools_assembly && tools_project_editor_assembly)
return true;
@@ -976,7 +967,6 @@ bool GDMono::_load_tools_assemblies() {
#endif
bool GDMono::_load_project_assembly() {
-
if (project_assembly)
return true;
@@ -996,7 +986,6 @@ bool GDMono::_load_project_assembly() {
}
void GDMono::_install_trace_listener() {
-
#ifdef DEBUG_ENABLED
// Install the trace listener now before the project assembly is loaded
GDMonoClass *debug_utils = get_core_api_assembly()->get_class(BINDINGS_NAMESPACE, "DebuggingUtils");
@@ -1013,7 +1002,6 @@ void GDMono::_install_trace_listener() {
#ifndef GD_MONO_SINGLE_APPDOMAIN
Error GDMono::_load_scripts_domain() {
-
ERR_FAIL_COND_V(scripts_domain != nullptr, ERR_BUG);
print_verbose("Mono: Loading scripts domain...");
@@ -1028,7 +1016,6 @@ Error GDMono::_load_scripts_domain() {
}
Error GDMono::_unload_scripts_domain() {
-
ERR_FAIL_NULL_V(scripts_domain, ERR_BUG);
print_verbose("Mono: Finalizing scripts domain...");
@@ -1081,7 +1068,6 @@ Error GDMono::_unload_scripts_domain() {
#ifdef GD_MONO_HOT_RELOAD
Error GDMono::reload_scripts_domain() {
-
ERR_FAIL_COND_V(!runtime_initialized, ERR_BUG);
if (scripts_domain) {
@@ -1118,7 +1104,6 @@ Error GDMono::reload_scripts_domain() {
#ifndef GD_MONO_SINGLE_APPDOMAIN
Error GDMono::finalize_and_unload_domain(MonoDomain *p_domain) {
-
CRASH_COND(p_domain == nullptr);
CRASH_COND(p_domain == GDMono::get_singleton()->get_scripts_domain()); // Should use _unload_scripts_domain() instead
@@ -1151,7 +1136,6 @@ Error GDMono::finalize_and_unload_domain(MonoDomain *p_domain) {
#endif
GDMonoClass *GDMono::get_class(MonoClass *p_raw_class) {
-
MonoImage *image = mono_class_get_image(p_raw_class);
if (image == corlib_assembly->get_image())
@@ -1175,7 +1159,6 @@ GDMonoClass *GDMono::get_class(MonoClass *p_raw_class) {
}
GDMonoClass *GDMono::get_class(const StringName &p_namespace, const StringName &p_name) {
-
GDMonoClass *klass = corlib_assembly->get_class(p_namespace, p_name);
if (klass)
return klass;
@@ -1195,7 +1178,6 @@ GDMonoClass *GDMono::get_class(const StringName &p_namespace, const StringName &
}
void GDMono::_domain_assemblies_cleanup(uint32_t p_domain_id) {
-
HashMap<String, GDMonoAssembly *> &domain_assemblies = assemblies[p_domain_id];
const String *k = nullptr;
@@ -1207,7 +1189,6 @@ void GDMono::_domain_assemblies_cleanup(uint32_t p_domain_id) {
}
void GDMono::unhandled_exception_hook(MonoObject *p_exc, void *) {
-
// This method will be called by the runtime when a thrown exception is not handled.
// It won't be called when we manually treat a thrown exception as unhandled.
// We assume the exception was already printed before calling this hook.
@@ -1224,7 +1205,6 @@ void GDMono::unhandled_exception_hook(MonoObject *p_exc, void *) {
}
GDMono::GDMono() {
-
singleton = this;
gdmono_log = memnew(GDMonoLog);
@@ -1251,7 +1231,6 @@ GDMono::GDMono() {
}
GDMono::~GDMono() {
-
if (is_runtime_initialized()) {
#ifndef GD_MONO_SINGLE_APPDOMAIN
if (scripts_domain) {
@@ -1325,51 +1304,42 @@ GDMono::~GDMono() {
_GodotSharp *_GodotSharp::singleton = nullptr;
void _GodotSharp::attach_thread() {
-
GDMonoUtils::attach_current_thread();
}
void _GodotSharp::detach_thread() {
-
GDMonoUtils::detach_current_thread();
}
int32_t _GodotSharp::get_domain_id() {
-
MonoDomain *domain = mono_domain_get();
CRASH_COND(!domain); // User must check if runtime is initialized before calling this method
return mono_domain_get_id(domain);
}
int32_t _GodotSharp::get_scripts_domain_id() {
-
MonoDomain *domain = GDMono::get_singleton()->get_scripts_domain();
CRASH_COND(!domain); // User must check if scripts domain is loaded before calling this method
return mono_domain_get_id(domain);
}
bool _GodotSharp::is_scripts_domain_loaded() {
-
return GDMono::get_singleton()->is_runtime_initialized() && GDMono::get_singleton()->get_scripts_domain() != nullptr;
}
bool _GodotSharp::_is_domain_finalizing_for_unload(int32_t p_domain_id) {
-
return is_domain_finalizing_for_unload(p_domain_id);
}
bool _GodotSharp::is_domain_finalizing_for_unload() {
-
return is_domain_finalizing_for_unload(mono_domain_get());
}
bool _GodotSharp::is_domain_finalizing_for_unload(int32_t p_domain_id) {
-
return is_domain_finalizing_for_unload(mono_domain_get_by_id(p_domain_id));
}
bool _GodotSharp::is_domain_finalizing_for_unload(MonoDomain *p_domain) {
-
if (!p_domain)
return true;
if (p_domain == GDMono::get_singleton()->get_scripts_domain() && GDMono::get_singleton()->is_finalizing_scripts_domain())
@@ -1378,23 +1348,23 @@ bool _GodotSharp::is_domain_finalizing_for_unload(MonoDomain *p_domain) {
}
bool _GodotSharp::is_runtime_shutting_down() {
-
return mono_runtime_is_shutting_down();
}
bool _GodotSharp::is_runtime_initialized() {
-
return GDMono::get_singleton()->is_runtime_initialized();
}
void _GodotSharp::_reload_assemblies(bool p_soft_reload) {
#ifdef GD_MONO_HOT_RELOAD
- CSharpLanguage::get_singleton()->reload_assemblies(p_soft_reload);
+ // This method may be called more than once with `call_deferred`, so we need to check
+ // again if reloading is needed to avoid reloading multiple times unnecessarily.
+ if (CSharpLanguage::get_singleton()->is_assembly_reloading_needed())
+ CSharpLanguage::get_singleton()->reload_assemblies(p_soft_reload);
#endif
}
void _GodotSharp::_bind_methods() {
-
ClassDB::bind_method(D_METHOD("attach_thread"), &_GodotSharp::attach_thread);
ClassDB::bind_method(D_METHOD("detach_thread"), &_GodotSharp::detach_thread);
@@ -1409,11 +1379,9 @@ void _GodotSharp::_bind_methods() {
}
_GodotSharp::_GodotSharp() {
-
singleton = this;
}
_GodotSharp::~_GodotSharp() {
-
singleton = nullptr;
}