Merge lp:~ricmm/kubuntu-packaging/qtdeclarative-opensource-src_532-implement-jit-cache into lp:~kubuntu-packagers/kubuntu-packaging/qtdeclarative-opensource-src_532
- qtdeclarative-opensource-src_532-implement-jit-cache
- Merge into qtdeclarative-opensource-s...
Proposed by
Ricardo Mendoza
Status: | Merged |
---|---|
Merged at revision: | 174 |
Proposed branch: | lp:~ricmm/kubuntu-packaging/qtdeclarative-opensource-src_532-implement-jit-cache |
Merge into: | lp:~kubuntu-packagers/kubuntu-packaging/qtdeclarative-opensource-src_532 |
Diff against target: |
1113 lines (+1093/-0) 3 files modified
debian/changelog (+9/-0) debian/patches/QML-Compilation-unit-caching-and-JIT-changes.patch (+1083/-0) debian/patches/series (+1/-0) |
To merge this branch: | bzr merge lp:~ricmm/kubuntu-packaging/qtdeclarative-opensource-src_532-implement-jit-cache |
Related bugs: |
Reviewer | Review Type | Date Requested | Status |
---|---|---|---|
PS Jenkins bot | continuous-integration | Needs Fixing | |
Timo Jyrinki | Approve | ||
Review via email: mp+248381@code.launchpad.net |
Commit message
Implement QV4 JIT cache, make it opt-in by default by means of the QV4_ENABLE_
Description of the change
To post a comment you must log in.
Revision history for this message
Timo Jyrinki (timo-jyrinki) wrote : | # |
Revision history for this message
Timo Jyrinki (timo-jyrinki) : | # |
review:
Approve
Revision history for this message
PS Jenkins bot (ps-jenkins) wrote : | # |
FAILED: Autolanding.
More details in the following jenkins job:
http://
Executed test runs:
FAILURE: http://
FAILURE: http://
review:
Needs Fixing
(continuous-integration)
Preview Diff
[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1 | === modified file 'debian/changelog' | |||
2 | --- debian/changelog 2014-12-08 10:58:09 +0000 | |||
3 | +++ debian/changelog 2015-02-04 10:51:00 +0000 | |||
4 | @@ -1,3 +1,12 @@ | |||
5 | 1 | qtdeclarative-opensource-src (5.3.2-3ubuntu3) UNRELEASED; urgency=medium | ||
6 | 2 | |||
7 | 3 | * debian/patches/QML-Compilation-unit-caching-and-JIT-changes.patch | ||
8 | 4 | - Implement QV4 JIT cache to reduce application startup speed by | ||
9 | 5 | removing unnecessary compiler/assembler runs. This can be enabled | ||
10 | 6 | by exporting QV4_ENABLE_JIT_CACHE=1. | ||
11 | 7 | |||
12 | 8 | -- Ricardo Mendoza <ricardo.mendoza@canonical.com> Tue, 03 Feb 2015 14:51:20 +0100 | ||
13 | 9 | |||
14 | 1 | qtdeclarative-opensource-src (5.3.2-3ubuntu2) vivid; urgency=medium | 10 | qtdeclarative-opensource-src (5.3.2-3ubuntu2) vivid; urgency=medium |
15 | 2 | 11 | ||
16 | 3 | * debian/patches/Avoid-race-condition-in-QQmlEngine-on-shutdown.patch | 12 | * debian/patches/Avoid-race-condition-in-QQmlEngine-on-shutdown.patch |
17 | 4 | 13 | ||
18 | === added file 'debian/patches/QML-Compilation-unit-caching-and-JIT-changes.patch' | |||
19 | --- debian/patches/QML-Compilation-unit-caching-and-JIT-changes.patch 1970-01-01 00:00:00 +0000 | |||
20 | +++ debian/patches/QML-Compilation-unit-caching-and-JIT-changes.patch 2015-02-04 10:51:00 +0000 | |||
21 | @@ -0,0 +1,1083 @@ | |||
22 | 1 | Index: qtdeclarative-opensource-src-5.3.2/src/3rdparty/masm/assembler/ARMv7Assembler.h | ||
23 | 2 | =================================================================== | ||
24 | 3 | --- qtdeclarative-opensource-src-5.3.2.orig/src/3rdparty/masm/assembler/ARMv7Assembler.h | ||
25 | 4 | +++ qtdeclarative-opensource-src-5.3.2/src/3rdparty/masm/assembler/ARMv7Assembler.h | ||
26 | 5 | @@ -445,6 +445,12 @@ public: | ||
27 | 6 | ConditionInvalid | ||
28 | 7 | } Condition; | ||
29 | 8 | |||
30 | 9 | + // Code inherited from the QMLC project | ||
31 | 10 | + void appendData(char *data, int len) | ||
32 | 11 | + { | ||
33 | 12 | + return m_formatter.appendData(data, len); | ||
34 | 13 | + } | ||
35 | 14 | + | ||
36 | 15 | #define JUMP_ENUM_WITH_SIZE(index, value) (((value) << 3) | (index)) | ||
37 | 16 | #define JUMP_ENUM_SIZE(jump) ((jump) >> 3) | ||
38 | 17 | enum JumpType { JumpFixed = JUMP_ENUM_WITH_SIZE(0, 0), | ||
39 | 18 | @@ -2782,6 +2788,7 @@ private: | ||
40 | 19 | AssemblerLabel label() const { return m_buffer.label(); } | ||
41 | 20 | bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); } | ||
42 | 21 | void* data() const { return m_buffer.data(); } | ||
43 | 22 | + void appendData(char *data, int len) { return m_buffer.appendData(data, len); } | ||
44 | 23 | |||
45 | 24 | unsigned debugOffset() { return m_buffer.debugOffset(); } | ||
46 | 25 | |||
47 | 26 | Index: qtdeclarative-opensource-src-5.3.2/src/3rdparty/masm/assembler/AbstractMacroAssembler.h | ||
48 | 27 | =================================================================== | ||
49 | 28 | --- qtdeclarative-opensource-src-5.3.2.orig/src/3rdparty/masm/assembler/AbstractMacroAssembler.h | ||
50 | 29 | +++ qtdeclarative-opensource-src-5.3.2/src/3rdparty/masm/assembler/AbstractMacroAssembler.h | ||
51 | 30 | @@ -486,6 +486,11 @@ public: | ||
52 | 31 | return Call(jump.m_label, Linkable); | ||
53 | 32 | } | ||
54 | 33 | |||
55 | 34 | + unsigned int getFlags(void) | ||
56 | 35 | + { | ||
57 | 36 | + return m_flags; | ||
58 | 37 | + } | ||
59 | 38 | + | ||
60 | 39 | AssemblerLabel m_label; | ||
61 | 40 | private: | ||
62 | 41 | Flags m_flags; | ||
63 | 42 | @@ -746,6 +751,12 @@ public: | ||
64 | 43 | { | ||
65 | 44 | AssemblerType::cacheFlush(code, size); | ||
66 | 45 | } | ||
67 | 46 | + | ||
68 | 47 | + void appendData(char *data, int len) | ||
69 | 48 | + { | ||
70 | 49 | + return m_assembler.appendData(data, len); | ||
71 | 50 | + } | ||
72 | 51 | + | ||
73 | 52 | protected: | ||
74 | 53 | AbstractMacroAssembler() | ||
75 | 54 | : m_randomSource(cryptographicallyRandomNumber()) | ||
76 | 55 | Index: qtdeclarative-opensource-src-5.3.2/src/3rdparty/masm/assembler/AssemblerBuffer.h | ||
77 | 56 | =================================================================== | ||
78 | 57 | --- qtdeclarative-opensource-src-5.3.2.orig/src/3rdparty/masm/assembler/AssemblerBuffer.h | ||
79 | 58 | +++ qtdeclarative-opensource-src-5.3.2/src/3rdparty/masm/assembler/AssemblerBuffer.h | ||
80 | 59 | @@ -86,6 +86,14 @@ namespace JSC { | ||
81 | 60 | grow(); | ||
82 | 61 | } | ||
83 | 62 | |||
84 | 63 | + void appendData(char *data, int len) | ||
85 | 64 | + { | ||
86 | 65 | + if (!isAvailable(len)) | ||
87 | 66 | + grow(len); | ||
88 | 67 | + memcpy(m_buffer + m_index, data, len); | ||
89 | 68 | + m_index += len; | ||
90 | 69 | + } | ||
91 | 70 | + | ||
92 | 71 | bool isAligned(int alignment) const | ||
93 | 72 | { | ||
94 | 73 | return !(m_index & (alignment - 1)); | ||
95 | 74 | Index: qtdeclarative-opensource-src-5.3.2/src/3rdparty/masm/assembler/LinkBuffer.h | ||
96 | 75 | =================================================================== | ||
97 | 76 | --- qtdeclarative-opensource-src-5.3.2.orig/src/3rdparty/masm/assembler/LinkBuffer.h | ||
98 | 77 | +++ qtdeclarative-opensource-src-5.3.2/src/3rdparty/masm/assembler/LinkBuffer.h | ||
99 | 78 | @@ -109,11 +109,13 @@ public: | ||
100 | 79 | |||
101 | 80 | // These methods are used to link or set values at code generation time. | ||
102 | 81 | |||
103 | 82 | - void link(Call call, FunctionPtr function) | ||
104 | 83 | + unsigned int link(Call call, FunctionPtr function) | ||
105 | 84 | { | ||
106 | 85 | ASSERT(call.isFlagSet(Call::Linkable)); | ||
107 | 86 | call.m_label = applyOffset(call.m_label); | ||
108 | 87 | MacroAssembler::linkCall(code(), call, function); | ||
109 | 88 | + | ||
110 | 89 | + return call.m_label.m_offset; | ||
111 | 90 | } | ||
112 | 91 | |||
113 | 92 | void link(Jump jump, CodeLocationLabel label) | ||
114 | 93 | Index: qtdeclarative-opensource-src-5.3.2/src/3rdparty/masm/assembler/X86Assembler.h | ||
115 | 94 | =================================================================== | ||
116 | 95 | --- qtdeclarative-opensource-src-5.3.2.orig/src/3rdparty/masm/assembler/X86Assembler.h | ||
117 | 96 | +++ qtdeclarative-opensource-src-5.3.2/src/3rdparty/masm/assembler/X86Assembler.h | ||
118 | 97 | @@ -101,6 +101,11 @@ public: | ||
119 | 98 | ConditionNC = ConditionAE, | ||
120 | 99 | } Condition; | ||
121 | 100 | |||
122 | 101 | + void appendData(char *data, int len) | ||
123 | 102 | + { | ||
124 | 103 | + return m_formatter.appendData(data, len); | ||
125 | 104 | + } | ||
126 | 105 | + | ||
127 | 106 | private: | ||
128 | 107 | typedef enum { | ||
129 | 108 | OP_ADD_EvGv = 0x01, | ||
130 | 109 | @@ -2380,6 +2385,7 @@ private: | ||
131 | 110 | AssemblerLabel label() const { return m_buffer.label(); } | ||
132 | 111 | bool isAligned(int alignment) const { return m_buffer.isAligned(alignment); } | ||
133 | 112 | void* data() const { return m_buffer.data(); } | ||
134 | 113 | + void appendData(char *data, int len) { return m_buffer.appendData(data, len); } | ||
135 | 114 | |||
136 | 115 | PassRefPtr<ExecutableMemoryHandle> executableCopy(JSGlobalData& globalData, void* ownerUID, JITCompilationEffort effort) | ||
137 | 116 | { | ||
138 | 117 | Index: qtdeclarative-opensource-src-5.3.2/src/qml/compiler/compiler.pri | ||
139 | 118 | =================================================================== | ||
140 | 119 | --- qtdeclarative-opensource-src-5.3.2.orig/src/qml/compiler/compiler.pri | ||
141 | 120 | +++ qtdeclarative-opensource-src-5.3.2/src/qml/compiler/compiler.pri | ||
142 | 121 | @@ -28,10 +28,10 @@ HEADERS += \ | ||
143 | 122 | $$PWD/qv4isel_moth_p.h \ | ||
144 | 123 | $$PWD/qv4instr_moth_p.h | ||
145 | 124 | |||
146 | 125 | - | ||
147 | 126 | SOURCES += \ | ||
148 | 127 | $$PWD/qqmltypecompiler.cpp \ | ||
149 | 128 | $$PWD/qv4instr_moth.cpp \ | ||
150 | 129 | $$PWD/qv4isel_moth.cpp | ||
151 | 130 | |||
152 | 131 | +DEFINES += V4_UNIT_CACHE | ||
153 | 132 | } | ||
154 | 133 | Index: qtdeclarative-opensource-src-5.3.2/src/qml/compiler/qqmlirbuilder.cpp | ||
155 | 134 | =================================================================== | ||
156 | 135 | --- qtdeclarative-opensource-src-5.3.2.orig/src/qml/compiler/qqmlirbuilder.cpp | ||
157 | 136 | +++ qtdeclarative-opensource-src-5.3.2/src/qml/compiler/qqmlirbuilder.cpp | ||
158 | 137 | @@ -1512,7 +1512,12 @@ bool IRBuilder::isStatementNodeScript(QQ | ||
159 | 138 | QV4::CompiledData::QmlUnit *QmlUnitGenerator::generate(Document &output) | ||
160 | 139 | { | ||
161 | 140 | QV4::CompiledData::CompilationUnit *compilationUnit = output.javaScriptCompilationUnit; | ||
162 | 141 | - QV4::CompiledData::Unit *jsUnit = compilationUnit->createUnitData(&output); | ||
163 | 142 | + QV4::CompiledData::Unit *jsUnit; | ||
164 | 143 | + if (!compilationUnit->data) | ||
165 | 144 | + jsUnit = compilationUnit->createUnitData(&output); | ||
166 | 145 | + else | ||
167 | 146 | + jsUnit = compilationUnit->data; | ||
168 | 147 | + | ||
169 | 148 | const uint unitSize = jsUnit->unitSize; | ||
170 | 149 | |||
171 | 150 | const int importSize = sizeof(QV4::CompiledData::Import) * output.imports.count(); | ||
172 | 151 | Index: qtdeclarative-opensource-src-5.3.2/src/qml/compiler/qqmltypecompiler.cpp | ||
173 | 152 | =================================================================== | ||
174 | 153 | --- qtdeclarative-opensource-src-5.3.2.orig/src/qml/compiler/qqmltypecompiler.cpp | ||
175 | 154 | +++ qtdeclarative-opensource-src-5.3.2/src/qml/compiler/qqmltypecompiler.cpp | ||
176 | 155 | @@ -226,6 +226,7 @@ bool QQmlTypeCompiler::compile() | ||
177 | 156 | QV4::ExecutionEngine *v4 = engine->v4engine(); | ||
178 | 157 | QScopedPointer<QV4::EvalInstructionSelection> isel(v4->iselFactory->create(engine, v4->executableAllocator, &document->jsModule, &document->jsGenerator)); | ||
179 | 158 | isel->setUseFastLookups(false); | ||
180 | 159 | + isel->setEngine(engine); | ||
181 | 160 | document->javaScriptCompilationUnit = isel->compile(/*generated unit data*/false); | ||
182 | 161 | } | ||
183 | 162 | |||
184 | 163 | @@ -435,6 +436,7 @@ QQmlPropertyCacheCreator::QQmlPropertyCa | ||
185 | 164 | , qmlObjects(*typeCompiler->qmlObjects()) | ||
186 | 165 | , imports(typeCompiler->imports()) | ||
187 | 166 | , resolvedTypes(typeCompiler->resolvedTypes()) | ||
188 | 167 | + , m_url(typeCompiler->url()) | ||
189 | 168 | { | ||
190 | 169 | } | ||
191 | 170 | |||
192 | 171 | Index: qtdeclarative-opensource-src-5.3.2/src/qml/compiler/qqmltypecompiler_p.h | ||
193 | 172 | =================================================================== | ||
194 | 173 | --- qtdeclarative-opensource-src-5.3.2.orig/src/qml/compiler/qqmltypecompiler_p.h | ||
195 | 174 | +++ qtdeclarative-opensource-src-5.3.2/src/qml/compiler/qqmltypecompiler_p.h | ||
196 | 175 | @@ -149,6 +149,7 @@ protected: | ||
197 | 176 | QHash<int, QQmlCompiledData::TypeReference*> *resolvedTypes; | ||
198 | 177 | QVector<QByteArray> vmeMetaObjects; | ||
199 | 178 | QVector<QQmlPropertyCache*> propertyCaches; | ||
200 | 179 | + QUrl m_url; | ||
201 | 180 | }; | ||
202 | 181 | |||
203 | 182 | // "Converts" signal expressions to full-fleged function declarations with | ||
204 | 183 | Index: qtdeclarative-opensource-src-5.3.2/src/qml/compiler/qv4compileddata_p.h | ||
205 | 184 | =================================================================== | ||
206 | 185 | --- qtdeclarative-opensource-src-5.3.2.orig/src/qml/compiler/qv4compileddata_p.h | ||
207 | 186 | +++ qtdeclarative-opensource-src-5.3.2/src/qml/compiler/qv4compileddata_p.h | ||
208 | 187 | @@ -607,6 +607,9 @@ struct Q_QML_PRIVATE_EXPORT CompilationU | ||
209 | 188 | QV4::InternalClass **runtimeClasses; | ||
210 | 189 | QVector<QV4::Function *> runtimeFunctions; | ||
211 | 190 | |||
212 | 191 | + QVector<int> lookupTable; | ||
213 | 192 | + bool isRestored; | ||
214 | 193 | + | ||
215 | 194 | QV4::Function *linkToEngine(QV4::ExecutionEngine *engine); | ||
216 | 195 | void unlink(); | ||
217 | 196 | |||
218 | 197 | Index: qtdeclarative-opensource-src-5.3.2/src/qml/compiler/qv4isel_moth_p.h | ||
219 | 198 | =================================================================== | ||
220 | 199 | --- qtdeclarative-opensource-src-5.3.2.orig/src/qml/compiler/qv4isel_moth_p.h | ||
221 | 200 | +++ qtdeclarative-opensource-src-5.3.2/src/qml/compiler/qv4isel_moth_p.h | ||
222 | 201 | @@ -72,6 +72,7 @@ public: | ||
223 | 202 | ~InstructionSelection(); | ||
224 | 203 | |||
225 | 204 | virtual void run(int functionIndex); | ||
226 | 205 | + virtual QV4::JIT::InstructionSelection* impl() { return NULL; };; | ||
227 | 206 | |||
228 | 207 | protected: | ||
229 | 208 | virtual QV4::CompiledData::CompilationUnit *backendCompileStep(); | ||
230 | 209 | Index: qtdeclarative-opensource-src-5.3.2/src/qml/compiler/qv4isel_p.cpp | ||
231 | 210 | =================================================================== | ||
232 | 211 | --- qtdeclarative-opensource-src-5.3.2.orig/src/qml/compiler/qv4isel_p.cpp | ||
233 | 212 | +++ qtdeclarative-opensource-src-5.3.2/src/qml/compiler/qv4isel_p.cpp | ||
234 | 213 | @@ -1,8 +1,14 @@ | ||
235 | 214 | -/**************************************************************************** | ||
236 | 215 | +/*************************************************************************** | ||
237 | 216 | ** | ||
238 | 217 | ** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies). | ||
239 | 218 | ** Contact: http://www.qt-project.org/legal | ||
240 | 219 | ** | ||
241 | 220 | +** Copyright (C) 2014 Nomovok Ltd. All rights reserved. | ||
242 | 221 | +** Contact: info@nomovok.com | ||
243 | 222 | +** | ||
244 | 223 | +** Copyright (C) 2014 Canonical Limited and/or its subsidiary(-ies). | ||
245 | 224 | +** Contact: ricardo.mendoza@canonical.com | ||
246 | 225 | +** | ||
247 | 226 | ** This file is part of the QtQml module of the Qt Toolkit. | ||
248 | 227 | ** | ||
249 | 228 | ** $QT_BEGIN_LICENSE:LGPL$ | ||
250 | 229 | @@ -49,6 +55,54 @@ | ||
251 | 230 | |||
252 | 231 | #include <QString> | ||
253 | 232 | |||
254 | 233 | +#ifndef V4_ENABLE_JIT | ||
255 | 234 | +#undef V4_UNIT_CACHE | ||
256 | 235 | +#endif | ||
257 | 236 | + | ||
258 | 237 | +#ifdef V4_UNIT_CACHE | ||
259 | 238 | +#include <private/qqmltypenamecache_p.h> | ||
260 | 239 | +#include <private/qqmlcompiler_p.h> | ||
261 | 240 | +#include <private/qqmltypeloader_p.h> | ||
262 | 241 | +#include <private/qv4compileddata_p.h> | ||
263 | 242 | +#include <private/qv4assembler_p.h> | ||
264 | 243 | +#include "../jit/qv4cachedlinkdata_p.h" | ||
265 | 244 | +#include "../jit/qv4assembler_p.h" | ||
266 | 245 | +#include <sys/stat.h> | ||
267 | 246 | +#include <QCryptographicHash> | ||
268 | 247 | +#include <QStandardPaths> | ||
269 | 248 | +#include <QDir> | ||
270 | 249 | +#include <QFile> | ||
271 | 250 | +#include <QDataStream> | ||
272 | 251 | +#include <QBuffer> | ||
273 | 252 | +#endif | ||
274 | 253 | + | ||
275 | 254 | +bool writeData(QDataStream& stream, const char* data, int len) | ||
276 | 255 | +{ | ||
277 | 256 | + if (stream.writeRawData(data, len) != len) | ||
278 | 257 | + return false; | ||
279 | 258 | + else | ||
280 | 259 | + return true; | ||
281 | 260 | +} | ||
282 | 261 | + | ||
283 | 262 | +bool writeDataWithLen(QDataStream& stream, const char* data, int len) | ||
284 | 263 | +{ | ||
285 | 264 | + quint32 l = len; | ||
286 | 265 | + if (!writeData(stream, (const char *)&l, sizeof(quint32))) | ||
287 | 266 | + return false; | ||
288 | 267 | + if (!writeData(stream, data, len)) | ||
289 | 268 | + return false; | ||
290 | 269 | + return true; | ||
291 | 270 | +} | ||
292 | 271 | + | ||
293 | 272 | +bool readData(char *data, int len, QDataStream &stream) | ||
294 | 273 | +{ | ||
295 | 274 | + if (stream.readRawData(data, len) != len) { | ||
296 | 275 | + return false; | ||
297 | 276 | + } else { | ||
298 | 277 | + return true; | ||
299 | 278 | + } | ||
300 | 279 | +} | ||
301 | 280 | + | ||
302 | 281 | namespace { | ||
303 | 282 | Q_GLOBAL_STATIC_WITH_ARGS(QTextStream, qout, (stderr, QIODevice::WriteOnly)); | ||
304 | 283 | #define qout *qout() | ||
305 | 284 | @@ -57,6 +111,14 @@ Q_GLOBAL_STATIC_WITH_ARGS(QTextStream, q | ||
306 | 285 | using namespace QV4; | ||
307 | 286 | using namespace QV4::IR; | ||
308 | 287 | |||
309 | 288 | +static bool do_cache = false; | ||
310 | 289 | + | ||
311 | 290 | +enum CacheState { | ||
312 | 291 | + UNTESTED = 0, | ||
313 | 292 | + VALID = 1, | ||
314 | 293 | + INVALID = 2 | ||
315 | 294 | +}; | ||
316 | 295 | + | ||
317 | 296 | EvalInstructionSelection::EvalInstructionSelection(QV4::ExecutableAllocator *execAllocator, Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator) | ||
318 | 297 | : useFastLookups(true) | ||
319 | 298 | , executableAllocator(execAllocator) | ||
320 | 299 | @@ -71,6 +133,9 @@ EvalInstructionSelection::EvalInstructio | ||
321 | 300 | Q_ASSERT(execAllocator); | ||
322 | 301 | #endif | ||
323 | 302 | Q_ASSERT(module); | ||
324 | 303 | + | ||
325 | 304 | + // Enable JIT cache only when explicitly requested and only cache files-on-disk (no qrc or inlines) | ||
326 | 305 | + do_cache = !qgetenv("QV4_ENABLE_JIT_CACHE").isEmpty() && irModule->fileName.startsWith(QStringLiteral("file://")); | ||
327 | 306 | } | ||
328 | 307 | |||
329 | 308 | EvalInstructionSelection::~EvalInstructionSelection() | ||
330 | 309 | @@ -79,17 +144,306 @@ EvalInstructionSelection::~EvalInstructi | ||
331 | 310 | EvalISelFactory::~EvalISelFactory() | ||
332 | 311 | {} | ||
333 | 312 | |||
334 | 313 | -QV4::CompiledData::CompilationUnit *EvalInstructionSelection::compile(bool generateUnitData) | ||
335 | 314 | +QV4::CompiledData::CompilationUnit *EvalInstructionSelection::runAll(bool generateUnitData) | ||
336 | 315 | { | ||
337 | 316 | - for (int i = 0; i < irModule->functions.size(); ++i) | ||
338 | 317 | - run(i); | ||
339 | 318 | + QV4::CompiledData::CompilationUnit *unit; | ||
340 | 319 | + | ||
341 | 320 | + for (int i = 0; i < irModule->functions.size(); ++i) { | ||
342 | 321 | + run(i); // Performs the actual compilation | ||
343 | 322 | + } | ||
344 | 323 | + | ||
345 | 324 | + unit = backendCompileStep(); | ||
346 | 325 | + | ||
347 | 326 | +#ifdef V4_UNIT_CACHE | ||
348 | 327 | + unit->isRestored = false; | ||
349 | 328 | +#endif | ||
350 | 329 | |||
351 | 330 | - QV4::CompiledData::CompilationUnit *unit = backendCompileStep(); | ||
352 | 331 | if (generateUnitData) | ||
353 | 332 | unit->data = jsGenerator->generateUnit(); | ||
354 | 333 | + | ||
355 | 334 | return unit; | ||
356 | 335 | } | ||
357 | 336 | |||
358 | 337 | +QV4::CompiledData::CompilationUnit *EvalInstructionSelection::compile(bool generateUnitData) | ||
359 | 338 | +{ | ||
360 | 339 | +#ifndef V4_UNIT_CACHE | ||
361 | 340 | + return runAll(generateUnitData); | ||
362 | 341 | +#else | ||
363 | 342 | + // Check if running JIT mode and if cache is enabled | ||
364 | 343 | + if (!do_cache || !this->impl()) | ||
365 | 344 | + return runAll(generateUnitData); | ||
366 | 345 | + | ||
367 | 346 | + QV4::CompiledData::CompilationUnit *unit; | ||
368 | 347 | + | ||
369 | 348 | + bool loaded = false; | ||
370 | 349 | + bool do_save = true; | ||
371 | 350 | + | ||
372 | 351 | + QByteArray path(qgetenv("HOME") + QByteArray("/.cache/QML/Apps/") + (qgetenv("APP_ID").isEmpty() ? QCoreApplication::applicationName().toLatin1() : qgetenv("APP_ID"))); | ||
373 | 352 | + | ||
374 | 353 | + if (m_engine && m_engine->qmlCacheValid == CacheState::UNTESTED) { | ||
375 | 354 | + bool valid = true; | ||
376 | 355 | + QDir cacheDir; | ||
377 | 356 | + cacheDir.setPath(QLatin1String(path)); | ||
378 | 357 | + QStringList files = cacheDir.entryList(); | ||
379 | 358 | + for (int i = 0; i < files.size(); i++) { | ||
380 | 359 | + if (valid == false) | ||
381 | 360 | + break; | ||
382 | 361 | + | ||
383 | 362 | + QFile cacheFile(path + QDir::separator() + files.at(i)); | ||
384 | 363 | + if (cacheFile.open(QIODevice::ReadOnly)) { | ||
385 | 364 | + QDataStream stream(&cacheFile); | ||
386 | 365 | + quint32 strLen = 0; | ||
387 | 366 | + readData((char *)&strLen, sizeof(quint32), stream); | ||
388 | 367 | + if (strLen == 0) { | ||
389 | 368 | + cacheFile.close(); | ||
390 | 369 | + continue; | ||
391 | 370 | + } | ||
392 | 371 | + | ||
393 | 372 | + char *tmpStr = (char *) malloc(strLen); | ||
394 | 373 | + readData((char *)tmpStr, strLen, stream); | ||
395 | 374 | + quint32 mtime = 0; | ||
396 | 375 | + readData((char *)&mtime, sizeof(quint32), stream); | ||
397 | 376 | + | ||
398 | 377 | + struct stat sb; | ||
399 | 378 | + stat(tmpStr, &sb); | ||
400 | 379 | + if (QFile::exists(QLatin1String(tmpStr))) { | ||
401 | 380 | + QByteArray time(ctime(&sb.st_mtime)); | ||
402 | 381 | + if (mtime != (quint32) sb.st_mtime) { | ||
403 | 382 | + if (m_engine) m_engine->qmlCacheValid = CacheState::INVALID; | ||
404 | 383 | + valid = false; | ||
405 | 384 | + } | ||
406 | 385 | + } else { | ||
407 | 386 | + // Compilation unit of unresolvable type (inline), remove | ||
408 | 387 | + cacheFile.remove(); | ||
409 | 388 | + } | ||
410 | 389 | + | ||
411 | 390 | + free(tmpStr); | ||
412 | 391 | + cacheFile.close(); | ||
413 | 392 | + } | ||
414 | 393 | + } | ||
415 | 394 | + if (valid) { | ||
416 | 395 | + m_engine->qmlCacheValid = CacheState::VALID; | ||
417 | 396 | + } else { | ||
418 | 397 | + for (int i = 0; i < files.size(); i++) | ||
419 | 398 | + cacheDir.remove(files.at(i)); | ||
420 | 399 | + } | ||
421 | 400 | + } | ||
422 | 401 | + | ||
423 | 402 | + // Search for cache blob by mtime/app_id/file hash | ||
424 | 403 | + struct stat sb; | ||
425 | 404 | + stat(irModule->fileName.toLatin1().remove(0, 7).constData(), &sb); | ||
426 | 405 | + QByteArray time(ctime(&sb.st_mtime)); | ||
427 | 406 | + QByteArray urlHash(QCryptographicHash::hash((irModule->fileName.toLatin1() + qgetenv("APP_ID") + time), QCryptographicHash::Md5).toHex()); | ||
428 | 407 | + QDir dir; | ||
429 | 408 | + dir.mkpath(QLatin1String(path)); | ||
430 | 409 | + QFile cacheFile(path + QDir::separator() + urlHash); | ||
431 | 410 | + | ||
432 | 411 | + QByteArray fileData; | ||
433 | 412 | + | ||
434 | 413 | + // TODO: Support inline compilation units | ||
435 | 414 | + if (cacheFile.exists() && cacheFile.open(QIODevice::ReadOnly)) { | ||
436 | 415 | + if (!irModule->fileName.isEmpty() && !irModule->fileName.contains(QStringLiteral("inline")) && m_engine) { | ||
437 | 416 | + loaded = true; | ||
438 | 417 | + fileData.append(cacheFile.readAll()); | ||
439 | 418 | + } else { | ||
440 | 419 | + loaded = false; | ||
441 | 420 | + cacheFile.close(); | ||
442 | 421 | + return runAll(generateUnitData); | ||
443 | 422 | + } | ||
444 | 423 | + } | ||
445 | 424 | + | ||
446 | 425 | + // Check file integrity | ||
447 | 426 | + QString fileHash(QLatin1String(QCryptographicHash::hash(fileData.left(fileData.size()-32), QCryptographicHash::Md5).toHex())); | ||
448 | 427 | + if (!fileHash.contains(QLatin1String(fileData.right(32)))) { | ||
449 | 428 | + cacheFile.close(); | ||
450 | 429 | + cacheFile.remove(); | ||
451 | 430 | + loaded = false; | ||
452 | 431 | + } | ||
453 | 432 | + | ||
454 | 433 | + // This code has been inspired and influenced by Nomovok's QMLC compiler available at | ||
455 | 434 | + // https://github.com/qmlc/qmlc. All original Copyrights are maintained for the | ||
456 | 435 | + // basic code snippets. | ||
457 | 436 | + | ||
458 | 437 | + if (loaded) { | ||
459 | 438 | + // Retrieve unit skeleton from isel implementation | ||
460 | 439 | + unit = backendCompileStep(); | ||
461 | 440 | + QV4::JIT::CompilationUnit *tmpUnit = (QV4::JIT::CompilationUnit *) unit; | ||
462 | 441 | + tmpUnit->codeRefs.resize(irModule->functions.size()); | ||
463 | 442 | + | ||
464 | 443 | + QDataStream stream(fileData); | ||
465 | 444 | + | ||
466 | 445 | + quint32 strLen = 0; | ||
467 | 446 | + readData((char *)&strLen, sizeof(quint32), stream); | ||
468 | 447 | + char *tmpStr = (char *) malloc(strLen); | ||
469 | 448 | + readData((char *)tmpStr, strLen, stream); | ||
470 | 449 | + quint32 mtime = 0; | ||
471 | 450 | + readData((char *)&mtime, sizeof(quint32), stream); | ||
472 | 451 | + | ||
473 | 452 | + unit->lookupTable.reserve(tmpUnit->codeRefs.size()); | ||
474 | 453 | + quint32 len; | ||
475 | 454 | + for (int i = 0; i < tmpUnit->codeRefs.size(); i++) { | ||
476 | 455 | + quint32 strLen; | ||
477 | 456 | + readData((char *)&strLen, sizeof(quint32), stream); | ||
478 | 457 | + | ||
479 | 458 | + char *fStr = (char *) malloc(strLen); | ||
480 | 459 | + readData(fStr, strLen, stream); | ||
481 | 460 | + | ||
482 | 461 | + QString hashString(QLatin1String(irModule->functions.at(i)->name->toLatin1().constData())); | ||
483 | 462 | + hashString.append(QString::number(irModule->functions.at(i)->line)); | ||
484 | 463 | + hashString.append(QString::number(irModule->functions.at(i)->column)); | ||
485 | 464 | + | ||
486 | 465 | + if (!hashString.contains(QLatin1String(fStr))) | ||
487 | 466 | + return runAll(generateUnitData); | ||
488 | 467 | + | ||
489 | 468 | + unit->lookupTable.append(i); | ||
490 | 469 | + | ||
491 | 470 | + len = 0; | ||
492 | 471 | + readData((char *)&len, sizeof(quint32), stream); | ||
493 | 472 | + | ||
494 | 473 | + // Temporary unlinked code buffer | ||
495 | 474 | + executableAllocator->allocate(len); | ||
496 | 475 | + char *data = (char *) malloc(len); | ||
497 | 476 | + readData(data, len, stream); | ||
498 | 477 | + | ||
499 | 478 | + quint32 linkCallCount = 0; | ||
500 | 479 | + readData((char *)&linkCallCount, sizeof(quint32), stream); | ||
501 | 480 | + | ||
502 | 481 | + QVector<QV4::JIT::CachedLinkData> linkCalls; | ||
503 | 482 | + linkCalls.resize(linkCallCount); | ||
504 | 483 | + readData((char *)linkCalls.data(), linkCallCount * sizeof(QV4::JIT::CachedLinkData), stream); | ||
505 | 484 | + | ||
506 | 485 | + quint32 constVectorLen = 0; | ||
507 | 486 | + readData((char *)&constVectorLen, sizeof(quint32), stream); | ||
508 | 487 | + | ||
509 | 488 | + QVector<QV4::Primitive > constantVector; | ||
510 | 489 | + if (constVectorLen > 0) { | ||
511 | 490 | + constantVector.resize(constVectorLen); | ||
512 | 491 | + readData((char *)constantVector.data(), constVectorLen * sizeof(QV4::Primitive), stream); | ||
513 | 492 | + } | ||
514 | 493 | + | ||
515 | 494 | + // Pre-allocate link buffer to append code | ||
516 | 495 | + QV4::ExecutableAllocator* executableAllocator = m_engine->v4engine()->executableAllocator; | ||
517 | 496 | + | ||
518 | 497 | + QV4::IR::Function nullFunction(0, 0, QLatin1String("")); | ||
519 | 498 | + | ||
520 | 499 | + QV4::JIT::Assembler* as = new QV4::JIT::Assembler(this->impl(), &nullFunction, executableAllocator, 6); | ||
521 | 500 | + | ||
522 | 501 | + QList<QV4::JIT::Assembler::CallToLink>& callsToLink = as->callsToLink(); | ||
523 | 502 | + for (int i = 0; i < linkCalls.size(); i++) { | ||
524 | 503 | + QV4::JIT::CachedLinkData& call = linkCalls[i]; | ||
525 | 504 | + void *functionPtr = CACHED_LINK_TABLE[call.index].addr; | ||
526 | 505 | + QV4::JIT::Assembler::CallToLink c; | ||
527 | 506 | + JSC::AssemblerLabel label(call.offset); | ||
528 | 507 | + c.call = QV4::JIT::Assembler::Call(label, QV4::JIT::Assembler::Call::Linkable); | ||
529 | 508 | + c.externalFunction = JSC::FunctionPtr((quint32(*)(void))functionPtr); | ||
530 | 509 | + c.functionName = CACHED_LINK_TABLE[call.index].name; | ||
531 | 510 | + callsToLink.append(c); | ||
532 | 511 | + } | ||
533 | 512 | + | ||
534 | 513 | + QV4::JIT::Assembler::ConstantTable& constTable = as->constantTable(); | ||
535 | 514 | + foreach (const QV4::Primitive &p, constantVector) | ||
536 | 515 | + constTable.add(p); | ||
537 | 516 | + | ||
538 | 517 | + as->appendData(data, len); | ||
539 | 518 | + | ||
540 | 519 | + int dummySize = -1; // Pass known value to trigger use of code buffer | ||
541 | 520 | + tmpUnit->codeRefs[i] = as->link(&dummySize); | ||
542 | 521 | + Q_ASSERT(dummySize == (int)codeRefLen); | ||
543 | 522 | + | ||
544 | 523 | + delete as; | ||
545 | 524 | + } | ||
546 | 525 | + | ||
547 | 526 | + quint32 size = 0; | ||
548 | 527 | + readData((char *)&size, sizeof(quint32), stream); | ||
549 | 528 | + | ||
550 | 529 | + void *dataPtr = malloc(size); | ||
551 | 530 | + QV4::CompiledData::Unit *finalUnit = reinterpret_cast<QV4::CompiledData::Unit*>(dataPtr); | ||
552 | 531 | + if (size > 0) | ||
553 | 532 | + readData((char *)dataPtr, size, stream); | ||
554 | 533 | + | ||
555 | 534 | + unit->data = nullptr; | ||
556 | 535 | + if (irModule->functions.size() > 0) | ||
557 | 536 | + unit->data = finalUnit; | ||
558 | 537 | + | ||
559 | 538 | + unit->isRestored = true; | ||
560 | 539 | + } else { | ||
561 | 540 | + // Not loading from cache, run all instructions | ||
562 | 541 | + unit = runAll(false); | ||
563 | 542 | + } | ||
564 | 543 | + | ||
565 | 544 | + if ((unit->data == nullptr) && (do_save || generateUnitData)) | ||
566 | 545 | + unit->data = jsGenerator->generateUnit(); | ||
567 | 546 | + | ||
568 | 547 | + // Save compilation unit | ||
569 | 548 | + QV4::JIT::CompilationUnit *jitUnit = (QV4::JIT::CompilationUnit *) unit; | ||
570 | 549 | + if (!loaded) { | ||
571 | 550 | + if (cacheFile.open(QIODevice::WriteOnly)) { | ||
572 | 551 | + // TODO: Support inline compilation units | ||
573 | 552 | + if (!irModule->fileName.isEmpty() && !irModule->fileName.contains(QLatin1String("inline")) && m_engine) { | ||
574 | 553 | + QBuffer fillBuff; | ||
575 | 554 | + fillBuff.open(QIODevice::WriteOnly); | ||
576 | 555 | + QDataStream stream(&fillBuff); | ||
577 | 556 | + | ||
578 | 557 | + quint32 fileNameSize = irModule->fileName.size(); | ||
579 | 558 | + writeData(stream, (const char *)&fileNameSize, sizeof(quint32)); | ||
580 | 559 | + writeData(stream, (const char *)irModule->fileName.toLatin1().remove(0, 7).constData(), irModule->fileName.size()); | ||
581 | 560 | + | ||
582 | 561 | + struct stat sb; | ||
583 | 562 | + stat(irModule->fileName.toLatin1().remove(0, 7).constData(), &sb); | ||
584 | 563 | + writeData(stream, (const char *)&sb.st_mtime, sizeof(quint32)); | ||
585 | 564 | + | ||
586 | 565 | + for (int i = 0; i < jitUnit->codeRefs.size(); i++) { | ||
587 | 566 | + const JSC::MacroAssemblerCodeRef &codeRef = jitUnit->codeRefs[i]; | ||
588 | 567 | + const QVector<QV4::Primitive> &constantValue = jitUnit->constantValues[i]; | ||
589 | 568 | + quint32 len = codeRef.size(); | ||
590 | 569 | + | ||
591 | 570 | + QString hashString(QLatin1String(irModule->functions.at(i)->name->toLatin1())); | ||
592 | 571 | + hashString.append(QString::number(irModule->functions.at(i)->line)); | ||
593 | 572 | + hashString.append(QString::number(irModule->functions.at(i)->column)); | ||
594 | 573 | + | ||
595 | 574 | + quint32 strLen = hashString.size(); | ||
596 | 575 | + strLen += 1; // /0 char | ||
597 | 576 | + writeData(stream, (const char *)&strLen, sizeof(quint32)); | ||
598 | 577 | + writeData(stream, (const char *)hashString.toLatin1().constData(), strLen); | ||
599 | 578 | + writeData(stream, (const char *)&len, sizeof(quint32)); | ||
600 | 579 | + writeData(stream, (const char *)(((unsigned long)codeRef.code().executableAddress())&~1), len); | ||
601 | 580 | + | ||
602 | 581 | + const QVector<QV4::JIT::CachedLinkData> &linkCalls = jitUnit->linkData[i]; | ||
603 | 582 | + quint32 linkCallCount = linkCalls.size(); | ||
604 | 583 | + | ||
605 | 584 | + writeData(stream, (const char *)&linkCallCount, sizeof(quint32)); | ||
606 | 585 | + if (linkCallCount > 0) | ||
607 | 586 | + writeData(stream, (const char *)linkCalls.data(), linkCalls.size() * sizeof (QV4::JIT::CachedLinkData)); | ||
608 | 587 | + | ||
609 | 588 | + quint32 constTableCount = constantValue.size(); | ||
610 | 589 | + writeData(stream, (const char *)&constTableCount, sizeof(quint32)); | ||
611 | 590 | + | ||
612 | 591 | + if (constTableCount > 0) | ||
613 | 592 | + writeData(stream, (const char*)constantValue.data(), sizeof(QV4::Primitive) * constantValue.size()); | ||
614 | 593 | + } | ||
615 | 594 | + | ||
616 | 595 | + QV4::CompiledData::Unit *retUnit = unit->data; | ||
617 | 596 | + quint32 size = retUnit->unitSize; | ||
618 | 597 | + | ||
619 | 598 | + if (size > 0) { | ||
620 | 599 | + writeData(stream, (const char*)&size, sizeof(quint32)); | ||
621 | 600 | + writeData(stream, (const char*)retUnit, size); | ||
622 | 601 | + } | ||
623 | 602 | + | ||
624 | 603 | + // Write MD5 hash of stored data for consistency check | ||
625 | 604 | + QByteArray fileHash(QCryptographicHash::hash(fillBuff.data(), QCryptographicHash::Md5).toHex()); | ||
626 | 605 | + fillBuff.write(fileHash); | ||
627 | 606 | + cacheFile.write(fillBuff.data()); | ||
628 | 607 | + } | ||
629 | 608 | + cacheFile.close(); | ||
630 | 609 | + } else { | ||
631 | 610 | + cacheFile.close(); | ||
632 | 611 | + } | ||
633 | 612 | + } | ||
634 | 613 | + return unit; | ||
635 | 614 | +#endif | ||
636 | 615 | +} | ||
637 | 616 | + | ||
638 | 617 | void IRDecoder::visitMove(IR::Move *s) | ||
639 | 618 | { | ||
640 | 619 | if (IR::Name *n = s->target->asName()) { | ||
641 | 620 | Index: qtdeclarative-opensource-src-5.3.2/src/qml/compiler/qv4isel_p.h | ||
642 | 621 | =================================================================== | ||
643 | 622 | --- qtdeclarative-opensource-src-5.3.2.orig/src/qml/compiler/qv4isel_p.h | ||
644 | 623 | +++ qtdeclarative-opensource-src-5.3.2/src/qml/compiler/qv4isel_p.h | ||
645 | 624 | @@ -56,6 +56,10 @@ class QQmlEnginePrivate; | ||
646 | 625 | |||
647 | 626 | namespace QV4 { | ||
648 | 627 | |||
649 | 628 | +namespace JIT { | ||
650 | 629 | + class InstructionSelection; | ||
651 | 630 | +} | ||
652 | 631 | + | ||
653 | 632 | class ExecutableAllocator; | ||
654 | 633 | struct Function; | ||
655 | 634 | |||
656 | 635 | @@ -65,6 +69,7 @@ public: | ||
657 | 636 | EvalInstructionSelection(QV4::ExecutableAllocator *execAllocator, IR::Module *module, QV4::Compiler::JSUnitGenerator *jsGenerator); | ||
658 | 637 | virtual ~EvalInstructionSelection() = 0; | ||
659 | 638 | |||
660 | 639 | + QV4::CompiledData::CompilationUnit *runAll(bool generateUnitData); | ||
661 | 640 | QV4::CompiledData::CompilationUnit *compile(bool generateUnitData = true); | ||
662 | 641 | |||
663 | 642 | void setUseFastLookups(bool b) { useFastLookups = b; } | ||
664 | 643 | @@ -78,9 +83,11 @@ public: | ||
665 | 644 | int registerRegExp(IR::RegExp *regexp) { return jsGenerator->registerRegExp(regexp); } | ||
666 | 645 | int registerJSClass(int count, IR::ExprList *args) { return jsGenerator->registerJSClass(count, args); } | ||
667 | 646 | QV4::Compiler::JSUnitGenerator *jsUnitGenerator() const { return jsGenerator; } | ||
668 | 647 | + void setEngine(QQmlEnginePrivate *qmlEngine) { m_engine = qmlEngine; } | ||
669 | 648 | |||
670 | 649 | protected: | ||
671 | 650 | virtual void run(int functionIndex) = 0; | ||
672 | 651 | + virtual QV4::JIT::InstructionSelection* impl() = 0; | ||
673 | 652 | virtual QV4::CompiledData::CompilationUnit *backendCompileStep() = 0; | ||
674 | 653 | |||
675 | 654 | bool useFastLookups; | ||
676 | 655 | @@ -88,6 +95,7 @@ protected: | ||
677 | 656 | QV4::Compiler::JSUnitGenerator *jsGenerator; | ||
678 | 657 | QScopedPointer<QV4::Compiler::JSUnitGenerator> ownJSGenerator; | ||
679 | 658 | IR::Module *irModule; | ||
680 | 659 | + QQmlEnginePrivate *m_engine; | ||
681 | 660 | }; | ||
682 | 661 | |||
683 | 662 | class Q_QML_PRIVATE_EXPORT EvalISelFactory | ||
684 | 663 | Index: qtdeclarative-opensource-src-5.3.2/src/qml/jit/qv4assembler.cpp | ||
685 | 664 | =================================================================== | ||
686 | 665 | --- qtdeclarative-opensource-src-5.3.2.orig/src/qml/jit/qv4assembler.cpp | ||
687 | 666 | +++ qtdeclarative-opensource-src-5.3.2/src/qml/jit/qv4assembler.cpp | ||
688 | 667 | @@ -77,7 +77,10 @@ void CompilationUnit::linkBackendToEngin | ||
689 | 668 | |||
690 | 669 | QV4::Function *runtimeFunction = new QV4::Function(engine, this, compiledFunction, | ||
691 | 670 | (ReturnedValue (*)(QV4::ExecutionContext *, const uchar *)) codeRefs[i].code().executableAddress()); | ||
692 | 671 | - runtimeFunctions[i] = runtimeFunction; | ||
693 | 672 | + if (isRestored) | ||
694 | 673 | + runtimeFunctions[lookupTable.at(i)] = runtimeFunction; | ||
695 | 674 | + else | ||
696 | 675 | + runtimeFunctions[i] = runtimeFunction; | ||
697 | 676 | } | ||
698 | 677 | } | ||
699 | 678 | |||
700 | 679 | Index: qtdeclarative-opensource-src-5.3.2/src/qml/jit/qv4assembler_p.h | ||
701 | 680 | =================================================================== | ||
702 | 681 | --- qtdeclarative-opensource-src-5.3.2.orig/src/qml/jit/qv4assembler_p.h | ||
703 | 682 | +++ qtdeclarative-opensource-src-5.3.2/src/qml/jit/qv4assembler_p.h | ||
704 | 683 | @@ -70,6 +70,16 @@ namespace JIT { | ||
705 | 684 | |||
706 | 685 | class InstructionSelection; | ||
707 | 686 | |||
708 | 687 | +struct CachedLinkData { | ||
709 | 688 | + quint32 index; // Link table index | ||
710 | 689 | + quint32 offset; // Offset inside the codeRef code | ||
711 | 690 | +}; | ||
712 | 691 | + | ||
713 | 692 | +struct LinkableCode { | ||
714 | 693 | + int len; | ||
715 | 694 | + void* code; | ||
716 | 695 | +}; | ||
717 | 696 | + | ||
718 | 697 | struct CompilationUnit : public QV4::CompiledData::CompilationUnit | ||
719 | 698 | { | ||
720 | 699 | virtual ~CompilationUnit(); | ||
721 | 700 | @@ -82,6 +92,8 @@ struct CompilationUnit : public QV4::Com | ||
722 | 701 | |||
723 | 702 | QVector<JSC::MacroAssemblerCodeRef> codeRefs; | ||
724 | 703 | QList<QVector<QV4::Primitive> > constantValues; | ||
725 | 704 | + QList<QVector<CachedLinkData>> linkData; | ||
726 | 705 | + QList<LinkableCode> linkableCode; | ||
727 | 706 | }; | ||
728 | 707 | |||
729 | 708 | struct RelativeCall { | ||
730 | 709 | @@ -1151,7 +1163,12 @@ public: | ||
731 | 710 | move(TrustedImm64(u.i), ReturnValueRegister); | ||
732 | 711 | move64ToDouble(ReturnValueRegister, target); | ||
733 | 712 | #else | ||
734 | 713 | - JSC::MacroAssembler::loadDouble(constantTable().loadValueAddress(c, ScratchRegister), target); | ||
735 | 714 | + QV4::Primitive vv = convertToValue(c); | ||
736 | 715 | + FPRegisterID scratchFp; | ||
737 | 716 | + scratchFp = target; | ||
738 | 717 | + move(TrustedImm32(vv.int_32), ReturnValueRegister); | ||
739 | 718 | + move(TrustedImm32(vv.tag), ScratchRegister); | ||
740 | 719 | + moveIntsToDouble(ReturnValueRegister, ScratchRegister, target, scratchFp); | ||
741 | 720 | #endif | ||
742 | 721 | return target; | ||
743 | 722 | } | ||
744 | 723 | @@ -1241,6 +1258,12 @@ public: | ||
745 | 724 | Label exceptionReturnLabel; | ||
746 | 725 | IR::BasicBlock * catchBlock; | ||
747 | 726 | QVector<Jump> exceptionPropagationJumps; | ||
748 | 727 | + | ||
749 | 728 | + LinkableCode tmpBuffer; | ||
750 | 729 | + | ||
751 | 730 | + LinkableCode& codeToLink() { return tmpBuffer; } | ||
752 | 731 | + QList<CallToLink>& callsToLink() { return _callsToLink; } | ||
753 | 732 | + | ||
754 | 733 | private: | ||
755 | 734 | const StackLayout _stackLayout; | ||
756 | 735 | ConstantTable _constTable; | ||
757 | 736 | Index: qtdeclarative-opensource-src-5.3.2/src/qml/jit/qv4cachedlinkdata_p.h | ||
758 | 737 | =================================================================== | ||
759 | 738 | --- /dev/null | ||
760 | 739 | +++ qtdeclarative-opensource-src-5.3.2/src/qml/jit/qv4cachedlinkdata_p.h | ||
761 | 740 | @@ -0,0 +1,188 @@ | ||
762 | 741 | +/*************************************************************************** | ||
763 | 742 | +** | ||
764 | 743 | +** Copyright (C) 2014 Nomovok Ltd. All rights reserved. | ||
765 | 744 | +** Contact: info@nomovok.com | ||
766 | 745 | +** | ||
767 | 746 | +** Copyright (C) 2014 Canonical Limited and/or its subsidiary(-ies). | ||
768 | 747 | +** Contact: ricardo.mendoza@canonical.com | ||
769 | 748 | +** | ||
770 | 749 | +** GNU Lesser General Public License Usage | ||
771 | 750 | +** Alternatively, this file may be used under the terms of the GNU Lesser | ||
772 | 751 | +** General Public License version 2.1 as published by the Free Software | ||
773 | 752 | +** Foundation and appearing in the file LICENSE.LGPL included in the | ||
774 | 753 | +** packaging of this file. Please review the following information to | ||
775 | 754 | +** ensure the GNU Lesser General Public License version 2.1 requirements | ||
776 | 755 | +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. | ||
777 | 756 | +** | ||
778 | 757 | +** In addition, as a special exception, Digia gives you certain additional | ||
779 | 758 | +** rights. These rights are described in the Digia Qt LGPL Exception | ||
780 | 759 | +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. | ||
781 | 760 | +** | ||
782 | 761 | +** GNU General Public License Usage | ||
783 | 762 | +** Alternatively, this file may be used under the terms of the GNU | ||
784 | 763 | +** General Public License version 3.0 as published by the Free Software | ||
785 | 764 | +** Foundation and appearing in the file LICENSE.GPL included in the | ||
786 | 765 | +** packaging of this file. Please review the following information to | ||
787 | 766 | +** ensure the GNU General Public License version 3.0 requirements will be | ||
788 | 767 | +** met: http://www.gnu.org/copyleft/gpl.html. | ||
789 | 768 | +** | ||
790 | 769 | +****************************************************************************/ | ||
791 | 770 | + | ||
792 | 771 | +#ifndef QV4CACHEDLINKDATA_P_H | ||
793 | 772 | +#define QV4CACHEDLINKDATA_P_H | ||
794 | 773 | + | ||
795 | 774 | +#include <qv4jsir_p.h> | ||
796 | 775 | +#include <qv4isel_masm_p.h> | ||
797 | 776 | +#include <qv4runtime_p.h> | ||
798 | 777 | + | ||
799 | 778 | +QT_BEGIN_NAMESPACE | ||
800 | 779 | + | ||
801 | 780 | +struct CachedLinkEntry { | ||
802 | 781 | + const char *name; | ||
803 | 782 | + void *addr; | ||
804 | 783 | +}; | ||
805 | 784 | + | ||
806 | 785 | +#define CACHED_LINK_TABLE_ADD_NS(x) QV4::Runtime::x | ||
807 | 786 | +#define CACHED_LINK_TABLE_STR(x) "Runtime::" #x | ||
808 | 787 | +#define CACHED_LINK_TABLE_ENTRY_RUNTIME(x) { (const char *)CACHED_LINK_TABLE_STR(x), (void *)CACHED_LINK_TABLE_ADD_NS(x) } | ||
809 | 788 | + | ||
810 | 789 | +// table to link objects | ||
811 | 790 | +// this table can be used to resolve functions, it is id -> object mapping to maximize performance in linking phase | ||
812 | 791 | +// when adding new calls, add to end of the list to maintain compatibility | ||
813 | 792 | +const CachedLinkEntry CACHED_LINK_TABLE[] = { | ||
814 | 793 | + // call | ||
815 | 794 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(callGlobalLookup), | ||
816 | 795 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(callActivationProperty), | ||
817 | 796 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(callProperty), | ||
818 | 797 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(callPropertyLookup), | ||
819 | 798 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(callElement), | ||
820 | 799 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(callValue), | ||
821 | 800 | + | ||
822 | 801 | + // construct | ||
823 | 802 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(constructGlobalLookup), | ||
824 | 803 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(constructActivationProperty), | ||
825 | 804 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(constructProperty), | ||
826 | 805 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(constructPropertyLookup), | ||
827 | 806 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(constructValue), | ||
828 | 807 | + | ||
829 | 808 | + // set & get | ||
830 | 809 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(setActivationProperty), | ||
831 | 810 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(setProperty), | ||
832 | 811 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(setElement), | ||
833 | 812 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(getProperty), | ||
834 | 813 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(getActivationProperty), | ||
835 | 814 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(getElement), | ||
836 | 815 | + | ||
837 | 816 | + // typeof | ||
838 | 817 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(typeofValue), | ||
839 | 818 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(typeofName), | ||
840 | 819 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(typeofMember), | ||
841 | 820 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(typeofElement), | ||
842 | 821 | + | ||
843 | 822 | + // delete | ||
844 | 823 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(deleteElement), | ||
845 | 824 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(deleteMember), | ||
846 | 825 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(deleteName), | ||
847 | 826 | + | ||
848 | 827 | + // exceptions & scopes | ||
849 | 828 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(throwException), | ||
850 | 829 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(unwindException), | ||
851 | 830 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(pushWithScope), | ||
852 | 831 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(pushCatchScope), | ||
853 | 832 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(popScope), | ||
854 | 833 | + | ||
855 | 834 | + // closures | ||
856 | 835 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(closure), | ||
857 | 836 | + | ||
858 | 837 | + // function header | ||
859 | 838 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(declareVar), | ||
860 | 839 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(setupArgumentsObject), | ||
861 | 840 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(convertThisToObject), | ||
862 | 841 | + | ||
863 | 842 | + // literals | ||
864 | 843 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(arrayLiteral), | ||
865 | 844 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(objectLiteral), | ||
866 | 845 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(regexpLiteral), | ||
867 | 846 | + | ||
868 | 847 | + // foreach | ||
869 | 848 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(foreachIterator), | ||
870 | 849 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(foreachNextPropertyName), | ||
871 | 850 | + | ||
872 | 851 | + // unary operators | ||
873 | 852 | + //typedef ReturnedValue (*UnaryOperation)(const ValueRef); | ||
874 | 853 | + {"NOOP", (void *)qt_noop}, | ||
875 | 854 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(uPlus), | ||
876 | 855 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(uMinus), | ||
877 | 856 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(uNot), | ||
878 | 857 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(complement), | ||
879 | 858 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(increment), | ||
880 | 859 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(decrement), | ||
881 | 860 | + | ||
882 | 861 | + // binary operators | ||
883 | 862 | + //typedef ReturnedValue (*BinaryOperation)(const ValueRef left, const ValueRef right); | ||
884 | 863 | + {"NOOP", (void *)qt_noop}, | ||
885 | 864 | + //typedef ReturnedValue (*BinaryOperationContext)(ExecutionContext *ctx, const ValueRef left, const ValueRef right); | ||
886 | 865 | + {"NOOP", (void *)qt_noop}, | ||
887 | 866 | + | ||
888 | 867 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(instanceof), | ||
889 | 868 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(in), | ||
890 | 869 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(add), | ||
891 | 870 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(addString), | ||
892 | 871 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(bitOr), | ||
893 | 872 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(bitXor), | ||
894 | 873 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(bitAnd), | ||
895 | 874 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(sub), | ||
896 | 875 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(mul), | ||
897 | 876 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(div), | ||
898 | 877 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(mod), | ||
899 | 878 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(shl), | ||
900 | 879 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(shr), | ||
901 | 880 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(ushr), | ||
902 | 881 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(greaterThan), | ||
903 | 882 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(lessThan), | ||
904 | 883 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(greaterEqual), | ||
905 | 884 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(lessEqual), | ||
906 | 885 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(equal), | ||
907 | 886 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(notEqual), | ||
908 | 887 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(strictEqual), | ||
909 | 888 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(strictNotEqual), | ||
910 | 889 | + | ||
911 | 890 | + // comparisons | ||
912 | 891 | + //typedef Bool (*CompareOperation)(const ValueRef left, const ValueRef right);} | ||
913 | 892 | + {"NOOP", (void *)qt_noop}, | ||
914 | 893 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(compareGreaterThan), | ||
915 | 894 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(compareLessThan), | ||
916 | 895 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(compareGreaterEqual), | ||
917 | 896 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(compareLessEqual), | ||
918 | 897 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(compareEqual), | ||
919 | 898 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(compareNotEqual), | ||
920 | 899 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(compareStrictEqual), | ||
921 | 900 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(compareStrictNotEqual), | ||
922 | 901 | + | ||
923 | 902 | + //typedef Bool (*CompareOperationContext)(ExecutionContext *ctx, const ValueRef left, const ValueRef right); | ||
924 | 903 | + {"NOOP", (void *)qt_noop}, | ||
925 | 904 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(compareInstanceof), | ||
926 | 905 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(compareIn), | ||
927 | 906 | + | ||
928 | 907 | + // conversions | ||
929 | 908 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(toBoolean), | ||
930 | 909 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(toDouble), | ||
931 | 910 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(toInt), | ||
932 | 911 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(doubleToInt), | ||
933 | 912 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(toUInt), | ||
934 | 913 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(doubleToUInt), | ||
935 | 914 | + | ||
936 | 915 | + // qml | ||
937 | 916 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(getQmlIdArray), | ||
938 | 917 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(getQmlImportedScripts), | ||
939 | 918 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(getQmlContextObject), | ||
940 | 919 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(getQmlScopeObject), | ||
941 | 920 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(getQmlSingleton), | ||
942 | 921 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(getQmlAttachedProperty), | ||
943 | 922 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(getQmlQObjectProperty), | ||
944 | 923 | + CACHED_LINK_TABLE_ENTRY_RUNTIME(setQmlQObjectProperty) | ||
945 | 924 | +}; | ||
946 | 925 | + | ||
947 | 926 | +QT_END_NAMESPACE | ||
948 | 927 | + | ||
949 | 928 | +#endif | ||
950 | 929 | Index: qtdeclarative-opensource-src-5.3.2/src/qml/jit/qv4isel_masm.cpp | ||
951 | 930 | =================================================================== | ||
952 | 931 | --- qtdeclarative-opensource-src-5.3.2.orig/src/qml/jit/qv4isel_masm.cpp | ||
953 | 932 | +++ qtdeclarative-opensource-src-5.3.2/src/qml/jit/qv4isel_masm.cpp | ||
954 | 933 | @@ -51,6 +51,7 @@ | ||
955 | 934 | #include "qv4assembler_p.h" | ||
956 | 935 | #include "qv4unop_p.h" | ||
957 | 936 | #include "qv4binop_p.h" | ||
958 | 937 | +#include "qv4cachedlinkdata_p.h" | ||
959 | 938 | |||
960 | 939 | #include <QtCore/QBuffer> | ||
961 | 940 | |||
962 | 941 | @@ -147,9 +148,13 @@ JSC::MacroAssemblerCodeRef Assembler::li | ||
963 | 942 | JSC::LinkBuffer linkBuffer(dummy, this, 0); | ||
964 | 943 | |||
965 | 944 | QHash<void*, const char*> functions; | ||
966 | 945 | + int i = 0; | ||
967 | 946 | foreach (CallToLink ctl, _callsToLink) { | ||
968 | 947 | - linkBuffer.link(ctl.call, ctl.externalFunction); | ||
969 | 948 | + unsigned int offset = linkBuffer.link(ctl.call, ctl.externalFunction); | ||
970 | 949 | + ctl.call.m_label.m_offset = offset; | ||
971 | 950 | functions[linkBuffer.locationOf(ctl.label).dataLocation()] = ctl.functionName; | ||
972 | 951 | + _callsToLink.replace(i, ctl); | ||
973 | 952 | + i++; | ||
974 | 953 | } | ||
975 | 954 | |||
976 | 955 | foreach (const DataLabelPatch &p, _dataLabelPatches) | ||
977 | 956 | @@ -367,6 +372,25 @@ void InstructionSelection::run(int funct | ||
978 | 957 | JSC::MacroAssemblerCodeRef codeRef =_as->link(&dummySize); | ||
979 | 958 | compilationUnit->codeRefs[functionIndex] = codeRef; | ||
980 | 959 | |||
981 | 960 | + QVector<CachedLinkData> calls; | ||
982 | 961 | + QList<Assembler::CallToLink>& callsToLink = _as->callsToLink(); | ||
983 | 962 | + for (int i = 0; i < callsToLink.size(); i++) { | ||
984 | 963 | + Assembler::CallToLink& ctl = callsToLink[i]; | ||
985 | 964 | + int index = -1; | ||
986 | 965 | + for (uint i = 0; i < sizeof(CACHED_LINK_TABLE) / sizeof (CachedLinkEntry); i++) { | ||
987 | 966 | + if (CACHED_LINK_TABLE[i].addr == ctl.externalFunction.value()) { | ||
988 | 967 | + index = i; | ||
989 | 968 | + break; | ||
990 | 969 | + } | ||
991 | 970 | + } | ||
992 | 971 | + CachedLinkData link; | ||
993 | 972 | + link.index = index; | ||
994 | 973 | + link.offset = ctl.call.m_label.m_offset; | ||
995 | 974 | + calls.append(link); | ||
996 | 975 | + } | ||
997 | 976 | + compilationUnit->linkData.insert(functionIndex, calls); // link data; | ||
998 | 977 | + compilationUnit->linkableCode.insert(functionIndex, _as->codeToLink()); // code to link | ||
999 | 978 | + | ||
1000 | 979 | qSwap(_function, function); | ||
1001 | 980 | delete _as; | ||
1002 | 981 | _as = oldAssembler; | ||
1003 | 982 | @@ -1828,5 +1852,4 @@ void InstructionSelection::visitCJumpEqu | ||
1004 | 983 | _block, trueBlock, falseBlock); | ||
1005 | 984 | } | ||
1006 | 985 | |||
1007 | 986 | - | ||
1008 | 987 | #endif // ENABLE(ASSEMBLER) | ||
1009 | 988 | Index: qtdeclarative-opensource-src-5.3.2/src/qml/jit/qv4isel_masm_p.h | ||
1010 | 989 | =================================================================== | ||
1011 | 990 | --- qtdeclarative-opensource-src-5.3.2.orig/src/qml/jit/qv4isel_masm_p.h | ||
1012 | 991 | +++ qtdeclarative-opensource-src-5.3.2/src/qml/jit/qv4isel_masm_p.h | ||
1013 | 992 | @@ -73,6 +73,8 @@ public: | ||
1014 | 993 | virtual void run(int functionIndex); | ||
1015 | 994 | |||
1016 | 995 | const void *addConstantTable(QVector<QV4::Primitive> *values); | ||
1017 | 996 | + | ||
1018 | 997 | + virtual InstructionSelection* impl() { return this; }; | ||
1019 | 998 | protected: | ||
1020 | 999 | virtual QV4::CompiledData::CompilationUnit *backendCompileStep(); | ||
1021 | 1000 | |||
1022 | 1001 | Index: qtdeclarative-opensource-src-5.3.2/src/qml/jsruntime/qv4functionobject.cpp | ||
1023 | 1002 | =================================================================== | ||
1024 | 1003 | --- qtdeclarative-opensource-src-5.3.2.orig/src/qml/jsruntime/qv4functionobject.cpp | ||
1025 | 1004 | +++ qtdeclarative-opensource-src-5.3.2/src/qml/jsruntime/qv4functionobject.cpp | ||
1026 | 1005 | @@ -234,6 +234,7 @@ ReturnedValue FunctionCtor::construct(Ma | ||
1027 | 1006 | |||
1028 | 1007 | QV4::Compiler::JSUnitGenerator jsGenerator(&module); | ||
1029 | 1008 | QScopedPointer<EvalInstructionSelection> isel(v4->iselFactory->create(QQmlEnginePrivate::get(v4), v4->executableAllocator, &module, &jsGenerator)); | ||
1030 | 1009 | + isel->setEngine(QQmlEnginePrivate::get(v4)); | ||
1031 | 1010 | QV4::CompiledData::CompilationUnit *compilationUnit = isel->compile(); | ||
1032 | 1011 | QV4::Function *vmf = compilationUnit->linkToEngine(v4); | ||
1033 | 1012 | |||
1034 | 1013 | Index: qtdeclarative-opensource-src-5.3.2/src/qml/jsruntime/qv4qobjectwrapper.cpp | ||
1035 | 1014 | =================================================================== | ||
1036 | 1015 | --- qtdeclarative-opensource-src-5.3.2.orig/src/qml/jsruntime/qv4qobjectwrapper.cpp | ||
1037 | 1016 | +++ qtdeclarative-opensource-src-5.3.2/src/qml/jsruntime/qv4qobjectwrapper.cpp | ||
1038 | 1017 | @@ -628,6 +628,7 @@ ReturnedValue QObjectWrapper::getPropert | ||
1039 | 1018 | QQmlPropertyCache *cache = ddata->propertyCache; | ||
1040 | 1019 | Q_ASSERT(cache); | ||
1041 | 1020 | QQmlPropertyData *property = cache->property(propertyIndex); | ||
1042 | 1021 | + | ||
1043 | 1022 | Q_ASSERT(property); // We resolved this property earlier, so it better exist! | ||
1044 | 1023 | return getProperty(object, ctx, property, captureRequired); | ||
1045 | 1024 | } | ||
1046 | 1025 | Index: qtdeclarative-opensource-src-5.3.2/src/qml/jsruntime/qv4script.cpp | ||
1047 | 1026 | =================================================================== | ||
1048 | 1027 | --- qtdeclarative-opensource-src-5.3.2.orig/src/qml/jsruntime/qv4script.cpp | ||
1049 | 1028 | +++ qtdeclarative-opensource-src-5.3.2/src/qml/jsruntime/qv4script.cpp | ||
1050 | 1029 | @@ -272,6 +272,7 @@ void Script::parse() | ||
1051 | 1030 | QScopedPointer<EvalInstructionSelection> isel(v4->iselFactory->create(QQmlEnginePrivate::get(v4), v4->executableAllocator, &module, &jsGenerator)); | ||
1052 | 1031 | if (inheritContext) | ||
1053 | 1032 | isel->setUseFastLookups(false); | ||
1054 | 1033 | + isel->setEngine(QQmlEnginePrivate::get(v4)); | ||
1055 | 1034 | QV4::CompiledData::CompilationUnit *compilationUnit = isel->compile(); | ||
1056 | 1035 | vmFunction = compilationUnit->linkToEngine(v4); | ||
1057 | 1036 | ScopedValue holder(valueScope, new (v4->memoryManager) CompilationUnitHolder(v4, compilationUnit)); | ||
1058 | 1037 | @@ -394,6 +395,7 @@ QV4::CompiledData::CompilationUnit *Scri | ||
1059 | 1038 | |||
1060 | 1039 | QScopedPointer<EvalInstructionSelection> isel(engine->iselFactory->create(QQmlEnginePrivate::get(engine), engine->executableAllocator, module, unitGenerator)); | ||
1061 | 1040 | isel->setUseFastLookups(false); | ||
1062 | 1041 | + isel->setEngine(QQmlEnginePrivate::get(engine)); | ||
1063 | 1042 | return isel->compile(/*generate unit data*/false); | ||
1064 | 1043 | } | ||
1065 | 1044 | |||
1066 | 1045 | Index: qtdeclarative-opensource-src-5.3.2/src/qml/qml/qqmlengine.cpp | ||
1067 | 1046 | =================================================================== | ||
1068 | 1047 | --- qtdeclarative-opensource-src-5.3.2.orig/src/qml/qml/qqmlengine.cpp | ||
1069 | 1048 | +++ qtdeclarative-opensource-src-5.3.2/src/qml/qml/qqmlengine.cpp | ||
1070 | 1049 | @@ -561,7 +561,8 @@ QQmlEnginePrivate::QQmlEnginePrivate(QQm | ||
1071 | 1050 | activeObjectCreator(0), | ||
1072 | 1051 | networkAccessManager(0), networkAccessManagerFactory(0), urlInterceptor(0), | ||
1073 | 1052 | scarceResourcesRefCount(0), typeLoader(e), importDatabase(e), uniqueId(1), | ||
1074 | 1053 | - incubatorCount(0), incubationController(0), mutex(QMutex::Recursive) | ||
1075 | 1054 | + incubatorCount(0), incubationController(0), mutex(QMutex::Recursive), | ||
1076 | 1055 | + qmlCacheValid(0) | ||
1077 | 1056 | { | ||
1078 | 1057 | useNewCompiler = true; | ||
1079 | 1058 | } | ||
1080 | 1059 | Index: qtdeclarative-opensource-src-5.3.2/src/qml/qml/qqmlengine_p.h | ||
1081 | 1060 | =================================================================== | ||
1082 | 1061 | --- qtdeclarative-opensource-src-5.3.2.orig/src/qml/qml/qqmlengine_p.h | ||
1083 | 1062 | +++ qtdeclarative-opensource-src-5.3.2/src/qml/qml/qqmlengine_p.h | ||
1084 | 1063 | @@ -270,6 +270,8 @@ public: | ||
1085 | 1064 | |||
1086 | 1065 | mutable QMutex mutex; | ||
1087 | 1066 | |||
1088 | 1067 | + int qmlCacheValid; | ||
1089 | 1068 | + | ||
1090 | 1069 | private: | ||
1091 | 1070 | // Locker locks the QQmlEnginePrivate data structures for read and write, if necessary. | ||
1092 | 1071 | // Currently, locking is only necessary if the threaded loader is running concurrently. If it is | ||
1093 | 1072 | Index: qtdeclarative-opensource-src-5.3.2/src/qml/qml/qqmljavascriptexpression.cpp | ||
1094 | 1073 | =================================================================== | ||
1095 | 1074 | --- qtdeclarative-opensource-src-5.3.2.orig/src/qml/qml/qqmljavascriptexpression.cpp | ||
1096 | 1075 | +++ qtdeclarative-opensource-src-5.3.2/src/qml/qml/qqmljavascriptexpression.cpp | ||
1097 | 1076 | @@ -335,6 +335,7 @@ QV4::ReturnedValue QQmlJavaScriptExpress | ||
1098 | 1077 | |||
1099 | 1078 | QV4::ScopedObject qmlScopeObject(scope, QV4::QmlContextWrapper::qmlScope(ep->v8engine(), ctxt, qmlScope)); | ||
1100 | 1079 | QV4::Script script(v4, qmlScopeObject, code, filename, line); | ||
1101 | 1080 | + | ||
1102 | 1081 | QV4::ScopedValue result(scope); | ||
1103 | 1082 | script.parse(); | ||
1104 | 1083 | if (!v4->hasException) | ||
1105 | 0 | 1084 | ||
1106 | === modified file 'debian/patches/series' | |||
1107 | --- debian/patches/series 2014-12-08 10:58:09 +0000 | |||
1108 | +++ debian/patches/series 2015-02-04 10:51:00 +0000 | |||
1109 | @@ -6,3 +6,4 @@ | |||
1110 | 6 | Support-RFC2822Date-date-format-similar-to-V8.patch | 6 | Support-RFC2822Date-date-format-similar-to-V8.patch |
1111 | 7 | Avoid-race-condition-in-QQmlEngine-on-shutdown.patch | 7 | Avoid-race-condition-in-QQmlEngine-on-shutdown.patch |
1112 | 8 | Fix-crashes-when-calling-Array.sort-with-imperfect-s.patch | 8 | Fix-crashes-when-calling-Array.sort-with-imperfect-s.patch |
1113 | 9 | QML-Compilation-unit-caching-and-JIT-changes.patch |
Published to archives after testing.