mirror of
https://github.com/servo/servo.git
synced 2025-08-03 04:30:10 +01:00
Replace FlowRef with Arc<Flow>, now that Arc supports DST.
… and WeakFlowRef with Weak<Flow>.
This commit is contained in:
parent
2d22aa8e7e
commit
649250130b
7 changed files with 62 additions and 276 deletions
|
@ -375,7 +375,7 @@ impl<'a> FlowConstructor<'a> {
|
||||||
style,
|
style,
|
||||||
child_node.restyle_damage(),
|
child_node.restyle_damage(),
|
||||||
SpecificFragmentInfo::TableRow);
|
SpecificFragmentInfo::TableRow);
|
||||||
let mut new_child = FlowRef::new(box TableRowFlow::from_fragment(fragment));
|
let mut new_child: FlowRef = Arc::new(TableRowFlow::from_fragment(fragment));
|
||||||
new_child.add_new_child(child.clone());
|
new_child.add_new_child(child.clone());
|
||||||
child.finish();
|
child.finish();
|
||||||
*child = new_child
|
*child = new_child
|
||||||
|
@ -388,7 +388,7 @@ impl<'a> FlowConstructor<'a> {
|
||||||
style,
|
style,
|
||||||
child_node.restyle_damage(),
|
child_node.restyle_damage(),
|
||||||
SpecificFragmentInfo::Table);
|
SpecificFragmentInfo::Table);
|
||||||
let mut new_child = FlowRef::new(box TableFlow::from_fragment(fragment));
|
let mut new_child: FlowRef = Arc::new(TableFlow::from_fragment(fragment));
|
||||||
new_child.add_new_child(child.clone());
|
new_child.add_new_child(child.clone());
|
||||||
child.finish();
|
child.finish();
|
||||||
*child = new_child
|
*child = new_child
|
||||||
|
@ -402,7 +402,7 @@ impl<'a> FlowConstructor<'a> {
|
||||||
style,
|
style,
|
||||||
child_node.restyle_damage(),
|
child_node.restyle_damage(),
|
||||||
SpecificFragmentInfo::TableWrapper);
|
SpecificFragmentInfo::TableWrapper);
|
||||||
let mut new_child = FlowRef::new(box TableWrapperFlow::from_fragment(fragment, None));
|
let mut new_child: FlowRef = Arc::new(TableWrapperFlow::from_fragment(fragment, None));
|
||||||
new_child.add_new_child(child.clone());
|
new_child.add_new_child(child.clone());
|
||||||
child.finish();
|
child.finish();
|
||||||
*child = new_child
|
*child = new_child
|
||||||
|
@ -457,9 +457,8 @@ impl<'a> FlowConstructor<'a> {
|
||||||
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 =
|
let mut inline_flow_ref: FlowRef = Arc::new(
|
||||||
FlowRef::new(box InlineFlow::from_fragments(scanned_fragments,
|
InlineFlow::from_fragments(scanned_fragments, node.style().writing_mode));
|
||||||
node.style().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 {
|
||||||
|
@ -753,12 +752,12 @@ impl<'a> FlowConstructor<'a> {
|
||||||
fn build_flow_for_block(&mut self, node: &ThreadSafeLayoutNode, float_kind: Option<FloatKind>)
|
fn build_flow_for_block(&mut self, node: &ThreadSafeLayoutNode, float_kind: Option<FloatKind>)
|
||||||
-> ConstructionResult {
|
-> ConstructionResult {
|
||||||
let fragment = self.build_fragment_for_block(node);
|
let fragment = self.build_fragment_for_block(node);
|
||||||
let flow = if node.style().is_multicol() {
|
let flow: FlowRef = if node.style().is_multicol() {
|
||||||
box MulticolFlow::from_fragment(fragment, float_kind) as Box<Flow>
|
Arc::new(MulticolFlow::from_fragment(fragment, float_kind))
|
||||||
} else {
|
} else {
|
||||||
box BlockFlow::from_fragment(fragment, float_kind) as Box<Flow>
|
Arc::new(BlockFlow::from_fragment(fragment, float_kind))
|
||||||
};
|
};
|
||||||
self.build_flow_for_block_like(FlowRef::new(flow), node)
|
self.build_flow_for_block_like(flow, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Bubbles up {ib} splits.
|
/// Bubbles up {ib} splits.
|
||||||
|
@ -1072,13 +1071,11 @@ impl<'a> FlowConstructor<'a> {
|
||||||
fn build_flow_for_table_wrapper(&mut self, node: &ThreadSafeLayoutNode, float_value: float::T)
|
fn build_flow_for_table_wrapper(&mut self, node: &ThreadSafeLayoutNode, float_value: float::T)
|
||||||
-> ConstructionResult {
|
-> ConstructionResult {
|
||||||
let fragment = Fragment::new(node, SpecificFragmentInfo::TableWrapper);
|
let fragment = Fragment::new(node, SpecificFragmentInfo::TableWrapper);
|
||||||
let wrapper_flow =
|
let mut wrapper_flow: FlowRef = Arc::new(
|
||||||
box TableWrapperFlow::from_fragment(fragment, FloatKind::from_property(float_value));
|
TableWrapperFlow::from_fragment(fragment, FloatKind::from_property(float_value)));
|
||||||
let mut wrapper_flow = FlowRef::new(wrapper_flow as Box<Flow>);
|
|
||||||
|
|
||||||
let table_fragment = Fragment::new(node, SpecificFragmentInfo::Table);
|
let table_fragment = Fragment::new(node, SpecificFragmentInfo::Table);
|
||||||
let table_flow = box TableFlow::from_fragment(table_fragment);
|
let table_flow = Arc::new(TableFlow::from_fragment(table_fragment));
|
||||||
let table_flow = FlowRef::new(table_flow as Box<Flow>);
|
|
||||||
|
|
||||||
// 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);
|
||||||
|
@ -1135,8 +1132,8 @@ impl<'a> FlowConstructor<'a> {
|
||||||
/// 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: &ThreadSafeLayoutNode) -> ConstructionResult {
|
fn build_flow_for_table_caption(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
||||||
let fragment = self.build_fragment_for_block(node);
|
let fragment = self.build_fragment_for_block(node);
|
||||||
let flow = box TableCaptionFlow::from_fragment(fragment) as Box<Flow>;
|
let flow = Arc::new(TableCaptionFlow::from_fragment(fragment));
|
||||||
self.build_flow_for_block_like(FlowRef::new(flow), node)
|
self.build_flow_for_block_like(flow, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a flow for a node with `display: table-row-group`. This yields a `TableRowGroupFlow`
|
/// Builds a flow for a node with `display: table-row-group`. This yields a `TableRowGroupFlow`
|
||||||
|
@ -1144,16 +1141,16 @@ impl<'a> FlowConstructor<'a> {
|
||||||
fn build_flow_for_table_rowgroup(&mut self, node: &ThreadSafeLayoutNode)
|
fn build_flow_for_table_rowgroup(&mut self, node: &ThreadSafeLayoutNode)
|
||||||
-> ConstructionResult {
|
-> ConstructionResult {
|
||||||
let fragment = Fragment::new(node, SpecificFragmentInfo::TableRow);
|
let fragment = Fragment::new(node, SpecificFragmentInfo::TableRow);
|
||||||
let flow = box TableRowGroupFlow::from_fragment(fragment) as Box<Flow>;
|
let flow = Arc::new(TableRowGroupFlow::from_fragment(fragment));
|
||||||
self.build_flow_for_block_like(FlowRef::new(flow), node)
|
self.build_flow_for_block_like(flow, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a flow for a node with `display: table-row`. This yields a `TableRowFlow` with
|
/// Builds a flow for a node with `display: table-row`. This yields a `TableRowFlow` with
|
||||||
/// possibly other `TableCellFlow`s underneath it.
|
/// possibly other `TableCellFlow`s underneath it.
|
||||||
fn build_flow_for_table_row(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
fn build_flow_for_table_row(&mut self, node: &ThreadSafeLayoutNode) -> ConstructionResult {
|
||||||
let fragment = Fragment::new(node, SpecificFragmentInfo::TableRow);
|
let fragment = Fragment::new(node, SpecificFragmentInfo::TableRow);
|
||||||
let flow = box TableRowFlow::from_fragment(fragment) as Box<Flow>;
|
let flow = Arc::new(TableRowFlow::from_fragment(fragment));
|
||||||
self.build_flow_for_block_like(FlowRef::new(flow), node)
|
self.build_flow_for_block_like(flow, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a flow for a node with `display: table-cell`. This yields a `TableCellFlow` with
|
/// Builds a flow for a node with `display: table-cell`. This yields a `TableCellFlow` with
|
||||||
|
@ -1172,9 +1169,9 @@ impl<'a> FlowConstructor<'a> {
|
||||||
position == position::T::fixed
|
position == position::T::fixed
|
||||||
});
|
});
|
||||||
|
|
||||||
let flow = box TableCellFlow::from_node_fragment_and_visibility_flag(node, fragment, !hide)
|
let flow = Arc::new(
|
||||||
as Box<Flow>;
|
TableCellFlow::from_node_fragment_and_visibility_flag(node, fragment, !hide));
|
||||||
self.build_flow_for_block_like(FlowRef::new(flow), node)
|
self.build_flow_for_block_like(flow, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Builds a flow for a node with `display: list-item`. This yields a `ListItemFlow` with
|
/// Builds a flow for a node with `display: list-item`. This yields a `ListItemFlow` with
|
||||||
|
@ -1222,21 +1219,19 @@ impl<'a> FlowConstructor<'a> {
|
||||||
let main_fragment = self.build_fragment_for_block(node);
|
let main_fragment = self.build_fragment_for_block(node);
|
||||||
let flow = match node.style().get_list().list_style_position {
|
let flow = match node.style().get_list().list_style_position {
|
||||||
list_style_position::T::outside => {
|
list_style_position::T::outside => {
|
||||||
box ListItemFlow::from_fragments_and_flotation(main_fragment,
|
Arc::new(ListItemFlow::from_fragments_and_flotation(
|
||||||
marker_fragments,
|
main_fragment, marker_fragments, flotation))
|
||||||
flotation)
|
|
||||||
}
|
}
|
||||||
list_style_position::T::inside => {
|
list_style_position::T::inside => {
|
||||||
for marker_fragment in marker_fragments {
|
for marker_fragment in marker_fragments {
|
||||||
initial_fragments.fragments.push_back(marker_fragment)
|
initial_fragments.fragments.push_back(marker_fragment)
|
||||||
}
|
}
|
||||||
box ListItemFlow::from_fragments_and_flotation(main_fragment, vec![], flotation)
|
Arc::new(ListItemFlow::from_fragments_and_flotation(
|
||||||
|
main_fragment, vec![], flotation))
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
self.build_flow_for_block_starting_with_fragments(FlowRef::new(flow as Box<Flow>),
|
self.build_flow_for_block_starting_with_fragments(flow, node, initial_fragments)
|
||||||
node,
|
|
||||||
initial_fragments)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Creates a fragment for a node with `display: table-column`.
|
/// Creates a fragment for a node with `display: table-column`.
|
||||||
|
@ -1277,8 +1272,7 @@ impl<'a> FlowConstructor<'a> {
|
||||||
let specific = SpecificFragmentInfo::TableColumn(TableColumnFragmentInfo::new(node));
|
let specific = SpecificFragmentInfo::TableColumn(TableColumnFragmentInfo::new(node));
|
||||||
col_fragments.push(Fragment::new(node, specific));
|
col_fragments.push(Fragment::new(node, specific));
|
||||||
}
|
}
|
||||||
let flow = box TableColGroupFlow::from_fragments(fragment, col_fragments);
|
let mut flow: FlowRef = Arc::new(TableColGroupFlow::from_fragments(fragment, col_fragments));
|
||||||
let mut flow = FlowRef::new(flow as Box<Flow>);
|
|
||||||
flow.finish();
|
flow.finish();
|
||||||
|
|
||||||
ConstructionResult::Flow(flow, AbsoluteDescendants::new())
|
ConstructionResult::Flow(flow, AbsoluteDescendants::new())
|
||||||
|
|
|
@ -57,7 +57,7 @@ use std::mem;
|
||||||
use std::raw;
|
use std::raw;
|
||||||
use std::slice::IterMut;
|
use std::slice::IterMut;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
use std::sync::atomic::{AtomicUsize, Ordering};
|
use std::sync::atomic::Ordering;
|
||||||
use style::computed_values::{clear, display, empty_cells, float, position, text_align};
|
use style::computed_values::{clear, display, empty_cells, float, position, text_align};
|
||||||
use style::properties::{self, ComputedValues};
|
use style::properties::{self, ComputedValues};
|
||||||
use style::values::computed::LengthOrPercentageOrAuto;
|
use style::values::computed::LengthOrPercentageOrAuto;
|
||||||
|
@ -68,7 +68,7 @@ use util::logical_geometry::{LogicalRect, LogicalSize, WritingMode};
|
||||||
///
|
///
|
||||||
/// Note that virtual methods have a cost; we should not overuse them in Servo. Consider adding
|
/// Note that virtual methods have a cost; we should not overuse them in Servo. Consider adding
|
||||||
/// methods to `ImmutableFlowUtils` or `MutableFlowUtils` before adding more methods here.
|
/// methods to `ImmutableFlowUtils` or `MutableFlowUtils` before adding more methods here.
|
||||||
pub trait Flow: fmt::Debug + Sync {
|
pub trait Flow: fmt::Debug + Sync + Send + 'static {
|
||||||
// RTTI
|
// RTTI
|
||||||
//
|
//
|
||||||
// TODO(pcwalton): Use Rust's RTTI, once that works.
|
// TODO(pcwalton): Use Rust's RTTI, once that works.
|
||||||
|
@ -770,9 +770,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;
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
fn next(&mut self) -> Option<&'a mut (Flow + 'a)> {
|
fn next(&mut self) -> Option<&'a mut Flow> {
|
||||||
self.iter.next().map(|info| unsafe { flow_ref::deref_mut(&mut info.flow) })
|
self.iter.next().map(|info| unsafe { flow_ref::deref_mut(&mut info.flow) })
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -815,13 +815,6 @@ impl AbsolutePositionInfo {
|
||||||
|
|
||||||
/// Data common to all flows.
|
/// Data common to all flows.
|
||||||
pub struct BaseFlow {
|
pub struct BaseFlow {
|
||||||
/// NB: Must be the first element.
|
|
||||||
///
|
|
||||||
/// The necessity of this will disappear once we have dynamically-sized types.
|
|
||||||
strong_ref_count: AtomicUsize,
|
|
||||||
|
|
||||||
weak_ref_count: AtomicUsize,
|
|
||||||
|
|
||||||
pub restyle_damage: RestyleDamage,
|
pub restyle_damage: RestyleDamage,
|
||||||
|
|
||||||
/// The children of this flow.
|
/// The children of this flow.
|
||||||
|
@ -963,15 +956,6 @@ impl Encodable for BaseFlow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for BaseFlow {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
if self.strong_ref_count.load(Ordering::SeqCst) != 0 &&
|
|
||||||
self.weak_ref_count.load(Ordering::SeqCst) != 0 {
|
|
||||||
panic!("Flow destroyed before its ref count hit zero—this is unsafe!")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Whether a base flow should be forced to be nonfloated. This can affect e.g. `TableFlow`, which
|
/// Whether a base flow should be forced to be nonfloated. This can affect e.g. `TableFlow`, which
|
||||||
/// is never floated because the table wrapper flow is the floated one.
|
/// is never floated because the table wrapper flow is the floated one.
|
||||||
#[derive(Clone, PartialEq)]
|
#[derive(Clone, PartialEq)]
|
||||||
|
@ -1039,8 +1023,6 @@ impl BaseFlow {
|
||||||
damage.remove(RECONSTRUCT_FLOW);
|
damage.remove(RECONSTRUCT_FLOW);
|
||||||
|
|
||||||
BaseFlow {
|
BaseFlow {
|
||||||
strong_ref_count: AtomicUsize::new(1),
|
|
||||||
weak_ref_count: AtomicUsize::new(1),
|
|
||||||
restyle_damage: damage,
|
restyle_damage: damage,
|
||||||
children: FlowList::new(),
|
children: FlowList::new(),
|
||||||
intrinsic_inline_sizes: IntrinsicISizes::new(),
|
intrinsic_inline_sizes: IntrinsicISizes::new(),
|
||||||
|
@ -1069,16 +1051,6 @@ impl BaseFlow {
|
||||||
self.children.iter_mut()
|
self.children.iter_mut()
|
||||||
}
|
}
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
|
||||||
pub unsafe fn strong_ref_count<'a>(&'a self) -> &'a AtomicUsize {
|
|
||||||
&self.strong_ref_count
|
|
||||||
}
|
|
||||||
|
|
||||||
#[allow(unsafe_code)]
|
|
||||||
pub unsafe fn weak_ref_count<'a>(&'a self) -> &'a AtomicUsize {
|
|
||||||
&self.weak_ref_count
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn debug_id(&self) -> usize {
|
pub fn debug_id(&self) -> usize {
|
||||||
let p = self as *const _;
|
let p = self as *const _;
|
||||||
p as usize
|
p as usize
|
||||||
|
@ -1115,7 +1087,7 @@ impl BaseFlow {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> ImmutableFlowUtils for &'a (Flow + 'a) {
|
impl<'a> ImmutableFlowUtils for &'a Flow {
|
||||||
/// Returns true if this flow is a block flow or subclass thereof.
|
/// Returns true if this flow is a block flow or subclass thereof.
|
||||||
fn is_block_like(self) -> bool {
|
fn is_block_like(self) -> bool {
|
||||||
match self.class() {
|
match self.class() {
|
||||||
|
@ -1213,7 +1185,7 @@ impl<'a> ImmutableFlowUtils for &'a (Flow + 'a) {
|
||||||
/// as it's harder to understand.
|
/// as it's harder to understand.
|
||||||
fn generate_missing_child_flow(self, node: &ThreadSafeLayoutNode) -> FlowRef {
|
fn generate_missing_child_flow(self, node: &ThreadSafeLayoutNode) -> FlowRef {
|
||||||
let mut style = node.style().clone();
|
let mut style = node.style().clone();
|
||||||
let flow = match self.class() {
|
match self.class() {
|
||||||
FlowClass::Table | FlowClass::TableRowGroup => {
|
FlowClass::Table | FlowClass::TableRowGroup => {
|
||||||
properties::modify_style_for_anonymous_table_object(
|
properties::modify_style_for_anonymous_table_object(
|
||||||
&mut style,
|
&mut style,
|
||||||
|
@ -1224,7 +1196,7 @@ impl<'a> ImmutableFlowUtils for &'a (Flow + 'a) {
|
||||||
style,
|
style,
|
||||||
node.restyle_damage(),
|
node.restyle_damage(),
|
||||||
SpecificFragmentInfo::TableRow);
|
SpecificFragmentInfo::TableRow);
|
||||||
box TableRowFlow::from_fragment(fragment) as Box<Flow>
|
Arc::new(TableRowFlow::from_fragment(fragment))
|
||||||
},
|
},
|
||||||
FlowClass::TableRow => {
|
FlowClass::TableRow => {
|
||||||
properties::modify_style_for_anonymous_table_object(
|
properties::modify_style_for_anonymous_table_object(
|
||||||
|
@ -1237,14 +1209,12 @@ impl<'a> ImmutableFlowUtils for &'a (Flow + 'a) {
|
||||||
node.restyle_damage(),
|
node.restyle_damage(),
|
||||||
SpecificFragmentInfo::TableCell);
|
SpecificFragmentInfo::TableCell);
|
||||||
let hide = node.style().get_inheritedtable().empty_cells == empty_cells::T::hide;
|
let hide = node.style().get_inheritedtable().empty_cells == empty_cells::T::hide;
|
||||||
box TableCellFlow::from_node_fragment_and_visibility_flag(node, fragment, !hide) as
|
Arc::new(TableCellFlow::from_node_fragment_and_visibility_flag(node, fragment, !hide))
|
||||||
Box<Flow>
|
|
||||||
},
|
},
|
||||||
_ => {
|
_ => {
|
||||||
panic!("no need to generate a missing child")
|
panic!("no need to generate a missing child")
|
||||||
}
|
}
|
||||||
};
|
}
|
||||||
FlowRef::new(flow)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if this flow contains fragments that are roots of an absolute flow tree.
|
/// Returns true if this flow contains fragments that are roots of an absolute flow tree.
|
||||||
|
@ -1315,7 +1285,7 @@ impl<'a> ImmutableFlowUtils for &'a (Flow + 'a) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> MutableFlowUtils for &'a mut (Flow + 'a) {
|
impl<'a> MutableFlowUtils for &'a mut Flow {
|
||||||
/// Traverses the tree in preorder.
|
/// Traverses the tree in preorder.
|
||||||
fn traverse_preorder<T: PreorderFlowTraversal>(self, traversal: &T) {
|
fn traverse_preorder<T: PreorderFlowTraversal>(self, traversal: &T) {
|
||||||
if traversal.should_process(self) {
|
if traversal.should_process(self) {
|
||||||
|
|
|
@ -108,9 +108,9 @@ impl FlowList {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> Iterator for FlowListIterator<'a> {
|
impl<'a> Iterator for FlowListIterator<'a> {
|
||||||
type Item = &'a (Flow + 'a);
|
type Item = &'a Flow;
|
||||||
#[inline]
|
#[inline]
|
||||||
fn next(&mut self) -> Option<&'a (Flow + 'a)> {
|
fn next(&mut self) -> Option<&'a Flow> {
|
||||||
self.it.next().map(|x| &**x)
|
self.it.next().map(|x| &**x)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,10 +121,10 @@ 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;
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(unsafe_code)]
|
#[allow(unsafe_code)]
|
||||||
fn next(&mut self) -> Option<&'a mut (Flow + 'a)> {
|
fn next(&mut self) -> Option<&'a mut Flow> {
|
||||||
self.it.next().map(|x| unsafe { flow_ref::deref_mut(x) })
|
self.it.next().map(|x| unsafe { flow_ref::deref_mut(x) })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,190 +10,15 @@
|
||||||
|
|
||||||
#![allow(unsafe_code)]
|
#![allow(unsafe_code)]
|
||||||
|
|
||||||
use flow;
|
use flow::Flow;
|
||||||
use flow::{Flow, BaseFlow};
|
use std::sync::{Arc, Weak};
|
||||||
|
|
||||||
use std::mem;
|
pub type FlowRef = Arc<Flow>;
|
||||||
use std::ops::Deref;
|
pub type WeakFlowRef = Weak<Flow>;
|
||||||
use std::ptr;
|
|
||||||
use std::raw;
|
|
||||||
use std::rt::heap;
|
|
||||||
use std::sync::atomic::{self, Ordering};
|
|
||||||
|
|
||||||
#[unsafe_no_drop_flag]
|
|
||||||
pub struct FlowRef {
|
|
||||||
object: raw::TraitObject,
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl Send for FlowRef {}
|
|
||||||
unsafe impl Sync for FlowRef {}
|
|
||||||
|
|
||||||
#[unsafe_no_drop_flag]
|
|
||||||
pub struct WeakFlowRef {
|
|
||||||
object: raw::TraitObject,
|
|
||||||
}
|
|
||||||
|
|
||||||
unsafe impl Send for WeakFlowRef {}
|
|
||||||
unsafe impl Sync for WeakFlowRef {}
|
|
||||||
|
|
||||||
impl FlowRef {
|
|
||||||
pub fn new(mut flow: Box<Flow>) -> FlowRef {
|
|
||||||
unsafe {
|
|
||||||
let result = {
|
|
||||||
let flow_ref: &mut Flow = &mut *flow;
|
|
||||||
let object = mem::transmute::<&mut Flow, raw::TraitObject>(flow_ref);
|
|
||||||
FlowRef { object: object }
|
|
||||||
};
|
|
||||||
mem::forget(flow);
|
|
||||||
result
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Downgrades the FlowRef to a WeakFlowRef.
|
|
||||||
pub fn downgrade(&self) -> WeakFlowRef {
|
|
||||||
unsafe {
|
|
||||||
flow::base(&**self).weak_ref_count().fetch_add(1, Ordering::Relaxed);
|
|
||||||
}
|
|
||||||
WeakFlowRef { object: self.object }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Deref for FlowRef {
|
|
||||||
type Target = Flow + 'a;
|
|
||||||
fn deref(&self) -> &(Flow + 'a) {
|
|
||||||
unsafe {
|
|
||||||
mem::transmute_copy::<raw::TraitObject, &(Flow + 'a)>(&self.object)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME(https://github.com/servo/servo/issues/6503) This introduces unsound mutable aliasing.
|
// FIXME(https://github.com/servo/servo/issues/6503) This introduces unsound mutable aliasing.
|
||||||
// Try to replace it with Arc::get_mut (which checks that the reference count is 1).
|
// Try to replace it with Arc::get_mut (which checks that the reference count is 1).
|
||||||
pub unsafe fn deref_mut<'a>(flow_ref: &mut FlowRef) -> &mut (Flow + 'a) {
|
pub unsafe fn deref_mut<'a>(r: &'a mut FlowRef) -> &'a mut Flow {
|
||||||
mem::transmute_copy::<raw::TraitObject, &mut (Flow + 'a)>(&flow_ref.object)
|
let ptr: *const Flow = &**r;
|
||||||
}
|
&mut *(ptr as *mut Flow)
|
||||||
|
|
||||||
impl Drop for FlowRef {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe {
|
|
||||||
if self.object.vtable.is_null() ||
|
|
||||||
self.object.vtable as usize == mem::POST_DROP_USIZE {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if flow::base(&**self).strong_ref_count().fetch_sub(1, Ordering::Release) != 1 {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
atomic::fence(Ordering::Acquire);
|
|
||||||
|
|
||||||
// Normally we'd call the underlying Drop logic but not free the
|
|
||||||
// allocation, but this is almost impossible without DST in
|
|
||||||
// Rust. Instead we make a fake trait object to run the drop logic
|
|
||||||
// on.
|
|
||||||
let flow_ref: FlowRef = mem::replace(self, FlowRef {
|
|
||||||
object: raw::TraitObject {
|
|
||||||
vtable: ptr::null_mut(),
|
|
||||||
data: ptr::null_mut(),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
let vtable: &[usize; 3] = mem::transmute::<*mut (), &[usize; 3]>(flow_ref.object.vtable);
|
|
||||||
let object_size = vtable[1];
|
|
||||||
let object_align = vtable[2];
|
|
||||||
|
|
||||||
let fake_data = heap::allocate(object_size, object_align);
|
|
||||||
ptr::copy(flow_ref.object.data as *const u8, fake_data, object_size);
|
|
||||||
|
|
||||||
let fake_box = raw::TraitObject { vtable: flow_ref.object.vtable, data: fake_data as *mut () };
|
|
||||||
let fake_flow = mem::transmute::<raw::TraitObject, Box<Flow>>(fake_box);
|
|
||||||
drop(fake_flow);
|
|
||||||
|
|
||||||
if flow::base(&*flow_ref).weak_ref_count().fetch_sub(1, Ordering::Release) == 1 {
|
|
||||||
atomic::fence(Ordering::Acquire);
|
|
||||||
heap::deallocate(flow_ref.object.data as *mut u8, object_size, object_align);
|
|
||||||
}
|
|
||||||
|
|
||||||
mem::forget(flow_ref);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Clone for FlowRef {
|
|
||||||
fn clone(&self) -> FlowRef {
|
|
||||||
unsafe {
|
|
||||||
let _ = flow::base(&**self).strong_ref_count().fetch_add(1, Ordering::Relaxed);
|
|
||||||
FlowRef {
|
|
||||||
object: raw::TraitObject {
|
|
||||||
vtable: self.object.vtable,
|
|
||||||
data: self.object.data,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn base<'a>(r: &WeakFlowRef) -> &'a BaseFlow {
|
|
||||||
let data = r.object.data;
|
|
||||||
debug_assert!(!data.is_null());
|
|
||||||
unsafe {
|
|
||||||
mem::transmute::<*mut (), &'a BaseFlow>(data)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl WeakFlowRef {
|
|
||||||
/// Upgrades a WeakFlowRef to a FlowRef.
|
|
||||||
pub fn upgrade(&self) -> Option<FlowRef> {
|
|
||||||
unsafe {
|
|
||||||
let object = base(self);
|
|
||||||
// We use a CAS loop to increment the strong count instead of a
|
|
||||||
// fetch_add because once the count hits 0 is must never be above
|
|
||||||
// 0.
|
|
||||||
loop {
|
|
||||||
let n = object.strong_ref_count().load(Ordering::SeqCst);
|
|
||||||
if n == 0 { return None }
|
|
||||||
let old = object.strong_ref_count().compare_and_swap(n, n + 1, Ordering::SeqCst);
|
|
||||||
if old == n {
|
|
||||||
return Some(FlowRef { object: self.object })
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Clone for WeakFlowRef {
|
|
||||||
fn clone(&self) -> WeakFlowRef {
|
|
||||||
unsafe {
|
|
||||||
base(self).weak_ref_count().fetch_add(1, Ordering::Relaxed);
|
|
||||||
}
|
|
||||||
WeakFlowRef { object: self. object }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Drop for WeakFlowRef {
|
|
||||||
fn drop(&mut self) {
|
|
||||||
unsafe {
|
|
||||||
if self.object.vtable.is_null() ||
|
|
||||||
self.object.vtable as usize == mem::POST_DROP_USIZE {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if base(self).weak_ref_count().fetch_sub(1, Ordering::Release) == 1 {
|
|
||||||
atomic::fence(Ordering::Acquire);
|
|
||||||
|
|
||||||
// This dance deallocates the Box<Flow> without running its
|
|
||||||
// drop glue. The drop glue is run when the last strong
|
|
||||||
// reference is released.
|
|
||||||
let weak_ref: WeakFlowRef = mem::replace(self, WeakFlowRef {
|
|
||||||
object: raw::TraitObject {
|
|
||||||
vtable: ptr::null_mut(),
|
|
||||||
data: ptr::null_mut(),
|
|
||||||
}
|
|
||||||
});
|
|
||||||
let vtable: &[usize; 3] = mem::transmute::<*mut (), &[usize; 3]>(weak_ref.object.vtable);
|
|
||||||
let object_size = vtable[1];
|
|
||||||
let object_align = vtable[2];
|
|
||||||
heap::deallocate(weak_ref.object.data as *mut u8, object_size, object_align);
|
|
||||||
mem::forget(weak_ref);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -192,7 +192,7 @@ pub trait LayoutDamageComputation {
|
||||||
fn reflow_entire_document(self);
|
fn reflow_entire_document(self);
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> LayoutDamageComputation for &'a mut (Flow + 'a) {
|
impl<'a> LayoutDamageComputation for &'a mut Flow {
|
||||||
fn compute_layout_damage(self) -> SpecialRestyleDamage {
|
fn compute_layout_damage(self) -> SpecialRestyleDamage {
|
||||||
let mut special_damage = SpecialRestyleDamage::empty();
|
let mut special_damage = SpecialRestyleDamage::empty();
|
||||||
let is_absolutely_positioned = flow::base(self).flags.contains(IS_ABSOLUTELY_POSITIONED);
|
let is_absolutely_positioned = flow::base(self).flags.contains(IS_ABSOLUTELY_POSITIONED);
|
||||||
|
|
|
@ -4,13 +4,12 @@
|
||||||
|
|
||||||
#![feature(append)]
|
#![feature(append)]
|
||||||
#![feature(arc_unique)]
|
#![feature(arc_unique)]
|
||||||
|
#![feature(arc_weak)]
|
||||||
#![feature(box_str)]
|
#![feature(box_str)]
|
||||||
#![feature(box_syntax)]
|
#![feature(box_syntax)]
|
||||||
#![feature(cell_extras)]
|
#![feature(cell_extras)]
|
||||||
#![feature(custom_derive)]
|
#![feature(custom_derive)]
|
||||||
#![feature(filling_drop)]
|
|
||||||
#![feature(hashmap_hasher)]
|
#![feature(hashmap_hasher)]
|
||||||
#![feature(heap_api)]
|
|
||||||
#![feature(mpsc_select)]
|
#![feature(mpsc_select)]
|
||||||
#![feature(plugin)]
|
#![feature(plugin)]
|
||||||
#![feature(raw)]
|
#![feature(raw)]
|
||||||
|
|
|
@ -47,25 +47,25 @@ fn null_unsafe_flow() -> UnsafeFlow {
|
||||||
|
|
||||||
pub fn owned_flow_to_unsafe_flow(flow: *const FlowRef) -> UnsafeFlow {
|
pub fn owned_flow_to_unsafe_flow(flow: *const FlowRef) -> UnsafeFlow {
|
||||||
unsafe {
|
unsafe {
|
||||||
mem::transmute_copy(&*flow)
|
mem::transmute::<&Flow, UnsafeFlow>(&**flow)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mut_owned_flow_to_unsafe_flow(flow: *mut FlowRef) -> UnsafeFlow {
|
pub fn mut_owned_flow_to_unsafe_flow(flow: *mut FlowRef) -> UnsafeFlow {
|
||||||
unsafe {
|
unsafe {
|
||||||
mem::transmute_copy(&*flow)
|
mem::transmute::<&Flow, UnsafeFlow>(&**flow)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn borrowed_flow_to_unsafe_flow(flow: &Flow) -> UnsafeFlow {
|
pub fn borrowed_flow_to_unsafe_flow(flow: &Flow) -> UnsafeFlow {
|
||||||
unsafe {
|
unsafe {
|
||||||
mem::transmute_copy(&flow)
|
mem::transmute::<&Flow, UnsafeFlow>(flow)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mut_borrowed_flow_to_unsafe_flow(flow: &mut Flow) -> UnsafeFlow {
|
pub fn mut_borrowed_flow_to_unsafe_flow(flow: &mut Flow) -> UnsafeFlow {
|
||||||
unsafe {
|
unsafe {
|
||||||
mem::transmute_copy(&flow)
|
mem::transmute::<&Flow, UnsafeFlow>(flow)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,10 +239,9 @@ trait ParallelPostorderFlowTraversal : PostorderFlowTraversal {
|
||||||
fn run_parallel(&self, mut unsafe_flow: UnsafeFlow) {
|
fn run_parallel(&self, mut unsafe_flow: UnsafeFlow) {
|
||||||
loop {
|
loop {
|
||||||
// Get a real flow.
|
// Get a real flow.
|
||||||
let flow: &mut FlowRef = unsafe {
|
let flow: &mut Flow = unsafe {
|
||||||
mem::transmute(&mut unsafe_flow)
|
mem::transmute(unsafe_flow)
|
||||||
};
|
};
|
||||||
let flow = unsafe { flow_ref::deref_mut(flow) };
|
|
||||||
|
|
||||||
// Perform the appropriate traversal.
|
// Perform the appropriate traversal.
|
||||||
if self.should_process(flow) {
|
if self.should_process(flow) {
|
||||||
|
@ -257,7 +256,7 @@ trait ParallelPostorderFlowTraversal : PostorderFlowTraversal {
|
||||||
Ordering::Relaxed);
|
Ordering::Relaxed);
|
||||||
|
|
||||||
// Possibly enqueue the parent.
|
// Possibly enqueue the parent.
|
||||||
let mut unsafe_parent = base.parallel.parent;
|
let unsafe_parent = base.parallel.parent;
|
||||||
if unsafe_parent == null_unsafe_flow() {
|
if unsafe_parent == null_unsafe_flow() {
|
||||||
// We're done!
|
// We're done!
|
||||||
break
|
break
|
||||||
|
@ -266,10 +265,10 @@ trait ParallelPostorderFlowTraversal : PostorderFlowTraversal {
|
||||||
// No, we're not at the root yet. Then are we the last child
|
// No, we're not at the root yet. Then are we the last child
|
||||||
// of our parent to finish processing? If so, we can continue
|
// of our parent to finish processing? If so, we can continue
|
||||||
// on with our parent; otherwise, we've gotta wait.
|
// on with our parent; otherwise, we've gotta wait.
|
||||||
let parent: &mut FlowRef = unsafe {
|
let parent: &mut Flow = unsafe {
|
||||||
mem::transmute(&mut unsafe_parent)
|
mem::transmute(unsafe_parent)
|
||||||
};
|
};
|
||||||
let parent_base = flow::mut_base(unsafe { flow_ref::deref_mut(parent) });
|
let parent_base = flow::mut_base(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
|
||||||
|
@ -296,12 +295,11 @@ trait ParallelPreorderFlowTraversal : PreorderFlowTraversal {
|
||||||
top_down_func: ChunkedFlowTraversalFunction,
|
top_down_func: ChunkedFlowTraversalFunction,
|
||||||
bottom_up_func: FlowTraversalFunction) {
|
bottom_up_func: FlowTraversalFunction) {
|
||||||
let mut discovered_child_flows = Vec::new();
|
let mut discovered_child_flows = Vec::new();
|
||||||
for mut unsafe_flow in *unsafe_flows.0 {
|
for unsafe_flow in *unsafe_flows.0 {
|
||||||
let mut had_children = false;
|
let mut had_children = false;
|
||||||
unsafe {
|
unsafe {
|
||||||
// Get a real flow.
|
// Get a real flow.
|
||||||
let flow: &mut FlowRef = mem::transmute(&mut unsafe_flow);
|
let flow: &mut Flow = mem::transmute(unsafe_flow);
|
||||||
let flow = flow_ref::deref_mut(flow);
|
|
||||||
|
|
||||||
if self.should_record_thread_ids() {
|
if self.should_record_thread_ids() {
|
||||||
flow::mut_base(flow).thread_id = proxy.worker_index();
|
flow::mut_base(flow).thread_id = proxy.worker_index();
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue