summaryrefslogtreecommitdiff
path: root/modules/gdscript/gdscript_byte_codegen.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'modules/gdscript/gdscript_byte_codegen.cpp')
-rw-r--r--modules/gdscript/gdscript_byte_codegen.cpp204
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);