diff --git a/common/type_system/Type.cpp b/common/type_system/Type.cpp index 2b0318613f..6369d599bb 100644 --- a/common/type_system/Type.cpp +++ b/common/type_system/Type.cpp @@ -103,8 +103,11 @@ bool Field::operator==(const Field& other) const { // parent class of types, also has method logic. -Type::Type(std::string parent, std::string name, bool is_boxed) - : m_parent(std::move(parent)), m_name(std::move(name)), m_is_boxed(is_boxed) { +Type::Type(std::string parent, std::string name, bool is_boxed, int heap_base) + : m_parent(std::move(parent)), + m_name(std::move(name)), + m_is_boxed(is_boxed), + m_heap_base(heap_base) { m_runtime_name = m_name; } @@ -143,7 +146,8 @@ std::string Type::get_parent() const { bool Type::is_equal(const Type& other) const { return m_parent == other.m_parent && m_name == other.m_name && m_is_boxed == other.m_is_boxed && m_methods == other.m_methods && m_new_method_info == other.m_new_method_info && - m_new_method_info_defined == other.m_new_method_info_defined; + m_new_method_info_defined == other.m_new_method_info_defined && + m_heap_base == other.m_heap_base; } /*! @@ -253,7 +257,7 @@ std::string Type::print_method_info() const { // Special Type for both "none" and "_type_" types // it's an error to try to do anything with Null. -NullType::NullType(std::string name) : Type("", std::move(name), false) {} +NullType::NullType(std::string name) : Type("", std::move(name), false, 0) {} bool NullType::is_reference() const { throw std::runtime_error("is_reference called on NullType"); @@ -314,7 +318,7 @@ ValueType::ValueType(std::string parent, int size, bool sign_extend, RegClass reg) - : Type(std::move(parent), std::move(name), is_boxed), + : Type(std::move(parent), std::move(name), is_boxed, 0), m_size(size), m_sign_extend(sign_extend), m_reg_kind(reg) {} @@ -431,8 +435,8 @@ bool ValueType::operator==(const Type& other) const { // This means this type behaves like a C pointer - the thing that's passed around is a reference // to some memory somewhere. -ReferenceType::ReferenceType(std::string parent, std::string name, bool is_boxed) - : Type(std::move(parent), std::move(name), is_boxed) {} +ReferenceType::ReferenceType(std::string parent, std::string name, bool is_boxed, int heap_base) + : Type(std::move(parent), std::move(name), is_boxed, heap_base) {} /*! * By definition, this is a reference! @@ -478,8 +482,11 @@ StructureType::StructureType(std::string parent, std::string name, bool boxed, bool dynamic, - bool pack) - : ReferenceType(std::move(parent), std::move(name), boxed), m_dynamic(dynamic), m_pack(pack) {} + bool pack, + int heap_base) + : ReferenceType(std::move(parent), std::move(name), boxed, heap_base), + m_dynamic(dynamic), + m_pack(pack) {} std::string StructureType::print() const { std::string result = fmt::format( @@ -588,8 +595,8 @@ bool StructureType::lookup_field(const std::string& name, Field* out) { // BasicType ///////////////// -BasicType::BasicType(std::string parent, std::string name, bool dynamic) - : StructureType(std::move(parent), std::move(name), true, dynamic) {} +BasicType::BasicType(std::string parent, std::string name, bool dynamic, int heap_base) + : StructureType(std::move(parent), std::move(name), true, dynamic, false, heap_base) {} std::string BasicType::print() const { std::string result = diff --git a/common/type_system/Type.h b/common/type_system/Type.h index ac69c795c9..74d0979a70 100644 --- a/common/type_system/Type.h +++ b/common/type_system/Type.h @@ -93,8 +93,10 @@ class Type { bool is_boxed() const { return m_is_boxed; } + int heap_base() const { return m_heap_base; } + protected: - Type(std::string parent, std::string name, bool is_boxed); + Type(std::string parent, std::string name, bool is_boxed, int heap_base); std::vector m_methods; MethodInfo m_new_method_info; @@ -105,6 +107,8 @@ class Type { bool m_allow_in_runtime = true; std::string m_runtime_name; bool m_is_boxed = false; // does this have runtime type information? + + int m_heap_base = 0; }; /*! @@ -170,7 +174,7 @@ class ValueType : public Type { */ class ReferenceType : public Type { public: - ReferenceType(std::string parent, std::string name, bool is_boxed); + ReferenceType(std::string parent, std::string name, bool is_boxed, int heap_base); bool is_reference() const override; int get_load_size() const override; bool get_load_signed() const override; @@ -232,9 +236,10 @@ class StructureType : public ReferenceType { public: StructureType(std::string parent, std::string name, - bool boxed = false, - bool dynamic = false, - bool pack = false); + bool boxed, + bool dynamic, + bool pack, + int heap_base); std::string print() const override; void inherit(StructureType* parent); const std::vector& fields() const { return m_fields; } @@ -248,6 +253,7 @@ class StructureType : public ReferenceType { bool is_dynamic() const { return m_dynamic; } ~StructureType() = default; void set_pack(bool pack) { m_pack = pack; } + void set_heap_base(int hb) { m_heap_base = hb; } bool is_packed() const { return m_pack; } bool is_allowed_misalign() const { return m_allow_misalign; }; void set_allow_misalign(bool misalign) { m_allow_misalign = misalign; } @@ -276,7 +282,7 @@ class StructureType : public ReferenceType { class BasicType : public StructureType { public: - BasicType(std::string parent, std::string name, bool dynamic = false); + BasicType(std::string parent, std::string name, bool dynamic, int heap_base); int get_offset() const override; int get_inline_array_start_alignment() const override; std::string print() const override; diff --git a/common/type_system/TypeSystem.cpp b/common/type_system/TypeSystem.cpp index 7f5b423b15..c3c391c230 100644 --- a/common/type_system/TypeSystem.cpp +++ b/common/type_system/TypeSystem.cpp @@ -1009,7 +1009,7 @@ int TypeSystem::get_size_in_type(const Field& field) const { StructureType* TypeSystem::add_builtin_structure(const std::string& parent, const std::string& type_name, bool boxed) { - add_type(type_name, std::make_unique(parent, type_name, boxed)); + add_type(type_name, std::make_unique(parent, type_name, boxed, false, false, 0)); return get_type_of_type(type_name); } @@ -1018,7 +1018,7 @@ StructureType* TypeSystem::add_builtin_structure(const std::string& parent, * things in the wrong order. */ BasicType* TypeSystem::add_builtin_basic(const std::string& parent, const std::string& type_name) { - add_type(type_name, std::make_unique(parent, type_name)); + add_type(type_name, std::make_unique(parent, type_name, false, 0)); return get_type_of_type(type_name); } @@ -1339,11 +1339,15 @@ std::string TypeSystem::generate_deftype_footer(const Type* type) const { } } + if (type->heap_base()) { + result.append(fmt::format(" :heap-base #x{:x}\n", type->heap_base())); + } + auto method_count = get_next_method_id(type); result.append(fmt::format(" :method-count-assert {}\n", get_next_method_id(type))); result.append(fmt::format(" :size-assert #x{:x}\n", type->get_size_in_memory())); TypeFlags flags; - flags.heap_base = 0; + flags.heap_base = type->heap_base(); flags.size = type->get_size_in_memory(); flags.pad = 0; flags.methods = method_count; diff --git a/common/type_system/deftype.cpp b/common/type_system/deftype.cpp index 8df4753d78..4826ca2f31 100644 --- a/common/type_system/deftype.cpp +++ b/common/type_system/deftype.cpp @@ -433,7 +433,7 @@ DeftypeResult parse_deftype(const goos::Object& deftype, TypeSystem* ts) { DeftypeResult result; if (is_type("basic", parent_type, ts)) { - auto new_type = std::make_unique(parent_type_name, name); + auto new_type = std::make_unique(parent_type_name, name, false, 0); auto pto = dynamic_cast(ts->lookup_type(parent_type)); assert(pto); new_type->inherit(pto); @@ -451,9 +451,10 @@ DeftypeResult parse_deftype(const goos::Object& deftype, TypeSystem* ts) { name); throw std::runtime_error("invalid pack option on basic"); } + new_type->set_heap_base(result.flags.heap_base); ts->add_type(name, std::move(new_type)); } else if (is_type("structure", parent_type, ts)) { - auto new_type = std::make_unique(parent_type_name, name); + auto new_type = std::make_unique(parent_type_name, name, false, false, false, 0); auto pto = dynamic_cast(ts->lookup_type(parent_type)); assert(pto); new_type->inherit(pto); @@ -467,6 +468,7 @@ DeftypeResult parse_deftype(const goos::Object& deftype, TypeSystem* ts) { if (sr.allow_misaligned) { new_type->set_allow_misalign(true); } + new_type->set_heap_base(result.flags.heap_base); ts->add_type(name, std::move(new_type)); } else if (is_type("integer", parent_type, ts)) { auto pto = ts->lookup_type(parent_type); diff --git a/game/system/vm/vm.cpp b/game/system/vm/vm.cpp index 964d9543f7..5b59dd7c9f 100644 --- a/game/system/vm/vm.cpp +++ b/game/system/vm/vm.cpp @@ -20,20 +20,19 @@ namespace { Status status; std::condition_variable vm_init_cv; std::condition_variable vm_dead_cv; -std::mutex init_mutex; -std::mutex dead_mutex; +std::mutex status_mutex; int components = 0; } // namespace void wait_vm_init() { - std::unique_lock lk(init_mutex); + std::unique_lock lk(status_mutex); vm_init_cv.wait(lk, [&] { return status == Status::Inited; }); } void wait_vm_dead() { - std::unique_lock lk(dead_mutex); + std::unique_lock lk(status_mutex); vm_dead_cv.wait(lk, [&] { return status == Status::Dead; }); } @@ -44,7 +43,10 @@ bool vm_want_exit() { void vm_prepare() { lg::debug("[VM] Preparing..."); - status = Status::Uninited; + { + std::unique_lock lk(status_mutex); + status = Status::Uninited; + } lg::debug("[VM] Prepared"); } @@ -54,14 +56,20 @@ void vm_init() { } lg::debug("[VM] Inited"); - status = Status::Inited; + { + std::unique_lock lk(status_mutex); + status = Status::Inited; + } vm_init_cv.notify_all(); } void vm_kill() { lg::debug("[VM] Killing"); - status = Status::Kill; + { + std::unique_lock lk(status_mutex); + status = Status::Kill; + } // stall caller until VM is done dying wait_vm_dead(); @@ -81,7 +89,10 @@ void unsubscribe_component() { // the VM is "killed" when there's no more components running if (status == Status::Kill && components == 0) { - status = Status::Dead; + { + std::unique_lock lk(status_mutex); + status = Status::Dead; + } vm_dead_cv.notify_all(); } } diff --git a/goal_src/engine/camera/pov-camera-h.gc b/goal_src/engine/camera/pov-camera-h.gc index 6b9468f67e..0c9cc29569 100644 --- a/goal_src/engine/camera/pov-camera-h.gc +++ b/goal_src/engine/camera/pov-camera-h.gc @@ -15,9 +15,10 @@ (music-volume-movie float :offset-assert 212) (sfx-volume-movie float :offset-assert 216) ) + :heap-base #x70 :method-count-assert 30 :size-assert #xdc - :flag-assert #x1e000000dc + :flag-assert #x1e007000dc (:methods (dummy-20 () none 20) (dummy-21 () none 21) diff --git a/goal_src/engine/draw/drawable-ambient-h.gc b/goal_src/engine/draw/drawable-ambient-h.gc index a9fdea1ea3..c232b6333c 100644 --- a/goal_src/engine/draw/drawable-ambient-h.gc +++ b/goal_src/engine/draw/drawable-ambient-h.gc @@ -68,9 +68,10 @@ (last-time uint64 :offset-assert 152) (voicebox uint64 :offset-assert 160) ) + :heap-base #x40 :method-count-assert 16 :size-assert #xa8 - :flag-assert #x10000000a8 + :flag-assert #x10004000a8 (:methods (dummy-14 () none 14) (dummy-15 () none 15) diff --git a/goal_src/engine/gfx/time-of-day-h.gc b/goal_src/engine/gfx/time-of-day-h.gc index 5a91658865..1500cccd98 100644 --- a/goal_src/engine/gfx/time-of-day-h.gc +++ b/goal_src/engine/gfx/time-of-day-h.gc @@ -56,9 +56,10 @@ (moon-count int32 :offset-assert 176) (moon basic :offset-assert 180) ) + :heap-base #x50 :method-count-assert 14 :size-assert #xb8 - :flag-assert #xe000000b8 + :flag-assert #xe005000b8 ) (deftype time-of-day-palette (basic) diff --git a/goal_src/engine/ui/hud-h.gc b/goal_src/engine/ui/hud-h.gc index d86075d060..7ec3c04d1b 100644 --- a/goal_src/engine/ui/hud-h.gc +++ b/goal_src/engine/ui/hud-h.gc @@ -60,9 +60,10 @@ (nb-of-particles int32 :offset-assert 248) (particles hud-particle 7 :offset-assert 252) ) + :heap-base #xb0 :method-count-assert 27 :size-assert #x118 - :flag-assert #x1b00000118 + :flag-assert #x1b00b00118 (:methods (dummy-14 () none 14) (dummy-15 () none 15) diff --git a/test/decompiler/reference/engine/camera/pov-camera-h_REF.gc b/test/decompiler/reference/engine/camera/pov-camera-h_REF.gc index 397a63e26c..cfae9b3491 100644 --- a/test/decompiler/reference/engine/camera/pov-camera-h_REF.gc +++ b/test/decompiler/reference/engine/camera/pov-camera-h_REF.gc @@ -12,9 +12,10 @@ (music-volume-movie float :offset-assert 212) (sfx-volume-movie float :offset-assert 216) ) + :heap-base #x70 :method-count-assert 30 :size-assert #xdc - :flag-assert #x1e000000dc + :flag-assert #x1e007000dc (:methods (dummy-20 () none 20) (dummy-21 () none 21) diff --git a/test/decompiler/reference/engine/draw/drawable-ambient-h_REF.gc b/test/decompiler/reference/engine/draw/drawable-ambient-h_REF.gc index a35e25406b..410805eb1d 100644 --- a/test/decompiler/reference/engine/draw/drawable-ambient-h_REF.gc +++ b/test/decompiler/reference/engine/draw/drawable-ambient-h_REF.gc @@ -64,9 +64,10 @@ (last-time uint64 :offset-assert 152) (voicebox uint64 :offset-assert 160) ) + :heap-base #x40 :method-count-assert 16 :size-assert #xa8 - :flag-assert #x10000000a8 + :flag-assert #x10004000a8 (:methods (dummy-14 () none 14) (dummy-15 () none 15) diff --git a/test/decompiler/reference/engine/ui/hud-h_REF.gc b/test/decompiler/reference/engine/ui/hud-h_REF.gc index 4b2412b02d..4193ac7f07 100644 --- a/test/decompiler/reference/engine/ui/hud-h_REF.gc +++ b/test/decompiler/reference/engine/ui/hud-h_REF.gc @@ -78,9 +78,10 @@ (nb-of-particles int32 :offset-assert 248) (particles hud-particle 7 :offset-assert 252) ) + :heap-base #xb0 :method-count-assert 27 :size-assert #x118 - :flag-assert #x1b00000118 + :flag-assert #x1b00b00118 (:methods (dummy-14 () none 14) (dummy-15 () none 15) diff --git a/test/test_type_system.cpp b/test/test_type_system.cpp index 153ffbbd16..3813197444 100644 --- a/test/test_type_system.cpp +++ b/test/test_type_system.cpp @@ -207,10 +207,10 @@ TEST(TypeSystem, AddMethodAndLookupMethod) { TEST(TypeSystem, NewMethod) { TypeSystem ts; ts.add_builtin_types(); - ts.add_type("test-1", std::make_unique("basic", "test-1")); + ts.add_type("test-1", std::make_unique("basic", "test-1", false, 0)); ts.add_method(ts.lookup_type("test-1"), "new", ts.make_function_typespec({"symbol", "string"}, "test-1")); - ts.add_type("test-2", std::make_unique("test-1", "test-2")); + ts.add_type("test-2", std::make_unique("test-1", "test-2", false, 0)); ts.add_method(ts.lookup_type("test-2"), "new", ts.make_function_typespec({"symbol", "string", "symbol"}, "test-2")); @@ -218,10 +218,10 @@ TEST(TypeSystem, NewMethod) { EXPECT_EQ(ts.lookup_method("test-2", "new").type.print(), "(function symbol string symbol test-2)"); - ts.add_type("test-3", std::make_unique("test-1", "test-3")); + ts.add_type("test-3", std::make_unique("test-1", "test-3", false, 0)); EXPECT_EQ(ts.lookup_method("test-3", "new").type.print(), "(function symbol string test-1)"); - ts.add_type("test-4", std::make_unique("test-2", "test-4")); + ts.add_type("test-4", std::make_unique("test-2", "test-4", false, 0)); EXPECT_EQ(ts.lookup_method("test-4", "new").type.print(), "(function symbol string symbol test-2)"); } @@ -229,7 +229,7 @@ TEST(TypeSystem, NewMethod) { TEST(TypeSystem, MethodSubstitute) { TypeSystem ts; ts.add_builtin_types(); - ts.add_type("test-1", std::make_unique("basic", "test-1")); + ts.add_type("test-1", std::make_unique("basic", "test-1", false, 0)); ts.add_method(ts.lookup_type("test-1"), "new", ts.make_function_typespec({"symbol", "string", "_type_"}, "_type_"));