diff options
author | Pedro J. Estébanez <pedrojrulez@gmail.com> | 2023-04-11 17:20:03 +0200 |
---|---|---|
committer | Pedro J. Estébanez <pedrojrulez@gmail.com> | 2023-04-11 17:27:39 +0200 |
commit | 2f4168daeba6e70de51bb2abbad1cc0b0bc54fe4 (patch) | |
tree | d2178d64ff87b3481eb153ba41cf82540685fec6 /modules/gdscript/gdscript_byte_codegen.cpp | |
parent | 59b8c700072c6bb25b0f1f95c40e54941d941383 (diff) | |
download | redot-engine-2f4168daeba6e70de51bb2abbad1cc0b0bc54fe4.tar.gz |
Fix edge cases of object lifetime when signals involved
Diffstat (limited to 'modules/gdscript/gdscript_byte_codegen.cpp')
-rw-r--r-- | modules/gdscript/gdscript_byte_codegen.cpp | 21 |
1 files changed, 20 insertions, 1 deletions
diff --git a/modules/gdscript/gdscript_byte_codegen.cpp b/modules/gdscript/gdscript_byte_codegen.cpp index eb827d375c..1414075ba8 100644 --- a/modules/gdscript/gdscript_byte_codegen.cpp +++ b/modules/gdscript/gdscript_byte_codegen.cpp @@ -142,7 +142,9 @@ void GDScriptByteCodeGenerator::pop_temporary() { if (slot.type == Variant::NIL) { // 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)); + // However, the cleanup will be performed an the end of the + // statement, to allow object references to survive chaining. + temporaries_pending_clear.push_back(slot_idx); } temporaries_pool[slot.type].push_back(slot_idx); used_temporaries.pop_back(); @@ -1752,6 +1754,23 @@ void GDScriptByteCodeGenerator::end_block() { pop_stack_identifiers(); } +void GDScriptByteCodeGenerator::clean_temporaries() { + List<int>::Element *E = temporaries_pending_clear.front(); + while (E) { + // The temporary may have been re-used as something else than an object + // since it was added to the list. In that case, there's no need to clear it. + int slot_idx = E->get(); + const StackSlot &slot = temporaries[slot_idx]; + if (slot.type == Variant::NIL) { + write_assign_false(Address(Address::TEMPORARY, slot_idx)); + } + + List<int>::Element *next = E->next(); + E->erase(); + E = next; + } +} + GDScriptByteCodeGenerator::~GDScriptByteCodeGenerator() { if (!ended && function != nullptr) { memdelete(function); |