summaryrefslogtreecommitdiffstats
path: root/src/declarative
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2010-01-27 01:26:12 (GMT)
committerAaron Kennedy <aaron.kennedy@nokia.com>2010-01-27 01:27:21 (GMT)
commit6f1d4e8bdd9a11a4d35c8386e0c7e236bcfebd95 (patch)
treed14e4129940b5c584993ad9929b4d55500cf9a8c /src/declarative
parent167cbed98b5d9fadbe5d6f506e3937a25e7189b1 (diff)
downloadQt-6f1d4e8bdd9a11a4d35c8386e0c7e236bcfebd95.zip
Qt-6f1d4e8bdd9a11a4d35c8386e0c7e236bcfebd95.tar.gz
Qt-6f1d4e8bdd9a11a4d35c8386e0c7e236bcfebd95.tar.bz2
Harden binding optimizer
Diffstat (limited to 'src/declarative')
-rw-r--r--src/declarative/qml/qml.pri2
-rw-r--r--src/declarative/qml/qmlbasicscript.cpp760
-rw-r--r--src/declarative/qml/qmlbasicscript_p.h117
-rw-r--r--src/declarative/qml/qmlbindingoptimizations.cpp87
-rw-r--r--src/declarative/qml/qmlbindingoptimizations_p.h27
-rw-r--r--src/declarative/qml/qmlbindingvme.cpp92
-rw-r--r--src/declarative/qml/qmlbindingvme_p.h73
-rw-r--r--src/declarative/qml/qmlcompiler.cpp92
-rw-r--r--src/declarative/qml/qmlcompiler_p.h2
-rw-r--r--src/declarative/qml/qmlcontext.cpp6
-rw-r--r--src/declarative/qml/qmlcontext.h1
-rw-r--r--src/declarative/qml/qmlcontext_p.h3
-rw-r--r--src/declarative/qml/qmlengine.cpp1
-rw-r--r--src/declarative/qml/qmlexpression.cpp86
-rw-r--r--src/declarative/qml/qmlexpression.h1
-rw-r--r--src/declarative/qml/qmlexpression_p.h8
-rw-r--r--src/declarative/qml/qmlinstruction.cpp3
-rw-r--r--src/declarative/qml/qmlinstruction_p.h1
-rw-r--r--src/declarative/qml/qmlvme.cpp17
19 files changed, 213 insertions, 1166 deletions
diff --git a/src/declarative/qml/qml.pri b/src/declarative/qml/qml.pri
index b3a3905..9268545 100644
--- a/src/declarative/qml/qml.pri
+++ b/src/declarative/qml/qml.pri
@@ -32,7 +32,6 @@ SOURCES += \
$$PWD/qmlscriptparser.cpp \
$$PWD/qmlenginedebug.cpp \
$$PWD/qmlrewrite.cpp \
- $$PWD/qmlbasicscript.cpp \
$$PWD/qmlbindingvme.cpp \
$$PWD/qmlvaluetype.cpp \
$$PWD/qmlbindingoptimizations.cpp \
@@ -96,7 +95,6 @@ HEADERS += \
$$PWD/qmldeclarativedata_p.h \
$$PWD/qmlerror.h \
$$PWD/qmlscriptparser_p.h \
- $$PWD/qmlbasicscript_p.h \
$$PWD/qmlbindingvme_p.h \
$$PWD/qmlenginedebug_p.h \
$$PWD/qmlrewrite_p.h \
diff --git a/src/declarative/qml/qmlbasicscript.cpp b/src/declarative/qml/qmlbasicscript.cpp
deleted file mode 100644
index 3d566c7..0000000
--- a/src/declarative/qml/qmlbasicscript.cpp
+++ /dev/null
@@ -1,760 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qmlbasicscript_p.h"
-
-#include "qmlengine_p.h"
-#include "qmlcontext_p.h"
-#include "qmlrefcount_p.h"
-#include "qmlglobal_p.h"
-
-#include <qfxperf_p_p.h>
-#include <qmljsast_p.h>
-#include <qmljsengine_p.h>
-
-#include <QColor>
-#include <QDebug>
-#include <QStack>
-
-QT_BEGIN_NAMESPACE
-
-DEFINE_BOOL_CONFIG_OPTION(qmlBasicScriptDump, QML_BASICSCRIPT_DUMP);
-
-using namespace QmlJS;
-
-struct ScriptInstruction {
- enum {
- LoadIdObject, // fetch
- FetchConstant, // constant
- FetchContextConstant, // constant
- FetchRootConstant, // constant
-
- Equals, // NA
-
- Int, // integer
- Bool, // boolean
- } type;
-
- union {
- struct {
- int idx;
- } fetch;
- struct {
- int value;
- } integer;
- struct {
- bool value;
- } boolean;
- struct {
- short idx;
- short notify;
- int type;
- } constant;
- };
-};
-
-class QmlBasicScriptPrivate
-{
-public:
- enum Flags { OwnData = 0x00000001 };
-
- int size;
- int stateSize;
- int instructionCount;
- int exprLen;
-
- ScriptInstruction *instructions() const { return (ScriptInstruction *)((char *)this + sizeof(QmlBasicScriptPrivate)); }
-
- const char *expr() const
- {
- return (const char *)(instructions() + instructionCount);
- }
-
- const char *data() const
- {
- return (const char *)(instructions() + instructionCount) + exprLen + 1;
- }
-
- static unsigned int alignRound(int s)
- {
- if (s % 4)
- s += 4 - (s % 4);
- return s;
- }
-};
-
-// anchors.left: (nop convert)(qobject)parent.(anchorline)right
-
-/*
- Property chains: a.b.c.d
- if else value selection statements: if(a) b else if(c) d else e
- trinary selection: a?b:c
- addition: a + b
- negation: a - a
- equality: ==
-*/
-static QVariant fetch_value(QObject *o, int idx, int type)
-{
- if (!o)
- return QVariant();
-
- switch(type) {
- case QVariant::String:
- {
- QString val;
- void *args[] = { &val, 0 };
- QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
- return QVariant(val);
- }
- break;
- case QVariant::UInt:
- {
- uint val;
- void *args[] = { &val, 0 };
- QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
- return QVariant(val);
- }
- break;
- case QVariant::Int:
- {
- int val;
- void *args[] = { &val, 0 };
- QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
- return QVariant(val);
- }
- break;
- case QMetaType::Float:
- {
- float val;
- void *args[] = { &val, 0 };
- QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
- return QVariant(val);
- }
- break;
- case QVariant::Double:
- {
- double val;
- void *args[] = { &val, 0 };
- QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
- return QVariant(val);
- }
- break;
- case QVariant::Color:
- {
- QColor val;
- void *args[] = { &val, 0 };
- QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
- return QVariant(val);
- }
- break;
- case QVariant::Bool:
- {
- bool val;
- void *args[] = { &val, 0 };
- QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
- return QVariant(val);
- }
- break;
- default:
- {
- // If the object is null, we extract the predicted type. While this isn't
- // 100% reliable, in many cases it gives us better error messages if we
- // assign this null-object to an incompatible property
- if (QmlMetaType::isObject(type)) {
- // NOTE: This assumes a cast to QObject does not alter the
- // object pointer
- QObject *val = 0;
- void *args[] = { &val, 0 };
- QMetaObject::metacall(o, QMetaObject::ReadProperty, idx, args);
- if (!val) return QVariant(type, &val);
- else return QVariant::fromValue(val);
- } else {
- QVariant var = o->metaObject()->property(idx).read(o);
- if (QmlMetaType::isObject(var.userType())) {
- QObject *obj = 0;
- obj = *(QObject **)var.data();
- if (!obj) var = QVariant(var.userType(), &obj);
- else var = QVariant::fromValue(obj);
- }
- return var;
- }
- }
- break;
- };
-}
-
-struct QmlBasicScriptCompiler
-{
- QmlBasicScriptCompiler()
- : script(0), stateSize(0) {}
-
- QmlBasicScript *script;
- int stateSize;
-
- QmlParser::Object *context;
- QmlParser::Object *component;
- QHash<QString, QmlParser::Object *> ids;
-
- bool compile(QmlJS::AST::Node *);
-
- bool compileExpression(QmlJS::AST::Node *);
-
- bool tryConstant(QmlJS::AST::Node *);
- bool parseConstant(QmlJS::AST::Node *);
- bool tryName(QmlJS::AST::Node *);
- 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 *);
-
- QByteArray data;
- QList<ScriptInstruction> bytecode;
-};
-
-/*!
- \internal
- \class QmlBasicScript
- \brief The QmlBasicScript class provides a fast implementation of a limited subset of QmlJS bindings.
-
- QmlBasicScript instances are used to accelerate binding. Instead of using
- the slower, fully fledged QmlJS engine, many simple bindings can be
- evaluated using the QmlBasicScript engine.
-
- To see if the QmlBasicScript engine can handle a binding, call compile()
- and check the return value, or isValid() afterwards.
-
- To accelerate binding, QmlBasicScript can return a precompiled
- version of itself that can be saved for future use. Call compileData() to
- get an opaque pointer to the compiled state, and compileDataSize() for the
- size of this data in bytes. This data can be saved and passed to future
- instances of the QmlBasicScript constructor. The initial copy of compile
- data is owned by the QmlBindScript instance on which compile() was called.
-*/
-
-/*!
- Create a new QmlBasicScript instance.
-*/
-QmlBasicScript::QmlBasicScript()
-: flags(0), d(0), rc(0)
-{
-}
-
-/*!
- Load the QmlBasicScript instance with saved \a data.
-
- \a data \b must be data previously acquired from calling compileData() on a
- previously created QmlBasicScript instance. Any other data will almost
- certainly cause the QmlBasicScript engine to crash.
-
- \a data must continue to be valid throughout the QmlBasicScript instance
- life. It does not assume ownership of the memory.
-
- If \a owner is set, it is referenced on creation and dereferenced on
- destruction of this instance.
-*/
-
-void QmlBasicScript::load(const char *data, QmlRefCount *owner)
-{
- clear();
- d = (QmlBasicScriptPrivate *)data;
- rc = owner;
- if (rc) rc->addref();
-}
-
-/*!
- Return the text of the script expression.
- */
-QByteArray QmlBasicScript::expression() const
-{
- if (!d)
- return QByteArray();
- else
- return QByteArray(d->expr());
-}
-
-/*!
- Destroy the script instance.
-*/
-QmlBasicScript::~QmlBasicScript()
-{
- clear();
-}
-
-/*!
- Clear this script. The object will then be in its initial state, as though
- it were freshly constructed with default constructor.
-*/
-void QmlBasicScript::clear()
-{
- if (flags & QmlBasicScriptPrivate::OwnData)
- free(d);
- if (rc) rc->release();
- d = 0;
- rc = 0;
- flags = 0;
-}
-
-/*!
- Dump the script instructions to stderr for debugging.
- */
-void QmlBasicScript::dump()
-{
- if (!d)
- return;
-
- qWarning() << d->instructionCount << "instructions:";
- for (int ii = 0; ii < d->instructionCount; ++ii) {
- const ScriptInstruction &instr = d->instructions()[ii];
-
- switch(instr.type) {
- case ScriptInstruction::LoadIdObject:
- qWarning().nospace() << "LOAD_ID_OBJECT";
- break;
- case ScriptInstruction::FetchConstant:
- qWarning().nospace() << "FETCH_CONSTANT";
- break;
- case ScriptInstruction::FetchContextConstant:
- qWarning().nospace() << "FETCH_CONTEXT_CONSTANT";
- break;
- case ScriptInstruction::FetchRootConstant:
- qWarning().nospace() << "FETCH_ROOT_CONSTANT";
- break;
- case ScriptInstruction::Equals:
- qWarning().nospace() << "EQUALS";
- break;
- case ScriptInstruction::Int:
- qWarning().nospace() << "INT\t\t" << instr.integer.value;
- break;
- case ScriptInstruction::Bool:
- qWarning().nospace() << "BOOL\t\t" << instr.boolean.value;
- break;
- default:
- qWarning().nospace() << "UNKNOWN";
- break;
- }
- }
-}
-
-/*!
- Return true if this is a valid script binding, otherwise returns false.
- */
-bool QmlBasicScript::isValid() const
-{
- return d != 0;
-}
-
-bool QmlBasicScript::compile(const Expression &expression)
-{
- if (!expression.expression.asAST()) return false;
-
- QByteArray expr = expression.expression.asScript().toUtf8();
- const char *src = expr.constData();
-
- QmlBasicScriptCompiler bsc;
- bsc.script = this;
- bsc.context = expression.context;
- bsc.component = expression.component;
- bsc.ids = expression.ids;
-
- if (d) {
- if (flags & QmlBasicScriptPrivate::OwnData)
- free(d);
- d = 0;
- flags = 0;
- }
-
- if (bsc.compile(expression.expression.asAST())) {
- int len = ::strlen(src);
- flags = QmlBasicScriptPrivate::OwnData;
- int size = sizeof(QmlBasicScriptPrivate) +
- bsc.bytecode.count() * sizeof(ScriptInstruction) +
- QmlBasicScriptPrivate::alignRound(bsc.data.count() + len + 1);
- d = (QmlBasicScriptPrivate *) malloc(size);
- d->size = size;
- d->stateSize = bsc.stateSize;
- d->instructionCount = bsc.bytecode.count();
- d->exprLen = len;
- ::memcpy((char *)d->expr(), src, len + 1);
- for (int ii = 0; ii < d->instructionCount; ++ii)
- d->instructions()[ii] = bsc.bytecode.at(ii);
- ::memcpy((char *)d->data(), bsc.data.constData(), bsc.data.count());
- }
-
- if (d && qmlBasicScriptDump())
- dump();
- return d != 0;
-}
-
-bool QmlBasicScriptCompiler::compile(QmlJS::AST::Node *node)
-{
- return compileExpression(node);
-}
-
-bool QmlBasicScriptCompiler::tryConstant(QmlJS::AST::Node *node)
-{
- if (node->kind == AST::Node::Kind_TrueLiteral ||
- node->kind == AST::Node::Kind_FalseLiteral)
- return true;
-
- if (node->kind == AST::Node::Kind_NumericLiteral) {
- AST::NumericLiteral *lit = static_cast<AST::NumericLiteral *>(node);
-
- return double(int(lit->value)) == lit->value;
- }
-
- return false;
-}
-
-bool QmlBasicScriptCompiler::parseConstant(QmlJS::AST::Node *node)
-{
- ScriptInstruction instr;
-
- if (node->kind == AST::Node::Kind_NumericLiteral) {
- AST::NumericLiteral *lit = static_cast<AST::NumericLiteral *>(node);
- instr.type = ScriptInstruction::Int;
- instr.integer.value = int(lit->value);
- } else {
- instr.type = ScriptInstruction::Bool;
- instr.boolean.value = node->kind == AST::Node::Kind_TrueLiteral;
- }
-
- bytecode.append(instr);
-
- return true;
-}
-
-bool QmlBasicScriptCompiler::tryName(QmlJS::AST::Node *node)
-{
- return node->kind == AST::Node::Kind_IdentifierExpression ||
- node->kind == AST::Node::Kind_FieldMemberExpression;
-}
-
-bool QmlBasicScriptCompiler::buildName(QStringList &name,
- QmlJS::AST::Node *node)
-{
- if (node->kind == AST::Node::Kind_IdentifierExpression) {
- name << static_cast<AST::IdentifierExpression*>(node)->name->asString();
- } else if (node->kind == AST::Node::Kind_FieldMemberExpression) {
- AST::FieldMemberExpression *expr =
- static_cast<AST::FieldMemberExpression *>(node);
-
- if (!buildName(name, expr->base))
- return false;
-
- name << expr->name->asString();
- } else {
- return false;
- }
-
- return true;
-}
-
-const QMetaObject *
-QmlBasicScriptCompiler::fetch(int type, const QMetaObject *mo, int idx)
-{
- ScriptInstruction instr;
- *((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());
-}
-
-bool QmlBasicScriptCompiler::parseName(AST::Node *node)
-{
- QStringList nameParts;
- if (!buildName(nameParts, node))
- return false;
-
- 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 {
- return false;
- }
- } else {
-
- if (!name.at(0).isLower())
- return false;
-
- const QMetaObject *mo = 0;
- if (absType)
- mo = absType->metaObject();
- else if(metaType)
- mo = metaType;
- else
- 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;
- }
-
- }
- }
-
- return true;
-}
-
-bool QmlBasicScriptCompiler::compileExpression(QmlJS::AST::Node *node)
-{
- if (tryBinaryExpression(node))
- return compileBinaryExpression(node);
- else if (tryConstant(node))
- return parseConstant(node);
- else if (tryName(node))
- return parseName(node);
- else
- return false;
-}
-
-bool QmlBasicScriptCompiler::tryBinaryExpression(AST::Node *node)
-{
- if (node->kind == AST::Node::Kind_BinaryExpression) {
- AST::BinaryExpression *expr =
- static_cast<AST::BinaryExpression *>(node);
-
- if (expr->op == QSOperator::Equal)
- return true;
- }
- return false;
-}
-
-bool QmlBasicScriptCompiler::compileBinaryExpression(AST::Node *node)
-{
- if (node->kind == AST::Node::Kind_BinaryExpression) {
- AST::BinaryExpression *expr =
- static_cast<AST::BinaryExpression *>(node);
-
- if (!compileExpression(expr->left)) return false;
- if (!compileExpression(expr->right)) return false;
-
- ScriptInstruction instr;
- switch (expr->op) {
- case QSOperator::Equal:
- instr.type = ScriptInstruction::Equals;
- break;
- default:
- return false;
- }
-
- bytecode.append(instr);
- return true;
- }
- return false;
-}
-
-/*!
- Run the script in \a context and return the result.
- */
-QVariant QmlBasicScript::run(QmlContext *context, QObject *me)
-{
- if (!isValid())
- return QVariant();
-
- QmlContextPrivate *contextPrivate = context->d_func();
- QmlEnginePrivate *enginePrivate = QmlEnginePrivate::get(context->engine());
-
- QStack<QVariant> stack;
-
- for (int idx = 0; idx < d->instructionCount; ++idx) {
- const ScriptInstruction &instr = d->instructions()[idx];
-
- switch(instr.type) {
- case ScriptInstruction::LoadIdObject:
- {
- stack.push(QVariant::fromValue(contextPrivate->idValues[instr.fetch.idx].data()));
- enginePrivate->capturedProperties <<
- QmlEnginePrivate::CapturedProperty(context, -1, contextPrivate->notifyIndex + instr.fetch.idx);
- }
- break;
-
- case ScriptInstruction::FetchContextConstant:
- {
- stack.push(fetch_value(me, instr.constant.idx, instr.constant.type));
- if (me && instr.constant.notify != 0)
- enginePrivate->capturedProperties <<
- QmlEnginePrivate::CapturedProperty(me, instr.constant.idx, instr.constant.notify);
- }
- break;
-
- case ScriptInstruction::FetchRootConstant:
- {
- QObject *obj = contextPrivate->defaultObjects.at(0);
-
- stack.push(fetch_value(obj, instr.constant.idx, instr.constant.type));
- if (obj && instr.constant.notify != 0)
- enginePrivate->capturedProperties <<
- QmlEnginePrivate::CapturedProperty(obj, instr.constant.idx, instr.constant.notify);
- }
- break;
-
- case ScriptInstruction::FetchConstant:
- {
- QVariant o = stack.pop();
- QObject *obj = *(QObject **)o.constData();
-
- stack.push(fetch_value(obj, instr.constant.idx, instr.constant.type));
- if (obj && instr.constant.notify != 0)
- enginePrivate->capturedProperties <<
- QmlEnginePrivate::CapturedProperty(obj, instr.constant.idx, instr.constant.notify);
- }
- 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();
- QVariant lhs = stack.pop();
-
- stack.push(rhs == lhs);
- }
- break;
- default:
- break;
- }
- }
-
- if (stack.isEmpty())
- return QVariant();
- else
- return stack.top();
-}
-
-bool QmlBasicScript::isSingleIdFetch() const
-{
- if (!isValid())
- return false;
-
- return d->instructionCount == 1 &&
- d->instructions()[0].type == ScriptInstruction::LoadIdObject;
-}
-
-int QmlBasicScript::singleIdFetchIndex() const
-{
- if (!isSingleIdFetch())
- return -1;
-
- return d->instructions()[0].fetch.idx;
-}
-
-/*!
- Return a pointer to the script's compile data, or null if there is no data.
- */
-const char *QmlBasicScript::compileData() const
-{
- return (const char *)d;
-}
-
-/*!
- Return the size of the script's compile data, or zero if there is no data.
- The size will always be a multiple of 4.
- */
-unsigned int QmlBasicScript::compileDataSize() const
-{
- if (d)
- return d->size;
- else
- return 0;
-}
-
-QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlbasicscript_p.h b/src/declarative/qml/qmlbasicscript_p.h
deleted file mode 100644
index c4b436d..0000000
--- a/src/declarative/qml/qmlbasicscript_p.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** No Commercial Usage
-** This file contains pre-release code and may not be distributed.
-** You may use this file in accordance with the terms and conditions
-** contained in the Technology Preview License Agreement accompanying
-** this package.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 2.1 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 2.1 requirements
-** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** If you have questions regarding the use of this file, please contact
-** Nokia at qt-info@nokia.com.
-**
-**
-**
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QMLBASICSCRIPT_P_H
-#define QMLBASICSCRIPT_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists purely as an
-// implementation detail. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include "qmlparser_p.h"
-#include "qmlengine_p.h"
-
-#include <QtCore/QList>
-#include <QtCore/QByteArray>
-#include <QtCore/QVariant>
-
-QT_BEGIN_HEADER
-
-QT_BEGIN_NAMESPACE
-
-class QmlRefCount;
-class QmlContext;
-class QmlBasicScriptPrivate;
-class QmlBasicScriptNodeCache;
-class QmlBasicScript
-{
-public:
- QmlBasicScript();
- ~QmlBasicScript();
-
- void load(const char *, QmlRefCount * = 0);
-
- // Always 4-byte aligned
- const char *compileData() const;
- unsigned int compileDataSize() const;
-
- QByteArray expression() const;
-
- struct Expression
- {
- QmlParser::Object *component;
- QmlParser::Object *context;
- QmlParser::Property *property;
- QmlParser::Variant expression;
- QHash<QString, QmlParser::Object *> ids;
- QmlEnginePrivate::Imports imports;
- };
-
- bool compile(const Expression &);
- bool isValid() const;
-
- void clear();
-
- void dump();
-
- QVariant run(QmlContext *, QObject *);
-
- bool isSingleIdFetch() const;
- int singleIdFetchIndex() const;
-
-private:
- int flags;
- QmlBasicScriptPrivate *d;
- QmlRefCount *rc;
-};
-
-QT_END_NAMESPACE
-
-QT_END_HEADER
-
-#endif // QMLBASICSCRIPT_P_H
diff --git a/src/declarative/qml/qmlbindingoptimizations.cpp b/src/declarative/qml/qmlbindingoptimizations.cpp
index beee3c9..1e49636 100644
--- a/src/declarative/qml/qmlbindingoptimizations.cpp
+++ b/src/declarative/qml/qmlbindingoptimizations.cpp
@@ -170,91 +170,4 @@ void QmlOptimizedBindings::run(Binding *binding)
}
}
-/*
- The QmlBinding_Id optimization handles expressions of the type:
-
- property: id
-
- where id is a local context id, and property is an object property.
- Coercian between id and property must be checked outside the QmlBinding_Id -
- it assumes that they coerce successfully.
-
- The QmlBinding_Id class avoids any signal slot connections, through the
- special "bindings" linked list maintained in the
- QmlContextPrivate::ContextGuard instance for each id object.
-*/
-QmlBinding_Id::QmlBinding_Id(QObject *object, int propertyIdx,
- QmlContext *context, int id)
-: m_prev(0), m_next(0), m_object(object), m_propertyIdx(propertyIdx), m_id(id)
-{
- QmlAbstractExpression::setContext(context);
-}
-
-QmlBinding_Id::~QmlBinding_Id()
-{
- removeFromContext();
-}
-
-void QmlBinding_Id::setEnabled(bool e, QmlMetaProperty::WriteFlags flags)
-{
- if (e) {
- addToObject(m_object);
- update(flags);
- } else {
- removeFromObject();
- }
-
- QmlAbstractBinding::setEnabled(e, flags);
-}
-
-int QmlBinding_Id::propertyIndex()
-{
- return m_propertyIdx;
-}
-
-void QmlBinding_Id::update(QmlMetaProperty::WriteFlags flags)
-{
- QmlContextPrivate *ctxtPriv =
- static_cast<QmlContextPrivate *>(QObjectPrivate::get(context()));
-
- if (ctxtPriv) {
-
- if (!m_prev) {
- m_next = ctxtPriv->idValues[m_id].bindings;
- if (m_next) m_next->m_prev = &m_next;
-
- m_prev = &ctxtPriv->idValues[m_id].bindings;
- ctxtPriv->idValues[m_id].bindings = this;
- }
-
- QObject *o = ctxtPriv->idValues[m_id].data();
- int status = -1;
- void *a[] = { &o, 0, &status, &flags };
- QMetaObject::metacall(m_object, QMetaObject::WriteProperty,
- m_propertyIdx, a);
- }
-}
-
-void QmlBinding_Id::removeFromContext()
-{
- if (m_prev) {
- *m_prev = m_next;
- if (m_next) m_next->m_prev = m_prev;
- m_next = 0;
- m_prev = 0;
- }
-}
-
-void QmlBinding_Id::reset()
-{
- removeFromContext();
-
- QObject *o = 0;
- int status = -1;
- QmlMetaProperty::WriteFlags flags = QmlMetaProperty::DontRemoveBinding;
- void *a[] = { &o, 0, &status, &flags };
- QMetaObject::metacall(m_object, QMetaObject::WriteProperty,
- m_propertyIdx, a);
-}
-
QT_END_NAMESPACE
diff --git a/src/declarative/qml/qmlbindingoptimizations_p.h b/src/declarative/qml/qmlbindingoptimizations_p.h
index 59a0cc6..42b7d17 100644
--- a/src/declarative/qml/qmlbindingoptimizations_p.h
+++ b/src/declarative/qml/qmlbindingoptimizations_p.h
@@ -55,7 +55,6 @@
#include "qmlexpression_p.h"
#include "qmlbinding.h"
-#include "qmlbasicscript_p.h"
#include "qmlbindingvme_p.h"
QT_BEGIN_HEADER
@@ -102,32 +101,6 @@ private:
static int methodCount;
};
-class QmlBinding_Id : public QmlAbstractExpression,
- public QmlAbstractBinding
-{
-public:
- QmlBinding_Id(QObject *object, int propertyIdx,
- QmlContext *context, int id);
- virtual ~QmlBinding_Id();
-
- // Inherited from QmlAbstractBinding
- virtual void setEnabled(bool, QmlMetaProperty::WriteFlags flags);
- virtual int propertyIndex();
- virtual void update(QmlMetaProperty::WriteFlags flags);
-
- void reset();
-
-private:
- void removeFromContext();
-
- QmlBinding_Id **m_prev;
- QmlBinding_Id *m_next;
-
- QObject *m_object;
- int m_propertyIdx;
- int m_id;
-};
-
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/declarative/qml/qmlbindingvme.cpp b/src/declarative/qml/qmlbindingvme.cpp
index 5efaaca..47f02b2 100644
--- a/src/declarative/qml/qmlbindingvme.cpp
+++ b/src/declarative/qml/qmlbindingvme.cpp
@@ -52,6 +52,22 @@ QT_BEGIN_NAMESPACE
using namespace QmlJS;
+QmlBindingVME::Config::Subscription::Signal *QmlBindingVME::Config::Subscription::signal()
+{
+ if (type == IdType) ((Id *)idData)->~Id();
+ if (type != SignalType) new (signalData) Signal;
+ type = SignalType;
+ return (Signal *)signalData;
+}
+
+QmlBindingVME::Config::Subscription::Id *QmlBindingVME::Config::Subscription::id()
+{
+ if (type == SignalType) ((Signal *)signalData)->~Signal();
+ if (type != IdType) new (idData) Id;
+ type = IdType;
+ return (Id *)idData;
+}
+
namespace {
// Supported types: int, qreal, QString (needs constr/destr), QObject*, bool
struct Register {
@@ -395,10 +411,53 @@ struct QmlBindingCompilerPrivate
QByteArray buildExceptionData() const;
};
+inline void unsubscribe(int subIndex, QmlBindingVME::Config *config)
+{
+ QmlBindingVME::Config::Subscription *sub = (config->subscriptions + subIndex);
+ if (sub->isSignal()) {
+ QmlBindingVME::Config::Subscription::Signal *s = sub->signal();
+ if (s->source)
+#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2))
+ QMetaObject::disconnectOne(s->source, s->notifyIndex,
+ config->target, config->targetSlot + subIndex);
+#else
+ // QTBUG-6781
+ QMetaObject::disconnect(s->source, s->notifyIndex,
+ config->target, config->targetSlot + subIndex);
+#endif
+ } else if (sub->isId()) {
+ sub->id()->reset();
+ }
+}
+
+inline void subscribeId(QmlContextPrivate *p, int idIndex,
+ int subIndex, QmlBindingVME::Config *config)
+{
+ unsubscribe(subIndex, config);
+
+ if (p->idValues[idIndex]) {
+ QmlBindingVME::Config::Subscription *sub = (config->subscriptions + subIndex);
+ QmlBindingVME::Config::Subscription::Id *i = sub->id();
+
+ i->next = p->idValues[idIndex].bindings;
+ i->prev = &p->idValues[idIndex].bindings;
+ p->idValues[idIndex].bindings = i;
+ if (i->next) i->next->prev = &i->next;
+
+ i->target = config->target;
+ i->methodIndex = config->targetSlot + subIndex;
+ }
+}
+
inline void subscribe(QObject *o, int notifyIndex,
int subIndex, QmlBindingVME::Config *config)
{
- QmlBindingVME::Config::Subscription *s = config->subscriptions + subIndex;
+ QmlBindingVME::Config::Subscription *sub = (config->subscriptions + subIndex);
+
+ if (sub->isId())
+ unsubscribe(subIndex, config);
+
+ QmlBindingVME::Config::Subscription::Signal *s = sub->signal();
if (o != s->source || notifyIndex != s->notifyIndex) {
if (s->source)
#if (QT_VERSION >= QT_VERSION_CHECK(4, 6, 2))
@@ -690,10 +749,14 @@ void QmlBindingVME::init(const char *programData, Config *config,
}
static void throwException(int id, QmlDelayedError *error,
- Program *program, QmlContextPrivate *context)
+ Program *program, QmlContextPrivate *context,
+ const QString &description = QString())
{
error->error.setUrl(context->url);
- error->error.setDescription("TypeError: Result of expression is not an object");
+ if (description.isEmpty())
+ error->error.setDescription(QLatin1String("TypeError: Result of expression is not an object"));
+ else
+ error->error.setDescription(description);
if (id != 0xFF) {
quint64 e = *((quint64 *)(program->data() + program->exceptionDataOffset) + id);
error->error.setLine((e >> 32) & 0xFFFFFFFF);
@@ -728,18 +791,16 @@ void QmlBindingVME::run(const char *programData, int instrIndex,
break;
case Instr::SubscribeId:
+ subscribeId(context, instr->subscribe.index, instr->subscribe.offset, config);
+ break;
+
case Instr::Subscribe:
{
QObject *o = 0;
int notifyIndex = instr->subscribe.index;
- if (instr->common.type == Instr::SubscribeId) {
- o = QmlContextPrivate::get(context);
- notifyIndex += context->notifyIndex;
- } else {
- const Register &object = registers[instr->subscribe.reg];
- if (!object.isUndefined()) o = object.getQObject();
- }
+ const Register &object = registers[instr->subscribe.reg];
+ if (!object.isUndefined()) o = object.getQObject();
subscribe(o, instr->subscribe.index, instr->subscribe.offset, config);
}
break;
@@ -998,7 +1059,8 @@ void QmlBindingVME::run(const char *programData, int instrIndex,
{
Register &data = registers[instr->store.reg];
if (data.isUndefined()) {
- throwException(instr->store.exceptionId, error, program, context);
+ throwException(instr->store.exceptionId, error, program, context,
+ QLatin1String("Unable to assign undefined value"));
return;
}
@@ -1374,7 +1436,7 @@ bool QmlBindingCompilerPrivate::compile(QmlJS::AST::Node *node)
instr.store.output = 0;
instr.store.index = destination->index;
instr.store.reg = convertReg;
- instr.store.exceptionId = 0xFF;
+ instr.store.exceptionId = exceptionId(node->expressionCast());
bytecode << instr;
if (destination->type == QVariant::String) {
@@ -1429,6 +1491,7 @@ bool QmlBindingCompilerPrivate::compile(QmlJS::AST::Node *node)
instr.store.output = 0;
instr.store.index = destination->index;
instr.store.reg = type.reg;
+ instr.store.exceptionId = exceptionId(node->expressionCast());
bytecode << instr;
releaseReg(type.reg);
@@ -2317,7 +2380,7 @@ bool QmlBindingCompilerPrivate::subscriptionNeutral(const QSet<QString> &base,
quint8 QmlBindingCompilerPrivate::exceptionId(QmlJS::AST::ExpressionNode *n)
{
quint8 rv = 0xFF;
- if (exceptions.count() < 0xFF) {
+ if (n && exceptions.count() < 0xFF) {
rv = (quint8)exceptions.count();
QmlJS::AST::SourceLocation l = n->firstSourceLocation();
quint64 e = l.startLine;
@@ -2349,8 +2412,7 @@ bool QmlBindingCompiler::isValid() const
/*
-1 on failure, otherwise the binding index to use.
*/
-int QmlBindingCompiler::compile(const QmlBasicScript::Expression &expression,
- QmlEnginePrivate *engine)
+int QmlBindingCompiler::compile(const Expression &expression, QmlEnginePrivate *engine)
{
if (!expression.expression.asAST()) return false;
diff --git a/src/declarative/qml/qmlbindingvme_p.h b/src/declarative/qml/qmlbindingvme_p.h
index 629a979..01280f0 100644
--- a/src/declarative/qml/qmlbindingvme_p.h
+++ b/src/declarative/qml/qmlbindingvme_p.h
@@ -54,8 +54,8 @@
//
#include <QtCore/qglobal.h>
-#include <private/qmlbasicscript_p.h>
#include <private/qscriptdeclarativeclass_p.h>
+#include "qmlexpression_p.h"
#include "qmlguard_p.h"
QT_BEGIN_HEADER
@@ -74,8 +74,32 @@ public:
int targetSlot;
struct Subscription {
- QmlGuard<QObject> source;
- int notifyIndex;
+ struct Signal {
+ QmlGuard<QObject> source;
+ int notifyIndex;
+ };
+
+ struct Id {
+ inline Id();
+ inline ~Id();
+ inline void reset();
+ Id *next;
+ Id**prev;
+ QObject *target;
+ int methodIndex;
+ };
+
+ enum { InvalidType, SignalType, IdType } type;
+ inline Subscription();
+ inline ~Subscription();
+ bool isSignal() const { return type == SignalType; }
+ bool isId() const { return type == IdType; }
+ inline Signal *signal();
+ inline Id *id();
+ union {
+ char signalData[sizeof(Signal)];
+ char idData[sizeof(Id)];
+ };
};
Subscription *subscriptions;
QScriptDeclarativeClass::PersistentIdentifier *identifiers;
@@ -89,6 +113,37 @@ public:
static void dump(const char *);
};
+QmlBindingVME::Config::Subscription::Subscription()
+: type(InvalidType)
+{
+}
+
+QmlBindingVME::Config::Subscription::~Subscription()
+{
+ if (type == SignalType) ((Signal *)signalData)->~Signal();
+ else if (type == IdType) ((Id *)idData)->~Id();
+}
+
+QmlBindingVME::Config::Subscription::Id::Id()
+: next(0), prev(0), target(0), methodIndex(-1)
+{
+}
+
+QmlBindingVME::Config::Subscription::Id::~Id()
+{
+ reset();
+}
+
+void QmlBindingVME::Config::Subscription::Id::reset()
+{
+ if (next) next->prev = prev;
+ if (prev) *prev = next;
+ next = 0;
+ prev = 0;
+ target = 0;
+ methodIndex = -1;
+}
+
class QmlBindingCompilerPrivate;
class QmlBindingCompiler
{
@@ -99,8 +154,18 @@ public:
// Returns true if bindings were compiled
bool isValid() const;
+ struct Expression
+ {
+ QmlParser::Object *component;
+ QmlParser::Object *context;
+ QmlParser::Property *property;
+ QmlParser::Variant expression;
+ QHash<QString, QmlParser::Object *> ids;
+ QmlEnginePrivate::Imports imports;
+ };
+
// -1 on failure, otherwise the binding index to use
- int compile(const QmlBasicScript::Expression &, QmlEnginePrivate *);
+ int compile(const Expression &, QmlEnginePrivate *);
// Returns the compiled program
QByteArray program() const;
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp
index 1368324..5937734 100644
--- a/src/declarative/qml/qmlcompiler.cpp
+++ b/src/declarative/qml/qmlcompiler.cpp
@@ -47,7 +47,6 @@
#include "qmlpropertyvaluesource.h"
#include "qmlcomponent.h"
#include "qmetaobjectbuilder_p.h"
-#include "qmlbasicscript_p.h"
#include "qmlstringconverters_p.h"
#include "qmlengine_p.h"
#include "qmlengine.h"
@@ -2558,23 +2557,6 @@ void QmlCompiler::genBindingAssignment(QmlParser::Value *binding,
}
QmlInstruction store;
-
- QmlBasicScript bs;
- if (ref.dataType == BindingReference::BasicScript)
- bs.load(ref.compiledData.constData() + sizeof(quint32));
-
- if (bs.isSingleIdFetch()) {
- int idIndex = bs.singleIdFetchIndex();
- QmlParser::Object *idObj = compileState.idIndexes.value(idIndex);
- if (canCoerce(prop->type, idObj)) {
- store.type = QmlInstruction::StoreIdOptBinding;
- store.assignIdOptBinding.id = idIndex;
- store.assignIdOptBinding.property = prop->index;
- output->bytecode << store;
- return;
- }
- }
-
store.type = QmlInstruction::StoreBinding;
store.assignBinding.value = output->indexForByteArray(ref.compiledData);
store.assignBinding.context = ref.bindingContext.stack;
@@ -2628,7 +2610,7 @@ bool QmlCompiler::completeComponentBuild()
COMPILE_CHECK(buildDynamicMeta(aliasObject, ResolveAliases));
}
- QmlBasicScript::Expression expr;
+ QmlBindingCompiler::Expression expr;
expr.component = compileState.root;
expr.ids = compileState.ids;
@@ -2637,15 +2619,12 @@ bool QmlCompiler::completeComponentBuild()
for (QHash<QmlParser::Value*,BindingReference>::Iterator iter = compileState.bindings.begin(); iter != compileState.bindings.end(); ++iter) {
BindingReference &binding = *iter;
- QmlBasicScript bs;
expr.context = binding.bindingContext.object;
expr.property = binding.property;
expr.expression = binding.expression;
expr.imports = unit->imports;
- bs.compile(expr);
-
- if (qmlExperimental() && (!bs.isValid() || !bs.isSingleIdFetch())) {
+ if (qmlExperimental()) {
int index = bindingCompiler.compile(expr, QmlEnginePrivate::get(engine));
if (index != -1) {
qWarning() << "Accepted for optimization:" << qPrintable(expr.expression.asScript());
@@ -2658,50 +2637,37 @@ bool QmlCompiler::completeComponentBuild()
}
}
- quint32 type;
- if (bs.isValid()) {
- binding.compiledData =
- QByteArray(bs.compileData(), bs.compileDataSize());
- type = QmlExpressionPrivate::BasicScriptEngineData;
- binding.dataType = BindingReference::BasicScript;
+ binding.dataType = BindingReference::QtScript;
- componentStat.optimizedBindings++;
- } else {
- type = QmlExpressionPrivate::PreTransformedQtScriptData;
- binding.dataType = BindingReference::QtScript;
-
- // Pre-rewrite the expression
- QString expression = binding.expression.asScript();
-
- // ### Optimize
- QmlRewrite::SharedBindingTester sharableTest;
- bool isSharable = sharableTest.isSharable(expression);
-
- QmlRewrite::RewriteBinding rewriteBinding;
- expression = rewriteBinding(expression);
-
- quint32 length = expression.length();
- quint32 pc;
-
- if (isSharable) {
- pc = output->cachedClosures.count();
- pc |= 0x80000000;
- output->cachedClosures.append(0);
- } else {
- pc = output->cachedPrograms.length();
- output->cachedPrograms.append(0);
- }
+ // Pre-rewrite the expression
+ QString expression = binding.expression.asScript();
- binding.compiledData =
- QByteArray((const char *)&pc, sizeof(quint32)) +
- QByteArray((const char *)&length, sizeof(quint32)) +
- QByteArray((const char *)expression.constData(),
- expression.length() * sizeof(QChar));
+ // ### Optimize
+ QmlRewrite::SharedBindingTester sharableTest;
+ bool isSharable = sharableTest.isSharable(expression);
+
+ QmlRewrite::RewriteBinding rewriteBinding;
+ expression = rewriteBinding(expression);
- componentStat.scriptBindings++;
+ quint32 length = expression.length();
+ quint32 pc;
+
+ if (isSharable) {
+ pc = output->cachedClosures.count();
+ pc |= 0x80000000;
+ output->cachedClosures.append(0);
+ } else {
+ pc = output->cachedPrograms.length();
+ output->cachedPrograms.append(0);
}
- binding.compiledData.prepend(QByteArray((const char *)&type,
- sizeof(quint32)));
+
+ binding.compiledData =
+ QByteArray((const char *)&pc, sizeof(quint32)) +
+ QByteArray((const char *)&length, sizeof(quint32)) +
+ QByteArray((const char *)expression.constData(),
+ expression.length() * sizeof(QChar));
+
+ componentStat.scriptBindings++;
}
if (bindingCompiler.isValid()) {
diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h
index 732fbad..f3f266b 100644
--- a/src/declarative/qml/qmlcompiler_p.h
+++ b/src/declarative/qml/qmlcompiler_p.h
@@ -279,7 +279,7 @@ private:
QmlParser::Property *property;
QmlParser::Value *value;
- enum DataType { QtScript, BasicScript, Experimental };
+ enum DataType { QtScript, Experimental };
DataType dataType;
int compiledIndex;
diff --git a/src/declarative/qml/qmlcontext.cpp b/src/declarative/qml/qmlcontext.cpp
index e7ac864..f97f142 100644
--- a/src/declarative/qml/qmlcontext.cpp
+++ b/src/declarative/qml/qmlcontext.cpp
@@ -105,8 +105,12 @@ void QmlContextPrivate::destroyed(ContextGuard *guard)
if (parent && QObjectPrivate::get(parent)->wasDeleted)
return;
- while(guard->bindings)
+ while(guard->bindings) {
+ QObject *o = guard->bindings->target;
+ int mi = guard->bindings->methodIndex;
guard->bindings->reset();
+ if (o) o->qt_metacall(QMetaObject::InvokeMetaMethod, mi, 0);
+ }
for (int ii = 0; ii < idValueCount; ++ii) {
if (&idValues[ii] == guard) {
diff --git a/src/declarative/qml/qmlcontext.h b/src/declarative/qml/qmlcontext.h
index 7547004..bf389a0 100644
--- a/src/declarative/qml/qmlcontext.h
+++ b/src/declarative/qml/qmlcontext.h
@@ -88,7 +88,6 @@ private:
friend class QmlEnginePrivate;
friend class QmlExpression;
friend class QmlExpressionPrivate;
- friend class QmlBasicScript;
friend class QmlContextScriptClass;
friend class QmlObjectScriptClass;
friend class QmlComponent;
diff --git a/src/declarative/qml/qmlcontext_p.h b/src/declarative/qml/qmlcontext_p.h
index e682ee2..ffb4298 100644
--- a/src/declarative/qml/qmlcontext_p.h
+++ b/src/declarative/qml/qmlcontext_p.h
@@ -59,6 +59,7 @@
#include "qmlengine_p.h"
#include "qmlintegercache_p.h"
#include "qmltypenamecache_p.h"
+#include "qmlbindingvme_p.h"
#include <QtCore/qhash.h>
#include <QtScript/qscriptvalue.h>
@@ -117,7 +118,7 @@ public:
{
ContextGuard() : priv(0), bindings(0) {}
QmlContextPrivate *priv;
- QmlBinding_Id *bindings;
+ QmlBindingVME::Config::Subscription::Id *bindings;
ContextGuard &operator=(QObject *obj) {
(QmlGuard<QObject>&)*this = obj; return *this;
}
diff --git a/src/declarative/qml/qmlengine.cpp b/src/declarative/qml/qmlengine.cpp
index 122eb07..5a40468 100644
--- a/src/declarative/qml/qmlengine.cpp
+++ b/src/declarative/qml/qmlengine.cpp
@@ -46,7 +46,6 @@
#include "qmlcompiler_p.h"
#include "qmlglobalscriptclass_p.h"
#include "qml.h"
-#include "qmlbasicscript_p.h"
#include "qmlcontext.h"
#include "qmlexpression.h"
#include "qmlcomponent.h"
diff --git a/src/declarative/qml/qmlexpression.cpp b/src/declarative/qml/qmlexpression.cpp
index dcc9c30..3e8d71a 100644
--- a/src/declarative/qml/qmlexpression.cpp
+++ b/src/declarative/qml/qmlexpression.cpp
@@ -114,52 +114,46 @@ void QmlExpressionPrivate::init(QmlContext *ctxt, void *expr, QmlRefCount *rc,
data->line = lineNumber;
quint32 *exprData = (quint32 *)expr;
- Q_ASSERT(*exprData == BasicScriptEngineData ||
- *exprData == PreTransformedQtScriptData);
- if (*exprData == BasicScriptEngineData) {
- data->sse.load((const char *)(exprData + 1), rc);
- } else {
- QmlCompiledData *dd = (QmlCompiledData *)rc;
+ QmlCompiledData *dd = (QmlCompiledData *)rc;
- data->expressionRewritten = true;
- data->expression = QString::fromRawData((QChar *)(exprData + 3), exprData[2]);
+ data->expressionRewritten = true;
+ data->expression = QString::fromRawData((QChar *)(exprData + 2), exprData[1]);
- int progIdx = *(exprData + 1);
- bool isShared = progIdx & 0x80000000;
- progIdx &= 0x7FFFFFFF;
+ int progIdx = *(exprData);
+ bool isShared = progIdx & 0x80000000;
+ progIdx &= 0x7FFFFFFF;
- QmlEngine *engine = ctxt->engine();
- QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
- QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
+ QmlEngine *engine = ctxt->engine();
+ QmlEnginePrivate *ep = QmlEnginePrivate::get(engine);
+ QScriptEngine *scriptEngine = QmlEnginePrivate::getScriptEngine(engine);
- if (isShared) {
+ if (isShared) {
- if (!dd->cachedClosures.at(progIdx)) {
- QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
- scriptContext->pushScope(ep->contextClass->newSharedContext());
- dd->cachedClosures[progIdx] = new QScriptValue(scriptEngine->evaluate(data->expression, data->url, data->line));
- scriptEngine->popContext();
- }
+ if (!dd->cachedClosures.at(progIdx)) {
+ QScriptContext *scriptContext = QScriptDeclarativeClass::pushCleanContext(scriptEngine);
+ scriptContext->pushScope(ep->contextClass->newSharedContext());
+ dd->cachedClosures[progIdx] = new QScriptValue(scriptEngine->evaluate(data->expression, data->url, data->line));
+ scriptEngine->popContext();
+ }
- data->expressionFunction = *dd->cachedClosures.at(progIdx);
- data->isShared = true;
- data->expressionFunctionValid = true;
+ data->expressionFunction = *dd->cachedClosures.at(progIdx);
+ data->isShared = true;
+ data->expressionFunctionValid = true;
- } else {
+ } else {
#if !defined(Q_OS_SYMBIAN) //XXX Why doesn't this work?
- if (!dd->cachedPrograms.at(progIdx)) {
- dd->cachedPrograms[progIdx] =
- new QScriptProgram(data->expression, data->url, data->line);
- }
+ if (!dd->cachedPrograms.at(progIdx)) {
+ dd->cachedPrograms[progIdx] =
+ new QScriptProgram(data->expression, data->url, data->line);
+ }
- data->expressionFunction = evalInObjectScope(ctxt, me, *dd->cachedPrograms.at(progIdx));
+ data->expressionFunction = evalInObjectScope(ctxt, me, *dd->cachedPrograms.at(progIdx));
#else
- data->expressionFunction = evalInObjectScope(ctxt, me, data->expression);
+ data->expressionFunction = evalInObjectScope(ctxt, me, data->expression);
#endif
- data->expressionFunctionValid = true;
- }
+ data->expressionFunctionValid = true;
}
data->QmlAbstractExpression::setContext(ctxt);
@@ -272,10 +266,7 @@ QmlContext *QmlExpression::context() const
QString QmlExpression::expression() const
{
Q_D(const QmlExpression);
- if (d->data->sse.isValid())
- return QString::fromUtf8(d->data->sse.expression());
- else
- return d->data->expression;
+ return d->data->expression;
}
/*!
@@ -299,19 +290,6 @@ void QmlExpression::setExpression(const QString &expression)
d->data->expressionFunctionValid = false;
d->data->expressionRewritten = false;
d->data->expressionFunction = QScriptValue();
-
- d->data->sse.clear();
-}
-
-QVariant QmlExpressionPrivate::evalSSE()
-{
-#ifdef Q_ENABLE_PERFORMANCE_LOG
- QmlPerfTimer<QmlPerf::BindValueSSE> perfsse;
-#endif
-
- QVariant rv = data->sse.run(data->context(), data->me);
-
- return rv;
}
void QmlExpressionPrivate::exceptionToError(QScriptEngine *scriptEngine,
@@ -456,7 +434,7 @@ QVariant QmlExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined)
return rv;
}
- if (!data->sse.isValid() && data->expression.isEmpty())
+ if (data->expression.isEmpty())
return rv;
#ifdef Q_ENABLE_PERFORMANCE_LOG
@@ -477,11 +455,7 @@ QVariant QmlExpressionPrivate::value(QObject *secondaryScope, bool *isUndefined)
QmlExpressionData *localData = data;
localData->addref();
- if (data->sse.isValid()) {
- rv = evalSSE();
- } else {
- rv = evalQtScript(secondaryScope, isUndefined);
- }
+ rv = evalQtScript(secondaryScope, isUndefined);
ep->currentExpression = lastCurrentExpression;
ep->captureProperties = lastCaptureProperties;
diff --git a/src/declarative/qml/qmlexpression.h b/src/declarative/qml/qmlexpression.h
index cc02d56..4df7641 100644
--- a/src/declarative/qml/qmlexpression.h
+++ b/src/declarative/qml/qmlexpression.h
@@ -58,7 +58,6 @@ class QmlRefCount;
class QmlEngine;
class QmlContext;
class QmlExpressionPrivate;
-class QmlBasicScript;
class Q_DECLARATIVE_EXPORT QmlExpression : public QObject
{
Q_OBJECT
diff --git a/src/declarative/qml/qmlexpression_p.h b/src/declarative/qml/qmlexpression_p.h
index 5be93f0..1fbb075 100644
--- a/src/declarative/qml/qmlexpression_p.h
+++ b/src/declarative/qml/qmlexpression_p.h
@@ -55,7 +55,6 @@
#include "qmlexpression.h"
-#include "qmlbasicscript_p.h"
#include "qmlengine_p.h"
#include "qmlguard_p.h"
@@ -120,7 +119,6 @@ public:
bool expressionRewritten:1;
QScriptValue expressionFunction;
- QmlBasicScript sse;
QObject *me;
bool trackChange;
@@ -160,18 +158,12 @@ public:
QmlExpressionPrivate(QmlExpressionData *);
~QmlExpressionPrivate();
- enum CompiledDataType {
- BasicScriptEngineData = 1,
- PreTransformedQtScriptData = 2
- };
-
void init(QmlContext *, const QString &, QObject *);
void init(QmlContext *, void *, QmlRefCount *, QObject *, const QString &, int);
QmlExpressionData *data;
QVariant value(QObject *secondaryScope = 0, bool *isUndefined = 0);
- QVariant evalSSE();
QVariant evalQtScript(QObject *secondaryScope, bool *isUndefined = 0);
void updateGuards(const QPODVector<QmlEnginePrivate::CapturedProperty> &properties);
diff --git a/src/declarative/qml/qmlinstruction.cpp b/src/declarative/qml/qmlinstruction.cpp
index 2ddad49..d99bf65 100644
--- a/src/declarative/qml/qmlinstruction.cpp
+++ b/src/declarative/qml/qmlinstruction.cpp
@@ -161,9 +161,6 @@ void QmlCompiledData::dump(QmlInstruction *instr, int idx)
case QmlInstruction::StoreCompiledBinding:
qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_COMPILED_BINDING\t" << instr->assignBinding.property << "\t" << instr->assignBinding.value << "\t" << instr->assignBinding.context;
break;
- case QmlInstruction::StoreIdOptBinding:
- qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_ID_OPT_BINDING\t" << instr->assignIdOptBinding.property << "\t" << instr->assignIdOptBinding.id;
- break;
case QmlInstruction::StoreValueSource:
qWarning().nospace() << idx << "\t\t" << line << "\t" << "STORE_VALUE_SOURCE\t" << instr->assignValueSource.property << "\t" << instr->assignValueSource.castValue;
break;
diff --git a/src/declarative/qml/qmlinstruction_p.h b/src/declarative/qml/qmlinstruction_p.h
index 44fa196..0639397 100644
--- a/src/declarative/qml/qmlinstruction_p.h
+++ b/src/declarative/qml/qmlinstruction_p.h
@@ -129,7 +129,6 @@ public:
StoreBinding, /* assignBinding */
StoreCompiledBinding, /* assignBinding */
- StoreIdOptBinding, /* assignIdOptBinding */
StoreValueSource, /* assignValueSource */
StoreValueInterceptor, /* assignValueInterceptor */
diff --git a/src/declarative/qml/qmlvme.cpp b/src/declarative/qml/qmlvme.cpp
index 06795a8..6b2e7af 100644
--- a/src/declarative/qml/qmlvme.cpp
+++ b/src/declarative/qml/qmlvme.cpp
@@ -627,23 +627,6 @@ QObject *QmlVME::run(QmlVMEStack<QObject *> &stack, QmlContext *ctxt,
}
break;
- case QmlInstruction::StoreIdOptBinding:
- {
- int coreIndex = instr.assignIdOptBinding.property;
- if (stack.count() == 1 && bindingSkipList.testBit(coreIndex))
- break;
-
- QObject *target = stack.top();
-
- QmlBinding_Id *bind =
- new QmlBinding_Id(target, instr.assignIdOptBinding.property,
- ctxt, instr.assignIdOptBinding.id);
- bindValues.append(bind);
- bind->m_mePtr = &bindValues.values[bindValues.count - 1];
- bind->addToObject(target);
- }
- break;
-
case QmlInstruction::StoreValueSource:
{
QObject *obj = stack.pop();