From 0b520c955881f1106bc037ef2444399eff7e98f9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Emilio=20Cobos=20=C3=81lvarez?= Date: Fri, 27 Jul 2018 14:30:14 +0200 Subject: [PATCH] style: Make NonCustomPropertyId <-> nsCSSPropertyId conversions fast. We have a different order in nsCSSPropertyId for no good reason. The only invariant there is that longhands come before shorthands, and shorthands before aliases. Luckily that's also an invariant that NonCustomPropertyId has, so we can reuse them. Differential Revision: https://phabricator.services.mozilla.com/D2463 MozReview-Commit-ID: 1hsQu6hmqiN --- .../style/properties/properties.mako.rs | 129 +++++++++++------- 1 file changed, 81 insertions(+), 48 deletions(-) diff --git a/components/style/properties/properties.mako.rs b/components/style/properties/properties.mako.rs index 28bdb05739cc..5e341e82d6da 100644 --- a/components/style/properties/properties.mako.rs +++ b/components/style/properties/properties.mako.rs @@ -410,17 +410,35 @@ pub mod animated_properties { #[derive(Clone, Copy, Debug)] pub struct NonCustomPropertyId(usize); +% if product == "gecko": +#[allow(dead_code)] +unsafe fn static_assert_nscsspropertyid() { + % for i, property in enumerate(data.longhands + data.shorthands + data.all_aliases()): + ::std::mem::transmute::<[u8; ${i}], [u8; ${property.nscsspropertyid()} as usize]>([0; ${i}]); // ${property.name} + % endfor +} +% endif + impl NonCustomPropertyId { #[cfg(feature = "gecko")] #[inline] fn to_nscsspropertyid(self) -> nsCSSPropertyID { - static MAP: [nsCSSPropertyID; ${len(data.longhands) + len(data.shorthands) + len(data.all_aliases())}] = [ - % for property in data.longhands + data.shorthands + data.all_aliases(): - ${property.nscsspropertyid()}, - % endfor - ]; + // unsafe: guaranteed by static_assert_nscsspropertyid above. + unsafe { ::std::mem::transmute(self.0 as i32) } + } - MAP[self.0] + #[cfg(feature = "gecko")] + #[inline] + fn from_nscsspropertyid(prop: nsCSSPropertyID) -> Result { + let prop = prop as i32; + if prop < 0 { + return Err(()); + } + if prop >= ${len(data.longhands) + len(data.shorthands) + len(data.all_aliases())} { + return Err(()); + } + // unsafe: guaranteed by static_assert_nscsspropertyid above. + Ok(unsafe { ::std::mem::transmute(prop as usize) }) } /// Get the property name. @@ -428,7 +446,7 @@ impl NonCustomPropertyId { fn name(self) -> &'static str { static MAP: [&'static str; ${len(data.longhands) + len(data.shorthands) + len(data.all_aliases())}] = [ % for property in data.longhands + data.shorthands + data.all_aliases(): - "${property.name}", + "${property.name}", % endfor ]; MAP[self.0] @@ -464,7 +482,7 @@ impl NonCustomPropertyId { PREFS.get(pref).as_boolean().unwrap_or(false) % else: - unsafe { structs::nsCSSProps_gPropertyEnabled[self.to_nscsspropertyid() as usize] } + unsafe { structs::nsCSSProps_gPropertyEnabled[self.0] } % endif }; @@ -585,6 +603,30 @@ impl NonCustomPropertyId { ]; COLLECT_FUNCTIONS[self.0](f); } + + #[inline] + fn to_property_id(self) -> PropertyId { + use std::mem::transmute; + if self.0 < ${len(data.longhands)} { + return unsafe { + PropertyId::Longhand(transmute(self.0 as u16)) + } + } + if self.0 < ${len(data.longhands) + len(data.shorthands)} { + return unsafe { + PropertyId::Shorthand(transmute((self.0 - ${len(data.longhands)}) as u16)) + } + } + assert!(self.0 < ${len(data.longhands) + len(data.shorthands) + len(data.all_aliases())}); + let alias_id: AliasId = unsafe { + transmute((self.0 - ${len(data.longhands) + len(data.shorthands)}) as u16) + }; + + match alias_id.aliased_property() { + AliasedPropertyId::Longhand(longhand) => PropertyId::LonghandAlias(longhand, alias_id), + AliasedPropertyId::Shorthand(shorthand) => PropertyId::ShorthandAlias(shorthand, alias_id), + } + } } impl From for NonCustomPropertyId { @@ -1237,10 +1279,11 @@ where /// An identifier for a given shorthand property. #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)] +#[repr(u16)] pub enum ShorthandId { - % for property in data.shorthands: + % for i, property in enumerate(data.shorthands): /// ${property.name} - ${property.camel_case}, + ${property.camel_case} = ${i}, % endfor } @@ -1767,42 +1810,11 @@ impl PropertyId { } /// Returns a property id from Gecko's nsCSSPropertyID. - /// - /// TODO(emilio): We should be able to make this a single integer cast to - /// `NonCustomPropertyId`. #[cfg(feature = "gecko")] #[allow(non_upper_case_globals)] + #[inline] pub fn from_nscsspropertyid(id: nsCSSPropertyID) -> Result { - use gecko_bindings::structs::*; - match id { - % for property in data.longhands: - ${property.nscsspropertyid()} => { - Ok(PropertyId::Longhand(LonghandId::${property.camel_case})) - } - % for alias in property.alias: - ${alias.nscsspropertyid()} => { - Ok(PropertyId::LonghandAlias( - LonghandId::${property.camel_case}, - AliasId::${alias.camel_case} - )) - } - % endfor - % endfor - % for property in data.shorthands: - ${property.nscsspropertyid()} => { - Ok(PropertyId::Shorthand(ShorthandId::${property.camel_case})) - } - % for alias in property.alias: - ${alias.nscsspropertyid()} => { - Ok(PropertyId::ShorthandAlias( - ShorthandId::${property.camel_case}, - AliasId::${alias.camel_case} - )) - } - % endfor - % endfor - _ => Err(()) - } + Ok(NonCustomPropertyId::from_nscsspropertyid(id)?.to_property_id()) } /// Returns true if the property is a shorthand or shorthand alias. @@ -4230,6 +4242,7 @@ pub fn adjust_border_width(style: &mut StyleBuilder) { /// An identifier for a given alias property. #[derive(Clone, Copy, Eq, PartialEq)] #[cfg_attr(feature = "servo", derive(MallocSizeOf))] +#[repr(u16)] pub enum AliasId { % for i, property in enumerate(data.all_aliases()): /// ${property.name} @@ -4237,17 +4250,37 @@ pub enum AliasId { % endfor } +#[derive(Clone, Copy, Eq, PartialEq)] +enum AliasedPropertyId { + Shorthand(ShorthandId), + Longhand(LonghandId), +} + impl fmt::Debug for AliasId { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { - let name = match *self { - % for property in data.all_aliases(): - AliasId::${property.camel_case} => "${property.camel_case}", - % endfor - }; + let name = NonCustomPropertyId::from(*self).name(); formatter.write_str(name) } } +impl AliasId { + /// Returns the property we're aliasing, as a longhand or a shorthand. + #[inline] + fn aliased_property(self) -> AliasedPropertyId { + static MAP: [AliasedPropertyId; ${len(data.all_aliases())}] = [ + % for alias in data.all_aliases(): + % if alias.original.type() == "longhand": + AliasedPropertyId::Longhand(LonghandId::${alias.original.camel_case}), + % else: + <% assert alias.original.type() == "shorthand" %> + AliasedPropertyId::Shorthand(ShorthandId::${alias.original.camel_case}), + % endif + % endfor + ]; + MAP[self as usize] + } +} + // NOTE(emilio): Callers are responsible to deal with prefs. #[macro_export] macro_rules! css_properties_accessors {