mirror of
https://github.com/servo/servo.git
synced 2025-08-05 13:40:08 +01:00
Merge pull request #2778 from Ms2ger/parallel
Remove some mem::transmute calls and reduce some unsafe blocks in parallel.rs.
This commit is contained in:
commit
7bf4007880
1 changed files with 79 additions and 91 deletions
|
@ -26,7 +26,7 @@ use servo_util::workqueue::{WorkQueue, WorkUnit, WorkerProxy};
|
||||||
use std::mem;
|
use std::mem;
|
||||||
use std::ptr;
|
use std::ptr;
|
||||||
use std::sync::atomics::{AtomicInt, Relaxed, SeqCst};
|
use std::sync::atomics::{AtomicInt, Relaxed, SeqCst};
|
||||||
use style::{Stylist, TNode};
|
use style::TNode;
|
||||||
|
|
||||||
#[allow(dead_code)]
|
#[allow(dead_code)]
|
||||||
fn static_assertion(node: UnsafeLayoutNode) {
|
fn static_assertion(node: UnsafeLayoutNode) {
|
||||||
|
@ -215,98 +215,98 @@ impl<'a> ParallelPostorderFlowTraversal for AssignHeightsAndStoreOverflowTravers
|
||||||
|
|
||||||
fn recalc_style_for_node(unsafe_layout_node: UnsafeLayoutNode,
|
fn recalc_style_for_node(unsafe_layout_node: UnsafeLayoutNode,
|
||||||
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeLayoutNode>) {
|
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeLayoutNode>) {
|
||||||
unsafe {
|
let layout_context = unsafe { &mut **proxy.user_data() };
|
||||||
let layout_context: &mut LayoutContext = mem::transmute(*proxy.user_data());
|
|
||||||
|
|
||||||
// Get a real layout node.
|
// Get a real layout node.
|
||||||
let node: LayoutNode = layout_node_from_unsafe_layout_node(&unsafe_layout_node);
|
let node: LayoutNode = layout_node_from_unsafe_layout_node(&unsafe_layout_node);
|
||||||
|
|
||||||
// Initialize layout data.
|
// Initialize layout data.
|
||||||
//
|
//
|
||||||
// FIXME(pcwalton): Stop allocating here. Ideally this should just be done by the HTML
|
// FIXME(pcwalton): Stop allocating here. Ideally this should just be done by the HTML
|
||||||
// parser.
|
// parser.
|
||||||
node.initialize_layout_data(layout_context.layout_chan.clone());
|
node.initialize_layout_data(layout_context.layout_chan.clone());
|
||||||
|
|
||||||
// Get the parent node.
|
// Get the parent node.
|
||||||
let opaque_node: OpaqueNode = OpaqueNodeMethods::from_layout_node(&node);
|
let opaque_node: OpaqueNode = OpaqueNodeMethods::from_layout_node(&node);
|
||||||
let parent_opt = if opaque_node == layout_context.reflow_root {
|
let parent_opt = if opaque_node == layout_context.reflow_root {
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
node.parent_node()
|
node.parent_node()
|
||||||
};
|
};
|
||||||
|
|
||||||
// First, check to see whether we can share a style with someone.
|
// First, check to see whether we can share a style with someone.
|
||||||
let style_sharing_candidate_cache = layout_context.style_sharing_candidate_cache();
|
let style_sharing_candidate_cache = layout_context.style_sharing_candidate_cache();
|
||||||
let sharing_result = node.share_style_if_possible(style_sharing_candidate_cache,
|
let sharing_result = unsafe {
|
||||||
parent_opt.clone());
|
node.share_style_if_possible(style_sharing_candidate_cache,
|
||||||
|
parent_opt.clone())
|
||||||
|
};
|
||||||
|
|
||||||
// Otherwise, match and cascade selectors.
|
// Otherwise, match and cascade selectors.
|
||||||
match sharing_result {
|
match sharing_result {
|
||||||
CannotShare(mut shareable) => {
|
CannotShare(mut shareable) => {
|
||||||
let mut applicable_declarations = ApplicableDeclarations::new();
|
let mut applicable_declarations = ApplicableDeclarations::new();
|
||||||
|
|
||||||
if node.is_element() {
|
if node.is_element() {
|
||||||
// Perform the CSS selector matching.
|
// Perform the CSS selector matching.
|
||||||
let stylist: &Stylist = mem::transmute(layout_context.stylist);
|
let stylist = unsafe { &*layout_context.stylist };
|
||||||
node.match_node(stylist, &mut applicable_declarations, &mut shareable);
|
node.match_node(stylist, &mut applicable_declarations, &mut shareable);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Perform the CSS cascade.
|
// Perform the CSS cascade.
|
||||||
|
unsafe {
|
||||||
node.cascade_node(parent_opt,
|
node.cascade_node(parent_opt,
|
||||||
&applicable_declarations,
|
&applicable_declarations,
|
||||||
layout_context.applicable_declarations_cache());
|
layout_context.applicable_declarations_cache());
|
||||||
|
|
||||||
// Add ourselves to the LRU cache.
|
|
||||||
if shareable {
|
|
||||||
style_sharing_candidate_cache.insert_if_possible(&node);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
StyleWasShared(index) => style_sharing_candidate_cache.touch(index),
|
|
||||||
}
|
|
||||||
|
|
||||||
// Prepare for flow construction by counting the node's children and storing that count.
|
// Add ourselves to the LRU cache.
|
||||||
let mut child_count = 0;
|
if shareable {
|
||||||
for _ in node.children() {
|
style_sharing_candidate_cache.insert_if_possible(&node);
|
||||||
child_count += 1;
|
|
||||||
}
|
|
||||||
if child_count != 0 {
|
|
||||||
let mut layout_data_ref = node.mutate_layout_data();
|
|
||||||
match &mut *layout_data_ref {
|
|
||||||
&Some(ref mut layout_data) => {
|
|
||||||
layout_data.data.parallel.children_count.store(child_count as int, Relaxed)
|
|
||||||
}
|
|
||||||
&None => fail!("no layout data"),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
StyleWasShared(index) => style_sharing_candidate_cache.touch(index),
|
||||||
// It's *very* important that this block is in a separate scope to the block above,
|
|
||||||
// to avoid a data race that can occur (github issue #2308). The block above issues
|
|
||||||
// a borrow on the node layout data. That borrow must be dropped before the child
|
|
||||||
// nodes are actually pushed into the work queue. Otherwise, it's possible for a child
|
|
||||||
// node to get into construct_flows() and move up it's parent hierarchy, which can call
|
|
||||||
// borrow on the layout data before it is dropped from the block above.
|
|
||||||
if child_count != 0 {
|
|
||||||
// Enqueue kids.
|
|
||||||
for kid in node.children() {
|
|
||||||
proxy.push(WorkUnit {
|
|
||||||
fun: recalc_style_for_node,
|
|
||||||
data: layout_node_to_unsafe_layout_node(&kid),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// If we got here, we're a leaf. Start construction of flows for this node.
|
|
||||||
construct_flows(unsafe_layout_node, proxy)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Prepare for flow construction by counting the node's children and storing that count.
|
||||||
|
let mut child_count = 0;
|
||||||
|
for _ in node.children() {
|
||||||
|
child_count += 1;
|
||||||
|
}
|
||||||
|
if child_count != 0 {
|
||||||
|
let mut layout_data_ref = node.mutate_layout_data();
|
||||||
|
match &mut *layout_data_ref {
|
||||||
|
&Some(ref mut layout_data) => {
|
||||||
|
layout_data.data.parallel.children_count.store(child_count as int, Relaxed)
|
||||||
|
}
|
||||||
|
&None => fail!("no layout data"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// It's *very* important that this block is in a separate scope to the block above,
|
||||||
|
// to avoid a data race that can occur (github issue #2308). The block above issues
|
||||||
|
// a borrow on the node layout data. That borrow must be dropped before the child
|
||||||
|
// nodes are actually pushed into the work queue. Otherwise, it's possible for a child
|
||||||
|
// node to get into construct_flows() and move up it's parent hierarchy, which can call
|
||||||
|
// borrow on the layout data before it is dropped from the block above.
|
||||||
|
if child_count != 0 {
|
||||||
|
// Enqueue kids.
|
||||||
|
for kid in node.children() {
|
||||||
|
proxy.push(WorkUnit {
|
||||||
|
fun: recalc_style_for_node,
|
||||||
|
data: layout_node_to_unsafe_layout_node(&kid),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// If we got here, we're a leaf. Start construction of flows for this node.
|
||||||
|
construct_flows(unsafe_layout_node, proxy)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn construct_flows(mut unsafe_layout_node: UnsafeLayoutNode,
|
fn construct_flows(mut unsafe_layout_node: UnsafeLayoutNode,
|
||||||
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeLayoutNode>) {
|
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeLayoutNode>) {
|
||||||
loop {
|
loop {
|
||||||
let layout_context: &mut LayoutContext = unsafe {
|
let layout_context = unsafe { &mut **proxy.user_data() };
|
||||||
mem::transmute(*proxy.user_data())
|
|
||||||
};
|
|
||||||
|
|
||||||
// Get a real layout node.
|
// Get a real layout node.
|
||||||
let node: LayoutNode = layout_node_from_unsafe_layout_node(&unsafe_layout_node);
|
let node: LayoutNode = layout_node_from_unsafe_layout_node(&unsafe_layout_node);
|
||||||
|
@ -373,9 +373,7 @@ fn construct_flows(mut unsafe_layout_node: UnsafeLayoutNode,
|
||||||
|
|
||||||
fn assign_widths(unsafe_flow: UnsafeFlow,
|
fn assign_widths(unsafe_flow: UnsafeFlow,
|
||||||
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) {
|
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) {
|
||||||
let layout_context: &mut LayoutContext = unsafe {
|
let layout_context = unsafe { &mut **proxy.user_data() };
|
||||||
mem::transmute(*proxy.user_data())
|
|
||||||
};
|
|
||||||
let mut assign_widths_traversal = AssignWidthsTraversal {
|
let mut assign_widths_traversal = AssignWidthsTraversal {
|
||||||
layout_context: layout_context,
|
layout_context: layout_context,
|
||||||
};
|
};
|
||||||
|
@ -384,9 +382,7 @@ fn assign_widths(unsafe_flow: UnsafeFlow,
|
||||||
|
|
||||||
fn assign_heights_and_store_overflow(unsafe_flow: UnsafeFlow,
|
fn assign_heights_and_store_overflow(unsafe_flow: UnsafeFlow,
|
||||||
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) {
|
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) {
|
||||||
let layout_context: &mut LayoutContext = unsafe {
|
let layout_context = unsafe { &mut **proxy.user_data() };
|
||||||
mem::transmute(*proxy.user_data())
|
|
||||||
};
|
|
||||||
let mut assign_heights_traversal = AssignHeightsAndStoreOverflowTraversal {
|
let mut assign_heights_traversal = AssignHeightsAndStoreOverflowTraversal {
|
||||||
layout_context: layout_context,
|
layout_context: layout_context,
|
||||||
};
|
};
|
||||||
|
@ -449,9 +445,7 @@ fn compute_absolute_position(unsafe_flow: UnsafeFlow,
|
||||||
|
|
||||||
fn build_display_list(mut unsafe_flow: UnsafeFlow,
|
fn build_display_list(mut unsafe_flow: UnsafeFlow,
|
||||||
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) {
|
proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) {
|
||||||
let layout_context: &mut LayoutContext = unsafe {
|
let layout_context = unsafe { &mut **proxy.user_data() };
|
||||||
mem::transmute(*proxy.user_data())
|
|
||||||
};
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
unsafe {
|
unsafe {
|
||||||
|
@ -510,9 +504,7 @@ fn build_display_list(mut unsafe_flow: UnsafeFlow,
|
||||||
pub fn recalc_style_for_subtree(root_node: &LayoutNode,
|
pub fn recalc_style_for_subtree(root_node: &LayoutNode,
|
||||||
layout_context: &mut LayoutContext,
|
layout_context: &mut LayoutContext,
|
||||||
queue: &mut WorkQueue<*mut LayoutContext,UnsafeLayoutNode>) {
|
queue: &mut WorkQueue<*mut LayoutContext,UnsafeLayoutNode>) {
|
||||||
unsafe {
|
queue.data = layout_context as *mut _;
|
||||||
queue.data = mem::transmute(layout_context)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Enqueue the root node.
|
// Enqueue the root node.
|
||||||
queue.push(WorkUnit {
|
queue.push(WorkUnit {
|
||||||
|
@ -529,9 +521,7 @@ pub fn traverse_flow_tree_preorder(root: &mut FlowRef,
|
||||||
time_profiler_chan: TimeProfilerChan,
|
time_profiler_chan: TimeProfilerChan,
|
||||||
layout_context: &mut LayoutContext,
|
layout_context: &mut LayoutContext,
|
||||||
queue: &mut WorkQueue<*mut LayoutContext,UnsafeFlow>) {
|
queue: &mut WorkQueue<*mut LayoutContext,UnsafeFlow>) {
|
||||||
unsafe {
|
queue.data = layout_context as *mut _;
|
||||||
queue.data = mem::transmute(layout_context)
|
|
||||||
}
|
|
||||||
|
|
||||||
profile(time::LayoutParallelWarmupCategory, time_profiler_chan, || {
|
profile(time::LayoutParallelWarmupCategory, time_profiler_chan, || {
|
||||||
queue.push(WorkUnit {
|
queue.push(WorkUnit {
|
||||||
|
@ -549,9 +539,7 @@ pub fn build_display_list_for_subtree(root: &mut FlowRef,
|
||||||
time_profiler_chan: TimeProfilerChan,
|
time_profiler_chan: TimeProfilerChan,
|
||||||
layout_context: &mut LayoutContext,
|
layout_context: &mut LayoutContext,
|
||||||
queue: &mut WorkQueue<*mut LayoutContext,UnsafeFlow>) {
|
queue: &mut WorkQueue<*mut LayoutContext,UnsafeFlow>) {
|
||||||
unsafe {
|
queue.data = layout_context as *mut _;
|
||||||
queue.data = mem::transmute(layout_context)
|
|
||||||
}
|
|
||||||
|
|
||||||
profile(time::LayoutParallelWarmupCategory, time_profiler_chan, || {
|
profile(time::LayoutParallelWarmupCategory, time_profiler_chan, || {
|
||||||
queue.push(WorkUnit {
|
queue.push(WorkUnit {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue