Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qv4executablecompilationunit.cpp
Go to the documentation of this file.
1// Copyright (C) 2019 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3
4#include "qml/qqmlprivate.h"
5#include "qv4engine_p.h"
7
8#include <private/qv4engine_p.h>
9#include <private/qv4regexp_p.h>
10#include <private/qv4lookup_p.h>
11#include <private/qv4qmlcontext_p.h>
12#include <private/qv4identifiertable_p.h>
13#include <private/qv4objectproto_p.h>
14#include <private/qqmlengine_p.h>
15#include <private/qv4qobjectwrapper_p.h>
16#include <private/qqmlvaluetypewrapper_p.h>
17#include <private/qqmlscriptdata_p.h>
18#include <private/qv4module_p.h>
19#include <private/qv4compilationunitmapper_p.h>
20#include <private/qqmltypewrapper_p.h>
21#include <private/qv4resolvedtypereference_p.h>
22#include <private/qv4objectiterator_p.h>
23
24#include <QtQml/qqmlpropertymap.h>
25
26#include <QtCore/qfileinfo.h>
27#include <QtCore/qcryptographichash.h>
28
30
31namespace QV4 {
32
34
38{
40}
41
43{
44 if (engine)
45 clear();
46}
47
48static QString toString(QV4::ReturnedValue v)
49{
50 Value val = Value::fromReturnedValue(v);
51 QString result;
52 if (val.isInt32())
53 result = QLatin1String("int ");
54 else if (val.isDouble())
55 result = QLatin1String("double ");
56 if (val.isEmpty())
57 result += QLatin1String("empty");
58 else
59 result += val.toQStringNoThrow();
60 return result;
61}
62
63static void dumpConstantTable(const StaticValue *constants, uint count)
64{
65 QDebug d = qDebug();
66 d.nospace() << Qt::right;
67 for (uint i = 0; i < count; ++i) {
68 d << qSetFieldWidth(8) << i << qSetFieldWidth(0) << ": "
69 << toString(constants[i].asReturnedValue()).toUtf8().constData() << "\n";
70 }
71}
72
74{
75 /* In general, we should use QV4::Scope whenever we allocate heap objects, and employ write barriers
76 for member variables pointing to heap objects. However, ExecutableCompilationUnit is special, as it
77 is always part of the root set. So instead of using scoped allocations and write barriers, we use a
78 slightly different approach: We temporarily block the gc from running. Afterwards, at the end of the
79 function we check whether the gc was already running, and mark the ExecutableCompilationUnit. This
80 ensures that all the newly allocated objects of the compilation unit will be marked in turn.
81 If the gc was not running, we don't have to do anything, because everything will be marked when the
82 gc starts marking the root set at the start of a run.
83 */
86
92 for (uint i = 0; i < stringCount; ++i)
94
97 for (uint i = 0; i < data->regexpTableSize; ++i) {
98 const CompiledData::RegExp *re = data->regexpAt(i);
99 uint f = re->flags();
100 const CompiledData::RegExp::Flags flags = static_cast<CompiledData::RegExp::Flags>(f);
103 }
104
105 if (data->lookupTableSize) {
109 for (uint i = 0; i < data->lookupTableSize; ++i) {
111
116 else if (type == CompiledData::Lookup::Type_Setter)
124 }
125 }
126
127 if (data->jsClassTableSize) {
130 sizeof(QV4::Heap::InternalClass *));
131
132 for (uint i = 0; i < data->jsClassTableSize; ++i) {
133 int memberCount = 0;
138 for (int j = 0; j < memberCount; ++j, ++member)
145 : QV4::Attr_Data);
146 }
147 }
148
151 = qEnvironmentVariableIsSet("QV4_FORCE_INTERPRETER")
153
156
157 auto advanceAotFunction = [&](int i) -> const QQmlPrivate::AOTCompiledFunction * {
158 if (aotFunction) {
161 return aotFunction++;
162 } else {
163 aotFunction = nullptr;
164 }
165 }
166 return nullptr;
167 };
168
169 for (int i = 0 ;i < runtimeFunctions.size(); ++i) {
173 }
174
177
179 for (int i = 0 ;i < runtimeBlocks.size(); ++i) {
182
183 // first locals
185 for (quint32 j = 0; j < compiledBlock->nLocals; ++j)
186 ic = ic->addMember(
189 runtimeBlocks[i] = ic->d();
190 }
191
192 static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE");
193 if (showCode) {
194 qDebug() << "=== Constant table";
196 qDebug() << "=== String table";
197 for (uint i = 0, end = totalStringCount(); i < end; ++i)
198 qDebug() << " " << i << ":" << runtimeStrings[i]->toQString();
199 qDebug() << "=== Closure table";
200 for (uint i = 0; i < data->functionTableSize; ++i)
201 qDebug() << " " << i << ":" << runtimeFunctions[i]->name()->toQString();
202 qDebug() << "root function at index "
203 << (data->indexOfRootFunction != -1
205 }
206}
207
241
243{
244 delete [] imports;
245 imports = nullptr;
246
247 if (runtimeLookups) {
249 for (uint i = 0; i < lookupTableSize; ++i)
251 }
252
253 delete [] runtimeLookups;
254 runtimeLookups = nullptr;
255
257 f->destroy();
259
261 runtimeStrings = nullptr;
265 runtimeClasses = nullptr;
266
270}
271
273{
275
276 if (runtimeStrings) {
277 for (uint i = 0, end = totalStringCount(); i < end; ++i)
278 if (runtimeStrings[i])
280 }
282 for (uint i = 0; i < data->regexpTableSize; ++i)
284 }
285 if (runtimeClasses) {
286 for (uint i = 0; i < data->jsClassTableSize; ++i)
287 if (runtimeClasses[i])
289 }
291 if (f && f->internalClass)
294 if (c)
295 c->mark(markStack);
296
298 if (o)
299 o->mark(markStack);
300
301 if (runtimeLookups) {
302 for (uint i = 0; i < data->lookupTableSize; ++i)
304 }
305
307 v->mark(markStack);
308}
309
311{
318 }
321}
322
325{
330 return result;
331}
332
334{
336
337 if (isESModule() && module())
338 return module();
339
340 if (data->indexOfRootFunction < 0)
341 return nullptr;
342
344 if (!runtimeStrings)
345 populate();
346
349
350 if (isESModule())
351 setModule(module->d());
352
354 for (const QString &request: moduleRequests) {
355 const QUrl url(request);
356 const auto dependentModuleUnit = engine->loadModule(url, this);
357 if (engine->hasException)
358 return nullptr;
361 }
362
364
366 if (importCount > 0) {
367 imports = new const StaticValue *[importCount];
368 memset(imports, 0, importCount * sizeof(StaticValue *));
369 }
370 for (uint i = 0; i < importCount; ++i) {
374
375 if (const auto module = engine->loadModule(url, this)) {
377 if (!valuePtr) {
378 QString referenceErrorMessage = QStringLiteral("Unable to resolve import reference ");
384 return nullptr;
385 }
386 imports[i] = valuePtr;
387 }
388 }
389
390 const auto throwReferenceError = [&](const CompiledData::ExportEntry &entry, const QString &importName) {
391 QString referenceErrorMessage = QStringLiteral("Unable to resolve re-export reference ");
396 };
397
398 for (uint i = 0; i < data->indirectExportEntryTableSize; ++i) {
404 return nullptr;
405 }
406 }
407 }
408
409 return module->d();
410}
411
414{
415 if (!module())
416 return nullptr;
417
418 for (const auto &entry: *resolveSet)
420 return nullptr;
421
423
424 if (exportName->toQString() == QLatin1String("*"))
425 return &module()->self;
426
428
429 Q_ASSERT(data);
431
433
438 if (index == UINT_MAX)
439 return nullptr;
440 if (index >= module()->scope->locals.size)
441 return &(imports[index - module()->scope->locals.size]->asValue<Value>());
442 return &module()->scope->locals[index];
443 }
444
448 if (auto dependentModule = engine->loadModule(request, this)) {
451 }
452 return nullptr;
453 }
454
455 if (exportName->toQString() == QLatin1String("default"))
456 return nullptr;
457
458 const Value *starResolution = nullptr;
459
460 for (uint i = 0; i < data->starExportEntryTableSize; ++i) {
463 const Value *resolution = nullptr;
464 if (auto dependentModule = engine->loadModule(request, this))
466
467 // ### handle ambiguous
468 if (resolution) {
469 if (!starResolution) {
471 continue;
472 }
474 return nullptr;
475 }
476 }
477
478 return starResolution;
479}
480
483{
486 return stringAt(lhs.exportName) < name->toQString();
487 });
489 return nullptr;
490 return matchingExport;
491}
492
495 bool includeDefaultExport) const
496{
497 if (exportNameSet->contains(this))
498 return;
499 exportNameSet->append(this);
500
501 const auto append = [names, includeDefaultExport](const QString &name) {
502 if (!includeDefaultExport && name == QLatin1String("default"))
503 return;
504 names->append(name);
505 };
506
508
509 Q_ASSERT(data);
511
512 for (uint i = 0; i < data->localExportEntryTableSize; ++i) {
515 }
516
517 for (uint i = 0; i < data->indirectExportEntryTableSize; ++i) {
520 }
521
522 for (uint i = 0; i < data->starExportEntryTableSize; ++i) {
526 names, exportNameSet, /*includeDefaultExport*/false);
527 }
528 }
529}
530
539
557
559{
560#if QT_CONFIG(translation)
561 using namespace CompiledData;
562 bool byId = false;
563 switch (binding->type()) {
565 byId = true;
569 }
570 default:
571 break;
572 }
573#endif
575}
576
578{
579#if !QT_CONFIG(translation)
580 return QString();
581#else
583
584 if (index.byId) {
587 }
588
589 const auto fileContext = [this]() {
590 // This code must match that in the qsTr() implementation
591 const QString &path = fileName();
593
595 ? QStringView{ path }.mid(lastSlash + 1, path.size() - lastSlash - 5)
596 : QStringView();
597 return context.toUtf8();
598 };
599
600 const bool hasContext
603 if (hasContext) {
605 } else {
609 }
610
614#endif
615}
616
618{
619 if (const Module *m = m_valueOrModule.as<QV4::Module>())
620 return m->d();
621 return nullptr;
622}
623
628
629} // namespace QV4
630
631QT_END_NAMESPACE
Combined button and popup list for selecting options.
Definition qjsvalue.h:23
static void dumpConstantTable(const StaticValue *constants, uint count)
static QString toString(QV4::ReturnedValue v)