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// Qt-Security score:significant
4
5#include "qml/qqmlprivate.h"
6#include "qv4engine_p.h"
8
9#include <private/qv4engine_p.h>
10#include <private/qv4regexp_p.h>
11#include <private/qv4lookup_p.h>
12#include <private/qv4qmlcontext_p.h>
13#include <private/qv4identifiertable_p.h>
14#include <private/qv4objectproto_p.h>
15#include <private/qqmlengine_p.h>
16#include <private/qv4qobjectwrapper_p.h>
17#include <private/qqmlvaluetypewrapper_p.h>
18#include <private/qqmlscriptdata_p.h>
19#include <private/qv4module_p.h>
20#include <private/qv4compilationunitmapper_p.h>
21#include <private/qqmltypewrapper_p.h>
22#include <private/qv4resolvedtypereference_p.h>
23#include <private/qv4objectiterator_p.h>
24
25#include <QtQml/qqmlpropertymap.h>
26
27#include <QtCore/qfileinfo.h>
28#include <QtCore/qcryptographichash.h>
29
31
32namespace QV4 {
33
35
39{
41}
42
44{
45 if (engine)
46 clear();
47}
48
49static QString toString(QV4::ReturnedValue v)
50{
51 Value val = Value::fromReturnedValue(v);
52 QString result;
53 if (val.isInt32())
54 result = QLatin1String("int ");
55 else if (val.isDouble())
56 result = QLatin1String("double ");
57 if (val.isEmpty())
58 result += QLatin1String("empty");
59 else
60 result += val.toQStringNoThrow();
61 return result;
62}
63
64static void dumpConstantTable(const StaticValue *constants, uint count)
65{
66 QDebug d = qDebug();
67 d.nospace() << Qt::right;
68 for (uint i = 0; i < count; ++i) {
69 d << qSetFieldWidth(8) << i << qSetFieldWidth(0) << ": "
70 << toString(constants[i].asReturnedValue()).toUtf8().constData() << "\n";
71 }
72}
73
75{
76 /* In general, we should use QV4::Scope whenever we allocate heap objects, and employ write barriers
77 for member variables pointing to heap objects. However, ExecutableCompilationUnit is special, as it
78 is always part of the root set. So instead of using scoped allocations and write barriers, we use a
79 slightly different approach: We temporarily block the gc from running. Afterwards, at the end of the
80 function we check whether the gc was already running, and mark the ExecutableCompilationUnit. This
81 ensures that all the newly allocated objects of the compilation unit will be marked in turn.
82 If the gc was not running, we don't have to do anything, because everything will be marked when the
83 gc starts marking the root set at the start of a run.
84 */
87
93 for (uint i = 0; i < stringCount; ++i)
95
98 for (uint i = 0; i < data->regexpTableSize; ++i) {
99 const CompiledData::RegExp *re = data->regexpAt(i);
100 uint f = re->flags();
101 const CompiledData::RegExp::Flags flags = static_cast<CompiledData::RegExp::Flags>(f);
104 }
105
106 if (data->lookupTableSize) {
110 for (uint i = 0; i < data->lookupTableSize; ++i) {
112
117 else if (type == CompiledData::Lookup::Type_Setter)
125 }
126 }
127
128 if (data->jsClassTableSize) {
131 sizeof(QV4::Heap::InternalClass *));
132
133 for (uint i = 0; i < data->jsClassTableSize; ++i) {
134 int memberCount = 0;
139 for (int j = 0; j < memberCount; ++j, ++member)
146 : QV4::Attr_Data);
147 }
148 }
149
152 = qEnvironmentVariableIsSet("QV4_FORCE_INTERPRETER")
154
157
158 auto advanceAotFunction = [&](int i) -> const QQmlPrivate::AOTCompiledFunction * {
159 if (aotFunction) {
162 return aotFunction++;
163 } else {
164 aotFunction = nullptr;
165 }
166 }
167 return nullptr;
168 };
169
170 for (int i = 0 ;i < runtimeFunctions.size(); ++i) {
174 }
175
178
180 for (int i = 0 ;i < runtimeBlocks.size(); ++i) {
183
184 // first locals
186 for (quint32 j = 0; j < compiledBlock->nLocals; ++j)
187 ic = ic->addMember(
190 runtimeBlocks[i] = ic->d();
191 }
192
193 static const bool showCode = qEnvironmentVariableIsSet("QV4_SHOW_BYTECODE");
194 if (showCode) {
195 qDebug() << "=== Constant table";
197 qDebug() << "=== String table";
198 for (uint i = 0, end = totalStringCount(); i < end; ++i)
199 qDebug() << " " << i << ":" << runtimeStrings[i]->toQString();
200 qDebug() << "=== Closure table";
201 for (uint i = 0; i < data->functionTableSize; ++i)
202 qDebug() << " " << i << ":" << runtimeFunctions[i]->name()->toQString();
203 qDebug() << "root function at index "
204 << (data->indexOfRootFunction != -1
206 }
207}
208
242
244{
245 delete [] imports;
246 imports = nullptr;
247
248 if (runtimeLookups) {
250 for (uint i = 0; i < lookupTableSize; ++i)
252 }
253
254 delete [] runtimeLookups;
255 runtimeLookups = nullptr;
256
258 f->destroy();
260
262 runtimeStrings = nullptr;
266 runtimeClasses = nullptr;
267
271}
272
274{
276
277 if (runtimeStrings) {
278 for (uint i = 0, end = totalStringCount(); i < end; ++i)
279 if (runtimeStrings[i])
281 }
283 for (uint i = 0; i < data->regexpTableSize; ++i)
285 }
286 if (runtimeClasses) {
287 for (uint i = 0; i < data->jsClassTableSize; ++i)
288 if (runtimeClasses[i])
290 }
292 if (f && f->internalClass)
295 if (c)
296 c->mark(markStack);
297
299 if (o)
300 o->mark(markStack);
301
302 if (runtimeLookups) {
303 for (uint i = 0; i < data->lookupTableSize; ++i)
305 }
306
308 v->mark(markStack);
309}
310
312{
319 }
322}
323
326{
331 return result;
332}
333
335{
337
338 if (isESModule() && module())
339 return module();
340
341 if (data->indexOfRootFunction < 0)
342 return nullptr;
343
345 if (!runtimeStrings)
346 populate();
347
350
351 if (isESModule())
352 setModule(module->d());
353
354 for (uint i = 0, end = data->moduleRequestTableSize; i < end; ++i) {
356 if (engine->hasException)
357 return nullptr;
360 }
361
363
365 if (importCount > 0) {
366 imports = new const StaticValue *[importCount];
367 memset(imports, 0, importCount * sizeof(StaticValue *));
368 }
369 for (uint i = 0; i < importCount; ++i) {
372
373 if (const auto module = dependentModule(urlAt(entry.moduleRequest))) {
375 if (!valuePtr) {
376 QString referenceErrorMessage = QStringLiteral("Unable to resolve import reference ");
382 return nullptr;
383 }
384 imports[i] = valuePtr;
385 }
386 }
387
388 const auto throwReferenceError = [&](const CompiledData::ExportEntry &entry, const QString &importName) {
389 QString referenceErrorMessage = QStringLiteral("Unable to resolve re-export reference ");
394 };
395
396 for (uint i = 0; i < data->indirectExportEntryTableSize; ++i) {
402 return nullptr;
403 }
404 }
405 }
406
407 return module->d();
408}
409
412{
413 if (!module())
414 return nullptr;
415
416 for (const auto &entry: *resolveSet)
418 return nullptr;
419
421
422 if (exportName->toQString() == QLatin1String("*"))
423 return &module()->self;
424
426
427 Q_ASSERT(data);
429
431
436 if (index == UINT_MAX)
437 return nullptr;
438 if (index >= module()->scope->locals.size)
439 return &(imports[index - module()->scope->locals.size]->asValue<Value>());
440 return &module()->scope->locals[index];
441 }
442
448 }
449 return nullptr;
450 }
451
452 if (exportName->toQString() == QLatin1String("default"))
453 return nullptr;
454
455 const Value *starResolution = nullptr;
456
457 for (uint i = 0; i < data->starExportEntryTableSize; ++i) {
459 const Value *resolution = nullptr;
462
463 // ### handle ambiguous
464 if (resolution) {
465 if (!starResolution) {
467 continue;
468 }
470 return nullptr;
471 }
472 }
473
474 return starResolution;
475}
476
479{
482 return stringAt(lhs.exportName) < name->toQString();
483 });
485 return nullptr;
486 return matchingExport;
487}
488
491 bool includeDefaultExport) const
492{
493 if (exportNameSet->contains(this))
494 return;
495 exportNameSet->append(this);
496
497 const auto append = [names, includeDefaultExport](const QString &name) {
498 if (!includeDefaultExport && name == QLatin1String("default"))
499 return;
500 names->append(name);
501 };
502
504
505 Q_ASSERT(data);
507
508 for (uint i = 0; i < data->localExportEntryTableSize; ++i) {
511 }
512
513 for (uint i = 0; i < data->indirectExportEntryTableSize; ++i) {
516 }
517
518 for (uint i = 0; i < data->starExportEntryTableSize; ++i) {
522 names, exportNameSet, /*includeDefaultExport*/false);
523 }
524 }
525}
526
535
537{
539
540 const CompiledData::Unit *data = unitData();
541 for (uint i = 0, end = data->moduleRequestTableSize; i < end; ++i) {
543
544 if (engine->hasException)
545 return;
546
548 module->evaluate();
549 if (engine->hasException)
550 return;
551 }
552}
553
555{
556#if QT_CONFIG(translation)
557 using namespace CompiledData;
558 bool byId = false;
559 switch (binding->type()) {
561 byId = true;
565 }
566 default:
567 break;
568 }
569#endif
571}
572
574{
575#if !QT_CONFIG(translation)
576 return QString();
577#else
579
580 if (index.byId) {
583 }
584
585 const auto fileContext = [this]() {
586 // This code must match that in the qsTr() implementation
587 const QString &path = fileName();
589
591 ? QStringView{ path }.mid(lastSlash + 1, path.size() - lastSlash - 5)
592 : QStringView();
593 return context.toUtf8();
594 };
595
596 const bool hasContext
599 if (hasContext) {
601 } else {
605 }
606
610#endif
611}
612
614{
615 if (const Module *m = m_valueOrModule.as<QV4::Module>())
616 return m->d();
617 return nullptr;
618}
619
624
625} // namespace QV4
626
627QT_END_NAMESPACE
Definition qjsvalue.h:23
static void dumpConstantTable(const StaticValue *constants, uint count)
static QString toString(QV4::ReturnedValue v)