Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactoring #37

Merged
merged 4 commits into from
Oct 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ set(CMAKE_CXX_STANDARD 20)
add_library(
rt OBJECT
src/rt/rt.cc
src/rt/objects/region.cc
src/rt/ui/mermaid.cc
src/rt/core/builtin.cc
)
Expand Down
21 changes: 3 additions & 18 deletions src/rt/core.h
Original file line number Diff line number Diff line change
@@ -1,26 +1,11 @@
#include "objects/dyn_object.h"
#include "objects/prototype_object.h"
#include "rt.h"

#include <map>

namespace rt::core
{
class PrototypeObject : public objects::DynObject
{
std::string name;

public:
PrototypeObject(std::string name_, objects::DynObject* prototype = nullptr)
: objects::DynObject(prototype), name(name_)
{}

std::string get_name() override
{
std::stringstream stream;
stream << "[" << name << "]";
return stream.str();
}
};
using PrototypeObject = objects::PrototypeObject;

inline PrototypeObject* framePrototypeObject()
{
Expand All @@ -39,7 +24,7 @@ namespace rt::core
if (parent_frame)
{
auto old_value = this->set(objects::ParentField, parent_frame);
add_reference(this, parent_frame);
objects::add_reference(this, parent_frame);
assert(!old_value);
}
}
Expand Down
12 changes: 6 additions & 6 deletions src/rt/core/builtin.cc
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ namespace rt::core
{
auto value = stack->back();
mermaid->add_always_hide(value);
remove_reference(frame, value);
rt::remove_reference(frame, value);
stack->pop_back();
}

Expand All @@ -42,7 +42,7 @@ namespace rt::core
auto value = stack->back();
mermaid->remove_unreachable_hide(value);
mermaid->remove_always_hide(value);
remove_reference(frame, value);
rt::remove_reference(frame, value);
stack->pop_back();
}

Expand All @@ -66,7 +66,7 @@ namespace rt::core

auto region = pop(stack, "region for cown creation");
auto cown = make_cown(region);
move_reference(frame, cown, region);
rt::move_reference(frame, cown, region);

return cown;
});
Expand All @@ -89,7 +89,7 @@ namespace rt::core

auto value = pop(stack, "object to freeze");
freeze(value);
remove_reference(frame, value);
rt::remove_reference(frame, value);

return std::nullopt;
});
Expand All @@ -98,8 +98,8 @@ namespace rt::core
assert(args == 1);

auto value = pop(stack, "region source");
create_region(value);
remove_reference(frame, value);
rt::create_region(value);
rt::remove_reference(frame, value);

return std::nullopt;
});
Expand Down
233 changes: 14 additions & 219 deletions src/rt/objects/dyn_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,11 @@ namespace rt::objects
const std::string PrototypeField{"__proto__"};
const std::string ParentField{"__parent__"};

Region* get_region(DynObject* obj);

Region* get_local_region();
void set_local_region(Region* region);

// Representation of objects
class DynObject
{
Expand All @@ -39,8 +44,8 @@ namespace rt::objects
friend void dealloc(DynObject* obj);
template<typename Pre, typename Post>
friend void visit(Edge, Pre, Post);

thread_local static RegionPointer local_region;
friend Region* get_region(DynObject* obj);
friend void add_to_region(Region* r, DynObject* target);

// TODO: Not concurrency safe
inline static size_t count{0};
Expand All @@ -53,68 +58,7 @@ namespace rt::objects

std::map<std::string, DynObject*> fields{};

static Region* get_region(DynObject* obj)
{
if ((obj == nullptr) || obj->is_immutable())
return nullptr;
return obj->region.get_ptr();
}

bool is_local_object()
{
return region.get_ptr() == get_local_region();
}

static void remove_region_reference(Region* src, Region* target)
{
if (src == target)
{
std::cout << "Same region, no need to do anything" << std::endl;
return;
}

// Handle immutable case
if (target == nullptr)
return;

if (src == get_local_region())
{
Region::dec_lrc(target);
return;
}

if (src)
{
assert(target->parent == src);
Region::dec_prc(target);
}
return;
}

static void add_region_reference(Region* src_region, DynObject* target)
{
if (target->is_immutable())
return;

auto target_region = get_region(target);
if (src_region == target_region)
return;

if (src_region == get_local_region())
{
Region::inc_lrc(target_region);
return;
}

if (target_region == get_local_region())
{
target->add_to_region(src_region);
return;
}

Region::set_parent(target_region, src_region);
}

public:
size_t change_rc(signed delta)
{
std::cout << "Change RC: " << get_name() << " " << rc << " + " << delta
Expand All @@ -134,50 +78,6 @@ namespace rt::objects
delta;
}

void add_to_region(Region* r)
{
size_t internal_references{0};
size_t rc_of_added_objects{0};
visit(this, [&](Edge e) {
auto obj = e.target;
if (obj == nullptr || obj->is_immutable())
return false;

if (obj->is_local_object())
{
std::cout << "Adding object to region: " << obj->get_name()
<< " rc = " << obj->rc << std::endl;
rc_of_added_objects += obj->rc;
internal_references++;
obj->region = {r};
get_local_region()->objects.erase(obj);
r->objects.insert(obj);
return true;
}

auto obj_region = get_region(obj);
if (obj_region == r)
{
std::cout << "Adding internal reference to object: "
<< obj->get_name() << std::endl;
internal_references++;
return false;
}

Region::set_parent(obj_region, r);
Region::dec_lrc(obj_region);
return false;
});
r->local_reference_count += rc_of_added_objects - internal_references;

std::cout << "Added " << rc_of_added_objects - internal_references
<< " to LRC of region" << std::endl;
std::cout << "Region LRC: " << r->local_reference_count << std::endl;
std::cout << "Internal references found: " << internal_references
<< std::endl;
}

public:
// prototype is borrowed, the caller does not need to provide an RC.
DynObject(DynObject* prototype_ = nullptr, bool first_frame = false)
: prototype(prototype_)
Expand All @@ -194,7 +94,7 @@ namespace rt::objects
if (prototype != nullptr)
{
// prototype->change_rc(1);
add_reference(this, prototype);
objects::add_reference(this, prototype);
}
std::cout << "Allocate: " << this << std::endl;
}
Expand Down Expand Up @@ -224,6 +124,11 @@ namespace rt::objects
std::cout << "Deallocate: " << get_name() << std::endl;
}

size_t get_rc()
{
return rc;
}

/// @brief The string representation of this value to
/// TODO remove virtual once we have primitive functions.
virtual std::string get_name()
Expand Down Expand Up @@ -333,127 +238,17 @@ namespace rt::objects
return prototype;
}

static void add_reference(DynObject* src, DynObject* target)
{
if (target == nullptr)
return;

target->change_rc(1);

auto src_region = get_region(src);
add_region_reference(src_region, target);
}

static void
remove_reference(DynObject* src_initial, DynObject* old_dst_initial)
{
visit(
{src_initial, "", old_dst_initial},
[&](Edge e) {
if (e.target == nullptr)
return false;

std::cout << "Remove reference from: " << e.src->get_name() << " to "
<< e.target->get_name() << std::endl;
bool result = e.target->change_rc(-1) == 0;

remove_region_reference(get_region(e.src), get_region(e.target));
return result;
},
[&](DynObject* obj) { delete obj; });

Region::collect();
}

static void
move_reference(DynObject* src, DynObject* dst, DynObject* target)
{
if (target == nullptr || target->is_immutable())
return;

auto src_region = get_region(src);
auto dst_region = get_region(dst);

if (src_region == dst_region)
return;

auto target_region = get_region(target);

add_region_reference(dst_region, target);
// Note that target_region and get_region(target) are not necessarily the
// same.
remove_region_reference(src_region, target_region);
}

void create_region()
{
Region* r = new Region();
add_to_region(r);
// Add root reference as external.
r->local_reference_count++;
}

static size_t get_count()
{
return count;
}

static Region* get_local_region()
{
return local_region;
}

static std::set<DynObject*> get_objects()
{
return all_objects;
}
};

inline void destruct(DynObject* obj)
{
// Called from the region destructor.
// Remove all references to other objects.
// If in the same region, then just remove the RC, but don't try to collect
// as the whole region is being torndown including any potential cycles.
auto same_region = [](DynObject* src, DynObject* target) {
return DynObject::get_region(src) == DynObject::get_region(target);
};
for (auto& [key, field] : obj->fields)
{
if (field == nullptr)
continue;
if (same_region(obj, field))
{
// Same region just remove the rc, but don't try to collect.
field->change_rc(-1);
continue;
}

auto old_value = obj->set(key, nullptr);
remove_reference(obj, old_value);
}

if (same_region(obj, obj->prototype))
{
obj->prototype->change_rc(-1);
}
else
{
auto old_value = obj->set_prototype(nullptr);
remove_reference(obj, old_value);
}
}

inline void dealloc(DynObject* obj)
{
// Called from the region destructor.
// So remove from region if in one.
// This ensures we don't try to remove it from the set that is being
// iterated.
obj->region = nullptr;
delete obj;
}

template<typename Pre, typename Post>
inline void visit(Edge e, Pre pre, Post post)
{
Expand Down
Loading