[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:
water111 2021-05-09 19:40:36 -04:00 committed by GitHub
parent fd3121bae5
commit 62dfa1bf07
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 79 additions and 42 deletions

View file

@ -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 =

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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();
}
}

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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)

View file

@ -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_"));