Skip to content

Commit 7ca038e

Browse files
committed
GDScript: Perform validated calls with static methods
When the types are validated at compile time, this type of call runs faster. It is already used for instance methods, this adds this optimization to native static methods as well.
1 parent 11d3768 commit 7ca038e

File tree

9 files changed

+329
-164
lines changed

9 files changed

+329
-164
lines changed

modules/gdscript/gdscript_byte_codegen.cpp

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1196,23 +1196,49 @@ void GDScriptByteCodeGenerator::write_call_builtin_type_static(const Address &p_
11961196
}
11971197

11981198
void GDScriptByteCodeGenerator::write_call_native_static(const Address &p_target, const StringName &p_class, const StringName &p_method, const Vector<Address> &p_arguments) {
1199-
bool is_validated = false;
1200-
12011199
MethodBind *method = ClassDB::get_method(p_class, p_method);
12021200

1203-
if (!is_validated) {
1204-
// Perform regular call.
1205-
append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_NATIVE_STATIC, p_arguments.size() + 1);
1206-
for (int i = 0; i < p_arguments.size(); i++) {
1207-
append(p_arguments[i]);
1201+
// Perform regular call.
1202+
append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_NATIVE_STATIC, p_arguments.size() + 1);
1203+
for (int i = 0; i < p_arguments.size(); i++) {
1204+
append(p_arguments[i]);
1205+
}
1206+
CallTarget ct = get_call_target(p_target);
1207+
append(ct.target);
1208+
append(method);
1209+
append(p_arguments.size());
1210+
ct.cleanup();
1211+
return;
1212+
}
1213+
1214+
void GDScriptByteCodeGenerator::write_call_native_static_validated(const GDScriptCodeGenerator::Address &p_target, MethodBind *p_method, const Vector<GDScriptCodeGenerator::Address> &p_arguments) {
1215+
Variant::Type return_type = Variant::NIL;
1216+
bool has_return = p_method->has_return();
1217+
1218+
if (has_return) {
1219+
PropertyInfo return_info = p_method->get_return_info();
1220+
return_type = return_info.type;
1221+
}
1222+
1223+
CallTarget ct = get_call_target(p_target, return_type);
1224+
1225+
if (has_return) {
1226+
Variant::Type temp_type = temporaries[ct.target.address].type;
1227+
if (temp_type != return_type) {
1228+
write_type_adjust(ct.target, return_type);
12081229
}
1209-
CallTarget ct = get_call_target(p_target);
1210-
append(ct.target);
1211-
append(method);
1212-
append(p_arguments.size());
1213-
ct.cleanup();
1214-
return;
12151230
}
1231+
1232+
GDScriptFunction::Opcode code = p_method->has_return() ? GDScriptFunction::OPCODE_CALL_NATIVE_STATIC_VALIDATED_RETURN : GDScriptFunction::OPCODE_CALL_NATIVE_STATIC_VALIDATED_NO_RETURN;
1233+
append_opcode_and_argcount(code, 1 + p_arguments.size());
1234+
1235+
for (int i = 0; i < p_arguments.size(); i++) {
1236+
append(p_arguments[i]);
1237+
}
1238+
append(ct.target);
1239+
append(p_arguments.size());
1240+
append(p_method);
1241+
ct.cleanup();
12161242
}
12171243

12181244
void GDScriptByteCodeGenerator::write_call_method_bind(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) {

modules/gdscript/gdscript_byte_codegen.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -518,6 +518,7 @@ class GDScriptByteCodeGenerator : public GDScriptCodeGenerator {
518518
virtual void write_call_builtin_type(const Address &p_target, const Address &p_base, Variant::Type p_type, const StringName &p_method, const Vector<Address> &p_arguments) override;
519519
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;
520520
virtual void write_call_native_static(const Address &p_target, const StringName &p_class, const StringName &p_method, const Vector<Address> &p_arguments) override;
521+
virtual void write_call_native_static_validated(const Address &p_target, MethodBind *p_method, const Vector<Address> &p_arguments) override;
521522
virtual void write_call_method_bind(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) override;
522523
virtual void write_call_method_bind_validated(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) override;
523524
virtual void write_call_self(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) override;

modules/gdscript/gdscript_codegen.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,7 @@ class GDScriptCodeGenerator {
131131
virtual void write_call_builtin_type(const Address &p_target, const Address &p_base, Variant::Type p_type, const StringName &p_method, const Vector<Address> &p_arguments) = 0;
132132
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;
133133
virtual void write_call_native_static(const Address &p_target, const StringName &p_class, const StringName &p_method, const Vector<Address> &p_arguments) = 0;
134+
virtual void write_call_native_static_validated(const Address &p_target, MethodBind *p_method, const Vector<Address> &p_arguments) = 0;
134135
virtual void write_call_method_bind(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) = 0;
135136
virtual void write_call_method_bind_validated(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) = 0;
136137
virtual void write_call_self(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) = 0;

modules/gdscript/gdscript_compiler.cpp

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -673,7 +673,15 @@ GDScriptCodeGenerator::Address GDScriptCompiler::_parse_expression(CodeGen &code
673673
} else if (!call->is_super && subscript->base->type == GDScriptParser::Node::IDENTIFIER && call->function_name != SNAME("new") &&
674674
ClassDB::class_exists(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name) && !Engine::get_singleton()->has_singleton(static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name)) {
675675
// It's a static native method call.
676-
gen->write_call_native_static(result, static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name, subscript->attribute->name, arguments);
676+
StringName class_name = static_cast<GDScriptParser::IdentifierNode *>(subscript->base)->name;
677+
MethodBind *method = ClassDB::get_method(class_name, subscript->attribute->name);
678+
if (_can_use_validate_call(method, arguments)) {
679+
// Exact arguments, use validated call.
680+
gen->write_call_native_static_validated(result, method, arguments);
681+
} else {
682+
// Not exact arguments, use regular static call
683+
gen->write_call_native_static(result, class_name, subscript->attribute->name, arguments);
684+
}
677685
} else {
678686
GDScriptCodeGenerator::Address base = _parse_expression(codegen, r_error, subscript->base);
679687
if (r_error) {

modules/gdscript/gdscript_disassembler.cpp

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -678,6 +678,50 @@ void GDScriptFunction::disassemble(const Vector<String> &p_code_lines) const {
678678
incr += 4 + argc;
679679
} break;
680680

681+
case OPCODE_CALL_NATIVE_STATIC_VALIDATED_RETURN: {
682+
int instr_var_args = _code_ptr[++ip];
683+
text += "call native static method validated (return) ";
684+
MethodBind *method = _methods_ptr[_code_ptr[ip + 2 + instr_var_args]];
685+
int argc = _code_ptr[ip + 1 + instr_var_args];
686+
text += DADDR(1 + argc) + " = ";
687+
text += method->get_instance_class();
688+
text += ".";
689+
text += method->get_name();
690+
text += "(";
691+
for (int i = 0; i < argc; i++) {
692+
if (i > 0)
693+
text += ", ";
694+
text += DADDR(1 + i);
695+
}
696+
text += ")";
697+
incr = 4 + argc;
698+
} break;
699+
700+
case OPCODE_CALL_NATIVE_STATIC_VALIDATED_NO_RETURN: {
701+
int instr_var_args = _code_ptr[++ip];
702+
703+
text += "call native static method validated (no return) ";
704+
705+
MethodBind *method = _methods_ptr[_code_ptr[ip + 2 + instr_var_args]];
706+
707+
int argc = _code_ptr[ip + 1 + instr_var_args];
708+
709+
text += method->get_instance_class();
710+
text += ".";
711+
text += method->get_name();
712+
text += "(";
713+
714+
for (int i = 0; i < argc; i++) {
715+
if (i > 0) {
716+
text += ", ";
717+
}
718+
text += DADDR(1 + i);
719+
}
720+
text += ")";
721+
722+
incr = 4 + argc;
723+
} break;
724+
681725
case OPCODE_CALL_METHOD_BIND_VALIDATED_RETURN: {
682726
int instr_var_args = _code_ptr[++ip];
683727
text += "call method-bind validated (return) ";

modules/gdscript/gdscript_function.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -264,6 +264,8 @@ class GDScriptFunction {
264264
OPCODE_CALL_METHOD_BIND_RET,
265265
OPCODE_CALL_BUILTIN_STATIC,
266266
OPCODE_CALL_NATIVE_STATIC,
267+
OPCODE_CALL_NATIVE_STATIC_VALIDATED_RETURN,
268+
OPCODE_CALL_NATIVE_STATIC_VALIDATED_NO_RETURN,
267269
OPCODE_CALL_METHOD_BIND_VALIDATED_RETURN,
268270
OPCODE_CALL_METHOD_BIND_VALIDATED_NO_RETURN,
269271
OPCODE_AWAIT,

0 commit comments

Comments
 (0)