diff options
| author | Ulf Hermann <ulf.hermann@qt.io> | 2024-11-15 13:52:25 +0100 |
|---|---|---|
| committer | Ulf Hermann <ulf.hermann@qt.io> | 2024-11-20 10:00:56 +0100 |
| commit | 1e095058e165b1c2f244799ca1928ae4cc046a2c (patch) | |
| tree | e85ad67398f6724d723cf3c3b40f602db6f37193 /src | |
| parent | 55c3b94035787ea265c5ff6e3c271d7154186def (diff) | |
QmlCompiler: Split QQmlJSRegisterContent in public and private classes
We want an easy way to hold pointers to other QQmlJSRegisterContents in
QQmlJSRegisterContent. Furthermore, copying a QQmlJSRegisterContent so
far is very expensive. Solve both problems by introducing the PIMPL
pattern with a shared d-pointer.
This also changes the equality semantics of QQmlJSRegisterContent. Two
QQmlJSRegisterContents are only equal if they contain the same d-pointer
now, not if their contents are otherwise equal. However, since we
generally don't rely on immediate equality of QQmlJSRegisterContent
anyway, this is not a problem. QQmlJSTypeResolver::equals() still works.
There is one place where the equality was used, though. That one is
adapted.
Furthermore, we now want to keep the register contents in a pool that's
automatically cleared when we're done with our analysis. Therefore the
creation methods cannot be static anymore and storedIn() as well as
castTo() need to go through the pool as well.
Task-number: QTBUG-124670
Change-Id: I0a51b609fc769ccb33c1d82930bda83c2a40e1a5
Reviewed-by: Olivier De Cannière <olivier.decanniere@qt.io>
Diffstat (limited to 'src')
| -rw-r--r-- | src/qmlcompiler/qqmljscodegenerator.cpp | 41 | ||||
| -rw-r--r-- | src/qmlcompiler/qqmljscodegenerator_p.h | 9 | ||||
| -rw-r--r-- | src/qmlcompiler/qqmljscompilepass_p.h | 2 | ||||
| -rw-r--r-- | src/qmlcompiler/qqmljsfunctioninitializer.cpp | 4 | ||||
| -rw-r--r-- | src/qmlcompiler/qqmljsregistercontent.cpp | 427 | ||||
| -rw-r--r-- | src/qmlcompiler/qqmljsregistercontent_p.h | 324 | ||||
| -rw-r--r-- | src/qmlcompiler/qqmljsshadowcheck.cpp | 2 | ||||
| -rw-r--r-- | src/qmlcompiler/qqmljsstoragegeneralizer.cpp | 2 | ||||
| -rw-r--r-- | src/qmlcompiler/qqmljsstorageinitializer.cpp | 4 | ||||
| -rw-r--r-- | src/qmlcompiler/qqmljstypepropagator.cpp | 22 | ||||
| -rw-r--r-- | src/qmlcompiler/qqmljstyperesolver.cpp | 113 | ||||
| -rw-r--r-- | src/qmlcompiler/qqmljstyperesolver_p.h | 13 |
12 files changed, 577 insertions, 386 deletions
diff --git a/src/qmlcompiler/qqmljscodegenerator.cpp b/src/qmlcompiler/qqmljscodegenerator.cpp index ce315646dc..4474fc4696 100644 --- a/src/qmlcompiler/qqmljscodegenerator.cpp +++ b/src/qmlcompiler/qqmljscodegenerator.cpp @@ -835,7 +835,8 @@ void QQmlJSCodeGenerator::generate_LoadElement(int base) // Since we can do .at() below, we know that we can natively store the element type. QQmlJSRegisterContent elementType = m_typeResolver->valueType(baseType); - elementType = elementType.storedIn(m_typeResolver->storedType(elementType.containedType())); + elementType = m_pool->storedIn( + elementType, m_typeResolver->storedType(elementType.containedType())); QString access = baseName + u".at("_s + indexName + u')'; @@ -1329,7 +1330,8 @@ QString QQmlJSCodeGenerator::generateCallConstructor( argPointers.append(contentPointer(argumentType, arg)); } else { const QQmlJSRegisterContent parameterTypeConversion - = argumentType.castTo(parameterType).storedIn( + = m_pool->storedIn( + m_pool->castTo(argumentType, parameterType), m_typeResolver->genericType(parameterType)); result += conversion(argumentType, parameterTypeConversion, argument); argPointers.append(contentPointer(parameterTypeConversion, arg)); @@ -1610,9 +1612,10 @@ void QQmlJSCodeGenerator::generate_SetLookup(int index, int baseReg) if (m_typeResolver->isPrimitive(specific.storedType()) && m_typeResolver->isPrimitive(valueType)) { // Preferably store in QJSPrimitiveValue since we need the content pointer below. - property = property.storedIn(m_typeResolver->jsPrimitiveType()); + property = m_pool->storedIn(property, m_typeResolver->jsPrimitiveType()); } else { - property = property.storedIn(m_typeResolver->merge(specific.storedType(), valueType)); + property = m_pool->storedIn( + property, m_typeResolver->merge(specific.storedType(), valueType)); } } @@ -2474,8 +2477,8 @@ void QQmlJSCodeGenerator::generate_Construct(int func, int argc, int argv) metaObject(extension ? extension : originalContained)); m_body += m_state.accumulatorVariableOut + u" = "_s - + conversion(originalResult.storedIn( - m_typeResolver->varType()), m_state.accumulatorOut(), result) + + conversion(m_pool->storedIn(originalResult, m_typeResolver->varType()), + m_state.accumulatorOut(), result) + u";\n"_s; return; @@ -2657,7 +2660,7 @@ void QQmlJSCodeGenerator::generate_IteratorNext(int value, int offset) // We know that this works because we can do ->next() below. QQmlJSRegisterContent iteratorValue = m_typeResolver->valueType(iteratorContent); - iteratorValue = iteratorValue.storedIn(iteratorValue.containedType()); + iteratorValue = m_pool->storedIn(iteratorValue, iteratorValue.containedType()); m_body += changedRegisterVariable() + u" = " + conversion( @@ -3499,24 +3502,30 @@ void QQmlJSCodeGenerator::generateEqualityOperation( } else if (m_typeResolver->equals(contained, containedOriginal)) { if (originalContent.isConversion()) { // The original conversion origins are more accurate - return originalContent.storedIn(content.storedType()); + return m_pool->storedIn(originalContent, content.storedType()); } } else if (m_typeResolver->canHold(contained, containedOriginal)) { - return originalContent.storedIn(content.storedType()); + return m_pool->storedIn(originalContent, content.storedType()); } return content; }; + const QQmlJSScope::ConstPtr lhsType = lhsContent.storedType(); + const QQmlJSScope::ConstPtr rhsType = rhsContent.storedType(); + if (!isComparable()) { QQmlJSRegisterContent lhsOriginal = retrieveOriginal(lhsContent); QQmlJSRegisterContent rhsOriginal = retrieveOriginal(rhsContent); - if (lhsOriginal != lhsContent || rhsOriginal != rhsContent) { + if (lhsOriginal.containedType() != lhsContent.containedType() + || lhsOriginal.storedType() != lhsType + || rhsOriginal.containedType() != rhsContent.containedType() + || rhsOriginal.storedType() != rhsType) { // If either side is simply a wrapping of a specific type into a more general one, we // can compare the original types instead. You can't nest wrappings after all. generateEqualityOperation(lhsOriginal, rhsOriginal, - conversion(lhsContent.storedType(), lhsOriginal, lhsName), - conversion(rhsContent.storedType(), rhsOriginal, rhsName), + conversion(lhsType, lhsOriginal, lhsName), + conversion(rhsType, rhsOriginal, rhsName), function, invert); return; } @@ -3525,9 +3534,6 @@ void QQmlJSCodeGenerator::generateEqualityOperation( rhsContent.descriptiveName(), lhsContent.descriptiveName())); } - const QQmlJSScope::ConstPtr lhsType = lhsContent.storedType(); - const QQmlJSScope::ConstPtr rhsType = rhsContent.storedType(); - if (strictlyComparableWithVar) { // Determine which side is holding a storable type if (!lhsName.isEmpty() && rhsName.isEmpty()) { @@ -4334,11 +4340,12 @@ QString QQmlJSCodeGenerator::convertContained(const QQmlJSRegisterContent &from, && m_typeResolver->canHold(containedFrom, containedOriginalFrom)) { // If from is simply a wrapping of a specific type into a more general one, we can convert // the original type instead. You can't nest wrappings after all. - return conversion(originalFrom.storedIn(from.storedType()), to, variable); + return conversion(m_pool->storedIn(originalFrom, from.storedType()), to, variable); } if (m_typeResolver->isPrimitive(containedFrom) && m_typeResolver->isPrimitive(containedTo)) { - const QQmlJSRegisterContent intermediate = from.storedIn(m_typeResolver->jsPrimitiveType()); + const QQmlJSRegisterContent intermediate + = m_pool->storedIn(from, m_typeResolver->jsPrimitiveType()); return conversion(intermediate, to, conversion(from, intermediate, variable)); } diff --git a/src/qmlcompiler/qqmljscodegenerator_p.h b/src/qmlcompiler/qqmljscodegenerator_p.h index baf9553f5c..7fd969e7d0 100644 --- a/src/qmlcompiler/qqmljscodegenerator_p.h +++ b/src/qmlcompiler/qqmljscodegenerator_p.h @@ -231,7 +231,8 @@ protected: return convertStored(from, to.storedType(), variable); } else { return convertContained( - m_typeResolver->syntheticType(from).storedIn(m_typeResolver->storedType(from)), + m_pool->storedIn( + m_typeResolver->syntheticType(from), m_typeResolver->storedType(from)), to, variable); } } @@ -241,7 +242,7 @@ protected: const QString &variable) { Q_ASSERT(m_typeResolver->equals(m_typeResolver->storedType(to), to)); - return conversion(from, from.castTo(to).storedIn(to), variable); + return conversion(from, m_pool->storedIn(m_pool->castTo(from, to), to), variable); } QString conversion(const QQmlJSScope::ConstPtr &from, @@ -361,12 +362,12 @@ private: QQmlJSRegisterContent originalType(const QQmlJSRegisterContent &tracked) { const QQmlJSRegisterContent restored = m_typeResolver->original(tracked); - return restored.storedIn(m_typeResolver->originalType(tracked.storedType())); + return m_pool->storedIn(restored, m_typeResolver->originalType(tracked.storedType())); } QQmlJSRegisterContent literalType(const QQmlJSScope::ConstPtr &contained) { - return m_typeResolver->literalType(contained).storedIn(contained); + return m_pool->storedIn(m_typeResolver->literalType(contained), contained); } bool registerIsStoredIn( diff --git a/src/qmlcompiler/qqmljscompilepass_p.h b/src/qmlcompiler/qqmljscompilepass_p.h index 3fd85356f5..77384a4ab2 100644 --- a/src/qmlcompiler/qqmljscompilepass_p.h +++ b/src/qmlcompiler/qqmljscompilepass_p.h @@ -274,6 +274,7 @@ public: const InstructionAnnotations &annotations = {}) : m_jsUnitGenerator(jsUnitGenerator) , m_typeResolver(typeResolver) + , m_pool(typeResolver->registerContentPool()) , m_logger(logger) , m_errors(errors) , m_basicBlocks(basicBlocks) @@ -283,6 +284,7 @@ public: protected: const QV4::Compiler::JSUnitGenerator *m_jsUnitGenerator = nullptr; const QQmlJSTypeResolver *m_typeResolver = nullptr; + QQmlJSRegisterContentPool *m_pool = nullptr; QQmlJSLogger *m_logger = nullptr; const Function *m_function = nullptr; diff --git a/src/qmlcompiler/qqmljsfunctioninitializer.cpp b/src/qmlcompiler/qqmljsfunctioninitializer.cpp index c276d2ff4f..2419c425ad 100644 --- a/src/qmlcompiler/qqmljsfunctioninitializer.cpp +++ b/src/qmlcompiler/qqmljsfunctioninitializer.cpp @@ -162,7 +162,7 @@ QQmlJSCompilePass::Function QQmlJSFunctionInitializer::run( bindingLocation.startColumn = irBinding.location.column(); QQmlJSCompilePass::Function function; - function.qmlScope = QQmlJSRegisterContent::create( + function.qmlScope = m_typeResolver->registerContentPool()->create( m_scopeType, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::ScopeObject); @@ -275,7 +275,7 @@ QQmlJSCompilePass::Function QQmlJSFunctionInitializer::run( Q_UNUSED(functionName); QQmlJSCompilePass::Function function; - function.qmlScope = QQmlJSRegisterContent::create( + function.qmlScope = m_typeResolver->registerContentPool()->create( m_scopeType, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::ScopeObject); diff --git a/src/qmlcompiler/qqmljsregistercontent.cpp b/src/qmlcompiler/qqmljsregistercontent.cpp index cc5d92eff7..04cc547f22 100644 --- a/src/qmlcompiler/qqmljsregistercontent.cpp +++ b/src/qmlcompiler/qqmljsregistercontent.cpp @@ -3,22 +3,171 @@ #include "qqmljsregistercontent_p.h" +#include <variant> + QT_BEGIN_NAMESPACE using namespace Qt::StringLiterals; -QQmlJSRegisterContent::QQmlJSRegisterContent() = default; +struct QQmlJSRegisterContentPrivate +{ +public: + + using ContentVariant = QQmlJSRegisterContent::ContentVariant; + + enum class Kind : size_t { + Type, Property, Enum, Method, ImportNamespace, Conversion, MethodCall + }; + + struct ConvertedTypes + { + QList<QQmlJSRegisterContent> origins; + QQmlJSScope::ConstPtr result; + QQmlJSRegisterContent resultScope; + + friend size_t qHash(const ConvertedTypes &types, size_t seed = 0) + { + return qHashMulti(seed, types.origins, types.result, types.resultScope); + } + + friend bool operator==(const ConvertedTypes &a, const ConvertedTypes &b) + { + return a.origins == b.origins && a.result == b.result && a.resultScope == b.resultScope; + } + + friend bool operator!=(const ConvertedTypes &a, const ConvertedTypes &b) + { + return !(a == b); + } + }; + + struct PropertyLookup + { + QQmlJSMetaProperty property; + int baseLookupIndex = QQmlJSRegisterContent::InvalidLookupIndex; + int resultLookupIndex = QQmlJSRegisterContent::InvalidLookupIndex; + + friend size_t qHash(const PropertyLookup &property, size_t seed = 0) + { + return qHashMulti( + seed, property.property, property.baseLookupIndex, property.resultLookupIndex); + } + + friend bool operator==(const PropertyLookup &a, const PropertyLookup &b) + { + return a.baseLookupIndex == b.baseLookupIndex + && a.resultLookupIndex == b.resultLookupIndex + && a.property == b.property; + } + + friend bool operator!=(const PropertyLookup &a, const PropertyLookup &b) + { + return !(a == b); + } + }; + + using Content = std::variant< + std::pair<QQmlJSScope::ConstPtr, int>, + PropertyLookup, + std::pair<QQmlJSMetaEnum, QString>, + std::pair<QList<QQmlJSMetaMethod>, QQmlJSScope::ConstPtr>, + std::pair<uint, QQmlJSScope::ConstPtr>, + ConvertedTypes, + QQmlJSMetaMethod + >; + + friend size_t qHash(const QQmlJSRegisterContentPrivate ®isterContent, size_t seed = 0) + { + seed = qHashMulti( + seed, registerContent.m_storedType, registerContent.m_content.index(), + registerContent.m_variant, registerContent.m_scope); + + switch (Kind(registerContent.m_content.index())) { + case Kind::Type: + return qHash(std::get<std::pair<QQmlJSScope::ConstPtr, int>>(registerContent.m_content), + seed); + case Kind::Property: + return qHash(std::get<PropertyLookup>(registerContent.m_content), seed); + case Kind::Enum: + return qHash(std::get<std::pair<QQmlJSMetaEnum, QString>>(registerContent.m_content), + seed); + case Kind::Method: + return qHash(std::get<std::pair<QList<QQmlJSMetaMethod>, QQmlJSScope::ConstPtr>>( + registerContent.m_content), seed); + case Kind::ImportNamespace: + return qHash(std::get<std::pair<uint, QQmlJSScope::ConstPtr>>( + registerContent.m_content), seed); + case Kind::Conversion: + return qHash(std::get<ConvertedTypes>(registerContent.m_content), seed); + case Kind::MethodCall: + return qHash(std::get<QQmlJSMetaMethod>(registerContent.m_content), seed); + } + + Q_UNREACHABLE_RETURN(seed); + } + + friend bool operator==( + const QQmlJSRegisterContentPrivate &a, const QQmlJSRegisterContentPrivate &b) + { + return a.m_storedType == b.m_storedType && a.m_variant == b.m_variant + && a.m_scope == b.m_scope && a.m_content == b.m_content; + } + + friend bool operator!=( + const QQmlJSRegisterContentPrivate &a, const QQmlJSRegisterContentPrivate &b) + { + return !(a == b); + } + + QQmlJSScope::ConstPtr m_storedType; + QQmlJSRegisterContent m_scope; + Content m_content; + ContentVariant m_variant = ContentVariant::Unknown; + + int resultLookupIndex() const + { + switch (Kind(m_content.index())) { + case Kind::Type: + return std::get<std::pair<QQmlJSScope::ConstPtr, int>>(m_content).second; + case Kind::Property: + return std::get<PropertyLookup>(m_content).resultLookupIndex; + default: + return QQmlJSRegisterContent::InvalidLookupIndex; + } + } + +private: + friend class QQmlJSRegisterContentPool; + + QQmlJSRegisterContentPrivate() = default; + ~QQmlJSRegisterContentPrivate() = default; + QQmlJSRegisterContentPrivate(const QQmlJSRegisterContentPrivate &) = default; + QQmlJSRegisterContentPrivate(QQmlJSRegisterContentPrivate &&) = default; + QQmlJSRegisterContentPrivate &operator=(const QQmlJSRegisterContentPrivate &) = default; + QQmlJSRegisterContentPrivate &operator=(QQmlJSRegisterContentPrivate &&) = default; +}; + +QQmlJSRegisterContent::QQmlJSRegisterContent() + : d(QQmlJSRegisterContentPool::invalid()) +{} + +bool QQmlJSRegisterContent::isValid() const +{ + return !containedType().isNull(); +}; QString QQmlJSRegisterContent::descriptiveName() const { - if (m_storedType.isNull() && containedType().isNull()) + using Kind = QQmlJSRegisterContentPrivate::Kind; + + if (d->m_storedType.isNull() && containedType().isNull()) return u"(invalid type)"_s; const auto scope = [this]() -> QString { - if (m_scope.isNull()) + if (!d->m_scope.isValid()) return u"(invalid type)::"_s; - const QQmlJSScope::ConstPtr scopeContained = m_scope->containedType(); + const QQmlJSScope::ConstPtr scopeContained = d->m_scope.containedType(); if (scopeContained.isNull()) return u"(invalid type)::"_s; @@ -31,19 +180,19 @@ QString QQmlJSRegisterContent::descriptiveName() const }; QString result; - switch (Kind(m_content.index())) { + switch (Kind(d->m_content.index())) { case Kind::Type: { const QQmlJSScope::ConstPtr contained = type(); result += contained->internalName(); - if (m_storedType && m_storedType->internalName() != contained->internalName()) - result += u" stored as "_s + m_storedType->internalName(); + if (d->m_storedType && d->m_storedType->internalName() != contained->internalName()) + result += u" stored as "_s + d->m_storedType->internalName(); return result; } case Kind::Property: { const QQmlJSMetaProperty prop = property(); result += scope() + prop.propertyName() + u" with type "_s + prop.typeName(); - if (m_storedType && m_storedType->internalName() != prop.typeName()) - result += u" (stored as "_s + m_storedType->internalName() + u")"; + if (d->m_storedType && d->m_storedType->internalName() != prop.typeName()) + result += u" (stored as "_s + d->m_storedType->internalName() + u")"; return result; } case Kind::Method: { @@ -52,8 +201,8 @@ QString QQmlJSRegisterContent::descriptiveName() const result = scope() + u"(unknown method)"_s; else result = scope() + methods[0].methodName() + u"(...)"_s; - if (m_storedType) - return result + u" (stored as "_s + m_storedType->internalName() + u")"; + if (d->m_storedType) + return result + u" (stored as "_s + d->m_storedType->internalName() + u")"; return result; } case Kind::Enum: { @@ -63,8 +212,8 @@ QString QQmlJSRegisterContent::descriptiveName() const result = scope() + enumName; else result = scope() + enumName + u"::"_s + memberName; - if (m_storedType) - return result + u" (stored as "_s + m_storedType->internalName() + u")"; + if (d->m_storedType) + return result + u" (stored as "_s + d->m_storedType->internalName() + u")"; return result; } case Kind::ImportNamespace: { @@ -74,7 +223,7 @@ QString QQmlJSRegisterContent::descriptiveName() const return u"conversion to %1"_s.arg(conversionResult()->internalName()); } case Kind::MethodCall: { - const QQmlJSMetaMethod &method = std::get<QQmlJSMetaMethod>(m_content); + const QQmlJSMetaMethod &method = std::get<QQmlJSMetaMethod>(d->m_content); return u"call to method %1, returning %2"_s.arg( method.methodName(), method.returnTypeName()); } @@ -100,21 +249,58 @@ QString QQmlJSRegisterContent::containedTypeName() const type->internalName().isEmpty() ? type->baseTypeName() : type->internalName()); } +bool QQmlJSRegisterContent::isType() const +{ + return d->m_content.index() == size_t(QQmlJSRegisterContentPrivate::Kind::Type); +} + +bool QQmlJSRegisterContent::isProperty() const +{ + return d->m_content.index() == size_t(QQmlJSRegisterContentPrivate::Kind::Property); +} + +bool QQmlJSRegisterContent::isEnumeration() const +{ + return d->m_content.index() == size_t(QQmlJSRegisterContentPrivate::Kind::Enum); +} + +bool QQmlJSRegisterContent::isMethod() const +{ + return d->m_content.index() == size_t(QQmlJSRegisterContentPrivate::Kind::Method); +} + +bool QQmlJSRegisterContent::isImportNamespace() const +{ + return d->m_content.index() == size_t(QQmlJSRegisterContentPrivate::Kind::ImportNamespace); +} + +bool QQmlJSRegisterContent::isConversion() const +{ + return d->m_content.index() == size_t(QQmlJSRegisterContentPrivate::Kind::Conversion); +} + +bool QQmlJSRegisterContent::isMethodCall() const +{ + return d->m_content.index() == size_t(QQmlJSRegisterContentPrivate::Kind::MethodCall); +} + bool QQmlJSRegisterContent::isList() const { - switch (Kind(m_content.index())) { + using Kind = QQmlJSRegisterContentPrivate::Kind; + + switch (Kind(d->m_content.index())) { case Kind::Type: - return std::get<std::pair<QQmlJSScope::ConstPtr, int>>(m_content).first->accessSemantics() - == QQmlJSScope::AccessSemantics::Sequence; + return std::get<std::pair<QQmlJSScope::ConstPtr, int>>(d->m_content).first + ->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence; case Kind::Property: - return std::get<PropertyLookup>(m_content).property.type()->accessSemantics() - == QQmlJSScope::AccessSemantics::Sequence; + return std::get<QQmlJSRegisterContentPrivate::PropertyLookup>(d->m_content).property.type() + ->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence; case Kind::Conversion: - return std::get<ConvertedTypes>(m_content).result->accessSemantics() - == QQmlJSScope::AccessSemantics::Sequence; + return std::get<QQmlJSRegisterContentPrivate::ConvertedTypes>(d->m_content).result + ->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence; case Kind::MethodCall: - return std::get<QQmlJSMetaMethod>(m_content).returnType()->accessSemantics() - == QQmlJSScope::AccessSemantics::Sequence; + return std::get<QQmlJSMetaMethod>(d->m_content).returnType() + ->accessSemantics() == QQmlJSScope::AccessSemantics::Sequence; default: return false; } @@ -122,9 +308,12 @@ bool QQmlJSRegisterContent::isList() const bool QQmlJSRegisterContent::isWritable() const { - switch (Kind(m_content.index())) { + using Kind = QQmlJSRegisterContentPrivate::Kind; + + switch (Kind(d->m_content.index())) { case Kind::Property: - return std::get<PropertyLookup>(m_content).property.isWritable(); + return std::get<QQmlJSRegisterContentPrivate::PropertyLookup>(d->m_content) + .property.isWritable(); // TODO: What can we actually write? default: @@ -134,6 +323,11 @@ bool QQmlJSRegisterContent::isWritable() const return true; } +bool QQmlJSRegisterContent::isJavaScriptReturnValue() const +{ + return isMethodCall() && std::get<QQmlJSMetaMethod>(d->m_content).isJavaScriptFunction(); +} + /*! * \internal * Precondition: This is an attachment. @@ -141,7 +335,7 @@ bool QQmlJSRegisterContent::isWritable() const */ QQmlJSRegisterContent QQmlJSRegisterContent::attacher() const { - Q_ASSERT(m_variant == Attachment); + Q_ASSERT(d->m_variant == Attachment); return scopeType(); } @@ -152,21 +346,26 @@ QQmlJSRegisterContent QQmlJSRegisterContent::attacher() const */ QQmlJSRegisterContent QQmlJSRegisterContent::attachee() const { - Q_ASSERT(m_variant == Attachment); + Q_ASSERT(d->m_variant == Attachment); QQmlJSRegisterContent attachee = attacher().scopeType(); while (attachee.variant() == ModulePrefix) attachee = attachee.scopeType(); return attachee; } +QQmlJSScope::ConstPtr QQmlJSRegisterContent::storedType() const +{ + return d->m_storedType; +} + QQmlJSScope::ConstPtr QQmlJSRegisterContent::containedType() const { if (isType()) return type(); if (isProperty()) - return std::get<PropertyLookup>(m_content).property.type(); + return std::get<QQmlJSRegisterContentPrivate::PropertyLookup>(d->m_content).property.type(); if (isEnumeration()) - return std::get<std::pair<QQmlJSMetaEnum, QString>>(m_content).first.type(); + return std::get<std::pair<QQmlJSMetaEnum, QString>>(d->m_content).first.type(); if (isMethod()) return methodType(); if (isImportNamespace()) @@ -174,86 +373,210 @@ QQmlJSScope::ConstPtr QQmlJSRegisterContent::containedType() const if (isConversion()) return conversionResult(); if (isMethodCall()) - return std::get<QQmlJSMetaMethod>(m_content).returnType(); + return std::get<QQmlJSMetaMethod>(d->m_content).returnType(); Q_UNREACHABLE_RETURN({}); } -QQmlJSRegisterContent QQmlJSRegisterContent::create( +QQmlJSRegisterContent QQmlJSRegisterContent::scopeType() const +{ + return d->m_scope; +} + +QQmlJSScope::ConstPtr QQmlJSRegisterContent::type() const +{ + return std::get<std::pair<QQmlJSScope::ConstPtr, int>>(d->m_content).first; +} + +QQmlJSMetaProperty QQmlJSRegisterContent::property() const +{ + return std::get<QQmlJSRegisterContentPrivate::PropertyLookup>(d->m_content).property; +} + +int QQmlJSRegisterContent::baseLookupIndex() const +{ + return std::get<QQmlJSRegisterContentPrivate::PropertyLookup>(d->m_content).baseLookupIndex; +} + +int QQmlJSRegisterContent::resultLookupIndex() const +{ + return d->resultLookupIndex(); +} + +QQmlJSMetaEnum QQmlJSRegisterContent::enumeration() const +{ + return std::get<std::pair<QQmlJSMetaEnum, QString>>(d->m_content).first; +} + +QString QQmlJSRegisterContent::enumMember() const +{ + return std::get<std::pair<QQmlJSMetaEnum, QString>>(d->m_content).second; +} + +QList<QQmlJSMetaMethod> QQmlJSRegisterContent::method() const +{ + return std::get<std::pair<QList<QQmlJSMetaMethod>, QQmlJSScope::ConstPtr>>(d->m_content).first; +} + +QQmlJSScope::ConstPtr QQmlJSRegisterContent::methodType() const +{ + return std::get<std::pair<QList<QQmlJSMetaMethod>, QQmlJSScope::ConstPtr>>(d->m_content).second; +} + +uint QQmlJSRegisterContent::importNamespace() const +{ + return std::get<std::pair<uint, QQmlJSScope::ConstPtr>>(d->m_content).first; +} + +QQmlJSScope::ConstPtr QQmlJSRegisterContent::importNamespaceType() const +{ + return std::get<std::pair<uint, QQmlJSScope::ConstPtr>>(d->m_content).second; +} + +QQmlJSScope::ConstPtr QQmlJSRegisterContent::conversionResult() const +{ + return std::get<QQmlJSRegisterContentPrivate::ConvertedTypes>(d->m_content).result; +} + +QQmlJSRegisterContent QQmlJSRegisterContent::conversionResultScope() const +{ + return std::get<QQmlJSRegisterContentPrivate::ConvertedTypes>(d->m_content).resultScope; +} + +QList<QQmlJSRegisterContent> QQmlJSRegisterContent::conversionOrigins() const +{ + return std::get<QQmlJSRegisterContentPrivate::ConvertedTypes>(d->m_content).origins; +} + +QQmlJSMetaMethod QQmlJSRegisterContent::methodCall() const +{ + return std::get<QQmlJSMetaMethod>(d->m_content); +} + +QQmlJSRegisterContent::ContentVariant QQmlJSRegisterContent::variant() const +{ + return d->m_variant; +} + +QQmlJSRegisterContentPool::QQmlJSRegisterContentPool() = default; +QQmlJSRegisterContentPool::~QQmlJSRegisterContentPool() = default; + +const QQmlJSRegisterContentPrivate QQmlJSRegisterContentPool::s_invalid; + +QQmlJSRegisterContent QQmlJSRegisterContentPool::create( const QQmlJSScope::ConstPtr &type, int resultLookupIndex, QQmlJSRegisterContent::ContentVariant variant, const QQmlJSRegisterContent &scope) { - QQmlJSRegisterContent result(scope, variant); - result.m_content = std::make_pair(type, resultLookupIndex); + QQmlJSRegisterContentPrivate *result = create(scope, variant); + result->m_content = std::make_pair(type, resultLookupIndex); return result; } -QQmlJSRegisterContent QQmlJSRegisterContent::create( +QQmlJSRegisterContent QQmlJSRegisterContentPool::create( const QQmlJSMetaProperty &property, int baseLookupIndex, int resultLookupIndex, QQmlJSRegisterContent::ContentVariant variant, const QQmlJSRegisterContent &scope) { - QQmlJSRegisterContent result(scope, variant); - result.m_content = PropertyLookup { property, baseLookupIndex, resultLookupIndex}; + QQmlJSRegisterContentPrivate *result = create(scope, variant); + result->m_content = QQmlJSRegisterContentPrivate::PropertyLookup { + property, + baseLookupIndex, + resultLookupIndex + }; return result; } -QQmlJSRegisterContent QQmlJSRegisterContent::create( +QQmlJSRegisterContent QQmlJSRegisterContentPool::create( const QQmlJSMetaEnum &enumeration, const QString &enumMember, QQmlJSRegisterContent::ContentVariant variant, const QQmlJSRegisterContent &scope) { - QQmlJSRegisterContent result(scope, variant); - result.m_content = std::make_pair(enumeration, enumMember); + QQmlJSRegisterContentPrivate *result = create(scope, variant); + result->m_content = std::make_pair(enumeration, enumMember); return result; } -QQmlJSRegisterContent QQmlJSRegisterContent::create( +QQmlJSRegisterContent QQmlJSRegisterContentPool::create( const QList<QQmlJSMetaMethod> &methods, const QQmlJSScope::ConstPtr &methodType, QQmlJSRegisterContent::ContentVariant variant, const QQmlJSRegisterContent &scope) { // Methods can only be stored in QJSValue. Q_ASSERT(methodType->internalName() == u"QJSValue"_s); - QQmlJSRegisterContent result(scope, variant); - result.m_content = std::make_pair(methods, methodType); + QQmlJSRegisterContentPrivate *result = create(scope, variant); + result->m_content = std::make_pair(methods, methodType); return result; } -QQmlJSRegisterContent QQmlJSRegisterContent::create( +QQmlJSRegisterContent QQmlJSRegisterContentPool::create( const QQmlJSMetaMethod &method, const QQmlJSScope::ConstPtr &returnType, const QQmlJSRegisterContent &scope) { - QQmlJSRegisterContent result(scope, MethodCall); + QQmlJSRegisterContentPrivate *result = create(scope, ContentVariant::MethodCall); QQmlJSMetaMethod resultMethod = method; resultMethod.setReturnType({ returnType }); resultMethod.setReturnTypeName(returnType->internalName()); - result.m_content = std::move(resultMethod); + result->m_content = std::move(resultMethod); return result; } -QQmlJSRegisterContent QQmlJSRegisterContent::create( +QQmlJSRegisterContent QQmlJSRegisterContentPool::create( uint importNamespaceStringId, const QQmlJSScope::ConstPtr &importNamespaceType, QQmlJSRegisterContent::ContentVariant variant, const QQmlJSRegisterContent &scope) { - QQmlJSRegisterContent result(scope, variant); - result.m_content = std::make_pair(importNamespaceStringId, importNamespaceType); + QQmlJSRegisterContentPrivate *result = create(scope, variant); + result->m_content = std::make_pair(importNamespaceStringId, importNamespaceType); return result; } -QQmlJSRegisterContent QQmlJSRegisterContent::create( +QQmlJSRegisterContent QQmlJSRegisterContentPool::create( const QList<QQmlJSRegisterContent> &origins, const QQmlJSScope::ConstPtr &conversion, const QQmlJSRegisterContent &conversionScope, ContentVariant variant, const QQmlJSRegisterContent &scope) { - QQmlJSRegisterContent result(scope, variant); + QQmlJSRegisterContentPrivate *result = create(scope, variant); - result.m_content = ConvertedTypes { + result->m_content = QQmlJSRegisterContentPrivate::ConvertedTypes { origins, conversion, - QSharedPointer<QQmlJSRegisterContent>::create(conversionScope) + conversionScope }; return result; } +QQmlJSRegisterContent QQmlJSRegisterContentPool::storedIn( + const QQmlJSRegisterContent &content, const QQmlJSScope::ConstPtr &newStoredType) +{ + QQmlJSRegisterContentPrivate *result = clone(content.d); + result->m_storedType = newStoredType; + return result; +} + +QQmlJSRegisterContent QQmlJSRegisterContentPool::castTo( + const QQmlJSRegisterContent &content, const QQmlJSScope::ConstPtr &newContainedType) +{ + // This is not a conversion but a run time cast. It may result in null or undefined. + QQmlJSRegisterContentPrivate *result = clone(content.d); + result->m_content = std::make_pair(newContainedType, result->resultLookupIndex()); + return result; +} + +QQmlJSRegisterContentPrivate *QQmlJSRegisterContentPool::clone( + const QQmlJSRegisterContentPrivate *from) +{ + m_pool.push_back(std::unique_ptr<QQmlJSRegisterContentPrivate, Deleter>(from + ? new QQmlJSRegisterContentPrivate(*from) + : new QQmlJSRegisterContentPrivate)); + return m_pool.back().get(); +} + +QQmlJSRegisterContentPrivate *QQmlJSRegisterContentPool::create( + const QQmlJSRegisterContent &scope, ContentVariant variant) +{ + QQmlJSRegisterContentPrivate *result = create(); + result->m_scope = scope; + result->m_variant = variant; + return result; +} + QT_END_NAMESPACE diff --git a/src/qmlcompiler/qqmljsregistercontent_p.h b/src/qmlcompiler/qqmljsregistercontent_p.h index 56817969e9..433a62ac9e 100644 --- a/src/qmlcompiler/qqmljsregistercontent_p.h +++ b/src/qmlcompiler/qqmljsregistercontent_p.h @@ -18,10 +18,9 @@ #include <QtCore/qhash.h> #include <QtCore/qstring.h> -#include <variant> - QT_BEGIN_NAMESPACE +struct QQmlJSRegisterContentPrivate; class Q_QMLCOMPILER_EXPORT QQmlJSRegisterContent { public: @@ -57,277 +56,140 @@ public: enum { InvalidLookupIndex = -1 }; QQmlJSRegisterContent(); - bool isValid() const { return !containedType().isNull(); } + bool isValid() const; QString descriptiveName() const; QString containedTypeName() const; - friend bool operator==(const QQmlJSRegisterContent &a, const QQmlJSRegisterContent &b) - { - return a.m_storedType == b.m_storedType && a.m_variant == b.m_variant - && (a.m_scope ? (b.m_scope && *a.m_scope == *b.m_scope) : !b.m_scope) - && a.m_content == b.m_content; - } - - friend bool operator!=(const QQmlJSRegisterContent &a, const QQmlJSRegisterContent &b) - { - return !(a == b); - } - - bool isType() const { return m_content.index() == size_t(Kind::Type); } - bool isProperty() const { return m_content.index() == size_t(Kind::Property); } - bool isEnumeration() const { return m_content.index() == size_t(Kind::Enum); } - bool isMethod() const { return m_content.index() == size_t(Kind::Method); } - bool isImportNamespace() const { return m_content.index() == size_t(Kind::ImportNamespace); } - bool isConversion() const { return m_content.index() == size_t(Kind::Conversion); } - bool isMethodCall() const { return m_content.index() == size_t(Kind::MethodCall); } + bool isType() const; + bool isProperty() const; + bool isEnumeration() const; + bool isMethod() const; + bool isImportNamespace() const; + bool isConversion() const; + bool isMethodCall() const; bool isList() const; bool isWritable() const; - bool isJavaScriptReturnValue() const - { - return isMethodCall() && std::get<QQmlJSMetaMethod>(m_content).isJavaScriptFunction(); - } + bool isJavaScriptReturnValue() const; QQmlJSRegisterContent attacher() const; QQmlJSRegisterContent attachee() const; - QQmlJSScope::ConstPtr storedType() const { return m_storedType; } + QQmlJSScope::ConstPtr storedType() const; QQmlJSScope::ConstPtr containedType() const; - QQmlJSRegisterContent scopeType() const { return m_scope ? *m_scope : QQmlJSRegisterContent(); } + QQmlJSRegisterContent scopeType() const; + + QQmlJSScope::ConstPtr type() const; + QQmlJSMetaProperty property() const; + int baseLookupIndex() const; + + int resultLookupIndex() const; + + QQmlJSMetaEnum enumeration() const; + QString enumMember() const; + QList<QQmlJSMetaMethod> method() const; + QQmlJSScope::ConstPtr methodType() const; + uint importNamespace() const; + QQmlJSScope::ConstPtr importNamespaceType() const; + QQmlJSScope::ConstPtr conversionResult() const; + QQmlJSRegisterContent conversionResultScope() const; + QList<QQmlJSRegisterContent> conversionOrigins() const; + QQmlJSMetaMethod methodCall() const; + ContentVariant variant() const; - QQmlJSScope::ConstPtr type() const - { - return std::get<std::pair<QQmlJSScope::ConstPtr, int>>(m_content).first; - } - QQmlJSMetaProperty property() const - { - return std::get<PropertyLookup>(m_content).property; - } - int baseLookupIndex() const - { - return std::get<PropertyLookup>(m_content).baseLookupIndex; - } - int resultLookupIndex() const - { - switch (Kind(m_content.index())) { - case Kind::Type: - return std::get<std::pair<QQmlJSScope::ConstPtr, int>>(m_content).second; - case Kind::Property: - return std::get<PropertyLookup>(m_content).resultLookupIndex; - default: - return InvalidLookupIndex; - } - } - QQmlJSMetaEnum enumeration() const - { - return std::get<std::pair<QQmlJSMetaEnum, QString>>(m_content).first; - } - QString enumMember() const - { - return std::get<std::pair<QQmlJSMetaEnum, QString>>(m_content).second; - } - QList<QQmlJSMetaMethod> method() const - { - return std::get<std::pair<QList<QQmlJSMetaMethod>, QQmlJSScope::ConstPtr>>( - m_content).first; - } - QQmlJSScope::ConstPtr methodType() const - { - return std::get<std::pair<QList<QQmlJSMetaMethod>, QQmlJSScope::ConstPtr>>( - m_content).second; - } - uint importNamespace() const - { - return std::get<std::pair<uint, QQmlJSScope::ConstPtr>>(m_content).first; - } - QQmlJSScope::ConstPtr importNamespaceType() const - { - return std::get<std::pair<uint, QQmlJSScope::ConstPtr>>(m_content).second; - } +private: + friend class QQmlJSRegisterContentPool; + // TODO: Constant string/number/bool/enumval - QQmlJSScope::ConstPtr conversionResult() const - { - return std::get<ConvertedTypes>(m_content).result; - } + QQmlJSRegisterContent(QQmlJSRegisterContentPrivate *dd) : d(dd) {}; - QQmlJSRegisterContent conversionResultScope() const + friend bool operator==(const QQmlJSRegisterContent &a, const QQmlJSRegisterContent &b) { - const auto result = std::get<ConvertedTypes>(m_content).resultScope; - return result ? *result : QQmlJSRegisterContent(); + return a.d == b.d; } - QList<QQmlJSRegisterContent> conversionOrigins() const + friend bool operator!=(const QQmlJSRegisterContent &a, const QQmlJSRegisterContent &b) { - return std::get<ConvertedTypes>(m_content).origins; + return !(a == b); } - QQmlJSMetaMethod methodCall() const + friend size_t qHash(const QQmlJSRegisterContent ®isterContent, size_t seed = 0) { - return std::get<QQmlJSMetaMethod>(m_content); + return qHash(registerContent.d, seed); } - ContentVariant variant() const { return m_variant; } + const QQmlJSRegisterContentPrivate *d = nullptr; +}; - friend size_t qHash(const QQmlJSRegisterContent ®isterContent, size_t seed = 0) - { - seed = qHashMulti( - seed, registerContent.m_storedType, registerContent.m_content.index(), - registerContent.m_variant); - - if (registerContent.m_scope) - seed = qHash(registerContent.m_scope, seed); - - switch (Kind(registerContent.m_content.index())) { - case Kind::Type: - return qHash(std::get<std::pair<QQmlJSScope::ConstPtr, int>>(registerContent.m_content), - seed); - case Kind::Property: - return qHash(std::get<PropertyLookup>(registerContent.m_content), seed); - case Kind::Enum: - return qHash(std::get<std::pair<QQmlJSMetaEnum, QString>>(registerContent.m_content), - seed); - case Kind::Method: - return qHash(std::get<std::pair<QList<QQmlJSMetaMethod>, QQmlJSScope::ConstPtr>>( - registerContent.m_content), seed); - case Kind::ImportNamespace: - return qHash(std::get<std::pair<uint, QQmlJSScope::ConstPtr>>( - registerContent.m_content), seed); - case Kind::Conversion: - return qHash(std::get<ConvertedTypes>(registerContent.m_content), seed); - case Kind::MethodCall: - return qHash(std::get<QQmlJSMetaMethod>(registerContent.m_content), seed); - } - - Q_UNREACHABLE_RETURN(seed); - } +class Q_QMLCOMPILER_EXPORT QQmlJSRegisterContentPool +{ + Q_DISABLE_COPY_MOVE(QQmlJSRegisterContentPool) +public: + using ContentVariant = QQmlJSRegisterContent::ContentVariant; - static QQmlJSRegisterContent create(const QQmlJSScope::ConstPtr &type, - int resultLookupIndex, ContentVariant variant, - const QQmlJSRegisterContent &scope = {}); + QQmlJSRegisterContentPool(); + ~QQmlJSRegisterContentPool(); - static QQmlJSRegisterContent create(const QQmlJSMetaProperty &property, - int baseLookupIndex, int resultLookupIndex, - ContentVariant variant, - const QQmlJSRegisterContent &scope); + QQmlJSRegisterContent create(const QQmlJSScope::ConstPtr &type, + int resultLookupIndex, ContentVariant variant, + const QQmlJSRegisterContent &scope = {}); - static QQmlJSRegisterContent create(const QQmlJSMetaEnum &enumeration, - const QString &enumMember, ContentVariant variant, - const QQmlJSRegisterContent &scope); + QQmlJSRegisterContent create(const QQmlJSMetaProperty &property, + int baseLookupIndex, int resultLookupIndex, + ContentVariant variant, + const QQmlJSRegisterContent &scope); - static QQmlJSRegisterContent create(const QList<QQmlJSMetaMethod> &methods, - const QQmlJSScope::ConstPtr &methodType, - ContentVariant variant, - const QQmlJSRegisterContent &scope); + QQmlJSRegisterContent create(const QQmlJSMetaEnum &enumeration, + const QString &enumMember, ContentVariant variant, + const QQmlJSRegisterContent &scope); - static QQmlJSRegisterContent create(const QQmlJSMetaMethod &method, - const QQmlJSScope::ConstPtr &returnType, - const QQmlJSRegisterContent &scope); + QQmlJSRegisterContent create(const QList<QQmlJSMetaMethod> &methods, + const QQmlJSScope::ConstPtr &methodType, + ContentVariant variant, + const QQmlJSRegisterContent &scope); - static QQmlJSRegisterContent create(uint importNamespaceStringId, - const QQmlJSScope::ConstPtr &importNamespaceType, - ContentVariant variant, - const QQmlJSRegisterContent &scope = {}); + QQmlJSRegisterContent create(const QQmlJSMetaMethod &method, + const QQmlJSScope::ConstPtr &returnType, + const QQmlJSRegisterContent &scope); - static QQmlJSRegisterContent create(const QList<QQmlJSRegisterContent> &origins, - const QQmlJSScope::ConstPtr &conversion, - const QQmlJSRegisterContent &conversionScope, - ContentVariant variant, - const QQmlJSRegisterContent &scope = {}); + QQmlJSRegisterContent create(uint importNamespaceStringId, + const QQmlJSScope::ConstPtr &importNamespaceType, + ContentVariant variant, + const QQmlJSRegisterContent &scope = {}); - QQmlJSRegisterContent storedIn(const QQmlJSScope::ConstPtr &newStoredType) const - { - QQmlJSRegisterContent result = *this; - result.m_storedType = newStoredType; - return result; - } + QQmlJSRegisterContent create(const QList<QQmlJSRegisterContent> &origins, + const QQmlJSScope::ConstPtr &conversion, + const QQmlJSRegisterContent &conversionScope, + ContentVariant variant, + const QQmlJSRegisterContent &scope = {}); - QQmlJSRegisterContent castTo(const QQmlJSScope::ConstPtr &newContainedType) const - { - // This is not a conversion but a run time cast. It may result in null or undefined. - QQmlJSRegisterContent result = *this; - result.m_content = std::make_pair(newContainedType, result.resultLookupIndex()); - return result; - } + QQmlJSRegisterContent storedIn( + const QQmlJSRegisterContent &content, const QQmlJSScope::ConstPtr &newStoredType); -private: - enum class Kind : size_t { - Type, Property, Enum, Method, ImportNamespace, Conversion, MethodCall - }; + QQmlJSRegisterContent castTo( + const QQmlJSRegisterContent &content, const QQmlJSScope::ConstPtr &newContainedType); - struct ConvertedTypes - { - QList<QQmlJSRegisterContent> origins; - QQmlJSScope::ConstPtr result; - QSharedPointer<QQmlJSRegisterContent> resultScope; - - friend size_t qHash(const ConvertedTypes &types, size_t seed = 0) - { - return qHashMulti(seed, types.origins, types.result, - types.resultScope ? *types.resultScope : QQmlJSRegisterContent()); - } - - friend bool operator==(const ConvertedTypes &a, const ConvertedTypes &b) - { - return a.origins == b.origins && a.result == b.result - && (a.resultScope - ? (b.resultScope && *a.resultScope == *b.resultScope) - : !b.resultScope); - } - - friend bool operator!=(const ConvertedTypes &a, const ConvertedTypes &b) - { - return !(a == b); - } - }; + static const QQmlJSRegisterContentPrivate *invalid() { return &s_invalid; } - struct PropertyLookup - { - QQmlJSMetaProperty property; - int baseLookupIndex = InvalidLookupIndex; - int resultLookupIndex = InvalidLookupIndex; - - friend size_t qHash(const PropertyLookup &property, size_t seed = 0) - { - return qHashMulti( - seed, property.property, property.baseLookupIndex, property.resultLookupIndex); - } - - friend bool operator==(const PropertyLookup &a, const PropertyLookup &b) - { - return a.baseLookupIndex == b.baseLookupIndex - && a.resultLookupIndex == b.resultLookupIndex - && a.property == b.property; - } - - friend bool operator!=(const PropertyLookup &a, const PropertyLookup &b) - { - return !(a == b); - } +private: + struct Deleter { + // It's a template so that we only need the QQmlJSRegisterContentPrivate dtor on usage. + template<typename Private> + constexpr void operator()(Private *d) const { delete d; } }; - using Content = std::variant< - std::pair<QQmlJSScope::ConstPtr, int>, - PropertyLookup, - std::pair<QQmlJSMetaEnum, QString>, - std::pair<QList<QQmlJSMetaMethod>, QQmlJSScope::ConstPtr>, - std::pair<uint, QQmlJSScope::ConstPtr>, - ConvertedTypes, - QQmlJSMetaMethod - >; - - QQmlJSRegisterContent(const QQmlJSRegisterContent &scope, ContentVariant variant) - : m_scope(QSharedPointer<QQmlJSRegisterContent>::create(scope)), m_variant(variant) - { - } + using Pool = std::vector<std::unique_ptr<QQmlJSRegisterContentPrivate, Deleter>>; - QQmlJSScope::ConstPtr m_storedType; - QSharedPointer<QQmlJSRegisterContent> m_scope; - Content m_content; - ContentVariant m_variant = Unknown; - // TODO: Constant string/number/bool/enumval + QQmlJSRegisterContentPrivate *clone(const QQmlJSRegisterContentPrivate *from); + QQmlJSRegisterContentPrivate *create() { return clone(nullptr); } + QQmlJSRegisterContentPrivate *create( + const QQmlJSRegisterContent &scope, ContentVariant variant); + + Pool m_pool; + static const QQmlJSRegisterContentPrivate s_invalid; }; QT_END_NAMESPACE diff --git a/src/qmlcompiler/qqmljsshadowcheck.cpp b/src/qmlcompiler/qqmljsshadowcheck.cpp index cf5d0fba04..2d574f920d 100644 --- a/src/qmlcompiler/qqmljsshadowcheck.cpp +++ b/src/qmlcompiler/qqmljsshadowcheck.cpp @@ -223,7 +223,7 @@ void QQmlJSShadowCheck::checkResettable( // will be in the basic blocks pass. For the purpose of adjusting newly // shadowable types we can ignore it. We only want to know if any of the // contents can hold undefined. - if (!m_typeResolver->canHoldUndefined(accumulatorIn.storedIn(varType))) + if (!m_typeResolver->canHoldUndefined(m_pool->storedIn(accumulatorIn, varType))) return; QQmlJSRegisterContent &readAccumulator diff --git a/src/qmlcompiler/qqmljsstoragegeneralizer.cpp b/src/qmlcompiler/qqmljsstoragegeneralizer.cpp index ce9f096ac6..49a88d9880 100644 --- a/src/qmlcompiler/qqmljsstoragegeneralizer.cpp +++ b/src/qmlcompiler/qqmljsstoragegeneralizer.cpp @@ -26,7 +26,7 @@ QQmlJSCompilePass::BlocksAndAnnotations QQmlJSStorageGeneralizer::run(Function * if (QQmlJSRegisterContent &returnType = function->returnType; returnType.isValid()) { if (QQmlJSScope::ConstPtr stored = m_typeResolver->genericType( returnType.storedType(), QQmlJSTypeResolver::ComponentIsGeneric::Yes)) { - returnType = returnType.storedIn(stored); + returnType = m_pool->storedIn(returnType, stored); } else { addError(QStringLiteral("Cannot store the return type %1.") .arg(returnType.storedType()->internalName())); diff --git a/src/qmlcompiler/qqmljsstorageinitializer.cpp b/src/qmlcompiler/qqmljsstorageinitializer.cpp index 27169001f2..a542e03e3f 100644 --- a/src/qmlcompiler/qqmljsstorageinitializer.cpp +++ b/src/qmlcompiler/qqmljsstorageinitializer.cpp @@ -23,7 +23,7 @@ QQmlJSCompilePass::BlocksAndAnnotations QQmlJSStorageInitializer::run(Function * if (QQmlJSRegisterContent &returnType = function->returnType; returnType.isValid()) { if (const QQmlJSScope::ConstPtr stored = m_typeResolver->storedType(returnType.containedType())) { - returnType = returnType.storedIn(m_typeResolver->trackedType(stored)); + returnType = m_pool->storedIn(returnType, m_typeResolver->trackedType(stored)); } else { addError(QStringLiteral("Cannot store the return type %1.") .arg(returnType.containedType()->internalName())); @@ -39,7 +39,7 @@ QQmlJSCompilePass::BlocksAndAnnotations QQmlJSStorageInitializer::run(Function * = m_typeResolver->originalType(content.containedType()); const QQmlJSScope::ConstPtr originalStored = m_typeResolver->storedType(original); const QQmlJSScope::ConstPtr originalTracked = m_typeResolver->trackedType(originalStored); - content = content.storedIn(originalTracked); + content = m_pool->storedIn(content, originalTracked); const QQmlJSScope::ConstPtr adjustedStored = m_typeResolver->storedType(content.containedType()); diff --git a/src/qmlcompiler/qqmljstypepropagator.cpp b/src/qmlcompiler/qqmljstypepropagator.cpp index 1376192087..16e4046806 100644 --- a/src/qmlcompiler/qqmljstypepropagator.cpp +++ b/src/qmlcompiler/qqmljstypepropagator.cpp @@ -231,7 +231,7 @@ void QQmlJSTypePropagator::generate_LoadLocal(int index) local.setType(m_typeResolver->jsValueType()); local.setIndex(index); - setAccumulator(QQmlJSRegisterContent::create( + setAccumulator(m_pool->create( local, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::Property, QQmlJSRegisterContent())); @@ -610,7 +610,7 @@ void QQmlJSTypePropagator::generate_LoadQmlContextPropertyLookup(int index) setAccumulator(m_typeResolver->scopedType(m_function->qmlScope, name, index)); if (!m_state.accumulatorOut().isValid() && m_typeResolver->isPrefix(name)) { - setAccumulator(QQmlJSRegisterContent::create( + setAccumulator(m_pool->create( nameIndex, m_typeResolver->voidType(), QQmlJSRegisterContent::ModulePrefix, m_function->qmlScope)); return; @@ -778,7 +778,7 @@ void QQmlJSTypePropagator::generate_LoadElement(int base) property.setTypeName(jsValue->internalName()); property.setType(jsValue); - setAccumulator(QQmlJSRegisterContent::create( + setAccumulator(m_pool->create( property, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::ListValue, m_typeResolver->convert(m_typeResolver->valueType(baseRegister), jsValue))); @@ -879,7 +879,7 @@ void QQmlJSTypePropagator::propagatePropertyLookup(const QString &propertyName, if (m_typeResolver->isPrefix(propertyName)) { Q_ASSERT(m_state.accumulatorIn().isValid()); addReadAccumulator(m_state.accumulatorIn()); - setAccumulator(QQmlJSRegisterContent::create( + setAccumulator(m_pool->create( m_jsUnitGenerator->getStringId(propertyName), m_state.accumulatorIn().containedType(), QQmlJSRegisterContent::ModulePrefix, @@ -983,7 +983,7 @@ void QQmlJSTypePropagator::propagatePropertyLookup(const QString &propertyName, prop.setTypeName(u"double"_s); prop.setType(m_typeResolver->realType()); setAccumulator( - QQmlJSRegisterContent::create( + m_pool->create( prop, m_state.accumulatorIn().resultLookupIndex(), lookupIndex, QQmlJSRegisterContent::Property, m_state.accumulatorIn()) ); @@ -1110,7 +1110,7 @@ void QQmlJSTypePropagator::generate_StoreProperty(int nameIndex, int base) const QQmlJSScope::ConstPtr varType = m_typeResolver->varType(); const QQmlJSRegisterContent readType = m_typeResolver->canHoldUndefined(m_state.accumulatorIn()) - ? property.castTo(varType) + ? m_pool->castTo(property, varType) : std::move(property); addReadAccumulator(readType); addReadRegister(base, callBase); @@ -2202,7 +2202,7 @@ void QQmlJSTypePropagator::generate_GetIterator(int iterator) prop.setPropertyName(u"<>"_s); prop.setTypeName(jsValue->internalName()); prop.setType(jsValue); - setAccumulator(QQmlJSRegisterContent::create( + setAccumulator(m_pool->create( prop, currentInstructionOffset(), QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::ListIterator, listType)); @@ -2616,7 +2616,7 @@ void QQmlJSTypePropagator::generate_As(int lhs) if (m_typeResolver->inherits(inContained, outContained)) output = input; else - output = m_typeResolver->cast(input, outContained); + output = m_pool->castTo(input, outContained); } else { if (!m_typeResolver->canAddressValueTypes()) { addError(u"invalid cast from %1 to %2. You can only cast object types."_s.arg( @@ -2625,13 +2625,13 @@ void QQmlJSTypePropagator::generate_As(int lhs) if (m_typeResolver->inherits(inContained, outContained)) { // A "slicing" cannot result in void - output = m_typeResolver->cast(input, outContained); + output = m_pool->castTo(input, outContained); } else { // A value type cast can result in either the type or undefined. // Using convert() retains the variant of the input type. output = m_typeResolver->merge( - m_typeResolver->cast(input, outContained), - m_typeResolver->cast(input, m_typeResolver->voidType())); + m_pool->castTo(input, outContained), + m_pool->castTo(input, m_typeResolver->voidType())); } } diff --git a/src/qmlcompiler/qqmljstyperesolver.cpp b/src/qmlcompiler/qqmljstyperesolver.cpp index 728db9d5ca..e7ba7a8764 100644 --- a/src/qmlcompiler/qqmljstyperesolver.cpp +++ b/src/qmlcompiler/qqmljstyperesolver.cpp @@ -27,8 +27,9 @@ static inline void assertExtension(const QQmlJSScope::ConstPtr &type, QLatin1Str } QQmlJSTypeResolver::QQmlJSTypeResolver(QQmlJSImporter *importer) - : m_imports(importer->builtinInternalNames()), - m_trackedTypes(std::make_unique<QHash<QQmlJSScope::ConstPtr, TrackedType>>()) + : m_pool(std::make_unique<QQmlJSRegisterContentPool>()) + , m_imports(importer->builtinInternalNames()) + , m_trackedTypes(std::make_unique<QHash<QQmlJSScope::ConstPtr, TrackedType>>()) { const QQmlJSImporter::ImportedTypes &builtinTypes = m_imports; @@ -164,7 +165,7 @@ QQmlJSTypeResolver::QQmlJSTypeResolver(QQmlJSImporter *importer) m_forOfIteratorPtr = forOfIteratorPtr; // We use this as scope type quite often, and it should always be the same scope type. - m_jsGlobalObjectContent = QQmlJSRegisterContent::create( + m_jsGlobalObjectContent = m_pool->create( m_jsGlobalObject, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::ScopeObject); } @@ -411,7 +412,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::shallowTransformed( const QQmlJSRegisterContent &transformedScope) const { if (origin.isType()) { - return QQmlJSRegisterContent::create( + return m_pool->create( (this->*op)(origin.type()), origin.resultLookupIndex(), origin.variant(), transformedScope); } @@ -419,7 +420,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::shallowTransformed( if (origin.isProperty()) { QQmlJSMetaProperty prop = origin.property(); prop.setType((this->*op)(prop.type())); - return QQmlJSRegisterContent::create( + return m_pool->create( prop, origin.baseLookupIndex(), origin.resultLookupIndex(), origin.variant(), transformedScope); } @@ -427,25 +428,25 @@ QQmlJSRegisterContent QQmlJSTypeResolver::shallowTransformed( if (origin.isEnumeration()) { QQmlJSMetaEnum enumeration = origin.enumeration(); enumeration.setType((this->*op)(enumeration.type())); - return QQmlJSRegisterContent::create( + return m_pool->create( enumeration, origin.enumMember(), origin.variant(), transformedScope); } if (origin.isMethod()) { - return QQmlJSRegisterContent::create( + return m_pool->create( origin.method(), (this->*op)(origin.methodType()), origin.variant(), transformedScope); } if (origin.isImportNamespace()) { - return QQmlJSRegisterContent::create( + return m_pool->create( origin.importNamespace(), (this->*op)(origin.importNamespaceType()), origin.variant(), transformedScope); } if (origin.isMethodCall()) { - return QQmlJSRegisterContent::create( + return m_pool->create( origin.methodCall(), (this->*op)(origin.containedType()), transformedScope); } @@ -463,7 +464,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::shallowTransformed( transformedOrigins.append(shallowTransformed(origin, op, origin.scopeType())); } - return QQmlJSRegisterContent::create( + return m_pool->create( transformedOrigins, (this->*op)(origin.conversionResult()), shallowTransformed( @@ -518,18 +519,18 @@ QQmlJSRegisterContent QQmlJSTypeResolver::registerContentForName( return QQmlJSRegisterContent(); if (type->isSingleton()) { - return QQmlJSRegisterContent::create( + return m_pool->create( type, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::Singleton, scopeType); } if (type->isScript()) { - return QQmlJSRegisterContent::create( + return m_pool->create( type, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::Script, scopeType); } - const QQmlJSRegisterContent namedType = QQmlJSRegisterContent::create( + const QQmlJSRegisterContent namedType = m_pool->create( type, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::TypeByName, scopeType); @@ -548,7 +549,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::registerContentForName( // We don't know yet whether we need the attached or the plain object. In direct // mode, we will figure this out using the scope type and access any enums of the // plain type directly. In indirect mode, we can use enum lookups. - return QQmlJSRegisterContent::create( + return m_pool->create( attached, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::Attachment, namedType); } @@ -561,13 +562,13 @@ QQmlJSRegisterContent QQmlJSTypeResolver::registerContentForName( // We may still need the plain type reference for enum lookups, // Store it as QMetaObject. // This only works with namespaces and object types. - return QQmlJSRegisterContent::create( + return m_pool->create( metaObjectType(), QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::MetaType, namedType); case QQmlJSScope::AccessSemantics::Sequence: case QQmlJSScope::AccessSemantics::Value: if (scopeType.isImportNamespace() || canAddressValueTypes()) { - return QQmlJSRegisterContent::create( + return m_pool->create( metaObjectType(), QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::MetaType, namedType); } @@ -749,7 +750,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::merge(const QQmlJSRegisterContent &a, bResultScope = b.scopeType(); } - return QQmlJSRegisterContent::create( + return m_pool->create( origins.values(), merge(a.containedType(), b.containedType()), merge(aResultScope, bResultScope), @@ -998,9 +999,9 @@ QQmlJSScope::ConstPtr QQmlJSTypeResolver::genericType( * \internal * The type of a JavaScript literal value appearing in script code */ -QQmlJSRegisterContent QQmlJSTypeResolver::literalType(const QQmlJSScope::ConstPtr &type) +QQmlJSRegisterContent QQmlJSTypeResolver::literalType(const QQmlJSScope::ConstPtr &type) const { - return QQmlJSRegisterContent::create( + return m_pool->create( type, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::Literal); } @@ -1008,9 +1009,9 @@ QQmlJSRegisterContent QQmlJSTypeResolver::literalType(const QQmlJSScope::ConstPt * \internal * The type of the result of a JavaScript operation */ -QQmlJSRegisterContent QQmlJSTypeResolver::operationType(const QQmlJSScope::ConstPtr &type) +QQmlJSRegisterContent QQmlJSTypeResolver::operationType(const QQmlJSScope::ConstPtr &type) const { - return QQmlJSRegisterContent::create( + return m_pool->create( type, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::Operation); } @@ -1018,15 +1019,15 @@ QQmlJSRegisterContent QQmlJSTypeResolver::operationType(const QQmlJSScope::Const * \internal * A type named explicitly, for example in "as"-casts or as function annotation. */ -QQmlJSRegisterContent QQmlJSTypeResolver::namedType(const QQmlJSScope::ConstPtr &type) +QQmlJSRegisterContent QQmlJSTypeResolver::namedType(const QQmlJSScope::ConstPtr &type) const { - return QQmlJSRegisterContent::create( + return m_pool->create( type, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::TypeByName); } -QQmlJSRegisterContent QQmlJSTypeResolver::syntheticType(const QQmlJSScope::ConstPtr &type) +QQmlJSRegisterContent QQmlJSTypeResolver::syntheticType(const QQmlJSScope::ConstPtr &type) const { - return QQmlJSRegisterContent::create( + return m_pool->create( type, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::Unknown); } @@ -1184,7 +1185,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::scopedType(const QQmlJSRegisterContent { const QQmlJSScope::ConstPtr contained = scope.containedType(); if (QQmlJSScope::ConstPtr identified = m_objectsById.scope(name, contained, options)) { - return QQmlJSRegisterContent::create( + return m_pool->create( identified, lookupIndex, QQmlJSRegisterContent::ObjectById, scope); } @@ -1205,7 +1206,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::scopedType(const QQmlJSRegisterContent return false; prop.setType(resolveParentProperty(name, base, prop.type())); - result = QQmlJSRegisterContent::create( + result = m_pool->create( prop, QQmlJSRegisterContent::InvalidLookupIndex, lookupIndex, scopeContentVariant(mode, false), resultScope); return true; @@ -1221,7 +1222,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::scopedType(const QQmlJSRegisterContent } if (methods.isEmpty()) return false; - result = QQmlJSRegisterContent::create( + result = m_pool->create( methods, jsValueType(), scopeContentVariant(mode, true), resultScope); return true; } @@ -1239,11 +1240,11 @@ QQmlJSRegisterContent QQmlJSTypeResolver::scopedType(const QQmlJSRegisterContent return result; if (m_jsGlobalObject->hasProperty(name)) { - return QQmlJSRegisterContent::create( + return m_pool->create( m_jsGlobalObject->property(name), QQmlJSRegisterContent::InvalidLookupIndex, lookupIndex, QQmlJSRegisterContent::Property, m_jsGlobalObjectContent); } else if (m_jsGlobalObject->hasMethod(name)) { - return QQmlJSRegisterContent::create( + return m_pool->create( m_jsGlobalObject->methods(name), jsValueType(), QQmlJSRegisterContent::Property, m_jsGlobalObjectContent); } @@ -1275,7 +1276,7 @@ bool QQmlJSTypeResolver::checkEnums( const auto enums = scope.containedType()->ownEnumerations(); for (const auto &enumeration : enums) { if ((enumeration.isScoped() || enumeration.isQml()) && enumeration.name() == name) { - *result = QQmlJSRegisterContent::create( + *result = m_pool->create( enumeration, QString(), QQmlJSRegisterContent::Enum, scope); @@ -1284,7 +1285,7 @@ bool QQmlJSTypeResolver::checkEnums( if ((!enumeration.isScoped() || enumeration.isQml() || !scope.containedType()->enforcesScopedEnums()) && enumeration.hasKey(name)) { - *result = QQmlJSRegisterContent::create( + *result = m_pool->create( enumeration, name, QQmlJSRegisterContent::Enum, scope); @@ -1552,7 +1553,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::lengthProperty( prop.setTypeName(u"qsizetype"_s); prop.setType(sizeType()); prop.setIsWritable(isWritable); - return QQmlJSRegisterContent::create( + return m_pool->create( prop, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::Property, scope); } @@ -1574,7 +1575,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::memberType( prop.setTypeName(u"QVariant"_s); prop.setType(varType()); prop.setIsWritable(true); - return QQmlJSRegisterContent::create( + return m_pool->create( prop, baseLookupIndex, resultLookupIndex, QQmlJSRegisterContent::Property, type); } @@ -1585,7 +1586,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::memberType( prop.setTypeName(u"QJSValue"_s); prop.setType(jsValueType()); prop.setIsWritable(true); - return QQmlJSRegisterContent::create( + return m_pool->create( prop, baseLookupIndex, resultLookupIndex, QQmlJSRegisterContent::Property, type); } @@ -1604,7 +1605,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::memberType( if (mode != QQmlJSScope::ExtensionNamespace) { if (scope->hasOwnProperty(name)) { const auto prop = scope->ownProperty(name); - result = QQmlJSRegisterContent::create( + result = m_pool->create( prop, baseLookupIndex, resultLookupIndex, QQmlJSRegisterContent::Property, resultScope); return true; @@ -1612,7 +1613,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::memberType( if (scope->hasOwnMethod(name)) { const auto methods = scope->ownMethods(name); - result = QQmlJSRegisterContent::create( + result = m_pool->create( methods, jsValueType(), QQmlJSRegisterContent::Method, resultScope); return true; } @@ -1635,7 +1636,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::memberType( prop.setType(jsValueType()); prop.setIsWritable(!(ownIdentifier.value().isConst)); - return QQmlJSRegisterContent::create( + return m_pool->create( prop, baseLookupIndex, resultLookupIndex, QQmlJSRegisterContent::Property, parentScope(scope, type)); @@ -1655,11 +1656,11 @@ QQmlJSRegisterContent QQmlJSTypeResolver::memberType( qmlCompiler, contained->sourceLocation()); return {}; } else { - const QQmlJSRegisterContent namedType = QQmlJSRegisterContent::create( + const QQmlJSRegisterContent namedType = m_pool->create( attachedBase, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::TypeByName, type); - return QQmlJSRegisterContent::create( + return m_pool->create( attached, resultLookupIndex, QQmlJSRegisterContent::Attachment, namedType); } @@ -1706,7 +1707,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::memberType( const auto enumeration = type.enumeration(); if (!type.enumMember().isEmpty() || !enumeration.hasKey(name)) return {}; - return QQmlJSRegisterContent::create( + return m_pool->create( enumeration, name, QQmlJSRegisterContent::Enum, type.scopeType()); } if (type.isMethod()) { @@ -1715,7 +1716,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::memberType( prop.setPropertyName(name); prop.setType(jsValueType()); prop.setIsWritable(true); - return QQmlJSRegisterContent::create( + return m_pool->create( prop, QQmlJSRegisterContent::InvalidLookupIndex, lookupIndex, QQmlJSRegisterContent::Property, type); } @@ -1794,7 +1795,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::valueType(const QQmlJSRegisterContent property.setTypeName(value->internalName()); property.setType(value); - return QQmlJSRegisterContent::create( + return m_pool->create( property, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::ListValue, list); @@ -1804,13 +1805,13 @@ QQmlJSRegisterContent QQmlJSTypeResolver::returnType( const QQmlJSMetaMethod &method, const QQmlJSScope::ConstPtr &returnType, const QQmlJSRegisterContent &scope) const { - return QQmlJSRegisterContent::create(method, returnType, scope); + return m_pool->create(method, returnType, scope); } QQmlJSRegisterContent QQmlJSTypeResolver::extensionType( const QQmlJSScope::ConstPtr &extension, const QQmlJSRegisterContent &base) const { - return QQmlJSRegisterContent::create( + return m_pool->create( extension, base.resultLookupIndex(), QQmlJSRegisterContent::Extension, base); } @@ -1826,7 +1827,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::baseType( { if (derived.containedType() == base) return derived; - return QQmlJSRegisterContent::create( + return m_pool->create( base, derived.resultLookupIndex(), QQmlJSRegisterContent::BaseType, derived); } @@ -1842,7 +1843,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::parentScope( { if (child.containedType() == parent) return child; - return QQmlJSRegisterContent::create( + return m_pool->create( parent, child.resultLookupIndex(), QQmlJSRegisterContent::ParentScope, child); } @@ -1862,7 +1863,7 @@ QQmlJSRegisterContent QQmlJSTypeResolver::iteratorPointer( prop.setPropertyName(u"<>"_s); prop.setTypeName(iteratorPointer->internalName()); prop.setType(iteratorPointer); - return QQmlJSRegisterContent::create( + return m_pool->create( prop, lookupIndex, QQmlJSRegisterContent::InvalidLookupIndex, QQmlJSRegisterContent::ListIterator, listType); @@ -1915,16 +1916,16 @@ bool QQmlJSTypeResolver::equals(const QQmlJSScope::ConstPtr &a, const QQmlJSScop static QQmlJSRegisterContent doConvert( const QQmlJSRegisterContent &from, const QQmlJSScope::ConstPtr &to, - const QQmlJSRegisterContent &scope) + const QQmlJSRegisterContent &scope, QQmlJSRegisterContentPool *pool) { if (from.isConversion()) { - return QQmlJSRegisterContent::create( + return pool->create( from.conversionOrigins(), to, scope.isValid() ? scope : from.conversionResultScope(), from.variant(), from.scopeType()); } - return QQmlJSRegisterContent::create( + return pool->create( QList<QQmlJSRegisterContent>{from}, to, scope, from.variant(), from.scopeType()); @@ -1933,19 +1934,13 @@ static QQmlJSRegisterContent doConvert( QQmlJSRegisterContent QQmlJSTypeResolver::convert( const QQmlJSRegisterContent &from, const QQmlJSRegisterContent &to) const { - return doConvert(from, to.containedType(), to.scopeType()); + return doConvert(from, to.containedType(), to.scopeType(), m_pool.get()); } QQmlJSRegisterContent QQmlJSTypeResolver::convert( const QQmlJSRegisterContent &from, const QQmlJSScope::ConstPtr &to) const { - return doConvert(from, to, QQmlJSRegisterContent()); -} - -QQmlJSRegisterContent QQmlJSTypeResolver::cast( - const QQmlJSRegisterContent &from, const QQmlJSScope::ConstPtr &to) const -{ - return from.castTo(to); + return doConvert(from, to, QQmlJSRegisterContent(), m_pool.get()); } QQmlJSScope::ConstPtr QQmlJSTypeResolver::comparableType(const QQmlJSScope::ConstPtr &type) const diff --git a/src/qmlcompiler/qqmljstyperesolver_p.h b/src/qmlcompiler/qqmljstyperesolver_p.h index 59f56aa7dd..94a10594d7 100644 --- a/src/qmlcompiler/qqmljstyperesolver_p.h +++ b/src/qmlcompiler/qqmljstyperesolver_p.h @@ -40,6 +40,7 @@ public: // Note: must be called after the construction to read the QML program void init(QQmlJSImportVisitor *visitor, QQmlJS::AST::Node *program); + QQmlJSRegisterContentPool *registerContentPool() const { return m_pool.get(); } QQmlJSScope::ConstPtr voidType() const { return m_voidType; } QQmlJSScope::ConstPtr emptyType() const { return m_emptyType; } @@ -144,10 +145,10 @@ public: genericType(const QQmlJSScope::ConstPtr &type, ComponentIsGeneric allowComponent = ComponentIsGeneric::No) const; - static QQmlJSRegisterContent literalType(const QQmlJSScope::ConstPtr &type); - static QQmlJSRegisterContent operationType(const QQmlJSScope::ConstPtr &type); - static QQmlJSRegisterContent namedType(const QQmlJSScope::ConstPtr &type); - static QQmlJSRegisterContent syntheticType(const QQmlJSScope::ConstPtr &type); + QQmlJSRegisterContent literalType(const QQmlJSScope::ConstPtr &type) const; + QQmlJSRegisterContent operationType(const QQmlJSScope::ConstPtr &type) const; + QQmlJSRegisterContent namedType(const QQmlJSScope::ConstPtr &type) const; + QQmlJSRegisterContent syntheticType(const QQmlJSScope::ConstPtr &type) const; QQmlJSScope::ConstPtr scopedType( const QQmlJSScope::ConstPtr &scope, const QString &name, @@ -223,8 +224,6 @@ public: const QQmlJSRegisterContent &from, const QQmlJSRegisterContent &to) const; QQmlJSRegisterContent convert( const QQmlJSRegisterContent &from, const QQmlJSScope::ConstPtr &to) const; - QQmlJSRegisterContent cast( - const QQmlJSRegisterContent &from, const QQmlJSScope::ConstPtr &to) const; QQmlJSScope::ConstPtr merge(const QQmlJSScope::ConstPtr &a, const QQmlJSScope::ConstPtr &b) const; @@ -287,6 +286,8 @@ protected: const QString &name, const QQmlJSScope::ConstPtr &base, const QQmlJSScope::ConstPtr &propType) const; + std::unique_ptr<QQmlJSRegisterContentPool> m_pool; + QQmlJSScope::ConstPtr m_voidType; QQmlJSScope::ConstPtr m_emptyType; QQmlJSScope::ConstPtr m_nullType; |
