From 9303b0225e4092c9e28207010ec611f655ac0765 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alf-Andr=C3=A9=20Walla?= Date: Sat, 26 Oct 2024 13:32:08 +0200 Subject: [PATCH] Implement hot-reloading support for ELFScript --- src/elf/script_elf.cpp | 17 ++++++++++++++--- src/elf/script_elf.h | 5 +++++ src/sandbox.cpp | 16 ++++++++++++++-- src/sandbox.h | 1 + 4 files changed, 34 insertions(+), 5 deletions(-) diff --git a/src/elf/script_elf.cpp b/src/elf/script_elf.cpp index 3a9c81c..f2f3d79 100644 --- a/src/elf/script_elf.cpp +++ b/src/elf/script_elf.cpp @@ -271,7 +271,15 @@ String ELFScript::get_elf_programming_language() const { void ELFScript::set_file(const String &p_path) { path = p_path; - source_code = FileAccess::get_file_as_bytes(path); + PackedByteArray new_source_code = FileAccess::get_file_as_bytes(path); + if (new_source_code == source_code) { + if constexpr (VERBOSE_ELFSCRIPT) { + printf("ELFScript::set_file: No changes in %s\n", path.utf8().ptr()); + } + return; + } + source_code = std::move(new_source_code); + global_name = "Sandbox_" + path.get_basename().replace("res://", "").replace("/", "_").replace("-", "_").capitalize().replace(" ", ""); Sandbox::BinaryInfo info = Sandbox::get_program_info_from_binary(source_code); info.functions.sort(); @@ -279,8 +287,11 @@ void ELFScript::set_file(const String &p_path) { this->elf_programming_language = info.language; this->elf_api_version = info.version; - for (ELFScriptInstance *instance : instances) { - instance->reload(this); + if constexpr (VERBOSE_ELFSCRIPT) { + printf("ELFScript::set_file: %s Sandbox instances: %d\n", path.utf8().ptr(), sandbox_map[path].size()); + } + for (Sandbox *sandbox : sandbox_map[path]) { + sandbox->set_program(Ref(this)); } } diff --git a/src/elf/script_elf.h b/src/elf/script_elf.h index 6d907df..7dc72a9 100644 --- a/src/elf/script_elf.h +++ b/src/elf/script_elf.h @@ -26,6 +26,8 @@ class ELFScript : public ScriptExtension { mutable HashSet instances; friend class ELFScriptInstance; + static inline HashMap> sandbox_map; + public: PackedStringArray functions; String get_elf_programming_language() const; @@ -47,6 +49,9 @@ class ELFScript : public ScriptExtension { /// @return An ELF program as a byte array. const PackedByteArray &get_content(); + void register_instance(Sandbox *p_sandbox) { sandbox_map[path].insert(p_sandbox); } + void unregister_instance(Sandbox *p_sandbox) { sandbox_map[path].erase(p_sandbox); } + virtual bool _editor_can_reload_from_file() override; virtual void _placeholder_erased(void *p_placeholder) override; virtual bool _can_instantiate() const override; diff --git a/src/sandbox.cpp b/src/sandbox.cpp index f5c9838..2711652 100644 --- a/src/sandbox.cpp +++ b/src/sandbox.cpp @@ -209,6 +209,7 @@ Sandbox::~Sandbox() { ERR_PRINT("Sandbox instance destroyed while a VM call is in progress."); } this->m_global_instance_count -= 1; + this->set_program_data_internal(nullptr); try { if (this->m_machine != dummy_machine) delete this->m_machine; @@ -244,7 +245,7 @@ void Sandbox::set_program(Ref program) { property_values.push_back(value); } - this->m_program_data = program; + this->set_program_data_internal(program); this->m_program_bytes = {}; // Unload program and reset the machine @@ -273,6 +274,17 @@ void Sandbox::set_program(Ref program) { } } } +void Sandbox::set_program_data_internal(Ref program) { + if (this->m_program_data.is_valid()) { + //printf("Sandbox %p: Program *unset* from %s\n", this, this->m_program_data->get_path().utf8().ptr()); + this->m_program_data->unregister_instance(this); + } + this->m_program_data = program; + if (this->m_program_data.is_valid()) { + //printf("Sandbox %p: Program set to %s\n", this, this->m_program_data->get_path().utf8().ptr()); + this->m_program_data->register_instance(this); + } +} Ref Sandbox::get_program() { return m_program_data; } @@ -284,7 +296,7 @@ void Sandbox::load_buffer(const PackedByteArray &buffer) { return; } - this->m_program_data.unref(); + this->set_program_data_internal(nullptr); this->m_program_bytes = buffer; this->load(&this->m_program_bytes); } diff --git a/src/sandbox.h b/src/sandbox.h index d4788cd..166e95e 100644 --- a/src/sandbox.h +++ b/src/sandbox.h @@ -441,6 +441,7 @@ class Sandbox : public Node { void constructor_initialize(); void full_reset(); void reset_machine(); + void set_program_data_internal(Ref program); bool load(const PackedByteArray *vbuf, const std::vector *argv = nullptr); void read_program_properties(bool editor) const; void handle_exception(gaddr_t);