Skip to content
Permalink
Browse files

style: Parse sheets on the thread pool.

Note that we also drop the dead optional aReusableSheets argument from
the async parsing path, since it was always null.

Bug: 1346988
Reviewed-by: bz,emilio
MozReview-Commit-ID: KddpGFdaqEe
  • Loading branch information
bholley authored and emilio committed Apr 28, 2018
1 parent c06e3dc commit dfa019c884ae2a8f1d4109adfd947690098c1d0f
@@ -312,3 +312,9 @@ impl_threadsafe_refcount!(
Gecko_AddRefSharedFontListArbitraryThread,
Gecko_ReleaseSharedFontListArbitraryThread
);

impl_threadsafe_refcount!(
::gecko_bindings::structs::SheetLoadDataHolder,
Gecko_AddRefSheetLoadDataHolderArbitraryThread,
Gecko_ReleaseSheetLoadDataHolderArbitraryThread
);
@@ -171,10 +171,9 @@ pub struct ImportRule {
/// The `<url>` this `@import` rule is loading.
pub url: CssUrl,

/// The stylesheet is always present.
///
/// It contains an empty list of rules and namespace set that is updated
/// when it loads.
/// The stylesheet is always present. However, in the case of gecko async
/// parsing, we don't actually have a Gecko sheet at first, and so the
/// ImportSheet just has stub behavior until it appears.
pub stylesheet: ImportSheet,

/// The line and column of the rule's source code.
@@ -6,6 +6,7 @@ use cssparser::{ParseErrorKind, Parser, ParserInput, SourceLocation};
use cssparser::ToCss as ParserToCss;
use env_logger::Builder;
use malloc_size_of::MallocSizeOfOps;
use nsstring::nsCString;
use selectors::{NthIndexCache, SelectorList};
use selectors::matching::{MatchingContext, MatchingMode, matches_selector};
use servo_arc::{Arc, ArcBorrow, RawOffsetArc};
@@ -92,7 +93,8 @@ use style::gecko_bindings::structs;
use style::gecko_bindings::structs::{CallerType, CSSPseudoElementType, CompositeOperation};
use style::gecko_bindings::structs::{Loader, LoaderReusableStyleSheets};
use style::gecko_bindings::structs::{RawServoStyleRule, ComputedStyleStrong, RustString};
use style::gecko_bindings::structs::{ServoStyleSheet, SheetLoadData, SheetParsingMode, nsAtom, nsCSSPropertyID};
use style::gecko_bindings::structs::{ServoStyleSheet, SheetLoadData, SheetLoadDataHolder};
use style::gecko_bindings::structs::{SheetParsingMode, nsAtom, nsCSSPropertyID};
use style::gecko_bindings::structs::{nsCSSFontDesc, nsCSSCounterDesc};
use style::gecko_bindings::structs::{nsRestyleHint, nsChangeHint, PropertyValuePair};
use style::gecko_bindings::structs::AtomArray;
@@ -145,6 +147,7 @@ use style::stylesheets::{DocumentRule, FontFaceRule, FontFeatureValuesRule, Impo
use style::stylesheets::{KeyframesRule, MediaRule, NamespaceRule, Origin, OriginSet, PageRule};
use style::stylesheets::{StyleRule, StylesheetContents, SupportsRule};
use style::stylesheets::StylesheetLoader as StyleStylesheetLoader;
use style::stylesheets::import_rule::ImportSheet;
use style::stylesheets::keyframes_rule::{Keyframe, KeyframeSelector, KeyframesStepValue};
use style::stylesheets::supports_rule::parse_condition_or_declaration;
use style::stylist::{add_size_of_ua_cache, AuthorStylesEnabled, RuleInclusion, Stylist};
@@ -163,7 +166,7 @@ use style::values::specified::gecko::{IntersectionObserverRootMargin, PixelOrPer
use style::values::specified::source_size_list::SourceSizeList;
use style_traits::{CssWriter, ParsingMode, StyleParseErrorKind, ToCss};
use super::error_reporter::ErrorReporter;
use super::stylesheet_loader::StylesheetLoader;
use super::stylesheet_loader::{AsyncStylesheetParser, StylesheetLoader};

/*
* For Gecko->Servo function calls, we need to redeclare the same signature that was declared in
@@ -1122,6 +1125,15 @@ pub extern "C" fn Servo_StyleSheet_Empty(mode: SheetParsingMode) -> RawServoStyl
).into_strong()
}

fn mode_to_origin(mode: SheetParsingMode) -> Origin {
match mode {
SheetParsingMode::eAuthorSheetFeatures => Origin::Author,
SheetParsingMode::eUserSheetFeatures => Origin::User,
SheetParsingMode::eAgentSheetFeatures => Origin::UserAgent,
SheetParsingMode::eSafeAgentSheetFeatures => Origin::UserAgent,
}
}

/// Note: The load_data corresponds to this sheet, and is passed as the parent
/// load data for child sheet loads. It may be null for certain cases where we
/// know we won't have child loads.
@@ -1140,13 +1152,6 @@ pub extern "C" fn Servo_StyleSheet_FromUTF8Bytes(
let global_style_data = &*GLOBAL_STYLE_DATA;
let input: &str = unsafe { (*bytes).as_str_unchecked() };

let origin = match mode {
SheetParsingMode::eAuthorSheetFeatures => Origin::Author,
SheetParsingMode::eUserSheetFeatures => Origin::User,
SheetParsingMode::eAgentSheetFeatures => Origin::UserAgent,
SheetParsingMode::eSafeAgentSheetFeatures => Origin::UserAgent,
};

let reporter = ErrorReporter::new(stylesheet, loader, extra_data);
let url_data = unsafe { RefPtr::from_ptr_ref(&extra_data) };
let loader = if loader.is_null() {
@@ -1163,12 +1168,44 @@ pub extern "C" fn Servo_StyleSheet_FromUTF8Bytes(


Arc::new(StylesheetContents::from_str(
input, url_data.clone(), origin,
input, url_data.clone(), mode_to_origin(mode),
&global_style_data.shared_lock, loader, &reporter,
quirks_mode.into(), line_number_offset)
).into_strong()
}

#[no_mangle]
pub extern "C" fn Servo_StyleSheet_FromUTF8BytesAsync(
load_data: *mut SheetLoadDataHolder,
extra_data: *mut URLExtraData,
bytes: *const nsACString,
mode: SheetParsingMode,
line_number_offset: u32,
quirks_mode: nsCompatibility,
) {
let (load_data, extra_data, bytes) = unsafe {
let mut b = nsCString::new();
b.assign(&*bytes);
(RefPtr::new(load_data), RefPtr::new(extra_data), b)
};
let async_parser = AsyncStylesheetParser::new(
load_data,
extra_data,
bytes,
mode_to_origin(mode),
quirks_mode.into(),
line_number_offset
);

if let Some(thread_pool) = STYLE_THREAD_POOL.style_thread_pool.as_ref() {
thread_pool.spawn(|| {
async_parser.parse();
});
} else {
async_parser.parse();
}
}

#[no_mangle]
pub extern "C" fn Servo_StyleSet_AppendStyleSheet(
raw_data: RawServoStyleSetBorrowed,
@@ -2051,6 +2088,17 @@ pub extern "C" fn Servo_ImportRule_GetSheet(
})
}

#[no_mangle]
pub extern "C" fn Servo_ImportRule_SetSheet(
rule: RawServoImportRuleBorrowed,
sheet: *mut ServoStyleSheet,
) {
write_locked_arc(rule, |rule: &mut ImportRule| {
let sheet = unsafe { GeckoStyleSheet::new(sheet) };
rule.stylesheet = ImportSheet::new(sheet);
})
}

#[no_mangle]
pub extern "C" fn Servo_Keyframe_GetKeyText(
keyframe: RawServoKeyframeBorrowed,
@@ -9,6 +9,7 @@ extern crate env_logger;
extern crate libc;
#[macro_use] extern crate log;
extern crate malloc_size_of;
extern crate nsstring;
extern crate selectors;
extern crate servo_arc;
extern crate smallvec;
@@ -3,15 +3,24 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */

use cssparser::SourceLocation;
use nsstring::nsCString;
use servo_arc::Arc;
use style::context::QuirksMode;
use style::error_reporting::NullReporter;
use style::gecko::data::GeckoStyleSheet;
use style::gecko::global_style_data::GLOBAL_STYLE_DATA;
use style::gecko_bindings::bindings;
use style::gecko_bindings::bindings::Gecko_LoadStyleSheet;
use style::gecko_bindings::structs::{Loader, ServoStyleSheet, SheetLoadData, LoaderReusableStyleSheets};
use style::gecko_bindings::structs::{Loader, LoaderReusableStyleSheets};
use style::gecko_bindings::structs::{ServoStyleSheet, SheetLoadData, SheetLoadDataHolder};
use style::gecko_bindings::structs::URLExtraData;
use style::gecko_bindings::sugar::ownership::FFIArcHelpers;
use style::gecko_bindings::sugar::refptr::RefPtr;
use style::media_queries::MediaList;
use style::parser::ParserContext;
use style::shared_lock::{Locked, SharedRwLock};
use style::stylesheets::{ImportRule, StylesheetLoader as StyleStylesheetLoader};
use style::stylesheets::{ImportRule, Origin, StylesheetLoader as StyleStylesheetLoader};
use style::stylesheets::StylesheetContents;
use style::stylesheets::import_rule::ImportSheet;
use style::values::CssUrl;

@@ -41,15 +50,11 @@ impl StyleStylesheetLoader for StylesheetLoader {
// so this raw pointer will still be valid.

let child_sheet = unsafe {
let (spec_bytes, spec_len) = url.as_slice_components();
let base_url_data = url.extra_data.get();
Gecko_LoadStyleSheet(self.0,
self.1,
self.2,
self.3,
base_url_data,
spec_bytes,
spec_len as u32,
url.for_ffi(),
media.into_strong())
};

@@ -60,3 +65,75 @@ impl StyleStylesheetLoader for StylesheetLoader {
Arc::new(lock.wrap(ImportRule { url, source_location, stylesheet }))
}
}

pub struct AsyncStylesheetParser {
load_data: RefPtr<SheetLoadDataHolder>,
extra_data: RefPtr<URLExtraData>,
bytes: nsCString,
origin: Origin,
quirks_mode: QuirksMode,
line_number_offset: u32,
}

impl AsyncStylesheetParser {
pub fn new(
load_data: RefPtr<SheetLoadDataHolder>,
extra_data: RefPtr<URLExtraData>,
bytes: nsCString,
origin: Origin,
quirks_mode: QuirksMode,
line_number_offset: u32,
) -> Self {
AsyncStylesheetParser {
load_data,
extra_data,
bytes,
origin,
quirks_mode,
line_number_offset,
}
}

pub fn parse(self) {
let global_style_data = &*GLOBAL_STYLE_DATA;
let input: &str = unsafe { (*self.bytes).as_str_unchecked() };

// Note: Parallel CSS parsing doesn't report CSS errors. When errors
// are being logged, Gecko prevents the parallel parsing path from
// running.
let sheet = Arc::new(StylesheetContents::from_str(
input, self.extra_data.clone(), self.origin,
&global_style_data.shared_lock, Some(&self), &NullReporter,
self.quirks_mode.into(), self.line_number_offset)
);

unsafe {
bindings::Gecko_StyleSheet_FinishAsyncParse(self.load_data.get(), sheet.into_strong());
}
}
}

impl StyleStylesheetLoader for AsyncStylesheetParser {
fn request_stylesheet(
&self,
url: CssUrl,
source_location: SourceLocation,
_context: &ParserContext,
lock: &SharedRwLock,
media: Arc<Locked<MediaList>>,
) -> Arc<Locked<ImportRule>> {
let stylesheet = ImportSheet::new_pending(self.origin, self.quirks_mode);
let rule = Arc::new(lock.wrap(ImportRule { url: url.clone(), source_location, stylesheet }));

unsafe {
bindings::Gecko_LoadStyleSheetAsync(
self.load_data.get(),
url.for_ffi(),
media.into_strong(),
rule.clone().into_strong()
);
}

rule
}
}

0 comments on commit dfa019c

Please sign in to comment.
You can’t perform that action at this time.