diff options
author | Josh Matthews <josh@joshmatthews.net> | 2014-04-17 17:03:58 -0400 |
---|---|---|
committer | Josh Matthews <josh@joshmatthews.net> | 2014-05-03 14:18:31 -0400 |
commit | bbfed381686aef5703da53a104f9c05c6d3475c5 (patch) | |
tree | a5469f4ae02f3657ed6b2c10e668561c875a2859 /src | |
parent | 8e10daba979a7a30b69ffd66dd4f3b256c39b615 (diff) | |
download | servo-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.rs | 83 |
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 } } |