aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/qml/qdeclarativecompiledbindings.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/declarative/qml/qdeclarativecompiledbindings.cpp')
-rw-r--r--src/declarative/qml/qdeclarativecompiledbindings.cpp2906
1 files changed, 0 insertions, 2906 deletions
diff --git a/src/declarative/qml/qdeclarativecompiledbindings.cpp b/src/declarative/qml/qdeclarativecompiledbindings.cpp
deleted file mode 100644
index a6fcce4c99..0000000000
--- a/src/declarative/qml/qdeclarativecompiledbindings.cpp
+++ /dev/null
@@ -1,2906 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 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$
-**
-****************************************************************************/
-
-// #define COMPILEDBINDINGS_DEBUG
-// #define REGISTER_CLEANUP_DEBUG
-
-#include "private/qdeclarativecompiledbindings_p.h"
-
-#include <QtDeclarative/qdeclarativeinfo.h>
-#include <private/qdeclarativecontext_p.h>
-#include <private/qdeclarativejsast_p.h>
-#include <private/qdeclarativejsengine_p.h>
-#include <private/qdeclarativeexpression_p.h>
-#include <QtCore/qcoreapplication.h>
-#include <QtCore/qdebug.h>
-#include <QtCore/qnumeric.h>
-#include <private/qdeclarativeanchors_p_p.h>
-#include <private/qdeclarativeglobal_p.h>
-#include <private/qdeclarativefastproperties_p.h>
-#include <private/qdeclarativedebugtrace_p.h>
-
-QT_BEGIN_NAMESPACE
-
-DEFINE_BOOL_CONFIG_OPTION(qmlExperimental, QML_EXPERIMENTAL);
-DEFINE_BOOL_CONFIG_OPTION(qmlDisableOptimizer, QML_DISABLE_OPTIMIZER);
-DEFINE_BOOL_CONFIG_OPTION(qmlDisableFastProperties, QML_DISABLE_FAST_PROPERTIES);
-DEFINE_BOOL_CONFIG_OPTION(bindingsDump, QML_BINDINGS_DUMP);
-
-Q_GLOBAL_STATIC(QDeclarativeFastProperties, fastProperties);
-
-#if defined(Q_CC_GNU) && (!defined(Q_CC_INTEL) || __INTEL_COMPILER >= 1200)
-# define QML_THREADED_INTERPRETER
-#endif
-
-#define FOR_EACH_QML_INSTR(F) \
- F(Noop) /* Nop */ \
- F(BindingId) /* id */ \
- F(Subscribe) /* subscribe */ \
- F(SubscribeId) /* subscribe */ \
- F(FetchAndSubscribe) /* fetchAndSubscribe */ \
- F(LoadId) /* load */ \
- F(LoadScope) /* load */ \
- F(LoadRoot) /* load */ \
- F(LoadAttached) /* attached */ \
- F(ConvertIntToReal) /* unaryop */ \
- F(ConvertRealToInt) /* unaryop */ \
- F(Real) /* real_value */ \
- F(Int) /* int_value */ \
- F(Bool) /* bool_value */ \
- F(String) /* string_value */ \
- F(AddReal) /* binaryop */ \
- F(AddInt) /* binaryop */ \
- F(AddString) /* binaryop */ \
- F(MinusReal) /* binaryop */ \
- F(MinusInt) /* binaryop */ \
- F(CompareReal) /* binaryop */ \
- F(CompareString) /* binaryop */ \
- F(NotCompareReal) /* binaryop */ \
- F(NotCompareString) /* binaryop */ \
- F(GreaterThanReal) /* binaryop */ \
- F(MaxReal) /* binaryop */ \
- F(MinReal) /* binaryop */ \
- F(NewString) /* construct */ \
- F(NewUrl) /* construct */ \
- F(CleanupUrl) /* cleanup */ \
- F(CleanupString) /* cleanup */ \
- F(Copy) /* copy */ \
- F(Fetch) /* fetch */ \
- F(Store) /* store */ \
- F(Skip) /* skip */ \
- F(Done) /* done */ \
- /* Speculative property resolution */ \
- F(InitString) /* initstring */ \
- F(FindGeneric) /* find */ \
- F(FindGenericTerminal) /* find */ \
- F(FindProperty) /* find */ \
- F(FindPropertyTerminal) /* find */ \
- F(CleanupGeneric) /* cleanup */ \
- F(ConvertGenericToReal) /* unaryop */ \
- F(ConvertGenericToBool) /* unaryop */ \
- F(ConvertGenericToString) /* unaryop */ \
- F(ConvertGenericToUrl) /* unaryop */
-
-#define QML_INSTR_ENUM(I) I,
-#define QML_INSTR_ADDR(I) &&op_##I,
-
-#ifdef QML_THREADED_INTERPRETER
-# define QML_BEGIN_INSTR(I) op_##I:
-# define QML_END_INSTR(I) ++instr; goto *instr->common.code;
-# define QML_INSTR_HEADER void *code;
-#else
-# define QML_BEGIN_INSTR(I) case Instr::I:
-# define QML_END_INSTR(I) break;
-# define QML_INSTR_HEADER
-#endif
-
-
-using namespace QDeclarativeJS;
-
-namespace {
-// Supported types: int, qreal, QString (needs constr/destr), QObject*, bool
-struct Register {
- void setUndefined() { type = 0; }
- void setUnknownButDefined() { type = -1; }
- void setNaN() { setqreal(qSNaN()); }
- bool isUndefined() const { return type == 0; }
-
- void setQObject(QObject *o) { *((QObject **)data) = o; type = QMetaType::QObjectStar; }
- QObject *getQObject() const { return *((QObject **)data); }
-
- void setqreal(qreal v) { *((qreal *)data) = v; type = QMetaType::QReal; }
- qreal getqreal() const { return *((qreal *)data); }
-
- void setint(int v) { *((int *)data) = v; type = QMetaType::Int; }
- int getint() const { return *((int *)data); }
-
- void setbool(bool v) { *((bool *)data) = v; type = QMetaType::Bool; }
- bool getbool() const { return *((bool *)data); }
-
- QVariant *getvariantptr() { return (QVariant *)typeDataPtr(); }
- QString *getstringptr() { return (QString *)typeDataPtr(); }
- QUrl *geturlptr() { return (QUrl *)typeDataPtr(); }
- const QVariant *getvariantptr() const { return (QVariant *)typeDataPtr(); }
- const QString *getstringptr() const { return (QString *)typeDataPtr(); }
- const QUrl *geturlptr() const { return (QUrl *)typeDataPtr(); }
-
- void *typeDataPtr() { return (void *)&data; }
- void *typeMemory() { return (void *)data; }
- const void *typeDataPtr() const { return (void *)&data; }
- const void *typeMemory() const { return (void *)data; }
-
- int gettype() const { return type; }
- void settype(int t) { type = t; }
-
- int type; // Optional type
- void *data[2]; // Object stored here
-
-#ifdef REGISTER_CLEANUP_DEBUG
- Register() {
- type = 0;
- }
-
- ~Register() {
- int allowedTypes[] = { QMetaType::QObjectStar, QMetaType::QReal, QMetaType::Int, QMetaType::Bool, 0 };
- bool found = (type == 0);
- int *ctype = allowedTypes;
- while (!found && *ctype) {
- found = (*ctype == type);
- ++ctype;
- }
- if (!found)
- qWarning("Register leaked of type %d", type);
- }
-#endif
-};
-}
-
-class QDeclarativeCompiledBindingsPrivate : public QObjectPrivate
-{
- Q_DECLARE_PUBLIC(QDeclarativeCompiledBindings)
-
-public:
- QDeclarativeCompiledBindingsPrivate();
- virtual ~QDeclarativeCompiledBindingsPrivate();
-
- struct Binding : public QDeclarativeAbstractBinding, public QDeclarativeDelayedError {
- Binding() : enabled(false), updating(0), property(0),
- scope(0), target(0), parent(0) {}
-
- // Inherited from QDeclarativeAbstractBinding
- virtual void setEnabled(bool, QDeclarativePropertyPrivate::WriteFlags flags);
- virtual void update(QDeclarativePropertyPrivate::WriteFlags flags);
- virtual void destroy();
-
- int index:30;
- bool enabled:1;
- bool updating:1;
- int property;
- QObject *scope;
- QObject *target;
-
- QDeclarativeCompiledBindingsPrivate *parent;
- };
-
- typedef QDeclarativeNotifierEndpoint Subscription;
- Subscription *subscriptions;
- QScriptDeclarativeClass::PersistentIdentifier *identifiers;
-
- void run(Binding *, QDeclarativePropertyPrivate::WriteFlags flags);
-
- const char *programData;
- Binding *m_bindings;
- quint32 *m_signalTable;
-
- static int methodCount;
-
- void init();
- void run(int instr, QDeclarativeContextData *context,
- QDeclarativeDelayedError *error, QObject *scope, QObject *output, QDeclarativePropertyPrivate::WriteFlags storeFlags);
-
-
- inline void unsubscribe(int subIndex);
- inline void subscribeId(QDeclarativeContextData *p, int idIndex, int subIndex);
- inline void subscribe(QObject *o, int notifyIndex, int subIndex);
-
- QDeclarativePropertyCache::Data *findproperty(QObject *obj,
- const QScriptDeclarativeClass::Identifier &name,
- QDeclarativeEnginePrivate *enginePriv,
- QDeclarativePropertyCache::Data &local);
- bool findproperty(QObject *obj,
- Register *output,
- QDeclarativeEnginePrivate *enginePriv,
- int subIdx,
- const QScriptDeclarativeClass::Identifier &name,
- bool isTerminal);
- void findgeneric(Register *output, // value output
- int subIdx, // Subscription index in config
- QDeclarativeContextData *context, // Context to search in
- const QScriptDeclarativeClass::Identifier &name,
- bool isTerminal);
-};
-
-QDeclarativeCompiledBindingsPrivate::QDeclarativeCompiledBindingsPrivate()
-: subscriptions(0), identifiers(0)
-{
-}
-
-QDeclarativeCompiledBindingsPrivate::~QDeclarativeCompiledBindingsPrivate()
-{
- delete [] subscriptions; subscriptions = 0;
- delete [] identifiers; identifiers = 0;
-}
-
-int QDeclarativeCompiledBindingsPrivate::methodCount = -1;
-
-QDeclarativeCompiledBindings::QDeclarativeCompiledBindings(const char *program, QDeclarativeContextData *context)
-: QObject(*(new QDeclarativeCompiledBindingsPrivate))
-{
- Q_D(QDeclarativeCompiledBindings);
-
- if (d->methodCount == -1)
- d->methodCount = QDeclarativeCompiledBindings::staticMetaObject.methodCount();
-
- d->programData = program;
-
- d->init();
-
- QDeclarativeAbstractExpression::setContext(context);
-}
-
-QDeclarativeCompiledBindings::~QDeclarativeCompiledBindings()
-{
- Q_D(QDeclarativeCompiledBindings);
-
- delete [] d->m_bindings;
-}
-
-QDeclarativeAbstractBinding *QDeclarativeCompiledBindings::configBinding(int index, QObject *target,
- QObject *scope, int property)
-{
- Q_D(QDeclarativeCompiledBindings);
-
- QDeclarativeCompiledBindingsPrivate::Binding *rv = d->m_bindings + index;
-
- rv->index = index;
- rv->property = property;
- rv->target = target;
- rv->scope = scope;
- rv->parent = d;
-
- addref(); // This is decremented in Binding::destroy()
-
- return rv;
-}
-
-void QDeclarativeCompiledBindingsPrivate::Binding::setEnabled(bool e, QDeclarativePropertyPrivate::WriteFlags flags)
-{
- if (enabled != e) {
- enabled = e;
-
- if (e) update(flags);
- }
-}
-
-void QDeclarativeCompiledBindingsPrivate::Binding::update(QDeclarativePropertyPrivate::WriteFlags flags)
-{
- QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Binding);
- parent->run(this, flags);
- QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Binding);
-}
-
-void QDeclarativeCompiledBindingsPrivate::Binding::destroy()
-{
- enabled = false;
- removeFromObject();
- clear();
- parent->q_func()->release();
-}
-
-int QDeclarativeCompiledBindings::qt_metacall(QMetaObject::Call c, int id, void **)
-{
- Q_D(QDeclarativeCompiledBindings);
-
- if (c == QMetaObject::InvokeMetaMethod && id >= d->methodCount) {
- id -= d->methodCount;
-
- quint32 *reeval = d->m_signalTable + d->m_signalTable[id];
- quint32 count = *reeval;
- ++reeval;
- for (quint32 ii = 0; ii < count; ++ii) {
- d->run(d->m_bindings + reeval[ii], QDeclarativePropertyPrivate::DontRemoveBinding);
- }
- }
- return -1;
-}
-
-void QDeclarativeCompiledBindingsPrivate::run(Binding *binding, QDeclarativePropertyPrivate::WriteFlags flags)
-{
- Q_Q(QDeclarativeCompiledBindings);
-
- if (!binding->enabled)
- return;
-
- QDeclarativeContextData *context = q->QDeclarativeAbstractExpression::context();
- if (!context || !context->isValid())
- return;
-
- if (binding->updating) {
- QString name;
- if (binding->property & 0xFFFF0000) {
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine);
-
- QDeclarativeValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF];
- Q_ASSERT(vt);
-
- name = QLatin1String(binding->target->metaObject()->property(binding->property & 0xFFFF).name());
- name.append(QLatin1String("."));
- name.append(QLatin1String(vt->metaObject()->property(binding->property >> 24).name()));
- } else {
- name = QLatin1String(binding->target->metaObject()->property(binding->property).name());
- }
- qmlInfo(binding->target) << QCoreApplication::translate("QDeclarativeCompiledBindings", "Binding loop detected for property \"%1\"").arg(name);
- return;
- }
-
- binding->updating = true;
- if (binding->property & 0xFFFF0000) {
- QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine);
-
- QDeclarativeValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF];
- Q_ASSERT(vt);
- vt->read(binding->target, binding->property & 0xFFFF);
-
- QObject *target = vt;
- run(binding->index, context, binding, binding->scope, target, flags);
-
- vt->write(binding->target, binding->property & 0xFFFF, flags);
- } else {
- run(binding->index, context, binding, binding->scope, binding->target, flags);
- }
- binding->updating = false;
-}
-
-namespace {
-// This structure is exactly 8-bytes in size
-struct Instr {
- enum {
- FOR_EACH_QML_INSTR(QML_INSTR_ENUM)
- };
-
- union {
- struct {
- QML_INSTR_HEADER
- quint8 type;
- quint8 packing[7];
- } common;
- struct {
- QML_INSTR_HEADER
- quint8 type;
- quint8 packing;
- quint16 column;
- quint32 line;
- } id;
- struct {
- QML_INSTR_HEADER
- quint8 type;
- quint8 packing[3];
- quint16 subscriptions;
- quint16 identifiers;
- } init;
- struct {
- QML_INSTR_HEADER
- quint8 type;
- qint8 reg;
- quint16 offset;
- quint32 index;
- } subscribe;
- struct {
- QML_INSTR_HEADER
- quint8 type;
- qint8 reg;
- quint8 packing[2];
- quint32 index;
- } load;
- struct {
- QML_INSTR_HEADER
- quint8 type;
- qint8 output;
- qint8 reg;
- quint8 exceptionId;
- quint32 id;
- } attached;
- struct {
- QML_INSTR_HEADER
- quint8 type;
- qint8 output;
- qint8 reg;
- quint8 exceptionId;
- quint32 index;
- } store;
- struct {
- QML_INSTR_HEADER
- quint8 type;
- qint8 output;
- qint8 objectReg;
- quint8 exceptionId;
- quint16 subscription;
- quint16 function;
- } fetchAndSubscribe;
- struct {
- QML_INSTR_HEADER
- quint8 type;
- qint8 output;
- qint8 objectReg;
- quint8 exceptionId;
- quint32 index;
- } fetch;
- struct {
- QML_INSTR_HEADER
- quint8 type;
- qint8 reg;
- qint8 src;
- quint8 packing[5];
- } copy;
- struct {
- QML_INSTR_HEADER
- quint8 type;
- qint8 reg;
- quint8 packing[6];
- } construct;
- struct {
- QML_INSTR_HEADER
- quint8 type;
- qint8 reg;
- quint8 packing[2];
- float value;
- } real_value;
- struct {
- QML_INSTR_HEADER
- quint8 type;
- qint8 reg;
- quint8 packing[2];
- int value;
- } int_value;
- struct {
- QML_INSTR_HEADER
- quint8 type;
- qint8 reg;
- bool value;
- quint8 packing[5];
- } bool_value;
- struct {
- QML_INSTR_HEADER
- quint8 type;
- qint8 reg;
- quint16 length;
- quint32 offset;
- } string_value;
- struct {
- QML_INSTR_HEADER
- quint8 type;
- qint8 output;
- qint8 src1;
- qint8 src2;
- quint8 packing[4];
- } binaryop;
- struct {
- QML_INSTR_HEADER
- quint8 type;
- qint8 output;
- qint8 src;
- quint8 packing[5];
- } unaryop;
- struct {
- QML_INSTR_HEADER
- quint8 type;
- qint8 reg;
- quint8 packing[2];
- quint32 count;
- } skip;
- struct {
- QML_INSTR_HEADER
- quint8 type;
- qint8 reg;
- qint8 src;
- quint8 exceptionId;
- quint16 name;
- quint16 subscribeIndex;
- } find;
- struct {
- QML_INSTR_HEADER
- quint8 type;
- qint8 reg;
- quint8 packing[6];
- } cleanup;
- struct {
- QML_INSTR_HEADER
- quint8 type;
- quint8 packing[1];
- quint16 offset;
- quint32 dataIdx;
- } initstring;
- };
-};
-
-struct Program {
- quint32 bindings;
- quint32 dataLength;
- quint32 signalTableOffset;
- quint32 exceptionDataOffset;
- quint16 subscriptions;
- quint16 identifiers;
- quint16 instructionCount;
- quint16 compiled;
-
- const char *data() const { return ((const char *)this) + sizeof(Program); }
- const Instr *instructions() const { return (const Instr *)(data() + dataLength); }
-};
-}
-
-struct QDeclarativeBindingCompilerPrivate
-{
- struct Result {
- Result() : unknownType(false), metaObject(0), type(-1), reg(-1) {}
- bool operator==(const Result &o) const {
- return unknownType == o.unknownType &&
- metaObject == o.metaObject &&
- type == o.type &&
- reg == o.reg;
- }
- bool operator!=(const Result &o) const {
- return !(*this == o);
- }
- bool unknownType;
- const QMetaObject *metaObject;
- int type;
- int reg;
-
- QSet<QString> subscriptionSet;
- };
-
- QDeclarativeBindingCompilerPrivate() : registers(0) {}
-
- void resetInstanceState();
- int commitCompile();
-
- QDeclarativeParser::Object *context;
- QDeclarativeParser::Object *component;
- QDeclarativeParser::Property *destination;
- QHash<QString, QDeclarativeParser::Object *> ids;
- QDeclarativeImports imports;
- QDeclarativeEnginePrivate *engine;
-
- QString contextName() const { return QLatin1String("$$$SCOPE_") + QString::number((quintptr)context, 16); }
-
- bool compile(QDeclarativeJS::AST::Node *);
-
- bool parseExpression(QDeclarativeJS::AST::Node *, Result &);
-
- bool tryName(QDeclarativeJS::AST::Node *);
- bool parseName(QDeclarativeJS::AST::Node *, Result &);
-
- bool tryArith(QDeclarativeJS::AST::Node *);
- bool parseArith(QDeclarativeJS::AST::Node *, Result &);
- bool numberArith(Result &, const Result &, const Result &, QSOperator::Op op);
- bool stringArith(Result &, const Result &, const Result &, QSOperator::Op op);
-
- bool tryLogic(QDeclarativeJS::AST::Node *);
- bool parseLogic(QDeclarativeJS::AST::Node *, Result &);
-
- bool tryConditional(QDeclarativeJS::AST::Node *);
- bool parseConditional(QDeclarativeJS::AST::Node *, Result &);
-
- bool tryConstant(QDeclarativeJS::AST::Node *);
- bool parseConstant(QDeclarativeJS::AST::Node *, Result &);
-
- bool tryMethod(QDeclarativeJS::AST::Node *);
- bool parseMethod(QDeclarativeJS::AST::Node *, Result &);
-
- bool buildName(QStringList &, QDeclarativeJS::AST::Node *, QList<QDeclarativeJS::AST::ExpressionNode *> *nodes = 0);
- bool fetch(Result &type, const QMetaObject *, int reg, int idx, const QStringList &, QDeclarativeJS::AST::ExpressionNode *);
-
- quint32 registers;
- QHash<int, QPair<int, int> > registerCleanups;
- int acquireReg(int cleanup = Instr::Noop, int cleanupType = 0);
- void registerCleanup(int reg, int cleanup, int cleanupType = 0);
- void releaseReg(int);
-
- int registerLiteralString(const QString &);
- int registerString(const QString &);
- QHash<QString, QPair<int, int> > registeredStrings;
- QByteArray data;
-
- bool subscription(const QStringList &, Result *);
- int subscriptionIndex(const QStringList &);
- bool subscriptionNeutral(const QSet<QString> &base, const QSet<QString> &lhs, const QSet<QString> &rhs);
-
- quint8 exceptionId(QDeclarativeJS::AST::ExpressionNode *);
- QVector<quint64> exceptions;
-
- QSet<int> usedSubscriptionIds;
- QSet<QString> subscriptionSet;
- QHash<QString, int> subscriptionIds;
- QVector<Instr> bytecode;
-
- // Committed binding data
- struct {
- QList<int> offsets;
- QList<QSet<int> > dependencies;
-
- QVector<Instr> bytecode;
- QByteArray data;
- QHash<QString, int> subscriptionIds;
- QVector<quint64> exceptions;
-
- QHash<QString, QPair<int, int> > registeredStrings;
-
- int count() const { return offsets.count(); }
- } committed;
-
- QByteArray buildSignalTable() const;
- QByteArray buildExceptionData() const;
-};
-
-void QDeclarativeCompiledBindingsPrivate::unsubscribe(int subIndex)
-{
- QDeclarativeCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex);
- sub->disconnect();
-}
-
-void QDeclarativeCompiledBindingsPrivate::subscribeId(QDeclarativeContextData *p, int idIndex, int subIndex)
-{
- Q_Q(QDeclarativeCompiledBindings);
-
- unsubscribe(subIndex);
-
- if (p->idValues[idIndex]) {
- QDeclarativeCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex);
- sub->target = q;
- sub->targetMethod = methodCount + subIndex;
- sub->connect(&p->idValues[idIndex].bindings);
- }
-}
-
-void QDeclarativeCompiledBindingsPrivate::subscribe(QObject *o, int notifyIndex, int subIndex)
-{
- Q_Q(QDeclarativeCompiledBindings);
-
- QDeclarativeCompiledBindingsPrivate::Subscription *sub = (subscriptions + subIndex);
- sub->target = q;
- sub->targetMethod = methodCount + subIndex;
- if (o)
- sub->connect(o, notifyIndex);
- else
- sub->disconnect();
-}
-
-// Conversion functions - these MUST match the QtScript expression path
-inline static qreal toReal(Register *reg, int type, bool *ok = 0)
-{
- if (ok) *ok = true;
-
- if (type == QMetaType::QReal) {
- return reg->getqreal();
- } else if (type == qMetaTypeId<QVariant>()) {
- return reg->getvariantptr()->toReal();
- } else {
- if (ok) *ok = false;
- return 0;
- }
-}
-
-inline static QString toString(Register *reg, int type, bool *ok = 0)
-{
- if (ok) *ok = true;
-
- if (type == QMetaType::QReal) {
- return QString::number(reg->getqreal());
- } else if (type == QMetaType::Int) {
- return QString::number(reg->getint());
- } else if (type == qMetaTypeId<QVariant>()) {
- return reg->getvariantptr()->toString();
- } else if (type == QMetaType::QString) {
- return *reg->getstringptr();
- } else {
- if (ok) *ok = false;
- return QString();
- }
-}
-
-inline static bool toBool(Register *reg, int type, bool *ok = 0)
-{
- if (ok) *ok = true;
-
- if (type == QMetaType::Bool) {
- return reg->getbool();
- } else if (type == qMetaTypeId<QVariant>()) {
- return reg->getvariantptr()->toBool();
- } else {
- if (ok) *ok = false;
- return false;
- }
-}
-
-inline static QUrl toUrl(Register *reg, int type, QDeclarativeContextData *context, bool *ok = 0)
-{
- if (ok) *ok = true;
-
- QUrl base;
- if (type == qMetaTypeId<QVariant>()) {
- QVariant *var = reg->getvariantptr();
- int vt = var->type();
- if (vt == QVariant::Url) {
- base = var->toUrl();
- } else if (vt == QVariant::ByteArray) {
- base = QUrl(QString::fromUtf8(var->toByteArray()));
- } else if (vt == QVariant::String) {
- base = QUrl(var->toString());
- } else {
- if (ok) *ok = false;
- return QUrl();
- }
- } else if (type == QMetaType::QString) {
- base = QUrl(*reg->getstringptr());
- } else {
- if (ok) *ok = false;
- return QUrl();
- }
-
- if (!base.isEmpty() && base.isRelative())
- return context->url.resolved(base);
- else
- return base;
-}
-
-static QObject *variantToQObject(const QVariant &value, bool *ok)
-{
- if (ok) *ok = true;
-
- if (value.userType() == QMetaType::QObjectStar) {
- return qvariant_cast<QObject*>(value);
- } else {
- if (ok) *ok = false;
- return 0;
- }
-}
-
-bool QDeclarativeCompiledBindingsPrivate::findproperty(QObject *obj, Register *output,
- QDeclarativeEnginePrivate *enginePriv,
- int subIdx, const QScriptDeclarativeClass::Identifier &name,
- bool isTerminal)
-{
- if (!obj) {
- output->setUndefined();
- return false;
- }
-
- QDeclarativePropertyCache::Data local;
- QDeclarativePropertyCache::Data *property =
- QDeclarativePropertyCache::property(QDeclarativeEnginePrivate::get(enginePriv), obj, name, local);
-
- if (property) {
- if (subIdx != -1)
- subscribe(obj, property->notifyIndex, subIdx);
-
- if (property->flags & QDeclarativePropertyCache::Data::IsQObjectDerived) {
- void *args[] = { output->typeDataPtr(), 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, property->coreIndex, args);
- output->settype(QMetaType::QObjectStar);
- } else if (property->propType == qMetaTypeId<QVariant>()) {
- QVariant v;
- void *args[] = { &v, 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, property->coreIndex, args);
-
- if (isTerminal) {
- new (output->typeDataPtr()) QVariant(v);
- output->settype(qMetaTypeId<QVariant>());
- } else {
- bool ok;
- output->setQObject(variantToQObject(v, &ok));
- if (!ok)
- output->setUndefined();
- else
- output->settype(QMetaType::QObjectStar);
- }
-
- } else {
- if (!isTerminal) {
- output->setUndefined();
- } else if (property->propType == QMetaType::QReal) {
- void *args[] = { output->typeDataPtr(), 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, property->coreIndex, args);
- output->settype(QMetaType::QReal);
- } else if (property->propType == QMetaType::Int) {
- void *args[] = { output->typeDataPtr(), 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, property->coreIndex, args);
- output->settype(QMetaType::Int);
- } else if (property->propType == QMetaType::Bool) {
- void *args[] = { output->typeDataPtr(), 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, property->coreIndex, args);
- output->settype(QMetaType::Bool);
- } else if (property->propType == QMetaType::QString) {
- new (output->typeDataPtr()) QString();
- void *args[] = { output->typeDataPtr(), 0 };
- QMetaObject::metacall(obj, QMetaObject::ReadProperty, property->coreIndex, args);
- output->settype(QMetaType::QString);
- } else {
- new (output->typeDataPtr())
- QVariant(obj->metaObject()->property(property->coreIndex).read(obj));
- output->settype(qMetaTypeId<QVariant>());
- }
- }
-
- return true;
- } else {
- output->setUndefined();
- return false;
- }
-}
-
-void QDeclarativeCompiledBindingsPrivate::findgeneric(Register *output,
- int subIdx,
- QDeclarativeContextData *context,
- const QScriptDeclarativeClass::Identifier &name,
- bool isTerminal)
-{
- QDeclarativeEnginePrivate *enginePriv = QDeclarativeEnginePrivate::get(context->engine);
-
- while (context) {
-
- int contextPropertyIndex = context->propertyNames?context->propertyNames->value(name):-1;
-
-
- if (contextPropertyIndex != -1) {
-
- if (contextPropertyIndex < context->idValueCount) {
- output->setQObject(context->idValues[contextPropertyIndex]);
- output->settype(QMetaType::QObjectStar);
-
- if (subIdx != -1)
- subscribeId(context, contextPropertyIndex, subIdx);
-
- } else {
- QDeclarativeContextPrivate *cp = context->asQDeclarativeContextPrivate();
- const QVariant &value = cp->propertyValues.at(contextPropertyIndex);
-
- if (isTerminal) {
- new (output->typeDataPtr()) QVariant(value);
- output->settype(qMetaTypeId<QVariant>());
- } else {
- bool ok;
- output->setQObject(variantToQObject(value, &ok));
- if (!ok) { output->setUndefined(); }
- else { output->settype(QMetaType::QObjectStar); }
- return;
- }
-
- if (subIdx != -1)
- subscribe(context->asQDeclarativeContext(), contextPropertyIndex + cp->notifyIndex, subIdx);
-
-
- }
-
- return;
- }
-
- if (QObject *root = context->contextObject) {
-
- if (findproperty(root, output, enginePriv, subIdx, name, isTerminal))
- return;
-
- }
-
- context = context->parent;
- }
-
- output->setUndefined();
-}
-
-void QDeclarativeCompiledBindingsPrivate::init()
-{
- Program *program = (Program *)programData;
- if (program->subscriptions)
- subscriptions = new QDeclarativeCompiledBindingsPrivate::Subscription[program->subscriptions];
- if (program->identifiers)
- identifiers = new QScriptDeclarativeClass::PersistentIdentifier[program->identifiers];
-
- m_signalTable = (quint32 *)(program->data() + program->signalTableOffset);
- m_bindings = new QDeclarativeCompiledBindingsPrivate::Binding[program->bindings];
-}
-
-static void throwException(int id, QDeclarativeDelayedError *error,
- Program *program, QDeclarativeContextData *context,
- const QString &description = QString())
-{
- error->error.setUrl(context->url);
- 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);
- error->error.setColumn(e & 0xFFFFFFFF);
- } else {
- error->error.setLine(-1);
- error->error.setColumn(-1);
- }
- if (!context->engine || !error->addError(QDeclarativeEnginePrivate::get(context->engine)))
- QDeclarativeEnginePrivate::warning(context->engine, error->error);
-}
-
-static void dumpInstruction(const Instr *instr)
-{
- switch (instr->common.type) {
- case Instr::Noop:
- qWarning().nospace() << "\t" << "Noop";
- break;
- case Instr::BindingId:
- qWarning().nospace() << instr->id.line << ":" << instr->id.column << ":";
- break;
- case Instr::Subscribe:
- qWarning().nospace() << "\t" << "Subscribe" << "\t\t" << instr->subscribe.offset << "\t" << instr->subscribe.reg << "\t" << instr->subscribe.index;
- break;
- case Instr::SubscribeId:
- qWarning().nospace() << "\t" << "SubscribeId" << "\t\t" << instr->subscribe.offset << "\t" << instr->subscribe.reg << "\t" << instr->subscribe.index;
- break;
- case Instr::FetchAndSubscribe:
- qWarning().nospace() << "\t" << "FetchAndSubscribe" << "\t" << instr->fetchAndSubscribe.output << "\t" << instr->fetchAndSubscribe.objectReg << "\t" << instr->fetchAndSubscribe.subscription;
- break;
- case Instr::LoadId:
- qWarning().nospace() << "\t" << "LoadId" << "\t\t\t" << instr->load.index << "\t" << instr->load.reg;
- break;
- case Instr::LoadScope:
- qWarning().nospace() << "\t" << "LoadScope" << "\t\t" << instr->load.index << "\t" << instr->load.reg;
- break;
- case Instr::LoadRoot:
- qWarning().nospace() << "\t" << "LoadRoot" << "\t\t" << instr->load.index << "\t" << instr->load.reg;
- break;
- case Instr::LoadAttached:
- qWarning().nospace() << "\t" << "LoadAttached" << "\t\t" << instr->attached.output << "\t" << instr->attached.reg << "\t" << instr->attached.id;
- break;
- case Instr::ConvertIntToReal:
- qWarning().nospace() << "\t" << "ConvertIntToReal" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src;
- break;
- case Instr::ConvertRealToInt:
- qWarning().nospace() << "\t" << "ConvertRealToInt" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src;
- break;
- case Instr::Real:
- qWarning().nospace() << "\t" << "Real" << "\t\t\t" << instr->real_value.reg << "\t" << instr->real_value.value;
- break;
- case Instr::Int:
- qWarning().nospace() << "\t" << "Int" << "\t\t\t" << instr->int_value.reg << "\t" << instr->int_value.value;
- break;
- case Instr::Bool:
- qWarning().nospace() << "\t" << "Bool" << "\t\t\t" << instr->bool_value.reg << "\t" << instr->bool_value.value;
- break;
- case Instr::String:
- qWarning().nospace() << "\t" << "String" << "\t\t\t" << instr->string_value.reg << "\t" << instr->string_value.offset << "\t" << instr->string_value.length;
- break;
- case Instr::AddReal:
- qWarning().nospace() << "\t" << "AddReal" << "\t\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
- break;
- case Instr::AddInt:
- qWarning().nospace() << "\t" << "AddInt" << "\t\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
- break;
- case Instr::AddString:
- qWarning().nospace() << "\t" << "AddString" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
- break;
- case Instr::MinusReal:
- qWarning().nospace() << "\t" << "MinusReal" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
- break;
- case Instr::MinusInt:
- qWarning().nospace() << "\t" << "MinusInt" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
- break;
- case Instr::CompareReal:
- qWarning().nospace() << "\t" << "CompareReal" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
- break;
- case Instr::CompareString:
- qWarning().nospace() << "\t" << "CompareString" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
- break;
- case Instr::NotCompareReal:
- qWarning().nospace() << "\t" << "NotCompareReal" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
- break;
- case Instr::NotCompareString:
- qWarning().nospace() << "\t" << "NotCompareString" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
- break;
- case Instr::GreaterThanReal:
- qWarning().nospace() << "\t" << "GreaterThanReal" << "\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
- break;
- case Instr::MaxReal:
- qWarning().nospace() << "\t" << "MaxReal" << "\t\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
- break;
- case Instr::MinReal:
- qWarning().nospace() << "\t" << "MinReal" << "\t\t\t" << instr->binaryop.output << "\t" << instr->binaryop.src1 << "\t" << instr->binaryop.src2;
- break;
- case Instr::NewString:
- qWarning().nospace() << "\t" << "NewString" << "\t\t" << instr->construct.reg;
- break;
- case Instr::NewUrl:
- qWarning().nospace() << "\t" << "NewUrl" << "\t\t\t" << instr->construct.reg;
- break;
- case Instr::CleanupString:
- qWarning().nospace() << "\t" << "CleanupString" << "\t\t" << instr->cleanup.reg;
- break;
- case Instr::CleanupUrl:
- qWarning().nospace() << "\t" << "CleanupUrl" << "\t\t" << instr->cleanup.reg;
- break;
- case Instr::Fetch:
- qWarning().nospace() << "\t" << "Fetch" << "\t\t\t" << instr->fetch.output << "\t" << instr->fetch.index << "\t" << instr->fetch.objectReg;
- break;
- case Instr::Store:
- qWarning().nospace() << "\t" << "Store" << "\t\t\t" << instr->store.output << "\t" << instr->store.index << "\t" << instr->store.reg;
- break;
- case Instr::Copy:
- qWarning().nospace() << "\t" << "Copy" << "\t\t\t" << instr->copy.reg << "\t" << instr->copy.src;
- break;
- case Instr::Skip:
- qWarning().nospace() << "\t" << "Skip" << "\t\t\t" << instr->skip.reg << "\t" << instr->skip.count;
- break;
- case Instr::Done:
- qWarning().nospace() << "\t" << "Done";
- break;
- case Instr::InitString:
- qWarning().nospace() << "\t" << "InitString" << "\t\t" << instr->initstring.offset << "\t" << instr->initstring.dataIdx;
- break;
- case Instr::FindGeneric:
- qWarning().nospace() << "\t" << "FindGeneric" << "\t\t" << instr->find.reg << "\t" << instr->find.name;
- break;
- case Instr::FindGenericTerminal:
- qWarning().nospace() << "\t" << "FindGenericTerminal" << "\t" << instr->find.reg << "\t" << instr->find.name;
- break;
- case Instr::FindProperty:
- qWarning().nospace() << "\t" << "FindProperty" << "\t\t" << instr->find.reg << "\t" << instr->find.src << "\t" << instr->find.name;
- break;
- case Instr::FindPropertyTerminal:
- qWarning().nospace() << "\t" << "FindPropertyTerminal" << "\t" << instr->find.reg << "\t" << instr->find.src << "\t" << instr->find.name;
- break;
- case Instr::CleanupGeneric:
- qWarning().nospace() << "\t" << "CleanupGeneric" << "\t\t" << instr->cleanup.reg;
- break;
- case Instr::ConvertGenericToReal:
- qWarning().nospace() << "\t" << "ConvertGenericToReal" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src;
- break;
- case Instr::ConvertGenericToBool:
- qWarning().nospace() << "\t" << "ConvertGenericToBool" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src;
- break;
- case Instr::ConvertGenericToString:
- qWarning().nospace() << "\t" << "ConvertGenericToString" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src;
- break;
- case Instr::ConvertGenericToUrl:
- qWarning().nospace() << "\t" << "ConvertGenericToUrl" << "\t" << instr->unaryop.output << "\t" << instr->unaryop.src;
- break;
- default:
- qWarning().nospace() << "\t" << "Unknown";
- break;
- }
-}
-
-void QDeclarativeCompiledBindingsPrivate::run(int instrIndex,
- QDeclarativeContextData *context, QDeclarativeDelayedError *error,
- QObject *scope, QObject *output, QDeclarativePropertyPrivate::WriteFlags storeFlags)
-{
- Q_Q(QDeclarativeCompiledBindings);
-
- error->removeError();
-
- Register registers[32];
-
- QDeclarativeEnginePrivate *engine = QDeclarativeEnginePrivate::get(context->engine);
- Program *program = (Program *)programData;
- const Instr *instr = program->instructions();
- instr += instrIndex;
- const char *data = program->data();
-
-#ifdef QML_THREADED_INTERPRETER
- static void *decode_instr[] = {
- FOR_EACH_QML_INSTR(QML_INSTR_ADDR)
- };
-
- if (!program->compiled) {
- program->compiled = true;
- const Instr *inop = program->instructions();
- for (int i = 0; i < program->instructionCount; ++i) {
- Instr *op = (Instr *) inop++;
- op->common.code = decode_instr[op->common.type];
- }
- }
-
- goto *instr->common.code;
-#else
- // return;
-
-#ifdef COMPILEDBINDINGS_DEBUG
- qWarning().nospace() << "Begin binding run";
-#endif
-
- while (instr) {
- switch (instr->common.type) {
-
-#ifdef COMPILEDBINDINGS_DEBUG
- dumpInstruction(instr);
-#endif
-
-#endif
-
- QML_BEGIN_INSTR(Noop)
- QML_END_INSTR(Noop)
-
- QML_BEGIN_INSTR(BindingId)
- QML_END_INSTR(BindingId)
-
- QML_BEGIN_INSTR(SubscribeId)
- subscribeId(context, instr->subscribe.index, instr->subscribe.offset);
- QML_END_INSTR(SubscribeId)
-
- QML_BEGIN_INSTR(Subscribe)
- {
- QObject *o = 0;
- const Register &object = registers[instr->subscribe.reg];
- if (!object.isUndefined()) o = object.getQObject();
- subscribe(o, instr->subscribe.index, instr->subscribe.offset);
- }
- QML_END_INSTR(Subscribe)
-
- QML_BEGIN_INSTR(FetchAndSubscribe)
- {
- const Register &input = registers[instr->fetchAndSubscribe.objectReg];
- Register &output = registers[instr->fetchAndSubscribe.output];
-
- if (input.isUndefined()) {
- throwException(instr->fetchAndSubscribe.exceptionId, error, program, context);
- return;
- }
-
- QObject *object = input.getQObject();
- if (!object) {
- output.setUndefined();
- } else {
- int subIdx = instr->fetchAndSubscribe.subscription;
- QDeclarativeCompiledBindingsPrivate::Subscription *sub = 0;
- if (subIdx != -1) {
- sub = (subscriptions + subIdx);
- sub->target = q;
- sub->targetMethod = methodCount + subIdx;
- }
- fastProperties()->accessor(instr->fetchAndSubscribe.function)(object, output.typeDataPtr(), sub);
- }
- }
- QML_END_INSTR(FetchAndSubscribe)
-
- QML_BEGIN_INSTR(LoadId)
- registers[instr->load.reg].setQObject(context->idValues[instr->load.index].data());
- QML_END_INSTR(LoadId)
-
- QML_BEGIN_INSTR(LoadScope)
- registers[instr->load.reg].setQObject(scope);
- QML_END_INSTR(LoadScope)
-
- QML_BEGIN_INSTR(LoadRoot)
- registers[instr->load.reg].setQObject(context->contextObject);
- QML_END_INSTR(LoadRoot)
-
- QML_BEGIN_INSTR(LoadAttached)
- {
- const Register &input = registers[instr->attached.reg];
- Register &output = registers[instr->attached.output];
- if (input.isUndefined()) {
- throwException(instr->attached.exceptionId, error, program, context);
- return;
- }
-
- QObject *object = registers[instr->attached.reg].getQObject();
- if (!object) {
- output.setUndefined();
- } else {
- QObject *attached =
- qmlAttachedPropertiesObjectById(instr->attached.id,
- registers[instr->attached.reg].getQObject(),
- true);
- Q_ASSERT(attached);
- output.setQObject(attached);
- }
- }
- QML_END_INSTR(LoadAttached)
-
- QML_BEGIN_INSTR(ConvertIntToReal)
- {
- const Register &input = registers[instr->unaryop.src];
- Register &output = registers[instr->unaryop.output];
- if (input.isUndefined()) output.setUndefined();
- else output.setqreal(qreal(input.getint()));
- }
- QML_END_INSTR(ConvertIntToReal)
-
- QML_BEGIN_INSTR(ConvertRealToInt)
- {
- const Register &input = registers[instr->unaryop.src];
- Register &output = registers[instr->unaryop.output];
- if (input.isUndefined()) output.setUndefined();
- else output.setint(qRound(input.getqreal()));
- }
- QML_END_INSTR(ConvertRealToInt)
-
- QML_BEGIN_INSTR(Real)
- registers[instr->real_value.reg].setqreal(instr->real_value.value);
- QML_END_INSTR(Real)
-
- QML_BEGIN_INSTR(Int)
- registers[instr->int_value.reg].setint(instr->int_value.value);
- QML_END_INSTR(Int)
-
- QML_BEGIN_INSTR(Bool)
- registers[instr->bool_value.reg].setbool(instr->bool_value.value);
- QML_END_INSTR(Bool)
-
- QML_BEGIN_INSTR(String)
- {
- Register &output = registers[instr->string_value.reg];
- new (output.getstringptr())
- QString((QChar *)(data + instr->string_value.offset), instr->string_value.length);
- output.settype(QMetaType::QString);
- }
- QML_END_INSTR(String)
-
- QML_BEGIN_INSTR(AddReal)
- {
- const Register &lhs = registers[instr->binaryop.src1];
- const Register &rhs = registers[instr->binaryop.src2];
- Register &output = registers[instr->binaryop.output];
- if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN();
- else output.setqreal(lhs.getqreal() + rhs.getqreal());
- }
- QML_END_INSTR(AddReal)
-
- QML_BEGIN_INSTR(AddInt)
- {
- const Register &lhs = registers[instr->binaryop.src1];
- const Register &rhs = registers[instr->binaryop.src2];
- Register &output = registers[instr->binaryop.output];
- if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN();
- else output.setint(lhs.getint() + rhs.getint());
- }
- QML_END_INSTR(AddInt)
-
- QML_BEGIN_INSTR(AddString)
- {
- const Register &lhs = registers[instr->binaryop.src1];
- const Register &rhs = registers[instr->binaryop.src2];
- Register &output = registers[instr->binaryop.output];
- if (lhs.isUndefined() && rhs.isUndefined()) { output.setNaN(); }
- else {
- if (lhs.isUndefined())
- new (output.getstringptr())
- QString(QLatin1String("undefined") + *registers[instr->binaryop.src2].getstringptr());
- else if (rhs.isUndefined())
- new (output.getstringptr())
- QString(*registers[instr->binaryop.src1].getstringptr() + QLatin1String("undefined"));
- else
- new (output.getstringptr())
- QString(*registers[instr->binaryop.src1].getstringptr() +
- *registers[instr->binaryop.src2].getstringptr());
- output.settype(QMetaType::QString);
- }
- }
- QML_END_INSTR(AddString)
-
- QML_BEGIN_INSTR(MinusReal)
- {
- const Register &lhs = registers[instr->binaryop.src1];
- const Register &rhs = registers[instr->binaryop.src2];
- Register &output = registers[instr->binaryop.output];
- if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN();
- else output.setqreal(lhs.getqreal() - rhs.getqreal());
- }
- QML_END_INSTR(MinusReal)
-
- QML_BEGIN_INSTR(MinusInt)
- {
- const Register &lhs = registers[instr->binaryop.src1];
- const Register &rhs = registers[instr->binaryop.src2];
- Register &output = registers[instr->binaryop.output];
- if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN();
- else output.setint(lhs.getint() - rhs.getint());
- }
- QML_END_INSTR(MinusInt)
-
- QML_BEGIN_INSTR(CompareReal)
- {
- const Register &lhs = registers[instr->binaryop.src1];
- const Register &rhs = registers[instr->binaryop.src2];
- Register &output = registers[instr->binaryop.output];
- if (lhs.isUndefined() || rhs.isUndefined()) output.setbool(lhs.isUndefined() == rhs.isUndefined());
- else output.setbool(lhs.getqreal() == rhs.getqreal());
- }
- QML_END_INSTR(CompareReal)
-
- QML_BEGIN_INSTR(CompareString)
- {
- const Register &lhs = registers[instr->binaryop.src1];
- const Register &rhs = registers[instr->binaryop.src2];
- Register &output = registers[instr->binaryop.output];
- if (lhs.isUndefined() || rhs.isUndefined()) output.setbool(lhs.isUndefined() == rhs.isUndefined());
- else output.setbool(*lhs.getstringptr() == *rhs.getstringptr());
- }
- QML_END_INSTR(CompareString)
-
- QML_BEGIN_INSTR(NotCompareReal)
- {
- const Register &lhs = registers[instr->binaryop.src1];
- const Register &rhs = registers[instr->binaryop.src2];
- Register &output = registers[instr->binaryop.output];
- if (lhs.isUndefined() || rhs.isUndefined()) output.setbool(lhs.isUndefined() != rhs.isUndefined());
- else output.setbool(lhs.getqreal() != rhs.getqreal());
- }
- QML_END_INSTR(NotCompareReal)
-
- QML_BEGIN_INSTR(NotCompareString)
- {
- const Register &lhs = registers[instr->binaryop.src1];
- const Register &rhs = registers[instr->binaryop.src2];
- Register &output = registers[instr->binaryop.output];
- if (lhs.isUndefined() || rhs.isUndefined()) output.setbool(lhs.isUndefined() != rhs.isUndefined());
- else output.setbool(*lhs.getstringptr() != *rhs.getstringptr());
- }
- QML_END_INSTR(NotCompareString)
-
- QML_BEGIN_INSTR(GreaterThanReal)
- {
- const Register &lhs = registers[instr->binaryop.src1];
- const Register &rhs = registers[instr->binaryop.src2];
- Register &output = registers[instr->binaryop.output];
- if (lhs.isUndefined() || rhs.isUndefined()) output.setbool(false);
- else output.setbool(lhs.getqreal() > rhs.getqreal());
- }
- QML_END_INSTR(GreaterThanReal)
-
- QML_BEGIN_INSTR(MaxReal)
- {
- const Register &lhs = registers[instr->binaryop.src1];
- const Register &rhs = registers[instr->binaryop.src2];
- Register &output = registers[instr->binaryop.output];
- if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN();
- else output.setqreal(qMax(lhs.getqreal(), rhs.getqreal()));
- }
- QML_END_INSTR(MaxReal)
-
- QML_BEGIN_INSTR(MinReal)
- {
- const Register &lhs = registers[instr->binaryop.src1];
- const Register &rhs = registers[instr->binaryop.src2];
- Register &output = registers[instr->binaryop.output];
- if (lhs.isUndefined() || rhs.isUndefined()) output.setNaN();
- else output.setqreal(qMin(lhs.getqreal(), rhs.getqreal()));
- }
- QML_END_INSTR(MinReal)
-
- QML_BEGIN_INSTR(NewString)
- {
- Register &output = registers[instr->construct.reg];
- new (output.getstringptr()) QString;
- output.settype(QMetaType::QString);
- }
- QML_END_INSTR(NewString)
-
- QML_BEGIN_INSTR(NewUrl)
- {
- Register &output = registers[instr->construct.reg];
- new (output.geturlptr()) QUrl;
- output.settype(QMetaType::QUrl);
- }
- QML_END_INSTR(NewUrl)
-
- QML_BEGIN_INSTR(CleanupString)
- registers[instr->cleanup.reg].getstringptr()->~QString();
-#ifdef REGISTER_CLEANUP_DEBUG
- registers[instr->cleanup.reg].setUndefined();
-#endif
- QML_END_INSTR(CleanupString)
-
- QML_BEGIN_INSTR(CleanupUrl)
- registers[instr->cleanup.reg].geturlptr()->~QUrl();
-#ifdef REGISTER_CLEANUP_DEBUG
- registers[instr->cleanup.reg].setUndefined();
-#endif
- QML_END_INSTR(CleanupUrl)
-
- QML_BEGIN_INSTR(Fetch)
- {
- const Register &input = registers[instr->fetch.objectReg];
- Register &output = registers[instr->fetch.output];
-
- if (input.isUndefined()) {
- throwException(instr->fetch.exceptionId, error, program, context);
- return;
- }
-
- QObject *object = input.getQObject();
- if (!object) {
- output.setUndefined();
- } else {
- void *argv[] = { output.typeDataPtr(), 0 };
- QMetaObject::metacall(object, QMetaObject::ReadProperty, instr->fetch.index, argv);
- }
- }
- QML_END_INSTR(Fetch)
-
- QML_BEGIN_INSTR(Store)
- {
- Register &data = registers[instr->store.reg];
- if (data.isUndefined()) {
- throwException(instr->store.exceptionId, error, program, context,
- QLatin1String("Unable to assign undefined value"));
- return;
- }
-
- int status = -1;
- void *argv[] = { data.typeDataPtr(), 0, &status, &storeFlags };
- QMetaObject::metacall(output, QMetaObject::WriteProperty,
- instr->store.index, argv);
- }
- QML_END_INSTR(Store)
-
- QML_BEGIN_INSTR(Copy)
- registers[instr->copy.reg] = registers[instr->copy.src];
- QML_END_INSTR(Copy)
-
- QML_BEGIN_INSTR(Skip)
- if (instr->skip.reg == -1 || !registers[instr->skip.reg].getbool())
- instr += instr->skip.count;
- QML_END_INSTR(Skip)
-
- QML_BEGIN_INSTR(Done)
- return;
- QML_END_INSTR(Done)
-
- QML_BEGIN_INSTR(InitString)
- if (!identifiers[instr->initstring.offset].identifier) {
- quint32 len = *(quint32 *)(data + instr->initstring.dataIdx);
- QChar *strdata = (QChar *)(data + instr->initstring.dataIdx + sizeof(quint32));
-
- QString str = QString::fromRawData(strdata, len);
-
- identifiers[instr->initstring.offset] = engine->objectClass->createPersistentIdentifier(str);
- }
- QML_END_INSTR(InitString)
-
- QML_BEGIN_INSTR(FindGenericTerminal)
- // We start the search in the parent context, as we know that the
- // name is not present in the current context or it would have been
- // found during the static compile
- findgeneric(registers + instr->find.reg, instr->find.subscribeIndex,
- context->parent,
- identifiers[instr->find.name].identifier,
- instr->common.type == Instr::FindGenericTerminal);
- QML_END_INSTR(FindGenericTerminal)
-
- QML_BEGIN_INSTR(FindGeneric)
- // We start the search in the parent context, as we know that the
- // name is not present in the current context or it would have been
- // found during the static compile
- findgeneric(registers + instr->find.reg, instr->find.subscribeIndex,
- context->parent,
- identifiers[instr->find.name].identifier,
- instr->common.type == Instr::FindGenericTerminal);
- QML_END_INSTR(FindGeneric)
-
- QML_BEGIN_INSTR(FindPropertyTerminal)
- {
- const Register &object = registers[instr->find.src];
- if (object.isUndefined()) {
- throwException(instr->find.exceptionId, error, program, context);
- return;
- }
-
- findproperty(object.getQObject(), registers + instr->find.reg,
- QDeclarativeEnginePrivate::get(context->engine),
- instr->find.subscribeIndex, identifiers[instr->find.name].identifier,
- instr->common.type == Instr::FindPropertyTerminal);
- }
- QML_END_INSTR(FindPropertyTerminal)
-
- QML_BEGIN_INSTR(FindProperty)
- {
- const Register &object = registers[instr->find.src];
- if (object.isUndefined()) {
- throwException(instr->find.exceptionId, error, program, context);
- return;
- }
-
- findproperty(object.getQObject(), registers + instr->find.reg,
- QDeclarativeEnginePrivate::get(context->engine),
- instr->find.subscribeIndex, identifiers[instr->find.name].identifier,
- instr->common.type == Instr::FindPropertyTerminal);
- }
- QML_END_INSTR(FindProperty)
-
- QML_BEGIN_INSTR(CleanupGeneric)
- {
- int type = registers[instr->cleanup.reg].gettype();
- if (type == qMetaTypeId<QVariant>()) {
- registers[instr->cleanup.reg].getvariantptr()->~QVariant();
-#ifdef REGISTER_CLEANUP_DEBUG
- registers[instr->cleanup.reg].setUndefined();
-#endif
- } else if (type == QMetaType::QString) {
- registers[instr->cleanup.reg].getstringptr()->~QString();
-#ifdef REGISTER_CLEANUP_DEBUG
- registers[instr->cleanup.reg].setUndefined();
-#endif
- } else if (type == QMetaType::QUrl) {
- registers[instr->cleanup.reg].geturlptr()->~QUrl();
-#ifdef REGISTER_CLEANUP_DEBUG
- registers[instr->cleanup.reg].setUndefined();
-#endif
- }
- }
- QML_END_INSTR(CleanupGeneric)
-
- QML_BEGIN_INSTR(ConvertGenericToReal)
- {
- Register &output = registers[instr->unaryop.output];
- Register &input = registers[instr->unaryop.src];
- bool ok = true;
- output.setqreal(toReal(&input, input.gettype(), &ok));
- if (!ok) output.setUndefined();
- }
- QML_END_INSTR(ConvertGenericToReal)
-
- QML_BEGIN_INSTR(ConvertGenericToBool)
- {
- Register &output = registers[instr->unaryop.output];
- Register &input = registers[instr->unaryop.src];
- bool ok = true;
- output.setbool(toBool(&input, input.gettype(), &ok));
- if (!ok) output.setUndefined();
- }
- QML_END_INSTR(ConvertGenericToBool)
-
- QML_BEGIN_INSTR(ConvertGenericToString)
- {
- Register &output = registers[instr->unaryop.output];
- Register &input = registers[instr->unaryop.src];
- bool ok = true;
- QString str = toString(&input, input.gettype(), &ok);
- if (ok) { new (output.getstringptr()) QString(str); output.settype(QMetaType::QString); }
- else { output.setUndefined(); }
- }
- QML_END_INSTR(ConvertGenericToString)
-
- QML_BEGIN_INSTR(ConvertGenericToUrl)
- {
- Register &output = registers[instr->unaryop.output];
- Register &input = registers[instr->unaryop.src];
- bool ok = true;
- QUrl url = toUrl(&input, input.gettype(), context, &ok);
- if (ok) { new (output.geturlptr()) QUrl(url); output.settype(QMetaType::QUrl); }
- else { output.setUndefined(); }
- }
- QML_END_INSTR(ConvertGenericToUrl)
-
-#ifdef QML_THREADED_INTERPRETER
- // nothing to do
-#else
- default:
- qFatal("EEK");
- break;
- } // switch
-
- ++instr;
- } // while
-#endif
-}
-
-void QDeclarativeBindingCompiler::dump(const QByteArray &programData)
-{
- const Program *program = (const Program *)programData.constData();
-
- qWarning() << "Program.bindings:" << program->bindings;
- qWarning() << "Program.dataLength:" << program->dataLength;
- qWarning() << "Program.subscriptions:" << program->subscriptions;
- qWarning() << "Program.indentifiers:" << program->identifiers;
-
- int count = program->instructionCount;
- const Instr *instr = program->instructions();
-
- while (count--) {
-
- dumpInstruction(instr);
- ++instr;
- }
-}
-
-/*!
-Clear the state associated with attempting to compile a specific binding.
-This does not clear the global "committed binding" states.
-*/
-void QDeclarativeBindingCompilerPrivate::resetInstanceState()
-{
- registers = 0;
- registerCleanups.clear();
- data = committed.data;
- exceptions = committed.exceptions;
- usedSubscriptionIds.clear();
- subscriptionSet.clear();
- subscriptionIds = committed.subscriptionIds;
- registeredStrings = committed.registeredStrings;
- bytecode.clear();
-}
-
-/*!
-Mark the last compile as successful, and add it to the "committed data"
-section.
-
-Returns the index for the committed binding.
-*/
-int QDeclarativeBindingCompilerPrivate::commitCompile()
-{
- int rv = committed.count();
- committed.offsets << committed.bytecode.count();
- committed.dependencies << usedSubscriptionIds;
- committed.bytecode << bytecode;
- committed.data = data;
- committed.exceptions = exceptions;
- committed.subscriptionIds = subscriptionIds;
- committed.registeredStrings = registeredStrings;
- return rv;
-}
-
-bool QDeclarativeBindingCompilerPrivate::compile(QDeclarativeJS::AST::Node *node)
-{
- resetInstanceState();
-
- if (destination->type == -1)
- return false;
-
- if (bindingsDump()) {
- QDeclarativeJS::AST::ExpressionNode *n = node->expressionCast();
- if (n) {
- Instr id;
- id.common.type = Instr::BindingId;
- id.id.column = n->firstSourceLocation().startColumn;
- id.id.line = n->firstSourceLocation().startLine;
- bytecode << id;
- }
- }
-
- Result type;
-
- if (!parseExpression(node, type))
- return false;
-
- if (subscriptionSet.count() > 0xFFFF ||
- registeredStrings.count() > 0xFFFF)
- return false;
-
- if (type.unknownType) {
- if (!qmlExperimental())
- return false;
-
- if (destination->type != QMetaType::QReal &&
- destination->type != QVariant::String &&
- destination->type != QMetaType::Bool &&
- destination->type != QVariant::Url)
- return false;
-
- int convertReg = acquireReg();
- if (convertReg == -1)
- return false;
-
- if (destination->type == QMetaType::QReal) {
- Instr convert;
- convert.common.type = Instr::ConvertGenericToReal;
- convert.unaryop.output = convertReg;
- convert.unaryop.src = type.reg;
- bytecode << convert;
- } else if (destination->type == QVariant::String) {
- Instr convert;
- convert.common.type = Instr::ConvertGenericToString;
- convert.unaryop.output = convertReg;
- convert.unaryop.src = type.reg;
- bytecode << convert;
- } else if (destination->type == QMetaType::Bool) {
- Instr convert;
- convert.common.type = Instr::ConvertGenericToBool;
- convert.unaryop.output = convertReg;
- convert.unaryop.src = type.reg;
- bytecode << convert;
- } else if (destination->type == QVariant::Url) {
- Instr convert;
- convert.common.type = Instr::ConvertGenericToUrl;
- convert.unaryop.output = convertReg;
- convert.unaryop.src = type.reg;
- bytecode << convert;
- }
-
- Instr cleanup;
- cleanup.common.type = Instr::CleanupGeneric;
- cleanup.cleanup.reg = type.reg;
- bytecode << cleanup;
-
- Instr instr;
- instr.common.type = Instr::Store;
- instr.store.output = 0;
- instr.store.index = destination->index;
- instr.store.reg = convertReg;
- instr.store.exceptionId = exceptionId(node->expressionCast());
- bytecode << instr;
-
- if (destination->type == QVariant::String) {
- Instr cleanup;
- cleanup.common.type = Instr::CleanupString;
- cleanup.cleanup.reg = convertReg;
- bytecode << cleanup;
- } else if (destination->type == QVariant::Url) {
- Instr cleanup;
- cleanup.common.type = Instr::CleanupUrl;
- cleanup.cleanup.reg = convertReg;
- bytecode << cleanup;
- }
-
- releaseReg(convertReg);
-
- Instr done;
- done.common.type = Instr::Done;
- bytecode << done;
-
- } else {
- // Can we store the final value?
- if (type.type == QVariant::Int &&
- destination->type == QMetaType::QReal) {
- Instr instr;
- instr.common.type = Instr::ConvertIntToReal;
- instr.unaryop.output = type.reg;
- instr.unaryop.src = type.reg;
- bytecode << instr;
- type.type = QMetaType::QReal;
- } else if (type.type == QMetaType::QReal &&
- destination->type == QVariant::Int) {
- Instr instr;
- instr.common.type = Instr::ConvertRealToInt;
- instr.unaryop.output = type.reg;
- instr.unaryop.src = type.reg;
- bytecode << instr;
- type.type = QVariant::Int;
- } else if (type.type == destination->type) {
- } else {
- const QMetaObject *from = type.metaObject;
- const QMetaObject *to = engine->rawMetaObjectForType(destination->type);
-
- if (QDeclarativePropertyPrivate::canConvert(from, to))
- type.type = destination->type;
- }
-
- if (type.type == destination->type) {
- Instr instr;
- instr.common.type = Instr::Store;
- 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);
-
- Instr done;
- done.common.type = Instr::Done;
- bytecode << done;
- } else {
- return false;
- }
- }
-
- return true;
-}
-
-bool QDeclarativeBindingCompilerPrivate::parseExpression(QDeclarativeJS::AST::Node *node, Result &type)
-{
- while (node->kind == AST::Node::Kind_NestedExpression)
- node = static_cast<AST::NestedExpression *>(node)->expression;
-
- if (tryArith(node)) {
- if (!parseArith(node, type)) return false;
- } else if (tryLogic(node)) {
- if (!parseLogic(node, type)) return false;
- } else if (tryConditional(node)) {
- if (!parseConditional(node, type)) return false;
- } else if (tryName(node)) {
- if (!parseName(node, type)) return false;
- } else if (tryConstant(node)) {
- if (!parseConstant(node, type)) return false;
- } else if (tryMethod(node)) {
- if (!parseMethod(node, type)) return false;
- } else {
- return false;
- }
- return true;
-}
-
-bool QDeclarativeBindingCompilerPrivate::tryName(QDeclarativeJS::AST::Node *node)
-{
- return node->kind == AST::Node::Kind_IdentifierExpression ||
- node->kind == AST::Node::Kind_FieldMemberExpression;
-}
-
-bool QDeclarativeBindingCompilerPrivate::parseName(AST::Node *node, Result &type)
-{
- QStringList nameParts;
- QList<AST::ExpressionNode *> nameNodes;
- if (!buildName(nameParts, node, &nameNodes))
- return false;
-
- int reg = acquireReg();
- if (reg == -1)
- return false;
- type.reg = reg;
-
- QDeclarativeParser::Object *absType = 0;
-
- QStringList subscribeName;
-
- bool wasAttachedObject = false;
-
- for (int ii = 0; ii < nameParts.count(); ++ii) {
- const QString &name = nameParts.at(ii);
-
- // We don't handle signal properties or attached properties
- if (name.length() > 2 && name.startsWith(QLatin1String("on")) &&
- name.at(2).isUpper())
- return false;
-
- QDeclarativeType *attachType = 0;
- if (name.at(0).isUpper()) {
- // Could be an attached property
- if (ii == nameParts.count() - 1)
- return false;
- if (nameParts.at(ii + 1).at(0).isUpper())
- return false;
-
- QDeclarativeImportedNamespace *ns = 0;
- if (!imports.resolveType(name.toUtf8(), &attachType, 0, 0, 0, &ns))
- return false;
- if (ns || !attachType || !attachType->attachedPropertiesType())
- return false;
-
- wasAttachedObject = true;
- }
-
- if (ii == 0) {
-
- if (attachType) {
- Instr instr;
- instr.common.type = Instr::LoadScope;
- instr.load.index = 0;
- instr.load.reg = reg;
- bytecode << instr;
-
- Instr attach;
- attach.common.type = Instr::LoadAttached;
- attach.attached.output = reg;
- attach.attached.reg = reg;
- attach.attached.id = attachType->attachedPropertiesId();
- attach.attached.exceptionId = exceptionId(nameNodes.at(ii));
- bytecode << attach;
-
- subscribeName << contextName();
- subscribeName << QLatin1String("$$$ATTACH_") + name;
-
- absType = 0;
- type.metaObject = attachType->attachedPropertiesType();
-
- continue;
- } else if (ids.contains(name)) {
- QDeclarativeParser::Object *idObject = ids.value(name);
- absType = idObject;
- type.metaObject = absType->metaObject();
-
- // We check if the id object is the root or
- // scope object to avoid a subscription
- if (idObject == component) {
- Instr instr;
- instr.common.type = Instr::LoadRoot;
- instr.load.index = 0;
- instr.load.reg = reg;
- bytecode << instr;
- } else if (idObject == context) {
- Instr instr;
- instr.common.type = Instr::LoadScope;
- instr.load.index = 0;
- instr.load.reg = reg;
- bytecode << instr;
- } else {
- Instr instr;
- instr.common.type = Instr::LoadId;
- instr.load.index = idObject->idIndex;
- instr.load.reg = reg;
- bytecode << instr;
-
- subscribeName << QLatin1String("$$$ID_") + name;
-
- if (subscription(subscribeName, &type)) {
- Instr sub;
- sub.common.type = Instr::SubscribeId;
- sub.subscribe.offset = subscriptionIndex(subscribeName);
- sub.subscribe.reg = reg;
- sub.subscribe.index = instr.load.index;
- bytecode << sub;
- }
- }
-
- } else {
-
- QByteArray utf8Name = name.toUtf8();
- const char *cname = utf8Name.constData();
-
- int d0Idx = (context == component)?-1:context->metaObject()->indexOfProperty(cname);
- int d1Idx = -1;
- if (d0Idx == -1)
- d1Idx = component->metaObject()->indexOfProperty(cname);
-
- if (d0Idx != -1) {
- Instr instr;
- instr.common.type = Instr::LoadScope;
- instr.load.index = 0;
- instr.load.reg = reg;
- bytecode << instr;
-
- subscribeName << contextName();
- subscribeName << name;
-
- if (!fetch(type, context->metaObject(), reg, d0Idx, subscribeName, nameNodes.at(ii)))
- return false;
- } else if(d1Idx != -1) {
- Instr instr;
- instr.common.type = Instr::LoadRoot;
- instr.load.index = 0;
- instr.load.reg = reg;
- bytecode << instr;
-
- subscribeName << QLatin1String("$$$ROOT");
- subscribeName << name;
-
- if (!fetch(type, component->metaObject(), reg, d1Idx, subscribeName, nameNodes.at(ii)))
- return false;
- } else if (qmlExperimental()) {
- Instr find;
- if (nameParts.count() == 1)
- find.common.type = Instr::FindGenericTerminal;
- else
- find.common.type = Instr::FindGeneric;
-
- find.find.reg = reg;
- find.find.src = -1;
- find.find.name = registerString(name);
- find.find.exceptionId = exceptionId(nameNodes.at(ii));
-
- subscribeName << QString(QLatin1String("$$$Generic_") + name);
- if (subscription(subscribeName, &type))
- find.find.subscribeIndex = subscriptionIndex(subscribeName);
- else
- find.find.subscribeIndex = -1;
-
- bytecode << find;
- type.unknownType = true;
- }
-
- if (!type.unknownType && type.type == -1)
- return false; // Couldn't fetch that type
- }
-
- } else {
-
- if (attachType) {
- Instr attach;
- attach.common.type = Instr::LoadAttached;
- attach.attached.output = reg;
- attach.attached.reg = reg;
- attach.attached.id = attachType->attachedPropertiesId();
- bytecode << attach;
-
- absType = 0;
- type.metaObject = attachType->attachedPropertiesType();
-
- subscribeName << QLatin1String("$$$ATTACH_") + name;
- continue;
- }
-
- const QMetaObject *mo = 0;
- if (absType)
- mo = absType->metaObject();
- else if (type.metaObject)
- mo = type.metaObject;
-
- QByteArray utf8Name = name.toUtf8();
- const char *cname = utf8Name.constData();
- int idx = mo?mo->indexOfProperty(cname):-1;
- if (absType && idx == -1)
- return false;
-
- subscribeName << name;
-
- if (absType || (wasAttachedObject && idx != -1) || (mo && mo->property(idx).isFinal())) {
- absType = 0;
- if (!fetch(type, mo, reg, idx, subscribeName, nameNodes.at(ii)))
- return false;
- } else {
-
- Instr prop;
- if (ii == nameParts.count() -1 )
- prop.common.type = Instr::FindPropertyTerminal;
- else
- prop.common.type = Instr::FindProperty;
-
- prop.find.reg = reg;
- prop.find.src = reg;
- prop.find.name = registerString(name);
- prop.find.exceptionId = exceptionId(nameNodes.at(ii));
-
- if (subscription(subscribeName, &type))
- prop.find.subscribeIndex = subscriptionIndex(subscribeName);
- else
- prop.find.subscribeIndex = -1;
-
- type.unknownType = true;
- type.metaObject = 0;
- type.type = -1;
- type.reg = reg;
- bytecode << prop;
- }
- }
-
- wasAttachedObject = false;
- }
-
- return true;
-}
-
-bool QDeclarativeBindingCompilerPrivate::tryArith(QDeclarativeJS::AST::Node *node)
-{
- if (node->kind != AST::Node::Kind_BinaryExpression)
- return false;
-
- AST::BinaryExpression *expression = static_cast<AST::BinaryExpression *>(node);
- if (expression->op == QSOperator::Add ||
- expression->op == QSOperator::Sub)
- return true;
- else
- return false;
-}
-
-bool QDeclarativeBindingCompilerPrivate::parseArith(QDeclarativeJS::AST::Node *node, Result &type)
-{
- AST::BinaryExpression *expression = static_cast<AST::BinaryExpression *>(node);
-
- type.reg = acquireReg();
- if (type.reg == -1)
- return false;
-
- Result lhs;
- Result rhs;
-
- if (!parseExpression(expression->left, lhs)) return false;
- if (!parseExpression(expression->right, rhs)) return false;
-
- if ((lhs.type == QVariant::Int || lhs.type == QMetaType::QReal) &&
- (rhs.type == QVariant::Int || rhs.type == QMetaType::QReal))
- return numberArith(type, lhs, rhs, (QSOperator::Op)expression->op);
- else if(expression->op == QSOperator::Sub)
- return numberArith(type, lhs, rhs, (QSOperator::Op)expression->op);
- else if ((lhs.type == QMetaType::QString || lhs.unknownType) &&
- (rhs.type == QMetaType::QString || rhs.unknownType) &&
- (lhs.type == QMetaType::QString || rhs.type == QMetaType::QString))
- return stringArith(type, lhs, rhs, (QSOperator::Op)expression->op);
- else
- return false;
-}
-
-bool QDeclarativeBindingCompilerPrivate::numberArith(Result &type, const Result &lhs, const Result &rhs, QSOperator::Op op)
-{
- bool nativeReal = rhs.type == QMetaType::QReal ||
- lhs.type == QMetaType::QReal ||
- lhs.unknownType ||
- rhs.unknownType;
-
- if (nativeReal && lhs.type == QMetaType::Int) {
- Instr convert;
- convert.common.type = Instr::ConvertIntToReal;
- convert.unaryop.output = lhs.reg;
- convert.unaryop.src = lhs.reg;
- bytecode << convert;
- }
-
- if (nativeReal && rhs.type == QMetaType::Int) {
- Instr convert;
- convert.common.type = Instr::ConvertIntToReal;
- convert.unaryop.output = rhs.reg;
- convert.unaryop.src = rhs.reg;
- bytecode << convert;
- }
-
- int lhsTmp = -1;
- int rhsTmp = -1;
-
- if (lhs.unknownType) {
- if (!qmlExperimental())
- return false;
-
- lhsTmp = acquireReg();
- if (lhsTmp == -1)
- return false;
-
- Instr conv;
- conv.common.type = Instr::ConvertGenericToReal;
- conv.unaryop.output = lhsTmp;
- conv.unaryop.src = lhs.reg;
- bytecode << conv;
- }
-
- if (rhs.unknownType) {
- if (!qmlExperimental())
- return false;
-
- rhsTmp = acquireReg();
- if (rhsTmp == -1)
- return false;
-
- Instr conv;
- conv.common.type = Instr::ConvertGenericToReal;
- conv.unaryop.output = rhsTmp;
- conv.unaryop.src = rhs.reg;
- bytecode << conv;
- }
-
- Instr arith;
- if (op == QSOperator::Add) {
- arith.common.type = nativeReal?Instr::AddReal:Instr::AddInt;
- } else if (op == QSOperator::Sub) {
- arith.common.type = nativeReal?Instr::MinusReal:Instr::MinusInt;
- } else {
- qFatal("Unsupported arithmetic operator");
- }
-
- arith.binaryop.output = type.reg;
- arith.binaryop.src1 = (lhsTmp == -1)?lhs.reg:lhsTmp;
- arith.binaryop.src2 = (rhsTmp == -1)?rhs.reg:rhsTmp;
- bytecode << arith;
-
- type.metaObject = 0;
- type.type = nativeReal?QMetaType::QReal:QMetaType::Int;
- type.subscriptionSet.unite(lhs.subscriptionSet);
- type.subscriptionSet.unite(rhs.subscriptionSet);
-
- if (lhsTmp != -1) releaseReg(lhsTmp);
- if (rhsTmp != -1) releaseReg(rhsTmp);
- releaseReg(lhs.reg);
- releaseReg(rhs.reg);
-
- return true;
-}
-
-bool QDeclarativeBindingCompilerPrivate::stringArith(Result &type, const Result &lhs, const Result &rhs, QSOperator::Op op)
-{
- if (op != QSOperator::Add)
- return false;
-
- int lhsTmp = -1;
- int rhsTmp = -1;
-
- if (lhs.unknownType) {
- if (!qmlExperimental())
- return false;
-
- lhsTmp = acquireReg(Instr::CleanupString);
- if (lhsTmp == -1)
- return false;
-
- Instr convert;
- convert.common.type = Instr::ConvertGenericToString;
- convert.unaryop.output = lhsTmp;
- convert.unaryop.src = lhs.reg;
- bytecode << convert;
- }
-
- if (rhs.unknownType) {
- if (!qmlExperimental())
- return false;
-
- rhsTmp = acquireReg(Instr::CleanupString);
- if (rhsTmp == -1)
- return false;
-
- Instr convert;
- convert.common.type = Instr::ConvertGenericToString;
- convert.unaryop.output = rhsTmp;
- convert.unaryop.src = rhs.reg;
- bytecode << convert;
- }
-
- type.reg = acquireReg(Instr::CleanupString);
- if (type.reg == -1)
- return false;
-
- type.type = QMetaType::QString;
-
- Instr add;
- add.common.type = Instr::AddString;
- add.binaryop.output = type.reg;
- add.binaryop.src1 = (lhsTmp == -1)?lhs.reg:lhsTmp;
- add.binaryop.src2 = (rhsTmp == -1)?rhs.reg:rhsTmp;
- bytecode << add;
-
- if (lhsTmp != -1) releaseReg(lhsTmp);
- if (rhsTmp != -1) releaseReg(rhsTmp);
- releaseReg(lhs.reg);
- releaseReg(rhs.reg);
-
- return true;
-}
-
-bool QDeclarativeBindingCompilerPrivate::tryLogic(QDeclarativeJS::AST::Node *node)
-{
- if (node->kind != AST::Node::Kind_BinaryExpression)
- return false;
-
- AST::BinaryExpression *expression = static_cast<AST::BinaryExpression *>(node);
- if (expression->op == QSOperator::Gt ||
- expression->op == QSOperator::Equal ||
- expression->op == QSOperator::NotEqual)
- return true;
- else
- return false;
-}
-
-bool QDeclarativeBindingCompilerPrivate::parseLogic(QDeclarativeJS::AST::Node *node, Result &type)
-{
- AST::BinaryExpression *expression = static_cast<AST::BinaryExpression *>(node);
-
- Result lhs;
- Result rhs;
-
- if (!parseExpression(expression->left, lhs)) return false;
- if (!parseExpression(expression->right, rhs)) return false;
-
- type.reg = acquireReg();
- if (type.reg == -1)
- return false;
-
- type.metaObject = 0;
- type.type = QVariant::Bool;
-
- if (lhs.type == QMetaType::QReal && rhs.type == QMetaType::QReal) {
-
- Instr op;
- if (expression->op == QSOperator::Gt)
- op.common.type = Instr::GreaterThanReal;
- else if (expression->op == QSOperator::Equal)
- op.common.type = Instr::CompareReal;
- else if (expression->op == QSOperator::NotEqual)
- op.common.type = Instr::NotCompareReal;
- else
- return false;
- op.binaryop.output = type.reg;
- op.binaryop.src1 = lhs.reg;
- op.binaryop.src2 = rhs.reg;
- bytecode << op;
-
-
- } else if (lhs.type == QMetaType::QString && rhs.type == QMetaType::QString) {
-
- Instr op;
- if (expression->op == QSOperator::Equal)
- op.common.type = Instr::CompareString;
- else if (expression->op == QSOperator::NotEqual)
- op.common.type = Instr::NotCompareString;
- else
- return false;
- op.binaryop.output = type.reg;
- op.binaryop.src1 = lhs.reg;
- op.binaryop.src2 = rhs.reg;
- bytecode << op;
-
- } else {
- return false;
- }
-
- releaseReg(lhs.reg);
- releaseReg(rhs.reg);
-
- return true;
-}
-
-bool QDeclarativeBindingCompilerPrivate::tryConditional(QDeclarativeJS::AST::Node *node)
-{
- return (node->kind == AST::Node::Kind_ConditionalExpression);
-}
-
-bool QDeclarativeBindingCompilerPrivate::parseConditional(QDeclarativeJS::AST::Node *node, Result &type)
-{
- AST::ConditionalExpression *expression = static_cast<AST::ConditionalExpression *>(node);
-
- AST::Node *test = expression->expression;
- if (test->kind == AST::Node::Kind_NestedExpression)
- test = static_cast<AST::NestedExpression*>(test)->expression;
-
- Result etype;
- if (!parseExpression(test, etype)) return false;
-
- if (etype.type != QVariant::Bool)
- return false;
-
- Instr skip;
- skip.common.type = Instr::Skip;
- skip.skip.reg = etype.reg;
- skip.skip.count = 0;
- int skipIdx = bytecode.count();
- bytecode << skip;
-
- // Release to allow reuse of reg
- releaseReg(etype.reg);
-
- QSet<QString> preSubSet = subscriptionSet;
-
- // int preConditionalSubscriptions = subscriptionSet.count();
-
- Result ok;
- if (!parseExpression(expression->ok, ok)) return false;
- if (ok.unknownType) return false;
-
- int skipIdx2 = bytecode.count();
- skip.skip.reg = -1;
- bytecode << skip;
-
- // Release to allow reuse of reg
- releaseReg(ok.reg);
- bytecode[skipIdx].skip.count = bytecode.count() - skipIdx - 1;
-
- subscriptionSet = preSubSet;
-
- Result ko;
- if (!parseExpression(expression->ko, ko)) return false;
- if (ko.unknownType) return false;
-
- // Release to allow reuse of reg
- releaseReg(ko.reg);
- bytecode[skipIdx2].skip.count = bytecode.count() - skipIdx2 - 1;
-
- if (ok != ko)
- return false; // Must be same type and in same register
-
- subscriptionSet = preSubSet;
-
- if (!subscriptionNeutral(subscriptionSet, ok.subscriptionSet, ko.subscriptionSet))
- return false; // Conditionals cannot introduce new subscriptions
-
- type = ok;
-
- return true;
-}
-
-bool QDeclarativeBindingCompilerPrivate::tryConstant(QDeclarativeJS::AST::Node *node)
-{
- return node->kind == AST::Node::Kind_TrueLiteral ||
- node->kind == AST::Node::Kind_FalseLiteral ||
- node->kind == AST::Node::Kind_NumericLiteral ||
- node->kind == AST::Node::Kind_StringLiteral;
-}
-
-bool QDeclarativeBindingCompilerPrivate::parseConstant(QDeclarativeJS::AST::Node *node, Result &type)
-{
- type.metaObject = 0;
- type.type = -1;
- type.reg = acquireReg();
- if (type.reg == -1)
- return false;
-
- if (node->kind == AST::Node::Kind_TrueLiteral) {
- type.type = QVariant::Bool;
- Instr instr;
- instr.common.type = Instr::Bool;
- instr.bool_value.reg = type.reg;
- instr.bool_value.value = true;
- bytecode << instr;
- return true;
- } else if (node->kind == AST::Node::Kind_FalseLiteral) {
- type.type = QVariant::Bool;
- Instr instr;
- instr.common.type = Instr::Bool;
- instr.bool_value.reg = type.reg;
- instr.bool_value.value = false;
- bytecode << instr;
- return true;
- } else if (node->kind == AST::Node::Kind_NumericLiteral) {
- qreal value = qreal(static_cast<AST::NumericLiteral *>(node)->value);
-
- if (qreal(float(value)) != value)
- return false;
-
- type.type = QMetaType::QReal;
- Instr instr;
- instr.common.type = Instr::Real;
- instr.real_value.reg = type.reg;
- instr.real_value.value = float(value);
- bytecode << instr;
- return true;
- } else if (node->kind == AST::Node::Kind_StringLiteral) {
- QString str = static_cast<AST::StringLiteral *>(node)->value->asString();
- type.type = QMetaType::QString;
- type.reg = registerLiteralString(str);
- return true;
- } else {
- return false;
- }
-}
-
-bool QDeclarativeBindingCompilerPrivate::tryMethod(QDeclarativeJS::AST::Node *node)
-{
- return node->kind == AST::Node::Kind_CallExpression;
-}
-
-bool QDeclarativeBindingCompilerPrivate::parseMethod(QDeclarativeJS::AST::Node *node, Result &result)
-{
- AST::CallExpression *expr = static_cast<AST::CallExpression *>(node);
-
- QStringList name;
- if (!buildName(name, expr->base))
- return false;
-
- if (name.count() != 2 || name.at(0) != QLatin1String("Math"))
- return false;
-
- QString method = name.at(1);
-
- AST::ArgumentList *args = expr->arguments;
- if (!args) return false;
- AST::ExpressionNode *arg0 = args->expression;
- args = args->next;
- if (!args) return false;
- AST::ExpressionNode *arg1 = args->expression;
- if (args->next != 0) return false;
- if (!arg0 || !arg1) return false;
-
- Result r0;
- if (!parseExpression(arg0, r0)) return false;
- Result r1;
- if (!parseExpression(arg1, r1)) return false;
-
- if (r0.type != QMetaType::QReal || r1.type != QMetaType::QReal)
- return false;
-
- Instr op;
- if (method == QLatin1String("max")) {
- op.common.type = Instr::MaxReal;
- } else if (method == QLatin1String("min")) {
- op.common.type = Instr::MinReal;
- } else {
- return false;
- }
- // We release early to reuse registers
- releaseReg(r0.reg);
- releaseReg(r1.reg);
-
- op.binaryop.output = acquireReg();
- if (op.binaryop.output == -1)
- return false;
-
- op.binaryop.src1 = r0.reg;
- op.binaryop.src2 = r1.reg;
- bytecode << op;
-
- result.type = QMetaType::QReal;
- result.reg = op.binaryop.output;
-
- return true;
-}
-
-bool QDeclarativeBindingCompilerPrivate::buildName(QStringList &name,
- QDeclarativeJS::AST::Node *node,
- QList<QDeclarativeJS::AST::ExpressionNode *> *nodes)
-{
- if (node->kind == AST::Node::Kind_IdentifierExpression) {
- name << static_cast<AST::IdentifierExpression*>(node)->name->asString();
- if (nodes) *nodes << static_cast<AST::IdentifierExpression*>(node);
- } else if (node->kind == AST::Node::Kind_FieldMemberExpression) {
- AST::FieldMemberExpression *expr =
- static_cast<AST::FieldMemberExpression *>(node);
-
- if (!buildName(name, expr->base, nodes))
- return false;
-
- name << expr->name->asString();
- if (nodes) *nodes << expr;
- } else {
- return false;
- }
-
- return true;
-}
-
-bool QDeclarativeBindingCompilerPrivate::fetch(Result &rv, const QMetaObject *mo, int reg,
- int idx, const QStringList &subName,
- QDeclarativeJS::AST::ExpressionNode *node)
-{
- QMetaProperty prop = mo->property(idx);
- rv.metaObject = 0;
- rv.type = 0;
-
- //XXX binding optimizer doesn't handle properties with a revision
- if (prop.revision() > 0)
- return false;
-
- int fastFetchIndex = fastProperties()->accessorIndexForProperty(mo, idx);
-
- Instr fetch;
-
- if (!qmlDisableFastProperties() && fastFetchIndex != -1) {
- fetch.common.type = Instr::FetchAndSubscribe;
- fetch.fetchAndSubscribe.objectReg = reg;
- fetch.fetchAndSubscribe.output = reg;
- fetch.fetchAndSubscribe.function = fastFetchIndex;
- fetch.fetchAndSubscribe.subscription = subscriptionIndex(subName);
- fetch.fetchAndSubscribe.exceptionId = exceptionId(node);
- } else {
- if (subscription(subName, &rv) && prop.hasNotifySignal() && prop.notifySignalIndex() != -1) {
- Instr sub;
- sub.common.type = Instr::Subscribe;
- sub.subscribe.offset = subscriptionIndex(subName);
- sub.subscribe.reg = reg;
- sub.subscribe.index = prop.notifySignalIndex();
- bytecode << sub;
- }
-
- fetch.common.type = Instr::Fetch;
- fetch.fetch.objectReg = reg;
- fetch.fetch.index = idx;
- fetch.fetch.output = reg;
- fetch.fetch.exceptionId = exceptionId(node);
- }
-
- rv.type = prop.userType();
- rv.metaObject = engine->metaObjectForType(rv.type);
- rv.reg = reg;
-
- if (rv.type == QMetaType::QString) {
- int tmp = acquireReg();
- if (tmp == -1)
- return false;
- Instr copy;
- copy.common.type = Instr::Copy;
- copy.copy.reg = tmp;
- copy.copy.src = reg;
- bytecode << copy;
- releaseReg(tmp);
- fetch.fetch.objectReg = tmp;
-
- Instr setup;
- setup.common.type = Instr::NewString;
- setup.construct.reg = reg;
- bytecode << setup;
- registerCleanup(reg, Instr::CleanupString);
- }
-
- bytecode << fetch;
-
- if (!rv.metaObject &&
- rv.type != QMetaType::QReal &&
- rv.type != QMetaType::Int &&
- rv.type != QMetaType::Bool &&
- rv.type != qMetaTypeId<QDeclarativeAnchorLine>() &&
- rv.type != QMetaType::QString) {
- rv.metaObject = 0;
- rv.type = 0;
- return false; // Unsupported type (string not supported yet);
- }
-
- return true;
-}
-
-void QDeclarativeBindingCompilerPrivate::registerCleanup(int reg, int cleanup, int cleanupType)
-{
- registerCleanups.insert(reg, qMakePair(cleanup, cleanupType));
-}
-
-int QDeclarativeBindingCompilerPrivate::acquireReg(int cleanup, int cleanupType)
-{
- for (int ii = 0; ii < 32; ++ii) {
- if (!(registers & (1 << ii))) {
- registers |= (1 << ii);
-
- if (cleanup != Instr::Noop)
- registerCleanup(ii, cleanup, cleanupType);
-
- return ii;
- }
- }
- return -1;
-}
-
-void QDeclarativeBindingCompilerPrivate::releaseReg(int reg)
-{
- Q_ASSERT(reg >= 0 && reg <= 31);
-
- if (registerCleanups.contains(reg)) {
- QPair<int, int> c = registerCleanups[reg];
- registerCleanups.remove(reg);
- Instr cleanup;
- cleanup.common.type = (quint8)c.first;
- cleanup.cleanup.reg = reg;
- bytecode << cleanup;
- }
-
- quint32 mask = 1 << reg;
- registers &= ~mask;
-}
-
-// Returns a reg
-int QDeclarativeBindingCompilerPrivate::registerLiteralString(const QString &str)
-{
- QByteArray strdata((const char *)str.constData(), str.length() * sizeof(QChar));
- int offset = data.count();
- data += strdata;
-
- int reg = acquireReg(Instr::CleanupString);
- if (reg == -1)
- return false;
-
- Instr string;
- string.common.type = Instr::String;
- string.string_value.reg = reg;
- string.string_value.offset = offset;
- string.string_value.length = str.length();
- bytecode << string;
-
- return reg;
-}
-
-// Returns an identifier offset
-int QDeclarativeBindingCompilerPrivate::registerString(const QString &string)
-{
- Q_ASSERT(!string.isEmpty());
-
- QHash<QString, QPair<int, int> >::ConstIterator iter = registeredStrings.find(string);
-
- if (iter == registeredStrings.end()) {
- quint32 len = string.length();
- QByteArray lendata((const char *)&len, sizeof(quint32));
- QByteArray strdata((const char *)string.constData(), string.length() * sizeof(QChar));
- strdata.prepend(lendata);
- int rv = data.count();
- data += strdata;
-
- iter = registeredStrings.insert(string, qMakePair(registeredStrings.count(), rv));
- }
-
- Instr reg;
- reg.common.type = Instr::InitString;
- reg.initstring.offset = iter->first;
- reg.initstring.dataIdx = iter->second;
- bytecode << reg;
- return reg.initstring.offset;
-}
-
-bool QDeclarativeBindingCompilerPrivate::subscription(const QStringList &sub, Result *result)
-{
- QString str = sub.join(QLatin1String("."));
- result->subscriptionSet.insert(str);
-
- if (subscriptionSet.contains(str)) {
- return false;
- } else {
- subscriptionSet.insert(str);
- return true;
- }
-}
-
-int QDeclarativeBindingCompilerPrivate::subscriptionIndex(const QStringList &sub)
-{
- QString str = sub.join(QLatin1String("."));
- QHash<QString, int>::ConstIterator iter = subscriptionIds.find(str);
- if (iter == subscriptionIds.end())
- iter = subscriptionIds.insert(str, subscriptionIds.count());
- usedSubscriptionIds.insert(*iter);
- return *iter;
-}
-
-/*
- Returns true if lhs contains no subscriptions that aren't also in base or rhs AND
- rhs contains no subscriptions that aren't also in base or lhs.
-*/
-bool QDeclarativeBindingCompilerPrivate::subscriptionNeutral(const QSet<QString> &base,
- const QSet<QString> &lhs,
- const QSet<QString> &rhs)
-{
- QSet<QString> difflhs = lhs;
- difflhs.subtract(rhs);
- QSet<QString> diffrhs = rhs;
- diffrhs.subtract(lhs);
-
- difflhs.unite(diffrhs);
- difflhs.subtract(base);
-
- return difflhs.isEmpty();
-}
-
-quint8 QDeclarativeBindingCompilerPrivate::exceptionId(QDeclarativeJS::AST::ExpressionNode *n)
-{
- quint8 rv = 0xFF;
- if (n && exceptions.count() < 0xFF) {
- rv = (quint8)exceptions.count();
- QDeclarativeJS::AST::SourceLocation l = n->firstSourceLocation();
- quint64 e = l.startLine;
- e <<= 32;
- e |= l.startColumn;
- exceptions.append(e);
- }
- return rv;
-}
-
-QDeclarativeBindingCompiler::QDeclarativeBindingCompiler()
-: d(new QDeclarativeBindingCompilerPrivate)
-{
-}
-
-QDeclarativeBindingCompiler::~QDeclarativeBindingCompiler()
-{
- delete d; d = 0;
-}
-
-/*
-Returns true if any bindings were compiled.
-*/
-bool QDeclarativeBindingCompiler::isValid() const
-{
- return !d->committed.bytecode.isEmpty();
-}
-
-/*
--1 on failure, otherwise the binding index to use.
-*/
-int QDeclarativeBindingCompiler::compile(const Expression &expression, QDeclarativeEnginePrivate *engine)
-{
- if (!expression.expression.asAST()) return false;
-
- if (!qmlExperimental() && expression.property->isValueTypeSubProperty)
- return -1;
-
- if (qmlDisableOptimizer())
- return -1;
-
- d->context = expression.context;
- d->component = expression.component;
- d->destination = expression.property;
- d->ids = expression.ids;
- d->imports = expression.imports;
- d->engine = engine;
-
- if (d->compile(expression.expression.asAST())) {
- return d->commitCompile();
- } else {
- return -1;
- }
-}
-
-
-QByteArray QDeclarativeBindingCompilerPrivate::buildSignalTable() const
-{
- QHash<int, QList<int> > table;
-
- for (int ii = 0; ii < committed.count(); ++ii) {
- const QSet<int> &deps = committed.dependencies.at(ii);
- for (QSet<int>::ConstIterator iter = deps.begin(); iter != deps.end(); ++iter)
- table[*iter].append(ii);
- }
-
- QVector<quint32> header;
- QVector<quint32> data;
- for (int ii = 0; ii < committed.subscriptionIds.count(); ++ii) {
- header.append(committed.subscriptionIds.count() + data.count());
- const QList<int> &bindings = table[ii];
- data.append(bindings.count());
- for (int jj = 0; jj < bindings.count(); ++jj)
- data.append(bindings.at(jj));
- }
- header << data;
-
- return QByteArray((const char *)header.constData(), header.count() * sizeof(quint32));
-}
-
-QByteArray QDeclarativeBindingCompilerPrivate::buildExceptionData() const
-{
- QByteArray rv;
- rv.resize(committed.exceptions.count() * sizeof(quint64));
- ::memcpy(rv.data(), committed.exceptions.constData(), rv.size());
- return rv;
-}
-
-/*
-Returns the compiled program.
-*/
-QByteArray QDeclarativeBindingCompiler::program() const
-{
- QByteArray programData;
-
- if (isValid()) {
- Program prog;
- prog.bindings = d->committed.count();
-
- QVector<Instr> bytecode;
- Instr skip;
- skip.common.type = Instr::Skip;
- skip.skip.reg = -1;
- for (int ii = 0; ii < d->committed.count(); ++ii) {
- skip.skip.count = d->committed.count() - ii - 1;
- skip.skip.count+= d->committed.offsets.at(ii);
- bytecode << skip;
- }
- bytecode << d->committed.bytecode;
-
- QByteArray data = d->committed.data;
- while (data.count() % 4) data.append('\0');
- prog.signalTableOffset = data.count();
- data += d->buildSignalTable();
- while (data.count() % 4) data.append('\0');
- prog.exceptionDataOffset = data.count();
- data += d->buildExceptionData();
-
- prog.dataLength = 4 * ((data.size() + 3) / 4);
- prog.subscriptions = d->committed.subscriptionIds.count();
- prog.identifiers = d->committed.registeredStrings.count();
- prog.instructionCount = bytecode.count();
- prog.compiled = false;
- int size = sizeof(Program) + bytecode.count() * sizeof(Instr);
- size += prog.dataLength;
-
- programData.resize(size);
- memcpy(programData.data(), &prog, sizeof(Program));
- if (prog.dataLength)
- memcpy((char *)((Program *)programData.data())->data(), data.constData(),
- data.size());
- memcpy((char *)((Program *)programData.data())->instructions(), bytecode.constData(),
- bytecode.count() * sizeof(Instr));
- }
-
- return programData;
-}
-
-
-
-QT_END_NAMESPACE