mirror of
https://github.com/servo/servo.git
synced 2025-08-06 22:15:33 +01:00
layout: Promote absolute positioning, floatedness, and clearance into
flags to avoid virtual calls. These were showing up really high in the maze solver profile.
This commit is contained in:
parent
c20bb66aef
commit
587cf98209
7 changed files with 156 additions and 133 deletions
|
@ -211,15 +211,6 @@ pub trait Flow: fmt::Show + ToString + Sync {
|
|||
/// Phase 5 of reflow: builds display lists.
|
||||
fn build_display_list(&mut self, layout_context: &LayoutContext);
|
||||
|
||||
/// Returns the direction that this flow clears floats in, if any.
|
||||
fn float_clearance(&self) -> clear::T {
|
||||
clear::none
|
||||
}
|
||||
|
||||
fn float_kind(&self) -> float::T {
|
||||
float::none
|
||||
}
|
||||
|
||||
fn compute_collapsible_block_start_margin(&mut self,
|
||||
_layout_context: &mut LayoutContext,
|
||||
_margin_collapse_info: &mut MarginCollapseInfo) {
|
||||
|
@ -260,17 +251,13 @@ pub trait Flow: fmt::Show + ToString + Sync {
|
|||
}
|
||||
|
||||
fn is_positioned(&self) -> bool {
|
||||
self.is_relatively_positioned() || self.is_absolutely_positioned()
|
||||
self.is_relatively_positioned() || base(self).flags.is_absolutely_positioned()
|
||||
}
|
||||
|
||||
fn is_relatively_positioned(&self) -> bool {
|
||||
self.positioning() == position::relative
|
||||
}
|
||||
|
||||
fn is_absolutely_positioned(&self) -> bool {
|
||||
self.positioning() == position::absolute || self.is_fixed()
|
||||
}
|
||||
|
||||
/// Return true if this is the root of an absolute flow tree.
|
||||
fn is_root_of_absolute_flow_tree(&self) -> bool {
|
||||
false
|
||||
|
@ -485,48 +472,77 @@ pub trait PostorderFlowTraversal {
|
|||
|
||||
/// Flags used in flows, tightly packed to save space.
|
||||
#[deriving(Clone, Encodable)]
|
||||
pub struct FlowFlags(pub u8);
|
||||
pub struct FlowFlags(pub u16);
|
||||
|
||||
/// The bitmask of flags that represent the `has_left_floated_descendants` and
|
||||
/// `has_right_floated_descendants` fields.
|
||||
///
|
||||
/// NB: If you update this field, you must update the bitfields below.
|
||||
static HAS_FLOATED_DESCENDANTS_BITMASK: u8 = 0b0000_0011;
|
||||
static HAS_FLOATED_DESCENDANTS_BITMASK: u16 = 0b0000_0000_0000_0011;
|
||||
|
||||
// Whether this flow has descendants that float left in the same block formatting context.
|
||||
bitfield!(FlowFlags, has_left_floated_descendants, set_has_left_floated_descendants, 0b0000_0001)
|
||||
bitfield!(FlowFlags,
|
||||
has_left_floated_descendants,
|
||||
set_has_left_floated_descendants,
|
||||
0b0000_0000_0000_0001)
|
||||
|
||||
// Whether this flow has descendants that float right in the same block formatting context.
|
||||
bitfield!(FlowFlags, has_right_floated_descendants, set_has_right_floated_descendants, 0b0000_0010)
|
||||
bitfield!(FlowFlags,
|
||||
has_right_floated_descendants,
|
||||
set_has_right_floated_descendants,
|
||||
0b0000_0000_0000_0010)
|
||||
|
||||
// Whether this flow is impacted by floats to the left in the same block formatting context (i.e.
|
||||
// its block-size depends on some prior flows with `float: left`).
|
||||
bitfield!(FlowFlags, impacted_by_left_floats, set_impacted_by_left_floats, 0b0000_0100)
|
||||
bitfield!(FlowFlags,
|
||||
impacted_by_left_floats,
|
||||
set_impacted_by_left_floats,
|
||||
0b0000_0000_0000_0100)
|
||||
|
||||
// Whether this flow is impacted by floats to the right in the same block formatting context (i.e.
|
||||
// its block-size depends on some prior flows with `float: right`).
|
||||
bitfield!(FlowFlags, impacted_by_right_floats, set_impacted_by_right_floats, 0b0000_1000)
|
||||
bitfield!(FlowFlags, impacted_by_right_floats, set_impacted_by_right_floats, 0b0000_0000_0000_1000)
|
||||
|
||||
/// The bitmask of flags that represent the text alignment field.
|
||||
///
|
||||
/// NB: If you update this field, you must update the bitfields below.
|
||||
static TEXT_ALIGN_BITMASK: u8 = 0b0011_0000;
|
||||
static TEXT_ALIGN_BITMASK: u16 = 0b0000_0000_0011_0000;
|
||||
|
||||
/// The number of bits we must shift off to handle the text alignment field.
|
||||
///
|
||||
/// NB: If you update this field, you must update the bitfields below.
|
||||
static TEXT_ALIGN_SHIFT: u8 = 4;
|
||||
static TEXT_ALIGN_SHIFT: u16 = 4;
|
||||
|
||||
// Whether this flow contains a flow that has its own layer within the same absolute containing
|
||||
// block.
|
||||
bitfield!(FlowFlags,
|
||||
layers_needed_for_descendants,
|
||||
set_layers_needed_for_descendants,
|
||||
0b0100_0000)
|
||||
0b0000_0000_0100_0000)
|
||||
|
||||
// Whether this flow must have its own layer. Even if this flag is not set, it might get its own
|
||||
// layer if it's deemed to be likely to overlap flows with their own layer.
|
||||
bitfield!(FlowFlags, needs_layer, set_needs_layer, 0b1000_0000)
|
||||
bitfield!(FlowFlags, needs_layer, set_needs_layer, 0b0000_0000_1000_0000)
|
||||
|
||||
// Whether this flow is absolutely positioned. This is checked all over layout, so a virtual call
|
||||
// is too expensive.
|
||||
bitfield!(FlowFlags, is_absolutely_positioned, set_is_absolutely_positioned, 0b0000_0001_0000_0000)
|
||||
|
||||
// Whether this flow is left-floated. This is checked all over layout, so a virtual call is too
|
||||
// expensive.
|
||||
bitfield!(FlowFlags, floats_left, set_floats_left, 0b0000_0010_0000_0000)
|
||||
|
||||
// Whether this flow is right-floated. This is checked all over layout, so a virtual call is too
|
||||
// expensive.
|
||||
bitfield!(FlowFlags, floats_right, set_floats_right, 0b0000_0100_0000_0000)
|
||||
|
||||
// Whether this flow clears to the left. This is checked all over layout, so a virtual call is too
|
||||
// expensive.
|
||||
bitfield!(FlowFlags, clears_left, set_clears_left, 0b0000_1000_0000_0000)
|
||||
|
||||
// Whether this flow clears to the right. This is checked all over layout, so a virtual call is too
|
||||
// expensive.
|
||||
bitfield!(FlowFlags, clears_right, set_clears_right, 0b0001_0000_0000_0000)
|
||||
|
||||
impl FlowFlags {
|
||||
/// Creates a new set of flow flags.
|
||||
|
@ -545,13 +561,13 @@ impl FlowFlags {
|
|||
#[inline]
|
||||
pub fn text_align(self) -> text_align::T {
|
||||
let FlowFlags(ff) = self;
|
||||
FromPrimitive::from_u8((ff & TEXT_ALIGN_BITMASK) >> TEXT_ALIGN_SHIFT as uint).unwrap()
|
||||
FromPrimitive::from_u16((ff & TEXT_ALIGN_BITMASK) >> TEXT_ALIGN_SHIFT as uint).unwrap()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn set_text_align(&mut self, value: text_align::T) {
|
||||
let FlowFlags(ff) = *self;
|
||||
*self = FlowFlags((ff & !TEXT_ALIGN_BITMASK) | ((value as u8) << TEXT_ALIGN_SHIFT as uint))
|
||||
*self = FlowFlags((ff & !TEXT_ALIGN_BITMASK) | ((value as u16) << TEXT_ALIGN_SHIFT as uint))
|
||||
}
|
||||
|
||||
#[inline]
|
||||
|
@ -572,6 +588,22 @@ impl FlowFlags {
|
|||
pub fn impacted_by_floats(&self) -> bool {
|
||||
self.impacted_by_left_floats() || self.impacted_by_right_floats()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn float_kind(&self) -> float::T {
|
||||
if self.floats_left() {
|
||||
float::left
|
||||
} else if self.floats_right() {
|
||||
float::right
|
||||
} else {
|
||||
float::none
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn clears_floats(&self) -> bool {
|
||||
self.clears_left() || self.clears_right()
|
||||
}
|
||||
}
|
||||
|
||||
/// The Descendants of a flow.
|
||||
|
@ -813,15 +845,39 @@ impl Drop for BaseFlow {
|
|||
|
||||
impl BaseFlow {
|
||||
#[inline]
|
||||
pub fn new(node: ThreadSafeLayoutNode) -> BaseFlow {
|
||||
let writing_mode = node.style().writing_mode;
|
||||
pub fn new(node: Option<ThreadSafeLayoutNode>, writing_mode: WritingMode) -> BaseFlow {
|
||||
let mut flags = FlowFlags::new();
|
||||
match node {
|
||||
None => {}
|
||||
Some(node) => {
|
||||
let node_style = node.style();
|
||||
match node_style.get_box().position {
|
||||
position::absolute | position::fixed => {
|
||||
flags.set_is_absolutely_positioned(true)
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
match node_style.get_box().float {
|
||||
float::none => {}
|
||||
float::left => flags.set_floats_left(true),
|
||||
float::right => flags.set_floats_right(true),
|
||||
}
|
||||
match node_style.get_box().clear {
|
||||
clear::none => {}
|
||||
clear::left => flags.set_clears_left(true),
|
||||
clear::right => flags.set_clears_right(true),
|
||||
clear::both => {
|
||||
flags.set_clears_left(true);
|
||||
flags.set_clears_right(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BaseFlow {
|
||||
ref_count: AtomicUint::new(1),
|
||||
|
||||
restyle_damage: node.restyle_damage(),
|
||||
|
||||
restyle_damage: RestyleDamage::all(),
|
||||
children: FlowList::new(),
|
||||
|
||||
intrinsic_inline_sizes: IntrinsicISizes::new(),
|
||||
position: LogicalRect::zero(writing_mode),
|
||||
overflow: LogicalRect::zero(writing_mode),
|
||||
|
@ -839,8 +895,7 @@ impl BaseFlow {
|
|||
layers: DList::new(),
|
||||
absolute_position_info: AbsolutePositionInfo::new(writing_mode),
|
||||
clip_rect: Rect(Zero::zero(), Size2D(Au(0), Au(0))),
|
||||
|
||||
flags: FlowFlags::new(),
|
||||
flags: flags,
|
||||
writing_mode: writing_mode,
|
||||
}
|
||||
}
|
||||
|
@ -1124,7 +1179,7 @@ impl<'a> MutableFlowUtils for &'a mut Flow + 'a {
|
|||
let mut gives_absolute_offsets = true;
|
||||
if kid.is_block_like() {
|
||||
let kid_block = kid.as_block();
|
||||
if kid_block.is_fixed() || kid_block.is_absolutely_positioned() {
|
||||
if kid_block.is_fixed() || kid_block.base.flags.is_absolutely_positioned() {
|
||||
// It won't contribute any offsets for descendants because it would be the
|
||||
// containing block for them.
|
||||
gives_absolute_offsets = false;
|
||||
|
@ -1162,28 +1217,17 @@ impl<'a> MutableFlowUtils for &'a mut Flow + 'a {
|
|||
}
|
||||
|
||||
fn doit(flow: &mut Flow, down: RestyleDamage, dirty_floats: &mut DirtyFloats) -> RestyleDamage {
|
||||
match flow.float_clearance() {
|
||||
clear::none => {}
|
||||
clear::left => {
|
||||
(*dirty_floats).left = false;
|
||||
}
|
||||
clear::right => {
|
||||
(*dirty_floats).right = false;
|
||||
}
|
||||
clear::both => {
|
||||
(*dirty_floats).left = false;
|
||||
(*dirty_floats).right = false;
|
||||
}
|
||||
if base(flow).flags.clears_left() {
|
||||
dirty_floats.left = false;
|
||||
}
|
||||
if base(flow).flags.clears_right() {
|
||||
dirty_floats.right = false;
|
||||
}
|
||||
|
||||
match flow.float_kind() {
|
||||
float::none => {}
|
||||
float::left => {
|
||||
(*dirty_floats).left = true;
|
||||
}
|
||||
float::right => {
|
||||
(*dirty_floats).right = true;
|
||||
}
|
||||
if base(flow).flags.floats_left() {
|
||||
(*dirty_floats).left = true;
|
||||
} else if base(flow).flags.floats_right() {
|
||||
(*dirty_floats).right = true;
|
||||
}
|
||||
|
||||
let mut my_damage = mut_base(flow).restyle_damage;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue