From 385e34acee65b3c7fdf9ff410722b3963a3827ee Mon Sep 17 00:00:00 2001 From: Boris Zbarsky Date: Sat, 9 Sep 2017 04:31:25 -0400 Subject: [PATCH] Avoid array overallocation when parsing background shorthand. r=xidorn This is part 2 of the fix for Gecko bug 1397614 --- .../style/properties/shorthand/background.mako.rs | 14 +++++++++++--- components/style/properties/shorthand/mask.mako.rs | 14 +++++++++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/components/style/properties/shorthand/background.mako.rs b/components/style/properties/shorthand/background.mako.rs index 10ecddf3c1c..32cf30b6db6 100644 --- a/components/style/properties/shorthand/background.mako.rs +++ b/components/style/properties/shorthand/background.mako.rs @@ -37,7 +37,11 @@ let mut background_color = None; % for name in "image position_x position_y repeat size attachment origin clip".split(): - let mut background_${name} = background_${name}::SpecifiedValue(Vec::new()); + // Vec grows from 0 to 4 by default on first push(). So allocate + // with capacity 1, so in the common case of only one item we don't + // way overallocate. Note that we always push at least one item if + // parsing succeeds. + let mut background_${name} = background_${name}::SpecifiedValue(Vec::with_capacity(1)); % endfor input.parse_comma_separated(|input| { // background-color can only be in the last element, so if it @@ -197,8 +201,12 @@ pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { - let mut position_x = background_position_x::SpecifiedValue(Vec::new()); - let mut position_y = background_position_y::SpecifiedValue(Vec::new()); + // Vec grows from 0 to 4 by default on first push(). So allocate with + // capacity 1, so in the common case of only one item we don't way + // overallocate. Note that we always push at least one item if parsing + // succeeds. + let mut position_x = background_position_x::SpecifiedValue(Vec::with_capacity(1)); + let mut position_y = background_position_y::SpecifiedValue(Vec::with_capacity(1)); let mut any = false; input.parse_comma_separated(|input| { diff --git a/components/style/properties/shorthand/mask.mako.rs b/components/style/properties/shorthand/mask.mako.rs index 5b84052c45a..b0e298317fe 100644 --- a/components/style/properties/shorthand/mask.mako.rs +++ b/components/style/properties/shorthand/mask.mako.rs @@ -38,7 +38,11 @@ pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { % for name in "image mode position_x position_y size repeat origin clip composite".split(): - let mut mask_${name} = mask_${name}::SpecifiedValue(Vec::new()); + // Vec grows from 0 to 4 by default on first push(). So allocate + // with capacity 1, so in the common case of only one item we don't + // way overallocate. Note that we always push at least one item if + // parsing succeeds. + let mut mask_${name} = mask_${name}::SpecifiedValue(Vec::with_capacity(1)); % endfor input.parse_comma_separated(|input| { @@ -183,8 +187,12 @@ pub fn parse_value<'i, 't>(context: &ParserContext, input: &mut Parser<'i, 't>) -> Result> { - let mut position_x = mask_position_x::SpecifiedValue(Vec::new()); - let mut position_y = mask_position_y::SpecifiedValue(Vec::new()); + // Vec grows from 0 to 4 by default on first push(). So allocate with + // capacity 1, so in the common case of only one item we don't way + // overallocate. Note that we always push at least one item if parsing + // succeeds. + let mut position_x = mask_position_x::SpecifiedValue(Vec::with_capacity(1)); + let mut position_y = mask_position_y::SpecifiedValue(Vec::with_capacity(1)); let mut any = false; input.parse_comma_separated(|input| {