diff options
Diffstat (limited to 'src/corelib')
59 files changed, 725 insertions, 360 deletions
diff --git a/src/corelib/configure.json b/src/corelib/configure.json index 8cd73d6ce4..9f9512942a 100644 --- a/src/corelib/configure.json +++ b/src/corelib/configure.json @@ -15,7 +15,8 @@ "posix-ipc": { "type": "boolean", "name": "ipc_posix" }, "pps": { "type": "boolean", "name": "qqnx_pps" }, "slog2": "boolean", - "syslog": "boolean" + "syslog": "boolean", + "trace": { "type": "optionalString", "values": [ "etw", "lttng", "no", "yes" ] } } }, @@ -147,6 +148,18 @@ "-lrt" ] }, + "lttng-ust": { + "label": "lttng-ust", + "test": { + "include": "lttng/ust-events.h", + "main": "lttng_session_destroy(nullptr);" + }, + "sources": [ + { "type": "pkgConfig", "args": "lttng-ust" }, + "-llttng-ust" + ], + "use": "libdl" + }, "pcre2": { "label": "PCRE2", "test": { @@ -858,6 +871,22 @@ "section": "Utilities", "output": [ "publicFeature" ] }, + "lttng": { + "label": "LTTNG", + "autoDetect": false, + "enable": "input.trace == 'lttng' || (input.trace =='yes' && config.linux)", + "disable": "input.trace == 'etw' || input.trace =='no'", + "condition": "config.linux && libs.lttng-ust", + "output": [ "privateFeature" ] + }, + "etw": { + "label": "ETW", + "autoDetect": false, + "enable": "input.trace == 'etw' || (input.trace == 'yes' && config.win32)", + "disable": "input.trace == 'lttng' || input.trace == 'no'", + "condition": "config.win32", + "output": [ "privateFeature" ] + }, "topleveldomain": { "label": "QUrl::topLevelDomain()", "purpose": "Provides support for extracting the top level domain from URLs. @@ -908,6 +937,11 @@ Please apply the patch corresponding to your Standard Library vendor, found in "iconv", "icu", { + "message": "Tracing backend", + "type": "firstAvailableFeature", + "args": "etw lttng" + }, + { "section": "Logging backends", "entries": [ "journald", "syslog", "slog2" diff --git a/src/corelib/corelib.pro b/src/corelib/corelib.pro index 6dc4af1bfe..2079d2117f 100644 --- a/src/corelib/corelib.pro +++ b/src/corelib/corelib.pro @@ -6,6 +6,9 @@ MODULE = core # not corelib, as per project file MODULE_CONFIG = moc resources !isEmpty(QT_NAMESPACE): MODULE_DEFINES = QT_NAMESPACE=$$QT_NAMESPACE +TRACEPOINT_PROVIDER = $$PWD/qtcore.tracepoints +CONFIG += qt_tracepoints + CONFIG += $$MODULE_CONFIG DEFINES += $$MODULE_DEFINES DEFINES += QT_NO_USING_NAMESPACE QT_NO_FOREACH @@ -35,13 +38,12 @@ include(thread/thread.pri) include(tools/tools.pri) include(io/io.pri) include(itemmodels/itemmodels.pri) -include(json/json.pri) include(plugin/plugin.pri) include(kernel/kernel.pri) include(codecs/codecs.pri) +include(serialization/serialization.pri) include(statemachine/statemachine.pri) include(mimetypes/mimetypes.pri) -include(xml/xml.pri) win32 { LIBS_PRIVATE += -lws2_32 diff --git a/src/corelib/global/qconfig-bootstrapped.h b/src/corelib/global/qconfig-bootstrapped.h index 0df593941d..86ef1a2613 100644 --- a/src/corelib/global/qconfig-bootstrapped.h +++ b/src/corelib/global/qconfig-bootstrapped.h @@ -78,6 +78,7 @@ #define QT_FEATURE_cxx11_random (QT_HAS_INCLUDE(<random>) ? 1 : -1) #define QT_NO_DATASTREAM #define QT_FEATURE_datetimeparser -1 +#define QT_FEATURE_etw -1 #define QT_FEATURE_getauxval (QT_HAS_INCLUDE(<sys/auxv.h>) ? 1 : -1) #define QT_FEATURE_getentropy -1 #define QT_NO_GEOM_VARIANT @@ -92,6 +93,7 @@ #else # define QT_FEATURE_linkat -1 #endif +#define QT_FEATURE_lttng -1 #define QT_NO_QOBJECT #define QT_FEATURE_process -1 #define QT_FEATURE_regularexpression -1 diff --git a/src/corelib/global/qfloat16.cpp b/src/corelib/global/qfloat16.cpp index 3046a47292..fd608efe55 100644 --- a/src/corelib/global/qfloat16.cpp +++ b/src/corelib/global/qfloat16.cpp @@ -178,6 +178,7 @@ static void qFloatFromFloat16_fast(float *, const quint16 *, qsizetype) Q_DECL_N #endif /*! \since 5.11 + \relates <QFloat16> Converts \a len floats from \a in to qfloat16 and stores them in \a out. Both \a in and \a out must have \a len allocated entries. @@ -193,6 +194,7 @@ Q_CORE_EXPORT void qFloatToFloat16(qfloat16 *out, const float *in, qsizetype len /*! \since 5.11 + \relates <QFloat16> Converts \a len qfloat16 from \a in to floats and stores them in \a out. Both \a in and \a out must have \a len allocated entries. diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 7764707de0..aa9446221b 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -88,6 +88,11 @@ #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) # define QT_NO_UNSHARABLE_CONTAINERS +# define QT6_VIRTUAL virtual +# define QT6_NOT_VIRTUAL +#else +# define QT6_VIRTUAL +# define QT6_NOT_VIRTUAL virtual #endif /* These two macros makes it possible to turn the builtin line expander into a diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h index a352e39ef0..9b86a16516 100644 --- a/src/corelib/global/qnumeric_p.h +++ b/src/corelib/global/qnumeric_p.h @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2018 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -58,8 +58,6 @@ #if defined(Q_CC_MSVC) # include <intrin.h> -#elif defined(Q_CC_INTEL) -# include <immintrin.h> // for _addcarry_u<nn> #endif #if defined(Q_CC_MSVC) @@ -164,10 +162,33 @@ Q_DECL_CONST_FUNCTION static inline bool qt_is_finite(float f) } #ifndef Q_CLANG_QDOC -// -// Unsigned overflow math -// namespace { +// Overflow math. +// This provides efficient implementations for int, unsigned, qsizetype and +// size_t. Implementations for 8- and 16-bit types will work but may not be as +// efficient. Implementations for 64-bit may be missing on 32-bit platforms. + +#if (defined(Q_CC_GNU) && (Q_CC_GNU >= 500) || defined(Q_CC_INTEL)) || QT_HAS_BUILTIN(__builtin_add_overflowx) +// GCC 5, ICC 18, and Clang 3.8 have builtins to detect overflows + +template <typename T> inline +typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type +add_overflow(T v1, T v2, T *r) +{ return __builtin_add_overflow(v1, v2, r); } + +template <typename T> inline +typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type +sub_overflow(T v1, T v2, T *r) +{ return __builtin_sub_overflow(v1, v2, r); } + +template <typename T> inline +typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type +mul_overflow(T v1, T v2, T *r) +{ return __builtin_mul_overflow(v1, v2, r); } + +#else +// Generic implementations + template <typename T> inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type add_overflow(T v1, T v2, T *r) { @@ -176,69 +197,92 @@ add_overflow(T v1, T v2, T *r) return v1 > T(v1 + v2); } +template <typename T> inline typename std::enable_if<std::is_signed<T>::value, bool>::type +add_overflow(T v1, T v2, T *r) +{ + // Here's how we calculate the overflow: + // 1) unsigned addition is well-defined, so we can always execute it + // 2) conversion from unsigned back to signed is implementation- + // defined and in the implementations we use, it's a no-op. + // 3) signed integer overflow happens if the sign of the two input operands + // is the same but the sign of the result is different. In other words, + // the sign of the result must be the same as the sign of either + // operand. + + using U = typename std::make_unsigned<T>::type; + *r = T(U(v1) + U(v2)); + + // If int is two's complement, assume all integer types are too. + if (std::is_same<int32_t, int>::value) { + // Two's complement equivalent (generates slightly shorter code): + // x ^ y is negative if x and y have different signs + // x & y is negative if x and y are negative + // (x ^ z) & (y ^ z) is negative if x and z have different signs + // AND y and z have different signs + return ((v1 ^ *r) & (v2 ^ *r)) < 0; + } + + bool s1 = (v1 < 0); + bool s2 = (v2 < 0); + bool sr = (*r < 0); + return s1 != sr && s2 != sr; + // also: return s1 == s2 && s1 != sr; +} + template <typename T> inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type +sub_overflow(T v1, T v2, T *r) +{ + // unsigned subtractions are well-defined + *r = v1 - v2; + return v1 < v2; +} + +template <typename T> inline typename std::enable_if<std::is_signed<T>::value, bool>::type +sub_overflow(T v1, T v2, T *r) +{ + // See above for explanation. This is the same with some signs reversed. + // We can't use add_overflow(v1, -v2, r) because it would be UB if + // v2 == std::numeric_limits<T>::min(). + + using U = typename std::make_unsigned<T>::type; + *r = T(U(v1) - U(v2)); + + if (std::is_same<int32_t, int>::value) + return ((v1 ^ *r) & (~v2 ^ *r)) < 0; + + bool s1 = (v1 < 0); + bool s2 = !(v2 < 0); + bool sr = (*r < 0); + return s1 != sr && s2 != sr; + // also: return s1 == s2 && s1 != sr; +} + +template <typename T> inline +typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type mul_overflow(T v1, T v2, T *r) { // use the next biggest type // Note: for 64-bit systems where __int128 isn't supported, this will cause an error. - // A fallback is present below. - typedef typename QIntegerForSize<sizeof(T) * 2>::Unsigned Larger; + using LargerInt = QIntegerForSize<sizeof(T) * 2>; + using Larger = typename std::conditional<std::is_signed<T>::value, + typename LargerInt::Signed, typename LargerInt::Unsigned>::type; Larger lr = Larger(v1) * Larger(v2); *r = T(lr); - return lr > std::numeric_limits<T>::max(); + return lr > std::numeric_limits<T>::max() || lr < std::numeric_limits<T>::min(); } -#if defined(__SIZEOF_INT128__) -# define HAVE_MUL64_OVERFLOW -#endif - -// GCC 5 and Clang have builtins to detect overflows -#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_uadd_overflow) +# if defined(Q_CC_MSVC) && defined(Q_PROCESSOR_X86) +// We can use intrinsics for the unsigned operations with MSVC template <> inline bool add_overflow(unsigned v1, unsigned v2, unsigned *r) -{ return __builtin_uadd_overflow(v1, v2, r); } -#endif -#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_uaddl_overflow) -template <> inline bool add_overflow(unsigned long v1, unsigned long v2, unsigned long *r) -{ return __builtin_uaddl_overflow(v1, v2, r); } -#endif -#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_uaddll_overflow) -template <> inline bool add_overflow(unsigned long long v1, unsigned long long v2, unsigned long long *r) -{ return __builtin_uaddll_overflow(v1, v2, r); } -#endif +{ return _addcarry_u32(0, v1, v2, r); } -#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_umul_overflow) -template <> inline bool mul_overflow(unsigned v1, unsigned v2, unsigned *r) -{ return __builtin_umul_overflow(v1, v2, r); } -#endif -#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_umull_overflow) -template <> inline bool mul_overflow(unsigned long v1, unsigned long v2, unsigned long *r) -{ return __builtin_umull_overflow(v1, v2, r); } -#endif -#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_umulll_overflow) -template <> inline bool mul_overflow(unsigned long long v1, unsigned long long v2, unsigned long long *r) -{ return __builtin_umulll_overflow(v1, v2, r); } -# define HAVE_MUL64_OVERFLOW -#endif +// 32-bit mul_overflow is fine with the generic code above -#if (defined(Q_CC_MSVC) || defined(Q_CC_INTEL)) && defined(Q_PROCESSOR_X86) && !QT_HAS_BUILTIN(__builtin_uadd_overflow) -template <> inline bool add_overflow(unsigned v1, unsigned v2, unsigned *r) -{ return _addcarry_u32(0, v1, v2, r); } -# ifdef Q_CC_MSVC // longs are 32-bit -template <> inline bool add_overflow(unsigned long v1, unsigned long v2, unsigned long *r) -{ return _addcarry_u32(0, v1, v2, reinterpret_cast<unsigned *>(r)); } -# endif -#endif -#if (defined(Q_CC_MSVC) || defined(Q_CC_INTEL)) && defined(Q_PROCESSOR_X86_64) && !QT_HAS_BUILTIN(__builtin_uadd_overflow) +# if defined(Q_PROCESSOR_X86_64) template <> inline bool add_overflow(quint64 v1, quint64 v2, quint64 *r) { return _addcarry_u64(0, v1, v2, reinterpret_cast<unsigned __int64 *>(r)); } -# ifndef Q_CC_MSVC // longs are 64-bit -template <> inline bool add_overflow(unsigned long v1, unsigned long v2, unsigned long *r) -{ return _addcarry_u64(0, v1, v2, reinterpret_cast<unsigned __int64 *>(r)); } -# endif -#endif -#if defined(Q_CC_MSVC) && (defined(Q_PROCESSOR_X86_64) || defined(Q_PROCESSOR_IA64)) && !QT_HAS_BUILTIN(__builtin_uadd_overflow) -#pragma intrinsic(_umul128) +# pragma intrinsic(_umul128) template <> inline bool mul_overflow(quint64 v1, quint64 v2, quint64 *r) { // use 128-bit multiplication with the _umul128 intrinsic @@ -247,117 +291,30 @@ template <> inline bool mul_overflow(quint64 v1, quint64 v2, quint64 *r) *r = _umul128(v1, v2, &high); return high; } -# define HAVE_MUL64_OVERFLOW -#endif - -#if !defined(HAVE_MUL64_OVERFLOW) && defined(__LP64__) -// no 128-bit multiplication, we need to figure out with a slow division -template <> inline bool mul_overflow(quint64 v1, quint64 v2, quint64 *r) -{ - if (v2 && v1 > std::numeric_limits<quint64>::max() / v2) - return true; - *r = v1 * v2; - return false; -} -template <> inline bool mul_overflow(unsigned long v1, unsigned long v2, unsigned long *r) -{ - return mul_overflow<quint64>(v1, v2, reinterpret_cast<quint64 *>(r)); -} -#else -# undef HAVE_MUL64_OVERFLOW -#endif - -// -// Signed overflow math -// -// In C++, signed overflow math is Undefined Behavior. However, many CPUs do implement some way to -// check for overflow. Some compilers expose intrinsics to use this functionality. If the no -// intrinsic is exposed, overflow checking can be done by widening the result type and "manually" -// checking for overflow. Or, alternatively, by using inline assembly to use the CPU features. -// -// Only int overflow checking is implemented, because it's the only one used. -#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_sadd_overflow) -inline bool add_overflow(int v1, int v2, int *r) -{ return __builtin_sadd_overflow(v1, v2, r); } -#elif defined(Q_CC_GNU) && defined(Q_PROCESSOR_X86) -inline bool add_overflow(int v1, int v2, int *r) -{ - quint8 overflow = 0; - int res = v1; - - asm ("addl %2, %1\n" - "seto %0" - : "=q" (overflow), "=r" (res) - : "r" (v2), "1" (res) - : "cc" - ); - *r = res; - return overflow; -} -#else -inline bool add_overflow(int v1, int v2, int *r) -{ - qint64 t = qint64(v1) + v2; - *r = static_cast<int>(t); - return t > std::numeric_limits<int>::max() || t < std::numeric_limits<int>::min(); -} -#endif -#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_ssub_overflow) -inline bool sub_overflow(int v1, int v2, int *r) -{ return __builtin_ssub_overflow(v1, v2, r); } -#elif defined(Q_CC_GNU) && defined(Q_PROCESSOR_X86) -inline bool sub_overflow(int v1, int v2, int *r) +# pragma intrinsic(_mul128) +template <> inline bool mul_overflow(qint64 v1, qint64 v2, qint64 *r) { - quint8 overflow = 0; - int res = v1; - - asm ("subl %2, %1\n" - "seto %0" - : "=q" (overflow), "=r" (res) - : "r" (v2), "1" (res) - : "cc" - ); - *r = res; - return overflow; + // Use 128-bit multiplication with the _mul128 intrinsic + // https://msdn.microsoft.com/en-us/library/82cxdw50.aspx + + // This is slightly more complex than the unsigned case above: the sign bit + // of 'low' must be replicated as the entire 'high', so the only valid + // values for 'high' are 0 and -1. + + qint64 high; + *r = _mul128(v1, v2, &high); + if (high == 0) + return *r < 0; + if (high == -1) + return *r >= 0; + return true; } -#else -inline bool sub_overflow(int v1, int v2, int *r) -{ - qint64 t = qint64(v1) - v2; - *r = static_cast<int>(t); - return t > std::numeric_limits<int>::max() || t < std::numeric_limits<int>::min(); +# endif // x86-64 +# endif // MSVC x86 +#endif // !GCC } -#endif - -#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_smul_overflow) -inline bool mul_overflow(int v1, int v2, int *r) -{ return __builtin_smul_overflow(v1, v2, r); } -#elif defined(Q_CC_GNU) && defined(Q_PROCESSOR_X86) -inline bool mul_overflow(int v1, int v2, int *r) -{ - quint8 overflow = 0; - int res = v1; - - asm ("imul %2, %1\n" - "seto %0" - : "=q" (overflow), "=r" (res) - : "r" (v2), "1" (res) - : "cc" - ); - *r = res; - return overflow; -} -#else -inline bool mul_overflow(int v1, int v2, int *r) -{ - qint64 t = qint64(v1) * v2; - *r = static_cast<int>(t); - return t > std::numeric_limits<int>::max() || t < std::numeric_limits<int>::min(); -} -#endif #endif // Q_CLANG_QDOC -} QT_END_NAMESPACE diff --git a/src/corelib/global/qtrace_p.h b/src/corelib/global/qtrace_p.h new file mode 100644 index 0000000000..ab8fc14af5 --- /dev/null +++ b/src/corelib/global/qtrace_p.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTRACE_P_H +#define QTRACE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +/* + * The Qt tracepoints API consists of only three macros: + * + * - Q_TRACE(tracepoint, args...) + * Fires 'tracepoint' if it is enabled. + * + * - Q_UNCONDITIONAL_TRACE(tracepoint, args...) + * Fires 'tracepoint' unconditionally: no check is performed to query + * whether 'tracepoint' is enabled. + * + * - Q_TRACE_ENABLED(tracepoint) + * Returns 'true' if 'tracepoint' is enabled; false otherwise. + * + * When using LTTNG, Q_TRACE, Q_UNCONDITIONAL_TRACE and Q_TRACE_ENABLED map + * ultimately to tracepoint(), do_tracepoint() and tracepoint_enabled(), + * respectively, described on the lttng-ust manpage (man 3 lttng-ust). + * + * On ETW, Q_TRACE() and Q_UNCONDITIONAL_TRACE() are equivalent, ultimately + * amounting to a call to TraceLoggingWrite(), whereas Q_TRACE_ENABLED() + * wraps around TraceLoggingProviderEnabled(). + * + * A tracepoint provider is defined in a separate file, that follows the + * following format: + * + * tracepoint_name(arg_type arg_name, ...) + * + * For instance: + * + * qcoreapplication_ctor(int argc, const char * const argv) + * qcoreapplication_foo(int argc, const char[10] argv) + * qcoreapplication_baz(const char[len] some_string, unsigned int len) + * qcoreapplication_qstring(const QString &foo) + * qcoreapplication_qrect(const QRect &rect) + * + * The provider file is then parsed by src/tools/tracegen, which can be + * switched to output either ETW or LTTNG tracepoint definitions. The provider + * name is deduced to be basename(provider_file). + * + * To use the above (inside qtcore), you need to include + * <providername_tracepoints_p.h>. After that, the following call becomes + * possible: + * + * Q_TRACE(qcoreapplication_qrect, myRect); + * + * Currently, all C++ primitive non-pointer types are supported for + * arguments. Additionally, char * is supported, and is assumed to + * be a NULL-terminated string. Finally, the following subset of Qt types also + * currently supported: + * + * - QString + * - QByteArray + * - QUrl + * - QRect + * + * Dynamic arrays are supported using the syntax illustrated by + * qcoreapplication_baz above. + */ + +QT_BEGIN_NAMESPACE + +#if defined(Q_TRACEPOINT) && !defined(QT_BOOTSTRAPPED) +# define Q_TRACE(x, ...) QtPrivate::trace_ ## x(__VA_ARGS__) +# define Q_UNCONDITIONAL_TRACE(x, ...) QtPrivate::do_trace_ ## x(__VA_ARGS__) +# define Q_TRACE_ENABLED(x) QtPrivate::trace_ ## x ## _enabled() +#else +# define Q_TRACE(x, ...) +# define Q_UNCONDITIONAL_TRACE(x, ...) +# define Q_TRACE_ENABLED(x) false +#endif // defined(Q_TRACEPOINT) && !defined(QT_BOOTSTRAPPED) + +QT_END_NAMESPACE + +#endif // QTRACE_P_H diff --git a/src/corelib/io/io.pri b/src/corelib/io/io.pri index 4614fe2a6b..c6a5973306 100644 --- a/src/corelib/io/io.pri +++ b/src/corelib/io/io.pri @@ -3,8 +3,6 @@ HEADERS += \ io/qabstractfileengine_p.h \ io/qbuffer.h \ - io/qdatastream.h \ - io/qdatastream_p.h \ io/qdataurl_p.h \ io/qdebug.h \ io/qdebug_p.h \ @@ -22,8 +20,6 @@ HEADERS += \ io/qlockfile.h \ io/qlockfile_p.h \ io/qnoncontiguousbytedevice_p.h \ - io/qtextstream.h \ - io/qtextstream_p.h \ io/qtemporarydir.h \ io/qtemporaryfile.h \ io/qtemporaryfile_p.h \ @@ -57,7 +53,6 @@ HEADERS += \ SOURCES += \ io/qabstractfileengine.cpp \ io/qbuffer.cpp \ - io/qdatastream.cpp \ io/qdataurl.cpp \ io/qtldurl.cpp \ io/qdebug.cpp \ @@ -71,7 +66,6 @@ SOURCES += \ io/qlockfile.cpp \ io/qnoncontiguousbytedevice.cpp \ io/qstorageinfo.cpp \ - io/qtextstream.cpp \ io/qtemporarydir.cpp \ io/qtemporaryfile.cpp \ io/qresource.cpp \ diff --git a/src/corelib/json/json.pri b/src/corelib/json/json.pri deleted file mode 100644 index 1a4e2a72bf..0000000000 --- a/src/corelib/json/json.pri +++ /dev/null @@ -1,17 +0,0 @@ -HEADERS += \ - json/qjson_p.h \ - json/qjsondocument.h \ - json/qjsonobject.h \ - json/qjsonvalue.h \ - json/qjsonarray.h \ - json/qjsonwriter_p.h \ - json/qjsonparser_p.h - -SOURCES += \ - json/qjson.cpp \ - json/qjsondocument.cpp \ - json/qjsonobject.cpp \ - json/qjsonarray.cpp \ - json/qjsonvalue.cpp \ - json/qjsonwriter.cpp \ - json/qjsonparser.cpp diff --git a/src/corelib/kernel/qcoreapplication.cpp b/src/corelib/kernel/qcoreapplication.cpp index e93a14c116..4bab0b9f01 100644 --- a/src/corelib/kernel/qcoreapplication.cpp +++ b/src/corelib/kernel/qcoreapplication.cpp @@ -116,6 +116,12 @@ # include <taskLib.h> #endif +#ifdef QT_BOOTSTRAPPED +#include <private/qtrace_p.h> +#else +#include <qtcore_tracepoints_p.h> +#endif + #include <algorithm> QT_BEGIN_NAMESPACE @@ -790,6 +796,8 @@ QCoreApplication::QCoreApplication(int &argc, char **argv void QCoreApplicationPrivate::init() { + Q_TRACE(qcoreapplicationprivate_init_entry); + #if defined(Q_OS_MACOS) QMacAutoReleasePool pool; #endif @@ -873,6 +881,8 @@ void QCoreApplicationPrivate::init() #ifndef QT_NO_QOBJECT is_app_running = true; // No longer starting up. #endif + + Q_TRACE(qcoreapplicationprivate_init_exit); } /*! diff --git a/src/corelib/kernel/qeventdispatcher_cf.mm b/src/corelib/kernel/qeventdispatcher_cf.mm index 608dea5426..8499b3fd57 100644 --- a/src/corelib/kernel/qeventdispatcher_cf.mm +++ b/src/corelib/kernel/qeventdispatcher_cf.mm @@ -112,14 +112,15 @@ static CFStringRef runLoopMode(NSDictionary *dictionary) if (CFStringRef mode = runLoopMode(notification.userInfo)) m_runLoopModes.push(mode); else - qWarning("Encountered run loop push notification without run loop mode!"); + qCWarning(lcEventDispatcher) << "Encountered run loop push notification without run loop mode!"; } else if (CFStringHasSuffix((CFStringRef)notification.name, CFSTR("RunLoopModePopNotification"))) { CFStringRef mode = runLoopMode(notification.userInfo); if (CFStringCompare(mode, [self currentMode], 0) == kCFCompareEqualTo) m_runLoopModes.pop(); else - qWarning("Tried to pop run loop mode '%s' that was never pushed!", qPrintable(QString::fromCFString(mode))); + qCWarning(lcEventDispatcher) << "Tried to pop run loop mode" + << qPrintable(QString::fromCFString(mode)) << "that was never pushed!"; Q_ASSERT(m_runLoopModes.size() >= 1); } @@ -134,6 +135,9 @@ static CFStringRef runLoopMode(NSDictionary *dictionary) QT_BEGIN_NAMESPACE +Q_LOGGING_CATEGORY(lcEventDispatcher, "qt.eventdispatcher"); +Q_LOGGING_CATEGORY(lcEventDispatcherTimers, "qt.eventdispatcher.timers"); + class RunLoopDebugger : public QObject { Q_OBJECT @@ -177,10 +181,6 @@ QDebug operator<<(QDebug s, timespec tv) return s; } -#if DEBUG_EVENT_DISPATCHER -uint g_eventDispatcherIndentationLevel = 0; -#endif - static const CFTimeInterval kCFTimeIntervalMinimum = 0; static const CFTimeInterval kCFTimeIntervalDistantFuture = std::numeric_limits<CFTimeInterval>::max(); @@ -190,13 +190,7 @@ QEventDispatcherCoreFoundation::QEventDispatcherCoreFoundation(QObject *parent) : QAbstractEventDispatcher(parent) , m_processEvents(QEventLoop::EventLoopExec) , m_postedEventsRunLoopSource(this, &QEventDispatcherCoreFoundation::processPostedEvents) - , m_runLoopActivityObserver(this, &QEventDispatcherCoreFoundation::handleRunLoopActivity, -#if DEBUG_EVENT_DISPATCHER - kCFRunLoopAllActivities -#else - kCFRunLoopBeforeWaiting | kCFRunLoopAfterWaiting -#endif - ) + , m_runLoopActivityObserver(this, &QEventDispatcherCoreFoundation::handleRunLoopActivity, kCFRunLoopAllActivities) , m_runLoopModeTracker([[RunLoopModeTracker alloc] init]) , m_runLoopTimer(0) , m_blockedRunLoopTimer(0) @@ -247,14 +241,14 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag bool eventsProcessed = false; if (flags & (QEventLoop::ExcludeUserInputEvents | QEventLoop::ExcludeSocketNotifiers)) - qWarning() << "processEvents() flags" << flags << "not supported on iOS"; + qCWarning(lcEventDispatcher) << "processEvents() flags" << flags << "not supported on iOS"; - qEventDispatcherDebug() << "Entering with " << flags; qIndent(); + qCDebug(lcEventDispatcher) << "Processing events with flags" << flags; if (m_blockedRunLoopTimer) { Q_ASSERT(m_blockedRunLoopTimer == m_runLoopTimer); - qEventDispatcherDebug() << "Recursing from blocked timer " << m_blockedRunLoopTimer; + qCDebug(lcEventDispatcher) << "Recursing from blocked timer" << m_blockedRunLoopTimer; m_runLoopTimer = 0; // Unset current timer to force creation of new timer updateTimers(); } @@ -266,7 +260,7 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag m_postedEventsRunLoopSource.signal(); m_processEvents.deferredWakeUp = false; - qEventDispatcherDebug() << "Processed deferred wake-up"; + qCDebug(lcEventDispatcher) << "Processed deferred wake-up"; } // The documentation states that this signal is emitted after the event @@ -287,12 +281,12 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag CFTimeInterval duration = (m_processEvents.flags & QEventLoop::WaitForMoreEvents) ? kCFTimeIntervalDistantFuture : kCFTimeIntervalMinimum; - qEventDispatcherDebug() << "Calling CFRunLoopRunInMode = " << qPrintable(QString::fromCFString(mode)) - << " for " << duration << " ms, processing single source = " << returnAfterSingleSourceHandled; qIndent(); + qCDebug(lcEventDispatcher) << "Calling CFRunLoopRunInMode =" << qPrintable(QString::fromCFString(mode)) + << "for" << duration << "ms, processing single source =" << returnAfterSingleSourceHandled; SInt32 result = CFRunLoopRunInMode(mode, duration, returnAfterSingleSourceHandled); - qUnIndent(); qEventDispatcherDebug() << "result = " << qPrintableResult(result); + qCDebug(lcEventDispatcher) << "result =" << qPrintableResult(result); eventsProcessed |= (result == kCFRunLoopRunHandledSource || m_processEvents.processedPostedEvents @@ -316,15 +310,15 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag // immediately, since it has already been exited. if (!currentEventLoop()->isRunning()) { - qEventDispatcherDebug() << "Top level event loop was exited"; + qCDebug(lcEventDispatcher) << "Top level event loop was exited"; break; } else { - qEventDispatcherDebug() << "Top level event loop still running, making another pass"; + qCDebug(lcEventDispatcher) << "Top level event loop still running, making another pass"; } } else { // We were called manually, through processEvents(), and should stop processing // events, even if we didn't finish processing all the queued events. - qEventDispatcherDebug() << "Top level processEvents was interrupted"; + qCDebug(lcEventDispatcher) << "Top level processEvents was interrupted"; break; } } @@ -353,7 +347,7 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag // date in the past (overdue) will fire on the next run loop pass. The Qt // APIs on the other hand document eg. zero-interval timers to always be // handled after processing all available window-system events. - qEventDispatcherDebug() << "Manually processing timers due to overdue timer"; + qCDebug(lcEventDispatcher) << "Manually processing timers due to overdue timer"; processTimers(0); eventsProcessed = true; } @@ -372,7 +366,7 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag if (m_processEvents.deferredWakeUp) { m_postedEventsRunLoopSource.signal(); - qEventDispatcherDebug() << "Processed deferred wake-up"; + qCDebug(lcEventDispatcher) << "Processed deferred wake-up"; } bool wasInterrupted = m_processEvents.wasInterrupted; @@ -385,11 +379,11 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag // others below it (eg, in the case of nested event loops). We need to trigger // another interrupt so that the parent processEvents call has a chance to check // if it should continue. - qEventDispatcherDebug() << "Forwarding interrupt in case of nested processEvents"; + qCDebug(lcEventDispatcher) << "Forwarding interrupt in case of nested processEvents"; interrupt(); } - qEventDispatcherDebug() << "Returning with eventsProcessed = " << eventsProcessed; qUnIndent(); + qCDebug(lcEventDispatcher) << "Returning with eventsProcessed =" << eventsProcessed; return eventsProcessed; } @@ -397,15 +391,14 @@ bool QEventDispatcherCoreFoundation::processEvents(QEventLoop::ProcessEventsFlag bool QEventDispatcherCoreFoundation::processPostedEvents() { if (m_processEvents.processedPostedEvents && !(m_processEvents.flags & QEventLoop::EventLoopExec)) { - qEventDispatcherDebug() << "Already processed events this pass"; + qCDebug(lcEventDispatcher) << "Already processed events this pass"; return false; } m_processEvents.processedPostedEvents = true; - qEventDispatcherDebug() << "Sending posted events for " << m_processEvents.flags; qIndent(); + qCDebug(lcEventDispatcher) << "Sending posted events for" << m_processEvents.flags; QCoreApplication::sendPostedEvents(); - qUnIndent(); return true; } @@ -413,12 +406,12 @@ bool QEventDispatcherCoreFoundation::processPostedEvents() void QEventDispatcherCoreFoundation::processTimers(CFRunLoopTimerRef timer) { if (m_processEvents.processedTimers && !(m_processEvents.flags & QEventLoop::EventLoopExec)) { - qEventDispatcherDebug() << "Already processed timers this pass"; + qCDebug(lcEventDispatcher) << "Already processed timers this pass"; m_processEvents.deferredUpdateTimers = true; return; } - qEventDispatcherDebug() << "CFRunLoopTimer " << timer << " fired, activating Qt timers"; qIndent(); + qCDebug(lcEventDispatcher) << "CFRunLoopTimer" << timer << "fired, activating Qt timers"; // Activating Qt timers might recurse into processEvents() if a timer-callback // brings up a new event-loop or tries to processes events manually. Although @@ -436,15 +429,15 @@ void QEventDispatcherCoreFoundation::processTimers(CFRunLoopTimerRef timer) m_blockedRunLoopTimer = previouslyBlockedRunLoopTimer; m_processEvents.processedTimers = true; - qUnIndent(); - // Now that the timer source is unblocked we may need to schedule it again updateTimers(); } +Q_LOGGING_CATEGORY(lcEventDispatcherActivity, "qt.eventdispatcher.activity") + void QEventDispatcherCoreFoundation::handleRunLoopActivity(CFRunLoopActivity activity) { - qEventDispatcherDebug() << qPrintableActivity(activity); + qCDebug(lcEventDispatcherActivity) << "Runloop entered activity" << qPrintableActivity(activity); switch (activity) { case kCFRunLoopBeforeWaiting: @@ -463,13 +456,11 @@ void QEventDispatcherCoreFoundation::handleRunLoopActivity(CFRunLoopActivity act case kCFRunLoopAfterWaiting: emit awake(); break; -#if DEBUG_EVENT_DISPATCHER case kCFRunLoopEntry: case kCFRunLoopBeforeTimers: case kCFRunLoopBeforeSources: case kCFRunLoopExit: break; -#endif default: Q_UNREACHABLE(); } @@ -502,19 +493,19 @@ void QEventDispatcherCoreFoundation::wakeUp() // posted event gets processed on the next processEvents() call, so we flag the // need to do a deferred wake-up. m_processEvents.deferredWakeUp = true; - qEventDispatcherDebug() << "Already processed posted events, deferring wakeUp"; + qCDebug(lcEventDispatcher) << "Already processed posted events, deferring wakeUp"; return; } m_postedEventsRunLoopSource.signal(); CFRunLoopWakeUp(CFRunLoopGetMain()); - qEventDispatcherDebug() << "Signaled posted event run-loop source"; + qCDebug(lcEventDispatcher) << "Signaled posted event run-loop source"; } void QEventDispatcherCoreFoundation::interrupt() { - qEventDispatcherDebug() << "Marking current processEvent as interrupted"; + qCDebug(lcEventDispatcher) << "Marking current processEvent as interrupted"; m_processEvents.wasInterrupted = true; CFRunLoopStop(CFRunLoopGetMain()); } @@ -540,8 +531,8 @@ void QEventDispatcherCoreFoundation::unregisterSocketNotifier(QSocketNotifier *n void QEventDispatcherCoreFoundation::registerTimer(int timerId, int interval, Qt::TimerType timerType, QObject *object) { - qEventDispatcherDebug() << "id = " << timerId << ", interval = " << interval - << ", type = " << timerType << ", object = " << object; + qCDebug(lcEventDispatcherTimers) << "Registering timer with id =" << timerId << "interval =" << interval + << "type =" << timerType << "object =" << object; Q_ASSERT(timerId > 0 && interval >= 0 && object); Q_ASSERT(object->thread() == thread() && thread() == QThread::currentThread()); @@ -557,7 +548,7 @@ bool QEventDispatcherCoreFoundation::unregisterTimer(int timerId) bool returnValue = m_timerInfoList.unregisterTimer(timerId); - qEventDispatcherDebug() << "id = " << timerId << ", timers left: " << m_timerInfoList.size(); + qCDebug(lcEventDispatcherTimers) << "Unegistered timer with id =" << timerId << "Timers left:" << m_timerInfoList.size(); updateTimers(); return returnValue; @@ -569,7 +560,7 @@ bool QEventDispatcherCoreFoundation::unregisterTimers(QObject *object) bool returnValue = m_timerInfoList.unregisterTimers(object); - qEventDispatcherDebug() << "object = " << object << ", timers left: " << m_timerInfoList.size(); + qCDebug(lcEventDispatcherTimers) << "Unegistered timers for object =" << object << "Timers left:" << m_timerInfoList.size(); updateTimers(); return returnValue; @@ -612,16 +603,16 @@ void QEventDispatcherCoreFoundation::updateTimers() }); CFRunLoopAddTimer(CFRunLoopGetMain(), m_runLoopTimer, kCFRunLoopCommonModes); - qEventDispatcherDebug() << "Created new CFRunLoopTimer " << m_runLoopTimer; + qCDebug(lcEventDispatcherTimers) << "Created new CFRunLoopTimer" << m_runLoopTimer; } else { CFRunLoopTimerSetNextFireDate(m_runLoopTimer, timeToFire); - qEventDispatcherDebug() << "Re-scheduled CFRunLoopTimer " << m_runLoopTimer; + qCDebug(lcEventDispatcherTimers) << "Re-scheduled CFRunLoopTimer" << m_runLoopTimer; } m_overdueTimerScheduled = !timespecToSeconds(tv); - qEventDispatcherDebug() << "Next timeout in " << tv << " seconds"; + qCDebug(lcEventDispatcherTimers) << "Next timeout in" << tv << "seconds"; } else { // No Qt timers are registered, so make sure we're not running any CF timers @@ -637,7 +628,7 @@ void QEventDispatcherCoreFoundation::invalidateTimer() return; CFRunLoopTimerInvalidate(m_runLoopTimer); - qEventDispatcherDebug() << "Invalidated CFRunLoopTimer " << m_runLoopTimer; + qCDebug(lcEventDispatcherTimers) << "Invalidated CFRunLoopTimer" << m_runLoopTimer; CFRelease(m_runLoopTimer); m_runLoopTimer = 0; diff --git a/src/corelib/kernel/qeventdispatcher_cf_p.h b/src/corelib/kernel/qeventdispatcher_cf_p.h index 8a234ebc40..a607ab7a15 100644 --- a/src/corelib/kernel/qeventdispatcher_cf_p.h +++ b/src/corelib/kernel/qeventdispatcher_cf_p.h @@ -85,19 +85,22 @@ // We mean it. // -#define DEBUG_EVENT_DISPATCHER 0 - #include <QtCore/qabstracteventdispatcher.h> #include <QtCore/private/qtimerinfo_unix_p.h> #include <QtCore/private/qcfsocketnotifier_p.h> #include <QtCore/private/qcore_mac_p.h> #include <QtCore/qdebug.h> +#include <QtCore/qloggingcategory.h> + #include <CoreFoundation/CoreFoundation.h> Q_FORWARD_DECLARE_OBJC_CLASS(QT_MANGLE_NAMESPACE(RunLoopModeTracker)); QT_BEGIN_NAMESPACE +Q_DECLARE_LOGGING_CATEGORY(lcEventDispatcher); +Q_DECLARE_LOGGING_CATEGORY(lcEventDispatcherTimers) + class QEventDispatcherCoreFoundation; template <class T = QEventDispatcherCoreFoundation> @@ -269,17 +272,4 @@ private: QT_END_NAMESPACE -#if DEBUG_EVENT_DISPATCHER -extern uint g_eventDispatcherIndentationLevel; -#define qEventDispatcherDebug() qDebug().nospace() \ - << qPrintable(QString(QLatin1String("| ")).repeated(g_eventDispatcherIndentationLevel)) \ - << __FUNCTION__ << "(): " -#define qIndent() ++g_eventDispatcherIndentationLevel -#define qUnIndent() --g_eventDispatcherIndentationLevel -#else -#define qEventDispatcherDebug() QT_NO_QDEBUG_MACRO() -#define qIndent() -#define qUnIndent() -#endif - #endif // QEVENTDISPATCHER_CF_P_H diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index 6fcc6b8d30..7ccacd883f 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -3892,6 +3892,19 @@ QDebug operator<<(QDebug dbg, const QVariant::Type p) \sa setValue(), value() */ +/*! \fn static inline QVariant fromStdVariant(const std::variant<T, Types...> &value) + \since 5.11 + + Returns a QVariant with the type and value of the active variant of \a value. If + the active type is std::monostate a default QVariant is returned. + + \note With this method you do not need to register the variant as a Qt metatype, + since the std::variant is resolved before being stored. The component types + should be registered however. + + \sa fromValue() +*/ + /*! \fn template<typename T> QVariant qVariantFromValue(const T &value) \relates QVariant diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h index 29e67e9dd8..fe1ef1bdfc 100644 --- a/src/corelib/kernel/qvariant.h +++ b/src/corelib/kernel/qvariant.h @@ -53,6 +53,10 @@ #include <QtCore/qbytearraylist.h> #endif +#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L +#include <variant> +#endif + QT_BEGIN_NAMESPACE @@ -355,6 +359,16 @@ class Q_CORE_EXPORT QVariant static inline QVariant fromValue(const T &value) { return qVariantFromValue(value); } +#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L + template<typename... Types> + static inline QVariant fromStdVariant(const std::variant<Types...> &value) + { + if (value.valueless_by_exception()) + return QVariant(); + return std::visit([](const auto &arg) { return fromValue(arg); }, value); + } +#endif + template<typename T> bool canConvert() const { return canConvert(qMetaTypeId<T>()); } @@ -503,6 +517,11 @@ inline QVariant qVariantFromValue(const T &t) template <> inline QVariant qVariantFromValue(const QVariant &t) { return t; } +#if QT_HAS_INCLUDE(<variant>) && __cplusplus >= 201703L +template <> +inline QVariant qVariantFromValue(const std::monostate &) { return QVariant(); } +#endif + template <typename T> inline void qVariantSetValue(QVariant &v, const T &t) { diff --git a/src/corelib/mimetypes/qmimetype.cpp b/src/corelib/mimetypes/qmimetype.cpp index 8f6237c1cb..d7590ecf1f 100644 --- a/src/corelib/mimetypes/qmimetype.cpp +++ b/src/corelib/mimetypes/qmimetype.cpp @@ -466,6 +466,8 @@ QStringList QMimeType::suffixes() const */ QString QMimeType::preferredSuffix() const { + if (isDefault()) // workaround for unwanted *.bin suffix for octet-stream, https://bugs.freedesktop.org/show_bug.cgi?id=101667, fixed upstream in 1.10 + return QString(); const QStringList suffixList = suffixes(); return suffixList.isEmpty() ? QString() : suffixList.at(0); } diff --git a/src/corelib/plugin/qfactoryloader.cpp b/src/corelib/plugin/qfactoryloader.cpp index 0cc193c325..a4be18a67f 100644 --- a/src/corelib/plugin/qfactoryloader.cpp +++ b/src/corelib/plugin/qfactoryloader.cpp @@ -54,6 +54,8 @@ #include "qjsonobject.h" #include "qjsonarray.h" +#include <qtcore_tracepoints_p.h> + QT_BEGIN_NAMESPACE class QFactoryLoaderPrivate : public QObjectPrivate @@ -142,6 +144,9 @@ void QFactoryLoader::update() if (qt_debug_component()) { qDebug() << "QFactoryLoader::QFactoryLoader() looking at" << fileName; } + + Q_TRACE(qfactoryloader_update, fileName); + library = QLibraryPrivate::findOrCreate(QFileInfo(fileName).canonicalFilePath()); if (!library->isPlugin()) { if (qt_debug_component()) { diff --git a/src/corelib/plugin/qlibrary.cpp b/src/corelib/plugin/qlibrary.cpp index ebad7f1751..bca6918b4a 100644 --- a/src/corelib/plugin/qlibrary.cpp +++ b/src/corelib/plugin/qlibrary.cpp @@ -64,6 +64,8 @@ #include "qelfparser_p.h" #include "qmachparser_p.h" +#include <qtcore_tracepoints_p.h> + QT_BEGIN_NAMESPACE #ifdef QT_NO_DEBUG @@ -535,6 +537,8 @@ bool QLibraryPrivate::load() if (fileName.isEmpty()) return false; + Q_TRACE(qlibraryprivate_load_entry, fileName); + bool ret = load_sys(); if (qt_debug_component()) { if (ret) { @@ -551,6 +555,8 @@ bool QLibraryPrivate::load() installCoverageTool(this); } + Q_TRACE(qlibraryprivate_load_exit, ret); + return ret; } diff --git a/src/corelib/plugin/quuid.cpp b/src/corelib/plugin/quuid.cpp index 4d658e064c..b113ca13ce 100644 --- a/src/corelib/plugin/quuid.cpp +++ b/src/corelib/plugin/quuid.cpp @@ -149,7 +149,6 @@ static QUuid _q_uuidFromHex(const char *src) return QUuid(); } -#ifndef QT_BOOTSTRAPPED static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCryptographicHash::Algorithm algorithm, int version) { QByteArray hashResult; @@ -172,7 +171,6 @@ static QUuid createFromName(const QUuid &ns, const QByteArray &baseData, QCrypto return result; } -#endif /*! \class QUuid @@ -510,12 +508,12 @@ QUuid QUuid::createUuidV3(const QUuid &ns, const QByteArray &baseData) { return createFromName(ns, baseData, QCryptographicHash::Md5, 3); } +#endif QUuid QUuid::createUuidV5(const QUuid &ns, const QByteArray &baseData) { return createFromName(ns, baseData, QCryptographicHash::Sha1, 5); } -#endif /*! Creates a QUuid object from the binary representation of the UUID, as diff --git a/src/corelib/plugin/quuid.h b/src/corelib/plugin/quuid.h index 27a84b4e01..08a1843640 100644 --- a/src/corelib/plugin/quuid.h +++ b/src/corelib/plugin/quuid.h @@ -201,18 +201,20 @@ public: static QUuid createUuid(); #ifndef QT_BOOTSTRAPPED static QUuid createUuidV3(const QUuid &ns, const QByteArray &baseData); +#endif static QUuid createUuidV5(const QUuid &ns, const QByteArray &baseData); +#ifndef QT_BOOTSTRAPPED static inline QUuid createUuidV3(const QUuid &ns, const QString &baseData) { return QUuid::createUuidV3(ns, baseData.toUtf8()); } +#endif static inline QUuid createUuidV5(const QUuid &ns, const QString &baseData) { return QUuid::createUuidV5(ns, baseData.toUtf8()); } -#endif QUuid::Variant variant() const Q_DECL_NOTHROW; QUuid::Version version() const Q_DECL_NOTHROW; diff --git a/src/corelib/qtcore.tracepoints b/src/corelib/qtcore.tracepoints new file mode 100644 index 0000000000..e6b666ac74 --- /dev/null +++ b/src/corelib/qtcore.tracepoints @@ -0,0 +1,5 @@ +qcoreapplicationprivate_init_entry() +qcoreapplicationprivate_init_exit() +qfactoryloader_update(const QString &fileName) +qlibraryprivate_load_entry(const QString &fileName) +qlibraryprivate_load_exit(bool success) diff --git a/src/corelib/xml/.gitignore b/src/corelib/serialization/.gitignore index 89f9ac04aa..89f9ac04aa 100644 --- a/src/corelib/xml/.gitignore +++ b/src/corelib/serialization/.gitignore diff --git a/src/corelib/xml/make-parser.sh b/src/corelib/serialization/make-xml-parser.sh index 0296e4c22b..0296e4c22b 100755 --- a/src/corelib/xml/make-parser.sh +++ b/src/corelib/serialization/make-xml-parser.sh diff --git a/src/corelib/io/qdatastream.cpp b/src/corelib/serialization/qdatastream.cpp index 8f419a4a46..8f419a4a46 100644 --- a/src/corelib/io/qdatastream.cpp +++ b/src/corelib/serialization/qdatastream.cpp diff --git a/src/corelib/io/qdatastream.h b/src/corelib/serialization/qdatastream.h index 1f1b13686c..1f1b13686c 100644 --- a/src/corelib/io/qdatastream.h +++ b/src/corelib/serialization/qdatastream.h diff --git a/src/corelib/io/qdatastream_p.h b/src/corelib/serialization/qdatastream_p.h index 3ca0ae840e..3ca0ae840e 100644 --- a/src/corelib/io/qdatastream_p.h +++ b/src/corelib/serialization/qdatastream_p.h diff --git a/src/corelib/json/qjson.cpp b/src/corelib/serialization/qjson.cpp index e4bca3bcd0..e4bca3bcd0 100644 --- a/src/corelib/json/qjson.cpp +++ b/src/corelib/serialization/qjson.cpp diff --git a/src/corelib/json/qjson_p.h b/src/corelib/serialization/qjson_p.h index 131528376b..7743382806 100644 --- a/src/corelib/json/qjson_p.h +++ b/src/corelib/serialization/qjson_p.h @@ -154,14 +154,7 @@ static inline bool useCompressed(const QString &s) { if (s.length() >= 0x8000) return false; - const ushort *uc = (const ushort *)s.constData(); - const ushort *e = uc + s.length(); - while (uc < e) { - if (*uc > 0xff) - return false; - ++uc; - } - return true; + return QtPrivate::isLatin1(s); } static inline int qStringSize(const QString &string, bool compress) diff --git a/src/corelib/json/qjsonarray.cpp b/src/corelib/serialization/qjsonarray.cpp index c5a5aaf39d..c5a5aaf39d 100644 --- a/src/corelib/json/qjsonarray.cpp +++ b/src/corelib/serialization/qjsonarray.cpp diff --git a/src/corelib/json/qjsonarray.h b/src/corelib/serialization/qjsonarray.h index 8d41138c97..8d41138c97 100644 --- a/src/corelib/json/qjsonarray.h +++ b/src/corelib/serialization/qjsonarray.h diff --git a/src/corelib/json/qjsondocument.cpp b/src/corelib/serialization/qjsondocument.cpp index 9794bca60d..9794bca60d 100644 --- a/src/corelib/json/qjsondocument.cpp +++ b/src/corelib/serialization/qjsondocument.cpp diff --git a/src/corelib/json/qjsondocument.h b/src/corelib/serialization/qjsondocument.h index b784890c54..b784890c54 100644 --- a/src/corelib/json/qjsondocument.h +++ b/src/corelib/serialization/qjsondocument.h diff --git a/src/corelib/json/qjsonobject.cpp b/src/corelib/serialization/qjsonobject.cpp index 4a316c8a6f..4a316c8a6f 100644 --- a/src/corelib/json/qjsonobject.cpp +++ b/src/corelib/serialization/qjsonobject.cpp diff --git a/src/corelib/json/qjsonobject.h b/src/corelib/serialization/qjsonobject.h index 610bce694c..610bce694c 100644 --- a/src/corelib/json/qjsonobject.h +++ b/src/corelib/serialization/qjsonobject.h diff --git a/src/corelib/json/qjsonparser.cpp b/src/corelib/serialization/qjsonparser.cpp index 39738b90a8..39738b90a8 100644 --- a/src/corelib/json/qjsonparser.cpp +++ b/src/corelib/serialization/qjsonparser.cpp diff --git a/src/corelib/json/qjsonparser_p.h b/src/corelib/serialization/qjsonparser_p.h index 379256847f..379256847f 100644 --- a/src/corelib/json/qjsonparser_p.h +++ b/src/corelib/serialization/qjsonparser_p.h diff --git a/src/corelib/json/qjsonvalue.cpp b/src/corelib/serialization/qjsonvalue.cpp index 33707b6ec3..33707b6ec3 100644 --- a/src/corelib/json/qjsonvalue.cpp +++ b/src/corelib/serialization/qjsonvalue.cpp diff --git a/src/corelib/json/qjsonvalue.h b/src/corelib/serialization/qjsonvalue.h index 96538ebbf9..96538ebbf9 100644 --- a/src/corelib/json/qjsonvalue.h +++ b/src/corelib/serialization/qjsonvalue.h diff --git a/src/corelib/json/qjsonwriter.cpp b/src/corelib/serialization/qjsonwriter.cpp index 12ce20ef09..12ce20ef09 100644 --- a/src/corelib/json/qjsonwriter.cpp +++ b/src/corelib/serialization/qjsonwriter.cpp diff --git a/src/corelib/json/qjsonwriter_p.h b/src/corelib/serialization/qjsonwriter_p.h index 76a8460449..76a8460449 100644 --- a/src/corelib/json/qjsonwriter_p.h +++ b/src/corelib/serialization/qjsonwriter_p.h diff --git a/src/corelib/io/qtextstream.cpp b/src/corelib/serialization/qtextstream.cpp index ee3cb4efcb..ee3cb4efcb 100644 --- a/src/corelib/io/qtextstream.cpp +++ b/src/corelib/serialization/qtextstream.cpp diff --git a/src/corelib/io/qtextstream.h b/src/corelib/serialization/qtextstream.h index ee0b09419d..ee0b09419d 100644 --- a/src/corelib/io/qtextstream.h +++ b/src/corelib/serialization/qtextstream.h diff --git a/src/corelib/io/qtextstream_p.h b/src/corelib/serialization/qtextstream_p.h index a642beddc4..a642beddc4 100644 --- a/src/corelib/io/qtextstream_p.h +++ b/src/corelib/serialization/qtextstream_p.h diff --git a/src/corelib/xml/qxmlstream.cpp b/src/corelib/serialization/qxmlstream.cpp index 9b5295a17e..a92dd71df5 100644 --- a/src/corelib/xml/qxmlstream.cpp +++ b/src/corelib/serialization/qxmlstream.cpp @@ -409,6 +409,11 @@ QXmlStreamReader::QXmlStreamReader(const QByteArray &data) /*! Creates a new stream reader that reads from \a data. + This function should only be used if the XML header either says the encoding + is "UTF-8" or lacks any encoding information (the latter is the case of + QXmlStreamWriter writing to a QString). Any other encoding is likely going to + cause data corruption ("mojibake"). + \sa addData(), clear(), setDevice() */ QXmlStreamReader::QXmlStreamReader(const QString &data) @@ -3268,6 +3273,9 @@ QXmlStreamWriter::QXmlStreamWriter(QByteArray *array) /*! Constructs a stream writer that writes into \a string. + * + * Note that when writing to QString, QXmlStreamWriter ignores the codec set + * with setCodec(). See that function for more information. */ QXmlStreamWriter::QXmlStreamWriter(QString *string) : d_ptr(new QXmlStreamWriterPrivate(this)) @@ -3326,6 +3334,12 @@ QIODevice *QXmlStreamWriter::device() const gets written when you call writeStartDocument(). Call this function before calling writeStartDocument(). + \note When writing the XML to a QString, the codec information is ignored + and the XML header will not include any encoding information, since all + QStrings are UTF-16. If you later convert the QString to an 8-bit format, + you must arrange for the encoding information to be transmitted + out-of-band. + \sa codec() */ void QXmlStreamWriter::setCodec(QTextCodec *codec) @@ -3345,6 +3359,12 @@ void QXmlStreamWriter::setCodec(QTextCodec *codec) "ISO 8859-1", "UTF-8", and "UTF-16". If the encoding isn't recognized, nothing happens. + \note When writing the XML to a QString, the codec information is ignored + and the XML header will not include any encoding information, since all + QStrings are UTF-16. If you later convert the QString to an 8-bit format, + you must arrange for the encoding information to be transmitted + out-of-band. + \sa QTextCodec::codecForName() */ void QXmlStreamWriter::setCodec(const char *codecName) diff --git a/src/corelib/xml/qxmlstream.g b/src/corelib/serialization/qxmlstream.g index fd69a6e4af..fd69a6e4af 100644 --- a/src/corelib/xml/qxmlstream.g +++ b/src/corelib/serialization/qxmlstream.g diff --git a/src/corelib/xml/qxmlstream.h b/src/corelib/serialization/qxmlstream.h index 2350d12dd6..2350d12dd6 100644 --- a/src/corelib/xml/qxmlstream.h +++ b/src/corelib/serialization/qxmlstream.h diff --git a/src/corelib/xml/qxmlstream_p.h b/src/corelib/serialization/qxmlstream_p.h index 5645d812eb..5645d812eb 100644 --- a/src/corelib/xml/qxmlstream_p.h +++ b/src/corelib/serialization/qxmlstream_p.h diff --git a/src/corelib/xml/qxmlutils.cpp b/src/corelib/serialization/qxmlutils.cpp index 01c84251fd..01c84251fd 100644 --- a/src/corelib/xml/qxmlutils.cpp +++ b/src/corelib/serialization/qxmlutils.cpp diff --git a/src/corelib/xml/qxmlutils_p.h b/src/corelib/serialization/qxmlutils_p.h index db6bddd5be..db6bddd5be 100644 --- a/src/corelib/xml/qxmlutils_p.h +++ b/src/corelib/serialization/qxmlutils_p.h diff --git a/src/corelib/serialization/serialization.pri b/src/corelib/serialization/serialization.pri new file mode 100644 index 0000000000..3d039dc30f --- /dev/null +++ b/src/corelib/serialization/serialization.pri @@ -0,0 +1,30 @@ +# Qt data formats core module + +HEADERS += \ + serialization/qdatastream.h \ + serialization/qdatastream_p.h \ + serialization/qjson_p.h \ + serialization/qjsondocument.h \ + serialization/qjsonobject.h \ + serialization/qjsonvalue.h \ + serialization/qjsonarray.h \ + serialization/qjsonwriter_p.h \ + serialization/qjsonparser_p.h \ + serialization/qtextstream.h \ + serialization/qtextstream_p.h \ + serialization/qxmlstream.h \ + serialization/qxmlstream_p.h \ + serialization/qxmlutils_p.h + +SOURCES += \ + serialization/qdatastream.cpp \ + serialization/qjson.cpp \ + serialization/qjsondocument.cpp \ + serialization/qjsonobject.cpp \ + serialization/qjsonarray.cpp \ + serialization/qjsonvalue.cpp \ + serialization/qjsonwriter.cpp \ + serialization/qjsonparser.cpp \ + serialization/qtextstream.cpp \ + serialization/qxmlstream.cpp \ + serialization/qxmlutils.cpp diff --git a/src/corelib/thread/qthread_unix.cpp b/src/corelib/thread/qthread_unix.cpp index fb5c9fd770..1bb8e613e0 100644 --- a/src/corelib/thread/qthread_unix.cpp +++ b/src/corelib/thread/qthread_unix.cpp @@ -311,16 +311,14 @@ void QThreadPrivate::createEventDispatcher(QThreadData *data) #ifndef QT_NO_THREAD #if (defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_QNX)) -static void setCurrentThreadName(pthread_t threadId, const char *name) +static void setCurrentThreadName(const char *name) { # if defined(Q_OS_LINUX) && !defined(QT_LINUXBASE) - Q_UNUSED(threadId); prctl(PR_SET_NAME, (unsigned long)name, 0, 0, 0); # elif defined(Q_OS_MAC) - Q_UNUSED(threadId); pthread_setname_np(name); # elif defined(Q_OS_QNX) - pthread_setname_np(threadId, name); + pthread_setname_np(pthread_self(), name); # endif } #endif @@ -361,14 +359,13 @@ void *QThreadPrivate::start(void *arg) #if (defined(Q_OS_LINUX) || defined(Q_OS_MAC) || defined(Q_OS_QNX)) { - // sets the name of the current thread. - QString objectName = thr->objectName(); - - pthread_t thread_id = from_HANDLE<pthread_t>(data->threadId.load()); - if (Q_LIKELY(objectName.isEmpty())) - setCurrentThreadName(thread_id, thr->metaObject()->className()); + // Sets the name of the current thread. We can only do this + // when the thread is starting, as we don't have a cross + // platform way of setting the name of an arbitrary thread. + if (Q_LIKELY(thr->objectName().isEmpty())) + setCurrentThreadName(thr->metaObject()->className()); else - setCurrentThreadName(thread_id, objectName.toLocal8Bit()); + setCurrentThreadName(thr->objectName().toLocal8Bit()); } #endif diff --git a/src/corelib/tools/qbitarray.cpp b/src/corelib/tools/qbitarray.cpp index 12e4687b3c..f68a807203 100644 --- a/src/corelib/tools/qbitarray.cpp +++ b/src/corelib/tools/qbitarray.cpp @@ -300,6 +300,46 @@ void QBitArray::fill(bool value, int begin, int end) setBit(begin++, value); } +/*! + \fn const char *QBitArray::bits() const + \since 5.11 + + Returns a pointer to a dense bit array for this QBitArray. Bits are counted + upwards from the least significant bit in each byte. The the number of bits + relevant in the last byte is given by \c{size() % 8}. + + \sa fromBits(), size() + */ + +/*! + \since 5.11 + + Creates a QBitArray with the dense bit array located at \a data, with \a + len bits. The byte array at \a data must be at least \a size / 8 (rounded up) + bytes long. + + If \a size is not a multiple of 8, this function will include the lowest + \a size % 8 bits from the last byte in \a data. + + \sa bits() + */ +QBitArray QBitArray::fromBits(const char *data, qsizetype size) +{ + QBitArray result; + qsizetype nbytes = (size + 7) / 8; + + result.d = QByteArray(nbytes + 1, Qt::Uninitialized); + char *bits = result.d.data(); + memcpy(bits + 1, data, nbytes); + + // clear any unused bits from the last byte + if (size & 7) + bits[nbytes] &= 0xffU >> (size & 7); + + *bits = result.d.size() * 8 - size; + return result; +} + /*! \fn bool QBitArray::isDetached() const \internal diff --git a/src/corelib/tools/qbitarray.h b/src/corelib/tools/qbitarray.h index 8fa5323127..ff40bf5654 100644 --- a/src/corelib/tools/qbitarray.h +++ b/src/corelib/tools/qbitarray.h @@ -104,6 +104,9 @@ public: inline void truncate(int pos) { if (pos < size()) resize(pos); } + const char *bits() const { return isEmpty() ? nullptr : d.constData() + 1; } + static QBitArray fromBits(const char *data, qsizetype len); + public: typedef QByteArray::DataPtr DataPtr; inline DataPtr &data_ptr() { return d.data_ptr(); } diff --git a/src/corelib/tools/qsimd_p.h b/src/corelib/tools/qsimd_p.h index fafc3e37b0..eb56b31348 100644 --- a/src/corelib/tools/qsimd_p.h +++ b/src/corelib/tools/qsimd_p.h @@ -177,55 +177,37 @@ # define QT_FUNCTION_TARGET(x) #endif -#if defined(Q_CC_MSVC) && (defined(_M_AVX) || defined(__AVX__)) -// Visual Studio defines __AVX__ when /arch:AVX is passed, but not the earlier macros -// See: https://msdn.microsoft.com/en-us/library/b0084kay.aspx -// SSE2 is handled by _M_IX86_FP below -# define __SSE3__ 1 -# define __SSSE3__ 1 -// no Intel CPU supports SSE4a, so don't define it -# define __SSE4_1__ 1 -# define __SSE4_2__ 1 -# ifndef __AVX__ -# define __AVX__ 1 -# endif -#endif - -// SSE intrinsics -#if defined(__SSE2__) || (defined(QT_COMPILER_SUPPORTS_SSE2) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS)) -#if defined(QT_LINUXBASE) -/// this is an evil hack - the posix_memalign declaration in LSB -/// is wrong - see http://bugs.linuxbase.org/show_bug.cgi?id=2431 -# define posix_memalign _lsb_hack_posix_memalign -# include <emmintrin.h> -# undef posix_memalign -#else -# include <emmintrin.h> -#endif -#if defined(Q_CC_MSVC) && (defined(_M_X64) || _M_IX86_FP >= 2) -# define __SSE__ 1 -# define __SSE2__ 1 -#endif -#endif +#ifdef Q_PROCESSOR_X86 +/* -- x86 intrinsic support -- */ -// SSE3 intrinsics -#if defined(__SSE3__) || (defined(QT_COMPILER_SUPPORTS_SSE3) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS)) -#include <pmmintrin.h> -#endif +# if defined(Q_CC_MSVC) && (defined(_M_X64) || _M_IX86_FP >= 2) +// MSVC doesn't define __SSE2__, so do it ourselves +# define __SSE__ 1 +# define __SSE2__ 1 +# endif -// SSSE3 intrinsics -#if defined(__SSSE3__) || (defined(QT_COMPILER_SUPPORTS_SSSE3) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS)) -#include <tmmintrin.h> -#endif +# ifdef __SSE2__ +// #include the intrinsics +# include <immintrin.h> +# endif -// SSE4.1 intrinsics -#if defined(__SSE4_1__) || (defined(QT_COMPILER_SUPPORTS_SSE4_1) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS)) -#include <smmintrin.h> -#endif +# if defined(Q_CC_GNU) && !defined(Q_CC_INTEL) +// GCC 4.4 and Clang 2.8 added a few more intrinsics there +# include <x86intrin.h> +# endif -// SSE4.2 intrinsics -#if defined(__SSE4_2__) || (defined(QT_COMPILER_SUPPORTS_SSE4_2) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS)) -#include <nmmintrin.h> +# if defined(Q_CC_MSVC) && (defined(_M_AVX) || defined(__AVX__)) +// Visual Studio defines __AVX__ when /arch:AVX is passed, but not the earlier macros +// See: https://msdn.microsoft.com/en-us/library/b0084kay.aspx +# define __SSE3__ 1 +# define __SSSE3__ 1 +// no Intel CPU supports SSE4a, so don't define it +# define __SSE4_1__ 1 +# define __SSE4_2__ 1 +# ifndef __AVX__ +# define __AVX__ 1 +# endif +# endif # if defined(__SSE4_2__) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS) && (defined(Q_CC_INTEL) || defined(Q_CC_MSVC)) // POPCNT instructions: @@ -233,13 +215,8 @@ // (but neither MSVC nor the Intel compiler define this macro) # define __POPCNT__ 1 # endif -#endif // AVX intrinsics -#if defined(__AVX__) || (defined(QT_COMPILER_SUPPORTS_AVX) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS)) -// immintrin.h is the ultimate header, we don't need anything else after this -#include <immintrin.h> - # if defined(__AVX__) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS) && (defined(Q_CC_INTEL) || defined(Q_CC_MSVC)) // AES, PCLMULQDQ instructions: // All processors that support AVX support AES, PCLMULQDQ @@ -255,11 +232,6 @@ # define __F16C__ 1 # define __RDRND__ 1 # endif -#endif - -#if defined(__AES__) || defined(__PCLMUL__) || (defined(QT_COMPILER_SUPPORTS_AES) && defined(QT_COMPILER_SUPPORTS_SIMD_ALWAYS)) -# include <wmmintrin.h> -#endif #define QT_FUNCTION_TARGET_STRING_SSE2 "sse2" #define QT_FUNCTION_TARGET_STRING_SSE3 "sse3" @@ -288,19 +260,7 @@ #define QT_FUNCTION_TARGET_STRING_RDSEED "rdseed" #define QT_FUNCTION_TARGET_STRING_SHA "sha" -// other x86 intrinsics -#if defined(Q_PROCESSOR_X86) && ((defined(Q_CC_GNU) && (Q_CC_GNU >= 404)) \ - || (defined(Q_CC_CLANG) && (Q_CC_CLANG >= 208)) \ - || defined(Q_CC_INTEL)) -# define QT_COMPILER_SUPPORTS_X86INTRIN -# ifdef Q_CC_INTEL -// The Intel compiler has no <x86intrin.h> -- all intrinsics are in <immintrin.h>; -# include <immintrin.h> -# else -// GCC 4.4 and Clang 2.8 added a few more intrinsics there -# include <x86intrin.h> -# endif -#endif +#endif /* Q_PROCESSOR_X86 */ // Clang compiler fix, see http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20160222/151168.html // This should be tweaked with an "upper version" of clang once we know which release fixes the diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 5eeaa2a2a8..4040d59b0a 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2018 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -251,6 +251,151 @@ inline RetType UnrollTailLoop<0>::exec(Number, RetType returnIfExited, Functor1, } #endif +#ifdef __SSE2__ +static bool simdTestMask(const char *&ptr, const char *end, quint32 maskval) +{ +# if defined(__AVX2__) + // AVX2 implementation: test 32 bytes at a time + const __m256i mask256 = _mm256_broadcastd_epi32(_mm_cvtsi32_si128(maskval)); + while (ptr + 32 < end) { + __m256i data = _mm256_loadu_si256(reinterpret_cast<const __m256i *>(ptr)); + if (!_mm256_testz_si256(mask256, data)) + return false; + ptr += 32; + } + + const __m128i mask = _mm256_castsi256_si128(mask256); +# elif defined(__SSE4_1__) + // SSE 4.1 implementation: test 32 bytes at a time (two 16-byte + // comparisons, unrolled) + const __m128i mask = _mm_set1_epi32(maskval); + while (ptr + 32 < end) { + __m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr)); + __m128i data2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr + 16)); + if (!_mm_testz_si128(mask, data1)) + return false; + if (!_mm_testz_si128(mask, data2)) + return false; + ptr += 32; + } +# endif +# if defined(__SSE4_1__) + // AVX2 and SSE4.1: final 16-byte comparison + if (ptr + 16 < end) { + __m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr)); + if (!_mm_testz_si128(mask, data1)) + return false; + ptr += 16; + } +# else + // SSE2 implementation: test 16 bytes at a time. + const __m128i mask = _mm_set1_epi32(maskval); + while (ptr + 16 < end) { + __m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr)); + __m128i masked = _mm_andnot_si128(mask, data); + __m128i comparison = _mm_cmpeq_epi16(masked, _mm_setzero_si128()); + if (quint16(_mm_movemask_epi8(comparison)) != 0xffff) + return false; + ptr += 16; + } +# endif + + return true; +} +#endif + +bool QtPrivate::isAscii(QLatin1String s) Q_DECL_NOTHROW +{ + const char *ptr = s.begin(); + const char *end = s.end(); + +#if defined(__AVX2__) + if (!simdTestMask(ptr, end, 0x80808080)) + return false; +#elif defined(__SSE2__) + // Testing for the high bit can be done efficiently with just PMOVMSKB + while (ptr + 16 < end) { + __m128i data = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr)); + quint32 mask = _mm_movemask_epi8(data); + if (mask) + return false; + ptr += 16; + } +#endif + + while (ptr + 4 < end) { + quint32 data = qFromUnaligned<quint32>(ptr); + if (data & 0x80808080U) + return false; + ptr += 4; + } + + while (ptr != end) { + if (quint8(*ptr++) & 0x80) + return false; + } + return true; +} + +bool QtPrivate::isAscii(QStringView s) Q_DECL_NOTHROW +{ + const QChar *ptr = s.begin(); + const QChar *end = s.end(); + +#ifdef __SSE2__ + const char *ptr8 = reinterpret_cast<const char *>(ptr); + const char *end8 = reinterpret_cast<const char *>(end); + if (!simdTestMask(ptr8, end8, 0xff80ff80)) + return false; + ptr = reinterpret_cast<const QChar *>(ptr8); +#endif + + while (ptr != end) { + if ((*ptr++).unicode() & 0xff80) + return false; + } + return true; +} + +bool QtPrivate::isLatin1(QStringView s) Q_DECL_NOTHROW +{ + const QChar *ptr = s.begin(); + const QChar *end = s.end(); + +#if defined(__SSE4_1__) + const char *ptr8 = reinterpret_cast<const char *>(ptr); + const char *end8 = reinterpret_cast<const char *>(end); + if (!simdTestMask(ptr8, end8, 0xff00ff00)) + return false; + ptr = reinterpret_cast<const QChar *>(ptr8); +#elif defined(__SSE2__) + // Testing if every other byte is non-zero can be done efficiently by + // using PUNPCKHBW (unpack high order bytes) and comparing that to zero. + while (ptr + 32 < end) { + __m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr)); + __m128i data2 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr + 16)); + __m128i high = _mm_unpackhi_epi8(data1, data2); + __m128i comparison = _mm_cmpeq_epi16(high, _mm_setzero_si128()); + if (_mm_movemask_epi8(comparison)) + return false; + ptr += 16; + } + if (ptr + 16 < end) { + __m128i data1 = _mm_loadu_si128(reinterpret_cast<const __m128i *>(ptr)); + __m128i high = _mm_unpackhi_epi8(data1, data1); + __m128i comparison = _mm_cmpeq_epi16(high, _mm_setzero_si128()); + if (_mm_movemask_epi8(comparison)) + return false; + } +#endif + + while (ptr != end) { + if ((*ptr++).unicode() > 0xff) + return false; + } + return true; +} + // conversion between Latin 1 and UTF-16 void qt_from_latin1(ushort *dst, const char *str, size_t size) Q_DECL_NOTHROW { @@ -2441,6 +2586,21 @@ QString &QString::remove(int pos, int len) return *this; } +template<typename T> +static void removeStringImpl(QString &s, const T &needle, Qt::CaseSensitivity cs) +{ + const int needleSize = needle.size(); + if (needleSize) { + if (needleSize == 1) { + s.remove(needle.front(), cs); + } else { + int i = 0; + while ((i = s.indexOf(needle, i, cs)) != -1) + s.remove(i, needleSize); + } + } +} + /*! Removes every occurrence of the given \a str string in this string, and returns a reference to this string. @@ -2454,11 +2614,27 @@ QString &QString::remove(int pos, int len) */ QString &QString::remove(const QString &str, Qt::CaseSensitivity cs) { - if (str.d->size) { - int i = 0; - while ((i = indexOf(str, i, cs)) != -1) - remove(i, str.d->size); - } + removeStringImpl(*this, str, cs); + return *this; +} + +/*! + \since 5.11 + \overload + + Removes every occurrence of the given \a str string in this + string, and returns a reference to this string. + + If \a cs is Qt::CaseSensitive (default), the search is + case sensitive; otherwise the search is case insensitive. + + This is the same as \c replace(str, "", cs). + + \sa replace() +*/ +QString &QString::remove(QLatin1String str, Qt::CaseSensitivity cs) +{ + removeStringImpl(*this, str, cs); return *this; } diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 808f388c89..0138ae4098 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -202,6 +202,12 @@ Q_DECLARE_TYPEINFO(QLatin1String, Q_MOVABLE_TYPE); typedef QLatin1String QLatin1Literal; // +// QLatin1String inline implementations +// +inline bool QtPrivate::isLatin1(QLatin1String) Q_DECL_NOTHROW +{ return true; } + +// // QStringView members that require QLatin1String: // bool QStringView::startsWith(QLatin1String s, Qt::CaseSensitivity cs) const Q_DECL_NOTHROW @@ -477,6 +483,7 @@ public: QString &remove(int i, int len); QString &remove(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive); + QString &remove(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive); QString &remove(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive); QString &replace(int i, int len, QChar after); QString &replace(int i, int len, const QChar *s, int slen); diff --git a/src/corelib/tools/qstringalgorithms.h b/src/corelib/tools/qstringalgorithms.h index 6146e525d9..8446d85239 100644 --- a/src/corelib/tools/qstringalgorithms.h +++ b/src/corelib/tools/qstringalgorithms.h @@ -82,6 +82,11 @@ Q_REQUIRED_RESULT Q_CORE_EXPORT QByteArray convertToLocal8Bit(QStringView str); Q_REQUIRED_RESULT Q_CORE_EXPORT QVector<uint> convertToUcs4(QStringView str); Q_REQUIRED_RESULT Q_CORE_EXPORT bool isRightToLeft(QStringView string); +Q_REQUIRED_RESULT Q_CORE_EXPORT bool isAscii(QLatin1String s) Q_DECL_NOTHROW; +Q_REQUIRED_RESULT Q_CORE_EXPORT bool isAscii(QStringView s) Q_DECL_NOTHROW; +Q_REQUIRED_RESULT bool isLatin1(QLatin1String s) Q_DECL_NOTHROW; // in qstring.h +Q_REQUIRED_RESULT Q_CORE_EXPORT bool isLatin1(QStringView s) Q_DECL_NOTHROW; + } // namespace QtPRivate QT_END_NAMESPACE diff --git a/src/corelib/tools/qvarlengtharray.qdoc b/src/corelib/tools/qvarlengtharray.qdoc index aff2f986e6..336f2afaca 100644 --- a/src/corelib/tools/qvarlengtharray.qdoc +++ b/src/corelib/tools/qvarlengtharray.qdoc @@ -725,8 +725,7 @@ vector. */ -/*! - \fn template<class T, int Prealloc> QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::insert(const_iterator before, const T &value) +/*! \fn template<class T, int Prealloc> QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::insert(const_iterator before, const T &value) \fn template<class T, int Prealloc> QVarLengthArray<T, Prealloc>::iterator QVarLengthArray<T, Prealloc>::insert(const_iterator before, T &&value) \overload diff --git a/src/corelib/tools/qvector.qdoc b/src/corelib/tools/qvector.qdoc index 173bdb5abf..cc250b72a5 100644 --- a/src/corelib/tools/qvector.qdoc +++ b/src/corelib/tools/qvector.qdoc @@ -607,8 +607,7 @@ \sa append(), insert() */ -/*! - \fn template <typename T> void QVector<T>::insert(int i, const T &value) +/*! \fn template <typename T> void QVector<T>::insert(int i, const T &value) \fn template <typename T> void QVector<T>::insert(int i, T &&value) Inserts \a value at index position \a i in the vector. If \a i is diff --git a/src/corelib/xml/xml.pri b/src/corelib/xml/xml.pri deleted file mode 100644 index 2401c09ab7..0000000000 --- a/src/corelib/xml/xml.pri +++ /dev/null @@ -1,10 +0,0 @@ -# Qt xml core module - -HEADERS += \ - xml/qxmlstream.h \ - xml/qxmlstream_p.h \ - xml/qxmlutils_p.h - -SOURCES += \ - xml/qxmlstream.cpp \ - xml/qxmlutils.cpp |