Auto merge of #18059 - sendilkumarn:mito, r=nox

Using OnceCell<T> from Mitochondria

<!-- Please describe your changes on the following line: -->
---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [x] These changes fix #13402  (github issue number if applicable).

<!-- Also, please make sure that "Allow edits from maintainers" checkbox is checked, so that we can help you if you get stuck somewhere along the way.-->

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/18059)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2017-09-21 13:20:29 -05:00 committed by GitHub
commit 5c797d1943
5 changed files with 66 additions and 11 deletions

View file

@ -32,6 +32,7 @@ use dom::bindings::trace::trace_reflector;
use dom::node::Node;
use heapsize::HeapSizeOf;
use js::jsapi::{JSObject, JSTracer};
use mitochondria::OnceCell;
use script_layout_interface::TrustedNodeAddress;
use script_thread::STACK_ROOTS;
use std::cell::UnsafeCell;
@ -391,6 +392,55 @@ impl<T: DomObject> HeapSizeOf for MutNullableJS<T> {
}
}
/// A holder that allows to lazily initialize the value only once
/// `JS<T>`, using OnceCell
/// Essentially a `OnceCell<JS<T>>`.
///
/// This should only be used as a field in other DOM objects; see warning
/// on `JS<T>`.
#[must_root]
pub struct OnceCellJS<T: DomObject> {
ptr: OnceCell<JS<T>>,
}
impl<T: DomObject> OnceCellJS<T> {
/// Retrieve a copy of the current inner value. If it is `None`, it is
/// initialized with the result of `cb` first.
#[allow(unrooted_must_root)]
pub fn init_once<F>(&self, cb: F) -> &T
where F: FnOnce() -> Root<T>
{
debug_assert!(thread_state::get().is_script());
&self.ptr.init_once(|| JS::from_ref(&cb()))
}
}
impl<T: DomObject> Default for OnceCellJS<T> {
#[allow(unrooted_must_root)]
fn default() -> OnceCellJS<T> {
debug_assert!(thread_state::get().is_script());
OnceCellJS {
ptr: OnceCell::new(),
}
}
}
impl<T: DomObject> HeapSizeOf for OnceCellJS<T> {
fn heap_size_of_children(&self) -> usize {
// See comment on HeapSizeOf for JS<T>.
0
}
}
#[allow(unrooted_must_root)]
unsafe impl<T: DomObject> JSTraceable for OnceCellJS<T> {
unsafe fn trace(&self, trc: *mut JSTracer) {
if let Some(ptr) = self.ptr.as_ref() {
ptr.trace(trc);
}
}
}
impl<T: DomObject> LayoutJS<T> {
/// Returns an unsafe pointer to the interior of this JS object. This is
/// the only method that be safely accessed from layout. (The fact that