moc: replace inefficient QLists with QVectors

These types are larger than a void*, so holding them in QLists
is needlessly inefficient. Worse, the code could come to depend
on the fragile property of (inefficient) QLists that references
to elements therein never are invalidated.

Fix by marking them movable, and holding them in a QVector instead.

Change-Id: I42f494ed87854eadc33d78db4479203ff5e0370f
Reviewed-by: Lars Knoll <lars.knoll@theqtcompany.com>
Reviewed-by: Milian Wolff <milian.wolff@kdab.com>
Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
This commit is contained in:
Marc Mutz 2015-06-24 02:04:09 +02:00 committed by Olivier Goffart (Woboq GmbH)
parent 3e63a58a96
commit cc2938b5b6
5 changed files with 41 additions and 31 deletions

View File

@ -121,7 +121,7 @@ int Generator::stridx(const QByteArray &s)
// Returns the sum of all parameters (including return type) for the given
// \a list of methods. This is needed for calculating the size of the methods'
// parameter type/name meta-data.
static int aggregateParameterCount(const QList<FunctionDef> &list)
static int aggregateParameterCount(const QVector<FunctionDef> &list)
{
int sum = 0;
for (int i = 0; i < list.count(); ++i)
@ -194,7 +194,7 @@ void Generator::generateCode()
// filter out undeclared enumerators and sets
{
QList<EnumDef> enumList;
QVector<EnumDef> enumList;
for (int i = 0; i < cdef->enumList.count(); ++i) {
EnumDef def = cdef->enumList.at(i);
if (cdef->enumDeclarations.contains(def.name)) {
@ -571,7 +571,7 @@ void Generator::generateCode()
cname, cname, cdef->classname.constData());
}
for (int i = 0; i < cdef->interfaceList.size(); ++i) {
const QList<ClassDef::Interface> &iface = cdef->interfaceList.at(i);
const QVector<ClassDef::Interface> &iface = cdef->interfaceList.at(i);
for (int j = 0; j < iface.size(); ++j) {
fprintf(out, " if (!strcmp(_clname, %s))\n return ", iface.at(j).interfaceId.constData());
for (int k = j; k >= 0; --k)
@ -628,7 +628,7 @@ void Generator::generateClassInfos()
}
}
void Generator::registerFunctionStrings(const QList<FunctionDef>& list)
void Generator::registerFunctionStrings(const QVector<FunctionDef>& list)
{
for (int i = 0; i < list.count(); ++i) {
const FunctionDef &f = list.at(i);
@ -648,7 +648,7 @@ void Generator::registerFunctionStrings(const QList<FunctionDef>& list)
}
}
void Generator::generateFunctions(const QList<FunctionDef>& list, const char *functype, int type, int &paramsIndex)
void Generator::generateFunctions(const QVector<FunctionDef>& list, const char *functype, int type, int &paramsIndex)
{
if (list.isEmpty())
return;
@ -694,7 +694,7 @@ void Generator::generateFunctions(const QList<FunctionDef>& list, const char *fu
}
}
void Generator::generateFunctionRevisions(const QList<FunctionDef>& list, const char *functype)
void Generator::generateFunctionRevisions(const QVector<FunctionDef>& list, const char *functype)
{
if (list.count())
fprintf(out, "\n // %ss: revision\n", functype);
@ -704,7 +704,7 @@ void Generator::generateFunctionRevisions(const QList<FunctionDef>& list, const
}
}
void Generator::generateFunctionParameters(const QList<FunctionDef>& list, const char *functype)
void Generator::generateFunctionParameters(const QVector<FunctionDef>& list, const char *functype)
{
if (list.isEmpty())
return;
@ -917,7 +917,7 @@ void Generator::generateMetacall()
fprintf(out, " ");
bool needElse = false;
QList<FunctionDef> methodList;
QVector<FunctionDef> methodList;
methodList += cdef->signalList;
methodList += cdef->slotList;
methodList += cdef->methodList;
@ -1079,7 +1079,7 @@ QMultiMap<QByteArray, int> Generator::automaticPropertyMetaTypesHelper()
return automaticPropertyMetaTypes;
}
QMap<int, QMultiMap<QByteArray, int> > Generator::methodsWithAutomaticTypesHelper(const QList<FunctionDef> &methodList)
QMap<int, QMultiMap<QByteArray, int> > Generator::methodsWithAutomaticTypesHelper(const QVector<FunctionDef> &methodList)
{
QMap<int, QMultiMap<QByteArray, int> > methodsWithAutomaticTypes;
for (int i = 0; i < methodList.size(); ++i) {
@ -1133,7 +1133,7 @@ void Generator::generateStaticMetacall()
isUsed_a = true;
}
QList<FunctionDef> methodList;
QVector<FunctionDef> methodList;
methodList += cdef->signalList;
methodList += cdef->slotList;
methodList += cdef->methodList;

View File

@ -45,10 +45,10 @@ private:
bool registerableMetaType(const QByteArray &propertyType);
void registerClassInfoStrings();
void generateClassInfos();
void registerFunctionStrings(const QList<FunctionDef> &list);
void generateFunctions(const QList<FunctionDef> &list, const char *functype, int type, int &paramsIndex);
void generateFunctionRevisions(const QList<FunctionDef>& list, const char *functype);
void generateFunctionParameters(const QList<FunctionDef> &list, const char *functype);
void registerFunctionStrings(const QVector<FunctionDef> &list);
void generateFunctions(const QVector<FunctionDef> &list, const char *functype, int type, int &paramsIndex);
void generateFunctionRevisions(const QVector<FunctionDef> &list, const char *functype);
void generateFunctionParameters(const QVector<FunctionDef> &list, const char *functype);
void generateTypeInfo(const QByteArray &typeName, bool allowEmptyName = false);
void registerEnumStrings();
void generateEnums(int index);
@ -59,7 +59,7 @@ private:
void generateSignal(FunctionDef *def, int index);
void generatePluginMetaData();
QMultiMap<QByteArray, int> automaticPropertyMetaTypesHelper();
QMap<int, QMultiMap<QByteArray, int> > methodsWithAutomaticTypesHelper(const QList<FunctionDef> &methodList);
QMap<int, QMultiMap<QByteArray, int> > methodsWithAutomaticTypesHelper(const QVector<FunctionDef> &methodList);
void strreg(const QByteArray &); // registers a string
int stridx(const QByteArray &); // returns a string's id

View File

@ -538,7 +538,7 @@ bool Moc::parseMaybeFunction(const ClassDef *cdef, FunctionDef *def)
void Moc::parse()
{
QList<NamespaceDef> namespaceList;
QVector<NamespaceDef> namespaceList;
bool templateClass = false;
while (hasNext()) {
Token t = next();
@ -801,7 +801,7 @@ void Moc::parse()
}
}
static bool any_type_contains(const QList<PropertyDef> &properties, const QByteArray &pattern)
static bool any_type_contains(const QVector<PropertyDef> &properties, const QByteArray &pattern)
{
for (const auto &p : properties) {
if (p.type.contains(pattern))
@ -810,7 +810,7 @@ static bool any_type_contains(const QList<PropertyDef> &properties, const QByteA
return false;
}
static bool any_arg_contains(const QList<FunctionDef> &functions, const QByteArray &pattern)
static bool any_arg_contains(const QVector<FunctionDef> &functions, const QByteArray &pattern)
{
for (const auto &f : functions) {
for (const auto &arg : f.arguments) {
@ -835,7 +835,7 @@ static QByteArrayList make_candidates()
return result;
}
static QByteArrayList requiredQtContainers(const QList<ClassDef> &classes)
static QByteArrayList requiredQtContainers(const QVector<ClassDef> &classes)
{
static const QByteArrayList candidates = make_candidates();
@ -1319,7 +1319,7 @@ void Moc::parseInterfaces(ClassDef *def)
{
next(LPAREN);
while (test(IDENTIFIER)) {
QList<ClassDef::Interface> iface;
QVector<ClassDef::Interface> iface;
iface += ClassDef::Interface(lexem());
while (test(SCOPE)) {
iface.last().className += lexem();

View File

@ -59,6 +59,7 @@ struct Type
Token firstToken;
ReferenceType referenceType;
};
Q_DECLARE_TYPEINFO(Type, Q_MOVABLE_TYPE);
struct EnumDef
{
@ -67,6 +68,7 @@ struct EnumDef
bool isEnumClass; // c++11 enum class
EnumDef() : isEnumClass(false) {}
};
Q_DECLARE_TYPEINFO(EnumDef, Q_MOVABLE_TYPE);
struct ArgumentDef
{
@ -76,6 +78,7 @@ struct ArgumentDef
QByteArray typeNameForCast; // type name to be used in cast from void * in metacall
bool isDefault;
};
Q_DECLARE_TYPEINFO(ArgumentDef, Q_MOVABLE_TYPE);
struct FunctionDef
{
@ -89,7 +92,7 @@ struct FunctionDef
QByteArray name;
bool returnTypeIsVolatile;
QList<ArgumentDef> arguments;
QVector<ArgumentDef> arguments;
enum Access { Private, Protected, Public };
Access access;
@ -112,6 +115,7 @@ struct FunctionDef
int revision;
};
Q_DECLARE_TYPEINFO(FunctionDef, Q_MOVABLE_TYPE);
struct PropertyDef
{
@ -130,6 +134,7 @@ struct PropertyDef
}
int revision;
};
Q_DECLARE_TYPEINFO(PropertyDef, Q_MOVABLE_TYPE);
struct ClassInfoDef
@ -137,6 +142,7 @@ struct ClassInfoDef
QByteArray name;
QByteArray value;
};
Q_DECLARE_TYPEINFO(ClassInfoDef, Q_MOVABLE_TYPE);
struct ClassDef {
ClassDef():
@ -144,16 +150,17 @@ struct ClassDef {
, revisionedMethods(0), revisionedProperties(0), begin(0), end(0){}
QByteArray classname;
QByteArray qualified;
QList<QPair<QByteArray, FunctionDef::Access> > superclassList;
QVector<QPair<QByteArray, FunctionDef::Access> > superclassList;
struct Interface
{
Interface() {} // for QVector, don't use
inline explicit Interface(const QByteArray &_className)
: className(_className) {}
QByteArray className;
QByteArray interfaceId;
};
QList<QList<Interface> >interfaceList;
QVector<QVector<Interface> >interfaceList;
bool hasQObject;
bool hasQGadget;
@ -164,13 +171,13 @@ struct ClassDef {
QJsonDocument metaData;
} pluginData;
QList<FunctionDef> constructorList;
QList<FunctionDef> signalList, slotList, methodList, publicList;
QVector<FunctionDef> constructorList;
QVector<FunctionDef> signalList, slotList, methodList, publicList;
int notifyableProperties;
QList<PropertyDef> propertyList;
QList<ClassInfoDef> classInfoList;
QVector<PropertyDef> propertyList;
QVector<ClassInfoDef> classInfoList;
QMap<QByteArray, bool> enumDeclarations;
QList<EnumDef> enumList;
QVector<EnumDef> enumList;
QMap<QByteArray, QByteArray> flagAliases;
int revisionedMethods;
int revisionedProperties;
@ -178,12 +185,15 @@ struct ClassDef {
int begin;
int end;
};
Q_DECLARE_TYPEINFO(ClassDef, Q_MOVABLE_TYPE);
Q_DECLARE_TYPEINFO(ClassDef::Interface, Q_MOVABLE_TYPE);
struct NamespaceDef {
QByteArray name;
int begin;
int end;
};
Q_DECLARE_TYPEINFO(NamespaceDef, Q_MOVABLE_TYPE);
class Moc : public Parser
{
@ -198,7 +208,7 @@ public:
bool mustIncludeQPluginH;
QByteArray includePath;
QList<QByteArray> includeFiles;
QList<ClassDef> classList;
QVector<ClassDef> classList;
QMap<QByteArray, QByteArray> interface2IdMap;
QList<QByteArray> metaTypes;
// map from class name to fully qualified name

View File

@ -127,7 +127,7 @@ static QString addFunction(const FunctionDef &mm, bool isSignal = false) {
return QString(); // wasn't a valid type
}
}
QList<ArgumentDef> names = mm.arguments;
QVector<ArgumentDef> names = mm.arguments;
QVector<int> types;
QString errorMsg;
int inputCount = qDBusParametersForMethod(mm, types, errorMsg);
@ -396,7 +396,7 @@ int main(int argc, char **argv)
args.append(QString::fromLocal8Bit(argv[n]));
parseCmdLine(args);
QList<ClassDef> classes;
QVector<ClassDef> classes;
for (int i = 0; i < args.count(); ++i) {
const QString arg = args.at(i);