summaryrefslogtreecommitdiffstats
path: root/modules/gdscript/gdscript_vm.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript/gdscript_vm.cpp')
-rw-r--r--modules/gdscript/gdscript_vm.cpp159
1 files changed, 88 insertions, 71 deletions
diff --git a/modules/gdscript/gdscript_vm.cpp b/modules/gdscript/gdscript_vm.cpp
index d31411b26b..7b03ac74d6 100644
--- a/modules/gdscript/gdscript_vm.cpp
+++ b/modules/gdscript/gdscript_vm.cpp
@@ -36,6 +36,18 @@
#include "core/os/os.h"
#ifdef DEBUG_ENABLED
+
+static bool _profile_count_as_native(const Object *p_base_obj, const StringName &p_methodname) {
+ if (!p_base_obj) {
+ return false;
+ }
+ StringName cname = p_base_obj->get_class_name();
+ if ((p_methodname == "new" && cname == "GDScript") || p_methodname == "call") {
+ return false;
+ }
+ return ClassDB::class_exists(cname) && ClassDB::has_method(cname, p_methodname, false);
+}
+
static String _get_element_type(Variant::Type builtin_type, const StringName &native_type, const Ref<Script> &script_type) {
if (script_type.is_valid() && script_type->is_valid()) {
return GDScript::debug_get_script_name(script_type);
@@ -84,6 +96,18 @@ static String _get_var_type(const Variant *p_var) {
return basestr;
}
+
+void GDScriptFunction::_profile_native_call(uint64_t p_t_taken, const String &p_func_name, const String &p_instance_class_name) {
+ HashMap<String, Profile::NativeProfile>::Iterator inner_prof = profile.native_calls.find(p_func_name);
+ if (inner_prof) {
+ inner_prof->value.call_count += 1;
+ } else {
+ String sig = vformat("%s::0::%s%s%s", get_script()->get_script_path(), p_instance_class_name, p_instance_class_name.is_empty() ? "" : ".", p_func_name);
+ inner_prof = profile.native_calls.insert(p_func_name, Profile::NativeProfile{ 1, 0, sig });
+ }
+ inner_prof->value.total_time += p_t_taken;
+}
+
#endif // DEBUG_ENABLED
Variant GDScriptFunction::_get_default_variant_for_data_type(const GDScriptDataType &p_data_type) {
@@ -91,8 +115,8 @@ Variant GDScriptFunction::_get_default_variant_for_data_type(const GDScriptDataT
if (p_data_type.builtin_type == Variant::ARRAY) {
Array array;
// Typed array.
- if (p_data_type.has_container_element_type()) {
- const GDScriptDataType &element_type = p_data_type.get_container_element_type();
+ if (p_data_type.has_container_element_type(0)) {
+ const GDScriptDataType &element_type = p_data_type.get_container_element_type(0);
array.set_typed(element_type.builtin_type, element_type.native_type, element_type.script_type);
}
@@ -631,9 +655,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
bool exit_ok = false;
bool awaited = false;
-#endif
-
-#ifdef DEBUG_ENABLED
int variant_address_limits[ADDR_TYPE_MAX] = { _stack_size, _constant_count, p_instance ? p_instance->members.size() : 0 };
#endif
@@ -852,8 +873,12 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
GET_VARIANT_PTR(value, 2);
bool valid;
+#ifdef DEBUG_ENABLED
+ Variant::VariantSetError err_code;
+ dst->set(*index, *value, &valid, &err_code);
+#else
dst->set(*index, *value, &valid);
-
+#endif
#ifdef DEBUG_ENABLED
if (!valid) {
Object *obj = dst->get_validated_object();
@@ -870,7 +895,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
} else {
v = "of type '" + _get_var_type(index) + "'";
}
- err_text = "Invalid set index " + v + " (on base: '" + _get_var_type(dst) + "') with value of type '" + _get_var_type(value) + "'";
+ err_text = "Invalid assignment of property or key " + v + " with value of type '" + _get_var_type(value) + "' on a base object of type '" + _get_var_type(dst) + "'.";
+ if (err_code == Variant::VariantSetError::SET_INDEXED_ERR) {
+ err_text = "Invalid assignment of index " + v + " (on base: '" + _get_var_type(dst) + "') with value of type '" + _get_var_type(value) + "'.";
+ }
}
OPCODE_BREAK;
}
@@ -901,7 +929,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
} else {
v = "of type '" + _get_var_type(index) + "'";
}
- err_text = "Invalid set index " + v + " (on base: '" + _get_var_type(dst) + "') with value of type '" + _get_var_type(value) + "'";
+ err_text = "Invalid assignment of property or key " + v + " with value of type '" + _get_var_type(value) + "' on a base object of type '" + _get_var_type(dst) + "'.";
OPCODE_BREAK;
}
#endif
@@ -951,7 +979,8 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
bool valid;
#ifdef DEBUG_ENABLED
// Allow better error message in cases where src and dst are the same stack position.
- Variant ret = src->get(*index, &valid);
+ Variant::VariantGetError err_code;
+ Variant ret = src->get(*index, &valid, &err_code);
#else
*dst = src->get(*index, &valid);
@@ -964,7 +993,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
} else {
v = "of type '" + _get_var_type(index) + "'";
}
- err_text = "Invalid get index " + v + " (on base: '" + _get_var_type(src) + "').";
+ err_text = "Invalid access to property or key " + v + " on a base object of type '" + _get_var_type(src) + "'.";
+ if (err_code == Variant::VariantGetError::GET_INDEXED_ERR) {
+ err_text = "Invalid access of index " + v + " on a base object of type: '" + _get_var_type(src) + "'.";
+ }
OPCODE_BREAK;
}
*dst = ret;
@@ -1000,7 +1032,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
} else {
v = "of type '" + _get_var_type(key) + "'";
}
- err_text = "Invalid get index " + v + " (on base: '" + _get_var_type(src) + "').";
+ err_text = "Invalid access to property or key " + v + " on a base object of type '" + _get_var_type(src) + "'.";
OPCODE_BREAK;
}
*dst = ret;
@@ -1065,7 +1097,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
if (read_only_property) {
err_text = vformat(R"(Cannot set value into property "%s" (on base "%s") because it is read-only.)", String(*index), _get_var_type(dst));
} else {
- err_text = "Invalid set index '" + String(*index) + "' (on base: '" + _get_var_type(dst) + "') with value of type '" + _get_var_type(value) + "'.";
+ err_text = "Invalid assignment of property or key '" + String(*index) + "' with value of type '" + _get_var_type(value) + "' on a base object of type '" + _get_var_type(dst) + "'.";
}
OPCODE_BREAK;
}
@@ -1110,7 +1142,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#endif
#ifdef DEBUG_ENABLED
if (!valid) {
- err_text = "Invalid get index '" + index->operator String() + "' (on base: '" + _get_var_type(src) + "').";
+ err_text = "Invalid access to property or key '" + index->operator String() + "' on a base object of type '" + _get_var_type(src) + "'.";
OPCODE_BREAK;
}
*dst = ret;
@@ -1661,16 +1693,14 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
if (GDScriptLanguage::get_singleton()->profiling) {
call_time = OS::get_singleton()->get_ticks_usec();
}
-
+ Variant::Type base_type = base->get_type();
+ Object *base_obj = base->get_validated_object();
+ StringName base_class = base_obj ? base_obj->get_class_name() : StringName();
#endif
+
Callable::CallError err;
if (call_ret) {
GET_INSTRUCTION_ARG(ret, argc + 1);
-#ifdef DEBUG_ENABLED
- Variant::Type base_type = base->get_type();
- Object *base_obj = base->get_validated_object();
- StringName base_class = base_obj ? base_obj->get_class_name() : StringName();
-#endif
base->callp(*methodname, (const Variant **)argptrs, argc, *ret, err);
#ifdef DEBUG_ENABLED
if (ret->get_type() == Variant::NIL) {
@@ -1704,8 +1734,13 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
base->callp(*methodname, (const Variant **)argptrs, argc, ret, err);
}
#ifdef DEBUG_ENABLED
+
if (GDScriptLanguage::get_singleton()->profiling) {
- function_call_time += OS::get_singleton()->get_ticks_usec() - call_time;
+ uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
+ if (GDScriptLanguage::get_singleton()->profile_native_calls && _profile_count_as_native(base_obj, *methodname)) {
+ _profile_native_call(t_taken, *methodname, base_class);
+ }
+ function_call_time += t_taken;
}
if (err.error != Callable::CallError::CALL_OK) {
@@ -1782,8 +1817,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#ifdef DEBUG_ENABLED
uint64_t call_time = 0;
-
- if (GDScriptLanguage::get_singleton()->profiling) {
+ if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
call_time = OS::get_singleton()->get_ticks_usec();
}
#endif
@@ -1797,8 +1831,11 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
}
#ifdef DEBUG_ENABLED
- if (GDScriptLanguage::get_singleton()->profiling) {
- function_call_time += OS::get_singleton()->get_ticks_usec() - call_time;
+
+ if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
+ uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
+ _profile_native_call(t_taken, method->get_name(), method->get_instance_class());
+ function_call_time += t_taken;
}
if (err.error != Callable::CallError::CALL_OK) {
@@ -1851,22 +1888,10 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
const Variant **argptrs = const_cast<const Variant **>(instruction_args);
-#ifdef DEBUG_ENABLED
- uint64_t call_time = 0;
-
- if (GDScriptLanguage::get_singleton()->profiling) {
- call_time = OS::get_singleton()->get_ticks_usec();
- }
-#endif
-
Callable::CallError err;
Variant::call_static(builtin_type, *methodname, argptrs, argc, *ret, err);
#ifdef DEBUG_ENABLED
- if (GDScriptLanguage::get_singleton()->profiling) {
- function_call_time += OS::get_singleton()->get_ticks_usec() - call_time;
- }
-
if (err.error != Callable::CallError::CALL_OK) {
err_text = _get_call_error(err, "static function '" + methodname->operator String() + "' in type '" + Variant::get_type_name(builtin_type) + "'", argptrs);
OPCODE_BREAK;
@@ -1895,8 +1920,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#ifdef DEBUG_ENABLED
uint64_t call_time = 0;
-
- if (GDScriptLanguage::get_singleton()->profiling) {
+ if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
call_time = OS::get_singleton()->get_ticks_usec();
}
#endif
@@ -1905,15 +1929,17 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
*ret = method->call(nullptr, argptrs, argc, err);
#ifdef DEBUG_ENABLED
- if (GDScriptLanguage::get_singleton()->profiling) {
- function_call_time += OS::get_singleton()->get_ticks_usec() - call_time;
+ if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
+ uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
+ _profile_native_call(t_taken, method->get_name(), method->get_instance_class());
+ function_call_time += t_taken;
}
+#endif
if (err.error != Callable::CallError::CALL_OK) {
err_text = _get_call_error(err, "static function '" + method->get_name().operator String() + "' in type '" + method->get_instance_class().operator String() + "'", argptrs);
OPCODE_BREAK;
}
-#endif
ip += 3;
}
@@ -1951,8 +1977,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#ifdef DEBUG_ENABLED
uint64_t call_time = 0;
-
- if (GDScriptLanguage::get_singleton()->profiling) {
+ if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
call_time = OS::get_singleton()->get_ticks_usec();
}
#endif
@@ -1961,10 +1986,13 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
method->validated_call(base_obj, (const Variant **)argptrs, ret);
#ifdef DEBUG_ENABLED
- if (GDScriptLanguage::get_singleton()->profiling) {
- function_call_time += OS::get_singleton()->get_ticks_usec() - call_time;
+ if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
+ uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
+ _profile_native_call(t_taken, method->get_name(), method->get_instance_class());
+ function_call_time += t_taken;
}
#endif
+
ip += 3;
}
DISPATCH_OPCODE;
@@ -1998,8 +2026,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
Variant **argptrs = instruction_args;
#ifdef DEBUG_ENABLED
uint64_t call_time = 0;
-
- if (GDScriptLanguage::get_singleton()->profiling) {
+ if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
call_time = OS::get_singleton()->get_ticks_usec();
}
#endif
@@ -2009,10 +2036,13 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
method->validated_call(base_obj, (const Variant **)argptrs, nullptr);
#ifdef DEBUG_ENABLED
- if (GDScriptLanguage::get_singleton()->profiling) {
- function_call_time += OS::get_singleton()->get_ticks_usec() - call_time;
+ if (GDScriptLanguage::get_singleton()->profiling && GDScriptLanguage::get_singleton()->profile_native_calls) {
+ uint64_t t_taken = OS::get_singleton()->get_ticks_usec() - call_time;
+ _profile_native_call(t_taken, method->get_name(), method->get_instance_class());
+ function_call_time += t_taken;
}
#endif
+
ip += 3;
}
DISPATCH_OPCODE;
@@ -2033,22 +2063,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
Variant::ValidatedBuiltInMethod method = _builtin_methods_ptr[_code_ptr[ip + 2]];
Variant **argptrs = instruction_args;
-#ifdef DEBUG_ENABLED
- uint64_t call_time = 0;
- if (GDScriptLanguage::get_singleton()->profiling) {
- call_time = OS::get_singleton()->get_ticks_usec();
- }
-#endif
-
GET_INSTRUCTION_ARG(ret, argc + 1);
method(base, (const Variant **)argptrs, argc, ret);
-#ifdef DEBUG_ENABLED
- if (GDScriptLanguage::get_singleton()->profiling) {
- function_call_time += OS::get_singleton()->get_ticks_usec() - call_time;
- }
-#endif
-
ip += 3;
}
DISPATCH_OPCODE;
@@ -2467,7 +2484,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
Variant::construct(ret_type, retvalue, const_cast<const Variant **>(&r), 1, ce);
} else {
#ifdef DEBUG_ENABLED
- err_text = vformat(R"(Trying to return value of type "%s" from a function which the return type is "%s".)",
+ err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)",
Variant::get_type_name(r->get_type()), Variant::get_type_name(ret_type));
#endif // DEBUG_ENABLED
@@ -2497,9 +2514,9 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
if (r->get_type() != Variant::ARRAY) {
#ifdef DEBUG_ENABLED
- err_text = vformat(R"(Trying to return a value of type "%s" where expected return type is "Array[%s]".)",
- _get_var_type(r), _get_element_type(builtin_type, native_type, *script_type));
-#endif // DEBUG_ENABLED
+ err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "Array[%s]".)",
+ Variant::get_type_name(r->get_type()), Variant::get_type_name(builtin_type));
+#endif
OPCODE_BREAK;
}
@@ -2530,7 +2547,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
GD_ERR_BREAK(!nc);
if (r->get_type() != Variant::OBJECT && r->get_type() != Variant::NIL) {
- err_text = vformat(R"(Trying to return value of type "%s" from a function which the return type is "%s".)",
+ err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)",
Variant::get_type_name(r->get_type()), nc->get_name());
OPCODE_BREAK;
}
@@ -2548,7 +2565,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
#endif // DEBUG_ENABLED
if (ret_obj && !ClassDB::is_parent_class(ret_obj->get_class_name(), nc->get_name())) {
#ifdef DEBUG_ENABLED
- err_text = vformat(R"(Trying to return value of type "%s" from a function which the return type is "%s".)",
+ err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)",
ret_obj->get_class_name(), nc->get_name());
#endif // DEBUG_ENABLED
OPCODE_BREAK;
@@ -2571,7 +2588,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
if (r->get_type() != Variant::OBJECT && r->get_type() != Variant::NIL) {
#ifdef DEBUG_ENABLED
- err_text = vformat(R"(Trying to return value of type "%s" from a function which the return type is "%s".)",
+ err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)",
Variant::get_type_name(r->get_type()), GDScript::debug_get_script_name(Ref<Script>(base_type)));
#endif // DEBUG_ENABLED
OPCODE_BREAK;
@@ -2593,7 +2610,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
ScriptInstance *ret_inst = ret_obj->get_script_instance();
if (!ret_inst) {
#ifdef DEBUG_ENABLED
- err_text = vformat(R"(Trying to return value of type "%s" from a function which the return type is "%s".)",
+ err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)",
ret_obj->get_class_name(), GDScript::debug_get_script_name(Ref<GDScript>(base_type)));
#endif // DEBUG_ENABLED
OPCODE_BREAK;
@@ -2612,7 +2629,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
if (!valid) {
#ifdef DEBUG_ENABLED
- err_text = vformat(R"(Trying to return value of type "%s" from a function which the return type is "%s".)",
+ err_text = vformat(R"(Trying to return value of type "%s" from a function whose return type is "%s".)",
GDScript::debug_get_script_name(ret_obj->get_script_instance()->get_script()), GDScript::debug_get_script_name(Ref<GDScript>(base_type)));
#endif // DEBUG_ENABLED
OPCODE_BREAK;