diff options
Diffstat (limited to 'modules/gdscript/gdscript_byte_codegen.cpp')
-rw-r--r-- | modules/gdscript/gdscript_byte_codegen.cpp | 204 |
1 files changed, 123 insertions, 81 deletions
diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp index 6c80fb7665..45008b0e87 100644 --- a/modules/gdscript/gdscript_byte_codegen.cpp +++ b/modules/gdscript/gdscript_byte_codegen.cpp @@ -143,6 +143,11 @@ void GDScriptByteCodeGenerator::pop_temporary() { ERR_FAIL_COND(used_temporaries.is_empty()); int slot_idx = used_temporaries.back()->get(); const StackSlot &slot = temporaries[slot_idx]; + if (slot.type == Variant::OBJECT) { + // Avoid keeping in the stack long-lived references to objects, + // which may prevent RefCounted objects from being freed. + write_assign_false(Address(Address::TEMPORARY, slot_idx)); + } temporaries_pool[slot.type].push_back(slot_idx); used_temporaries.pop_back(); } @@ -401,6 +406,16 @@ GDScriptFunction *GDScriptByteCodeGenerator::write_end() { function->_instruction_args_size = instr_args_max; function->_ptrcall_args_size = ptrcall_max; +#ifdef DEBUG_ENABLED + function->operator_names = operator_names; + function->setter_names = setter_names; + function->getter_names = getter_names; + function->builtin_methods_names = builtin_methods_names; + function->constructors_names = constructors_names; + function->utilities_names = utilities_names; + function->gds_utilities_names = gds_utilities_names; +#endif + ended = true; return function; } @@ -551,6 +566,9 @@ void GDScriptByteCodeGenerator::write_unary_operator(const Address &p_target, Va append(Address()); append(p_target); append(op_func); +#ifdef DEBUG_ENABLED + add_debug_name(operator_names, get_operation_pos(op_func), Variant::get_operator_name(p_operator)); +#endif return; } @@ -580,6 +598,9 @@ void GDScriptByteCodeGenerator::write_binary_operator(const Address &p_target, V append(p_right_operand); append(p_target); append(op_func); +#ifdef DEBUG_ENABLED + add_debug_name(operator_names, get_operation_pos(op_func), Variant::get_operator_name(p_operator)); +#endif return; } @@ -765,6 +786,9 @@ void GDScriptByteCodeGenerator::write_set_named(const Address &p_target, const S append(p_target); append(p_source); append(setter); +#ifdef DEBUG_ENABLED + add_debug_name(setter_names, get_setter_pos(setter), p_name); +#endif return; } append_opcode(GDScriptFunction::OPCODE_SET_NAMED); @@ -780,6 +804,9 @@ void GDScriptByteCodeGenerator::write_get_named(const Address &p_target, const S append(p_source); append(p_target); append(getter); +#ifdef DEBUG_ENABLED + add_debug_name(getter_names, get_getter_pos(getter), p_name); +#endif return; } append_opcode(GDScriptFunction::OPCODE_GET_NAMED); @@ -804,9 +831,13 @@ void GDScriptByteCodeGenerator::write_assign_with_conversion(const Address &p_ta switch (p_target.type.kind) { case GDScriptDataType::BUILTIN: { if (p_target.type.builtin_type == Variant::ARRAY && p_target.type.has_container_element_type()) { + const GDScriptDataType &element_type = p_target.type.get_container_element_type(); append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_ARRAY); append(p_target); append(p_source); + append(get_constant_pos(element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS)); + append(element_type.builtin_type); + append(element_type.native_type); } else { append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN); append(p_target); @@ -846,9 +877,13 @@ void GDScriptByteCodeGenerator::write_assign_with_conversion(const Address &p_ta void GDScriptByteCodeGenerator::write_assign(const Address &p_target, const Address &p_source) { if (p_target.type.kind == GDScriptDataType::BUILTIN && p_target.type.builtin_type == Variant::ARRAY && p_target.type.has_container_element_type()) { + const GDScriptDataType &element_type = p_target.type.get_container_element_type(); append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_ARRAY); append(p_target); append(p_source); + append(get_constant_pos(element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS)); + append(element_type.builtin_type); + append(element_type.native_type); } else if (p_target.type.kind == GDScriptDataType::BUILTIN && p_source.type.kind == GDScriptDataType::BUILTIN && p_target.type.builtin_type != p_source.type.builtin_type) { // Need conversion. append_opcode(GDScriptFunction::OPCODE_ASSIGN_TYPED_BUILTIN); @@ -924,7 +959,7 @@ void GDScriptByteCodeGenerator::write_cast(const Address &p_target, const Addres append(index); } -GDScriptCodeGenerator::Address GDScriptByteCodeGenerator::get_call_target(const GDScriptCodeGenerator::Address &p_target, Variant::Type p_type) { +GDScriptByteCodeGenerator::CallTarget GDScriptByteCodeGenerator::get_call_target(const GDScriptCodeGenerator::Address &p_target, Variant::Type p_type) { if (p_target.mode == Address::NIL) { GDScriptDataType type; if (p_type != Variant::NIL) { @@ -933,10 +968,9 @@ GDScriptCodeGenerator::Address GDScriptByteCodeGenerator::get_call_target(const type.builtin_type = p_type; } uint32_t addr = add_temporary(type); - pop_temporary(); - return Address(Address::TEMPORARY, addr, type); + return CallTarget(Address(Address::TEMPORARY, addr, type), true, this); } else { - return p_target; + return CallTarget(p_target, false, this); } } @@ -946,9 +980,11 @@ void GDScriptByteCodeGenerator::write_call(const Address &p_target, const Addres append(p_arguments[i]); } append(p_base); - append(get_call_target(p_target)); + CallTarget ct = get_call_target(p_target); + append(ct.target); append(p_arguments.size()); append(p_function_name); + ct.cleanup(); } void GDScriptByteCodeGenerator::write_super_call(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) { @@ -956,9 +992,11 @@ void GDScriptByteCodeGenerator::write_super_call(const Address &p_target, const for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } - append(get_call_target(p_target)); + CallTarget ct = get_call_target(p_target); + append(ct.target); append(p_arguments.size()); append(p_function_name); + ct.cleanup(); } void GDScriptByteCodeGenerator::write_call_async(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) { @@ -967,19 +1005,27 @@ void GDScriptByteCodeGenerator::write_call_async(const Address &p_target, const append(p_arguments[i]); } append(p_base); - append(get_call_target(p_target)); + CallTarget ct = get_call_target(p_target); + append(ct.target); append(p_arguments.size()); append(p_function_name); + ct.cleanup(); } -void GDScriptByteCodeGenerator::write_call_gdscript_utility(const Address &p_target, GDScriptUtilityFunctions::FunctionPtr p_function, const Vector<Address> &p_arguments) { +void GDScriptByteCodeGenerator::write_call_gdscript_utility(const Address &p_target, const StringName &p_function, const Vector<Address> &p_arguments) { append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_GDSCRIPT_UTILITY, 1 + p_arguments.size()); + GDScriptUtilityFunctions::FunctionPtr gds_function = GDScriptUtilityFunctions::get_function(p_function); for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } - append(get_call_target(p_target)); + CallTarget ct = get_call_target(p_target); + append(ct.target); append(p_arguments.size()); - append(p_function); + append(gds_function); + ct.cleanup(); +#ifdef DEBUG_ENABLED + add_debug_name(gds_utilities_names, get_gds_utility_pos(gds_function), p_function); +#endif } void GDScriptByteCodeGenerator::write_call_utility(const Address &p_target, const StringName &p_function, const Vector<Address> &p_arguments) { @@ -1000,26 +1046,32 @@ void GDScriptByteCodeGenerator::write_call_utility(const Address &p_target, cons if (is_validated) { Variant::Type result_type = Variant::has_utility_function_return_value(p_function) ? Variant::get_utility_function_return_type(p_function) : Variant::NIL; - Address target = get_call_target(p_target, result_type); - Variant::Type temp_type = temporaries[target.address].type; + CallTarget ct = get_call_target(p_target, result_type); + Variant::Type temp_type = temporaries[ct.target.address].type; if (result_type != temp_type) { - write_type_adjust(target, result_type); + write_type_adjust(ct.target, result_type); } append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_UTILITY_VALIDATED, 1 + p_arguments.size()); for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } - append(target); + append(ct.target); append(p_arguments.size()); append(Variant::get_validated_utility_function(p_function)); + ct.cleanup(); +#ifdef DEBUG_ENABLED + add_debug_name(utilities_names, get_utility_pos(Variant::get_validated_utility_function(p_function)), p_function); +#endif } else { append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_UTILITY, 1 + p_arguments.size()); for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } - append(get_call_target(p_target)); + CallTarget ct = get_call_target(p_target); + append(ct.target); append(p_arguments.size()); append(p_function); + ct.cleanup(); } } @@ -1048,10 +1100,12 @@ void GDScriptByteCodeGenerator::write_call_builtin_type(const Address &p_target, for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } - append(get_call_target(p_target)); + CallTarget ct = get_call_target(p_target); + append(ct.target); append(p_type); append(p_method); append(p_arguments.size()); + ct.cleanup(); } else { write_call(p_target, p_base, p_method, p_arguments); } @@ -1059,10 +1113,10 @@ void GDScriptByteCodeGenerator::write_call_builtin_type(const Address &p_target, } Variant::Type result_type = Variant::get_builtin_method_return_type(p_type, p_method); - Address target = get_call_target(p_target, result_type); - Variant::Type temp_type = temporaries[target.address].type; + CallTarget ct = get_call_target(p_target, result_type); + Variant::Type temp_type = temporaries[ct.target.address].type; if (result_type != temp_type) { - write_type_adjust(target, result_type); + write_type_adjust(ct.target, result_type); } append_opcode_and_argcount(GDScriptFunction::OPCODE_CALL_BUILTIN_TYPE_VALIDATED, 2 + p_arguments.size()); @@ -1071,9 +1125,14 @@ void GDScriptByteCodeGenerator::write_call_builtin_type(const Address &p_target, append(p_arguments[i]); } append(p_base); - append(target); + append(ct.target); append(p_arguments.size()); append(Variant::get_validated_builtin_method(p_type, p_method)); + ct.cleanup(); + +#ifdef DEBUG_ENABLED + add_debug_name(builtin_methods_names, get_builtin_method_pos(Variant::get_validated_builtin_method(p_type, p_method)), p_method); +#endif } void GDScriptByteCodeGenerator::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) { @@ -1095,9 +1154,11 @@ void GDScriptByteCodeGenerator::write_call_native_static(const Address &p_target for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } - append(get_call_target(p_target)); + CallTarget ct = get_call_target(p_target); + append(ct.target); append(method); append(p_arguments.size()); + ct.cleanup(); return; } } @@ -1107,10 +1168,12 @@ void GDScriptByteCodeGenerator::write_call_method_bind(const Address &p_target, for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } + CallTarget ct = get_call_target(p_target); append(p_base); - append(get_call_target(p_target)); + append(ct.target); append(p_arguments.size()); append(p_method); + ct.cleanup(); } void GDScriptByteCodeGenerator::write_call_ptrcall(const Address &p_target, const Address &p_base, MethodBind *p_method, const Vector<Address> &p_arguments) { @@ -1172,9 +1235,11 @@ void GDScriptByteCodeGenerator::write_call_ptrcall(const Address &p_target, cons append(p_arguments[i]); } append(p_base); - append(get_call_target(p_target)); + 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()); } @@ -1188,9 +1253,11 @@ void GDScriptByteCodeGenerator::write_call_self(const Address &p_target, const S append(p_arguments[i]); } append(GDScriptFunction::ADDR_TYPE_STACK << GDScriptFunction::ADDR_BITS); - append(get_call_target(p_target)); + CallTarget ct = get_call_target(p_target); + append(ct.target); append(p_arguments.size()); append(p_function_name); + ct.cleanup(); } void GDScriptByteCodeGenerator::write_call_self_async(const Address &p_target, const StringName &p_function_name, const Vector<Address> &p_arguments) { @@ -1199,9 +1266,11 @@ void GDScriptByteCodeGenerator::write_call_self_async(const Address &p_target, c append(p_arguments[i]); } append(GDScriptFunction::ADDR_SELF); - append(get_call_target(p_target)); + CallTarget ct = get_call_target(p_target); + append(ct.target); append(p_arguments.size()); append(p_function_name); + ct.cleanup(); } void GDScriptByteCodeGenerator::write_call_script_function(const Address &p_target, const Address &p_base, const StringName &p_function_name, const Vector<Address> &p_arguments) { @@ -1210,9 +1279,11 @@ void GDScriptByteCodeGenerator::write_call_script_function(const Address &p_targ append(p_arguments[i]); } append(p_base); - append(get_call_target(p_target)); + CallTarget ct = get_call_target(p_target); + append(ct.target); append(p_arguments.size()); append(p_function_name); + ct.cleanup(); } void GDScriptByteCodeGenerator::write_lambda(const Address &p_target, GDScriptFunction *p_function, const Vector<Address> &p_captures, bool p_use_self) { @@ -1221,9 +1292,11 @@ void GDScriptByteCodeGenerator::write_lambda(const Address &p_target, GDScriptFu append(p_captures[i]); } - append(get_call_target(p_target)); + CallTarget ct = get_call_target(p_target); + append(ct.target); append(p_captures.size()); append(p_function); + ct.cleanup(); } void GDScriptByteCodeGenerator::write_construct(const Address &p_target, Variant::Type p_type, const Vector<Address> &p_arguments) { @@ -1260,9 +1333,14 @@ void GDScriptByteCodeGenerator::write_construct(const Address &p_target, Variant for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } - append(get_call_target(p_target)); + CallTarget ct = get_call_target(p_target); + append(ct.target); append(p_arguments.size()); append(Variant::get_validated_constructor(p_type, valid_constructor)); + ct.cleanup(); +#ifdef DEBUG_ENABLED + add_debug_name(constructors_names, get_constructor_pos(Variant::get_validated_constructor(p_type, valid_constructor)), Variant::get_type_name(p_type)); +#endif return; } } @@ -1271,9 +1349,11 @@ void GDScriptByteCodeGenerator::write_construct(const Address &p_target, Variant for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } - append(get_call_target(p_target)); + CallTarget ct = get_call_target(p_target); + append(ct.target); append(p_arguments.size()); append(p_type); + ct.cleanup(); } void GDScriptByteCodeGenerator::write_construct_array(const Address &p_target, const Vector<Address> &p_arguments) { @@ -1281,8 +1361,10 @@ void GDScriptByteCodeGenerator::write_construct_array(const Address &p_target, c for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } - append(get_call_target(p_target)); + CallTarget ct = get_call_target(p_target); + append(ct.target); append(p_arguments.size()); + ct.cleanup(); } void GDScriptByteCodeGenerator::write_construct_typed_array(const Address &p_target, const GDScriptDataType &p_element_type, const Vector<Address> &p_arguments) { @@ -1290,18 +1372,13 @@ void GDScriptByteCodeGenerator::write_construct_typed_array(const Address &p_tar for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } - append(get_call_target(p_target)); - if (p_element_type.script_type) { - Variant script_type = Ref<Script>(p_element_type.script_type); - int addr = get_constant_pos(script_type); - addr |= GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS; - append(addr); - } else { - append(Address()); // null. - } + CallTarget ct = get_call_target(p_target); + append(ct.target); + append(get_constant_pos(p_element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS)); append(p_arguments.size()); append(p_element_type.builtin_type); append(p_element_type.native_type); + ct.cleanup(); } void GDScriptByteCodeGenerator::write_construct_dictionary(const Address &p_target, const Vector<Address> &p_arguments) { @@ -1309,8 +1386,10 @@ void GDScriptByteCodeGenerator::write_construct_dictionary(const Address &p_targ for (int i = 0; i < p_arguments.size(); i++) { append(p_arguments[i]); } - append(get_call_target(p_target)); + CallTarget ct = get_call_target(p_target); + append(ct.target); append(p_arguments.size() / 2); // This is number of key-value pairs, so only half of actual arguments. + ct.cleanup(); } void GDScriptByteCodeGenerator::write_await(const Address &p_target, const Address &p_operand) { @@ -1543,28 +1622,6 @@ void GDScriptByteCodeGenerator::write_endwhile() { current_breaks_to_patch.pop_back(); } -void GDScriptByteCodeGenerator::start_match() { - match_continues_to_patch.push_back(List<int>()); -} - -void GDScriptByteCodeGenerator::start_match_branch() { - // Patch continue statements. - for (const int &E : match_continues_to_patch.back()->get()) { - patch_jump(E); - } - match_continues_to_patch.pop_back(); - // Start a new list for next branch. - match_continues_to_patch.push_back(List<int>()); -} - -void GDScriptByteCodeGenerator::end_match() { - // Patch continue statements. - for (const int &E : match_continues_to_patch.back()->get()) { - patch_jump(E); - } - match_continues_to_patch.pop_back(); -} - void GDScriptByteCodeGenerator::write_break() { append_opcode(GDScriptFunction::OPCODE_JUMP); current_breaks_to_patch.back()->get().push_back(opcodes.size()); @@ -1576,12 +1633,6 @@ void GDScriptByteCodeGenerator::write_continue() { append(continue_addrs.back()->get()); } -void GDScriptByteCodeGenerator::write_continue_match() { - append_opcode(GDScriptFunction::OPCODE_JUMP); - match_continues_to_patch.back()->get().push_back(opcodes.size()); - append(0); -} - void GDScriptByteCodeGenerator::write_breakpoint() { append_opcode(GDScriptFunction::OPCODE_BREAKPOINT); } @@ -1601,14 +1652,10 @@ void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) { if (function->return_type.kind == GDScriptDataType::BUILTIN && function->return_type.builtin_type == Variant::ARRAY && function->return_type.has_container_element_type()) { // Typed array. const GDScriptDataType &element_type = function->return_type.get_container_element_type(); - - Variant script = element_type.script_type; - int script_idx = get_constant_pos(script) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS); - append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_ARRAY); append(p_return_value); - append(script_idx); - append(element_type.kind == GDScriptDataType::BUILTIN ? element_type.builtin_type : Variant::OBJECT); + append(get_constant_pos(element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS)); + append(element_type.builtin_type); append(element_type.native_type); } else if (function->return_type.kind == GDScriptDataType::BUILTIN && p_return_value.type.kind == GDScriptDataType::BUILTIN && function->return_type.builtin_type != p_return_value.type.builtin_type) { // Add conversion. @@ -1629,15 +1676,10 @@ void GDScriptByteCodeGenerator::write_return(const Address &p_return_value) { case GDScriptDataType::BUILTIN: { if (function->return_type.builtin_type == Variant::ARRAY && function->return_type.has_container_element_type()) { const GDScriptDataType &element_type = function->return_type.get_container_element_type(); - - Variant script = function->return_type.script_type; - int script_idx = get_constant_pos(script); - script_idx |= (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS); - append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_ARRAY); append(p_return_value); - append(script_idx); - append(element_type.kind == GDScriptDataType::BUILTIN ? element_type.builtin_type : Variant::OBJECT); + append(get_constant_pos(element_type.script_type) | (GDScriptFunction::ADDR_TYPE_CONSTANT << GDScriptFunction::ADDR_BITS)); + append(element_type.builtin_type); append(element_type.native_type); } else { append_opcode(GDScriptFunction::OPCODE_RETURN_TYPED_BUILTIN); |