2016-12-16 20:43:19 +03:00
|
|
|
|
/* This Source Code Form is subject to the terms of the Mozilla Public
|
|
|
|
|
* License, v. 2.0. If a copy of the MPL was not distributed with this
|
2018-12-02 21:46:06 +03:00
|
|
|
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/. */
|
2016-12-16 20:43:19 +03:00
|
|
|
|
|
2017-07-02 17:00:39 +03:00
|
|
|
|
use cssparser::SourceLocation;
|
2018-02-15 03:39:35 +03:00
|
|
|
|
use nsstring::nsCString;
|
2017-07-19 16:03:17 +03:00
|
|
|
|
use servo_arc::Arc;
|
2018-02-15 03:39:35 +03:00
|
|
|
|
use style::context::QuirksMode;
|
2017-07-02 17:00:39 +03:00
|
|
|
|
use style::gecko::data::GeckoStyleSheet;
|
2018-02-15 03:39:35 +03:00
|
|
|
|
use style::gecko::global_style_data::GLOBAL_STYLE_DATA;
|
|
|
|
|
use style::gecko_bindings::bindings;
|
2016-12-31 06:12:55 +03:00
|
|
|
|
use style::gecko_bindings::bindings::Gecko_LoadStyleSheet;
|
2018-02-15 03:39:35 +03:00
|
|
|
|
use style::gecko_bindings::structs::{Loader, LoaderReusableStyleSheets};
|
2018-11-20 07:37:53 +03:00
|
|
|
|
use style::gecko_bindings::structs::{
|
|
|
|
|
SheetLoadData, SheetLoadDataHolder, StyleSheet as DomStyleSheet,
|
|
|
|
|
};
|
2018-08-21 13:31:11 +03:00
|
|
|
|
use style::gecko_bindings::sugar::ownership::{FFIArcHelpers, HasBoxFFI, OwnedOrNull};
|
2018-02-15 03:39:35 +03:00
|
|
|
|
use style::gecko_bindings::sugar::refptr::RefPtr;
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
|
use style::media_queries::MediaList;
|
2017-07-02 17:00:39 +03:00
|
|
|
|
use style::parser::ParserContext;
|
|
|
|
|
use style::shared_lock::{Locked, SharedRwLock};
|
2018-11-20 07:37:53 +03:00
|
|
|
|
use style::stylesheets::import_rule::ImportSheet;
|
2018-02-15 03:39:35 +03:00
|
|
|
|
use style::stylesheets::{ImportRule, Origin, StylesheetLoader as StyleStylesheetLoader};
|
2018-06-21 14:09:35 +03:00
|
|
|
|
use style::stylesheets::{StylesheetContents, UrlExtraData};
|
2018-08-20 20:03:11 +03:00
|
|
|
|
use style::use_counters::UseCounters;
|
2018-03-08 16:06:35 +03:00
|
|
|
|
use style::values::CssUrl;
|
2016-12-16 20:43:19 +03:00
|
|
|
|
|
2018-11-20 07:37:53 +03:00
|
|
|
|
pub struct StylesheetLoader(
|
|
|
|
|
*mut Loader,
|
|
|
|
|
*mut DomStyleSheet,
|
|
|
|
|
*mut SheetLoadData,
|
|
|
|
|
*mut LoaderReusableStyleSheets,
|
|
|
|
|
);
|
2016-12-16 20:43:19 +03:00
|
|
|
|
|
|
|
|
|
impl StylesheetLoader {
|
2018-04-30 20:23:14 +03:00
|
|
|
|
pub fn new(
|
|
|
|
|
loader: *mut Loader,
|
|
|
|
|
parent: *mut DomStyleSheet,
|
|
|
|
|
parent_load_data: *mut SheetLoadData,
|
|
|
|
|
reusable_sheets: *mut LoaderReusableStyleSheets,
|
|
|
|
|
) -> Self {
|
2018-02-28 19:32:00 +03:00
|
|
|
|
StylesheetLoader(loader, parent, parent_load_data, reusable_sheets)
|
2016-12-16 20:43:19 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl StyleStylesheetLoader for StylesheetLoader {
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
|
fn request_stylesheet(
|
|
|
|
|
&self,
|
2018-03-08 16:06:35 +03:00
|
|
|
|
url: CssUrl,
|
2017-07-02 17:00:39 +03:00
|
|
|
|
source_location: SourceLocation,
|
|
|
|
|
_context: &ParserContext,
|
|
|
|
|
lock: &SharedRwLock,
|
2017-04-12 18:00:26 +03:00
|
|
|
|
media: Arc<Locked<MediaList>>,
|
servo: Merge #16014 - Per-process lock for CSSOM objects (from servo:style-ref); r=emilio
<!-- Please describe your changes on the following line: -->
Before this PR, every object reflected in CSSOM is in `Arc<RwLock<_>>` to enable safe (synchronized) mutable aliasing. Acquiring all these locks has significant cost during selector matching:
* https://bugzilla.mozilla.org/show_bug.cgi?id=1311469
* https://bugzilla.mozilla.org/show_bug.cgi?id=1335941
* https://bugzilla.mozilla.org/show_bug.cgi?id=1339703
This PR introduce a mechanism to protect many objects with the same `RwLock` that only needs to be acquired once.
In Stylo, there is one such lock per process (in a `lazy_static`), used for everything.
I non-Stylo Servo, I originally intended to have one such lock per document (for author-origin stylesheets, and one per process for user-agent and user sytlesheets since they’re shared across documents, and never mutated anyway). However I failed to have the same document-specific (or pipeline-specific) `Arc` reachable from both `Document` nodes and `LayoutThread`. Recursively following callers lead me to include this `Arc` in `UnprivilegedPipelineContent`, but that needs to be serializable. So there is a second process-wide lock.
This was previously #15998, closed accidentally.
---
<!-- 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
- [ ] These changes do not require tests because _____
<!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. -->
Source-Repo: https://github.com/servo/servo
Source-Revision: bb54f0a429de0e8b8861f8071b6cf82f73622664
--HG--
extra : subtree_source : https%3A//hg.mozilla.org/projects/converted-servo-linear
extra : subtree_revision : 851230e57ac8775707df5f0f103be5feac81fc41
2017-03-20 00:31:19 +03:00
|
|
|
|
) -> Arc<Locked<ImportRule>> {
|
|
|
|
|
// After we get this raw pointer ImportRule will be moved into a lock and Arc
|
|
|
|
|
// and so the Arc<Url> pointer inside will also move,
|
|
|
|
|
// but the Url it points to or the allocating backing the String inside that Url won’t,
|
|
|
|
|
// so this raw pointer will still be valid.
|
2016-12-31 06:12:55 +03:00
|
|
|
|
|
2017-07-02 17:00:39 +03:00
|
|
|
|
let child_sheet = unsafe {
|
2018-11-20 07:37:53 +03:00
|
|
|
|
Gecko_LoadStyleSheet(
|
|
|
|
|
self.0,
|
|
|
|
|
self.1,
|
|
|
|
|
self.2,
|
|
|
|
|
self.3,
|
|
|
|
|
url.0.clone().into_strong(),
|
|
|
|
|
media.into_strong(),
|
|
|
|
|
)
|
2017-07-02 17:00:39 +03:00
|
|
|
|
};
|
|
|
|
|
|
2018-11-20 07:37:53 +03:00
|
|
|
|
debug_assert!(
|
|
|
|
|
!child_sheet.is_null(),
|
|
|
|
|
"Import rules should always have a strong sheet"
|
|
|
|
|
);
|
2018-02-21 02:52:13 +03:00
|
|
|
|
let sheet = unsafe { GeckoStyleSheet::from_addrefed(child_sheet) };
|
|
|
|
|
let stylesheet = ImportSheet::new(sheet);
|
2018-11-20 07:37:53 +03:00
|
|
|
|
Arc::new(lock.wrap(ImportRule {
|
|
|
|
|
url,
|
|
|
|
|
source_location,
|
|
|
|
|
stylesheet,
|
|
|
|
|
}))
|
2016-12-16 20:43:19 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
2018-02-15 03:39:35 +03:00
|
|
|
|
|
|
|
|
|
pub struct AsyncStylesheetParser {
|
|
|
|
|
load_data: RefPtr<SheetLoadDataHolder>,
|
2018-06-21 14:09:35 +03:00
|
|
|
|
extra_data: UrlExtraData,
|
2018-02-15 03:39:35 +03:00
|
|
|
|
bytes: nsCString,
|
|
|
|
|
origin: Origin,
|
|
|
|
|
quirks_mode: QuirksMode,
|
|
|
|
|
line_number_offset: u32,
|
2018-08-21 13:31:11 +03:00
|
|
|
|
should_record_use_counters: bool,
|
2018-02-15 03:39:35 +03:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl AsyncStylesheetParser {
|
|
|
|
|
pub fn new(
|
|
|
|
|
load_data: RefPtr<SheetLoadDataHolder>,
|
2018-06-21 14:09:35 +03:00
|
|
|
|
extra_data: UrlExtraData,
|
2018-02-15 03:39:35 +03:00
|
|
|
|
bytes: nsCString,
|
|
|
|
|
origin: Origin,
|
|
|
|
|
quirks_mode: QuirksMode,
|
|
|
|
|
line_number_offset: u32,
|
2018-08-21 13:31:11 +03:00
|
|
|
|
should_record_use_counters: bool,
|
2018-02-15 03:39:35 +03:00
|
|
|
|
) -> Self {
|
|
|
|
|
AsyncStylesheetParser {
|
|
|
|
|
load_data,
|
|
|
|
|
extra_data,
|
|
|
|
|
bytes,
|
|
|
|
|
origin,
|
|
|
|
|
quirks_mode,
|
|
|
|
|
line_number_offset,
|
2018-08-21 13:31:11 +03:00
|
|
|
|
should_record_use_counters,
|
2018-02-15 03:39:35 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pub fn parse(self) {
|
|
|
|
|
let global_style_data = &*GLOBAL_STYLE_DATA;
|
|
|
|
|
let input: &str = unsafe { (*self.bytes).as_str_unchecked() };
|
|
|
|
|
|
2018-08-21 13:31:11 +03:00
|
|
|
|
let use_counters = if self.should_record_use_counters {
|
|
|
|
|
Some(Box::new(UseCounters::default()))
|
2018-11-20 07:37:53 +03:00
|
|
|
|
} else {
|
|
|
|
|
None
|
|
|
|
|
};
|
2018-08-21 13:31:11 +03:00
|
|
|
|
|
2018-08-20 20:03:11 +03:00
|
|
|
|
// Note: Parallel CSS parsing doesn't report CSS errors. When errors are
|
|
|
|
|
// being logged, Gecko prevents the parallel parsing path from running.
|
2018-02-15 03:39:35 +03:00
|
|
|
|
let sheet = Arc::new(StylesheetContents::from_str(
|
2018-06-20 22:07:45 +03:00
|
|
|
|
input,
|
|
|
|
|
self.extra_data.clone(),
|
|
|
|
|
self.origin,
|
|
|
|
|
&global_style_data.shared_lock,
|
|
|
|
|
Some(&self),
|
|
|
|
|
None,
|
|
|
|
|
self.quirks_mode.into(),
|
|
|
|
|
self.line_number_offset,
|
2018-08-21 13:31:11 +03:00
|
|
|
|
use_counters.as_ref().map(|c| &**c),
|
2018-06-20 22:07:45 +03:00
|
|
|
|
));
|
2018-02-15 03:39:35 +03:00
|
|
|
|
|
2018-08-21 13:31:11 +03:00
|
|
|
|
let use_counters = match use_counters {
|
|
|
|
|
Some(c) => c.into_ffi().maybe(),
|
|
|
|
|
None => OwnedOrNull::null(),
|
|
|
|
|
};
|
|
|
|
|
|
2018-02-15 03:39:35 +03:00
|
|
|
|
unsafe {
|
2018-08-21 13:31:11 +03:00
|
|
|
|
bindings::Gecko_StyleSheet_FinishAsyncParse(
|
|
|
|
|
self.load_data.get(),
|
|
|
|
|
sheet.into_strong(),
|
|
|
|
|
use_counters,
|
|
|
|
|
);
|
2018-02-15 03:39:35 +03:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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);
|
2018-11-20 07:37:53 +03:00
|
|
|
|
let rule = Arc::new(lock.wrap(ImportRule {
|
|
|
|
|
url: url.clone(),
|
|
|
|
|
source_location,
|
|
|
|
|
stylesheet,
|
|
|
|
|
}));
|
2018-02-15 03:39:35 +03:00
|
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
|
bindings::Gecko_LoadStyleSheetAsync(
|
|
|
|
|
self.load_data.get(),
|
2018-10-17 15:36:49 +03:00
|
|
|
|
url.0.into_strong(),
|
2018-02-15 03:39:35 +03:00
|
|
|
|
media.into_strong(),
|
2018-11-20 07:37:53 +03:00
|
|
|
|
rule.clone().into_strong(),
|
2018-02-15 03:39:35 +03:00
|
|
|
|
);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
rule
|
|
|
|
|
}
|
|
|
|
|
}
|