aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJosh Matthews <josh@joshmatthews.net>2014-04-17 17:03:58 -0400
committerJosh Matthews <josh@joshmatthews.net>2014-05-03 14:18:31 -0400
commitbbfed381686aef5703da53a104f9c05c6d3475c5 (patch)
treea5469f4ae02f3657ed6b2c10e668561c875a2859 /src
parent8e10daba979a7a30b69ffd66dd4f3b256c39b615 (diff)
downloadservo-bbfed381686aef5703da53a104f9c05c6d3475c5.tar.gz
servo-bbfed381686aef5703da53a104f9c05c6d3475c5.zip
Move stack roots into Root types instead of RootCollection, removing the aribtrary 10 roots per stack frame restriction.
Diffstat (limited to 'src')
-rw-r--r--src/components/script/dom/bindings/js.rs83
1 files changed, 23 insertions, 60 deletions
diff --git a/src/components/script/dom/bindings/js.rs b/src/components/script/dom/bindings/js.rs
index 3a3b6bd7166..b26d2601139 100644
--- a/src/components/script/dom/bindings/js.rs
+++ b/src/components/script/dom/bindings/js.rs
@@ -8,8 +8,7 @@ use js::jsapi::{JSObject, JSContext};
use layout_interface::TrustedNodeAddress;
use std::cast;
-use std::cell::{Cell, RefCell};
-use std::ptr;
+use std::cell::RefCell;
/// A type that represents a JS-owned value that may or may not be rooted.
/// Importantly, it requires rooting in order to interact with the value in any way.
@@ -238,32 +237,15 @@ impl<T: Reflectable> UnrootedPushable<T> for Vec<JS<T>> {
}
}
-#[deriving(Eq, Clone)]
-struct RootReference(*JSObject);
-
-impl RootReference {
- fn new<'a, 'b, T: Reflectable>(unrooted: &Root<'a, 'b, T>) -> RootReference {
- RootReference(unrooted.rooted())
- }
-
- fn null() -> RootReference {
- RootReference(ptr::null())
- }
-}
-
-static MAX_STACK_ROOTS: uint = 10;
-
/// An opaque, LIFO rooting mechanism.
pub struct RootCollection {
- roots: [Cell<RootReference>, ..MAX_STACK_ROOTS],
- current: Cell<uint>,
+ roots: RefCell<~[*JSObject]>,
}
impl RootCollection {
pub fn new() -> RootCollection {
RootCollection {
- roots: [Cell::new(RootReference::null()), ..MAX_STACK_ROOTS],
- current: Cell::new(0),
+ roots: RefCell::new(~[]),
}
}
@@ -271,40 +253,27 @@ impl RootCollection {
Root::new(self, unrooted)
}
- fn root_impl(&self, unrooted: RootReference) {
- let current = self.current.get();
- assert!(current < MAX_STACK_ROOTS);
- self.roots[current].set(unrooted);
- debug!(" rooting {:?}", unrooted);
- self.current.set(current + 1);
- }
-
fn root<'a, 'b, T: Reflectable>(&self, unrooted: &Root<'a, 'b, T>) {
- self.root_impl(RootReference::new(unrooted));
+ self.root_raw(unrooted.js_ptr);
}
/// Root a raw JS pointer.
pub fn root_raw(&self, unrooted: *JSObject) {
- self.root_impl(RootReference(unrooted));
- }
-
- fn unroot_impl(&self, rooted: RootReference) {
- let mut current = self.current.get();
- assert!(current != 0);
- current -= 1;
- debug!("unrooting {:?} (expecting {:?}", self.roots[current].get(), rooted);
- assert!(self.roots[current].get() == rooted);
- self.roots[current].set(RootReference::null());
- self.current.set(current);
+ let mut roots = self.roots.borrow_mut();
+ roots.push(unrooted);
+ debug!(" rooting {:?}", unrooted);
}
fn unroot<'a, 'b, T: Reflectable>(&self, rooted: &Root<'a, 'b, T>) {
- self.unroot_impl(RootReference::new(rooted));
+ self.unroot_raw(rooted.js_ptr);
}
/// Unroot a raw JS pointer. Must occur in reverse order to its rooting.
pub fn unroot_raw(&self, rooted: *JSObject) {
- self.unroot_impl(RootReference(rooted));
+ let mut roots = self.roots.borrow_mut();
+ debug!("unrooting {:?} (expecting {:?}", roots.last().unwrap(), rooted);
+ assert!(*roots.last().unwrap() == rooted);
+ roots.pop().unwrap();
}
}
@@ -314,9 +283,14 @@ impl RootCollection {
/// Attempts to transfer ownership of a Root via moving will trigger dynamic unrooting
/// failures due to incorrect ordering.
pub struct Root<'a, 'b, T> {
+ /// List that ensures correct dynamic root ordering
root_list: &'a RootCollection,
+ /// Reference to rooted value that must not outlive this container
jsref: JSRef<'b, T>,
+ /// Pointer to underlying Rust data
ptr: RefCell<*mut T>,
+ /// On-stack JS pointer to assuage conservative stack scanner
+ js_ptr: *JSObject,
}
impl<'a, 'b, T: Reflectable> Root<'a, 'b, T> {
@@ -325,9 +299,10 @@ impl<'a, 'b, T: Reflectable> Root<'a, 'b, T> {
root_list: roots,
jsref: JSRef {
ptr: unrooted.ptr.clone(),
- chain: unsafe { ::std::cast::transmute_region(&()) },
+ chain: unsafe { cast::transmute_region(&()) },
},
- ptr: unrooted.ptr.clone()
+ ptr: unrooted.ptr.clone(),
+ js_ptr: unrooted.reflector().get_jsobject(),
};
roots.root(&root);
root
@@ -347,20 +322,8 @@ impl<'a, 'b, T: Reflectable> Root<'a, 'b, T> {
}
}
- fn rooted(&self) -> *JSObject {
- self.reflector().get_jsobject()
- }
-
- fn internal_root_ref<'a>(&'a self) -> &'a JSRef<'b, T> {
- &'a self.jsref
- }
-
- fn mut_internal_root_ref<'a>(&'a mut self) -> &'a mut JSRef<'b, T> {
- &'a mut self.jsref
- }
-
pub fn root_ref<'b>(&'b self) -> JSRef<'b,T> {
- self.internal_root_ref().clone()
+ self.jsref.clone()
}
}
@@ -383,13 +346,13 @@ impl<'a, 'b, T: Reflectable> Reflectable for Root<'a, 'b, T> {
impl<'a, 'b, T: Reflectable> Deref<JSRef<'b, T>> for Root<'a, 'b, T> {
fn deref<'c>(&'c self) -> &'c JSRef<'b, T> {
- self.internal_root_ref()
+ &'a self.jsref
}
}
impl<'a, 'b, T: Reflectable> DerefMut<JSRef<'b, T>> for Root<'a, 'b, T> {
fn deref_mut<'c>(&'c mut self) -> &'c mut JSRef<'b, T> {
- self.mut_internal_root_ref()
+ &'a mut self.jsref
}
}