aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/qml/jsruntime/qv4engine.cpp18
-rw-r--r--src/qml/jsruntime/qv4engine_p.h14
-rw-r--r--src/qml/jsruntime/qv4function_p.h1
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp8
-rw-r--r--tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp25
5 files changed, 50 insertions, 16 deletions
diff --git a/src/qml/jsruntime/qv4engine.cpp b/src/qml/jsruntime/qv4engine.cpp
index c57f39f61c..c97ba38dec 100644
--- a/src/qml/jsruntime/qv4engine.cpp
+++ b/src/qml/jsruntime/qv4engine.cpp
@@ -168,6 +168,15 @@ ExecutionEngine::ExecutionEngine()
/* writable */ true, /* executable */ false,
/* includesGuardPages */ true);
+ {
+ bool ok = false;
+ jitCallCountThreshold = qEnvironmentVariableIntValue("QV4_JIT_CALL_THRESHOLD", &ok);
+ if (!ok)
+ jitCallCountThreshold = 3;
+ if (qEnvironmentVariableIsSet("QV4_FORCE_INTERPRETER"))
+ jitCallCountThreshold = std::numeric_limits<int>::max();
+ }
+
exceptionValue = jsAlloca(1);
globalObject = static_cast<Object *>(jsAlloca(1));
jsObjects = jsAlloca(NJSObjects);
@@ -1545,15 +1554,6 @@ QV4::ReturnedValue ExecutionEngine::metaTypeToJS(int type, const void *data)
return 0;
}
-bool ExecutionEngine::canJIT()
-{
-#ifdef V4_ENABLE_JIT
- return true;
-#else
- return false;
-#endif
-}
-
// Converts a JS value to a meta-type.
// data must point to a place that can store a value of the given type.
// Returns true if conversion succeeded, false otherwise.
diff --git a/src/qml/jsruntime/qv4engine_p.h b/src/qml/jsruntime/qv4engine_p.h
index 346f290feb..61efe0c41e 100644
--- a/src/qml/jsruntime/qv4engine_p.h
+++ b/src/qml/jsruntime/qv4engine_p.h
@@ -56,7 +56,9 @@
#include <private/qintrusivelist_p.h>
#include "qv4enginebase_p.h"
+
#ifndef V4_BOOTSTRAP
+# include "qv4function_p.h"
# include <private/qv8engine_p.h>
# include <private/qv4compileddata_p.h>
#endif
@@ -85,6 +87,7 @@ namespace CompiledData {
struct CompilationUnit;
}
+struct Function;
struct InternalClass;
struct InternalClassPool;
@@ -481,13 +484,22 @@ public:
bool checkStackLimits();
- static bool canJIT();
+ bool canJIT(Function *f)
+ {
+#if defined(V4_ENABLE_JIT) && !defined(V4_BOOTSTRAP)
+ return f->interpreterCallCount > jitCallCountThreshold;
+#else
+ Q_UNUSED(f);
+ return false;
+#endif
+ }
private:
#if QT_CONFIG(qml_debug)
QScopedPointer<QV4::Debugging::Debugger> m_debugger;
QScopedPointer<QV4::Profiling::Profiler> m_profiler;
#endif
+ int jitCallCountThreshold;
};
// This is a trick to tell the code generators that functions taking a NoThrowContext won't
diff --git a/src/qml/jsruntime/qv4function_p.h b/src/qml/jsruntime/qv4function_p.h
index 0e61be5115..dcbd41f2e6 100644
--- a/src/qml/jsruntime/qv4function_p.h
+++ b/src/qml/jsruntime/qv4function_p.h
@@ -83,6 +83,7 @@ struct Q_QML_EXPORT Function {
// first nArguments names in internalClass are the actual arguments
InternalClass *internalClass;
uint nFormals;
+ int interpreterCallCount = 0;
bool hasQmlDependencies;
Function(ExecutionEngine *engine, CompiledData::CompilationUnit *unit, const CompiledData::Function *function, Code codePtr);
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index c21d992e98..6956112718 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -552,17 +552,17 @@ QV4::ReturnedValue VME::exec(const FunctionObject *fo, const Value *thisObject,
Profiling::FunctionCallProfiler profiler(engine, function); // start execution profiling
QV4::Debugging::Debugger *debugger = engine->debugger();
-
const uchar *exceptionHandler = 0;
QV4::Value &accumulator = frame.jsFrame->accumulator;
QV4::ReturnedValue acc = Encode::undefined();
#ifdef V4_ENABLE_JIT
- static const bool forceInterpreter = qEnvironmentVariableIsSet("QV4_FORCE_INTERPRETER");
- if (function->jittedCode == nullptr) {
- if (ExecutionEngine::canJIT() && debugger == nullptr && !forceInterpreter)
+ if (function->jittedCode == nullptr && debugger == nullptr) {
+ if (engine->canJIT(function))
QV4::JIT::BaselineJIT(function).generate();
+ else
+ ++function->interpreterCallCount;
}
#endif // V4_ENABLE_JIT
diff --git a/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp b/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp
index 4303aec2a7..0d58d045b9 100644
--- a/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp
+++ b/tests/auto/qml/ecmascripttests/tst_ecmascripttests.cpp
@@ -34,17 +34,28 @@
class tst_EcmaScriptTests : public QObject
{
Q_OBJECT
+
+ void runTests(bool interpret);
+
private slots:
- void runTests();
+ void runInterpreted();
+ void runJitted();
};
-void tst_EcmaScriptTests::runTests()
+void tst_EcmaScriptTests::runTests(bool interpret)
{
#if defined(Q_OS_LINUX) && defined(Q_PROCESSOR_X86_64)
+ QProcessEnvironment env = QProcessEnvironment::systemEnvironment();
+ if (interpret)
+ env.insert("QV4_FORCE_INTERPRETER", "1");
+ else
+ env.insert("QV4_JIT_CALL_THRESHOLD", "0");
+
QProcess process;
process.setProcessChannelMode(QProcess::ForwardedChannels);
process.setWorkingDirectory(QLatin1String(SRCDIR));
process.setProgram("python");
+ process.setProcessEnvironment(env);
process.setArguments(QStringList() << "test262.py" << "--command=" + QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmljs" << "--parallel" << "--with-test-expectations");
qDebug() << "Going to run" << process.program() << process.arguments() << "in" << process.workingDirectory();
@@ -60,6 +71,16 @@ void tst_EcmaScriptTests::runTests()
#endif
}
+void tst_EcmaScriptTests::runInterpreted()
+{
+ runTests(true);
+}
+
+void tst_EcmaScriptTests::runJitted()
+{
+ runTests(false);
+}
+
QTEST_GUILESS_MAIN(tst_EcmaScriptTests)
#include "tst_ecmascripttests.moc"