Skip to content

Commit 083925d

Browse files
authored
Merge pull request #69 from fxpl/pldi-redo
And Lungfish documentation
2 parents 2b42281 + 81656de commit 083925d

File tree

2 files changed

+31
-10
lines changed

2 files changed

+31
-10
lines changed

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,3 +54,24 @@ You can run in interactive mode by running:
5454

5555
Which will keep overwritting the `mermaid.md` file with the new heap state after each step.
5656

57+
## Lungfish
58+
59+
FrankenScript has been submitted as an PLDI25 artifact to explain the *Lungfish*
60+
Ownership Model implemented here.
61+
62+
A critical part of Lungfish is the write-barrier shown in Figure 6 of the Paper. FrankenScript implements
63+
these functions in `src/rt/objects/region.cc`. The important functions are:
64+
65+
* `add_reference(source, target)`: This adds a new reference from `source` to `target`.
66+
* `add_to_region(region, target, source)`: This adds `target` and all reachable nodes to `region` if possible.
67+
* `remove_reference(source, old_target)`: This removes a reference from `source` to `old_target`
68+
* `move_reference(old_src, new_src, target)`: This is the `writeBarrier()` function, which adds a new reference
69+
from `new_src` to `target` and removes the reference from `old_src` to `target`.
70+
71+
The interpreter, implemented in `src/lang/interpreter.cc`, calls these functions via the public API of the
72+
runtime (`rt::add_reference`, `rt::remove_reference`, `rt::move_reference`). The `add_to_region()` method is
73+
never called directly by the interpreter.
74+
75+
A good example for the write-barrier is the `StoreField` bytecode implementation:
76+
77+
https://github.com/fxpl/frankenscript/blob/30e431c7ba8022f29fb4927913976bbf18356789/src/lang/interpreter.cc#L303-L318

src/rt/objects/region.cc

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -218,10 +218,10 @@ namespace rt::objects
218218
add_region_reference(src_region, target, src);
219219
}
220220

221-
void remove_reference(DynObject* src_initial, DynObject* old_dst_initial)
221+
void remove_reference(DynObject* source, DynObject* old_target)
222222
{
223223
visit(
224-
{src_initial, "", old_dst_initial},
224+
{source, "", old_target},
225225
[&](Edge e) {
226226
if (e.target == nullptr)
227227
return false;
@@ -238,26 +238,26 @@ namespace rt::objects
238238
Region::collect();
239239
}
240240

241-
void move_reference(DynObject* src, DynObject* dst, DynObject* target)
241+
void move_reference(DynObject* old_src, DynObject* new_src, DynObject* target)
242242
{
243-
assert(src != nullptr);
244-
assert(dst != nullptr);
243+
assert(old_src != nullptr);
244+
assert(new_src != nullptr);
245245
if (target == nullptr || target->is_immutable() || target->is_cown())
246246
{
247247
return;
248248
}
249249

250-
auto src_region = get_region(src);
251-
auto dst_region = get_region(dst);
252-
if (src_region == dst_region)
250+
auto old_src_region = get_region(old_src);
251+
auto new_src_region = get_region(new_src);
252+
if (old_src_region == new_src_region)
253253
{
254254
return;
255255
}
256256

257257
auto old_target_region = get_region(target);
258258
auto old_target_bridge = old_target_region->bridge;
259259

260-
add_region_reference(dst_region, target, src);
260+
add_region_reference(new_src_region, target, old_src);
261261

262262
// If the bridge was implicitly frozen we don't need to remove
263263
// the region reference. In fact, we shouldn't since the region
@@ -269,7 +269,7 @@ namespace rt::objects
269269

270270
// Note that the region of the target might have changed after the
271271
// `add_region_refernce` call
272-
remove_region_reference(src_region, old_target_region);
272+
remove_region_reference(old_src_region, old_target_region);
273273
}
274274

275275
void Region::clean_lrcs_and_close(Region* to_close_reg)

0 commit comments

Comments
 (0)