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
This commit is contained in:
Emilio Cobos Álvarez 2018-07-27 14:30:14 +02:00
parent 5a7358b833
commit 0b520c9558
No known key found for this signature in database
GPG key ID: 056B727BB9C1027C

View file

@ -410,17 +410,35 @@ pub mod animated_properties {
#[derive(Clone, Copy, Debug)] #[derive(Clone, Copy, Debug)]
pub struct NonCustomPropertyId(usize); 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 { impl NonCustomPropertyId {
#[cfg(feature = "gecko")] #[cfg(feature = "gecko")]
#[inline] #[inline]
fn to_nscsspropertyid(self) -> nsCSSPropertyID { fn to_nscsspropertyid(self) -> nsCSSPropertyID {
static MAP: [nsCSSPropertyID; ${len(data.longhands) + len(data.shorthands) + len(data.all_aliases())}] = [ // unsafe: guaranteed by static_assert_nscsspropertyid above.
% for property in data.longhands + data.shorthands + data.all_aliases(): unsafe { ::std::mem::transmute(self.0 as i32) }
${property.nscsspropertyid()}, }
% endfor
];
MAP[self.0] #[cfg(feature = "gecko")]
#[inline]
fn from_nscsspropertyid(prop: nsCSSPropertyID) -> Result<Self, ()> {
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. /// Get the property name.
@ -428,7 +446,7 @@ impl NonCustomPropertyId {
fn name(self) -> &'static str { fn name(self) -> &'static str {
static MAP: [&'static str; ${len(data.longhands) + len(data.shorthands) + len(data.all_aliases())}] = [ static MAP: [&'static str; ${len(data.longhands) + len(data.shorthands) + len(data.all_aliases())}] = [
% for property in data.longhands + data.shorthands + data.all_aliases(): % for property in data.longhands + data.shorthands + data.all_aliases():
"${property.name}", "${property.name}",
% endfor % endfor
]; ];
MAP[self.0] MAP[self.0]
@ -464,7 +482,7 @@ impl NonCustomPropertyId {
PREFS.get(pref).as_boolean().unwrap_or(false) PREFS.get(pref).as_boolean().unwrap_or(false)
% else: % else:
unsafe { structs::nsCSSProps_gPropertyEnabled[self.to_nscsspropertyid() as usize] } unsafe { structs::nsCSSProps_gPropertyEnabled[self.0] }
% endif % endif
}; };
@ -585,6 +603,30 @@ impl NonCustomPropertyId {
]; ];
COLLECT_FUNCTIONS[self.0](f); 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<LonghandId> for NonCustomPropertyId { impl From<LonghandId> for NonCustomPropertyId {
@ -1237,10 +1279,11 @@ where
/// An identifier for a given shorthand property. /// An identifier for a given shorthand property.
#[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)] #[derive(Clone, Copy, Debug, Eq, Hash, MallocSizeOf, PartialEq)]
#[repr(u16)]
pub enum ShorthandId { pub enum ShorthandId {
% for property in data.shorthands: % for i, property in enumerate(data.shorthands):
/// ${property.name} /// ${property.name}
${property.camel_case}, ${property.camel_case} = ${i},
% endfor % endfor
} }
@ -1767,42 +1810,11 @@ impl PropertyId {
} }
/// Returns a property id from Gecko's nsCSSPropertyID. /// 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")] #[cfg(feature = "gecko")]
#[allow(non_upper_case_globals)] #[allow(non_upper_case_globals)]
#[inline]
pub fn from_nscsspropertyid(id: nsCSSPropertyID) -> Result<Self, ()> { pub fn from_nscsspropertyid(id: nsCSSPropertyID) -> Result<Self, ()> {
use gecko_bindings::structs::*; Ok(NonCustomPropertyId::from_nscsspropertyid(id)?.to_property_id())
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(())
}
} }
/// Returns true if the property is a shorthand or shorthand alias. /// 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. /// An identifier for a given alias property.
#[derive(Clone, Copy, Eq, PartialEq)] #[derive(Clone, Copy, Eq, PartialEq)]
#[cfg_attr(feature = "servo", derive(MallocSizeOf))] #[cfg_attr(feature = "servo", derive(MallocSizeOf))]
#[repr(u16)]
pub enum AliasId { pub enum AliasId {
% for i, property in enumerate(data.all_aliases()): % for i, property in enumerate(data.all_aliases()):
/// ${property.name} /// ${property.name}
@ -4237,17 +4250,37 @@ pub enum AliasId {
% endfor % endfor
} }
#[derive(Clone, Copy, Eq, PartialEq)]
enum AliasedPropertyId {
Shorthand(ShorthandId),
Longhand(LonghandId),
}
impl fmt::Debug for AliasId { impl fmt::Debug for AliasId {
fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
let name = match *self { let name = NonCustomPropertyId::from(*self).name();
% for property in data.all_aliases():
AliasId::${property.camel_case} => "${property.camel_case}",
% endfor
};
formatter.write_str(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. // NOTE(emilio): Callers are responsible to deal with prefs.
#[macro_export] #[macro_export]
macro_rules! css_properties_accessors { macro_rules! css_properties_accessors {