aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/compiler
diff options
context:
space:
mode:
authorSimon Hausmann <simon.hausmann@digia.com>2013-11-15 00:06:18 +0100
committerThe Qt Project <gerrit-noreply@qt-project.org>2013-11-28 13:47:40 +0100
commitf474eede801ed7bec712069e95bbe2f4ab5558ae (patch)
tree94470e17070c1ff1b9805c38ed2bec10cc9110ff /src/qml/compiler
parent140400be0f8a8c91ce02ad5691d81d7604e5a4db (diff)
Add support for accelerated property access to QML types and namespace support
* Resolve lookups in namespaces at compile time and instruct the SSA optimizer to eliminate reads from the namespace (QQmlTypeWrapper) if possible. For example access to attached properties of types (i.e. MyNameSpace.ListView.isCurrentItem) requires neither reading the namespace nor the type. * Add support for accelerated lookup of attached properties Change-Id: Ib0b66404ed7e70e1d4a46a1ac8218743a4cc8608 Reviewed-by: Lars Knoll <lars.knoll@digia.com>
Diffstat (limited to 'src/qml/compiler')
-rw-r--r--src/qml/compiler/qqmlcodegenerator.cpp129
-rw-r--r--src/qml/compiler/qv4instr_moth_p.h9
-rw-r--r--src/qml/compiler/qv4isel_masm.cpp9
-rw-r--r--src/qml/compiler/qv4isel_masm_p.h2
-rw-r--r--src/qml/compiler/qv4isel_moth.cpp22
-rw-r--r--src/qml/compiler/qv4isel_moth_p.h2
-rw-r--r--src/qml/compiler/qv4isel_p.cpp6
-rw-r--r--src/qml/compiler/qv4isel_p.h2
-rw-r--r--src/qml/compiler/qv4jsir.cpp24
-rw-r--r--src/qml/compiler/qv4jsir_p.h31
-rw-r--r--src/qml/compiler/qv4regalloc.cpp2
-rw-r--r--src/qml/compiler/qv4ssa.cpp18
12 files changed, 200 insertions, 56 deletions
diff --git a/src/qml/compiler/qqmlcodegenerator.cpp b/src/qml/compiler/qqmlcodegenerator.cpp
index c32ad2958d..d80c4d120d 100644
--- a/src/qml/compiler/qqmlcodegenerator.cpp
+++ b/src/qml/compiler/qqmlcodegenerator.cpp
@@ -1332,6 +1332,97 @@ enum MetaObjectResolverFlags {
LookupsExcludeProperties = 0x4
};
+static void initMetaObjectResolver(V4IR::MemberExpressionResolver *resolver, QQmlPropertyCache *metaObject);
+
+static V4IR::Type resolveQmlType(QQmlEnginePrivate *qmlEngine, V4IR::MemberExpressionResolver *resolver, V4IR::Member *member)
+{
+ V4IR::Type result = V4IR::VarType;
+
+ QQmlType *type = static_cast<QQmlType*>(resolver->data);
+ if (type->isSingleton()) {
+ if (type->isCompositeSingleton()) {
+ QQmlTypeData *tdata = qmlEngine->typeLoader.getType(type->singletonInstanceInfo()->url);
+ Q_ASSERT(tdata);
+ Q_ASSERT(tdata->isComplete());
+ initMetaObjectResolver(resolver, qmlEngine->propertyCacheForType(tdata->compiledData()->metaTypeId));
+ resolver->flags |= AllPropertiesAreFinal;
+ } else {
+ const QMetaObject *singletonMo = type->singletonInstanceInfo()->instanceMetaObject;
+ if (!singletonMo) { // We can only accelerate C++ singletons that were registered with their meta-type
+ resolver->clear();
+ return result;
+ }
+ initMetaObjectResolver(resolver, qmlEngine->cache(singletonMo));
+ resolver->flags |= LookupsIncludeEnums;
+ }
+ return resolver->resolveMember(qmlEngine, resolver, member);
+ } else {
+ if (member->name->constData()->isUpper()) {
+ bool ok = false;
+ int value = type->enumValue(*member->name, &ok);
+ if (ok) {
+ member->memberIsEnum = true;
+ member->enumValue = value;
+ resolver->clear();
+ return V4IR::SInt32Type;
+ }
+ } else if (const QMetaObject *attachedMeta = type->attachedPropertiesType()) {
+ QQmlPropertyCache *cache = qmlEngine->cache(attachedMeta);
+ initMetaObjectResolver(resolver, cache);
+ member->attachedPropertiesId = type->attachedPropertiesId();
+ return resolver->resolveMember(qmlEngine, resolver, member);
+ }
+ }
+
+ resolver->clear();
+ return result;
+}
+
+static void initQmlTypeResolver(V4IR::MemberExpressionResolver *resolver, QQmlType *qmlType)
+{
+ resolver->resolveMember = &resolveQmlType;
+ resolver->data = qmlType;
+ resolver->extraData = 0;
+ resolver->flags = 0;
+}
+
+static V4IR::Type resolveImportNamespace(QQmlEnginePrivate *, V4IR::MemberExpressionResolver *resolver, V4IR::Member *member)
+{
+ V4IR::Type result = V4IR::VarType;
+ QQmlTypeNameCache *typeNamespace = static_cast<QQmlTypeNameCache*>(resolver->extraData);
+ void *importNamespace = resolver->data;
+
+ QQmlTypeNameCache::Result r = typeNamespace->query(*member->name, importNamespace);
+ if (r.isValid()) {
+ member->freeOfSideEffects = true;
+ if (r.scriptIndex != -1) {
+ // TODO: remember the index and replace with subscript later.
+ result = V4IR::VarType;
+ } else if (r.type) {
+ // TODO: Propagate singleton information, so that it is loaded
+ // through the singleton getter in the run-time. Until then we
+ // can't accelerate access :(
+ if (!r.type->isSingleton()) {
+ initQmlTypeResolver(resolver, r.type);
+ return V4IR::QObjectType;
+ }
+ } else {
+ Q_ASSERT(false); // How can this happen?
+ }
+ }
+
+ resolver->clear();
+ return result;
+}
+
+static void initImportNamespaceResolver(V4IR::MemberExpressionResolver *resolver, QQmlTypeNameCache *imports, const void *importNamespace)
+{
+ resolver->resolveMember = &resolveImportNamespace;
+ resolver->data = const_cast<void*>(importNamespace);
+ resolver->extraData = imports;
+ resolver->flags = 0;
+}
+
static V4IR::Type resolveMetaObjectProperty(QQmlEnginePrivate *qmlEngine, V4IR::MemberExpressionResolver *resolver, V4IR::Member *member)
{
V4IR::Type result = V4IR::VarType;
@@ -1397,6 +1488,7 @@ static void initMetaObjectResolver(V4IR::MemberExpressionResolver *resolver, QQm
resolver->resolveMember = &resolveMetaObjectProperty;
resolver->data = metaObject;
resolver->flags = 0;
+ resolver->isQObjectResolver = true;
}
void JSCodeGen::beginFunctionBodyHook()
@@ -1453,35 +1545,24 @@ V4IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int col
return subscript(_block->TEMP(_importedScriptsTemp), _block->CONST(V4IR::SInt32Type, r.scriptIndex));
} else if (r.type) {
V4IR::Name *typeName = _block->NAME(name, line, col);
- V4IR::Temp *result = _block->TEMP(_block->newTemp());
+ // Make sure the run-time loads this through the more efficient singleton getter.
+ typeName->qmlSingleton = r.type->isSingleton();
+ typeName->freeOfSideEffects = true;
- if (r.type->isSingleton()) {
- if (r.type->isCompositeSingleton()) {
- QQmlTypeData *tdata = engine->typeLoader.getType(r.type->singletonInstanceInfo()->url);
- Q_ASSERT(tdata);
- Q_ASSERT(tdata->isComplete());
- initMetaObjectResolver(&result->memberResolver, engine->propertyCacheForType(tdata->compiledData()->metaTypeId));
- result->memberResolver.flags |= AllPropertiesAreFinal;
- } else {
- const QMetaObject *singletonMo = r.type->singletonInstanceInfo()->instanceMetaObject;
- if (!singletonMo) // We can only accelerate C++ singletons that were registered with their meta-type
- return 0;
- initMetaObjectResolver(&result->memberResolver, engine->cache(singletonMo));
- }
+ V4IR::Temp *result = _block->TEMP(_block->newTemp());
+ initQmlTypeResolver(&result->memberResolver, r.type);
- // Instruct the isel to not load this as activation property but through the
- // run-time's singleton getter.
- typeName->qmlSingleton = true;
- } else {
- initMetaObjectResolver(&result->memberResolver,engine->cache(r.type->metaObject()));
- result->memberResolver.flags |= LookupsExcludeProperties;
- }
- typeName->freeOfSideEffects = true;
- result->memberResolver.flags |= LookupsIncludeEnums;
_block->MOVE(result, typeName);
return _block->TEMP(result->index);
} else {
- return 0; // TODO: We can't do fast lookup for these yet.
+ Q_ASSERT(r.importNamespace);
+ V4IR::Name *namespaceName = _block->NAME(name, line, col);
+ namespaceName->freeOfSideEffects = true;
+ V4IR::Temp *result = _block->TEMP(_block->newTemp());
+ initImportNamespaceResolver(&result->memberResolver, imports, r.importNamespace);
+
+ _block->MOVE(result, namespaceName);
+ return _block->TEMP(result->index);
}
}
}
diff --git a/src/qml/compiler/qv4instr_moth_p.h b/src/qml/compiler/qv4instr_moth_p.h
index 180391ff33..5b5667abb4 100644
--- a/src/qml/compiler/qv4instr_moth_p.h
+++ b/src/qml/compiler/qv4instr_moth_p.h
@@ -67,6 +67,7 @@ QT_BEGIN_NAMESPACE
F(SetLookup, setLookup) \
F(StoreQObjectProperty, storeQObjectProperty) \
F(LoadQObjectProperty, loadQObjectProperty) \
+ F(LoadAttachedQObjectProperty, loadAttachedQObjectProperty) \
F(Push, push) \
F(CallValue, callValue) \
F(CallProperty, callProperty) \
@@ -288,8 +289,15 @@ union Instr
int propertyIndex;
Param base;
Param result;
+ int attachedPropertiesId;
bool captureRequired;
};
+ struct instr_loadAttachedQObjectProperty {
+ MOTH_INSTR_HEADER
+ int propertyIndex;
+ Param result;
+ int attachedPropertiesId;
+ };
struct instr_storeProperty {
MOTH_INSTR_HEADER
int name;
@@ -692,6 +700,7 @@ union Instr
instr_loadProperty loadProperty;
instr_getLookup getLookup;
instr_loadQObjectProperty loadQObjectProperty;
+ instr_loadAttachedQObjectProperty loadAttachedQObjectProperty;
instr_storeProperty storeProperty;
instr_setLookup setLookup;
instr_storeQObjectProperty storeQObjectProperty;
diff --git a/src/qml/compiler/qv4isel_masm.cpp b/src/qml/compiler/qv4isel_masm.cpp
index ed57852cd6..67c4f672c6 100644
--- a/src/qml/compiler/qv4isel_masm.cpp
+++ b/src/qml/compiler/qv4isel_masm.cpp
@@ -983,10 +983,13 @@ void InstructionSelection::getProperty(V4IR::Expr *base, const QString &name, V4
}
}
-void InstructionSelection::getQObjectProperty(V4IR::Expr *base, int propertyIndex, bool captureRequired, V4IR::Temp *target)
+void InstructionSelection::getQObjectProperty(V4IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, V4IR::Temp *target)
{
- generateFunctionCall(target, __qmljs_get_qobject_property, Assembler::ContextRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(propertyIndex),
- Assembler::TrustedImm32(captureRequired));
+ if (attachedPropertiesId != 0)
+ generateFunctionCall(target, __qmljs_get_attached_property, Assembler::ContextRegister, Assembler::TrustedImm32(attachedPropertiesId), Assembler::TrustedImm32(propertyIndex));
+ else
+ generateFunctionCall(target, __qmljs_get_qobject_property, Assembler::ContextRegister, Assembler::PointerToValue(base), Assembler::TrustedImm32(propertyIndex),
+ Assembler::TrustedImm32(captureRequired));
}
void InstructionSelection::setProperty(V4IR::Expr *source, V4IR::Expr *targetBase,
diff --git a/src/qml/compiler/qv4isel_masm_p.h b/src/qml/compiler/qv4isel_masm_p.h
index 4b0d19df07..f7987aac5c 100644
--- a/src/qml/compiler/qv4isel_masm_p.h
+++ b/src/qml/compiler/qv4isel_masm_p.h
@@ -1471,7 +1471,7 @@ protected:
virtual void getProperty(V4IR::Expr *base, const QString &name, V4IR::Temp *target);
virtual void setProperty(V4IR::Expr *source, V4IR::Expr *targetBase, const QString &targetName);
virtual void setQObjectProperty(V4IR::Expr *source, V4IR::Expr *targetBase, int propertyIndex);
- virtual void getQObjectProperty(V4IR::Expr *base, int propertyIndex, bool captureRequired, V4IR::Temp *target);
+ virtual void getQObjectProperty(V4IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, V4IR::Temp *target);
virtual void getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR::Temp *target);
virtual void setElement(V4IR::Expr *source, V4IR::Expr *targetBase, V4IR::Expr *targetIndex);
virtual void copyValue(V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp);
diff --git a/src/qml/compiler/qv4isel_moth.cpp b/src/qml/compiler/qv4isel_moth.cpp
index ee7e8ce2e8..bf9af178fe 100644
--- a/src/qml/compiler/qv4isel_moth.cpp
+++ b/src/qml/compiler/qv4isel_moth.cpp
@@ -526,14 +526,22 @@ void InstructionSelection::setQObjectProperty(V4IR::Expr *source, V4IR::Expr *ta
addInstruction(store);
}
-void InstructionSelection::getQObjectProperty(V4IR::Expr *base, int propertyIndex, bool captureRequired, V4IR::Temp *target)
+void InstructionSelection::getQObjectProperty(V4IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, V4IR::Temp *target)
{
- Instruction::LoadQObjectProperty load;
- load.base = getParam(base);
- load.propertyIndex = propertyIndex;
- load.result = getResultParam(target);
- load.captureRequired = captureRequired;
- addInstruction(load);
+ if (attachedPropertiesId != 0) {
+ Instruction::LoadAttachedQObjectProperty load;
+ load.propertyIndex = propertyIndex;
+ load.result = getResultParam(target);
+ load.attachedPropertiesId = attachedPropertiesId;
+ addInstruction(load);
+ } else {
+ Instruction::LoadQObjectProperty load;
+ load.base = getParam(base);
+ load.propertyIndex = propertyIndex;
+ load.result = getResultParam(target);
+ load.captureRequired = captureRequired;
+ addInstruction(load);
+ }
}
void InstructionSelection::getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR::Temp *target)
diff --git a/src/qml/compiler/qv4isel_moth_p.h b/src/qml/compiler/qv4isel_moth_p.h
index 031c2d838a..d8a85ff249 100644
--- a/src/qml/compiler/qv4isel_moth_p.h
+++ b/src/qml/compiler/qv4isel_moth_p.h
@@ -126,7 +126,7 @@ protected:
virtual void getProperty(V4IR::Expr *base, const QString &name, V4IR::Temp *target);
virtual void setProperty(V4IR::Expr *source, V4IR::Expr *targetBase, const QString &targetName);
virtual void setQObjectProperty(V4IR::Expr *source, V4IR::Expr *targetBase, int propertyIndex);
- virtual void getQObjectProperty(V4IR::Expr *base, int propertyIndex, bool captureRequired, V4IR::Temp *target);
+ virtual void getQObjectProperty(V4IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, V4IR::Temp *target);
virtual void getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR::Temp *target);
virtual void setElement(V4IR::Expr *source, V4IR::Expr *targetBase, V4IR::Expr *targetIndex);
virtual void copyValue(V4IR::Temp *sourceTemp, V4IR::Temp *targetTemp);
diff --git a/src/qml/compiler/qv4isel_p.cpp b/src/qml/compiler/qv4isel_p.cpp
index 96a3370903..7f0d8313fe 100644
--- a/src/qml/compiler/qv4isel_p.cpp
+++ b/src/qml/compiler/qv4isel_p.cpp
@@ -148,11 +148,11 @@ void IRDecoder::visitMove(V4IR::Move *s)
} else if (V4IR::Member *m = s->source->asMember()) {
if (m->property) {
bool captureRequired = true;
- if (_function) {
+ if (_function && m->attachedPropertiesId == 0) {
captureRequired = !_function->contextObjectDependencies.contains(m->property)
&& !_function->scopeObjectDependencies.contains(m->property);
}
- getQObjectProperty(m->base, m->property->coreIndex, captureRequired, t);
+ getQObjectProperty(m->base, m->property->coreIndex, captureRequired, m->attachedPropertiesId, t);
return;
} else if (m->base->asTemp() || m->base->asConst()) {
getProperty(m->base, *m->name, t);
@@ -191,7 +191,7 @@ void IRDecoder::visitMove(V4IR::Move *s)
} else if (V4IR::Member *m = s->target->asMember()) {
if (m->base->asTemp() || m->base->asConst()) {
if (s->source->asTemp() || s->source->asConst()) {
- if (m->property) {
+ if (m->property && m->attachedPropertiesId == 0) {
setQObjectProperty(s->source, m->base, m->property->coreIndex);
return;
} else {
diff --git a/src/qml/compiler/qv4isel_p.h b/src/qml/compiler/qv4isel_p.h
index 7ee5cbba4e..5ddafc07ab 100644
--- a/src/qml/compiler/qv4isel_p.h
+++ b/src/qml/compiler/qv4isel_p.h
@@ -156,7 +156,7 @@ public: // to implement by subclasses:
virtual void setActivationProperty(V4IR::Expr *source, const QString &targetName) = 0;
virtual void initClosure(V4IR::Closure *closure, V4IR::Temp *target) = 0;
virtual void getProperty(V4IR::Expr *base, const QString &name, V4IR::Temp *target) = 0;
- virtual void getQObjectProperty(V4IR::Expr *base, int propertyIndex, bool captureRequired, V4IR::Temp *targetTemp) = 0;
+ virtual void getQObjectProperty(V4IR::Expr *base, int propertyIndex, bool captureRequired, int attachedPropertiesId, V4IR::Temp *targetTemp) = 0;
virtual void setProperty(V4IR::Expr *source, V4IR::Expr *targetBase, const QString &targetName) = 0;
virtual void setQObjectProperty(V4IR::Expr *source, V4IR::Expr *targetBase, int propertyIndex) = 0;
virtual void getElement(V4IR::Expr *base, V4IR::Expr *index, V4IR::Temp *target) = 0;
diff --git a/src/qml/compiler/qv4jsir.cpp b/src/qml/compiler/qv4jsir.cpp
index 41502dbd4f..a2dbf44375 100644
--- a/src/qml/compiler/qv4jsir.cpp
+++ b/src/qml/compiler/qv4jsir.cpp
@@ -278,7 +278,7 @@ static QString dumpStart(const Expr *e) {
QString result = typeName(e->type);
const Temp *temp = const_cast<Expr*>(e)->asTemp();
- if (e->type == QObjectType && temp && temp->memberResolver.data) {
+ if (e->type == QObjectType && temp && temp->memberResolver.isQObjectResolver) {
result += QLatin1Char('<');
result += QString::fromUtf8(static_cast<QQmlPropertyCache*>(temp->memberResolver.data)->className());
result += QLatin1Char('>');
@@ -554,7 +554,10 @@ void Subscript::dump(QTextStream &out) const
void Member::dump(QTextStream &out) const
{
- base->dump(out);
+ if (attachedPropertiesId != 0 && !base->asTemp())
+ out << "[[attached property from " << attachedPropertiesId << "]]";
+ else
+ base->dump(out);
out << '.' << *name;
if (property)
out << " (meta-property " << property->coreIndex << " <" << QMetaType::typeName(property->propType) << ">)";
@@ -840,10 +843,17 @@ Expr *BasicBlock::SUBSCRIPT(Expr *base, Expr *index)
return e;
}
-Expr *BasicBlock::MEMBER(Expr *base, const QString *name, QQmlPropertyData *property)
+Expr *BasicBlock::MEMBER(Expr *base, const QString *name, QQmlPropertyData *property, int attachedPropertiesId)
+{
+ Member*e = function->New<Member>();
+ e->init(base, name, property, attachedPropertiesId);
+ return e;
+}
+
+Expr *BasicBlock::MEMBER(Expr *base, const QString *name, int enumValue)
{
Member*e = function->New<Member>();
- e->init(base, name, property);
+ e->init(base, name, enumValue);
return e;
}
@@ -1033,7 +1043,11 @@ void CloneExpr::visitSubscript(Subscript *e)
void CloneExpr::visitMember(Member *e)
{
- cloned = block->MEMBER(clone(e->base), e->name, e->property);
+ Expr *clonedBase = clone(e->base);
+ if (e->memberIsEnum)
+ cloned = block->MEMBER(clonedBase, e->name, e->enumValue);
+ else
+ cloned = block->MEMBER(clonedBase, e->name, e->property, e->attachedPropertiesId);
}
} // end of namespace IR
diff --git a/src/qml/compiler/qv4jsir_p.h b/src/qml/compiler/qv4jsir_p.h
index aa85c4cf3c..9105a9137d 100644
--- a/src/qml/compiler/qv4jsir_p.h
+++ b/src/qml/compiler/qv4jsir_p.h
@@ -236,14 +236,16 @@ struct MemberExpressionResolver
typedef Type (*ResolveFunction)(QQmlEnginePrivate *engine, MemberExpressionResolver *resolver, Member *member);
MemberExpressionResolver()
- : resolveMember(0), data(0), flags(0) {}
+ : resolveMember(0), data(0), extraData(0), flags(0), isQObjectResolver(false) {}
bool isValid() const { return !!resolveMember; }
void clear() { *this = MemberExpressionResolver(); }
ResolveFunction resolveMember;
- void *data; // Could be pointer to meta object, QQmlTypeNameCache, etc. - depends on resolveMember implementation
- int flags;
+ void *data; // Could be pointer to meta object, importNameSpace, etc. - depends on resolveMember implementation
+ void *extraData; // Could be QQmlTypeNameCache
+ unsigned int flags : 31;
+ unsigned int isQObjectResolver; // neede for IR dump helpers
};
struct Expr {
@@ -555,15 +557,31 @@ struct Member: Expr {
Expr *base;
const QString *name;
QQmlPropertyData *property;
+ int attachedPropertiesId;
int enumValue;
- bool memberIsEnum;
+ bool memberIsEnum : 1;
+ bool freeOfSideEffects : 1;
- void init(Expr *base, const QString *name, QQmlPropertyData *property = 0)
+ void init(Expr *base, const QString *name, QQmlPropertyData *property = 0, int attachedPropertiesId = 0)
{
this->base = base;
this->name = name;
this->property = property;
+ this->attachedPropertiesId = attachedPropertiesId;
+ this->enumValue = 0;
this->memberIsEnum = false;
+ this->freeOfSideEffects = false;
+ }
+
+ void init(Expr *base, const QString *name, int enumValue)
+ {
+ this->base = base;
+ this->name = name;
+ this->property = 0;
+ this->attachedPropertiesId = 0;
+ this->enumValue = enumValue;
+ this->memberIsEnum = true;
+ this->freeOfSideEffects = false;
}
virtual void accept(ExprVisitor *v) { v->visitMember(this); }
@@ -869,7 +887,8 @@ struct BasicBlock {
Expr *CALL(Expr *base, ExprList *args = 0);
Expr *NEW(Expr *base, ExprList *args = 0);
Expr *SUBSCRIPT(Expr *base, Expr *index);
- Expr *MEMBER(Expr *base, const QString *name, QQmlPropertyData *property = 0);
+ Expr *MEMBER(Expr *base, const QString *name, QQmlPropertyData *property = 0, int attachedPropertiesId = 0);
+ Expr *MEMBER(Expr *base, const QString *name, int enumValue);
Stmt *EXP(Expr *expr);
diff --git a/src/qml/compiler/qv4regalloc.cpp b/src/qml/compiler/qv4regalloc.cpp
index 5d1dc14500..5d341ed149 100644
--- a/src/qml/compiler/qv4regalloc.cpp
+++ b/src/qml/compiler/qv4regalloc.cpp
@@ -435,7 +435,7 @@ protected: // IRDecoder
addCall();
}
- virtual void getQObjectProperty(V4IR::Expr *base, int /*propertyIndex*/, bool /*captureRequired*/, V4IR::Temp *target)
+ virtual void getQObjectProperty(V4IR::Expr *base, int /*propertyIndex*/, bool /*captureRequired*/, int /*attachedPropertiesId*/, V4IR::Temp *target)
{
addDef(target);
addUses(base->asTemp(), Use::CouldHaveRegister);
diff --git a/src/qml/compiler/qv4ssa.cpp b/src/qml/compiler/qv4ssa.cpp
index f9acf99a65..5e2c7ba722 100644
--- a/src/qml/compiler/qv4ssa.cpp
+++ b/src/qml/compiler/qv4ssa.cpp
@@ -1260,6 +1260,8 @@ protected:
virtual void visitMember(Member *e) {
e->base->accept(this);
+ if (e->freeOfSideEffects)
+ return;
markAsSideEffect();
}
@@ -2514,14 +2516,22 @@ void optimizeSSA(Function *function, DefUsesCalculator &defUses)
}
continue;
}
- if (Member *potentialEnumMember = m->source->asMember()) {
- if (potentialEnumMember->memberIsEnum) {
+ if (Member *member = m->source->asMember()) {
+ if (member->memberIsEnum) {
Const *c = function->New<Const>();
- c->init(SInt32Type, potentialEnumMember->enumValue);
+ c->init(SInt32Type, member->enumValue);
W += replaceUses(targetTemp, c);
defUses.removeDef(*targetTemp);
*ref[s] = 0;
- defUses.removeUse(s, *potentialEnumMember->base->asTemp());
+ defUses.removeUse(s, *member->base->asTemp());
+ continue;
+ } else if (member->attachedPropertiesId != 0 && member->property && member->base->asTemp()) {
+ // Attached properties have no dependency on their base. Isel doesn't
+ // need it and we can eliminate the temp used to initialize it.
+ defUses.removeUse(s, *member->base->asTemp());
+ Const *c = function->New<Const>();
+ c->init(SInt32Type, 0);
+ member->base = c;
continue;
}
}