Explorar o código

Merge pull request #79893 from vnen/gdscript-validated-method-bind-call

GDScript: Replace ptrcalls on MethodBind to validated calls
Rémi Verschelde hai 1 ano
pai
achega
2f919f0fd0

+ 18 - 59
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<Address> &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<Address> &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<Address> &p_arguments) {

+ 1 - 8
modules/gdscript/gdscript_byte_codegen.h

@@ -97,7 +97,6 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
 	int max_locals = 0;
 	int current_line = 0;
 	int instr_args_max = 0;
-	int ptrcall_max = 0;
 
 #ifdef DEBUG_ENABLED
 	List<int> temp_stack;
@@ -346,12 +345,6 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
 		return pos;
 	}
 
-	void alloc_ptrcall(int p_params) {
-		if (p_params >= ptrcall_max) {
-			ptrcall_max = p_params;
-		}
-	}
-
 	CallTarget get_call_target(const Address &p_target, Variant::Type p_type = Variant::NIL);
 
 	int address_of(const Address &p_address) {
@@ -519,7 +512,7 @@ public:
 	virtual void write_call_builtin_type_static(const Address &p_target, Variant::Type p_type, const StringName &p_method, const Vector<Address> &p_arguments) override;
 	virtual void write_call_native_static(const Address &p_target, const StringName &p_class, const StringName &p_method, const Vector<Address> &p_arguments) override;
 	virtual void write_call_method_bind(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) override;
-	virtual void write_call_ptrcall(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) override;
+	virtual void write_call_method_bind_validated(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) override;
 	virtual void write_call_self(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) override;
 	virtual void write_call_self_async(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) override;
 	virtual void write_call_script_function(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) override;

+ 1 - 1
modules/gdscript/gdscript_codegen.h

@@ -129,7 +129,7 @@ public:
 	virtual void write_call_builtin_type_static(const Address &p_target, Variant::Type p_type, const StringName &p_method, const Vector<Address> &p_arguments) = 0;
 	virtual void write_call_native_static(const Address &p_target, const StringName &p_class, const StringName &p_method, const Vector<Address> &p_arguments) = 0;
 	virtual void write_call_method_bind(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) = 0;
-	virtual void write_call_ptrcall(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) = 0;
+	virtual void write_call_method_bind_validated(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) = 0;
 	virtual void write_call_self(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0;
 	virtual void write_call_self_async(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0;
 	virtual void write_call_script_function(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0;

+ 10 - 10
modules/gdscript/gdscript_compiler.cpp

@@ -229,13 +229,13 @@ static bool _is_exact_type(const PropertyInfo &p_par_type, const GDScriptDataTyp
 	}
 }
 
-static bool _can_use_ptrcall(const MethodBind *p_method, const Vector<GDScriptCodeGenerator::Address> &p_arguments) {
+static bool _can_use_validate_call(const MethodBind *p_method, const Vector<GDScriptCodeGenerator::Address> &p_arguments) {
 	if (p_method->is_vararg()) {
-		// ptrcall won't work with vararg methods.
+		// Validated call won't work with vararg methods.
 		return false;
 	}
 	if (p_method->get_argument_count() != p_arguments.size()) {
-		// ptrcall won't work with default arguments.
+		// Validated call won't work with default arguments.
 		return false;
 	}
 	MethodInfo info;
@@ -636,9 +636,9 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
 							self.mode = GDScriptCodeGenerator::Address::SELF;
 							MethodBind *method = ClassDB::get_method(codegen.script->native->get_name(), call->function_name);
 
-							if (_can_use_ptrcall(method, arguments)) {
-								// Exact arguments, use ptrcall.
-								gen->write_call_ptrcall(result, self, method, arguments);
+							if (_can_use_validate_call(method, arguments)) {
+								// Exact arguments, use validated call.
+								gen->write_call_method_bind_validated(result, self, method, arguments);
 							} else {
 								// Not exact arguments, but still can use method bind call.
 								gen->write_call_method_bind(result, self, method, arguments);
@@ -686,9 +686,9 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
 									}
 									if (ClassDB::class_exists(class_name) && ClassDB::has_method(class_name, call->function_name)) {
 										MethodBind *method = ClassDB::get_method(class_name, call->function_name);
-										if (_can_use_ptrcall(method, arguments)) {
-											// Exact arguments, use ptrcall.
-											gen->write_call_ptrcall(result, base, method, arguments);
+										if (_can_use_validate_call(method, arguments)) {
+											// Exact arguments, use validated call.
+											gen->write_call_method_bind_validated(result, base, method, arguments);
 										} else {
 											// Not exact arguments, but still can use method bind call.
 											gen->write_call_method_bind(result, base, method, arguments);
@@ -733,7 +733,7 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
 			GDScriptCodeGenerator::Address result = codegen.add_temporary(_gdtype_from_datatype(get_node->get_datatype(), codegen.script));
 
 			MethodBind *get_node_method = ClassDB::get_method("Node", "get_node");
-			gen->write_call_ptrcall(result, GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::SELF), get_node_method, args);
+			gen->write_call_method_bind_validated(result, GDScriptCodeGenerator::Address(GDScriptCodeGenerator::Address::SELF), get_node_method, args);
 
 			return result;
 		} break;

+ 21 - 61
modules/gdscript/gdscript_disassembler.cpp

@@ -670,10 +670,29 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
 
 				incr += 4 + argc;
 			} break;
-			case OPCODE_CALL_PTRCALL_NO_RETURN: {
+
+			case OPCODE_CALL_METHOD_BIND_VALIDATED_RETURN: {
 				int instr_var_args = _code_ptr[++ip];
+				text += "call method-bind validated (return) ";
+				MethodBind *method = _methods_ptr[_code_ptr[ip + 2 + instr_var_args]];
+				int argc = _code_ptr[ip + 1 + instr_var_args];
+				text += DADDR(2 + argc) + " = ";
+				text += DADDR(1 + argc) + ".";
+				text += method->get_name();
+				text += "(";
+				for (int i = 0; i < argc; i++) {
+					if (i > 0)
+						text += ", ";
+					text += DADDR(1 + i);
+				}
+				text += ")";
+				incr = 5 + argc;
+			} break;
 
-				text += "call-ptrcall (no return) ";
+			case OPCODE_CALL_METHOD_BIND_VALIDATED_NO_RETURN: {
+				int instr_var_args = _code_ptr[++ip];
+
+				text += "call method-bind validated (no return) ";
 
 				MethodBind *method = _methods_ptr[_code_ptr[ip + 2 + instr_var_args]];
 
@@ -694,65 +713,6 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
 				incr = 5 + argc;
 			} break;
 
-#define DISASSEMBLE_PTRCALL(m_type)                                            \
-	case OPCODE_CALL_PTRCALL_##m_type: {                                       \
-		int instr_var_args = _code_ptr[++ip];                                  \
-		text += "call-ptrcall (return ";                                       \
-		text += #m_type;                                                       \
-		text += ") ";                                                          \
-		MethodBind *method = _methods_ptr[_code_ptr[ip + 2 + instr_var_args]]; \
-		int argc = _code_ptr[ip + 1 + instr_var_args];                         \
-		text += DADDR(2 + argc) + " = ";                                       \
-		text += DADDR(1 + argc) + ".";                                         \
-		text += method->get_name();                                            \
-		text += "(";                                                           \
-		for (int i = 0; i < argc; i++) {                                       \
-			if (i > 0)                                                         \
-				text += ", ";                                                  \
-			text += DADDR(1 + i);                                              \
-		}                                                                      \
-		text += ")";                                                           \
-		incr = 5 + argc;                                                       \
-	} break
-
-				DISASSEMBLE_PTRCALL(BOOL);
-				DISASSEMBLE_PTRCALL(INT);
-				DISASSEMBLE_PTRCALL(FLOAT);
-				DISASSEMBLE_PTRCALL(STRING);
-				DISASSEMBLE_PTRCALL(VECTOR2);
-				DISASSEMBLE_PTRCALL(VECTOR2I);
-				DISASSEMBLE_PTRCALL(RECT2);
-				DISASSEMBLE_PTRCALL(RECT2I);
-				DISASSEMBLE_PTRCALL(VECTOR3);
-				DISASSEMBLE_PTRCALL(VECTOR3I);
-				DISASSEMBLE_PTRCALL(TRANSFORM2D);
-				DISASSEMBLE_PTRCALL(VECTOR4);
-				DISASSEMBLE_PTRCALL(VECTOR4I);
-				DISASSEMBLE_PTRCALL(PLANE);
-				DISASSEMBLE_PTRCALL(AABB);
-				DISASSEMBLE_PTRCALL(BASIS);
-				DISASSEMBLE_PTRCALL(TRANSFORM3D);
-				DISASSEMBLE_PTRCALL(PROJECTION);
-				DISASSEMBLE_PTRCALL(COLOR);
-				DISASSEMBLE_PTRCALL(STRING_NAME);
-				DISASSEMBLE_PTRCALL(NODE_PATH);
-				DISASSEMBLE_PTRCALL(RID);
-				DISASSEMBLE_PTRCALL(QUATERNION);
-				DISASSEMBLE_PTRCALL(OBJECT);
-				DISASSEMBLE_PTRCALL(CALLABLE);
-				DISASSEMBLE_PTRCALL(SIGNAL);
-				DISASSEMBLE_PTRCALL(DICTIONARY);
-				DISASSEMBLE_PTRCALL(ARRAY);
-				DISASSEMBLE_PTRCALL(PACKED_BYTE_ARRAY);
-				DISASSEMBLE_PTRCALL(PACKED_INT32_ARRAY);
-				DISASSEMBLE_PTRCALL(PACKED_INT64_ARRAY);
-				DISASSEMBLE_PTRCALL(PACKED_FLOAT32_ARRAY);
-				DISASSEMBLE_PTRCALL(PACKED_FLOAT64_ARRAY);
-				DISASSEMBLE_PTRCALL(PACKED_STRING_ARRAY);
-				DISASSEMBLE_PTRCALL(PACKED_VECTOR2_ARRAY);
-				DISASSEMBLE_PTRCALL(PACKED_VECTOR3_ARRAY);
-				DISASSEMBLE_PTRCALL(PACKED_COLOR_ARRAY);
-
 			case OPCODE_CALL_BUILTIN_TYPE_VALIDATED: {
 				int instr_var_args = _code_ptr[++ip];
 				int argc = _code_ptr[ip + 1 + instr_var_args];

+ 2 - 40
modules/gdscript/gdscript_function.h

@@ -241,45 +241,8 @@ public:
 		OPCODE_CALL_METHOD_BIND_RET,
 		OPCODE_CALL_BUILTIN_STATIC,
 		OPCODE_CALL_NATIVE_STATIC,
-		// ptrcall have one instruction per return type.
-		OPCODE_CALL_PTRCALL_NO_RETURN,
-		OPCODE_CALL_PTRCALL_BOOL,
-		OPCODE_CALL_PTRCALL_INT,
-		OPCODE_CALL_PTRCALL_FLOAT,
-		OPCODE_CALL_PTRCALL_STRING,
-		OPCODE_CALL_PTRCALL_VECTOR2,
-		OPCODE_CALL_PTRCALL_VECTOR2I,
-		OPCODE_CALL_PTRCALL_RECT2,
-		OPCODE_CALL_PTRCALL_RECT2I,
-		OPCODE_CALL_PTRCALL_VECTOR3,
-		OPCODE_CALL_PTRCALL_VECTOR3I,
-		OPCODE_CALL_PTRCALL_TRANSFORM2D,
-		OPCODE_CALL_PTRCALL_VECTOR4,
-		OPCODE_CALL_PTRCALL_VECTOR4I,
-		OPCODE_CALL_PTRCALL_PLANE,
-		OPCODE_CALL_PTRCALL_QUATERNION,
-		OPCODE_CALL_PTRCALL_AABB,
-		OPCODE_CALL_PTRCALL_BASIS,
-		OPCODE_CALL_PTRCALL_TRANSFORM3D,
-		OPCODE_CALL_PTRCALL_PROJECTION,
-		OPCODE_CALL_PTRCALL_COLOR,
-		OPCODE_CALL_PTRCALL_STRING_NAME,
-		OPCODE_CALL_PTRCALL_NODE_PATH,
-		OPCODE_CALL_PTRCALL_RID,
-		OPCODE_CALL_PTRCALL_OBJECT,
-		OPCODE_CALL_PTRCALL_CALLABLE,
-		OPCODE_CALL_PTRCALL_SIGNAL,
-		OPCODE_CALL_PTRCALL_DICTIONARY,
-		OPCODE_CALL_PTRCALL_ARRAY,
-		OPCODE_CALL_PTRCALL_PACKED_BYTE_ARRAY,
-		OPCODE_CALL_PTRCALL_PACKED_INT32_ARRAY,
-		OPCODE_CALL_PTRCALL_PACKED_INT64_ARRAY,
-		OPCODE_CALL_PTRCALL_PACKED_FLOAT32_ARRAY,
-		OPCODE_CALL_PTRCALL_PACKED_FLOAT64_ARRAY,
-		OPCODE_CALL_PTRCALL_PACKED_STRING_ARRAY,
-		OPCODE_CALL_PTRCALL_PACKED_VECTOR2_ARRAY,
-		OPCODE_CALL_PTRCALL_PACKED_VECTOR3_ARRAY,
-		OPCODE_CALL_PTRCALL_PACKED_COLOR_ARRAY,
+		OPCODE_CALL_METHOD_BIND_VALIDATED_RETURN,
+		OPCODE_CALL_METHOD_BIND_VALIDATED_NO_RETURN,
 		OPCODE_AWAIT,
 		OPCODE_AWAIT_RESUME,
 		OPCODE_CREATE_LAMBDA,
@@ -425,7 +388,6 @@ private:
 	int _argument_count = 0;
 	int _stack_size = 0;
 	int _instruction_args_size = 0;
-	int _ptrcall_args_size = 0;
 
 	SelfList<GDScriptFunction> function_list{ this };
 	mutable Variant nil;

+ 157 - 315
modules/gdscript/gdscript_vm.cpp

@@ -187,191 +187,155 @@ void (*type_init_function_table[])(Variant *) = {
 };
 
 #if defined(__GNUC__)
-#define OPCODES_TABLE                                \
-	static const void *switch_table_ops[] = {        \
-		&&OPCODE_OPERATOR,                           \
-		&&OPCODE_OPERATOR_VALIDATED,                 \
-		&&OPCODE_TYPE_TEST_BUILTIN,                  \
-		&&OPCODE_TYPE_TEST_ARRAY,                    \
-		&&OPCODE_TYPE_TEST_NATIVE,                   \
-		&&OPCODE_TYPE_TEST_SCRIPT,                   \
-		&&OPCODE_SET_KEYED,                          \
-		&&OPCODE_SET_KEYED_VALIDATED,                \
-		&&OPCODE_SET_INDEXED_VALIDATED,              \
-		&&OPCODE_GET_KEYED,                          \
-		&&OPCODE_GET_KEYED_VALIDATED,                \
-		&&OPCODE_GET_INDEXED_VALIDATED,              \
-		&&OPCODE_SET_NAMED,                          \
-		&&OPCODE_SET_NAMED_VALIDATED,                \
-		&&OPCODE_GET_NAMED,                          \
-		&&OPCODE_GET_NAMED_VALIDATED,                \
-		&&OPCODE_SET_MEMBER,                         \
-		&&OPCODE_GET_MEMBER,                         \
-		&&OPCODE_SET_STATIC_VARIABLE,                \
-		&&OPCODE_GET_STATIC_VARIABLE,                \
-		&&OPCODE_ASSIGN,                             \
-		&&OPCODE_ASSIGN_TRUE,                        \
-		&&OPCODE_ASSIGN_FALSE,                       \
-		&&OPCODE_ASSIGN_TYPED_BUILTIN,               \
-		&&OPCODE_ASSIGN_TYPED_ARRAY,                 \
-		&&OPCODE_ASSIGN_TYPED_NATIVE,                \
-		&&OPCODE_ASSIGN_TYPED_SCRIPT,                \
-		&&OPCODE_CAST_TO_BUILTIN,                    \
-		&&OPCODE_CAST_TO_NATIVE,                     \
-		&&OPCODE_CAST_TO_SCRIPT,                     \
-		&&OPCODE_CONSTRUCT,                          \
-		&&OPCODE_CONSTRUCT_VALIDATED,                \
-		&&OPCODE_CONSTRUCT_ARRAY,                    \
-		&&OPCODE_CONSTRUCT_TYPED_ARRAY,              \
-		&&OPCODE_CONSTRUCT_DICTIONARY,               \
-		&&OPCODE_CALL,                               \
-		&&OPCODE_CALL_RETURN,                        \
-		&&OPCODE_CALL_ASYNC,                         \
-		&&OPCODE_CALL_UTILITY,                       \
-		&&OPCODE_CALL_UTILITY_VALIDATED,             \
-		&&OPCODE_CALL_GDSCRIPT_UTILITY,              \
-		&&OPCODE_CALL_BUILTIN_TYPE_VALIDATED,        \
-		&&OPCODE_CALL_SELF_BASE,                     \
-		&&OPCODE_CALL_METHOD_BIND,                   \
-		&&OPCODE_CALL_METHOD_BIND_RET,               \
-		&&OPCODE_CALL_BUILTIN_STATIC,                \
-		&&OPCODE_CALL_NATIVE_STATIC,                 \
-		&&OPCODE_CALL_PTRCALL_NO_RETURN,             \
-		&&OPCODE_CALL_PTRCALL_BOOL,                  \
-		&&OPCODE_CALL_PTRCALL_INT,                   \
-		&&OPCODE_CALL_PTRCALL_FLOAT,                 \
-		&&OPCODE_CALL_PTRCALL_STRING,                \
-		&&OPCODE_CALL_PTRCALL_VECTOR2,               \
-		&&OPCODE_CALL_PTRCALL_VECTOR2I,              \
-		&&OPCODE_CALL_PTRCALL_RECT2,                 \
-		&&OPCODE_CALL_PTRCALL_RECT2I,                \
-		&&OPCODE_CALL_PTRCALL_VECTOR3,               \
-		&&OPCODE_CALL_PTRCALL_VECTOR3I,              \
-		&&OPCODE_CALL_PTRCALL_TRANSFORM2D,           \
-		&&OPCODE_CALL_PTRCALL_VECTOR4,               \
-		&&OPCODE_CALL_PTRCALL_VECTOR4I,              \
-		&&OPCODE_CALL_PTRCALL_PLANE,                 \
-		&&OPCODE_CALL_PTRCALL_QUATERNION,            \
-		&&OPCODE_CALL_PTRCALL_AABB,                  \
-		&&OPCODE_CALL_PTRCALL_BASIS,                 \
-		&&OPCODE_CALL_PTRCALL_TRANSFORM3D,           \
-		&&OPCODE_CALL_PTRCALL_PROJECTION,            \
-		&&OPCODE_CALL_PTRCALL_COLOR,                 \
-		&&OPCODE_CALL_PTRCALL_STRING_NAME,           \
-		&&OPCODE_CALL_PTRCALL_NODE_PATH,             \
-		&&OPCODE_CALL_PTRCALL_RID,                   \
-		&&OPCODE_CALL_PTRCALL_OBJECT,                \
-		&&OPCODE_CALL_PTRCALL_CALLABLE,              \
-		&&OPCODE_CALL_PTRCALL_SIGNAL,                \
-		&&OPCODE_CALL_PTRCALL_DICTIONARY,            \
-		&&OPCODE_CALL_PTRCALL_ARRAY,                 \
-		&&OPCODE_CALL_PTRCALL_PACKED_BYTE_ARRAY,     \
-		&&OPCODE_CALL_PTRCALL_PACKED_INT32_ARRAY,    \
-		&&OPCODE_CALL_PTRCALL_PACKED_INT64_ARRAY,    \
-		&&OPCODE_CALL_PTRCALL_PACKED_FLOAT32_ARRAY,  \
-		&&OPCODE_CALL_PTRCALL_PACKED_FLOAT64_ARRAY,  \
-		&&OPCODE_CALL_PTRCALL_PACKED_STRING_ARRAY,   \
-		&&OPCODE_CALL_PTRCALL_PACKED_VECTOR2_ARRAY,  \
-		&&OPCODE_CALL_PTRCALL_PACKED_VECTOR3_ARRAY,  \
-		&&OPCODE_CALL_PTRCALL_PACKED_COLOR_ARRAY,    \
-		&&OPCODE_AWAIT,                              \
-		&&OPCODE_AWAIT_RESUME,                       \
-		&&OPCODE_CREATE_LAMBDA,                      \
-		&&OPCODE_CREATE_SELF_LAMBDA,                 \
-		&&OPCODE_JUMP,                               \
-		&&OPCODE_JUMP_IF,                            \
-		&&OPCODE_JUMP_IF_NOT,                        \
-		&&OPCODE_JUMP_TO_DEF_ARGUMENT,               \
-		&&OPCODE_JUMP_IF_SHARED,                     \
-		&&OPCODE_RETURN,                             \
-		&&OPCODE_RETURN_TYPED_BUILTIN,               \
-		&&OPCODE_RETURN_TYPED_ARRAY,                 \
-		&&OPCODE_RETURN_TYPED_NATIVE,                \
-		&&OPCODE_RETURN_TYPED_SCRIPT,                \
-		&&OPCODE_ITERATE_BEGIN,                      \
-		&&OPCODE_ITERATE_BEGIN_INT,                  \
-		&&OPCODE_ITERATE_BEGIN_FLOAT,                \
-		&&OPCODE_ITERATE_BEGIN_VECTOR2,              \
-		&&OPCODE_ITERATE_BEGIN_VECTOR2I,             \
-		&&OPCODE_ITERATE_BEGIN_VECTOR3,              \
-		&&OPCODE_ITERATE_BEGIN_VECTOR3I,             \
-		&&OPCODE_ITERATE_BEGIN_STRING,               \
-		&&OPCODE_ITERATE_BEGIN_DICTIONARY,           \
-		&&OPCODE_ITERATE_BEGIN_ARRAY,                \
-		&&OPCODE_ITERATE_BEGIN_PACKED_BYTE_ARRAY,    \
-		&&OPCODE_ITERATE_BEGIN_PACKED_INT32_ARRAY,   \
-		&&OPCODE_ITERATE_BEGIN_PACKED_INT64_ARRAY,   \
-		&&OPCODE_ITERATE_BEGIN_PACKED_FLOAT32_ARRAY, \
-		&&OPCODE_ITERATE_BEGIN_PACKED_FLOAT64_ARRAY, \
-		&&OPCODE_ITERATE_BEGIN_PACKED_STRING_ARRAY,  \
-		&&OPCODE_ITERATE_BEGIN_PACKED_VECTOR2_ARRAY, \
-		&&OPCODE_ITERATE_BEGIN_PACKED_VECTOR3_ARRAY, \
-		&&OPCODE_ITERATE_BEGIN_PACKED_COLOR_ARRAY,   \
-		&&OPCODE_ITERATE_BEGIN_OBJECT,               \
-		&&OPCODE_ITERATE,                            \
-		&&OPCODE_ITERATE_INT,                        \
-		&&OPCODE_ITERATE_FLOAT,                      \
-		&&OPCODE_ITERATE_VECTOR2,                    \
-		&&OPCODE_ITERATE_VECTOR2I,                   \
-		&&OPCODE_ITERATE_VECTOR3,                    \
-		&&OPCODE_ITERATE_VECTOR3I,                   \
-		&&OPCODE_ITERATE_STRING,                     \
-		&&OPCODE_ITERATE_DICTIONARY,                 \
-		&&OPCODE_ITERATE_ARRAY,                      \
-		&&OPCODE_ITERATE_PACKED_BYTE_ARRAY,          \
-		&&OPCODE_ITERATE_PACKED_INT32_ARRAY,         \
-		&&OPCODE_ITERATE_PACKED_INT64_ARRAY,         \
-		&&OPCODE_ITERATE_PACKED_FLOAT32_ARRAY,       \
-		&&OPCODE_ITERATE_PACKED_FLOAT64_ARRAY,       \
-		&&OPCODE_ITERATE_PACKED_STRING_ARRAY,        \
-		&&OPCODE_ITERATE_PACKED_VECTOR2_ARRAY,       \
-		&&OPCODE_ITERATE_PACKED_VECTOR3_ARRAY,       \
-		&&OPCODE_ITERATE_PACKED_COLOR_ARRAY,         \
-		&&OPCODE_ITERATE_OBJECT,                     \
-		&&OPCODE_STORE_GLOBAL,                       \
-		&&OPCODE_STORE_NAMED_GLOBAL,                 \
-		&&OPCODE_TYPE_ADJUST_BOOL,                   \
-		&&OPCODE_TYPE_ADJUST_INT,                    \
-		&&OPCODE_TYPE_ADJUST_FLOAT,                  \
-		&&OPCODE_TYPE_ADJUST_STRING,                 \
-		&&OPCODE_TYPE_ADJUST_VECTOR2,                \
-		&&OPCODE_TYPE_ADJUST_VECTOR2I,               \
-		&&OPCODE_TYPE_ADJUST_RECT2,                  \
-		&&OPCODE_TYPE_ADJUST_RECT2I,                 \
-		&&OPCODE_TYPE_ADJUST_VECTOR3,                \
-		&&OPCODE_TYPE_ADJUST_VECTOR3I,               \
-		&&OPCODE_TYPE_ADJUST_TRANSFORM2D,            \
-		&&OPCODE_TYPE_ADJUST_VECTOR4,                \
-		&&OPCODE_TYPE_ADJUST_VECTOR4I,               \
-		&&OPCODE_TYPE_ADJUST_PLANE,                  \
-		&&OPCODE_TYPE_ADJUST_QUATERNION,             \
-		&&OPCODE_TYPE_ADJUST_AABB,                   \
-		&&OPCODE_TYPE_ADJUST_BASIS,                  \
-		&&OPCODE_TYPE_ADJUST_TRANSFORM3D,            \
-		&&OPCODE_TYPE_ADJUST_PROJECTION,             \
-		&&OPCODE_TYPE_ADJUST_COLOR,                  \
-		&&OPCODE_TYPE_ADJUST_STRING_NAME,            \
-		&&OPCODE_TYPE_ADJUST_NODE_PATH,              \
-		&&OPCODE_TYPE_ADJUST_RID,                    \
-		&&OPCODE_TYPE_ADJUST_OBJECT,                 \
-		&&OPCODE_TYPE_ADJUST_CALLABLE,               \
-		&&OPCODE_TYPE_ADJUST_SIGNAL,                 \
-		&&OPCODE_TYPE_ADJUST_DICTIONARY,             \
-		&&OPCODE_TYPE_ADJUST_ARRAY,                  \
-		&&OPCODE_TYPE_ADJUST_PACKED_BYTE_ARRAY,      \
-		&&OPCODE_TYPE_ADJUST_PACKED_INT32_ARRAY,     \
-		&&OPCODE_TYPE_ADJUST_PACKED_INT64_ARRAY,     \
-		&&OPCODE_TYPE_ADJUST_PACKED_FLOAT32_ARRAY,   \
-		&&OPCODE_TYPE_ADJUST_PACKED_FLOAT64_ARRAY,   \
-		&&OPCODE_TYPE_ADJUST_PACKED_STRING_ARRAY,    \
-		&&OPCODE_TYPE_ADJUST_PACKED_VECTOR2_ARRAY,   \
-		&&OPCODE_TYPE_ADJUST_PACKED_VECTOR3_ARRAY,   \
-		&&OPCODE_TYPE_ADJUST_PACKED_COLOR_ARRAY,     \
-		&&OPCODE_ASSERT,                             \
-		&&OPCODE_BREAKPOINT,                         \
-		&&OPCODE_LINE,                               \
-		&&OPCODE_END                                 \
-	};                                               \
+#define OPCODES_TABLE                                  \
+	static const void *switch_table_ops[] = {          \
+		&&OPCODE_OPERATOR,                             \
+		&&OPCODE_OPERATOR_VALIDATED,                   \
+		&&OPCODE_TYPE_TEST_BUILTIN,                    \
+		&&OPCODE_TYPE_TEST_ARRAY,                      \
+		&&OPCODE_TYPE_TEST_NATIVE,                     \
+		&&OPCODE_TYPE_TEST_SCRIPT,                     \
+		&&OPCODE_SET_KEYED,                            \
+		&&OPCODE_SET_KEYED_VALIDATED,                  \
+		&&OPCODE_SET_INDEXED_VALIDATED,                \
+		&&OPCODE_GET_KEYED,                            \
+		&&OPCODE_GET_KEYED_VALIDATED,                  \
+		&&OPCODE_GET_INDEXED_VALIDATED,                \
+		&&OPCODE_SET_NAMED,                            \
+		&&OPCODE_SET_NAMED_VALIDATED,                  \
+		&&OPCODE_GET_NAMED,                            \
+		&&OPCODE_GET_NAMED_VALIDATED,                  \
+		&&OPCODE_SET_MEMBER,                           \
+		&&OPCODE_GET_MEMBER,                           \
+		&&OPCODE_SET_STATIC_VARIABLE,                  \
+		&&OPCODE_GET_STATIC_VARIABLE,                  \
+		&&OPCODE_ASSIGN,                               \
+		&&OPCODE_ASSIGN_TRUE,                          \
+		&&OPCODE_ASSIGN_FALSE,                         \
+		&&OPCODE_ASSIGN_TYPED_BUILTIN,                 \
+		&&OPCODE_ASSIGN_TYPED_ARRAY,                   \
+		&&OPCODE_ASSIGN_TYPED_NATIVE,                  \
+		&&OPCODE_ASSIGN_TYPED_SCRIPT,                  \
+		&&OPCODE_CAST_TO_BUILTIN,                      \
+		&&OPCODE_CAST_TO_NATIVE,                       \
+		&&OPCODE_CAST_TO_SCRIPT,                       \
+		&&OPCODE_CONSTRUCT,                            \
+		&&OPCODE_CONSTRUCT_VALIDATED,                  \
+		&&OPCODE_CONSTRUCT_ARRAY,                      \
+		&&OPCODE_CONSTRUCT_TYPED_ARRAY,                \
+		&&OPCODE_CONSTRUCT_DICTIONARY,                 \
+		&&OPCODE_CALL,                                 \
+		&&OPCODE_CALL_RETURN,                          \
+		&&OPCODE_CALL_ASYNC,                           \
+		&&OPCODE_CALL_UTILITY,                         \
+		&&OPCODE_CALL_UTILITY_VALIDATED,               \
+		&&OPCODE_CALL_GDSCRIPT_UTILITY,                \
+		&&OPCODE_CALL_BUILTIN_TYPE_VALIDATED,          \
+		&&OPCODE_CALL_SELF_BASE,                       \
+		&&OPCODE_CALL_METHOD_BIND,                     \
+		&&OPCODE_CALL_METHOD_BIND_RET,                 \
+		&&OPCODE_CALL_BUILTIN_STATIC,                  \
+		&&OPCODE_CALL_NATIVE_STATIC,                   \
+		&&OPCODE_CALL_METHOD_BIND_VALIDATED_RETURN,    \
+		&&OPCODE_CALL_METHOD_BIND_VALIDATED_NO_RETURN, \
+		&&OPCODE_AWAIT,                                \
+		&&OPCODE_AWAIT_RESUME,                         \
+		&&OPCODE_CREATE_LAMBDA,                        \
+		&&OPCODE_CREATE_SELF_LAMBDA,                   \
+		&&OPCODE_JUMP,                                 \
+		&&OPCODE_JUMP_IF,                              \
+		&&OPCODE_JUMP_IF_NOT,                          \
+		&&OPCODE_JUMP_TO_DEF_ARGUMENT,                 \
+		&&OPCODE_JUMP_IF_SHARED,                       \
+		&&OPCODE_RETURN,                               \
+		&&OPCODE_RETURN_TYPED_BUILTIN,                 \
+		&&OPCODE_RETURN_TYPED_ARRAY,                   \
+		&&OPCODE_RETURN_TYPED_NATIVE,                  \
+		&&OPCODE_RETURN_TYPED_SCRIPT,                  \
+		&&OPCODE_ITERATE_BEGIN,                        \
+		&&OPCODE_ITERATE_BEGIN_INT,                    \
+		&&OPCODE_ITERATE_BEGIN_FLOAT,                  \
+		&&OPCODE_ITERATE_BEGIN_VECTOR2,                \
+		&&OPCODE_ITERATE_BEGIN_VECTOR2I,               \
+		&&OPCODE_ITERATE_BEGIN_VECTOR3,                \
+		&&OPCODE_ITERATE_BEGIN_VECTOR3I,               \
+		&&OPCODE_ITERATE_BEGIN_STRING,                 \
+		&&OPCODE_ITERATE_BEGIN_DICTIONARY,             \
+		&&OPCODE_ITERATE_BEGIN_ARRAY,                  \
+		&&OPCODE_ITERATE_BEGIN_PACKED_BYTE_ARRAY,      \
+		&&OPCODE_ITERATE_BEGIN_PACKED_INT32_ARRAY,     \
+		&&OPCODE_ITERATE_BEGIN_PACKED_INT64_ARRAY,     \
+		&&OPCODE_ITERATE_BEGIN_PACKED_FLOAT32_ARRAY,   \
+		&&OPCODE_ITERATE_BEGIN_PACKED_FLOAT64_ARRAY,   \
+		&&OPCODE_ITERATE_BEGIN_PACKED_STRING_ARRAY,    \
+		&&OPCODE_ITERATE_BEGIN_PACKED_VECTOR2_ARRAY,   \
+		&&OPCODE_ITERATE_BEGIN_PACKED_VECTOR3_ARRAY,   \
+		&&OPCODE_ITERATE_BEGIN_PACKED_COLOR_ARRAY,     \
+		&&OPCODE_ITERATE_BEGIN_OBJECT,                 \
+		&&OPCODE_ITERATE,                              \
+		&&OPCODE_ITERATE_INT,                          \
+		&&OPCODE_ITERATE_FLOAT,                        \
+		&&OPCODE_ITERATE_VECTOR2,                      \
+		&&OPCODE_ITERATE_VECTOR2I,                     \
+		&&OPCODE_ITERATE_VECTOR3,                      \
+		&&OPCODE_ITERATE_VECTOR3I,                     \
+		&&OPCODE_ITERATE_STRING,                       \
+		&&OPCODE_ITERATE_DICTIONARY,                   \
+		&&OPCODE_ITERATE_ARRAY,                        \
+		&&OPCODE_ITERATE_PACKED_BYTE_ARRAY,            \
+		&&OPCODE_ITERATE_PACKED_INT32_ARRAY,           \
+		&&OPCODE_ITERATE_PACKED_INT64_ARRAY,           \
+		&&OPCODE_ITERATE_PACKED_FLOAT32_ARRAY,         \
+		&&OPCODE_ITERATE_PACKED_FLOAT64_ARRAY,         \
+		&&OPCODE_ITERATE_PACKED_STRING_ARRAY,          \
+		&&OPCODE_ITERATE_PACKED_VECTOR2_ARRAY,         \
+		&&OPCODE_ITERATE_PACKED_VECTOR3_ARRAY,         \
+		&&OPCODE_ITERATE_PACKED_COLOR_ARRAY,           \
+		&&OPCODE_ITERATE_OBJECT,                       \
+		&&OPCODE_STORE_GLOBAL,                         \
+		&&OPCODE_STORE_NAMED_GLOBAL,                   \
+		&&OPCODE_TYPE_ADJUST_BOOL,                     \
+		&&OPCODE_TYPE_ADJUST_INT,                      \
+		&&OPCODE_TYPE_ADJUST_FLOAT,                    \
+		&&OPCODE_TYPE_ADJUST_STRING,                   \
+		&&OPCODE_TYPE_ADJUST_VECTOR2,                  \
+		&&OPCODE_TYPE_ADJUST_VECTOR2I,                 \
+		&&OPCODE_TYPE_ADJUST_RECT2,                    \
+		&&OPCODE_TYPE_ADJUST_RECT2I,                   \
+		&&OPCODE_TYPE_ADJUST_VECTOR3,                  \
+		&&OPCODE_TYPE_ADJUST_VECTOR3I,                 \
+		&&OPCODE_TYPE_ADJUST_TRANSFORM2D,              \
+		&&OPCODE_TYPE_ADJUST_VECTOR4,                  \
+		&&OPCODE_TYPE_ADJUST_VECTOR4I,                 \
+		&&OPCODE_TYPE_ADJUST_PLANE,                    \
+		&&OPCODE_TYPE_ADJUST_QUATERNION,               \
+		&&OPCODE_TYPE_ADJUST_AABB,                     \
+		&&OPCODE_TYPE_ADJUST_BASIS,                    \
+		&&OPCODE_TYPE_ADJUST_TRANSFORM3D,              \
+		&&OPCODE_TYPE_ADJUST_PROJECTION,               \
+		&&OPCODE_TYPE_ADJUST_COLOR,                    \
+		&&OPCODE_TYPE_ADJUST_STRING_NAME,              \
+		&&OPCODE_TYPE_ADJUST_NODE_PATH,                \
+		&&OPCODE_TYPE_ADJUST_RID,                      \
+		&&OPCODE_TYPE_ADJUST_OBJECT,                   \
+		&&OPCODE_TYPE_ADJUST_CALLABLE,                 \
+		&&OPCODE_TYPE_ADJUST_SIGNAL,                   \
+		&&OPCODE_TYPE_ADJUST_DICTIONARY,               \
+		&&OPCODE_TYPE_ADJUST_ARRAY,                    \
+		&&OPCODE_TYPE_ADJUST_PACKED_BYTE_ARRAY,        \
+		&&OPCODE_TYPE_ADJUST_PACKED_INT32_ARRAY,       \
+		&&OPCODE_TYPE_ADJUST_PACKED_INT64_ARRAY,       \
+		&&OPCODE_TYPE_ADJUST_PACKED_FLOAT32_ARRAY,     \
+		&&OPCODE_TYPE_ADJUST_PACKED_FLOAT64_ARRAY,     \
+		&&OPCODE_TYPE_ADJUST_PACKED_STRING_ARRAY,      \
+		&&OPCODE_TYPE_ADJUST_PACKED_VECTOR2_ARRAY,     \
+		&&OPCODE_TYPE_ADJUST_PACKED_VECTOR3_ARRAY,     \
+		&&OPCODE_TYPE_ADJUST_PACKED_COLOR_ARRAY,       \
+		&&OPCODE_ASSERT,                               \
+		&&OPCODE_BREAKPOINT,                           \
+		&&OPCODE_LINE,                                 \
+		&&OPCODE_END                                   \
+	};                                                 \
 	static_assert((sizeof(switch_table_ops) / sizeof(switch_table_ops[0]) == (OPCODE_END + 1)), "Opcodes in jump table aren't the same as opcodes in enum.");
 
 #define OPCODE(m_op) \
@@ -489,7 +453,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 	Variant retvalue;
 	Variant *stack = nullptr;
 	Variant **instruction_args = nullptr;
-	const void **call_args_ptr = nullptr;
 	int defarg = 0;
 
 #ifdef DEBUG_ENABLED
@@ -578,12 +541,6 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 		}
 	}
 
-	if (_ptrcall_args_size) {
-		call_args_ptr = (const void **)alloca(_ptrcall_args_size * sizeof(void *));
-	} else {
-		call_args_ptr = nullptr;
-	}
-
 	if (p_instance) {
 		memnew_placement(&stack[ADDR_STACK_SELF], Variant(p_instance->owner));
 		script = p_instance->script.ptr();
@@ -1954,106 +1911,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 			}
 			DISPATCH_OPCODE;
 
-#ifdef DEBUG_ENABLED
-#define OPCODE_CALL_PTR(m_type)                                                      \
-	OPCODE(OPCODE_CALL_PTRCALL_##m_type) {                                           \
-		LOAD_INSTRUCTION_ARGS                                                        \
-		CHECK_SPACE(3 + instr_arg_count);                                            \
-		ip += instr_arg_count;                                                       \
-		int argc = _code_ptr[ip + 1];                                                \
-		GD_ERR_BREAK(argc < 0);                                                      \
-		GET_INSTRUCTION_ARG(base, argc);                                             \
-		GD_ERR_BREAK(_code_ptr[ip + 2] < 0 || _code_ptr[ip + 2] >= _methods_count);  \
-		MethodBind *method = _methods_ptr[_code_ptr[ip + 2]];                        \
-		bool freed = false;                                                          \
-		Object *base_obj = base->get_validated_object_with_check(freed);             \
-		if (freed) {                                                                 \
-			err_text = METHOD_CALL_ON_FREED_INSTANCE_ERROR(method);                  \
-			OPCODE_BREAK;                                                            \
-		} else if (!base_obj) {                                                      \
-			err_text = METHOD_CALL_ON_NULL_VALUE_ERROR(method);                      \
-			OPCODE_BREAK;                                                            \
-		}                                                                            \
-		const void **argptrs = call_args_ptr;                                        \
-		for (int i = 0; i < argc; i++) {                                             \
-			GET_INSTRUCTION_ARG(v, i);                                               \
-			argptrs[i] = VariantInternal::get_opaque_pointer((const Variant *)v);    \
-		}                                                                            \
-		uint64_t call_time = 0;                                                      \
-		if (GDScriptLanguage::get_singleton()->profiling) {                          \
-			call_time = OS::get_singleton()->get_ticks_usec();                       \
-		}                                                                            \
-		GET_INSTRUCTION_ARG(ret, argc + 1);                                          \
-		VariantInternal::initialize(ret, Variant::m_type);                           \
-		void *ret_opaque = VariantInternal::OP_GET_##m_type(ret);                    \
-		method->ptrcall(base_obj, argptrs, ret_opaque);                              \
-		if (GDScriptLanguage::get_singleton()->profiling) {                          \
-			function_call_time += OS::get_singleton()->get_ticks_usec() - call_time; \
-		}                                                                            \
-		ip += 3;                                                                     \
-	}                                                                                \
-	DISPATCH_OPCODE
-#else
-#define OPCODE_CALL_PTR(m_type)                                                   \
-	OPCODE(OPCODE_CALL_PTRCALL_##m_type) {                                        \
-		LOAD_INSTRUCTION_ARGS                                                     \
-		CHECK_SPACE(3 + instr_arg_count);                                         \
-		ip += instr_arg_count;                                                    \
-		int argc = _code_ptr[ip + 1];                                             \
-		GET_INSTRUCTION_ARG(base, argc);                                          \
-		MethodBind *method = _methods_ptr[_code_ptr[ip + 2]];                     \
-		Object *base_obj = *VariantInternal::get_object(base);                    \
-		const void **argptrs = call_args_ptr;                                     \
-		for (int i = 0; i < argc; i++) {                                          \
-			GET_INSTRUCTION_ARG(v, i);                                            \
-			argptrs[i] = VariantInternal::get_opaque_pointer((const Variant *)v); \
-		}                                                                         \
-		GET_INSTRUCTION_ARG(ret, argc + 1);                                       \
-		VariantInternal::initialize(ret, Variant::m_type);                        \
-		void *ret_opaque = VariantInternal::OP_GET_##m_type(ret);                 \
-		method->ptrcall(base_obj, argptrs, ret_opaque);                           \
-		ip += 3;                                                                  \
-	}                                                                             \
-	DISPATCH_OPCODE
-#endif
-
-			OPCODE_CALL_PTR(BOOL);
-			OPCODE_CALL_PTR(INT);
-			OPCODE_CALL_PTR(FLOAT);
-			OPCODE_CALL_PTR(STRING);
-			OPCODE_CALL_PTR(VECTOR2);
-			OPCODE_CALL_PTR(VECTOR2I);
-			OPCODE_CALL_PTR(RECT2);
-			OPCODE_CALL_PTR(RECT2I);
-			OPCODE_CALL_PTR(VECTOR3);
-			OPCODE_CALL_PTR(VECTOR3I);
-			OPCODE_CALL_PTR(TRANSFORM2D);
-			OPCODE_CALL_PTR(VECTOR4);
-			OPCODE_CALL_PTR(VECTOR4I);
-			OPCODE_CALL_PTR(PLANE);
-			OPCODE_CALL_PTR(QUATERNION);
-			OPCODE_CALL_PTR(AABB);
-			OPCODE_CALL_PTR(BASIS);
-			OPCODE_CALL_PTR(TRANSFORM3D);
-			OPCODE_CALL_PTR(PROJECTION);
-			OPCODE_CALL_PTR(COLOR);
-			OPCODE_CALL_PTR(STRING_NAME);
-			OPCODE_CALL_PTR(NODE_PATH);
-			OPCODE_CALL_PTR(RID);
-			OPCODE_CALL_PTR(CALLABLE);
-			OPCODE_CALL_PTR(SIGNAL);
-			OPCODE_CALL_PTR(DICTIONARY);
-			OPCODE_CALL_PTR(ARRAY);
-			OPCODE_CALL_PTR(PACKED_BYTE_ARRAY);
-			OPCODE_CALL_PTR(PACKED_INT32_ARRAY);
-			OPCODE_CALL_PTR(PACKED_INT64_ARRAY);
-			OPCODE_CALL_PTR(PACKED_FLOAT32_ARRAY);
-			OPCODE_CALL_PTR(PACKED_FLOAT64_ARRAY);
-			OPCODE_CALL_PTR(PACKED_STRING_ARRAY);
-			OPCODE_CALL_PTR(PACKED_VECTOR2_ARRAY);
-			OPCODE_CALL_PTR(PACKED_VECTOR3_ARRAY);
-			OPCODE_CALL_PTR(PACKED_COLOR_ARRAY);
-			OPCODE(OPCODE_CALL_PTRCALL_OBJECT) {
+			OPCODE(OPCODE_CALL_METHOD_BIND_VALIDATED_RETURN) {
 				LOAD_INSTRUCTION_ARGS
 				CHECK_SPACE(3 + instr_arg_count);
 
@@ -2066,6 +1924,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 				MethodBind *method = _methods_ptr[_code_ptr[ip + 2]];
 
 				GET_INSTRUCTION_ARG(base, argc);
+
 #ifdef DEBUG_ENABLED
 				bool freed = false;
 				Object *base_obj = base->get_validated_object_with_check(freed);
@@ -2080,12 +1939,8 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 				Object *base_obj = *VariantInternal::get_object(base);
 #endif
 
-				const void **argptrs = call_args_ptr;
+				Variant **argptrs = instruction_args;
 
-				for (int i = 0; i < argc; i++) {
-					GET_INSTRUCTION_ARG(v, i);
-					argptrs[i] = VariantInternal::get_opaque_pointer((const Variant *)v);
-				}
 #ifdef DEBUG_ENABLED
 				uint64_t call_time = 0;
 
@@ -2095,16 +1950,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 #endif
 
 				GET_INSTRUCTION_ARG(ret, argc + 1);
-				VariantInternal::initialize(ret, Variant::OBJECT);
-				Object **ret_opaque = VariantInternal::get_object(ret);
-				method->ptrcall(base_obj, argptrs, ret_opaque);
-				if (method->is_return_type_raw_object_ptr()) {
-					// The Variant has to participate in the ref count since the method returns a raw Object *.
-					VariantInternal::object_assign(ret, *ret_opaque);
-				} else {
-					// The method, in case it returns something, returns an already encapsulated object.
-					VariantInternal::update_object_id(ret);
-				}
+				method->validated_call(base_obj, (const Variant **)argptrs, ret);
 
 #ifdef DEBUG_ENABLED
 				if (GDScriptLanguage::get_singleton()->profiling) {
@@ -2114,7 +1960,8 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 				ip += 3;
 			}
 			DISPATCH_OPCODE;
-			OPCODE(OPCODE_CALL_PTRCALL_NO_RETURN) {
+
+			OPCODE(OPCODE_CALL_METHOD_BIND_VALIDATED_NO_RETURN) {
 				LOAD_INSTRUCTION_ARGS
 				CHECK_SPACE(3 + instr_arg_count);
 
@@ -2140,12 +1987,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 #else
 				Object *base_obj = *VariantInternal::get_object(base);
 #endif
-				const void **argptrs = call_args_ptr;
-
-				for (int i = 0; i < argc; i++) {
-					GET_INSTRUCTION_ARG(v, i);
-					argptrs[i] = VariantInternal::get_opaque_pointer((const Variant *)v);
-				}
+				Variant **argptrs = instruction_args;
 #ifdef DEBUG_ENABLED
 				uint64_t call_time = 0;
 
@@ -2156,7 +1998,7 @@ Variant GDScriptFunction::call(GDScriptInstance *p_instance, const Variant **p_a
 
 				GET_INSTRUCTION_ARG(ret, argc + 1);
 				VariantInternal::initialize(ret, Variant::NIL);
-				method->ptrcall(base_obj, argptrs, nullptr);
+				method->validated_call(base_obj, (const Variant **)argptrs, nullptr);
 
 #ifdef DEBUG_ENABLED
 				if (GDScriptLanguage::get_singleton()->profiling) {

+ 3 - 3
modules/gdscript/tests/scripts/runtime/features/standalone-calls-do-not-write-to-nil.gd

@@ -7,7 +7,7 @@ func test():
 	test_builtin_call_validated(Vector2.UP, false)
 	test_object_call(RefCounted.new(), false)
 	test_object_call_method_bind(Resource.new(), false)
-	test_object_call_ptrcall(RefCounted.new(), false)
+	test_object_call_method_bind_validated(RefCounted.new(), false)
 
 	print("end")
 
@@ -40,7 +40,7 @@ func test_object_call_method_bind(v: Resource, f):
 	v.duplicate() # Native type method call with MethodBind.
 	assert(not f) # Test unary operator reading from `nil`.
 
-func test_object_call_ptrcall(v: RefCounted, f):
+func test_object_call_method_bind_validated(v: RefCounted, f):
 	@warning_ignore("return_value_discarded")
-	v.get_reference_count() # Native type method call with ptrcall.
+	v.get_reference_count() # Native type method call with validated MethodBind.
 	assert(not f) # Test unary operator reading from `nil`.