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_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;
|
2019-01-22 04:59:21 +03:00
|
|
|
|
use style::global_style_data::GLOBAL_STYLE_DATA;
|
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};
|
2021-11-19 02:03:56 +03:00
|
|
|
|
use style::stylesheets::import_rule::{ImportSheet, ImportLayer};
|
2020-11-22 03:41:29 +03:00
|
|
|
|
use style::stylesheets::AllowImportRules;
|
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>>,
|
2021-09-06 19:43:04 +03:00
|
|
|
|
layer: Option<ImportLayer>,
|
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 {
|
2020-11-22 03:41:29 +03:00
|
|
|
|
Gecko_LoadStyleSheet(self.0, self.1, self.2, self.3, &url, 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,
|
2021-09-06 19:32:53 +03:00
|
|
|
|
stylesheet,
|
2021-09-06 19:43:04 +03:00
|
|
|
|
layer,
|
|
|
|
|
source_location,
|
2018-11-20 07:37:53 +03:00
|
|
|
|
}))
|
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,
|
2020-03-12 21:11:09 +03:00
|
|
|
|
allow_import_rules: AllowImportRules,
|
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,
|
2020-03-12 21:11:09 +03:00
|
|
|
|
allow_import_rules: AllowImportRules,
|
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,
|
2020-03-12 21:11:09 +03:00
|
|
|
|
allow_import_rules,
|
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.
|
2021-05-19 12:00:38 +03:00
|
|
|
|
let sheet = 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,
|
2020-10-08 12:42:49 +03:00
|
|
|
|
use_counters.as_deref(),
|
2020-03-12 21:11:09 +03:00
|
|
|
|
self.allow_import_rules,
|
2019-12-12 16:57:54 +03:00
|
|
|
|
/* sanitized_output = */ None,
|
2021-05-19 12:00:38 +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>>,
|
2021-09-06 19:43:04 +03:00
|
|
|
|
layer: Option<ImportLayer>,
|
2018-02-15 03:39:35 +03:00
|
|
|
|
) -> Arc<Locked<ImportRule>> {
|
2021-10-20 02:31:04 +03:00
|
|
|
|
let stylesheet = ImportSheet::new_pending();
|
2018-11-20 07:37:53 +03:00
|
|
|
|
let rule = Arc::new(lock.wrap(ImportRule {
|
|
|
|
|
url: url.clone(),
|
2021-09-06 19:32:53 +03:00
|
|
|
|
stylesheet,
|
2021-09-06 19:43:04 +03:00
|
|
|
|
layer,
|
|
|
|
|
source_location,
|
2018-11-20 07:37:53 +03:00
|
|
|
|
}));
|
2018-02-15 03:39:35 +03:00
|
|
|
|
|
|
|
|
|
unsafe {
|
|
|
|
|
bindings::Gecko_LoadStyleSheetAsync(
|
|
|
|
|
self.load_data.get(),
|
Bug 1552708 - Use cbindgen for URIs. r=heycam
This doesn't clean up as much as a whole, but it's a step in the right
direction. In particular, it allows us to start using simple bindings for:
* Filters
* Shapes and images, almost. Need to:
* Get rid of the complex -moz- gradient parsing (let
layout.css.simple-moz-gradient.enabled get to release).
* Counters, almost. Need to:
* Share the Attr representation with Gecko, by not using Option<>.
* Just another variant should be enough (ContentItem::{Attr,Prefixedattr},
maybe).
Which in turn allows us to remove a whole lot of bindings in followups to this.
The setup changes a bit. This also removes the double pointer I complained about
while reviewing the shared UA sheet patches. The old setup is:
```
SpecifiedUrl
* CssUrl
* Arc<CssUrlData>
* String
* UrlExtraData
* UrlValueSource
* Arc<CssUrlData>
* load id
* resolved uri
* CORS mode.
* ...
```
The new one removes the double reference to the url data via URLValue, and looks
like:
```
SpecifiedUrl
* CssUrl
* Arc<CssUrlData>
* String
* UrlExtraData
* CorsMode
* LoadData
* load id
* resolved URI
```
The LoadData is the only mutable bit that C++ can change, and is not used from
Rust. Ideally, in the future, we could just use rust-url to resolve the URL
after parsing or something, and make it all immutable. Maybe.
I've verified that this approach still works with the UA sheet patches (via the
LoadDataSource::Lazy).
The reordering of mWillChange is to avoid nsStyleDisplay from going over the
size limit. We want to split it up anyway in bug 1552587, but mBinding gains a
tag member, which means that we were having a bit of extra padding.
One thing I want to explore is to see if we can abuse rustc's non-zero
optimizations to predict the layout from C++, but that's something to explore at
some other point in time and with a lot of care and help from Michael (who sits
next to me and works on rustc ;)).
Differential Revision: https://phabricator.services.mozilla.com/D31742
2019-05-27 14:45:12 +03:00
|
|
|
|
&url,
|
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
|
|
|
|
|
}
|
|
|
|
|
}
|