aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLars Knoll <lars.knoll@qt.io>2018-01-15 15:36:25 +0100
committerLars Knoll <lars.knoll@qt.io>2018-01-17 09:20:59 +0000
commitc2b4c6393fee37e0c6c4a8c5d40d13120cc8a94e (patch)
tree1e3454e819e248337ad460b0db6a7a7239882523
parentc2d0693ca99171ebeb8f35423f29562b0d26c6c0 (diff)
Use a more optimized lookup for global properties
Force the use of a global lookup if we know that the property can and will be found in the global object. This is possible, as the global object is frozen in QML mode and can't be overwritten. Shaves of .5% on the delegates_item_states benchmark, and will significantly speed up all accesses to e.g. the Math object. Change-Id: Ia1e248781a13ebaeb8bc43652e53a6fdde336d0d Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
-rw-r--r--src/qml/compiler/qqmlirbuilder.cpp6
-rw-r--r--src/qml/compiler/qqmlirbuilder_p.h3
-rw-r--r--src/qml/compiler/qqmltypecompiler.cpp2
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp6
-rw-r--r--src/qml/compiler/qv4jsir.cpp5
-rw-r--r--src/qml/compiler/qv4jsir_p.h9
-rw-r--r--src/qml/jit/qv4isel_masm.cpp6
-rw-r--r--tools/qmlcachegen/qmlcachegen.cpp22
8 files changed, 42 insertions, 17 deletions
diff --git a/src/qml/compiler/qqmlirbuilder.cpp b/src/qml/compiler/qqmlirbuilder.cpp
index 3974f9ae4e..9749324060 100644
--- a/src/qml/compiler/qqmlirbuilder.cpp
+++ b/src/qml/compiler/qqmlirbuilder.cpp
@@ -1555,7 +1555,7 @@ char *QmlUnitGenerator::writeBindings(char *bindingPtr, const Object *o, Binding
JSCodeGen::JSCodeGen(const QString &fileName, const QString &finalUrl, const QString &sourceCode,
QV4::IR::Module *jsModule, QQmlJS::Engine *jsEngine,
QQmlJS::AST::UiProgram *qmlRoot, QQmlTypeNameCache *imports,
- const QV4::Compiler::StringTableGenerator *stringPool)
+ const QV4::Compiler::StringTableGenerator *stringPool, const QSet<QString> &globalNames)
: QQmlJS::Codegen(/*strict mode*/false)
, sourceCode(sourceCode)
, jsEngine(jsEngine)
@@ -1567,6 +1567,7 @@ JSCodeGen::JSCodeGen(const QString &fileName, const QString &finalUrl, const QSt
, _scopeObject(0)
, _qmlContextTemp(-1)
, _importedScriptsTemp(-1)
+ , m_globalNames(globalNames)
{
_module = jsModule;
_module->setFileName(fileName);
@@ -2010,6 +2011,9 @@ QV4::IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int
}
}
+ if (m_globalNames.contains(name))
+ return _block->GLOBALNAME(name, line, col, /*forceLookup =*/ true);
+
#else
Q_UNUSED(name)
#endif // V4_BOOTSTRAP
diff --git a/src/qml/compiler/qqmlirbuilder_p.h b/src/qml/compiler/qqmlirbuilder_p.h
index 8f8a6d090e..ad34864242 100644
--- a/src/qml/compiler/qqmlirbuilder_p.h
+++ b/src/qml/compiler/qqmlirbuilder_p.h
@@ -584,7 +584,7 @@ struct Q_QML_PRIVATE_EXPORT JSCodeGen : public QQmlJS::Codegen
{
JSCodeGen(const QString &fileName, const QString &finalUrl, const QString &sourceCode,
QV4::IR::Module *jsModule, QQmlJS::Engine *jsEngine, QQmlJS::AST::UiProgram *qmlRoot,
- QQmlTypeNameCache *imports, const QV4::Compiler::StringTableGenerator *stringPool);
+ QQmlTypeNameCache *imports, const QV4::Compiler::StringTableGenerator *stringPool, const QSet<QString> &globalNames);
struct IdMapping
{
@@ -619,6 +619,7 @@ private:
QQmlPropertyCache *_scopeObject;
int _qmlContextTemp;
int _importedScriptsTemp;
+ QSet<QString> m_globalNames;
};
struct Q_QML_PRIVATE_EXPORT IRLoader {
diff --git a/src/qml/compiler/qqmltypecompiler.cpp b/src/qml/compiler/qqmltypecompiler.cpp
index 0dd3cf9bfa..d152d26968 100644
--- a/src/qml/compiler/qqmltypecompiler.cpp
+++ b/src/qml/compiler/qqmltypecompiler.cpp
@@ -143,7 +143,7 @@ QV4::CompiledData::CompilationUnit *QQmlTypeCompiler::compile()
QmlIR::JSCodeGen v4CodeGenerator(typeData->urlString(), typeData->finalUrlString(),
document->code, &document->jsModule,
&document->jsParserEngine, document->program,
- typeNameCache, &document->jsGenerator.stringTable);
+ typeNameCache, &document->jsGenerator.stringTable, engine->v8engine()->illegalNames());
QQmlJSCodeGenerator jsCodeGen(this, &v4CodeGenerator);
if (!jsCodeGen.generateCodeForComponents())
return nullptr;
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index 82f5225f28..c29ffa10c2 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -386,7 +386,7 @@ void InstructionSelection::constructActivationProperty(IR::Name *func,
IR::ExprList *args,
IR::Expr *target)
{
- if (useFastLookups && func->global) {
+ if ((useFastLookups || func->forceLookup) && func->global) {
Instruction::ConstructGlobalLookup call;
call.index = registerGlobalGetterLookup(*func->id);
prepareCallArgs(args, call.argc);
@@ -491,7 +491,7 @@ void InstructionSelection::loadRegexp(IR::RegExp *sourceRegexp, IR::Expr *target
void InstructionSelection::getActivationProperty(const IR::Name *name, IR::Expr *target)
{
- if (useFastLookups && name->global) {
+ if ((useFastLookups || name->forceLookup) && name->global) {
Instruction::GetGlobalLookup load;
load.index = registerGlobalGetterLookup(*name->id);
load.result = getResultParam(target);
@@ -1015,7 +1015,7 @@ void InstructionSelection::visitRet(IR::Ret *s)
void InstructionSelection::callBuiltinInvalid(IR::Name *func, IR::ExprList *args, IR::Expr *result)
{
- if (useFastLookups && func->global) {
+ if ((useFastLookups || func->forceLookup) && func->global) {
Instruction::CallGlobalLookup call;
call.index = registerGlobalGetterLookup(*func->id);
prepareCallArgs(args, call.argc);
diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp
index a8e18784c7..a4038f827a 100644
--- a/src/qml/compiler/qv4jsir.cpp
+++ b/src/qml/compiler/qv4jsir.cpp
@@ -243,11 +243,12 @@ private:
}
};
-void Name::initGlobal(const QString *id, quint32 line, quint32 column)
+void Name::initGlobal(const QString *id, quint32 line, quint32 column, bool forceLookup)
{
this->id = id;
this->builtin = builtin_invalid;
this->global = true;
+ this->forceLookup = forceLookup;
this->qmlSingleton = false;
this->freeOfSideEffects = false;
this->line = line;
@@ -259,6 +260,7 @@ void Name::init(const QString *id, quint32 line, quint32 column)
this->id = id;
this->builtin = builtin_invalid;
this->global = false;
+ this->forceLookup = false;
this->qmlSingleton = false;
this->freeOfSideEffects = false;
this->line = line;
@@ -270,6 +272,7 @@ void Name::init(Builtin builtin, quint32 line, quint32 column)
this->id = 0;
this->builtin = builtin;
this->global = false;
+ this->forceLookup = false;
this->qmlSingleton = false;
this->freeOfSideEffects = false;
this->line = line;
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index 9980a21912..317abd09bb 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -480,6 +480,7 @@ struct Name: Expr {
const QString *id;
Builtin builtin;
bool global : 1;
+ bool forceLookup : 1;
bool qmlSingleton : 1;
bool freeOfSideEffects : 1;
quint32 line;
@@ -487,7 +488,7 @@ struct Name: Expr {
Name(): Expr(NameExpr) {}
- void initGlobal(const QString *id, quint32 line, quint32 column);
+ void initGlobal(const QString *id, quint32 line, quint32 column, bool forceLookup = false);
void init(const QString *id, quint32 line, quint32 column);
void init(Builtin builtin, quint32 line, quint32 column);
@@ -1141,7 +1142,7 @@ public:
Name *NAME(const QString &id, quint32 line, quint32 column);
Name *NAME(Name::Builtin builtin, quint32 line, quint32 column);
- Name *GLOBALNAME(const QString &id, quint32 line, quint32 column);
+ Name *GLOBALNAME(const QString &id, quint32 line, quint32 column, bool forceLookup = false);
Closure *CLOSURE(int functionInModule);
@@ -1583,11 +1584,11 @@ inline Name *BasicBlock::NAME(const QString &id, quint32 line, quint32 column)
return e;
}
-inline Name *BasicBlock::GLOBALNAME(const QString &id, quint32 line, quint32 column)
+inline Name *BasicBlock::GLOBALNAME(const QString &id, quint32 line, quint32 column, bool forceLookup)
{
Q_ASSERT(!isRemoved());
Name *e = function->New<Name>();
- e->initGlobal(function->newString(id), line, column);
+ e->initGlobal(function->newString(id), line, column, forceLookup);
return e;
}
diff --git a/src/qml/jit/qv4isel_masm.cpp b/src/qml/jit/qv4isel_masm.cpp
index 50d40f6f98..9ddab8f838 100644
--- a/src/qml/jit/qv4isel_masm.cpp
+++ b/src/qml/jit/qv4isel_masm.cpp
@@ -168,7 +168,7 @@ void InstructionSelection<JITAssembler>::callBuiltinInvalid(IR::Name *func, IR::
{
prepareCallData(args, 0);
- if (useFastLookups && func->global) {
+ if ((useFastLookups || func->forceLookup) && func->global) {
uint index = registerGlobalGetterLookup(*func->id);
generateRuntimeCall(_as, result, callGlobalLookup,
JITTargetPlatform::EngineRegister,
@@ -517,7 +517,7 @@ void InstructionSelection<JITAssembler>::loadRegexp(IR::RegExp *sourceRegexp, IR
template <typename JITAssembler>
void InstructionSelection<JITAssembler>::getActivationProperty(const IR::Name *name, IR::Expr *target)
{
- if (useFastLookups && name->global) {
+ if ((useFastLookups || name->forceLookup) && name->global) {
uint index = registerGlobalGetterLookup(*name->id);
generateLookupCall(target, index, offsetof(QV4::Lookup, globalGetter), JITTargetPlatform::EngineRegister, JITAssembler::Void);
return;
@@ -1128,7 +1128,7 @@ void InstructionSelection<JITAssembler>::constructActivationProperty(IR::Name *f
Q_ASSERT(func != 0);
prepareCallData(args, 0);
- if (useFastLookups && func->global) {
+ if ((useFastLookups || func->forceLookup) && func->global) {
uint index = registerGlobalGetterLookup(*func->id);
generateRuntimeCall(_as, result, constructGlobalLookup,
JITTargetPlatform::EngineRegister,
diff --git a/tools/qmlcachegen/qmlcachegen.cpp b/tools/qmlcachegen/qmlcachegen.cpp
index 69612eb514..844cd816bc 100644
--- a/tools/qmlcachegen/qmlcachegen.cpp
+++ b/tools/qmlcachegen/qmlcachegen.cpp
@@ -47,6 +47,23 @@ Q_QML_EXPORT QV4::EvalISelFactory *createISelForArchitecture(const QString &arch
QT_END_NAMESPACE
+QSet<QString> illegalNames;
+
+void setupIllegalNames()
+{
+ // #### this in incomplete
+ illegalNames.insert(QStringLiteral("Math"));
+ illegalNames.insert(QStringLiteral("Array"));
+ illegalNames.insert(QStringLiteral("String"));
+ illegalNames.insert(QStringLiteral("Function"));
+ illegalNames.insert(QStringLiteral("Boolean"));
+ illegalNames.insert(QStringLiteral("Number"));
+ illegalNames.insert(QStringLiteral("Date"));
+ illegalNames.insert(QStringLiteral("RegExp"));
+ illegalNames.insert(QStringLiteral("Error"));
+ illegalNames.insert(QStringLiteral("Object"));
+}
+
struct Error
{
QString message;
@@ -165,7 +182,6 @@ static bool compileQmlFile(const QString &inputFileName, const QString &outputFi
}
{
- QSet<QString> illegalNames; // ####
QmlIR::IRBuilder irBuilder(illegalNames);
if (!irBuilder.generateFromQml(sourceCode, inputFileName, &irDocument)) {
for (const QQmlJS::DiagnosticMessage &parseError: qAsConst(irBuilder.errors)) {
@@ -183,7 +199,7 @@ static bool compileQmlFile(const QString &inputFileName, const QString &outputFi
QmlIR::JSCodeGen v4CodeGen(/*empty input file name*/QString(), QString(), irDocument.code,
&irDocument.jsModule, &irDocument.jsParserEngine,
irDocument.program, /*import cache*/0,
- &irDocument.jsGenerator.stringTable);
+ &irDocument.jsGenerator.stringTable, illegalNames);
for (QmlIR::Object *object: qAsConst(irDocument.objects)) {
if (object->functionsAndExpressions->count == 0)
continue;
@@ -295,7 +311,7 @@ static bool compileJSFile(const QString &inputFileName, const QString &outputFil
QmlIR::JSCodeGen v4CodeGen(inputFileName, inputFileName,
irDocument.code, &irDocument.jsModule,
&irDocument.jsParserEngine, irDocument.program,
- /*import cache*/0, &irDocument.jsGenerator.stringTable);
+ /*import cache*/0, &irDocument.jsGenerator.stringTable, illegalNames);
v4CodeGen.generateFromProgram(/*empty input file name*/QString(), QString(), sourceCode,
program, &irDocument.jsModule, QQmlJS::Codegen::GlobalCode);
QList<QQmlJS::DiagnosticMessage> jsErrors = v4CodeGen.errors();