Guardians

From MozillaWiki
Jump to: navigation, search

This is a proposal, not an implemented fact; it is being discussed in bug 698463.

Guardians allow objects to be saved from garbage collection so that clean-up operations can be performed on them. Guardians avoid the more serious problems associated with traditional object finalizers: the application has full control over the timing of the clean-up operations, and the guarded objects remain fully alive until after they have been removed from the guardian's care.

In a Mozilla application, guardians can use the event loop to notify the application when an object has been proven to be reachable only through the guardian mechanism, and not via any other JavaScript objects, XPCOM references, or other roots.

R. Kent Dybvig, David Eby, and Carl Bruggeman first described guardians in their 1993 paper, Guardians in a generation-based collector; guardians have been implemented as part of Chez Scheme since roughly that time, as documented in The Chez Scheme User's Guide.

Guardians

A guardian protects a group of JavaScript objects from deallocation, and allows the system to determine when they would otherwise have been deallocated. The objects in a guardian's care are divided into two disjoint subgroups: "accessible" objects, and "inaccessible" objects. The "inaccessible" objects are those that the garbage collector have proven to be unreachable other than through guardians. The "accessible" objects are those for which this has not been proven: they are either still live --- reachable via non-guardian JavaScript objects and roots --- or the garbage collector has not yet noticed that they have become inaccessible.

Suppose your program has a heap that includes three objects:

Guardians-1.png

We can create a guardian, and register two of the objects with it:

 var guardian = new Guardian();
 guardian.add(obj2);
 guardian.add(obj3);

This leaves obj1 alone, but adds obj2 and obj3 to guardian's accessible set:

Guardians-2.png

Suppose that, as the program runs, the last reference to obj1 goes away, and that the last reference to obj3, other than the one in guardian, goes away as well:

Guardians-3.png

When the garbage collector notices this situation, it will silently free obj1, but instead of freeing obj3, it will move guardian's reference to it to the "inaccessible" group:

Guardians-4.png

Now, guardian keeps obj3 alive until we call guardian's next method to retrieve it:

 var saved = guardian.next();

This removes obj3 from guardian's care altogether, and stores it in saved:

Guardians-5.png

(Guardians are iterators: if we try to get another object from the guardian now that its "inaccessible" set is empty, it throws a StopIteration exception.) We can now clean up obj3's state as needed, and then drop our last reference to it, so the next garbage collection can really free it:

Guardians-6.png

Note that at no point does obj3 enter any special allocation state. The guardian's reference to obj3 is a strong reference, keeping obj3 and any objects it refers to alive until they are removed from the guardian and dropped. Once removed from guardian, obj3 can be handed out to other JavaScript code, registered with a guardian again, or simply dropped. If the clean-up code itself puts obj3 in a "destructed" state—one where it no longer has the properties expected of a live instance of its type—it is simply the clean-up code's responsibility not to hand obj3 to code expecting a fully functioning object.

Image sources

Here are the SVG sources for the embedded diagrams above:

Guardians-1.svg Guardians-2.svg Guardians-3.svg Guardians-4.svg Guardians-5.svg Guardians-6.svg