1
0
mirror of https://github.com/godotengine/godot.git synced 2025-12-05 17:15:09 +00:00

Add ValidatedCall to MethodBind

* This should optimize GDScript function calling _enormously_.
* It also should simplify the GDScript VM considerably.

NOTE: GDExtension calling performance has most likely been affected until going via ptrcall is fixed.
This commit is contained in:
Juan Linietsky
2023-04-25 00:21:32 +02:00
parent 14c582bca8
commit 1c93606e47
31 changed files with 299 additions and 84 deletions

View File

@@ -146,9 +146,11 @@ String GDExtension::find_extension_library(const String &p_path, Ref<ConfigFile>
class GDExtensionMethodBind : public MethodBind {
GDExtensionClassMethodCall call_func;
GDExtensionClassMethodValidatedCall validated_call_func;
GDExtensionClassMethodPtrCall ptrcall_func;
void *method_userdata;
bool vararg;
uint32_t argument_count;
PropertyInfo return_value_info;
GodotTypeInfo::Metadata return_value_metadata;
List<PropertyInfo> arguments_info;
@@ -191,6 +193,40 @@ public:
r_error.expected = ce.expected;
return ret;
}
virtual void validated_call(Object *p_object, const Variant **p_args, Variant *r_ret) const override {
ERR_FAIL_COND_MSG(vararg, "Validated methods don't have ptrcall support. This is most likely an engine bug.");
GDExtensionClassInstancePtr extension_instance = is_static() ? nullptr : p_object->_get_extension_instance();
if (validated_call_func) {
// This is added here, but it's unlikely to be provided by most extensions.
validated_call_func(method_userdata, extension_instance, reinterpret_cast<GDExtensionConstVariantPtr *>(p_args), (GDExtensionVariantPtr)r_ret);
} else {
#if 1
// Slow code-path, but works for the time being.
Callable::CallError ce;
call(p_object, p_args, argument_count, ce);
#else
// This is broken, because it needs more information to do the calling properly
// If not provided, go via ptrcall, which is faster than resorting to regular call.
const void **argptrs = (const void **)alloca(argument_count * sizeof(void *));
for (uint32_t i = 0; i < argument_count; i++) {
argptrs[i] = VariantInternal::get_opaque_pointer(p_args[i]);
}
bool returns = true;
void *ret_opaque;
if (returns) {
ret_opaque = VariantInternal::get_opaque_pointer(r_ret);
} else {
ret_opaque = nullptr; // May be unnecessary as this is ignored, but just in case.
}
ptrcall(p_object, argptrs, ret_opaque);
#endif
}
}
virtual void ptrcall(Object *p_object, const void **p_args, void *r_ret) const override {
ERR_FAIL_COND_MSG(vararg, "Vararg methods don't have ptrcall support. This is most likely an engine bug.");
GDExtensionClassInstancePtr extension_instance = p_object->_get_extension_instance();
@@ -204,6 +240,7 @@ public:
explicit GDExtensionMethodBind(const GDExtensionClassMethodInfo *p_method_info) {
method_userdata = p_method_info->method_userdata;
call_func = p_method_info->call_func;
validated_call_func = nullptr;
ptrcall_func = p_method_info->ptrcall_func;
set_name(*reinterpret_cast<StringName *>(p_method_info->name));
@@ -218,7 +255,7 @@ public:
}
set_hint_flags(p_method_info->method_flags);
argument_count = p_method_info->argument_count;
vararg = p_method_info->method_flags & GDEXTENSION_METHOD_FLAG_VARARG;
_set_returns(p_method_info->has_return_value);
_set_const(p_method_info->method_flags & GDEXTENSION_METHOD_FLAG_CONST);