mirror of
https://github.com/servo/servo.git
synced 2025-07-23 15:23:42 +01:00
Use a stack guard and a macro for RootedVec instead of return_address.
This commit is contained in:
parent
0db1faf876
commit
b79a7d468e
8 changed files with 77 additions and 71 deletions
|
@ -1166,23 +1166,22 @@ class CGArgumentConverter(CGThing):
|
||||||
template, variadicConversion, declType, "slot")]
|
template, variadicConversion, declType, "slot")]
|
||||||
|
|
||||||
arg = "arg%d" % index
|
arg = "arg%d" % index
|
||||||
|
|
||||||
if argument.type.isGeckoInterface():
|
if argument.type.isGeckoInterface():
|
||||||
vec = "RootedVec::new()"
|
init = "rooted_vec!(let mut %s)" % arg
|
||||||
innerConverter.append(CGGeneric("%s.push(JS::from_ref(&*slot));" % arg))
|
innerConverter.append(CGGeneric("%s.push(JS::from_ref(&*slot));" % arg))
|
||||||
else:
|
else:
|
||||||
vec = "vec![]"
|
init = "let mut %s = vec![]" % arg
|
||||||
innerConverter.append(CGGeneric("%s.push(slot);" % arg))
|
innerConverter.append(CGGeneric("%s.push(slot);" % arg))
|
||||||
inner = CGIndenter(CGList(innerConverter, "\n"), 8).define()
|
inner = CGIndenter(CGList(innerConverter, "\n"), 8).define()
|
||||||
|
|
||||||
self.converter = CGGeneric("""\
|
self.converter = CGGeneric("""\
|
||||||
let mut %(arg)s = %(vec)s;
|
%(init)s;
|
||||||
if %(argc)s > %(index)s {
|
if %(argc)s > %(index)s {
|
||||||
%(arg)s.reserve(%(argc)s as usize - %(index)s);
|
%(arg)s.reserve(%(argc)s as usize - %(index)s);
|
||||||
for variadicArg in %(index)s..%(argc)s {
|
for variadicArg in %(index)s..%(argc)s {
|
||||||
%(inner)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):
|
def define(self):
|
||||||
return self.converter.define()
|
return self.converter.define()
|
||||||
|
@ -5603,7 +5602,6 @@ class CGBindingRoot(CGThing):
|
||||||
'dom::bindings::proxyhandler::{get_expando_object, get_property_descriptor}',
|
'dom::bindings::proxyhandler::{get_expando_object, get_property_descriptor}',
|
||||||
'dom::bindings::num::Finite',
|
'dom::bindings::num::Finite',
|
||||||
'dom::bindings::str::{ByteString, DOMString, USVString}',
|
'dom::bindings::str::{ByteString, DOMString, USVString}',
|
||||||
'dom::bindings::trace::RootedVec',
|
|
||||||
'dom::bindings::weakref::{DOM_WEAK_SLOT, WeakBox, WeakReferenceable}',
|
'dom::bindings::weakref::{DOM_WEAK_SLOT, WeakBox, WeakReferenceable}',
|
||||||
'dom::browsingcontext::BrowsingContext',
|
'dom::browsingcontext::BrowsingContext',
|
||||||
'mem::heap_size_of_raw_self_and_children',
|
'mem::heap_size_of_raw_self_and_children',
|
||||||
|
|
|
@ -77,8 +77,6 @@ use std::boxed::FnBox;
|
||||||
use std::cell::{Cell, UnsafeCell};
|
use std::cell::{Cell, UnsafeCell};
|
||||||
use std::collections::{BTreeMap, HashMap, HashSet};
|
use std::collections::{BTreeMap, HashMap, HashSet};
|
||||||
use std::hash::{BuildHasher, Hash};
|
use std::hash::{BuildHasher, Hash};
|
||||||
use std::intrinsics::return_address;
|
|
||||||
use std::iter::{FromIterator, IntoIterator};
|
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ops::{Deref, DerefMut};
|
use std::ops::{Deref, DerefMut};
|
||||||
use std::rc::Rc;
|
use std::rc::Rc;
|
||||||
|
@ -466,7 +464,7 @@ impl RootedTraceableSet {
|
||||||
///
|
///
|
||||||
/// If you have a valid Reflectable, use Root.
|
/// If you have a valid Reflectable, use Root.
|
||||||
/// If you have GC things like *mut JSObject or JSVal, use rooted!.
|
/// 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.
|
/// If you know what you're doing, use this.
|
||||||
#[derive(JSTraceable)]
|
#[derive(JSTraceable)]
|
||||||
pub struct RootedTraceable<'a, T: 'a + 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)]
|
#[allow(unrooted_must_root)]
|
||||||
#[no_move]
|
|
||||||
#[derive(JSTraceable)]
|
#[derive(JSTraceable)]
|
||||||
#[allow_unrooted_interior]
|
#[allow_unrooted_interior]
|
||||||
pub struct RootedVec<T: JSTraceable> {
|
pub struct RootableVec<T: JSTraceable> {
|
||||||
v: Vec<T>,
|
v: Vec<T>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: JSTraceable> RootableVec<T> {
|
||||||
impl<T: JSTraceable> RootedVec<T> {
|
/// Create a vector of items of type T that can be rooted later.
|
||||||
/// Create a vector of items of type T that is rooted for
|
pub fn new_unrooted() -> RootableVec<T> {
|
||||||
/// the lifetime of this struct
|
RootableVec {
|
||||||
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![],
|
v: vec![],
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: JSTraceable + Reflectable> RootedVec<JS<T>> {
|
/// 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<'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<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<'a, T: JSTraceable + Reflectable> RootedVec<'a, JS<T>> {
|
||||||
/// Obtain a safe slice of references that can't outlive that RootedVec.
|
/// Obtain a safe slice of references that can't outlive that RootedVec.
|
||||||
pub fn r(&self) -> &[&T] {
|
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) {
|
fn drop(&mut self) {
|
||||||
|
self.clear();
|
||||||
unsafe {
|
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>;
|
type Target = Vec<T>;
|
||||||
fn deref(&self) -> &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> {
|
fn deref_mut(&mut self) -> &mut Vec<T> {
|
||||||
&mut self.v
|
&mut self.root.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
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -28,7 +28,6 @@ use dom::bindings::num::Finite;
|
||||||
use dom::bindings::refcounted::Trusted;
|
use dom::bindings::refcounted::Trusted;
|
||||||
use dom::bindings::reflector::{Reflectable, reflect_dom_object};
|
use dom::bindings::reflector::{Reflectable, reflect_dom_object};
|
||||||
use dom::bindings::str::{DOMString, USVString};
|
use dom::bindings::str::{DOMString, USVString};
|
||||||
use dom::bindings::trace::RootedVec;
|
|
||||||
use dom::bindings::xmlname::XMLName::InvalidXMLName;
|
use dom::bindings::xmlname::XMLName::InvalidXMLName;
|
||||||
use dom::bindings::xmlname::{validate_and_extract, namespace_from_domstring, xml_name_type};
|
use dom::bindings::xmlname::{validate_and_extract, namespace_from_domstring, xml_name_type};
|
||||||
use dom::browsingcontext::BrowsingContext;
|
use dom::browsingcontext::BrowsingContext;
|
||||||
|
@ -115,6 +114,7 @@ use std::cell::{Cell, Ref, RefMut};
|
||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
use std::collections::hash_map::Entry::{Occupied, Vacant};
|
||||||
use std::default::Default;
|
use std::default::Default;
|
||||||
|
use std::iter::once;
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::rc::Rc;
|
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());
|
touches.extend(self.active_touch_points.borrow().iter().cloned());
|
||||||
|
rooted_vec!(let mut target_touches);
|
||||||
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
|
target_touches.extend(self.active_touch_points
|
||||||
.borrow()
|
.borrow()
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|t| t.Target() == target)
|
.filter(|t| t.Target() == target)
|
||||||
.cloned());
|
.cloned());
|
||||||
|
rooted_vec!(let changed_touches <- once(touch));
|
||||||
|
|
||||||
let event = TouchEvent::new(window,
|
let event = TouchEvent::new(window,
|
||||||
DOMString::from(event_name),
|
DOMString::from(event_name),
|
||||||
|
|
|
@ -9,7 +9,6 @@ use dom::bindings::global::GlobalRoot;
|
||||||
use dom::bindings::inheritance::Castable;
|
use dom::bindings::inheritance::Castable;
|
||||||
use dom::bindings::js::{JS, Root, RootedReference};
|
use dom::bindings::js::{JS, Root, RootedReference};
|
||||||
use dom::bindings::reflector::Reflectable;
|
use dom::bindings::reflector::Reflectable;
|
||||||
use dom::bindings::trace::RootedVec;
|
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
use dom::event::{Event, EventPhase};
|
use dom::event::{Event, EventPhase};
|
||||||
use dom::eventtarget::{CompiledEventListener, EventTarget, ListenerPhase};
|
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,
|
// Step 3. The "invoke" algorithm is only used on `target` separately,
|
||||||
// so we don't put it in the path.
|
// 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.
|
// Step 4.
|
||||||
if let Some(target_node) = target.downcast::<Node>() {
|
if let Some(target_node) = target.downcast::<Node>() {
|
||||||
for ancestor in target_node.ancestors() {
|
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 =
|
let top_most_ancestor_or_target =
|
||||||
Root::from_ref(event_path.r().last().cloned().unwrap_or(target));
|
Root::from_ref(event_path.r().last().cloned().unwrap_or(target));
|
||||||
|
|
|
@ -503,3 +503,18 @@ macro_rules! document_and_element_event_handlers(
|
||||||
event_handler!(paste, GetOnpaste, SetOnpaste);
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -28,7 +28,6 @@ use dom::bindings::js::RootedReference;
|
||||||
use dom::bindings::js::{JS, LayoutJS, MutNullableHeap};
|
use dom::bindings::js::{JS, LayoutJS, MutNullableHeap};
|
||||||
use dom::bindings::reflector::{Reflectable, reflect_dom_object};
|
use dom::bindings::reflector::{Reflectable, reflect_dom_object};
|
||||||
use dom::bindings::str::{DOMString, USVString};
|
use dom::bindings::str::{DOMString, USVString};
|
||||||
use dom::bindings::trace::RootedVec;
|
|
||||||
use dom::bindings::xmlname::namespace_from_domstring;
|
use dom::bindings::xmlname::namespace_from_domstring;
|
||||||
use dom::characterdata::{CharacterData, LayoutCharacterDataHelpers};
|
use dom::characterdata::{CharacterData, LayoutCharacterDataHelpers};
|
||||||
use dom::document::{Document, DocumentSource, IsHTMLDocument};
|
use dom::document::{Document, DocumentSource, IsHTMLDocument};
|
||||||
|
@ -1559,7 +1558,7 @@ impl Node {
|
||||||
parent.ranges.increase_above(parent, index, count);
|
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() {
|
let new_nodes = if let NodeTypeId::DocumentFragment = node.type_id() {
|
||||||
// Step 3.
|
// Step 3.
|
||||||
new_nodes.extend(node.children().map(|kid| JS::from_ref(&*kid)));
|
new_nodes.extend(node.children().map(|kid| JS::from_ref(&*kid)));
|
||||||
|
@ -1603,9 +1602,9 @@ impl Node {
|
||||||
Node::adopt(node, &*parent.owner_doc());
|
Node::adopt(node, &*parent.owner_doc());
|
||||||
}
|
}
|
||||||
// Step 2.
|
// Step 2.
|
||||||
let removed_nodes = parent.children().collect::<RootedVec<_>>();
|
rooted_vec!(let removed_nodes <- parent.children());
|
||||||
// Step 3.
|
// Step 3.
|
||||||
let mut added_nodes = RootedVec::new();
|
rooted_vec!(let mut added_nodes);
|
||||||
let added_nodes = if let Some(node) = node.as_ref() {
|
let added_nodes = if let Some(node) = node.as_ref() {
|
||||||
if let NodeTypeId::DocumentFragment = node.type_id() {
|
if let NodeTypeId::DocumentFragment = node.type_id() {
|
||||||
added_nodes.extend(node.children().map(|child| JS::from_ref(&*child)));
|
added_nodes.extend(node.children().map(|child| JS::from_ref(&*child)));
|
||||||
|
@ -2149,7 +2148,7 @@ impl NodeMethods for Node {
|
||||||
};
|
};
|
||||||
|
|
||||||
// Step 12.
|
// Step 12.
|
||||||
let mut nodes = RootedVec::new();
|
rooted_vec!(let mut nodes);
|
||||||
let nodes = if node.type_id() == NodeTypeId::DocumentFragment {
|
let nodes = if node.type_id() == NodeTypeId::DocumentFragment {
|
||||||
nodes.extend(node.children().map(|node| JS::from_ref(&*node)));
|
nodes.extend(node.children().map(|node| JS::from_ref(&*node)));
|
||||||
nodes.r()
|
nodes.r()
|
||||||
|
|
|
@ -17,7 +17,7 @@ use dom::bindings::inheritance::{CharacterDataTypeId, NodeTypeId};
|
||||||
use dom::bindings::js::{JS, MutHeap, Root, RootedReference};
|
use dom::bindings::js::{JS, MutHeap, Root, RootedReference};
|
||||||
use dom::bindings::reflector::{Reflector, reflect_dom_object};
|
use dom::bindings::reflector::{Reflector, reflect_dom_object};
|
||||||
use dom::bindings::str::DOMString;
|
use dom::bindings::str::DOMString;
|
||||||
use dom::bindings::trace::{JSTraceable, RootedVec};
|
use dom::bindings::trace::JSTraceable;
|
||||||
use dom::bindings::weakref::{WeakRef, WeakRefVec};
|
use dom::bindings::weakref::{WeakRef, WeakRefVec};
|
||||||
use dom::characterdata::CharacterData;
|
use dom::characterdata::CharacterData;
|
||||||
use dom::document::Document;
|
use dom::document::Document;
|
||||||
|
@ -762,7 +762,7 @@ impl RangeMethods for Range {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Step 4.
|
// Step 4.
|
||||||
let mut contained_children: RootedVec<JS<Node>> = RootedVec::new();
|
rooted_vec!(let mut contained_children);
|
||||||
let ancestor = self.CommonAncestorContainer();
|
let ancestor = self.CommonAncestorContainer();
|
||||||
|
|
||||||
let mut iter = start_node.following_nodes(ancestor.r());
|
let mut iter = start_node.following_nodes(ancestor.r());
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
#![feature(borrow_state)]
|
#![feature(borrow_state)]
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
#![feature(const_fn)]
|
#![feature(const_fn)]
|
||||||
#![feature(core_intrinsics)]
|
#![cfg_attr(debug_assertions, feature(core_intrinsics))]
|
||||||
#![feature(custom_attribute)]
|
#![feature(custom_attribute)]
|
||||||
#![feature(custom_derive)]
|
#![feature(custom_derive)]
|
||||||
#![feature(fnbox)]
|
#![feature(fnbox)]
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue