Mono/C#: Optimize the way we store GC handles for scripts
Don't store GC handles for C# script instances and instance bindings as 'Ref<MonoGCHandle>'; store the raw data instead. Initially this was not possible as we needed to store a Variant, but this had not been the case for a looong time yet the stored type was never updated.
This commit is contained in:
@@ -186,7 +186,7 @@ void CachedData::clear_godot_api_cache() {
|
||||
|
||||
// End of MarshalUtils methods
|
||||
|
||||
task_scheduler_handle = Ref<MonoGCHandle>();
|
||||
task_scheduler_handle = Ref<MonoGCHandleRef>();
|
||||
}
|
||||
|
||||
#define GODOT_API_CLASS(m_class) (GDMono::get_singleton()->get_core_api_assembly()->get_class(BINDINGS_NAMESPACE, #m_class))
|
||||
@@ -316,7 +316,7 @@ void update_godot_api_cache() {
|
||||
// TODO Move to CSharpLanguage::init() and do handle disposal
|
||||
MonoObject *task_scheduler = mono_object_new(mono_domain_get(), GODOT_API_CLASS(GodotTaskScheduler)->get_mono_ptr());
|
||||
GDMonoUtils::runtime_object_init(task_scheduler, GODOT_API_CLASS(GodotTaskScheduler));
|
||||
cached_data.task_scheduler_handle = MonoGCHandle::create_strong(task_scheduler);
|
||||
cached_data.task_scheduler_handle = MonoGCHandleRef::create_strong(task_scheduler);
|
||||
|
||||
cached_data.godot_api_cache_updated = true;
|
||||
}
|
||||
|
||||
@@ -156,7 +156,7 @@ struct CachedData {
|
||||
|
||||
// End of MarshalUtils methods
|
||||
|
||||
Ref<MonoGCHandle> task_scheduler_handle;
|
||||
Ref<MonoGCHandleRef> task_scheduler_handle;
|
||||
|
||||
bool corlib_cache_updated;
|
||||
bool godot_api_cache_updated;
|
||||
|
||||
@@ -75,7 +75,7 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
|
||||
script_binding.inited = true;
|
||||
script_binding.type_name = NATIVE_GDMONOCLASS_NAME(klass);
|
||||
script_binding.wrapper_class = klass;
|
||||
script_binding.gchandle = ref ? MonoGCHandle::create_weak(managed) : MonoGCHandle::create_strong(managed);
|
||||
script_binding.gchandle = ref ? MonoGCHandleData::new_weak_handle(managed) : MonoGCHandleData::new_strong_handle(managed);
|
||||
script_binding.owner = unmanaged;
|
||||
|
||||
if (ref) {
|
||||
@@ -101,7 +101,7 @@ void tie_managed_to_unmanaged(MonoObject *managed, Object *unmanaged) {
|
||||
return;
|
||||
}
|
||||
|
||||
Ref<MonoGCHandle> gchandle = ref ? MonoGCHandle::create_weak(managed) : MonoGCHandle::create_strong(managed);
|
||||
MonoGCHandleData gchandle = ref ? MonoGCHandleData::new_weak_handle(managed) : MonoGCHandleData::new_strong_handle(managed);
|
||||
|
||||
Ref<CSharpScript> script = CSharpScript::create_for_managed_type(klass, native);
|
||||
|
||||
|
||||
@@ -86,10 +86,9 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) {
|
||||
}
|
||||
}
|
||||
|
||||
Ref<MonoGCHandle> &gchandle = script_binding.gchandle;
|
||||
ERR_FAIL_COND_V(gchandle.is_null(), NULL);
|
||||
MonoGCHandleData &gchandle = script_binding.gchandle;
|
||||
|
||||
MonoObject *target = gchandle->get_target();
|
||||
MonoObject *target = gchandle.get_target();
|
||||
|
||||
if (target)
|
||||
return target;
|
||||
@@ -106,7 +105,7 @@ MonoObject *unmanaged_get_managed(Object *unmanaged) {
|
||||
MonoObject *mono_object = GDMonoUtils::create_managed_for_godot_object(script_binding.wrapper_class, script_binding.type_name, unmanaged);
|
||||
ERR_FAIL_NULL_V(mono_object, NULL);
|
||||
|
||||
gchandle->set_handle(MonoGCHandle::new_strong_handle(mono_object), MonoGCHandle::STRONG_HANDLE);
|
||||
gchandle = MonoGCHandleData::new_strong_handle(mono_object);
|
||||
|
||||
// Tie managed to unmanaged
|
||||
Reference *ref = Object::cast_to<Reference>(unmanaged);
|
||||
@@ -156,6 +155,22 @@ bool is_thread_attached() {
|
||||
return mono_domain_get() != NULL;
|
||||
}
|
||||
|
||||
uint32_t new_strong_gchandle(MonoObject *p_object) {
|
||||
return mono_gchandle_new(p_object, /* pinned: */ false);
|
||||
}
|
||||
|
||||
uint32_t new_strong_gchandle_pinned(MonoObject *p_object) {
|
||||
return mono_gchandle_new(p_object, /* pinned: */ true);
|
||||
}
|
||||
|
||||
uint32_t new_weak_gchandle(MonoObject *p_object) {
|
||||
return mono_gchandle_new_weakref(p_object, /* track_resurrection: */ false);
|
||||
}
|
||||
|
||||
void free_gchandle(uint32_t p_gchandle) {
|
||||
mono_gchandle_free(p_gchandle);
|
||||
}
|
||||
|
||||
void runtime_object_init(MonoObject *p_this_obj, GDMonoClass *p_class, MonoException **r_exc) {
|
||||
GDMonoMethod *ctor = p_class->get_method(".ctor", 0);
|
||||
ERR_FAIL_NULL(ctor);
|
||||
|
||||
@@ -92,6 +92,11 @@ _FORCE_INLINE_ bool is_main_thread() {
|
||||
return mono_domain_get() != NULL && mono_thread_get_main() == mono_thread_current();
|
||||
}
|
||||
|
||||
uint32_t new_strong_gchandle(MonoObject *p_object);
|
||||
uint32_t new_strong_gchandle_pinned(MonoObject *p_object);
|
||||
uint32_t new_weak_gchandle(MonoObject *p_object);
|
||||
void free_gchandle(uint32_t p_gchandle);
|
||||
|
||||
void runtime_object_init(MonoObject *p_this_obj, GDMonoClass *p_class, MonoException **r_exc = NULL);
|
||||
|
||||
bool mono_delegate_equal(MonoDelegate *p_a, MonoDelegate *p_b);
|
||||
|
||||
Reference in New Issue
Block a user