diff --git a/servo/Cargo.lock b/servo/Cargo.lock index fda32df1fe83..9b07d56bd6ad 100644 --- a/servo/Cargo.lock +++ b/servo/Cargo.lock @@ -2885,6 +2885,7 @@ dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)", "cssparser 0.23.2 (registry+https://github.com/rust-lang/crates.io-index)", + "debug_unreachable 0.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "encoding_rs 0.7.1 (registry+https://github.com/rust-lang/crates.io-index)", "euclid 0.16.4 (registry+https://github.com/rust-lang/crates.io-index)", "fallible 0.0.1", diff --git a/servo/components/style/Cargo.toml b/servo/components/style/Cargo.toml index cb4b93d198e0..ac7d71f64781 100644 --- a/servo/components/style/Cargo.toml +++ b/servo/components/style/Cargo.toml @@ -32,6 +32,7 @@ bitflags = "1.0" byteorder = "1.0" cfg-if = "0.1.0" cssparser = "0.23.0" +debug_unreachable = "0.1.1" encoding_rs = {version = "0.7", optional = true} euclid = "0.16" fallible = { path = "../fallible" } diff --git a/servo/components/style/lib.rs b/servo/components/style/lib.rs index 59c9f69b0220..cbe8a12ee020 100644 --- a/servo/components/style/lib.rs +++ b/servo/components/style/lib.rs @@ -33,6 +33,7 @@ extern crate bitflags; #[allow(unused_extern_crates)] extern crate byteorder; #[cfg(feature = "gecko")] #[macro_use] #[no_link] extern crate cfg_if; #[macro_use] extern crate cssparser; +#[macro_use] extern crate debug_unreachable; extern crate euclid; extern crate fallible; extern crate fnv; diff --git a/servo/components/style/properties/data.py b/servo/components/style/properties/data.py index 9974815d88c8..ae25fb58e840 100644 --- a/servo/components/style/properties/data.py +++ b/servo/components/style/properties/data.py @@ -229,6 +229,58 @@ class Longhand(object): def enabled_in_content(self): return self.enabled_in == "content" + def specified_type(self): + if self.predefined_type and not self.is_vector: + ty = "::values::specified::{}".format(self.predefined_type) + else: + ty = "longhands::{}::SpecifiedValue".format(self.ident) + if self.boxed: + ty = "Box<{}>".format(ty) + return ty + + def specified_is_copy(self): + if self.is_vector or self.boxed: + return False + if self.predefined_type: + return self.predefined_type in { + "AlignContent", + "AlignItems", + "AlignSelf", + "BackgroundRepeat", + "BorderImageRepeat", + "BorderStyle", + "Contain", + "FontStyleAdjust", + "FontSynthesis", + "FontWeight", + "GridAutoFlow", + "ImageOrientation", + "InitialLetter", + "Integer", + "IntegerOrAuto", + "JustifyContent", + "JustifyItems", + "JustifySelf", + "MozForceBrokenImageIcon", + "MozScriptLevel", + "MozScriptMinSize", + "MozScriptSizeMultiplier", + "NonNegativeNumber", + "Opacity", + "OutlineStyle", + "OverscrollBehavior", + "Percentage", + "PositiveIntegerOrAuto", + "SVGPaintOrder", + "ScrollSnapType", + "TextDecorationLine", + "TouchAction", + "TransformStyle", + "XSpan", + "XTextZoom", + } + return bool(self.keyword) + class Shorthand(object): def __init__(self, name, sub_properties, spec=None, servo_pref=None, gecko_pref=None, diff --git a/servo/components/style/properties/properties.mako.rs b/servo/components/style/properties/properties.mako.rs index 73bfe8cf4006..01d32eb0e49a 100644 --- a/servo/components/style/properties/properties.mako.rs +++ b/servo/components/style/properties/properties.mako.rs @@ -206,31 +206,35 @@ pub mod animated_properties { <% from itertools import groupby + # After this code, `data.longhands` is sorted in the following order: + # - first all keyword variants and all variants known to be Copy, + # - second all the other variants, such as all variants with the same field + # have consecutive discriminants. + # The variable `variants` contain the same entries as `data.longhands` in + # the same order, but must exist separately to the data source, because + # we then need to add three additional variants `WideKeywordDeclaration`, + # `VariableDeclaration` and `CustomDeclaration`. + variants = [] for property in data.longhands: - if property.predefined_type and not property.is_vector: - ty = "::values::specified::{}".format(property.predefined_type) - else: - ty = "longhands::{}::SpecifiedValue".format(property.ident) - if property.boxed: - ty = "Box<{}>".format(ty) variants.append({ "name": property.camel_case, - "type": ty, + "type": property.specified_type(), "doc": "`" + property.name + "`", + "copy": property.specified_is_copy(), }) groups = {} keyfunc = lambda x: x["type"] sortkeys = {} for ty, group in groupby(sorted(variants, key=keyfunc), keyfunc): - group = [v["name"] for v in group] + group = list(group) groups[ty] = group for v in group: if len(group) == 1: - sortkeys[v] = (1, v, "") + sortkeys[v["name"]] = (not v["copy"], 1, v["name"], "") else: - sortkeys[v] = (len(group), ty, v) + sortkeys[v["name"]] = (not v["copy"], len(group), ty, v["name"]) variants.sort(key=lambda x: sortkeys[x["name"]]) # It is extremely important to sort the `data.longhands` array here so @@ -250,21 +254,24 @@ pub mod animated_properties { "name": "CSSWideKeyword", "type": "WideKeywordDeclaration", "doc": "A CSS-wide keyword.", + "copy": False, }, { "name": "WithVariables", "type": "VariableDeclaration", "doc": "An unparsed declaration.", + "copy": False, }, { "name": "Custom", "type": "CustomDeclaration", "doc": "A custom property declaration.", + "copy": False, }, ] for v in extra: variants.append(v) - groups[v["type"]] = [v["name"]] + groups[v["type"]] = [v] %> /// Servo's representation for a property declaration. @@ -287,14 +294,46 @@ impl Clone for PropertyDeclaration { fn clone(&self) -> Self { use self::PropertyDeclaration::*; + <% + [copy, others] = [list(g) for _, g in groupby(variants, key=lambda x: not x["copy"])] + %> + + let self_tag = unsafe { + (*(self as *const _ as *const PropertyDeclarationVariantRepr<()>)).tag + }; + if self_tag <= LonghandId::${copy[-1]["name"]} as u16 { + #[derive(Clone, Copy)] + #[repr(u16)] + enum CopyVariants { + % for v in copy: + _${v["name"]}(${v["type"]}), + % endfor + } + + unsafe { + let mut out = mem::uninitialized(); + ptr::write( + &mut out as *mut _ as *mut CopyVariants, + *(self as *const _ as *const CopyVariants), + ); + return out; + } + } + match *self { - % for ty, variants in groups.iteritems(): - % if len(variants) == 1: - ${variants[0]}(ref value) => { - ${variants[0]}(value.clone()) + ${" |\n".join("{}(..)".format(v["name"]) for v in copy)} => { + unsafe { debug_unreachable!() } + } + % for ty, vs in groupby(others, key=lambda x: x["type"]): + <% + vs = list(vs) + %> + % if len(vs) == 1: + ${vs[0]["name"]}(ref value) => { + ${vs[0]["name"]}(value.clone()) } % else: - ${" | ".join("{}(ref value)".format(v) for v in variants)} => { + ${" |\n".join("{}(ref value)".format(v["name"]) for v in vs)} => { unsafe { let mut out = ManuallyDrop::new(mem::uninitialized()); ptr::write( @@ -327,8 +366,8 @@ impl PartialEq for PropertyDeclaration { return false; } match *self { - % for ty, variants in groups.iteritems(): - ${" | ".join("{}(ref this)".format(v) for v in variants)} => { + % for ty, vs in groupby(variants, key=lambda x: x["type"]): + ${" |\n".join("{}(ref this)".format(v["name"]) for v in vs)} => { let other_repr = &*(other as *const _ as *const PropertyDeclarationVariantRepr<${ty}>); *this == other_repr.value @@ -346,8 +385,8 @@ impl MallocSizeOf for PropertyDeclaration { use self::PropertyDeclaration::*; match *self { - % for ty, variants in groups.iteritems(): - ${" | ".join("{}(ref value)".format(v) for v in variants)} => { + % for ty, vs in groupby(variants, key=lambda x: x["type"]): + ${" | ".join("{}(ref value)".format(v["name"]) for v in vs)} => { value.size_of(ops) } % endfor @@ -365,8 +404,8 @@ impl PropertyDeclaration { let mut dest = CssWriter::new(dest); match *self { - % for ty, variants in groups.iteritems(): - ${" | ".join("{}(ref value)".format(v) for v in variants)} => { + % for ty, vs in groupby(variants, key=lambda x: x["type"]): + ${" | ".join("{}(ref value)".format(v["name"]) for v in vs)} => { value.to_css(&mut dest) } % endfor diff --git a/servo/components/style/values/generics/transform.rs b/servo/components/style/values/generics/transform.rs index f28188427239..caa71d151023 100644 --- a/servo/components/style/values/generics/transform.rs +++ b/servo/components/style/values/generics/transform.rs @@ -675,8 +675,8 @@ pub fn get_normalized_vector_and_angle( } } -#[derive(ComputeSquaredDistance, ToAnimatedZero, ToComputedValue)] -#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)] +#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq)] +#[derive(ToAnimatedZero, ToComputedValue, ToCss)] /// A value of the `Rotate` property /// /// @@ -689,8 +689,8 @@ pub enum Rotate { Rotate3D(Number, Number, Number, Angle), } -#[derive(ComputeSquaredDistance, ToAnimatedZero, ToComputedValue)] -#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)] +#[derive(Clone, ComputeSquaredDistance, Copy, Debug, MallocSizeOf, PartialEq)] +#[derive(ToAnimatedZero, ToComputedValue, ToCss)] /// A value of the `Scale` property /// /// diff --git a/servo/components/style/values/specified/background.rs b/servo/components/style/values/specified/background.rs index e26414ca7683..4387563a3b14 100644 --- a/servo/components/style/values/specified/background.rs +++ b/servo/components/style/values/specified/background.rs @@ -58,7 +58,7 @@ pub enum BackgroundRepeatKeyword { /// The specified value for the `background-repeat` property. /// /// https://drafts.csswg.org/css-backgrounds/#the-background-repeat -#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)] pub enum BackgroundRepeat { /// `repeat-x` RepeatX, diff --git a/servo/components/style/values/specified/border.rs b/servo/components/style/values/specified/border.rs index f382e1d4634b..a9cc4fc2983e 100644 --- a/servo/components/style/values/specified/border.rs +++ b/servo/components/style/values/specified/border.rs @@ -186,7 +186,7 @@ pub enum BorderImageRepeatKeyword { /// The specified value for the `border-image-repeat` property. /// /// https://drafts.csswg.org/css-backgrounds/#the-border-image-repeat -#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToCss)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToCss)] pub struct BorderImageRepeat(pub BorderImageRepeatKeyword, pub Option); impl BorderImageRepeat { diff --git a/servo/components/style/values/specified/font.rs b/servo/components/style/values/specified/font.rs index 6d126def2287..a9309267ad40 100644 --- a/servo/components/style/values/specified/font.rs +++ b/servo/components/style/values/specified/font.rs @@ -1757,7 +1757,7 @@ impl Parse for FontFeatureSettings { } } -#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue)] /// Whether user agents are allowed to synthesize bold or oblique font faces /// when a font family lacks bold or italic faces pub struct FontSynthesis { @@ -2035,7 +2035,7 @@ impl Parse for VariationValue { } -#[derive(Clone, Debug, MallocSizeOf, PartialEq, ToComputedValue)] +#[derive(Clone, Copy, Debug, MallocSizeOf, PartialEq, ToComputedValue)] /// text-zoom. Enable if true, disable if false pub struct XTextZoom(pub bool); @@ -2087,7 +2087,7 @@ impl ToCss for XLang { } #[cfg_attr(feature = "gecko", derive(MallocSizeOf))] -#[derive(Clone, Debug, PartialEq, ToCss)] +#[derive(Clone, Copy, Debug, PartialEq, ToCss)] /// Specifies the minimum font size allowed due to changes in scriptlevel. /// Ref: https://wiki.mozilla.org/MathML:mstyle pub struct MozScriptMinSize(pub NoCalcLength);