diff options
Diffstat (limited to 'src/qml/compiler')
-rw-r--r-- | src/qml/compiler/qqmlirbuilder.cpp | 411 | ||||
-rw-r--r-- | src/qml/compiler/qqmlirbuilder_p.h | 40 | ||||
-rw-r--r-- | src/qml/compiler/qqmltypecompiler.cpp | 34 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen.cpp | 368 | ||||
-rw-r--r-- | src/qml/compiler/qv4codegen_p.h | 181 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata.cpp | 22 | ||||
-rw-r--r-- | src/qml/compiler/qv4compileddata_p.h | 39 | ||||
-rw-r--r-- | src/qml/compiler/qv4compiler.cpp | 57 | ||||
-rw-r--r-- | src/qml/compiler/qv4compiler_p.h | 2 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilercontext.cpp | 7 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilercontext_p.h | 6 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilerscanfunctions.cpp | 27 | ||||
-rw-r--r-- | src/qml/compiler/qv4compilerscanfunctions_p.h | 7 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth.cpp | 44 | ||||
-rw-r--r-- | src/qml/compiler/qv4instr_moth_p.h | 20 |
15 files changed, 322 insertions, 943 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp index ea5efcfc66..a22dd7aa32 100644 --- a/src/qml/compiler/qqmlirbuilder.cpp +++ b/src/qml/compiler/qqmlirbuilder.cpp @@ -566,7 +566,7 @@ bool IRBuilder::visit(QQmlJS::AST::UiQualifiedId *id) void IRBuilder::accept(QQmlJS::AST::Node *node) { - QQmlJS::AST::Node::acceptChild(node, this); + QQmlJS::AST::Node::accept(node, this); } bool IRBuilder::defineQMLObject(int *objectIndex, QQmlJS::AST::UiQualifiedId *qualifiedTypeNameId, const QQmlJS::AST::SourceLocation &location, QQmlJS::AST::UiObjectInitializer *initializer, Object *declarationsOverride) @@ -974,7 +974,6 @@ bool IRBuilder::visit(QQmlJS::AST::UiSourceElement *node) foe->node = funDecl; foe->parentNode = funDecl; foe->nameIndex = registerString(funDecl->name.toString()); - foe->disableAcceleratedLookups = false; const int index = _object->functionsAndExpressions->append(foe); Function *f = New<Function>(); @@ -1098,7 +1097,6 @@ void IRBuilder::setBindingValue(QV4::CompiledData::Binding *binding, QQmlJS::AST expr->parentNode = parentNode; expr->nameIndex = registerString(QLatin1String("expression for ") + stringAt(binding->propertyNameIndex)); - expr->disableAcceleratedLookups = false; const int index = bindingsTarget()->functionsAndExpressions->append(expr); binding->value.compiledScriptIndex = index; // We don't need to store the binding script as string, except for script strings @@ -1825,19 +1823,13 @@ char *QmlUnitGenerator::writeBindings(char *bindingPtr, const Object *o, Binding JSCodeGen::JSCodeGen(const QString &sourceCode, QV4::Compiler::JSUnitGenerator *jsUnitGenerator, QV4::Compiler::Module *jsModule, QQmlJS::Engine *jsEngine, - QQmlJS::AST::UiProgram *qmlRoot, QQmlTypeNameCache *imports, + QQmlJS::AST::UiProgram *qmlRoot, const QV4::Compiler::StringTableGenerator *stringPool, const QSet<QString> &globalNames) : QV4::Compiler::Codegen(jsUnitGenerator, /*strict mode*/false) , sourceCode(sourceCode) , jsEngine(jsEngine) , qmlRoot(qmlRoot) - , imports(imports) , stringPool(stringPool) - , _disableAcceleratedLookups(false) - , _contextObject(nullptr) - , _scopeObject(nullptr) - , _qmlContextSlot(-1) - , _importedScriptsSlot(-1) { m_globalNames = globalNames; @@ -1845,18 +1837,6 @@ JSCodeGen::JSCodeGen(const QString &sourceCode, QV4::Compiler::JSUnitGenerator * _fileNameIsUrl = true; } -void JSCodeGen::beginContextScope(const JSCodeGen::ObjectIdMapping &objectIds, QQmlPropertyCache *contextObject) -{ - _idObjects = objectIds; - _contextObject = contextObject; - _scopeObject = nullptr; -} - -void JSCodeGen::beginObjectScope(QQmlPropertyCache *scopeObject) -{ - _scopeObject = scopeObject; -} - QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<CompiledFunctionOrExpression> &functions) { auto qmlName = [&](const CompiledFunctionOrExpression &c) { @@ -1921,7 +1901,6 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<Compil body = body->finish(); } - _disableAcceleratedLookups = qmlFunction.disableAcceleratedLookups; int idx = defineFunction(name, function ? function : qmlFunction.parentNode, function ? function->formals : nullptr, body); @@ -1931,391 +1910,6 @@ QVector<int> JSCodeGen::generateJSCodeForFunctionsAndBindings(const QList<Compil return runtimeFunctionIndices; } -int JSCodeGen::defineFunction(const QString &name, AST::Node *ast, AST::FormalParameterList *formals, AST::StatementList *body) -{ - int qmlContextTemp = -1; - int importedScriptsTemp = -1; - qSwap(_qmlContextSlot, qmlContextTemp); - qSwap(_importedScriptsSlot, importedScriptsTemp); - - int result = Codegen::defineFunction(name, ast, formals, body); - - qSwap(_importedScriptsSlot, importedScriptsTemp); - qSwap(_qmlContextSlot, qmlContextTemp); - - return result; -} - -#ifndef V4_BOOTSTRAP -QQmlPropertyData *JSCodeGen::lookupQmlCompliantProperty(QQmlPropertyCache *cache, const QString &name) -{ - QQmlPropertyData *pd = cache->property(name, /*object*/nullptr, /*context*/nullptr); - - if (pd && !cache->isAllowedInRevision(pd)) - return nullptr; - - return pd; -} - -enum MetaObjectResolverFlags { - AllPropertiesAreFinal = 0x1, - LookupsIncludeEnums = 0x2, - LookupsExcludeProperties = 0x4, - ResolveTypeInformationOnly = 0x8 -}; - -#if 0 -static void initMetaObjectResolver(QV4::IR::MemberExpressionResolver *resolver, QQmlPropertyCache *metaObject); - -static void initScopedEnumResolver(QV4::IR::MemberExpressionResolver *resolver, const QQmlType &qmlType, int index); - -static QV4::IR::DiscoveredType resolveQmlType(QQmlEnginePrivate *qmlEngine, - const QV4::IR::MemberExpressionResolver *resolver, - QV4::IR::Member *member) -{ - QV4::IR::Type result = QV4::IR::VarType; - - QQmlType type = resolver->qmlType; - - if (member->name->constData()->isUpper()) { - bool ok = false; - int value = type.enumValue(qmlEngine, *member->name, &ok); - if (ok) { - member->setEnumValue(value); - return QV4::IR::SInt32Type; - } else { - int index = type.scopedEnumIndex(qmlEngine, *member->name, &ok); - if (ok) { - auto newResolver = resolver->owner->New<QV4::IR::MemberExpressionResolver>(); - newResolver->owner = resolver->owner; - initScopedEnumResolver(newResolver, type, index); - return QV4::IR::DiscoveredType(newResolver); - } - } - } - - if (type.isCompositeSingleton()) { - QQmlRefPointer<QQmlTypeData> tdata = qmlEngine->typeLoader.getType(type.singletonInstanceInfo()->url); - Q_ASSERT(tdata); - tdata->release(); // Decrease the reference count added from QQmlTypeLoader::getType() - // When a singleton tries to reference itself, it may not be complete yet. - if (tdata->isComplete()) { - auto newResolver = resolver->owner->New<QV4::IR::MemberExpressionResolver>(); - newResolver->owner = resolver->owner; - initMetaObjectResolver(newResolver, qmlEngine->propertyCacheForType(tdata->compilationUnit()->metaTypeId)); - newResolver->flags |= AllPropertiesAreFinal; - return newResolver->resolveMember(qmlEngine, newResolver, member); - } - } else if (type.isSingleton()) { - const QMetaObject *singletonMeta = type.singletonInstanceInfo()->instanceMetaObject; - if (singletonMeta) { // QJSValue-based singletons cannot be accelerated - auto newResolver = resolver->owner->New<QV4::IR::MemberExpressionResolver>(); - newResolver->owner = resolver->owner; - initMetaObjectResolver(newResolver, qmlEngine->cache(singletonMeta)); - member->kind = QV4::IR::Member::MemberOfSingletonObject; - return newResolver->resolveMember(qmlEngine, newResolver, member); - } - } -#if 0 - else if (const QMetaObject *attachedMeta = type->attachedPropertiesType(qmlEngine)) { - // Right now the attached property IDs are not stable and cannot be embedded in the - // code that is cached on disk. - QQmlPropertyCache *cache = qmlEngine->cache(attachedMeta); - auto newResolver = resolver->owner->New<QV4::IR::MemberExpressionResolver>(); - newResolver->owner = resolver->owner; - initMetaObjectResolver(newResolver, cache); - member->setAttachedPropertiesId(type->attachedPropertiesId(qmlEngine)); - return newResolver->resolveMember(qmlEngine, newResolver, member); - } -#endif - - return result; -} - -static void initQmlTypeResolver(QV4::IR::MemberExpressionResolver *resolver, const QQmlType &qmlType) -{ - Q_ASSERT(resolver); - - resolver->resolveMember = &resolveQmlType; - resolver->qmlType = qmlType; - resolver->typenameCache = 0; - resolver->flags = 0; -} - -static QV4::IR::DiscoveredType resolveImportNamespace( - QQmlEnginePrivate *, const QV4::IR::MemberExpressionResolver *resolver, - QV4::IR::Member *member) -{ - QV4::IR::Type result = QV4::IR::VarType; - QQmlTypeNameCache *typeNamespace = resolver->typenameCache; - const QQmlImportRef *importNamespace = resolver->import; - - QQmlTypeNameCache::Result r = typeNamespace->query(*member->name, importNamespace); - if (r.isValid()) { - member->freeOfSideEffects = true; - if (r.scriptIndex != -1) { - // TODO: remember the index and replace with subscript later. - result = QV4::IR::VarType; - } else if (r.type.isValid()) { - // TODO: Propagate singleton information, so that it is loaded - // through the singleton getter in the run-time. Until then we - // can't accelerate access :( - if (!r.type.isSingleton()) { - auto newResolver = resolver->owner->New<QV4::IR::MemberExpressionResolver>(); - newResolver->owner = resolver->owner; - initQmlTypeResolver(newResolver, r.type); - return QV4::IR::DiscoveredType(newResolver); - } - } else { - Q_ASSERT(false); // How can this happen? - } - } - - return result; -} - -static void initImportNamespaceResolver(QV4::IR::MemberExpressionResolver *resolver, - QQmlTypeNameCache *imports, const QQmlImportRef *importNamespace) -{ - resolver->resolveMember = &resolveImportNamespace; - resolver->import = importNamespace; - resolver->typenameCache = imports; - resolver->flags = 0; -} - -static QV4::IR::DiscoveredType resolveMetaObjectProperty( - QQmlEnginePrivate *qmlEngine, const QV4::IR::MemberExpressionResolver *resolver, - QV4::IR::Member *member) -{ - QV4::IR::Type result = QV4::IR::VarType; - QQmlPropertyCache *metaObject = resolver->propertyCache; - - if (member->name->constData()->isUpper() && (resolver->flags & LookupsIncludeEnums)) { - const QMetaObject *mo = metaObject->createMetaObject(); - QByteArray enumName = member->name->toUtf8(); - for (int ii = mo->enumeratorCount() - 1; ii >= 0; --ii) { - QMetaEnum metaEnum = mo->enumerator(ii); - bool ok; - int value = metaEnum.keyToValue(enumName.constData(), &ok); - if (ok) { - member->setEnumValue(value); - return QV4::IR::SInt32Type; - } - } - } - - if (member->kind != QV4::IR::Member::MemberOfIdObjectsArray && member->kind != QV4::IR::Member::MemberOfSingletonObject && - qmlEngine && !(resolver->flags & LookupsExcludeProperties)) { - QQmlPropertyData *property = member->property; - if (!property && metaObject) { - if (QQmlPropertyData *candidate = metaObject->property(*member->name, /*object*/0, /*context*/0)) { - const bool isFinalProperty = (candidate->isFinal() || (resolver->flags & AllPropertiesAreFinal)) - && !candidate->isFunction(); - - if (lookupHints() - && !(resolver->flags & AllPropertiesAreFinal) - && !candidate->isFinal() - && !candidate->isFunction() - && candidate->isDirect()) { - qWarning() << "Hint: Access to property" << *member->name << "of" << metaObject->className() << "could be accelerated if it was marked as FINAL"; - } - - if (isFinalProperty && metaObject->isAllowedInRevision(candidate)) { - property = candidate; - member->inhibitTypeConversionOnWrite = true; - if (!(resolver->flags & ResolveTypeInformationOnly)) - member->property = candidate; // Cache for next iteration and isel needs it. - } - } - } - - if (property) { - // Enums cannot be mapped to IR types, they need to go through the run-time handling - // of accepting strings that will then be converted to the right values. - if (property->isEnum()) - return QV4::IR::VarType; - - switch (property->propType()) { - case QMetaType::Bool: result = QV4::IR::BoolType; break; - case QMetaType::Int: result = QV4::IR::SInt32Type; break; - case QMetaType::Double: result = QV4::IR::DoubleType; break; - case QMetaType::QString: result = QV4::IR::StringType; break; - default: - if (property->isQObject()) { - if (QQmlPropertyCache *cache = qmlEngine->propertyCacheForType(property->propType())) { - auto newResolver = resolver->owner->New<QV4::IR::MemberExpressionResolver>(); - newResolver->owner = resolver->owner; - initMetaObjectResolver(newResolver, cache); - return QV4::IR::DiscoveredType(newResolver); - } - } else if (const QMetaObject *valueTypeMetaObject = QQmlValueTypeFactory::metaObjectForMetaType(property->propType())) { - if (QQmlPropertyCache *cache = qmlEngine->cache(valueTypeMetaObject)) { - auto newResolver = resolver->owner->New<QV4::IR::MemberExpressionResolver>(); - newResolver->owner = resolver->owner; - initMetaObjectResolver(newResolver, cache); - newResolver->flags |= ResolveTypeInformationOnly; - return QV4::IR::DiscoveredType(newResolver); - } - } - break; - } - } - } - - return result; -} - -static void initMetaObjectResolver(QV4::IR::MemberExpressionResolver *resolver, QQmlPropertyCache *metaObject) -{ - Q_ASSERT(resolver); - - resolver->resolveMember = &resolveMetaObjectProperty; - resolver->propertyCache = metaObject; - resolver->flags = 0; -} - -static QV4::IR::DiscoveredType resolveScopedEnum(QQmlEnginePrivate *qmlEngine, - const QV4::IR::MemberExpressionResolver *resolver, - QV4::IR::Member *member) -{ - if (!member->name->constData()->isUpper()) - return QV4::IR::VarType; - - QQmlType type = resolver->qmlType; - int index = resolver->flags; - - bool ok = false; - int value = type.scopedEnumValue(qmlEngine, index, *member->name, &ok); - if (!ok) - return QV4::IR::VarType; - member->setEnumValue(value); - return QV4::IR::SInt32Type; -} - -static void initScopedEnumResolver(QV4::IR::MemberExpressionResolver *resolver, const QQmlType &qmlType, int index) -{ - Q_ASSERT(resolver); - - resolver->resolveMember = &resolveScopedEnum; - resolver->qmlType = qmlType; - resolver->flags = index; -} -#endif - -#endif // V4_BOOTSTRAP - -void JSCodeGen::beginFunctionBodyHook() -{ - _qmlContextSlot = bytecodeGenerator->newRegister(); - _importedScriptsSlot = bytecodeGenerator->newRegister(); - -#ifndef V4_BOOTSTRAP - Instruction::LoadQmlContext load; - load.result = Reference::fromStackSlot(this, _qmlContextSlot).stackSlot(); - bytecodeGenerator->addInstruction(load); - -#if 0 - temp->type = QV4::IR::QObjectType; - temp->memberResolver = _function->New<QV4::IR::MemberExpressionResolver>(); - initMetaObjectResolver(temp->memberResolver, _scopeObject); - auto name = _block->NAME(QV4::IR::Name::builtin_qml_context, 0, 0); - name->type = temp->type; -#endif - - Instruction::LoadQmlImportedScripts loadScripts; - loadScripts.result = Reference::fromStackSlot(this, _importedScriptsSlot).stackSlot(); - bytecodeGenerator->addInstruction(loadScripts); -#endif -} - -QV4::Compiler::Codegen::Reference JSCodeGen::fallbackNameLookup(const QString &name) -{ -#ifndef V4_BOOTSTRAP - if (_disableAcceleratedLookups) - return Reference(); - - // Implement QML lookup semantics in the current file context. - // - // Note: We do not check if properties of the qml scope object or context object - // are final. That's because QML tries to get as close as possible to lexical scoping, - // which means in terms of properties that only those visible at compile time are chosen. - // I.e. access to a "foo" property declared within the same QML component as "property int foo" - // will always access that instance and as integer. If a sub-type implements its own property string foo, - // then that one is not chosen for accesses from within this file, because it wasn't visible at compile - // time. This corresponds to the logic in QQmlPropertyCache::findProperty to find the property associated - // with the correct QML context. - - // Look for IDs first. - for (const IdMapping &mapping : qAsConst(_idObjects)) { - if (name == mapping.name) { - if (_context->contextType == QV4::Compiler::ContextType::Binding) - _context->idObjectDependencies.insert(mapping.idIndex); - - Instruction::LoadIdObject load; - load.base = Reference::fromStackSlot(this, _qmlContextSlot).stackSlot(); - load.index = mapping.idIndex; - - Reference result = Reference::fromAccumulator(this); - bytecodeGenerator->addInstruction(load); - result.isReadonly = true; - return result; - } - } - - if (name.at(0).isUpper()) { - QQmlTypeNameCache::Result r = imports->query(name); - if (r.isValid()) { - if (r.scriptIndex != -1) { - Reference imports = Reference::fromStackSlot(this, _importedScriptsSlot); - return Reference::fromSubscript(imports, Reference::fromConst(this, QV4::Encode(r.scriptIndex))); - } else if (r.type.isValid()) { - return Reference::fromName(this, name); - } else { - Q_ASSERT(r.importNamespace); - return Reference::fromName(this, name); - } - } - } - - if (_scopeObject) { - QQmlPropertyData *data = lookupQmlCompliantProperty(_scopeObject, name); - if (data) { - // Q_INVOKABLEs can't be FINAL, so we have to look them up at run-time - if (data->isFunction()) - return Reference::fromName(this, name); - - Reference base = Reference::fromStackSlot(this, _qmlContextSlot); - Reference::PropertyCapturePolicy capturePolicy; - if (!data->isConstant() && !data->isQmlBinding()) - capturePolicy = Reference::CaptureAtRuntime; - else - capturePolicy = data->isConstant() ? Reference::DontCapture : Reference::CaptureAheadOfTime; - return Reference::fromQmlScopeObject(base, data->coreIndex(), data->notifyIndex(), capturePolicy); - } - } - - if (_contextObject) { - QQmlPropertyData *data = lookupQmlCompliantProperty(_contextObject, name); - if (data) { - // Q_INVOKABLEs can't be FINAL, so we have to look them up at run-time - if (data->isFunction()) - return Reference::fromName(this, name); - - Reference base = Reference::fromStackSlot(this, _qmlContextSlot); - Reference::PropertyCapturePolicy capturePolicy; - if (!data->isConstant() && !data->isQmlBinding()) - capturePolicy = Reference::CaptureAtRuntime; - else - capturePolicy = data->isConstant() ? Reference::DontCapture : Reference::CaptureAheadOfTime; - return Reference::fromQmlContextObject(base, data->coreIndex(), data->notifyIndex(), capturePolicy); - } - } -#else - Q_UNUSED(name) -#endif // V4_BOOTSTRAP - return Reference(); -} - #ifndef V4_BOOTSTRAP QQmlPropertyData *PropertyResolver::property(const QString &name, bool *notInRevision, RevisionCheck check) const @@ -2435,7 +2029,6 @@ QmlIR::Object *IRLoader::loadObject(const QV4::CompiledData::Object *serializedO b->value.compiledScriptIndex = functionIndices.count() - 1; QmlIR::CompiledFunctionOrExpression *foe = pool->New<QmlIR::CompiledFunctionOrExpression>(); - foe->disableAcceleratedLookups = true; foe->nameIndex = 0; QQmlJS::AST::ExpressionNode *expr; diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h index 8512b22fbd..298fe7dd92 100644 --- a/src/qml/compiler/qqmlirbuilder_p.h +++ b/src/qml/compiler/qqmlirbuilder_p.h @@ -278,7 +278,6 @@ struct Q_QML_PRIVATE_EXPORT CompiledFunctionOrExpression QQmlJS::AST::Node *parentNode = nullptr; // FunctionDeclaration, Statement or Expression QQmlJS::AST::Node *node = nullptr; // FunctionDeclaration, Statement or Expression quint32 nameIndex = 0; - bool disableAcceleratedLookups = false; CompiledFunctionOrExpression *next = nullptr; }; @@ -431,6 +430,12 @@ public: bool visit(QQmlJS::AST::UiScriptBinding *ast) override; bool visit(QQmlJS::AST::UiSourceElement *ast) override; + void throwRecursionDepthError() override + { + recordError(AST::SourceLocation(), + QStringLiteral("Maximum statement or expression depth exceeded")); + } + void accept(QQmlJS::AST::Node *node); // returns index in _objects @@ -533,47 +538,16 @@ struct Q_QML_PRIVATE_EXPORT JSCodeGen : public QV4::Compiler::Codegen { JSCodeGen(const QString &sourceCode, QV4::Compiler::JSUnitGenerator *jsUnitGenerator, QV4::Compiler::Module *jsModule, QQmlJS::Engine *jsEngine, QQmlJS::AST::UiProgram *qmlRoot, - QQmlTypeNameCache *imports, const QV4::Compiler::StringTableGenerator *stringPool, const QSet<QString> &globalNames); - - struct IdMapping - { - QString name; - int idIndex; - QQmlPropertyCache *type; - }; - typedef QVector<IdMapping> ObjectIdMapping; - - void beginContextScope(const ObjectIdMapping &objectIds, QQmlPropertyCache *contextObject); - void beginObjectScope(QQmlPropertyCache *scopeObject); + const QV4::Compiler::StringTableGenerator *stringPool, const QSet<QString> &globalNames); // Returns mapping from input functions to index in IR::Module::functions / compiledData->runtimeFunctions QVector<int> generateJSCodeForFunctionsAndBindings(const QList<CompiledFunctionOrExpression> &functions); - int defineFunction(const QString &name, AST::Node *ast, - AST::FormalParameterList *formals, - AST::StatementList *body) override; - -protected: - void beginFunctionBodyHook() override; - bool canAccelerateGlobalLookups() const override { return !_disableAcceleratedLookups; } - Reference fallbackNameLookup(const QString &name) override; - private: - // returns nullptr if lookup needs to happen by name - QQmlPropertyData *lookupQmlCompliantProperty(QQmlPropertyCache *cache, const QString &name); - QString sourceCode; QQmlJS::Engine *jsEngine; // needed for memory pool QQmlJS::AST::UiProgram *qmlRoot; - QQmlTypeNameCache *imports; const QV4::Compiler::StringTableGenerator *stringPool; - - bool _disableAcceleratedLookups; - ObjectIdMapping _idObjects; - QQmlPropertyCache *_contextObject; - QQmlPropertyCache *_scopeObject; - int _qmlContextSlot; - int _importedScriptsSlot; }; struct Q_QML_PRIVATE_EXPORT IRLoader { diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp index 70b048d737..66d3afc7a0 100644 --- a/src/qml/compiler/qqmltypecompiler.cpp +++ b/src/qml/compiler/qqmltypecompiler.cpp @@ -146,8 +146,7 @@ QQmlRefPointer<QV4::CompiledData::CompilationUnit> QQmlTypeCompiler::compile() document->jsModule.fileName = typeData->urlString(); document->jsModule.finalUrl = typeData->finalUrlString(); QmlIR::JSCodeGen v4CodeGenerator(document->code, &document->jsGenerator, &document->jsModule, &document->jsParserEngine, - document->program, typeNameCache.data(), &document->jsGenerator.stringTable, engine->v8engine()->illegalNames()); - v4CodeGenerator.setUseFastLookups(false); + document->program, &document->jsGenerator.stringTable, engine->v8engine()->illegalNames()); QQmlJSCodeGenerator jsCodeGen(this, &v4CodeGenerator); if (!jsCodeGen.generateCodeForComponents()) return nullptr; @@ -767,10 +766,6 @@ void QQmlScriptStringScanner::scan() if (!pd || pd->propType() != scriptStringMetaType) continue; - QmlIR::CompiledFunctionOrExpression *foe = obj->functionsAndExpressions->slowAt(binding->value.compiledScriptIndex); - if (foe) - foe->disableAcceleratedLookups = true; - QString script = compiler->bindingAsString(obj, binding->value.compiledScriptIndex); binding->stringIndex = compiler->registerString(script); } @@ -1324,24 +1319,6 @@ bool QQmlJSCodeGenerator::compileComponent(int contextObject) contextObject = componentBinding->value.objectIndex; } - QmlIR::JSCodeGen::ObjectIdMapping idMapping; - idMapping.reserve(obj->namedObjectsInComponent.size()); - for (int i = 0; i < obj->namedObjectsInComponent.size(); ++i) { - const int objectIndex = obj->namedObjectsInComponent.at(i); - QmlIR::JSCodeGen::IdMapping m; - const QmlIR::Object *obj = qmlObjects.at(objectIndex); - m.name = stringAt(obj->idNameIndex); - m.idIndex = obj->id; - m.type = propertyCaches->at(objectIndex); - - auto *tref = resolvedType(obj->inheritedTypeNameIndex); - if (tref && tref->isFullyDynamicType) - m.type = nullptr; - - idMapping << m; - } - v4CodeGen->beginContextScope(idMapping, propertyCaches->at(contextObject)); - if (!compileJavaScriptCodeInObjectsRecursively(contextObject, contextObject)) return false; @@ -1355,16 +1332,9 @@ bool QQmlJSCodeGenerator::compileJavaScriptCodeInObjectsRecursively(int objectIn return true; if (object->functionsAndExpressions->count > 0) { - QQmlPropertyCache *scopeObject = propertyCaches->at(scopeObjectIndex); - v4CodeGen->beginObjectScope(scopeObject); - QList<QmlIR::CompiledFunctionOrExpression> functionsToCompile; - for (QmlIR::CompiledFunctionOrExpression *foe = object->functionsAndExpressions->first; foe; foe = foe->next) { - const bool haveCustomParser = customParsers.contains(object->inheritedTypeNameIndex); - if (haveCustomParser) - foe->disableAcceleratedLookups = true; + for (QmlIR::CompiledFunctionOrExpression *foe = object->functionsAndExpressions->first; foe; foe = foe->next) functionsToCompile << *foe; - } const QVector<int> runtimeFunctionIndices = v4CodeGen->generateJSCodeForFunctionsAndBindings(functionsToCompile); const QList<QQmlError> jsErrors = v4CodeGen->qmlErrors(); if (!jsErrors.isEmpty()) { diff --git a/src/qml/compiler/qv4codegen.cpp b/src/qml/compiler/qv4codegen.cpp index 1149c9ff1e..a2bfd55332 100644 --- a/src/qml/compiler/qv4codegen.cpp +++ b/src/qml/compiler/qv4codegen.cpp @@ -100,9 +100,10 @@ Codegen::Codegen(QV4::Compiler::JSUnitGenerator *jsUnitGenerator, bool strict) , hasError(false) { jsUnitGenerator->codeGeneratorName = QStringLiteral("moth"); + pushExpr(); } -const char *globalNames[] = { +const char *Codegen::s_globalNames[] = { "isNaN", "parseFloat", "String", @@ -182,7 +183,7 @@ void Codegen::generateFromProgram(const QString &fileName, // // Since this can be called from the loader thread we can't get the list // directly from the engine, so let's hardcode the most important ones here - for (const char **g = globalNames; *g != nullptr; ++g) + for (const char **g = s_globalNames; *g != nullptr; ++g) m_globalNames << QString::fromLatin1(*g); } @@ -264,7 +265,7 @@ Context *Codegen::enterBlock(Node *node) Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr) { if (hasError) - return _expr.result(); + return exprResult(); if (expr.isConstant()) { auto v = Value::fromReturnedValue(expr.constant); @@ -310,7 +311,7 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr) return Reference::fromAccumulator(this); } case PostIncrement: - if (!_expr.accept(nx) || requiresReturnValue) { + if (!exprAccept(nx) || requiresReturnValue) { Reference e = expr.asLValue(); e.loadInAccumulator(); Instruction::UPlus uplus = {}; @@ -330,13 +331,13 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr) e.loadInAccumulator(); Instruction::Increment inc = {}; bytecodeGenerator->addTracingInstruction(inc); - if (_expr.accept(nx)) + if (exprAccept(nx)) return e.storeConsumeAccumulator(); else return e.storeRetainAccumulator(); } case PostDecrement: - if (!_expr.accept(nx) || requiresReturnValue) { + if (!exprAccept(nx) || requiresReturnValue) { Reference e = expr.asLValue(); e.loadInAccumulator(); Instruction::UPlus uplus = {}; @@ -356,7 +357,7 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr) e.loadInAccumulator(); Instruction::Decrement dec = {}; bytecodeGenerator->addTracingInstruction(dec); - if (_expr.accept(nx)) + if (exprAccept(nx)) return e.storeConsumeAccumulator(); else return e.storeRetainAccumulator(); @@ -368,22 +369,13 @@ Codegen::Reference Codegen::unop(UnaryOperation op, const Reference &expr) void Codegen::addCJump() { - bytecodeGenerator->addCJumpInstruction(_expr.trueBlockFollowsCondition(), - _expr.iftrue(), _expr.iffalse()); -} - -void Codegen::accept(Node *node) -{ - if (hasError) - return; - - if (node) - node->accept(this); + const Result &expression = currentExpr(); + bytecodeGenerator->addCJumpInstruction(expression.trueBlockFollowsCondition(), + expression.iftrue(), expression.iffalse()); } void Codegen::statement(Statement *ast) { - RecursionDepthCheck depthCheck(this, ast->lastSourceLocation()); RegisterScope scope(this); bytecodeGenerator->setLocation(ast->firstSourceLocation()); @@ -399,23 +391,21 @@ void Codegen::statement(ExpressionNode *ast) if (! ast) { return; } else { - RecursionDepthCheck depthCheck(this, ast->lastSourceLocation()); RegisterScope scope(this); - Result r(nx); - qSwap(_expr, r); + pushExpr(Result(nx)); VolatileMemoryLocations vLocs = scanVolatileMemoryLocations(ast); qSwap(_volatileMemoryLocations, vLocs); accept(ast); qSwap(_volatileMemoryLocations, vLocs); - qSwap(_expr, r); + Reference result = popResult(); if (hasError) return; - if (r.result().loadTriggersSideEffect()) - r.result().loadInAccumulator(); // triggers side effects + if (result.loadTriggersSideEffect()) + result.loadInAccumulator(); // triggers side effects } } @@ -428,11 +418,9 @@ void Codegen::condition(ExpressionNode *ast, const BytecodeGenerator::Label *ift if (!ast) return; - RecursionDepthCheck depthCheck(this, ast->lastSourceLocation()); - Result r(iftrue, iffalse, trueBlockFollowsCondition); - qSwap(_expr, r); + pushExpr(Result(iftrue, iffalse, trueBlockFollowsCondition)); accept(ast); - qSwap(_expr, r); + Result r = popExpr(); if (hasError) return; @@ -450,18 +438,6 @@ void Codegen::condition(ExpressionNode *ast, const BytecodeGenerator::Label *ift } } -Codegen::Reference Codegen::expression(ExpressionNode *ast) -{ - RecursionDepthCheck depthCheck(this, ast->lastSourceLocation()); - Result r; - if (ast) { - qSwap(_expr, r); - accept(ast); - qSwap(_expr, r); - } - return r.result(); -} - void Codegen::program(Program *ast) { if (ast) { @@ -875,17 +851,13 @@ bool Codegen::visit(ExportDeclaration *ast) Reference exportedValue; if (auto *fdecl = AST::cast<FunctionDeclaration*>(ast->variableStatementOrDeclaration)) { - Result r; - qSwap(_expr, r); + pushExpr(); visit(static_cast<FunctionExpression*>(fdecl)); - qSwap(_expr, r); - exportedValue = r.result(); + exportedValue = popResult(); } else if (auto *classDecl = AST::cast<ClassDeclaration*>(ast->variableStatementOrDeclaration)) { - Result r; - qSwap(_expr, r); + pushExpr(); visit(static_cast<ClassExpression*>(classDecl)); - qSwap(_expr, r); - exportedValue = r.result(); + exportedValue = popResult(); } else if (ExpressionNode *expr = ast->variableStatementOrDeclaration->expressionCast()) { exportedValue = expression(expr); } @@ -1068,7 +1040,7 @@ bool Codegen::visit(ClassExpression *ast) (void) ctor.storeRetainAccumulator(); } - _expr.setResult(Reference::fromAccumulator(this)); + setExprResult(Reference::fromAccumulator(this)); return false; } @@ -1151,7 +1123,7 @@ bool Codegen::visit(ArrayPattern *ast) } if (!it) { - _expr.setResult(Reference::fromAccumulator(this)); + setExprResult(Reference::fromAccumulator(this)); return false; } Q_ASSERT(it->element && it->element->type == PatternElement::SpreadElement); @@ -1246,7 +1218,7 @@ bool Codegen::visit(ArrayPattern *ast) } array.loadInAccumulator(); - _expr.setResult(Reference::fromAccumulator(this)); + setExprResult(Reference::fromAccumulator(this)); return false; } @@ -1262,7 +1234,7 @@ bool Codegen::visit(ArrayMemberExpression *ast) return false; if (base.isSuper()) { Reference index = expression(ast->expression).storeOnStack(); - _expr.setResult(Reference::fromSuperProperty(index)); + setExprResult(Reference::fromSuperProperty(index)); return false; } base = base.storeOnStack(); @@ -1272,17 +1244,17 @@ bool Codegen::visit(ArrayMemberExpression *ast) QString s = str->value.toString(); uint arrayIndex = QV4::String::toArrayIndex(s); if (arrayIndex == UINT_MAX) { - _expr.setResult(Reference::fromMember(base, str->value.toString())); + setExprResult(Reference::fromMember(base, str->value.toString())); return false; } Reference index = Reference::fromConst(this, QV4::Encode(arrayIndex)); - _expr.setResult(Reference::fromSubscript(base, index)); + setExprResult(Reference::fromSubscript(base, index)); return false; } Reference index = expression(ast->expression); if (hasError) return false; - _expr.setResult(Reference::fromSubscript(base, index)); + setExprResult(Reference::fromSubscript(base, index)); return false; } @@ -1313,12 +1285,13 @@ bool Codegen::visit(BinaryExpression *ast) TailCallBlocker blockTailCalls(this); if (ast->op == QSOperator::And) { - if (_expr.accept(cx)) { + if (exprAccept(cx)) { auto iftrue = bytecodeGenerator->newLabel(); - condition(ast->left, &iftrue, _expr.iffalse(), true); + condition(ast->left, &iftrue, currentExpr().iffalse(), true); iftrue.link(); blockTailCalls.unblock(); - condition(ast->right, _expr.iftrue(), _expr.iffalse(), _expr.trueBlockFollowsCondition()); + const Result &expr = currentExpr(); + condition(ast->right, expr.iftrue(), expr.iffalse(), expr.trueBlockFollowsCondition()); } else { auto iftrue = bytecodeGenerator->newLabel(); auto endif = bytecodeGenerator->newLabel(); @@ -1340,15 +1313,16 @@ bool Codegen::visit(BinaryExpression *ast) endif.link(); - _expr.setResult(Reference::fromAccumulator(this)); + setExprResult(Reference::fromAccumulator(this)); } return false; } else if (ast->op == QSOperator::Or) { - if (_expr.accept(cx)) { + if (exprAccept(cx)) { auto iffalse = bytecodeGenerator->newLabel(); - condition(ast->left, _expr.iftrue(), &iffalse, false); + condition(ast->left, currentExpr().iftrue(), &iffalse, false); iffalse.link(); - condition(ast->right, _expr.iftrue(), _expr.iffalse(), _expr.trueBlockFollowsCondition()); + const Result &expr = currentExpr(); + condition(ast->right, expr.iftrue(), expr.iffalse(), expr.trueBlockFollowsCondition()); } else { auto iffalse = bytecodeGenerator->newLabel(); auto endif = bytecodeGenerator->newLabel(); @@ -1370,7 +1344,7 @@ bool Codegen::visit(BinaryExpression *ast) endif.link(); - _expr.setResult(Reference::fromAccumulator(this)); + setExprResult(Reference::fromAccumulator(this)); } return false; } else if (ast->op == QSOperator::Assign) { @@ -1381,9 +1355,9 @@ bool Codegen::visit(BinaryExpression *ast) return false; right = right.storeOnStack(); destructurePattern(p, right); - if (!_expr.accept(nx)) { + if (!exprAccept(nx)) { right.loadInAccumulator(); - _expr.setResult(Reference::fromAccumulator(this)); + setExprResult(Reference::fromAccumulator(this)); } return false; } @@ -1403,10 +1377,10 @@ bool Codegen::visit(BinaryExpression *ast) if (hasError) return false; r.loadInAccumulator(); - if (_expr.accept(nx)) - _expr.setResult(left.storeConsumeAccumulator()); + if (exprAccept(nx)) + setExprResult(left.storeConsumeAccumulator()); else - _expr.setResult(left.storeRetainAccumulator()); + setExprResult(left.storeRetainAccumulator()); return false; } @@ -1449,7 +1423,7 @@ bool Codegen::visit(BinaryExpression *ast) return false; binopHelper(baseOp(ast->op), tempLeft, right).loadInAccumulator(); - _expr.setResult(left.storeRetainAccumulator()); + setExprResult(left.storeRetainAccumulator()); break; } @@ -1461,7 +1435,7 @@ bool Codegen::visit(BinaryExpression *ast) Reference right = expression(ast->right); if (hasError) return false; - _expr.setResult(binopHelper(static_cast<QSOperator::Op>(ast->op), right, left)); + setExprResult(binopHelper(static_cast<QSOperator::Op>(ast->op), right, left)); break; } // intentional fall-through! @@ -1487,7 +1461,7 @@ bool Codegen::visit(BinaryExpression *ast) Reference right; if (AST::NumericLiteral *rhs = AST::cast<AST::NumericLiteral *>(ast->right)) { visit(rhs); - right = _expr.result(); + right = exprResult(); } else { left = left.storeOnStack(); // force any loads of the lhs, so the rhs won't clobber it right = expression(ast->right); @@ -1495,7 +1469,7 @@ bool Codegen::visit(BinaryExpression *ast) if (hasError) return false; - _expr.setResult(binopHelper(static_cast<QSOperator::Op>(ast->op), left, right)); + setExprResult(binopHelper(static_cast<QSOperator::Op>(ast->op), left, right)); break; } @@ -1672,7 +1646,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re break; } case QSOperator::StrictEqual: { - if (_expr.accept(cx)) + if (exprAccept(cx)) return jumpBinop(oper, left, right); Instruction::CmpStrictEqual cmp; @@ -1683,7 +1657,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re break; } case QSOperator::StrictNotEqual: { - if (_expr.accept(cx)) + if (exprAccept(cx)) return jumpBinop(oper, left, right); Instruction::CmpStrictNotEqual cmp; @@ -1694,7 +1668,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re break; } case QSOperator::Equal: { - if (_expr.accept(cx)) + if (exprAccept(cx)) return jumpBinop(oper, left, right); Instruction::CmpEq cmp; @@ -1705,7 +1679,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re break; } case QSOperator::NotEqual: { - if (_expr.accept(cx)) + if (exprAccept(cx)) return jumpBinop(oper, left, right); Instruction::CmpNe cmp; @@ -1716,7 +1690,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re break; } case QSOperator::Gt: { - if (_expr.accept(cx)) + if (exprAccept(cx)) return jumpBinop(oper, left, right); Instruction::CmpGt cmp; @@ -1727,7 +1701,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re break; } case QSOperator::Ge: { - if (_expr.accept(cx)) + if (exprAccept(cx)) return jumpBinop(oper, left, right); Instruction::CmpGe cmp; @@ -1738,7 +1712,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re break; } case QSOperator::Lt: { - if (_expr.accept(cx)) + if (exprAccept(cx)) return jumpBinop(oper, left, right); Instruction::CmpLt cmp; @@ -1749,7 +1723,7 @@ Codegen::Reference Codegen::binopHelper(QSOperator::Op oper, Reference &left, Re break; } case QSOperator::Le: - if (_expr.accept(cx)) + if (exprAccept(cx)) return jumpBinop(oper, left, right); Instruction::CmpLe cmp; @@ -1902,8 +1876,6 @@ bool Codegen::visit(CallExpression *ast) switch (base.type) { case Reference::Member: case Reference::Subscript: - case Reference::QmlScopeObject: - case Reference::QmlContextObject: base = base.asLValue(); break; case Reference::Name: @@ -1953,7 +1925,7 @@ bool Codegen::visit(CallExpression *ast) bytecodeGenerator->addInstruction(call); } - _expr.setResult(Reference::fromAccumulator(this)); + setExprResult(Reference::fromAccumulator(this)); return false; } @@ -1965,21 +1937,7 @@ bool Codegen::visit(CallExpression *ast) void Codegen::handleCall(Reference &base, Arguments calldata, int slotForFunction, int slotForThisObject) { //### Do we really need all these call instructions? can's we load the callee in a temp? - if (base.type == Reference::QmlScopeObject) { - Instruction::CallScopeObjectProperty call; - call.base = base.qmlBase.stackSlot(); - call.name = base.qmlCoreIndex; - call.argc = calldata.argc; - call.argv = calldata.argv; - bytecodeGenerator->addTracingInstruction(call); - } else if (base.type == Reference::QmlContextObject) { - Instruction::CallContextObjectProperty call; - call.base = base.qmlBase.stackSlot(); - call.name = base.qmlCoreIndex; - call.argc = calldata.argc; - call.argv = calldata.argv; - bytecodeGenerator->addTracingInstruction(call); - } else if (base.type == Reference::Member) { + if (base.type == Reference::Member) { if (!disable_lookups && useFastLookups) { Instruction::CallPropertyLookup call; call.base = base.propertyBase.stackSlot(); @@ -2009,11 +1967,19 @@ void Codegen::handleCall(Reference &base, Arguments calldata, int slotForFunctio call.argv = calldata.argv; bytecodeGenerator->addTracingInstruction(call); } else if (!disable_lookups && useFastLookups && base.global) { - Instruction::CallGlobalLookup call; - call.index = registerGlobalGetterLookup(base.nameAsIndex()); - call.argc = calldata.argc; - call.argv = calldata.argv; - bytecodeGenerator->addTracingInstruction(call); + if (base.qmlGlobal) { + Instruction::CallQmlContextPropertyLookup call; + call.index = registerQmlContextPropertyGetterLookup(base.nameAsIndex()); + call.argc = calldata.argc; + call.argv = calldata.argv; + bytecodeGenerator->addTracingInstruction(call); + } else { + Instruction::CallGlobalLookup call; + call.index = registerGlobalGetterLookup(base.nameAsIndex()); + call.argc = calldata.argc; + call.argv = calldata.argv; + bytecodeGenerator->addTracingInstruction(call); + } } else { Instruction::CallName call; call.name = base.nameAsIndex(); @@ -2046,7 +2012,7 @@ void Codegen::handleCall(Reference &base, Arguments calldata, int slotForFunctio bytecodeGenerator->addTracingInstruction(call); } - _expr.setResult(Reference::fromAccumulator(this)); + setExprResult(Reference::fromAccumulator(this)); } Codegen::Arguments Codegen::pushArgs(ArgumentList *args) @@ -2142,7 +2108,7 @@ bool Codegen::visit(ConditionalExpression *ast) ko.loadInAccumulator(); jump_endif.link(); - _expr.setResult(Reference::fromAccumulator(this)); + setExprResult(Reference::fromAccumulator(this)); return false; } @@ -2172,7 +2138,7 @@ bool Codegen::visit(DeleteExpression *ast) throwSyntaxError(ast->deleteToken, QStringLiteral("Delete of an unqualified identifier in strict mode.")); return false; } - _expr.setResult(Reference::fromConst(this, QV4::Encode(false))); + setExprResult(Reference::fromConst(this, QV4::Encode(false))); return false; case Reference::Name: { if (_context->isStrict) { @@ -2182,7 +2148,7 @@ bool Codegen::visit(DeleteExpression *ast) Instruction::DeleteName del; del.name = expr.nameAsIndex(); bytecodeGenerator->addInstruction(del); - _expr.setResult(Reference::fromAccumulator(this)); + setExprResult(Reference::fromAccumulator(this)); return false; } case Reference::Member: { @@ -2197,7 +2163,7 @@ bool Codegen::visit(DeleteExpression *ast) del.base = expr.propertyBase.stackSlot(); del.index = index.stackSlot(); bytecodeGenerator->addInstruction(del); - _expr.setResult(Reference::fromAccumulator(this)); + setExprResult(Reference::fromAccumulator(this)); return false; } case Reference::Subscript: { @@ -2207,14 +2173,14 @@ bool Codegen::visit(DeleteExpression *ast) del.base = expr.elementBase; del.index = expr.elementSubscript.stackSlot(); bytecodeGenerator->addInstruction(del); - _expr.setResult(Reference::fromAccumulator(this)); + setExprResult(Reference::fromAccumulator(this)); return false; } default: break; } // [[11.4.1]] Return true if it's not a reference - _expr.setResult(Reference::fromConst(this, QV4::Encode(true))); + setExprResult(Reference::fromConst(this, QV4::Encode(true))); return false; } @@ -2223,7 +2189,7 @@ bool Codegen::visit(FalseLiteral *) if (hasError) return false; - _expr.setResult(Reference::fromConst(this, QV4::Encode(false))); + setExprResult(Reference::fromConst(this, QV4::Encode(false))); return false; } @@ -2232,7 +2198,7 @@ bool Codegen::visit(SuperLiteral *) if (hasError) return false; - _expr.setResult(Reference::fromSuper(this)); + setExprResult(Reference::fromSuper(this)); return false; } @@ -2250,12 +2216,12 @@ bool Codegen::visit(FieldMemberExpression *ast) if (_context->isArrowFunction || _context->contextType == ContextType::Eval) { Reference r = referenceForName(QStringLiteral("new.target"), false); r.isReadonly = true; - _expr.setResult(r); + setExprResult(r); return false; } Reference r = Reference::fromStackSlot(this, CallData::NewTarget); - _expr.setResult(r); + setExprResult(r); return false; } } @@ -2268,10 +2234,10 @@ bool Codegen::visit(FieldMemberExpression *ast) load.stringId = registerString(ast->name.toString()); bytecodeGenerator->addInstruction(load); Reference property = Reference::fromAccumulator(this).storeOnStack(); - _expr.setResult(Reference::fromSuperProperty(property)); + setExprResult(Reference::fromSuperProperty(property)); return false; } - _expr.setResult(Reference::fromMember(base, ast->name.toString())); + setExprResult(Reference::fromMember(base, ast->name.toString())); return false; } @@ -2281,12 +2247,15 @@ bool Codegen::visit(TaggedTemplate *ast) return false; RegisterScope scope(this); + return handleTaggedTemplate(expression(ast->base), ast); +} - int functionObject = -1, thisObject = -1; - - Reference base = expression(ast->base); +bool Codegen::handleTaggedTemplate(Reference base, TaggedTemplate *ast) +{ if (hasError) return false; + + int functionObject = -1, thisObject = -1; switch (base.type) { case Reference::Member: case Reference::Subscript: @@ -2347,7 +2316,7 @@ bool Codegen::visit(FunctionExpression *ast) if (hasError) return false; loadClosure(function); - _expr.setResult(Reference::fromAccumulator(this)); + setExprResult(Reference::fromAccumulator(this)); return false; } @@ -2379,14 +2348,10 @@ Codegen::Reference Codegen::referenceForName(const QString &name, bool isLhs, co return r; } - // This hook allows implementing QML lookup semantics - Reference fallback = fallbackNameLookup(name); - if (fallback.type != Reference::Invalid) - return fallback; - Reference r = Reference::fromName(this, name); - r.global = useFastLookups && (resolved.type == Context::ResolvedName::Global); - if (!r.global && canAccelerateGlobalLookups() && m_globalNames.contains(name)) + r.global = useFastLookups && (resolved.type == Context::ResolvedName::Global || resolved.type == Context::ResolvedName::QmlGlobal); + r.qmlGlobal = resolved.type == Context::ResolvedName::QmlGlobal; + if (!r.global && !r.qmlGlobal && m_globalNames.contains(name)) r.global = true; return r; } @@ -2402,18 +2367,12 @@ void Codegen::loadClosure(int closureId) } } -Codegen::Reference Codegen::fallbackNameLookup(const QString &name) -{ - Q_UNUSED(name) - return Reference(); -} - bool Codegen::visit(IdentifierExpression *ast) { if (hasError) return false; - _expr.setResult(referenceForName(ast->name.toString(), false, ast->firstSourceLocation())); + setExprResult(referenceForName(ast->name.toString(), false, ast->firstSourceLocation())); return false; } @@ -2463,7 +2422,7 @@ void Codegen::handleConstruct(const Reference &base, ArgumentList *arguments) // set the result up as the thisObject Reference::fromAccumulator(this).storeOnStack(CallData::This); - _expr.setResult(Reference::fromAccumulator(this)); + setExprResult(Reference::fromAccumulator(this)); } bool Codegen::visit(NewExpression *ast) @@ -2512,7 +2471,7 @@ bool Codegen::visit(NotExpression *ast) return false; TailCallBlocker blockTailCalls(this); - _expr.setResult(unop(Not, expression(ast->expression))); + setExprResult(unop(Not, expression(ast->expression))); return false; } @@ -2521,10 +2480,10 @@ bool Codegen::visit(NullExpression *) if (hasError) return false; - if (_expr.accept(cx)) - bytecodeGenerator->jump().link(*_expr.iffalse()); + if (exprAccept(cx)) + bytecodeGenerator->jump().link(*currentExpr().iffalse()); else - _expr.setResult(Reference::fromConst(this, Encode::null())); + setExprResult(Reference::fromConst(this, Encode::null())); return false; } @@ -2534,7 +2493,7 @@ bool Codegen::visit(NumericLiteral *ast) if (hasError) return false; - _expr.setResult(Reference::fromConst(this, QV4::Encode::smallestNumber(ast->value))); + setExprResult(Reference::fromConst(this, QV4::Encode::smallestNumber(ast->value))); return false; } @@ -2646,8 +2605,7 @@ bool Codegen::visit(ObjectPattern *ast) call.argc = argc; call.args = Moth::StackSlot::createRegister(args); bytecodeGenerator->addInstruction(call); - Reference result = Reference::fromAccumulator(this); - _expr.setResult(result); + setExprResult(Reference::fromAccumulator(this)); return false; } @@ -2666,7 +2624,7 @@ bool Codegen::visit(PostDecrementExpression *ast) if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(expr, ast->decrementToken)) return false; - _expr.setResult(unop(PostDecrement, expr)); + setExprResult(unop(PostDecrement, expr)); return false; } @@ -2686,7 +2644,7 @@ bool Codegen::visit(PostIncrementExpression *ast) if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(expr, ast->incrementToken)) return false; - _expr.setResult(unop(PostIncrement, expr)); + setExprResult(unop(PostIncrement, expr)); return false; } @@ -2704,7 +2662,7 @@ bool Codegen::visit(PreDecrementExpression *ast) if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(expr, ast->decrementToken)) return false; - _expr.setResult(unop(PreDecrement, expr)); + setExprResult(unop(PreDecrement, expr)); return false; } @@ -2723,7 +2681,7 @@ bool Codegen::visit(PreIncrementExpression *ast) if (throwSyntaxErrorOnEvalOrArgumentsInStrictMode(expr, ast->incrementToken)) return false; - _expr.setResult(unop(PreIncrement, expr)); + setExprResult(unop(PreIncrement, expr)); return false; } @@ -2734,7 +2692,7 @@ bool Codegen::visit(RegExpLiteral *ast) auto r = Reference::fromStackSlot(this); r.isReadonly = true; - _expr.setResult(r); + setExprResult(r); Instruction::MoveRegExp instr; instr.regExpId = jsUnitGenerator->registerRegExp(ast); @@ -2750,7 +2708,7 @@ bool Codegen::visit(StringLiteral *ast) auto r = Reference::fromAccumulator(this); r.isReadonly = true; - _expr.setResult(r); + setExprResult(r); Instruction::LoadRuntimeString instr; instr.stringId = registerString(ast->value.toString()); @@ -2800,7 +2758,7 @@ bool Codegen::visit(TemplateLiteral *ast) auto r = Reference::fromAccumulator(this); r.isReadonly = true; - _expr.setResult(r); + setExprResult(r); return false; } @@ -2813,10 +2771,10 @@ bool Codegen::visit(ThisExpression *) if (_context->isArrowFunction) { Reference r = referenceForName(QStringLiteral("this"), false); r.isReadonly = true; - _expr.setResult(r); + setExprResult(r); return false; } - _expr.setResult(Reference::fromThis(this)); + setExprResult(Reference::fromThis(this)); return false; } @@ -2826,7 +2784,7 @@ bool Codegen::visit(TildeExpression *ast) return false; TailCallBlocker blockTailCalls(this); - _expr.setResult(unop(Compl, expression(ast->expression))); + setExprResult(unop(Compl, expression(ast->expression))); return false; } @@ -2835,7 +2793,7 @@ bool Codegen::visit(TrueLiteral *) if (hasError) return false; - _expr.setResult(Reference::fromConst(this, QV4::Encode(true))); + setExprResult(Reference::fromConst(this, QV4::Encode(true))); return false; } @@ -2861,7 +2819,7 @@ bool Codegen::visit(TypeOfExpression *ast) Instruction::TypeofValue instr; bytecodeGenerator->addInstruction(instr); } - _expr.setResult(Reference::fromAccumulator(this)); + setExprResult(Reference::fromAccumulator(this)); return false; } @@ -2872,7 +2830,7 @@ bool Codegen::visit(UnaryMinusExpression *ast) return false; TailCallBlocker blockTailCalls(this); - _expr.setResult(unop(UMinus, expression(ast->expression))); + setExprResult(unop(UMinus, expression(ast->expression))); return false; } @@ -2882,7 +2840,7 @@ bool Codegen::visit(UnaryPlusExpression *ast) return false; TailCallBlocker blockTailCalls(this); - _expr.setResult(unop(UPlus, expression(ast->expression))); + setExprResult(unop(UPlus, expression(ast->expression))); return false; } @@ -2895,7 +2853,7 @@ bool Codegen::visit(VoidExpression *ast) TailCallBlocker blockTailCalls(this); statement(ast->expression); - _expr.setResult(Reference::fromConst(this, Encode::undefined())); + setExprResult(Reference::fromConst(this, Encode::undefined())); return false; } @@ -2909,7 +2867,7 @@ bool Codegen::visit(FunctionDeclaration * ast) if (_functionContext->contextType == ContextType::Binding) referenceForName(ast->name.toString(), true).loadInAccumulator(); - _expr.accept(nx); + exprAccept(nx); return false; } @@ -2965,7 +2923,7 @@ bool Codegen::visit(YieldExpression *ast) done.link(); lhsValue.loadInAccumulator(); - _expr.setResult(acc); + setExprResult(acc); return false; } @@ -2976,7 +2934,7 @@ bool Codegen::visit(YieldExpression *ast) BytecodeGenerator::Jump jump = bytecodeGenerator->addJumpInstruction(resume); emitReturn(acc); jump.link(); - _expr.setResult(acc); + setExprResult(acc); return false; } @@ -3115,8 +3073,6 @@ int Codegen::defineFunction(const QString &name, AST::Node *ast, bytecodeGenerator->addInstruction(yield); } - beginFunctionBodyHook(); - statementList(body); if (!hasError) { @@ -3855,8 +3811,14 @@ QQmlRefPointer<CompiledData::CompilationUnit> Codegen::createUnitForLoading() class Codegen::VolatileMemoryLocationScanner: protected QQmlJS::AST::Visitor { VolatileMemoryLocations locs; + Codegen *parent; public: + VolatileMemoryLocationScanner(Codegen *parent) : + QQmlJS::AST::Visitor(parent->recursionDepth()), + parent(parent) + {} + Codegen::VolatileMemoryLocations scan(AST::Node *s) { s->accept(this); @@ -3921,25 +3883,41 @@ public: } } + void throwRecursionDepthError() override + { + parent->throwRecursionDepthError(); + } + private: - void collectIdentifiers(QVector<QStringView> &ids, AST::Node *node) const { + void collectIdentifiers(QVector<QStringView> &ids, AST::Node *node) { class Collector: public QQmlJS::AST::Visitor { + private: QVector<QStringView> &ids; + VolatileMemoryLocationScanner *parent; + public: - Collector(QVector<QStringView> &ids): ids(ids) {} - virtual bool visit(IdentifierExpression *ie) { + Collector(QVector<QStringView> &ids, VolatileMemoryLocationScanner *parent) : + QQmlJS::AST::Visitor(parent->recursionDepth()), ids(ids), parent(parent) + {} + + bool visit(IdentifierExpression *ie) final { ids.append(ie->name); return false; } + + void throwRecursionDepthError() final + { + parent->throwRecursionDepthError(); + } }; - Collector collector(ids); + Collector collector(ids, this); node->accept(&collector); } }; -Codegen::VolatileMemoryLocations Codegen::scanVolatileMemoryLocations(AST::Node *ast) const +Codegen::VolatileMemoryLocations Codegen::scanVolatileMemoryLocations(AST::Node *ast) { - VolatileMemoryLocationScanner scanner; + VolatileMemoryLocationScanner scanner(this); return scanner.scan(ast); } @@ -4041,10 +4019,6 @@ bool Codegen::Reference::operator==(const Codegen::Reference &other) const return index == other.index; case Const: return constant == other.constant; - case QmlScopeObject: - case QmlContextObject: - return qmlCoreIndex == other.qmlCoreIndex && qmlNotifyIndex == other.qmlNotifyIndex - && capturePolicy == other.capturePolicy; } return true; } @@ -4102,9 +4076,7 @@ Codegen::Reference Codegen::Reference::storeConsumeAccumulator() const Codegen::Reference Codegen::Reference::baseObject() const { - if (type == Reference::QmlScopeObject || type == Reference::QmlContextObject) { - return Reference::fromStackSlot(codegen, qmlBase.stackSlot()); - } else if (type == Reference::Member) { + if (type == Reference::Member) { RValue rval = propertyBase; if (!rval.isValid()) return Reference::fromConst(codegen, Encode::undefined()); @@ -4189,8 +4161,6 @@ bool Codegen::Reference::storeWipesAccumulator() const case Name: case Member: case Subscript: - case QmlScopeObject: - case QmlContextObject: return true; } } @@ -4270,18 +4240,6 @@ void Codegen::Reference::storeAccumulator() const store.index = elementSubscript.stackSlot(); codegen->bytecodeGenerator->addTracingInstruction(store); } return; - case QmlScopeObject: { - Instruction::StoreScopeObjectProperty store; - store.base = qmlBase; - store.propertyIndex = qmlCoreIndex; - codegen->bytecodeGenerator->addInstruction(store); - } return; - case QmlContextObject: { - Instruction::StoreContextObjectProperty store; - store.base = qmlBase; - store.propertyIndex = qmlCoreIndex; - codegen->bytecodeGenerator->addInstruction(store); - } return; case Invalid: case Accumulator: case Const: @@ -4396,9 +4354,15 @@ QT_WARNING_POP } } if (!disable_lookups && global) { - Instruction::LoadGlobalLookup load; - load.index = codegen->registerGlobalGetterLookup(nameAsIndex()); - codegen->bytecodeGenerator->addTracingInstruction(load); + if (qmlGlobal) { + Instruction::LoadQmlContextPropertyLookup load; + load.index = codegen->registerQmlContextPropertyGetterLookup(nameAsIndex()); + codegen->bytecodeGenerator->addTracingInstruction(load); + } else { + Instruction::LoadGlobalLookup load; + load.index = codegen->registerGlobalGetterLookup(nameAsIndex()); + codegen->bytecodeGenerator->addTracingInstruction(load); + } } else { Instruction::LoadName load; load.name = nameAsIndex(); @@ -4432,24 +4396,6 @@ QT_WARNING_POP load.base = elementBase; codegen->bytecodeGenerator->addTracingInstruction(load); } return; - case QmlScopeObject: { - Instruction::LoadScopeObjectProperty load; - load.base = qmlBase; - load.propertyIndex = qmlCoreIndex; - load.captureRequired = capturePolicy == CaptureAtRuntime; - codegen->bytecodeGenerator->addInstruction(load); - if (capturePolicy == CaptureAheadOfTime) - codegen->_context->scopeObjectPropertyDependencies.insert(qmlCoreIndex, qmlNotifyIndex); - } return; - case QmlContextObject: { - Instruction::LoadContextObjectProperty load; - load.base = qmlBase; - load.propertyIndex = qmlCoreIndex; - load.captureRequired = capturePolicy == CaptureAtRuntime; - codegen->bytecodeGenerator->addInstruction(load); - if (capturePolicy == CaptureAheadOfTime) - codegen->_context->contextObjectPropertyDependencies.insert(qmlCoreIndex, qmlNotifyIndex); - } return; case Invalid: break; } diff --git a/src/qml/compiler/qv4codegen_p.h b/src/qml/compiler/qv4codegen_p.h index 4d7001fe64..ad86483132 100644 --- a/src/qml/compiler/qv4codegen_p.h +++ b/src/qml/compiler/qv4codegen_p.h @@ -184,16 +184,31 @@ public: Member, Subscript, Import, - QmlScopeObject, - QmlContextObject, - LastLValue = QmlContextObject, + LastLValue = Import, Const } type = Invalid; bool isLValue() const { return !isReadonly && type > Accumulator; } - Reference(Codegen *cg, Type type = Invalid) : type(type), constant(0), codegen(cg) {} - Reference(): constant(0) {} + Reference(Codegen *cg, Type t = Invalid) : Reference() + { + type = t; + codegen = cg; + } + + Reference() : + constant(0), + isArgOrEval(false), + isReadonly(false), + isReferenceToConst(false), + requiresTDZCheck(false), + subscriptRequiresTDZCheck(false), + stackSlotIsLocalOrArgument(false), + isVolatile(false), + global(false), + qmlGlobal(false) + {} + Reference(const Reference &) = default; Reference(Reference &&) = default; Reference &operator =(const Reference &) = default; @@ -206,10 +221,6 @@ public: bool isValid() const { return type != Invalid; } bool loadTriggersSideEffect() const { switch (type) { - case QmlScopeObject: - return capturePolicy != DontCapture; - case QmlContextObject: - return capturePolicy != DontCapture; case Name: case Member: case Subscript: @@ -228,28 +239,6 @@ public: return isStackSlot(); } - enum PropertyCapturePolicy { - /* - We're reading a property from the scope or context object, but it's a CONSTANT property, - so we don't need to register a dependency at all. - */ - DontCapture, - /* - We're reading the property of a QObject, and we know that it's the - scope object or context object, which we know very well. Instead of registering a - property capture every time, we can do that ahead of time and then register all those - captures in one shot in registerQmlDependencies(). - */ - CaptureAheadOfTime, - /* - We're reading the property of a QObject, and we're not quite sure where - the QObject comes from or what it is. So, when reading that property at run-time, - make sure that we capture where we read that property so that if it changes we can - re-evaluate the entire expression. - */ - CaptureAtRuntime - }; - static Reference fromAccumulator(Codegen *cg) { return Reference(cg, Accumulator); } @@ -316,22 +305,6 @@ public: r.isReadonly = true; return r; } - static Reference fromQmlScopeObject(const Reference &base, qint16 coreIndex, qint16 notifyIndex, PropertyCapturePolicy capturePolicy) { - Reference r(base.codegen, QmlScopeObject); - r.qmlBase = base.storeOnStack().stackSlot(); - r.qmlCoreIndex = coreIndex; - r.qmlNotifyIndex = notifyIndex; - r.capturePolicy = capturePolicy; - return r; - } - static Reference fromQmlContextObject(const Reference &base, qint16 coreIndex, qint16 notifyIndex, PropertyCapturePolicy capturePolicy) { - Reference r(base.codegen, QmlContextObject); - r.qmlBase = base.storeOnStack().stackSlot(); - r.qmlCoreIndex = coreIndex; - r.qmlNotifyIndex = notifyIndex; - r.capturePolicy = capturePolicy; - return r; - } static Reference fromThis(Codegen *cg) { Reference r = fromStackSlot(cg, CallData::This); r.isReadonly = true; @@ -386,25 +359,21 @@ public: Moth::StackSlot elementBase; RValue elementSubscript; }; - struct { // QML scope/context object case - Moth::StackSlot qmlBase; - qint16 qmlCoreIndex; - qint16 qmlNotifyIndex; - PropertyCapturePolicy capturePolicy; - }; Moth::StackSlot property; // super property }; QString name; - mutable bool isArgOrEval = false; - bool isReadonly = false; - bool isReferenceToConst = false; - bool requiresTDZCheck = false; - bool subscriptRequiresTDZCheck = false; - bool stackSlotIsLocalOrArgument = false; - bool isVolatile = false; - bool global = false; Codegen *codegen = nullptr; + quint32 isArgOrEval:1; + quint32 isReadonly:1; + quint32 isReferenceToConst:1; + quint32 requiresTDZCheck:1; + quint32 subscriptRequiresTDZCheck:1; + quint32 stackSlotIsLocalOrArgument:1; + quint32 isVolatile:1; + quint32 global:1; + quint32 qmlGlobal:1; + private: void storeAccumulator() const; Reference doStoreOnStack(int tempIndex) const; @@ -499,6 +468,10 @@ protected: void setResult(const Reference &result) { _result = result; } + + void setResult(Reference &&result) { + _result = std::move(result); + } }; void enterContext(AST::Node *node); @@ -532,6 +505,7 @@ public: int registerGetterLookup(int nameIndex) { return jsUnitGenerator->registerGetterLookup(nameIndex); } int registerSetterLookup(int nameIndex) { return jsUnitGenerator->registerSetterLookup(nameIndex); } int registerGlobalGetterLookup(int nameIndex) { return jsUnitGenerator->registerGlobalGetterLookup(nameIndex); } + int registerQmlContextPropertyGetterLookup(int nameIndex) { return jsUnitGenerator->registerQmlContextPropertyGetterLookup(nameIndex); } // Returns index in _module->functions virtual int defineFunction(const QString &name, AST::Node *ast, @@ -544,9 +518,22 @@ protected: void condition(AST::ExpressionNode *ast, const BytecodeGenerator::Label *iftrue, const BytecodeGenerator::Label *iffalse, bool trueBlockFollowsCondition); - Reference expression(AST::ExpressionNode *ast); - void accept(AST::Node *node); + inline Reference expression(AST::ExpressionNode *ast) + { + if (!ast || hasError) + return Reference(); + + pushExpr(); + ast->accept(this); + return popResult(); + } + + inline void accept(AST::Node *node) + { + if (!hasError && node) + node->accept(this); + } void program(AST::Program *ast); void statementList(AST::StatementList *ast); @@ -561,12 +548,6 @@ protected: Reference referenceForPropertyName(const Codegen::Reference &object, AST::PropertyName *name); - // Hooks provided to implement QML lookup semantics - virtual bool canAccelerateGlobalLookups() const { return true; } - virtual Reference fallbackNameLookup(const QString &name); - - virtual void beginFunctionBodyHook() {} - void emitReturn(const Reference &expr); // nodes @@ -670,6 +651,11 @@ protected: bool throwSyntaxErrorOnEvalOrArgumentsInStrictMode(const Reference &r, const AST::SourceLocation &loc); virtual void throwSyntaxError(const AST::SourceLocation &loc, const QString &detail); virtual void throwReferenceError(const AST::SourceLocation &loc, const QString &detail); + void throwRecursionDepthError() override + { + throwSyntaxError(AST::SourceLocation(), + QStringLiteral("Maximum statement or expression depth exceeded")); + } public: QList<DiagnosticMessage> errors() const; @@ -684,6 +670,7 @@ public: void handleCall(Reference &base, Arguments calldata, int slotForFunction, int slotForThisObject); Arguments pushTemplateArgs(AST::TemplateLiteral *args); + bool handleTaggedTemplate(Reference base, AST::TaggedTemplate *ast); void createTemplateObject(AST::TemplateLiteral *t); void setUseFastLookups(bool b) { useFastLookups = b; } @@ -714,13 +701,40 @@ public: m_globalNames = globalNames; } + static const char *s_globalNames[]; protected: friend class ScanFunctions; friend struct ControlFlow; friend struct ControlFlowCatch; friend struct ControlFlowFinally; - Result _expr; + + inline void setExprResult(const Reference &result) { m_expressions.back().setResult(result); } + inline void setExprResult(Reference &&result) { m_expressions.back().setResult(std::move(result)); } + inline Reference exprResult() const { return m_expressions.back().result(); } + + inline bool exprAccept(Format f) { return m_expressions.back().accept(f); } + + inline const Result ¤tExpr() const { return m_expressions.back(); } + + inline void pushExpr(Result &&expr) { m_expressions.push_back(std::move(expr)); } + inline void pushExpr(const Result &expr) { m_expressions.push_back(expr); } + inline void pushExpr() { m_expressions.emplace_back(); } + + inline Result popExpr() + { + const Result result = m_expressions.back(); + m_expressions.pop_back(); + return result; + } + + inline Reference popResult() { + const Reference result = m_expressions.back().result(); + m_expressions.pop_back(); + return result; + } + + std::vector<Result> m_expressions; VolatileMemoryLocations _volatileMemoryLocations; Module *_module; int _returnAddress; @@ -769,33 +783,8 @@ protected: bool _onoff; }; - class RecursionDepthCheck { - public: - RecursionDepthCheck(Codegen *cg, const AST::SourceLocation &loc) - : _cg(cg) - { -#ifdef QT_NO_DEBUG - const int depthLimit = 4000; // limit to ~1000 deep -#else - const int depthLimit = 1000; // limit to ~250 deep -#endif // QT_NO_DEBUG - - ++_cg->_recursionDepth; - if (_cg->_recursionDepth > depthLimit) - _cg->throwSyntaxError(loc, QStringLiteral("Maximum statement or expression depth exceeded")); - } - - ~RecursionDepthCheck() - { --_cg->_recursionDepth; } - - private: - Codegen *_cg; - }; - int _recursionDepth = 0; - friend class RecursionDepthCheck; - private: - VolatileMemoryLocations scanVolatileMemoryLocations(AST::Node *ast) const; + VolatileMemoryLocations scanVolatileMemoryLocations(AST::Node *ast); void handleConstruct(const Reference &base, AST::ArgumentList *args); }; diff --git a/src/qml/compiler/qv4compileddata.cpp b/src/qml/compiler/qv4compileddata.cpp index 5dd6fca023..e4cc9c9c5a 100644 --- a/src/qml/compiler/qv4compileddata.cpp +++ b/src/qml/compiler/qv4compileddata.cpp @@ -50,6 +50,8 @@ #include <private/qqmlengine_p.h> #include <private/qv4vme_moth_p.h> #include <private/qv4module_p.h> +#include <private/qv4qobjectwrapper_p.h> +#include <private/qqmlvaluetypewrapper_p.h> #include "qv4compilationunitmapper_p.h" #include <QQmlPropertyMap> #include <QDateTime> @@ -167,6 +169,8 @@ QV4::Function *CompilationUnit::linkToEngine(ExecutionEngine *engine) l->setter = QV4::Lookup::setterGeneric; else if (type == CompiledData::Lookup::Type_GlobalGetter) l->globalGetter = QV4::Lookup::globalGetterGeneric; + else if (type == CompiledData::Lookup::Type_QmlContextPropertyGetter) + l->qmlContextPropertyGetter = QQmlContextWrapper::resolveQmlContextPropertyLookupGetter; l->nameIndex = compiledLookups[i].nameIndex; } } @@ -269,6 +273,24 @@ void CompilationUnit::unlink() propertyCaches.clear(); + if (runtimeLookups) { + for (uint i = 0; i < data->lookupTableSize; ++i) { + QV4::Lookup &l = runtimeLookups[i]; + if (l.getter == QV4::QObjectWrapper::lookupGetter) { + if (QQmlPropertyCache *pc = l.qobjectLookup.propertyCache) + pc->release(); + } else if (l.getter == QQmlValueTypeWrapper::lookupGetter) { + if (QQmlPropertyCache *pc = l.qgadgetLookup.propertyCache) + pc->release(); + } + + if (l.qmlContextPropertyGetter == QQmlContextWrapper::lookupScopeObjectProperty) { + if (QQmlPropertyCache *pc = l.qobjectLookup.propertyCache) + pc->release(); + } + } + } + dependentScripts.clear(); typeNameCache = nullptr; diff --git a/src/qml/compiler/qv4compileddata_p.h b/src/qml/compiler/qv4compileddata_p.h index 726b82fea9..fe3e6bad6e 100644 --- a/src/qml/compiler/qv4compileddata_p.h +++ b/src/qml/compiler/qv4compileddata_p.h @@ -79,7 +79,7 @@ QT_BEGIN_NAMESPACE // Also change the comment behind the number to describe the latest change. This has the added // benefit that if another patch changes the version too, it will result in a merge conflict, and // not get removed silently. -#define QV4_DATA_STRUCTURE_VERSION 0x1c // Add trace slot to UPlus +#define QV4_DATA_STRUCTURE_VERSION 0x22 // Add trace slot to UPlus class QIODevice; class QQmlPropertyData; @@ -165,9 +165,10 @@ static_assert(sizeof(RegExp) == 4, "RegExp structure needs to have the expected struct Lookup { enum Type : unsigned int { - Type_Getter = 0x0, - Type_Setter = 0x1, - Type_GlobalGetter = 2 + Type_Getter = 0, + Type_Setter = 1, + Type_GlobalGetter = 2, + Type_QmlContextPropertyGetter = 3 }; union { @@ -292,29 +293,16 @@ struct Function quint16_le nRegisters; Location location; - // Qml Extensions Begin - // Array of resolved ID objects - size_t dependingIdObjectsOffset() const { return lineNumberOffset() + nLineNumbers * sizeof(CodeOffsetToLine); } - quint16_le nDependingIdObjects; - quint16_le nDependingContextProperties; - // Array of int pairs (property index and notify index) - size_t dependingContextPropertiesOffset() const { return dependingIdObjectsOffset() + nDependingIdObjects * sizeof(quint32); } - quint16_le nDependingScopeProperties; - // Array of int pairs (property index and notify index) - size_t dependingScopePropertiesOffset() const { return dependingContextPropertiesOffset() + nDependingContextProperties * sizeof(quint32); } - // Qml Extensions End + quint32_le nLabelInfos; + size_t labelInfosOffset() const { return lineNumberOffset() + nLineNumbers * sizeof(CodeOffsetToLine); } typedef quint16_le TraceInfoCount; TraceInfoCount nTraceInfos; static constexpr TraceInfoCount NoTracing() { return TraceInfoCount::max(); } - quint32_le nLabelInfos; - size_t labelInfosOffset() const { return dependingScopePropertiesOffset() + nDependingScopeProperties; } - // Keep all unaligned data at the end quint8 flags; quint8 padding1; - quint16 padding2; // quint32 formalsIndex[nFormals] // quint32 localsIndex[nLocals] @@ -322,9 +310,6 @@ struct Function const quint32_le *formalsTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + formalsOffset); } const quint32_le *localsTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + localsOffset); } const CodeOffsetToLine *lineNumberTable() const { return reinterpret_cast<const CodeOffsetToLine *>(reinterpret_cast<const char *>(this) + lineNumberOffset()); } - const quint32_le *qmlIdObjectDependencyTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + dependingIdObjectsOffset()); } - const quint32_le *qmlContextPropertiesDependencyTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + dependingContextPropertiesOffset()); } - const quint32_le *qmlScopePropertiesDependencyTable() const { return reinterpret_cast<const quint32_le *>(reinterpret_cast<const char *>(this) + dependingScopePropertiesOffset()); } // --- QQmlPropertyCacheCreator interface const quint32_le *formalsBegin() const { return formalsTable(); } @@ -335,11 +320,9 @@ struct Function const char *code() const { return reinterpret_cast<const char *>(this) + codeOffset; } - inline bool hasQmlDependencies() const { return nDependingIdObjects > 0 || nDependingContextProperties > 0 || nDependingScopeProperties > 0; } - - static int calculateSize(int nFormals, int nLocals, int nLines, int nInnerfunctions, int nIdObjectDependencies, int nPropertyDependencies, int labelInfoSize, int codeSize) { - int trailingData = (nFormals + nLocals + nInnerfunctions + nIdObjectDependencies + labelInfoSize + - 2 * nPropertyDependencies)*sizeof (quint32) + nLines*sizeof(CodeOffsetToLine); + static int calculateSize(int nFormals, int nLocals, int nLines, int nInnerfunctions, int labelInfoSize, int codeSize) { + int trailingData = (nFormals + nLocals + nInnerfunctions + labelInfoSize)*sizeof (quint32) + + nLines*sizeof(CodeOffsetToLine); size_t size = align(align(sizeof(Function)) + size_t(trailingData)) + align(codeSize); Q_ASSERT(size < INT_MAX); return int(size); @@ -349,7 +332,7 @@ struct Function return (a + 7) & ~size_t(7); } }; -static_assert(sizeof(Function) == 60, "Function structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); +static_assert(sizeof(Function) == 52, "Function structure needs to have the expected size to be binary compatible on disk when generated by host compiler and loaded by target"); struct Method { enum Type { diff --git a/src/qml/compiler/qv4compiler.cpp b/src/qml/compiler/qv4compiler.cpp index 0833f552e6..01c033cb2a 100644 --- a/src/qml/compiler/qv4compiler.cpp +++ b/src/qml/compiler/qv4compiler.cpp @@ -154,15 +154,19 @@ int QV4::Compiler::JSUnitGenerator::registerSetterLookup(int nameIndex) return lookups.size() - 1; } -int QV4::Compiler::JSUnitGenerator::registerGlobalGetterLookup(const QString &name) +int QV4::Compiler::JSUnitGenerator::registerGlobalGetterLookup(int nameIndex) { - return registerGlobalGetterLookup(registerString(name)); + CompiledData::Lookup l; + l.type_and_flags = CompiledData::Lookup::Type_GlobalGetter; + l.nameIndex = nameIndex; + lookups << l; + return lookups.size() - 1; } -int QV4::Compiler::JSUnitGenerator::registerGlobalGetterLookup(int nameIndex) +int QV4::Compiler::JSUnitGenerator::registerQmlContextPropertyGetterLookup(int nameIndex) { CompiledData::Lookup l; - l.type_and_flags = CompiledData::Lookup::Type_GlobalGetter; + l.type_and_flags = CompiledData::Lookup::Type_QmlContextPropertyGetter; l.nameIndex = nameIndex; lookups << l; return lookups.size() - 1; @@ -423,28 +427,6 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte function->nTraceInfos = irFunction->nTraceInfos; function->nRegisters = irFunction->registerCountInFunction; - function->nDependingIdObjects = 0; - function->nDependingContextProperties = 0; - function->nDependingScopeProperties = 0; - - if (!irFunction->idObjectDependencies.isEmpty()) { - function->nDependingIdObjects = irFunction->idObjectDependencies.count(); - Q_ASSERT(function->dependingIdObjectsOffset() == currentOffset); - currentOffset += function->nDependingIdObjects * sizeof(quint32); - } - - if (!irFunction->contextObjectPropertyDependencies.isEmpty()) { - function->nDependingContextProperties = irFunction->contextObjectPropertyDependencies.count(); - Q_ASSERT(function->dependingContextPropertiesOffset() == currentOffset); - currentOffset += function->nDependingContextProperties * sizeof(quint32) * 2; - } - - if (!irFunction->scopeObjectPropertyDependencies.isEmpty()) { - function->nDependingScopeProperties = irFunction->scopeObjectPropertyDependencies.count(); - Q_ASSERT(function->dependingScopePropertiesOffset() == currentOffset); - currentOffset += function->nDependingScopeProperties * sizeof(quint32) * 2; - } - if (!irFunction->labelInfo.empty()) { function->nLabelInfos = quint32(irFunction->labelInfo.size()); Q_ASSERT(function->labelInfosOffset() == currentOffset); @@ -470,25 +452,6 @@ void QV4::Compiler::JSUnitGenerator::writeFunction(char *f, QV4::Compiler::Conte // write line numbers memcpy(f + function->lineNumberOffset(), irFunction->lineNumberMapping.constData(), irFunction->lineNumberMapping.size()*sizeof(CompiledData::CodeOffsetToLine)); - // write QML dependencies - quint32_le *writtenDeps = (quint32_le *)(f + function->dependingIdObjectsOffset()); - for (int id : irFunction->idObjectDependencies) { - Q_ASSERT(id >= 0); - *writtenDeps++ = static_cast<quint32>(id); - } - - writtenDeps = (quint32_le *)(f + function->dependingContextPropertiesOffset()); - for (auto property : irFunction->contextObjectPropertyDependencies) { - *writtenDeps++ = property.key(); // property index - *writtenDeps++ = property.value(); // notify index - } - - writtenDeps = (quint32_le *)(f + function->dependingScopePropertiesOffset()); - for (auto property : irFunction->scopeObjectPropertyDependencies) { - *writtenDeps++ = property.key(); // property index - *writtenDeps++ = property.value(); // notify index - } - quint32_le *labels = (quint32_le *)(f + function->labelInfosOffset()); for (unsigned u : irFunction->labelInfo) { *labels++ = u; @@ -690,10 +653,8 @@ QV4::CompiledData::Unit QV4::Compiler::JSUnitGenerator::generateHeader(QV4::Comp Context *f = module->functions.at(i); blockAndFunctionOffsets[i] = nextOffset; - const int qmlIdDepsCount = f->idObjectDependencies.count(); - const int qmlPropertyDepsCount = f->scopeObjectPropertyDependencies.count() + f->contextObjectPropertyDependencies.count(); quint32 size = QV4::CompiledData::Function::calculateSize(f->arguments.size(), f->locals.size(), f->lineNumberMapping.size(), f->nestedContexts.size(), - qmlIdDepsCount, qmlPropertyDepsCount, int(f->labelInfo.size()), f->code.size()); + int(f->labelInfo.size()), f->code.size()); functionSize += size - f->code.size(); nextOffset += size; } diff --git a/src/qml/compiler/qv4compiler_p.h b/src/qml/compiler/qv4compiler_p.h index 2f5889ab53..49e334bb81 100644 --- a/src/qml/compiler/qv4compiler_p.h +++ b/src/qml/compiler/qv4compiler_p.h @@ -118,8 +118,8 @@ struct Q_QML_PRIVATE_EXPORT JSUnitGenerator { int registerGetterLookup(int nameIndex); int registerSetterLookup(const QString &name); int registerSetterLookup(int nameIndex); - int registerGlobalGetterLookup(const QString &name); int registerGlobalGetterLookup(int nameIndex); + int registerQmlContextPropertyGetterLookup(int nameIndex); int registerRegExp(QQmlJS::AST::RegExpLiteral *regexp); diff --git a/src/qml/compiler/qv4compilercontext.cpp b/src/qml/compiler/qv4compilercontext.cpp index 931759fa72..7586611035 100644 --- a/src/qml/compiler/qv4compilercontext.cpp +++ b/src/qml/compiler/qv4compilercontext.cpp @@ -187,10 +187,13 @@ Context::ResolvedName Context::resolveName(const QString &name, const QQmlJS::AS } // ### can we relax the restrictions here? - if (c->contextType == ContextType::Eval || c->contextType == ContextType::Binding) + if (c->contextType == ContextType::Eval) return result; - result.type = ResolvedName::Global; + if (c->contextType == ContextType::Binding) + result.type = ResolvedName::QmlGlobal; + else + result.type = ResolvedName::Global; return result; } diff --git a/src/qml/compiler/qv4compilercontext_p.h b/src/qml/compiler/qv4compilercontext_p.h index 5b91b93346..cb20ea9d57 100644 --- a/src/qml/compiler/qv4compilercontext_p.h +++ b/src/qml/compiler/qv4compilercontext_p.h @@ -278,11 +278,6 @@ struct Context { } }; - // Qml extension: - SmallSet<int> idObjectDependencies; - PropertyDependencyMap contextObjectPropertyDependencies; - PropertyDependencyMap scopeObjectPropertyDependencies; - Context(Context *parent, ContextType type) : parent(parent) , contextType(type) @@ -338,6 +333,7 @@ struct Context { struct ResolvedName { enum Type { Unresolved, + QmlGlobal, Global, Local, Stack, diff --git a/src/qml/compiler/qv4compilerscanfunctions.cpp b/src/qml/compiler/qv4compilerscanfunctions.cpp index e0eaa8867b..04593f202a 100644 --- a/src/qml/compiler/qv4compilerscanfunctions.cpp +++ b/src/qml/compiler/qv4compilerscanfunctions.cpp @@ -57,7 +57,8 @@ using namespace QV4::Compiler; using namespace QQmlJS::AST; ScanFunctions::ScanFunctions(Codegen *cg, const QString &sourceCode, ContextType defaultProgramType) - : _cg(cg) + : QQmlJS::AST::Visitor(cg->recursionDepth()) + , _cg(cg) , _sourceCode(sourceCode) , _context(nullptr) , _allowFuncDecls(true) @@ -96,25 +97,6 @@ void ScanFunctions::leaveEnvironment() _context = _contextStack.isEmpty() ? nullptr : _contextStack.top(); } -bool ScanFunctions::preVisit(Node *ast) -{ - if (_cg->hasError) - return false; - ++_recursionDepth; - - if (_recursionDepth > 1000) { - _cg->throwSyntaxError(ast->lastSourceLocation(), QStringLiteral("Maximum statement or expression depth exceeded")); - return false; - } - - return true; -} - -void ScanFunctions::postVisit(Node *) -{ - --_recursionDepth; -} - void ScanFunctions::checkDirectivePrologue(StatementList *ast) { for (StatementList *it = ast; it; it = it->next) { @@ -893,3 +875,8 @@ void ScanFunctions::calcEscapingVariables() } } } + +void ScanFunctions::throwRecursionDepthError() +{ + _cg->throwRecursionDepthError(); +} diff --git a/src/qml/compiler/qv4compilerscanfunctions_p.h b/src/qml/compiler/qv4compilerscanfunctions_p.h index 28ad846bcd..0f7bf1818a 100644 --- a/src/qml/compiler/qv4compilerscanfunctions_p.h +++ b/src/qml/compiler/qv4compilerscanfunctions_p.h @@ -96,9 +96,6 @@ protected: using Visitor::visit; using Visitor::endVisit; - bool preVisit(AST::Node *ast) override; - void postVisit(AST::Node *) override; - void checkDirectivePrologue(AST::StatementList *ast); void checkName(const QStringRef &name, const AST::SourceLocation &loc); @@ -160,6 +157,8 @@ protected: bool visit(AST::WithStatement *ast) override; void endVisit(AST::WithStatement *ast) override; + void throwRecursionDepthError() override; + protected: bool enterFunction(AST::Node *ast, const QString &name, AST::FormalParameterList *formals, AST::StatementList *body, bool enterName); @@ -173,8 +172,6 @@ protected: bool _allowFuncDecls; ContextType defaultProgramType; - unsigned _recursionDepth = 0; - private: static constexpr AST::Node *astNodeForGlobalEnvironment = nullptr; }; diff --git a/src/qml/compiler/qv4instr_moth.cpp b/src/qml/compiler/qv4instr_moth.cpp index f528e1f9d3..b019f191fa 100644 --- a/src/qml/compiler/qv4instr_moth.cpp +++ b/src/qml/compiler/qv4instr_moth.cpp @@ -287,6 +287,10 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st d << index << TRACE_SLOT; MOTH_END_INSTR(LoadGlobalLookup) + MOTH_BEGIN_INSTR(LoadQmlContextPropertyLookup) + d << index << TRACE_SLOT; + MOTH_END_INSTR(LoadQmlContextPropertyLookup) + MOTH_BEGIN_INSTR(StoreNameSloppy) d << name; MOTH_END_INSTR(StoreNameSloppy) @@ -328,26 +332,6 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st d << dumpRegister(property, nFormals); MOTH_END_INSTR(StoreSuperProperty) - MOTH_BEGIN_INSTR(StoreScopeObjectProperty) - d << dumpRegister(base, nFormals) << "[" << propertyIndex << "]"; - MOTH_END_INSTR(StoreScopeObjectProperty) - - MOTH_BEGIN_INSTR(LoadScopeObjectProperty) - d << dumpRegister(base, nFormals) << "[" << propertyIndex << "]" << (captureRequired ? " (capture)" : " (no capture)"); - MOTH_END_INSTR(LoadScopeObjectProperty) - - MOTH_BEGIN_INSTR(StoreContextObjectProperty) - d << dumpRegister(base, nFormals) << "[" << propertyIndex << "]"; - MOTH_END_INSTR(StoreContextObjectProperty) - - MOTH_BEGIN_INSTR(LoadContextObjectProperty) - d << dumpRegister(base, nFormals) << "[" << propertyIndex << "]" << (captureRequired ? " (capture)" : " (no capture)"); - MOTH_END_INSTR(LoadContextObjectProperty) - - MOTH_BEGIN_INSTR(LoadIdObject) - d << dumpRegister(base, nFormals) << "[" << index << "]"; - MOTH_END_INSTR(LoadIdObject) - MOTH_BEGIN_INSTR(Yield) MOTH_END_INSTR(Yield) @@ -394,15 +378,9 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st d << index << dumpArguments(argc, argv, nFormals) << TRACE_SLOT; MOTH_END_INSTR(CallGlobalLookup) - MOTH_BEGIN_INSTR(CallScopeObjectProperty) - d << dumpRegister(base, nFormals) << "." << name << dumpArguments(argc, argv, nFormals) - << TRACE_SLOT; - MOTH_END_INSTR(CallScopeObjectProperty) - - MOTH_BEGIN_INSTR(CallContextObjectProperty) - d << dumpRegister(base, nFormals) << "." << name << dumpArguments(argc, argv, nFormals) - << TRACE_SLOT; - MOTH_END_INSTR(CallContextObjectProperty) + MOTH_BEGIN_INSTR(CallQmlContextPropertyLookup) + d << index << dumpArguments(argc, argv, nFormals) << TRACE_SLOT; + MOTH_END_INSTR(CallQmlContextPropertyLookup) MOTH_BEGIN_INSTR(CallWithSpread) d << "new " << dumpRegister(func, nFormals) << dumpRegister(thisObject, nFormals) @@ -730,14 +708,6 @@ void dumpBytecode(const char *code, int len, int nLocals, int nFormals, int /*st d << index; MOTH_END_INSTR(GetTemplateObject) - MOTH_BEGIN_INSTR(LoadQmlContext) - d << dumpRegister(result, nFormals); - MOTH_END_INSTR(LoadQmlContext) - - MOTH_BEGIN_INSTR(LoadQmlImportedScripts) - d << dumpRegister(result, nFormals); - MOTH_END_INSTR(LoadQmlImportedScripts) - MOTH_BEGIN_INSTR(TailCall) d << dumpRegister(func, nFormals) << dumpRegister(thisObject, nFormals) << dumpArguments(argc, argv, nFormals); MOTH_END_INSTR(TailCall) diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h index f853c1f1ab..6a8c9a9549 100644 --- a/src/qml/compiler/qv4instr_moth_p.h +++ b/src/qml/compiler/qv4instr_moth_p.h @@ -86,12 +86,11 @@ QT_BEGIN_NAMESPACE #define INSTR_LoadClosure(op) INSTRUCTION(op, LoadClosure, 1, value) #define INSTR_LoadName(op) INSTRUCTION(op, LoadName, 2, name, traceSlot) #define INSTR_LoadGlobalLookup(op) INSTRUCTION(op, LoadGlobalLookup, 2, index, traceSlot) +#define INSTR_LoadQmlContextPropertyLookup(op) INSTRUCTION(op, LoadQmlContextPropertyLookup, 2, index, traceSlot) #define INSTR_StoreNameSloppy(op) INSTRUCTION(op, StoreNameSloppy, 1, name) #define INSTR_StoreNameStrict(op) INSTRUCTION(op, StoreNameStrict, 1, name) #define INSTR_LoadProperty(op) INSTRUCTION(op, LoadProperty, 2, name, traceSlot) #define INSTR_GetLookup(op) INSTRUCTION(op, GetLookup, 2, index, traceSlot) -#define INSTR_LoadScopeObjectProperty(op) INSTRUCTION(op, LoadScopeObjectProperty, 3, propertyIndex, base, captureRequired) -#define INSTR_LoadContextObjectProperty(op) INSTRUCTION(op, LoadContextObjectProperty, 3, propertyIndex, base, captureRequired) #define INSTR_LoadIdObject(op) INSTRUCTION(op, LoadIdObject, 2, index, base) #define INSTR_Yield(op) INSTRUCTION(op, Yield, 0) #define INSTR_YieldStar(op) INSTRUCTION(op, YieldStar, 0) @@ -101,8 +100,6 @@ QT_BEGIN_NAMESPACE #define INSTR_SetLookup(op) INSTRUCTION(op, SetLookup, 2, index, base) #define INSTR_LoadSuperProperty(op) INSTRUCTION(op, LoadSuperProperty, 1, property) #define INSTR_StoreSuperProperty(op) INSTRUCTION(op, StoreSuperProperty, 1, property) -#define INSTR_StoreScopeObjectProperty(op) INSTRUCTION(op, StoreScopeObjectProperty, 2, base, propertyIndex) -#define INSTR_StoreContextObjectProperty(op) INSTRUCTION(op, StoreContextObjectProperty, 2, base, propertyIndex) #define INSTR_LoadElement(op) INSTRUCTION(op, LoadElement, 2, base, traceSlot) #define INSTR_StoreElement(op) INSTRUCTION(op, StoreElement, 3, base, index, traceSlot) #define INSTR_CallValue(op) INSTRUCTION(op, CallValue, 4, name, argc, argv, traceSlot) @@ -113,8 +110,7 @@ QT_BEGIN_NAMESPACE #define INSTR_CallName(op) INSTRUCTION(op, CallName, 4, name, argc, argv, traceSlot) #define INSTR_CallPossiblyDirectEval(op) INSTRUCTION(op, CallPossiblyDirectEval, 3, argc, argv, traceSlot) #define INSTR_CallGlobalLookup(op) INSTRUCTION(op, CallGlobalLookup, 4, index, argc, argv, traceSlot) -#define INSTR_CallScopeObjectProperty(op) INSTRUCTION(op, CallScopeObjectProperty, 5, name, base, argc, argv, traceSlot) -#define INSTR_CallContextObjectProperty(op) INSTRUCTION(op, CallContextObjectProperty, 5, name, base, argc, argv, traceSlot) +#define INSTR_CallQmlContextPropertyLookup(op) INSTRUCTION(op, CallQmlContextPropertyLookup, 4, index, argc, argv, traceSlot) #define INSTR_CallWithSpread(op) INSTRUCTION(op, CallWithSpread, 5, func, thisObject, argc, argv, traceSlot) #define INSTR_Construct(op) INSTRUCTION(op, Construct, 3, func, argc, argv) #define INSTR_ConstructWithSpread(op) INSTRUCTION(op, ConstructWithSpread, 3, func, argc, argv) @@ -194,7 +190,6 @@ QT_BEGIN_NAMESPACE #define INSTR_Div(op) INSTRUCTION(op, Div, 1, lhs) #define INSTR_Mod(op) INSTRUCTION(op, Mod, 2, lhs, traceSlot) #define INSTR_Sub(op) INSTRUCTION(op, Sub, 2, lhs, traceSlot) -#define INSTR_LoadQmlContext(op) INSTRUCTION(op, LoadQmlContext, 1, result) #define INSTR_LoadQmlImportedScripts(op) INSTRUCTION(op, LoadQmlImportedScripts, 1, result) #define INSTR_InitializeBlockDeadTemporalZone(op) INSTRUCTION(op, InitializeBlockDeadTemporalZone, 2, firstReg, count) #define INSTR_ThrowOnNullOrUndefined(op) INSTRUCTION(op, ThrowOnNullOrUndefined, 0) @@ -228,6 +223,7 @@ QT_BEGIN_NAMESPACE F(LoadClosure) \ F(LoadName) \ F(LoadGlobalLookup) \ + F(LoadQmlContextPropertyLookup) \ F(StoreNameSloppy) \ F(StoreNameStrict) \ F(LoadElement) \ @@ -238,11 +234,6 @@ QT_BEGIN_NAMESPACE F(SetLookup) \ F(LoadSuperProperty) \ F(StoreSuperProperty) \ - F(StoreScopeObjectProperty) \ - F(StoreContextObjectProperty) \ - F(LoadScopeObjectProperty) \ - F(LoadContextObjectProperty) \ - F(LoadIdObject) \ F(ConvertThisToObject) \ F(ToObject) \ F(Jump) \ @@ -296,8 +287,7 @@ QT_BEGIN_NAMESPACE F(CallName) \ F(CallPossiblyDirectEval) \ F(CallGlobalLookup) \ - F(CallScopeObjectProperty) \ - F(CallContextObjectProperty) \ + F(CallQmlContextPropertyLookup) \ F(CallWithSpread) \ F(Construct) \ F(ConstructWithSpread) \ @@ -328,8 +318,6 @@ QT_BEGIN_NAMESPACE F(CreateMappedArgumentsObject) \ F(CreateUnmappedArgumentsObject) \ F(CreateRestParameter) \ - F(LoadQmlContext) \ - F(LoadQmlImportedScripts) \ F(Yield) \ F(YieldStar) \ F(Resume) \ |