diff --git a/modules/mono/csharp_script.cpp b/modules/mono/csharp_script.cpp index 99bd3edb9e35..ae464700ff28 100644 --- a/modules/mono/csharp_script.cpp +++ b/modules/mono/csharp_script.cpp @@ -104,7 +104,7 @@ Error CSharpLanguage::execute_file(const String &p_path) { return OK; } -extern void *godotsharp_pinvoke_funcs[179]; +extern void *godotsharp_pinvoke_funcs[181]; [[maybe_unused]] volatile void **do_not_strip_godotsharp_pinvoke_funcs; #ifdef TOOLS_ENABLED extern void *godotsharp_editor_pinvoke_funcs[30]; @@ -793,6 +793,20 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { // (while hot-reload is not yet implemented) gdmono->initialize_load_assemblies(); + { + MutexLock lock(script_instances_mutex); + + for (SelfList *elem = script_list.first(); elem; elem = elem->next()) { + Ref script(elem->self()); + + script->exports_invalidated = true; + + if (!script->get_path().is_empty()) { + script->reload(p_soft_reload); + } + } + } + #if 0 // There is no soft reloading with Mono. It's always hard reloading. @@ -1010,7 +1024,7 @@ void CSharpLanguage::reload_assemblies(bool p_soft_reload) { GDMonoClass *native = GDMonoUtils::get_class_native_base(script_class); - CSharpScript::initialize_for_managed_type(script, script_class, native); + CSharpScript::reload_registered_script(script, script_class, native); } StringName native_name = NATIVE_GDMONOCLASS_NAME(script->native); @@ -1563,9 +1577,13 @@ void CSharpLanguage::tie_native_managed_to_unmanaged(GCHandleIntPtr p_gchandle_i CSharpLanguage::set_instance_binding(p_unmanaged, data); } -void CSharpLanguage::tie_user_managed_to_unmanaged(GCHandleIntPtr p_gchandle_intptr, Object *p_unmanaged, CSharpScript *p_script, bool p_ref_counted) { +void CSharpLanguage::tie_user_managed_to_unmanaged(GCHandleIntPtr p_gchandle_intptr, Object *p_unmanaged, Ref *p_script, bool p_ref_counted) { // This method should not fail + Ref script = *p_script; + // We take care of destructing this reference here, so the managed code won't need to do another P/Invoke call + p_script->~Ref(); + CRASH_COND(!p_unmanaged); // All mono objects created from the managed world (e.g.: 'new Player()') @@ -1578,12 +1596,8 @@ void CSharpLanguage::tie_user_managed_to_unmanaged(GCHandleIntPtr p_gchandle_int MonoGCHandleData gchandle = MonoGCHandleData(p_gchandle_intptr, p_ref_counted ? gdmono::GCHandleType::WEAK_HANDLE : gdmono::GCHandleType::STRONG_HANDLE); - Ref script = p_script; - CRASH_COND(script.is_null()); - CSharpScript::initialize_for_managed_type(script); - CSharpInstance *csharp_instance = CSharpInstance::create_for_managed_type(p_unmanaged, script.ptr(), gchandle); p_unmanaged->set_script_and_instance(script, csharp_instance); @@ -2345,12 +2359,17 @@ void CSharpScript::_bind_methods() { ClassDB::bind_vararg_method(METHOD_FLAGS_DEFAULT, "new", &CSharpScript::_new, MethodInfo("new")); } -void CSharpScript::initialize_for_managed_type(Ref p_script) { +void CSharpScript::reload_registered_script(Ref p_script) { // IMPORTANT: // This method must be called only after the CSharpScript and its associated type // have been added to the script bridge map in the ScriptManagerBridge C# class. + // Other than that, it's the same as `CSharpScript::reload`. - // This method should not fail, only assertions allowed + // This method should not fail, only assertions allowed. + + // Unlike `reload`, we print an error rather than silently returning, + // as we can assert this won't be called a second time until invalidated. + ERR_FAIL_COND(!p_script->reload_invalidated); p_script->valid = true; p_script->reload_invalidated = false; @@ -2607,9 +2626,6 @@ Error CSharpScript::reload(bool p_keep_state) { String script_path = get_path(); - // In case it was already added by a previous reload - GDMonoCache::managed_callbacks.ScriptManagerBridge_RemoveScriptBridge(this); - valid = GDMonoCache::managed_callbacks.ScriptManagerBridge_AddScriptBridge(this, &script_path); if (valid) { @@ -2817,9 +2833,13 @@ Ref ResourceFormatLoaderCSharpScript::load(const String &p_path, const // TODO ignore anything inside bin/ and obj/ in tools builds? - CSharpScript *script = memnew(CSharpScript); + Ref script; - Ref scriptres(script); + if (GDMonoCache::godot_api_cache_updated) { + GDMonoCache::managed_callbacks.ScriptManagerBridge_GetOrCreateScriptBridgeForPath(&p_path, &script); + } else { + script = Ref(memnew(CSharpScript)); + } #if defined(DEBUG_ENABLED) || defined(TOOLS_ENABLED) Error err = script->load_source_code(p_path); @@ -2834,7 +2854,7 @@ Ref ResourceFormatLoaderCSharpScript::load(const String &p_path, const *r_error = OK; } - return scriptres; + return script; } void ResourceFormatLoaderCSharpScript::get_recognized_extensions(List *p_extensions) const { diff --git a/modules/mono/csharp_script.h b/modules/mono/csharp_script.h index d4891395baf4..eb72df9f429f 100644 --- a/modules/mono/csharp_script.h +++ b/modules/mono/csharp_script.h @@ -134,7 +134,6 @@ private: // Do not use unless you know what you are doing static void update_script_class_info(Ref p_script); - static void initialize_for_managed_type(Ref p_script); protected: static void _bind_methods(); @@ -144,6 +143,8 @@ protected: void _get_property_list(List *p_properties) const; public: + static void reload_registered_script(Ref p_script); + bool can_instantiate() const override; StringName get_instance_base_type() const override; ScriptInstance *instance_create(Object *p_this) override; @@ -460,7 +461,7 @@ public: bool setup_csharp_script_binding(CSharpScriptBinding &r_script_binding, Object *p_object); static void tie_native_managed_to_unmanaged(GCHandleIntPtr p_gchandle_intptr, Object *p_unmanaged, const StringName *p_native_name, bool p_ref_counted); - static void tie_user_managed_to_unmanaged(GCHandleIntPtr p_gchandle_intptr, Object *p_unmanaged, CSharpScript *p_script, bool p_ref_counted); + static void tie_user_managed_to_unmanaged(GCHandleIntPtr p_gchandle_intptr, Object *p_unmanaged, Ref *p_script, bool p_ref_counted); static void tie_managed_to_unmanaged_with_pre_setup(GCHandleIntPtr p_gchandle_intptr, Object *p_unmanaged); #warning TODO diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ManagedCallbacks.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ManagedCallbacks.cs index 7a6748b4eb72..a34877687466 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ManagedCallbacks.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ManagedCallbacks.cs @@ -21,6 +21,7 @@ namespace Godot.Bridge public delegate* unmanaged ScriptManagerBridge_HasScriptSignal; public delegate* unmanaged ScriptManagerBridge_ScriptIsOrInherits; public delegate* unmanaged ScriptManagerBridge_AddScriptBridge; + public delegate* unmanaged ScriptManagerBridge_GetOrCreateScriptBridgeForPath; public delegate* unmanaged ScriptManagerBridge_RemoveScriptBridge; public delegate* unmanaged ScriptManagerBridge_UpdateScriptClassInfo; public delegate* unmanaged ScriptManagerBridge_SwapGCHandleForType; @@ -56,6 +57,7 @@ namespace Godot.Bridge ScriptManagerBridge_HasScriptSignal = &ScriptManagerBridge.HasScriptSignal, ScriptManagerBridge_ScriptIsOrInherits = &ScriptManagerBridge.ScriptIsOrInherits, ScriptManagerBridge_AddScriptBridge = &ScriptManagerBridge.AddScriptBridge, + ScriptManagerBridge_GetOrCreateScriptBridgeForPath = &ScriptManagerBridge.GetOrCreateScriptBridgeForPath, ScriptManagerBridge_RemoveScriptBridge = &ScriptManagerBridge.RemoveScriptBridge, ScriptManagerBridge_UpdateScriptClassInfo = &ScriptManagerBridge.UpdateScriptClassInfo, ScriptManagerBridge_SwapGCHandleForType = &ScriptManagerBridge.SwapGCHandleForType, diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs index 8348598b6548..d812626fab25 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/Bridge/ScriptManagerBridge.cs @@ -12,22 +12,11 @@ namespace Godot.Bridge { public static class ScriptManagerBridge { - private static System.Collections.Generic.Dictionary _scriptLookupMap = new(); - private static System.Collections.Generic.Dictionary _scriptBridgeMap = new(); + private static System.Collections.Generic.Dictionary _pathScriptMap = new(); - private struct ScriptLookupInfo - { - public string ClassNamespace { get; private set; } - public string ClassName { get; private set; } - public Type ScriptType { get; private set; } - - public ScriptLookupInfo(string classNamespace, string className, Type scriptType) - { - ClassNamespace = classNamespace; - ClassName = className; - ScriptType = scriptType; - } - }; + private static readonly object ScriptBridgeLock = new(); + private static System.Collections.Generic.Dictionary _scriptTypeMap = new(); + private static System.Collections.Generic.Dictionary _typeScriptMap = new(); [UnmanagedCallersOnly] internal static void FrameCallback() @@ -80,7 +69,7 @@ namespace Godot.Bridge try { // Performance is not critical here as this will be replaced with source generators. - Type scriptType = _scriptBridgeMap[scriptPtr]; + Type scriptType = _scriptTypeMap[scriptPtr]; var obj = (Object)FormatterServices.GetUninitializedObject(scriptType); var ctor = scriptType @@ -133,7 +122,7 @@ namespace Godot.Bridge try { // Performance is not critical here as this will be replaced with source generators. - if (!_scriptBridgeMap.TryGetValue(scriptPtr, out var scriptType)) + if (!_scriptTypeMap.TryGetValue(scriptPtr, out var scriptType)) { *outRes = default; return; @@ -225,7 +214,7 @@ namespace Godot.Bridge if (scriptPathAttr == null) return; - _scriptLookupMap[scriptPathAttr.Path] = new ScriptLookupInfo(type.Namespace, type.Name, type); + _pathScriptMap[scriptPathAttr.Path] = type; } var assemblyHasScriptsAttr = assembly.GetCustomAttributes(inherit: false) @@ -304,7 +293,7 @@ namespace Godot.Bridge // Performance is not critical here as this will be replaced with source generators. using var signals = new Dictionary(); - Type top = _scriptBridgeMap[scriptPtr]; + Type top = _scriptTypeMap[scriptPtr]; Type native = Object.InternalGetClassNativeBase(top); while (top != null && top != native) @@ -400,7 +389,7 @@ namespace Godot.Bridge string signalNameStr = Marshaling.ConvertStringToManaged(*signalName); - Type top = _scriptBridgeMap[scriptPtr]; + Type top = _scriptTypeMap[scriptPtr]; Type native = Object.InternalGetClassNativeBase(top); while (top != null && top != native) @@ -446,10 +435,10 @@ namespace Godot.Bridge { try { - if (!_scriptBridgeMap.TryGetValue(scriptPtr, out var scriptType)) + if (!_scriptTypeMap.TryGetValue(scriptPtr, out var scriptType)) return false.ToGodotBool(); - if (!_scriptBridgeMap.TryGetValue(scriptPtrMaybeBase, out var maybeBaseType)) + if (!_scriptTypeMap.TryGetValue(scriptPtrMaybeBase, out var maybeBaseType)) return false.ToGodotBool(); return (scriptType == maybeBaseType || maybeBaseType.IsAssignableFrom(scriptType)).ToGodotBool(); @@ -466,12 +455,19 @@ namespace Godot.Bridge { try { - string scriptPathStr = Marshaling.ConvertStringToManaged(*scriptPath); + lock (ScriptBridgeLock) + { + if (!_scriptTypeMap.ContainsKey(scriptPtr)) + { + string scriptPathStr = Marshaling.ConvertStringToManaged(*scriptPath); - if (!_scriptLookupMap.TryGetValue(scriptPathStr, out var lookupInfo)) - return false.ToGodotBool(); + if (!_pathScriptMap.TryGetValue(scriptPathStr, out Type scriptType)) + return false.ToGodotBool(); - _scriptBridgeMap.Add(scriptPtr, lookupInfo.ScriptType); + _scriptTypeMap.Add(scriptPtr, scriptType); + _typeScriptMap.Add(scriptType, scriptPtr); + } + } return true.ToGodotBool(); } @@ -482,15 +478,49 @@ namespace Godot.Bridge } } - internal static void AddScriptBridgeWithType(IntPtr scriptPtr, Type scriptType) - => _scriptBridgeMap.Add(scriptPtr, scriptType); + [UnmanagedCallersOnly] + internal static unsafe void GetOrCreateScriptBridgeForPath(godot_string* scriptPath, godot_ref* outScript) + { + string scriptPathStr = Marshaling.ConvertStringToManaged(*scriptPath); + + if (!_pathScriptMap.TryGetValue(scriptPathStr, out Type scriptType)) + { + NativeFuncs.godotsharp_internal_new_csharp_script(outScript); + return; + } + + GetOrCreateScriptBridgeForType(scriptType, outScript); + } + + internal static unsafe void GetOrCreateScriptBridgeForType(Type scriptType, godot_ref* outScript) + { + lock (ScriptBridgeLock) + { + if (_typeScriptMap.TryGetValue(scriptType, out IntPtr scriptPtr)) + { + NativeFuncs.godotsharp_ref_new_from_ref_counted_ptr(out *outScript, scriptPtr); + return; + } + + NativeFuncs.godotsharp_internal_new_csharp_script(outScript); + scriptPtr = outScript->Reference; + + _scriptTypeMap.Add(scriptPtr, scriptType); + _typeScriptMap.Add(scriptType, scriptPtr); + + NativeFuncs.godotsharp_internal_reload_registered_script(scriptPtr); + } + } [UnmanagedCallersOnly] internal static void RemoveScriptBridge(IntPtr scriptPtr) { try { - _scriptBridgeMap.Remove(scriptPtr); + lock (ScriptBridgeLock) + { + _ = _scriptTypeMap.Remove(scriptPtr); + } } catch (Exception e) { @@ -505,7 +535,7 @@ namespace Godot.Bridge try { // Performance is not critical here as this will be replaced with source generators. - var scriptType = _scriptBridgeMap[scriptPtr]; + var scriptType = _scriptTypeMap[scriptPtr]; *outTool = scriptType.GetCustomAttributes(inherit: false) .OfType() @@ -630,7 +660,7 @@ namespace Godot.Bridge { try { - Type scriptType = _scriptBridgeMap[scriptPtr]; + Type scriptType = _scriptTypeMap[scriptPtr]; GetPropertyInfoListForType(scriptType, scriptPtr, addPropInfoFunc); } catch (Exception e) @@ -752,7 +782,7 @@ namespace Godot.Bridge { try { - Type top = _scriptBridgeMap[scriptPtr]; + Type top = _scriptTypeMap[scriptPtr]; Type native = Object.InternalGetClassNativeBase(top); while (top != null && top != native) diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropUtils.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropUtils.cs index 8ddf28ba16e5..f6f0186016f5 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropUtils.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/InteropUtils.cs @@ -60,13 +60,17 @@ namespace Godot.NativeInterop } else { - IntPtr scriptPtr = NativeFuncs.godotsharp_internal_new_csharp_script(); + unsafe + { + // We don't dispose `script` ourselves here. + // `tie_user_managed_to_unmanaged` does it for us to avoid another P/Invoke call. + godot_ref script; + ScriptManagerBridge.GetOrCreateScriptBridgeForType(type, &script); - ScriptManagerBridge.AddScriptBridgeWithType(scriptPtr, type); - - // IMPORTANT: This must be called after AddScriptWithTypeBridge - NativeFuncs.godotsharp_internal_tie_user_managed_to_unmanaged( - GCHandle.ToIntPtr(gcHandle), unmanaged, scriptPtr, refCounted.ToGodotBool()); + // IMPORTANT: This must be called after GetOrCreateScriptBridgeForType + NativeFuncs.godotsharp_internal_tie_user_managed_to_unmanaged( + GCHandle.ToIntPtr(gcHandle), unmanaged, &script, refCounted.ToGodotBool()); + } } } diff --git a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs index 01add1bf4561..2c81ae781651 100644 --- a/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs +++ b/modules/mono/glue/GodotSharp/GodotSharp/Core/NativeInterop/NativeFuncs.cs @@ -42,7 +42,8 @@ namespace Godot.NativeInterop internal static extern void godotsharp_internal_object_disposed(IntPtr ptr, IntPtr gcHandleToFree); [DllImport(GodotDllName)] - internal static extern void godotsharp_internal_refcounted_disposed(IntPtr ptr, IntPtr gcHandleToFree, godot_bool isFinalizer); + internal static extern void godotsharp_internal_refcounted_disposed(IntPtr ptr, IntPtr gcHandleToFree, + godot_bool isFinalizer); [DllImport(GodotDllName)] internal static extern void godotsharp_internal_object_connect_event_signal(IntPtr obj, @@ -59,7 +60,7 @@ namespace Godot.NativeInterop [DllImport(GodotDllName)] internal static extern void godotsharp_internal_tie_user_managed_to_unmanaged(IntPtr gcHandleIntPtr, - IntPtr unmanaged, IntPtr scriptPtr, godot_bool refCounted); + IntPtr unmanaged, godot_ref* scriptPtr, godot_bool refCounted); [DllImport(GodotDllName)] internal static extern void godotsharp_internal_tie_managed_to_unmanaged_with_pre_setup( @@ -77,7 +78,10 @@ namespace Godot.NativeInterop IntPtr oldGCHandlePtr); [DllImport(GodotDllName)] - internal static extern IntPtr godotsharp_internal_new_csharp_script(); + internal static extern void godotsharp_internal_new_csharp_script(godot_ref* r_script); + + [DllImport(GodotDllName)] + internal static extern void godotsharp_internal_reload_registered_script(IntPtr scriptPtr); [DllImport(GodotDllName)] internal static extern void godotsharp_array_filter_godot_objects_by_native(in godot_string_name p_native_name, @@ -87,6 +91,9 @@ namespace Godot.NativeInterop internal static extern void godotsharp_array_filter_godot_objects_by_non_native(in godot_array p_input, out godot_array r_output); + [DllImport(GodotDllName)] + public static extern void godotsharp_ref_new_from_ref_counted_ptr(out godot_ref r_dest, IntPtr p_ref_counted_ptr); + [DllImport(GodotDllName)] public static extern void godotsharp_ref_destroy(ref godot_ref p_instance); diff --git a/modules/mono/glue/runtime_interop.cpp b/modules/mono/glue/runtime_interop.cpp index 7150e2e35bbe..84db9473c55a 100644 --- a/modules/mono/glue/runtime_interop.cpp +++ b/modules/mono/glue/runtime_interop.cpp @@ -285,7 +285,7 @@ GD_PINVOKE_EXPORT void godotsharp_internal_tie_native_managed_to_unmanaged(GCHan CSharpLanguage::tie_native_managed_to_unmanaged(p_gchandle_intptr, p_unmanaged, p_native_name, p_ref_counted); } -GD_PINVOKE_EXPORT void godotsharp_internal_tie_user_managed_to_unmanaged(GCHandleIntPtr p_gchandle_intptr, Object *p_unmanaged, CSharpScript *p_script, bool p_ref_counted) { +GD_PINVOKE_EXPORT void godotsharp_internal_tie_user_managed_to_unmanaged(GCHandleIntPtr p_gchandle_intptr, Object *p_unmanaged, Ref *p_script, bool p_ref_counted) { CSharpLanguage::tie_user_managed_to_unmanaged(p_gchandle_intptr, p_unmanaged, p_script, p_ref_counted); } @@ -293,10 +293,13 @@ GD_PINVOKE_EXPORT void godotsharp_internal_tie_managed_to_unmanaged_with_pre_set CSharpLanguage::tie_managed_to_unmanaged_with_pre_setup(p_gchandle_intptr, p_unmanaged); } -GD_PINVOKE_EXPORT CSharpScript *godotsharp_internal_new_csharp_script() { - CSharpScript *script = memnew(CSharpScript); - CRASH_COND(!script); - return script; +GD_PINVOKE_EXPORT void godotsharp_internal_new_csharp_script(Ref *r_dest) { + memnew_placement(r_dest, Ref(memnew(CSharpScript))); +} + +GD_PINVOKE_EXPORT void godotsharp_internal_reload_registered_script(CSharpScript *p_script) { + CRASH_COND(!p_script); + CSharpScript::reload_registered_script(Ref(p_script)); } GD_PINVOKE_EXPORT void godotsharp_array_filter_godot_objects_by_native(StringName *p_native_name, const Array *p_input, Array *r_output) { @@ -321,6 +324,10 @@ GD_PINVOKE_EXPORT void godotsharp_array_filter_godot_objects_by_non_native(const } } +GD_PINVOKE_EXPORT void godotsharp_ref_new_from_ref_counted_ptr(Ref *r_dest, RefCounted *p_ref_counted_ptr) { + memnew_placement(r_dest, Ref(p_ref_counted_ptr)); +} + GD_PINVOKE_EXPORT void godotsharp_ref_destroy(Ref *p_instance) { p_instance->~Ref(); } @@ -1281,7 +1288,7 @@ GD_PINVOKE_EXPORT void godotsharp_object_to_string(Object *p_ptr, godot_string * #endif // We need this to prevent the functions from being stripped. -void *godotsharp_pinvoke_funcs[179] = { +void *godotsharp_pinvoke_funcs[181] = { (void *)godotsharp_method_bind_get_method, (void *)godotsharp_get_class_constructor, (void *)godotsharp_engine_get_singleton, @@ -1297,8 +1304,10 @@ void *godotsharp_pinvoke_funcs[179] = { (void *)godotsharp_internal_tie_user_managed_to_unmanaged, (void *)godotsharp_internal_tie_managed_to_unmanaged_with_pre_setup, (void *)godotsharp_internal_new_csharp_script, + (void *)godotsharp_internal_reload_registered_script, (void *)godotsharp_array_filter_godot_objects_by_native, (void *)godotsharp_array_filter_godot_objects_by_non_native, + (void *)godotsharp_ref_new_from_ref_counted_ptr, (void *)godotsharp_ref_destroy, (void *)godotsharp_string_name_new_from_string, (void *)godotsharp_node_path_new_from_string, diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index 0792a88f52bc..7adb6f60eb11 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -49,10 +49,9 @@ #include #include -#warning TODO mobile +// TODO mobile #if 0 #ifdef ANDROID_ENABLED -#include "android_mono_config.h" #include "support/android_support.h" #elif defined(IOS_ENABLED) #include "support/ios_support.h" @@ -61,75 +60,6 @@ GDMono *GDMono::singleton = nullptr; -namespace { - -#warning "TODO .NET debugging and profiling. What's needed?" -#if 0 -void gd_mono_profiler_init() { - String profiler_args = GLOBAL_DEF("mono/profiler/args", "log:calls,alloc,sample,output=output.mlpd"); - bool profiler_enabled = GLOBAL_DEF("mono/profiler/enabled", false); - if (profiler_enabled) { - mono_profiler_load(profiler_args.utf8()); - return; - } - - const String env_var_name = "MONO_ENV_OPTIONS"; - if (OS::get_singleton()->has_environment(env_var_name)) { - const String mono_env_ops = OS::get_singleton()->get_environment(env_var_name); - // Usually MONO_ENV_OPTIONS looks like: --profile=jb:prof=timeline,ctl=remote,host=127.0.0.1:55467 - const String prefix = "--profile="; - if (mono_env_ops.begins_with(prefix)) { - const String ops = mono_env_ops.substr(prefix.length(), mono_env_ops.length()); - mono_profiler_load(ops.utf8()); - } - } -} - -void gd_mono_debug_init() { - 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); - int da_timeout = GLOBAL_DEF("mono/debugger_agent/wait_timeout", 3000); - - if (Engine::get_singleton()->is_editor_hint() || - ProjectSettings::get_singleton()->get_resource_path().is_empty() || - Engine::get_singleton()->is_project_manager_hint()) { - if (da_args.size() == 0) { - return; - } - } - - if (da_args.length() == 0) { - da_args = String("--debugger-agent=transport=dt_socket,address=127.0.0.1:" + itos(da_port) + - ",embedding=1,server=y,suspend=" + (da_suspend ? "y,timeout=" + itos(da_timeout) : "n")) - .utf8(); - } -#else - if (da_args.length() == 0) { - 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", - da_args.get_data() - }; - mono_jit_parse_options(2, (char **)options); -} -#endif -} // namespace - namespace { hostfxr_initialize_for_dotnet_command_line_fn hostfxr_initialize_for_dotnet_command_line = nullptr; hostfxr_initialize_for_runtime_config_fn hostfxr_initialize_for_runtime_config = nullptr; diff --git a/modules/mono/mono_gd/gd_mono_cache.h b/modules/mono/mono_gd/gd_mono_cache.h index 7a75532fb774..7daa4c92d386 100644 --- a/modules/mono/mono_gd/gd_mono_cache.h +++ b/modules/mono/mono_gd/gd_mono_cache.h @@ -84,6 +84,7 @@ struct ManagedCallbacks { using FuncScriptManagerBridge_HasScriptSignal = bool(GD_CLR_STDCALL *)(const CSharpScript *, const String *); using FuncScriptManagerBridge_ScriptIsOrInherits = bool(GD_CLR_STDCALL *)(const CSharpScript *, const CSharpScript *); using FuncScriptManagerBridge_AddScriptBridge = bool(GD_CLR_STDCALL *)(const CSharpScript *, const String *); + using FuncScriptManagerBridge_GetOrCreateScriptBridgeForPath = void(GD_CLR_STDCALL *)(const String *, Ref *); using FuncScriptManagerBridge_RemoveScriptBridge = void(GD_CLR_STDCALL *)(const CSharpScript *); using FuncScriptManagerBridge_UpdateScriptClassInfo = void(GD_CLR_STDCALL *)(const CSharpScript *, bool *, Dictionary *); using FuncScriptManagerBridge_SwapGCHandleForType = bool(GD_CLR_STDCALL *)(GCHandleIntPtr, GCHandleIntPtr *, bool); @@ -113,6 +114,7 @@ struct ManagedCallbacks { FuncScriptManagerBridge_HasScriptSignal ScriptManagerBridge_HasScriptSignal; FuncScriptManagerBridge_ScriptIsOrInherits ScriptManagerBridge_ScriptIsOrInherits; FuncScriptManagerBridge_AddScriptBridge ScriptManagerBridge_AddScriptBridge; + FuncScriptManagerBridge_GetOrCreateScriptBridgeForPath ScriptManagerBridge_GetOrCreateScriptBridgeForPath; FuncScriptManagerBridge_RemoveScriptBridge ScriptManagerBridge_RemoveScriptBridge; FuncScriptManagerBridge_UpdateScriptClassInfo ScriptManagerBridge_UpdateScriptClassInfo; FuncScriptManagerBridge_SwapGCHandleForType ScriptManagerBridge_SwapGCHandleForType;