1 /****************************************************************************
3 ** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
4 ** All rights reserved.
5 ** Contact: Nokia Corporation (qt-info@nokia.com)
7 ** This file is part of the QtDeclarative module of the Qt Toolkit.
9 ** $QT_BEGIN_LICENSE:LGPL$
10 ** No Commercial Usage
11 ** This file contains pre-release code and may not be distributed.
12 ** You may use this file in accordance with the terms and conditions
13 ** contained in the Technology Preview License Agreement accompanying
16 ** GNU Lesser General Public License Usage
17 ** Alternatively, this file may be used under the terms of the GNU Lesser
18 ** General Public License version 2.1 as published by the Free Software
19 ** Foundation and appearing in the file LICENSE.LGPL included in the
20 ** packaging of this file. Please review the following information to
21 ** ensure the GNU Lesser General Public License version 2.1 requirements
22 ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
24 ** In addition, as a special exception, Nokia gives you certain additional
25 ** rights. These rights are described in the Nokia Qt LGPL Exception
26 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
40 ****************************************************************************/
42 // #define REGISTER_CLEANUP_DEBUG
44 #include "private/qdeclarativev4bindings_p.h"
45 #include "private/qdeclarativev4program_p.h"
46 #include "private/qdeclarativev4compiler_p.h"
48 #include <private/qdeclarativefastproperties_p.h>
49 #include <private/qdeclarativedebugtrace_p.h>
50 #include <private/qdeclarativeanchors_p_p.h> // For AnchorLine
51 #include <private/qsganchors_p_p.h> // For AnchorLine
53 #include <QtDeclarative/qdeclarativeinfo.h>
54 #include <QtCore/qnumeric.h>
55 #include <QtCore/qmath.h>
56 #include <math.h> // ::fmod
60 using namespace QDeclarativeJS;
64 typedef QDeclarativeRegisterType Type;
66 void setUndefined() { dataType = UndefinedType; }
67 void setNaN() { setqreal(qSNaN()); }
68 bool isUndefined() const { return dataType == UndefinedType; }
70 void setQObject(QObject *o) { *((QObject **)data) = o; dataType = QObjectStarType; }
71 QObject *getQObject() const { return *((QObject **)data); }
73 void setqreal(qreal v) { *((qreal *)data) = v; dataType = QRealType; }
74 qreal getqreal() const { return *((qreal *)data); }
75 qreal &getqrealref() const { return *((qreal *)data); }
77 void setint(int v) { *((int *)data) = v; dataType = IntType; }
78 int getint() const { return *((int *)data); }
79 int &getintref() const { return *((int *)data); }
81 void setbool(bool v) { *((bool *)data) = v; dataType = BoolType; }
82 bool getbool() const { return *((bool *)data); }
83 bool &getboolref() const { return *((bool *)data); }
85 QVariant *getvariantptr() { return (QVariant *)typeDataPtr(); }
86 QString *getstringptr() { return (QString *)typeDataPtr(); }
87 QUrl *geturlptr() { return (QUrl *)typeDataPtr(); }
88 const QVariant *getvariantptr() const { return (QVariant *)typeDataPtr(); }
89 const QString *getstringptr() const { return (QString *)typeDataPtr(); }
90 const QUrl *geturlptr() const { return (QUrl *)typeDataPtr(); }
92 void *typeDataPtr() { return (void *)&data; }
93 void *typeMemory() { return (void *)data; }
94 const void *typeDataPtr() const { return (void *)&data; }
95 const void *typeMemory() const { return (void *)data; }
97 Type gettype() const { return dataType; }
98 void settype(Type t) { dataType = t; }
100 // int type; // Optional type
102 Type dataType; // Type of data
103 void *data[2]; // Object stored here
105 inline void cleanup();
106 inline void cleanupString();
107 inline void cleanupUrl();
108 inline void cleanupVariant();
110 inline void copy(const Register &other);
111 inline void init(Type type);
112 #ifdef REGISTER_CLEANUP_DEBUG
118 if (dataType >= FirstCleanupType)
119 qWarning("Register leaked of type %d", dataType);
124 void Register::cleanup()
126 if (dataType >= FirstCleanupType) {
127 if (dataType == QStringType) {
128 getstringptr()->~QString();
129 } else if (dataType == QUrlType) {
130 geturlptr()->~QUrl();
131 } else if (dataType == QVariantType) {
132 getvariantptr()->~QVariant();
138 void Register::cleanupString()
140 getstringptr()->~QString();
144 void Register::cleanupUrl()
146 geturlptr()->~QUrl();
150 void Register::cleanupVariant()
152 getvariantptr()->~QVariant();
156 void Register::copy(const Register &other)
159 if (other.dataType >= FirstCleanupType) {
160 if (other.dataType == QStringType)
161 new (getstringptr()) QString(*other.getstringptr());
162 else if (other.dataType == QUrlType)
163 new (geturlptr()) QUrl(*other.geturlptr());
164 else if (other.dataType == QVariantType)
165 new (getvariantptr()) QVariant(*other.getvariantptr());
169 void Register::init(Type type)
172 if (dataType >= FirstCleanupType) {
173 if (dataType == QStringType)
174 new (getstringptr()) QString();
175 else if (dataType == QUrlType)
176 new (geturlptr()) QUrl();
177 else if (dataType == QVariantType)
178 new (getvariantptr()) QVariant();
182 } // end of anonymous namespace
184 class QDeclarativeV4BindingsPrivate : public QObjectPrivate
186 Q_DECLARE_PUBLIC(QDeclarativeV4Bindings)
189 QDeclarativeV4BindingsPrivate();
190 virtual ~QDeclarativeV4BindingsPrivate();
192 struct Binding : public QDeclarativeAbstractBinding, public QDeclarativeDelayedError {
193 Binding() : enabled(false), updating(0), property(0),
194 scope(0), target(0), executedBlocks(0), parent(0) {}
196 // Inherited from QDeclarativeAbstractBinding
197 virtual void setEnabled(bool, QDeclarativePropertyPrivate::WriteFlags flags);
198 virtual void update(QDeclarativePropertyPrivate::WriteFlags flags);
199 virtual void destroy();
207 quint32 executedBlocks;
209 QDeclarativeV4BindingsPrivate *parent;
212 typedef QDeclarativeNotifierEndpoint Subscription;
213 Subscription *subscriptions;
214 QScriptDeclarativeClass::PersistentIdentifier *identifiers;
216 void run(Binding *, QDeclarativePropertyPrivate::WriteFlags flags);
218 QDeclarativeV4Program *program;
221 static int methodCount;
224 void run(int instr, quint32 &executedBlocks, QDeclarativeContextData *context,
225 QDeclarativeDelayedError *error, QObject *scope, QObject *output,
226 QDeclarativePropertyPrivate::WriteFlags storeFlags
227 #ifdef QML_THREADED_INTERPRETER
228 , void ***decode_instr = 0
233 inline void unsubscribe(int subIndex);
234 inline void subscribeId(QDeclarativeContextData *p, int idIndex, int subIndex);
235 inline void subscribe(QObject *o, int notifyIndex, int subIndex);
237 inline static qint32 toInt32(qsreal n);
238 static const qsreal D32;
239 static quint32 toUint32(qsreal n);
242 QDeclarativeV4BindingsPrivate::QDeclarativeV4BindingsPrivate()
243 : subscriptions(0), identifiers(0), program(0), bindings(0)
247 QDeclarativeV4BindingsPrivate::~QDeclarativeV4BindingsPrivate()
249 delete [] subscriptions; subscriptions = 0;
250 delete [] identifiers; identifiers = 0;
253 int QDeclarativeV4BindingsPrivate::methodCount = -1;
255 QDeclarativeV4Bindings::QDeclarativeV4Bindings(const char *program, QDeclarativeContextData *context)
256 : QObject(*(new QDeclarativeV4BindingsPrivate))
258 Q_D(QDeclarativeV4Bindings);
260 if (d->methodCount == -1)
261 d->methodCount = QDeclarativeV4Bindings::staticMetaObject.methodCount();
263 d->program = (QDeclarativeV4Program *)program;
268 QDeclarativeAbstractExpression::setContext(context);
272 QDeclarativeV4Bindings::~QDeclarativeV4Bindings()
274 Q_D(QDeclarativeV4Bindings);
276 delete [] d->bindings;
279 QDeclarativeAbstractBinding *QDeclarativeV4Bindings::configBinding(int index, QObject *target,
280 QObject *scope, int property)
282 Q_D(QDeclarativeV4Bindings);
284 QDeclarativeV4BindingsPrivate::Binding *rv = d->bindings + index;
287 rv->property = property;
292 addref(); // This is decremented in Binding::destroy()
297 void QDeclarativeV4BindingsPrivate::Binding::setEnabled(bool e, QDeclarativePropertyPrivate::WriteFlags flags)
302 if (e) update(flags);
306 void QDeclarativeV4BindingsPrivate::Binding::update(QDeclarativePropertyPrivate::WriteFlags flags)
308 QDeclarativeDebugTrace::startRange(QDeclarativeDebugTrace::Binding);
309 parent->run(this, flags);
310 QDeclarativeDebugTrace::endRange(QDeclarativeDebugTrace::Binding);
313 void QDeclarativeV4BindingsPrivate::Binding::destroy()
318 parent->q_func()->release();
321 int QDeclarativeV4Bindings::qt_metacall(QMetaObject::Call c, int id, void **)
323 Q_D(QDeclarativeV4Bindings);
325 if (c == QMetaObject::InvokeMetaMethod && id >= d->methodCount) {
326 id -= d->methodCount;
328 QDeclarativeV4Program::BindingReferenceList *list = d->program->signalTable(id);
330 for (quint32 ii = 0; ii < list->count; ++ii) {
331 QDeclarativeV4Program::BindingReference *bindingRef = list->bindings + ii;
333 QDeclarativeV4BindingsPrivate::Binding *binding = d->bindings + bindingRef->binding;
334 if (binding->executedBlocks & bindingRef->blockMask)
335 d->run(binding, QDeclarativePropertyPrivate::DontRemoveBinding);
341 void QDeclarativeV4BindingsPrivate::run(Binding *binding, QDeclarativePropertyPrivate::WriteFlags flags)
343 Q_Q(QDeclarativeV4Bindings);
345 if (!binding->enabled)
348 QDeclarativeContextData *context = q->QDeclarativeAbstractExpression::context();
349 if (!context || !context->isValid())
352 if (binding->updating) {
354 if (binding->property & 0xFFFF0000) {
355 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine);
357 QDeclarativeValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF];
360 name = QLatin1String(binding->target->metaObject()->property(binding->property & 0xFFFF).name());
361 name.append(QLatin1String("."));
362 name.append(QLatin1String(vt->metaObject()->property(binding->property >> 24).name()));
364 name = QLatin1String(binding->target->metaObject()->property(binding->property).name());
366 qmlInfo(binding->target) << QCoreApplication::translate("QDeclarativeV4Bindings", "Binding loop detected for property \"%1\"").arg(name);
370 binding->updating = true;
371 if (binding->property & 0xFFFF0000) {
372 QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(context->engine);
374 QDeclarativeValueType *vt = ep->valueTypes[(binding->property >> 16) & 0xFF];
376 vt->read(binding->target, binding->property & 0xFFFF);
378 QObject *target = vt;
379 run(binding->index, binding->executedBlocks, context, binding, binding->scope, target, flags);
381 vt->write(binding->target, binding->property & 0xFFFF, flags);
383 run(binding->index, binding->executedBlocks, context, binding, binding->scope, binding->target, flags);
385 binding->updating = false;
389 void QDeclarativeV4BindingsPrivate::unsubscribe(int subIndex)
391 QDeclarativeV4BindingsPrivate::Subscription *sub = (subscriptions + subIndex);
395 void QDeclarativeV4BindingsPrivate::subscribeId(QDeclarativeContextData *p, int idIndex, int subIndex)
397 Q_Q(QDeclarativeV4Bindings);
399 unsubscribe(subIndex);
401 if (p->idValues[idIndex]) {
402 QDeclarativeV4BindingsPrivate::Subscription *sub = (subscriptions + subIndex);
404 sub->targetMethod = methodCount + subIndex;
405 sub->connect(&p->idValues[idIndex].bindings);
409 void QDeclarativeV4BindingsPrivate::subscribe(QObject *o, int notifyIndex, int subIndex)
411 Q_Q(QDeclarativeV4Bindings);
413 QDeclarativeV4BindingsPrivate::Subscription *sub = (subscriptions + subIndex);
415 sub->targetMethod = methodCount + subIndex;
417 sub->connect(o, notifyIndex);
422 // Conversion functions - these MUST match the QtScript expression path
423 inline static qreal toReal(Register *reg, int type, bool *ok = 0)
427 if (type == QMetaType::QReal) {
428 return reg->getqreal();
429 } else if (type == qMetaTypeId<QVariant>()) {
430 return reg->getvariantptr()->toReal();
437 inline static QString toString(Register *reg, int type, bool *ok = 0)
441 if (type == QMetaType::QReal) {
442 return QString::number(reg->getqreal());
443 } else if (type == QMetaType::Int) {
444 return QString::number(reg->getint());
445 } else if (type == qMetaTypeId<QVariant>()) {
446 return reg->getvariantptr()->toString();
447 } else if (type == QMetaType::QString) {
448 return *reg->getstringptr();
455 inline static bool toBool(Register *reg, int type, bool *ok = 0)
459 if (type == QMetaType::Bool) {
460 return reg->getbool();
461 } else if (type == qMetaTypeId<QVariant>()) {
462 return reg->getvariantptr()->toBool();
469 inline static QUrl toUrl(Register *reg, int type, QDeclarativeContextData *context, bool *ok = 0)
474 if (type == qMetaTypeId<QVariant>()) {
475 QVariant *var = reg->getvariantptr();
476 int vt = var->type();
477 if (vt == QVariant::Url) {
479 } else if (vt == QVariant::ByteArray) {
480 base = QUrl(QString::fromUtf8(var->toByteArray()));
481 } else if (vt == QVariant::String) {
482 base = QUrl(var->toString());
487 } else if (type == QMetaType::QString) {
488 base = QUrl(*reg->getstringptr());
494 if (!base.isEmpty() && base.isRelative())
495 return context->url.resolved(base);
500 static QObject *variantToQObject(const QVariant &value, bool *ok)
504 if (value.userType() == QMetaType::QObjectStar) {
505 return qvariant_cast<QObject*>(value);
512 void QDeclarativeV4BindingsPrivate::init()
514 if (program->subscriptions)
515 subscriptions = new QDeclarativeV4BindingsPrivate::Subscription[program->subscriptions];
516 if (program->identifiers)
517 identifiers = new QScriptDeclarativeClass::PersistentIdentifier[program->identifiers];
519 bindings = new QDeclarativeV4BindingsPrivate::Binding[program->bindings];
522 static bool testCompareVariants(const QVariant &qtscriptRaw, const QVariant &v4)
524 QVariant qtscript = qtscriptRaw;
526 if (qtscript.userType() == v4.userType()) {
527 } else if (qtscript.canConvert((QVariant::Type)v4.userType())) {
528 qtscript.convert((QVariant::Type)v4.userType());
529 } else if (qtscript.userType() == QVariant::Invalid && v4.userType() == QMetaType::QObjectStar) {
530 qtscript = qVariantFromValue<QObject *>(0);
535 int type = qtscript.userType();
537 if (type == qMetaTypeId<QDeclarativeAnchorLine>()) {
538 QDeclarativeAnchorLine la = qvariant_cast<QDeclarativeAnchorLine>(qtscript);
539 QDeclarativeAnchorLine ra = qvariant_cast<QDeclarativeAnchorLine>(v4);
542 } else if (type == qMetaTypeId<QSGAnchorLine>()) {
543 QSGAnchorLine la = qvariant_cast<QSGAnchorLine>(qtscript);
544 QSGAnchorLine ra = qvariant_cast<QSGAnchorLine>(v4);
547 } else if (type == QMetaType::Double) {
549 double la = qvariant_cast<double>(qtscript);
550 double lr = qvariant_cast<double>(v4);
552 return la == lr || (qIsNaN(la) && qIsNaN(lr));
554 } else if (type == QMetaType::Float) {
556 float la = qvariant_cast<float>(qtscript);
557 float lr = qvariant_cast<float>(v4);
559 return la == lr || (qIsNaN(la) && qIsNaN(lr));
562 return qtscript == v4;
566 QByteArray testResultToString(const QVariant &result, bool undefined)
578 static void testBindingResult(const QString &binding, int line, int column,
579 QDeclarativeContextData *context, QObject *scope,
580 const Register &result, int resultType)
582 QDeclarativeExpression expression(context->asQDeclarativeContext(), scope, binding);
583 bool isUndefined = false;
584 QVariant value = expression.evaluate(&isUndefined);
586 bool iserror = false;
587 QByteArray qtscriptResult;
590 if (expression.hasError()) {
592 qtscriptResult = "exception";
594 qtscriptResult = testResultToString(value, isUndefined);
597 if (isUndefined && result.isUndefined()) {
599 } else if(isUndefined != result.isUndefined()) {
604 if (!result.isUndefined()) {
605 switch (resultType) {
606 case QMetaType::QString:
607 v4value = *result.getstringptr();
609 case QMetaType::QUrl:
610 v4value = *result.geturlptr();
612 case QMetaType::QObjectStar:
613 v4value = qVariantFromValue<QObject *>(result.getQObject());
615 case QMetaType::Bool:
616 v4value = result.getbool();
619 v4value = result.getint();
621 case QMetaType::QReal:
622 v4value = result.getqreal();
625 if (resultType == qMetaTypeId<QDeclarativeAnchorLine>()) {
626 v4value = qVariantFromValue<QDeclarativeAnchorLine>(*(QDeclarativeAnchorLine *)result.typeDataPtr());
627 } else if (resultType == qMetaTypeId<QSGAnchorLine>()) {
628 v4value = qVariantFromValue<QSGAnchorLine>(*(QSGAnchorLine *)result.typeDataPtr());
631 v4Result = "Unknown V4 type";
635 if (v4Result.isEmpty())
636 v4Result = testResultToString(v4value, result.isUndefined());
638 if (!testCompareVariants(value, v4value))
642 qWarning().nospace() << "QDeclarativeV4: Optimization error @" << context->url.toString().toUtf8().constData() << ":" << line << ":" << column;
644 qWarning().nospace() << " Binding: " << binding;
645 qWarning().nospace() << " QtScript: " << qtscriptResult.constData();
646 qWarning().nospace() << " V4: " << v4Result.constData();
650 static void testBindingException(const QString &binding, int line, int column,
651 QDeclarativeContextData *context, QObject *scope)
653 QDeclarativeExpression expression(context->asQDeclarativeContext(), scope, binding);
654 bool isUndefined = false;
655 QVariant value = expression.evaluate(&isUndefined);
657 if (!expression.hasError()) {
658 QByteArray qtscriptResult = testResultToString(value, isUndefined);
659 qWarning().nospace() << "QDeclarativeV4: Optimization error @" << context->url.toString().toUtf8().constData() << ":" << line << ":" << column;
660 qWarning().nospace() << " Binding: " << binding;
661 qWarning().nospace() << " QtScript: " << qtscriptResult.constData();
662 qWarning().nospace() << " V4: exception";
666 static void throwException(int id, QDeclarativeDelayedError *error,
667 QDeclarativeV4Program *program, QDeclarativeContextData *context,
668 const QString &description = QString())
670 error->error.setUrl(context->url);
671 if (description.isEmpty())
672 error->error.setDescription(QLatin1String("TypeError: Result of expression is not an object"));
674 error->error.setDescription(description);
676 quint64 e = *((quint64 *)(program->data() + program->exceptionDataOffset) + id);
677 error->error.setLine((e >> 32) & 0xFFFFFFFF);
678 error->error.setColumn(e & 0xFFFFFFFF);
680 error->error.setLine(-1);
681 error->error.setColumn(-1);
683 if (!context->engine || !error->addError(QDeclarativeEnginePrivate::get(context->engine)))
684 QDeclarativeEnginePrivate::warning(context->engine, error->error);
687 const qsreal QDeclarativeV4BindingsPrivate::D32 = 4294967296.0;
689 qint32 QDeclarativeV4BindingsPrivate::toInt32(qsreal n)
691 if (qIsNaN(n) || qIsInf(n) || (n == 0))
694 double sign = (n < 0) ? -1.0 : 1.0;
695 qsreal abs_n = fabs(n);
697 n = ::fmod(sign * ::floor(abs_n), D32);
698 const double D31 = D32 / 2.0;
700 if (sign == -1 && n < -D31)
703 else if (sign != -1 && n >= D31)
709 inline quint32 QDeclarativeV4BindingsPrivate::toUint32(qsreal n)
711 if (qIsNaN(n) || qIsInf(n) || (n == 0))
714 double sign = (n < 0) ? -1.0 : 1.0;
715 qsreal abs_n = fabs(n);
717 n = ::fmod(sign * ::floor(abs_n), D32);
725 #define THROW_EXCEPTION_STR(id, str) { \
726 if (testBinding) testBindingException(*testBindingSource, bindingLine, bindingColumn, context, scope); \
727 throwException((id), error, program, context, (str)); \
728 goto exceptionExit; \
731 #define THROW_EXCEPTION(id) THROW_EXCEPTION_STR(id, QString())
733 #define MARK_REGISTER(reg) cleanupRegisterMask |= (1 << (reg))
734 #define MARK_CLEAN_REGISTER(reg) cleanupRegisterMask &= ~(1 << (reg))
736 #define STRING_REGISTER(reg) { \
737 registers[(reg)].settype(QStringType); \
738 MARK_REGISTER(reg); \
741 #define URL_REGISTER(reg) { \
742 registers[(reg)].settype(QUrlType); \
743 MARK_REGISTER(reg); \
746 #define VARIANT_REGISTER(reg) { \
747 registers[(reg)].settype(QVariantType); \
748 MARK_REGISTER(reg); \
751 #ifdef QML_THREADED_INTERPRETER
752 void **QDeclarativeV4Bindings::getDecodeInstrTable()
754 static void **decode_instr;
756 QDeclarativeV4Bindings dummy(0, 0);
757 quint32 executedBlocks = 0;
758 dummy.d_func()->run(0, executedBlocks, 0, 0, 0, 0, QDeclarativePropertyPrivate::BypassInterceptor, &decode_instr);
764 void QDeclarativeV4BindingsPrivate::run(int instrIndex, quint32 &executedBlocks,
765 QDeclarativeContextData *context, QDeclarativeDelayedError *error,
766 QObject *scope, QObject *output, QDeclarativePropertyPrivate::WriteFlags storeFlags
767 #ifdef QML_THREADED_INTERPRETER
772 Q_Q(QDeclarativeV4Bindings);
774 #ifdef QML_THREADED_INTERPRETER
776 static void *decode_instr[] = {
777 FOR_EACH_V4_INSTR(QML_V4_INSTR_ADDR)
780 *table = decode_instr;
786 error->removeError();
788 Register registers[32];
789 quint32 cleanupRegisterMask = 0;
793 QDeclarativeEnginePrivate *engine = QDeclarativeEnginePrivate::get(context->engine);
794 const char *code = program->instructions();
795 code += instrIndex * QML_V4_INSTR_SIZE(Jump, jump);
796 const Instr *instr = (const Instr *) code;
798 const char *data = program->data();
800 QString *testBindingSource = 0;
801 bool testBinding = false;
803 int bindingColumn = 0;
805 #ifdef QML_THREADED_INTERPRETER
806 goto *instr->common.code;
809 switch (instr->common.type) {
812 QML_V4_BEGIN_INSTR(Noop, common)
813 QML_V4_END_INSTR(Noop, common)
815 QML_V4_BEGIN_INSTR(BindingId, id)
816 bindingLine = instr->id.line;
817 bindingColumn = instr->id.column;
818 QML_V4_END_INSTR(BindingId, id)
820 QML_V4_BEGIN_INSTR(SubscribeId, subscribeop)
821 subscribeId(context, instr->subscribeop.index, instr->subscribeop.offset);
822 QML_V4_END_INSTR(SubscribeId, subscribeop)
824 QML_V4_BEGIN_INSTR(Subscribe, subscribeop)
827 const Register &object = registers[instr->subscribeop.reg];
828 if (!object.isUndefined()) o = object.getQObject();
829 subscribe(o, instr->subscribeop.index, instr->subscribeop.offset);
831 QML_V4_END_INSTR(Subscribe, subscribeop)
833 QML_V4_BEGIN_INSTR(FetchAndSubscribe, fetchAndSubscribe)
835 Register ® = registers[instr->fetchAndSubscribe.reg];
837 if (reg.isUndefined())
838 THROW_EXCEPTION(instr->fetchAndSubscribe.exceptionId);
840 QObject *object = reg.getQObject();
844 int subIdx = instr->fetchAndSubscribe.subscription;
845 QDeclarativeV4BindingsPrivate::Subscription *sub = 0;
847 sub = (subscriptions + subIdx);
849 sub->targetMethod = methodCount + subIdx;
851 reg.init((Register::Type)instr->fetchAndSubscribe.valueType);
852 if (instr->fetchAndSubscribe.valueType >= FirstCleanupType)
853 MARK_REGISTER(instr->fetchAndSubscribe.reg);
854 QDeclarativeV4Compiler::fastPropertyAccessor()->accessor(instr->fetchAndSubscribe.function)(object, reg.typeDataPtr(), sub);
857 QML_V4_END_INSTR(FetchAndSubscribe, fetchAndSubscribe)
859 QML_V4_BEGIN_INSTR(LoadId, load)
860 registers[instr->load.reg].setQObject(context->idValues[instr->load.index].data());
861 QML_V4_END_INSTR(LoadId, load)
863 QML_V4_BEGIN_INSTR(LoadScope, load)
864 registers[instr->load.reg].setQObject(scope);
865 QML_V4_END_INSTR(LoadScope, load)
867 QML_V4_BEGIN_INSTR(LoadRoot, load)
868 registers[instr->load.reg].setQObject(context->contextObject);
869 QML_V4_END_INSTR(LoadRoot, load)
871 QML_V4_BEGIN_INSTR(LoadAttached, attached)
873 const Register &input = registers[instr->attached.reg];
874 Register &output = registers[instr->attached.output];
875 if (input.isUndefined())
876 THROW_EXCEPTION(instr->attached.exceptionId);
878 QObject *object = registers[instr->attached.reg].getQObject();
880 output.setUndefined();
882 QObject *attached = qmlAttachedPropertiesObjectById(instr->attached.id, input.getQObject(), true);
884 output.setQObject(attached);
887 QML_V4_END_INSTR(LoadAttached, attached)
889 QML_V4_BEGIN_INSTR(UnaryNot, unaryop)
891 registers[instr->unaryop.output].setbool(!registers[instr->unaryop.src].getbool());
893 QML_V4_END_INSTR(UnaryNot, unaryop)
895 QML_V4_BEGIN_INSTR(UnaryMinusReal, unaryop)
897 registers[instr->unaryop.output].setqreal(-registers[instr->unaryop.src].getqreal());
899 QML_V4_END_INSTR(UnaryMinusReal, unaryop)
901 QML_V4_BEGIN_INSTR(UnaryMinusInt, unaryop)
903 registers[instr->unaryop.output].setint(-registers[instr->unaryop.src].getint());
905 QML_V4_END_INSTR(UnaryMinusInt, unaryop)
907 QML_V4_BEGIN_INSTR(UnaryPlusReal, unaryop)
909 registers[instr->unaryop.output].setqreal(+registers[instr->unaryop.src].getqreal());
911 QML_V4_END_INSTR(UnaryPlusReal, unaryop)
913 QML_V4_BEGIN_INSTR(UnaryPlusInt, unaryop)
915 registers[instr->unaryop.output].setint(+registers[instr->unaryop.src].getint());
917 QML_V4_END_INSTR(UnaryPlusInt, unaryop)
919 QML_V4_BEGIN_INSTR(ConvertBoolToInt, unaryop)
921 const Register &src = registers[instr->unaryop.src];
922 Register &output = registers[instr->unaryop.output];
923 if (src.isUndefined()) output.setUndefined();
924 else output.setint(src.getbool());
926 QML_V4_END_INSTR(ConvertBoolToInt, unaryop)
928 QML_V4_BEGIN_INSTR(ConvertBoolToReal, unaryop)
930 const Register &src = registers[instr->unaryop.src];
931 Register &output = registers[instr->unaryop.output];
932 if (src.isUndefined()) output.setUndefined();
933 else output.setqreal(src.getbool());
935 QML_V4_END_INSTR(ConvertBoolToReal, unaryop)
937 QML_V4_BEGIN_INSTR(ConvertBoolToString, unaryop)
939 const Register &src = registers[instr->unaryop.src];
940 Register &output = registers[instr->unaryop.output];
941 if (src.isUndefined()) {
942 output.setUndefined();
944 new (output.getstringptr()) QString(QLatin1String(src.getbool() ? "true" : "false"));
945 STRING_REGISTER(instr->unaryop.output);
948 QML_V4_END_INSTR(ConvertBoolToString, unaryop)
950 QML_V4_BEGIN_INSTR(ConvertIntToBool, unaryop)
952 const Register &src = registers[instr->unaryop.src];
953 Register &output = registers[instr->unaryop.output];
954 if (src.isUndefined()) output.setUndefined();
955 else output.setbool(src.getint());
957 QML_V4_END_INSTR(ConvertIntToBool, unaryop)
959 QML_V4_BEGIN_INSTR(ConvertIntToReal, unaryop)
961 const Register &src = registers[instr->unaryop.src];
962 Register &output = registers[instr->unaryop.output];
963 if (src.isUndefined()) output.setUndefined();
964 else output.setqreal(qreal(src.getint()));
966 QML_V4_END_INSTR(ConvertIntToReal, unaryop)
968 QML_V4_BEGIN_INSTR(ConvertIntToString, unaryop)
970 const Register &src = registers[instr->unaryop.src];
971 Register &output = registers[instr->unaryop.output];
972 if (src.isUndefined()) {
973 output.setUndefined();
975 new (output.getstringptr()) QString(QString::number(src.getint()));
976 STRING_REGISTER(instr->unaryop.output);
979 QML_V4_END_INSTR(ConvertIntToString, unaryop)
981 QML_V4_BEGIN_INSTR(ConvertRealToBool, unaryop)
983 const Register &src = registers[instr->unaryop.src];
984 Register &output = registers[instr->unaryop.output];
985 if (src.isUndefined()) output.setUndefined();
986 else output.setbool(src.getqreal() != 0);
988 QML_V4_END_INSTR(ConvertRealToBool, unaryop)
990 QML_V4_BEGIN_INSTR(ConvertRealToInt, unaryop)
992 const Register &src = registers[instr->unaryop.src];
993 Register &output = registers[instr->unaryop.output];
994 if (src.isUndefined()) output.setUndefined();
995 else output.setint(toInt32(src.getqreal()));
997 QML_V4_END_INSTR(ConvertRealToInt, unaryop)
999 QML_V4_BEGIN_INSTR(ConvertRealToString, unaryop)
1001 const Register &src = registers[instr->unaryop.src];
1002 Register &output = registers[instr->unaryop.output];
1004 if (src.isUndefined()) {
1005 output.setUndefined();
1007 new (output.getstringptr()) QString(QString::number(src.getqreal()));
1008 STRING_REGISTER(instr->unaryop.output);
1011 QML_V4_END_INSTR(ConvertRealToString, unaryop)
1013 QML_V4_BEGIN_INSTR(ConvertStringToBool, unaryop)
1015 const Register &src = registers[instr->unaryop.src];
1016 Register &output = registers[instr->unaryop.output];
1018 if (src.isUndefined()) {
1019 output.setUndefined();
1021 // Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine.
1022 // Ideally we should just call the methods in the QScript namespace directly.
1023 QScriptValue tmp(*src.getstringptr());
1024 if (instr->unaryop.src == instr->unaryop.output) {
1025 output.cleanupString();
1026 MARK_CLEAN_REGISTER(instr->unaryop.output);
1028 output.setbool(tmp.toBool());
1031 QML_V4_END_INSTR(ConvertStringToBool, unaryop)
1033 QML_V4_BEGIN_INSTR(ConvertStringToInt, unaryop)
1035 const Register &src = registers[instr->unaryop.src];
1036 Register &output = registers[instr->unaryop.output];
1038 if (src.isUndefined()) {
1039 output.setUndefined();
1041 // Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine.
1042 // Ideally we should just call the methods in the QScript namespace directly.
1043 QScriptValue tmp(*src.getstringptr());
1044 if (instr->unaryop.src == instr->unaryop.output) {
1045 output.cleanupString();
1046 MARK_CLEAN_REGISTER(instr->unaryop.output);
1048 output.setint(tmp.toInt32());
1051 QML_V4_END_INSTR(ConvertStringToInt, unaryop)
1053 QML_V4_BEGIN_INSTR(ConvertStringToReal, unaryop)
1055 const Register &src = registers[instr->unaryop.src];
1056 Register &output = registers[instr->unaryop.output];
1058 if (src.isUndefined()) {
1059 output.setUndefined();
1061 // Delegate the conversion. This is pretty fast and it doesn't require a QScriptEngine.
1062 // Ideally we should just call the methods in the QScript namespace directly.
1063 QScriptValue tmp(*src.getstringptr());
1064 if (instr->unaryop.src == instr->unaryop.output) {
1065 output.cleanupString();
1066 MARK_CLEAN_REGISTER(instr->unaryop.output);
1068 output.setqreal(tmp.toNumber());
1071 QML_V4_END_INSTR(ConvertStringToReal, unaryop)
1073 QML_V4_BEGIN_INSTR(MathSinReal, unaryop)
1075 const Register &src = registers[instr->unaryop.src];
1076 Register &output = registers[instr->unaryop.output];
1077 if (src.isUndefined()) output.setUndefined();
1078 else output.setqreal(qSin(src.getqreal()));
1080 QML_V4_END_INSTR(MathSinReal, unaryop)
1082 QML_V4_BEGIN_INSTR(MathCosReal, unaryop)
1084 const Register &src = registers[instr->unaryop.src];
1085 Register &output = registers[instr->unaryop.output];
1086 if (src.isUndefined()) output.setUndefined();
1087 else output.setqreal(qCos(src.getqreal()));
1089 QML_V4_END_INSTR(MathCosReal, unaryop)
1091 QML_V4_BEGIN_INSTR(MathRoundReal, unaryop)
1093 const Register &src = registers[instr->unaryop.src];
1094 Register &output = registers[instr->unaryop.output];
1095 if (src.isUndefined()) output.setUndefined();
1096 else output.setint(qRound(src.getqreal()));
1098 QML_V4_END_INSTR(MathRoundReal, unaryop)
1100 QML_V4_BEGIN_INSTR(MathFloorReal, unaryop)
1102 const Register &src = registers[instr->unaryop.src];
1103 Register &output = registers[instr->unaryop.output];
1104 if (src.isUndefined()) output.setUndefined();
1105 else output.setint(qFloor(src.getqreal()));
1107 QML_V4_END_INSTR(MathFloorReal, unaryop)
1109 QML_V4_BEGIN_INSTR(MathPIReal, unaryop)
1111 static const qsreal qmlPI = 2.0 * qAsin(1.0);
1112 Register &output = registers[instr->unaryop.output];
1113 output.setqreal(qmlPI);
1115 QML_V4_END_INSTR(MathPIReal, unaryop)
1117 QML_V4_BEGIN_INSTR(Real, real_value)
1118 registers[instr->real_value.reg].setqreal(instr->real_value.value);
1119 QML_V4_END_INSTR(Real, real_value)
1121 QML_V4_BEGIN_INSTR(Int, int_value)
1122 registers[instr->int_value.reg].setint(instr->int_value.value);
1123 QML_V4_END_INSTR(Int, int_value)
1125 QML_V4_BEGIN_INSTR(Bool, bool_value)
1126 registers[instr->bool_value.reg].setbool(instr->bool_value.value);
1127 QML_V4_END_INSTR(Bool, bool_value)
1129 QML_V4_BEGIN_INSTR(String, string_value)
1131 Register &output = registers[instr->string_value.reg];
1132 QChar *string = (QChar *)(data + instr->string_value.offset);
1133 new (output.getstringptr()) QString(string, instr->string_value.length);
1134 STRING_REGISTER(instr->string_value.reg);
1136 QML_V4_END_INSTR(String, string_value)
1138 QML_V4_BEGIN_INSTR(EnableV4Test, string_value)
1140 testBindingSource = new QString((QChar *)(data + instr->string_value.offset), instr->string_value.length);
1143 QML_V4_END_INSTR(String, string_value)
1145 QML_V4_BEGIN_INSTR(BitAndInt, binaryop)
1147 registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() &
1148 registers[instr->binaryop.right].getint());
1150 QML_V4_END_INSTR(BitAndInt, binaryop)
1152 QML_V4_BEGIN_INSTR(BitOrInt, binaryop)
1154 registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() |
1155 registers[instr->binaryop.right].getint());
1157 QML_V4_END_INSTR(BitAndInt, binaryop)
1159 QML_V4_BEGIN_INSTR(BitXorInt, binaryop)
1161 registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() ^
1162 registers[instr->binaryop.right].getint());
1164 QML_V4_END_INSTR(BitXorInt, binaryop)
1166 QML_V4_BEGIN_INSTR(AddReal, binaryop)
1168 registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() +
1169 registers[instr->binaryop.right].getqreal());
1171 QML_V4_END_INSTR(AddReal, binaryop)
1173 QML_V4_BEGIN_INSTR(AddString, binaryop)
1175 QString &string = *registers[instr->binaryop.output].getstringptr();
1176 if (instr->binaryop.output == instr->binaryop.left) {
1177 string += registers[instr->binaryop.right].getstringptr();
1179 string = *registers[instr->binaryop.left].getstringptr() +
1180 *registers[instr->binaryop.right].getstringptr();
1183 QML_V4_END_INSTR(AddString, binaryop)
1185 QML_V4_BEGIN_INSTR(SubReal, binaryop)
1187 registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() -
1188 registers[instr->binaryop.right].getqreal());
1190 QML_V4_END_INSTR(SubReal, binaryop)
1192 QML_V4_BEGIN_INSTR(MulReal, binaryop)
1194 registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() *
1195 registers[instr->binaryop.right].getqreal());
1197 QML_V4_END_INSTR(MulReal, binaryop)
1199 QML_V4_BEGIN_INSTR(DivReal, binaryop)
1201 registers[instr->binaryop.output].setqreal(registers[instr->binaryop.left].getqreal() /
1202 registers[instr->binaryop.right].getqreal());
1204 QML_V4_END_INSTR(DivReal, binaryop)
1206 QML_V4_BEGIN_INSTR(ModReal, binaryop)
1208 Register &target = registers[instr->binaryop.output];
1209 const Register &left = registers[instr->binaryop.left];
1210 const Register &right = registers[instr->binaryop.right];
1211 if (QMetaType::QReal == QMetaType::Float)
1212 target.setqreal(::fmodf(left.getqreal(), right.getqreal()));
1214 target.setqreal(::fmod(left.getqreal(), right.getqreal()));
1216 QML_V4_END_INSTR(ModInt, binaryop)
1218 QML_V4_BEGIN_INSTR(LShiftInt, binaryop)
1220 registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() <<
1221 registers[instr->binaryop.right].getint());
1223 QML_V4_END_INSTR(LShiftInt, binaryop)
1225 QML_V4_BEGIN_INSTR(RShiftInt, binaryop)
1227 registers[instr->binaryop.output].setint(registers[instr->binaryop.left].getint() >>
1228 registers[instr->binaryop.right].getint());
1230 QML_V4_END_INSTR(RShiftInt, binaryop)
1232 QML_V4_BEGIN_INSTR(URShiftInt, binaryop)
1234 registers[instr->binaryop.output].setint((unsigned)registers[instr->binaryop.left].getint() >>
1235 registers[instr->binaryop.right].getint());
1237 QML_V4_END_INSTR(URShiftInt, binaryop)
1239 QML_V4_BEGIN_INSTR(GtReal, binaryop)
1241 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() >
1242 registers[instr->binaryop.right].getqreal());
1244 QML_V4_END_INSTR(GtReal, binaryop)
1246 QML_V4_BEGIN_INSTR(LtReal, binaryop)
1248 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() <
1249 registers[instr->binaryop.right].getqreal());
1251 QML_V4_END_INSTR(LtReal, binaryop)
1253 QML_V4_BEGIN_INSTR(GeReal, binaryop)
1255 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() >=
1256 registers[instr->binaryop.right].getqreal());
1258 QML_V4_END_INSTR(GeReal, binaryop)
1260 QML_V4_BEGIN_INSTR(LeReal, binaryop)
1262 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() <=
1263 registers[instr->binaryop.right].getqreal());
1265 QML_V4_END_INSTR(LeReal, binaryop)
1267 QML_V4_BEGIN_INSTR(EqualReal, binaryop)
1269 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() ==
1270 registers[instr->binaryop.right].getqreal());
1272 QML_V4_END_INSTR(EqualReal, binaryop)
1274 QML_V4_BEGIN_INSTR(NotEqualReal, binaryop)
1276 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() !=
1277 registers[instr->binaryop.right].getqreal());
1279 QML_V4_END_INSTR(NotEqualReal, binaryop)
1281 QML_V4_BEGIN_INSTR(StrictEqualReal, binaryop)
1283 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() ==
1284 registers[instr->binaryop.right].getqreal());
1286 QML_V4_END_INSTR(StrictEqualReal, binaryop)
1288 QML_V4_BEGIN_INSTR(StrictNotEqualReal, binaryop)
1290 registers[instr->binaryop.output].setbool(registers[instr->binaryop.left].getqreal() !=
1291 registers[instr->binaryop.right].getqreal());
1293 QML_V4_END_INSTR(StrictNotEqualReal, binaryop)
1295 QML_V4_BEGIN_INSTR(GtString, binaryop)
1297 const QString &a = *registers[instr->binaryop.left].getstringptr();
1298 const QString &b = *registers[instr->binaryop.right].getstringptr();
1299 bool result = a > b;
1300 if (instr->binaryop.left == instr->binaryop.output) {
1301 registers[instr->binaryop.output].cleanupString();
1302 MARK_CLEAN_REGISTER(instr->binaryop.output);
1304 registers[instr->binaryop.output].setbool(result);
1306 QML_V4_END_INSTR(GtString, binaryop)
1308 QML_V4_BEGIN_INSTR(LtString, binaryop)
1310 const QString &a = *registers[instr->binaryop.left].getstringptr();
1311 const QString &b = *registers[instr->binaryop.right].getstringptr();
1312 bool result = a < b;
1313 if (instr->binaryop.left == instr->binaryop.output) {
1314 registers[instr->binaryop.output].cleanupString();
1315 MARK_CLEAN_REGISTER(instr->binaryop.output);
1317 registers[instr->binaryop.output].setbool(result);
1319 QML_V4_END_INSTR(LtString, binaryop)
1321 QML_V4_BEGIN_INSTR(GeString, binaryop)
1323 const QString &a = *registers[instr->binaryop.left].getstringptr();
1324 const QString &b = *registers[instr->binaryop.right].getstringptr();
1325 bool result = a >= b;
1326 if (instr->binaryop.left == instr->binaryop.output) {
1327 registers[instr->binaryop.output].cleanupString();
1328 MARK_CLEAN_REGISTER(instr->binaryop.output);
1330 registers[instr->binaryop.output].setbool(result);
1332 QML_V4_END_INSTR(GeString, binaryop)
1334 QML_V4_BEGIN_INSTR(LeString, binaryop)
1336 const QString &a = *registers[instr->binaryop.left].getstringptr();
1337 const QString &b = *registers[instr->binaryop.right].getstringptr();
1338 bool result = a <= b;
1339 if (instr->binaryop.left == instr->binaryop.output) {
1340 registers[instr->binaryop.output].cleanupString();
1341 MARK_CLEAN_REGISTER(instr->binaryop.output);
1343 registers[instr->binaryop.output].setbool(result);
1345 QML_V4_END_INSTR(LeString, binaryop)
1347 QML_V4_BEGIN_INSTR(EqualString, binaryop)
1349 const QString &a = *registers[instr->binaryop.left].getstringptr();
1350 const QString &b = *registers[instr->binaryop.right].getstringptr();
1351 bool result = a == b;
1352 if (instr->binaryop.left == instr->binaryop.output) {
1353 registers[instr->binaryop.output].cleanupString();
1354 MARK_CLEAN_REGISTER(instr->binaryop.output);
1356 registers[instr->binaryop.output].setbool(result);
1358 QML_V4_END_INSTR(EqualString, binaryop)
1360 QML_V4_BEGIN_INSTR(NotEqualString, binaryop)
1362 const QString &a = *registers[instr->binaryop.left].getstringptr();
1363 const QString &b = *registers[instr->binaryop.right].getstringptr();
1364 bool result = a != b;
1365 if (instr->binaryop.left == instr->binaryop.output) {
1366 registers[instr->binaryop.output].cleanupString();
1367 MARK_CLEAN_REGISTER(instr->binaryop.output);
1369 registers[instr->binaryop.output].setbool(result);
1371 QML_V4_END_INSTR(NotEqualString, binaryop)
1373 QML_V4_BEGIN_INSTR(StrictEqualString, binaryop)
1375 const QString &a = *registers[instr->binaryop.left].getstringptr();
1376 const QString &b = *registers[instr->binaryop.right].getstringptr();
1377 bool result = a == b;
1378 if (instr->binaryop.left == instr->binaryop.output) {
1379 registers[instr->binaryop.output].cleanupString();
1380 MARK_CLEAN_REGISTER(instr->binaryop.output);
1382 registers[instr->binaryop.output].setbool(result);
1384 QML_V4_END_INSTR(StrictEqualString, binaryop)
1386 QML_V4_BEGIN_INSTR(StrictNotEqualString, binaryop)
1388 const QString &a = *registers[instr->binaryop.left].getstringptr();
1389 const QString &b = *registers[instr->binaryop.right].getstringptr();
1390 bool result = a != b;
1391 if (instr->binaryop.left == instr->binaryop.output) {
1392 registers[instr->binaryop.output].cleanupString();
1393 MARK_CLEAN_REGISTER(instr->binaryop.output);
1395 registers[instr->binaryop.output].setbool(result);
1397 QML_V4_END_INSTR(StrictNotEqualString, binaryop)
1399 QML_V4_BEGIN_INSTR(NewString, construct)
1401 Register &output = registers[instr->construct.reg];
1402 new (output.getstringptr()) QString;
1403 STRING_REGISTER(instr->construct.reg);
1405 QML_V4_END_INSTR(NewString, construct)
1407 QML_V4_BEGIN_INSTR(NewUrl, construct)
1409 Register &output = registers[instr->construct.reg];
1410 new (output.geturlptr()) QUrl;
1411 URL_REGISTER(instr->construct.reg);
1413 QML_V4_END_INSTR(NewUrl, construct)
1415 QML_V4_BEGIN_INSTR(Fetch, fetch)
1417 Register ® = registers[instr->fetch.reg];
1419 if (reg.isUndefined())
1420 THROW_EXCEPTION(instr->fetch.exceptionId);
1422 QObject *object = reg.getQObject();
1424 THROW_EXCEPTION(instr->fetch.exceptionId);
1426 reg.init((Register::Type)instr->fetch.valueType);
1427 if (instr->fetch.valueType >= FirstCleanupType)
1428 MARK_REGISTER(instr->fetch.reg);
1429 void *argv[] = { reg.typeDataPtr(), 0 };
1430 QMetaObject::metacall(object, QMetaObject::ReadProperty, instr->fetch.index, argv);
1433 QML_V4_END_INSTR(Fetch, fetch)
1435 QML_V4_BEGIN_INSTR(TestV4Store, storetest)
1437 Register &data = registers[instr->storetest.reg];
1438 testBindingResult(*testBindingSource, bindingLine, bindingColumn, context,
1439 scope, data, instr->storetest.regType);
1441 QML_V4_END_INSTR(TestV4Store, storetest)
1443 QML_V4_BEGIN_INSTR(Store, store)
1445 Register &data = registers[instr->store.reg];
1447 if (data.isUndefined())
1448 THROW_EXCEPTION_STR(instr->store.exceptionId, QLatin1String("Unable to assign undefined value"));
1451 void *argv[] = { data.typeDataPtr(), 0, &status, &storeFlags };
1452 QMetaObject::metacall(output, QMetaObject::WriteProperty,
1453 instr->store.index, argv);
1457 QML_V4_END_INSTR(Store, store)
1459 QML_V4_BEGIN_INSTR(Copy, copy)
1460 registers[instr->copy.reg].copy(registers[instr->copy.src]);
1461 if (registers[instr->copy.reg].gettype() >= FirstCleanupType)
1462 MARK_REGISTER(instr->copy.reg);
1463 QML_V4_END_INSTR(Copy, copy)
1465 QML_V4_BEGIN_INSTR(Jump, jump)
1466 if (instr->jump.reg == -1 || !registers[instr->jump.reg].getbool())
1467 code += instr->jump.count;
1468 QML_V4_END_INSTR(Jump, jump)
1470 QML_V4_BEGIN_INSTR(BranchTrue, branchop)
1471 if (registers[instr->branchop.reg].getbool())
1472 code += instr->branchop.offset;
1473 QML_V4_END_INSTR(BranchTrue, branchop)
1475 QML_V4_BEGIN_INSTR(BranchFalse, branchop)
1476 if (! registers[instr->branchop.reg].getbool())
1477 code += instr->branchop.offset;
1478 QML_V4_END_INSTR(BranchFalse, branchop)
1480 QML_V4_BEGIN_INSTR(Branch, branchop)
1481 code += instr->branchop.offset;
1482 QML_V4_END_INSTR(Branch, branchop)
1484 QML_V4_BEGIN_INSTR(Block, blockop)
1485 executedBlocks |= instr->blockop.block;
1486 QML_V4_END_INSTR(Block, blockop)
1488 QML_V4_BEGIN_INSTR(InitString, initstring)
1489 if (!identifiers[instr->initstring.offset].identifier) {
1490 quint32 len = *(quint32 *)(data + instr->initstring.dataIdx);
1491 QChar *strdata = (QChar *)(data + instr->initstring.dataIdx + sizeof(quint32));
1493 QString str = QString::fromRawData(strdata, len);
1495 identifiers[instr->initstring.offset] = engine->objectClass->createPersistentIdentifier(str);
1497 QML_V4_END_INSTR(InitString, initstring)
1499 QML_V4_BEGIN_INSTR(CleanupRegister, cleanup)
1500 registers[instr->cleanup.reg].cleanup();
1501 QML_V4_END_INSTR(CleanupRegister, cleanup)
1503 #ifdef QML_THREADED_INTERPRETER
1507 qFatal("QDeclarativeV4: Unknown instruction %d encountered.", instr->common.type);
1514 Q_ASSERT(!"Unreachable code reached");
1518 delete testBindingSource;
1521 while (cleanupRegisterMask) {
1522 if (cleanupRegisterMask & 0x1)
1523 registers[reg].cleanup();
1526 cleanupRegisterMask >>= 1;