aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorFrederik Gladhorn <frederik.gladhorn@digia.com>2013-11-29 16:00:17 +0100
committerFrederik Gladhorn <frederik.gladhorn@digia.com>2013-11-29 16:00:17 +0100
commit7c7665bbd6609d5c0ee7abd635e37c626b60802b (patch)
treecaf634b0df75f66a3812a0f839da3f0ad66d28ff /src
parent536e1cccf15963b586f3112a0654ddc0d101fa69 (diff)
parentdd1bd3b01b506a05b475514fb2ba7e387f7b17fa (diff)
Merge remote-tracking branch 'origin/stable' into dev
Diffstat (limited to 'src')
-rw-r--r--src/qml/compiler/qqmlcodegenerator.cpp161
-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.h39
-rw-r--r--src/qml/compiler/qv4regalloc.cpp2
-rw-r--r--src/qml/compiler/qv4ssa.cpp24
-rw-r--r--src/qml/debugger/qqmlprofilerservice.cpp200
-rw-r--r--src/qml/debugger/qqmlprofilerservice_p.h84
-rw-r--r--src/qml/jsruntime/qv4object.cpp8
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper.cpp54
-rw-r--r--src/qml/jsruntime/qv4qobjectwrapper_p.h6
-rw-r--r--src/qml/jsruntime/qv4runtime.cpp15
-rw-r--r--src/qml/jsruntime/qv4runtime_p.h1
-rw-r--r--src/qml/jsruntime/qv4vme_moth.cpp4
-rw-r--r--src/qml/qml/qqmlcompiler_p.h2
-rw-r--r--src/qml/qml/qqmlcomponent.cpp16
-rw-r--r--src/qml/qml/qqmlcomponent_p.h4
-rw-r--r--src/qml/qml/qqmlcontextwrapper.cpp6
-rw-r--r--src/qml/qml/qqmldata_p.h3
-rw-r--r--src/qml/qml/qqmlengine.cpp18
-rw-r--r--src/qml/qml/qqmlinstruction_p.h6
-rw-r--r--src/qml/qml/qqmlvaluetype_p.h42
-rw-r--r--src/qml/qml/qqmlvme.cpp27
-rw-r--r--src/qml/qml/qqmlvme_p.h2
-rw-r--r--src/quick/items/qquicktextinput.cpp4
-rw-r--r--src/quick/scenegraph/qsgcontext.cpp2
-rw-r--r--src/quick/scenegraph/qsgrenderloop.cpp8
-rw-r--r--src/quick/scenegraph/shaders/distancefieldshiftedtext.frag2
-rw-r--r--src/quick/util/qquickvaluetypes_p.h82
35 files changed, 662 insertions, 236 deletions
diff --git a/src/qml/compiler/qqmlcodegenerator.cpp b/src/qml/compiler/qqmlcodegenerator.cpp
index c32ad2958d..15004801f5 100644
--- a/src/qml/compiler/qqmlcodegenerator.cpp
+++ b/src/qml/compiler/qqmlcodegenerator.cpp
@@ -45,6 +45,7 @@
#include <private/qqmljsparser_p.h>
#include <private/qqmljslexer_p.h>
#include <private/qqmlcompiler_p.h>
+#include <private/qqmlglobal_p.h>
#include <QCoreApplication>
#ifdef CONST
@@ -53,6 +54,8 @@
QT_USE_NAMESPACE
+DEFINE_BOOL_CONFIG_OPTION(lookupHints, QML_LOOKUP_HINTS);
+
using namespace QtQml;
#define COMPILE_EXCEPTION(location, desc) \
@@ -1327,11 +1330,103 @@ QQmlPropertyData *JSCodeGen::lookupQmlCompliantProperty(QQmlPropertyCache *cache
static void initMetaObjectResolver(V4IR::MemberExpressionResolver *resolver, QQmlPropertyCache *metaObject);
enum MetaObjectResolverFlags {
- AllPropertiesAreFinal = 0x1,
- LookupsIncludeEnums = 0x2,
- LookupsExcludeProperties = 0x4
+ AllPropertiesAreFinal = 0x1,
+ LookupsIncludeEnums = 0x2,
+ LookupsExcludeProperties = 0x4,
+ ResolveTypeInformationOnly = 0x8
};
+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;
@@ -1359,9 +1454,20 @@ static V4IR::Type resolveMetaObjectProperty(QQmlEnginePrivate *qmlEngine, V4IR::
if (QQmlPropertyData *candidate = metaObject->property(*member->name, /*object*/0, /*context*/0)) {
const bool isFinalProperty = (candidate->isFinal() || (resolver->flags & AllPropertiesAreFinal))
&& !candidate->isFunction();
+
+ if (lookupHints()
+ && !(resolver->flags & AllPropertiesAreFinal)
+ && !candidate->isFinal()
+ && !candidate->isFunction()
+ && candidate->isDirect()) {
+ qWarning() << "Hint: Access to property" << *member->name << "of" << metaObject->className() << "could be accelerated if it was marked as FINAL";
+ }
+
if (isFinalProperty && metaObject->isAllowedInRevision(candidate)) {
property = candidate;
- member->property = candidate; // Cache for next iteration and isel needs it.
+ member->inhibitTypeConversionOnWrite = true;
+ if (!(resolver->flags & ResolveTypeInformationOnly))
+ member->property = candidate; // Cache for next iteration and isel needs it.
}
}
}
@@ -1383,6 +1489,12 @@ static V4IR::Type resolveMetaObjectProperty(QQmlEnginePrivate *qmlEngine, V4IR::
initMetaObjectResolver(resolver, cache);
return V4IR::QObjectType;
}
+ } else if (QQmlValueType *valueType = QQmlValueTypeFactory::valueType(property->propType)) {
+ if (QQmlPropertyCache *cache = qmlEngine->cache(valueType->metaObject())) {
+ initMetaObjectResolver(resolver, cache);
+ resolver->flags |= ResolveTypeInformationOnly;
+ return V4IR::QObjectType;
+ }
}
break;
}
@@ -1397,6 +1509,7 @@ static void initMetaObjectResolver(V4IR::MemberExpressionResolver *resolver, QQm
resolver->resolveMember = &resolveMetaObjectProperty;
resolver->data = metaObject;
resolver->flags = 0;
+ resolver->isQObjectResolver = true;
}
void JSCodeGen::beginFunctionBodyHook()
@@ -1439,9 +1552,10 @@ V4IR::Expr *JSCodeGen::fallbackNameLookup(const QString &name, int line, int col
_function->idObjectDependencies.insert(mapping.idIndex);
V4IR::Expr *s = subscript(_block->TEMP(_idArrayTemp), _block->CONST(V4IR::SInt32Type, mapping.idIndex));
V4IR::Temp *result = _block->TEMP(_block->newTemp());
- initMetaObjectResolver(&result->memberResolver, mapping.type);
_block->MOVE(result, s);
result = _block->TEMP(result->index);
+ initMetaObjectResolver(&result->memberResolver, mapping.type);
+ result->memberResolver.flags |= AllPropertiesAreFinal;
result->isReadOnly = true; // don't allow use as lvalue
return result;
}
@@ -1453,35 +1567,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..59e8d02bbc 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,39 @@ 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)
+ // This is set for example for for QObject properties. All sorts of extra behavior
+ // is defined when writing to them, for example resettable properties are reset
+ // when writing undefined to them, and an exception is thrown when they're missing
+ // a reset function. And then there's also Qt.binding().
+ bool inhibitTypeConversionOnWrite: 1;
+
+ 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;
+ this->inhibitTypeConversionOnWrite = property != 0;
+ }
+
+ 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;
+ this->inhibitTypeConversionOnWrite = false;
}
virtual void accept(ExprVisitor *v) { v->visitMember(this); }
@@ -869,7 +895,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..249dfab660 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();
}
@@ -1904,12 +1906,8 @@ protected:
}
}
- // Don't convert when writing to QObject properties. All sorts of extra behavior
- // is defined when writing to them, for example resettable properties are reset
- // when writing undefined to them, and an exception is thrown when they're missing
- // a reset function.
const Member *targetMember = s->target->asMember();
- const bool inhibitConversion = targetMember && targetMember->property;
+ const bool inhibitConversion = targetMember && targetMember->inhibitTypeConversionOnWrite;
run(s->source, s->target->type, !inhibitConversion);
}
@@ -2514,14 +2512,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;
}
}
diff --git a/src/qml/debugger/qqmlprofilerservice.cpp b/src/qml/debugger/qqmlprofilerservice.cpp
index 0ba939cdca..b83de937c6 100644
--- a/src/qml/debugger/qqmlprofilerservice.cpp
+++ b/src/qml/debugger/qqmlprofilerservice.cpp
@@ -425,4 +425,204 @@ void QQmlProfilerService::messageReceived(const QByteArray &message)
m_initializeCondition.wakeAll();
}
+/*!
+ * \brief QQmlVmeProfiler::Data::clear Reset to defaults
+ * Reset the profiling data to defaults.
+ */
+void QQmlVmeProfiler::Data::clear()
+{
+ url = QUrl();
+ line = 0;
+ column = 0;
+ typeName = QString();
+}
+
+/*!
+ * \brief QQmlVmeProfiler::start Start profiler and set data
+ * \param url URL of file being executed
+ * \param line Curent line in file
+ * \param column Current column in file
+ * \param typeName Type of object be created
+ * Stops the profiler previously running in the foreground if there is one, then starts a
+ * new one and sets it up with the data given.
+ * Preconditions: Profiling must be enabled.
+ */
+void QQmlVmeProfiler::start(const QUrl &url, int line, int column, const QString &typeName)
+{
+ Q_ASSERT_X(enabled, Q_FUNC_INFO, "method called although profiler is not enabled.");
+ if (enabled) {
+ switchRange();
+ updateLocation(url, line, column);
+ updateTypeName(typeName);
+ }
+}
+
+/*!
+ * \brief QQmlVmeProfiler::start Start profiler without data
+ * Clears the current range data, then stops the profiler previously running in the
+ * foreground if any, then starts a new one.
+ * Preconditions: Profiling must be enabled.
+ */
+void QQmlVmeProfiler::start()
+{
+ Q_ASSERT_X(enabled, Q_FUNC_INFO, "method called although profiler is not enabled.");
+ if (enabled) {
+ currentRange.clear();
+ switchRange();
+ }
+}
+
+/*!
+ * \brief QQmlVmeProfiler::switchRange Switch foreground profilers
+ * Stops the current profiler if any, and starts a new one.
+ */
+void QQmlVmeProfiler::switchRange()
+{
+ if (running)
+ QQmlProfilerService::instance->endRange(QQmlProfilerService::Creating);
+ else
+ running = true;
+ QQmlProfilerService::instance->startRange(QQmlProfilerService::Creating);
+}
+
+/*!
+ * \brief QQmlVmeProfiler::updateLocation Update current location information
+ * \param url URL of file being executed
+ * \param line line Curent line in file
+ * \param column column Current column in file
+ * Updates the current profiler's location information.
+ * Preconditions: Profiling must be enabled and a profiler must be running in the foreground.
+ */
+void QQmlVmeProfiler::updateLocation(const QUrl &url, int line, int column)
+{
+ Q_ASSERT_X(enabled, Q_FUNC_INFO, "method called although profiler is not enabled.");
+ Q_ASSERT_X(running, Q_FUNC_INFO, "trying to update location on stopped profiler");
+ if (enabled && running) {
+ currentRange.url = url;
+ currentRange.line = line;
+ currentRange.column = column;
+ QQmlProfilerService::instance->rangeLocation(
+ QQmlProfilerService::Creating, url, line, column);
+ }
+}
+
+/*!
+ * \brief QQmlVmeProfiler::updateTypeName Update current type information
+ * \param typeName Type of object being created
+ * Updates the current profiler's type information.
+ * Preconditions: Profiling must be enabled and a profiler must be running in the foreground.
+ */
+void QQmlVmeProfiler::updateTypeName(const QString &typeName)
+{
+ Q_ASSERT_X(enabled, Q_FUNC_INFO, "method called although profiler is not enabled.");
+ Q_ASSERT_X(running, Q_FUNC_INFO, "trying to update typeName on stopped profiler");
+ if (enabled && running) {
+ currentRange.typeName = typeName;
+ QQmlProfilerService::instance->rangeData(QQmlProfilerService::Creating, typeName);
+ }
+}
+
+/*!
+ * \brief QQmlVmeProfiler::pop Pops a paused profiler from the stack and restarts it
+ * Stops the currently running profiler, if any, then retrieves an old one from the stack
+ * of paused profilers and starts that.
+ * Preconditions: Profiling must be enabled and there must be at least one profiler on the
+ * stack.
+ */
+void QQmlVmeProfiler::pop()
+{
+ Q_ASSERT_X(enabled, Q_FUNC_INFO, "method called although profiler is not enabled.");
+ Q_ASSERT_X(ranges.count() > 0, Q_FUNC_INFO, "trying to pop an invalid profiler");
+ if (enabled && ranges.count() > 0) {
+ start();
+ currentRange = ranges.pop();
+ QQmlProfilerService::instance->rangeLocation(
+ QQmlProfilerService::Creating, currentRange.url, currentRange.line, currentRange.column);
+ QQmlProfilerService::instance->rangeData(QQmlProfilerService::Creating, currentRange.typeName);
+ }
+}
+
+/*!
+ * \brief QQmlVmeProfiler::push Pushes the currently running profiler on the stack.
+ * Pushes the currently running profiler on the stack of paused profilers. Note: The profiler
+ * isn't paused here. That's a separate step. If it's never paused, but pop()'ed later that
+ * won't do any harm, though.
+ * Preconditions: Profiling must be enabled and a profiler must be running in the foreground.
+ */
+void QQmlVmeProfiler::push()
+{
+ Q_ASSERT_X(enabled, Q_FUNC_INFO, "method called although profiler is not enabled.");
+ Q_ASSERT_X(running, Q_FUNC_INFO, "trying to push stopped profiler");
+ if (enabled && running)
+ ranges.push(currentRange);
+}
+
+/*!
+ * \brief QQmlVmeProfiler::clear Stop all running profilers and clear all data.
+ * Stops the currently running (foreground and background) profilers and removes all saved
+ * data about paused profilers.
+ * Precondtions: Profiling must be enabled.
+ */
+void QQmlVmeProfiler::clear()
+{
+ Q_ASSERT_X(enabled, Q_FUNC_INFO, "method called although profiler is not enabled.");
+ if (enabled) {
+ stop();
+ ranges.clear();
+ for (int i = 0; i < backgroundRanges.count(); ++i) {
+ QQmlProfilerService::instance->endRange(QQmlProfilerService::Creating);
+ }
+ backgroundRanges.clear();
+ }
+}
+
+/*!
+ * \brief QQmlVmeProfiler::stop Stop profiler running in the foreground, if any.
+ * Precondition: Profiling must be enabled.
+ */
+void QQmlVmeProfiler::stop()
+{
+ Q_ASSERT_X(enabled, Q_FUNC_INFO, "method called although profiler is not enabled.");
+ if (enabled && running) {
+ QQmlProfilerService::instance->endRange(QQmlProfilerService::Creating);
+ currentRange.clear();
+ running = false;
+ }
+}
+
+/*!
+ * \brief QQmlVmeProfiler::background Push the current profiler to the background.
+ * Push the profiler currently running in the foreground to the background so that it
+ * won't be stopped by stop() or start(). There can be multiple profilers in the background.
+ * You can retrieve them in reverse order by calling foreground().
+ * Precondition: Profiling must be enabled and a profiler must be running in the foreground.
+ */
+void QQmlVmeProfiler::background()
+{
+ Q_ASSERT_X(enabled, Q_FUNC_INFO, "method called although profiler is not enabled.");
+ Q_ASSERT_X(running, Q_FUNC_INFO, "trying to push stopped profiler to the background.");
+ if (enabled && running) {
+ backgroundRanges.push(currentRange);
+ running = false;
+ }
+}
+
+/*!
+ * \brief QQmlVmeProfiler::foreground Retrieve a profiler from the background
+ * Stop the profiler currently running in the foreground, if any and put the next profiler
+ * from the background in its place.
+ * Preconditions: Profiling must be enabled and there must be at least one profiler in the
+ * background.
+ */
+void QQmlVmeProfiler::foreground()
+{
+ Q_ASSERT_X(enabled, Q_FUNC_INFO, "method called although profiler is not enabled.");
+ Q_ASSERT_X(backgroundRanges.count() > 0, Q_FUNC_INFO, "trying to foreground stopped profiler.");
+ if (enabled && backgroundRanges.count() > 0) {
+ stop();
+ currentRange = backgroundRanges.pop();
+ running = true;
+ }
+}
+
QT_END_NAMESPACE
diff --git a/src/qml/debugger/qqmlprofilerservice_p.h b/src/qml/debugger/qqmlprofilerservice_p.h
index fb08a30c6a..c2e9eb421a 100644
--- a/src/qml/debugger/qqmlprofilerservice_p.h
+++ b/src/qml/debugger/qqmlprofilerservice_p.h
@@ -225,7 +225,7 @@ private:
friend struct QQmlBindingProfiler;
friend struct QQmlHandlingSignalProfiler;
- friend struct QQmlObjectCreatingProfiler;
+ friend struct QQmlVmeProfiler;
friend struct QQmlCompilingProfiler;
friend struct QQmlPixmapProfiler;
};
@@ -277,40 +277,6 @@ struct QQmlHandlingSignalProfiler {
bool enabled;
};
-struct QQmlObjectCreatingProfiler {
- QQmlObjectCreatingProfiler()
- {
- enabled = QQmlProfilerService::instance
- ? QQmlProfilerService::instance->profilingEnabled() : false;
- if (enabled) {
- QQmlProfilerService *service = QQmlProfilerService::instance;
- service->startRange(QQmlProfilerService::Creating);
- }
- }
-
- void setTypeName(const QString &typeName)
- {
- Q_ASSERT_X(enabled, Q_FUNC_INFO, "method called although profiler is not enabled.");
- QQmlProfilerService::instance->rangeData(QQmlProfilerService::Creating, typeName);
- }
-
- void setLocation(const QUrl &url, int line, int column)
- {
- Q_ASSERT_X(enabled, Q_FUNC_INFO, "method called although profiler is not enabled.");
- if (enabled)
- QQmlProfilerService::instance->rangeLocation(
- QQmlProfilerService::Creating, url, line, column);
- }
-
- ~QQmlObjectCreatingProfiler()
- {
- if (enabled)
- QQmlProfilerService::instance->endRange(QQmlProfilerService::Creating);
- }
-
- bool enabled;
-};
-
struct QQmlCompilingProfiler {
QQmlCompilingProfiler(const QString &name)
{
@@ -333,6 +299,54 @@ struct QQmlCompilingProfiler {
bool enabled;
};
+struct QQmlVmeProfiler {
+public:
+ const bool enabled;
+
+ struct Data {
+ Data() : line(0), column(0) {}
+ QUrl url;
+ int line;
+ int column;
+ QString typeName;
+ void clear();
+ };
+
+ QQmlVmeProfiler() :
+ enabled(QQmlProfilerService::instance ? QQmlProfilerService::instance->profilingEnabled() : false),
+ running(false)
+ {}
+
+ ~QQmlVmeProfiler()
+ {
+ if (enabled)
+ clear();
+ }
+
+ void clear();
+
+ void start(const QUrl &url, int line, int column, const QString &typeName);
+ void start();
+ void stop();
+
+ void updateLocation(const QUrl &url, int line, int column);
+ void updateTypeName(const QString &typeName);
+
+ void pop();
+ void push();
+
+ void background();
+ void foreground();
+
+private:
+ void switchRange();
+
+ Data currentRange;
+ QStack<Data> ranges;
+ QStack<Data> backgroundRanges;
+ bool running;
+};
+
struct QQmlPixmapProfiler {
QQmlPixmapProfiler() {
QQmlProfilerService *instance = QQmlProfilerService::instance;
diff --git a/src/qml/jsruntime/qv4object.cpp b/src/qml/jsruntime/qv4object.cpp
index e4df95716d..743d35fa69 100644
--- a/src/qml/jsruntime/qv4object.cpp
+++ b/src/qml/jsruntime/qv4object.cpp
@@ -1262,13 +1262,9 @@ void Object::arraySort(ExecutionContext *context, ObjectRef thisObject, const Va
ArrayElementLessThan lessThan(context, thisObject, comparefn);
+ if (!len)
+ return;
Property *begin = arrayData;
- // We deliberately choose qSort over std::sort here, because with
- // MSVC in debug builds, std::sort has an ASSERT() that verifies
- // that the return values of lessThan are perfectly consistent
- // and aborts otherwise. We do not want JavaScript to easily crash
- // the entire application and therefore choose qSort, which doesn't
- // have this property.
std::sort(begin, begin + len, lessThan);
}
diff --git a/src/qml/jsruntime/qv4qobjectwrapper.cpp b/src/qml/jsruntime/qv4qobjectwrapper.cpp
index f1b0e0bdc4..85e6878f7b 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper.cpp
+++ b/src/qml/jsruntime/qv4qobjectwrapper.cpp
@@ -331,23 +331,23 @@ ReturnedValue QObjectWrapper::getQmlProperty(ExecutionContext *ctx, QQmlContextD
if (hasProperty)
*hasProperty = true;
- return getProperty(ctx, result);
+ return getProperty(m_object, ctx, result);
}
-ReturnedValue QObjectWrapper::getProperty(ExecutionContext *ctx, QQmlPropertyData *property, bool captureRequired)
+ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx, QQmlPropertyData *property, bool captureRequired)
{
QV4::Scope scope(ctx);
if (property->isFunction() && !property->isVarProperty()) {
if (property->isVMEFunction()) {
- QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(m_object);
+ QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmemo);
return vmemo->vmeMethod(property->coreIndex);
} else if (property->isV4Function()) {
QV4::Scoped<QV4::Object> qmlcontextobject(scope, ctx->engine->qmlContextObject());
- return QV4::QObjectMethod::create(ctx->engine->rootContext, m_object, property->coreIndex, qmlcontextobject);
+ return QV4::QObjectMethod::create(ctx->engine->rootContext, object, property->coreIndex, qmlcontextobject);
} else if (property->isSignalHandler()) {
- QV4::Scoped<QV4::QmlSignalHandler> handler(scope, new (ctx->engine->memoryManager) QV4::QmlSignalHandler(ctx->engine, m_object, property->coreIndex));
+ QV4::Scoped<QV4::QmlSignalHandler> handler(scope, new (ctx->engine->memoryManager) QV4::QmlSignalHandler(ctx->engine, object, property->coreIndex));
QV4::ScopedString connect(scope, ctx->engine->newIdentifier(QStringLiteral("connect")));
QV4::ScopedString disconnect(scope, ctx->engine->newIdentifier(QStringLiteral("disconnect")));
@@ -356,7 +356,7 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionContext *ctx, QQmlPropertyDat
return handler.asReturnedValue();
} else {
- return QV4::QObjectMethod::create(ctx->engine->rootContext, m_object, property->coreIndex);
+ return QV4::QObjectMethod::create(ctx->engine->rootContext, object, property->coreIndex);
}
}
@@ -369,14 +369,14 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionContext *ctx, QQmlPropertyDat
if (ep && ep->propertyCapture && property->accessors->notifier)
nptr = &n;
- QV4::ScopedValue rv(scope, LoadProperty<ReadAccessor::Accessor>(ctx->engine->v8Engine, m_object, *property, nptr));
+ QV4::ScopedValue rv(scope, LoadProperty<ReadAccessor::Accessor>(ctx->engine->v8Engine, object, *property, nptr));
if (captureRequired) {
if (property->accessors->notifier) {
if (n)
ep->captureProperty(n);
} else {
- ep->captureProperty(m_object, property->coreIndex, property->notifyIndex);
+ ep->captureProperty(object, property->coreIndex, property->notifyIndex);
}
}
@@ -384,16 +384,16 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionContext *ctx, QQmlPropertyDat
}
if (captureRequired && ep && !property->isConstant())
- ep->captureProperty(m_object, property->coreIndex, property->notifyIndex);
+ ep->captureProperty(object, property->coreIndex, property->notifyIndex);
if (property->isVarProperty()) {
- QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(m_object);
+ QQmlVMEMetaObject *vmemo = QQmlVMEMetaObject::get(object);
Q_ASSERT(vmemo);
return vmemo->vmeProperty(property->coreIndex);
} else if (property->isDirect()) {
- return LoadProperty<ReadAccessor::Direct>(ctx->engine->v8Engine, m_object, *property, 0);
+ return LoadProperty<ReadAccessor::Direct>(ctx->engine->v8Engine, object, *property, 0);
} else {
- return LoadProperty<ReadAccessor::Indirect>(ctx->engine->v8Engine, m_object, *property, 0);
+ return LoadProperty<ReadAccessor::Indirect>(ctx->engine->v8Engine, object, *property, 0);
}
}
@@ -583,7 +583,7 @@ ReturnedValue QObjectWrapper::wrap(ExecutionEngine *engine, QObject *object)
ddata->jsEngineId == 0 || // No one owns the QObject
!ddata->hasTaintedV8Object)) { // Someone else has used the QObject, but it isn't tainted
- QV4::ScopedValue rv(scope, create(engine, ddata, object));
+ QV4::ScopedValue rv(scope, create(engine, object));
ddata->jsWrapper = rv;
ddata->jsEngineId = engine->m_engineId;
return rv.asReturnedValue();
@@ -598,14 +598,14 @@ ReturnedValue QObjectWrapper::wrap(ExecutionEngine *engine, QObject *object)
// If our tainted handle doesn't exist or has been collected, and there isn't
// a handle in the ddata, we can assume ownership of the ddata->v8object
if (ddata->jsWrapper.isUndefined() && !alternateWrapper) {
- QV4::ScopedValue result(scope, create(engine, ddata, object));
+ QV4::ScopedValue result(scope, create(engine, object));
ddata->jsWrapper = result;
ddata->jsEngineId = engine->m_engineId;
return result.asReturnedValue();
}
if (!alternateWrapper) {
- alternateWrapper = create(engine, ddata, object);
+ alternateWrapper = create(engine, object);
if (!engine->m_multiplyWrappedQObjects)
engine->m_multiplyWrappedQObjects = new MultiplyWrappedQObjectMap;
engine->m_multiplyWrappedQObjects->insert(object, alternateWrapper.getPointer());
@@ -616,11 +616,11 @@ ReturnedValue QObjectWrapper::wrap(ExecutionEngine *engine, QObject *object)
}
}
-ReturnedValue QObjectWrapper::getProperty(ExecutionContext *ctx, int propertyIndex, bool captureRequired)
+ReturnedValue QObjectWrapper::getProperty(QObject *object, ExecutionContext *ctx, int propertyIndex, bool captureRequired)
{
- if (QQmlData::wasDeleted(m_object))
+ if (QQmlData::wasDeleted(object))
return QV4::Encode::null();
- QQmlData *ddata = QQmlData::get(m_object, /*create*/false);
+ QQmlData *ddata = QQmlData::get(object, /*create*/false);
if (!ddata)
return QV4::Encode::undefined();
@@ -628,7 +628,7 @@ ReturnedValue QObjectWrapper::getProperty(ExecutionContext *ctx, int propertyInd
Q_ASSERT(cache);
QQmlPropertyData *property = cache->property(propertyIndex);
Q_ASSERT(property); // We resolved this property earlier, so it better exist!
- return getProperty(ctx, property, captureRequired);
+ return getProperty(object, ctx, property, captureRequired);
}
void QObjectWrapper::setProperty(ExecutionContext *ctx, int propertyIndex, const ValueRef value)
@@ -655,14 +655,11 @@ bool QObjectWrapper::isEqualTo(Managed *a, Managed *b)
return false;
}
-ReturnedValue QObjectWrapper::create(ExecutionEngine *engine, QQmlData *ddata, QObject *object)
+ReturnedValue QObjectWrapper::create(ExecutionEngine *engine, QObject *object)
{
QQmlEngine *qmlEngine = engine->v8Engine->engine();
- if (!ddata->propertyCache && qmlEngine) {
- ddata->propertyCache = QQmlEnginePrivate::get(qmlEngine)->cache(object);
- if (ddata->propertyCache) ddata->propertyCache->addref();
- }
-
+ if (qmlEngine)
+ QQmlData::ensurePropertyCache(qmlEngine, object);
return (new (engine->memoryManager) QV4::QObjectWrapper(engine, object))->asReturnedValue();
}
@@ -851,7 +848,7 @@ ReturnedValue QObjectWrapper::method_connect(CallContext *ctx)
QPair<QObject *, int> signalInfo = extractQtSignal(ctx->callData->thisObject);
QObject *signalObject = signalInfo.first;
- int signalIndex = signalInfo.second;
+ int signalIndex = signalInfo.second; // in method range, not signal range!
if (signalIndex < 0)
V4THROW_ERROR("Function.prototype.connect: this object is not a signal");
@@ -885,6 +882,11 @@ ReturnedValue QObjectWrapper::method_connect(CallContext *ctx)
slot->thisObject = thisObject;
slot->function = f;
+ if (QQmlData *ddata = QQmlData::get(signalObject)) {
+ if (QQmlPropertyCache *propertyCache = ddata->propertyCache) {
+ QQmlPropertyPrivate::flushSignal(signalObject, propertyCache->methodIndexToSignalIndex(signalIndex));
+ }
+ }
QObjectPrivate::connect(signalObject, signalIndex, slot, Qt::AutoConnection);
return Encode::undefined();
diff --git a/src/qml/jsruntime/qv4qobjectwrapper_p.h b/src/qml/jsruntime/qv4qobjectwrapper_p.h
index a73c96d098..07de1933c5 100644
--- a/src/qml/jsruntime/qv4qobjectwrapper_p.h
+++ b/src/qml/jsruntime/qv4qobjectwrapper_p.h
@@ -94,17 +94,17 @@ struct Q_QML_EXPORT QObjectWrapper : public QV4::Object
using Object::get;
- ReturnedValue getProperty(ExecutionContext *ctx, int propertyIndex, bool captureRequired);
+ static ReturnedValue getProperty(QObject *object, ExecutionContext *ctx, int propertyIndex, bool captureRequired);
void setProperty(ExecutionContext *ctx, int propertyIndex, const ValueRef value);
protected:
static bool isEqualTo(Managed *that, Managed *o);
private:
- ReturnedValue getProperty(ExecutionContext *ctx, QQmlPropertyData *property, bool captureRequired = true);
+ static ReturnedValue getProperty(QObject *object, ExecutionContext *ctx, QQmlPropertyData *property, bool captureRequired = true);
static void setProperty(QObject *object, ExecutionContext *ctx, QQmlPropertyData *property, const ValueRef value);
- static ReturnedValue create(ExecutionEngine *engine, QQmlData *ddata, QObject *object);
+ static ReturnedValue create(ExecutionEngine *engine, QObject *object);
QObjectWrapper(ExecutionEngine *engine, QObject *object);
diff --git a/src/qml/jsruntime/qv4runtime.cpp b/src/qml/jsruntime/qv4runtime.cpp
index a5a93e1f84..50fea04b2f 100644
--- a/src/qml/jsruntime/qv4runtime.cpp
+++ b/src/qml/jsruntime/qv4runtime.cpp
@@ -53,6 +53,7 @@
#include "qv4scopedvalue_p.h"
#include <private/qqmlcontextwrapper_p.h>
#include "qv4qobjectwrapper_p.h"
+#include <private/qv8engine_p.h>
#include <QtCore/qmath.h>
#include <QtCore/qnumeric.h>
@@ -1268,7 +1269,19 @@ ReturnedValue __qmljs_get_qobject_property(ExecutionContext *ctx, const ValueRef
ctx->throwTypeError(QStringLiteral("Cannot read property of null"));
return Encode::undefined();
}
- return wrapper->getProperty(ctx, propertyIndex, captureRequired);
+ return QV4::QObjectWrapper::getProperty(wrapper->object(), ctx, propertyIndex, captureRequired);
+}
+
+QV4::ReturnedValue __qmljs_get_attached_property(ExecutionContext *ctx, int attachedPropertiesId, int propertyIndex)
+{
+ Scope scope(ctx);
+ QV4::Scoped<QmlContextWrapper> c(scope, ctx->engine->qmlContextObject()->getPointer()->as<QmlContextWrapper>());
+ QObject *scopeObject = c->getScopeObject();
+ QObject *attachedObject = qmlAttachedPropertiesObjectById(attachedPropertiesId, scopeObject);
+
+ QQmlEngine *qmlEngine = ctx->engine->v8Engine->engine();
+ QQmlData::ensurePropertyCache(qmlEngine, attachedObject);
+ return QV4::QObjectWrapper::getProperty(attachedObject, ctx, propertyIndex, /*captureRequired*/true);
}
void __qmljs_set_qobject_property(ExecutionContext *ctx, const ValueRef object, int propertyIndex, const ValueRef value)
diff --git a/src/qml/jsruntime/qv4runtime_p.h b/src/qml/jsruntime/qv4runtime_p.h
index da596b180c..9524b2459c 100644
--- a/src/qml/jsruntime/qv4runtime_p.h
+++ b/src/qml/jsruntime/qv4runtime_p.h
@@ -176,6 +176,7 @@ QV4::ReturnedValue __qmljs_get_imported_scripts(NoThrowContext *ctx);
QV4::ReturnedValue __qmljs_get_context_object(NoThrowContext *ctx);
QV4::ReturnedValue __qmljs_get_scope_object(NoThrowContext *ctx);
QV4::ReturnedValue __qmljs_get_qobject_property(ExecutionContext *ctx, const ValueRef object, int propertyIndex, bool captureRequired);
+QV4::ReturnedValue __qmljs_get_attached_property(ExecutionContext *ctx, int attachedPropertiesId, int propertyIndex);
void __qmljs_set_qobject_property(ExecutionContext *ctx, const ValueRef object, int propertyIndex, const ValueRef value);
QV4::ReturnedValue __qmljs_get_qml_singleton(NoThrowContext *ctx, const QV4::StringRef name);
diff --git a/src/qml/jsruntime/qv4vme_moth.cpp b/src/qml/jsruntime/qv4vme_moth.cpp
index 00672fea0f..9d6540ebe9 100644
--- a/src/qml/jsruntime/qv4vme_moth.cpp
+++ b/src/qml/jsruntime/qv4vme_moth.cpp
@@ -320,6 +320,10 @@ QV4::ReturnedValue VME::run(QV4::ExecutionContext *context, const uchar *code,
STOREVALUE(instr.result, __qmljs_get_qobject_property(context, VALUEPTR(instr.base), instr.propertyIndex, instr.captureRequired));
MOTH_END_INSTR(LoadQObjectProperty)
+ MOTH_BEGIN_INSTR(LoadAttachedQObjectProperty)
+ STOREVALUE(instr.result, __qmljs_get_attached_property(context, instr.attachedPropertiesId, instr.propertyIndex));
+ MOTH_END_INSTR(LoadAttachedQObjectProperty)
+
MOTH_BEGIN_INSTR(Push)
TRACE(inline, "stack size: %u", instr.value);
stackSize = instr.value;
diff --git a/src/qml/qml/qqmlcompiler_p.h b/src/qml/qml/qqmlcompiler_p.h
index 3ca4566e41..05c877d98b 100644
--- a/src/qml/qml/qqmlcompiler_p.h
+++ b/src/qml/qml/qqmlcompiler_p.h
@@ -169,7 +169,7 @@ public:
int addInstruction(const QQmlInstructionData<Instr> &data)
{
QQmlInstruction genericInstr;
- QQmlInstructionMeta<Instr>::setData(genericInstr, data);
+ QQmlInstructionMeta<Instr>::setDataNoCommon(genericInstr, data);
return addInstructionHelper(static_cast<QQmlInstruction::Type>(Instr), genericInstr);
}
int nextInstructionIndex();
diff --git a/src/qml/qml/qqmlcomponent.cpp b/src/qml/qml/qqmlcomponent.cpp
index 2973944215..ae246f5cd4 100644
--- a/src/qml/qml/qqmlcomponent.cpp
+++ b/src/qml/qml/qqmlcomponent.cpp
@@ -52,7 +52,6 @@
#include "qqmlbinding_p.h"
#include "qqmlglobal_p.h"
#include "qqmlscript_p.h"
-#include <private/qqmlprofilerservice_p.h>
#include <private/qqmlenginedebugservice_p.h>
#include "qqmlincubator.h"
#include "qqmlincubator_p.h"
@@ -884,11 +883,6 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
QQmlEnginePrivate *enginePriv = QQmlEnginePrivate::get(engine);
- if (enginePriv->inProgressCreations == 0) {
- // only track root, since further ones might not be properly nested
- profiler = new QQmlObjectCreatingProfiler();
- }
-
enginePriv->inProgressCreations++;
state.errors.clear();
state.completePending = true;
@@ -924,13 +918,6 @@ QQmlComponentPrivate::beginCreate(QQmlContextData *context)
if (!context->isInternal)
context->asQQmlContextPrivate()->instances.append(rv);
QQmlEngineDebugService::instance()->objectCreated(engine, rv);
-
- if (profiler && profiler->enabled) {
- profiler->setTypeName(buildTypeNameForDebug(rv->metaObject()));
- QQmlData *data = QQmlData::get(rv);
- Q_ASSERT(data);
- profiler->setLocation(cc->url, data->lineNumber, data->columnNumber);
- }
}
return rv;
@@ -995,9 +982,6 @@ void QQmlComponentPrivate::completeCreate()
if (state.completePending) {
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(engine);
complete(ep, &state);
-
- delete profiler;
- profiler = 0;
}
if (depthIncreased) {
diff --git a/src/qml/qml/qqmlcomponent_p.h b/src/qml/qml/qqmlcomponent_p.h
index d9a2427cd5..8bf4005dd6 100644
--- a/src/qml/qml/qqmlcomponent_p.h
+++ b/src/qml/qml/qqmlcomponent_p.h
@@ -61,7 +61,6 @@
#include "qqmlvme_p.h"
#include "qqmlerror.h"
#include "qqml.h"
-#include <private/qqmlprofilerservice_p.h>
#include <private/qqmlobjectcreator_p.h>
#include <QtCore/QString>
@@ -85,7 +84,7 @@ class Q_QML_PRIVATE_EXPORT QQmlComponentPrivate : public QObjectPrivate, public
public:
QQmlComponentPrivate()
- : typeData(0), progress(0.), start(-1), cc(0), engine(0), creationContext(0), profiler(0), depthIncreased(false) {}
+ : typeData(0), progress(0.), start(-1), cc(0), engine(0), creationContext(0), depthIncreased(false) {}
void loadUrl(const QUrl &newUrl, QQmlComponent::CompilationMode mode = QQmlComponent::PreferSynchronous);
@@ -131,7 +130,6 @@ public:
QQmlEngine *engine;
QQmlGuardedContextData creationContext;
- QQmlObjectCreatingProfiler *profiler;
bool depthIncreased;
void clear();
diff --git a/src/qml/qml/qqmlcontextwrapper.cpp b/src/qml/qml/qqmlcontextwrapper.cpp
index 0b3b282061..54b540bb4c 100644
--- a/src/qml/qml/qqmlcontextwrapper.cpp
+++ b/src/qml/qml/qqmlcontextwrapper.cpp
@@ -53,6 +53,7 @@
#include <private/qv4compileddata_p.h>
#include <private/qqmltypewrapper_p.h>
#include <private/qqmllistwrapper_p.h>
+#include <private/qjsvalue_p.h>
QT_BEGIN_NAMESPACE
@@ -427,8 +428,9 @@ ReturnedValue QmlContextWrapper::qmlSingletonWrapper(const StringRef &name)
QQmlType::SingletonInstanceInfo *siinfo = r.type->singletonInstanceInfo();
siinfo->init(e);
- QObject *qobjectSingleton = siinfo->qobjectApi(e);
- return QV4::QObjectWrapper::wrap(engine(), qobjectSingleton);
+ if (QObject *qobjectSingleton = siinfo->qobjectApi(e))
+ return QV4::QObjectWrapper::wrap(engine(), qobjectSingleton);
+ return QJSValuePrivate::get(siinfo->scriptApi(e))->getValue(engine());
}
DEFINE_MANAGED_VTABLE(QQmlIdObjectsArray);
diff --git a/src/qml/qml/qqmldata_p.h b/src/qml/qml/qqmldata_p.h
index 621b3d3c2e..982156ea15 100644
--- a/src/qml/qml/qqmldata_p.h
+++ b/src/qml/qml/qqmldata_p.h
@@ -61,6 +61,7 @@
QT_BEGIN_NAMESPACE
template <class Key, class T> class QHash;
+class QQmlEngine;
class QQmlGuardImpl;
class QQmlCompiledData;
class QQmlAbstractBinding;
@@ -222,6 +223,8 @@ public:
static inline void flushPendingBinding(QObject *, int coreIndex);
+ static void ensurePropertyCache(QQmlEngine *engine, QObject *object);
+
private:
// For attachedProperties
mutable QQmlDataExtended *extendedData;
diff --git a/src/qml/qml/qqmlengine.cpp b/src/qml/qml/qqmlengine.cpp
index 1eec710c84..1f45cba732 100644
--- a/src/qml/qml/qqmlengine.cpp
+++ b/src/qml/qml/qqmlengine.cpp
@@ -1339,14 +1339,6 @@ void qmlExecuteDeferred(QObject *object)
QQmlData *data = QQmlData::get(object);
if (data && data->deferredData && !data->wasDeleted(object)) {
- QQmlObjectCreatingProfiler prof;
- if (prof.enabled) {
- QQmlType *type = QQmlMetaType::qmlType(object->metaObject());
- prof.setTypeName(type ? type->qmlTypeName()
- : QString::fromUtf8(object->metaObject()->className()));
- if (data->outerContext)
- prof.setLocation(data->outerContext->url, data->lineNumber, data->columnNumber);
- }
QQmlEnginePrivate *ep = QQmlEnginePrivate::get(data->context->engine);
QQmlComponentPrivate::ConstructionState state;
@@ -1734,6 +1726,16 @@ void QQmlData::setPendingBindingBit(QObject *obj, int coreIndex)
QQmlData_setBit(this, obj, coreIndex * 2 + 1);
}
+void QQmlData::ensurePropertyCache(QQmlEngine *engine, QObject *object)
+{
+ Q_ASSERT(engine);
+ QQmlData *ddata = QQmlData::get(object, /*create*/true);
+ if (ddata->propertyCache)
+ return;
+ ddata->propertyCache = QQmlEnginePrivate::get(engine)->cache(object);
+ if (ddata->propertyCache) ddata->propertyCache->addref();
+}
+
void QQmlEnginePrivate::sendQuit()
{
Q_Q(QQmlEngine);
diff --git a/src/qml/qml/qqmlinstruction_p.h b/src/qml/qml/qqmlinstruction_p.h
index 150ee8df19..bda8c3db0d 100644
--- a/src/qml/qml/qqmlinstruction_p.h
+++ b/src/qml/qml/qqmlinstruction_p.h
@@ -536,7 +536,11 @@ struct QQmlInstructionMeta {
typedef QQmlInstruction::instr_##FMT DataType; \
static const DataType &data(const QQmlInstruction &instr) { return instr.FMT; } \
static void setData(QQmlInstruction &instr, const DataType &v) { memcpy(&instr.FMT, &v, Size); } \
- };
+ static void setDataNoCommon(QQmlInstruction &instr, const DataType &v) \
+ { memcpy(reinterpret_cast<char *>(&instr.FMT) + sizeof(QQmlInstruction::instr_common), \
+ reinterpret_cast<const char *>(&v) + sizeof(QQmlInstruction::instr_common), \
+ Size - sizeof(QQmlInstruction::instr_common)); } \
+ };
FOR_EACH_QML_INSTR(QML_INSTR_META_TEMPLATE);
#undef QML_INSTR_META_TEMPLATE
diff --git a/src/qml/qml/qqmlvaluetype_p.h b/src/qml/qml/qqmlvaluetype_p.h
index c55b86b55a..bd44dfb0cf 100644
--- a/src/qml/qml/qqmlvaluetype_p.h
+++ b/src/qml/qml/qqmlvaluetype_p.h
@@ -169,8 +169,8 @@ public:
class Q_QML_PRIVATE_EXPORT QQmlPointFValueType : public QQmlValueTypeBase<QPointF>
{
- Q_PROPERTY(qreal x READ x WRITE setX)
- Q_PROPERTY(qreal y READ y WRITE setY)
+ Q_PROPERTY(qreal x READ x WRITE setX FINAL)
+ Q_PROPERTY(qreal y READ y WRITE setY FINAL)
Q_OBJECT
public:
QQmlPointFValueType(QObject *parent = 0);
@@ -185,8 +185,8 @@ public:
class Q_QML_PRIVATE_EXPORT QQmlPointValueType : public QQmlValueTypeBase<QPoint>
{
- Q_PROPERTY(int x READ x WRITE setX)
- Q_PROPERTY(int y READ y WRITE setY)
+ Q_PROPERTY(int x READ x WRITE setX FINAL)
+ Q_PROPERTY(int y READ y WRITE setY FINAL)
Q_OBJECT
public:
QQmlPointValueType(QObject *parent = 0);
@@ -201,8 +201,8 @@ public:
class Q_QML_PRIVATE_EXPORT QQmlSizeFValueType : public QQmlValueTypeBase<QSizeF>
{
- Q_PROPERTY(qreal width READ width WRITE setWidth)
- Q_PROPERTY(qreal height READ height WRITE setHeight)
+ Q_PROPERTY(qreal width READ width WRITE setWidth FINAL)
+ Q_PROPERTY(qreal height READ height WRITE setHeight FINAL)
Q_OBJECT
public:
QQmlSizeFValueType(QObject *parent = 0);
@@ -217,8 +217,8 @@ public:
class Q_QML_PRIVATE_EXPORT QQmlSizeValueType : public QQmlValueTypeBase<QSize>
{
- Q_PROPERTY(int width READ width WRITE setWidth)
- Q_PROPERTY(int height READ height WRITE setHeight)
+ Q_PROPERTY(int width READ width WRITE setWidth FINAL)
+ Q_PROPERTY(int height READ height WRITE setHeight FINAL)
Q_OBJECT
public:
QQmlSizeValueType(QObject *parent = 0);
@@ -233,10 +233,10 @@ public:
class Q_QML_PRIVATE_EXPORT QQmlRectFValueType : public QQmlValueTypeBase<QRectF>
{
- Q_PROPERTY(qreal x READ x WRITE setX)
- Q_PROPERTY(qreal y READ y WRITE setY)
- Q_PROPERTY(qreal width READ width WRITE setWidth)
- Q_PROPERTY(qreal height READ height WRITE setHeight)
+ Q_PROPERTY(qreal x READ x WRITE setX FINAL)
+ Q_PROPERTY(qreal y READ y WRITE setY FINAL)
+ Q_PROPERTY(qreal width READ width WRITE setWidth FINAL)
+ Q_PROPERTY(qreal height READ height WRITE setHeight FINAL)
Q_OBJECT
public:
QQmlRectFValueType(QObject *parent = 0);
@@ -256,10 +256,10 @@ public:
class Q_QML_PRIVATE_EXPORT QQmlRectValueType : public QQmlValueTypeBase<QRect>
{
- Q_PROPERTY(int x READ x WRITE setX)
- Q_PROPERTY(int y READ y WRITE setY)
- Q_PROPERTY(int width READ width WRITE setWidth)
- Q_PROPERTY(int height READ height WRITE setHeight)
+ Q_PROPERTY(int x READ x WRITE setX FINAL)
+ Q_PROPERTY(int y READ y WRITE setY FINAL)
+ Q_PROPERTY(int width READ width WRITE setWidth FINAL)
+ Q_PROPERTY(int height READ height WRITE setHeight FINAL)
Q_OBJECT
public:
QQmlRectValueType(QObject *parent = 0);
@@ -282,11 +282,11 @@ class Q_QML_PRIVATE_EXPORT QQmlEasingValueType : public QQmlValueTypeBase<QEasin
Q_OBJECT
Q_ENUMS(Type)
- Q_PROPERTY(QQmlEasingValueType::Type type READ type WRITE setType)
- Q_PROPERTY(qreal amplitude READ amplitude WRITE setAmplitude)
- Q_PROPERTY(qreal overshoot READ overshoot WRITE setOvershoot)
- Q_PROPERTY(qreal period READ period WRITE setPeriod)
- Q_PROPERTY(QVariantList bezierCurve READ bezierCurve WRITE setBezierCurve)
+ Q_PROPERTY(QQmlEasingValueType::Type type READ type WRITE setType FINAL)
+ Q_PROPERTY(qreal amplitude READ amplitude WRITE setAmplitude FINAL)
+ Q_PROPERTY(qreal overshoot READ overshoot WRITE setOvershoot FINAL)
+ Q_PROPERTY(qreal period READ period WRITE setPeriod FINAL)
+ Q_PROPERTY(QVariantList bezierCurve READ bezierCurve WRITE setBezierCurve FINAL)
public:
enum Type {
Linear = QEasingCurve::Linear,
diff --git a/src/qml/qml/qqmlvme.cpp b/src/qml/qml/qqmlvme.cpp
index 983136a846..ad1e9d862e 100644
--- a/src/qml/qml/qqmlvme.cpp
+++ b/src/qml/qml/qqmlvme.cpp
@@ -503,6 +503,12 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
const QQmlCompiledData::TypeReference &type = TYPES.at(instr.type);
Q_ASSERT(type.component);
+ if (profiler.enabled) {
+ profiler.start();
+ profiler.updateTypeName(type.component->name);
+ profiler.background();
+ }
+
states.push(State());
State *cState = &states[states.count() - 2];
@@ -524,6 +530,11 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QML_END_INSTR(CreateQMLObject)
QML_BEGIN_INSTR(CompleteQMLObject)
+ if (profiler.enabled) {
+ profiler.foreground();
+ profiler.updateLocation(CTXT->url, instr.line, instr.column);
+ }
+
QObject *o = objects.top();
Q_ASSERT(o);
@@ -566,6 +577,8 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QML_BEGIN_INSTR(CreateCppObject)
const QQmlCompiledData::TypeReference &type = TYPES.at(instr.type);
Q_ASSERT(type.type);
+ if (profiler.enabled)
+ profiler.start(CTXT->url, instr.line, instr.column, type.type->qmlTypeName());
QObject *o = 0;
void *memory = 0;
@@ -637,12 +650,14 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QML_END_INSTR(CreateCppObject)
QML_BEGIN_INSTR(CreateSimpleObject)
+ const QQmlCompiledData::TypeReference &ref = TYPES.at(instr.type);
+ if (profiler.enabled)
+ profiler.start(CTXT->url, instr.line, instr.column, ref.type->qmlTypeName());
QObject *o = (QObject *)operator new(instr.typeSize + sizeof(QQmlData));
::memset(static_cast<void *>(o), 0, instr.typeSize + sizeof(QQmlData));
instr.create(o);
QQmlData *ddata = (QQmlData *)(((const char *)o) + instr.typeSize);
- const QQmlCompiledData::TypeReference &ref = TYPES.at(instr.type);
if (!ddata->propertyCache && ref.typePropertyCache) {
ddata->propertyCache = ref.typePropertyCache;
ddata->propertyCache->addref();
@@ -817,6 +832,8 @@ QObject *QQmlVME::run(QList<QQmlError> *errors,
QML_END_INSTR(StoreScriptString)
QML_BEGIN_INSTR(BeginObject)
+ if (profiler.enabled)
+ profiler.push();
QObject *target = objects.top();
QQmlParserStatus *status = reinterpret_cast<QQmlParserStatus *>(reinterpret_cast<char *>(target) + instr.castValue);
parserStatus.push(status);
@@ -1074,6 +1091,8 @@ normalExit:
objects.deallocate();
lists.deallocate();
states.clear();
+ if (profiler.enabled)
+ profiler.stop();
return rv;
}
@@ -1111,6 +1130,8 @@ void QQmlVME::reset()
states.clear();
rootContext = 0;
creationContext = 0;
+ if (profiler.enabled)
+ profiler.clear();
}
#ifdef QML_THREADED_VME_INTERPRETER
@@ -1170,6 +1191,8 @@ QQmlContextData *QQmlVME::complete(const Interrupt &interrupt)
if (componentCompleteEnabled()) { // the qml designer does the component complete later
QQmlTrace trace("VME Component Complete");
while (!parserStatus.isEmpty()) {
+ if (profiler.enabled)
+ profiler.pop();
QQmlParserStatus *status = parserStatus.pop();
#ifdef QML_ENABLE_TRACE
QQmlData *data = parserStatusData.pop();
@@ -1189,6 +1212,8 @@ QQmlContextData *QQmlVME::complete(const Interrupt &interrupt)
return 0;
}
parserStatus.deallocate();
+ if (profiler.enabled)
+ profiler.clear();
}
{
diff --git a/src/qml/qml/qqmlvme_p.h b/src/qml/qml/qqmlvme_p.h
index e76b485a5c..d5afd4c67a 100644
--- a/src/qml/qml/qqmlvme_p.h
+++ b/src/qml/qml/qqmlvme_p.h
@@ -68,6 +68,7 @@
#include <private/qfinitestack_p.h>
#include <private/qqmltrace_p.h>
+#include <private/qqmlprofilerservice_p.h>
QT_BEGIN_NAMESPACE
@@ -171,6 +172,7 @@ private:
#ifdef QML_ENABLE_TRACE
QFiniteStack<QQmlData *> parserStatusData;
#endif
+ QQmlVmeProfiler profiler;
QQmlGuardedContextData rootContext;
QQmlGuardedContextData creationContext;
diff --git a/src/quick/items/qquicktextinput.cpp b/src/quick/items/qquicktextinput.cpp
index c56f3648e6..d4427eb47e 100644
--- a/src/quick/items/qquicktextinput.cpp
+++ b/src/quick/items/qquicktextinput.cpp
@@ -2533,7 +2533,7 @@ void QQuickTextInputPrivate::handleFocusEvent(QFocusEvent *event)
&& !persistentSelection)
deselect();
- if (hasAcceptableInput(m_text) || fixup())
+ if (q->hasAcceptableInput() || fixup())
emit q->editingFinished();
#ifndef QT_NO_IM
@@ -4117,7 +4117,7 @@ void QQuickTextInputPrivate::processKeyEvent(QKeyEvent* event)
Q_Q(QQuickTextInput);
if (event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return) {
- if (hasAcceptableInput(m_text) || fixup()) {
+ if (q->hasAcceptableInput() || fixup()) {
emit q->accepted();
emit q->editingFinished();
}
diff --git a/src/quick/scenegraph/qsgcontext.cpp b/src/quick/scenegraph/qsgcontext.cpp
index afde7939f2..90803db9fe 100644
--- a/src/quick/scenegraph/qsgcontext.cpp
+++ b/src/quick/scenegraph/qsgcontext.cpp
@@ -454,6 +454,8 @@ void QSGRenderContext::initialize(QOpenGLContext *context)
const char *renderer = (const char *) glGetString(GL_RENDERER);
if (strstr(renderer, "llvmpipe"))
m_serializedRender = true;
+ if (strstr(vendor, "Hisilicon Technologies") && strstr(renderer, "Immersion.16"))
+ m_brokenIBOs = true;
#endif
emit initialized();
diff --git a/src/quick/scenegraph/qsgrenderloop.cpp b/src/quick/scenegraph/qsgrenderloop.cpp
index aa0d7b5a6c..52df55fa92 100644
--- a/src/quick/scenegraph/qsgrenderloop.cpp
+++ b/src/quick/scenegraph/qsgrenderloop.cpp
@@ -122,6 +122,7 @@ public:
QSGRenderContext *rc;
QImage grabContent;
+ int m_update_timer;
bool eventPending;
};
@@ -384,7 +385,8 @@ void QSGGuiThreadRenderLoop::maybeUpdate(QQuickWindow *window)
m_windows[window].updatePending = true;
if (!eventPending) {
- QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+ const int exhaust_delay = 5;
+ m_update_timer = startTimer(exhaust_delay, Qt::PreciseTimer);
eventPending = true;
}
}
@@ -399,8 +401,10 @@ QSGContext *QSGGuiThreadRenderLoop::sceneGraphContext() const
bool QSGGuiThreadRenderLoop::event(QEvent *e)
{
- if (e->type() == QEvent::User) {
+ if (e->type() == QEvent::Timer) {
eventPending = false;
+ killTimer(m_update_timer);
+ m_update_timer = 0;
for (QHash<QQuickWindow *, WindowData>::const_iterator it = m_windows.constBegin();
it != m_windows.constEnd(); ++it) {
const WindowData &data = it.value();
diff --git a/src/quick/scenegraph/shaders/distancefieldshiftedtext.frag b/src/quick/scenegraph/shaders/distancefieldshiftedtext.frag
index 60c1c7468b..42fead8713 100644
--- a/src/quick/scenegraph/shaders/distancefieldshiftedtext.frag
+++ b/src/quick/scenegraph/shaders/distancefieldshiftedtext.frag
@@ -1,7 +1,7 @@
varying highp vec2 sampleCoord;
varying highp vec2 shiftedSampleCoord;
-uniform sampler2D _qt_texture;
+uniform mediump sampler2D _qt_texture;
uniform lowp vec4 color;
uniform lowp vec4 styleColor;
uniform mediump float alphaMin;
diff --git a/src/quick/util/qquickvaluetypes_p.h b/src/quick/util/qquickvaluetypes_p.h
index 88570f3b6e..94db7a8729 100644
--- a/src/quick/util/qquickvaluetypes_p.h
+++ b/src/quick/util/qquickvaluetypes_p.h
@@ -64,10 +64,10 @@ void registerValueTypes();
class Q_AUTOTEST_EXPORT QQuickColorValueType : public QQmlValueTypeBase<QColor>
{
- Q_PROPERTY(qreal r READ r WRITE setR)
- Q_PROPERTY(qreal g READ g WRITE setG)
- Q_PROPERTY(qreal b READ b WRITE setB)
- Q_PROPERTY(qreal a READ a WRITE setA)
+ Q_PROPERTY(qreal r READ r WRITE setR FINAL)
+ Q_PROPERTY(qreal g READ g WRITE setG FINAL)
+ Q_PROPERTY(qreal b READ b WRITE setB FINAL)
+ Q_PROPERTY(qreal a READ a WRITE setA FINAL)
Q_OBJECT
public:
QQuickColorValueType(QObject *parent = 0);
@@ -86,8 +86,8 @@ public:
class Q_AUTOTEST_EXPORT QQuickVector2DValueType : public QQmlValueTypeBase<QVector2D>
{
- Q_PROPERTY(qreal x READ x WRITE setX)
- Q_PROPERTY(qreal y READ y WRITE setY)
+ Q_PROPERTY(qreal x READ x WRITE setX FINAL)
+ Q_PROPERTY(qreal y READ y WRITE setY FINAL)
Q_OBJECT
public:
QQuickVector2DValueType(QObject *parent = 0);
@@ -115,9 +115,9 @@ public:
class Q_AUTOTEST_EXPORT QQuickVector3DValueType : public QQmlValueTypeBase<QVector3D>
{
- Q_PROPERTY(qreal x READ x WRITE setX)
- Q_PROPERTY(qreal y READ y WRITE setY)
- Q_PROPERTY(qreal z READ z WRITE setZ)
+ Q_PROPERTY(qreal x READ x WRITE setX FINAL)
+ Q_PROPERTY(qreal y READ y WRITE setY FINAL)
+ Q_PROPERTY(qreal z READ z WRITE setZ FINAL)
Q_OBJECT
public:
QQuickVector3DValueType(QObject *parent = 0);
@@ -149,10 +149,10 @@ public:
class Q_AUTOTEST_EXPORT QQuickVector4DValueType : public QQmlValueTypeBase<QVector4D>
{
- Q_PROPERTY(qreal x READ x WRITE setX)
- Q_PROPERTY(qreal y READ y WRITE setY)
- Q_PROPERTY(qreal z READ z WRITE setZ)
- Q_PROPERTY(qreal w READ w WRITE setW)
+ Q_PROPERTY(qreal x READ x WRITE setX FINAL)
+ Q_PROPERTY(qreal y READ y WRITE setY FINAL)
+ Q_PROPERTY(qreal z READ z WRITE setZ FINAL)
+ Q_PROPERTY(qreal w READ w WRITE setW FINAL)
Q_OBJECT
public:
QQuickVector4DValueType(QObject *parent = 0);
@@ -207,22 +207,22 @@ public:
class Q_AUTOTEST_EXPORT QQuickMatrix4x4ValueType : public QQmlValueTypeBase<QMatrix4x4>
{
- Q_PROPERTY(qreal m11 READ m11 WRITE setM11)
- Q_PROPERTY(qreal m12 READ m12 WRITE setM12)
- Q_PROPERTY(qreal m13 READ m13 WRITE setM13)
- Q_PROPERTY(qreal m14 READ m14 WRITE setM14)
- Q_PROPERTY(qreal m21 READ m21 WRITE setM21)
- Q_PROPERTY(qreal m22 READ m22 WRITE setM22)
- Q_PROPERTY(qreal m23 READ m23 WRITE setM23)
- Q_PROPERTY(qreal m24 READ m24 WRITE setM24)
- Q_PROPERTY(qreal m31 READ m31 WRITE setM31)
- Q_PROPERTY(qreal m32 READ m32 WRITE setM32)
- Q_PROPERTY(qreal m33 READ m33 WRITE setM33)
- Q_PROPERTY(qreal m34 READ m34 WRITE setM34)
- Q_PROPERTY(qreal m41 READ m41 WRITE setM41)
- Q_PROPERTY(qreal m42 READ m42 WRITE setM42)
- Q_PROPERTY(qreal m43 READ m43 WRITE setM43)
- Q_PROPERTY(qreal m44 READ m44 WRITE setM44)
+ Q_PROPERTY(qreal m11 READ m11 WRITE setM11 FINAL)
+ Q_PROPERTY(qreal m12 READ m12 WRITE setM12 FINAL)
+ Q_PROPERTY(qreal m13 READ m13 WRITE setM13 FINAL)
+ Q_PROPERTY(qreal m14 READ m14 WRITE setM14 FINAL)
+ Q_PROPERTY(qreal m21 READ m21 WRITE setM21 FINAL)
+ Q_PROPERTY(qreal m22 READ m22 WRITE setM22 FINAL)
+ Q_PROPERTY(qreal m23 READ m23 WRITE setM23 FINAL)
+ Q_PROPERTY(qreal m24 READ m24 WRITE setM24 FINAL)
+ Q_PROPERTY(qreal m31 READ m31 WRITE setM31 FINAL)
+ Q_PROPERTY(qreal m32 READ m32 WRITE setM32 FINAL)
+ Q_PROPERTY(qreal m33 READ m33 WRITE setM33 FINAL)
+ Q_PROPERTY(qreal m34 READ m34 WRITE setM34 FINAL)
+ Q_PROPERTY(qreal m41 READ m41 WRITE setM41 FINAL)
+ Q_PROPERTY(qreal m42 READ m42 WRITE setM42 FINAL)
+ Q_PROPERTY(qreal m43 READ m43 WRITE setM43 FINAL)
+ Q_PROPERTY(qreal m44 READ m44 WRITE setM44 FINAL)
Q_OBJECT
public:
QQuickMatrix4x4ValueType(QObject *parent = 0);
@@ -288,18 +288,18 @@ class Q_AUTOTEST_EXPORT QQuickFontValueType : public QQmlValueTypeBase<QFont>
Q_ENUMS(FontWeight)
Q_ENUMS(Capitalization)
- Q_PROPERTY(QString family READ family WRITE setFamily)
- Q_PROPERTY(bool bold READ bold WRITE setBold)
- Q_PROPERTY(FontWeight weight READ weight WRITE setWeight)
- Q_PROPERTY(bool italic READ italic WRITE setItalic)
- Q_PROPERTY(bool underline READ underline WRITE setUnderline)
- Q_PROPERTY(bool overline READ overline WRITE setOverline)
- Q_PROPERTY(bool strikeout READ strikeout WRITE setStrikeout)
- Q_PROPERTY(qreal pointSize READ pointSize WRITE setPointSize)
- Q_PROPERTY(int pixelSize READ pixelSize WRITE setPixelSize)
- Q_PROPERTY(Capitalization capitalization READ capitalization WRITE setCapitalization)
- Q_PROPERTY(qreal letterSpacing READ letterSpacing WRITE setLetterSpacing)
- Q_PROPERTY(qreal wordSpacing READ wordSpacing WRITE setWordSpacing)
+ Q_PROPERTY(QString family READ family WRITE setFamily FINAL)
+ Q_PROPERTY(bool bold READ bold WRITE setBold FINAL)
+ Q_PROPERTY(FontWeight weight READ weight WRITE setWeight FINAL)
+ Q_PROPERTY(bool italic READ italic WRITE setItalic FINAL)
+ Q_PROPERTY(bool underline READ underline WRITE setUnderline FINAL)
+ Q_PROPERTY(bool overline READ overline WRITE setOverline FINAL)
+ Q_PROPERTY(bool strikeout READ strikeout WRITE setStrikeout FINAL)
+ Q_PROPERTY(qreal pointSize READ pointSize WRITE setPointSize FINAL)
+ Q_PROPERTY(int pixelSize READ pixelSize WRITE setPixelSize FINAL)
+ Q_PROPERTY(Capitalization capitalization READ capitalization WRITE setCapitalization FINAL)
+ Q_PROPERTY(qreal letterSpacing READ letterSpacing WRITE setLetterSpacing FINAL)
+ Q_PROPERTY(qreal wordSpacing READ wordSpacing WRITE setWordSpacing FINAL)
public:
enum FontWeight { Light = QFont::Light,