diff --git a/gfx/2d/Coord.h b/gfx/2d/Coord.h index fd2ab15f88b5..9ec2c1e8a22c 100644 --- a/gfx/2d/Coord.h +++ b/gfx/2d/Coord.h @@ -86,7 +86,7 @@ struct CoordOperatorsHelper { }; template -struct IntCoordTyped +struct MOZ_EMPTY_BASES IntCoordTyped : public BaseCoord>, public units, public CoordOperatorsHelper, float>, @@ -96,30 +96,46 @@ struct IntCoordTyped using Super = BaseCoord>; - constexpr IntCoordTyped() : Super() {} - constexpr MOZ_IMPLICIT IntCoordTyped(Rep aValue) : Super(aValue) {} + constexpr IntCoordTyped() : Super() { + static_assert(sizeof(IntCoordTyped) == sizeof(Rep), + "Would be unfortunate otherwise!"); + } + constexpr MOZ_IMPLICIT IntCoordTyped(Rep aValue) : Super(aValue) { + static_assert(sizeof(IntCoordTyped) == sizeof(Rep), + "Would be unfortunate otherwise!"); + } }; template -struct CoordTyped : public BaseCoord>, - public units, - public CoordOperatorsHelper, - CoordTyped, int32_t>, - public CoordOperatorsHelper, - CoordTyped, uint32_t>, - public CoordOperatorsHelper, - CoordTyped, double>, - public CoordOperatorsHelper, - CoordTyped, float> { +struct MOZ_EMPTY_BASES CoordTyped + : public BaseCoord>, + public units, + public CoordOperatorsHelper, + CoordTyped, int32_t>, + public CoordOperatorsHelper, + CoordTyped, uint32_t>, + public CoordOperatorsHelper, + CoordTyped, double>, + public CoordOperatorsHelper, + CoordTyped, float> { static_assert(IsPixel::value, "'units' must be a coordinate system tag"); using Super = BaseCoord>; - constexpr CoordTyped() : Super() {} - constexpr MOZ_IMPLICIT CoordTyped(F aValue) : Super(aValue) {} + constexpr CoordTyped() : Super() { + static_assert(sizeof(CoordTyped) == sizeof(F), + "Would be unfortunate otherwise!"); + } + constexpr MOZ_IMPLICIT CoordTyped(F aValue) : Super(aValue) { + static_assert(sizeof(CoordTyped) == sizeof(F), + "Would be unfortunate otherwise!"); + } explicit constexpr CoordTyped(const IntCoordTyped& aCoord) - : Super(F(aCoord.value)) {} + : Super(F(aCoord.value)) { + static_assert(sizeof(CoordTyped) == sizeof(F), + "Would be unfortunate otherwise!"); + } void Round() { this->value = floor(this->value + 0.5); } void Truncate() { this->value = int32_t(this->value); } diff --git a/gfx/2d/Point.h b/gfx/2d/Point.h index 485843022584..3bd971bfe3c3 100644 --- a/gfx/2d/Point.h +++ b/gfx/2d/Point.h @@ -70,7 +70,7 @@ template struct SizeTyped; template -struct IntPointTyped +struct MOZ_EMPTY_BASES IntPointTyped : public BasePoint, IntCoordTyped >, public units { static_assert(IsPixel::value, @@ -80,7 +80,10 @@ struct IntPointTyped typedef IntCoordTyped Coord; typedef BasePoint, IntCoordTyped > Super; - constexpr IntPointTyped() : Super() {} + constexpr IntPointTyped() : Super() { + static_assert(sizeof(IntPointTyped) == sizeof(int32_t) * 2, + "Would be unfortunate otherwise!"); + } constexpr IntPointTyped(ToInt aX, ToInt aY) : Super(Coord(aX.value), Coord(aY.value)) {} @@ -121,7 +124,7 @@ struct IntPointTyped typedef IntPointTyped IntPoint; template -struct PointTyped +struct MOZ_EMPTY_BASES PointTyped : public BasePoint, CoordTyped >, public units { static_assert(IsPixel::value, @@ -130,7 +133,10 @@ struct PointTyped typedef CoordTyped Coord; typedef BasePoint, CoordTyped > Super; - constexpr PointTyped() : Super() {} + constexpr PointTyped() : Super() { + static_assert(sizeof(PointTyped) == sizeof(F) * 2, + "Would be unfortunate otherwise!"); + } constexpr PointTyped(F aX, F aY) : Super(Coord(aX), Coord(aY)) {} // The mixed-type constructors (Float, Coord) and (Coord, Float) are needed to // avoid ambiguities because Coord is implicitly convertible to Float. @@ -177,7 +183,10 @@ struct Point3DTyped : public BasePoint3D > { typedef BasePoint3D > Super; - Point3DTyped() : Super() {} + Point3DTyped() : Super() { + static_assert(sizeof(Point3DTyped) == sizeof(F) * 3, + "Would be unfortunate otherwise!"); + } Point3DTyped(F aX, F aY, F aZ) : Super(aX, aY, aZ) {} // XXX When all of the code is ported, the following functions to convert to @@ -226,7 +235,10 @@ struct Point4DTyped : public BasePoint4D > { typedef BasePoint4D > Super; - Point4DTyped() : Super() {} + Point4DTyped() : Super() { + static_assert(sizeof(Point4DTyped) == sizeof(F) * 4, + "Would be unfortunate otherwise!"); + } Point4DTyped(F aX, F aY, F aZ, F aW) : Super(aX, aY, aZ, aW) {} explicit Point4DTyped(const Point3DTyped& aPoint) @@ -257,15 +269,19 @@ typedef Point4DTyped Point4D; typedef Point4DTyped PointDouble4D; template -struct IntSizeTyped : public BaseSize >, - public units { +struct MOZ_EMPTY_BASES IntSizeTyped + : public BaseSize >, + public units { static_assert(IsPixel::value, "'units' must be a coordinate system tag"); typedef IntParam ToInt; typedef BaseSize > Super; - constexpr IntSizeTyped() : Super() {} + constexpr IntSizeTyped() : Super() { + static_assert(sizeof(IntSizeTyped) == sizeof(int32_t) * 2, + "Would be unfortunate otherwise!"); + } constexpr IntSizeTyped(ToInt aWidth, ToInt aHeight) : Super(aWidth.value, aHeight.value) {} @@ -307,13 +323,17 @@ typedef IntSizeTyped IntSize; typedef Maybe MaybeIntSize; template -struct SizeTyped : public BaseSize >, public units { +struct MOZ_EMPTY_BASES SizeTyped : public BaseSize >, + public units { static_assert(IsPixel::value, "'units' must be a coordinate system tag"); typedef BaseSize > Super; - constexpr SizeTyped() : Super() {} + constexpr SizeTyped() : Super() { + static_assert(sizeof(SizeTyped) == sizeof(F) * 2, + "Would be unfortunate otherwise!"); + } constexpr SizeTyped(F aWidth, F aHeight) : Super(aWidth, aHeight) {} explicit SizeTyped(const IntSizeTyped& size) : Super(F(size.width), F(size.height)) {} diff --git a/gfx/2d/Rect.h b/gfx/2d/Rect.h index d16506104b91..17750dc2d497 100644 --- a/gfx/2d/Rect.h +++ b/gfx/2d/Rect.h @@ -27,14 +27,18 @@ template struct RectTyped; template -struct IntMarginTyped : public BaseMargin >, - public units { +struct MOZ_EMPTY_BASES IntMarginTyped + : public BaseMargin >, + public units { static_assert(IsPixel::value, "'units' must be a coordinate system tag"); typedef BaseMargin > Super; - IntMarginTyped() : Super() {} + IntMarginTyped() : Super() { + static_assert(sizeof(IntMarginTyped) == sizeof(int32_t) * 4, + "Would be unfortunate otherwise!"); + } IntMarginTyped(int32_t aTop, int32_t aRight, int32_t aBottom, int32_t aLeft) : Super(aTop, aRight, aBottom, aLeft) {} @@ -92,7 +96,7 @@ IntMarginTyped RoundedToInt(const MarginTyped& aMargin) { } template -struct IntRectTyped +struct MOZ_EMPTY_BASES IntRectTyped : public BaseRect, IntPointTyped, IntSizeTyped, IntMarginTyped >, public units { @@ -105,7 +109,10 @@ struct IntRectTyped typedef IntRectTyped Self; typedef IntParam ToInt; - IntRectTyped() : Super() {} + IntRectTyped() : Super() { + static_assert(sizeof(IntRectTyped) == sizeof(int32_t) * 4, + "Would be unfortunate otherwise!"); + } IntRectTyped(const IntPointTyped& aPos, const IntSizeTyped& aSize) : Super(aPos, aSize) {} @@ -242,9 +249,10 @@ struct IntRectTyped typedef IntRectTyped IntRect; template -struct RectTyped : public BaseRect, PointTyped, - SizeTyped, MarginTyped >, - public units { +struct MOZ_EMPTY_BASES RectTyped + : public BaseRect, PointTyped, + SizeTyped, MarginTyped >, + public units { static_assert(IsPixel::value, "'units' must be a coordinate system tag"); @@ -252,7 +260,10 @@ struct RectTyped : public BaseRect, PointTyped, SizeTyped, MarginTyped > Super; - RectTyped() : Super() {} + RectTyped() : Super() { + static_assert(sizeof(RectTyped) == sizeof(F) * 4, + "Would be unfortunate otherwise!"); + } RectTyped(const PointTyped& aPos, const SizeTyped& aSize) : Super(aPos, aSize) {} RectTyped(F _x, F _y, F _width, F _height) : Super(_x, _y, _width, _height) {} diff --git a/mfbt/Attributes.h b/mfbt/Attributes.h index 182122808a9b..23c5f60b2181 100644 --- a/mfbt/Attributes.h +++ b/mfbt/Attributes.h @@ -910,4 +910,17 @@ # define MOZ_XPCOM_ABI #endif +/** + * MSVC / clang-cl don't optimize empty bases correctly unless we explicitly + * tell it to, see: + * + * https://stackoverflow.com/questions/12701469/why-is-the-empty-base-class-optimization-ebo-is-not-working-in-msvc + * https://devblogs.microsoft.com/cppblog/optimizing-the-layout-of-empty-base-classes-in-vs2015-update-2-3/ + */ +#if defined(_MSC_VER) +# define MOZ_EMPTY_BASES __declspec(empty_bases) +#else +# define MOZ_EMPTY_BASES +#endif + #endif /* mozilla_Attributes_h */