summaryrefslogtreecommitdiffstats
path: root/src/network
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2015-08-10 13:08:15 -0700
committerJędrzej Nowacki <jedrzej.nowacki@theqtcompany.com>2015-08-19 06:13:33 +0000
commitdd92002416270c56c795cce81fb9f0e55c1b2ddd (patch)
tree220bf20215468061670059ab61b2a7f3d30d4966 /src/network
parentb479d5befbf6f6ed1bffef0dbccecf504263e1d6 (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.cpp99
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;