Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Introduce safe checking whether DOMRefCell<T>.borrow_for_layout() is called from layout task #3770

Closed
wants to merge 1 commit into from
Closed
Changes from all commits
Commits
File filter...
Filter file types
Jump to…
Jump to file
Failed to load files.

Always

Just for now

Introduce safe checking whether DOMRefCell<T>.borrow_for_layout() is …

…called from layout task.

This also introduces that checking DOMRefCell<T>'s borrow methods are NOT
called from layout task.
  • Loading branch information
tetsuharuohzeki committed Oct 22, 2014
commit e27a25e591f2b156b32241666e50caf84e8aba25
@@ -39,6 +39,7 @@ use script::layout_interface::{ContentBoxResponse, HitTestResponse, MouseOverRes
use script::layout_interface::{LayoutChan, Msg, PrepareToExitMsg};
use script::layout_interface::{GetRPCMsg, LayoutRPC, ReapLayoutDataMsg, Reflow};
use script::layout_interface::{ReflowForDisplay, ReflowMsg};
use script::layout_interface::LayoutBorrowTLS;
use script_traits::{SendEventMsg, ReflowEvent, ReflowCompleteMsg, OpaqueScriptLayoutChannel};
use script_traits::{ScriptControlChan, UntrustedNodeAddress};
use servo_msg::compositor_msg::Scrollable;
@@ -286,6 +287,8 @@ impl LayoutTask {

/// Starts listening on the port.
fn start(self) {
let _layout_borrow_tls = LayoutBorrowTLS::new();

let mut possibly_locked_rw_data = Some(self.rw_data.lock());
while self.handle_request(&mut possibly_locked_rw_data) {
// Loop indefinitely.
@@ -5,6 +5,9 @@
use dom::bindings::trace::JSTraceable;
use js::jsapi::{JSTracer};

#[cfg(debug)]
use layout_interface::LayoutBorrowMarker;

use std::cell;
use std::cell::RefCell;
use std::mem;
@@ -36,6 +39,7 @@ impl<T> DOMRefCell<T> {

#[inline(always)]
pub fn try_borrow<'a>(&'a self) -> Option<Ref<'a, T>> {
check_not_called_from_layout();
self.base.try_borrow()
}

@@ -46,6 +50,7 @@ impl<T> DOMRefCell<T> {

#[inline(always)]
pub fn try_borrow_mut<'a>(&'a self) -> Option<RefMut<'a, T>> {
check_not_called_from_layout();
self.base.try_borrow_mut()
}

@@ -56,6 +61,8 @@ impl<T> DOMRefCell<T> {

/// This returns the pointer which refers T in `RefCell<T>` directly.
pub unsafe fn borrow_for_layout<'a>(&'a self) -> &'a T {
check_called_in_layout();

let val = mem::transmute::<&RefCell<T>, &T>(&self.base);
val
}
@@ -66,3 +73,25 @@ impl<T: JSTraceable> JSTraceable for DOMRefCell<T> {
(*self).base.borrow().trace(trc)
}
}

#[cfg(debug)]
fn check_called_in_layout() {
if LayoutBorrowMarker.get().is_none() {
fail!("you must not call this method in non layout task.");
}
}

#[cfg(not(debug))]
fn check_called_in_layout() {
}

#[cfg(debug)]
fn check_not_called_from_layout() {
if LayoutBorrowMarker.get().is_some() {
fail!("you must not call this method in layout task.");
}
}

#[cfg(not(debug))]
fn check_not_called_from_layout() {
}
@@ -137,3 +137,31 @@ impl ScriptLayoutChan for OpaqueScriptLayoutChannel {
*receiver.downcast::<Receiver<Msg>>().unwrap()
}
}

/// A task local data to check whether a function (e.g. DOMRefCell<T>.borrow_for_layout)
/// is called from layout task or not.
/// This checker is enabled on debug build only by performance reason.
#[cfg(debug)]
local_data_key!(pub LayoutBorrowMarker: ())

pub struct LayoutBorrowTLS;

impl LayoutBorrowTLS {
#[cfg(debug)]
pub fn new() -> LayoutBorrowTLS {
LayoutBorrowMarker.replace(Some(()));
LayoutBorrowTLS
}

#[cfg(not(debug))]
pub fn new() -> LayoutBorrowTLS {
LayoutBorrowTLS
}
}

#[cfg(debug)]
impl Drop for LayoutBorrowTLS {
fn drop(&mut self) {
let _ = LayoutBorrowMarker.replace(None);
}
}
ProTip! Use n and p to navigate between commits in a pull request.
You can’t perform that action at this time.