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": [
"nsINode", "nsIDocument", "nsIPrincipal", "nsIURI",
],
"servo_arc_types": ["ServoComputedValues", "RawServoStyleSheet"]
"servo_arc_types": [
"ServoComputedValues", "RawServoStyleSheet",
"ServoDeclarationBlock"
]
},
"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 RawServoStyleSheetStrong = ::sugar::refptr::Strong<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;
unsafe impl Send for nsStyleFont {}
unsafe impl Sync for nsStyleFont {}
@ -254,7 +256,7 @@ extern "C" {
classList: *mut *mut *mut nsIAtom)
-> u32;
pub fn Gecko_GetServoDeclarationBlock(element: *mut RawGeckoElement)
-> *mut ServoDeclarationBlock;
-> ServoDeclarationBlockBorrowed;
pub fn Gecko_GetNodeData(node: *mut RawGeckoNode) -> *mut ServoNodeData;
pub fn Gecko_SetNodeData(node: *mut RawGeckoNode,
data: *mut ServoNodeData);
@ -467,16 +469,18 @@ extern "C" {
pub fn Servo_DropStyleSet(set: *mut RawServoStyleSet);
pub fn Servo_ParseStyleAttribute(bytes: *const u8, length: u32,
cache: *mut nsHTMLCSSStyleSheet)
-> *mut ServoDeclarationBlock;
pub fn Servo_DropDeclarationBlock(declarations:
*mut ServoDeclarationBlock);
-> ServoDeclarationBlockStrong;
pub fn Servo_DeclarationBlock_AddRef(declarations:
ServoDeclarationBlockBorrowed);
pub fn Servo_DeclarationBlock_Release(declarations:
ServoDeclarationBlockBorrowed);
pub fn Servo_GetDeclarationBlockCache(declarations:
*mut ServoDeclarationBlock)
ServoDeclarationBlockBorrowed)
-> *mut nsHTMLCSSStyleSheet;
pub fn Servo_SetDeclarationBlockImmutable(declarations:
*mut ServoDeclarationBlock);
ServoDeclarationBlockBorrowed);
pub fn Servo_ClearDeclarationBlockCachePointer(declarations:
*mut ServoDeclarationBlock);
ServoDeclarationBlockBorrowed);
pub fn Servo_CSSSupports(name: *const u8, name_length: u32,
value: *const u8, value_length: u32) -> bool;
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::{RawServoStyleSheetStrong, ServoComputedValuesStrong};
use gecko_bindings::bindings::{ServoDeclarationBlock, ServoNodeData, ThreadSafePrincipalHolder};
use gecko_bindings::bindings::{ServoDeclarationBlockBorrowed, ServoDeclarationBlockStrong};
use gecko_bindings::bindings::{ThreadSafeURIHolder, nsHTMLCSSStyleSheet};
use gecko_bindings::ptr::{GeckoArcPrincipal, GeckoArcURI};
use gecko_bindings::structs::ServoElementSnapshot;
@ -25,6 +26,7 @@ use std::mem::transmute;
use std::ptr;
use std::slice;
use std::str::from_utf8_unchecked;
use std::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
use std::sync::{Arc, Mutex};
use style::arc_ptr_eq;
use style::context::{LocalStyleContextCreationInfo, ReflowGoal, SharedStyleContext};
@ -355,47 +357,62 @@ pub extern "C" fn Servo_DropStyleSet(data: *mut RawServoStyleSet) -> () {
pub struct GeckoDeclarationBlock {
pub declarations: Option<PropertyDeclarationBlock>,
pub cache: *mut nsHTMLCSSStyleSheet,
pub immutable: bool,
// XXX The following two fields are made atomic to work around the
// 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]
pub extern "C" fn Servo_ParseStyleAttribute(bytes: *const u8, length: u32,
cache: *mut nsHTMLCSSStyleSheet)
-> *mut ServoDeclarationBlock {
-> ServoDeclarationBlockStrong {
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),
cache: cache,
immutable: false,
});
Box::into_raw(declarations) as *mut ServoDeclarationBlock
cache: AtomicPtr::new(cache),
immutable: AtomicBool::new(false),
}))
}
#[no_mangle]
pub extern "C" fn Servo_DropDeclarationBlock(declarations: *mut ServoDeclarationBlock) {
unsafe {
let _ = Box::<GeckoDeclarationBlock>::from_raw(declarations as *mut GeckoDeclarationBlock);
}
pub extern "C" fn Servo_DeclarationBlock_AddRef(declarations: ServoDeclarationBlockBorrowed) {
unsafe { GeckoDeclarationBlock::addref(declarations) };
}
#[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 {
let declarations = unsafe { (declarations as *const GeckoDeclarationBlock).as_ref().unwrap() };
declarations.cache
GeckoDeclarationBlock::with(declarations, |declarations| {
declarations.cache.load(Ordering::Relaxed)
})
}
#[no_mangle]
pub extern "C" fn Servo_SetDeclarationBlockImmutable(declarations: *mut ServoDeclarationBlock) {
let declarations = unsafe { (declarations as *mut GeckoDeclarationBlock).as_mut().unwrap() };
declarations.immutable = true;
pub extern "C" fn Servo_SetDeclarationBlockImmutable(declarations: ServoDeclarationBlockBorrowed) {
GeckoDeclarationBlock::with(declarations, |declarations| {
declarations.immutable.store(true, Ordering::Relaxed)
})
}
#[no_mangle]
pub extern "C" fn Servo_ClearDeclarationBlockCachePointer(declarations: *mut ServoDeclarationBlock) {
let declarations = unsafe { (declarations as *mut GeckoDeclarationBlock).as_mut().unwrap() };
declarations.cache = ptr::null_mut();
pub extern "C" fn Servo_ClearDeclarationBlockCachePointer(declarations: ServoDeclarationBlockBorrowed) {
GeckoDeclarationBlock::with(declarations, |declarations| {
declarations.cache.store(ptr::null_mut(), Ordering::Relaxed)
});
}
#[no_mangle]

View file

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