WIP: Use Toggle Refs on Object Instances
Overview
This merge fixes the "cycle issue" with the currently proposed expando system. (explanation of the "cycle issue" below)
Commits
The first commit in this merge was the first attempt at using toggle references to resolve the "cycle issue" with the current branch. (should be removed before picking)
The second commit is the successful attempt to resolve the cycle issue with toggle references.
The first was unsuccessful because it attempted to add toggle references on the ExpandoHolder, not ObjectInstance. Because ObjectInstance always held a reference - the toggle references on ExpandoHolder were not triggered.
What is the cycle issue?
In our JavaScript engine, SpiderMonkey, garbage collection is a trace-based system. Every object "traces" it's references, allowing the garbage collector to identify objects which are no longer referenced and clean them up.
A "cycle" occurs when an object references itself or two objects reference each other.
this.me = this;
a.b = b;
b.a = a;
In these cases the garbage collector will only be able to collect this
or a
/b
if no other code references them.
In the current expando system, the garbage collector can never break these cycles for GObject's because the objects are never isolated.
This is the current trace of an expando and GObject. red
denotes C-based references (counting), black
denotes JavaScript based references (traces). Note that the JSContext
always traces the ExpandoHolder
which always traces Expando
. Because JSContext
is not cleaned up until we exit, this is essentially a permanent reference. This is done to prevent custom JS properties (expando properties) on GObjects from "disappearing" if they are passed into C code and no longer referenced from JavaScript code. The downside, is that it will keep reference cycles alive indefinitely and the objects which they reference.
Solution
To prevent this, we need to "toggle" the tracing behavior once it is passed into C code and no longer referenced by JavaScript.
To meet that condition, we use GObject's toggle_ref
which notifies us when only one reference remains on a given ObjectInstance
. If only one reference remains, we know only JavaScript references the object. In that case, we remove the trace from JSContext to prevent a permanent reference and allow SpiderMonkey to garbage collect as needed. Otherwise, we keep the permanent reference in place to keep the JS properties alive when no longer referenced from JavaScript.
The diagram below represents this system. green
highlights the changes made, red
is GObject references, and black
is JavaScript traces.