diff options
author | Thiago Macieira <thiago.macieira@intel.com> | 2015-08-10 13:08:15 -0700 |
---|---|---|
committer | Jędrzej Nowacki <jedrzej.nowacki@theqtcompany.com> | 2015-08-19 06:13:33 +0000 |
commit | dd92002416270c56c795cce81fb9f0e55c1b2ddd (patch) | |
tree | 220bf20215468061670059ab61b2a7f3d30d4966 /src/network | |
parent | b479d5befbf6f6ed1bffef0dbccecf504263e1d6 (diff) |
QHostAddress: Improve code generation
Mostly related to IPv6, because Q_IPV6ADDR is an array of char, so the
compilers were generating byte access to each value. Instead, force
access as 32- and 64-bit in most places that make sense (64-bit access
decays to 32-bit on 32-bit machines). In one isLoopback(), this is now a
128-bit access for best improvement.
Some smaller improvements relating to SpecialAddress by combining the
three IPv4 special addresses.
Change-Id: I7de033f80b0e4431b7f1ffff13f932b1cd7b5d21
Reviewed-by: Richard J. Moore <rich@kde.org>
Diffstat (limited to 'src/network')
-rw-r--r-- | src/network/kernel/qhostaddress.cpp | 99 |
1 files changed, 52 insertions, 47 deletions
diff --git a/src/network/kernel/qhostaddress.cpp b/src/network/kernel/qhostaddress.cpp index 6ee76a4250..935af04e31 100644 --- a/src/network/kernel/qhostaddress.cpp +++ b/src/network/kernel/qhostaddress.cpp @@ -46,6 +46,9 @@ #ifndef QT_NO_DATASTREAM #include <qdatastream.h> #endif +#ifdef __SSE2__ +# include <private/qsimd_p.h> +#endif #ifdef QT_LINUXBASE # include <arpa/inet.h> @@ -106,7 +109,11 @@ public: QString scopeId; quint32 a; // IPv4 address - Q_IPV6ADDR a6; // IPv6 address + union { + Q_IPV6ADDR a6; // IPv6 address + struct { quint64 c[2]; } a6_64; + struct { quint32 c[4]; } a6_32; + }; QAbstractSocket::NetworkLayerProtocol protocol; bool isParsed; @@ -123,24 +130,17 @@ QHostAddressPrivate::QHostAddressPrivate() void QHostAddressPrivate::setAddress(quint32 a_) { a = a_; + protocol = QAbstractSocket::IPv4Protocol; + isParsed = true; + //create mapped address, except for a_ == 0 (any) - memset(&a6, 0, sizeof(a6)); + a6_64.c[0] = 0; if (a) { - a6[11] = 0xFF; - a6[10] = 0xFF; + a6_32.c[2] = qToBigEndian(0xffff); + a6_32.c[3] = qToBigEndian(a); } else { - a6[11] = 0; - a6[10] = 0; + a6_64.c[1] = 0; } - - int i; - for (i=15; a_ != 0; i--) { - a6[i] = a_ & 0xFF; - a_ >>=8; - } - Q_ASSERT(i >= 11); - protocol = QAbstractSocket::IPv4Protocol; - isParsed = true; } /// parses v4-mapped addresses or the AnyIPv6 address and stores in \a a; @@ -163,21 +163,16 @@ static bool convertToIpv4(quint32& a, const Q_IPV6ADDR &a6) void QHostAddressPrivate::setAddress(const quint8 *a_) { - for (int i = 0; i < 16; i++) - a6[i] = a_[i]; - a = 0; - convertToIpv4(a, a6); protocol = QAbstractSocket::IPv6Protocol; isParsed = true; + memcpy(a6.c, a_, sizeof(a6)); + a = 0; + convertToIpv4(a, a6); } void QHostAddressPrivate::setAddress(const Q_IPV6ADDR &a_) { - a6 = a_; - a = 0; - convertToIpv4(a, a6); - protocol = QAbstractSocket::IPv6Protocol; - isParsed = true; + setAddress(a_.c); } static bool parseIp6(const QString &address, QIPAddressUtils::IPv6Address &addr, QString *scopeId) @@ -486,31 +481,35 @@ QHostAddress::QHostAddress(SpecialAddress address) { Q_IPV6ADDR ip6; memset(&ip6, 0, sizeof ip6); + quint32 ip4 = INADDR_ANY; switch (address) { case Null: - break; + return; + case Broadcast: - d->setAddress(quint32(-1)); + ip4 = INADDR_BROADCAST; break; case LocalHost: - d->setAddress(0x7f000001); - break; - case LocalHostIPv6: - ip6[15] = 1; - d->setAddress(ip6); + ip4 = INADDR_LOOPBACK; break; case AnyIPv4: - setAddress(0u); break; + + case LocalHostIPv6: + ip6[15] = 1; + // fall through case AnyIPv6: d->setAddress(ip6); - break; + return; + case Any: - d->clear(); d->protocol = QAbstractSocket::AnyIPProtocol; - break; + return; } + + // common IPv4 part + d->setAddress(ip4); } /*! @@ -837,34 +836,36 @@ bool QHostAddress::operator==(const QHostAddress &other) const bool QHostAddress::operator ==(SpecialAddress other) const { QT_ENSURE_PARSED(this); + quint32 ip4 = INADDR_ANY; switch (other) { case Null: return d->protocol == QAbstractSocket::UnknownNetworkLayerProtocol; case Broadcast: - return d->protocol == QAbstractSocket::IPv4Protocol && d->a == INADDR_BROADCAST; + ip4 = INADDR_BROADCAST; + break; case LocalHost: - return d->protocol == QAbstractSocket::IPv4Protocol && d->a == INADDR_LOOPBACK; + ip4 = INADDR_LOOPBACK; + break; case Any: return d->protocol == QAbstractSocket::AnyIPProtocol; case AnyIPv4: - return d->protocol == QAbstractSocket::IPv4Protocol && d->a == INADDR_ANY; + break; case LocalHostIPv6: case AnyIPv6: if (d->protocol == QAbstractSocket::IPv6Protocol) { - Q_IPV6ADDR ip6 = { { 0 } }; - ip6[15] = quint8(other == LocalHostIPv6); // 1 for localhost, 0 for any - return memcmp(&d->a6, &ip6, sizeof ip6) == 0; + quint64 second = quint8(other == LocalHostIPv6); // 1 for localhost, 0 for any + return d->a6_64.c[0] == 0 && d->a6_64.c[1] == qToBigEndian(second); } return false; } - Q_UNREACHABLE(); - return false; + // common IPv4 part + return d->protocol == QAbstractSocket::IPv4Protocol && d->a == ip4; } /*! @@ -1086,11 +1087,15 @@ bool QHostAddress::isLoopback() const if ((d->a & 0xFF000000) == 0x7F000000) return true; // v4 range (including IPv6 wrapped IPv4 addresses) if (d->protocol == QAbstractSocket::IPv6Protocol) { - if (d->a6.c[15] != 1) +#ifdef __SSE2__ + const __m128i loopback = _mm_setr_epi8(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); + __m128i ipv6 = _mm_loadu_si128((const __m128i *)d->a6.c); + __m128i cmp = _mm_cmpeq_epi8(ipv6, loopback); + return _mm_movemask_epi8(cmp) == 0xffff; +#else + if (d->a6_64.c[0] != 0 || qFromBigEndian(d->a6_64.c[1]) != 1) return false; - for (int i = 0; i < 15; i++) - if (d->a6[i] != 0) - return false; +#endif return true; } return false; |