diff options
author | Eduard Burtescu <edy.burt@gmail.com> | 2016-07-04 20:24:06 +0300 |
---|---|---|
committer | Eduard Burtescu <edy.burt@gmail.com> | 2016-07-04 20:59:06 +0300 |
commit | b79a7d468e99f335dce49cc48342f0cd447eb855 (patch) | |
tree | a98f95839eb04fcda6bf5ea8f4d1ee0e53423fdb | |
parent | 0db1faf87651c99223683faafc836353f016ffb3 (diff) | |
download | servo-b79a7d468e99f335dce49cc48342f0cd447eb855.tar.gz servo-b79a7d468e99f335dce49cc48342f0cd447eb855.zip |
Use a stack guard and a macro for RootedVec instead of return_address.
-rw-r--r-- | components/script/dom/bindings/codegen/CodegenRust.py | 10 | ||||
-rw-r--r-- | components/script/dom/bindings/trace.rs | 78 | ||||
-rw-r--r-- | components/script/dom/document.rs | 11 | ||||
-rw-r--r-- | components/script/dom/eventdispatcher.rs | 5 | ||||
-rw-r--r-- | components/script/dom/macros.rs | 15 | ||||
-rw-r--r-- | components/script/dom/node.rs | 9 | ||||
-rw-r--r-- | components/script/dom/range.rs | 4 | ||||
-rw-r--r-- | components/script/lib.rs | 2 |
8 files changed, 70 insertions, 64 deletions
diff --git a/components/script/dom/bindings/codegen/CodegenRust.py b/components/script/dom/bindings/codegen/CodegenRust.py index ef50ebeb71d..12510e25d7d 100644 --- a/components/script/dom/bindings/codegen/CodegenRust.py +++ b/components/script/dom/bindings/codegen/CodegenRust.py @@ -1166,23 +1166,22 @@ class CGArgumentConverter(CGThing): template, variadicConversion, declType, "slot")] arg = "arg%d" % index - if argument.type.isGeckoInterface(): - vec = "RootedVec::new()" + init = "rooted_vec!(let mut %s)" % arg innerConverter.append(CGGeneric("%s.push(JS::from_ref(&*slot));" % arg)) else: - vec = "vec![]" + init = "let mut %s = vec![]" % arg innerConverter.append(CGGeneric("%s.push(slot);" % arg)) inner = CGIndenter(CGList(innerConverter, "\n"), 8).define() self.converter = CGGeneric("""\ -let mut %(arg)s = %(vec)s; +%(init)s; if %(argc)s > %(index)s { %(arg)s.reserve(%(argc)s as usize - %(index)s); for variadicArg in %(index)s..%(argc)s { %(inner)s } -}""" % {'arg': arg, 'argc': argc, 'index': index, 'inner': inner, 'vec': vec}) +}""" % {'arg': arg, 'argc': argc, 'index': index, 'inner': inner, 'init': init}) def define(self): return self.converter.define() @@ -5603,7 +5602,6 @@ class CGBindingRoot(CGThing): 'dom::bindings::proxyhandler::{get_expando_object, get_property_descriptor}', 'dom::bindings::num::Finite', 'dom::bindings::str::{ByteString, DOMString, USVString}', - 'dom::bindings::trace::RootedVec', 'dom::bindings::weakref::{DOM_WEAK_SLOT, WeakBox, WeakReferenceable}', 'dom::browsingcontext::BrowsingContext', 'mem::heap_size_of_raw_self_and_children', diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs index 8816da8b099..aa9fa1b075d 100644 --- a/components/script/dom/bindings/trace.rs +++ b/components/script/dom/bindings/trace.rs @@ -77,8 +77,6 @@ use std::boxed::FnBox; use std::cell::{Cell, UnsafeCell}; use std::collections::{BTreeMap, HashMap, HashSet}; use std::hash::{BuildHasher, Hash}; -use std::intrinsics::return_address; -use std::iter::{FromIterator, IntoIterator}; use std::mem; use std::ops::{Deref, DerefMut}; use std::rc::Rc; @@ -466,7 +464,7 @@ impl RootedTraceableSet { /// /// If you have a valid Reflectable, use Root. /// If you have GC things like *mut JSObject or JSVal, use rooted!. -/// If you have an arbitrary number of Reflectables to root, use RootedVec<JS<T>> +/// If you have an arbitrary number of Reflectables to root, use rooted_vec!. /// If you know what you're doing, use this. #[derive(JSTraceable)] pub struct RootedTraceable<'a, T: 'a + JSTraceable> { @@ -493,73 +491,73 @@ impl<'a, T: JSTraceable> Drop for RootedTraceable<'a, T> { } } -/// A vector of items that are rooted for the lifetime of this struct. +/// A vector of items to be rooted with `RootedVec`. +/// Guaranteed to be empty when not rooted. +/// Usage: `rooted_vec!(let mut v);` or if you have an +/// iterator of `Root`s, `rooted_vec!(let v <- iterator);`. #[allow(unrooted_must_root)] -#[no_move] #[derive(JSTraceable)] #[allow_unrooted_interior] -pub struct RootedVec<T: JSTraceable> { +pub struct RootableVec<T: JSTraceable> { v: Vec<T>, } +impl<T: JSTraceable> RootableVec<T> { + /// Create a vector of items of type T that can be rooted later. + pub fn new_unrooted() -> RootableVec<T> { + RootableVec { + v: vec![], + } + } +} + +/// A vector of items that are rooted for the lifetime 'a. +#[allow_unrooted_interior] +pub struct RootedVec<'a, T: 'a + JSTraceable> { + root: &'a mut RootableVec<T>, +} -impl<T: JSTraceable> RootedVec<T> { +impl<'a, T: JSTraceable + Reflectable> RootedVec<'a, JS<T>> { /// Create a vector of items of type T that is rooted for /// the lifetime of this struct - pub fn new() -> RootedVec<T> { - let addr = unsafe { return_address() as *const libc::c_void }; - - unsafe { RootedVec::new_with_destination_address(addr) } - } - - /// Create a vector of items of type T. This constructor is specific - /// for RootTraceableSet. - pub unsafe fn new_with_destination_address(addr: *const libc::c_void) -> RootedVec<T> { - RootedTraceableSet::add::<RootedVec<T>>(&*(addr as *const _)); - RootedVec::<T> { - v: vec![], + pub fn new<I: Iterator<Item = Root<T>>>(root: &'a mut RootableVec<JS<T>>, iter: I) + -> RootedVec<'a, JS<T>> { + unsafe { + RootedTraceableSet::add(root); + } + root.v.extend(iter.map(|item| JS::from_ref(&*item))); + RootedVec { + root: root, } } } -impl<T: JSTraceable + Reflectable> RootedVec<JS<T>> { +impl<'a, T: JSTraceable + Reflectable> RootedVec<'a, JS<T>> { /// Obtain a safe slice of references that can't outlive that RootedVec. pub fn r(&self) -> &[&T] { - unsafe { mem::transmute(&self.v[..]) } + unsafe { mem::transmute(&self[..]) } } } -impl<T: JSTraceable> Drop for RootedVec<T> { +impl<'a, T: JSTraceable> Drop for RootedVec<'a, T> { fn drop(&mut self) { + self.clear(); unsafe { - RootedTraceableSet::remove(self); + RootedTraceableSet::remove(self.root); } } } -impl<T: JSTraceable> Deref for RootedVec<T> { +impl<'a, T: JSTraceable> Deref for RootedVec<'a, T> { type Target = Vec<T>; fn deref(&self) -> &Vec<T> { - &self.v + &self.root.v } } -impl<T: JSTraceable> DerefMut for RootedVec<T> { +impl<'a, T: JSTraceable> DerefMut for RootedVec<'a, T> { fn deref_mut(&mut self) -> &mut Vec<T> { - &mut self.v - } -} - -impl<A: JSTraceable + Reflectable> FromIterator<Root<A>> for RootedVec<JS<A>> { - #[allow(moved_no_move)] - fn from_iter<T>(iterable: T) -> RootedVec<JS<A>> - where T: IntoIterator<Item = Root<A>> - { - let mut vec = unsafe { - RootedVec::new_with_destination_address(return_address() as *const libc::c_void) - }; - vec.extend(iterable.into_iter().map(|item| JS::from_ref(&*item))); - vec + &mut self.root.v } } diff --git a/components/script/dom/document.rs b/components/script/dom/document.rs index 23c50075068..7b3697e6a1b 100644 --- a/components/script/dom/document.rs +++ b/components/script/dom/document.rs @@ -28,7 +28,6 @@ use dom::bindings::num::Finite; use dom::bindings::refcounted::Trusted; use dom::bindings::reflector::{Reflectable, reflect_dom_object}; use dom::bindings::str::{DOMString, USVString}; -use dom::bindings::trace::RootedVec; use dom::bindings::xmlname::XMLName::InvalidXMLName; use dom::bindings::xmlname::{validate_and_extract, namespace_from_domstring, xml_name_type}; use dom::browsingcontext::BrowsingContext; @@ -115,6 +114,7 @@ use std::cell::{Cell, Ref, RefMut}; use std::collections::HashMap; use std::collections::hash_map::Entry::{Occupied, Vacant}; use std::default::Default; +use std::iter::once; use std::mem; use std::ptr; use std::rc::Rc; @@ -1009,18 +1009,15 @@ impl Document { } } - let mut touches = RootedVec::new(); + rooted_vec!(let mut touches); touches.extend(self.active_touch_points.borrow().iter().cloned()); - - let mut changed_touches = RootedVec::new(); - changed_touches.push(JS::from_ref(&*touch)); - - let mut target_touches = RootedVec::new(); + rooted_vec!(let mut target_touches); target_touches.extend(self.active_touch_points .borrow() .iter() .filter(|t| t.Target() == target) .cloned()); + rooted_vec!(let changed_touches <- once(touch)); let event = TouchEvent::new(window, DOMString::from(event_name), diff --git a/components/script/dom/eventdispatcher.rs b/components/script/dom/eventdispatcher.rs index cef67d2d18c..7509df2ef13 100644 --- a/components/script/dom/eventdispatcher.rs +++ b/components/script/dom/eventdispatcher.rs @@ -9,7 +9,6 @@ use dom::bindings::global::GlobalRoot; use dom::bindings::inheritance::Castable; use dom::bindings::js::{JS, Root, RootedReference}; use dom::bindings::reflector::Reflectable; -use dom::bindings::trace::RootedVec; use dom::document::Document; use dom::event::{Event, EventPhase}; use dom::eventtarget::{CompiledEventListener, EventTarget, ListenerPhase}; @@ -128,12 +127,12 @@ pub fn dispatch_event(target: &EventTarget, // Step 3. The "invoke" algorithm is only used on `target` separately, // so we don't put it in the path. - let mut event_path: RootedVec<JS<EventTarget>> = RootedVec::new(); + rooted_vec!(let mut event_path); // Step 4. if let Some(target_node) = target.downcast::<Node>() { for ancestor in target_node.ancestors() { - event_path.push(JS::from_ref(ancestor.upcast())); + event_path.push(JS::from_ref(ancestor.upcast::<EventTarget>())); } let top_most_ancestor_or_target = Root::from_ref(event_path.r().last().cloned().unwrap_or(target)); diff --git a/components/script/dom/macros.rs b/components/script/dom/macros.rs index 3ad9713fb70..58af2b28ac6 100644 --- a/components/script/dom/macros.rs +++ b/components/script/dom/macros.rs @@ -503,3 +503,18 @@ macro_rules! document_and_element_event_handlers( event_handler!(paste, GetOnpaste, SetOnpaste); ) ); + +#[macro_export] +macro_rules! rooted_vec { + (let mut $name:ident) => { + rooted_vec!(let mut $name <- ::std::iter::empty()) + }; + (let $name:ident <- $iter:expr) => { + let mut __root = $crate::dom::bindings::trace::RootableVec::new_unrooted(); + let $name = $crate::dom::bindings::trace::RootedVec::new(&mut __root, $iter); + }; + (let mut $name:ident <- $iter:expr) => { + let mut __root = $crate::dom::bindings::trace::RootableVec::new_unrooted(); + let mut $name = $crate::dom::bindings::trace::RootedVec::new(&mut __root, $iter); + } +} diff --git a/components/script/dom/node.rs b/components/script/dom/node.rs index ec370dff293..7c844cab02e 100644 --- a/components/script/dom/node.rs +++ b/components/script/dom/node.rs @@ -28,7 +28,6 @@ use dom::bindings::js::RootedReference; use dom::bindings::js::{JS, LayoutJS, MutNullableHeap}; use dom::bindings::reflector::{Reflectable, reflect_dom_object}; use dom::bindings::str::{DOMString, USVString}; -use dom::bindings::trace::RootedVec; use dom::bindings::xmlname::namespace_from_domstring; use dom::characterdata::{CharacterData, LayoutCharacterDataHelpers}; use dom::document::{Document, DocumentSource, IsHTMLDocument}; @@ -1559,7 +1558,7 @@ impl Node { parent.ranges.increase_above(parent, index, count); } } - let mut new_nodes = RootedVec::new(); + rooted_vec!(let mut new_nodes); let new_nodes = if let NodeTypeId::DocumentFragment = node.type_id() { // Step 3. new_nodes.extend(node.children().map(|kid| JS::from_ref(&*kid))); @@ -1603,9 +1602,9 @@ impl Node { Node::adopt(node, &*parent.owner_doc()); } // Step 2. - let removed_nodes = parent.children().collect::<RootedVec<_>>(); + rooted_vec!(let removed_nodes <- parent.children()); // Step 3. - let mut added_nodes = RootedVec::new(); + rooted_vec!(let mut added_nodes); let added_nodes = if let Some(node) = node.as_ref() { if let NodeTypeId::DocumentFragment = node.type_id() { added_nodes.extend(node.children().map(|child| JS::from_ref(&*child))); @@ -2149,7 +2148,7 @@ impl NodeMethods for Node { }; // Step 12. - let mut nodes = RootedVec::new(); + rooted_vec!(let mut nodes); let nodes = if node.type_id() == NodeTypeId::DocumentFragment { nodes.extend(node.children().map(|node| JS::from_ref(&*node))); nodes.r() diff --git a/components/script/dom/range.rs b/components/script/dom/range.rs index bde5515238b..b8cb72c4dc4 100644 --- a/components/script/dom/range.rs +++ b/components/script/dom/range.rs @@ -17,7 +17,7 @@ use dom::bindings::inheritance::{CharacterDataTypeId, NodeTypeId}; use dom::bindings::js::{JS, MutHeap, Root, RootedReference}; use dom::bindings::reflector::{Reflector, reflect_dom_object}; use dom::bindings::str::DOMString; -use dom::bindings::trace::{JSTraceable, RootedVec}; +use dom::bindings::trace::JSTraceable; use dom::bindings::weakref::{WeakRef, WeakRefVec}; use dom::characterdata::CharacterData; use dom::document::Document; @@ -762,7 +762,7 @@ impl RangeMethods for Range { } // Step 4. - let mut contained_children: RootedVec<JS<Node>> = RootedVec::new(); + rooted_vec!(let mut contained_children); let ancestor = self.CommonAncestorContainer(); let mut iter = start_node.following_nodes(ancestor.r()); diff --git a/components/script/lib.rs b/components/script/lib.rs index ebc5b4a1686..4f66095e1ff 100644 --- a/components/script/lib.rs +++ b/components/script/lib.rs @@ -6,7 +6,7 @@ #![feature(borrow_state)] #![feature(box_syntax)] #![feature(const_fn)] -#![feature(core_intrinsics)] +#![cfg_attr(debug_assertions, feature(core_intrinsics))] #![feature(custom_attribute)] #![feature(custom_derive)] #![feature(fnbox)] |