summaryrefslogtreecommitdiffstats
path: root/src/declarative
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative')
-rw-r--r--src/declarative/qml/qmlbasicscript.cpp424
-rw-r--r--src/declarative/qml/qmlbasicscript_p.h38
-rw-r--r--src/declarative/qml/qmlengine.cpp68
-rw-r--r--src/declarative/qml/qmlengine_p.h9
4 files changed, 116 insertions, 423 deletions
diff --git a/src/declarative/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp
index 3fe24ea..fb52b91 100644
--- a/src/declarative/qml/qmlbasicscript.cpp
+++ b/src/declarative/qml/qmlbasicscript.cpp
@@ -56,13 +56,10 @@ using namespace QmlJS;
struct ScriptInstruction {
enum {
- Load, // fetch
- Fetch, // fetch
-
LoadIdObject, // fetch
FetchConstant, // constant
- FetchD0Constant, // constant
- FetchD1Constant, // constant
+ FetchContextConstant, // constant
+ FetchRootConstant, // constant
Equals, // NA
@@ -88,8 +85,6 @@ struct ScriptInstruction {
};
};
-DEFINE_BOOL_CONFIG_OPTION(scriptWarnings, QML_SCRIPT_WARNINGS);
-
class QmlBasicScriptPrivate
{
public:
@@ -120,60 +115,6 @@ public:
}
};
-QDebug operator<<(QDebug lhs, const QmlBasicScriptNodeCache &rhs)
-{
- switch(rhs.type) {
- case QmlBasicScriptNodeCache::Invalid:
- lhs << "Invalid";
- break;
- case QmlBasicScriptNodeCache::Core:
- lhs << "Core" << rhs.object << rhs.core;
- break;
- case QmlBasicScriptNodeCache::Attached:
- lhs << "Attached" << rhs.object << rhs.attached;
- break;
- case QmlBasicScriptNodeCache::SignalProperty:
- lhs << "SignalProperty" << rhs.object << rhs.core;
- break;
- case QmlBasicScriptNodeCache::Variant:
- lhs << "Variant" << rhs.context;
- break;
- }
-
- return lhs;
-}
-
-void QmlBasicScriptNodeCache::clear()
-{
- object = 0;
- metaObject = 0;
- type = Invalid;
-}
-
-static QVariant toObjectOrVariant(const QVariant &v)
-{
- switch(v.userType()) {
- case QVariant::String:
- case QVariant::UInt:
- case QVariant::Int:
- case QMetaType::Float:
- case QVariant::Double:
- case QVariant::Color:
- case QVariant::Bool:
- default:
- {
- if (v.type() == QVariant::UserType) {
- QObject *o = QmlMetaType::toQObject(v);
- if (o)
- return qVariantFromValue(o);
- else
- return v;
- }
- return v;
- }
- }
-}
-
static QVariant fetch_value(QObject *o, int idx, int type)
{
if (!o)
@@ -259,26 +200,6 @@ static QVariant fetch_value(QObject *o, int idx, int type)
};
}
-QVariant QmlBasicScriptNodeCache::value(const char *) const
-{
- //QFxPerfTimer<QFxPerf::BasicScriptValue> pt;
- switch(type) {
- case Invalid:
- break;
- case Core:
- return fetch_value(object, core, coreType);
- break;
- case Attached:
- return qVariantFromValue(static_cast<QObject *>(attached));
- break;
- case SignalProperty:
- break;
- case Variant:
- return context->propertyValues[contextIndex];
- };
- return QVariant();
-}
-
struct QmlBasicScriptCompiler
{
QmlBasicScriptCompiler()
@@ -298,7 +219,11 @@ struct QmlBasicScriptCompiler
bool tryConstant(QmlJS::AST::Node *);
bool parseConstant(QmlJS::AST::Node *);
bool tryName(QmlJS::AST::Node *);
- bool parseName(QmlJS::AST::Node *, QmlParser::Object ** = 0);
+ bool parseName(QmlJS::AST::Node *);
+
+ bool buildName(QStringList &, QmlJS::AST::Node *);
+ const QMetaObject *fetch(int type, const QMetaObject *, int idx);
+
bool tryBinaryExpression(QmlJS::AST::Node *);
bool compileBinaryExpression(QmlJS::AST::Node *);
@@ -374,11 +299,7 @@ QByteArray QmlBasicScript::expression() const
*/
QmlBasicScript::~QmlBasicScript()
{
- if (flags & QmlBasicScriptPrivate::OwnData)
- free(d);
- if (rc) rc->release();
- d = 0;
- rc = 0;
+ clear();
}
/*!
@@ -401,24 +322,14 @@ void QmlBasicScript::clear()
*/
void *QmlBasicScript::newScriptState()
{
- if (!d) {
- return 0;
- } else {
- void *rv = ::malloc(d->stateSize * sizeof(QmlBasicScriptNodeCache));
- ::memset(rv, 0, d->stateSize * sizeof(QmlBasicScriptNodeCache));
- return rv;
- }
+ return 0;
}
/*!
Delete the \a data previously allocated by newScriptState().
*/
-void QmlBasicScript::deleteScriptState(void *data)
+void QmlBasicScript::deleteScriptState(void *)
{
- if (!data) return;
- Q_ASSERT(d);
- clearCache(data);
- free(data);
}
/*!
@@ -430,30 +341,21 @@ void QmlBasicScript::dump()
return;
qWarning() << d->instructionCount << "instructions:";
- const char *data = d->data();
for (int ii = 0; ii < d->instructionCount; ++ii) {
const ScriptInstruction &instr = d->instructions()[ii];
switch(instr.type) {
- case ScriptInstruction::Load:
- qWarning().nospace() << "LOAD\t\t" << instr.fetch.idx << "\t\t"
- << QByteArray(data + instr.fetch.idx);
- break;
- case ScriptInstruction::Fetch:
- qWarning().nospace() << "FETCH\t\t" << instr.fetch.idx << "\t\t"
- << QByteArray(data + instr.fetch.idx);
- break;
case ScriptInstruction::LoadIdObject:
qWarning().nospace() << "LOAD_ID_OBJECT";
break;
case ScriptInstruction::FetchConstant:
qWarning().nospace() << "FETCH_CONSTANT";
break;
- case ScriptInstruction::FetchD0Constant:
- qWarning().nospace() << "FETCH_D0_CONSTANT";
+ case ScriptInstruction::FetchContextConstant:
+ qWarning().nospace() << "FETCH_CONTEXT_CONSTANT";
break;
- case ScriptInstruction::FetchD1Constant:
- qWarning().nospace() << "FETCH_D1_CONSTANT";
+ case ScriptInstruction::FetchRootConstant:
+ qWarning().nospace() << "FETCH_ROOT_CONSTANT";
break;
case ScriptInstruction::Equals:
qWarning().nospace() << "EQUALS";
@@ -564,101 +466,120 @@ bool QmlBasicScriptCompiler::tryName(QmlJS::AST::Node *node)
node->kind == AST::Node::Kind_FieldMemberExpression;
}
-bool QmlBasicScriptCompiler::parseName(AST::Node *node,
- QmlParser::Object **type)
+bool QmlBasicScriptCompiler::buildName(QStringList &name,
+ QmlJS::AST::Node *node)
{
- bool load = false;
- QmlParser::Object *loadedType = 0;
- QString name;
if (node->kind == AST::Node::Kind_IdentifierExpression) {
- name = static_cast<AST::IdentifierExpression *>(node)->name->asString();
- load = true;
+ name << static_cast<AST::IdentifierExpression*>(node)->name->asString();
} else if (node->kind == AST::Node::Kind_FieldMemberExpression) {
- AST::FieldMemberExpression *expr = static_cast<AST::FieldMemberExpression *>(node);
+ AST::FieldMemberExpression *expr =
+ static_cast<AST::FieldMemberExpression *>(node);
- if (!parseName(expr->base, &loadedType))
+ if (!buildName(name, expr->base))
return false;
- name = expr->name->asString();
+ name << expr->name->asString();
} else {
return false;
}
+ return true;
+}
+
+const QMetaObject *
+QmlBasicScriptCompiler::fetch(int type, const QMetaObject *mo, int idx)
+{
ScriptInstruction instr;
- if (load) {
+ (int &)instr.type = type;
+ instr.constant.idx = idx;
+ QMetaProperty prop = mo->property(idx);
+ if (prop.isConstant())
+ instr.constant.notify = 0;
+ else
+ instr.constant.notify = prop.notifySignalIndex();
+ instr.constant.type = prop.userType();
+ bytecode << instr;
+ return QmlMetaType::metaObjectForType(prop.userType());
+}
- if (ids.contains(name)) {
- instr.type = ScriptInstruction::LoadIdObject;
- instr.fetch.idx = ids.value(name)->idIndex;
+bool QmlBasicScriptCompiler::parseName(AST::Node *node)
+{
- if (type)
- *type = ids.value(name);
+ QStringList nameParts;
+ if (!buildName(nameParts, node))
+ return false;
- } else {
- int d0Idx = context->metaObject()->indexOfProperty(name.toUtf8().constData());
- int d1Idx = -1;
- if (d0Idx == -1)
- d1Idx = component->metaObject()->indexOfProperty(name.toUtf8().constData());
- if (d0Idx != -1) {
-
- instr.type = ScriptInstruction::FetchD0Constant;
- instr.constant.idx = d0Idx;
- QMetaProperty prop = context->metaObject()->property(d0Idx);
- if (prop.isConstant())
- instr.constant.notify = 0;
- else
- instr.constant.notify = prop.notifySignalIndex();
- instr.constant.type = prop.userType();
-
- } else if (d1Idx != -1) {
-
- instr.type = ScriptInstruction::FetchD1Constant;
- instr.constant.idx = d1Idx;
- QMetaProperty prop = component->metaObject()->property(d1Idx);
- if (prop.isConstant())
- instr.constant.notify = 0;
- else
- instr.constant.notify = prop.notifySignalIndex();
- instr.constant.type = prop.userType();
-
- } else {
-
- int nref = data.count();
- data.append(name.toUtf8());
- data.append('\0');
- instr.type = ScriptInstruction::Load;
- instr.fetch.idx = nref;
- ++stateSize;
+ QmlParser::Object *absType = 0;
+ const QMetaObject *metaType = 0;
+
+ for (int ii = 0; ii < nameParts.count(); ++ii) {
+ const QString &name = nameParts.at(ii);
+
+ // We don't handle signal properties
+ if (name.length() > 2 && name.startsWith(QLatin1String("on")) &&
+ name.at(2).isUpper())
+ return false;
+
+ if (ii == 0) {
+
+ if (0) {
+ // ### - Must test for an attached type name
+ } else if (ids.contains(name)) {
+ ScriptInstruction instr;
+ instr.type = ScriptInstruction::LoadIdObject;
+ instr.fetch.idx = ids.value(name)->idIndex;
+ bytecode << instr;
+ absType = ids.value(name);
+ } else if(name.at(0).isLower()) {
+
+ QByteArray utf8Name = name.toUtf8();
+ const char *cname = utf8Name.constData();
+
+ int d0Idx = context->metaObject()->indexOfProperty(cname);
+ int d1Idx = -1;
+ if (d0Idx == -1)
+ d1Idx = component->metaObject()->indexOfProperty(cname);
+
+ if (d0Idx != -1) {
+ metaType = fetch(ScriptInstruction::FetchContextConstant,
+ context->metaObject(), d0Idx);
+ } else if(d1Idx != -1) {
+ metaType = fetch(ScriptInstruction::FetchRootConstant,
+ component->metaObject(), d1Idx);
+ } else {
+ return false;
+ }
}
- }
+ } else {
- } else {
+ if (!name.at(0).isLower())
+ return false;
- int idx = -1;
- if (loadedType)
- idx = loadedType->metaObject()->indexOfProperty(name.toUtf8().constData());
- if (idx != -1) {
- instr.type = ScriptInstruction::FetchConstant;
- instr.constant.idx = idx;
- QMetaProperty prop = loadedType->metaObject()->property(idx);
- if (prop.isConstant())
- instr.constant.notify = 0;
+ const QMetaObject *mo = 0;
+ if (absType)
+ mo = absType->metaObject();
+ else if(metaType)
+ mo = metaType;
else
- instr.constant.notify = prop.notifySignalIndex();
- instr.constant.type = prop.userType();
- } else {
- int nref = data.count();
- data.append(name.toUtf8());
- data.append('\0');
- instr.type = ScriptInstruction::Fetch;
- instr.fetch.idx = nref;
- ++stateSize;
- }
+ return false;
+
+ QByteArray utf8Name = name.toUtf8();
+ const char *cname = utf8Name.constData();
+ int idx = mo->indexOfProperty(cname);
+ if (idx == -1)
+ return false;
+
+ if (absType || mo->property(idx).isFinal()) {
+ absType = 0; metaType = 0;
+ metaType = fetch(ScriptInstruction::FetchConstant, mo, idx);
+ } else {
+ return false;
+ }
+ }
}
- bytecode.append(instr);
return true;
}
@@ -711,44 +632,6 @@ bool QmlBasicScriptCompiler::compileBinaryExpression(AST::Node *node)
}
/*!
- \internal
-*/
-void QmlBasicScript::clearCache(void *voidCache)
-{
- QmlBasicScriptNodeCache *dataCache =
- reinterpret_cast<QmlBasicScriptNodeCache *>(voidCache);
-
- for (int ii = 0; ii < d->stateSize; ++ii) {
- if (!dataCache[ii].isCore() && !dataCache[ii].isVariant() &&
- dataCache[ii].object) {
- QMetaObject::removeGuard(&dataCache[ii].object);
- dataCache[ii].object = 0;
- }
- dataCache[ii].clear();
- }
-}
-
-void QmlBasicScript::guard(QmlBasicScriptNodeCache &n)
-{
- if (n.object) {
- if (n.isVariant()) {
- } else if (n.isCore()) {
- n.metaObject =
- n.object->metaObject();
- } else {
- QMetaObject::addGuard(&n.object);
- }
- }
-}
-
-bool QmlBasicScript::valid(QmlBasicScriptNodeCache &n, QObject *obj)
-{
- return n.object == obj &&
- (!n.isCore() || obj->metaObject() == n.metaObject);
-}
-
-
-/*!
\enum QmlBasicScript::CacheState
\value NoChange The query has not change. Any previous monitoring is still
valid.
@@ -765,31 +648,17 @@ bool QmlBasicScript::valid(QmlBasicScriptNodeCache &n, QObject *obj)
*/
QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *cached)
{
+ Q_UNUSED(voidCache);
if (!isValid())
return QVariant();
QmlContextPrivate *contextPrivate = context->d_func();
QmlEnginePrivate *enginePrivate = context->engine()->d_func();
- QmlBasicScriptNodeCache *dataCache =
- reinterpret_cast<QmlBasicScriptNodeCache *>(voidCache);
- int dataCacheItem;
-
QStack<QVariant> stack;
- bool resetting = false;
- bool hasReset = false;
-
- const char *data = d->data();
-
- if (dataCache[0].type == QmlBasicScriptNodeCache::Invalid) {
- resetting = true;
- hasReset = true;
- }
-
CacheState state = NoChange;
- dataCacheItem = 0;
for (int idx = 0; idx < d->instructionCount; ++idx) {
const ScriptInstruction &instr = d->instructions()[idx];
@@ -803,7 +672,7 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c
}
break;
- case ScriptInstruction::FetchD0Constant:
+ case ScriptInstruction::FetchContextConstant:
{
QObject *obj = contextPrivate->defaultObjects.at(0);
@@ -815,7 +684,7 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c
}
break;
- case ScriptInstruction::FetchD1Constant:
+ case ScriptInstruction::FetchRootConstant:
{
QObject *obj = contextPrivate->defaultObjects.at(1);
@@ -840,64 +709,14 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c
}
break;
- case ScriptInstruction::Load: // either an object or a property
- case ScriptInstruction::Fetch: // can only be a property
- {
- const char *id = data + instr.fetch.idx;
- QmlBasicScriptNodeCache &n = dataCache[dataCacheItem];
-
- if (instr.type == ScriptInstruction::Load) {
-
- if (n.type == QmlBasicScriptNodeCache::Invalid || state == Reset) {
- context->engine()->d_func()->loadCache(n, QLatin1String(id), static_cast<QmlContextPrivate*>(context->d_ptr));
- if (state != Reset)
- state = Incremental;
- }
-
- if(!n.isValid())
- qWarning("ReferenceError: %s is not defined", id);
-
- } else { // instr.type == ScriptInstruction::Fetch
-
- QVariant o = stack.pop();
- QObject *obj = qvariant_cast<QObject *>(o);
- if (!obj) {
- if (n.type == QmlBasicScriptNodeCache::Invalid) {
- if (scriptWarnings())
- qWarning() << "QmlBasicScript: Unable to convert" << o;
- *cached = state;
- return QVariant();
- } else {
- clearCache(dataCache);
- *cached = Reset;
- CacheState dummy;
- return run(context, voidCache, &dummy);
- }
- } else if (n.type == QmlBasicScriptNodeCache::Invalid || state == Reset) {
- context->engine()->d_func()->fetchCache(n, QLatin1String(id), obj);
- guard(n);
- if (state != Reset)
- state = Incremental;
- } else if (!valid(n, obj)) {
- clearCache(dataCache);
- *cached = Reset;
- CacheState dummy;
- return run(context, voidCache, &dummy);
- }
-
- }
-
- QVariant var = n.value(id);
- stack.push(var);
- ++dataCacheItem;
- }
- break;
case ScriptInstruction::Int:
stack.push(QVariant(instr.integer.value));
break;
+
case ScriptInstruction::Bool:
stack.push(QVariant(instr.boolean.value));
break;
+
case ScriptInstruction::Equals:
{
QVariant rhs = stack.pop();
@@ -911,7 +730,7 @@ QVariant QmlBasicScript::run(QmlContext *context, void *voidCache, CacheState *c
}
}
- *cached = state;
+ *cached = Reset;
if (stack.isEmpty())
return QVariant();
@@ -939,23 +758,4 @@ unsigned int QmlBasicScript::compileDataSize() const
return 0;
}
-bool QmlBasicScript::isSingleLoad() const
-{
- if (!d)
- return false;
-
- return d->instructionCount == 1 &&
- d->instructions()[0].type == ScriptInstruction::Load;
-}
-
-QByteArray QmlBasicScript::singleLoadTarget() const
-{
- if (!isSingleLoad())
- return QByteArray();
-
- // We know there is one instruction and it is a load
- return QByteArray(d->data() + d->instructions()[0].fetch.idx);
-}
-
-
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlbasicscript_p.h b/src/declarative/qml/qmlbasicscript_p.h
index 77d59eb..eacd1d8 100644
--- a/src/declarative/qml/qmlbasicscript_p.h
+++ b/src/declarative/qml/qmlbasicscript_p.h
@@ -100,50 +100,12 @@ public:
enum CacheState { NoChange, Incremental, Reset };
QVariant run(QmlContext *, void *, CacheState *);
- // Optimization opportunities
- bool isSingleLoad() const;
- QByteArray singleLoadTarget() const;
-
private:
int flags;
QmlBasicScriptPrivate *d;
QmlRefCount *rc;
-
- void clearCache(void *);
- void guard(QmlBasicScriptNodeCache &);
- bool valid(QmlBasicScriptNodeCache &, QObject *);
-};
-
-class QmlContextPrivate;
-class QDebug;
-class QmlBasicScriptNodeCache
-{
-public:
- QObject *object;
- const QMetaObject *metaObject;
- enum { Invalid,
- Core,
- Attached,
- SignalProperty,
- Variant
- } type;
- union {
- int core;
- QObject *attached;
- QmlContextPrivate *context;
- };
- int coreType;
- int contextIndex;
-
- bool isValid() const { return type != Invalid; }
- bool isCore() const { return type == Core; }
- bool isVariant() const { return type == Variant; }
- void clear();
- QVariant value(const char *) const;
};
-QDebug operator<<(QDebug, const QmlBasicScriptNodeCache &);
-
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index a6f5b28..429e3b0 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -254,74 +254,6 @@ QScriptValue QmlEnginePrivate::propertyObject(const QScriptString &propName,
return QScriptValue();
}
-////////////////////////////////////////////////////////////////////
-
-bool QmlEnginePrivate::fetchCache(QmlBasicScriptNodeCache &cache, const QString &propName, QObject *obj)
-{
- QmlMetaProperty prop(obj, propName);
-
- if (!prop.isValid())
- return false;
-
- if (prop.needsChangedNotifier())
- capturedProperties << CapturedProperty(prop);
-
- if (prop.type() & QmlMetaProperty::Attached) {
-
- cache.object = obj;
- cache.type = QmlBasicScriptNodeCache::Attached;
- cache.attached = prop.d->attachedObject();
- return true;
-
- } else if (prop.type() & QmlMetaProperty::Property) {
-
- cache.object = obj;
- cache.type = QmlBasicScriptNodeCache::Core;
- cache.core = prop.property().propertyIndex();
- cache.coreType = prop.propertyType();
- return true;
-
- } else if (prop.type() & QmlMetaProperty::SignalProperty) {
-
- cache.object = obj;
- cache.type = QmlBasicScriptNodeCache::SignalProperty;
- cache.core = prop.coreIndex();
- return true;
-
- }
-
- return false;
-}
-
-bool QmlEnginePrivate::loadCache(QmlBasicScriptNodeCache &cache, const QString &propName, QmlContextPrivate *context)
-{
- while(context) {
-
- QHash<QString, int>::ConstIterator iter =
- context->propertyNames.find(propName);
- if (iter != context->propertyNames.end()) {
- cache.object = 0;
- cache.type = QmlBasicScriptNodeCache::Variant;
- cache.context = context;
- cache.contextIndex = *iter;
- capturedProperties << CapturedProperty(context->q_ptr, -1, *iter + context->notifyIndex);
- return true;
- }
-
- foreach(QObject *obj, context->defaultObjects) {
- if (fetchCache(cache, propName, obj))
- return true;
- }
-
- if (context->parent)
- context = context->parent->d_func();
- else
- context = 0;
- }
- return false;
-}
-
-
/*!
\class QmlEngine
\brief The QmlEngine class provides an environment for instantiating QML components.
diff --git a/src/declarative/qml/qmlengine_p.h b/src/declarative/qml/qmlengine_p.h
index f459dc5..4bef85a 100644
--- a/src/declarative/qml/qmlengine_p.h
+++ b/src/declarative/qml/qmlengine_p.h
@@ -93,11 +93,10 @@ public:
void init();
- bool fetchCache(QmlBasicScriptNodeCache &cache, const QString &propName, QObject *);
- bool loadCache(QmlBasicScriptNodeCache &cache, const QString &propName, QmlContextPrivate *context);
-
- QScriptClass::QueryFlags queryObject(const QString &name, uint *id, QObject *);
- QScriptValue propertyObject(const QScriptString &propName, QObject *, uint id = 0);
+ QScriptClass::QueryFlags queryObject(const QString &name, uint *id,
+ QObject *);
+ QScriptValue propertyObject(const QScriptString &propName, QObject *,
+ uint id = 0);
struct CapturedProperty {
CapturedProperty(QObject *o, int c, int n)