QRegularExpression: do not use JIT in debug builds
authorGiuseppe D'Angelo <dangelog@gmail.com>
Wed, 8 Feb 2012 19:28:14 +0000 (19:28 +0000)
committerQt by Nokia <qt-info@nokia.com>
Tue, 6 Mar 2012 20:54:30 +0000 (21:54 +0100)
PCRE's JIT uses self-modifying code extensively, requiring full SMC
checks enabled by tools like valgrind, which slow down the execution
considerably; not enabling SMC checks lead to crashes.

Therefore, JIT is now disabled by default in debug builds of Qt.
Its usage (both in debug and release builds) can be controlled
by setting the QT_ENABLE_REGEXP_JIT environment variable.

Change-Id: Ib38952400e4219582942ce65ab9edcd89c432f3e
Reviewed-by: Lars Knoll <lars.knoll@nokia.com>
src/corelib/tools/qregularexpression.cpp

index b7a5c3d..17988bd 100644 (file)
@@ -509,6 +509,22 @@ QT_BEGIN_NAMESPACE
     QRegExp::CaretAtOffset behaviour. There is no equivalent for the other
     QRegExp::CaretMode modes.
 
+    \section1 Debugging code that uses QRegularExpression
+
+    QRegularExpression internally uses a just in time compiler (JIT) to
+    optimize the execution of the matching algorithm. The JIT makes extensive
+    usage of self-modifying code, which can lead debugging tools such as
+    Valgrind to crash. You must enable all checks for self-modifying code if
+    you want to debug programs using QRegularExpression (f.i., see Valgrind's
+    \c{--smc-check} command line option). The downside of enabling such checks
+    is that your program will run considerably slower.
+
+    To avoid that, the JIT is disabled by default if you compile Qt in debug
+    mode. It is possible to override the default and enable or disable the JIT
+    usage (both in debug or release mode) by setting the
+    \c{QT_ENABLE_REGEXP_JIT} environment variable to a non-zero or zero value
+    respectively.
+
     \sa QRegularExpressionMatch, QRegularExpressionMatchIterator
 */
 
@@ -972,6 +988,25 @@ void QRegularExpressionPrivate::getPatternInfo()
 /*!
     \internal
 */
+static bool isJitEnabled()
+{
+    QByteArray jitEnvironment = qgetenv("QT_ENABLE_REGEXP_JIT");
+    if (!jitEnvironment.isEmpty()) {
+        bool ok;
+        int enableJit = jitEnvironment.toInt(&ok);
+        return ok ? (enableJit != 0) : true;
+    }
+
+#ifdef QT_DEBUG
+    return false;
+#else
+    return true;
+#endif
+}
+
+/*!
+    \internal
+*/
 void QRegularExpressionPrivate::optimizePattern()
 {
     Q_ASSERT(compiledPattern);
@@ -981,7 +1016,12 @@ void QRegularExpressionPrivate::optimizePattern()
     if (studyData || (++usedCount != OPTIMIZE_AFTER_USE_COUNT))
         return;
 
-    int studyOptions = PCRE_STUDY_JIT_COMPILE;
+    static const bool enableJit = isJitEnabled();
+
+    int studyOptions = 0;
+    if (enableJit)
+        studyOptions |= PCRE_STUDY_JIT_COMPILE;
+
     const char *err;
     studyData = pcre16_study(compiledPattern, studyOptions, &err);