From 01fb804320b948e19424c2b2fc84c83f6099dc72 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Wed, 7 Jun 2023 00:03:23 +0200 Subject: 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 --- components/style/gecko/wrapper.rs | 31 ++++++++++++++++++++++++------- 1 file 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; @@ -265,9 +266,29 @@ impl<'ln> GeckoNode<'ln> { GeckoNode(&content._base) } + #[inline] + fn flags_atomic(&self) -> &AtomicU32 { + use std::cell::Cell; + let flags: &Cell = &(self.0)._base._base_1.mFlags; + + #[allow(dead_code)] + fn static_assert() { + let _: [u8; std::mem::size_of::>()] = [0u8; std::mem::size_of::()]; + let _: [u8; std::mem::align_of::>()] = [0u8; std::mem::align_of::()]; + } + + // 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, &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, 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. -- cgit v1.2.3