diff options
author | Zach Bjornson <zbbjornson@gmail.com> | 2016-09-21 18:02:45 -0700 |
---|---|---|
committer | Jeremiah Senkpiel <fishrock123@rocketmail.com> | 2016-10-11 12:31:41 -0400 |
commit | 8a2ba6fe83ad04a60ef3060f628af2241dcbeba5 (patch) | |
tree | 93493cc27581b50f71132cdf0f47adeb7f96719c /src/util-inl.h | |
parent | bee1955f4e3eaaafcf2cb22ab33ff0a69b27bbc8 (diff) | |
download | node-new-8a2ba6fe83ad04a60ef3060f628af2241dcbeba5.tar.gz |
src: fix build for older clang
Removes use of builtins that are unavailable for older clang. Per
benchmarks, only uses builtins on Windows, where speedup is
significant.
Also adds test for unaligned ucs2 buffer write. Between #3410
and #7645, bytes were swapped twice on bigendian platforms if buffer
was not two-byte aligned. See comment in #7645.
PR-URL: https://github.com/nodejs/node/pull/7645
Fixes: https://github.com/nodejs/node/issues/7618
Reviewed-By: Anna Henningsen <anna@addaleax.net>
Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
Reviewed-By: James M Snell <jasnell@gmail.com>
Conflicts:
src/node_buffer.cc
Diffstat (limited to 'src/util-inl.h')
-rw-r--r-- | src/util-inl.h | 97 |
1 files changed, 94 insertions, 3 deletions
diff --git a/src/util-inl.h b/src/util-inl.h index 9357f67502..27bced48fe 100644 --- a/src/util-inl.h +++ b/src/util-inl.h @@ -4,6 +4,30 @@ #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS #include "util.h" +#include <cstring> + +#if defined(_MSC_VER) +#include <intrin.h> +#define BSWAP_2(x) _byteswap_ushort(x) +#define BSWAP_4(x) _byteswap_ulong(x) +#define BSWAP_8(x) _byteswap_uint64(x) +#else +#define BSWAP_2(x) ((x) << 8) | ((x) >> 8) +#define BSWAP_4(x) \ + (((x) & 0xFF) << 24) | \ + (((x) & 0xFF00) << 8) | \ + (((x) >> 8) & 0xFF00) | \ + (((x) >> 24) & 0xFF) +#define BSWAP_8(x) \ + (((x) & 0xFF00000000000000ull) >> 56) | \ + (((x) & 0x00FF000000000000ull) >> 40) | \ + (((x) & 0x0000FF0000000000ull) >> 24) | \ + (((x) & 0x000000FF00000000ull) >> 8) | \ + (((x) & 0x00000000FF000000ull) << 8) | \ + (((x) & 0x0000000000FF0000ull) << 24) | \ + (((x) & 0x000000000000FF00ull) << 40) | \ + (((x) & 0x00000000000000FFull) << 56) +#endif namespace node { @@ -200,9 +224,76 @@ TypeName* Unwrap(v8::Local<v8::Object> object) { return static_cast<TypeName*>(pointer); } -void SwapBytes(uint16_t* dst, const uint16_t* src, size_t buflen) { - for (size_t i = 0; i < buflen; i += 1) - dst[i] = (src[i] << 8) | (src[i] >> 8); +void SwapBytes16(char* data, size_t nbytes) { + CHECK_EQ(nbytes % 2, 0); + +#if defined(_MSC_VER) + int align = reinterpret_cast<uintptr_t>(data) % sizeof(uint16_t); + if (align == 0) { + // MSVC has no strict aliasing, and is able to highly optimize this case. + uint16_t* data16 = reinterpret_cast<uint16_t*>(data); + size_t len16 = nbytes / sizeof(*data16); + for (size_t i = 0; i < len16; i++) { + data16[i] = BSWAP_2(data16[i]); + } + return; + } +#endif + + uint16_t temp; + for (size_t i = 0; i < nbytes; i += sizeof(temp)) { + memcpy(&temp, &data[i], sizeof(temp)); + temp = BSWAP_2(temp); + memcpy(&data[i], &temp, sizeof(temp)); + } +} + +void SwapBytes32(char* data, size_t nbytes) { + CHECK_EQ(nbytes % 4, 0); + +#if defined(_MSC_VER) + int align = reinterpret_cast<uintptr_t>(data) % sizeof(uint32_t); + // MSVC has no strict aliasing, and is able to highly optimize this case. + if (align == 0) { + uint32_t* data32 = reinterpret_cast<uint32_t*>(data); + size_t len32 = nbytes / sizeof(*data32); + for (size_t i = 0; i < len32; i++) { + data32[i] = BSWAP_4(data32[i]); + } + return; + } +#endif + + uint32_t temp; + for (size_t i = 0; i < nbytes; i += sizeof(temp)) { + memcpy(&temp, &data[i], sizeof(temp)); + temp = BSWAP_4(temp); + memcpy(&data[i], &temp, sizeof(temp)); + } +} + +void SwapBytes64(char* data, size_t nbytes) { + CHECK_EQ(nbytes % 8, 0); + +#if defined(_MSC_VER) + int align = reinterpret_cast<uintptr_t>(data) % sizeof(uint64_t); + if (align == 0) { + // MSVC has no strict aliasing, and is able to highly optimize this case. + uint64_t* data64 = reinterpret_cast<uint64_t*>(data); + size_t len64 = nbytes / sizeof(*data64); + for (size_t i = 0; i < len64; i++) { + data64[i] = BSWAP_8(data64[i]); + } + return; + } +#endif + + uint64_t temp; + for (size_t i = 0; i < nbytes; i += sizeof(temp)) { + memcpy(&temp, &data[i], sizeof(temp)); + temp = BSWAP_8(temp); + memcpy(&data[i], &temp, sizeof(temp)); + } } char ToLower(char c) { |