1/****************************************************************************
2**
3** Copyright (C) 2018 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the test suite of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:GPL-EXCEPT$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU
19** General Public License version 3 as published by the Free Software
20** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
21** included in the packaging of this file. Please review the following
22** information to ensure the GNU General Public License requirements will
23** be met: https://www.gnu.org/licenses/gpl-3.0.html.
24**
25** $QT_END_LICENSE$
26**
27****************************************************************************/
28
29#include <util.h>
30
31#include <QtTest/QtTest>
32#include <QtCore/qprocess.h>
33#include <QtCore/qtemporaryfile.h>
34#include <QtQml/qqml.h>
35#include <QtQml/qqmlapplicationengine.h>
36
37#include <private/qv4global_p.h>
38
39#ifdef Q_OS_WIN
40#include <windows.h>
41#endif
42
43class tst_QV4Assembler : public QQmlDataTest
44{
45 Q_OBJECT
46
47private slots:
48 void initTestCase() override;
49 void perfMapFile();
50 void functionTable();
51 void jitEnabled();
52};
53
54void tst_QV4Assembler::initTestCase()
55{
56 qputenv(varName: "QV4_JIT_CALL_THRESHOLD", value: "0");
57 QQmlDataTest::initTestCase();
58}
59
60void tst_QV4Assembler::perfMapFile()
61{
62#if !defined(Q_OS_LINUX) || defined(Q_OS_ANDROID)
63 QSKIP("perf map files are only generated on linux");
64#else
65 const QString qmljs = QLibraryInfo::location(QLibraryInfo::BinariesPath) + "/qmljs";
66 QProcess process;
67
68 QTemporaryFile infile;
69 QVERIFY(infile.open());
70 infile.write(data: "'use strict'; function foo() { return 42 }; foo();");
71 infile.close();
72
73 QProcessEnvironment environment = QProcessEnvironment::systemEnvironment();
74 environment.insert(name: "QV4_PROFILE_WRITE_PERF_MAP", value: "1");
75 environment.insert(name: "QV4_JIT_CALL_THRESHOLD", value: "0");
76
77 process.setProcessEnvironment(environment);
78 process.start(program: qmljs, arguments: QStringList({infile.fileName()}));
79 QVERIFY(process.waitForStarted());
80 const qint64 pid = process.processId();
81 QVERIFY(pid != 0);
82 QVERIFY(process.waitForFinished());
83 QCOMPARE(process.exitCode(), 0);
84
85 QFile file(QString::fromLatin1(str: "/tmp/perf-%1.map").arg(a: pid));
86 QVERIFY(file.exists());
87 QVERIFY(file.open(QIODevice::ReadOnly));
88 QList<QByteArray> functions;
89 while (!file.atEnd()) {
90 const QByteArray contents = file.readLine();
91 QVERIFY(contents.endsWith('\n'));
92 QList<QByteArray> fields = contents.split(sep: ' ');
93 QCOMPARE(fields.length(), 3);
94 bool ok = false;
95 const qulonglong address = fields[0].toULongLong(ok: &ok, base: 16);
96 QVERIFY(ok);
97 QVERIFY(address > 0);
98 const ulong size = fields[1].toULong(ok: &ok, base: 16);
99 QVERIFY(ok);
100 QVERIFY(size > 0);
101 functions.append(t: fields[2]);
102 }
103 QVERIFY(functions.contains("foo\n"));
104#endif
105}
106
107#ifdef Q_OS_WIN
108class Crash : public QObject
109{
110 Q_OBJECT
111public:
112 explicit Crash(QObject *parent = nullptr) : QObject(parent) { }
113 Q_INVOKABLE static void crash();
114};
115
116static bool crashHandlerHit = false;
117
118static LONG WINAPI crashHandler(EXCEPTION_POINTERS*)
119{
120 crashHandlerHit = true;
121 return EXCEPTION_CONTINUE_EXECUTION;
122}
123
124void Crash::crash()
125{
126 SetUnhandledExceptionFilter(crashHandler);
127 RaiseException(EXCEPTION_ACCESS_VIOLATION, 0, 0, nullptr);
128}
129#endif
130
131void tst_QV4Assembler::functionTable()
132{
133#ifndef Q_OS_WIN
134 QSKIP("Function tables only exist on windows.");
135#else
136 QQmlApplicationEngine engine;
137 qmlRegisterType<Crash>("Crash", 1, 0, "Crash");
138 engine.load(testFileUrl("crash.qml"));
139 QTRY_VERIFY(crashHandlerHit);
140#endif
141}
142
143void tst_QV4Assembler::jitEnabled()
144{
145#if defined(Q_OS_IOS) || defined(Q_OS_TVOS)
146 /* JIT should be disabled on iOS and tvOS. */
147 QVERIFY(!QT_CONFIG(qml_jit));
148#elif defined(Q_OS_WIN) && defined(Q_PROCESSOR_ARM)
149 /* JIT should be disabled Windows on ARM/ARM64 for now. */
150 QVERIFY(!QT_CONFIG(qml_jit));
151#elif defined(Q_OS_MACOS) && defined(Q_PROCESSOR_ARM)
152 /* JIT should be disabled on macOS on ARM/ARM64 for now. */
153 QVERIFY(!QT_CONFIG(qml_jit));
154#else
155 /* JIT should be enabled on all other architectures/OSes tested in CI. */
156 QVERIFY(QT_CONFIG(qml_jit));
157#endif
158}
159
160QTEST_MAIN(tst_QV4Assembler)
161
162#include "tst_qv4assembler.moc"
163
164

source code of qtdeclarative/tests/auto/qml/qv4assembler/tst_qv4assembler.cpp