valeri/src/arena.cpp

177 lines
4.2 KiB
C++

#include "arena.hpp"
#include "error.hpp"
GcRootBase::GcRootBase(PodObject* ptr, GcRootList* node)
: _ptr(ptr), _node(node) {}
GcRootBase::~GcRootBase() {
if (_node != 0) _node->remove();
}
Result<void> Arena::gc() {
std::swap(_first, _second);
_first->reset();
TRY(gc_roots());
_second->reset();
return Result<void>();
}
Result<void> Arena::gc_roots() {
auto node = _gcroot.next();
while (node != 0) {
node = TRY(gc_root(node));
node = node->next();
}
return Result<void>();
}
Result<GcRootList*> Arena::gc_root(GcRootList* node) {
auto pod = TRY(gc_pod(node->_root->_ptr));
auto lst = TRY(alloc<GcRootList>());
node->_root->_ptr = pod;
node->_root->_node = lst;
lst->_root = node->_root;
GcRootList* prev = node->_prev;
GcRootList* next = node->_next;
prev->_next = lst;
if (next) next->_prev = lst;
lst->_prev = prev;
lst->_next = next;
// Not strictly needed, but useful for debugging
node->_prev = 0;
node->_next = 0;
node->_root = 0;
return lst;
}
Result<PodObject*> Arena::gc_pod(PodObject* obj) {
switch (obj->header.tag) {
case Tag::Nil:
return gc_nil((PodNil*)obj);
case Tag::Bool:
return gc_bool((PodBool*)obj);
case Tag::Int64:
return gc_int64((PodInt64*)obj);
case Tag::Float:
return gc_float((PodFloat*)obj);
case Tag::String:
return gc_string((PodString*)obj);
case Tag::Symbol:
return gc_symbol((PodSymbol*)obj);
case Tag::Syntax:
return gc_syntax((PodSyntax*)obj);
case Tag::Pair:
return gc_pair((PodPair*)obj);
case Tag::Array:
return gc_array((PodArray*)obj);
case Tag::ByteArray:
return gc_bytearray((PodByteArray*)obj);
case Tag::Dict:
return gc_dict((PodDict*)obj);
}
return ErrorCode::TypeMismatch;
}
Result<PodObject*> Arena::gc_nil(PodNil* obj) {
auto nobj = TRY(alloc<PodNil>());
nobj->header.tag = Tag::Nil;
return nobj;
}
Result<PodObject*> Arena::gc_bool(PodBool* obj) {
auto nobj = TRY(alloc<PodBool>());
nobj->header.tag = Tag::Bool;
nobj->value = obj->value;
return nobj;
}
Result<PodObject*> Arena::gc_int64(PodInt64* obj) {
auto nobj = TRY(alloc<PodInt64>());
nobj->header.tag = Tag::Int64;
nobj->value = obj->value;
return nobj;
}
Result<PodObject*> Arena::gc_float(PodFloat* obj) {
auto nobj = TRY(alloc<PodFloat>());
nobj->header.tag = Tag::Float;
nobj->value = obj->value;
return nobj;
}
Result<PodObject*> Arena::gc_string(PodString* obj) {
auto nobj = TRY(alloc<PodString>(obj->size * sizeof(char32_t)));
nobj->header.tag = Tag::String;
nobj->size = obj->size;
memcpy(nobj->data, obj->data, obj->size * sizeof(char32_t));
return nobj;
}
Result<PodObject*> Arena::gc_symbol(PodSymbol* obj) {
auto nobj = TRY(alloc<PodSymbol>(obj->size * sizeof(char32_t)));
nobj->header.tag = Tag::Symbol;
nobj->size = obj->size;
memcpy(nobj->data, obj->data, obj->size * sizeof(char32_t));
return nobj;
}
Result<PodObject*> Arena::gc_syntax(PodSyntax* obj) {
return ErrorCode::NotImplemented;
}
Result<PodObject*> Arena::gc_pair(PodPair* obj) {
auto nobj = TRY(alloc<PodPair>());
nobj->header.tag = Tag::Pair;
PodObject* first = obj->first.get();
PodObject* rest = obj->rest.get();
first = TRY(gc_pod(first));
rest = TRY(gc_pod(rest));
nobj->first = first;
nobj->rest = rest;
return nobj;
}
Result<PodObject*> Arena::gc_array(PodArray* obj) {
auto nobj = TRY(alloc<PodArray>(sizeof(OffPtr<PodObject>) * obj->size));
nobj->header.tag = Tag::Array;
nobj->size = obj->size;
for (uint64_t i = 0; i < obj->size; i++) {
PodObject* val = obj->data[i].get();
nobj->data[i] = TRY(gc_pod(val));
}
return nobj;
}
Result<PodObject*> Arena::gc_bytearray(PodByteArray* obj) {
auto nobj = TRY(alloc<PodByteArray>(obj->size));
nobj->header.tag = Tag::ByteArray;
nobj->size = obj->size;
memcpy(nobj->data, obj->data, obj->size);
return nobj;
}
Result<PodObject*> Arena::gc_dict(PodDict* obj) {
auto nobj = TRY(alloc<PodDict>(obj->size * 2 * sizeof(OffPtr<PodObject>)));
nobj->header.tag = Tag::Dict;
nobj->size = obj->size;
for (uint64_t i = 0; i < obj->size * 2; i++) {
PodObject* val = obj->data[i].get();
nobj->data[i] = TRY(gc_pod(val));
}
return nobj;
// return ErrorCode::NotImplemented;
}