QtQml: Move ResolvedTypeReference into base CU

Change-Id: I25063457aad3a6d29a8c2a5b236f9a51b56a2f51
Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
Ulf Hermann 2024-01-08 12:56:38 +01:00
parent 21cf487816
commit c225e23e00
9 changed files with 103 additions and 80 deletions

View File

@ -3,9 +3,10 @@
#include "qv4compileddata_p.h"
#include <private/qv4resolvedtypereference_p.h>
#include <QtQml/qqmlfile.h>
#include <QtCore/qcryptographichash.h>
#include <QtCore/qdir.h>
#include <QtCore/qscopeguard.h>
#include <QtCore/qstandardpaths.h>
@ -15,6 +16,48 @@ QT_BEGIN_NAMESPACE
namespace QV4 {
namespace CompiledData {
/*!
\internal
This function creates a temporary key vector and sorts it to guarantuee a stable
hash. This is used to calculate a check-sum on dependent meta-objects.
*/
bool ResolvedTypeReferenceMap::addToHash(
QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums) const
{
std::vector<int> keys (size());
int i = 0;
for (auto it = constBegin(), end = constEnd(); it != end; ++it) {
keys[i] = it.key();
++i;
}
std::sort(keys.begin(), keys.end());
for (int key: keys) {
if (!this->operator[](key)->addToHash(hash, checksums))
return false;
}
return true;
}
CompilationUnit::~CompilationUnit()
{
qDeleteAll(resolvedTypes);
if (data) {
if (data->qmlUnit() != qmlData)
free(const_cast<QmlUnit *>(qmlData));
qmlData = nullptr;
if (!(data->flags & QV4::CompiledData::Unit::StaticData))
free(const_cast<Unit *>(data));
}
data = nullptr;
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
delete [] constants;
constants = nullptr;
#endif
}
QString CompilationUnit::localCacheFilePath(const QUrl &url)
{
static const QByteArray envCachePath = qgetenv("QML_DISK_CACHE_PATH");
@ -117,6 +160,16 @@ QStringList CompilationUnit::moduleRequests() const
return requests;
}
ResolvedTypeReference *CompilationUnit::resolvedType(QMetaType type) const
{
for (ResolvedTypeReference *ref : std::as_const(resolvedTypes)) {
if (ref->type().typeId() == type)
return ref;
}
return nullptr;
}
} // namespace CompiledData
} // namespace QV4

View File

@ -16,6 +16,7 @@
#include <functional>
#include <QtCore/qcryptographichash.h>
#include <QtCore/qhash.h>
#include <QtCore/qhashfunctions.h>
#include <QtCore/qlocale.h>
@ -74,12 +75,19 @@ struct InternalClass;
struct Function;
class EvalISelFactory;
class ResolvedTypeReference;
namespace CompiledData {
// index is per-object binding index
using BindingPropertyData = QVector<const QQmlPropertyData *>;
// map from name index
struct ResolvedTypeReferenceMap: public QHash<int, ResolvedTypeReference*>
{
bool addToHash(QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums) const;
};
struct String;
struct Function;
struct Lookup;
@ -1473,6 +1481,8 @@ struct CompilationUnit final : public QQmlRefCounted<CompilationUnit>
// lookups by string (property name).
QVector<BindingPropertyData> bindingPropertyDataPerObject;
ResolvedTypeReferenceMap resolvedTypes;
public:
using CompiledObject = CompiledData::Object;
@ -1489,22 +1499,7 @@ public:
this->aotCompiledFunctions = aotCompiledFunctions;
}
~CompilationUnit()
{
if (data) {
if (data->qmlUnit() != qmlData)
free(const_cast<QmlUnit *>(qmlData));
qmlData = nullptr;
if (!(data->flags & QV4::CompiledData::Unit::StaticData))
free(const_cast<Unit *>(data));
}
data = nullptr;
#if Q_BYTE_ORDER == Q_BIG_ENDIAN
delete [] constants;
constants = nullptr;
#endif
}
Q_QML_EXPORT ~CompilationUnit();
const Unit *unitData() const { return data; }
@ -1620,6 +1615,9 @@ public:
return m_finalUrl;
}
ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes.value(id); }
ResolvedTypeReference *resolvedType(QMetaType type) const;
private:
QString m_fileName; // initialized from data->sourceFileIndex
QString m_finalUrlString; // initialized from data->finalUrlIndex

View File

@ -268,9 +268,6 @@ void ExecutableCompilationUnit::clear()
typeNameCache.reset();
qDeleteAll(resolvedTypes);
resolvedTypes.clear();
delete [] runtimeLookups;
runtimeLookups = nullptr;
@ -391,7 +388,7 @@ void ExecutableCompilationUnit::finalizeCompositeType(const QQmlType &type)
QQmlMetaType::registerInternalCompositeType(this);
} else {
const QV4::CompiledData::Object *obj = objectAt(/*root object*/0);
auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex);
auto *typeRef = m_compilationUnit->resolvedTypes.value(obj->inheritedTypeNameIndex);
Q_ASSERT(typeRef);
if (const auto compilationUnit = typeRef->compilationUnit())
qmlType = compilationUnit->qmlType;
@ -435,7 +432,7 @@ void ExecutableCompilationUnit::finalizeCompositeType(const QQmlType &type)
m_compilationUnit->inlineComponentData[lastICRootName].totalBindingCount
+= obj->nBindings;
if (auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) {
if (auto *typeRef = m_compilationUnit->resolvedTypes.value(obj->inheritedTypeNameIndex)) {
const auto type = typeRef->type();
if (type.isValid() && type.parserStatusCast() != -1)
++m_compilationUnit->inlineComponentData[lastICRootName].totalParserStatusCount;
@ -463,7 +460,7 @@ void ExecutableCompilationUnit::finalizeCompositeType(const QQmlType &type)
continue;
bindingCount += obj->nBindings;
if (auto *typeRef = resolvedTypes.value(obj->inheritedTypeNameIndex)) {
if (auto *typeRef = m_compilationUnit->resolvedTypes.value(obj->inheritedTypeNameIndex)) {
const auto type = typeRef->type();
if (type.isValid() && type.parserStatusCast() != -1)
++parserStatusCount;
@ -495,15 +492,6 @@ int ExecutableCompilationUnit::totalObjectCount() const {
return m_compilationUnit->inlineComponentData[*icRootName()].totalObjectCount;
}
ResolvedTypeReference *ExecutableCompilationUnit::resolvedType(QMetaType type) const
{
for (ResolvedTypeReference *ref : std::as_const(resolvedTypes)) {
if (ref->type().typeId() == type)
return ref;
}
return nullptr;
}
int ExecutableCompilationUnit::totalParserStatusCount() const {
if (!m_compilationUnit->icRootName)
return m_totalParserStatusCount;
@ -854,29 +842,6 @@ void ExecutableCompilationUnit::evaluateModuleRequests()
}
}
/*!
\internal
This function creates a temporary key vector and sorts it to guarantuee a stable
hash. This is used to calculate a check-sum on dependent meta-objects.
*/
bool ResolvedTypeReferenceMap::addToHash(
QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums) const
{
std::vector<int> keys (size());
int i = 0;
for (auto it = constBegin(), end = constEnd(); it != end; ++it) {
keys[i] = it.key();
++i;
}
std::sort(keys.begin(), keys.end());
for (int key: keys) {
if (!this->operator[](key)->addToHash(hash, checksums))
return false;
}
return true;
}
QString ExecutableCompilationUnit::bindingValueAsString(const CompiledData::Binding *binding) const
{
#if QT_CONFIG(translation)

View File

@ -34,12 +34,6 @@ class QQmlEnginePrivate;
namespace QV4 {
class CompilationUnitMapper;
class ResolvedTypeReference;
// map from name index
struct ResolvedTypeReferenceMap: public QHash<int, ResolvedTypeReference*>
{
bool addToHash(QCryptographicHash *hash, QHash<quintptr, QByteArray> *checksums) const;
};
struct CompilationUnitRuntimeData
{
@ -113,9 +107,21 @@ public:
int totalObjectCount() const;
QVector<QQmlRefPointer<QQmlScriptData>> dependentScripts;
ResolvedTypeReferenceMap resolvedTypes;
ResolvedTypeReference *resolvedType(int id) const { return resolvedTypes.value(id); }
ResolvedTypeReference *resolvedType(QMetaType type) const;
ResolvedTypeReference *resolvedType(int id) const
{
return m_compilationUnit->resolvedType(id);
}
ResolvedTypeReference *resolvedType(QMetaType type) const
{
return m_compilationUnit->resolvedType(type);
}
void setResolvedTypes(const CompiledData::ResolvedTypeReferenceMap &resolvedTypes)
{
m_compilationUnit->resolvedTypes = resolvedTypes;
}
bool verifyChecksum(const CompiledData::DependentTypesHasher &dependencyHasher) const;

View File

@ -26,7 +26,7 @@ Q_LOGGING_CATEGORY(lcQmlTypeCompiler, "qt.qml.typecompiler");
QQmlTypeCompiler::QQmlTypeCompiler(
QQmlEnginePrivate *engine, QQmlTypeData *typeData, QmlIR::Document *parsedQML,
QV4::ResolvedTypeReferenceMap *resolvedTypeCache,
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache,
const QV4::CompiledData::DependentTypesHasher &dependencyHasher)
: resolvedTypes(resolvedTypeCache)
, engine(engine)

View File

@ -46,7 +46,7 @@ public:
QQmlTypeCompiler(QQmlEnginePrivate *engine,
QQmlTypeData *typeData,
QmlIR::Document *document,
QV4::ResolvedTypeReferenceMap *resolvedTypeCache,
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache,
const QV4::CompiledData::DependentTypesHasher &dependencyHasher);
// --- interface used by QQmlPropertyCacheCreator
@ -63,7 +63,7 @@ public:
QString stringAt(int idx) const;
QmlIR::PoolList<QmlIR::Function>::Iterator objectFunctionsBegin(const QmlIR::Object *object) const { return object->functionsBegin(); }
QmlIR::PoolList<QmlIR::Function>::Iterator objectFunctionsEnd(const QmlIR::Object *object) const { return object->functionsEnd(); }
QV4::ResolvedTypeReferenceMap *resolvedTypes = nullptr;
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypes = nullptr;
ListPropertyAssignBehavior listPropertyAssignBehavior() const
{
for (const QmlIR::Pragma *pragma: document->pragmas) {

View File

@ -236,11 +236,11 @@ bool QQmlComponentAndAliasResolver<QV4::ExecutableCompilationUnit>::wrapImplicit
QQmlError QQmlTypeData::createTypeAndPropertyCaches(
const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
const QV4::ResolvedTypeReferenceMap &resolvedTypeCache)
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache)
{
Q_ASSERT(m_compiledData);
m_compiledData->typeNameCache = typeNameCache;
m_compiledData->resolvedTypes = resolvedTypeCache;
m_compiledData->setResolvedTypes(resolvedTypeCache);
m_compiledData->setInlineComponentData(m_inlineComponentData);
QQmlEnginePrivate * const engine = QQmlEnginePrivate::get(typeLoader()->engine());
@ -440,7 +440,7 @@ void QQmlTypeData::done()
else
setupICs(m_compiledData, &m_inlineComponentData, finalUrl(), m_compiledData);
QV4::ResolvedTypeReferenceMap resolvedTypeCache;
QV4::CompiledData::ResolvedTypeReferenceMap resolvedTypeCache;
QQmlRefPointer<QQmlTypeNameCache> typeNameCache;
{
QQmlError error = buildTypeResolutionCaches(&typeNameCache, &resolvedTypeCache);
@ -482,7 +482,7 @@ void QQmlTypeData::done()
return;
// We want to keep our resolve types ...
m_compiledData->resolvedTypes.clear();
m_compiledData->setResolvedTypes({});
// ... but we don't want the property caches we've created for the broken CU.
for (QV4::ResolvedTypeReference *ref: std::as_const(resolvedTypeCache)) {
const auto compilationUnit = ref->compilationUnit();
@ -808,7 +808,7 @@ QString QQmlTypeData::stringAt(int index) const
}
void QQmlTypeData::compile(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
QV4::ResolvedTypeReferenceMap *resolvedTypeCache,
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache,
const QV4::CompiledData::DependentTypesHasher &dependencyHasher)
{
Q_ASSERT(m_compiledData.isNull());
@ -847,7 +847,7 @@ void QQmlTypeData::compile(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCach
m_compiledData = enginePrivate->v4engine()->executableCompilationUnit(
std::move(compilationUnit));
m_compiledData->typeNameCache = typeNameCache;
m_compiledData->resolvedTypes = *resolvedTypeCache;
m_compiledData->setResolvedTypes(*resolvedTypeCache);
m_compiledData->propertyCaches = std::move(*compiler.propertyCaches());
Q_ASSERT(m_compiledData->propertyCaches.count()
== static_cast<int>(m_compiledData->objectCount()));
@ -958,7 +958,7 @@ void QQmlTypeData::resolveTypes()
QQmlError QQmlTypeData::buildTypeResolutionCaches(
QQmlRefPointer<QQmlTypeNameCache> *typeNameCache,
QV4::ResolvedTypeReferenceMap *resolvedTypeCache) const
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache) const
{
typeNameCache->adopt(new QQmlTypeNameCache(m_importCache));

View File

@ -92,13 +92,14 @@ private:
void resolveTypes();
QQmlError buildTypeResolutionCaches(
QQmlRefPointer<QQmlTypeNameCache> *typeNameCache,
QV4::ResolvedTypeReferenceMap *resolvedTypeCache
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache
) const;
void compile(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
QV4::ResolvedTypeReferenceMap *resolvedTypeCache,
QV4::CompiledData::ResolvedTypeReferenceMap *resolvedTypeCache,
const QV4::CompiledData::DependentTypesHasher &dependencyHasher);
QQmlError createTypeAndPropertyCaches(const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
const QV4::ResolvedTypeReferenceMap &resolvedTypeCache);
QQmlError createTypeAndPropertyCaches(
const QQmlRefPointer<QQmlTypeNameCache> &typeNameCache,
const QV4::CompiledData::ResolvedTypeReferenceMap &resolvedTypeCache);
bool resolveType(const QString &typeName, QTypeRevision &version,
TypeReference &ref, int lineNumber = -1, int columnNumber = -1,
bool reportErrors = true,

View File

@ -367,8 +367,8 @@ private:
if (object->hasFlag(Object::IsInlineComponentRoot))
return result;
if (const auto superTypeUnit = compilationUnit->resolvedTypes.value(
object->inheritedTypeNameIndex)->compilationUnit()) {
if (const auto superTypeUnit = compilationUnit->resolvedType(object->inheritedTypeNameIndex)
->compilationUnit()) {
// We have a non-C++ super type, which could indicate we're a subtype of a TestCase
if (testCaseType.isValid() && superTypeUnit->url() == testCaseType.sourceUrl())
result.isTestCase = true;