From 4a7d49a89a381f78f19d0b989c5cb5b500f098c9 Mon Sep 17 00:00:00 2001 From: George Marques Date: Tue, 25 Jul 2023 12:42:07 -0300 Subject: GDScript: Replace ptrcalls on MethodBind to validated calls This improves the performance of typed calls to engine methods when the argument types are exact. Using validated calls delegate more of the work the core instead of doing argument unpacking in the VM. It also does not need different instructions for each return type, simplifying the code. --- modules/gdscript/gdscript_byte_codegen.cpp | 77 +++++++----------------------- 1 file changed, 18 insertions(+), 59 deletions(-) (limited to 'modules/gdscript/gdscript_byte_codegen.cpp') diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp index 8394fce9b3..25e20c0e76 100644 --- a/modules/gdscript/gdscript_byte_codegen.cpp +++ b/modules/gdscript/gdscript_byte_codegen.cpp @@ -400,7 +400,6 @@ GDScriptFunction *GDScriptByteCodeGenerator::write_end() { } function->_stack_size = RESERVED_STACK + max_locals + temporaries.size(); function->_instruction_args_size = instr_args_max; - function->_ptrcall_args_size = ptrcall_max; #ifdef DEBUG_ENABLED function->operator_names = operator_names; @@ -1225,75 +1224,35 @@ void GDScriptByteCodeGenerator::write_call_method_bind(const Address &p_target, ct.cleanup(); } -void GDScriptByteCodeGenerator::write_call_ptrcall(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector
&p_arguments) { -#define CASE_TYPE(m_type) \ - case Variant::m_type: \ - append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_PTRCALL_##m_type, 2 + p_arguments.size()); \ - break - - bool is_ptrcall = true; - - if (p_method->has_return()) { - MethodInfo info; - ClassDB::get_method_info(p_method->get_instance_class(), p_method->get_name(), &info); - switch (info.return_val.type) { - CASE_TYPE(BOOL); - CASE_TYPE(INT); - CASE_TYPE(FLOAT); - CASE_TYPE(STRING); - CASE_TYPE(VECTOR2); - CASE_TYPE(VECTOR2I); - CASE_TYPE(RECT2); - CASE_TYPE(RECT2I); - CASE_TYPE(VECTOR3); - CASE_TYPE(VECTOR3I); - CASE_TYPE(TRANSFORM2D); - CASE_TYPE(PLANE); - CASE_TYPE(AABB); - CASE_TYPE(BASIS); - CASE_TYPE(TRANSFORM3D); - CASE_TYPE(COLOR); - CASE_TYPE(STRING_NAME); - CASE_TYPE(NODE_PATH); - CASE_TYPE(RID); - CASE_TYPE(QUATERNION); - CASE_TYPE(OBJECT); - CASE_TYPE(CALLABLE); - CASE_TYPE(SIGNAL); - CASE_TYPE(DICTIONARY); - CASE_TYPE(ARRAY); - CASE_TYPE(PACKED_BYTE_ARRAY); - CASE_TYPE(PACKED_INT32_ARRAY); - CASE_TYPE(PACKED_INT64_ARRAY); - CASE_TYPE(PACKED_FLOAT32_ARRAY); - CASE_TYPE(PACKED_FLOAT64_ARRAY); - CASE_TYPE(PACKED_STRING_ARRAY); - CASE_TYPE(PACKED_VECTOR2_ARRAY); - CASE_TYPE(PACKED_VECTOR3_ARRAY); - CASE_TYPE(PACKED_COLOR_ARRAY); - default: - append_opcode_and_argcount(p_target.mode == Address::NIL ? GDScriptFunction::OPCODE_CALL_METHOD_BIND : GDScriptFunction::OPCODE_CALL_METHOD_BIND_RET, 2 + p_arguments.size()); - is_ptrcall = false; - break; +void GDScriptByteCodeGenerator::write_call_method_bind_validated(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector
&p_arguments) { + Variant::Type return_type = Variant::NIL; + bool has_return = p_method->has_return(); + + if (has_return) { + PropertyInfo return_info = p_method->get_return_info(); + return_type = return_info.type; + } + + CallTarget ct = get_call_target(p_target, return_type); + + if (has_return) { + Variant::Type temp_type = temporaries[ct.target.address].type; + if (temp_type != return_type) { + write_type_adjust(ct.target, return_type); } - } else { - append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_PTRCALL_NO_RETURN, 2 + p_arguments.size()); } + GDScriptFunction::Opcode code = p_method->has_return() ? GDScriptFunction::OPCODE_CALL_METHOD_BIND_VALIDATED_RETURN : GDScriptFunction::OPCODE_CALL_METHOD_BIND_VALIDATED_NO_RETURN; + append_opcode_and_argcount(code, 2 + p_arguments.size()); + for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } append(p_base); - CallTarget ct = get_call_target(p_target); append(ct.target); append(p_arguments.size()); append(p_method); ct.cleanup(); - if (is_ptrcall) { - alloc_ptrcall(p_arguments.size()); - } - -#undef CASE_TYPE } void GDScriptByteCodeGenerator::write_call_self(const Address &p_target, const StringName &p_function_name, const Vector
&p_arguments) { -- cgit v1.2.3