зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1612301 - Fix LengthPercentage on big-endian machines. r=jfkthame
Always store the pointer in little-endian order so that the tag trick works. Differential Revision: https://phabricator.services.mozilla.com/D61386 --HG-- extra : moz-landing-system : lando
This commit is contained in:
Родитель
884563052a
Коммит
44abf87d9d
|
@ -10,6 +10,7 @@
|
|||
#define mozilla_ServoStyleConstsInlines_h
|
||||
|
||||
#include "mozilla/ServoStyleConsts.h"
|
||||
#include "mozilla/EndianUtils.h"
|
||||
#include "mozilla/URLExtraData.h"
|
||||
#include "nsGkAtoms.h"
|
||||
#include "MainThreadUtils.h"
|
||||
|
@ -530,7 +531,12 @@ bool LengthPercentage::IsCalc() const { return Tag() == TAG_CALC; }
|
|||
|
||||
StyleCalcLengthPercentage& LengthPercentage::AsCalc() {
|
||||
MOZ_ASSERT(IsCalc());
|
||||
#ifdef SERVO_32_BITS
|
||||
return *calc.ptr;
|
||||
#else
|
||||
return *reinterpret_cast<StyleCalcLengthPercentage*>(
|
||||
NativeEndian::swapFromLittleEndian(calc.ptr));
|
||||
#endif
|
||||
}
|
||||
|
||||
const StyleCalcLengthPercentage& LengthPercentage::AsCalc() const {
|
||||
|
@ -544,11 +550,14 @@ StyleLengthPercentageUnion::StyleLengthPercentageUnion(const Self& aOther) {
|
|||
percentage = {TAG_PERCENTAGE, aOther.AsPercentage()};
|
||||
} else {
|
||||
MOZ_ASSERT(aOther.IsCalc());
|
||||
auto* ptr = new StyleCalcLengthPercentage(aOther.AsCalc());
|
||||
calc = {
|
||||
#ifdef SERVO_32_BITS
|
||||
TAG_CALC,
|
||||
ptr,
|
||||
#else
|
||||
NativeEndian::swapToLittleEndian(reinterpret_cast<uintptr_t>(ptr)),
|
||||
#endif
|
||||
new StyleCalcLengthPercentage(aOther.AsCalc()),
|
||||
};
|
||||
}
|
||||
MOZ_ASSERT(Tag() == aOther.Tag());
|
||||
|
@ -556,7 +565,7 @@ StyleLengthPercentageUnion::StyleLengthPercentageUnion(const Self& aOther) {
|
|||
|
||||
StyleLengthPercentageUnion::~StyleLengthPercentageUnion() {
|
||||
if (IsCalc()) {
|
||||
delete calc.ptr;
|
||||
delete &AsCalc();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -42,7 +42,7 @@ use style_traits::{CssWriter, ToCss};
|
|||
#[derive(Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct LengthVariant {
|
||||
tag: u32,
|
||||
tag: u8,
|
||||
length: Length,
|
||||
}
|
||||
|
||||
|
@ -50,7 +50,7 @@ pub struct LengthVariant {
|
|||
#[derive(Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct PercentageVariant {
|
||||
tag: u32,
|
||||
tag: u8,
|
||||
percentage: Percentage,
|
||||
}
|
||||
|
||||
|
@ -61,7 +61,7 @@ pub struct PercentageVariant {
|
|||
#[repr(C)]
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
pub struct CalcVariant {
|
||||
tag: u32,
|
||||
tag: u8,
|
||||
ptr: *mut CalcLengthPercentage,
|
||||
}
|
||||
|
||||
|
@ -70,14 +70,14 @@ pub struct CalcVariant {
|
|||
#[repr(C)]
|
||||
#[cfg(target_pointer_width = "64")]
|
||||
pub struct CalcVariant {
|
||||
ptr: *mut CalcLengthPercentage,
|
||||
ptr: usize, // In little-endian byte order
|
||||
}
|
||||
|
||||
#[doc(hidden)]
|
||||
#[derive(Copy, Clone)]
|
||||
#[repr(C)]
|
||||
pub struct TagVariant {
|
||||
tag: u32,
|
||||
tag: u8,
|
||||
}
|
||||
|
||||
/// A `<length-percentage>` value. This can be either a `<length>`, a
|
||||
|
@ -110,17 +110,17 @@ pub union LengthPercentageUnion {
|
|||
|
||||
impl LengthPercentageUnion {
|
||||
#[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)]
|
||||
pub const TAG_LENGTH: u32 = 1;
|
||||
pub const TAG_LENGTH: u8 = 1;
|
||||
#[doc(hidden)]
|
||||
pub const TAG_PERCENTAGE: u32 = 2;
|
||||
pub const TAG_PERCENTAGE: u8 = 2;
|
||||
#[doc(hidden)]
|
||||
pub const TAG_MASK: u32 = 0b11;
|
||||
pub const TAG_MASK: u8 = 0b11;
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialEq)]
|
||||
#[repr(u32)]
|
||||
#[repr(u8)]
|
||||
enum Tag {
|
||||
Calc = LengthPercentageUnion::TAG_CALC,
|
||||
Length = LengthPercentageUnion::TAG_LENGTH,
|
||||
|
@ -139,7 +139,7 @@ unsafe fn static_assert() {
|
|||
impl Drop for LengthPercentage {
|
||||
fn drop(&mut self) {
|
||||
if self.tag() == Tag::Calc {
|
||||
let _ = unsafe { Box::from_raw(self.0.calc.ptr) };
|
||||
let _ = unsafe { Box::from_raw(self.calc_ptr()) };
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -228,13 +228,22 @@ impl LengthPercentage {
|
|||
/// checking.
|
||||
fn new_calc_unchecked(calc: Box<CalcLengthPercentage>) -> Self {
|
||||
let ptr = Box::into_raw(calc);
|
||||
let calc = Self(LengthPercentageUnion {
|
||||
calc: CalcVariant {
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
tag: LengthPercentageUnion::TAG_CALC,
|
||||
ptr,
|
||||
}
|
||||
});
|
||||
|
||||
#[cfg(target_pointer_width = "32")]
|
||||
let calc = CalcVariant {
|
||||
tag: LengthPercentageUnion::TAG_CALC,
|
||||
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);
|
||||
calc
|
||||
}
|
||||
|
@ -253,13 +262,23 @@ impl LengthPercentage {
|
|||
fn unpack<'a>(&'a self) -> Unpacked<'a> {
|
||||
unsafe {
|
||||
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::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]
|
||||
fn to_serializable(&self) -> Serializable {
|
||||
match self.unpack() {
|
||||
|
|
|
@ -266,13 +266,13 @@ renaming_overrides_prefixing = true
|
|||
|
||||
// TODO(emilio): cbindgen should be able to generate these in the body of the
|
||||
// union, but it seems it's only implemented for structs, not unions.
|
||||
static const uint32_t TAG_CALC = StyleLengthPercentageUnion_TAG_CALC;
|
||||
static const uint32_t TAG_LENGTH = StyleLengthPercentageUnion_TAG_LENGTH;
|
||||
static const uint32_t TAG_PERCENTAGE = StyleLengthPercentageUnion_TAG_PERCENTAGE;
|
||||
static const uint32_t TAG_MASK = StyleLengthPercentageUnion_TAG_MASK;
|
||||
static const uint8_t TAG_CALC = StyleLengthPercentageUnion_TAG_CALC;
|
||||
static const uint8_t TAG_LENGTH = StyleLengthPercentageUnion_TAG_LENGTH;
|
||||
static const uint8_t TAG_PERCENTAGE = StyleLengthPercentageUnion_TAG_PERCENTAGE;
|
||||
static const uint8_t TAG_MASK = StyleLengthPercentageUnion_TAG_MASK;
|
||||
|
||||
private:
|
||||
uint32_t Tag() const {
|
||||
uint8_t Tag() const {
|
||||
return tag.tag & TAG_MASK;
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче