GDScript: Fix too many calls to 'remove_parser'
+fix excessive memory allocations when 'load'ing many dependant scripts +fix excessive calls to vformat
This commit is contained in:
parent
6e8fa6dd50
commit
e680369d5b
|
@ -299,12 +299,14 @@ void GDScriptAnalyzer::get_class_node_current_scope_classes(GDScriptParser::Clas
|
||||||
|
|
||||||
// Prioritize node base type over its outer class
|
// Prioritize node base type over its outer class
|
||||||
if (p_node->base_type.class_type != nullptr) {
|
if (p_node->base_type.class_type != nullptr) {
|
||||||
ensure_cached_parser_for_class(p_node->base_type.class_type, p_node, vformat(R"(Trying to fetch classes in the current scope: base class of "%s")", p_node->fqcn), p_source);
|
// TODO: 'ensure_cached_external_parser_for_class()' is only necessary because 'resolve_class_inheritance()' is not getting called here.
|
||||||
|
ensure_cached_external_parser_for_class(p_node->base_type.class_type, p_node, "Trying to fetch classes in the current scope", p_source);
|
||||||
get_class_node_current_scope_classes(p_node->base_type.class_type, p_list, p_source);
|
get_class_node_current_scope_classes(p_node->base_type.class_type, p_list, p_source);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (p_node->outer != nullptr) {
|
if (p_node->outer != nullptr) {
|
||||||
ensure_cached_parser_for_class(p_node->outer, p_node, vformat(R"(Trying to fetch classes in the current scope: outer class of "%s")", p_node->fqcn), p_source);
|
// TODO: 'ensure_cached_external_parser_for_class()' is only necessary because 'resolve_class_inheritance()' is not getting called here.
|
||||||
|
ensure_cached_external_parser_for_class(p_node->outer, p_node, "Trying to fetch classes in the current scope", p_source);
|
||||||
get_class_node_current_scope_classes(p_node->outer, p_list, p_source);
|
get_class_node_current_scope_classes(p_node->outer, p_list, p_source);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -314,10 +316,10 @@ Error GDScriptAnalyzer::resolve_class_inheritance(GDScriptParser::ClassNode *p_c
|
||||||
p_source = p_class;
|
p_source = p_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<GDScriptParserRef> parser_ref = ensure_cached_parser_for_class(p_class, nullptr, vformat(R"(Trying to resolve class inheritance of "%s")", p_class->fqcn), p_source);
|
Ref<GDScriptParserRef> parser_ref = ensure_cached_external_parser_for_class(p_class, nullptr, "Trying to resolve class inheritance", p_source);
|
||||||
Finally finally([&]() {
|
Finally finally([&]() {
|
||||||
for (GDScriptParser::ClassNode *look_class = p_class; look_class != nullptr; look_class = look_class->base_type.class_type) {
|
for (GDScriptParser::ClassNode *look_class = p_class; look_class != nullptr; look_class = look_class->base_type.class_type) {
|
||||||
ensure_cached_parser_for_class(look_class->base_type.class_type, look_class, vformat(R"(Trying to resolve class inheritance of "%s")", p_class->fqcn), p_source);
|
ensure_cached_external_parser_for_class(look_class->base_type.class_type, look_class, "Trying to resolve class inheritance", p_source);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -888,12 +890,12 @@ void GDScriptAnalyzer::resolve_class_member(GDScriptParser::ClassNode *p_class,
|
||||||
p_source = member.get_source_node();
|
p_source = member.get_source_node();
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<GDScriptParserRef> parser_ref = ensure_cached_parser_for_class(p_class, nullptr, vformat(R"(Trying to resolve class member "%s" of "%s")", member.get_name(), p_class->fqcn), p_source);
|
Ref<GDScriptParserRef> parser_ref = ensure_cached_external_parser_for_class(p_class, nullptr, "Trying to resolve class member", p_source);
|
||||||
Finally finally([&]() {
|
Finally finally([&]() {
|
||||||
ensure_cached_parser_for_class(member.get_datatype().class_type, p_class, vformat(R"(Trying to resolve datatype of class member "%s" of "%s")", member.get_name(), p_class->fqcn), p_source);
|
ensure_cached_external_parser_for_class(member.get_datatype().class_type, p_class, "Trying to resolve datatype of class member", p_source);
|
||||||
GDScriptParser::DataType member_type = member.get_datatype();
|
GDScriptParser::DataType member_type = member.get_datatype();
|
||||||
if (member_type.has_container_element_type(0)) {
|
if (member_type.has_container_element_type(0)) {
|
||||||
ensure_cached_parser_for_class(member_type.get_container_element_type(0).class_type, p_class, vformat(R"(Trying to resolve datatype of class member "%s" of "%s")", member.get_name(), p_class->fqcn), p_source);
|
ensure_cached_external_parser_for_class(member_type.get_container_element_type(0).class_type, p_class, "Trying to resolve datatype of class member", p_source);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1181,7 +1183,7 @@ void GDScriptAnalyzer::resolve_class_interface(GDScriptParser::ClassNode *p_clas
|
||||||
p_source = p_class;
|
p_source = p_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<GDScriptParserRef> parser_ref = ensure_cached_parser_for_class(p_class, nullptr, vformat(R"(Trying to resolve class interface of "%s")", p_class->fqcn), p_source);
|
Ref<GDScriptParserRef> parser_ref = ensure_cached_external_parser_for_class(p_class, nullptr, "Trying to resolve class interface", p_source);
|
||||||
|
|
||||||
if (!p_class->resolved_interface) {
|
if (!p_class->resolved_interface) {
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
|
@ -1271,7 +1273,7 @@ void GDScriptAnalyzer::resolve_class_body(GDScriptParser::ClassNode *p_class, co
|
||||||
p_source = p_class;
|
p_source = p_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<GDScriptParserRef> parser_ref = ensure_cached_parser_for_class(p_class, nullptr, vformat(R"(Trying to resolve class body of "%s")", p_class->fqcn), p_source);
|
Ref<GDScriptParserRef> parser_ref = ensure_cached_external_parser_for_class(p_class, nullptr, "Trying to resolve class body", p_source);
|
||||||
|
|
||||||
if (p_class->resolved_body) {
|
if (p_class->resolved_body) {
|
||||||
return;
|
return;
|
||||||
|
@ -3654,19 +3656,19 @@ GDScriptParser::DataType GDScriptAnalyzer::make_global_class_meta_type(const Str
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<GDScriptParserRef> GDScriptAnalyzer::ensure_cached_parser_for_class(const GDScriptParser::ClassNode *p_class, const GDScriptParser::ClassNode *p_from_class, const String &p_context, const GDScriptParser::Node *p_source) {
|
Ref<GDScriptParserRef> GDScriptAnalyzer::ensure_cached_external_parser_for_class(const GDScriptParser::ClassNode *p_class, const GDScriptParser::ClassNode *p_from_class, const char *p_context, const GDScriptParser::Node *p_source) {
|
||||||
if (p_class == nullptr) {
|
if (p_class == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parser->has_class(p_class)) {
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (HashMap<const GDScriptParser::ClassNode *, Ref<GDScriptParserRef>>::Iterator E = external_class_parser_cache.find(p_class)) {
|
if (HashMap<const GDScriptParser::ClassNode *, Ref<GDScriptParserRef>>::Iterator E = external_class_parser_cache.find(p_class)) {
|
||||||
return E->value;
|
return E->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (parser->has_class(p_class)) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (p_from_class == nullptr) {
|
if (p_from_class == nullptr) {
|
||||||
p_from_class = parser->head;
|
p_from_class = parser->head;
|
||||||
}
|
}
|
||||||
|
@ -3676,14 +3678,14 @@ Ref<GDScriptParserRef> GDScriptAnalyzer::ensure_cached_parser_for_class(const GD
|
||||||
Ref<GDScriptParserRef> parser_ref;
|
Ref<GDScriptParserRef> parser_ref;
|
||||||
for (const GDScriptParser::ClassNode *look_class = p_from_class; look_class != nullptr; look_class = look_class->base_type.class_type) {
|
for (const GDScriptParser::ClassNode *look_class = p_from_class; look_class != nullptr; look_class = look_class->base_type.class_type) {
|
||||||
if (parser->has_class(look_class)) {
|
if (parser->has_class(look_class)) {
|
||||||
parser_ref = find_cached_parser_for_class(p_class, parser);
|
parser_ref = find_cached_external_parser_for_class(p_class, parser);
|
||||||
if (parser_ref.is_valid()) {
|
if (parser_ref.is_valid()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HashMap<const GDScriptParser::ClassNode *, Ref<GDScriptParserRef>>::Iterator E = external_class_parser_cache.find(look_class)) {
|
if (HashMap<const GDScriptParser::ClassNode *, Ref<GDScriptParserRef>>::Iterator E = external_class_parser_cache.find(look_class)) {
|
||||||
parser_ref = find_cached_parser_for_class(p_class, E->value);
|
parser_ref = find_cached_external_parser_for_class(p_class, E->value);
|
||||||
if (parser_ref.is_valid()) {
|
if (parser_ref.is_valid()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3691,7 +3693,7 @@ Ref<GDScriptParserRef> GDScriptAnalyzer::ensure_cached_parser_for_class(const GD
|
||||||
|
|
||||||
String look_class_script_path = look_class->get_datatype().script_path;
|
String look_class_script_path = look_class->get_datatype().script_path;
|
||||||
if (HashMap<String, Ref<GDScriptParserRef>>::Iterator E = parser->depended_parsers.find(look_class_script_path)) {
|
if (HashMap<String, Ref<GDScriptParserRef>>::Iterator E = parser->depended_parsers.find(look_class_script_path)) {
|
||||||
parser_ref = find_cached_parser_for_class(p_class, E->value);
|
parser_ref = find_cached_external_parser_for_class(p_class, E->value);
|
||||||
if (parser_ref.is_valid()) {
|
if (parser_ref.is_valid()) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -3699,8 +3701,8 @@ Ref<GDScriptParserRef> GDScriptAnalyzer::ensure_cached_parser_for_class(const GD
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parser_ref.is_null()) {
|
if (parser_ref.is_null()) {
|
||||||
push_error(vformat(R"(Parser bug: Could not find external parser. (%s))", p_context), p_source);
|
push_error(vformat(R"(Parser bug (please report): Could not find external parser for class "%s". (%s))", p_class->fqcn, p_context), p_source);
|
||||||
// A null parser will be inserted into the cache and this error won't spam for the same class.
|
// A null parser will be inserted into the cache, so this error won't spam for the same class.
|
||||||
// This is ok, the values of external_class_parser_cache are not assumed to be valid references.
|
// This is ok, the values of external_class_parser_cache are not assumed to be valid references.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3708,7 +3710,7 @@ Ref<GDScriptParserRef> GDScriptAnalyzer::ensure_cached_parser_for_class(const GD
|
||||||
return parser_ref;
|
return parser_ref;
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<GDScriptParserRef> GDScriptAnalyzer::find_cached_parser_for_class(const GDScriptParser::ClassNode *p_class, const Ref<GDScriptParserRef> &p_dependant_parser) {
|
Ref<GDScriptParserRef> GDScriptAnalyzer::find_cached_external_parser_for_class(const GDScriptParser::ClassNode *p_class, const Ref<GDScriptParserRef> &p_dependant_parser) {
|
||||||
if (p_dependant_parser.is_null()) {
|
if (p_dependant_parser.is_null()) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -3729,10 +3731,10 @@ Ref<GDScriptParserRef> GDScriptAnalyzer::find_cached_parser_for_class(const GDSc
|
||||||
|
|
||||||
// Silently ensure it's parsed.
|
// Silently ensure it's parsed.
|
||||||
p_dependant_parser->raise_status(GDScriptParserRef::PARSED);
|
p_dependant_parser->raise_status(GDScriptParserRef::PARSED);
|
||||||
return find_cached_parser_for_class(p_class, p_dependant_parser->get_parser());
|
return find_cached_external_parser_for_class(p_class, p_dependant_parser->get_parser());
|
||||||
}
|
}
|
||||||
|
|
||||||
Ref<GDScriptParserRef> GDScriptAnalyzer::find_cached_parser_for_class(const GDScriptParser::ClassNode *p_class, GDScriptParser *p_dependant_parser) {
|
Ref<GDScriptParserRef> GDScriptAnalyzer::find_cached_external_parser_for_class(const GDScriptParser::ClassNode *p_class, GDScriptParser *p_dependant_parser) {
|
||||||
if (p_dependant_parser == nullptr) {
|
if (p_dependant_parser == nullptr) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
@ -4474,7 +4476,11 @@ void GDScriptAnalyzer::reduce_preload(GDScriptParser::PreloadNode *p_preload) {
|
||||||
p_preload->is_constant = true;
|
p_preload->is_constant = true;
|
||||||
p_preload->reduced_value = p_preload->resource;
|
p_preload->reduced_value = p_preload->resource;
|
||||||
p_preload->set_datatype(type_from_variant(p_preload->reduced_value, p_preload));
|
p_preload->set_datatype(type_from_variant(p_preload->reduced_value, p_preload));
|
||||||
ensure_cached_parser_for_class(p_preload->get_datatype().class_type, nullptr, vformat(R"(Trying to resolve preload of "%s")", p_preload->resolved_path), p_preload);
|
|
||||||
|
// TODO: Not sure if this is necessary anymore.
|
||||||
|
// 'type_from_variant()' should call 'resolve_class_inheritance()' which would call 'ensure_cached_external_parser_for_class()'
|
||||||
|
// Better safe than sorry.
|
||||||
|
ensure_cached_external_parser_for_class(p_preload->get_datatype().class_type, nullptr, "Trying to resolve preload", p_preload);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GDScriptAnalyzer::reduce_self(GDScriptParser::SelfNode *p_self) {
|
void GDScriptAnalyzer::reduce_self(GDScriptParser::SelfNode *p_self) {
|
||||||
|
|
|
@ -145,9 +145,9 @@ class GDScriptAnalyzer {
|
||||||
void resolve_pending_lambda_bodies();
|
void resolve_pending_lambda_bodies();
|
||||||
bool class_exists(const StringName &p_class) const;
|
bool class_exists(const StringName &p_class) const;
|
||||||
void reduce_identifier_from_base_set_class(GDScriptParser::IdentifierNode *p_identifier, GDScriptParser::DataType p_identifier_datatype);
|
void reduce_identifier_from_base_set_class(GDScriptParser::IdentifierNode *p_identifier, GDScriptParser::DataType p_identifier_datatype);
|
||||||
Ref<GDScriptParserRef> ensure_cached_parser_for_class(const GDScriptParser::ClassNode *p_class, const GDScriptParser::ClassNode *p_from_class, const String &p_context, const GDScriptParser::Node *p_source);
|
Ref<GDScriptParserRef> ensure_cached_external_parser_for_class(const GDScriptParser::ClassNode *p_class, const GDScriptParser::ClassNode *p_from_class, const char *p_context, const GDScriptParser::Node *p_source);
|
||||||
Ref<GDScriptParserRef> find_cached_parser_for_class(const GDScriptParser::ClassNode *p_class, const Ref<GDScriptParserRef> &p_dependant_parser);
|
Ref<GDScriptParserRef> find_cached_external_parser_for_class(const GDScriptParser::ClassNode *p_class, const Ref<GDScriptParserRef> &p_dependant_parser);
|
||||||
Ref<GDScriptParserRef> find_cached_parser_for_class(const GDScriptParser::ClassNode *p_class, GDScriptParser *p_dependant_parser);
|
Ref<GDScriptParserRef> find_cached_external_parser_for_class(const GDScriptParser::ClassNode *p_class, GDScriptParser *p_dependant_parser);
|
||||||
Ref<GDScript> get_depended_shallow_script(const String &p_path, Error &r_error);
|
Ref<GDScript> get_depended_shallow_script(const String &p_path, Error &r_error);
|
||||||
#ifdef DEBUG_ENABLED
|
#ifdef DEBUG_ENABLED
|
||||||
void is_shadowing(GDScriptParser::IdentifierNode *p_identifier, const String &p_context, const bool p_in_local_scope);
|
void is_shadowing(GDScriptParser::IdentifierNode *p_identifier, const String &p_context, const bool p_in_local_scope);
|
||||||
|
|
|
@ -135,8 +135,10 @@ void GDScriptParserRef::clear() {
|
||||||
|
|
||||||
GDScriptParserRef::~GDScriptParserRef() {
|
GDScriptParserRef::~GDScriptParserRef() {
|
||||||
clear();
|
clear();
|
||||||
|
|
||||||
if (!abandoned) {
|
if (!abandoned) {
|
||||||
GDScriptCache::remove_parser(path);
|
MutexLock lock(GDScriptCache::singleton->mutex);
|
||||||
|
GDScriptCache::singleton->parser_map.erase(path);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue