aboutsummaryrefslogtreecommitdiffstats
path: root/components/script/dom/bindings/trace.rs
diff options
context:
space:
mode:
authorbors-servo <lbergstrom+bors@mozilla.com>2016-07-04 11:03:35 -0700
committerGitHub <noreply@github.com>2016-07-04 11:03:35 -0700
commit80cb0cf8214fd52d2884724614c40cb278ee7575 (patch)
treed5d98004a84375aea65a74d594dead5a27fc2392 /components/script/dom/bindings/trace.rs
parent36974f0746261b971c93ed7dfb9bd726675ccf69 (diff)
parentb79a7d468e99f335dce49cc48342f0cd447eb855 (diff)
downloadservo-80cb0cf8214fd52d2884724614c40cb278ee7575.tar.gz
servo-80cb0cf8214fd52d2884724614c40cb278ee7575.zip
Auto merge of #11872 - eddyb:back-to-roots, r=Ms2ger
Replace return_address usage for rooting with stack guards and convenience macros. The existing `Rooted` and `RootedVec` users were migrated the the following two macros: ```rust let x = Rooted::new(cx, value); // Was changed to: rooted!(in(cx) let x = value); // Which expands to: let mut __root = Rooted::new_unrooted(value); let x = RootedGuard::new(cx, &mut __root); ``` ```rust let mut v = RootedVec::new(); v.extend(iterator); // Was changed to: rooted_vec!(let v <- iterator); // Which expands to: let mut __root = RootableVec::new(); let v = RootedVec::new(&mut __root, iterator); ``` The `rooted!` macro depends on servo/rust-mozjs#272. These APIs based on two types, a container to be rooted and a rooting guard, allow implementing both `Rooted`-style rooting and `Traceable`-based rooting in stable Rust, without abusing `return_address`. Such macros may have been tried before, but in 1.9 their hygiene is broken, they work only since 1.10. Sadly, `Rooted` is a FFI type and completely exposed, so I cannot prevent anyone from creating their own, although all fields but the value get overwritten by `RootedGuard::new` anyway. `RootableVec` OTOH is *guaranteed* to be empty when not rooted, which makes it harmless AFAICT. By fixing rust-lang/rust#34227, this PR enables Servo to build with `-Zorbit`. --- - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [x] These changes fix rust-lang/rust#34227 - [x] These changes do not require tests because they are not functional changes <!-- Reviewable:start --> --- This change is [<img src="https://reviewable.io/review_button.svg" height="35" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/11872) <!-- Reviewable:end -->
Diffstat (limited to 'components/script/dom/bindings/trace.rs')
-rw-r--r--components/script/dom/bindings/trace.rs80
1 files changed, 39 insertions, 41 deletions
diff --git a/components/script/dom/bindings/trace.rs b/components/script/dom/bindings/trace.rs
index a0813a047df..d066db9dfcb 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,8 +464,8 @@ impl RootedTraceableSet {
/// Roots any JSTraceable thing
///
/// If you have a valid Reflectable, use Root.
-/// If you have GC things like *mut JSObject or JSVal, use jsapi::Rooted.
-/// If you have an arbitrary number of Reflectables to root, use RootedVec<JS<T>>
+/// If you have GC things like *mut JSObject or JSVal, use rooted!.
+/// 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> {
@@ -494,73 +492,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
}
}