layout: Port parallel layout over to a generic "work queue"

infrastructure.

The work queue accepts abstract generic "work units", which in this case
are layout operations. The same speedups have been observed.
This commit is contained in:
Patrick Walton 2014-01-23 13:43:03 -08:00
parent 86c29d253a
commit 18a2050a64
12 changed files with 518 additions and 351 deletions

View file

@ -32,6 +32,7 @@ use layout::text::TextRunScanner;
use layout::util::LayoutDataAccess;
use layout::wrapper::{LayoutNode, PostorderNodeMutTraversal};
use gfx::font_context::FontContext;
use script::dom::element::{HTMLIframeElementTypeId, HTMLImageElementTypeId};
use script::dom::node::{CommentNodeTypeId, DoctypeNodeTypeId, DocumentFragmentNodeTypeId};
use script::dom::node::{DocumentNodeTypeId, ElementNodeTypeId, TextNodeTypeId};
@ -209,14 +210,19 @@ pub struct FlowConstructor<'a> {
///
/// FIXME(pcwalton): This is going to have to be atomic; can't we do something better?
next_flow_id: RefCell<int>,
/// The font context.
font_context: ~FontContext,
}
impl<'fc> FlowConstructor<'fc> {
/// Creates a new flow constructor.
pub fn init<'a>(layout_context: &'a mut LayoutContext) -> FlowConstructor<'a> {
let font_context = ~FontContext::new(layout_context.font_context_info.clone());
FlowConstructor {
layout_context: layout_context,
next_flow_id: RefCell::new(0),
font_context: font_context,
}
}
@ -235,7 +241,7 @@ impl<'fc> FlowConstructor<'fc> {
Some(url) => {
// FIXME(pcwalton): The fact that image boxes store the cache within them makes
// little sense to me.
Some(ImageBoxInfo::new(&node, url, self.layout_context.shared.image_cache.clone()))
Some(ImageBoxInfo::new(&node, url, self.layout_context.image_cache.clone()))
}
}
}
@ -262,20 +268,19 @@ impl<'fc> FlowConstructor<'fc> {
/// otherwise.
#[inline(always)]
fn flush_inline_boxes_to_flow(&mut self, boxes: ~[Box], flow: &mut ~Flow, node: LayoutNode) {
if boxes.len() > 0 {
let inline_base = BaseFlow::new(self.next_flow_id(), node);
let mut inline_flow = ~InlineFlow::from_boxes(inline_base, boxes) as ~Flow;
self.layout_context.shared.leaf_set.access(|leaf_set| leaf_set.insert(&inline_flow));
TextRunScanner::new().scan_for_runs(self.layout_context, inline_flow);
let mut inline_flow = Some(inline_flow);
self.layout_context.shared.leaf_set.access(|leaf_set| {
flow.add_new_child(inline_flow.take_unwrap(), leaf_set)
})
if boxes.len() == 0 {
return
}
let inline_base = BaseFlow::new(self.next_flow_id(), node);
let mut inline_flow = ~InlineFlow::from_boxes(inline_base, boxes) as ~Flow;
self.layout_context.leaf_set.access(|leaf_set| leaf_set.insert(&inline_flow));
TextRunScanner::new().scan_for_runs(self.font_context, inline_flow);
let mut inline_flow = Some(inline_flow);
self.layout_context.leaf_set.access(|leaf_set| {
flow.add_new_child(inline_flow.take_unwrap(), leaf_set)
})
}
/// Creates an inline flow from a set of inline boxes, if present, and adds it as a child of
@ -319,7 +324,7 @@ impl<'fc> FlowConstructor<'fc> {
flow,
node);
let mut kid_flow = Some(kid_flow);
self.layout_context.shared.leaf_set.access(|leaf_set| {
self.layout_context.leaf_set.access(|leaf_set| {
flow.add_new_child(kid_flow.take_unwrap(), leaf_set)
})
}
@ -362,7 +367,7 @@ impl<'fc> FlowConstructor<'fc> {
// Push the flow generated by the {ib} split onto our list of
// flows.
let mut kid_flow = Some(kid_flow);
self.layout_context.shared.leaf_set.access(|leaf_set| {
self.layout_context.leaf_set.access(|leaf_set| {
flow.add_new_child(kid_flow.take_unwrap(), leaf_set)
})
}
@ -391,7 +396,7 @@ impl<'fc> FlowConstructor<'fc> {
let box_ = self.build_box_for_node(node);
let mut flow = ~BlockFlow::from_box(base, box_, is_fixed) as ~Flow;
self.layout_context.shared.leaf_set.access(|leaf_set| leaf_set.insert(&flow));
self.layout_context.leaf_set.access(|leaf_set| leaf_set.insert(&flow));
self.build_children_of_block_flow(&mut flow, node);
flow
@ -406,7 +411,7 @@ impl<'fc> FlowConstructor<'fc> {
let mut flow = ~BlockFlow::float_from_box(base, float_type, box_) as ~Flow;
self.layout_context.shared.leaf_set.access(|leaf_set| leaf_set.insert(&flow));
self.layout_context.leaf_set.access(|leaf_set| leaf_set.insert(&flow));
self.build_children_of_block_flow(&mut flow, node);
flow
@ -484,7 +489,7 @@ impl<'fc> FlowConstructor<'fc> {
fn set_inline_info_for_inline_child(&mut self, boxes: &mut ~[Box], parent_node: LayoutNode) {
let parent_box = self.build_box_for_node(parent_node);
let font_style = parent_box.font_style();
let font_group = self.layout_context.font_ctx.get_resolved_font_for_style(&font_style);
let font_group = self.font_context.get_resolved_font_for_style(&font_style);
let (font_ascent,font_descent) = font_group.borrow().with_mut( |fg| {
fg.fonts[0].borrow().with_mut( |font| {
(font.metrics.ascent,font.metrics.descent)
@ -569,7 +574,7 @@ impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> {
// `display: none` contributes no flow construction result. Nuke the flow construction
// results of children.
(display::none, _, _) => {
self.layout_context.shared.leaf_set.access(|leaf_set| {
self.layout_context.leaf_set.access(|leaf_set| {
for child in node.children() {
let mut old_result = child.swap_out_construction_result();
old_result.destroy(leaf_set)