diff options
Diffstat (limited to 'src/qml/compiler/qv4compileddata.cpp')
-rw-r--r-- | src/qml/compiler/qv4compileddata.cpp | 117 |
1 files changed, 75 insertions, 42 deletions
diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 8dcc068a06..c809d497fd 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -78,26 +78,10 @@ namespace CompiledData { static_assert(sizeof(Unit::libraryVersionHash) >= QML_COMPILE_HASH_LENGTH + 1, "Compile hash length exceeds reserved size in data structure. Please adjust and bump the format version"); -#if !defined(V4_BOOTSTRAP) -static QString cacheFilePath(const QUrl &url) +CompilationUnit::CompilationUnit(const Unit *unitData) { - const QString localSourcePath = QQmlFile::urlToLocalFileOrQrc(url); - const QString localCachePath = localSourcePath + QLatin1Char('c'); -#ifndef Q_OS_ANDROID - if (QFile::exists(localCachePath) || QFileInfo(QFileInfo(localSourcePath).dir().absolutePath()).isWritable()) - return localCachePath; -#endif - QCryptographicHash fileNameHash(QCryptographicHash::Sha1); - fileNameHash.addData(localSourcePath.toUtf8()); - QString directory = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1String("/qmlcache/"); - QDir::root().mkpath(directory); - return directory + QString::fromUtf8(fileNameHash.result().toHex()) + QLatin1Char('.') + QFileInfo(localCachePath).completeSuffix(); + data = unitData; } -#endif - -CompilationUnit::CompilationUnit(const Unit *unitData) - : data(unitData) -{} #ifndef V4_BOOTSTRAP CompilationUnit::~CompilationUnit() @@ -108,6 +92,17 @@ CompilationUnit::~CompilationUnit() data = nullptr; } +QString CompilationUnit::localCacheFilePath(const QUrl &url) +{ + const QString localSourcePath = QQmlFile::urlToLocalFileOrQrc(url); + const QString cacheFileSuffix = QFileInfo(localSourcePath + QLatin1Char('c')).completeSuffix(); + QCryptographicHash fileNameHash(QCryptographicHash::Sha1); + fileNameHash.addData(localSourcePath.toUtf8()); + QString directory = QStandardPaths::writableLocation(QStandardPaths::CacheLocation) + QLatin1String("/qmlcache/"); + QDir::root().mkpath(directory); + return directory + QString::fromUtf8(fileNameHash.result().toHex()) + QLatin1Char('.') + cacheFileSuffix; +} + QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine) { this->engine = engine; @@ -157,15 +152,15 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine) } if (data->jsClassTableSize) { - runtimeClasses = (QV4::InternalClass**)malloc(data->jsClassTableSize * sizeof(QV4::InternalClass*)); + runtimeClasses = (QV4::Heap::InternalClass **)malloc(data->jsClassTableSize * sizeof(QV4::Heap::InternalClass *)); + // memset the regexps to 0 in case a GC run happens while we're within the loop below + memset(runtimeClasses, 0, data->jsClassTableSize * sizeof(QV4::Heap::InternalClass *)); for (uint i = 0; i < data->jsClassTableSize; ++i) { int memberCount = 0; const CompiledData::JSClassMember *member = data->jsClassAt(i, &memberCount); - QV4::InternalClass *klass = engine->internalClasses[QV4::ExecutionEngine::Class_Object]; + runtimeClasses[i] = engine->internalClasses(QV4::ExecutionEngine::Class_Object); for (int j = 0; j < memberCount; ++j, ++member) - klass = klass->addMember(engine->identifierTable->identifier(runtimeStrings[member->nameOffset]), member->isAccessor ? QV4::Attr_Accessor : QV4::Attr_Data); - - runtimeClasses[i] = klass; + runtimeClasses[i] = runtimeClasses[i]->addMember(engine->identifierTable->identifier(runtimeStrings[member->nameOffset]), member->isAccessor ? QV4::Attr_Accessor : QV4::Attr_Data); } } @@ -215,8 +210,6 @@ void CompilationUnit::unlink() propertyCaches.clear(); - for (int ii = 0; ii < dependentScripts.count(); ++ii) - dependentScripts.at(ii)->release(); dependentScripts.clear(); typeNameCache = nullptr; @@ -244,13 +237,31 @@ void CompilationUnit::unlink() void CompilationUnit::markObjects(QV4::MarkStack *markStack) { - for (uint i = 0; i < data->stringTableSize; ++i) - if (runtimeStrings[i]) - runtimeStrings[i]->mark(markStack); + if (runtimeStrings) { + for (uint i = 0; i < data->stringTableSize; ++i) + if (runtimeStrings[i]) + runtimeStrings[i]->mark(markStack); + } if (runtimeRegularExpressions) { for (uint i = 0; i < data->regexpTableSize; ++i) runtimeRegularExpressions[i].mark(markStack); } + if (runtimeClasses) { + for (uint i = 0; i < data->jsClassTableSize; ++i) + if (runtimeClasses[i]) + runtimeClasses[i]->mark(markStack); + } + for (QV4::Function *f : qAsConst(runtimeFunctions)) + if (f && f->internalClass) + f->internalClass->mark(markStack); + for (QV4::Heap::InternalClass *c : qAsConst(runtimeBlocks)) + if (c) + c->mark(markStack); + + if (runtimeLookups) { + for (uint i = 0; i < data->lookupTableSize; ++i) + runtimeLookups[i].markObjects(markStack); + } } IdentifierHash CompilationUnit::namedObjectsPerComponent(int componentObjectIndex) @@ -344,7 +355,11 @@ bool CompilationUnit::loadFromDisk(const QUrl &url, const QDateTime &sourceTimeS const QString sourcePath = QQmlFile::urlToLocalFileOrQrc(url); QScopedPointer<CompilationUnitMapper> cacheFile(new CompilationUnitMapper()); - CompiledData::Unit *mappedUnit = cacheFile->open(cacheFilePath(url), sourceTimeStamp, errorString); + QString cachePath = sourcePath + QLatin1Char('c'); + if (!QFile::exists(cachePath)) + cachePath = localCacheFilePath(url); + + CompiledData::Unit *mappedUnit = cacheFile->open(cachePath, sourceTimeStamp, errorString); if (!mappedUnit) return false; @@ -367,7 +382,22 @@ void CompilationUnit::linkBackendToEngine(ExecutionEngine *engine) runtimeFunctions.resize(data->functionTableSize); for (int i = 0 ;i < runtimeFunctions.size(); ++i) { const QV4::CompiledData::Function *compiledFunction = data->functionAt(i); - runtimeFunctions[i] = new QV4::Function(engine, this, compiledFunction, &Moth::VME::exec); + runtimeFunctions[i] = new QV4::Function(engine, this, compiledFunction); + } + + Scope scope(engine); + Scoped<InternalClass> ic(scope); + + runtimeBlocks.resize(data->blockTableSize); + for (int i = 0 ;i < runtimeBlocks.size(); ++i) { + const QV4::CompiledData::Block *compiledBlock = data->blockAt(i); + ic = engine->internalClasses(EngineBase::Class_CallContext); + + // first locals + const quint32_le *localsIndices = compiledBlock->localsTable(); + for (quint32 i = 0; i < compiledBlock->nLocals; ++i) + ic = ic->addMember(engine->identifierTable->identifier(runtimeStrings[localsIndices[i]]), Attr_NotConfigurable); + runtimeBlocks[i] = ic->d(); } } @@ -391,7 +421,7 @@ bool CompilationUnit::saveToDisk(const QUrl &unitUrl, QString *errorString) *errorString = QStringLiteral("File has to be a local file."); return false; } - const QString outputFileName = cacheFilePath(unitUrl); + const QString outputFileName = localCacheFilePath(unitUrl); #endif #if QT_CONFIG(temporaryfile) @@ -476,8 +506,11 @@ Unit *CompilationUnit::createUnitData(QmlIR::Document *irDocument) QQmlJS::AST::FormalParameterList *parameters = QQmlJS::AST::cast<QQmlJS::AST::FunctionDeclaration*>(foe->node)->formals; changedSignalParameters << parameters; - for (; parameters; parameters = parameters->next) - stringTable.registerString(parameters->name.toString()); + if (parameters) { + const QStringList formals = parameters->formals(); + for (const QString &arg : formals) + stringTable.registerString(arg); + } } } @@ -500,14 +533,14 @@ Unit *CompilationUnit::createUnitData(QmlIR::Document *irDocument) function->formalsOffset = signalParameterNameTableOffset - jsUnit->functionOffsetTable()[functionIndex]; - for (QQmlJS::AST::FormalParameterList *parameters = changedSignalParameters.at(i); - parameters; parameters = parameters->next) { - signalParameterNameTable.append(stringTable.getStringId(parameters->name.toString())); - function->nFormals = function->nFormals + 1; - } + if (QQmlJS::AST::FormalParameterList *parameters = changedSignalParameters.at(i)) { + const QStringList formals = parameters->formals(); + for (const QString &arg : formals) + signalParameterNameTable.append(stringTable.getStringId(arg)); - // Hack to ensure an activation is created. - function->flags |= QV4::CompiledData::Function::HasCatchOrWith | QV4::CompiledData::Function::HasDirectEval; + function->nFormals = formals.size(); + } + function->length = function->nFormals; signalParameterNameTableOffset += function->nFormals * sizeof(quint32); } @@ -626,7 +659,7 @@ QString Binding::valueAsScriptString(const Unit *unit) const /*! Returns the property cache, if one alread exists. The cache is not referenced. */ -QQmlPropertyCache *ResolvedTypeReference::propertyCache() const +QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::propertyCache() const { if (type.isValid()) return typePropertyCache; @@ -637,7 +670,7 @@ QQmlPropertyCache *ResolvedTypeReference::propertyCache() const /*! Returns the property cache, creating one if it doesn't already exist. The cache is not referenced. */ -QQmlPropertyCache *ResolvedTypeReference::createPropertyCache(QQmlEngine *engine) +QQmlRefPointer<QQmlPropertyCache> ResolvedTypeReference::createPropertyCache(QQmlEngine *engine) { if (typePropertyCache) { return typePropertyCache; |