Merge pull request #79893 from vnen/gdscript-validated-method-bind-call
GDScript: Replace ptrcalls on MethodBind to validated calls
This commit is contained in:
commit
2f919f0fd0
@ -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
|
||||
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();
|
||||
|
||||
bool is_ptrcall = true;
|
||||
if (has_return) {
|
||||
PropertyInfo return_info = p_method->get_return_info();
|
||||
return_type = return_info.type;
|
||||
}
|
||||
|
||||
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;
|
||||
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) {
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
case OPCODE_CALL_METHOD_BIND_VALIDATED_NO_RETURN: {
|
||||
int instr_var_args = _code_ptr[++ip];
|
||||
|
||||
text += "call-ptrcall (no return) ";
|
||||
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];
|
||||
|
@ -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;
|
||||
|
@ -236,44 +236,8 @@ void (*type_init_function_table[])(Variant *) = {
|
||||
&&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_CALL_METHOD_BIND_VALIDATED_RETURN, \
|
||||
&&OPCODE_CALL_METHOD_BIND_VALIDATED_NO_RETURN, \
|
||||
&&OPCODE_AWAIT, \
|
||||
&&OPCODE_AWAIT_RESUME, \
|
||||
&&OPCODE_CREATE_LAMBDA, \
|
||||
@ -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) {
|
||||
|
@ -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`.
|
||||
|
Loading…
Reference in New Issue
Block a user