Skip to content

Commit 731ea17

Browse files
committed
Merge pull request godotengine#91192 from vnen/gdscript-validated-native-static-calls
GDScript: Perform validated calls with static methods
2 parents f89de7a + 7ca038e commit 731ea17

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)