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:
Patrick Walton 2014-10-28 15:38:18 -07:00
parent c20bb66aef
commit 587cf98209
7 changed files with 156 additions and 133 deletions

View file

@ -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;