aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEmilio Cobos Álvarez <emilio@crisal.io>2023-06-07 00:03:23 +0200
committerOriol Brufau <obrufau@igalia.com>2023-06-09 11:18:08 +0200
commit01fb804320b948e19424c2b2fc84c83f6099dc72 (patch)
tree957e494447c240956cc9051ac42dde1d8b90d29f
parentece2a747090694166625db2428a1e0a82db9b2d5 (diff)
downloadservo-01fb804320b948e19424c2b2fc84c83f6099dc72.tar.gz
servo-01fb804320b948e19424c2b2fc84c83f6099dc72.zip
style: Use atomic ops to read / write node flags from stylo
The flags stylo cares about reading and writing potentially at the same time are disjoint, so there's no need for any strong memory ordering. Differential Revision: https://phabricator.services.mozilla.com/D141829
-rw-r--r--components/style/gecko/wrapper.rs31
1 files changed, 24 insertions, 7 deletions
diff --git a/components/style/gecko/wrapper.rs b/components/style/gecko/wrapper.rs
index d89cac962ee..875700fdf42 100644
--- a/components/style/gecko/wrapper.rs
+++ b/components/style/gecko/wrapper.rs
@@ -76,6 +76,7 @@ use selectors::matching::{ElementSelectorFlags, MatchingContext};
use selectors::sink::Push;
use selectors::{Element, OpaqueElement};
use servo_arc::{Arc, ArcBorrow, RawOffsetArc};
+use std::sync::atomic::{AtomicU32, Ordering};
use std::fmt;
use std::hash::{Hash, Hasher};
use std::mem;
@@ -266,8 +267,28 @@ impl<'ln> GeckoNode<'ln> {
}
#[inline]
+ fn flags_atomic(&self) -> &AtomicU32 {
+ use std::cell::Cell;
+ let flags: &Cell<u32> = &(self.0)._base._base_1.mFlags;
+
+ #[allow(dead_code)]
+ fn static_assert() {
+ let _: [u8; std::mem::size_of::<Cell<u32>>()] = [0u8; std::mem::size_of::<AtomicU32>()];
+ let _: [u8; std::mem::align_of::<Cell<u32>>()] = [0u8; std::mem::align_of::<AtomicU32>()];
+ }
+
+ // Rust doesn't provide standalone atomic functions like GCC/clang do
+ // (via the atomic intrinsics) or via std::atomic_ref, but it guarantees
+ // that the memory representation of u32 and AtomicU32 matches:
+ // https://doc.rust-lang.org/std/sync/atomic/struct.AtomicU32.html
+ unsafe {
+ std::mem::transmute::<&Cell<u32>, &AtomicU32>(flags)
+ }
+ }
+
+ #[inline]
fn flags(&self) -> u32 {
- (self.0)._base._base_1.mFlags
+ self.flags_atomic().load(Ordering::Relaxed)
}
#[inline]
@@ -648,18 +669,14 @@ impl<'le> GeckoElement<'le> {
self.as_node().flags()
}
- // FIXME: We can implement this without OOL calls, but we can't easily given
- // GeckoNode is a raw reference.
- //
- // We can use a Cell<T>, but that's a bit of a pain.
#[inline]
fn set_flags(&self, flags: u32) {
- unsafe { Gecko_SetNodeFlags(self.as_node().0, flags) }
+ self.as_node().flags_atomic().fetch_or(flags, Ordering::Relaxed);
}
#[inline]
unsafe fn unset_flags(&self, flags: u32) {
- Gecko_UnsetNodeFlags(self.as_node().0, flags)
+ self.as_node().flags_atomic().fetch_and(!flags, Ordering::Relaxed);
}
/// Returns true if this element has descendants for lazy frame construction.