Skip to content

Commit

Permalink
Edits dom/bindings/DESIGN.md
Browse files Browse the repository at this point in the history
This corrects and improves the dom/bindings/DESIGN.md document and also
corrects a grammatical error in a tests/reftest.rs message.
  • Loading branch information
gilles-leblanc committed Oct 18, 2014
1 parent b86344b commit 8b727e3
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 17 deletions.
32 changes: 16 additions & 16 deletions components/script/dom/bindings/DESIGN.md
@@ -1,39 +1,39 @@
# The design of Garbage collected DOM

These are how Servo provides an object graph to SpiderMonkey's Garbage Collection.
This is how Servo provides an object graph to SpiderMonkey's Garbage Collector.

## Construct
When Servo creates a Rusty DOM object, the binding code creates a wrapper `JSObject` with SpiderMonkey, is correspond to each Rusty DOM Object. It’s produced and set to the Rusty object in `FooBinding::Wrap`.
When Servo creates a Rusty DOM object the binding code creates a corresponding wrapper `JSObject` with SpiderMonkey. It’s produced and set to the Rusty object in `FooBinding::Wrap`.

In `FooBinding::Wrap`, the wrapper JSObject gets the pointer for Rusty Object to itself. And the same time, the wrapper `JSObject` are set to the Rusty Object’s `Reflector` field (All Rusty DOM objects have `dom::bindings::utils::Reflector` in their most basis field). These step are the “binding” work to create the relationship of both objects.
In `FooBinding::Wrap`, the wrapper `JSObject` gets the pointer for the Rusty object to itself. At the same time the wrapper `JSObject` is set to the Rusty object’s `Reflector` field (all Rusty DOM objects have `dom::bindings::utils::Reflector` in their most basic fields). These steps are the “binding” work necessary to create the relationship between both objects.


## Trace object graph from SpiderMonkey GC.
This is very tricky and magically mechanism helped by Rust Compiler.
## Trace object graph from SpiderMonkey GC
This is a tricky mechanism done with the help of the Rust compiler.
The outline is:

1. SpiderMonkey's GC calls `JSClass.trace` defined in `FooBinding` when marking phase. This JSClass is basis of each wrapper JSObject.
1. SpiderMonkey's GC calls `JSClass.trace` defined in `FooBinding` during the marking phase. This `JSClass` is the basis of each wrapper `JSObject`.
2. `JSClass.trace` calls `Foo::trace()` (an implementation of `JSTraceable`).
This is typically derived via a #[jstraceable] annotation
This is typically derived via a #[jstraceable] annotation.
3. For all fields, `Foo::trace()`
calls `trace()` on the field. For example, for fields of type `JS<T>`, `JS<T>::trace()` calls
`trace_reflector()`. Non-JS-managed types have an empty inline `trace()` method, achieved via `untraceable!` or similar.
4. `trace_reflector()` fetches the reflector that is reachable from a Rust object, and notifies it to the GC with using JSTracer.
5. This operation continues to the end of the graph.
6. Finally, GC gets whether Rust object lives or not from JSObjects which is hold by Rust object.
4. `trace_reflector()` fetches the reflector that is reachable from a Rust object and notifies it to the GC using JSTracer.
5. This operation continues for the rest of the graph.
6. Finally, the GC checks whether the Rust object lives or not from `JSObject`s which are held by Rust object.


## Destruct
When destructing DOM objects (wrapper JSObjects) by SpiderMonkey, SpiderMonkey calls the `JSClass.finalize()` which is basis of each wrapper `JSObject`s. This method refers each `FooBinding::_finalize()`.
When destructing DOM objects (wrapper JSObjects), SpiderMonkey calls the `JSClass.finalize()` which is basis of each wrapper `JSObject`. This method refers to `FooBinding::_finalize()`.

In this function, the pointer of Rusty DOM Object that is contained in the wrapper JSObject is unwrapped, it cast to Rust owned pointer, and we assign its owned pointer to the empty local variable of `FooBinding::_finalize()`. Thus we can destruct the Rusty Object after we left from it.
In the `_finalize()` function the pointer of the Rusty DOM object that is contained in the JSObject is unwrapped. It is then cast to a Rust owned pointer and assigned to an empty local variable. Thus we can destruct the Rusty object afterwards.


## Interact with Exact GC’s rooting
For supporting SpiderMonkey’s exact GC rooting, we introduce [some types](https://github.com/mozilla/servo/wiki/Using-DOM-types):

- `JS<T>` is used for the DOM typed field in a DOM type structure. GC can trace them recursively while enclosing DOM object (maybe root) is alive.
- `Temporary<T>` is used as a return value of functions returning DOM type. They are rooted while they are alive. But a retun value gets moved around. It’s breakable for the LIFO ordering constraint. Thus we need introduce `Root<T>`.
- `Root<T>` contains the pointer to `JSObject` which the represented DOM type has. SpiderMonkey's conservative stack scanner scans its pointer and mark a pointed `JSObject` as GC root.
- `JS<T>` is used for the DOM typed field in a DOM type structure. The GC can trace them recursively while the enclosing DOM object (maybe root) is alive.
- `Temporary<T>` is used as a return value for functions returning a DOM type. They are rooted for the duration of their lifetime. But a retun value gets moved around which can break the LIFO ordering constraint. Thus we need to introduce `Root<T>`.
- `Root<T>` contains the pointer to `JSObject` which the represented DOM type has. SpiderMonkey's conservative stack scanner scans it's pointers and marks a pointed `JSObject` as GC root.
- `JSRef` is just a reference to the value rooted by `Root<T>`.
- `RootCollection` is used for dynamic checking about rooting satisfies LIFO ordering, because SpiderMonkey GC requres LIFO order (See also: [Exact Stack Rooting - Storing a GCPointer on the CStack](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Internals/GC/Exact_Stack_Rooting)).
- `RootCollection` is used to dynamically check if rooting satisfies LIFO ordering, because SpiderMonkey's GC requires LIFO order (See also: [Exact Stack Rooting - Storing a GCPointer on the CStack](https://developer.mozilla.org/en-US/docs/Mozilla/Projects/SpiderMonkey/Internals/GC/Exact_Stack_Rooting)).
2 changes: 1 addition & 1 deletion tests/reftest.rs
Expand Up @@ -263,7 +263,7 @@ fn check_reftest(reftest: Reftest) {
let right_all_white = right_bytes.iter().all(|&p| p == 255);

if left_all_white && right_all_white {
fail!("Both rendering are empty")
fail!("Both renderings are empty")
}

let pixels = left_bytes.iter().zip(right_bytes.iter()).map(|(&a, &b)| {
Expand Down

5 comments on commit 8b727e3

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

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

saw approval from jdm
at gilles-leblanc@8b727e3

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

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

merging gilles-leblanc/servo/fix-grammatical-errors = 8b727e3 into auto

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

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

gilles-leblanc/servo/fix-grammatical-errors = 8b727e3 merged ok, testing candidate = 65856dd

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

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

@bors-servo
Copy link
Contributor

Choose a reason for hiding this comment

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

fast-forwarding master to auto = 65856dd

Please sign in to comment.