Merge pull request #69506 from adamscott/move-gdscript-uninit-to-finalize

Move GDScript uninitialization to `GDScriptLanguage::finish()`
This commit is contained in:
Rémi Verschelde 2022-12-06 16:11:21 +01:00
commit 9bd7ad53f7
No known key found for this signature in database
GPG Key ID: C3336907360768E1
5 changed files with 61 additions and 47 deletions

View File

@ -2019,6 +2019,42 @@ Error GDScriptLanguage::execute_file(const String &p_path) {
} }
void GDScriptLanguage::finish() { void GDScriptLanguage::finish() {
if (_call_stack) {
memdelete_arr(_call_stack);
_call_stack = nullptr;
}
// Clear the cache before parsing the script_list
GDScriptCache::clear();
// Clear dependencies between scripts, to ensure cyclic references are broken
// (to avoid leaks at exit).
SelfList<GDScript> *s = script_list.first();
while (s) {
// This ensures the current script is not released before we can check
// what's the next one in the list (we can't get the next upfront because we
// don't know if the reference breaking will cause it -or any other after
// it, for that matter- to be released so the next one is not the same as
// before).
Ref<GDScript> scr = s->self();
if (scr.is_valid()) {
for (KeyValue<StringName, GDScriptFunction *> &E : scr->member_functions) {
GDScriptFunction *func = E.value;
for (int i = 0; i < func->argument_types.size(); i++) {
func->argument_types.write[i].script_type_ref = Ref<Script>();
}
func->return_type.script_type_ref = Ref<Script>();
}
for (KeyValue<StringName, GDScript::MemberInfo> &E : scr->member_indices) {
E.value.data_type.script_type_ref = Ref<Script>();
}
// Clear backup for scripts that could slip out of the cyclic reference
// check
scr->clear();
}
s = s->next();
}
} }
void GDScriptLanguage::profiling_start() { void GDScriptLanguage::profiling_start() {
@ -2530,36 +2566,6 @@ GDScriptLanguage::GDScriptLanguage() {
} }
GDScriptLanguage::~GDScriptLanguage() { GDScriptLanguage::~GDScriptLanguage() {
if (_call_stack) {
memdelete_arr(_call_stack);
}
// Clear dependencies between scripts, to ensure cyclic references are broken (to avoid leaks at exit).
SelfList<GDScript> *s = script_list.first();
while (s) {
// This ensures the current script is not released before we can check what's the next one
// in the list (we can't get the next upfront because we don't know if the reference breaking
// will cause it -or any other after it, for that matter- to be released so the next one
// is not the same as before).
Ref<GDScript> scr = s->self();
if (scr.is_valid()) {
for (KeyValue<StringName, GDScriptFunction *> &E : scr->member_functions) {
GDScriptFunction *func = E.value;
for (int i = 0; i < func->argument_types.size(); i++) {
func->argument_types.write[i].script_type_ref = Ref<Script>();
}
func->return_type.script_type_ref = Ref<Script>();
}
for (KeyValue<StringName, GDScript::MemberInfo> &E : scr->member_indices) {
E.value.data_type.script_type_ref = Ref<Script>();
}
// Clear backup for scripts that could slip out of the cyclic reference check
scr->clear();
}
s = s->next();
}
singleton = nullptr; singleton = nullptr;
} }

View File

@ -381,15 +381,15 @@ void GDScriptCache::clear_unreferenced_packed_scenes() {
} }
} }
GDScriptCache::GDScriptCache() { void GDScriptCache::clear() {
singleton = this; if (singleton == nullptr) {
} return;
}
GDScriptCache::~GDScriptCache() { MutexLock lock(singleton->mutex);
destructing = true;
RBSet<Ref<GDScriptParserRef>> parser_map_refs; RBSet<Ref<GDScriptParserRef>> parser_map_refs;
for (KeyValue<String, GDScriptParserRef *> &E : parser_map) { for (KeyValue<String, GDScriptParserRef *> &E : singleton->parser_map) {
parser_map_refs.insert(E.value); parser_map_refs.insert(E.value);
} }
@ -399,12 +399,20 @@ GDScriptCache::~GDScriptCache() {
} }
parser_map_refs.clear(); parser_map_refs.clear();
parser_map.clear(); singleton->parser_map.clear();
shallow_gdscript_cache.clear(); singleton->shallow_gdscript_cache.clear();
full_gdscript_cache.clear(); singleton->full_gdscript_cache.clear();
packed_scene_cache.clear(); singleton->packed_scene_cache.clear();
packed_scene_dependencies.clear(); singleton->packed_scene_dependencies.clear();
}
GDScriptCache::GDScriptCache() {
singleton = this;
}
GDScriptCache::~GDScriptCache() {
destructing = true;
clear();
singleton = nullptr; singleton = nullptr;
} }

View File

@ -111,6 +111,8 @@ public:
return singleton->destructing; return singleton->destructing;
}; };
static void clear();
GDScriptCache(); GDScriptCache();
~GDScriptCache(); ~GDScriptCache();
}; };

View File

@ -124,7 +124,6 @@ Shape2D::Shape2D(const RID &p_rid) {
} }
Shape2D::~Shape2D() { Shape2D::~Shape2D() {
if (PhysicsServer2D::get_singleton() != nullptr) { ERR_FAIL_NULL(PhysicsServer2D::get_singleton());
PhysicsServer2D::get_singleton()->free(shape); PhysicsServer2D::get_singleton()->free(shape);
}
} }

View File

@ -128,7 +128,6 @@ Shape3D::Shape3D(RID p_shape) :
shape(p_shape) {} shape(p_shape) {}
Shape3D::~Shape3D() { Shape3D::~Shape3D() {
if (PhysicsServer3D::get_singleton() != nullptr) { ERR_FAIL_NULL(PhysicsServer3D::get_singleton());
PhysicsServer3D::get_singleton()->free(shape); PhysicsServer3D::get_singleton()->free(shape);
}
} }