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-19 21:31:19 +00: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
|
|
|
|
|
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
|
|
|
|
|
|
|
|
|
|
//! Different objects protected by the same lock
|
|
|
|
|
|
2017-03-21 00:00:31 +00:00
|
|
|
|
#[cfg(feature = "gecko")]
|
|
|
|
|
use atomic_refcell::{AtomicRefCell, AtomicRef, AtomicRefMut};
|
|
|
|
|
#[cfg(feature = "servo")]
|
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-19 21:31:19 +00:00
|
|
|
|
use parking_lot::RwLock;
|
|
|
|
|
use std::cell::UnsafeCell;
|
|
|
|
|
use std::fmt;
|
|
|
|
|
use std::sync::Arc;
|
|
|
|
|
|
|
|
|
|
/// A shared read/write lock that can protect multiple objects.
|
2017-03-21 00:00:31 +00:00
|
|
|
|
///
|
|
|
|
|
/// In Gecko builds, we don't need the blocking behavior, just the safety. As
|
|
|
|
|
/// such we implement this with an AtomicRefCell instead in Gecko builds,
|
|
|
|
|
/// which is ~2x as fast, and panics (rather than deadlocking) when things go
|
|
|
|
|
/// wrong (which is much easier to debug on CI).
|
|
|
|
|
///
|
|
|
|
|
/// Servo needs the blocking behavior for its unsynchronized animation setup,
|
|
|
|
|
/// but that may not be web-compatible and may need to be changed (at which
|
|
|
|
|
/// point Servo could use AtomicRefCell too).
|
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-19 21:31:19 +00:00
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
#[cfg_attr(feature = "servo", derive(HeapSizeOf))]
|
|
|
|
|
pub struct SharedRwLock {
|
2017-03-21 00:00:31 +00:00
|
|
|
|
#[cfg(feature = "servo")]
|
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-19 21:31:19 +00:00
|
|
|
|
#[cfg_attr(feature = "servo", ignore_heap_size_of = "Arc")]
|
|
|
|
|
arc: Arc<RwLock<()>>,
|
2017-03-21 00:00:31 +00:00
|
|
|
|
|
|
|
|
|
#[cfg(feature = "gecko")]
|
|
|
|
|
cell: Arc<AtomicRefCell<SomethingZeroSizedButTyped>>,
|
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-19 21:31:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-03-21 00:00:31 +00:00
|
|
|
|
#[cfg(feature = "gecko")]
|
|
|
|
|
struct SomethingZeroSizedButTyped;
|
|
|
|
|
|
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-19 21:31:19 +00:00
|
|
|
|
impl fmt::Debug for SharedRwLock {
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
|
f.write_str("SharedRwLock")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl SharedRwLock {
|
2017-03-21 00:00:31 +00:00
|
|
|
|
/// Create a new shared lock (servo).
|
|
|
|
|
#[cfg(feature = "servo")]
|
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-19 21:31:19 +00:00
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
SharedRwLock {
|
|
|
|
|
arc: Arc::new(RwLock::new(()))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-21 00:00:31 +00:00
|
|
|
|
/// Create a new shared lock (gecko).
|
|
|
|
|
#[cfg(feature = "gecko")]
|
|
|
|
|
pub fn new() -> Self {
|
|
|
|
|
SharedRwLock {
|
|
|
|
|
cell: Arc::new(AtomicRefCell::new(SomethingZeroSizedButTyped))
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
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-19 21:31:19 +00:00
|
|
|
|
/// Wrap the given data to make its access protected by this lock.
|
|
|
|
|
pub fn wrap<T>(&self, data: T) -> Locked<T> {
|
|
|
|
|
Locked {
|
|
|
|
|
shared_lock: self.clone(),
|
|
|
|
|
data: UnsafeCell::new(data),
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-21 00:00:31 +00:00
|
|
|
|
/// Obtain the lock for reading (servo).
|
|
|
|
|
#[cfg(feature = "servo")]
|
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-19 21:31:19 +00:00
|
|
|
|
pub fn read(&self) -> SharedRwLockReadGuard {
|
|
|
|
|
self.arc.raw_read();
|
2017-03-21 00:00:31 +00:00
|
|
|
|
SharedRwLockReadGuard(self)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Obtain the lock for reading (gecko).
|
|
|
|
|
#[cfg(feature = "gecko")]
|
|
|
|
|
pub fn read(&self) -> SharedRwLockReadGuard {
|
|
|
|
|
SharedRwLockReadGuard(self.cell.borrow())
|
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-19 21:31:19 +00:00
|
|
|
|
}
|
|
|
|
|
|
2017-03-21 00:00:31 +00:00
|
|
|
|
/// Obtain the lock for writing (servo).
|
|
|
|
|
#[cfg(feature = "servo")]
|
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-19 21:31:19 +00:00
|
|
|
|
pub fn write(&self) -> SharedRwLockWriteGuard {
|
|
|
|
|
self.arc.raw_write();
|
2017-03-21 00:00:31 +00:00
|
|
|
|
SharedRwLockWriteGuard(self)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Obtain the lock for writing (gecko).
|
|
|
|
|
#[cfg(feature = "gecko")]
|
|
|
|
|
pub fn write(&self) -> SharedRwLockWriteGuard {
|
|
|
|
|
SharedRwLockWriteGuard(self.cell.borrow_mut())
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Proof that a shared lock was obtained for reading (servo).
|
|
|
|
|
#[cfg(feature = "servo")]
|
|
|
|
|
pub struct SharedRwLockReadGuard<'a>(&'a SharedRwLock);
|
|
|
|
|
/// Proof that a shared lock was obtained for writing (gecko).
|
|
|
|
|
#[cfg(feature = "gecko")]
|
|
|
|
|
pub struct SharedRwLockReadGuard<'a>(AtomicRef<'a, SomethingZeroSizedButTyped>);
|
|
|
|
|
#[cfg(feature = "servo")]
|
|
|
|
|
impl<'a> Drop for SharedRwLockReadGuard<'a> {
|
|
|
|
|
fn drop(&mut self) {
|
|
|
|
|
// Unsafe: self.lock is private to this module, only ever set after `raw_read()`,
|
|
|
|
|
// and never copied or cloned (see `compile_time_assert` below).
|
|
|
|
|
unsafe {
|
|
|
|
|
self.0.arc.raw_unlock_read()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Proof that a shared lock was obtained for writing (servo).
|
|
|
|
|
#[cfg(feature = "servo")]
|
|
|
|
|
pub struct SharedRwLockWriteGuard<'a>(&'a SharedRwLock);
|
|
|
|
|
/// Proof that a shared lock was obtained for writing (gecko).
|
|
|
|
|
#[cfg(feature = "gecko")]
|
|
|
|
|
pub struct SharedRwLockWriteGuard<'a>(AtomicRefMut<'a, SomethingZeroSizedButTyped>);
|
|
|
|
|
#[cfg(feature = "servo")]
|
|
|
|
|
impl<'a> Drop for SharedRwLockWriteGuard<'a> {
|
|
|
|
|
fn drop(&mut self) {
|
|
|
|
|
// Unsafe: self.lock is private to this module, only ever set after `raw_write()`,
|
|
|
|
|
// and never copied or cloned (see `compile_time_assert` below).
|
|
|
|
|
unsafe {
|
|
|
|
|
self.0.arc.raw_unlock_write()
|
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-19 21:31:19 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Data protect by a shared lock.
|
|
|
|
|
pub struct Locked<T> {
|
|
|
|
|
shared_lock: SharedRwLock,
|
|
|
|
|
data: UnsafeCell<T>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Unsafe: the data inside `UnsafeCell` is only accessed in `read_with` and `write_with`,
|
|
|
|
|
// where guards ensure synchronization.
|
|
|
|
|
unsafe impl<T: Send> Send for Locked<T> {}
|
|
|
|
|
unsafe impl<T: Send + Sync> Sync for Locked<T> {}
|
|
|
|
|
|
|
|
|
|
impl<T: fmt::Debug> fmt::Debug for Locked<T> {
|
|
|
|
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
|
|
|
|
let guard = self.shared_lock.read();
|
|
|
|
|
self.read_with(&guard).fmt(f)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<T> Locked<T> {
|
2017-03-21 00:00:31 +00:00
|
|
|
|
#[cfg(feature = "servo")]
|
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-19 21:31:19 +00:00
|
|
|
|
fn same_lock_as(&self, lock: &SharedRwLock) -> bool {
|
|
|
|
|
::arc_ptr_eq(&self.shared_lock.arc, &lock.arc)
|
|
|
|
|
}
|
|
|
|
|
|
2017-03-21 00:00:31 +00:00
|
|
|
|
#[cfg(feature = "gecko")]
|
|
|
|
|
fn same_lock_as(&self, derefed_guard: &SomethingZeroSizedButTyped) -> bool {
|
|
|
|
|
::ptr_eq(self.shared_lock.cell.as_ptr(), derefed_guard)
|
|
|
|
|
}
|
|
|
|
|
|
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-19 21:31:19 +00:00
|
|
|
|
/// Access the data for reading.
|
|
|
|
|
pub fn read_with<'a>(&'a self, guard: &'a SharedRwLockReadGuard) -> &'a T {
|
2017-03-21 00:00:31 +00:00
|
|
|
|
assert!(self.same_lock_as(&guard.0),
|
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-19 21:31:19 +00:00
|
|
|
|
"Locked::read_with called with a guard from an unrelated SharedRwLock");
|
|
|
|
|
let ptr = self.data.get();
|
|
|
|
|
|
|
|
|
|
// Unsafe:
|
|
|
|
|
//
|
|
|
|
|
// * The guard guarantees that the lock is taken for reading,
|
|
|
|
|
// and we’ve checked that it’s the correct lock.
|
|
|
|
|
// * The returned reference borrows *both* the data and the guard,
|
|
|
|
|
// so that it can outlive neither.
|
|
|
|
|
unsafe {
|
|
|
|
|
&*ptr
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Access the data for writing.
|
|
|
|
|
pub fn write_with<'a>(&'a self, guard: &'a mut SharedRwLockWriteGuard) -> &'a mut T {
|
2017-03-21 00:00:31 +00:00
|
|
|
|
assert!(self.same_lock_as(&guard.0),
|
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-19 21:31:19 +00:00
|
|
|
|
"Locked::write_with called with a guard from an unrelated SharedRwLock");
|
|
|
|
|
let ptr = self.data.get();
|
|
|
|
|
|
|
|
|
|
// Unsafe:
|
|
|
|
|
//
|
|
|
|
|
// * The guard guarantees that the lock is taken for writing,
|
|
|
|
|
// and we’ve checked that it’s the correct lock.
|
|
|
|
|
// * The returned reference borrows *both* the data and the guard,
|
|
|
|
|
// so that it can outlive neither.
|
|
|
|
|
// * We require a mutable borrow of the guard,
|
|
|
|
|
// so that one write guard can only be used once at a time.
|
|
|
|
|
unsafe {
|
|
|
|
|
&mut *ptr
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[allow(dead_code)]
|
|
|
|
|
mod compile_time_assert {
|
|
|
|
|
use super::{SharedRwLockReadGuard, SharedRwLockWriteGuard};
|
|
|
|
|
|
|
|
|
|
trait Marker1 {}
|
|
|
|
|
impl<T: Clone> Marker1 for T {}
|
|
|
|
|
impl<'a> Marker1 for SharedRwLockReadGuard<'a> {} // Assert SharedRwLockReadGuard: !Clone
|
|
|
|
|
impl<'a> Marker1 for SharedRwLockWriteGuard<'a> {} // Assert SharedRwLockWriteGuard: !Clone
|
|
|
|
|
|
|
|
|
|
trait Marker2 {}
|
|
|
|
|
impl<T: Copy> Marker2 for T {}
|
|
|
|
|
impl<'a> Marker2 for SharedRwLockReadGuard<'a> {} // Assert SharedRwLockReadGuard: !Copy
|
|
|
|
|
impl<'a> Marker2 for SharedRwLockWriteGuard<'a> {} // Assert SharedRwLockWriteGuard: !Copy
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Like ToCss, but with a lock guard given by the caller.
|
|
|
|
|
pub trait ToCssWithGuard {
|
|
|
|
|
/// Serialize `self` in CSS syntax, writing to `dest`, using the given lock guard.
|
|
|
|
|
fn to_css<W>(&self, guard: &SharedRwLockReadGuard, dest: &mut W) -> fmt::Result
|
|
|
|
|
where W: fmt::Write;
|
|
|
|
|
|
|
|
|
|
/// Serialize `self` in CSS syntax using the given lock guard and return a string.
|
|
|
|
|
///
|
|
|
|
|
/// (This is a convenience wrapper for `to_css` and probably should not be overridden.)
|
|
|
|
|
#[inline]
|
|
|
|
|
fn to_css_string(&self, guard: &SharedRwLockReadGuard) -> String {
|
|
|
|
|
let mut s = String::new();
|
|
|
|
|
self.to_css(guard, &mut s).unwrap();
|
|
|
|
|
s
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/// Guards for a document
|
|
|
|
|
#[derive(Clone)]
|
|
|
|
|
pub struct StylesheetGuards<'a> {
|
|
|
|
|
/// For author-origin stylesheets
|
|
|
|
|
pub author: &'a SharedRwLockReadGuard<'a>,
|
|
|
|
|
|
|
|
|
|
/// For user-agent-origin and user-origin stylesheets
|
|
|
|
|
pub ua_or_user: &'a SharedRwLockReadGuard<'a>,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl<'a> StylesheetGuards<'a> {
|
|
|
|
|
/// Same guard for all origins
|
|
|
|
|
pub fn same(guard: &'a SharedRwLockReadGuard<'a>) -> Self {
|
|
|
|
|
StylesheetGuards {
|
|
|
|
|
author: guard,
|
|
|
|
|
ua_or_user: guard,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|