From 8ff6fe9e5593c1a5a0de24577f1e423fb6eae503 Mon Sep 17 00:00:00 2001 From: Tudor Bosman Date: Wed, 6 Jun 2012 19:56:43 -0700 Subject: [PATCH] Deuglify unaligned accesses in GroupVarint. Test Plan: folly/test Reviewed By: andrei.alexandrescu@fb.com FB internal diff: D488631 --- folly/Bits.h | 32 +++++++++++++++++++++++++++++ folly/GroupVarint.h | 50 +++++++++++++++++++++++---------------------- 2 files changed, 58 insertions(+), 24 deletions(-) diff --git a/folly/Bits.h b/folly/Bits.h index 32f51068..9795f8f5 100644 --- a/folly/Bits.h +++ b/folly/Bits.h @@ -513,6 +513,38 @@ BitIterator findFirstSet(BitIterator begin, return end; } + +namespace detail { + +template struct Unaligned; + +template +struct Unaligned< + T, + typename std::enable_if::value>::type> { + T value; +} __attribute__((packed)); + +} // namespace detail + +/** + * Read an unaligned value of type T and return it. + */ +template +inline T loadUnaligned(const void* p) { + static_assert(alignof(detail::Unaligned) == 1, "Invalid alignment"); + return static_cast*>(p)->value; +} + +/** + * Write an unaligned value of type T. + */ +template +inline void storeUnaligned(void* p, T value) { + static_assert(alignof(detail::Unaligned) == 1, "Invalid alignment"); + static_cast*>(p)->value = value; +} + } // namespace folly #endif /* FOLLY_BITS_H_ */ diff --git a/folly/GroupVarint.h b/folly/GroupVarint.h index 0af5cc48..6a3e4709 100644 --- a/folly/GroupVarint.h +++ b/folly/GroupVarint.h @@ -28,6 +28,7 @@ #include #include #include "folly/detail/GroupVarintDetail.h" +#include "folly/Bits.h" #include "folly/Range.h" #include @@ -133,13 +134,13 @@ class GroupVarint : public detail::GroupVarintBase { uint8_t b2key = key(c); uint8_t b3key = key(d); *p++ = (b3key << 6) | (b2key << 4) | (b1key << 2) | b0key; - *reinterpret_cast(p) = a; + storeUnaligned(p, a); p += b0key+1; - *reinterpret_cast(p) = b; + storeUnaligned(p, b); p += b1key+1; - *reinterpret_cast(p) = c; + storeUnaligned(p, c); p += b2key+1; - *reinterpret_cast(p) = d; + storeUnaligned(p, d); p += b3key+1; return p; } @@ -160,20 +161,20 @@ class GroupVarint : public detail::GroupVarintBase { */ static const char* decode_simple(const char* p, uint32_t* a, uint32_t* b, uint32_t* c, uint32_t* d) { - size_t k = *reinterpret_cast(p); + size_t k = loadUnaligned(p); const char* end = p + detail::groupVarintLengths[k]; ++p; size_t k0 = b0key(k); - *a = *reinterpret_cast(p) & kMask[k0]; + *a = loadUnaligned(p) & kMask[k0]; p += k0+1; size_t k1 = b1key(k); - *b = *reinterpret_cast(p) & kMask[k1]; + *b = loadUnaligned(p) & kMask[k1]; p += k1+1; size_t k2 = b2key(k); - *c = *reinterpret_cast(p) & kMask[k2]; + *c = loadUnaligned(p) & kMask[k2]; p += k2+1; size_t k3 = b3key(k); - *d = *reinterpret_cast(p) & kMask[k3]; + *d = loadUnaligned(p) & kMask[k3]; p += k3+1; return end; } @@ -294,7 +295,7 @@ class GroupVarint : public detail::GroupVarintBase { * buffer of size bytes. */ static size_t partialCount(const char* p, size_t size) { - uint16_t v = *reinterpret_cast(p); + uint16_t v = loadUnaligned(p); size_t s = kHeaderSize; s += 1 + b0key(v); if (s > size) return 0; @@ -314,7 +315,7 @@ class GroupVarint : public detail::GroupVarintBase { * return the number of bytes used by the encoding. */ static size_t encodedSize(const char* p) { - uint16_t n = *reinterpret_cast(p); + uint16_t n = loadUnaligned(p); return (kHeaderSize + kGroupSize + b0key(n) + b1key(n) + b2key(n) + b3key(n) + b4key(n)); } @@ -331,18 +332,19 @@ class GroupVarint : public detail::GroupVarintBase { uint8_t b2key = key(c); uint8_t b3key = key(d); uint8_t b4key = key(e); - *reinterpret_cast(p) = - (b4key << 12) | (b3key << 9) | (b2key << 6) | (b1key << 3) | b0key; + storeUnaligned( + p, + (b4key << 12) | (b3key << 9) | (b2key << 6) | (b1key << 3) | b0key); p += 2; - *reinterpret_cast(p) = a; + storeUnaligned(p, a); p += b0key+1; - *reinterpret_cast(p) = b; + storeUnaligned(p, b); p += b1key+1; - *reinterpret_cast(p) = c; + storeUnaligned(p, c); p += b2key+1; - *reinterpret_cast(p) = d; + storeUnaligned(p, d); p += b3key+1; - *reinterpret_cast(p) = e; + storeUnaligned(p, e); p += b4key+1; return p; } @@ -363,22 +365,22 @@ class GroupVarint : public detail::GroupVarintBase { */ static const char* decode(const char* p, uint64_t* a, uint64_t* b, uint64_t* c, uint64_t* d, uint64_t* e) { - uint16_t k = *reinterpret_cast(p); + uint16_t k = loadUnaligned(p); p += 2; uint8_t k0 = b0key(k); - *a = *reinterpret_cast(p) & kMask[k0]; + *a = loadUnaligned(p) & kMask[k0]; p += k0+1; uint8_t k1 = b1key(k); - *b = *reinterpret_cast(p) & kMask[k1]; + *b = loadUnaligned(p) & kMask[k1]; p += k1+1; uint8_t k2 = b2key(k); - *c = *reinterpret_cast(p) & kMask[k2]; + *c = loadUnaligned(p) & kMask[k2]; p += k2+1; uint8_t k3 = b3key(k); - *d = *reinterpret_cast(p) & kMask[k3]; + *d = loadUnaligned(p) & kMask[k3]; p += k3+1; uint8_t k4 = b4key(k); - *e = *reinterpret_cast(p) & kMask[k4]; + *e = loadUnaligned(p) & kMask[k4]; p += k4+1; return p; } -- 2.34.1