Auto merge of #12933 - upsuper:cssom-for-stylo, r=upsuper

Make GeckoDeclarationBlock refcounted

<!-- Please describe your changes on the following line: -->
This makes GeckoDeclarationBlock refcounted, so that it can share most of the logic Gecko currently uses for its existing `css::Declaration`. Although this is almost only useful for Gecko side, doing this in Servo side eliminates additional object allocation for holding it in the Gecko side.

Its Gecko side code change is in [bug 1296186](https://bugzilla.mozilla.org/show_bug.cgi?id=1296186). We may not want to land this before that part also gets reviewed.

r? @Manishearth

---
<!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: -->
- [x] `./mach build -d` does not report any errors
- [x] `./mach test-tidy` does not report any errors
- [ ] These changes fix #__ (github issue number if applicable).

<!-- Either: -->
- [ ] There are tests for these changes OR
- [x] These changes do not require tests because for Gecko binding only

<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->

<!-- Reviewable:start -->
---
This change is [<img src="https://reviewable.io/review_button.svg" height="34" align="absmiddle" alt="Reviewable"/>](https://reviewable.io/reviews/servo/servo/12933)
<!-- Reviewable:end -->
This commit is contained in:
bors-servo 2016-08-22 21:12:23 -05:00 committed by GitHub
commit 27f59cc250
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) }
})
}
}