From 2418dfb4b3fbd16c2dfc037fbe0c8a0d5162593a Mon Sep 17 00:00:00 2001 From: Jason Orendorff Date: Thu, 1 Mar 2018 11:05:13 -0600 Subject: [PATCH] Bug 1413049 - Part 1: Add methods to EndianUtils for pointer-sized integers. r=Waldo. --HG-- extra : rebase_source : 115e40ecaee589b07e4ff9534694e56af7690e9b --- mfbt/EndianUtils.h | 32 +++++++++++++++++++- mfbt/tests/TestEndian.cpp | 64 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 95 insertions(+), 1 deletion(-) diff --git a/mfbt/EndianUtils.h b/mfbt/EndianUtils.h index 00815580789ed..153895fa50779 100644 --- a/mfbt/EndianUtils.h +++ b/mfbt/EndianUtils.h @@ -9,7 +9,9 @@ /* * The classes LittleEndian and BigEndian expose static methods for * reading and writing 16-, 32-, and 64-bit signed and unsigned integers - * in their respective endianness. The naming scheme is: + * in their respective endianness. The addresses read from or written + * to may be misaligned (although misaligned accesses may incur + * architecture-specific performance costs). The naming scheme is: * * {Little,Big}Endian::{read,write}{Uint,Int} * @@ -361,6 +363,12 @@ class Endian : private EndianUtils return read(aPtr); } + /** Read a uintptr_t in ThisEndian endianness from |aPtr| and return it. */ + static MOZ_MUST_USE uintptr_t readUintptr(const void* aPtr) + { + return read(aPtr); + } + /** Read an int16_t in ThisEndian endianness from |aPtr| and return it. */ static MOZ_MUST_USE int16_t readInt16(const void* aPtr) { @@ -379,6 +387,12 @@ class Endian : private EndianUtils return read(aPtr); } + /** Read an intptr_t in ThisEndian endianness from |aPtr| and return it. */ + static MOZ_MUST_USE intptr_t readIntptr(const void* aPtr) + { + return read(aPtr); + } + /** Write |aValue| to |aPtr| using ThisEndian endianness. */ static void writeUint16(void* aPtr, uint16_t aValue) { @@ -397,6 +411,12 @@ class Endian : private EndianUtils write(aPtr, aValue); } + /** Write |aValue| to |aPtr| using ThisEndian endianness. */ + static void writeUintptr(void* aPtr, uintptr_t aValue) + { + write(aPtr, aValue); + } + /** Write |aValue| to |aPtr| using ThisEndian endianness. */ static void writeInt16(void* aPtr, int16_t aValue) { @@ -415,6 +435,12 @@ class Endian : private EndianUtils write(aPtr, aValue); } + /** Write |aValue| to |aPtr| using ThisEndian endianness. */ + static void writeIntptr(void* aPtr, intptr_t aValue) + { + write(aPtr, aValue); + } + /* * Converts a value of type T to little-endian format. * @@ -630,15 +656,19 @@ class EndianReadWrite : public Endian using super::readUint16; using super::readUint32; using super::readUint64; + using super::readUintptr; using super::readInt16; using super::readInt32; using super::readInt64; + using super::readIntptr; using super::writeUint16; using super::writeUint32; using super::writeUint64; + using super::writeUintptr; using super::writeInt16; using super::writeInt32; using super::writeInt64; + using super::writeIntptr; }; } /* namespace detail */ diff --git a/mfbt/tests/TestEndian.cpp b/mfbt/tests/TestEndian.cpp index 1fb8ac98f5407..f3ed96d068147 100644 --- a/mfbt/tests/TestEndian.cpp +++ b/mfbt/tests/TestEndian.cpp @@ -367,6 +367,18 @@ main() MOZ_RELEASE_ASSERT( BigEndian::readUint64(&unsigned_bytes[0]) == 0x102030405060708ULL); + if (sizeof(uintptr_t) == 8) { + MOZ_RELEASE_ASSERT( + LittleEndian::readUintptr(&unsigned_bytes[0]) == 0x0807060504030201ULL); + MOZ_RELEASE_ASSERT( + BigEndian::readUintptr(&unsigned_bytes[0]) == 0x0102030405060708ULL); + } else { + MOZ_RELEASE_ASSERT( + LittleEndian::readUintptr(&unsigned_bytes[0]) == 0x04030201U); + MOZ_RELEASE_ASSERT( + BigEndian::readUintptr(&unsigned_bytes[0]) == 0x01020304U); + } + LittleEndian::writeUint16(&buffer[0], 0x201); MOZ_RELEASE_ASSERT( memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uint16_t)) == 0); @@ -388,6 +400,26 @@ main() MOZ_RELEASE_ASSERT( memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uint64_t)) == 0); + memset(&buffer[0], 0xff, sizeof(buffer)); + LittleEndian::writeUintptr(&buffer[0], uintptr_t(0x0807060504030201ULL)); + MOZ_RELEASE_ASSERT( + memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uintptr_t)) == 0); + if (sizeof(uintptr_t) == 4) { + MOZ_RELEASE_ASSERT( + LittleEndian::readUint32(&buffer[4]) == 0xffffffffU); + } + + memset(&buffer[0], 0xff, sizeof(buffer)); + if (sizeof(uintptr_t) == 8) { + BigEndian::writeUintptr(&buffer[0], uintptr_t(0x0102030405060708ULL)); + } else { + BigEndian::writeUintptr(&buffer[0], uintptr_t(0x01020304U)); + MOZ_RELEASE_ASSERT( + LittleEndian::readUint32(&buffer[4]) == 0xffffffffU); + } + MOZ_RELEASE_ASSERT( + memcmp(&unsigned_bytes[0], &buffer[0], sizeof(uintptr_t)) == 0); + MOZ_RELEASE_ASSERT( LittleEndian::readInt16(&signed_bytes[0]) == int16_t(0xf2f1)); MOZ_RELEASE_ASSERT( @@ -403,6 +435,18 @@ main() MOZ_RELEASE_ASSERT( BigEndian::readInt64(&signed_bytes[0]) == int64_t(0xf1f2f3f4f5f6f7f8LL)); + if (sizeof(uintptr_t) == 8) { + MOZ_RELEASE_ASSERT( + LittleEndian::readIntptr(&signed_bytes[0]) == intptr_t(0xf8f7f6f5f4f3f2f1LL)); + MOZ_RELEASE_ASSERT( + BigEndian::readIntptr(&signed_bytes[0]) == intptr_t(0xf1f2f3f4f5f6f7f8LL)); + } else { + MOZ_RELEASE_ASSERT( + LittleEndian::readIntptr(&signed_bytes[0]) == intptr_t(0xf4f3f2f1)); + MOZ_RELEASE_ASSERT( + BigEndian::readIntptr(&signed_bytes[0]) == intptr_t(0xf1f2f3f4)); + } + LittleEndian::writeInt16(&buffer[0], int16_t(0xf2f1)); MOZ_RELEASE_ASSERT( memcmp(&signed_bytes[0], &buffer[0], sizeof(int16_t)) == 0); @@ -424,6 +468,26 @@ main() MOZ_RELEASE_ASSERT( memcmp(&signed_bytes[0], &buffer[0], sizeof(int64_t)) == 0); + memset(&buffer[0], 0xff, sizeof(buffer)); + LittleEndian::writeIntptr(&buffer[0], intptr_t(0xf8f7f6f5f4f3f2f1LL)); + MOZ_RELEASE_ASSERT( + memcmp(&signed_bytes[0], &buffer[0], sizeof(intptr_t)) == 0); + if (sizeof(intptr_t) == 4) { + MOZ_RELEASE_ASSERT( + LittleEndian::readUint32(&buffer[4]) == 0xffffffffU); + } + + memset(&buffer[0], 0xff, sizeof(buffer)); + if (sizeof(intptr_t) == 8) { + BigEndian::writeIntptr(&buffer[0], intptr_t(0xf1f2f3f4f5f6f7f8LL)); + } else { + BigEndian::writeIntptr(&buffer[0], intptr_t(0xf1f2f3f4)); + MOZ_RELEASE_ASSERT( + LittleEndian::readUint32(&buffer[4]) == 0xffffffffU); + } + MOZ_RELEASE_ASSERT( + memcmp(&signed_bytes[0], &buffer[0], sizeof(intptr_t)) == 0); + TestSingleSwap(uint16_t(0xf2f1), uint16_t(0xf1f2)); TestSingleSwap(uint32_t(0xf4f3f2f1), uint32_t(0xf1f2f3f4)); TestSingleSwap(uint64_t(0xf8f7f6f5f4f3f2f1), uint64_t(0xf1f2f3f4f5f6f7f8));