mirror of
https://github.com/servo/servo.git
synced 2025-06-25 01:24:37 +01:00
Move stack roots into Root types instead of RootCollection, removing the aribtrary 10 roots per stack frame restriction.
This commit is contained in:
parent
8e10daba97
commit
bbfed38168
1 changed files with 23 additions and 60 deletions
|
@ -8,8 +8,7 @@ use js::jsapi::{JSObject, JSContext};
|
||||||
use layout_interface::TrustedNodeAddress;
|
use layout_interface::TrustedNodeAddress;
|
||||||
|
|
||||||
use std::cast;
|
use std::cast;
|
||||||
use std::cell::{Cell, RefCell};
|
use std::cell::RefCell;
|
||||||
use std::ptr;
|
|
||||||
|
|
||||||
/// A type that represents a JS-owned value that may or may not be rooted.
|
/// 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.
|
/// 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.
|
/// An opaque, LIFO rooting mechanism.
|
||||||
pub struct RootCollection {
|
pub struct RootCollection {
|
||||||
roots: [Cell<RootReference>, ..MAX_STACK_ROOTS],
|
roots: RefCell<~[*JSObject]>,
|
||||||
current: Cell<uint>,
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl RootCollection {
|
impl RootCollection {
|
||||||
pub fn new() -> RootCollection {
|
pub fn new() -> RootCollection {
|
||||||
RootCollection {
|
RootCollection {
|
||||||
roots: [Cell::new(RootReference::null()), ..MAX_STACK_ROOTS],
|
roots: RefCell::new(~[]),
|
||||||
current: Cell::new(0),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,40 +253,27 @@ impl RootCollection {
|
||||||
Root::new(self, unrooted)
|
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>) {
|
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.
|
/// Root a raw JS pointer.
|
||||||
pub fn root_raw(&self, unrooted: *JSObject) {
|
pub fn root_raw(&self, unrooted: *JSObject) {
|
||||||
self.root_impl(RootReference(unrooted));
|
let mut roots = self.roots.borrow_mut();
|
||||||
}
|
roots.push(unrooted);
|
||||||
|
debug!(" rooting {:?}", 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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn unroot<'a, 'b, T: Reflectable>(&self, rooted: &Root<'a, 'b, T>) {
|
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.
|
/// Unroot a raw JS pointer. Must occur in reverse order to its rooting.
|
||||||
pub fn unroot_raw(&self, rooted: *JSObject) {
|
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
|
/// Attempts to transfer ownership of a Root via moving will trigger dynamic unrooting
|
||||||
/// failures due to incorrect ordering.
|
/// failures due to incorrect ordering.
|
||||||
pub struct Root<'a, 'b, T> {
|
pub struct Root<'a, 'b, T> {
|
||||||
|
/// List that ensures correct dynamic root ordering
|
||||||
root_list: &'a RootCollection,
|
root_list: &'a RootCollection,
|
||||||
|
/// Reference to rooted value that must not outlive this container
|
||||||
jsref: JSRef<'b, T>,
|
jsref: JSRef<'b, T>,
|
||||||
|
/// Pointer to underlying Rust data
|
||||||
ptr: RefCell<*mut T>,
|
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> {
|
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,
|
root_list: roots,
|
||||||
jsref: JSRef {
|
jsref: JSRef {
|
||||||
ptr: unrooted.ptr.clone(),
|
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);
|
roots.root(&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> {
|
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> {
|
impl<'a, 'b, T: Reflectable> Deref<JSRef<'b, T>> for Root<'a, 'b, T> {
|
||||||
fn deref<'c>(&'c self) -> &'c JSRef<'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> {
|
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> {
|
fn deref_mut<'c>(&'c mut self) -> &'c mut JSRef<'b, T> {
|
||||||
self.mut_internal_root_ref()
|
&'a mut self.jsref
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue