Replace the unsound impl DerefMut for FlowRef with an unsafe function.

See #6503.
This commit is contained in:
Simon Sapin 2015-08-14 14:33:58 +02:00
parent a5fbb2f2a6
commit 2d22aa8e7e
10 changed files with 112 additions and 81 deletions

View file

@ -19,7 +19,7 @@ use data::{HAS_NEWLY_CONSTRUCTED_FLOW, LayoutDataWrapper};
use floats::FloatKind; use floats::FloatKind;
use flow::{MutableFlowUtils, MutableOwnedFlowUtils}; use flow::{MutableFlowUtils, MutableOwnedFlowUtils};
use flow::{self, AbsoluteDescendants, Flow, ImmutableFlowUtils, IS_ABSOLUTELY_POSITIONED}; use flow::{self, AbsoluteDescendants, Flow, ImmutableFlowUtils, IS_ABSOLUTELY_POSITIONED};
use flow_ref::FlowRef; use flow_ref::{self, FlowRef};
use fragment::{CanvasFragmentInfo, ImageFragmentInfo, InlineAbsoluteFragmentInfo}; use fragment::{CanvasFragmentInfo, ImageFragmentInfo, InlineAbsoluteFragmentInfo};
use fragment::{Fragment, GeneratedContentInfo, IframeFragmentInfo}; use fragment::{Fragment, GeneratedContentInfo, IframeFragmentInfo};
use fragment::{InlineAbsoluteHypotheticalFragmentInfo, TableColumnFragmentInfo}; use fragment::{InlineAbsoluteHypotheticalFragmentInfo, TableColumnFragmentInfo};
@ -415,6 +415,7 @@ impl<'a> FlowConstructor<'a> {
/// `#[inline(always)]` because this is performance critical and LLVM will not inline it /// `#[inline(always)]` because this is performance critical and LLVM will not inline it
/// otherwise. /// otherwise.
#[inline(always)] #[inline(always)]
#[allow(unsafe_code)]
fn flush_inline_fragments_to_flow_or_list(&mut self, fn flush_inline_fragments_to_flow_or_list(&mut self,
fragment_accumulator: InlineFragmentsAccumulator, fragment_accumulator: InlineFragmentsAccumulator,
flow: &mut FlowRef, flow: &mut FlowRef,
@ -480,7 +481,8 @@ impl<'a> FlowConstructor<'a> {
absolute_descendants.push_descendants(fragments.absolute_descendants); absolute_descendants.push_descendants(fragments.absolute_descendants);
{ {
let inline_flow = inline_flow_ref.as_mut_inline(); // FIXME(#6503): Use Arc::get_mut().unwrap() here.
let inline_flow = unsafe { flow_ref::deref_mut(&mut inline_flow_ref) }.as_mut_inline();
let (ascent, descent) = let (ascent, descent) =
@ -1287,6 +1289,7 @@ impl<'a> FlowConstructor<'a> {
/// ///
/// TODO(pcwalton): Add some more fast paths, like toggling `display: none`, adding block kids /// TODO(pcwalton): Add some more fast paths, like toggling `display: none`, adding block kids
/// to block parents with no {ib} splits, adding out-of-flow kids, etc. /// to block parents with no {ib} splits, adding out-of-flow kids, etc.
#[allow(unsafe_code)]
pub fn repair_if_possible(&mut self, node: &ThreadSafeLayoutNode) -> bool { pub fn repair_if_possible(&mut self, node: &ThreadSafeLayoutNode) -> bool {
// We can skip reconstructing the flow if we don't have to reconstruct and none of our kids // We can skip reconstructing the flow if we don't have to reconstruct and none of our kids
// did either. // did either.
@ -1317,7 +1320,8 @@ impl<'a> FlowConstructor<'a> {
if !flow.is_block_flow() { if !flow.is_block_flow() {
return false return false
} }
flow::mut_base(&mut **flow).restyle_damage.insert(damage); let flow = unsafe { flow_ref::deref_mut(flow) };
flow::mut_base(flow).restyle_damage.insert(damage);
flow.repair_style_and_bubble_inline_sizes(&style); flow.repair_style_and_bubble_inline_sizes(&style);
true true
} }
@ -1341,27 +1345,29 @@ impl<'a> FlowConstructor<'a> {
match fragment.specific { match fragment.specific {
SpecificFragmentInfo::InlineBlock(ref mut inline_block_fragment) => { SpecificFragmentInfo::InlineBlock(ref mut inline_block_fragment) => {
flow::mut_base(&mut *inline_block_fragment.flow_ref).restyle_damage let flow_ref = unsafe {
.insert(damage); flow_ref::deref_mut(&mut inline_block_fragment.flow_ref)
};
flow::mut_base(flow_ref).restyle_damage.insert(damage);
// FIXME(pcwalton): Fragment restyle damage too? // FIXME(pcwalton): Fragment restyle damage too?
inline_block_fragment.flow_ref flow_ref.repair_style_and_bubble_inline_sizes(&style);
.repair_style_and_bubble_inline_sizes(&style);
} }
SpecificFragmentInfo::InlineAbsoluteHypothetical( SpecificFragmentInfo::InlineAbsoluteHypothetical(
ref mut inline_absolute_hypothetical_fragment) => { ref mut inline_absolute_hypothetical_fragment) => {
flow::mut_base(&mut *inline_absolute_hypothetical_fragment.flow_ref) let flow_ref = unsafe {
.restyle_damage.insert(damage); flow_ref::deref_mut(&mut inline_absolute_hypothetical_fragment.flow_ref)
};
flow::mut_base(flow_ref).restyle_damage.insert(damage);
// FIXME(pcwalton): Fragment restyle damage too? // FIXME(pcwalton): Fragment restyle damage too?
inline_absolute_hypothetical_fragment flow_ref.repair_style_and_bubble_inline_sizes(&style);
.flow_ref
.repair_style_and_bubble_inline_sizes(&style);
} }
SpecificFragmentInfo::InlineAbsolute(ref mut inline_absolute_fragment) => { SpecificFragmentInfo::InlineAbsolute(ref mut inline_absolute_fragment) => {
flow::mut_base(&mut *inline_absolute_fragment.flow_ref).restyle_damage let flow_ref = unsafe {
.insert(damage); flow_ref::deref_mut(&mut inline_absolute_fragment.flow_ref)
};
flow::mut_base(flow_ref).restyle_damage.insert(damage);
// FIXME(pcwalton): Fragment restyle damage too? // FIXME(pcwalton): Fragment restyle damage too?
inline_absolute_fragment.flow_ref flow_ref.repair_style_and_bubble_inline_sizes(&style);
.repair_style_and_bubble_inline_sizes(&style);
} }
SpecificFragmentInfo::ScannedText(_) | SpecificFragmentInfo::ScannedText(_) |
SpecificFragmentInfo::UnscannedText(_) => { SpecificFragmentInfo::UnscannedText(_) => {
@ -1655,13 +1661,14 @@ impl FlowConstructionUtils for FlowRef {
/// Adds a new flow as a child of this flow. Fails if this flow is marked as a leaf. /// Adds a new flow as a child of this flow. Fails if this flow is marked as a leaf.
/// ///
/// This must not be public because only the layout constructor can do this. /// This must not be public because only the layout constructor can do this.
#[allow(unsafe_code)]
fn add_new_child(&mut self, mut new_child: FlowRef) { fn add_new_child(&mut self, mut new_child: FlowRef) {
{ {
let kid_base = flow::mut_base(&mut *new_child); let kid_base = flow::mut_base(unsafe { flow_ref::deref_mut(&mut new_child) });
kid_base.parallel.parent = parallel::mut_owned_flow_to_unsafe_flow(self); kid_base.parallel.parent = parallel::mut_owned_flow_to_unsafe_flow(self);
} }
let base = flow::mut_base(&mut **self); let base = flow::mut_base(unsafe { flow_ref::deref_mut(self) });
base.children.push_back(new_child); base.children.push_back(new_child);
let _ = base.parallel.children_count.fetch_add(1, Ordering::Relaxed); let _ = base.parallel.children_count.fetch_add(1, Ordering::Relaxed);
} }
@ -1674,9 +1681,10 @@ impl FlowConstructionUtils for FlowRef {
/// properly computed. (This is not, however, a memory safety problem.) /// properly computed. (This is not, however, a memory safety problem.)
/// ///
/// This must not be public because only the layout constructor can do this. /// This must not be public because only the layout constructor can do this.
#[allow(unsafe_code)]
fn finish(&mut self) { fn finish(&mut self) {
if !opts::get().bubble_inline_sizes_separately { if !opts::get().bubble_inline_sizes_separately {
self.bubble_inline_sizes() unsafe { flow_ref::deref_mut(self) }.bubble_inline_sizes()
} }
} }
} }

View file

@ -14,6 +14,7 @@ use azure::azure_hl::Color;
use block::BlockFlow; use block::BlockFlow;
use context::LayoutContext; use context::LayoutContext;
use flow::{self, BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED, NEEDS_LAYER}; use flow::{self, BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED, NEEDS_LAYER};
use flow_ref;
use fragment::{CoordinateSystem, Fragment, IframeFragmentInfo, ImageFragmentInfo}; use fragment::{CoordinateSystem, Fragment, IframeFragmentInfo, ImageFragmentInfo};
use fragment::{ScannedTextFragmentInfo, SpecificFragmentInfo}; use fragment::{ScannedTextFragmentInfo, SpecificFragmentInfo};
use inline::InlineFlow; use inline::InlineFlow;
@ -1770,6 +1771,7 @@ pub trait InlineFlowDisplayListBuilding {
} }
impl InlineFlowDisplayListBuilding for InlineFlow { impl InlineFlowDisplayListBuilding for InlineFlow {
#[allow(unsafe_code)]
fn build_display_list_for_inline(&mut self, layout_context: &LayoutContext) { fn build_display_list_for_inline(&mut self, layout_context: &LayoutContext) {
// TODO(#228): Once we form lines and have their cached bounds, we can be smarter and // TODO(#228): Once we form lines and have their cached bounds, we can be smarter and
// not recurse on a line if nothing in it can intersect the dirty region. // not recurse on a line if nothing in it can intersect the dirty region.
@ -1796,17 +1798,17 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
match fragment.specific { match fragment.specific {
SpecificFragmentInfo::InlineBlock(ref mut block_flow) => { SpecificFragmentInfo::InlineBlock(ref mut block_flow) => {
let block_flow = &mut *block_flow.flow_ref; let block_flow = unsafe { flow_ref::deref_mut(&mut block_flow.flow_ref) };
flow::mut_base(block_flow).display_list_building_result flow::mut_base(block_flow).display_list_building_result
.add_to(&mut *display_list) .add_to(&mut *display_list)
} }
SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut block_flow) => { SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut block_flow) => {
let block_flow = &mut *block_flow.flow_ref; let block_flow = unsafe { flow_ref::deref_mut(&mut block_flow.flow_ref) };
flow::mut_base(block_flow).display_list_building_result flow::mut_base(block_flow).display_list_building_result
.add_to(&mut *display_list) .add_to(&mut *display_list)
} }
SpecificFragmentInfo::InlineAbsolute(ref mut block_flow) => { SpecificFragmentInfo::InlineAbsolute(ref mut block_flow) => {
let block_flow = &mut *block_flow.flow_ref; let block_flow = unsafe { flow_ref::deref_mut(&mut block_flow.flow_ref) };
flow::mut_base(block_flow).display_list_building_result flow::mut_base(block_flow).display_list_building_result
.add_to(&mut *display_list) .add_to(&mut *display_list)
} }

View file

@ -30,7 +30,7 @@ use context::LayoutContext;
use display_list_builder::DisplayListBuildingResult; use display_list_builder::DisplayListBuildingResult;
use floats::Floats; use floats::Floats;
use flow_list::{FlowList, FlowListIterator, MutFlowListIterator}; use flow_list::{FlowList, FlowListIterator, MutFlowListIterator};
use flow_ref::{FlowRef, WeakFlowRef}; use flow_ref::{self, FlowRef, WeakFlowRef};
use fragment::{Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo}; use fragment::{Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo};
use incremental::{self, RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDamage}; use incremental::{self, RECONSTRUCT_FLOW, REFLOW, REFLOW_OUT_OF_FLOW, RestyleDamage};
use inline::InlineFlow; use inline::InlineFlow;
@ -771,8 +771,9 @@ pub struct AbsoluteDescendantIter<'a> {
impl<'a> Iterator for AbsoluteDescendantIter<'a> { impl<'a> Iterator for AbsoluteDescendantIter<'a> {
type Item = &'a mut (Flow + 'a); type Item = &'a mut (Flow + 'a);
#[allow(unsafe_code)]
fn next(&mut self) -> Option<&'a mut (Flow + 'a)> { fn next(&mut self) -> Option<&'a mut (Flow + 'a)> {
self.iter.next().map(|info| &mut *info.flow) self.iter.next().map(|info| unsafe { flow_ref::deref_mut(&mut info.flow) })
} }
} }
@ -1382,9 +1383,10 @@ impl MutableOwnedFlowUtils for FlowRef {
/// This is called during flow construction, so nothing else can be accessing the descendant /// This is called during flow construction, so nothing else can be accessing the descendant
/// flows. This is enforced by the fact that we have a mutable `FlowRef`, which only flow /// flows. This is enforced by the fact that we have a mutable `FlowRef`, which only flow
/// construction is allowed to possess. /// construction is allowed to possess.
#[allow(unsafe_code)]
fn set_absolute_descendants(&mut self, abs_descendants: AbsoluteDescendants) { fn set_absolute_descendants(&mut self, abs_descendants: AbsoluteDescendants) {
let this = self.clone(); let this = self.clone();
let base = mut_base(&mut **self); let base = mut_base(unsafe { flow_ref::deref_mut(self) });
base.abs_descendants = abs_descendants; base.abs_descendants = abs_descendants;
for descendant_link in base.abs_descendants.iter() { for descendant_link in base.abs_descendants.iter() {
let descendant_base = mut_base(descendant_link); let descendant_base = mut_base(descendant_link);

View file

@ -3,7 +3,7 @@
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
use flow::Flow; use flow::Flow;
use flow_ref::FlowRef; use flow_ref::{self, FlowRef};
use std::collections::{linked_list, LinkedList}; use std::collections::{linked_list, LinkedList};
@ -33,7 +33,7 @@ impl FlowList {
#[inline] #[inline]
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub unsafe fn front_mut<'a>(&'a mut self) -> Option<&'a mut Flow> { pub unsafe fn front_mut<'a>(&'a mut self) -> Option<&'a mut Flow> {
self.flows.front_mut().map(|head| &mut **head) self.flows.front_mut().map(|head| flow_ref::deref_mut(head))
} }
/// Provide a reference to the back element, or None if the list is empty /// Provide a reference to the back element, or None if the list is empty
@ -46,7 +46,7 @@ impl FlowList {
#[inline] #[inline]
#[allow(unsafe_code)] #[allow(unsafe_code)]
pub unsafe fn back_mut<'a>(&'a mut self) -> Option<&'a mut Flow> { pub unsafe fn back_mut<'a>(&'a mut self) -> Option<&'a mut Flow> {
self.flows.back_mut().map(|tail| &mut **tail) self.flows.back_mut().map(|tail| flow_ref::deref_mut(tail))
} }
/// Add an element first in the list /// Add an element first in the list
@ -123,8 +123,9 @@ impl<'a> Iterator for FlowListIterator<'a> {
impl<'a> Iterator for MutFlowListIterator<'a> { impl<'a> Iterator for MutFlowListIterator<'a> {
type Item = &'a mut (Flow + 'a); type Item = &'a mut (Flow + 'a);
#[inline] #[inline]
#[allow(unsafe_code)]
fn next(&mut self) -> Option<&'a mut (Flow + 'a)> { fn next(&mut self) -> Option<&'a mut (Flow + 'a)> {
self.it.next().map(|x| &mut **x) self.it.next().map(|x| unsafe { flow_ref::deref_mut(x) })
} }
#[inline] #[inline]

View file

@ -14,7 +14,7 @@ use flow;
use flow::{Flow, BaseFlow}; use flow::{Flow, BaseFlow};
use std::mem; use std::mem;
use std::ops::{Deref, DerefMut}; use std::ops::Deref;
use std::ptr; use std::ptr;
use std::raw; use std::raw;
use std::rt::heap; use std::rt::heap;
@ -67,12 +67,10 @@ impl<'a> Deref for FlowRef {
} }
} }
impl DerefMut for FlowRef { // FIXME(https://github.com/servo/servo/issues/6503) This introduces unsound mutable aliasing.
fn deref_mut<'a>(&mut self) -> &mut (Flow + 'a) { // Try to replace it with Arc::get_mut (which checks that the reference count is 1).
unsafe { pub unsafe fn deref_mut<'a>(flow_ref: &mut FlowRef) -> &mut (Flow + 'a) {
mem::transmute_copy::<raw::TraitObject, &mut (Flow + 'a)>(&self.object) mem::transmute_copy::<raw::TraitObject, &mut (Flow + 'a)>(&flow_ref.object)
}
}
} }
impl Drop for FlowRef { impl Drop for FlowRef {

View file

@ -11,7 +11,7 @@ use context::LayoutContext;
use floats::ClearType; use floats::ClearType;
use flow; use flow;
use flow::Flow; use flow::Flow;
use flow_ref::FlowRef; use flow_ref::{self, FlowRef};
use incremental::{self, RestyleDamage}; use incremental::{self, RestyleDamage};
use inline::{InlineFragmentContext, InlineFragmentNodeInfo, InlineMetrics}; use inline::{InlineFragmentContext, InlineFragmentNodeInfo, InlineMetrics};
use layout_debug; use layout_debug;
@ -1248,6 +1248,7 @@ impl Fragment {
} }
/// Computes the intrinsic inline-sizes of this fragment. /// Computes the intrinsic inline-sizes of this fragment.
#[allow(unsafe_code)]
pub fn compute_intrinsic_inline_sizes(&mut self) -> IntrinsicISizesContribution { pub fn compute_intrinsic_inline_sizes(&mut self) -> IntrinsicISizesContribution {
let mut result = self.style_specified_intrinsic_inline_size(); let mut result = self.style_specified_intrinsic_inline_size();
match self.specific { match self.specific {
@ -1260,11 +1261,11 @@ impl Fragment {
SpecificFragmentInfo::TableRow | SpecificFragmentInfo::TableRow |
SpecificFragmentInfo::TableWrapper | SpecificFragmentInfo::TableWrapper |
SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => {} SpecificFragmentInfo::InlineAbsoluteHypothetical(_) => {}
SpecificFragmentInfo::InlineBlock(ref mut info) => { SpecificFragmentInfo::InlineBlock(ref info) => {
let block_flow = info.flow_ref.as_block(); let block_flow = info.flow_ref.as_block();
result.union_block(&block_flow.base.intrinsic_inline_sizes) result.union_block(&block_flow.base.intrinsic_inline_sizes)
} }
SpecificFragmentInfo::InlineAbsolute(ref mut info) => { SpecificFragmentInfo::InlineAbsolute(ref info) => {
let block_flow = info.flow_ref.as_block(); let block_flow = info.flow_ref.as_block();
result.union_block(&block_flow.base.intrinsic_inline_sizes) result.union_block(&block_flow.base.intrinsic_inline_sizes)
} }
@ -1619,6 +1620,7 @@ impl Fragment {
/// Assigns replaced inline-size, padding, and margins for this fragment only if it is replaced /// Assigns replaced inline-size, padding, and margins for this fragment only if it is replaced
/// content per CSS 2.1 § 10.3.2. /// content per CSS 2.1 § 10.3.2.
#[allow(unsafe_code)]
pub fn assign_replaced_inline_size_if_necessary<'a>(&'a mut self, container_inline_size: Au) { pub fn assign_replaced_inline_size_if_necessary<'a>(&'a mut self, container_inline_size: Au) {
match self.specific { match self.specific {
SpecificFragmentInfo::Generic | SpecificFragmentInfo::Generic |
@ -1647,7 +1649,7 @@ impl Fragment {
match self.specific { match self.specific {
SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => { SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => {
let block_flow = info.flow_ref.as_mut_block(); let block_flow = unsafe { flow_ref::deref_mut(&mut info.flow_ref) }.as_mut_block();
block_flow.base.position.size.inline = block_flow.base.position.size.inline =
block_flow.base.intrinsic_inline_sizes.preferred_inline_size; block_flow.base.intrinsic_inline_sizes.preferred_inline_size;
@ -1655,7 +1657,7 @@ impl Fragment {
self.border_box.size.inline = Au(0); self.border_box.size.inline = Au(0);
} }
SpecificFragmentInfo::InlineBlock(ref mut info) => { SpecificFragmentInfo::InlineBlock(ref mut info) => {
let block_flow = info.flow_ref.as_mut_block(); let block_flow = unsafe { flow_ref::deref_mut(&mut info.flow_ref) }.as_mut_block();
self.border_box.size.inline = self.border_box.size.inline =
max(block_flow.base.intrinsic_inline_sizes.minimum_inline_size, max(block_flow.base.intrinsic_inline_sizes.minimum_inline_size,
block_flow.base.intrinsic_inline_sizes.preferred_inline_size); block_flow.base.intrinsic_inline_sizes.preferred_inline_size);
@ -1663,7 +1665,7 @@ impl Fragment {
block_flow.base.block_container_writing_mode = self.style.writing_mode; block_flow.base.block_container_writing_mode = self.style.writing_mode;
} }
SpecificFragmentInfo::InlineAbsolute(ref mut info) => { SpecificFragmentInfo::InlineAbsolute(ref mut info) => {
let block_flow = info.flow_ref.as_mut_block(); let block_flow = unsafe { flow_ref::deref_mut(&mut info.flow_ref) }.as_mut_block();
self.border_box.size.inline = self.border_box.size.inline =
max(block_flow.base.intrinsic_inline_sizes.minimum_inline_size, max(block_flow.base.intrinsic_inline_sizes.minimum_inline_size,
block_flow.base.intrinsic_inline_sizes.preferred_inline_size); block_flow.base.intrinsic_inline_sizes.preferred_inline_size);
@ -1711,6 +1713,7 @@ impl Fragment {
/// been assigned first. /// been assigned first.
/// ///
/// Ideally, this should follow CSS 2.1 § 10.6.2. /// Ideally, this should follow CSS 2.1 § 10.6.2.
#[allow(unsafe_code)]
pub fn assign_replaced_block_size_if_necessary(&mut self, containing_block_block_size: Option<Au>) { pub fn assign_replaced_block_size_if_necessary(&mut self, containing_block_block_size: Option<Au>) {
match self.specific { match self.specific {
SpecificFragmentInfo::Generic | SpecificFragmentInfo::Generic |
@ -1767,18 +1770,18 @@ impl Fragment {
} }
SpecificFragmentInfo::InlineBlock(ref mut info) => { SpecificFragmentInfo::InlineBlock(ref mut info) => {
// Not the primary fragment, so we do not take the noncontent size into account. // Not the primary fragment, so we do not take the noncontent size into account.
let block_flow = info.flow_ref.as_block(); let block_flow = unsafe { flow_ref::deref_mut(&mut info.flow_ref) }.as_block();
self.border_box.size.block = block_flow.base.position.size.block + self.border_box.size.block = block_flow.base.position.size.block +
block_flow.fragment.margin.block_start_end() block_flow.fragment.margin.block_start_end()
} }
SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => { SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => {
// Not the primary fragment, so we do not take the noncontent size into account. // Not the primary fragment, so we do not take the noncontent size into account.
let block_flow = info.flow_ref.as_block(); let block_flow = unsafe { flow_ref::deref_mut(&mut info.flow_ref) }.as_block();
self.border_box.size.block = block_flow.base.position.size.block; self.border_box.size.block = block_flow.base.position.size.block;
} }
SpecificFragmentInfo::InlineAbsolute(ref mut info) => { SpecificFragmentInfo::InlineAbsolute(ref mut info) => {
// Not the primary fragment, so we do not take the noncontent size into account. // Not the primary fragment, so we do not take the noncontent size into account.
let block_flow = info.flow_ref.as_block(); let block_flow = unsafe { flow_ref::deref_mut(&mut info.flow_ref) }.as_block();
self.border_box.size.block = block_flow.base.position.size.block + self.border_box.size.block = block_flow.base.position.size.block +
block_flow.fragment.margin.block_start_end() block_flow.fragment.margin.block_start_end()
} }
@ -1904,9 +1907,10 @@ impl Fragment {
/// Determines the inline sizes of inline-block fragments. These cannot be fully computed until /// Determines the inline sizes of inline-block fragments. These cannot be fully computed until
/// inline size assignment has run for the child flow: thus it is computed "late", during /// inline size assignment has run for the child flow: thus it is computed "late", during
/// block size assignment. /// block size assignment.
#[allow(unsafe_code)]
pub fn update_late_computed_replaced_inline_size_if_necessary(&mut self) { pub fn update_late_computed_replaced_inline_size_if_necessary(&mut self) {
if let SpecificFragmentInfo::InlineBlock(ref mut inline_block_info) = self.specific { if let SpecificFragmentInfo::InlineBlock(ref mut inline_block_info) = self.specific {
let block_flow = inline_block_info.flow_ref.as_block(); let block_flow = unsafe { flow_ref::deref_mut(&mut inline_block_info.flow_ref) }.as_block();
let margin = block_flow.fragment.style.logical_margin(); let margin = block_flow.fragment.style.logical_margin();
self.border_box.size.inline = block_flow.fragment.border_box.size.inline + self.border_box.size.inline = block_flow.fragment.border_box.size.inline +
MaybeAuto::from_style(margin.inline_start, Au(0)).specified_or_zero() + MaybeAuto::from_style(margin.inline_start, Au(0)).specified_or_zero() +
@ -1914,21 +1918,25 @@ impl Fragment {
} }
} }
#[allow(unsafe_code)]
pub fn update_late_computed_inline_position_if_necessary(&mut self) { pub fn update_late_computed_inline_position_if_necessary(&mut self) {
match self.specific { match self.specific {
SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => { SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => {
let position = self.border_box.start.i; let position = self.border_box.start.i;
info.flow_ref.update_late_computed_inline_position_if_necessary(position) unsafe { flow_ref::deref_mut(&mut info.flow_ref) }
.update_late_computed_inline_position_if_necessary(position)
} }
_ => {} _ => {}
} }
} }
#[allow(unsafe_code)]
pub fn update_late_computed_block_position_if_necessary(&mut self) { pub fn update_late_computed_block_position_if_necessary(&mut self) {
match self.specific { match self.specific {
SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => { SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => {
let position = self.border_box.start.b; let position = self.border_box.start.b;
info.flow_ref.update_late_computed_block_position_if_necessary(position) unsafe { flow_ref::deref_mut(&mut info.flow_ref) }
.update_late_computed_block_position_if_necessary(position)
} }
_ => {} _ => {}
} }

View file

@ -10,6 +10,7 @@ use display_list_builder::{FragmentDisplayListBuilding, InlineFlowDisplayListBui
use floats::{FloatKind, Floats, PlacementInfo}; use floats::{FloatKind, Floats, PlacementInfo};
use flow::{MutableFlowUtils, OpaqueFlow}; use flow::{MutableFlowUtils, OpaqueFlow};
use flow::{self, BaseFlow, FlowClass, Flow, ForceNonfloatedFlag, IS_ABSOLUTELY_POSITIONED}; use flow::{self, BaseFlow, FlowClass, Flow, ForceNonfloatedFlag, IS_ABSOLUTELY_POSITIONED};
use flow_ref;
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo}; use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo};
use incremental::{REFLOW, REFLOW_OUT_OF_FLOW, RESOLVE_GENERATED_CONTENT}; use incremental::{REFLOW, REFLOW_OUT_OF_FLOW, RESOLVE_GENERATED_CONTENT};
use layout_debug; use layout_debug;
@ -1596,6 +1597,7 @@ impl Flow for InlineFlow {
self.base.restyle_damage.remove(REFLOW_OUT_OF_FLOW | REFLOW); self.base.restyle_damage.remove(REFLOW_OUT_OF_FLOW | REFLOW);
} }
#[allow(unsafe_code)]
fn compute_absolute_position(&mut self, _: &LayoutContext) { fn compute_absolute_position(&mut self, _: &LayoutContext) {
// First, gather up the positions of all the containing blocks (if any). // First, gather up the positions of all the containing blocks (if any).
// //
@ -1656,9 +1658,10 @@ impl Flow for InlineFlow {
let is_positioned = fragment.is_positioned(); let is_positioned = fragment.is_positioned();
match fragment.specific { match fragment.specific {
SpecificFragmentInfo::InlineBlock(ref mut info) => { SpecificFragmentInfo::InlineBlock(ref mut info) => {
flow::mut_base(&mut *info.flow_ref).clip = clip; let flow = unsafe { flow_ref::deref_mut(&mut info.flow_ref) };
flow::mut_base(flow).clip = clip;
let block_flow = info.flow_ref.as_mut_block(); let block_flow = flow.as_mut_block();
block_flow.base.absolute_position_info = self.base.absolute_position_info; block_flow.base.absolute_position_info = self.base.absolute_position_info;
let stacking_relative_position = self.base.stacking_relative_position; let stacking_relative_position = self.base.stacking_relative_position;
@ -1676,9 +1679,9 @@ impl Flow for InlineFlow {
self.base.stacking_relative_position_of_display_port; self.base.stacking_relative_position_of_display_port;
} }
SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => { SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => {
flow::mut_base(&mut *info.flow_ref).clip = clip; let flow = unsafe { flow_ref::deref_mut(&mut info.flow_ref) };
flow::mut_base(flow).clip = clip;
let block_flow = info.flow_ref.as_mut_block(); let block_flow = flow.as_mut_block();
block_flow.base.absolute_position_info = self.base.absolute_position_info; block_flow.base.absolute_position_info = self.base.absolute_position_info;
block_flow.base.stacking_relative_position = block_flow.base.stacking_relative_position =
@ -1687,9 +1690,10 @@ impl Flow for InlineFlow {
self.base.stacking_relative_position_of_display_port; self.base.stacking_relative_position_of_display_port;
} }
SpecificFragmentInfo::InlineAbsolute(ref mut info) => { SpecificFragmentInfo::InlineAbsolute(ref mut info) => {
flow::mut_base(&mut *info.flow_ref).clip = clip; let flow = unsafe { flow_ref::deref_mut(&mut info.flow_ref) };
flow::mut_base(flow).clip = clip;
let block_flow = info.flow_ref.as_mut_block(); let block_flow = flow.as_mut_block();
block_flow.base.absolute_position_info = self.base.absolute_position_info; block_flow.base.absolute_position_info = self.base.absolute_position_info;
let stacking_relative_position = self.base.stacking_relative_position; let stacking_relative_position = self.base.stacking_relative_position;

View file

@ -14,7 +14,7 @@ use cssparser::ToCss;
use data::LayoutDataWrapper; use data::LayoutDataWrapper;
use display_list_builder::ToGfxColor; use display_list_builder::ToGfxColor;
use flow::{self, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils}; use flow::{self, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
use flow_ref::FlowRef; use flow_ref::{self, FlowRef};
use fragment::{Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo}; use fragment::{Fragment, FragmentBorderBoxIterator, SpecificFragmentInfo};
use incremental::{LayoutDamageComputation, REFLOW, REFLOW_ENTIRE_DOCUMENT, REPAINT}; use incremental::{LayoutDamageComputation, REFLOW, REFLOW_ENTIRE_DOCUMENT, REPAINT};
use layout_debug; use layout_debug;
@ -781,7 +781,7 @@ impl LayoutTask {
_ => return None, _ => return None,
}; };
flow.mark_as_root(); unsafe { flow_ref::deref_mut(&mut flow) }.mark_as_root();
Some(flow) Some(flow)
} }
@ -999,11 +999,11 @@ impl LayoutTask {
self.profiler_metadata(), self.profiler_metadata(),
self.time_profiler_chan.clone(), self.time_profiler_chan.clone(),
|| { || {
flow::mut_base(&mut **layout_root).stacking_relative_position = flow::mut_base(unsafe { flow_ref::deref_mut(layout_root) }).stacking_relative_position =
LogicalPoint::zero(writing_mode).to_physical(writing_mode, LogicalPoint::zero(writing_mode).to_physical(writing_mode,
rw_data.screen_size); rw_data.screen_size);
flow::mut_base(&mut **layout_root).clip = flow::mut_base(unsafe { flow_ref::deref_mut(layout_root) }).clip =
ClippingRegion::from_rect(&data.page_clip_rect); ClippingRegion::from_rect(&data.page_clip_rect);
match (&mut rw_data.parallel_traversal, opts::get().parallel_display_list_building) { match (&mut rw_data.parallel_traversal, opts::get().parallel_display_list_building) {
@ -1023,13 +1023,15 @@ impl LayoutTask {
if data.goal == ReflowGoal::ForDisplay { if data.goal == ReflowGoal::ForDisplay {
debug!("Done building display list."); debug!("Done building display list.");
let root_background_color = get_root_flow_background_color(&mut **layout_root); let root_background_color = get_root_flow_background_color(
unsafe { flow_ref::deref_mut(layout_root) });
let root_size = { let root_size = {
let root_flow = flow::base(&**layout_root); let root_flow = flow::base(&**layout_root);
root_flow.position.size.to_physical(root_flow.writing_mode) root_flow.position.size.to_physical(root_flow.writing_mode)
}; };
let mut display_list = box DisplayList::new(); let mut display_list = box DisplayList::new();
flow::mut_base(&mut **layout_root).display_list_building_result flow::mut_base(unsafe { flow_ref::deref_mut(layout_root) })
.display_list_building_result
.add_to(&mut *display_list); .add_to(&mut *display_list);
let paint_layer = PaintLayer::new(layout_root.layer_id(0), let paint_layer = PaintLayer::new(layout_root.layer_id(0),
root_background_color, root_background_color,
@ -1128,7 +1130,7 @@ impl LayoutTask {
} }
if needs_reflow { if needs_reflow {
if let Some(mut flow) = self.try_get_layout_root(*node) { if let Some(mut flow) = self.try_get_layout_root(*node) {
LayoutTask::reflow_all_nodes(&mut *flow); LayoutTask::reflow_all_nodes(unsafe { flow_ref::deref_mut(&mut flow) });
} }
} }
@ -1289,7 +1291,7 @@ impl LayoutTask {
self.profiler_metadata(), self.profiler_metadata(),
self.time_profiler_chan.clone(), self.time_profiler_chan.clone(),
|| { || {
animation::recalc_style_for_animations(root_flow.deref_mut(), animation::recalc_style_for_animations(unsafe { flow_ref::deref_mut(&mut root_flow) },
animations) animations)
}); });
} }
@ -1309,10 +1311,10 @@ impl LayoutTask {
self.profiler_metadata(), self.profiler_metadata(),
self.time_profiler_chan.clone(), self.time_profiler_chan.clone(),
|| { || {
if opts::get().nonincremental_layout || root_flow.deref_mut() if opts::get().nonincremental_layout || unsafe { flow_ref::deref_mut(&mut root_flow) }
.compute_layout_damage() .compute_layout_damage()
.contains(REFLOW_ENTIRE_DOCUMENT) { .contains(REFLOW_ENTIRE_DOCUMENT) {
root_flow.deref_mut().reflow_entire_document() unsafe { flow_ref::deref_mut(&mut root_flow) }.reflow_entire_document()
} }
}); });

View file

@ -11,7 +11,7 @@
use context::{LayoutContext, SharedLayoutContext}; use context::{LayoutContext, SharedLayoutContext};
use flow; use flow;
use flow::{Flow, MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal}; use flow::{Flow, MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal};
use flow_ref::FlowRef; use flow_ref::{self, FlowRef};
use traversal::PostorderNodeMutTraversal; use traversal::PostorderNodeMutTraversal;
use traversal::{BubbleISizes, AssignISizes, AssignBSizesAndStoreOverflow}; use traversal::{BubbleISizes, AssignISizes, AssignBSizesAndStoreOverflow};
use traversal::{ComputeAbsolutePositions, BuildDisplayList}; use traversal::{ComputeAbsolutePositions, BuildDisplayList};
@ -242,14 +242,15 @@ trait ParallelPostorderFlowTraversal : PostorderFlowTraversal {
let flow: &mut FlowRef = unsafe { let flow: &mut FlowRef = unsafe {
mem::transmute(&mut unsafe_flow) mem::transmute(&mut unsafe_flow)
}; };
let flow = unsafe { flow_ref::deref_mut(flow) };
// Perform the appropriate traversal. // Perform the appropriate traversal.
if self.should_process(&mut **flow) { if self.should_process(flow) {
self.process(&mut **flow); self.process(flow);
} }
let base = flow::mut_base(&mut **flow); let base = flow::mut_base(flow);
// Reset the count of children for the next layout traversal. // Reset the count of children for the next layout traversal.
base.parallel.children_count.store(base.children.len() as isize, base.parallel.children_count.store(base.children.len() as isize,
@ -268,7 +269,7 @@ trait ParallelPostorderFlowTraversal : PostorderFlowTraversal {
let parent: &mut FlowRef = unsafe { let parent: &mut FlowRef = unsafe {
mem::transmute(&mut unsafe_parent) mem::transmute(&mut unsafe_parent)
}; };
let parent_base = flow::mut_base(&mut **parent); let parent_base = flow::mut_base(unsafe { flow_ref::deref_mut(parent) });
if parent_base.parallel.children_count.fetch_sub(1, Ordering::Relaxed) == 1 { if parent_base.parallel.children_count.fetch_sub(1, Ordering::Relaxed) == 1 {
// We were the last child of our parent. Reflow our parent. // We were the last child of our parent. Reflow our parent.
unsafe_flow = unsafe_parent unsafe_flow = unsafe_parent
@ -300,18 +301,19 @@ trait ParallelPreorderFlowTraversal : PreorderFlowTraversal {
unsafe { unsafe {
// Get a real flow. // Get a real flow.
let flow: &mut FlowRef = mem::transmute(&mut unsafe_flow); let flow: &mut FlowRef = mem::transmute(&mut unsafe_flow);
let flow = flow_ref::deref_mut(flow);
if self.should_record_thread_ids() { if self.should_record_thread_ids() {
flow::mut_base(&mut **flow).thread_id = proxy.worker_index(); flow::mut_base(flow).thread_id = proxy.worker_index();
} }
if self.should_process(&mut **flow) { if self.should_process(flow) {
// Perform the appropriate traversal. // Perform the appropriate traversal.
self.process(&mut **flow); self.process(flow);
} }
// Possibly enqueue the children. // Possibly enqueue the children.
for kid in flow::child_iter(&mut **flow) { for kid in flow::child_iter(flow) {
had_children = true; had_children = true;
discovered_child_flows.push(borrowed_flow_to_unsafe_flow(kid)); discovered_child_flows.push(borrowed_flow_to_unsafe_flow(kid));
} }
@ -470,7 +472,7 @@ pub fn traverse_flow_tree_preorder(
if opts::get().bubble_inline_sizes_separately { if opts::get().bubble_inline_sizes_separately {
let layout_context = LayoutContext::new(shared_layout_context); let layout_context = LayoutContext::new(shared_layout_context);
let bubble_inline_sizes = BubbleISizes { layout_context: &layout_context }; let bubble_inline_sizes = BubbleISizes { layout_context: &layout_context };
root.traverse_postorder(&bubble_inline_sizes); unsafe { flow_ref::deref_mut(root) }.traverse_postorder(&bubble_inline_sizes);
} }
run_queue_with_custom_work_data_type(queue, |queue| { run_queue_with_custom_work_data_type(queue, |queue| {

View file

@ -7,7 +7,7 @@
use context::{LayoutContext, SharedLayoutContext}; use context::{LayoutContext, SharedLayoutContext};
use flow::{PostorderFlowTraversal, PreorderFlowTraversal}; use flow::{PostorderFlowTraversal, PreorderFlowTraversal};
use flow::{self, Flow, ImmutableFlowUtils, InorderFlowTraversal, MutableFlowUtils}; use flow::{self, Flow, ImmutableFlowUtils, InorderFlowTraversal, MutableFlowUtils};
use flow_ref::FlowRef; use flow_ref::{self, FlowRef};
use fragment::FragmentBorderBoxIterator; use fragment::FragmentBorderBoxIterator;
use generated_content::ResolveGeneratedContent; use generated_content::ResolveGeneratedContent;
use traversal::PostorderNodeMutTraversal; use traversal::PostorderNodeMutTraversal;
@ -40,6 +40,7 @@ pub fn traverse_dom_preorder(root: LayoutNode,
doit(root, recalc_style, construct_flows); doit(root, recalc_style, construct_flows);
} }
#[allow(unsafe_code)]
pub fn resolve_generated_content(root: &mut FlowRef, shared_layout_context: &SharedLayoutContext) { pub fn resolve_generated_content(root: &mut FlowRef, shared_layout_context: &SharedLayoutContext) {
fn doit(flow: &mut Flow, level: u32, traversal: &mut ResolveGeneratedContent) { fn doit(flow: &mut Flow, level: u32, traversal: &mut ResolveGeneratedContent) {
if !traversal.should_process(flow) { if !traversal.should_process(flow) {
@ -55,9 +56,10 @@ pub fn resolve_generated_content(root: &mut FlowRef, shared_layout_context: &Sha
let layout_context = LayoutContext::new(shared_layout_context); let layout_context = LayoutContext::new(shared_layout_context);
let mut traversal = ResolveGeneratedContent::new(&layout_context); let mut traversal = ResolveGeneratedContent::new(&layout_context);
doit(&mut **root, 0, &mut traversal) doit(unsafe { flow_ref::deref_mut(root) }, 0, &mut traversal)
} }
#[allow(unsafe_code)]
pub fn traverse_flow_tree_preorder(root: &mut FlowRef, pub fn traverse_flow_tree_preorder(root: &mut FlowRef,
shared_layout_context: &SharedLayoutContext) { shared_layout_context: &SharedLayoutContext) {
fn doit(flow: &mut Flow, fn doit(flow: &mut Flow,
@ -78,7 +80,7 @@ pub fn traverse_flow_tree_preorder(root: &mut FlowRef,
let layout_context = LayoutContext::new(shared_layout_context); let layout_context = LayoutContext::new(shared_layout_context);
let root = &mut **root; let root = unsafe { flow_ref::deref_mut(root) };
if opts::get().bubble_inline_sizes_separately { if opts::get().bubble_inline_sizes_separately {
let bubble_inline_sizes = BubbleISizes { layout_context: &layout_context }; let bubble_inline_sizes = BubbleISizes { layout_context: &layout_context };
@ -94,6 +96,7 @@ pub fn traverse_flow_tree_preorder(root: &mut FlowRef,
doit(root, assign_inline_sizes, assign_block_sizes); doit(root, assign_inline_sizes, assign_block_sizes);
} }
#[allow(unsafe_code)]
pub fn build_display_list_for_subtree(root: &mut FlowRef, pub fn build_display_list_for_subtree(root: &mut FlowRef,
shared_layout_context: &SharedLayoutContext) { shared_layout_context: &SharedLayoutContext) {
fn doit(flow: &mut Flow, fn doit(flow: &mut Flow,
@ -116,9 +119,10 @@ pub fn build_display_list_for_subtree(root: &mut FlowRef,
let compute_absolute_positions = ComputeAbsolutePositions { layout_context: &layout_context }; let compute_absolute_positions = ComputeAbsolutePositions { layout_context: &layout_context };
let build_display_list = BuildDisplayList { layout_context: &layout_context }; let build_display_list = BuildDisplayList { layout_context: &layout_context };
doit(&mut **root, compute_absolute_positions, build_display_list); doit(unsafe { flow_ref::deref_mut(root) }, compute_absolute_positions, build_display_list);
} }
#[allow(unsafe_code)]
pub fn iterate_through_flow_tree_fragment_border_boxes(root: &mut FlowRef, pub fn iterate_through_flow_tree_fragment_border_boxes(root: &mut FlowRef,
iterator: &mut FragmentBorderBoxIterator) { iterator: &mut FragmentBorderBoxIterator) {
fn doit(flow: &mut Flow, fn doit(flow: &mut Flow,
@ -141,5 +145,5 @@ pub fn iterate_through_flow_tree_fragment_border_boxes(root: &mut FlowRef,
} }
} }
doit(&mut **root, 0, iterator, &ZERO_POINT); doit(unsafe { flow_ref::deref_mut(root) }, 0, iterator, &ZERO_POINT);
} }