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>
24#include <QtQml/qqmlpropertymap.h>
26#include <QtCore/qfileinfo.h>
27#include <QtCore/qcryptographichash.h>
33ExecutableCompilationUnit::ExecutableCompilationUnit() =
default;
35ExecutableCompilationUnit::ExecutableCompilationUnit(
36 QQmlRefPointer<CompiledData::CompilationUnit> &&compilationUnit)
37 : m_compilationUnit(
std::move(compilationUnit))
39 constants = m_compilationUnit->constants;
42ExecutableCompilationUnit::~ExecutableCompilationUnit()
54 else if (
val.isDouble())
69 <<
toString(constants[
i].asReturnedValue()).toUtf8().constData() <<
"\n";
73void ExecutableCompilationUnit::populate()
85 GCCriticalSection<ExecutableCompilationUnit> criticalSection(
engine,
this);
90 const quint32 stringCount = totalStringCount();
92 for (
uint i = 0;
i < stringCount; ++
i)
93 runtimeStrings[
i] =
engine->newString(stringAt(
i));
95 runtimeRegularExpressions
105 if (
data->lookupTableSize) {
107 memset(runtimeLookups, 0,
data->lookupTableSize *
sizeof(
QV4::Lookup));
114 if (
type == CompiledData::Lookup::Type_Getter)
116 else if (
type == CompiledData::Lookup::Type_Setter)
118 else if (
type == CompiledData::Lookup::Type_GlobalGetter)
120 else if (
type == CompiledData::Lookup::Type_QmlContextPropertyGetter)
122 l->
forCall = compiledLookups[
i].mode() == CompiledData::Lookup::Mode_ForCall;
123 l->
nameIndex = compiledLookups[
i].nameIndex();
127 if (
data->jsClassTableSize) {
132 for (
uint i = 0;
i <
data->jsClassTableSize; ++
i) {
135 =
data->jsClassAt(
i, &memberCount);
138 for (
int j = 0;
j < memberCount; ++
j, ++member)
140 = runtimeClasses[
i]->addMember(
141 engine->identifierTable->asPropertyKey(
149 runtimeFunctions.resize(
data->functionTableSize);
150 static bool ignoreAotCompiledFunctions
152 || !(
engine->diskCacheOptions() & ExecutionEngine::DiskCache::AotNative);
155 = ignoreAotCompiledFunctions ?
nullptr : m_compilationUnit->aotCompiledFunctions;
159 if (aotFunction->functionPtr) {
160 if (aotFunction->functionIndex ==
i)
161 return aotFunction++;
163 aotFunction =
nullptr;
169 for (
int i = 0 ;
i < runtimeFunctions.size(); ++
i) {
172 advanceAotFunction(
i));
176 Scoped<InternalClass> ic(scope);
178 runtimeBlocks.resize(
data->blockTableSize);
179 for (
int i = 0 ;
i < runtimeBlocks.size(); ++
i) {
181 ic =
engine->internalClasses(EngineBase::Class_CallContext);
184 const quint32_le *localsIndices = compiledBlock->localsTable();
185 for (
quint32 j = 0;
j < compiledBlock->nLocals; ++
j)
187 engine->identifierTable->asPropertyKey(runtimeStrings[localsIndices[
j]]),
189 runtimeBlocks[
i] = ic->d();
194 qDebug() <<
"=== Constant table";
196 qDebug() <<
"=== String table";
198 qDebug() <<
" " <<
i <<
":" << runtimeStrings[
i]->toQString();
199 qDebug() <<
"=== Closure table";
201 qDebug() <<
" " <<
i <<
":" << runtimeFunctions[
i]->name()->toQString();
202 qDebug() <<
"root function at index "
203 << (
data->indexOfRootFunction != -1
204 ?
data->indexOfRootFunction : 0);
208Heap::Object *ExecutableCompilationUnit::templateObjectAt(
int index)
const
215 if (!templateObjects.size())
216 templateObjects.resize(
data->templateObjectTableSize);
217 Heap::Object *
o = templateObjects.at(
index);
224 Scoped<ArrayObject>
a(scope,
engine->newArrayObject(
t->size));
225 Scoped<ArrayObject> raw(scope,
engine->newArrayObject(
t->size));
227 for (
uint i = 0;
i <
t->size; ++
i) {
228 s = runtimeStrings[
t->stringIndexAt(
i)];
230 s = runtimeStrings[
t->rawStringIndexAt(
i)];
234 ObjectPrototype::method_freeze(
engine->functionCtor(),
nullptr, raw, 1);
236 ObjectPrototype::method_freeze(
engine->functionCtor(),
nullptr,
a, 1);
238 templateObjects[
index] =
a->objectValue()->d();
239 return templateObjects.at(
index);
242void ExecutableCompilationUnit::clear()
247 if (runtimeLookups) {
248 const uint lookupTableSize = unitData()->lookupTableSize;
249 for (
uint i = 0;
i < lookupTableSize; ++
i)
250 runtimeLookups[
i].releasePropertyCache();
253 delete [] runtimeLookups;
254 runtimeLookups =
nullptr;
258 runtimeFunctions.clear();
260 free(runtimeStrings);
261 runtimeStrings =
nullptr;
262 delete [] runtimeRegularExpressions;
263 runtimeRegularExpressions =
nullptr;
264 free(runtimeClasses);
265 runtimeClasses =
nullptr;
272 if (runtimeStrings) {
274 if (runtimeStrings[
i])
275 runtimeStrings[
i]->mark(markStack);
277 if (runtimeRegularExpressions) {
279 Value::fromStaticValue(runtimeRegularExpressions[
i]).mark(markStack);
281 if (runtimeClasses) {
283 if (runtimeClasses[
i])
284 runtimeClasses[
i]->mark(markStack);
287 if (
f &&
f->internalClass)
288 f->internalClass->mark(markStack);
293 for (QV4::Heap::Object *
o : std::as_const(templateObjects))
297 if (runtimeLookups) {
299 runtimeLookups[
i].markObjects(markStack);
302 if (
auto mod = module())
303 mod->mark(markStack);
306IdentifierHash ExecutableCompilationUnit::createNamedObjectsPerComponent(
int componentObjectIndex)
313 namedObjectCache.add(runtimeStrings[namedObject->idNameIndex], namedObject->objectId());
315 Q_ASSERT(!namedObjectCache.isEmpty());
316 return *namedObjectsPerComponentCache.insert(componentObjectIndex, namedObjectCache);
319QQmlRefPointer<ExecutableCompilationUnit> ExecutableCompilationUnit::create(
320 QQmlRefPointer<CompiledData::CompilationUnit> &&compilationUnit, ExecutionEngine *
engine)
322 auto result = QQmlRefPointer<ExecutableCompilationUnit>(
323 new ExecutableCompilationUnit(std::move(compilationUnit)),
329Heap::Module *ExecutableCompilationUnit::instantiate()
333 if (isESModule() && module())
336 if (
data->indexOfRootFunction < 0)
347 setModule(module->d());
349 const QStringList moduleRequests = m_compilationUnit->moduleRequests();
352 const auto dependentModuleUnit =
engine->loadModule(
url,
this);
355 if (dependentModuleUnit.compiled)
356 dependentModuleUnit.compiled->instantiate();
361 const uint importCount =
data->importEntryTableSize;
362 if (importCount > 0) {
364 memset(imports, 0, importCount *
sizeof(
StaticValue *));
366 for (
uint i = 0;
i < importCount; ++
i) {
369 importName = runtimeStrings[
entry.importName];
371 const auto module = engine->loadModule(url, this);
372 if (module.compiled) {
373 const Value *valuePtr =
module.compiled->resolveExport(importName);
376 referenceErrorMessage += importName->toQString();
377 engine->throwReferenceError(
379 entry.location.line(),
entry.location.column());
382 imports[
i] = valuePtr;
385 if (
value->isNullOrUndefined()) {
398 const auto fragment =
engine->moduleForUrl(
url,
this);
399 if (fragment.native) {
400 imports[
i] = fragment.native;
402 Scope scope(this->engine);
406 referenceErrorMessage +=
name;
410 engine->throwReferenceError(
412 entry.location.line(),
entry.location.column());
426 referenceErrorMessage += importName;
427 engine->throwReferenceError(
429 entry.location.line(),
entry.location.column());
432 for (
uint i = 0;
i <
data->indirectExportEntryTableSize; ++
i) {
434 auto dependentModule =
engine->loadModule(urlAt(
entry.moduleRequest),
this);
436 if (
const auto dependentModuleUnit = dependentModule.compiled) {
437 if (!dependentModuleUnit->resolveExport(importName)) {
438 throwReferenceError(
entry, importName->toQString());
441 }
else if (
const auto native = dependentModule.native) {
445 if (
result->isUndefined()) {
446 throwReferenceError(
entry, importName->toQString());
455const Value *ExecutableCompilationUnit::resolveExportRecursively(
456 QV4::String *exportName, QVector<ResolveSetEntry> *resolveSet)
461 for (
const auto &
entry: *resolveSet)
465 (*resolveSet) << ResolveSetEntry(
this, exportName);
468 return &module()->self;
477 if (
auto localExport = lookupNameInExportTable(
478 data->localExportEntryTable(),
data->localExportEntryTableSize, exportName)) {
479 ScopedString localName(scope, runtimeStrings[localExport->localName]);
480 uint index = module()->scope->internalClass->indexOfValueOrGetter(localName->toPropertyKey());
481 if (
index == UINT_MAX)
483 if (
index >= module()->scope->locals.size)
484 return &(imports[
index - module()->scope->locals.size]->asValue<
Value>());
485 return &module()->scope->locals[
index];
488 if (
auto indirectExport = lookupNameInExportTable(
489 data->indirectExportEntryTable(),
data->indirectExportEntryTableSize, exportName)) {
490 QUrl request = urlAt(indirectExport->moduleRequest);
492 ScopedString importName(scope, runtimeStrings[indirectExport->importName]);
493 if (dependentModule.compiled) {
494 return dependentModule.compiled->resolveExportRecursively(importName, resolveSet);
495 }
else if (dependentModule.native) {
497 return dependentModule.native;
501 request.setFragment(importName->toQString());
504 return fragment.native;
519 const Value *starResolution =
nullptr;
521 for (
uint i = 0;
i <
data->starExportEntryTableSize; ++
i) {
522 const CompiledData::ExportEntry &
entry =
data->starExportEntryTable()[
i];
525 const Value *resolution =
nullptr;
526 if (dependentModule.compiled) {
527 resolution = dependentModule.compiled->resolveExportRecursively(
528 exportName, resolveSet);
529 }
else if (dependentModule.native) {
531 resolution = dependentModule.native;
535 if (fragment.native) {
536 resolution = fragment.native;
540 resolution =
engine->registerNativeModule(
request,
o->get(exportName));
547 if (!starResolution) {
548 starResolution = resolution;
551 if (resolution != starResolution)
556 return starResolution;
559const CompiledData::ExportEntry *ExecutableCompilationUnit::lookupNameInExportTable(
560 const CompiledData::ExportEntry *firstExportEntry,
int tableSize,
QV4::String *
name)
const
562 const CompiledData::ExportEntry *lastExportEntry = firstExportEntry + tableSize;
563 auto matchingExport = std::lower_bound(firstExportEntry, lastExportEntry,
name, [
this](
const CompiledData::ExportEntry &lhs,
QV4::String *
name) {
564 return stringAt(lhs.exportName) <
name->toQString();
566 if (matchingExport == lastExportEntry || stringAt(matchingExport->exportName) !=
name->toQString())
568 return matchingExport;
571void ExecutableCompilationUnit::getExportedNamesRecursively(
572 QStringList *
names, QVector<const ExecutableCompilationUnit*> *exportNameSet,
573 bool includeDefaultExport)
const
575 if (exportNameSet->contains(
this))
577 exportNameSet->append(
this);
585 const CompiledData::Unit *
data = m_compilationUnit->data;
590 for (
uint i = 0;
i <
data->localExportEntryTableSize; ++
i) {
591 const CompiledData::ExportEntry &
entry =
data->localExportEntryTable()[
i];
595 for (
uint i = 0;
i <
data->indirectExportEntryTableSize; ++
i) {
596 const CompiledData::ExportEntry &
entry =
data->indirectExportEntryTable()[
i];
600 for (
uint i = 0;
i <
data->starExportEntryTableSize; ++
i) {
601 const CompiledData::ExportEntry &
entry =
data->starExportEntryTable()[
i];
602 auto dependentModule =
engine->loadModule(urlAt(
entry.moduleRequest),
this);
603 if (dependentModule.compiled) {
604 dependentModule.compiled->getExportedNamesRecursively(
605 names, exportNameSet,
false);
606 }
else if (dependentModule.native) {
609 ObjectIterator
iterator(scope,
o, ObjectIterator::EnumerableOnly);
611 ScopedValue
val(scope,
iterator.nextPropertyNameAsString());
620void ExecutableCompilationUnit::evaluate()
629void ExecutableCompilationUnit::evaluateModuleRequests()
633 const QStringList moduleRequests = m_compilationUnit->moduleRequests();
636 if (dependentModule.native)
643 dependentModule.compiled->evaluate();
651#if QT_CONFIG(translation)
652 using namespace CompiledData;
654 switch (binding->
type()) {
655 case Binding::Type_TranslationById:
658 case Binding::Type_Translation: {
659 return translateFrom({ binding->
value.translationDataIndex, byId });
665 return m_compilationUnit->bindingValueAsString(binding);
670#if !QT_CONFIG(translation)
680 const auto fileContext = [
this]() {
691 const bool hasContext
697 auto pragmaTranslationContext = unitData()->translationContextIndex();
698 context = stringAt(*pragmaTranslationContext).toUtf8();
static QString translate(const char *context, const char *key, const char *disambiguation=nullptr, int n=-1)
\threadsafe
void throwError(const QString &message)
Throws a run-time error (exception) with the given message.
constexpr QStringView mid(qsizetype pos, qsizetype n=-1) const noexcept
Returns the substring of length length starting at position start in this object.
\macro QT_RESTRICTED_CAST_FROM_ASCII
QByteArray toUtf8() const &
void setFragment(const QString &fragment, ParsingMode mode=TolerantMode)
Sets the fragment of the URL to fragment.
QString toString(FormattingOptions options=FormattingOptions(PrettyDecoded)) const
Returns a string representation of the URL.
list append(new Employee("Blackpool", "Stephen"))
typename C::iterator iterator
Combined button and popup list for selecting options.
static void dumpConstantTable(const StaticValue *constants, uint count)
Scoped< Object > ScopedObject
Scoped< String > ScopedString
QTextStream & right(QTextStream &stream)
Calls QTextStream::setFieldAlignment(QTextStream::AlignRight) on stream and returns stream.
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
GLsizei const GLfloat * v
[13]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLenum GLsizei count
GLint GLsizei GLsizei GLenum GLenum GLsizei void * data
GLsizei const GLchar *const * path
static qreal component(const QPointF &point, unsigned int i)
QLatin1StringView QLatin1String
#define QStringLiteral(str)
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
QTextStreamManipulator qSetFieldWidth(int width)
Q_CORE_EXPORT QString qtTrId(const char *id, int n=-1)
static QString errorMessage(QUrlPrivate::ErrorCode errorCode, const QString &errorSource, qsizetype errorPosition)
if(qFloatDistance(a, b)<(1<< 7))
[0]
QUrl url("example.com")
[constructor-url-reference]
QNetworkRequest request(url)
char * toString(const MyType &t)
[31]
\inmodule QtCore \reentrant
union QV4::CompiledData::Binding::@540 value
quint32 nameOffset() const
IdentifierTable * identifierTable
static Function * create(ExecutionEngine *engine, ExecutableCompilationUnit *unit, const CompiledData::Function *function, const QQmlPrivate::AOTCompiledFunction *aotFunction)
PropertyKey asPropertyKey(const Heap::String *str)
ReturnedValue(* globalGetter)(Lookup *l, ExecutionEngine *engine)
ReturnedValue(* qmlContextPropertyGetter)(Lookup *l, ExecutionEngine *engine, Value *thisObject)
ReturnedValue(* getter)(Lookup *l, ExecutionEngine *engine, const Value &object)
static ReturnedValue getterGeneric(Lookup *l, ExecutionEngine *engine, const Value &object)
static bool setterGeneric(Lookup *l, ExecutionEngine *engine, Value &object, const Value &value)
static ReturnedValue globalGetterGeneric(Lookup *l, ExecutionEngine *engine)
bool(* setter)(Lookup *l, ExecutionEngine *engine, Value &object, const Value &v)
static Heap::RegExp * create(ExecutionEngine *engine, const QString &pattern, uint flags=CompiledData::RegExp::RegExp_NoFlags)
QString toQString() const