Skip to content
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
12 changes: 3 additions & 9 deletions src/rt/core.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace rt::core

class FrameObject : public objects::DynObject
{
FrameObject() : objects::DynObject(framePrototypeObject(), true) {}
FrameObject() : objects::DynObject(framePrototypeObject()) {}

public:
FrameObject(objects::DynObject* parent_frame)
Expand Down Expand Up @@ -58,8 +58,7 @@ namespace rt::core
class FuncObject : public objects::DynObject
{
public:
FuncObject(objects::DynObject* prototype_, bool global = false)
: objects::DynObject(prototype_, global)
FuncObject(objects::DynObject* prototype_) : objects::DynObject(prototype_)
{}
};

Expand Down Expand Up @@ -197,7 +196,7 @@ namespace rt::core
{
public:
CownObject(objects::DynObject* region)
: objects::DynObject(cownPrototypeObject())
: objects::DynObject(cownPrototypeObject(), objects::cown_region)
{
// FIXME: Add once regions are reified
// assert(
Expand Down Expand Up @@ -232,11 +231,6 @@ namespace rt::core
// always be opaque.
return true;
}

bool is_cown() override
{
return true;
}
};

inline std::set<objects::DynObject*>* globals()
Expand Down
34 changes: 15 additions & 19 deletions src/rt/objects/dyn_object.h
Original file line number Diff line number Diff line change
Expand Up @@ -79,17 +79,16 @@ namespace rt::objects
}

// prototype is borrowed, the caller does not need to provide an RC.
DynObject(DynObject* prototype_ = nullptr, bool first_frame = false)
DynObject(
DynObject* prototype_ = nullptr,
Region* containing_region = get_local_region())
: prototype(prototype_)
{
if (!first_frame)
{
count++;
all_objects.insert(this);
auto local_region = get_local_region();
region = local_region;
local_region->objects.insert(this);
}
assert(containing_region != nullptr);
count++;
all_objects.insert(this);
region = containing_region;
containing_region->objects.insert(this);

if (prototype != nullptr)
{
Expand Down Expand Up @@ -149,33 +148,30 @@ namespace rt::objects
return false;
}

virtual bool is_cown()
bool is_cown()
{
return false;
return region.get_ptr() == objects::cown_region;
}

void freeze()
{
// TODO SCC algorithm
visit(this, [](Edge e) {
auto obj = e.target;
if (!obj || obj->is_immutable())
if (!obj || obj->is_immutable() || obj->is_cown())
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This means that cowns can't be frozen. It makes sense, but we should check that this is inline with what is written up. If not, we probably want to correct the text on this one, as I like this implementation

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess I viewed them as already in the "shared" world, so freeze doesn't do anything. A frozen cown can still be mutated in "my view" of the model.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, I agree. This was just meant as a reminder to check/sync the docs

return false;

auto r = get_region(obj);
if (r != nullptr)
{
get_region(obj)->objects.erase(obj);
}
obj->region.set_tag(ImmutableTag);
get_region(obj)->objects.erase(obj);
obj->region.set_ptr(immutable_region);

return !obj->is_cown();
return true;
});
}

bool is_immutable()
{
return region.get_tag() == ImmutableTag;
return region.get_ptr() == immutable_region;
}

[[nodiscard]] DynObject* get(std::string name)
Expand Down
20 changes: 15 additions & 5 deletions src/rt/objects/region.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,7 @@ namespace rt::objects
{
Region* get_region(DynObject* obj)
{
if ((obj == nullptr) || obj->is_immutable())
return nullptr;
assert(obj != nullptr);
return obj->region.get_ptr();
}

Expand Down Expand Up @@ -75,7 +74,11 @@ namespace rt::objects
}

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

// Handle cown case
if (target == cown_region)
return;

if (src == get_local_region())
Expand All @@ -94,6 +97,7 @@ namespace rt::objects

void add_region_reference(Region* src_region, DynObject* target)
{
assert(target != nullptr);
if (target->is_immutable())
return;

Expand All @@ -118,6 +122,7 @@ namespace rt::objects

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

Expand Down Expand Up @@ -149,7 +154,9 @@ namespace rt::objects

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

auto src_region = get_region(src);
Expand All @@ -173,6 +180,8 @@ namespace rt::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) {
assert(src != nullptr);
assert(target != nullptr);
return get_region(src) == get_region(target);
};
for (auto& [key, field] : obj->fields)
Expand All @@ -190,8 +199,9 @@ namespace rt::objects
remove_reference(obj, old_value);
}

if (same_region(obj, obj->prototype))
if ((obj->prototype != nullptr) && same_region(obj, obj->prototype))
{
// TODO When freeze is no longer immortal, this will need to be updated.
obj->prototype->change_rc(-1);
}
else
Expand Down
5 changes: 5 additions & 0 deletions src/rt/objects/region.h
Original file line number Diff line number Diff line change
Expand Up @@ -179,4 +179,9 @@ namespace rt::objects
// encode special regions.
using RegionPointer = utils::TaggedPointer<Region>;

inline Region immutable_region_impl;
inline constexpr Region* immutable_region{&immutable_region_impl};

inline Region cown_region_impl;
inline constexpr Region* cown_region{&cown_region_impl};
} // namespace rt::objects
5 changes: 5 additions & 0 deletions src/utils/tagged_pointer.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,11 @@ namespace utils
ptr = (ptr & ~0x3) | tag;
}

void set_ptr(T* new_ptr)
{
ptr = (ptr & 0x3) | reinterpret_cast<uintptr_t>(new_ptr);
}

void add_tag(uintptr_t tag)
{
assert(tag < 4);
Expand Down