servo: Merge #14053 - Make `FlowRef` a newtype (from notriddle:flow_ref_unsafe); r=pcwalton

This creates a sharp distinction between `Arc<Flow>`s, which may be
owned by anyone, and `FlowRef`s, which may only be owned by the
traversal code. By checking the reference count, we ensure that a `Flow`
cannot be pointed to by `Arc`s and `FlowRef`s simultaneously.

This is not a complete fix for #6503, though it is a necessary start
(enforcing the no-aliasing rule of `FlowRef::deref_mut` will require far
more work).

---

- [X] `./mach build -d` does not report any errors
- [X] `./mach test-tidy` does not report any errors
- [X] These changes fix #14014 (github issue number if applicable).
- [X] These changes do not require tests because the existing tests, plus the added assertions, should be sufficient

Source-Repo: https://github.com/servo/servo
Source-Revision: 2b4a7b0b7ad9dd568dfde15ab47dc634ec561d70
This commit is contained in:
Michael Howell 2016-11-04 16:53:38 -05:00
Родитель 990ddaaabf
Коммит 5b347f4041
10 изменённых файлов: 145 добавлений и 101 удалений

Просмотреть файл

@ -40,7 +40,6 @@ use flow::{FragmentationContext, MARGINS_CANNOT_COLLAPSE, PreorderFlowTraversal}
use flow::{ImmutableFlowUtils, LateAbsolutePositionInfo, MutableFlowUtils, OpaqueFlow}; use flow::{ImmutableFlowUtils, LateAbsolutePositionInfo, MutableFlowUtils, OpaqueFlow};
use flow::IS_ABSOLUTELY_POSITIONED; use flow::IS_ABSOLUTELY_POSITIONED;
use flow_list::FlowList; use flow_list::FlowList;
use flow_ref::FlowRef;
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow}; use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow};
use fragment::SpecificFragmentInfo; use fragment::SpecificFragmentInfo;
use gfx::display_list::{ClippingRegion, StackingContext}; use gfx::display_list::{ClippingRegion, StackingContext};
@ -791,7 +790,7 @@ impl BlockFlow {
layout_context: &'a LayoutContext<'a>, layout_context: &'a LayoutContext<'a>,
mut fragmentation_context: Option<FragmentationContext>, mut fragmentation_context: Option<FragmentationContext>,
margins_may_collapse: MarginsMayCollapseFlag) margins_may_collapse: MarginsMayCollapseFlag)
-> Option<FlowRef> { -> Option<Arc<Flow>> {
let _scope = layout_debug_scope!("assign_block_size_block_base {:x}", let _scope = layout_debug_scope!("assign_block_size_block_base {:x}",
self.base.debug_id()); self.base.debug_id());
@ -1101,9 +1100,9 @@ impl BlockFlow {
} else { } else {
let mut children = self.base.children.split_off(i); let mut children = self.base.children.split_off(i);
if let Some(child) = child_remaining { if let Some(child) = child_remaining {
children.push_front(child); children.push_front_arc(child);
} }
Some(Arc::new(self.clone_with_children(children)) as FlowRef) Some(Arc::new(self.clone_with_children(children)) as Arc<Flow>)
} }
}) })
} }
@ -1898,7 +1897,7 @@ impl Flow for BlockFlow {
fn fragment(&mut self, layout_context: &LayoutContext, fn fragment(&mut self, layout_context: &LayoutContext,
fragmentation_context: Option<FragmentationContext>) fragmentation_context: Option<FragmentationContext>)
-> Option<FlowRef> { -> Option<Arc<Flow>> {
if self.is_replaced_content() { if self.is_replaced_content() {
let _scope = layout_debug_scope!("assign_replaced_block_size_if_necessary {:x}", let _scope = layout_debug_scope!("assign_replaced_block_size_if_necessary {:x}",
self.base.debug_id()); self.base.debug_id());

Просмотреть файл

@ -22,7 +22,7 @@ use floats::FloatKind;
use flow::{self, AbsoluteDescendants, Flow, FlowClass, ImmutableFlowUtils}; use flow::{self, AbsoluteDescendants, Flow, FlowClass, ImmutableFlowUtils};
use flow::{CAN_BE_FRAGMENTED, IS_ABSOLUTELY_POSITIONED, MARGINS_CANNOT_COLLAPSE}; use flow::{CAN_BE_FRAGMENTED, IS_ABSOLUTELY_POSITIONED, MARGINS_CANNOT_COLLAPSE};
use flow::{MutableFlowUtils, MutableOwnedFlowUtils}; use flow::{MutableFlowUtils, MutableOwnedFlowUtils};
use flow_ref::{self, FlowRef}; use flow_ref::FlowRef;
use fragment::{CanvasFragmentInfo, ImageFragmentInfo, InlineAbsoluteFragmentInfo, SvgFragmentInfo}; use fragment::{CanvasFragmentInfo, ImageFragmentInfo, InlineAbsoluteFragmentInfo, SvgFragmentInfo};
use fragment::{Fragment, GeneratedContentInfo, IframeFragmentInfo}; use fragment::{Fragment, GeneratedContentInfo, IframeFragmentInfo};
use fragment::{InlineAbsoluteHypotheticalFragmentInfo, TableColumnFragmentInfo}; use fragment::{InlineAbsoluteHypotheticalFragmentInfo, TableColumnFragmentInfo};
@ -397,9 +397,9 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
let scanned_fragments = let scanned_fragments =
TextRunScanner::new().scan_for_runs(&mut self.layout_context.font_context(), TextRunScanner::new().scan_for_runs(&mut self.layout_context.font_context(),
fragments.fragments); fragments.fragments);
let mut inline_flow_ref: FlowRef = let mut inline_flow_ref =
Arc::new(InlineFlow::from_fragments(scanned_fragments, FlowRef::new(Arc::new(InlineFlow::from_fragments(scanned_fragments,
node.style(self.style_context()).writing_mode)); node.style(self.style_context()).writing_mode)));
// Add all the inline-block fragments as children of the inline flow. // Add all the inline-block fragments as children of the inline flow.
for inline_block_flow in &inline_block_flows { for inline_block_flow in &inline_block_flows {
@ -423,7 +423,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
{ {
// FIXME(#6503): Use Arc::get_mut().unwrap() here. // FIXME(#6503): Use Arc::get_mut().unwrap() here.
let inline_flow = flow_ref::deref_mut(&mut inline_flow_ref).as_mut_inline(); let inline_flow = FlowRef::deref_mut(&mut inline_flow_ref).as_mut_inline();
inline_flow.minimum_line_metrics = inline_flow.minimum_line_metrics =
inline_flow.minimum_line_metrics(&mut self.layout_context.font_context(), inline_flow.minimum_line_metrics(&mut self.layout_context.font_context(),
&node.style(self.style_context())) &node.style(self.style_context()))
@ -697,8 +697,8 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
} }
let fragment = self.build_fragment_for_block(node); let fragment = self.build_fragment_for_block(node);
let flow: FlowRef = let flow =
Arc::new(BlockFlow::from_fragment_and_float_kind(fragment, float_kind)); FlowRef::new(Arc::new(BlockFlow::from_fragment_and_float_kind(fragment, float_kind)));
self.build_flow_for_block_like(flow, node) self.build_flow_for_block_like(flow, node)
} }
@ -1023,10 +1023,10 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
float_kind: Option<FloatKind>) float_kind: Option<FloatKind>)
-> ConstructionResult { -> ConstructionResult {
let fragment = Fragment::new(node, SpecificFragmentInfo::Multicol, self.layout_context); let fragment = Fragment::new(node, SpecificFragmentInfo::Multicol, self.layout_context);
let mut flow: FlowRef = Arc::new(MulticolFlow::from_fragment(fragment, float_kind)); let mut flow = FlowRef::new(Arc::new(MulticolFlow::from_fragment(fragment, float_kind)));
let column_fragment = Fragment::new(node, SpecificFragmentInfo::MulticolColumn, self.layout_context); let column_fragment = Fragment::new(node, SpecificFragmentInfo::MulticolColumn, self.layout_context);
let column_flow = Arc::new(MulticolColumnFlow::from_fragment(column_fragment)); let column_flow = FlowRef::new(Arc::new(MulticolColumnFlow::from_fragment(column_fragment)));
// First populate the column flow with its children. // First populate the column flow with its children.
let construction_result = self.build_flow_for_block_like(column_flow, node); let construction_result = self.build_flow_for_block_like(column_flow, node);
@ -1078,12 +1078,12 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
node.restyle_damage(), node.restyle_damage(),
SpecificFragmentInfo::TableWrapper); SpecificFragmentInfo::TableWrapper);
let wrapper_float_kind = FloatKind::from_property(float_value); let wrapper_float_kind = FloatKind::from_property(float_value);
let mut wrapper_flow: FlowRef = let mut wrapper_flow =
Arc::new(TableWrapperFlow::from_fragment_and_float_kind(wrapper_fragment, FlowRef::new(Arc::new(TableWrapperFlow::from_fragment_and_float_kind(wrapper_fragment,
wrapper_float_kind)); wrapper_float_kind)));
let table_fragment = Fragment::new(node, SpecificFragmentInfo::Table, self.layout_context); let table_fragment = Fragment::new(node, SpecificFragmentInfo::Table, self.layout_context);
let table_flow = Arc::new(TableFlow::from_fragment(table_fragment)); let table_flow = FlowRef::new(Arc::new(TableFlow::from_fragment(table_fragment)));
// First populate the table flow with its children. // First populate the table flow with its children.
let construction_result = self.build_flow_for_block_like(table_flow, node); let construction_result = self.build_flow_for_block_like(table_flow, node);
@ -1134,7 +1134,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
/// with possibly other `BlockFlow`s or `InlineFlow`s underneath it. /// with possibly other `BlockFlow`s or `InlineFlow`s underneath it.
fn build_flow_for_table_caption(&mut self, node: &ConcreteThreadSafeLayoutNode) -> ConstructionResult { fn build_flow_for_table_caption(&mut self, node: &ConcreteThreadSafeLayoutNode) -> ConstructionResult {
let fragment = self.build_fragment_for_block(node); let fragment = self.build_fragment_for_block(node);
let flow = Arc::new(TableCaptionFlow::from_fragment(fragment)); let flow = FlowRef::new(Arc::new(TableCaptionFlow::from_fragment(fragment)));
self.build_flow_for_block_like(flow, node) self.build_flow_for_block_like(flow, node)
} }
@ -1143,7 +1143,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
fn build_flow_for_table_rowgroup(&mut self, node: &ConcreteThreadSafeLayoutNode) fn build_flow_for_table_rowgroup(&mut self, node: &ConcreteThreadSafeLayoutNode)
-> ConstructionResult { -> ConstructionResult {
let fragment = Fragment::new(node, SpecificFragmentInfo::TableRow, self.layout_context); let fragment = Fragment::new(node, SpecificFragmentInfo::TableRow, self.layout_context);
let flow = Arc::new(TableRowGroupFlow::from_fragment(fragment)); let flow = FlowRef::new(Arc::new(TableRowGroupFlow::from_fragment(fragment)));
self.build_flow_for_block_like(flow, node) self.build_flow_for_block_like(flow, node)
} }
@ -1151,7 +1151,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
/// possibly other `TableCellFlow`s underneath it. /// possibly other `TableCellFlow`s underneath it.
fn build_flow_for_table_row(&mut self, node: &ConcreteThreadSafeLayoutNode) -> ConstructionResult { fn build_flow_for_table_row(&mut self, node: &ConcreteThreadSafeLayoutNode) -> ConstructionResult {
let fragment = Fragment::new(node, SpecificFragmentInfo::TableRow, self.layout_context); let fragment = Fragment::new(node, SpecificFragmentInfo::TableRow, self.layout_context);
let flow = Arc::new(TableRowFlow::from_fragment(fragment)); let flow = FlowRef::new(Arc::new(TableRowFlow::from_fragment(fragment)));
self.build_flow_for_block_like(flow, node) self.build_flow_for_block_like(flow, node)
} }
@ -1171,8 +1171,8 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
position == position::T::fixed position == position::T::fixed
}); });
let flow = Arc::new( let flow = FlowRef::new(Arc::new(
TableCellFlow::from_node_fragment_and_visibility_flag(node, fragment, !hide)); TableCellFlow::from_node_fragment_and_visibility_flag(node, fragment, !hide)));
self.build_flow_for_block_like(flow, node) self.build_flow_for_block_like(flow, node)
} }
@ -1236,7 +1236,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
} }
}; };
self.build_flow_for_block_starting_with_fragments(flow, node, initial_fragments) self.build_flow_for_block_starting_with_fragments(FlowRef::new(flow), node, initial_fragments)
} }
/// Creates a fragment for a node with `display: table-column`. /// Creates a fragment for a node with `display: table-column`.
@ -1276,7 +1276,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
let specific = SpecificFragmentInfo::TableColumn(TableColumnFragmentInfo::new(node)); let specific = SpecificFragmentInfo::TableColumn(TableColumnFragmentInfo::new(node));
col_fragments.push(Fragment::new(node, specific, self.layout_context)); col_fragments.push(Fragment::new(node, specific, self.layout_context));
} }
let mut flow: FlowRef = Arc::new(TableColGroupFlow::from_fragments(fragment, col_fragments)); let mut flow = FlowRef::new(Arc::new(TableColGroupFlow::from_fragments(fragment, col_fragments)));
flow.finish(); flow.finish();
ConstructionResult::Flow(flow, AbsoluteDescendants::new()) ConstructionResult::Flow(flow, AbsoluteDescendants::new())
@ -1288,7 +1288,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
float_kind: Option<FloatKind>) float_kind: Option<FloatKind>)
-> ConstructionResult { -> ConstructionResult {
let fragment = self.build_fragment_for_block(node); let fragment = self.build_fragment_for_block(node);
let flow = Arc::new(FlexFlow::from_fragment(fragment, float_kind)); let flow = FlowRef::new(Arc::new(FlexFlow::from_fragment(fragment, float_kind)));
self.build_flow_for_block_like(flow, node) self.build_flow_for_block_like(flow, node)
} }
@ -1345,7 +1345,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
return false return false
} }
let flow = flow_ref::deref_mut(flow); let flow = FlowRef::deref_mut(flow);
flow::mut_base(flow).restyle_damage.insert(damage); 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
@ -1370,21 +1370,21 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
match fragment.specific { match fragment.specific {
SpecificFragmentInfo::InlineBlock(ref mut inline_block_fragment) => { SpecificFragmentInfo::InlineBlock(ref mut inline_block_fragment) => {
let flow_ref = flow_ref::deref_mut(&mut inline_block_fragment.flow_ref); let flow_ref = FlowRef::deref_mut(&mut inline_block_fragment.flow_ref);
flow::mut_base(flow_ref).restyle_damage.insert(damage); flow::mut_base(flow_ref).restyle_damage.insert(damage);
// FIXME(pcwalton): Fragment restyle damage too? // FIXME(pcwalton): Fragment restyle damage too?
flow_ref.repair_style_and_bubble_inline_sizes(&style); flow_ref.repair_style_and_bubble_inline_sizes(&style);
} }
SpecificFragmentInfo::InlineAbsoluteHypothetical( SpecificFragmentInfo::InlineAbsoluteHypothetical(
ref mut inline_absolute_hypothetical_fragment) => { ref mut inline_absolute_hypothetical_fragment) => {
let flow_ref = flow_ref::deref_mut( let flow_ref = FlowRef::deref_mut(
&mut inline_absolute_hypothetical_fragment.flow_ref); &mut inline_absolute_hypothetical_fragment.flow_ref);
flow::mut_base(flow_ref).restyle_damage.insert(damage); flow::mut_base(flow_ref).restyle_damage.insert(damage);
// FIXME(pcwalton): Fragment restyle damage too? // FIXME(pcwalton): Fragment restyle damage too?
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) => {
let flow_ref = flow_ref::deref_mut( let flow_ref = FlowRef::deref_mut(
&mut inline_absolute_fragment.flow_ref); &mut inline_absolute_fragment.flow_ref);
flow::mut_base(flow_ref).restyle_damage.insert(damage); flow::mut_base(flow_ref).restyle_damage.insert(damage);
// FIXME(pcwalton): Fragment restyle damage too? // FIXME(pcwalton): Fragment restyle damage too?
@ -1631,7 +1631,7 @@ impl<ConcreteThreadSafeLayoutNode> NodeUtils for ConcreteThreadSafeLayoutNode
fn set_flow_construction_result(self, mut result: ConstructionResult) { fn set_flow_construction_result(self, mut result: ConstructionResult) {
if self.can_be_fragmented() { if self.can_be_fragmented() {
if let ConstructionResult::Flow(ref mut flow, _) = result { if let ConstructionResult::Flow(ref mut flow, _) = result {
flow::mut_base(flow_ref::deref_mut(flow)).flags.insert(CAN_BE_FRAGMENTED); flow::mut_base(FlowRef::deref_mut(flow)).flags.insert(CAN_BE_FRAGMENTED);
} }
} }
@ -1703,11 +1703,11 @@ 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.
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(flow_ref::deref_mut(&mut new_child)); let kid_base = flow::mut_base(FlowRef::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(flow_ref::deref_mut(self)); let base = flow::mut_base(FlowRef::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);
} }
@ -1720,8 +1720,8 @@ impl FlowConstructionUtils for FlowRef {
/// properly computed. (This is not, however, a memory safety problem.) /// properly computed. (This is not, however, a memory safety problem.)
fn finish(&mut self) { fn finish(&mut self) {
if !opts::get().bubble_inline_sizes_separately { if !opts::get().bubble_inline_sizes_separately {
flow_ref::deref_mut(self).bubble_inline_sizes(); FlowRef::deref_mut(self).bubble_inline_sizes();
flow::mut_base(flow_ref::deref_mut(self)).restyle_damage.remove(BUBBLE_ISIZES); flow::mut_base(FlowRef::deref_mut(self)).restyle_damage.remove(BUBBLE_ISIZES);
} }
} }
} }
@ -1921,14 +1921,14 @@ impl Legalizer {
} }
(FlowClass::Flex, FlowClass::Inline) => { (FlowClass::Flex, FlowClass::Inline) => {
flow::mut_base(flow_ref::deref_mut(child)).flags.insert(MARGINS_CANNOT_COLLAPSE); flow::mut_base(FlowRef::deref_mut(child)).flags.insert(MARGINS_CANNOT_COLLAPSE);
let mut block_wrapper = let mut block_wrapper =
Legalizer::create_anonymous_flow(stylist, Legalizer::create_anonymous_flow(stylist,
parent, parent,
&[PseudoElement::ServoAnonymousBlock], &[PseudoElement::ServoAnonymousBlock],
SpecificFragmentInfo::Generic, SpecificFragmentInfo::Generic,
BlockFlow::from_fragment); BlockFlow::from_fragment);
flow::mut_base(flow_ref::deref_mut(&mut flow::mut_base(FlowRef::deref_mut(&mut
block_wrapper)).flags block_wrapper)).flags
.insert(MARGINS_CANNOT_COLLAPSE); .insert(MARGINS_CANNOT_COLLAPSE);
block_wrapper.add_new_child((*child).clone()); block_wrapper.add_new_child((*child).clone());
@ -1938,7 +1938,7 @@ impl Legalizer {
} }
(FlowClass::Flex, _) => { (FlowClass::Flex, _) => {
flow::mut_base(flow_ref::deref_mut(child)).flags.insert(MARGINS_CANNOT_COLLAPSE); flow::mut_base(FlowRef::deref_mut(child)).flags.insert(MARGINS_CANNOT_COLLAPSE);
parent.add_new_child((*child).clone()); parent.add_new_child((*child).clone());
true true
} }
@ -2030,7 +2030,7 @@ impl Legalizer {
let fragment = reference_block.fragment let fragment = reference_block.fragment
.create_similar_anonymous_fragment(new_style, .create_similar_anonymous_fragment(new_style,
specific_fragment_info); specific_fragment_info);
Arc::new(constructor(fragment)) FlowRef::new(Arc::new(constructor(fragment)))
} }
} }

Просмотреть файл

@ -18,7 +18,7 @@ use context::SharedLayoutContext;
use euclid::{Matrix4D, Point2D, Radians, Rect, SideOffsets2D, Size2D}; use euclid::{Matrix4D, Point2D, Radians, Rect, SideOffsets2D, Size2D};
use flex::FlexFlow; use flex::FlexFlow;
use flow::{BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED}; use flow::{BaseFlow, Flow, IS_ABSOLUTELY_POSITIONED};
use flow_ref; use flow_ref::FlowRef;
use fragment::{CoordinateSystem, Fragment, ImageFragmentInfo, ScannedTextFragmentInfo}; use fragment::{CoordinateSystem, Fragment, ImageFragmentInfo, ScannedTextFragmentInfo};
use fragment::SpecificFragmentInfo; use fragment::SpecificFragmentInfo;
use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDisplayItem}; use gfx::display_list::{BLUR_INFLATION_FACTOR, BaseDisplayItem, BorderDisplayItem};
@ -1994,11 +1994,11 @@ impl InlineFlowDisplayListBuilding for InlineFlow {
for mut fragment in self.fragments.fragments.iter_mut() { for mut fragment in self.fragments.fragments.iter_mut() {
match fragment.specific { match fragment.specific {
SpecificFragmentInfo::InlineBlock(ref mut block_flow) => { SpecificFragmentInfo::InlineBlock(ref mut block_flow) => {
let block_flow = flow_ref::deref_mut(&mut block_flow.flow_ref); let block_flow = FlowRef::deref_mut(&mut block_flow.flow_ref);
block_flow.collect_stacking_contexts(parent, parent_scroll_root_id); block_flow.collect_stacking_contexts(parent, parent_scroll_root_id);
} }
SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut block_flow) => { SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut block_flow) => {
let block_flow = flow_ref::deref_mut(&mut block_flow.flow_ref); let block_flow = FlowRef::deref_mut(&mut block_flow.flow_ref);
block_flow.collect_stacking_contexts(parent, parent_scroll_root_id); block_flow.collect_stacking_contexts(parent, parent_scroll_root_id);
} }
_ if fragment.establishes_stacking_context() => { _ if fragment.establishes_stacking_context() => {

Просмотреть файл

@ -32,7 +32,7 @@ use display_list_builder::DisplayListBuildState;
use euclid::{Point2D, Size2D}; use euclid::{Point2D, Size2D};
use floats::{Floats, SpeculatedFloatPlacement}; use floats::{Floats, SpeculatedFloatPlacement};
use flow_list::{FlowList, MutFlowListIterator}; use flow_list::{FlowList, MutFlowListIterator};
use flow_ref::{self, FlowRef, WeakFlowRef}; use flow_ref::{FlowRef, WeakFlowRef};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx::display_list::{ClippingRegion, StackingContext}; use gfx::display_list::{ClippingRegion, StackingContext};
use gfx_traits::{ScrollRootId, StackingContextId}; use gfx_traits::{ScrollRootId, StackingContextId};
@ -212,7 +212,7 @@ pub trait Flow: fmt::Debug + Sync + Send + 'static {
fn fragment(&mut self, fn fragment(&mut self,
layout_context: &LayoutContext, layout_context: &LayoutContext,
_fragmentation_context: Option<FragmentationContext>) _fragmentation_context: Option<FragmentationContext>)
-> Option<FlowRef> { -> Option<Arc<Flow>> {
fn recursive_assign_block_size<F: ?Sized + Flow>(flow: &mut F, ctx: &LayoutContext) { fn recursive_assign_block_size<F: ?Sized + Flow>(flow: &mut F, ctx: &LayoutContext) {
for child in mut_base(flow).children.iter_mut() { for child in mut_base(flow).children.iter_mut() {
recursive_assign_block_size(child, ctx) recursive_assign_block_size(child, ctx)
@ -791,7 +791,7 @@ pub struct AbsoluteDescendantIter<'a> {
impl<'a> Iterator for AbsoluteDescendantIter<'a> { impl<'a> Iterator for AbsoluteDescendantIter<'a> {
type Item = &'a mut Flow; type Item = &'a mut Flow;
fn next(&mut self) -> Option<&'a mut Flow> { fn next(&mut self) -> Option<&'a mut Flow> {
self.iter.next().map(|info| flow_ref::deref_mut(&mut info.flow)) self.iter.next().map(|info| FlowRef::deref_mut(&mut info.flow))
} }
} }
@ -1403,11 +1403,11 @@ impl MutableOwnedFlowUtils for FlowRef {
/// construction is allowed to possess. /// construction is allowed to possess.
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(flow_ref::deref_mut(self)); let base = mut_base(FlowRef::deref_mut(self));
base.abs_descendants = abs_descendants; base.abs_descendants = abs_descendants;
for descendant_link in base.abs_descendants.descendant_links.iter_mut() { for descendant_link in base.abs_descendants.descendant_links.iter_mut() {
debug_assert!(!descendant_link.has_reached_containing_block); debug_assert!(!descendant_link.has_reached_containing_block);
let descendant_base = mut_base(flow_ref::deref_mut(&mut descendant_link.flow)); let descendant_base = mut_base(FlowRef::deref_mut(&mut descendant_link.flow));
descendant_base.absolute_cb.set(this.clone()); descendant_base.absolute_cb.set(this.clone());
} }
} }
@ -1433,7 +1433,7 @@ impl MutableOwnedFlowUtils for FlowRef {
}); });
let this = self.clone(); let this = self.clone();
let base = mut_base(flow_ref::deref_mut(self)); let base = mut_base(FlowRef::deref_mut(self));
base.abs_descendants = applicable_absolute_descendants; base.abs_descendants = applicable_absolute_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);
@ -1464,7 +1464,7 @@ impl ContainingBlockLink {
} }
fn set(&mut self, link: FlowRef) { fn set(&mut self, link: FlowRef) {
self.link = Some(Arc::downgrade(&link)) self.link = Some(FlowRef::downgrade(&link))
} }
#[inline] #[inline]

Просмотреть файл

@ -3,8 +3,9 @@
* 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::{self, FlowRef}; use flow_ref::FlowRef;
use std::collections::{LinkedList, linked_list}; use std::collections::{LinkedList, linked_list};
use std::sync::Arc;
/// This needs to be reworked now that we have dynamically-sized types in Rust. /// This needs to be reworked now that we have dynamically-sized types in Rust.
/// Until then, it's just a wrapper around LinkedList. /// Until then, it's just a wrapper around LinkedList.
@ -31,6 +32,10 @@ impl FlowList {
self.flows.push_back(new_tail); self.flows.push_back(new_tail);
} }
pub fn push_back_arc(&mut self, new_head: Arc<Flow>) {
self.flows.push_back(FlowRef::new(new_head));
}
pub fn back(&self) -> Option<&Flow> { pub fn back(&self) -> Option<&Flow> {
self.flows.back().map(|x| &**x) self.flows.back().map(|x| &**x)
} }
@ -42,8 +47,12 @@ impl FlowList {
self.flows.push_front(new_head); self.flows.push_front(new_head);
} }
pub fn pop_front(&mut self) -> Option<FlowRef> { pub fn push_front_arc(&mut self, new_head: Arc<Flow>) {
self.flows.pop_front() self.flows.push_front(FlowRef::new(new_head));
}
pub fn pop_front_arc(&mut self) -> Option<Arc<Flow>> {
self.flows.pop_front().map(FlowRef::into_arc)
} }
pub fn front(&self) -> Option<&Flow> { pub fn front(&self) -> Option<&Flow> {
@ -114,7 +123,7 @@ impl FlowList {
impl<'a> DoubleEndedIterator for MutFlowListIterator<'a> { impl<'a> DoubleEndedIterator for MutFlowListIterator<'a> {
fn next_back(&mut self) -> Option<&'a mut Flow> { fn next_back(&mut self) -> Option<&'a mut Flow> {
self.it.next_back().map(flow_ref::deref_mut) self.it.next_back().map(FlowRef::deref_mut)
} }
} }
@ -122,7 +131,7 @@ impl<'a> Iterator for MutFlowListIterator<'a> {
type Item = &'a mut Flow; type Item = &'a mut Flow;
#[inline] #[inline]
fn next(&mut self) -> Option<&'a mut Flow> { fn next(&mut self) -> Option<&'a mut Flow> {
self.it.next().map(flow_ref::deref_mut) self.it.next().map(FlowRef::deref_mut)
} }
#[inline] #[inline]
@ -146,6 +155,6 @@ impl<'a> FlowListRandomAccessMut<'a> {
Some(next_flow) => self.cache.push((*next_flow).clone()), Some(next_flow) => self.cache.push((*next_flow).clone()),
} }
} }
flow_ref::deref_mut(&mut self.cache[index]) FlowRef::deref_mut(&mut self.cache[index])
} }
} }

Просмотреть файл

@ -10,19 +10,56 @@
use flow::Flow; use flow::Flow;
use std::ops::Deref;
use std::sync::{Arc, Weak}; use std::sync::{Arc, Weak};
pub type FlowRef = Arc<Flow>; #[derive(Clone,Debug)]
pub type WeakFlowRef = Weak<Flow>; pub struct FlowRef(Arc<Flow>);
/// WARNING: This should only be used when there is no aliasing: impl Deref for FlowRef {
/// when the traversal ensures that no other threads accesses the same flow at the same time. type Target = Flow;
/// See https://github.com/servo/servo/issues/6503 fn deref(&self) -> &Flow {
/// Use Arc::get_mut instead when possible (e.g. on an Arc that was just created). self.0.deref()
#[allow(unsafe_code)] }
pub fn deref_mut<'a>(r: &'a mut FlowRef) -> &'a mut Flow { }
let ptr: *const Flow = &**r;
unsafe { impl FlowRef {
&mut *(ptr as *mut Flow) /// `FlowRef`s can only be made available to the traversal code.
/// See https://github.com/servo/servo/issues/14014 for more details.
pub fn new(mut r: Arc<Flow>) -> Self {
// This assertion checks that this `FlowRef` does not alias normal `Arc`s.
// If that happens, we're in trouble.
assert!(Arc::get_mut(&mut r).is_some());
FlowRef(r)
}
pub fn get_mut(this: &mut FlowRef) -> Option<&mut Flow> {
Arc::get_mut(&mut this.0)
}
pub fn downgrade(this: &FlowRef) -> WeakFlowRef {
WeakFlowRef(Arc::downgrade(&this.0))
}
pub fn into_arc(mut this: FlowRef) -> Arc<Flow> {
// This assertion checks that this `FlowRef` does not alias normal `Arc`s.
// If that happens, we're in trouble.
assert!(FlowRef::get_mut(&mut this).is_some());
this.0
}
/// WARNING: This should only be used when there is no aliasing:
/// when the traversal ensures that no other threads accesses the same flow at the same time.
/// See https://github.com/servo/servo/issues/6503
/// Use Arc::get_mut instead when possible (e.g. on an Arc that was just created).
#[allow(unsafe_code)]
pub fn deref_mut(this: &mut FlowRef) -> &mut Flow {
let ptr: *const Flow = &*this.0;
unsafe { &mut *(ptr as *mut Flow) }
}
}
#[derive(Clone,Debug)]
pub struct WeakFlowRef(Weak<Flow>);
impl WeakFlowRef {
pub fn upgrade(&self) -> Option<FlowRef> {
self.0.upgrade().map(FlowRef)
} }
} }

Просмотреть файл

@ -12,7 +12,7 @@ use context::{LayoutContext, SharedLayoutContext};
use euclid::{Point2D, Rect, Size2D}; use euclid::{Point2D, Rect, Size2D};
use floats::ClearType; use floats::ClearType;
use flow::{self, ImmutableFlowUtils}; use flow::{self, ImmutableFlowUtils};
use flow_ref::{self, FlowRef}; use flow_ref::FlowRef;
use gfx; use gfx;
use gfx::display_list::{BLUR_INFLATION_FACTOR, OpaqueNode}; use gfx::display_list::{BLUR_INFLATION_FACTOR, OpaqueNode};
use gfx::text::glyph::ByteIndex; use gfx::text::glyph::ByteIndex;
@ -1985,7 +1985,7 @@ impl Fragment {
match self.specific { match self.specific {
SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => { SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => {
let block_flow = flow_ref::deref_mut(&mut info.flow_ref).as_mut_block(); let block_flow = FlowRef::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;
@ -1993,7 +1993,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 = flow_ref::deref_mut(&mut info.flow_ref).as_mut_block(); let block_flow = FlowRef::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);
@ -2001,7 +2001,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 = flow_ref::deref_mut(&mut info.flow_ref).as_mut_block(); let block_flow = FlowRef::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);
@ -2133,18 +2133,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 = flow_ref::deref_mut(&mut info.flow_ref).as_block(); let block_flow = FlowRef::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 = flow_ref::deref_mut(&mut info.flow_ref).as_block(); let block_flow = FlowRef::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 = flow_ref::deref_mut(&mut info.flow_ref).as_block(); let block_flow = FlowRef::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()
} }
@ -2481,7 +2481,7 @@ impl Fragment {
/// block size assignment. /// block size assignment.
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 = flow_ref::deref_mut(&mut inline_block_info.flow_ref).as_block(); let block_flow = FlowRef::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() +
@ -2492,7 +2492,7 @@ impl Fragment {
pub fn update_late_computed_inline_position_if_necessary(&mut self) { pub fn update_late_computed_inline_position_if_necessary(&mut self) {
if let SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) = self.specific { if let SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) = self.specific {
let position = self.border_box.start.i; let position = self.border_box.start.i;
flow_ref::deref_mut(&mut info.flow_ref) FlowRef::deref_mut(&mut info.flow_ref)
.update_late_computed_inline_position_if_necessary(position) .update_late_computed_inline_position_if_necessary(position)
} }
} }
@ -2500,7 +2500,7 @@ impl Fragment {
pub fn update_late_computed_block_position_if_necessary(&mut self) { pub fn update_late_computed_block_position_if_necessary(&mut self) {
if let SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) = self.specific { if let SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) = self.specific {
let position = self.border_box.start.b; let position = self.border_box.start.b;
flow_ref::deref_mut(&mut info.flow_ref) FlowRef::deref_mut(&mut info.flow_ref)
.update_late_computed_block_position_if_necessary(position) .update_late_computed_block_position_if_necessary(position)
} }
} }

Просмотреть файл

@ -13,7 +13,7 @@ use floats::{FloatKind, Floats, PlacementInfo};
use flow::{self, BaseFlow, Flow, FlowClass, ForceNonfloatedFlag, IS_ABSOLUTELY_POSITIONED}; use flow::{self, BaseFlow, Flow, FlowClass, ForceNonfloatedFlag, IS_ABSOLUTELY_POSITIONED};
use flow::{CONTAINS_TEXT_OR_REPLACED_FRAGMENTS, EarlyAbsolutePositionInfo, MutableFlowUtils}; use flow::{CONTAINS_TEXT_OR_REPLACED_FRAGMENTS, EarlyAbsolutePositionInfo, MutableFlowUtils};
use flow::OpaqueFlow; use flow::OpaqueFlow;
use flow_ref; use flow_ref::FlowRef;
use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow}; use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow};
use fragment::SpecificFragmentInfo; use fragment::SpecificFragmentInfo;
use gfx::display_list::{OpaqueNode, StackingContext}; use gfx::display_list::{OpaqueNode, StackingContext};
@ -1468,14 +1468,14 @@ impl Flow for InlineFlow {
self.mutate_fragments(&mut |f: &mut Fragment| { self.mutate_fragments(&mut |f: &mut Fragment| {
match f.specific { match f.specific {
SpecificFragmentInfo::InlineBlock(ref mut info) => { SpecificFragmentInfo::InlineBlock(ref mut info) => {
let block = flow_ref::deref_mut(&mut info.flow_ref); let block = FlowRef::deref_mut(&mut info.flow_ref);
flow::mut_base(block).early_absolute_position_info = EarlyAbsolutePositionInfo { flow::mut_base(block).early_absolute_position_info = EarlyAbsolutePositionInfo {
relative_containing_block_size: containing_block_size, relative_containing_block_size: containing_block_size,
relative_containing_block_mode: writing_mode, relative_containing_block_mode: writing_mode,
}; };
} }
SpecificFragmentInfo::InlineAbsolute(ref mut info) => { SpecificFragmentInfo::InlineAbsolute(ref mut info) => {
let block = flow_ref::deref_mut(&mut info.flow_ref); let block = FlowRef::deref_mut(&mut info.flow_ref);
flow::mut_base(block).early_absolute_position_info = EarlyAbsolutePositionInfo { flow::mut_base(block).early_absolute_position_info = EarlyAbsolutePositionInfo {
relative_containing_block_size: containing_block_size, relative_containing_block_size: containing_block_size,
relative_containing_block_mode: writing_mode, relative_containing_block_mode: writing_mode,
@ -1551,7 +1551,7 @@ 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) => {
let flow = flow_ref::deref_mut(&mut info.flow_ref); let flow = FlowRef::deref_mut(&mut info.flow_ref);
let block_flow = flow.as_mut_block(); let block_flow = flow.as_mut_block();
block_flow.base.late_absolute_position_info = block_flow.base.late_absolute_position_info =
self.base.late_absolute_position_info; self.base.late_absolute_position_info;
@ -1573,7 +1573,7 @@ impl Flow for InlineFlow {
block_flow.base.clip = self.base.clip.clone() block_flow.base.clip = self.base.clip.clone()
} }
SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => { SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut info) => {
let flow = flow_ref::deref_mut(&mut info.flow_ref); let flow = FlowRef::deref_mut(&mut info.flow_ref);
let block_flow = flow.as_mut_block(); let block_flow = flow.as_mut_block();
block_flow.base.late_absolute_position_info = block_flow.base.late_absolute_position_info =
self.base.late_absolute_position_info; self.base.late_absolute_position_info;
@ -1585,7 +1585,7 @@ impl Flow for InlineFlow {
block_flow.base.clip = self.base.clip.clone() block_flow.base.clip = self.base.clip.clone()
} }
SpecificFragmentInfo::InlineAbsolute(ref mut info) => { SpecificFragmentInfo::InlineAbsolute(ref mut info) => {
let flow = flow_ref::deref_mut(&mut info.flow_ref); let flow = FlowRef::deref_mut(&mut info.flow_ref);
let block_flow = flow.as_mut_block(); let block_flow = flow.as_mut_block();
block_flow.base.late_absolute_position_info = block_flow.base.late_absolute_position_info =
self.base.late_absolute_position_info; self.base.late_absolute_position_info;

Просмотреть файл

@ -14,7 +14,6 @@ use euclid::Point2D;
use euclid::Size2D; use euclid::Size2D;
use floats::FloatKind; use floats::FloatKind;
use flow::{Flow, FlowClass, OpaqueFlow, mut_base, FragmentationContext}; use flow::{Flow, FlowClass, OpaqueFlow, mut_base, FragmentationContext};
use flow_ref::{self, FlowRef};
use fragment::{Fragment, FragmentBorderBoxIterator, Overflow}; use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
use gfx::display_list::StackingContext; use gfx::display_list::StackingContext;
use gfx_traits::ScrollRootId; use gfx_traits::ScrollRootId;
@ -148,14 +147,14 @@ impl Flow for MulticolFlow {
// Before layout, everything is in a single "column" // Before layout, everything is in a single "column"
assert!(self.block_flow.base.children.len() == 1); assert!(self.block_flow.base.children.len() == 1);
let mut column = self.block_flow.base.children.pop_front().unwrap(); let mut column = self.block_flow.base.children.pop_front_arc().unwrap();
// Pretend there is no children for this: // Pretend there is no children for this:
self.block_flow.assign_block_size(ctx); self.block_flow.assign_block_size(ctx);
loop { loop {
let remaining = flow_ref::deref_mut(&mut column).fragment(ctx, fragmentation_context); let remaining = Arc::get_mut(&mut column).unwrap().fragment(ctx, fragmentation_context);
self.block_flow.base.children.push_back(column); self.block_flow.base.children.push_back_arc(column);
column = match remaining { column = match remaining {
Some(remaining) => remaining, Some(remaining) => remaining,
None => break None => break
@ -249,7 +248,7 @@ impl Flow for MulticolColumnFlow {
fn fragment(&mut self, layout_context: &LayoutContext, fn fragment(&mut self, layout_context: &LayoutContext,
fragmentation_context: Option<FragmentationContext>) fragmentation_context: Option<FragmentationContext>)
-> Option<FlowRef> { -> Option<Arc<Flow>> {
Flow::fragment(&mut self.block_flow, layout_context, fragmentation_context) Flow::fragment(&mut self.block_flow, layout_context, fragmentation_context)
} }

Просмотреть файл

@ -65,7 +65,7 @@ use layout::construct::ConstructionResult;
use layout::context::{LayoutContext, SharedLayoutContext, heap_size_of_local_context}; use layout::context::{LayoutContext, SharedLayoutContext, heap_size_of_local_context};
use layout::display_list_builder::ToGfxColor; use layout::display_list_builder::ToGfxColor;
use layout::flow::{self, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils}; use layout::flow::{self, Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
use layout::flow_ref::{self, FlowRef}; use layout::flow_ref::FlowRef;
use layout::incremental::{LayoutDamageComputation, REFLOW_ENTIRE_DOCUMENT}; use layout::incremental::{LayoutDamageComputation, REFLOW_ENTIRE_DOCUMENT};
use layout::layout_debug; use layout::layout_debug;
use layout::parallel; use layout::parallel;
@ -594,7 +594,7 @@ impl LayoutThread {
let mut rw_data = possibly_locked_rw_data.lock(); let mut rw_data = possibly_locked_rw_data.lock();
if let Some(mut root_flow) = self.root_flow.clone() { if let Some(mut root_flow) = self.root_flow.clone() {
let flow = flow::mut_base(flow_ref::deref_mut(&mut root_flow)); let flow = flow::mut_base(FlowRef::deref_mut(&mut root_flow));
flow.restyle_damage.insert(REPAINT); flow.restyle_damage.insert(REPAINT);
} }
@ -836,7 +836,7 @@ impl LayoutThread {
_ => return None, _ => return None,
}; };
flow_ref::deref_mut(&mut flow).mark_as_root(); FlowRef::deref_mut(&mut flow).mark_as_root();
Some(flow) Some(flow)
} }
@ -1120,7 +1120,7 @@ impl LayoutThread {
} }
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) {
LayoutThread::reflow_all_nodes(flow_ref::deref_mut(&mut flow)); LayoutThread::reflow_all_nodes(FlowRef::deref_mut(&mut flow));
} }
} }
@ -1197,7 +1197,7 @@ impl LayoutThread {
Some(root_flow) => root_flow, Some(root_flow) => root_flow,
None => return, None => return,
}; };
let root_flow = flow_ref::deref_mut(&mut root_flow); let root_flow = FlowRef::deref_mut(&mut root_flow);
match *query_type { match *query_type {
ReflowQueryType::ContentBoxQuery(node) => { ReflowQueryType::ContentBoxQuery(node) => {
let node = unsafe { ServoLayoutNode::new(&node) }; let node = unsafe { ServoLayoutNode::new(&node) };
@ -1303,7 +1303,7 @@ impl LayoutThread {
self.time_profiler_chan.clone(), self.time_profiler_chan.clone(),
|| { || {
animation::recalc_style_for_animations(&layout_context, animation::recalc_style_for_animations(&layout_context,
flow_ref::deref_mut(&mut root_flow), FlowRef::deref_mut(&mut root_flow),
&animations) &animations)
}); });
} }
@ -1361,10 +1361,10 @@ impl LayoutThread {
|| { || {
// Call `compute_layout_damage` even in non-incremental mode, because it sets flags // Call `compute_layout_damage` even in non-incremental mode, because it sets flags
// that are needed in both incremental and non-incremental traversals. // that are needed in both incremental and non-incremental traversals.
let damage = flow_ref::deref_mut(&mut root_flow).compute_layout_damage(); let damage = FlowRef::deref_mut(&mut root_flow).compute_layout_damage();
if opts::get().nonincremental_layout || damage.contains(REFLOW_ENTIRE_DOCUMENT) { if opts::get().nonincremental_layout || damage.contains(REFLOW_ENTIRE_DOCUMENT) {
flow_ref::deref_mut(&mut root_flow).reflow_entire_document() FlowRef::deref_mut(&mut root_flow).reflow_entire_document()
} }
}); });
@ -1376,13 +1376,13 @@ impl LayoutThread {
profile(time::ProfilerCategory::LayoutGeneratedContent, profile(time::ProfilerCategory::LayoutGeneratedContent,
self.profiler_metadata(), self.profiler_metadata(),
self.time_profiler_chan.clone(), self.time_profiler_chan.clone(),
|| sequential::resolve_generated_content(flow_ref::deref_mut(&mut root_flow), &layout_context)); || sequential::resolve_generated_content(FlowRef::deref_mut(&mut root_flow), &layout_context));
// Guess float placement. // Guess float placement.
profile(time::ProfilerCategory::LayoutFloatPlacementSpeculation, profile(time::ProfilerCategory::LayoutFloatPlacementSpeculation,
self.profiler_metadata(), self.profiler_metadata(),
self.time_profiler_chan.clone(), self.time_profiler_chan.clone(),
|| sequential::guess_float_placement(flow_ref::deref_mut(&mut root_flow))); || sequential::guess_float_placement(FlowRef::deref_mut(&mut root_flow)));
// Perform the primary layout passes over the flow tree to compute the locations of all // Perform the primary layout passes over the flow tree to compute the locations of all
// the boxes. // the boxes.
@ -1395,12 +1395,12 @@ impl LayoutThread {
match self.parallel_traversal { match self.parallel_traversal {
None => { None => {
// Sequential mode. // Sequential mode.
LayoutThread::solve_constraints(flow_ref::deref_mut(&mut root_flow), &layout_context) LayoutThread::solve_constraints(FlowRef::deref_mut(&mut root_flow), &layout_context)
} }
Some(ref mut parallel) => { Some(ref mut parallel) => {
// Parallel mode. // Parallel mode.
LayoutThread::solve_constraints_parallel(parallel, LayoutThread::solve_constraints_parallel(parallel,
flow_ref::deref_mut(&mut root_flow), FlowRef::deref_mut(&mut root_flow),
profiler_metadata, profiler_metadata,
self.time_profiler_chan.clone(), self.time_profiler_chan.clone(),
&*layout_context); &*layout_context);
@ -1415,7 +1415,7 @@ impl LayoutThread {
|| { || {
let layout_context = LayoutContext::new(&*layout_context); let layout_context = LayoutContext::new(&*layout_context);
sequential::store_overflow(&layout_context, sequential::store_overflow(&layout_context,
flow_ref::deref_mut(&mut root_flow) as &mut Flow); FlowRef::deref_mut(&mut root_flow) as &mut Flow);
}); });
self.perform_post_main_layout_passes(data, self.perform_post_main_layout_passes(data,
@ -1437,7 +1437,7 @@ impl LayoutThread {
self.compute_abs_pos_and_build_display_list(data, self.compute_abs_pos_and_build_display_list(data,
query_type, query_type,
document, document,
flow_ref::deref_mut(&mut root_flow), FlowRef::deref_mut(&mut root_flow),
&mut *layout_context, &mut *layout_context,
rw_data); rw_data);
self.first_reflow = false; self.first_reflow = false;