Make OpaqueLayoutAndStyleData just a bit less opaque

It now stores a NonNull<dyn Any>.
This commit is contained in:
Anthony Ramine 2020-04-02 13:17:44 +02:00
parent e47e884cc7
commit 4c61baee30
11 changed files with 83 additions and 65 deletions

View file

@ -8,8 +8,7 @@ use script_layout_interface::StyleData;
#[repr(C)]
pub struct StyleAndLayoutData {
/// Data accessed by script_layout_interface. This must be first to allow
/// casting between StyleAndLayoutData and StyleData.
/// The style data associated with a node.
pub style_data: StyleData,
/// The layout data associated with a node.
pub layout_data: AtomicRefCell<LayoutData>,

View file

@ -6,6 +6,7 @@
use crate::construct::ConstructionResult;
use crate::context::LayoutContext;
use crate::data::StyleAndLayoutData;
use crate::display_list::items::{DisplayList, OpaqueNode, ScrollOffsetMap};
use crate::display_list::IndexableText;
use crate::flow::{Flow, GetBaseFlow};
@ -26,7 +27,6 @@ use script_layout_interface::rpc::{OffsetParentResponse, ResolvedStyleResponse,
use script_layout_interface::wrapper_traits::{
LayoutNode, ThreadSafeLayoutElement, ThreadSafeLayoutNode,
};
use script_layout_interface::StyleData;
use script_layout_interface::{LayoutElementType, LayoutNodeType};
use script_traits::LayoutMsg as ConstellationMsg;
use script_traits::UntrustedNodeAddress;
@ -1037,8 +1037,13 @@ fn inner_text_collection_steps<'dom>(
};
let element_data = unsafe {
node.get_style_and_layout_data()
.map(|d| &(*(d.ptr.as_ptr() as *mut StyleData)).element_data)
&node.get_style_and_layout_data().as_ref().map(|opaque| {
&opaque
.downcast_ref::<StyleAndLayoutData>()
.unwrap()
.style_data
.element_data
})
};
if element_data.is_none() {

View file

@ -73,7 +73,7 @@ where
// flow construction:
// (1) They child doesn't yet have layout data (preorder traversal initializes it).
// (2) The parent element has restyle damage (so the text flow also needs fixup).
node.get_raw_data().is_none() || !parent_data.damage.is_empty()
(unsafe { node.get_raw_data().is_none() }) || !parent_data.damage.is_empty()
}
fn shared_context(&self) -> &SharedStyleContext {

View file

@ -52,11 +52,11 @@ where
T: GetLayoutData<'dom>,
{
fn borrow_layout_data(&self) -> Option<AtomicRef<LayoutData>> {
self.get_raw_data().map(|d| d.layout_data.borrow())
unsafe { self.get_raw_data().map(|d| d.layout_data.borrow()) }
}
fn mutate_layout_data(&self) -> Option<AtomicRefMut<LayoutData>> {
self.get_raw_data().map(|d| d.layout_data.borrow_mut())
unsafe { self.get_raw_data().map(|d| d.layout_data.borrow_mut()) }
}
fn flow_debug_id(self) -> usize {
@ -66,18 +66,16 @@ where
}
pub trait GetRawData {
fn get_raw_data(&self) -> Option<&StyleAndLayoutData>;
unsafe fn get_raw_data(&self) -> Option<&StyleAndLayoutData>;
}
impl<'dom, T> GetRawData for T
where
T: GetLayoutData<'dom>,
{
fn get_raw_data(&self) -> Option<&StyleAndLayoutData> {
self.get_style_and_layout_data().map(|opaque| {
let container = opaque.ptr.as_ptr() as *mut StyleAndLayoutData;
unsafe { &*container }
})
unsafe fn get_raw_data(&self) -> Option<&StyleAndLayoutData> {
self.get_style_and_layout_data()
.map(|opaque| opaque.downcast_ref().unwrap())
}
}
@ -146,7 +144,7 @@ where
debug_assert!(node.is_element());
}
let damage = {
let damage = unsafe {
let data = node.get_raw_data().unwrap();
if !data

View file

@ -446,10 +446,13 @@ where
self.opaque()
}
#[allow(unsafe_code)]
fn layout_data_mut(&self) -> AtomicRefMut<LayoutDataForElement> {
self.get_raw_data()
.map(|d| d.layout_data.borrow_mut())
.unwrap()
unsafe {
self.get_raw_data()
.map(|d| d.layout_data.borrow_mut())
.unwrap()
}
}
fn element_box_slot(&self) -> BoxSlot<'dom> {

View file

@ -63,7 +63,7 @@ where
}
fn text_node_needs_traversal(node: E::ConcreteNode, parent_data: &ElementData) -> bool {
node.get_raw_data().is_none() || !parent_data.damage.is_empty()
(unsafe { node.get_raw_data().is_none() }) || !parent_data.damage.is_empty()
}
fn shared_context(&self) -> &SharedStyleContext {

View file

@ -8,17 +8,15 @@ use crate::data::StyleAndLayoutData;
use script_layout_interface::wrapper_traits::GetLayoutData;
pub trait GetRawData {
fn get_raw_data(&self) -> Option<&StyleAndLayoutData>;
unsafe fn get_raw_data(&self) -> Option<&StyleAndLayoutData>;
}
impl<'dom, T> GetRawData for T
where
T: GetLayoutData<'dom>,
{
fn get_raw_data(&self) -> Option<&StyleAndLayoutData> {
self.get_style_and_layout_data().map(|opaque| {
let container = opaque.ptr.as_ptr() as *mut StyleAndLayoutData;
unsafe { &*container }
})
unsafe fn get_raw_data(&self) -> Option<&StyleAndLayoutData> {
self.get_style_and_layout_data()
.map(|opaque| opaque.downcast_ref().unwrap())
}
}

View file

@ -70,7 +70,6 @@ use std::borrow::Cow;
use std::fmt;
use std::fmt::Debug;
use std::hash::{Hash, Hasher};
use std::ptr::NonNull;
use std::sync::atomic::Ordering;
use std::sync::Arc as StdArc;
use style::applicable_declarations::ApplicableDeclarationBlock;
@ -93,9 +92,7 @@ use style::stylist::CascadeData;
use style::CaseSensitivityExt;
pub unsafe fn drop_style_and_layout_data(data: OpaqueStyleAndLayoutData) {
let ptr = data.ptr.as_ptr() as *mut StyleData;
let non_opaque: *mut StyleAndLayoutData = ptr as *mut _;
let _ = Box::from_raw(non_opaque);
drop(Box::from_raw(data.as_ptr()));
}
#[derive(Clone, Copy)]
@ -276,10 +273,7 @@ impl<'ln> LayoutNode<'ln> for ServoLayoutNode<'ln> {
unsafe fn initialize_data(&self) {
if self.get_raw_data().is_none() {
let ptr: *mut StyleAndLayoutData = Box::into_raw(Box::new(StyleAndLayoutData::new()));
let opaque = OpaqueStyleAndLayoutData {
ptr: NonNull::new_unchecked(ptr as *mut StyleData),
};
let opaque = OpaqueStyleAndLayoutData::new(StyleAndLayoutData::new());
self.init_style_and_layout_data(opaque);
};
}
@ -558,10 +552,7 @@ impl<'le> TElement for ServoLayoutElement<'le> {
}
fn get_data(&self) -> Option<&AtomicRefCell<ElementData>> {
unsafe {
self.get_style_and_layout_data()
.map(|d| &(*(d.ptr.as_ptr() as *mut StyleData)).element_data)
}
self.get_style_data().map(|data| &data.element_data)
}
fn skip_item_display_fixup(&self) -> bool {
@ -697,10 +688,12 @@ impl<'le> ServoLayoutElement<'le> {
}
fn get_style_data(&self) -> Option<&StyleData> {
unsafe {
self.get_style_and_layout_data()
.map(|d| &*(d.ptr.as_ptr() as *mut StyleData))
}
self.get_style_and_layout_data().map(|opaque| {
&opaque
.downcast_ref::<StyleAndLayoutData>()
.unwrap()
.style_data
})
}
pub unsafe fn unset_snapshot_flags(&self) {

View file

@ -70,7 +70,6 @@ use std::borrow::Cow;
use std::fmt;
use std::fmt::Debug;
use std::hash::{Hash, Hasher};
use std::ptr::NonNull;
use std::sync::atomic::Ordering;
use std::sync::Arc as StdArc;
use style::applicable_declarations::ApplicableDeclarationBlock;
@ -93,9 +92,7 @@ use style::stylist::CascadeData;
use style::CaseSensitivityExt;
pub unsafe fn drop_style_and_layout_data(data: OpaqueStyleAndLayoutData) {
let ptr = data.ptr.as_ptr() as *mut StyleData;
let non_opaque: *mut StyleAndLayoutData = ptr as *mut _;
let _ = Box::from_raw(non_opaque);
drop(Box::from_raw(data.as_ptr()));
}
#[derive(Clone, Copy)]
@ -283,10 +280,7 @@ impl<'ln> LayoutNode<'ln> for ServoLayoutNode<'ln> {
unsafe fn initialize_data(&self) {
if self.get_raw_data().is_none() {
let ptr: *mut StyleAndLayoutData = Box::into_raw(Box::new(StyleAndLayoutData::new()));
let opaque = OpaqueStyleAndLayoutData {
ptr: NonNull::new_unchecked(ptr as *mut StyleData),
};
let opaque = OpaqueStyleAndLayoutData::new(StyleAndLayoutData::new());
self.init_style_and_layout_data(opaque);
};
}
@ -565,10 +559,7 @@ impl<'le> TElement for ServoLayoutElement<'le> {
}
fn get_data(&self) -> Option<&AtomicRefCell<ElementData>> {
unsafe {
self.get_style_and_layout_data()
.map(|d| &(*(d.ptr.as_ptr() as *mut StyleData)).element_data)
}
self.get_style_data().map(|data| &data.element_data)
}
fn skip_item_display_fixup(&self) -> bool {
@ -704,10 +695,12 @@ impl<'le> ServoLayoutElement<'le> {
}
fn get_style_data(&self) -> Option<&StyleData> {
unsafe {
self.get_style_and_layout_data()
.map(|d| &*(d.ptr.as_ptr() as *mut StyleData))
}
self.get_style_and_layout_data().map(|opaque| {
&opaque
.downcast_ref::<StyleAndLayoutData>()
.unwrap()
.style_data
})
}
pub unsafe fn unset_snapshot_flags(&self) {

View file

@ -7,6 +7,7 @@
//! to depend on script.
#![deny(unsafe_code)]
#![feature(box_into_raw_non_null)]
#[macro_use]
extern crate html5ever;
@ -24,6 +25,7 @@ use libc::c_void;
use net_traits::image_cache::PendingImageId;
use script_traits::UntrustedNodeAddress;
use servo_url::{ImmutableOrigin, ServoUrl};
use std::any::Any;
use std::ptr::NonNull;
use std::sync::atomic::AtomicIsize;
use style::data::ElementData;
@ -54,7 +56,34 @@ pub struct OpaqueStyleAndLayoutData {
// NB: We really store a `StyleAndLayoutData` here, so be careful!
#[ignore_malloc_size_of = "TODO(#6910) Box value that should be counted but \
the type lives in layout"]
pub ptr: NonNull<StyleData>,
ptr: NonNull<dyn Any + Send + Sync>,
}
impl OpaqueStyleAndLayoutData {
#[inline]
pub fn new<T>(value: T) -> Self
where
T: Any + Send + Sync,
{
Self {
ptr: Box::into_raw_non_null(Box::new(value) as Box<dyn Any + Send + Sync>),
}
}
#[inline]
pub fn as_ptr(&self) -> *mut (dyn Any + Send + Sync) {
self.ptr.as_ptr()
}
/// Extremely cursed.
#[allow(unsafe_code)]
#[inline]
pub unsafe fn downcast_ref<'extended, T>(&self) -> Option<&'extended T>
where
T: Any + Send + Sync,
{
(*self.ptr.as_ptr()).downcast_ref()
}
}
#[allow(unsafe_code)]

View file

@ -30,10 +30,10 @@ macro_rules! sizeof_checker (
// Update the sizes here
sizeof_checker!(size_event_target, EventTarget, 56);
sizeof_checker!(size_node, Node, 176);
sizeof_checker!(size_element, Element, 352);
sizeof_checker!(size_htmlelement, HTMLElement, 368);
sizeof_checker!(size_div, HTMLDivElement, 368);
sizeof_checker!(size_span, HTMLSpanElement, 368);
sizeof_checker!(size_text, Text, 208);
sizeof_checker!(size_characterdata, CharacterData, 208);
sizeof_checker!(size_node, Node, 184);
sizeof_checker!(size_element, Element, 360);
sizeof_checker!(size_htmlelement, HTMLElement, 376);
sizeof_checker!(size_div, HTMLDivElement, 376);
sizeof_checker!(size_span, HTMLSpanElement, 376);
sizeof_checker!(size_text, Text, 216);
sizeof_checker!(size_characterdata, CharacterData, 216);