style: Fix LengthPercentage on big-endian machines.

Always store the pointer in little-endian order so that the tag trick works.

Differential Revision: https://phabricator.services.mozilla.com/D61386
This commit is contained in:
Emilio Cobos Álvarez 2020-02-01 00:32:51 +01:00
parent 071ce6f345
commit d5b49f14da
No known key found for this signature in database
GPG key ID: E1152D0994E4BF8A

View file

@ -42,7 +42,7 @@ use style_traits::{CssWriter, ToCss};
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
#[repr(C)] #[repr(C)]
pub struct LengthVariant { pub struct LengthVariant {
tag: u32, tag: u8,
length: Length, length: Length,
} }
@ -50,7 +50,7 @@ pub struct LengthVariant {
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
#[repr(C)] #[repr(C)]
pub struct PercentageVariant { pub struct PercentageVariant {
tag: u32, tag: u8,
percentage: Percentage, percentage: Percentage,
} }
@ -61,7 +61,7 @@ pub struct PercentageVariant {
#[repr(C)] #[repr(C)]
#[cfg(target_pointer_width = "32")] #[cfg(target_pointer_width = "32")]
pub struct CalcVariant { pub struct CalcVariant {
tag: u32, tag: u8,
ptr: *mut CalcLengthPercentage, ptr: *mut CalcLengthPercentage,
} }
@ -70,7 +70,7 @@ pub struct CalcVariant {
#[repr(C)] #[repr(C)]
#[cfg(target_pointer_width = "64")] #[cfg(target_pointer_width = "64")]
pub struct CalcVariant { pub struct CalcVariant {
ptr: *mut CalcLengthPercentage, ptr: usize, // In little-endian byte order
} }
// `CalcLengthPercentage` is `Send + Sync` as asserted below. // `CalcLengthPercentage` is `Send + Sync` as asserted below.
@ -81,7 +81,7 @@ unsafe impl Sync for CalcVariant {}
#[derive(Clone, Copy)] #[derive(Clone, Copy)]
#[repr(C)] #[repr(C)]
pub struct TagVariant { pub struct TagVariant {
tag: u32, tag: u8,
} }
/// A `<length-percentage>` value. This can be either a `<length>`, a /// A `<length-percentage>` value. This can be either a `<length>`, a
@ -114,17 +114,17 @@ pub union LengthPercentageUnion {
impl LengthPercentageUnion { impl LengthPercentageUnion {
#[doc(hidden)] // Need to be public so that cbindgen generates it. #[doc(hidden)] // Need to be public so that cbindgen generates it.
pub const TAG_CALC: u32 = 0; pub const TAG_CALC: u8 = 0;
#[doc(hidden)] #[doc(hidden)]
pub const TAG_LENGTH: u32 = 1; pub const TAG_LENGTH: u8 = 1;
#[doc(hidden)] #[doc(hidden)]
pub const TAG_PERCENTAGE: u32 = 2; pub const TAG_PERCENTAGE: u8 = 2;
#[doc(hidden)] #[doc(hidden)]
pub const TAG_MASK: u32 = 0b11; pub const TAG_MASK: u8 = 0b11;
} }
#[derive(Clone, Copy, Debug, PartialEq)] #[derive(Clone, Copy, Debug, PartialEq)]
#[repr(u32)] #[repr(u8)]
enum Tag { enum Tag {
Calc = LengthPercentageUnion::TAG_CALC, Calc = LengthPercentageUnion::TAG_CALC,
Length = LengthPercentageUnion::TAG_LENGTH, Length = LengthPercentageUnion::TAG_LENGTH,
@ -147,7 +147,7 @@ unsafe fn static_assert() {
impl Drop for LengthPercentage { impl Drop for LengthPercentage {
fn drop(&mut self) { fn drop(&mut self) {
if self.tag() == Tag::Calc { if self.tag() == Tag::Calc {
let _ = unsafe { Box::from_raw(self.0.calc.ptr) }; let _ = unsafe { Box::from_raw(self.calc_ptr()) };
} }
} }
} }
@ -236,13 +236,22 @@ impl LengthPercentage {
/// checking. /// checking.
fn new_calc_unchecked(calc: Box<CalcLengthPercentage>) -> Self { fn new_calc_unchecked(calc: Box<CalcLengthPercentage>) -> Self {
let ptr = Box::into_raw(calc); let ptr = Box::into_raw(calc);
let calc = Self(LengthPercentageUnion {
calc: CalcVariant { #[cfg(target_pointer_width = "32")]
#[cfg(target_pointer_width = "32")] let calc = CalcVariant {
tag: LengthPercentageUnion::TAG_CALC, tag: LengthPercentageUnion::TAG_CALC,
ptr, ptr,
}, };
});
#[cfg(target_pointer_width = "64")]
let calc = CalcVariant {
#[cfg(target_endian = "little")]
ptr: ptr as usize,
#[cfg(target_endian = "big")]
ptr: (ptr as usize).swap_bytes(),
};
let calc = Self(LengthPercentageUnion { calc });
debug_assert_eq!(calc.tag(), Tag::Calc); debug_assert_eq!(calc.tag(), Tag::Calc);
calc calc
} }
@ -261,13 +270,25 @@ impl LengthPercentage {
fn unpack<'a>(&'a self) -> Unpacked<'a> { fn unpack<'a>(&'a self) -> Unpacked<'a> {
unsafe { unsafe {
match self.tag() { match self.tag() {
Tag::Calc => Unpacked::Calc(&*self.0.calc.ptr), Tag::Calc => Unpacked::Calc(&*self.calc_ptr()),
Tag::Length => Unpacked::Length(self.0.length.length), Tag::Length => Unpacked::Length(self.0.length.length),
Tag::Percentage => Unpacked::Percentage(self.0.percentage.percentage), Tag::Percentage => Unpacked::Percentage(self.0.percentage.percentage),
} }
} }
} }
#[inline]
unsafe fn calc_ptr(&self) -> *mut CalcLengthPercentage {
#[cfg(not(all(target_endian = "big", target_pointer_width = "64")))]
{
self.0.calc.ptr as *mut _
}
#[cfg(all(target_endian = "big", target_pointer_width = "64"))]
{
self.0.calc.ptr.swap_bytes() as *mut _
}
}
#[inline] #[inline]
fn to_serializable(&self) -> Serializable { fn to_serializable(&self) -> Serializable {
match self.unpack() { match self.unpack() {