mirror of
https://git.sfja.dk/Mikkel/slige.git
synced 2025-01-18 10:56:30 +00:00
garbage collector heap
This commit is contained in:
parent
4dccbcb17a
commit
e9c70f71b7
170
runtime/alloc.hpp
Normal file
170
runtime/alloc.hpp
Normal file
@ -0,0 +1,170 @@
|
||||
#pragma once
|
||||
|
||||
#include "value.hpp"
|
||||
#include <cstddef>
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <variant>
|
||||
#include <vector>
|
||||
|
||||
namespace sliger::heap {
|
||||
|
||||
struct Array {
|
||||
std::vector<Value> values;
|
||||
};
|
||||
|
||||
struct Struct {
|
||||
std::unordered_map<std::string, Value> fields;
|
||||
};
|
||||
|
||||
enum class AllocType {
|
||||
Value,
|
||||
Array,
|
||||
Struct,
|
||||
};
|
||||
|
||||
// clang-format off
|
||||
template <AllocType type> struct AllocTypeType {};
|
||||
template <> struct AllocTypeType<AllocType::Value> { using Type = Value; };
|
||||
template <> struct AllocTypeType<AllocType::Array> { using Type = Array; };
|
||||
template <> struct AllocTypeType<AllocType::Struct> { using Type = Struct; };
|
||||
// clang-format on
|
||||
|
||||
struct AllocItem {
|
||||
template <AllocType AT> inline auto as() & -> AllocTypeType<AT>::Type&
|
||||
{
|
||||
return std::get<typename AllocTypeType<AT>::Type>(this->value);
|
||||
}
|
||||
template <AllocType AT>
|
||||
inline auto as() const& -> const AllocTypeType<AT>::Type&
|
||||
{
|
||||
return std::get<typename AllocTypeType<AT>::Type>(this->value);
|
||||
}
|
||||
template <AllocType AT> inline auto as() && -> AllocTypeType<AT>::Type&&
|
||||
{
|
||||
return std::move(
|
||||
std::get<typename AllocTypeType<AT>::Type>(this->value));
|
||||
}
|
||||
template <AllocType AT>
|
||||
inline auto as() const&& -> const AllocTypeType<AT>::Type&&
|
||||
{
|
||||
return std::move(
|
||||
std::get<typename AllocTypeType<AT>::Type>(this->value));
|
||||
}
|
||||
|
||||
AllocType type;
|
||||
std::variant<Value, Array, Struct> value;
|
||||
};
|
||||
|
||||
enum class ErrType {
|
||||
InvalidPtrAccess,
|
||||
CannotAllocate,
|
||||
};
|
||||
|
||||
template <typename T> struct Res {
|
||||
Res(T val)
|
||||
: val(std::forward<T>(val))
|
||||
{
|
||||
}
|
||||
Res(ErrType err)
|
||||
: err(err)
|
||||
{
|
||||
}
|
||||
|
||||
std::optional<T> val;
|
||||
std::optional<ErrType> err;
|
||||
};
|
||||
|
||||
class Heap {
|
||||
public:
|
||||
inline auto can_allocate() const -> bool
|
||||
{
|
||||
return this->sel->size() < this->max_size;
|
||||
}
|
||||
|
||||
inline void collect(const std::vector<uint32_t>& ptr_stack_values)
|
||||
{
|
||||
this->other->reserve(this->max_size);
|
||||
for (auto ptr : ptr_stack_values) {
|
||||
move_item_to_other(ptr);
|
||||
}
|
||||
this->sel->clear();
|
||||
std::swap(this->sel, this->other);
|
||||
if (this->sel->size() + 1 >= this->max_size) {
|
||||
this->max_size *= 2;
|
||||
this->sel->reserve(this->max_size);
|
||||
} else if (this->sel->size() * 2 < this->max_size) {
|
||||
this->max_size /= 2;
|
||||
this->sel->shrink_to_fit();
|
||||
this->sel->reserve(this->max_size);
|
||||
}
|
||||
}
|
||||
|
||||
inline auto at(uint32_t ptr) -> Res<AllocItem*>
|
||||
{
|
||||
if (ptr >= this->sel->size()) {
|
||||
return ErrType::InvalidPtrAccess;
|
||||
}
|
||||
return &this->sel->at(ptr);
|
||||
}
|
||||
|
||||
template <AllocType type> auto alloc() -> Res<uint32_t>
|
||||
{
|
||||
if (not can_allocate()) {
|
||||
return ErrType::CannotAllocate;
|
||||
}
|
||||
auto ptr = static_cast<uint32_t>(this->sel->size());
|
||||
this->sel->push_back(typename AllocTypeType<type>::Type {});
|
||||
return ptr;
|
||||
}
|
||||
|
||||
private:
|
||||
inline void move_item_to_other(uint32_t ptr)
|
||||
{
|
||||
auto res = at(ptr);
|
||||
if (!res.val.has_value())
|
||||
return;
|
||||
auto val = res.val.value();
|
||||
switch (val->type) {
|
||||
case AllocType::Value: {
|
||||
auto& v = val->as<AllocType::Value>();
|
||||
if (v.type() == ValueType::Ptr) {
|
||||
move_item_to_other(v.template as<ValueType::Ptr>().value);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AllocType::Array: {
|
||||
auto& vs = val->as<AllocType::Array>();
|
||||
for (auto& v : vs.values) {
|
||||
if (v.type() == ValueType::Ptr) {
|
||||
move_item_to_other(
|
||||
v.template as<ValueType::Ptr>().value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
case AllocType::Struct: {
|
||||
auto& vs = val->as<AllocType::Struct>();
|
||||
for (auto& [key, v] : vs.fields) {
|
||||
if (v.type() == ValueType::Ptr) {
|
||||
move_item_to_other(
|
||||
v.template as<ValueType::Ptr>().value);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
size_t max_size = 4;
|
||||
|
||||
std::vector<AllocItem> heap_1;
|
||||
std::vector<AllocItem> heap_2;
|
||||
|
||||
std::vector<AllocItem>* sel = &heap_1;
|
||||
std::vector<AllocItem>* other = &heap_2;
|
||||
};
|
||||
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "alloc.hpp"
|
||||
#include "arch.hpp"
|
||||
#include "json.hpp"
|
||||
#include "value.hpp"
|
||||
@ -271,7 +272,7 @@ private:
|
||||
const uint32_t* program;
|
||||
size_t program_size;
|
||||
std::vector<Value> stack;
|
||||
std::vector<Value> pool_heap;
|
||||
heap::Heap heap;
|
||||
SourcePos current_pos = { 0, 1, 1 };
|
||||
int64_t instruction_counter = 0;
|
||||
|
||||
|
5
surveys/code_coverage/.vscode/settings.json
vendored
Normal file
5
surveys/code_coverage/.vscode/settings.json
vendored
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"deno.enable": true,
|
||||
"deno.lint": true,
|
||||
"deno.unstable": true
|
||||
}
|
@ -22,7 +22,7 @@ async function compileProgram(filepath: string) {
|
||||
const result = await compiler.compileWithDebug(filepath);
|
||||
}
|
||||
|
||||
async function runProgramWithDebug(program: string) {
|
||||
async function runProgramWithDebug(program: number[]) {
|
||||
const connection = await runtime.connect();
|
||||
connection.send({
|
||||
type: "run-debug",
|
||||
|
Loading…
Reference in New Issue
Block a user