7#include <private/qv4compileddata_p.h>
8#include <private/qv4staticvalue_p.h>
9#include <private/qv4alloca_p.h>
10#include <private/qqmljslexer_p.h>
11#include <private/qqmljsast_p.h>
12#include <private/qml_compile_hash_p.h>
13#include <private/qqmlirbuilder_p.h>
14#include <QCryptographicHash>
24 const size_t remainderMask =
divisor - 1;
25 return (
x + remainderMask) & ~remainderMask;
39 if (
it != stringToId.
cend())
49 Q_ASSERT(stringToId.contains(
string));
50 return stringToId.value(
string);
72 char *dataStart =
reinterpret_cast<char *
>(unit);
74 char *
stringData =
reinterpret_cast<char *
>(stringTable)
76 for (
int i = backingUnitTableSize ;
i <
strings.size(); ++
i) {
77 const int index =
i - backingUnitTableSize;
84 s->size = qstr.size();
86 ushort *uc =
reinterpret_cast<ushort *
>(
reinterpret_cast<char *
>(
s) +
sizeof(*
s));
87 qToLittleEndian<ushort>(qstr.constData(),
s->size, uc);
96#ifndef QT_CRYPTOGRAPHICHASH_ONLY_SHA1
99 const int checksummableDataOffset
102 const char *dataPtr =
reinterpret_cast<const char *
>(unit) + checksummableDataOffset;
122 return registerGetterLookup(registerString(
name),
mode);
136 return lookups.size() - 1;
141 return registerSetterLookup(registerString(
name));
149 return lookups.size() - 1;
156 return lookups.size() - 1;
165 return lookups.size() - 1;
183 return regexps.size() - 1;
188 int idx = constants.indexOf(
v);
192 return constants.size() - 1;
197 return constants.at(idx);
209 jsClassOffsets.append(jsClassData.size());
210 const int oldSize = jsClassData.size();
211 jsClassData.resize(jsClassData.size() +
size);
212 memset(jsClassData.data() + oldSize, 0,
size);
220 member->
set(registerString(
name),
false);
224 return jsClassOffsets.size() - 1;
231 jsClassData.data() + jsClassOffsets[jsClassId]);
238 jsClassData.data() + jsClassOffsets[jsClassId]);
243 return stringForIndex(
members[member].nameOffset());
248 translations.append(translation);
249 return translations.size() - 1;
258 if (
type->typeArgument) {
259 registerString(
type->typeArgument->toString());
260 registerString(
type->typeId->toString());
262 registerString(
type->toString());
265 registerString(module->fileName);
266 registerString(module->finalUrl);
267 for (
Context *
f : std::as_const(module->functions)) {
268 registerString(
f->name);
269 registerTypeStrings(
f->returnType);
270 for (
int i = 0;
i <
f->arguments.size(); ++
i) {
271 registerString(
f->arguments.at(
i).id);
273 =
f->arguments.at(
i).typeAnnotation.data()) {
274 registerTypeStrings(annotation->type);
277 for (
int i = 0;
i <
f->locals.size(); ++
i)
278 registerString(
f->locals.at(
i));
280 for (
Context *
c : std::as_const(module->blocks)) {
281 for (
int i = 0;
i <
c->locals.size(); ++
i)
282 registerString(
c->locals.at(
i));
286 registerString(
entry.exportName);
287 registerString(
entry.moduleRequest);
288 registerString(
entry.importName);
289 registerString(
entry.localName);
291 std::for_each(module->localExportEntries.constBegin(), module->localExportEntries.constEnd(), registerExportEntry);
292 std::for_each(module->indirectExportEntries.constBegin(), module->indirectExportEntries.constEnd(), registerExportEntry);
293 std::for_each(module->starExportEntries.constBegin(), module->starExportEntries.constEnd(), registerExportEntry);
296 for (
const auto &
entry:
module->importEntries) {
297 registerString(entry.moduleRequest);
298 registerString(
entry.importName);
299 registerString(
entry.localName);
303 registerString(request);
306 Q_ALLOCA_VAR(
quint32_le, blockClassAndFunctionOffsets, (module->functions.size() + module->classes.size() + module->templateObjects.size() + module->blocks.size()) *
sizeof(
quint32_le));
307 uint jsClassDataOffset = 0;
313 dataPtr =
reinterpret_cast<char *
>(malloc(tempHeader.unitSize));
314 memset(dataPtr, 0, tempHeader.unitSize);
316 memcpy(unit, &tempHeader,
sizeof(tempHeader));
324 for (
int i = 0;
i <
module->functions.size(); ++
i) {
325 Context *function =
module->functions.at(i);
326 if (function == module->rootContext)
329 writeFunction(dataPtr + blockClassAndFunctionOffsets[
i], function);
332 for (
int i = 0;
i <
module->classes.size(); ++
i) {
333 const Class &
c =
module->classes.at(i);
335 writeClass(dataPtr + blockClassAndFunctionOffsets[
i + module->functions.size()],
c);
338 for (
int i = 0;
i <
module->templateObjects.size(); ++
i) {
339 const TemplateObject &
t =
module->templateObjects.at(i);
341 writeTemplateObject(dataPtr + blockClassAndFunctionOffsets[
i + module->functions.size() + module->classes.size()],
t);
344 for (
int i = 0;
i <
module->blocks.size(); ++
i) {
345 Context *block =
module->blocks.at(i);
347 writeBlock(dataPtr + blockClassAndFunctionOffsets[
i + module->classes.size() + module->templateObjects.size() + module->functions.size()], block);
350 CompiledData::Lookup *lookupsToWrite =
reinterpret_cast<CompiledData::Lookup*
>(dataPtr + unit->
offsetToLookupTable);
351 for (
const CompiledData::Lookup &l :
std::as_const(lookups))
352 *lookupsToWrite++ = l;
356 memcpy(regexpTable, regexps.constData(), regexps.size() *
sizeof(*regexpTable));
358#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
360 if (constants.size())
361 memcpy(constantTable, constants.constData(), constants.size() *
sizeof(
ReturnedValue));
364 for (
int i = 0;
i < constants.count(); ++
i)
365 constantTable[
i] = constants.at(
i);
369 if (jsClassData.size())
370 memcpy(dataPtr + jsClassDataOffset, jsClassData.constData(), jsClassData.size());
374 for (
int i = 0;
i < jsClassOffsets.size(); ++
i)
375 jsClassOffsetTable[
i] = jsClassDataOffset + jsClassOffsets.at(
i);
378 if (translations.size()) {
379 memcpy(dataPtr + unit->
offsetToTranslationTable, translations.constData(), translations.size() *
sizeof(CompiledData::TranslationData));
383 const auto populateExportEntryTable = [
this, dataPtr](
const QVector<Compiler::ExportEntry> &
table,
quint32_le offset) {
384 CompiledData::ExportEntry *entryToWrite =
reinterpret_cast<CompiledData::ExportEntry *
>(dataPtr +
offset);
385 for (
const Compiler::ExportEntry &
entry:
table) {
386 entryToWrite->exportName = getStringId(
entry.exportName);
387 entryToWrite->moduleRequest = getStringId(
entry.moduleRequest);
388 entryToWrite->importName = getStringId(
entry.importName);
389 entryToWrite->localName = getStringId(
entry.localName);
390 entryToWrite->location =
entry.location;
400 CompiledData::ImportEntry *entryToWrite =
reinterpret_cast<CompiledData::ImportEntry *
>(dataPtr + unit->
offsetToImportEntryTable);
401 for (
const Compiler::ImportEntry &
entry: module->importEntries) {
402 entryToWrite->moduleRequest = getStringId(
entry.moduleRequest);
403 entryToWrite->importName = getStringId(
entry.importName);
404 entryToWrite->localName = getStringId(
entry.localName);
405 entryToWrite->location =
entry.location;
412 for (
const QString &moduleRequest: module->moduleRequests) {
413 *moduleRequestEntryToWrite = getStringId(moduleRequest);
414 moduleRequestEntryToWrite++;
419 if (
option == GenerateWithStringTable)
420 stringTable.serialize(unit);
422 generateUnitChecksum(unit);
433 function->
nameIndex = getStringId(irFunction->name);
435 if (irFunction->isStrict)
437 if (irFunction->isArrowFunction)
439 if (irFunction->isGenerator)
441 if (irFunction->returnsClosure)
444 if (!irFunction->returnsClosure
445 || irFunction->innerFunctionAccessesThis
446 || irFunction->innerFunctionAccessesNewTarget) {
449 function->nestedFunctionIndex = std::numeric_limits<uint32_t>::max();
452 function->nestedFunctionIndex
453 =
quint32(module->functions.indexOf(irFunction->nestedContexts.first()));
456 function->length = irFunction->formals ? irFunction->formals->length() : 0;
457 function->nFormals = irFunction->arguments.size();
458 function->formalsOffset = currentOffset;
461 const auto idGenerator = [
this](
const QString &
str) {
return getStringId(
str); };
465 function->sizeOfLocalTemporalDeadZone = irFunction->sizeOfLocalTemporalDeadZone;
466 function->sizeOfRegisterTemporalDeadZone = irFunction->sizeOfRegisterTemporalDeadZone;
467 function->firstTemporalDeadZoneRegister = irFunction->firstTemporalDeadZoneRegister;
469 function->nLocals = irFunction->locals.size();
470 function->localsOffset = currentOffset;
471 currentOffset += function->nLocals *
sizeof(
quint32);
473 function->nLineAndStatementNumbers
474 = irFunction->lineAndStatementNumberMapping.size();
475 Q_ASSERT(function->lineAndStatementNumberOffset() == currentOffset);
476 currentOffset += function->nLineAndStatementNumbers
479 function->nRegisters = irFunction->registerCountInFunction;
481 if (!irFunction->labelInfo.empty()) {
482 function->nLabelInfos =
quint32(irFunction->labelInfo.size());
483 Q_ASSERT(function->labelInfosOffset() == currentOffset);
484 currentOffset += function->nLabelInfos *
sizeof(
quint32);
487 function->location.set(irFunction->line, irFunction->column);
489 function->codeOffset = currentOffset;
490 function->codeSize = irFunction->code.size();
494 for (
int i = 0;
i < irFunction->arguments.size(); ++
i) {
495 auto *formal = &formals[
i];
496 formal->
nameIndex = getStringId(irFunction->arguments.at(
i).id);
503 for (
int i = 0;
i < irFunction->locals.size(); ++
i)
504 locals[
i] = getStringId(irFunction->locals.at(
i));
507 memcpy(
f + function->lineAndStatementNumberOffset(),
508 irFunction->lineAndStatementNumberMapping.constData(),
509 irFunction->lineAndStatementNumberMapping.size()
513 for (
unsigned u : irFunction->labelInfo) {
518 memcpy(
f + function->codeOffset, irFunction->code.constData(), irFunction->code.size());
531 QVector<Class::Method> allMethods =
c.staticMethods;
532 allMethods +=
c.methods;
535 cls->nameIndex =
c.nameIndex;
536 cls->nMethods =
c.methods.size();
537 cls->nStaticMethods =
c.staticMethods.size();
538 cls->methodTableOffset = currentOffset;
542 for (
int i = 0;
i < allMethods.size(); ++
i) {
543 method->name = allMethods.at(
i).nameIndex;
544 method->type = allMethods.at(
i).type;
545 method->function = allMethods.at(
i).functionIndex;
551 qDebug() <<
"=== Class" << stringForIndex(cls->nameIndex) <<
"static methods"
552 << cls->nStaticMethods <<
"methods" << cls->nMethods;
553 qDebug() <<
" constructor:" << cls->constructorFunction;
554 for (
uint i = 0;
i < cls->nStaticMethods + cls->nMethods; ++
i) {
557 if (i < cls->nStaticMethods)
559 switch (cls->methodTable()[
i].type) {
567 output << stringForIndex(cls->methodTable()[
i].name) <<
" "
568 << cls->methodTable()[
i].function;
577 tmpl->
size =
t.strings.size();
584 for (
int i = 0;
i <
t.strings.size(); ++
i)
588 for (
int i = 0;
i <
t.rawStrings.size(); ++
i)
593 qDebug() <<
"=== TemplateObject size" << tmpl->size;
594 for (
uint i = 0;
i < tmpl->size; ++
i) {
595 qDebug() <<
" " <<
i << stringForIndex(tmpl->stringIndexAt(
i));
596 qDebug() <<
" raw: " << stringForIndex(tmpl->rawStringIndexAt(
i));
609 block->
nLocals = irBlock->locals.size();
615 for (
int i = 0;
i < irBlock->locals.size(); ++
i)
616 locals[
i] = getStringId(irBlock->locals.at(
i));
620 qDebug() <<
"=== Variables for block" << irBlock->blockIndex;
621 for (
int i = 0;
i < irBlock->locals.size(); ++
i)
622 qDebug() <<
" " <<
i <<
":" << locals[
i];
630 memset(&unit, 0,
sizeof(unit));
633 unit.
flags |=
module->unitFlags;
677 *jsClassDataOffset = nextOffset;
678 nextOffset += jsClassData.size();
686 constexpr auto spaceForTranslationContextId =
sizeof(
quint32_le);
687 nextOffset += spaceForTranslationContextId;
693 *tableSizePtr =
count;
694 *offsetPtr = nextOffset;
714 for (
int i = 0;
i <
module->functions.size(); ++
i) {
715 Context *
f =
module->functions.at(i);
716 blockAndFunctionOffsets[
i] = nextOffset;
719 f->arguments.size(),
f->locals.size(),
f->lineAndStatementNumberMapping.size(),
720 f->nestedContexts.size(),
int(
f->labelInfo.size()),
f->code.size());
721 functionSize +=
size -
f->code.size();
725 blockAndFunctionOffsets +=
module->functions.size();
727 for (
int i = 0;
i <
module->classes.size(); ++
i) {
728 const Class &
c =
module->classes.at(i);
729 blockAndFunctionOffsets[
i] = nextOffset;
733 blockAndFunctionOffsets +=
module->classes.size();
735 for (
int i = 0;
i <
module->templateObjects.size(); ++
i) {
736 const TemplateObject &
t =
module->templateObjects.at(i);
737 blockAndFunctionOffsets[
i] = nextOffset;
741 blockAndFunctionOffsets +=
module->templateObjects.size();
743 for (
int i = 0;
i <
module->blocks.size(); ++
i) {
744 Context *
c =
module->blocks.at(i);
745 blockAndFunctionOffsets[
i] = nextOffset;
750 if (
option == GenerateWithStringTable) {
754 nextOffset += stringTable.sizeOfTableAndData();
762 unit.
sourceTimeStamp =
module->sourceTimeStamp.isValid() ? module->sourceTimeStamp.toMSecsSinceEpoch() : 0;
769 qDebug() <<
"Generated JS unit that is" << unit.
unitSize <<
"bytes contains:";
770 qDebug() <<
" " << functionSize <<
"bytes for non-code function data for" << unit.
functionTableSize <<
"functions";
771 qDebug() <<
" " << translations.size() *
sizeof(CompiledData::TranslationData) <<
"bytes for" << translations.size() <<
"translations";
const_iterator cend() const noexcept
const_iterator constFind(const T &value) const
iterator insert(const T &value)
\macro QT_RESTRICTED_CAST_FROM_ASCII
qsizetype size() const noexcept
Returns the number of characters in this string.
const QChar at(qsizetype i) const
Returns the character at the given index position in the string.
QHash< int, QWidget * > hash
[35multi]
QSet< QString >::iterator it
Combined button and popup list for selecting options.
static const char magic_str[]
static size_t roundUpToMultipleOf(size_t divisor, size_t x)
Q_CORE_EXPORT char * qstrcpy(char *dst, const char *src)
DBusConnection const char DBusError DBusBusType DBusError return DBusConnection DBusHandleMessageFunction void DBusFreeFunction return DBusConnection return DBusConnection return const char DBusError return DBusConnection DBusMessage dbus_uint32_t return DBusConnection dbus_bool_t DBusConnection DBusAddWatchFunction DBusRemoveWatchFunction DBusWatchToggledFunction void DBusFreeFunction return DBusConnection DBusDispatchStatusFunction void DBusFreeFunction DBusTimeout return DBusTimeout return DBusWatch return DBusWatch unsigned int return DBusError const DBusError return const DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessage return DBusMessageIter int const void return DBusMessageIter DBusMessageIter return DBusMessageIter void DBusMessageIter void int return DBusMessage DBusMessageIter return DBusMessageIter return DBusMessageIter DBusMessageIter const char const char const char const char * method
QLEInteger< quint32 > quint32_le
QLEInteger< quint64 > quint64_le
static quint32 checksum(const QByteArray &table)
GLboolean GLboolean GLboolean b
GLsizei const GLfloat * v
[13]
GLint GLint GLint GLint GLint x
[0]
GLenum GLuint GLintptr GLsizeiptr size
[1]
GLsizei const GLchar ** strings
[1]
GLenum GLenum GLsizei count
GLenum GLuint GLintptr offset
GLenum GLenum GLsizei void * table
Members members(const Members &candidates, QTypeRevision maxMajorVersion, Postprocess &&process)
Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept
#define Q_ALLOCA_VAR(type, name, size)
#define QV4_DATA_STRUCTURE_VERSION
static constexpr qsizetype jsClassMembersOffset
static QV4::CompiledData::Lookup::Mode lookupMode(QV4::Compiler::JSUnitGenerator::LookupMode mode)
QT_BEGIN_NAMESPACE typedef uchar * output
QNetworkRequest request(url)
quint16_le sizeOfLocalTemporalDeadZone
static int calculateSize(int nLocals)
static int calculateSize(int nStaticMethods, int nMethods)
quint32_le constructorFunction
static int calculateSize(int nFormals, int nLocals, int nLinesAndStatements, int nInnerfunctions, int labelInfoSize, int codeSize)
void set(quint32 nameOffset, bool isAccessor)
static int calculateSize(int nMembers)
@ Type_QmlContextPropertyGetter
static int calculateSize(const QString &str)
static int calculateSize(int size)
quint32_le offsetToLookupTable
quint32_le offsetToIndirectExportEntryTable
quint32_le offsetToJSClassTable
quint32_le jsClassTableSize
quint32_le offsetToTemplateObjectTable
quint32_le functionTableSize
quint32_le offsetToRegexpTable
quint32_le importEntryTableSize
quint32_le starExportEntryTableSize
quint32_le lookupTableSize
qint32_le indexOfRootFunction
QString stringAtInternal(uint idx) const
quint32_le offsetToLocalExportEntryTable
quint32_le offsetToClassTable
quint32_le classTableSize
quint32_le offsetToStringTable
quint32_le offsetToQmlUnit
quint32_le offsetToFunctionTable
quint32_le offsetToStarExportEntryTable
quint32_le offsetToModuleRequestTable
quint32_le translationTableSize
quint32_le sourceFileIndex
quint32_le moduleRequestTableSize
quint32_le offsetToTranslationTable
char libraryVersionHash[QmlCompileHashSpace]
quint32_le blockTableSize
quint32_le templateObjectTableSize
quint32_le localExportEntryTableSize
quint32_le regexpTableSize
quint32_le offsetToImportEntryTable
quint32_le stringTableSize
quint32_le constantTableSize
qint64_le sourceTimeStamp
char dependencyMD5Checksum[16]
quint32_le offsetToConstantTable
quint32_le offsetToBlockTable
quint32_le indirectExportEntryTableSize
int registerJSClass(const QStringList &members)
QString jsClassMember(int jsClassId, int member) const
int registerGlobalGetterLookup(int nameIndex, LookupMode mode)
void writeTemplateObject(char *f, const TemplateObject &o)
static void generateUnitChecksum(CompiledData::Unit *unit)
ReturnedValue constant(int idx) const
JSUnitGenerator(Module *module)
int registerTranslation(const CompiledData::TranslationData &translation)
void writeBlock(char *f, Context *irBlock) const
void writeClass(char *f, const Class &c)
int registerRegExp(QQmlJS::AST::RegExpLiteral *regexp)
QV4::CompiledData::Unit * generateUnit(GeneratorOption option=GenerateWithStringTable)
int registerSetterLookup(const QString &name)
int registerQmlContextPropertyGetterLookup(int nameIndex, LookupMode mode)
void writeFunction(char *f, Context *irFunction) const
int jsClassSize(int jsClassId) const
int registerConstant(ReturnedValue v)
int registerGetterLookup(const QString &name, LookupMode mode)
int registerString(const QString &str)
int getStringId(const QString &string) const
int registerString(const QString &str)
void serialize(CompiledData::Unit *unit)
void initializeFromBackingUnit(const CompiledData::Unit *unit)
static bool initType(QV4::CompiledData::ParameterType *type, const IdGenerator &idGenerator, const QQmlJS::AST::Type *annotation)