Make GeckoDeclarationBlock refcounted.

This commit is contained in:
Xidorn Quan 2016-08-19 14:49:27 +10:00
parent 7aa0071e9b
commit 2f4d6b5ce1
4 changed files with 61 additions and 32 deletions

View file

@ -148,7 +148,10 @@ COMPILATION_TARGETS = {
"void_types": [ "void_types": [
"nsINode", "nsIDocument", "nsIPrincipal", "nsIURI", "nsINode", "nsIDocument", "nsIPrincipal", "nsIURI",
], ],
"servo_arc_types": ["ServoComputedValues", "RawServoStyleSheet"] "servo_arc_types": [
"ServoComputedValues", "RawServoStyleSheet",
"ServoDeclarationBlock"
]
}, },
"atoms": { "atoms": {

View file

@ -9,6 +9,8 @@ pub type ServoComputedValuesStrong = ::sugar::refptr::Strong<ServoComputedValues
pub type ServoComputedValuesBorrowed<'a> = ::sugar::refptr::Borrowed<'a, ServoComputedValues>; pub type ServoComputedValuesBorrowed<'a> = ::sugar::refptr::Borrowed<'a, ServoComputedValues>;
pub type RawServoStyleSheetStrong = ::sugar::refptr::Strong<RawServoStyleSheet>; pub type RawServoStyleSheetStrong = ::sugar::refptr::Strong<RawServoStyleSheet>;
pub type RawServoStyleSheetBorrowed<'a> = ::sugar::refptr::Borrowed<'a, RawServoStyleSheet>; pub type RawServoStyleSheetBorrowed<'a> = ::sugar::refptr::Borrowed<'a, RawServoStyleSheet>;
pub type ServoDeclarationBlockStrong = ::sugar::refptr::Strong<ServoDeclarationBlock>;
pub type ServoDeclarationBlockBorrowed<'a> = ::sugar::refptr::Borrowed<'a, ServoDeclarationBlock>;
use structs::nsStyleFont; use structs::nsStyleFont;
unsafe impl Send for nsStyleFont {} unsafe impl Send for nsStyleFont {}
unsafe impl Sync for nsStyleFont {} unsafe impl Sync for nsStyleFont {}
@ -254,7 +256,7 @@ extern "C" {
classList: *mut *mut *mut nsIAtom) classList: *mut *mut *mut nsIAtom)
-> u32; -> u32;
pub fn Gecko_GetServoDeclarationBlock(element: *mut RawGeckoElement) pub fn Gecko_GetServoDeclarationBlock(element: *mut RawGeckoElement)
-> *mut ServoDeclarationBlock; -> ServoDeclarationBlockBorrowed;
pub fn Gecko_GetNodeData(node: *mut RawGeckoNode) -> *mut ServoNodeData; pub fn Gecko_GetNodeData(node: *mut RawGeckoNode) -> *mut ServoNodeData;
pub fn Gecko_SetNodeData(node: *mut RawGeckoNode, pub fn Gecko_SetNodeData(node: *mut RawGeckoNode,
data: *mut ServoNodeData); data: *mut ServoNodeData);
@ -467,16 +469,18 @@ extern "C" {
pub fn Servo_DropStyleSet(set: *mut RawServoStyleSet); pub fn Servo_DropStyleSet(set: *mut RawServoStyleSet);
pub fn Servo_ParseStyleAttribute(bytes: *const u8, length: u32, pub fn Servo_ParseStyleAttribute(bytes: *const u8, length: u32,
cache: *mut nsHTMLCSSStyleSheet) cache: *mut nsHTMLCSSStyleSheet)
-> *mut ServoDeclarationBlock; -> ServoDeclarationBlockStrong;
pub fn Servo_DropDeclarationBlock(declarations: pub fn Servo_DeclarationBlock_AddRef(declarations:
*mut ServoDeclarationBlock); ServoDeclarationBlockBorrowed);
pub fn Servo_DeclarationBlock_Release(declarations:
ServoDeclarationBlockBorrowed);
pub fn Servo_GetDeclarationBlockCache(declarations: pub fn Servo_GetDeclarationBlockCache(declarations:
*mut ServoDeclarationBlock) ServoDeclarationBlockBorrowed)
-> *mut nsHTMLCSSStyleSheet; -> *mut nsHTMLCSSStyleSheet;
pub fn Servo_SetDeclarationBlockImmutable(declarations: pub fn Servo_SetDeclarationBlockImmutable(declarations:
*mut ServoDeclarationBlock); ServoDeclarationBlockBorrowed);
pub fn Servo_ClearDeclarationBlockCachePointer(declarations: pub fn Servo_ClearDeclarationBlockCachePointer(declarations:
*mut ServoDeclarationBlock); ServoDeclarationBlockBorrowed);
pub fn Servo_CSSSupports(name: *const u8, name_length: u32, pub fn Servo_CSSSupports(name: *const u8, name_length: u32,
value: *const u8, value_length: u32) -> bool; value: *const u8, value_length: u32) -> bool;
pub fn Servo_GetComputedValues(node: *mut RawGeckoNode) pub fn Servo_GetComputedValues(node: *mut RawGeckoNode)

View file

@ -13,6 +13,7 @@ use gecko_bindings::bindings::{RawGeckoDocument, RawGeckoElement, RawGeckoNode};
use gecko_bindings::bindings::{RawServoStyleSheetBorrowed, ServoComputedValuesBorrowed}; use gecko_bindings::bindings::{RawServoStyleSheetBorrowed, ServoComputedValuesBorrowed};
use gecko_bindings::bindings::{RawServoStyleSheetStrong, ServoComputedValuesStrong}; use gecko_bindings::bindings::{RawServoStyleSheetStrong, ServoComputedValuesStrong};
use gecko_bindings::bindings::{ServoDeclarationBlock, ServoNodeData, ThreadSafePrincipalHolder}; use gecko_bindings::bindings::{ServoDeclarationBlock, ServoNodeData, ThreadSafePrincipalHolder};
use gecko_bindings::bindings::{ServoDeclarationBlockBorrowed, ServoDeclarationBlockStrong};
use gecko_bindings::bindings::{ThreadSafeURIHolder, nsHTMLCSSStyleSheet}; use gecko_bindings::bindings::{ThreadSafeURIHolder, nsHTMLCSSStyleSheet};
use gecko_bindings::ptr::{GeckoArcPrincipal, GeckoArcURI}; use gecko_bindings::ptr::{GeckoArcPrincipal, GeckoArcURI};
use gecko_bindings::structs::ServoElementSnapshot; use gecko_bindings::structs::ServoElementSnapshot;
@ -25,6 +26,7 @@ use std::mem::transmute;
use std::ptr; use std::ptr;
use std::slice; use std::slice;
use std::str::from_utf8_unchecked; use std::str::from_utf8_unchecked;
use std::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use style::arc_ptr_eq; use style::arc_ptr_eq;
use style::context::{LocalStyleContextCreationInfo, ReflowGoal, SharedStyleContext}; use style::context::{LocalStyleContextCreationInfo, ReflowGoal, SharedStyleContext};
@ -355,47 +357,62 @@ pub extern "C" fn Servo_DropStyleSet(data: *mut RawServoStyleSet) -> () {
pub struct GeckoDeclarationBlock { pub struct GeckoDeclarationBlock {
pub declarations: Option<PropertyDeclarationBlock>, pub declarations: Option<PropertyDeclarationBlock>,
pub cache: *mut nsHTMLCSSStyleSheet, // XXX The following two fields are made atomic to work around the
pub immutable: bool, // ownership system so that they can be changed inside a shared
// instance. It wouldn't provide safety as Rust usually promises,
// but it is fine as far as we only access them in a single thread.
// If we need to access them in different threads, we would need
// to redesign how it works with MiscContainer in Gecko side.
pub cache: AtomicPtr<nsHTMLCSSStyleSheet>,
pub immutable: AtomicBool,
}
unsafe impl HasArcFFI for GeckoDeclarationBlock {
type FFIType = ServoDeclarationBlock;
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn Servo_ParseStyleAttribute(bytes: *const u8, length: u32, pub extern "C" fn Servo_ParseStyleAttribute(bytes: *const u8, length: u32,
cache: *mut nsHTMLCSSStyleSheet) cache: *mut nsHTMLCSSStyleSheet)
-> *mut ServoDeclarationBlock { -> ServoDeclarationBlockStrong {
let value = unsafe { from_utf8_unchecked(slice::from_raw_parts(bytes, length as usize)) }; let value = unsafe { from_utf8_unchecked(slice::from_raw_parts(bytes, length as usize)) };
let declarations = Box::new(GeckoDeclarationBlock { GeckoDeclarationBlock::from_arc(Arc::new(GeckoDeclarationBlock {
declarations: GeckoElement::parse_style_attribute(value), declarations: GeckoElement::parse_style_attribute(value),
cache: cache, cache: AtomicPtr::new(cache),
immutable: false, immutable: AtomicBool::new(false),
}); }))
Box::into_raw(declarations) as *mut ServoDeclarationBlock
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn Servo_DropDeclarationBlock(declarations: *mut ServoDeclarationBlock) { pub extern "C" fn Servo_DeclarationBlock_AddRef(declarations: ServoDeclarationBlockBorrowed) {
unsafe { unsafe { GeckoDeclarationBlock::addref(declarations) };
let _ = Box::<GeckoDeclarationBlock>::from_raw(declarations as *mut GeckoDeclarationBlock);
}
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn Servo_GetDeclarationBlockCache(declarations: *mut ServoDeclarationBlock) pub extern "C" fn Servo_DeclarationBlock_Release(declarations: ServoDeclarationBlockBorrowed) {
unsafe { GeckoDeclarationBlock::release(declarations) };
}
#[no_mangle]
pub extern "C" fn Servo_GetDeclarationBlockCache(declarations: ServoDeclarationBlockBorrowed)
-> *mut nsHTMLCSSStyleSheet { -> *mut nsHTMLCSSStyleSheet {
let declarations = unsafe { (declarations as *const GeckoDeclarationBlock).as_ref().unwrap() }; GeckoDeclarationBlock::with(declarations, |declarations| {
declarations.cache declarations.cache.load(Ordering::Relaxed)
})
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn Servo_SetDeclarationBlockImmutable(declarations: *mut ServoDeclarationBlock) { pub extern "C" fn Servo_SetDeclarationBlockImmutable(declarations: ServoDeclarationBlockBorrowed) {
let declarations = unsafe { (declarations as *mut GeckoDeclarationBlock).as_mut().unwrap() }; GeckoDeclarationBlock::with(declarations, |declarations| {
declarations.immutable = true; declarations.immutable.store(true, Ordering::Relaxed)
})
} }
#[no_mangle] #[no_mangle]
pub extern "C" fn Servo_ClearDeclarationBlockCachePointer(declarations: *mut ServoDeclarationBlock) { pub extern "C" fn Servo_ClearDeclarationBlockCachePointer(declarations: ServoDeclarationBlockBorrowed) {
let declarations = unsafe { (declarations as *mut GeckoDeclarationBlock).as_mut().unwrap() }; GeckoDeclarationBlock::with(declarations, |declarations| {
declarations.cache = ptr::null_mut(); declarations.cache.store(ptr::null_mut(), Ordering::Relaxed)
});
} }
#[no_mangle] #[no_mangle]

View file

@ -35,6 +35,7 @@ use snapshot::GeckoElementSnapshot;
use snapshot_helpers; use snapshot_helpers;
use std::fmt; use std::fmt;
use std::marker::PhantomData; use std::marker::PhantomData;
use std::mem::transmute;
use std::ops::BitOr; use std::ops::BitOr;
use std::ptr; use std::ptr;
use std::sync::Arc; use std::sync::Arc;
@ -432,9 +433,13 @@ impl<'le> TElement for GeckoElement<'le> {
} }
fn style_attribute(&self) -> &Option<PropertyDeclarationBlock> { fn style_attribute(&self) -> &Option<PropertyDeclarationBlock> {
unsafe { let declarations = unsafe { Gecko_GetServoDeclarationBlock(self.element) };
let ptr = Gecko_GetServoDeclarationBlock(self.element) as *mut GeckoDeclarationBlock; if declarations.is_null() {
ptr.as_ref().map(|d| &d.declarations).unwrap_or(&NO_STYLE_ATTRIBUTE) &NO_STYLE_ATTRIBUTE
} else {
GeckoDeclarationBlock::with(declarations, |declarations| {
unsafe { transmute(&declarations.declarations) }
})
} }
} }