aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorGlenn Watson <gw@intuitionlibrary.com>2014-08-08 13:53:37 +1000
committerGlenn Watson <gw@intuitionlibrary.com>2014-08-11 12:10:28 +1000
commit4a0e01b4f033940b5d31ad1a47e322b2769ef1a5 (patch)
tree1e286508e0d54e3aad2e1155d39a252e783b8d77 /src
parent4062af69ec562c8a3f781a2918bc4134a809b391 (diff)
downloadservo-4a0e01b4f033940b5d31ad1a47e322b2769ef1a5.tar.gz
servo-4a0e01b4f033940b5d31ad1a47e322b2769ef1a5.zip
Refactor how LayoutContext structure works (reduce TLS lookups + simplify fns used by seq/parallel code paths).
- LayoutContext is renamed to SharedLayoutContext. - SharedLayoutContext is immutable. - LayoutContext is a wrapper around SharedLayoutContext + access to local caches (font, style etc). - Creating a LayoutContext does a single local_data lookup to fetch the cache information. - Android shares same implementation of context.rs as other platforms. - LayoutContext can be used from both green thread (parallel layout) and native thread (sequential layout). - Removes the need for other types (such as FontContext, StyleSharingCandidateCache etc) to be passed around.
Diffstat (limited to 'src')
-rw-r--r--src/components/layout/block.rs50
-rw-r--r--src/components/layout/construct.rs52
-rw-r--r--src/components/layout/context.rs182
-rw-r--r--src/components/layout/css/matching.rs41
-rw-r--r--src/components/layout/flow.rs12
-rw-r--r--src/components/layout/fragment.rs8
-rw-r--r--src/components/layout/inline.rs8
-rw-r--r--src/components/layout/layout_task.rs74
-rw-r--r--src/components/layout/parallel.rs82
-rw-r--r--src/components/layout/table.rs10
-rw-r--r--src/components/layout/table_caption.rs6
-rw-r--r--src/components/layout/table_cell.rs8
-rw-r--r--src/components/layout/table_colgroup.rs6
-rw-r--r--src/components/layout/table_row.rs8
-rw-r--r--src/components/layout/table_rowgroup.rs8
-rw-r--r--src/components/layout/table_wrapper.rs12
16 files changed, 212 insertions, 355 deletions
diff --git a/src/components/layout/block.rs b/src/components/layout/block.rs
index 23a402f24c9..e72515088c2 100644
--- a/src/components/layout/block.rs
+++ b/src/components/layout/block.rs
@@ -402,7 +402,7 @@ fn translate_including_floats(cur_b: &mut Au, delta: Au, floats: &mut Floats) {
///
/// Note that flows with position 'fixed' just form a flat list as they all
/// have the Root flow as their CB.
-struct AbsoluteAssignBSizesTraversal<'a>(&'a mut LayoutContext);
+struct AbsoluteAssignBSizesTraversal<'a>(&'a LayoutContext<'a>);
impl<'a> PreorderFlowTraversal for AbsoluteAssignBSizesTraversal<'a> {
#[inline]
@@ -429,7 +429,7 @@ impl<'a> PreorderFlowTraversal for AbsoluteAssignBSizesTraversal<'a> {
/// After that, it is up to the normal store-overflow traversal to propagate
/// it further up.
struct AbsoluteStoreOverflowTraversal<'a>{
- layout_context: &'a mut LayoutContext,
+ layout_context: &'a LayoutContext<'a>,
}
impl<'a> PostorderFlowTraversal for AbsoluteStoreOverflowTraversal<'a> {
@@ -579,7 +579,7 @@ impl BlockFlow {
}
/// Compute the used value of inline-size for this Block.
- fn compute_used_inline_size(&mut self, ctx: &mut LayoutContext, containing_block_inline_size: Au) {
+ fn compute_used_inline_size(&mut self, ctx: &LayoutContext, containing_block_inline_size: Au) {
let block_type = self.block_type();
match block_type {
AbsoluteReplacedType => {
@@ -805,8 +805,8 @@ impl BlockFlow {
/// `inline(always)` because this is only ever called by in-order or non-in-order top-level
/// methods
#[inline(always)]
- pub fn assign_block_size_block_base(&mut self,
- layout_context: &mut LayoutContext,
+ pub fn assign_block_size_block_base<'a>(&mut self,
+ layout_context: &'a LayoutContext<'a>,
margins_may_collapse: MarginsMayCollapseFlag) {
// Our current border-box position.
let mut cur_b = Au(0);
@@ -949,7 +949,7 @@ impl BlockFlow {
let mut block_size = cur_b - block_start_offset;
if self.is_root() {
let screen_size = LogicalSize::from_physical(
- self.fragment.style.writing_mode, layout_context.screen_size);
+ self.fragment.style.writing_mode, layout_context.shared.screen_size);
block_size = Au::max(screen_size.block, block_size)
}
@@ -1053,7 +1053,7 @@ impl BlockFlow {
/// should be calculated using CSS Section 10.6.7
///
/// It does not calculate the block-size of the flow itself.
- pub fn assign_block_size_float(&mut self, ctx: &mut LayoutContext) {
+ pub fn assign_block_size_float<'a>(&mut self, ctx: &'a LayoutContext<'a>) {
let mut floats = Floats::new(self.fragment.style.writing_mode);
for kid in self.base.child_iter() {
flow::mut_base(kid).floats = floats.clone();
@@ -1179,7 +1179,7 @@ impl BlockFlow {
/// + y-coordinate of the flow wrt its Containing Block.
/// + block-size, vertical margins, and y-coordinate for the flow's box.
fn calculate_abs_block_size_and_margins(&mut self, ctx: &LayoutContext) {
- let containing_block_block_size = self.containing_block_size(ctx.screen_size).block;
+ let containing_block_block_size = self.containing_block_size(ctx.shared.screen_size).block;
let static_b_offset = self.static_b_offset;
// This is the stored content block-size value from assign-block-size
@@ -1445,7 +1445,7 @@ impl Flow for BlockFlow {
/// any fragments it is responsible for flowing.
///
/// TODO(pcwalton): Inline blocks.
- fn bubble_inline_sizes(&mut self, _: &mut LayoutContext) {
+ fn bubble_inline_sizes(&mut self, _: &LayoutContext) {
let mut flags = self.base.flags;
flags.set_has_left_floated_descendants(false);
flags.set_has_right_floated_descendants(false);
@@ -1489,7 +1489,7 @@ impl Flow for BlockFlow {
///
/// Dual fragments consume some inline-size first, and the remainder is assigned to all child (block)
/// contexts.
- fn assign_inline_sizes(&mut self, layout_context: &mut LayoutContext) {
+ fn assign_inline_sizes(&mut self, layout_context: &LayoutContext) {
debug!("assign_inline_sizes({}): assigning inline_size for flow",
if self.is_float() {
"float"
@@ -1501,7 +1501,7 @@ impl Flow for BlockFlow {
debug!("Setting root position");
self.base.position.start = LogicalPoint::zero(self.base.writing_mode);
self.base.position.size.inline = LogicalSize::from_physical(
- self.base.writing_mode, layout_context.screen_size).inline;
+ self.base.writing_mode, layout_context.shared.screen_size).inline;
self.base.floats = Floats::new(self.base.writing_mode);
// The root element is never impacted by floats.
@@ -1559,7 +1559,7 @@ impl Flow for BlockFlow {
///
/// This is called on child flows by the parent. Hence, we can assume that `assign_block-size` has
/// already been called on the child (because of the bottom-up traversal).
- fn assign_block_size_for_inorder_child_if_necessary(&mut self, layout_context: &mut LayoutContext)
+ fn assign_block_size_for_inorder_child_if_necessary<'a>(&mut self, layout_context: &'a LayoutContext<'a>)
-> bool {
if self.is_float() {
self.place_float();
@@ -1573,7 +1573,7 @@ impl Flow for BlockFlow {
impacted
}
- fn assign_block_size(&mut self, ctx: &mut LayoutContext) {
+ fn assign_block_size<'a>(&mut self, ctx: &'a LayoutContext<'a>) {
// Assign block-size for fragment if it is an image fragment.
self.fragment.assign_replaced_block_size_if_necessary();
@@ -1794,7 +1794,7 @@ pub trait ISizeAndMarginsComputer {
fn compute_inline_size_constraint_inputs(&self,
block: &mut BlockFlow,
parent_flow_inline_size: Au,
- ctx: &mut LayoutContext)
+ ctx: &LayoutContext)
-> ISizeConstraintInput {
let containing_block_inline_size = self.containing_block_inline_size(block, parent_flow_inline_size, ctx);
let computed_inline_size = self.initial_computed_inline_size(block, parent_flow_inline_size, ctx);
@@ -1864,7 +1864,7 @@ pub trait ISizeAndMarginsComputer {
fn initial_computed_inline_size(&self,
block: &mut BlockFlow,
parent_flow_inline_size: Au,
- ctx: &mut LayoutContext)
+ ctx: &LayoutContext)
-> MaybeAuto {
MaybeAuto::from_style(block.fragment().style().content_inline_size(),
self.containing_block_inline_size(block, parent_flow_inline_size, ctx))
@@ -1873,7 +1873,7 @@ pub trait ISizeAndMarginsComputer {
fn containing_block_inline_size(&self,
_: &mut BlockFlow,
parent_flow_inline_size: Au,
- _: &mut LayoutContext)
+ _: &LayoutContext)
-> Au {
parent_flow_inline_size
}
@@ -1883,7 +1883,7 @@ pub trait ISizeAndMarginsComputer {
/// CSS Section 10.4: Minimum and Maximum inline-sizes
fn compute_used_inline_size(&self,
block: &mut BlockFlow,
- ctx: &mut LayoutContext,
+ ctx: &LayoutContext,
parent_flow_inline_size: Au) {
let mut input = self.compute_inline_size_constraint_inputs(block, parent_flow_inline_size, ctx);
@@ -2127,8 +2127,8 @@ impl ISizeAndMarginsComputer for AbsoluteNonReplaced {
ISizeConstraintSolution::for_absolute_flow(inline_start, inline_end, inline_size, margin_inline_start, margin_inline_end)
}
- fn containing_block_inline_size(&self, block: &mut BlockFlow, _: Au, ctx: &mut LayoutContext) -> Au {
- block.containing_block_size(ctx.screen_size).inline
+ fn containing_block_inline_size(&self, block: &mut BlockFlow, _: Au, ctx: &LayoutContext) -> Au {
+ block.containing_block_size(ctx.shared.screen_size).inline
}
fn set_flow_x_coord_if_necessary(&self,
@@ -2241,9 +2241,9 @@ impl ISizeAndMarginsComputer for AbsoluteReplaced {
fn initial_computed_inline_size(&self,
block: &mut BlockFlow,
_: Au,
- ctx: &mut LayoutContext)
+ ctx: &LayoutContext)
-> MaybeAuto {
- let containing_block_inline_size = block.containing_block_size(ctx.screen_size).inline;
+ let containing_block_inline_size = block.containing_block_size(ctx.shared.screen_size).inline;
let fragment = block.fragment();
fragment.assign_replaced_inline_size_if_necessary(containing_block_inline_size, None);
// For replaced absolute flow, the rest of the constraint solving will
@@ -2251,8 +2251,8 @@ impl ISizeAndMarginsComputer for AbsoluteReplaced {
Specified(fragment.content_inline_size())
}
- fn containing_block_inline_size(&self, block: &mut BlockFlow, _: Au, ctx: &mut LayoutContext) -> Au {
- block.containing_block_size(ctx.screen_size).inline
+ fn containing_block_inline_size(&self, block: &mut BlockFlow, _: Au, ctx: &LayoutContext) -> Au {
+ block.containing_block_size(ctx.shared.screen_size).inline
}
fn set_flow_x_coord_if_necessary(&self, block: &mut BlockFlow, solution: ISizeConstraintSolution) {
@@ -2291,7 +2291,7 @@ impl ISizeAndMarginsComputer for BlockReplaced {
fn initial_computed_inline_size(&self,
block: &mut BlockFlow,
parent_flow_inline_size: Au,
- _: &mut LayoutContext)
+ _: &LayoutContext)
-> MaybeAuto {
let fragment = block.fragment();
fragment.assign_replaced_inline_size_if_necessary(parent_flow_inline_size, None);
@@ -2347,7 +2347,7 @@ impl ISizeAndMarginsComputer for FloatReplaced {
fn initial_computed_inline_size(&self,
block: &mut BlockFlow,
parent_flow_inline_size: Au,
- _: &mut LayoutContext)
+ _: &LayoutContext)
-> MaybeAuto {
let fragment = block.fragment();
fragment.assign_replaced_inline_size_if_necessary(parent_flow_inline_size, None);
diff --git a/src/components/layout/construct.rs b/src/components/layout/construct.rs
index a780c073f17..db6084a1c02 100644
--- a/src/components/layout/construct.rs
+++ b/src/components/layout/construct.rs
@@ -47,7 +47,6 @@ use wrapper::{PostorderNodeMutTraversal, TLayoutNode, ThreadSafeLayoutNode};
use wrapper::{Before, BeforeBlock, After, AfterBlock, Normal};
use gfx::display_list::OpaqueNode;
-use gfx::font_context::FontContext;
use script::dom::element::{HTMLIFrameElementTypeId, HTMLImageElementTypeId};
use script::dom::element::{HTMLObjectElementTypeId};
use script::dom::element::{HTMLTableColElementTypeId, HTMLTableDataCellElementTypeId};
@@ -184,47 +183,20 @@ enum WhitespaceStrippingMode {
}
/// An object that knows how to create flows.
-pub struct FlowConstructor<'a> {
+pub struct FlowConstructor<'a, 'b> {
/// The layout context.
- pub layout_context: &'a mut LayoutContext,
-
- /// An optional font context. If this is `None`, then we fetch the font context from the
- /// layout context.
- ///
- /// FIXME(pcwalton): This is pretty bogus and is basically just a workaround for libgreen
- /// having slow TLS.
- pub font_context: Option<Box<FontContext>>,
+ pub layout_context: &'b LayoutContext<'b>,
}
-impl<'a> FlowConstructor<'a> {
+impl<'a, 'b> FlowConstructor<'a, 'b> {
/// Creates a new flow constructor.
- pub fn new(layout_context: &'a mut LayoutContext, font_context: Option<Box<FontContext>>)
- -> FlowConstructor<'a> {
+ pub fn new<'b>(layout_context: &'b LayoutContext)
+ -> FlowConstructor<'a, 'b> {
FlowConstructor {
layout_context: layout_context,
- font_context: font_context,
}
}
- fn font_context<'a>(&'a mut self) -> &'a mut FontContext {
- match self.font_context {
- Some(ref mut font_context) => {
- let font_context: &mut FontContext = &mut **font_context;
- font_context
- }
- None => self.layout_context.font_context(),
- }
- }
-
- /// Destroys this flow constructor and retrieves the font context.
- pub fn unwrap_font_context(self) -> Option<Box<FontContext>> {
- let FlowConstructor {
- font_context,
- ..
- } = self;
- font_context
- }
-
/// Builds the `ImageFragmentInfo` for the given image. This is out of line to guide inlining.
fn build_fragment_info_for_image(&mut self, node: &ThreadSafeLayoutNode, url: Option<Url>)
-> SpecificFragmentInfo {
@@ -233,7 +205,7 @@ impl<'a> FlowConstructor<'a> {
Some(url) => {
// FIXME(pcwalton): The fact that image fragments store the cache within them makes
// little sense to me.
- ImageFragment(ImageFragmentInfo::new(node, url, self.layout_context.image_cache.clone()))
+ ImageFragment(ImageFragmentInfo::new(node, url, self.layout_context.shared.image_cache.clone()))
}
}
}
@@ -293,11 +265,11 @@ impl<'a> FlowConstructor<'a> {
}
let mut inline_flow = box InlineFlow::from_fragments((*node).clone(), fragments);
- let (ascent, descent) = inline_flow.compute_minimum_ascent_and_descent(self.font_context(), &**node.style());
+ let (ascent, descent) = inline_flow.compute_minimum_ascent_and_descent(self.layout_context.font_context(), &**node.style());
inline_flow.minimum_block_size_above_baseline = ascent;
inline_flow.minimum_depth_below_baseline = descent;
let mut inline_flow = inline_flow as Box<Flow>;
- TextRunScanner::new().scan_for_runs(self.font_context(), inline_flow);
+ TextRunScanner::new().scan_for_runs(self.layout_context.font_context(), inline_flow);
let mut inline_flow = FlowRef::new(inline_flow);
inline_flow.finish(self.layout_context);
@@ -797,7 +769,7 @@ impl<'a> FlowConstructor<'a> {
}
}
-impl<'a> PostorderNodeMutTraversal for FlowConstructor<'a> {
+impl<'a, 'b> PostorderNodeMutTraversal for FlowConstructor<'a, 'b> {
// Construct Flow based on 'display', 'position', and 'float' values.
//
// CSS 2.1 Section 9.7
@@ -1039,7 +1011,7 @@ pub trait FlowConstructionUtils {
///
/// All flows must be finished at some point, or they will not have their intrinsic inline-sizes
/// properly computed. (This is not, however, a memory safety problem.)
- fn finish(&mut self, context: &mut LayoutContext);
+ fn finish(&mut self, context: &LayoutContext);
}
impl FlowConstructionUtils for FlowRef {
@@ -1066,8 +1038,8 @@ impl FlowConstructionUtils for FlowRef {
/// properly computed. (This is not, however, a memory safety problem.)
///
/// This must not be public because only the layout constructor can do this.
- fn finish(&mut self, context: &mut LayoutContext) {
- if !context.opts.bubble_inline_sizes_separately {
+ fn finish(&mut self, context: &LayoutContext) {
+ if !context.shared.opts.bubble_inline_sizes_separately {
self.get_mut().bubble_inline_sizes(context)
}
}
diff --git a/src/components/layout/context.rs b/src/components/layout/context.rs
index 0a58e3a761a..936314dcb63 100644
--- a/src/components/layout/context.rs
+++ b/src/components/layout/context.rs
@@ -10,8 +10,6 @@ use geom::{Rect, Size2D};
use gfx::display_list::OpaqueNode;
use gfx::font_context::FontContext;
use gfx::font_cache_task::FontCacheTask;
-#[cfg(not(target_os="android"))]
-use green::task::GreenTask;
use script::layout_interface::LayoutChan;
use servo_msg::constellation_msg::ConstellationChan;
use servo_net::local_image_cache::LocalImageCache;
@@ -19,42 +17,37 @@ use servo_util::geometry::Au;
use servo_util::opts::Opts;
use sync::{Arc, Mutex};
use std::mem;
-#[cfg(not(target_os="android"))]
-use std::ptr;
-#[cfg(not(target_os="android"))]
-use std::rt::local::Local;
-#[cfg(not(target_os="android"))]
-use std::rt::task::Task;
use style::Stylist;
use url::Url;
-#[cfg(not(target_os="android"))]
-#[thread_local]
-static mut FONT_CONTEXT: *mut FontContext = 0 as *mut FontContext;
-
-#[cfg(target_os="android")]
-local_data_key!(font_context: *mut FontContext)
-
-#[cfg(not(target_os="android"))]
-#[thread_local]
-static mut APPLICABLE_DECLARATIONS_CACHE: *mut ApplicableDeclarationsCache =
- 0 as *mut ApplicableDeclarationsCache;
-
-#[cfg(target_os="android")]
-local_data_key!(applicable_declarations_cache: *mut ApplicableDeclarationsCache)
-
-#[cfg(not(target_os="android"))]
-#[thread_local]
-static mut STYLE_SHARING_CANDIDATE_CACHE: *mut StyleSharingCandidateCache =
- 0 as *mut StyleSharingCandidateCache;
+struct LocalLayoutContext {
+ font_context: FontContext,
+ applicable_declarations_cache: ApplicableDeclarationsCache,
+ style_sharing_candidate_cache: StyleSharingCandidateCache,
+}
-#[cfg(target_os="android")]
-local_data_key!(style_sharing_candidate_cache: *mut StyleSharingCandidateCache)
+local_data_key!(local_context_key: *mut LocalLayoutContext)
+
+fn create_or_get_local_context(shared_layout_context: &SharedLayoutContext) -> *mut LocalLayoutContext {
+ let maybe_context = local_context_key.get();
+
+ let context = match maybe_context {
+ None => {
+ let context = box LocalLayoutContext {
+ font_context: FontContext::new(shared_layout_context.font_cache_task.clone()),
+ applicable_declarations_cache: ApplicableDeclarationsCache::new(),
+ style_sharing_candidate_cache: StyleSharingCandidateCache::new(),
+ };
+ local_context_key.replace(Some(unsafe { mem::transmute(context) }));
+ local_context_key.get().unwrap()
+ },
+ Some(context) => context
+ };
+
+ *context
+}
-/// Data shared by all layout workers.
-#[allow(raw_pointer_deriving)]
-#[deriving(Clone)]
-pub struct LayoutContext {
+pub struct SharedLayoutContext {
/// The local image cache.
pub image_cache: Arc<Mutex<LocalImageCache>>,
@@ -88,126 +81,43 @@ pub struct LayoutContext {
pub dirty: Rect<Au>,
}
-#[cfg(not(target_os="android"))]
-impl LayoutContext {
- pub fn font_context<'a>(&'a mut self) -> &'a mut FontContext {
- // Sanity check.
- {
- let mut task = Local::borrow(None::<Task>);
- match task.maybe_take_runtime::<GreenTask>() {
- Some(green) => {
- task.put_runtime(green);
- fail!("can't call this on a green task!")
- }
- None => {}
- }
- }
-
- unsafe {
- if FONT_CONTEXT == ptr::mut_null() {
- let context = box FontContext::new(self.font_cache_task.clone());
- FONT_CONTEXT = mem::transmute(context)
- }
- mem::transmute(FONT_CONTEXT)
- }
- }
-
- pub fn applicable_declarations_cache<'a>(&'a self) -> &'a mut ApplicableDeclarationsCache {
- // Sanity check.
- {
- let mut task = Local::borrow(None::<Task>);
- match task.maybe_take_runtime::<GreenTask>() {
- Some(green) => {
- task.put_runtime(green);
- fail!("can't call this on a green task!")
- }
- None => {}
- }
- }
+pub struct LayoutContext<'a> {
+ pub shared: &'a SharedLayoutContext,
+ cached_local_layout_context: *mut LocalLayoutContext,
+}
- unsafe {
- if APPLICABLE_DECLARATIONS_CACHE == ptr::mut_null() {
- let cache = box ApplicableDeclarationsCache::new();
- APPLICABLE_DECLARATIONS_CACHE = mem::transmute(cache)
- }
- mem::transmute(APPLICABLE_DECLARATIONS_CACHE)
- }
- }
+impl<'a> LayoutContext<'a> {
+ pub fn new(shared_layout_context: &'a SharedLayoutContext) -> LayoutContext<'a> {
- pub fn style_sharing_candidate_cache<'a>(&'a self) -> &'a mut StyleSharingCandidateCache {
- // Sanity check.
- {
- let mut task = Local::borrow(None::<Task>);
- match task.maybe_take_runtime::<GreenTask>() {
- Some(green) => {
- task.put_runtime(green);
- fail!("can't call this on a green task!")
- }
- None => {}
- }
- }
+ let local_context = create_or_get_local_context(shared_layout_context);
- unsafe {
- if STYLE_SHARING_CANDIDATE_CACHE == ptr::mut_null() {
- let cache = box StyleSharingCandidateCache::new();
- STYLE_SHARING_CANDIDATE_CACHE = mem::transmute(cache)
- }
- mem::transmute(STYLE_SHARING_CANDIDATE_CACHE)
+ LayoutContext {
+ shared: shared_layout_context,
+ cached_local_layout_context: local_context,
}
}
-}
-
-// On Android, we don't have the __tls_* functions emitted by rustc, so we
-// need to use the slower local_data functions.
-// Making matters worse, the local_data functions are very particular about
-// enforcing the lifetimes associated with objects that they hold onto,
-// which causes us some trouble we work around as below.
-#[cfg(target_os="android")]
-impl LayoutContext {
- pub fn font_context<'a>(&'a mut self) -> &'a mut FontContext {
+ #[inline(always)]
+ pub fn font_context<'a>(&'a self) -> &'a mut FontContext {
unsafe {
- let opt = font_context.replace(None);
- let mut context;
- match opt {
- Some(c) => context = mem::transmute(c),
- None => {
- context = mem::transmute(box FontContext::new(self.font_cache_task.clone()))
- }
- }
- font_context.replace(Some(context));
- mem::transmute(context)
+ let cached_context = &*self.cached_local_layout_context;
+ mem::transmute(&cached_context.font_context)
}
}
+ #[inline(always)]
pub fn applicable_declarations_cache<'a>(&'a self) -> &'a mut ApplicableDeclarationsCache {
unsafe {
- let opt = applicable_declarations_cache.replace(None);
- let mut cache;
- match opt {
- Some(c) => cache = mem::transmute(c),
- None => {
- cache = mem::transmute(box ApplicableDeclarationsCache::new());
- }
- }
- applicable_declarations_cache.replace(Some(cache));
- mem::transmute(cache)
+ let cached_context = &*self.cached_local_layout_context;
+ mem::transmute(&cached_context.applicable_declarations_cache)
}
}
+ #[inline(always)]
pub fn style_sharing_candidate_cache<'a>(&'a self) -> &'a mut StyleSharingCandidateCache {
unsafe {
- let opt = style_sharing_candidate_cache.replace(None);
- let mut cache;
- match opt {
- Some(c) => cache = mem::transmute(c),
- None => {
- cache = mem::transmute(box StyleSharingCandidateCache::new());
- }
- }
- style_sharing_candidate_cache.replace(Some(cache));
- mem::transmute(cache)
+ let cached_context = &*self.cached_local_layout_context;
+ mem::transmute(&cached_context.style_sharing_candidate_cache)
}
}
}
-
diff --git a/src/components/layout/css/matching.rs b/src/components/layout/css/matching.rs
index f6104195dab..3c7ee0d9a4c 100644
--- a/src/components/layout/css/matching.rs
+++ b/src/components/layout/css/matching.rs
@@ -11,7 +11,6 @@ use extra::LayoutAuxMethods;
use util::{LayoutDataAccess, LayoutDataWrapper};
use wrapper::{LayoutElement, LayoutNode, PostorderNodeMutTraversal, ThreadSafeLayoutNode};
-use gfx::font_context::FontContext;
use servo_util::atom::Atom;
use servo_util::cache::{Cache, LRUCache, SimpleHashCache};
use servo_util::namespace::Null;
@@ -283,13 +282,9 @@ pub trait MatchMethods {
/// sequentially.
fn recalc_style_for_subtree(&self,
stylist: &Stylist,
- layout_context: &mut LayoutContext,
- mut font_context: Box<FontContext>,
+ layout_context: &LayoutContext,
applicable_declarations: &mut ApplicableDeclarations,
- applicable_declarations_cache: &mut ApplicableDeclarationsCache,
- style_sharing_candidate_cache: &mut StyleSharingCandidateCache,
- parent: Option<LayoutNode>)
- -> Box<FontContext>;
+ parent: Option<LayoutNode>);
fn match_node(&self,
stylist: &Stylist,
@@ -462,18 +457,14 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
fn recalc_style_for_subtree(&self,
stylist: &Stylist,
- layout_context: &mut LayoutContext,
- mut font_context: Box<FontContext>,
+ layout_context: &LayoutContext,
applicable_declarations: &mut ApplicableDeclarations,
- applicable_declarations_cache: &mut ApplicableDeclarationsCache,
- style_sharing_candidate_cache: &mut StyleSharingCandidateCache,
- parent: Option<LayoutNode>)
- -> Box<FontContext> {
- self.initialize_layout_data(layout_context.layout_chan.clone());
+ parent: Option<LayoutNode>) {
+ self.initialize_layout_data(layout_context.shared.layout_chan.clone());
// First, check to see whether we can share a style with someone.
let sharing_result = unsafe {
- self.share_style_if_possible(style_sharing_candidate_cache, parent.clone())
+ self.share_style_if_possible(layout_context.style_sharing_candidate_cache(), parent.clone())
};
// Otherwise, match and cascade selectors.
@@ -486,34 +477,30 @@ impl<'ln> MatchMethods for LayoutNode<'ln> {
unsafe {
self.cascade_node(parent,
applicable_declarations,
- applicable_declarations_cache)
+ layout_context.applicable_declarations_cache())
}
applicable_declarations.clear();
// Add ourselves to the LRU cache.
if shareable {
- style_sharing_candidate_cache.insert_if_possible(self)
+ layout_context.style_sharing_candidate_cache().insert_if_possible(self)
}
}
- StyleWasShared(index) => style_sharing_candidate_cache.touch(index),
+ StyleWasShared(index) => layout_context.style_sharing_candidate_cache().touch(index),
}
for kid in self.children() {
- font_context = kid.recalc_style_for_subtree(stylist,
- layout_context,
- font_context,
- applicable_declarations,
- applicable_declarations_cache,
- style_sharing_candidate_cache,
- Some(self.clone()))
+ kid.recalc_style_for_subtree(stylist,
+ layout_context,
+ applicable_declarations,
+ Some(self.clone()))
}
// Construct flows.
let layout_node = ThreadSafeLayoutNode::new(self);
- let mut flow_constructor = FlowConstructor::new(layout_context, Some(font_context));
+ let mut flow_constructor = FlowConstructor::new(layout_context);
flow_constructor.process(&layout_node);
- flow_constructor.unwrap_font_context().unwrap()
}
unsafe fn cascade_node(&self,
diff --git a/src/components/layout/flow.rs b/src/components/layout/flow.rs
index 6f124ca81f1..e401a1f75c6 100644
--- a/src/components/layout/flow.rs
+++ b/src/components/layout/flow.rs
@@ -149,24 +149,24 @@ pub trait Flow: fmt::Show + ToString + Share {
/// this flow, all child flows have had their minimum and preferred inline-sizes set. This function
/// must decide minimum/preferred inline-sizes based on its children's inline-sizes and the dimensions of
/// any boxes it is responsible for flowing.
- fn bubble_inline_sizes(&mut self, _ctx: &mut LayoutContext) {
+ fn bubble_inline_sizes(&mut self, _ctx: &LayoutContext) {
fail!("bubble_inline_sizes not yet implemented")
}
/// Pass 2 of reflow: computes inline-size.
- fn assign_inline_sizes(&mut self, _ctx: &mut LayoutContext) {
+ fn assign_inline_sizes(&mut self, _ctx: &LayoutContext) {
fail!("assign_inline_sizes not yet implemented")
}
/// Pass 3a of reflow: computes block-size.
- fn assign_block_size(&mut self, _ctx: &mut LayoutContext) {
+ fn assign_block_size<'a>(&mut self, _ctx: &'a LayoutContext<'a>) {
fail!("assign_block_size not yet implemented")
}
/// Assigns block-sizes in-order; or, if this is a float, places the float. The default
/// implementation simply assigns block-sizes if this flow is impacted by floats. Returns true if
/// this child was impacted by floats or false otherwise.
- fn assign_block_size_for_inorder_child_if_necessary(&mut self, layout_context: &mut LayoutContext)
+ fn assign_block_size_for_inorder_child_if_necessary<'a>(&mut self, layout_context: &'a LayoutContext<'a>)
-> bool {
let impacted = base(&*self).flags.impacted_by_floats();
if impacted {
@@ -365,7 +365,7 @@ pub trait MutableFlowUtils {
// Mutators
/// Computes the overflow region for this flow.
- fn store_overflow(self, _: &mut LayoutContext);
+ fn store_overflow(self, _: &LayoutContext);
/// Builds the display lists for this flow.
fn build_display_list(self, layout_context: &LayoutContext);
@@ -963,7 +963,7 @@ impl<'a> MutableFlowUtils for &'a mut Flow {
/// Assumption: This is called in a bottom-up traversal, so kids' overflows have
/// already been set.
/// Assumption: Absolute descendants have had their overflow calculated.
- fn store_overflow(self, _: &mut LayoutContext) {
+ fn store_overflow(self, _: &LayoutContext) {
let my_position = mut_base(self).position;
let mut overflow = my_position;
diff --git a/src/components/layout/fragment.rs b/src/components/layout/fragment.rs
index ab004a3a17d..66ccb6b2d86 100644
--- a/src/components/layout/fragment.rs
+++ b/src/components/layout/fragment.rs
@@ -660,7 +660,7 @@ impl Fragment {
Some(ref image_url) => image_url,
};
- let mut holder = ImageHolder::new(image_url.clone(), layout_context.image_cache.clone());
+ let mut holder = ImageHolder::new(image_url.clone(), layout_context.shared.image_cache.clone());
let image = match holder.get_image() {
None => {
// No image data at all? Do nothing.
@@ -860,7 +860,7 @@ impl Fragment {
absolute_fragment_bounds,
self);
debug!("Fragment::build_display_list: dirty={}, flow_origin={}",
- layout_context.dirty,
+ layout_context.shared.dirty,
flow_origin);
let mut accumulator = ChildDisplayListAccumulator::new(self.style(),
@@ -871,7 +871,7 @@ impl Fragment {
return accumulator
}
- if !absolute_fragment_bounds.intersects(&layout_context.dirty) {
+ if !absolute_fragment_bounds.intersects(&layout_context.shared.dirty) {
debug!("Fragment::build_display_list: Did not intersect...");
return accumulator
}
@@ -1431,7 +1431,7 @@ impl Fragment {
iframe_fragment.pipeline_id,
iframe_fragment.subpage_id);
let msg = FrameRectMsg(iframe_fragment.pipeline_id, iframe_fragment.subpage_id, rect);
- let ConstellationChan(ref chan) = layout_context.constellation_chan;
+ let ConstellationChan(ref chan) = layout_context.shared.constellation_chan;
chan.send(msg)
}
}
diff --git a/src/components/layout/inline.rs b/src/components/layout/inline.rs
index e3aabadff35..89449ca5571 100644
--- a/src/components/layout/inline.rs
+++ b/src/components/layout/inline.rs
@@ -932,7 +932,7 @@ impl InlineFlow {
// FIXME(#2795): Get the real container size
let container_size = Size2D::zero();
if !abs_rect.to_physical(self.base.writing_mode, container_size)
- .intersects(&layout_context.dirty) {
+ .intersects(&layout_context.shared.dirty) {
return
}
@@ -1090,7 +1090,7 @@ impl Flow for InlineFlow {
self
}
- fn bubble_inline_sizes(&mut self, _: &mut LayoutContext) {
+ fn bubble_inline_sizes(&mut self, _: &LayoutContext) {
let writing_mode = self.base.writing_mode;
for kid in self.base.child_iter() {
flow::mut_base(kid).floats = Floats::new(writing_mode);
@@ -1115,7 +1115,7 @@ impl Flow for InlineFlow {
/// Recursively (top-down) determines the actual inline-size of child contexts and fragments. When called
/// on this context, the context has had its inline-size set by the parent context.
- fn assign_inline_sizes(&mut self, _: &mut LayoutContext) {
+ fn assign_inline_sizes(&mut self, _: &LayoutContext) {
// Initialize content fragment inline-sizes if they haven't been initialized already.
//
// TODO: Combine this with `LineBreaker`'s walk in the fragment list, or put this into `Fragment`.
@@ -1144,7 +1144,7 @@ impl Flow for InlineFlow {
}
/// Calculate and set the block-size of this flow. See CSS 2.1 § 10.6.1.
- fn assign_block_size(&mut self, _: &mut LayoutContext) {
+ fn assign_block_size(&mut self, _: &LayoutContext) {
debug!("assign_block_size_inline: assigning block_size for flow");
// Divide the fragments into lines.
diff --git a/src/components/layout/layout_task.rs b/src/components/layout/layout_task.rs
index 83809aa137e..0edb9436771 100644
--- a/src/components/layout/layout_task.rs
+++ b/src/components/layout/layout_task.rs
@@ -5,12 +5,11 @@
//! The layout task. Performs layout on the DOM, builds display lists and sends them to be
//! rendered.
-use css::matching::{ApplicableDeclarations, ApplicableDeclarationsCache, MatchMethods};
-use css::matching::{StyleSharingCandidateCache};
+use css::matching::{ApplicableDeclarations, MatchMethods};
use css::select::new_stylist;
use css::node_style::StyledNode;
use construct::{FlowConstructionResult, NoConstructionResult};
-use context::LayoutContext;
+use context::{LayoutContext, SharedLayoutContext};
use flow::{Flow, ImmutableFlowUtils, MutableFlowUtils, MutableOwnedFlowUtils};
use flow::{PreorderFlowTraversal, PostorderFlowTraversal};
use flow;
@@ -27,7 +26,6 @@ use geom::rect::Rect;
use geom::size::Size2D;
use gfx::display_list::{ClipDisplayItemClass, ContentStackingLevel, DisplayItem};
use gfx::display_list::{DisplayItemIterator, DisplayList, OpaqueNode};
-use gfx::font_context::FontContext;
use gfx::render_task::{RenderInitMsg, RenderChan, RenderLayer};
use gfx::{render_task, color};
use layout_traits;
@@ -104,7 +102,7 @@ pub struct LayoutTask {
pub stylist: Box<Stylist>,
/// The workers that we use for parallel operation.
- pub parallel_traversal: Option<WorkQueue<*mut LayoutContext,UnsafeFlow>>,
+ pub parallel_traversal: Option<WorkQueue<*const SharedLayoutContext,UnsafeFlow>>,
/// The channel on which messages can be sent to the time profiler.
pub time_profiler_chan: TimeProfilerChan,
@@ -178,7 +176,7 @@ impl PreorderFlowTraversal for FlowTreeVerificationTraversal {
/// The bubble-inline-sizes traversal, the first part of layout computation. This computes preferred
/// and intrinsic inline-sizes and bubbles them up the tree.
pub struct BubbleISizesTraversal<'a> {
- pub layout_context: &'a mut LayoutContext,
+ pub layout_context: &'a LayoutContext<'a>,
}
impl<'a> PostorderFlowTraversal for BubbleISizesTraversal<'a> {
@@ -199,7 +197,7 @@ impl<'a> PostorderFlowTraversal for BubbleISizesTraversal<'a> {
/// The assign-inline-sizes traversal. In Gecko this corresponds to `Reflow`.
pub struct AssignISizesTraversal<'a> {
- pub layout_context: &'a mut LayoutContext,
+ pub layout_context: &'a LayoutContext<'a>,
}
impl<'a> PreorderFlowTraversal for AssignISizesTraversal<'a> {
@@ -214,7 +212,7 @@ impl<'a> PreorderFlowTraversal for AssignISizesTraversal<'a> {
/// computation. Determines the final block-sizes for all layout objects, computes positions, and
/// computes overflow regions. In Gecko this corresponds to `FinishAndStoreOverflow`.
pub struct AssignBSizesAndStoreOverflowTraversal<'a> {
- pub layout_context: &'a mut LayoutContext,
+ pub layout_context: &'a LayoutContext<'a>,
}
impl<'a> PostorderFlowTraversal for AssignBSizesAndStoreOverflowTraversal<'a> {
@@ -237,7 +235,7 @@ impl<'a> PostorderFlowTraversal for AssignBSizesAndStoreOverflowTraversal<'a> {
/// The display list construction traversal.
pub struct BuildDisplayListTraversal<'a> {
- layout_context: &'a LayoutContext,
+ layout_context: &'a LayoutContext<'a>,
}
impl<'a> BuildDisplayListTraversal<'a> {
@@ -330,7 +328,7 @@ impl LayoutTask {
let local_image_cache = Arc::new(Mutex::new(LocalImageCache::new(image_cache_task.clone())));
let screen_size = Size2D(Au(0), Au(0));
let parallel_traversal = if opts.layout_threads != 1 {
- Some(WorkQueue::new("LayoutWorker", opts.layout_threads, ptr::mut_null()))
+ Some(WorkQueue::new("LayoutWorker", opts.layout_threads, ptr::null()))
} else {
None
};
@@ -365,8 +363,8 @@ impl LayoutTask {
}
// Create a layout context for use in building display lists, hit testing, &c.
- fn build_layout_context(&self, reflow_root: &LayoutNode, url: &Url) -> LayoutContext {
- LayoutContext {
+ fn build_shared_layout_context(&self, reflow_root: &LayoutNode, url: &Url) -> SharedLayoutContext {
+ SharedLayoutContext {
image_cache: self.local_image_cache.clone(),
screen_size: self.screen_size.clone(),
constellation_chan: self.constellation_chan.clone(),
@@ -542,10 +540,10 @@ impl LayoutTask {
/// This corresponds to `Reflow()` in Gecko and `layout()` in WebKit/Blink and should be
/// benchmarked against those two. It is marked `#[inline(never)]` to aid profiling.
#[inline(never)]
- fn solve_constraints(&mut self,
+ fn solve_constraints<'a>(&mut self,
layout_root: &mut Flow,
- layout_context: &mut LayoutContext) {
- if layout_context.opts.bubble_inline_sizes_separately {
+ layout_context: &'a LayoutContext<'a>) {
+ if layout_context.shared.opts.bubble_inline_sizes_separately {
let mut traversal = BubbleISizesTraversal {
layout_context: layout_context,
};
@@ -580,10 +578,10 @@ impl LayoutTask {
#[inline(never)]
fn solve_constraints_parallel(&mut self,
layout_root: &mut FlowRef,
- layout_context: &mut LayoutContext) {
- if layout_context.opts.bubble_inline_sizes_separately {
+ shared_layout_context: &SharedLayoutContext) {
+ if shared_layout_context.opts.bubble_inline_sizes_separately {
let mut traversal = BubbleISizesTraversal {
- layout_context: layout_context,
+ layout_context: &LayoutContext::new(shared_layout_context),
};
layout_root.get_mut().traverse_postorder(&mut traversal);
}
@@ -595,7 +593,7 @@ impl LayoutTask {
// operation out.
parallel::traverse_flow_tree_preorder(layout_root,
self.time_profiler_chan.clone(),
- layout_context,
+ shared_layout_context,
traversal);
}
}
@@ -654,17 +652,7 @@ impl LayoutTask {
self.screen_size = current_screen_size;
// Create a layout context for use throughout the following passes.
- let mut layout_ctx = self.build_layout_context(node, &data.url);
-
- // Create a font context, if this is sequential.
- //
- // FIXME(pcwalton): This is a pretty bogus thing to do. Essentially this is a workaround
- // for libgreen having slow TLS.
- let mut font_context_opt = if self.parallel_traversal.is_none() {
- Some(box FontContext::new(layout_ctx.font_cache_task.clone()))
- } else {
- None
- };
+ let mut shared_layout_ctx = self.build_shared_layout_context(node, &data.url);
let mut layout_root = profile(time::LayoutStyleRecalcCategory,
self.time_profiler_chan.clone(),
@@ -672,19 +660,15 @@ impl LayoutTask {
// Perform CSS selector matching and flow construction.
match self.parallel_traversal {
None => {
+ let layout_ctx = LayoutContext::new(&shared_layout_ctx);
let mut applicable_declarations = ApplicableDeclarations::new();
- let mut applicable_declarations_cache = ApplicableDeclarationsCache::new();
- let mut style_sharing_candidate_cache = StyleSharingCandidateCache::new();
- drop(node.recalc_style_for_subtree(&*self.stylist,
- &mut layout_ctx,
- font_context_opt.take_unwrap(),
- &mut applicable_declarations,
- &mut applicable_declarations_cache,
- &mut style_sharing_candidate_cache,
- None))
+ node.recalc_style_for_subtree(&*self.stylist,
+ &layout_ctx,
+ &mut applicable_declarations,
+ None)
}
Some(ref mut traversal) => {
- parallel::recalc_style_for_subtree(node, &mut layout_ctx, traversal)
+ parallel::recalc_style_for_subtree(node, &mut shared_layout_ctx, traversal)
}
}
@@ -710,11 +694,12 @@ impl LayoutTask {
match self.parallel_traversal {
None => {
// Sequential mode.
- self.solve_constraints(layout_root.get_mut(), &mut layout_ctx)
+ let layout_ctx = LayoutContext::new(&shared_layout_ctx);
+ self.solve_constraints(layout_root.get_mut(), &layout_ctx)
}
Some(_) => {
// Parallel mode.
- self.solve_constraints_parallel(&mut layout_root, &mut layout_ctx)
+ self.solve_constraints_parallel(&mut layout_root, &mut shared_layout_ctx)
}
}
});
@@ -725,11 +710,12 @@ impl LayoutTask {
profile(time::LayoutDispListBuildCategory, self.time_profiler_chan.clone(), || {
// FIXME(#2795): Get the real container size
let container_size = Size2D::zero();
- layout_ctx.dirty = flow::base(layout_root.get()).position.to_physical(
+ shared_layout_ctx.dirty = flow::base(layout_root.get()).position.to_physical(
writing_mode, container_size);
match self.parallel_traversal {
None => {
+ let layout_ctx = LayoutContext::new(&shared_layout_ctx);
let mut traversal = BuildDisplayListTraversal {
layout_context: &layout_ctx,
};
@@ -738,7 +724,7 @@ impl LayoutTask {
Some(ref mut traversal) => {
parallel::build_display_list_for_subtree(&mut layout_root,
self.time_profiler_chan.clone(),
- &mut layout_ctx,
+ &mut shared_layout_ctx,
traversal);
}
}
diff --git a/src/components/layout/parallel.rs b/src/components/layout/parallel.rs
index aa184cafda6..a2786e8ba91 100644
--- a/src/components/layout/parallel.rs
+++ b/src/components/layout/parallel.rs
@@ -8,7 +8,7 @@
use css::matching::{ApplicableDeclarations, CannotShare, MatchMethods, StyleWasShared};
use construct::FlowConstructor;
-use context::LayoutContext;
+use context::{LayoutContext, SharedLayoutContext};
use extra::LayoutAuxMethods;
use flow::{Flow, MutableFlowUtils, PreorderFlowTraversal, PostorderFlowTraversal};
use flow;
@@ -116,7 +116,7 @@ trait ParallelPostorderFlowTraversal : PostorderFlowTraversal {
/// fetch-and-subtract the parent's children count.
fn run_parallel(&mut self,
mut unsafe_flow: UnsafeFlow,
- _: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) {
+ _: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
loop {
unsafe {
// Get a real flow.
@@ -160,17 +160,17 @@ trait ParallelPostorderFlowTraversal : PostorderFlowTraversal {
trait ParallelPreorderFlowTraversal : PreorderFlowTraversal {
fn run_parallel(&mut self,
unsafe_flow: UnsafeFlow,
- proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>);
+ proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>);
#[inline(always)]
fn run_parallel_helper(&mut self,
unsafe_flow: UnsafeFlow,
- proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>,
+ proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>,
top_down_func: extern "Rust" fn(UnsafeFlow,
- &mut WorkerProxy<*mut LayoutContext,
+ &mut WorkerProxy<*const SharedLayoutContext,
UnsafeFlow>),
bottom_up_func: extern "Rust" fn(UnsafeFlow,
- &mut WorkerProxy<*mut LayoutContext,
+ &mut WorkerProxy<*const SharedLayoutContext,
UnsafeFlow>)) {
let mut had_children = false;
unsafe {
@@ -203,7 +203,7 @@ impl<'a> ParallelPostorderFlowTraversal for BubbleISizesTraversal<'a> {}
impl<'a> ParallelPreorderFlowTraversal for AssignISizesTraversal<'a> {
fn run_parallel(&mut self,
unsafe_flow: UnsafeFlow,
- proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) {
+ proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
self.run_parallel_helper(unsafe_flow,
proxy,
assign_inline_sizes,
@@ -214,8 +214,9 @@ impl<'a> ParallelPreorderFlowTraversal for AssignISizesTraversal<'a> {
impl<'a> ParallelPostorderFlowTraversal for AssignBSizesAndStoreOverflowTraversal<'a> {}
fn recalc_style_for_node(unsafe_layout_node: UnsafeLayoutNode,
- proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeLayoutNode>) {
- let layout_context = unsafe { &mut **proxy.user_data() };
+ proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeLayoutNode>) {
+ let shared_layout_context = unsafe { &**proxy.user_data() };
+ let layout_context = LayoutContext::new(shared_layout_context);
// Get a real layout node.
let node: LayoutNode = unsafe {
@@ -226,11 +227,11 @@ fn recalc_style_for_node(unsafe_layout_node: UnsafeLayoutNode,
//
// FIXME(pcwalton): Stop allocating here. Ideally this should just be done by the HTML
// parser.
- node.initialize_layout_data(layout_context.layout_chan.clone());
+ node.initialize_layout_data(layout_context.shared.layout_chan.clone());
// Get the parent 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.shared.reflow_root {
None
} else {
node.parent_node()
@@ -250,7 +251,7 @@ fn recalc_style_for_node(unsafe_layout_node: UnsafeLayoutNode,
if node.is_element() {
// Perform the CSS selector matching.
- let stylist = unsafe { &*layout_context.stylist };
+ let stylist = unsafe { &*layout_context.shared.stylist };
node.match_node(stylist, &mut applicable_declarations, &mut shareable);
}
@@ -302,14 +303,12 @@ fn recalc_style_for_node(unsafe_layout_node: UnsafeLayoutNode,
}
// If we got here, we're a leaf. Start construction of flows for this node.
- construct_flows(unsafe_layout_node, proxy)
+ construct_flows(unsafe_layout_node, &layout_context)
}
fn construct_flows(mut unsafe_layout_node: UnsafeLayoutNode,
- proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeLayoutNode>) {
+ layout_context: &LayoutContext) {
loop {
- let layout_context = unsafe { &mut **proxy.user_data() };
-
// Get a real layout node.
let node: LayoutNode = unsafe {
layout_node_from_unsafe_layout_node(&unsafe_layout_node)
@@ -317,7 +316,7 @@ fn construct_flows(mut unsafe_layout_node: UnsafeLayoutNode,
// Construct flows for this node.
{
- let mut flow_constructor = FlowConstructor::new(layout_context, None);
+ let mut flow_constructor = FlowConstructor::new(layout_context);
flow_constructor.process(&ThreadSafeLayoutNode::new(&node));
}
@@ -340,7 +339,7 @@ fn construct_flows(mut unsafe_layout_node: UnsafeLayoutNode,
// If this is the reflow root, we're done.
let opaque_node: OpaqueNode = OpaqueNodeMethods::from_layout_node(&node);
- if layout_context.reflow_root == opaque_node {
+ if layout_context.shared.reflow_root == opaque_node {
break
}
@@ -376,25 +375,27 @@ fn construct_flows(mut unsafe_layout_node: UnsafeLayoutNode,
}
fn assign_inline_sizes(unsafe_flow: UnsafeFlow,
- proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) {
- let layout_context = unsafe { &mut **proxy.user_data() };
+ proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
+ let shared_layout_context = unsafe { &**proxy.user_data() };
+ let layout_context = LayoutContext::new(shared_layout_context);
let mut assign_inline_sizes_traversal = AssignISizesTraversal {
- layout_context: layout_context,
+ layout_context: &layout_context,
};
assign_inline_sizes_traversal.run_parallel(unsafe_flow, proxy)
}
fn assign_block_sizes_and_store_overflow(unsafe_flow: UnsafeFlow,
- proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) {
- let layout_context = unsafe { &mut **proxy.user_data() };
+ proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
+ let shared_layout_context = unsafe { &**proxy.user_data() };
+ let layout_context = LayoutContext::new(shared_layout_context);
let mut assign_block_sizes_traversal = AssignBSizesAndStoreOverflowTraversal {
- layout_context: layout_context,
+ layout_context: &layout_context,
};
assign_block_sizes_traversal.run_parallel(unsafe_flow, proxy)
}
fn compute_absolute_position(unsafe_flow: UnsafeFlow,
- proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) {
+ proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
let mut had_descendants = false;
unsafe {
// Get a real flow.
@@ -448,8 +449,9 @@ fn compute_absolute_position(unsafe_flow: UnsafeFlow,
}
fn build_display_list(mut unsafe_flow: UnsafeFlow,
- proxy: &mut WorkerProxy<*mut LayoutContext,UnsafeFlow>) {
- let layout_context = unsafe { &mut **proxy.user_data() };
+ proxy: &mut WorkerProxy<*const SharedLayoutContext,UnsafeFlow>) {
+ let shared_layout_context = unsafe { &**proxy.user_data() };
+ let layout_context = LayoutContext::new(shared_layout_context);
loop {
unsafe {
@@ -457,7 +459,7 @@ fn build_display_list(mut unsafe_flow: UnsafeFlow,
let flow: &mut FlowRef = mem::transmute(&unsafe_flow);
// Build display lists.
- flow.get_mut().build_display_list(layout_context);
+ flow.get_mut().build_display_list(&layout_context);
{
let base = flow::mut_base(flow.get_mut());
@@ -506,9 +508,9 @@ fn build_display_list(mut unsafe_flow: UnsafeFlow,
}
pub fn recalc_style_for_subtree(root_node: &LayoutNode,
- layout_context: &mut LayoutContext,
- queue: &mut WorkQueue<*mut LayoutContext,UnsafeLayoutNode>) {
- queue.data = layout_context as *mut _;
+ shared_layout_context: &SharedLayoutContext,
+ queue: &mut WorkQueue<*const SharedLayoutContext,UnsafeLayoutNode>) {
+ queue.data = shared_layout_context as *const _;
// Enqueue the root node.
queue.push(WorkUnit {
@@ -518,14 +520,14 @@ pub fn recalc_style_for_subtree(root_node: &LayoutNode,
queue.run();
- queue.data = ptr::mut_null()
+ queue.data = ptr::null()
}
pub fn traverse_flow_tree_preorder(root: &mut FlowRef,
time_profiler_chan: TimeProfilerChan,
- layout_context: &mut LayoutContext,
- queue: &mut WorkQueue<*mut LayoutContext,UnsafeFlow>) {
- queue.data = layout_context as *mut _;
+ shared_layout_context: &SharedLayoutContext,
+ queue: &mut WorkQueue<*const SharedLayoutContext,UnsafeFlow>) {
+ queue.data = shared_layout_context as *const _;
profile(time::LayoutParallelWarmupCategory, time_profiler_chan, || {
queue.push(WorkUnit {
@@ -536,14 +538,14 @@ pub fn traverse_flow_tree_preorder(root: &mut FlowRef,
queue.run();
- queue.data = ptr::mut_null()
+ queue.data = ptr::null()
}
pub fn build_display_list_for_subtree(root: &mut FlowRef,
time_profiler_chan: TimeProfilerChan,
- layout_context: &mut LayoutContext,
- queue: &mut WorkQueue<*mut LayoutContext,UnsafeFlow>) {
- queue.data = layout_context as *mut _;
+ shared_layout_context: &SharedLayoutContext,
+ queue: &mut WorkQueue<*const SharedLayoutContext,UnsafeFlow>) {
+ queue.data = shared_layout_context as *const _;
profile(time::LayoutParallelWarmupCategory, time_profiler_chan, || {
queue.push(WorkUnit {
@@ -554,6 +556,6 @@ pub fn build_display_list_for_subtree(root: &mut FlowRef,
queue.run();
- queue.data = ptr::mut_null()
+ queue.data = ptr::null()
}
diff --git a/src/components/layout/table.rs b/src/components/layout/table.rs
index db6993c2a5e..98569d68c95 100644
--- a/src/components/layout/table.rs
+++ b/src/components/layout/table.rs
@@ -125,7 +125,7 @@ impl TableFlow {
/// inline(always) because this is only ever called by in-order or non-in-order top-level
/// methods
#[inline(always)]
- fn assign_block_size_table_base(&mut self, layout_context: &mut LayoutContext) {
+ fn assign_block_size_table_base<'a>(&mut self, layout_context: &'a LayoutContext<'a>) {
self.block_flow.assign_block_size_block_base(layout_context, MarginsMayNotCollapse);
}
@@ -164,7 +164,7 @@ impl Flow for TableFlow {
/// table layout calculation.
/// The maximum min/pref inline-sizes of each column are set from the rows for the automatic
/// table layout calculation.
- fn bubble_inline_sizes(&mut self, _: &mut LayoutContext) {
+ fn bubble_inline_sizes(&mut self, _: &LayoutContext) {
let mut min_inline_size = Au(0);
let mut pref_inline_size = Au(0);
let mut did_first_row = false;
@@ -235,7 +235,7 @@ impl Flow for TableFlow {
/// Recursively (top-down) determines the actual inline-size of child contexts and fragments. When
/// called on this context, the context has had its inline-size set by the parent context.
- fn assign_inline_sizes(&mut self, ctx: &mut LayoutContext) {
+ fn assign_inline_sizes(&mut self, ctx: &LayoutContext) {
debug!("assign_inline_sizes({}): assigning inline_size for flow", "table");
// The position was set to the containing block by the flow's parent.
@@ -282,7 +282,7 @@ impl Flow for TableFlow {
self.block_flow.propagate_assigned_inline_size_to_children(inline_start_content_edge, content_inline_size, Some(self.col_inline_sizes.clone()));
}
- fn assign_block_size(&mut self, ctx: &mut LayoutContext) {
+ fn assign_block_size<'a>(&mut self, ctx: &'a LayoutContext<'a>) {
debug!("assign_block_size: assigning block_size for table");
self.assign_block_size_table_base(ctx);
}
@@ -309,7 +309,7 @@ impl ISizeAndMarginsComputer for InternalTable {
/// CSS Section 10.4: Minimum and Maximum inline-sizes
fn compute_used_inline_size(&self,
block: &mut BlockFlow,
- ctx: &mut LayoutContext,
+ ctx: &LayoutContext,
parent_flow_inline_size: Au) {
let input = self.compute_inline_size_constraint_inputs(block, parent_flow_inline_size, ctx);
let solution = self.solve_inline_size_constraints(block, &input);
diff --git a/src/components/layout/table_caption.rs b/src/components/layout/table_caption.rs
index 9ad0e017813..8c1dba3e7ca 100644
--- a/src/components/layout/table_caption.rs
+++ b/src/components/layout/table_caption.rs
@@ -47,16 +47,16 @@ impl Flow for TableCaptionFlow {
&mut self.block_flow
}
- fn bubble_inline_sizes(&mut self, ctx: &mut LayoutContext) {
+ fn bubble_inline_sizes(&mut self, ctx: &LayoutContext) {
self.block_flow.bubble_inline_sizes(ctx);
}
- fn assign_inline_sizes(&mut self, ctx: &mut LayoutContext) {
+ fn assign_inline_sizes(&mut self, ctx: &LayoutContext) {
debug!("assign_inline_sizes({}): assigning inline_size for flow", "table_caption");
self.block_flow.assign_inline_sizes(ctx);
}
- fn assign_block_size(&mut self, ctx: &mut LayoutContext) {
+ fn assign_block_size<'a>(&mut self, ctx: &'a LayoutContext<'a>) {
debug!("assign_block_size: assigning block_size for table_caption");
self.block_flow.assign_block_size(ctx);
}
diff --git a/src/components/layout/table_cell.rs b/src/components/layout/table_cell.rs
index 57bc806f7fc..0011cd29fbc 100644
--- a/src/components/layout/table_cell.rs
+++ b/src/components/layout/table_cell.rs
@@ -45,7 +45,7 @@ impl TableCellFlow {
/// inline(always) because this is only ever called by in-order or non-in-order top-level
/// methods
#[inline(always)]
- fn assign_block_size_table_cell_base(&mut self, layout_context: &mut LayoutContext) {
+ fn assign_block_size_table_cell_base<'a>(&mut self, layout_context: &'a LayoutContext<'a>) {
self.block_flow.assign_block_size_block_base(layout_context, MarginsMayNotCollapse)
}
@@ -69,7 +69,7 @@ impl Flow for TableCellFlow {
}
/// Minimum/preferred inline-sizes set by this function are used in automatic table layout calculation.
- fn bubble_inline_sizes(&mut self, ctx: &mut LayoutContext) {
+ fn bubble_inline_sizes(&mut self, ctx: &LayoutContext) {
self.block_flow.bubble_inline_sizes(ctx);
let specified_inline_size = MaybeAuto::from_style(self.block_flow.fragment.style().content_inline_size(),
Au::new(0)).specified_or_zero();
@@ -85,7 +85,7 @@ impl Flow for TableCellFlow {
/// Recursively (top-down) determines the actual inline-size of child contexts and fragments. When
/// called on this context, the context has had its inline-size set by the parent table row.
- fn assign_inline_sizes(&mut self, ctx: &mut LayoutContext) {
+ fn assign_inline_sizes(&mut self, ctx: &LayoutContext) {
debug!("assign_inline_sizes({}): assigning inline_size for flow", "table_cell");
// The position was set to the column inline-size by the parent flow, table row flow.
@@ -104,7 +104,7 @@ impl Flow for TableCellFlow {
None);
}
- fn assign_block_size(&mut self, ctx: &mut LayoutContext) {
+ fn assign_block_size<'a>(&mut self, ctx: &'a LayoutContext<'a>) {
debug!("assign_block_size: assigning block_size for table_cell");
self.assign_block_size_table_cell_base(ctx);
}
diff --git a/src/components/layout/table_colgroup.rs b/src/components/layout/table_colgroup.rs
index a27cff86deb..270f55970b2 100644
--- a/src/components/layout/table_colgroup.rs
+++ b/src/components/layout/table_colgroup.rs
@@ -52,7 +52,7 @@ impl Flow for TableColGroupFlow {
self
}
- fn bubble_inline_sizes(&mut self, _: &mut LayoutContext) {
+ fn bubble_inline_sizes(&mut self, _: &LayoutContext) {
for fragment in self.cols.iter() {
// get the specified value from inline-size property
let inline_size = MaybeAuto::from_style(fragment.style().content_inline_size(),
@@ -70,11 +70,11 @@ impl Flow for TableColGroupFlow {
/// Table column inline-sizes are assigned in table flow and propagated to table row or rowgroup flow.
/// Therefore, table colgroup flow does not need to assign its inline-size.
- fn assign_inline_sizes(&mut self, _ctx: &mut LayoutContext) {
+ fn assign_inline_sizes(&mut self, _ctx: &LayoutContext) {
}
/// Table column do not have block-size.
- fn assign_block_size(&mut self, _ctx: &mut LayoutContext) {
+ fn assign_block_size(&mut self, _ctx: &LayoutContext) {
}
}
diff --git a/src/components/layout/table_row.rs b/src/components/layout/table_row.rs
index 6e8f5bfcfd7..101f00eb5cc 100644
--- a/src/components/layout/table_row.rs
+++ b/src/components/layout/table_row.rs
@@ -75,7 +75,7 @@ impl TableRowFlow {
/// inline(always) because this is only ever called by in-order or non-in-order top-level
/// methods
#[inline(always)]
- fn assign_block_size_table_row_base(&mut self, layout_context: &mut LayoutContext) {
+ fn assign_block_size_table_row_base<'a>(&mut self, layout_context: &'a LayoutContext<'a>) {
let (block_start_offset, _, _) = self.initialize_offsets();
let /* mut */ cur_y = block_start_offset;
@@ -165,7 +165,7 @@ impl Flow for TableRowFlow {
/// responsible for flowing.
/// Min/pref inline-sizes set by this function are used in automatic table layout calculation.
/// The specified column inline-sizes of children cells are used in fixed table layout calculation.
- fn bubble_inline_sizes(&mut self, _: &mut LayoutContext) {
+ fn bubble_inline_sizes(&mut self, _: &LayoutContext) {
let mut min_inline_size = Au(0);
let mut pref_inline_size = Au(0);
/* find the specified inline_sizes from child table-cell contexts */
@@ -194,7 +194,7 @@ impl Flow for TableRowFlow {
/// Recursively (top-down) determines the actual inline-size of child contexts and fragments. When called
/// on this context, the context has had its inline-size set by the parent context.
- fn assign_inline_sizes(&mut self, ctx: &mut LayoutContext) {
+ fn assign_inline_sizes(&mut self, ctx: &LayoutContext) {
debug!("assign_inline_sizes({}): assigning inline_size for flow", "table_row");
// The position was set to the containing block by the flow's parent.
@@ -208,7 +208,7 @@ impl Flow for TableRowFlow {
self.block_flow.propagate_assigned_inline_size_to_children(inline_start_content_edge, Au(0), Some(self.col_inline_sizes.clone()));
}
- fn assign_block_size(&mut self, ctx: &mut LayoutContext) {
+ fn assign_block_size<'a>(&mut self, ctx: &'a LayoutContext<'a>) {
debug!("assign_block_size: assigning block_size for table_row");
self.assign_block_size_table_row_base(ctx);
}
diff --git a/src/components/layout/table_rowgroup.rs b/src/components/layout/table_rowgroup.rs
index b39bee19596..48f9d376af3 100644
--- a/src/components/layout/table_rowgroup.rs
+++ b/src/components/layout/table_rowgroup.rs
@@ -74,7 +74,7 @@ impl TableRowGroupFlow {
/// inline(always) because this is only ever called by in-order or non-in-order top-level
/// methods
#[inline(always)]
- fn assign_block_size_table_rowgroup_base(&mut self, layout_context: &mut LayoutContext) {
+ fn assign_block_size_table_rowgroup_base<'a>(&mut self, layout_context: &'a LayoutContext<'a>) {
let (block_start_offset, _, _) = self.initialize_offsets();
let mut cur_y = block_start_offset;
@@ -133,7 +133,7 @@ impl Flow for TableRowGroupFlow {
/// Min/pref inline-sizes set by this function are used in automatic table layout calculation.
/// Also, this function finds the specified column inline-sizes from the first row.
/// Those are used in fixed table layout calculation
- fn bubble_inline_sizes(&mut self, _: &mut LayoutContext) {
+ fn bubble_inline_sizes(&mut self, _: &LayoutContext) {
let mut min_inline_size = Au(0);
let mut pref_inline_size = Au(0);
@@ -175,7 +175,7 @@ impl Flow for TableRowGroupFlow {
/// Recursively (top-down) determines the actual inline-size of child contexts and fragments. When
/// called on this context, the context has had its inline-size set by the parent context.
- fn assign_inline_sizes(&mut self, ctx: &mut LayoutContext) {
+ fn assign_inline_sizes(&mut self, ctx: &LayoutContext) {
debug!("assign_inline_sizes({}): assigning inline_size for flow", "table_rowgroup");
// The position was set to the containing block by the flow's parent.
@@ -191,7 +191,7 @@ impl Flow for TableRowGroupFlow {
self.block_flow.propagate_assigned_inline_size_to_children(inline_start_content_edge, content_inline_size, Some(self.col_inline_sizes.clone()));
}
- fn assign_block_size(&mut self, ctx: &mut LayoutContext) {
+ fn assign_block_size<'a>(&mut self, ctx: &'a LayoutContext<'a>) {
debug!("assign_block_size: assigning block_size for table_rowgroup");
self.assign_block_size_table_rowgroup_base(ctx);
}
diff --git a/src/components/layout/table_wrapper.rs b/src/components/layout/table_wrapper.rs
index 5d431e18c4e..2084ef52bdc 100644
--- a/src/components/layout/table_wrapper.rs
+++ b/src/components/layout/table_wrapper.rs
@@ -100,7 +100,7 @@ impl TableWrapperFlow {
/// inline(always) because this is only ever called by in-order or non-in-order top-level
/// methods
#[inline(always)]
- fn assign_block_size_table_wrapper_base(&mut self, layout_context: &mut LayoutContext) {
+ fn assign_block_size_table_wrapper_base<'a>(&mut self, layout_context: &'a LayoutContext<'a>) {
self.block_flow.assign_block_size_block_base(layout_context, MarginsMayNotCollapse);
}
@@ -129,7 +129,7 @@ impl Flow for TableWrapperFlow {
min/pref inline_sizes based on child context inline_sizes and dimensions of
any fragments it is responsible for flowing. */
- fn bubble_inline_sizes(&mut self, ctx: &mut LayoutContext) {
+ fn bubble_inline_sizes(&mut self, ctx: &LayoutContext) {
// get column inline-sizes info from table flow
for kid in self.block_flow.base.child_iter() {
assert!(kid.is_table_caption() || kid.is_table());
@@ -147,7 +147,7 @@ impl Flow for TableWrapperFlow {
///
/// Dual fragments consume some inline-size first, and the remainder is assigned to all child (block)
/// contexts.
- fn assign_inline_sizes(&mut self, ctx: &mut LayoutContext) {
+ fn assign_inline_sizes(&mut self, ctx: &LayoutContext) {
debug!("assign_inline_sizes({}): assigning inline_size for flow",
if self.is_float() {
"floated table_wrapper"
@@ -178,7 +178,7 @@ impl Flow for TableWrapperFlow {
self.block_flow.propagate_assigned_inline_size_to_children(inline_start_content_edge, content_inline_size, assigned_col_inline_sizes);
}
- fn assign_block_size(&mut self, ctx: &mut LayoutContext) {
+ fn assign_block_size<'a>(&mut self, ctx: &'a LayoutContext<'a>) {
if self.is_float() {
debug!("assign_block_size_float: assigning block_size for floated table_wrapper");
self.block_flow.assign_block_size_float(ctx);
@@ -208,7 +208,7 @@ struct TableWrapper;
impl TableWrapper {
fn compute_used_inline_size_table_wrapper(&self,
table_wrapper: &mut TableWrapperFlow,
- ctx: &mut LayoutContext,
+ ctx: &LayoutContext,
parent_flow_inline_size: Au) {
let input = self.compute_inline_size_constraint_inputs_table_wrapper(table_wrapper,
parent_flow_inline_size,
@@ -223,7 +223,7 @@ impl TableWrapper {
fn compute_inline_size_constraint_inputs_table_wrapper(&self,
table_wrapper: &mut TableWrapperFlow,
parent_flow_inline_size: Au,
- ctx: &mut LayoutContext)
+ ctx: &LayoutContext)
-> ISizeConstraintInput {
let mut input = self.compute_inline_size_constraint_inputs(&mut table_wrapper.block_flow,
parent_flow_inline_size,