servo: Merge #13417 - Simplify stacking context collection (from mrobinson:simplify-stacking-context-collection); r=glennw
authorMartin Robinson <mrobinson@igalia.com>
Thu, 29 Sep 2016 09:01:33 -0500
changeset 339772 2426f04588dad2ae29c0761402a31782c431ab48
parent 339771 e3aa905b693801d09ab779fc66d9405800b1dcc2
child 339773 9eaa11d63431e631cf1e475055dae266d8cfb095
push id31307
push usergszorc@mozilla.com
push dateSat, 04 Feb 2017 00:59:06 +0000
treeherdermozilla-central@94079d43835f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersglennw
servo: Merge #13417 - Simplify stacking context collection (from mrobinson:simplify-stacking-context-collection); r=glennw <!-- Please describe your changes on the following line: --> --- <!-- Thank you for contributing to Servo! Please replace each `[ ]` by `[X]` when the step is complete, and replace `__` with appropriate data: --> - [x] `./mach build -d` does not report any errors - [x] `./mach test-tidy` does not report any errors - [ ] These changes fix #__ (github issue number if applicable). <!-- Either: --> - [x] There are tests for these changes OR - [ ] These changes do not require tests because _____ <!-- Pull requests that do not address these steps are welcome, but they will require additional verification as part of the review process. --> Simplify the way that stacking contexts are collected. Instead of passing the StackingContextId down the tree, pass the parent StackingContext itself. This will allow future patches to get more information about the parent stacking context (such as location). Also remove the return value of collect_stacking_contexts, which was unused. Source-Repo: https://github.com/servo/servo Source-Revision: 81dfa6a96b99eae8a7232eab39de96edf663ba99
servo/components/gfx/display_list/mod.rs
servo/components/layout/block.rs
servo/components/layout/display_list_builder.rs
servo/components/layout/flex.rs
servo/components/layout/flow.rs
servo/components/layout/inline.rs
servo/components/layout/list_item.rs
servo/components/layout/multicol.rs
servo/components/layout/sequential.rs
servo/components/layout/table.rs
servo/components/layout/table_caption.rs
servo/components/layout/table_cell.rs
servo/components/layout/table_colgroup.rs
servo/components/layout/table_row.rs
servo/components/layout/table_rowgroup.rs
servo/components/layout/table_wrapper.rs
--- a/servo/components/gfx/display_list/mod.rs
+++ b/servo/components/gfx/display_list/mod.rs
@@ -613,17 +613,17 @@ pub struct StackingContext {
 
     /// Whether this stacking context scrolls its overflow area.
     pub scrolls_overflow_area: bool,
 
     /// The layer info for this stacking context, if there is any.
     pub layer_info: Option<LayerInfo>,
 
     /// Children of this StackingContext.
-    children: Vec<Box<StackingContext>>,
+    pub children: Vec<Box<StackingContext>>,
 }
 
 impl StackingContext {
     /// Creates a new stacking context.
     #[inline]
     pub fn new(id: StackingContextId,
                context_type: StackingContextType,
                bounds: &Rect<Au>,
@@ -649,60 +649,41 @@ impl StackingContext {
             perspective: perspective,
             establishes_3d_context: establishes_3d_context,
             scrolls_overflow_area: scrolls_overflow_area,
             layer_info: layer_info,
             children: Vec::new(),
         }
     }
 
-    pub fn set_children(&mut self, children: Vec<Box<StackingContext>>) {
-        debug_assert!(self.children.is_empty());
-        // We need to take into account the possible transformations of the
-        // child stacking contexts.
-        for child in &children {
-            self.update_overflow_for_new_child(&child);
-        }
-
-        self.children = children;
-    }
-
-    pub fn add_child(&mut self, child: Box<StackingContext>) {
-        self.update_overflow_for_new_child(&child);
-        self.children.push(child);
-    }
-
-    pub fn add_children(&mut self, children: Vec<Box<StackingContext>>) {
-        if self.children.is_empty() {
-            return self.set_children(children);
-        }
-
-        for child in children {
-            self.add_child(child);
-        }
+    pub fn add_child(&mut self, mut child: StackingContext) {
+        child.update_overflow_for_all_children();
+        self.children.push(Box::new(child));
     }
 
     pub fn child_at_mut(&mut self, index: usize) -> &mut StackingContext {
         &mut *self.children[index]
     }
 
     pub fn children(&self) -> &[Box<StackingContext>] {
         &self.children
     }
 
-    fn update_overflow_for_new_child(&mut self, child: &StackingContext) {
-        if self.context_type == StackingContextType::Real &&
-           child.context_type == StackingContextType::Real &&
-           !self.scrolls_overflow_area {
-            // This child might be transformed, so we need to take into account
-            // its transformed overflow rect too, but at the correct position.
-            let overflow =
-                child.overflow_rect_in_parent_space();
+    fn update_overflow_for_all_children(&mut self) {
+        for child in self.children.iter() {
+            if self.context_type == StackingContextType::Real &&
+               child.context_type == StackingContextType::Real &&
+               !self.scrolls_overflow_area {
+                // This child might be transformed, so we need to take into account
+                // its transformed overflow rect too, but at the correct position.
+                let overflow =
+                    child.overflow_rect_in_parent_space();
 
-            self.overflow = self.overflow.union(&overflow);
+                self.overflow = self.overflow.union(&overflow);
+            }
         }
     }
 
     fn overflow_rect_in_parent_space(&self) -> Rect<Au> {
         // Transform this stacking context to get it into the same space as
         // the parent stacking context.
         //
         // TODO: Take into account 3d transforms, even though it's a fairly
--- a/servo/components/layout/block.rs
+++ b/servo/components/layout/block.rs
@@ -39,17 +39,17 @@ use flow::{CONTAINS_TEXT_OR_REPLACED_FRA
 use flow::{FragmentationContext, NEEDS_LAYER, PreorderFlowTraversal};
 use flow::{ImmutableFlowUtils, LateAbsolutePositionInfo, MutableFlowUtils, OpaqueFlow};
 use flow::IS_ABSOLUTELY_POSITIONED;
 use flow_list::FlowList;
 use flow_ref::FlowRef;
 use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, HAS_LAYER, Overflow};
 use fragment::SpecificFragmentInfo;
 use gfx::display_list::{ClippingRegion, StackingContext};
-use gfx_traits::{LayerId, StackingContextId};
+use gfx_traits::LayerId;
 use gfx_traits::print_tree::PrintTree;
 use layout_debug;
 use model::{self, IntrinsicISizes, MarginCollapseInfo};
 use model::{CollapsibleMargins, MaybeAuto, specified, specified_or_none};
 use rustc_serialize::{Encodable, Encoder};
 use script_layout_interface::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW};
 use script_layout_interface::restyle_damage::REPOSITION;
 use std::cmp::{max, min};
@@ -2167,21 +2167,18 @@ impl Flow for BlockFlow {
                 self.fragment.style().logical_position().block_start ==
                     LengthOrPercentageOrAuto::Auto &&
                 self.fragment.style().logical_position().block_end ==
                 LengthOrPercentageOrAuto::Auto {
             self.base.position.start.b = block_position
         }
     }
 
-    fn collect_stacking_contexts(&mut self,
-                                 parent_id: StackingContextId,
-                                 contexts: &mut Vec<Box<StackingContext>>)
-                                 -> StackingContextId {
-        self.collect_stacking_contexts_for_block(parent_id, contexts)
+    fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) {
+        self.collect_stacking_contexts_for_block(parent);
     }
 
     fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
         self.build_display_list_for_block(state, BorderPaintingMode::Separate);
     }
 
     fn repair_style(&mut self, new_style: &Arc<ServoComputedValues>) {
         self.fragment.repair_style(new_style)
--- a/servo/components/layout/display_list_builder.rs
+++ b/servo/components/layout/display_list_builder.rs
@@ -287,17 +287,17 @@ pub trait FragmentDisplayListBuilding {
                                                   clip: &ClippingRegion);
 
     /// Creates a stacking context for associated fragment.
     fn create_stacking_context(&self,
                                id: StackingContextId,
                                base_flow: &BaseFlow,
                                scroll_policy: ScrollPolicy,
                                mode: StackingContextCreationMode)
-                               -> Box<StackingContext>;
+                               -> StackingContext;
 }
 
 fn handle_overlapping_radii(size: &Size2D<Au>, radii: &BorderRadii<Au>) -> BorderRadii<Au> {
     // No two corners' border radii may add up to more than the length of the edge
     // between them. To prevent that, all radii are scaled down uniformly.
     fn scale_factor(radius_a: Au, radius_b: Au, edge_length: Au) -> f32 {
         let required = radius_a + radius_b;
 
@@ -1364,17 +1364,17 @@ impl FragmentDisplayListBuilding for Fra
         }
     }
 
     fn create_stacking_context(&self,
                                id: StackingContextId,
                                base_flow: &BaseFlow,
                                scroll_policy: ScrollPolicy,
                                mode: StackingContextCreationMode)
-                               -> Box<StackingContext> {
+                               -> StackingContext {
         let use_webrender = opts::get().use_webrender;
         let border_box = match mode {
             StackingContextCreationMode::InnerScrollWrapper => {
                 Rect::new(Point2D::zero(), base_flow.overflow.scroll.size)
             }
             _ => {
                 self.stacking_relative_border_box(&base_flow.stacking_relative_position,
                                                   &base_flow.early_absolute_position_info
@@ -1505,28 +1505,28 @@ impl FragmentDisplayListBuilding for Fra
             transform_style == transform_style::T::flat;
 
         let context_type = match mode {
             StackingContextCreationMode::PseudoFloat => StackingContextType::PseudoFloat,
             StackingContextCreationMode::PseudoPositioned => StackingContextType::PseudoPositioned,
             _ => StackingContextType::Real,
         };
 
-        Box::new(StackingContext::new(id,
-                                      context_type,
-                                      &border_box,
-                                      &overflow,
-                                      self.effective_z_index(),
-                                      filters,
-                                      self.style().get_effects().mix_blend_mode,
-                                      transform,
-                                      perspective,
-                                      establishes_3d_context,
-                                      scrolls_overflow_area,
-                                      layer_info))
+        StackingContext::new(id,
+                             context_type,
+                             &border_box,
+                             &overflow,
+                             self.effective_z_index(),
+                             filters,
+                             self.style().get_effects().mix_blend_mode,
+                             transform,
+                             perspective,
+                             establishes_3d_context,
+                             scrolls_overflow_area,
+                             layer_info)
     }
 
     fn adjust_clipping_region_for_children(&self,
                                            current_clip: &mut ClippingRegion,
                                            stacking_relative_border_box: &Rect<Au>) {
         // Don't clip if we're text.
         if self.is_scanned_text_fragment() {
             return
@@ -1716,35 +1716,29 @@ impl FragmentDisplayListBuilding for Fra
             spread_radius: Au(0),
             border_radius: Au(0),
             clip_mode: BoxShadowClipMode::None,
         }));
     }
 }
 
 pub trait BlockFlowDisplayListBuilding {
-    fn collect_stacking_contexts_for_block(&mut self,
-                                           parent_id: StackingContextId,
-                                           contexts: &mut Vec<Box<StackingContext>>)
-                                           -> StackingContextId;
+    fn collect_stacking_contexts_for_block(&mut self, parent: &mut StackingContext);
     fn build_display_list_for_block(&mut self,
                                     state: &mut DisplayListBuildState,
                                     border_painting_mode: BorderPaintingMode);
 }
 
 impl BlockFlowDisplayListBuilding for BlockFlow {
-    fn collect_stacking_contexts_for_block(&mut self,
-                                           parent_id: StackingContextId,
-                                           contexts: &mut Vec<Box<StackingContext>>)
-                                           -> StackingContextId {
+    fn collect_stacking_contexts_for_block(&mut self, parent: &mut StackingContext) {
         let block_stacking_context_type = self.block_stacking_context_type();
         if block_stacking_context_type == BlockStackingContextType::NonstackingContext {
-            self.base.stacking_context_id = parent_id;
-            self.base.collect_stacking_contexts_for_children(parent_id, contexts);
-            return parent_id;
+            self.base.stacking_context_id = parent.id;
+            self.base.collect_stacking_contexts_for_children(parent);
+            return;
         }
 
         let has_scrolling_overflow = self.has_scrolling_overflow();
         let stacking_context_id = if has_scrolling_overflow {
             StackingContextId::new_outer(self.fragment.fragment_type())
         } else {
             StackingContextId::new_of_type(self.fragment.node.id() as usize,
                                            self.fragment.fragment_type())
@@ -1753,83 +1747,79 @@ impl BlockFlowDisplayListBuilding for Bl
 
         let inner_stacking_context_id = if has_scrolling_overflow {
             StackingContextId::new_of_type(self.fragment.node.id() as usize,
                                            self.fragment.fragment_type())
         } else {
             stacking_context_id
         };
 
-        let mut child_contexts = Vec::new();
-        self.base.collect_stacking_contexts_for_children(inner_stacking_context_id,
-                                                         &mut child_contexts);
 
         if block_stacking_context_type == BlockStackingContextType::PseudoStackingContext {
             let creation_mode = if self.base.flags.contains(IS_ABSOLUTELY_POSITIONED) ||
                                    self.fragment.style.get_box().position != position::T::static_ {
                 StackingContextCreationMode::PseudoPositioned
             } else {
                 assert!(self.base.flags.is_float());
                 StackingContextCreationMode::PseudoFloat
             };
 
-            let stacking_context_index = contexts.len();
-            contexts.push(self.fragment.create_stacking_context(stacking_context_id,
-                                                                &self.base,
-                                                                ScrollPolicy::Scrollable,
-                                                                creation_mode));
+            let mut new_context = self.fragment.create_stacking_context(stacking_context_id,
+                                                                        &self.base,
+                                                                        ScrollPolicy::Scrollable,
+                                                                        creation_mode);
+            self.base.collect_stacking_contexts_for_children(&mut new_context);
+            let new_children: Vec<Box<StackingContext>> = new_context.children.drain(..).collect();
 
-            let mut floating = vec![];
-            for child_context in child_contexts.into_iter() {
-                if child_context.context_type == StackingContextType::PseudoFloat {
-                    // Floating.
-                    floating.push(child_context)
+            let mut non_floating_children = Vec::new();
+            for child in new_children {
+                if child.context_type == StackingContextType::PseudoFloat {
+                    new_context.children.push(child);
                 } else {
-                    // Positioned.
-                    contexts.push(child_context)
+                    non_floating_children.push(child);
                 }
             }
 
-            contexts[stacking_context_index].set_children(floating);
-            return stacking_context_id;
+            parent.add_child(new_context);
+            parent.children.append(&mut non_floating_children);
+            return;
         }
 
         let scroll_policy = if self.is_fixed() {
             ScrollPolicy::FixedPosition
         } else {
             ScrollPolicy::Scrollable
         };
 
         let stacking_context = if self.has_scrolling_overflow() {
             let mut inner_stacking_context = self.fragment.create_stacking_context(
                 inner_stacking_context_id,
                 &self.base,
                 scroll_policy,
                 StackingContextCreationMode::InnerScrollWrapper);
-            inner_stacking_context.set_children(child_contexts);
+            self.base.collect_stacking_contexts_for_children(&mut inner_stacking_context);
 
             let mut outer_stacking_context = self.fragment.create_stacking_context(
                 stacking_context_id,
                 &self.base,
                 scroll_policy,
                 StackingContextCreationMode::OuterScrollWrapper);
             outer_stacking_context.add_child(inner_stacking_context);
             outer_stacking_context
         } else {
             let mut stacking_context = self.fragment.create_stacking_context(
                 stacking_context_id,
                 &self.base,
                 scroll_policy,
                 StackingContextCreationMode::Normal);
-            stacking_context.set_children(child_contexts);
+            self.base.collect_stacking_contexts_for_children(&mut stacking_context);
             stacking_context
         };
 
-        contexts.push(stacking_context);
-        stacking_context_id
+        parent.add_child(stacking_context);
     }
 
     fn build_display_list_for_block(&mut self,
                                     state: &mut DisplayListBuildState,
                                     border_painting_mode: BorderPaintingMode) {
         let establishes_stacking_context = self.fragment.establishes_stacking_context();
         let background_border_section = if self.base.flags.is_float() {
             DisplayListSection::BackgroundAndBorders
@@ -1866,57 +1856,50 @@ impl BlockFlowDisplayListBuilding for Bl
                                 clip,
                                 &self.base.stacking_relative_position_of_display_port);
 
         self.base.build_display_items_for_debugging_tint(state, self.fragment.node);
     }
 }
 
 pub trait InlineFlowDisplayListBuilding {
-    fn collect_stacking_contexts_for_inline(&mut self,
-                                            parent_id: StackingContextId,
-                                            contexts: &mut Vec<Box<StackingContext>>)
-                                            -> StackingContextId;
+    fn collect_stacking_contexts_for_inline(&mut self, parent: &mut StackingContext);
     fn build_display_list_for_inline_fragment_at_index(&mut self,
                                                        state: &mut DisplayListBuildState,
                                                        index: usize);
     fn build_display_list_for_inline(&mut self, state: &mut DisplayListBuildState);
 }
 
 impl InlineFlowDisplayListBuilding for InlineFlow {
-    fn collect_stacking_contexts_for_inline(&mut self,
-                                            parent_id: StackingContextId,
-                                            contexts: &mut Vec<Box<StackingContext>>)
-                                            -> StackingContextId {
-        self.base.stacking_context_id = parent_id;
+    fn collect_stacking_contexts_for_inline(&mut self, parent: &mut StackingContext) {
+        self.base.stacking_context_id = parent.id;
 
         for mut fragment in self.fragments.fragments.iter_mut() {
             match fragment.specific {
                 SpecificFragmentInfo::InlineBlock(ref mut block_flow) => {
                     let block_flow = flow_ref::deref_mut(&mut block_flow.flow_ref);
-                    block_flow.collect_stacking_contexts(parent_id, contexts);
+                    block_flow.collect_stacking_contexts(parent);
                 }
                 SpecificFragmentInfo::InlineAbsoluteHypothetical(ref mut block_flow) => {
                     let block_flow = flow_ref::deref_mut(&mut block_flow.flow_ref);
-                    block_flow.collect_stacking_contexts(parent_id, contexts);
+                    block_flow.collect_stacking_contexts(parent);
                 }
                 _ if fragment.establishes_stacking_context() => {
                     fragment.stacking_context_id =
                         StackingContextId::new_of_type(fragment.fragment_id(),
                                                        fragment.fragment_type());
-                    contexts.push(fragment.create_stacking_context(
+                    parent.add_child(fragment.create_stacking_context(
                         fragment.stacking_context_id,
                         &self.base,
                         ScrollPolicy::Scrollable,
                         StackingContextCreationMode::Normal));
                 }
-                _ => fragment.stacking_context_id = parent_id,
+                _ => fragment.stacking_context_id = parent.id,
             }
         }
-        parent_id
     }
 
     fn build_display_list_for_inline_fragment_at_index(&mut self,
                                                        state: &mut DisplayListBuildState,
                                                        index: usize) {
         let fragment = self.fragments.fragments.get_mut(index).unwrap();
         fragment.build_display_list(state,
                                     &self.base.stacking_relative_position,
--- a/servo/components/layout/flex.rs
+++ b/servo/components/layout/flex.rs
@@ -13,17 +13,16 @@ use display_list_builder::{DisplayListBu
 use euclid::Point2D;
 use floats::FloatKind;
 use flow;
 use flow::{Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow};
 use flow::{INLINE_POSITION_IS_STATIC, IS_ABSOLUTELY_POSITIONED};
 use flow_ref::{self, FlowRef};
 use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
 use gfx::display_list::StackingContext;
-use gfx_traits::StackingContextId;
 use layout_debug;
 use model::{Direction, IntrinsicISizes, MaybeAuto, MinMaxConstraint};
 use model::{specified, specified_or_none};
 use script_layout_interface::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW};
 use std::cmp::{max, min};
 use std::ops::Range;
 use std::sync::Arc;
 use style::computed_values::{align_content, align_self, flex_direction, flex_wrap, justify_content};
@@ -935,21 +934,18 @@ impl Flow for FlexFlow {
     fn update_late_computed_block_position_if_necessary(&mut self, block_position: Au) {
         self.block_flow.update_late_computed_block_position_if_necessary(block_position)
     }
 
     fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
         self.build_display_list_for_flex(state);
     }
 
-    fn collect_stacking_contexts(&mut self,
-                                 parent_id: StackingContextId,
-                                 contexts: &mut Vec<Box<StackingContext>>)
-                                 -> StackingContextId {
-        self.block_flow.collect_stacking_contexts(parent_id, contexts)
+    fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) {
+        self.block_flow.collect_stacking_contexts(parent);
     }
 
     fn repair_style(&mut self, new_style: &Arc<ServoComputedValues>) {
         self.block_flow.repair_style(new_style)
     }
 
     fn compute_overflow(&self) -> Overflow {
         self.block_flow.compute_overflow()
--- a/servo/components/layout/flow.rs
+++ b/servo/components/layout/flow.rs
@@ -219,20 +219,17 @@ pub trait Flow: fmt::Debug + Sync + Send
                 recursive_assign_block_size(child, ctx)
             }
             flow.assign_block_size(ctx);
         }
         recursive_assign_block_size(self, layout_context);
         None
     }
 
-    fn collect_stacking_contexts(&mut self,
-                                 _parent_id: StackingContextId,
-                                 _: &mut Vec<Box<StackingContext>>)
-                                 -> StackingContextId;
+    fn collect_stacking_contexts(&mut self, _parent: &mut StackingContext);
 
     /// If this is a float, places it. The default implementation does nothing.
     fn place_float_if_applicable<'a>(&mut self) {}
 
     /// Assigns block-sizes in-order; or, if this is a float, places the float. The default
     /// implementation simply assigns block-sizes if this flow might have floats in. Returns true
     /// if it was determined that this child might have had floats in or false otherwise.
     ///
@@ -1155,21 +1152,19 @@ impl BaseFlow {
         let p = self as *const _;
         p as usize
     }
 
     pub fn flow_id(&self) -> usize {
         return self as *const BaseFlow as usize;
     }
 
-    pub fn collect_stacking_contexts_for_children(&mut self,
-                                                  parent_id: StackingContextId,
-                                                  contexts: &mut Vec<Box<StackingContext>>) {
+    pub fn collect_stacking_contexts_for_children(&mut self, parent: &mut StackingContext) {
         for kid in self.children.iter_mut() {
-            kid.collect_stacking_contexts(parent_id, contexts);
+            kid.collect_stacking_contexts(parent);
         }
     }
 
     #[inline]
     pub fn might_have_floats_in(&self) -> bool {
         self.speculated_float_placement_in.left > Au(0) ||
             self.speculated_float_placement_in.right > Au(0)
     }
--- a/servo/components/layout/inline.rs
+++ b/servo/components/layout/inline.rs
@@ -15,17 +15,16 @@ use flow::{self, BaseFlow, Flow, FlowCla
 use flow::{CONTAINS_TEXT_OR_REPLACED_FRAGMENTS, EarlyAbsolutePositionInfo, MutableFlowUtils};
 use flow::OpaqueFlow;
 use flow_ref;
 use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, Overflow};
 use fragment::SpecificFragmentInfo;
 use gfx::display_list::{OpaqueNode, StackingContext};
 use gfx::font::FontMetrics;
 use gfx::font_context::FontContext;
-use gfx_traits::StackingContextId;
 use gfx_traits::print_tree::PrintTree;
 use layout_debug;
 use model::IntrinsicISizesContribution;
 use range::{Range, RangeIndex};
 use script_layout_interface::restyle_damage::{BUBBLE_ISIZES, REFLOW, REFLOW_OUT_OF_FLOW};
 use script_layout_interface::restyle_damage::{REPOSITION, RESOLVE_GENERATED_CONTENT};
 use script_layout_interface::wrapper_traits::PseudoElementType;
 use std::{fmt, i32, isize, mem};
@@ -1655,21 +1654,18 @@ impl Flow for InlineFlow {
 
         self.base.restyle_damage.remove(REPOSITION)
     }
 
     fn update_late_computed_inline_position_if_necessary(&mut self, _: Au) {}
 
     fn update_late_computed_block_position_if_necessary(&mut self, _: Au) {}
 
-    fn collect_stacking_contexts(&mut self,
-                                 parent_id: StackingContextId,
-                                 contexts: &mut Vec<Box<StackingContext>>)
-                                 -> StackingContextId {
-        self.collect_stacking_contexts_for_inline(parent_id, contexts)
+    fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) {
+        self.collect_stacking_contexts_for_inline(parent);
     }
 
     fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
         self.build_display_list_for_inline(state);
     }
 
     fn repair_style(&mut self, _: &Arc<ServoComputedValues>) {}
 
--- a/servo/components/layout/list_item.rs
+++ b/servo/components/layout/list_item.rs
@@ -13,17 +13,16 @@ use context::{LayoutContext, SharedLayou
 use display_list_builder::{DisplayListBuildState, ListItemFlowDisplayListBuilding};
 use euclid::Point2D;
 use floats::FloatKind;
 use flow::{Flow, FlowClass, OpaqueFlow};
 use fragment::{CoordinateSystem, Fragment, FragmentBorderBoxIterator, GeneratedContentInfo};
 use fragment::Overflow;
 use generated_content;
 use gfx::display_list::StackingContext;
-use gfx_traits::StackingContextId;
 use inline::InlineMetrics;
 use script_layout_interface::restyle_damage::RESOLVE_GENERATED_CONTENT;
 use std::sync::Arc;
 use style::computed_values::{list_style_type, position};
 use style::context::SharedStyleContext;
 use style::logical_geometry::LogicalSize;
 use style::properties::ServoComputedValues;
 use text;
@@ -143,21 +142,18 @@ impl Flow for ListItemFlow {
     fn update_late_computed_block_position_if_necessary(&mut self, block_position: Au) {
         self.block_flow.update_late_computed_block_position_if_necessary(block_position)
     }
 
     fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
         self.build_display_list_for_list_item(state);
     }
 
-    fn collect_stacking_contexts(&mut self,
-                                 parent_id: StackingContextId,
-                                 contexts: &mut Vec<Box<StackingContext>>)
-                                 -> StackingContextId {
-        self.block_flow.collect_stacking_contexts(parent_id, contexts)
+    fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) {
+        self.block_flow.collect_stacking_contexts(parent);
     }
 
     fn repair_style(&mut self, new_style: &Arc<ServoComputedValues>) {
         self.block_flow.repair_style(new_style)
     }
 
     fn compute_overflow(&self) -> Overflow {
         let mut overflow = self.block_flow.compute_overflow();
--- a/servo/components/layout/multicol.rs
+++ b/servo/components/layout/multicol.rs
@@ -12,17 +12,16 @@ use context::{LayoutContext, SharedLayou
 use display_list_builder::DisplayListBuildState;
 use euclid::Point2D;
 use euclid::Size2D;
 use floats::FloatKind;
 use flow::{Flow, FlowClass, OpaqueFlow, mut_base, FragmentationContext};
 use flow_ref::{self, FlowRef};
 use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
 use gfx::display_list::StackingContext;
-use gfx_traits::StackingContextId;
 use gfx_traits::print_tree::PrintTree;
 use std::cmp::{min, max};
 use std::fmt;
 use std::sync::Arc;
 use style::context::{StyleContext, SharedStyleContext};
 use style::logical_geometry::LogicalSize;
 use style::properties::ServoComputedValues;
 use style::values::computed::{LengthOrPercentageOrAuto, LengthOrPercentageOrNone};
@@ -181,21 +180,18 @@ impl Flow for MulticolFlow {
         self.block_flow.update_late_computed_block_position_if_necessary(block_position)
     }
 
     fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
         debug!("build_display_list_multicol");
         self.block_flow.build_display_list(state);
     }
 
-    fn collect_stacking_contexts(&mut self,
-                                 parent_id: StackingContextId,
-                                 contexts: &mut Vec<Box<StackingContext>>)
-                                 -> StackingContextId {
-        self.block_flow.collect_stacking_contexts(parent_id, contexts)
+    fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) {
+        self.block_flow.collect_stacking_contexts(parent);
     }
 
     fn repair_style(&mut self, new_style: &Arc<ServoComputedValues>) {
         self.block_flow.repair_style(new_style)
     }
 
     fn compute_overflow(&self) -> Overflow {
         self.block_flow.compute_overflow()
@@ -266,21 +262,18 @@ impl Flow for MulticolColumnFlow {
         self.block_flow.update_late_computed_block_position_if_necessary(block_position)
     }
 
     fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
         debug!("build_display_list_multicol column");
         self.block_flow.build_display_list(state);
     }
 
-    fn collect_stacking_contexts(&mut self,
-                                 parent_id: StackingContextId,
-                                 contexts: &mut Vec<Box<StackingContext>>)
-                                 -> StackingContextId {
-        self.block_flow.collect_stacking_contexts(parent_id, contexts)
+    fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) {
+        self.block_flow.collect_stacking_contexts(parent);
     }
 
     fn repair_style(&mut self, new_style: &Arc<ServoComputedValues>) {
         self.block_flow.repair_style(new_style)
     }
 
     fn compute_overflow(&self) -> Overflow {
         self.block_flow.compute_overflow()
--- a/servo/components/layout/sequential.rs
+++ b/servo/components/layout/sequential.rs
@@ -73,20 +73,17 @@ pub fn traverse_flow_tree_preorder(root:
 
     doit(root, assign_inline_sizes, assign_block_sizes);
 }
 
 pub fn build_display_list_for_subtree(flow_root: &mut Flow,
                                       root_stacking_context: &mut StackingContext,
                                       shared_layout_context: &SharedLayoutContext)
                                       -> Vec<DisplayItem> {
-    let mut children = vec![];
-    flow_root.collect_stacking_contexts(root_stacking_context.id,
-                                        &mut children);
-    root_stacking_context.add_children(children);
+    flow_root.collect_stacking_contexts(root_stacking_context);
     let mut build_display_list = BuildDisplayList {
         state: DisplayListBuildState::new(shared_layout_context,
                                           flow::base(flow_root).stacking_context_id),
     };
     build_display_list.traverse(flow_root);
     build_display_list.state.items
 }
 
--- a/servo/components/layout/table.rs
+++ b/servo/components/layout/table.rs
@@ -12,17 +12,16 @@ use block::{ISizeConstraintInput, ISizeC
 use context::{LayoutContext, SharedLayoutContext};
 use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode, DisplayListBuildState};
 use euclid::Point2D;
 use flow;
 use flow::{BaseFlow, EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow};
 use flow_list::MutFlowListIterator;
 use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
 use gfx::display_list::StackingContext;
-use gfx_traits::StackingContextId;
 use gfx_traits::print_tree::PrintTree;
 use layout_debug;
 use model::{IntrinsicISizes, IntrinsicISizesContribution, MaybeAuto};
 use script_layout_interface::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW};
 use std::cmp;
 use std::fmt;
 use std::sync::Arc;
 use style::computed_values::{border_collapse, border_spacing, table_layout};
@@ -472,21 +471,18 @@ impl Flow for TableFlow {
                                              .border_collapse {
             border_collapse::T::separate => BorderPaintingMode::Separate,
             border_collapse::T::collapse => BorderPaintingMode::Hidden,
         };
 
         self.block_flow.build_display_list_for_block(state, border_painting_mode);
     }
 
-    fn collect_stacking_contexts(&mut self,
-                                 parent_id: StackingContextId,
-                                 contexts: &mut Vec<Box<StackingContext>>)
-                                 -> StackingContextId {
-        self.block_flow.collect_stacking_contexts(parent_id, contexts)
+    fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) {
+        self.block_flow.collect_stacking_contexts(parent);
     }
 
     fn repair_style(&mut self, new_style: &Arc<ServoComputedValues>) {
         self.block_flow.repair_style(new_style)
     }
 
     fn compute_overflow(&self) -> Overflow {
         self.block_flow.compute_overflow()
--- a/servo/components/layout/table_caption.rs
+++ b/servo/components/layout/table_caption.rs
@@ -9,17 +9,16 @@
 use app_units::Au;
 use block::BlockFlow;
 use context::{LayoutContext, SharedLayoutContext};
 use display_list_builder::DisplayListBuildState;
 use euclid::Point2D;
 use flow::{Flow, FlowClass, OpaqueFlow};
 use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
 use gfx::display_list::StackingContext;
-use gfx_traits::StackingContextId;
 use gfx_traits::print_tree::PrintTree;
 use std::fmt;
 use std::sync::Arc;
 use style::context::SharedStyleContext;
 use style::logical_geometry::LogicalSize;
 use style::properties::ServoComputedValues;
 
 /// A table formatting context.
@@ -78,21 +77,18 @@ impl Flow for TableCaptionFlow {
         self.block_flow.update_late_computed_block_position_if_necessary(block_position)
     }
 
     fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
         debug!("build_display_list_table_caption: same process as block flow");
         self.block_flow.build_display_list(state);
     }
 
-    fn collect_stacking_contexts(&mut self,
-                                 parent_id: StackingContextId,
-                                 contexts: &mut Vec<Box<StackingContext>>)
-                                 -> StackingContextId {
-        self.block_flow.collect_stacking_contexts(parent_id, contexts)
+    fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) {
+        self.block_flow.collect_stacking_contexts(parent);
     }
 
     fn repair_style(&mut self, new_style: &Arc<ServoComputedValues>) {
         self.block_flow.repair_style(new_style)
     }
 
     fn compute_overflow(&self) -> Overflow {
         self.block_flow.compute_overflow()
--- a/servo/components/layout/table_cell.rs
+++ b/servo/components/layout/table_cell.rs
@@ -10,17 +10,16 @@ use app_units::Au;
 use block::{BlockFlow, ISizeAndMarginsComputer, MarginsMayCollapseFlag};
 use context::{LayoutContext, SharedLayoutContext};
 use cssparser::Color;
 use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode, DisplayListBuildState};
 use euclid::{Point2D, Rect, SideOffsets2D, Size2D};
 use flow::{self, Flow, FlowClass, OpaqueFlow};
 use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
 use gfx::display_list::StackingContext;
-use gfx_traits::StackingContextId;
 use gfx_traits::print_tree::PrintTree;
 use layout_debug;
 use model::MaybeAuto;
 use script_layout_interface::wrapper_traits::ThreadSafeLayoutNode;
 use std::fmt;
 use std::sync::Arc;
 use style::computed_values::{border_collapse, border_top_style, vertical_align};
 use style::context::SharedStyleContext;
@@ -232,21 +231,18 @@ impl Flow for TableCellFlow {
                                              .border_collapse {
             border_collapse::T::separate => BorderPaintingMode::Separate,
             border_collapse::T::collapse => BorderPaintingMode::Collapse(&self.collapsed_borders),
         };
 
         self.block_flow.build_display_list_for_block(state, border_painting_mode)
     }
 
-    fn collect_stacking_contexts(&mut self,
-                                 parent_id: StackingContextId,
-                                 contexts: &mut Vec<Box<StackingContext>>)
-                                 -> StackingContextId {
-        self.block_flow.collect_stacking_contexts(parent_id, contexts)
+    fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) {
+        self.block_flow.collect_stacking_contexts(parent);
     }
 
     fn repair_style(&mut self, new_style: &Arc<ServoComputedValues>) {
         self.block_flow.repair_style(new_style)
     }
 
     fn compute_overflow(&self) -> Overflow {
         self.block_flow.compute_overflow()
--- a/servo/components/layout/table_colgroup.rs
+++ b/servo/components/layout/table_colgroup.rs
@@ -8,17 +8,16 @@
 
 use app_units::Au;
 use context::LayoutContext;
 use display_list_builder::DisplayListBuildState;
 use euclid::Point2D;
 use flow::{BaseFlow, Flow, FlowClass, ForceNonfloatedFlag, OpaqueFlow};
 use fragment::{Fragment, FragmentBorderBoxIterator, Overflow, SpecificFragmentInfo};
 use gfx::display_list::StackingContext;
-use gfx_traits::StackingContextId;
 use layout_debug;
 use std::cmp::max;
 use std::fmt;
 use std::sync::Arc;
 use style::context::SharedStyleContext;
 use style::logical_geometry::LogicalSize;
 use style::properties::ServoComputedValues;
 use style::values::computed::LengthOrPercentageOrAuto;
@@ -91,22 +90,17 @@ impl Flow for TableColGroupFlow {
 
     fn update_late_computed_inline_position_if_necessary(&mut self, _: Au) {}
 
     fn update_late_computed_block_position_if_necessary(&mut self, _: Au) {}
 
     // Table columns are invisible.
     fn build_display_list(&mut self, _: &mut DisplayListBuildState) { }
 
-    fn collect_stacking_contexts(&mut self,
-                                 parent_id: StackingContextId,
-                                 _: &mut Vec<Box<StackingContext>>)
-                                 -> StackingContextId {
-        parent_id
-    }
+    fn collect_stacking_contexts(&mut self, _parent: &mut StackingContext) { }
 
     fn repair_style(&mut self, _: &Arc<ServoComputedValues>) {}
 
     fn compute_overflow(&self) -> Overflow {
         Overflow::new()
     }
 
     fn generated_containing_block_size(&self, _: OpaqueFlow) -> LogicalSize<Au> {
--- a/servo/components/layout/table_row.rs
+++ b/servo/components/layout/table_row.rs
@@ -11,17 +11,16 @@ use block::{BlockFlow, ISizeAndMarginsCo
 use context::{LayoutContext, SharedLayoutContext};
 use cssparser::{Color, RGBA};
 use display_list_builder::{BlockFlowDisplayListBuilding, BorderPaintingMode, DisplayListBuildState};
 use euclid::Point2D;
 use flow::{self, EarlyAbsolutePositionInfo, Flow, FlowClass, ImmutableFlowUtils, OpaqueFlow};
 use flow_list::MutFlowListIterator;
 use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
 use gfx::display_list::StackingContext;
-use gfx_traits::StackingContextId;
 use gfx_traits::print_tree::PrintTree;
 use layout_debug;
 use model::MaybeAuto;
 use rustc_serialize::{Encodable, Encoder};
 use script_layout_interface::restyle_damage::{REFLOW, REFLOW_OUT_OF_FLOW};
 use std::cmp::max;
 use std::fmt;
 use std::iter::{Enumerate, IntoIterator, Peekable};
@@ -450,21 +449,18 @@ impl Flow for TableRowFlow {
                                              .border_collapse {
             border_collapse::T::separate => BorderPaintingMode::Separate,
             border_collapse::T::collapse => BorderPaintingMode::Hidden,
         };
 
         self.block_flow.build_display_list_for_block(state, border_painting_mode);
     }
 
-    fn collect_stacking_contexts(&mut self,
-                                 parent_id: StackingContextId,
-                                 contexts: &mut Vec<Box<StackingContext>>)
-                                 -> StackingContextId {
-        self.block_flow.collect_stacking_contexts(parent_id, contexts)
+    fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) {
+        self.block_flow.collect_stacking_contexts(parent);
     }
 
     fn repair_style(&mut self, new_style: &Arc<ServoComputedValues>) {
         self.block_flow.repair_style(new_style)
     }
 
     fn compute_overflow(&self) -> Overflow {
         self.block_flow.compute_overflow()
--- a/servo/components/layout/table_rowgroup.rs
+++ b/servo/components/layout/table_rowgroup.rs
@@ -9,17 +9,16 @@
 use app_units::Au;
 use block::{BlockFlow, ISizeAndMarginsComputer};
 use context::{LayoutContext, SharedLayoutContext};
 use display_list_builder::DisplayListBuildState;
 use euclid::Point2D;
 use flow::{Flow, FlowClass, OpaqueFlow};
 use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
 use gfx::display_list::StackingContext;
-use gfx_traits::StackingContextId;
 use gfx_traits::print_tree::PrintTree;
 use layout_debug;
 use rustc_serialize::{Encodable, Encoder};
 use std::fmt;
 use std::iter::{IntoIterator, Iterator, Peekable};
 use std::sync::Arc;
 use style::computed_values::{border_collapse, border_spacing};
 use style::context::SharedStyleContext;
@@ -207,21 +206,18 @@ impl Flow for TableRowGroupFlow {
         self.block_flow.update_late_computed_block_position_if_necessary(block_position)
     }
 
     fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
         debug!("build_display_list_table_rowgroup: same process as block flow");
         self.block_flow.build_display_list(state);
     }
 
-    fn collect_stacking_contexts(&mut self,
-                                 parent_id: StackingContextId,
-                                 contexts: &mut Vec<Box<StackingContext>>)
-                                 -> StackingContextId {
-        self.block_flow.collect_stacking_contexts(parent_id, contexts)
+    fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) {
+        self.block_flow.collect_stacking_contexts(parent);
     }
 
     fn repair_style(&mut self, new_style: &Arc<ServoComputedValues>) {
         self.block_flow.repair_style(new_style)
     }
 
     fn compute_overflow(&self) -> Overflow {
         self.block_flow.compute_overflow()
--- a/servo/components/layout/table_wrapper.rs
+++ b/servo/components/layout/table_wrapper.rs
@@ -18,17 +18,16 @@ use block::{AbsoluteNonReplaced, BlockFl
 use block::{ISizeConstraintSolution, MarginsMayCollapseFlag};
 use context::{LayoutContext, SharedLayoutContext};
 use display_list_builder::DisplayListBuildState;
 use euclid::Point2D;
 use floats::FloatKind;
 use flow::{Flow, FlowClass, ImmutableFlowUtils, INLINE_POSITION_IS_STATIC, OpaqueFlow};
 use fragment::{Fragment, FragmentBorderBoxIterator, Overflow};
 use gfx::display_list::StackingContext;
-use gfx_traits::StackingContextId;
 use gfx_traits::print_tree::PrintTree;
 use model::MaybeAuto;
 use std::cmp::{max, min};
 use std::fmt;
 use std::ops::Add;
 use std::sync::Arc;
 use style::computed_values::{border_collapse, table_layout};
 use style::context::SharedStyleContext;
@@ -440,21 +439,18 @@ impl Flow for TableWrapperFlow {
     fn generated_containing_block_size(&self, flow: OpaqueFlow) -> LogicalSize<Au> {
         self.block_flow.generated_containing_block_size(flow)
     }
 
     fn build_display_list(&mut self, state: &mut DisplayListBuildState) {
         self.block_flow.build_display_list(state);
     }
 
-    fn collect_stacking_contexts(&mut self,
-                                 parent_id: StackingContextId,
-                                 contexts: &mut Vec<Box<StackingContext>>)
-                                 -> StackingContextId {
-        self.block_flow.collect_stacking_contexts(parent_id, contexts)
+    fn collect_stacking_contexts(&mut self, parent: &mut StackingContext) {
+        self.block_flow.collect_stacking_contexts(parent);
     }
 
     fn repair_style(&mut self, new_style: &Arc<ServoComputedValues>) {
         self.block_flow.repair_style(new_style)
     }
 
     fn compute_overflow(&self) -> Overflow {
         self.block_flow.compute_overflow()