mirror of
https://github.com/open-goal/jak-project.git
synced 2025-02-06 13:49:15 +00:00
[TypeSystem] add heap-base property to types (#431)
* support heap base in the type system * lock around modification of status
This commit is contained in:
parent
fd3121bae5
commit
62dfa1bf07
@ -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 =
|
||||
|
@ -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<MethodInfo> 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<Field>& 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;
|
||||
|
@ -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<StructureType>(parent, type_name, boxed));
|
||||
add_type(type_name, std::make_unique<StructureType>(parent, type_name, boxed, false, false, 0));
|
||||
return get_type_of_type<StructureType>(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<BasicType>(parent, type_name));
|
||||
add_type(type_name, std::make_unique<BasicType>(parent, type_name, false, 0));
|
||||
return get_type_of_type<BasicType>(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;
|
||||
|
@ -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<BasicType>(parent_type_name, name);
|
||||
auto new_type = std::make_unique<BasicType>(parent_type_name, name, false, 0);
|
||||
auto pto = dynamic_cast<BasicType*>(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<StructureType>(parent_type_name, name);
|
||||
auto new_type = std::make_unique<StructureType>(parent_type_name, name, false, false, false, 0);
|
||||
auto pto = dynamic_cast<StructureType*>(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);
|
||||
|
@ -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<std::mutex> lk(init_mutex);
|
||||
std::unique_lock<std::mutex> lk(status_mutex);
|
||||
|
||||
vm_init_cv.wait(lk, [&] { return status == Status::Inited; });
|
||||
}
|
||||
|
||||
void wait_vm_dead() {
|
||||
std::unique_lock<std::mutex> lk(dead_mutex);
|
||||
std::unique_lock<std::mutex> 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<std::mutex> 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<std::mutex> lk(status_mutex);
|
||||
status = Status::Inited;
|
||||
}
|
||||
vm_init_cv.notify_all();
|
||||
}
|
||||
|
||||
void vm_kill() {
|
||||
lg::debug("[VM] Killing");
|
||||
|
||||
status = Status::Kill;
|
||||
{
|
||||
std::unique_lock<std::mutex> 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<std::mutex> lk(status_mutex);
|
||||
status = Status::Dead;
|
||||
}
|
||||
vm_dead_cv.notify_all();
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -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)
|
||||
|
@ -207,10 +207,10 @@ TEST(TypeSystem, AddMethodAndLookupMethod) {
|
||||
TEST(TypeSystem, NewMethod) {
|
||||
TypeSystem ts;
|
||||
ts.add_builtin_types();
|
||||
ts.add_type("test-1", std::make_unique<BasicType>("basic", "test-1"));
|
||||
ts.add_type("test-1", std::make_unique<BasicType>("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<BasicType>("test-1", "test-2"));
|
||||
ts.add_type("test-2", std::make_unique<BasicType>("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<BasicType>("test-1", "test-3"));
|
||||
ts.add_type("test-3", std::make_unique<BasicType>("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<BasicType>("test-2", "test-4"));
|
||||
ts.add_type("test-4", std::make_unique<BasicType>("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<BasicType>("basic", "test-1"));
|
||||
ts.add_type("test-1", std::make_unique<BasicType>("basic", "test-1", false, 0));
|
||||
ts.add_method(ts.lookup_type("test-1"), "new",
|
||||
ts.make_function_typespec({"symbol", "string", "_type_"}, "_type_"));
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user