Skip to content

Commit

Permalink
Use a stack guard and a macro for RootedVec instead of return_address.
Browse files Browse the repository at this point in the history
  • Loading branch information
eddyb committed Jun 28, 2016
1 parent 8f9d90f commit 17383b5
Show file tree
Hide file tree
Showing 8 changed files with 70 additions and 70 deletions.
10 changes: 4 additions & 6 deletions components/script/dom/bindings/codegen/CodegenRust.py
Original file line number Diff line number Diff line change
Expand Up @@ -1166,23 +1166,22 @@ def __init__(self, argument, index, args, argc, descriptorProvider,
template, variadicConversion, declType, "slot")]

arg = "arg%d" % index

init = "let mut %s = vec![]" % arg
if argument.type.isGeckoInterface():
vec = "RootedVec::new()"
init = "rooted_vec!(%s)" % init
innerConverter.append(CGGeneric("%s.push(JS::from_ref(&*slot));" % arg))
else:
vec = "vec![]"
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()
Expand Down Expand Up @@ -5603,7 +5602,6 @@ def __init__(self, config, prefix, webIDLFile):
'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',
Expand Down
80 changes: 39 additions & 41 deletions components/script/dom/bindings/trace.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ use cssparser::RGBA;
use devtools_traits::CSSError;
use devtools_traits::WorkerId;
use dom::abstractworker::SharedRt;
use dom::bindings::js::{JS, Root};
use dom::bindings::js::JS;
use dom::bindings::refcounted::Trusted;
use dom::bindings::reflector::{Reflectable, Reflector};
use dom::bindings::str::{DOMString, USVString};
Expand Down Expand Up @@ -77,8 +77,7 @@ 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::iter::IntoIterator;
use std::mem;
use std::ops::{Deref, DerefMut};
use std::rc::Rc;
Expand Down Expand Up @@ -458,7 +457,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> {
Expand All @@ -485,73 +484,72 @@ 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 = iterable);`.
#[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> RootedVec<'a, 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: IntoIterator<Item = T>>(root: &'a mut RootableVec<T>, iter: I)
-> RootedVec<'a, T> {
unsafe {
RootedTraceableSet::add(root);
}
root.v.extend(iter);
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
}
}

Expand Down
20 changes: 7 additions & 13 deletions components/script/dom/document.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -1009,18 +1008,13 @@ impl Document {
}
}

let mut touches = RootedVec::new();
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();
target_touches.extend(self.active_touch_points
.borrow()
.iter()
.filter(|t| t.Target() == target)
.cloned());
rooted_vec!(let touches = self.active_touch_points.borrow().iter().cloned());
rooted_vec!(let changed_touches = Some(JS::from_ref(&*touch)));
rooted_vec!(let target_touches = self.active_touch_points
.borrow()
.iter()
.filter(|t| t.Target() == target)
.cloned());

let event = TouchEvent::new(window,
DOMString::from(event_name),
Expand Down
3 changes: 1 addition & 2 deletions components/script/dom/eventdispatcher.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -128,7 +127,7 @@ 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 = Vec::<JS<EventTarget>>::new());

// Step 4.
if let Some(target_node) = target.downcast::<Node>() {
Expand Down
12 changes: 12 additions & 0 deletions components/script/dom/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -503,3 +503,15 @@ macro_rules! document_and_element_event_handlers(
event_handler!(paste, GetOnpaste, SetOnpaste);
)
);

#[macro_export]
macro_rules! rooted_vec {
(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);
}
}
9 changes: 4 additions & 5 deletions components/script/dom/node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand Down Expand Up @@ -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 = vec![]);
let new_nodes = if let NodeTypeId::DocumentFragment = node.type_id() {
// Step 3.
new_nodes.extend(node.children().map(|kid| JS::from_ref(&*kid)));
Expand Down Expand Up @@ -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().map(|child| JS::from_ref(&*child)));
// Step 3.
let mut added_nodes = RootedVec::new();
rooted_vec!(let mut added_nodes = vec![]);
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)));
Expand Down Expand Up @@ -2149,7 +2148,7 @@ impl NodeMethods for Node {
};

// Step 12.
let mut nodes = RootedVec::new();
rooted_vec!(let mut nodes = vec![]);
let nodes = if node.type_id() == NodeTypeId::DocumentFragment {
nodes.extend(node.children().map(|node| JS::from_ref(&*node)));
nodes.r()
Expand Down
4 changes: 2 additions & 2 deletions components/script/dom/range.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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 = Vec::<JS<Node>>::new());
let ancestor = self.CommonAncestorContainer();

let mut iter = start_node.following_nodes(ancestor.r());
Expand Down
2 changes: 1 addition & 1 deletion components/script/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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)]
Expand Down

0 comments on commit 17383b5

Please sign in to comment.