mirror of
https://github.com/servo/servo.git
synced 2025-07-22 23:03:42 +01:00
Make FlowRef
a newtype
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). Fixes #14014
This commit is contained in:
parent
5b4cc9568d
commit
5f320bd2ca
10 changed files with 145 additions and 101 deletions
|
@ -22,7 +22,7 @@ use floats::FloatKind;
|
|||
use flow::{self, AbsoluteDescendants, Flow, FlowClass, ImmutableFlowUtils};
|
||||
use flow::{CAN_BE_FRAGMENTED, IS_ABSOLUTELY_POSITIONED, MARGINS_CANNOT_COLLAPSE};
|
||||
use flow::{MutableFlowUtils, MutableOwnedFlowUtils};
|
||||
use flow_ref::{self, FlowRef};
|
||||
use flow_ref::FlowRef;
|
||||
use fragment::{CanvasFragmentInfo, ImageFragmentInfo, InlineAbsoluteFragmentInfo, SvgFragmentInfo};
|
||||
use fragment::{Fragment, GeneratedContentInfo, IframeFragmentInfo};
|
||||
use fragment::{InlineAbsoluteHypotheticalFragmentInfo, TableColumnFragmentInfo};
|
||||
|
@ -397,9 +397,9 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
|||
let scanned_fragments =
|
||||
TextRunScanner::new().scan_for_runs(&mut self.layout_context.font_context(),
|
||||
fragments.fragments);
|
||||
let mut inline_flow_ref: FlowRef =
|
||||
Arc::new(InlineFlow::from_fragments(scanned_fragments,
|
||||
node.style(self.style_context()).writing_mode));
|
||||
let mut inline_flow_ref =
|
||||
FlowRef::new(Arc::new(InlineFlow::from_fragments(scanned_fragments,
|
||||
node.style(self.style_context()).writing_mode)));
|
||||
|
||||
// Add all the inline-block fragments as children of the inline flow.
|
||||
for inline_block_flow in &inline_block_flows {
|
||||
|
@ -423,7 +423,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
|||
|
||||
{
|
||||
// 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(&mut self.layout_context.font_context(),
|
||||
&node.style(self.style_context()))
|
||||
|
@ -697,8 +697,8 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
|||
}
|
||||
|
||||
let fragment = self.build_fragment_for_block(node);
|
||||
let flow: FlowRef =
|
||||
Arc::new(BlockFlow::from_fragment_and_float_kind(fragment, float_kind));
|
||||
let flow =
|
||||
FlowRef::new(Arc::new(BlockFlow::from_fragment_and_float_kind(fragment, float_kind)));
|
||||
self.build_flow_for_block_like(flow, node)
|
||||
}
|
||||
|
||||
|
@ -1023,10 +1023,10 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
|||
float_kind: Option<FloatKind>)
|
||||
-> ConstructionResult {
|
||||
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_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.
|
||||
let construction_result = self.build_flow_for_block_like(column_flow, node);
|
||||
|
@ -1078,12 +1078,12 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
|||
node.restyle_damage(),
|
||||
SpecificFragmentInfo::TableWrapper);
|
||||
let wrapper_float_kind = FloatKind::from_property(float_value);
|
||||
let mut wrapper_flow: FlowRef =
|
||||
Arc::new(TableWrapperFlow::from_fragment_and_float_kind(wrapper_fragment,
|
||||
wrapper_float_kind));
|
||||
let mut wrapper_flow =
|
||||
FlowRef::new(Arc::new(TableWrapperFlow::from_fragment_and_float_kind(wrapper_fragment,
|
||||
wrapper_float_kind)));
|
||||
|
||||
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.
|
||||
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.
|
||||
fn build_flow_for_table_caption(&mut self, node: &ConcreteThreadSafeLayoutNode) -> ConstructionResult {
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -1143,7 +1143,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
|||
fn build_flow_for_table_rowgroup(&mut self, node: &ConcreteThreadSafeLayoutNode)
|
||||
-> ConstructionResult {
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -1151,7 +1151,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
|||
/// possibly other `TableCellFlow`s underneath it.
|
||||
fn build_flow_for_table_row(&mut self, node: &ConcreteThreadSafeLayoutNode) -> ConstructionResult {
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -1171,8 +1171,8 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
|||
position == position::T::fixed
|
||||
});
|
||||
|
||||
let flow = Arc::new(
|
||||
TableCellFlow::from_node_fragment_and_visibility_flag(node, fragment, !hide));
|
||||
let flow = FlowRef::new(Arc::new(
|
||||
TableCellFlow::from_node_fragment_and_visibility_flag(node, fragment, !hide)));
|
||||
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`.
|
||||
|
@ -1276,7 +1276,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
|||
let specific = SpecificFragmentInfo::TableColumn(TableColumnFragmentInfo::new(node));
|
||||
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();
|
||||
|
||||
ConstructionResult::Flow(flow, AbsoluteDescendants::new())
|
||||
|
@ -1288,7 +1288,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
|||
float_kind: Option<FloatKind>)
|
||||
-> ConstructionResult {
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -1345,7 +1345,7 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
|||
return false
|
||||
}
|
||||
|
||||
let flow = flow_ref::deref_mut(flow);
|
||||
let flow = FlowRef::deref_mut(flow);
|
||||
flow::mut_base(flow).restyle_damage.insert(damage);
|
||||
flow.repair_style_and_bubble_inline_sizes(&style);
|
||||
true
|
||||
|
@ -1370,21 +1370,21 @@ impl<'a, ConcreteThreadSafeLayoutNode: ThreadSafeLayoutNode>
|
|||
|
||||
match fragment.specific {
|
||||
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);
|
||||
// FIXME(pcwalton): Fragment restyle damage too?
|
||||
flow_ref.repair_style_and_bubble_inline_sizes(&style);
|
||||
}
|
||||
SpecificFragmentInfo::InlineAbsoluteHypothetical(
|
||||
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);
|
||||
flow::mut_base(flow_ref).restyle_damage.insert(damage);
|
||||
// FIXME(pcwalton): Fragment restyle damage too?
|
||||
flow_ref.repair_style_and_bubble_inline_sizes(&style);
|
||||
}
|
||||
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);
|
||||
flow::mut_base(flow_ref).restyle_damage.insert(damage);
|
||||
// FIXME(pcwalton): Fragment restyle damage too?
|
||||
|
@ -1631,7 +1631,7 @@ impl<ConcreteThreadSafeLayoutNode> NodeUtils for ConcreteThreadSafeLayoutNode
|
|||
fn set_flow_construction_result(self, mut result: ConstructionResult) {
|
||||
if self.can_be_fragmented() {
|
||||
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.
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
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.)
|
||||
fn finish(&mut self) {
|
||||
if !opts::get().bubble_inline_sizes_separately {
|
||||
flow_ref::deref_mut(self).bubble_inline_sizes();
|
||||
flow::mut_base(flow_ref::deref_mut(self)).restyle_damage.remove(BUBBLE_ISIZES);
|
||||
FlowRef::deref_mut(self).bubble_inline_sizes();
|
||||
flow::mut_base(FlowRef::deref_mut(self)).restyle_damage.remove(BUBBLE_ISIZES);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1921,14 +1921,14 @@ impl Legalizer {
|
|||
}
|
||||
|
||||
(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 =
|
||||
Legalizer::create_anonymous_flow(stylist,
|
||||
parent,
|
||||
&[PseudoElement::ServoAnonymousBlock],
|
||||
SpecificFragmentInfo::Generic,
|
||||
BlockFlow::from_fragment);
|
||||
flow::mut_base(flow_ref::deref_mut(&mut
|
||||
flow::mut_base(FlowRef::deref_mut(&mut
|
||||
block_wrapper)).flags
|
||||
.insert(MARGINS_CANNOT_COLLAPSE);
|
||||
block_wrapper.add_new_child((*child).clone());
|
||||
|
@ -1938,7 +1938,7 @@ impl Legalizer {
|
|||
}
|
||||
|
||||
(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());
|
||||
true
|
||||
}
|
||||
|
@ -2030,7 +2030,7 @@ impl Legalizer {
|
|||
let fragment = reference_block.fragment
|
||||
.create_similar_anonymous_fragment(new_style,
|
||||
specific_fragment_info);
|
||||
Arc::new(constructor(fragment))
|
||||
FlowRef::new(Arc::new(constructor(fragment)))
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue