mirror of
https://github.com/servo/servo.git
synced 2025-07-23 23:33:43 +01:00
[script] Merge the binding design document into inline doc comments.
This commit is contained in:
parent
83a6b5d770
commit
6500544387
3 changed files with 15 additions and 51 deletions
|
@ -1,42 +0,0 @@
|
||||||
# The design of Garbage collected DOM
|
|
||||||
|
|
||||||
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 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 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 a tricky mechanism done with the help of the Rust compiler.
|
|
||||||
The outline is:
|
|
||||||
|
|
||||||
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.
|
|
||||||
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 `no_jsmanaged_fields!` or similar.
|
|
||||||
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), SpiderMonkey calls the `JSClass.finalize()` which is basis of each wrapper `JSObject`. This method refers to `FooBinding::_finalize()`.
|
|
||||||
|
|
||||||
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. The GC can trace them recursively while the enclosing DOM object (maybe root) is alive.
|
|
||||||
- `LayoutJS<T>` is specialized `JS<T>` to use in layout. `Layout*Helper` must be implemented on this type to prevent calling methods from non layout code.
|
|
||||||
- `Unrooted<T>` is used to wrap raw pointers to DOM objects extracted from their reflectors.
|
|
||||||
- `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 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)).
|
|
||||||
- `MutHeap<T>` is a version of `Cell<T>` that is safe to use for internal mutability of Spidermonkey heap objects like `JSVal` and `JS<T>`
|
|
|
@ -12,7 +12,9 @@
|
||||||
//! phase. (This happens through `JSClass.trace` for non-proxy bindings, and
|
//! phase. (This happens through `JSClass.trace` for non-proxy bindings, and
|
||||||
//! through `ProxyTraps.trace` otherwise.)
|
//! through `ProxyTraps.trace` otherwise.)
|
||||||
//! 2. `_trace` calls `Foo::trace()` (an implementation of `JSTraceable`).
|
//! 2. `_trace` calls `Foo::trace()` (an implementation of `JSTraceable`).
|
||||||
//! This is typically derived via a #[jstraceable] annotation
|
//! This is typically derived via a `#[dom_struct]` (implies `#[jstraceable]`) annotation.
|
||||||
|
//! Non-JS-managed types have an empty inline `trace()` method,
|
||||||
|
//! achieved via `no_jsmanaged_fields!` or similar.
|
||||||
//! 3. For all fields, `Foo::trace()`
|
//! 3. For all fields, `Foo::trace()`
|
||||||
//! calls `trace()` on the field.
|
//! calls `trace()` on the field.
|
||||||
//! For example, for fields of type `JS<T>`, `JS<T>::trace()` calls
|
//! For example, for fields of type `JS<T>`, `JS<T>::trace()` calls
|
||||||
|
@ -21,8 +23,10 @@
|
||||||
//! reflector.
|
//! reflector.
|
||||||
//! 5. `trace_object()` calls `JS_CallTracer()` to notify the GC, which will
|
//! 5. `trace_object()` calls `JS_CallTracer()` to notify the GC, which will
|
||||||
//! add the object to the graph, and will trace that object as well.
|
//! add the object to the graph, and will trace that object as well.
|
||||||
|
//! 6. When the GC finishes tracing, it [`finalizes`](../index.html#destruction)
|
||||||
|
//! any reflectors that were not reachable.
|
||||||
//!
|
//!
|
||||||
//! The no_jsmanaged_fields!() macro adds an empty implementation of JSTraceable to
|
//! The `no_jsmanaged_fields!()` macro adds an empty implementation of `JSTraceable` to
|
||||||
//! a datatype.
|
//! a datatype.
|
||||||
|
|
||||||
use dom::bindings::js::JS;
|
use dom::bindings::js::JS;
|
||||||
|
|
|
@ -67,10 +67,10 @@
|
||||||
//! (The result of either method can be wrapped in `Result`, if that is
|
//! (The result of either method can be wrapped in `Result`, if that is
|
||||||
//! appropriate for the type in question.)
|
//! appropriate for the type in question.)
|
||||||
//!
|
//!
|
||||||
//! The latter calls the former, boxes the result, and creates a reflector for
|
//! The latter calls the former, boxes the result, and creates a reflector
|
||||||
//! it by calling `dom::bindings::utils::reflect_dom_object` (which yields
|
//! corresponding to it by calling `dom::bindings::utils::reflect_dom_object`
|
||||||
//! ownership of the object to the SpiderMonkey Garbage Collector). This is the
|
//! (which yields ownership of the object to the SpiderMonkey Garbage Collector).
|
||||||
//! API to use when creating a DOM object.
|
//! This is the API to use when creating a DOM object.
|
||||||
//!
|
//!
|
||||||
//! The former should only be called by the latter, and by subclasses'
|
//! The former should only be called by the latter, and by subclasses'
|
||||||
//! `new_inherited` methods.
|
//! `new_inherited` methods.
|
||||||
|
@ -98,9 +98,11 @@
|
||||||
//! =============================
|
//! =============================
|
||||||
//!
|
//!
|
||||||
//! Every DOM object has a `Reflector` as its first (transitive) member field.
|
//! Every DOM object has a `Reflector` as its first (transitive) member field.
|
||||||
//! This contains a `*mut JSObject` that points to its reflector. This field
|
//! This contains a `*mut JSObject` that points to its reflector.
|
||||||
//! is initialized by the `FooBinding::Wrap` method, called from
|
//!
|
||||||
//! `reflect_dom_object`.
|
//! The `FooBinding::Wrap` function creates the reflector, stores a pointer to
|
||||||
|
//! the DOM object in the reflector, and initializes the pointer to the reflector
|
||||||
|
//! in the `Reflector` field.
|
||||||
//!
|
//!
|
||||||
//! The `Reflectable` trait provides a `reflector()` method that returns the
|
//! The `Reflectable` trait provides a `reflector()` method that returns the
|
||||||
//! DOM object's `Reflector`. It is implemented automatically for DOM structs
|
//! DOM object's `Reflector`. It is implemented automatically for DOM structs
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue