Don't use SmallVec<[T; 1]> for computed values with an empty default

This commit is contained in:
Anthony Ramine 2017-06-27 12:00:40 +02:00
parent da9d2001db
commit 813883e1bd
2 changed files with 48 additions and 35 deletions

View file

@ -83,6 +83,7 @@
delegate_animate=False, separator='Comma', **kwargs)"> delegate_animate=False, separator='Comma', **kwargs)">
<%call expr="longhand(name, vector=True, **kwargs)"> <%call expr="longhand(name, vector=True, **kwargs)">
% if not gecko_only: % if not gecko_only:
#[allow(unused_imports)]
use smallvec::SmallVec; use smallvec::SmallVec;
use std::fmt; use std::fmt;
#[allow(unused_imports)] #[allow(unused_imports)]
@ -113,13 +114,23 @@
pub mod computed_value { pub mod computed_value {
pub use super::single_value::computed_value as single_value; pub use super::single_value::computed_value as single_value;
pub use self::single_value::T as SingleComputedValue; pub use self::single_value::T as SingleComputedValue;
% if allow_empty and allow_empty != "NotInitial":
use std::vec::IntoIter;
% else:
use smallvec::{IntoIter, SmallVec}; use smallvec::{IntoIter, SmallVec};
% endif
use values::computed::ComputedVecIter; use values::computed::ComputedVecIter;
/// The computed value, effectively a list of single values. /// The computed value, effectively a list of single values.
#[derive(Debug, Clone, PartialEq)] #[derive(Debug, Clone, PartialEq)]
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
pub struct T(pub SmallVec<[single_value::T; 1]>); pub struct T(
% if allow_empty and allow_empty != "NotInitial":
pub Vec<single_value::T>,
% else:
pub SmallVec<[single_value::T; 1]>,
% endif
);
% if delegate_animate: % if delegate_animate:
use properties::animated_properties::Animatable; use properties::animated_properties::Animatable;
@ -149,7 +160,11 @@
impl IntoIterator for T { impl IntoIterator for T {
type Item = single_value::T; type Item = single_value::T;
% if allow_empty and allow_empty != "NotInitial":
type IntoIter = IntoIter<single_value::T>;
% else:
type IntoIter = IntoIter<[single_value::T; 1]>; type IntoIter = IntoIter<[single_value::T; 1]>;
% endif
fn into_iter(self) -> Self::IntoIter { fn into_iter(self) -> Self::IntoIter {
self.0.into_iter() self.0.into_iter()
} }
@ -207,7 +222,7 @@
pub fn get_initial_value() -> computed_value::T { pub fn get_initial_value() -> computed_value::T {
% if allow_empty and allow_empty != "NotInitial": % if allow_empty and allow_empty != "NotInitial":
computed_value::T(SmallVec::new()) computed_value::T(vec![])
% else: % else:
let mut v = SmallVec::new(); let mut v = SmallVec::new();
v.push(single_value::get_initial_value()); v.push(single_value::get_initial_value());

View file

@ -808,31 +808,37 @@ pub trait RepeatableListAnimatable: Animatable {}
impl RepeatableListAnimatable for LengthOrPercentage {} impl RepeatableListAnimatable for LengthOrPercentage {}
impl RepeatableListAnimatable for Either<f32, LengthOrPercentage> {} impl RepeatableListAnimatable for Either<f32, LengthOrPercentage> {}
impl<T: RepeatableListAnimatable> Animatable for SmallVec<[T; 1]> { macro_rules! repeated_vec_impl {
fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64) ($($ty:ty),*) => {
-> Result<Self, ()> { $(impl<T: RepeatableListAnimatable> Animatable for $ty {
use num_integer::lcm; fn add_weighted(&self, other: &Self, self_portion: f64, other_portion: f64)
let len = lcm(self.len(), other.len()); -> Result<Self, ()> {
self.iter().cycle().zip(other.iter().cycle()).take(len).map(|(me, you)| { use num_integer::lcm;
me.add_weighted(you, self_portion, other_portion) let len = lcm(self.len(), other.len());
}).collect() self.iter().cycle().zip(other.iter().cycle()).take(len).map(|(me, you)| {
} me.add_weighted(you, self_portion, other_portion)
}).collect()
}
#[inline] #[inline]
fn compute_distance(&self, other: &Self) -> Result<f64, ()> { fn compute_distance(&self, other: &Self) -> Result<f64, ()> {
self.compute_squared_distance(other).map(|sd| sd.sqrt()) self.compute_squared_distance(other).map(|sd| sd.sqrt())
} }
#[inline] #[inline]
fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> { fn compute_squared_distance(&self, other: &Self) -> Result<f64, ()> {
use num_integer::lcm; use num_integer::lcm;
let len = lcm(self.len(), other.len()); let len = lcm(self.len(), other.len());
self.iter().cycle().zip(other.iter().cycle()).take(len).map(|(me, you)| { self.iter().cycle().zip(other.iter().cycle()).take(len).map(|(me, you)| {
me.compute_squared_distance(you) me.compute_squared_distance(you)
}).collect::<Result<Vec<_>, _>>().map(|d| d.iter().sum()) }).sum()
} }
})*
};
} }
repeated_vec_impl!(SmallVec<[T; 1]>, Vec<T>);
/// https://drafts.csswg.org/css-transitions/#animtype-number /// https://drafts.csswg.org/css-transitions/#animtype-number
impl Animatable for Au { impl Animatable for Au {
#[inline] #[inline]
@ -3053,9 +3059,9 @@ pub struct IntermediateShadow {
#[cfg_attr(feature = "servo", derive(HeapSizeOf))] #[cfg_attr(feature = "servo", derive(HeapSizeOf))]
#[allow(missing_docs)] #[allow(missing_docs)]
/// Intermediate type for box-shadow list and text-shadow list. /// Intermediate type for box-shadow list and text-shadow list.
pub struct IntermediateShadowList(pub SmallVec<[IntermediateShadow; 1]>); pub struct IntermediateShadowList(pub Vec<IntermediateShadow>);
type ShadowList = SmallVec<[Shadow; 1]>; type ShadowList = Vec<Shadow>;
impl From<IntermediateShadowList> for ShadowList { impl From<IntermediateShadowList> for ShadowList {
fn from(shadow_list: IntermediateShadowList) -> Self { fn from(shadow_list: IntermediateShadowList) -> Self {
@ -3172,11 +3178,7 @@ impl Animatable for IntermediateShadowList {
let max_len = cmp::max(self.0.len(), other.0.len()); let max_len = cmp::max(self.0.len(), other.0.len());
let mut result = if max_len > 1 { let mut result = Vec::with_capacity(max_len);
SmallVec::from_vec(Vec::with_capacity(max_len))
} else {
SmallVec::new()
};
for i in 0..max_len { for i in 0..max_len {
let shadow = match (self.0.get(i), other.0.get(i)) { let shadow = match (self.0.get(i), other.0.get(i)) {
@ -3202,11 +3204,7 @@ impl Animatable for IntermediateShadowList {
fn add(&self, other: &Self) -> Result<Self, ()> { fn add(&self, other: &Self) -> Result<Self, ()> {
let len = self.0.len() + other.0.len(); let len = self.0.len() + other.0.len();
let mut result = if len > 1 { let mut result = Vec::with_capacity(len);
SmallVec::from_vec(Vec::with_capacity(len))
} else {
SmallVec::new()
};
result.extend(self.0.iter().cloned()); result.extend(self.0.iter().cloned());
result.extend(other.0.iter().cloned()); result.extend(other.0.iter().cloned());