Skip to content

Instantly share code, notes, and snippets.

View jdm's full-sized avatar

Josh Matthews jdm

View GitHub Profile
0:00.87 LOG: MainThread INFO Using existing host cert
0:00.88 LOG: MainThread wptserve INFO Starting http server on localhost:8001
0:00.88 LOG: MainThread wptserve INFO Starting http server on localhost:8000
0:00.89 LOG: MainThread wptserve INFO Starting http server on localhost:8443
0:02.88 SUITE_START: MainThread 1
0:02.88 LOG: MainThread INFO Running testharness tests
0:02.88 LOG: Thread-TestrunnerManager-1 INFO Starting runner
0:02.88 LOG: Thread-TestrunnerManager-2 INFO Starting runner
0:02.88 LOG: Thread-TestrunnerManager-3 INFO Starting runner
0:02.89 LOG: Thread-TestrunnerManager-4 INFO Starting runner
Thread 20 (Thread 0x7fffe5ff8700 (LWP 31230)):
#0 0x00000000004dc9e0 in comm::Clone$SharedChan::clone::h83558f8b1053bfe1RMaS::v0.0 ()
at /home/keegan/proj/servo/servo/src/components/main/layout/extra.rs:30
#1 0x00000000004dc934 in layout_interface::Clone$LayoutChan::clone::he75398f98adbed4eByaR::v0.0 ()
at /home/keegan/proj/servo/servo/src/components/main/layout/extra.rs:30
#2 0x00000000006354f3 in servo::layout::parallel::recalc_style_for_node (unsafe_layout_node=..., proxy=0x7fffe5ff79c0)
at /home/keegan/proj/servo/servo/src/components/main/layout/parallel.rs:231
#3 0x00000000005f8ebb in workqueue::WorkerThread::start::h9c887a3058c01fb80Uad::v0.0 ()
at /home/keegan/proj/servo/servo/src/components/main/compositing/compositor_layer.rs:257
#4 0x00000000005f84e2 in workqueue::WorkQueue::new::anon::expr_fn::_7UalaZ ()
@jdm
jdm / gist:9332689
Last active August 29, 2015 13:56 — forked from pcwalton/gist:9280996
#[feature(macro_rules)];
use std::cast;
trait RootedReference<T> {
fn root_ref<'a>(&'a self) -> Option<JSRef<'a, T>>;
}
impl<T> RootedReference<T> for Option<Rooted<T>> {
fn root_ref<'a>(&'a self) -> Option<JSRef<'a, T>> {
extern crate collections;
use std::cell::Cell;
use std::libc;
use std::ptr;
trait RootedReference<T> {
fn root_ref<'a>(&'a self) -> Option<JSRef<'a, T>>;
}
DOM types contain JSField<T> - this has an assign method which accepts Unrooted<T> values as well as &JSRef<T>, and a root method which returns Root<T>.
DOM methods accept &JSRef<T> - this is a rooted value reference, obtainable from a Root<T>.
DOM methods return Unrooted<T> - this is an unrooted value, and can only be used to obtain a Root<T>
There exist Root<T> types, which are stack-based roots for values that require explicit rooting. There should not be a need for DOM implementors to store or pass these around (or even refer to them).
If we implement all traits that are currently implemented on JS<T> on JSRef<T> instead, all self-references during method execution will be guaranteed rooted for the duration of the method. Any DOM method call will require explicitly rooting any used member fields in order to call any methods on them.
(in practice, JS<T> serves as JSField<T> if we change the target of the various traits currently implemented for JS<T>)
struct Root {
jsref: JSRef
}
impl Deref<JSRef> for Root {
fn deref<'a>(&'a self) -> &'a JSRef {
&self.jsref
}
}
[jdm@rosencrantz tmp]$ RUST_LOG=rustc::middle::typeck::check::method rustc deref.rs
method lookup(self_ty=&'a JSRef, expr=expr(51: self.get()), self_expr=expr(50: self))
searching inherent candidates
push_candidates_from_impl: get JSRef [AddChild, get]
method lookup_in_trait(self_ty=JSRef, self_expr=None)
push_candidates_from_impl: deref Root.Deref<JSRef> [deref]
push_candidates_from_impl: deref JSRef.Deref<Node> [deref]
push_candidates_from_impl: deref Rc<T>.Deref<T> [deref]
push_candidates_from_impl: deref Ref<'b, T>.Deref<T> [deref]
push_candidates_from_impl: deref RefMut<'b, T>.Deref<T> [deref]
// http://www.whatwg.org/specs/web-apps/current-work/#dom-document-body
pub fn SetBody(&self, abstract_self: &JSRef<Document>, new_body: Option<JSRef<HTMLElement>>) -> ErrorResult {
let roots = RootCollection::new();
// Step 1.
match new_body {
Some(ref node) => {
match node.get().element.node.type_id {
ElementNodeTypeId(HTMLBodyElementTypeId) | ElementNodeTypeId(HTMLFrameSetElementTypeId) => {}
_ => return Err(HierarchyRequest)
pub trait OptionalRootable {
fn root<'a>(&self, roots: &'a RootCollection) -> Option<Root<'a>>;
}
impl<T> OptionalRootable for Option<T> {
fn root<'a>(&self, roots: &'a RootCollection) -> Option<Root<'a>> {
None
}
}
Low-level DOM hackers for Gecko are concerned about the Rust SpiderMonkey integration for the following reasons:
* duplicating C++ logic in Rust is technical debt
* there are C++ classes designed to be inlined as much as possible (eg. Rooted, Value, Handle, MutableHandle, Heap, PersistentRooted (see RootingAPI.h)) for which we will need analogues, at minimum
* there are other C++ classes which don't necessarily need inlining, but reflect low-level implementation details that can be easy to get wrong (eg. shadow types in jsfriendapi.h, parts of js::Class)
* there are C++ methods designed for hot paths which use these details and expect to be inlined (eg. inline functions in jsfriendapi.h like ToNumber and ToString)
We want to reduce the maintenance burden of keeping up with SpiderMonkey upgrades that can change any of these at any time, and we want to ensure that we can achieve comparable speeds to Gecko's DOM bindings by using the same tricks and techniques that require these types/methods.