mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Introduce LayoutJS<T>
This commit is contained in:
parent
1d7b1e5c31
commit
a5d7240534
2 changed files with 67 additions and 4 deletions
|
@ -33,8 +33,9 @@ In the `_finalize()` function the pointer of the Rusty DOM object that is contai
|
||||||
For supporting SpiderMonkey’s exact GC rooting, we introduce [some types](https://github.com/mozilla/servo/wiki/Using-DOM-types):
|
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.
|
- `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.
|
||||||
- `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>`.
|
- `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.
|
- `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>`.
|
- `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)).
|
- `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>`
|
- `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>`
|
||||||
|
|
|
@ -129,8 +129,25 @@ pub struct JS<T> {
|
||||||
ptr: NonZero<*const T>
|
ptr: NonZero<*const T>
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> JS<T> {
|
||||||
|
/// Returns `LayoutJS<T>` containing the same pointer.
|
||||||
|
fn to_layout(self) -> LayoutJS<T> {
|
||||||
|
LayoutJS {
|
||||||
|
ptr: self.ptr.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// This is specialized `JS<T>` to use in under `layout` crate.
|
||||||
|
/// `Layout*Helpers` traits must be implemented on this.
|
||||||
|
pub struct LayoutJS<T> {
|
||||||
|
ptr: NonZero<*const T>
|
||||||
|
}
|
||||||
|
|
||||||
impl<T> Copy for JS<T> {}
|
impl<T> Copy for JS<T> {}
|
||||||
|
|
||||||
|
impl<T> Copy for LayoutJS<T> {}
|
||||||
|
|
||||||
impl<T> PartialEq for JS<T> {
|
impl<T> PartialEq for JS<T> {
|
||||||
#[allow(unrooted_must_root)]
|
#[allow(unrooted_must_root)]
|
||||||
fn eq(&self, other: &JS<T>) -> bool {
|
fn eq(&self, other: &JS<T>) -> bool {
|
||||||
|
@ -138,6 +155,13 @@ impl<T> PartialEq for JS<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T> PartialEq for LayoutJS<T> {
|
||||||
|
#[allow(unrooted_must_root)]
|
||||||
|
fn eq(&self, other: &LayoutJS<T>) -> bool {
|
||||||
|
self.ptr == other.ptr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl <T> Clone for JS<T> {
|
impl <T> Clone for JS<T> {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn clone(&self) -> JS<T> {
|
fn clone(&self) -> JS<T> {
|
||||||
|
@ -147,6 +171,15 @@ impl <T> Clone for JS<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl <T> Clone for LayoutJS<T> {
|
||||||
|
#[inline]
|
||||||
|
fn clone(&self) -> LayoutJS<T> {
|
||||||
|
LayoutJS {
|
||||||
|
ptr: self.ptr.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl JS<Node> {
|
impl JS<Node> {
|
||||||
/// Create a new JS-owned value wrapped from an address known to be a `Node` pointer.
|
/// Create a new JS-owned value wrapped from an address known to be a `Node` pointer.
|
||||||
pub unsafe fn from_trusted_node_address(inner: TrustedNodeAddress) -> JS<Node> {
|
pub unsafe fn from_trusted_node_address(inner: TrustedNodeAddress) -> JS<Node> {
|
||||||
|
@ -198,6 +231,15 @@ impl<T: Reflectable> Reflectable for JS<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// XXXjdm same above
|
||||||
|
impl<T: Reflectable> Reflectable for LayoutJS<T> {
|
||||||
|
fn reflector<'a>(&'a self) -> &'a Reflector {
|
||||||
|
unsafe {
|
||||||
|
(*self.unsafe_get()).reflector()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// A trait to be implemented for JS-managed types that can be stored in
|
/// A trait to be implemented for JS-managed types that can be stored in
|
||||||
/// mutable member fields.
|
/// mutable member fields.
|
||||||
///
|
///
|
||||||
|
@ -296,6 +338,12 @@ impl<T: Reflectable> MutNullableJS<T> {
|
||||||
self.ptr.get()
|
self.ptr.get()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieve a copy of the inner optional `JS<T>` as `LayoutJS<T>`.
|
||||||
|
/// For use by layout, which can't use safe types like Temporary.
|
||||||
|
pub unsafe fn get_inner_as_layout(&self) -> Option<LayoutJS<T>> {
|
||||||
|
self.get_inner().map(|js| js.to_layout())
|
||||||
|
}
|
||||||
|
|
||||||
/// Retrieve a copy of the current inner value. If it is `None`, it is
|
/// Retrieve a copy of the current inner value. If it is `None`, it is
|
||||||
/// initialized with the result of `cb` first.
|
/// initialized with the result of `cb` first.
|
||||||
pub fn or_init<F>(&self, cb: F) -> Temporary<T>
|
pub fn or_init<F>(&self, cb: F) -> Temporary<T>
|
||||||
|
@ -313,9 +361,8 @@ impl<T: Reflectable> MutNullableJS<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Reflectable> JS<T> {
|
impl<T: Reflectable> JS<T> {
|
||||||
/// Returns an unsafe pointer to the interior of this object. This is the
|
/// Returns an unsafe pointer to the interior of this object.
|
||||||
/// only method that be safely accessed from layout. (The fact that this is
|
/// This should only be used by the DOM bindings.
|
||||||
/// unsafe is what necessitates the layout wrappers.)
|
|
||||||
pub unsafe fn unsafe_get(&self) -> *const T {
|
pub unsafe fn unsafe_get(&self) -> *const T {
|
||||||
*self.ptr
|
*self.ptr
|
||||||
}
|
}
|
||||||
|
@ -328,6 +375,15 @@ impl<T: Reflectable> JS<T> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: Reflectable> LayoutJS<T> {
|
||||||
|
/// Returns an unsafe pointer to the interior of this JS object without touching the borrow
|
||||||
|
/// flags. This is the only method that be safely accessed from layout. (The fact that this
|
||||||
|
/// is unsafe is what necessitates the layout wrappers.)
|
||||||
|
pub unsafe fn unsafe_get(&self) -> *const T {
|
||||||
|
*self.ptr
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<From> JS<From> {
|
impl<From> JS<From> {
|
||||||
/// Return `self` as a `JS` of another type.
|
/// Return `self` as a `JS` of another type.
|
||||||
//XXXjdm It would be lovely if this could be private.
|
//XXXjdm It would be lovely if this could be private.
|
||||||
|
@ -341,6 +397,12 @@ impl<From> JS<From> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<From> LayoutJS<From> {
|
||||||
|
/// Return `self` as a `LayoutJS` of another type.
|
||||||
|
pub unsafe fn transmute_copy<To>(&self) -> LayoutJS<To> {
|
||||||
|
mem::transmute_copy(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Get an `Option<JSRef<T>>` out of an `Option<Root<T>>`
|
/// Get an `Option<JSRef<T>>` out of an `Option<Root<T>>`
|
||||||
pub trait RootedReference<T> {
|
pub trait RootedReference<T> {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue